Page MenuHomeFreeBSD

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: vendor/clang/dist-release_80/docs/LanguageExtensions.rst
===================================================================
--- vendor/clang/dist-release_80/docs/LanguageExtensions.rst (revision 343795)
+++ vendor/clang/dist-release_80/docs/LanguageExtensions.rst (revision 343796)
@@ -1,2910 +1,2924 @@
=========================
Clang Language Extensions
=========================
.. contents::
:local:
:depth: 1
.. toctree::
:hidden:
ObjectiveCLiterals
BlockLanguageSpec
Block-ABI-Apple
AutomaticReferenceCounting
Introduction
============
This document describes the language extensions provided by Clang. In addition
to the language extensions listed here, Clang aims to support a broad range of
GCC extensions. Please see the `GCC manual
<http://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html>`_ for more information on
these extensions.
.. _langext-feature_check:
Feature Checking Macros
=======================
Language extensions can be very useful, but only if you know you can depend on
them. In order to allow fine-grain features checks, we support three builtin
function-like macros. This allows you to directly test for a feature in your
code without having to resort to something like autoconf or fragile "compiler
version checks".
``__has_builtin``
-----------------
This function-like macro takes a single identifier argument that is the name of
a builtin function. It evaluates to 1 if the builtin is supported or 0 if not.
It can be used like this:
.. code-block:: c++
#ifndef __has_builtin // Optional of course.
#define __has_builtin(x) 0 // Compatibility with non-clang compilers.
#endif
...
#if __has_builtin(__builtin_trap)
__builtin_trap();
#else
abort();
#endif
...
.. _langext-__has_feature-__has_extension:
``__has_feature`` and ``__has_extension``
-----------------------------------------
These function-like macros take a single identifier argument that is the name
of a feature. ``__has_feature`` evaluates to 1 if the feature is both
supported by Clang and standardized in the current language standard or 0 if
not (but see :ref:`below <langext-has-feature-back-compat>`), while
``__has_extension`` evaluates to 1 if the feature is supported by Clang in the
current language (either as a language extension or a standard language
feature) or 0 if not. They can be used like this:
.. code-block:: c++
#ifndef __has_feature // Optional of course.
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
#endif
#ifndef __has_extension
#define __has_extension __has_feature // Compatibility with pre-3.0 compilers.
#endif
...
#if __has_feature(cxx_rvalue_references)
// This code will only be compiled with the -std=c++11 and -std=gnu++11
// options, because rvalue references are only standardized in C++11.
#endif
#if __has_extension(cxx_rvalue_references)
// This code will be compiled with the -std=c++11, -std=gnu++11, -std=c++98
// and -std=gnu++98 options, because rvalue references are supported as a
// language extension in C++98.
#endif
.. _langext-has-feature-back-compat:
For backward compatibility, ``__has_feature`` can also be used to test
for support for non-standardized features, i.e. features not prefixed ``c_``,
``cxx_`` or ``objc_``.
Another use of ``__has_feature`` is to check for compiler features not related
to the language standard, such as e.g. :doc:`AddressSanitizer
<AddressSanitizer>`.
If the ``-pedantic-errors`` option is given, ``__has_extension`` is equivalent
to ``__has_feature``.
The feature tag is described along with the language feature below.
The feature name or extension name can also be specified with a preceding and
following ``__`` (double underscore) to avoid interference from a macro with
the same name. For instance, ``__cxx_rvalue_references__`` can be used instead
of ``cxx_rvalue_references``.
``__has_cpp_attribute``
-----------------------
This function-like macro is available in C++2a by default, and is provided as an
extension in earlier language standards. It takes a single argument that is the
name of a double-square-bracket-style attribute. The argument can either be a
single identifier or a scoped identifier. If the attribute is supported, a
nonzero value is returned. If the attribute is a standards-based attribute, this
macro returns a nonzero value based on the year and month in which the attribute
was voted into the working draft. See `WG21 SD-6
<https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations>`_
for the list of values returned for standards-based attributes. If the attribute
is not supported by the current compliation target, this macro evaluates to 0.
It can be used like this:
.. code-block:: c++
#ifndef __has_cpp_attribute // For backwards compatibility
#define __has_cpp_attribute(x) 0
#endif
...
#if __has_cpp_attribute(clang::fallthrough)
#define FALLTHROUGH [[clang::fallthrough]]
#else
#define FALLTHROUGH
#endif
...
The attribute scope tokens ``clang`` and ``_Clang`` are interchangeable, as are
the attribute scope tokens ``gnu`` and ``__gnu__``. Attribute tokens in either
of these namespaces can be specified with a preceding and following ``__``
(double underscore) to avoid interference from a macro with the same name. For
instance, ``gnu::__const__`` can be used instead of ``gnu::const``.
``__has_c_attribute``
---------------------
This function-like macro takes a single argument that is the name of an
attribute exposed with the double square-bracket syntax in C mode. The argument
can either be a single identifier or a scoped identifier. If the attribute is
supported, a nonzero value is returned. If the attribute is not supported by the
current compilation target, this macro evaluates to 0. It can be used like this:
.. code-block:: c
#ifndef __has_c_attribute // Optional of course.
#define __has_c_attribute(x) 0 // Compatibility with non-clang compilers.
#endif
...
#if __has_c_attribute(fallthrough)
#define FALLTHROUGH [[fallthrough]]
#else
#define FALLTHROUGH
#endif
...
The attribute scope tokens ``clang`` and ``_Clang`` are interchangeable, as are
the attribute scope tokens ``gnu`` and ``__gnu__``. Attribute tokens in either
of these namespaces can be specified with a preceding and following ``__``
(double underscore) to avoid interference from a macro with the same name. For
instance, ``gnu::__const__`` can be used instead of ``gnu::const``.
``__has_attribute``
-------------------
This function-like macro takes a single identifier argument that is the name of
a GNU-style attribute. It evaluates to 1 if the attribute is supported by the
current compilation target, or 0 if not. It can be used like this:
.. code-block:: c++
#ifndef __has_attribute // Optional of course.
#define __has_attribute(x) 0 // Compatibility with non-clang compilers.
#endif
...
#if __has_attribute(always_inline)
#define ALWAYS_INLINE __attribute__((always_inline))
#else
#define ALWAYS_INLINE
#endif
...
The attribute name can also be specified with a preceding and following ``__``
(double underscore) to avoid interference from a macro with the same name. For
instance, ``__always_inline__`` can be used instead of ``always_inline``.
``__has_declspec_attribute``
----------------------------
This function-like macro takes a single identifier argument that is the name of
an attribute implemented as a Microsoft-style ``__declspec`` attribute. It
evaluates to 1 if the attribute is supported by the current compilation target,
or 0 if not. It can be used like this:
.. code-block:: c++
#ifndef __has_declspec_attribute // Optional of course.
#define __has_declspec_attribute(x) 0 // Compatibility with non-clang compilers.
#endif
...
#if __has_declspec_attribute(dllexport)
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif
...
The attribute name can also be specified with a preceding and following ``__``
(double underscore) to avoid interference from a macro with the same name. For
instance, ``__dllexport__`` can be used instead of ``dllexport``.
``__is_identifier``
-------------------
This function-like macro takes a single identifier argument that might be either
a reserved word or a regular identifier. It evaluates to 1 if the argument is just
a regular identifier and not a reserved word, in the sense that it can then be
used as the name of a user-defined function or variable. Otherwise it evaluates
to 0. It can be used like this:
.. code-block:: c++
...
#ifdef __is_identifier // Compatibility with non-clang compilers.
#if __is_identifier(__wchar_t)
typedef wchar_t __wchar_t;
#endif
#endif
__wchar_t WideCharacter;
...
Include File Checking Macros
============================
Not all developments systems have the same include files. The
:ref:`langext-__has_include` and :ref:`langext-__has_include_next` macros allow
you to check for the existence of an include file before doing a possibly
failing ``#include`` directive. Include file checking macros must be used
as expressions in ``#if`` or ``#elif`` preprocessing directives.
.. _langext-__has_include:
``__has_include``
-----------------
This function-like macro takes a single file name string argument that is the
name of an include file. It evaluates to 1 if the file can be found using the
include paths, or 0 otherwise:
.. code-block:: c++
// Note the two possible file name string formats.
#if __has_include("myinclude.h") && __has_include(<stdint.h>)
# include "myinclude.h"
#endif
To test for this feature, use ``#if defined(__has_include)``:
.. code-block:: c++
// To avoid problem with non-clang compilers not having this macro.
#if defined(__has_include)
#if __has_include("myinclude.h")
# include "myinclude.h"
#endif
#endif
.. _langext-__has_include_next:
``__has_include_next``
----------------------
This function-like macro takes a single file name string argument that is the
name of an include file. It is like ``__has_include`` except that it looks for
the second instance of the given file found in the include paths. It evaluates
to 1 if the second instance of the file can be found using the include paths,
or 0 otherwise:
.. code-block:: c++
// Note the two possible file name string formats.
#if __has_include_next("myinclude.h") && __has_include_next(<stdint.h>)
# include_next "myinclude.h"
#endif
// To avoid problem with non-clang compilers not having this macro.
#if defined(__has_include_next)
#if __has_include_next("myinclude.h")
# include_next "myinclude.h"
#endif
#endif
Note that ``__has_include_next``, like the GNU extension ``#include_next``
directive, is intended for use in headers only, and will issue a warning if
used in the top-level compilation file. A warning will also be issued if an
absolute path is used in the file argument.
``__has_warning``
-----------------
This function-like macro takes a string literal that represents a command line
option for a warning and returns true if that is a valid warning option.
.. code-block:: c++
#if __has_warning("-Wformat")
...
#endif
Builtin Macros
==============
``__BASE_FILE__``
Defined to a string that contains the name of the main input file passed to
Clang.
``__COUNTER__``
Defined to an integer value that starts at zero and is incremented each time
the ``__COUNTER__`` macro is expanded.
``__INCLUDE_LEVEL__``
Defined to an integral value that is the include depth of the file currently
being translated. For the main file, this value is zero.
``__TIMESTAMP__``
Defined to the date and time of the last modification of the current source
file.
``__clang__``
Defined when compiling with Clang
``__clang_major__``
Defined to the major marketing version number of Clang (e.g., the 2 in
2.0.1). Note that marketing version numbers should not be used to check for
language features, as different vendors use different numbering schemes.
Instead, use the :ref:`langext-feature_check`.
``__clang_minor__``
Defined to the minor version number of Clang (e.g., the 0 in 2.0.1). Note
that marketing version numbers should not be used to check for language
features, as different vendors use different numbering schemes. Instead, use
the :ref:`langext-feature_check`.
``__clang_patchlevel__``
Defined to the marketing patch level of Clang (e.g., the 1 in 2.0.1).
``__clang_version__``
Defined to a string that captures the Clang marketing version, including the
Subversion tag or revision number, e.g., "``1.5 (trunk 102332)``".
.. _langext-vectors:
Vectors and Extended Vectors
============================
Supports the GCC, OpenCL, AltiVec and NEON vector extensions.
OpenCL vector types are created using ``ext_vector_type`` attribute. It
support for ``V.xyzw`` syntax and other tidbits as seen in OpenCL. An example
is:
.. code-block:: c++
typedef float float4 __attribute__((ext_vector_type(4)));
typedef float float2 __attribute__((ext_vector_type(2)));
float4 foo(float2 a, float2 b) {
float4 c;
c.xz = a;
c.yw = b;
return c;
}
Query for this feature with ``__has_extension(attribute_ext_vector_type)``.
Giving ``-maltivec`` option to clang enables support for AltiVec vector syntax
and functions. For example:
.. code-block:: c++
vector float foo(vector int a) {
vector int b;
b = vec_add(a, a) + a;
return (vector float)b;
}
NEON vector types are created using ``neon_vector_type`` and
``neon_polyvector_type`` attributes. For example:
.. code-block:: c++
typedef __attribute__((neon_vector_type(8))) int8_t int8x8_t;
typedef __attribute__((neon_polyvector_type(16))) poly8_t poly8x16_t;
int8x8_t foo(int8x8_t a) {
int8x8_t v;
v = a;
return v;
}
Vector Literals
---------------
Vector literals can be used to create vectors from a set of scalars, or
vectors. Either parentheses or braces form can be used. In the parentheses
form the number of literal values specified must be one, i.e. referring to a
scalar value, or must match the size of the vector type being created. If a
single scalar literal value is specified, the scalar literal value will be
replicated to all the components of the vector type. In the brackets form any
number of literals can be specified. For example:
.. code-block:: c++
typedef int v4si __attribute__((__vector_size__(16)));
typedef float float4 __attribute__((ext_vector_type(4)));
typedef float float2 __attribute__((ext_vector_type(2)));
v4si vsi = (v4si){1, 2, 3, 4};
float4 vf = (float4)(1.0f, 2.0f, 3.0f, 4.0f);
vector int vi1 = (vector int)(1); // vi1 will be (1, 1, 1, 1).
vector int vi2 = (vector int){1}; // vi2 will be (1, 0, 0, 0).
vector int vi3 = (vector int)(1, 2); // error
vector int vi4 = (vector int){1, 2}; // vi4 will be (1, 2, 0, 0).
vector int vi5 = (vector int)(1, 2, 3, 4);
float4 vf = (float4)((float2)(1.0f, 2.0f), (float2)(3.0f, 4.0f));
Vector Operations
-----------------
The table below shows the support for each operation by vector extension. A
dash indicates that an operation is not accepted according to a corresponding
specification.
============================== ======= ======= ======= =======
Operator OpenCL AltiVec GCC NEON
============================== ======= ======= ======= =======
[] yes yes yes --
unary operators +, -- yes yes yes --
++, -- -- yes yes yes --
+,--,*,/,% yes yes yes --
bitwise operators &,|,^,~ yes yes yes --
>>,<< yes yes yes --
!, &&, || yes -- -- --
==, !=, >, <, >=, <= yes yes -- --
= yes yes yes yes
:? yes -- -- --
sizeof yes yes yes yes
C-style cast yes yes yes no
reinterpret_cast yes no yes no
static_cast yes no yes no
const_cast no no no no
============================== ======= ======= ======= =======
See also :ref:`langext-__builtin_shufflevector`, :ref:`langext-__builtin_convertvector`.
Half-Precision Floating Point
=============================
Clang supports two half-precision (16-bit) floating point types: ``__fp16`` and
-``_Float16``. ``__fp16`` is defined in the ARM C Language Extensions (`ACLE
-<http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053d/IHI0053D_acle_2_1.pdf>`_)
-and ``_Float16`` in ISO/IEC TS 18661-3:2015.
+``_Float16``. These types are supported in all language modes.
-``__fp16`` is a storage and interchange format only. This means that values of
-``__fp16`` promote to (at least) float when used in arithmetic operations.
-There are two ``__fp16`` formats. Clang supports the IEEE 754-2008 format and
-not the ARM alternative format.
+``__fp16`` is supported on every target, as it is purely a storage format; see below.
+``_Float16`` is currently only supported on the following targets, with further
+targets pending ABI standardization:
+- 32-bit ARM
+- 64-bit ARM (AArch64)
+- SPIR
+``_Float16`` will be supported on more targets as they define ABIs for it.
-ISO/IEC TS 18661-3:2015 defines C support for additional floating point types.
-``_FloatN`` is defined as a binary floating type, where the N suffix denotes
-the number of bits and is 16, 32, 64, or greater and equal to 128 and a
-multiple of 32. Clang supports ``_Float16``. The difference from ``__fp16`` is
-that arithmetic on ``_Float16`` is performed in half-precision, thus it is not
-a storage-only format. ``_Float16`` is available as a source language type in
-both C and C++ mode.
+``__fp16`` is a storage and interchange format only. This means that values of
+``__fp16`` are immediately promoted to (at least) ``float`` when used in arithmetic
+operations, so that e.g. the result of adding two ``__fp16`` values has type ``float``.
+The behavior of ``__fp16`` is specified by the ARM C Language Extensions (`ACLE <http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053d/IHI0053D_acle_2_1.pdf>`_).
+Clang uses the ``binary16`` format from IEEE 754-2008 for ``__fp16``, not the ARM
+alternative format.
-It is recommended that portable code use the ``_Float16`` type because
-``__fp16`` is an ARM C-Language Extension (ACLE), whereas ``_Float16`` is
-defined by the C standards committee, so using ``_Float16`` will not prevent
-code from being ported to architectures other than Arm. Also, ``_Float16``
-arithmetic and operations will directly map on half-precision instructions when
-they are available (e.g. Armv8.2-A), avoiding conversions to/from
-single-precision, and thus will result in more performant code. If
-half-precision instructions are unavailable, values will be promoted to
-single-precision, similar to the semantics of ``__fp16`` except that the
-results will be stored in single-precision.
+``_Float16`` is an extended floating-point type. This means that, just like arithmetic on
+``float`` or ``double``, arithmetic on ``_Float16`` operands is formally performed in the
+``_Float16`` type, so that e.g. the result of adding two ``_Float16`` values has type
+``_Float16``. The behavior of ``_Float16`` is specified by ISO/IEC TS 18661-3:2015
+("Floating-point extensions for C"). As with ``__fp16``, Clang uses the ``binary16``
+format from IEEE 754-2008 for ``_Float16``.
-In an arithmetic operation where one operand is of ``__fp16`` type and the
-other is of ``_Float16`` type, the ``_Float16`` type is first converted to
-``__fp16`` type and then the operation is completed as if both operands were of
-``__fp16`` type.
+``_Float16`` arithmetic will be performed using native half-precision support
+when available on the target (e.g. on ARMv8.2a); otherwise it will be performed
+at a higher precision (currently always ``float``) and then truncated down to
+``_Float16``. Note that C and C++ allow intermediate floating-point operands
+of an expression to be computed with greater precision than is expressible in
+their type, so Clang may avoid intermediate truncations in certain cases; this may
+lead to results that are inconsistent with native arithmetic.
-To define a ``_Float16`` literal, suffix ``f16`` can be appended to the compile-time
-constant declaration. There is no default argument promotion for ``_Float16``; this
-applies to the standard floating types only. As a consequence, for example, an
-explicit cast is required for printing a ``_Float16`` value (there is no string
-format specifier for ``_Float16``).
+It is recommended that portable code use ``_Float16`` instead of ``__fp16``,
+as it has been defined by the C standards committee and has behavior that is
+more familiar to most programmers.
+
+Because ``__fp16`` operands are always immediately promoted to ``float``, the
+common real type of ``__fp16`` and ``_Float16`` for the purposes of the usual
+arithmetic conversions is ``float``.
+
+A literal can be given ``_Float16`` type using the suffix ``f16``; for example:
+```
+3.14f16
+```
+
+Because default argument promotion only applies to the standard floating-point
+types, ``_Float16`` values are not promoted to ``double`` when passed as variadic
+or untyped arguments. As a consequence, some caution must be taken when using
+certain library facilities with ``_Float16``; for example, there is no ``printf`` format
+specifier for ``_Float16``, and (unlike ``float``) it will not be implicitly promoted to
+``double`` when passed to ``printf``, so the programmer must explicitly cast it to
+``double`` before using it with an ``%f`` or similar specifier.
Messages on ``deprecated`` and ``unavailable`` Attributes
=========================================================
An optional string message can be added to the ``deprecated`` and
``unavailable`` attributes. For example:
.. code-block:: c++
void explode(void) __attribute__((deprecated("extremely unsafe, use 'combust' instead!!!")));
If the deprecated or unavailable declaration is used, the message will be
incorporated into the appropriate diagnostic:
.. code-block:: none
harmless.c:4:3: warning: 'explode' is deprecated: extremely unsafe, use 'combust' instead!!!
[-Wdeprecated-declarations]
explode();
^
Query for this feature with
``__has_extension(attribute_deprecated_with_message)`` and
``__has_extension(attribute_unavailable_with_message)``.
Attributes on Enumerators
=========================
Clang allows attributes to be written on individual enumerators. This allows
enumerators to be deprecated, made unavailable, etc. The attribute must appear
after the enumerator name and before any initializer, like so:
.. code-block:: c++
enum OperationMode {
OM_Invalid,
OM_Normal,
OM_Terrified __attribute__((deprecated)),
OM_AbortOnError __attribute__((deprecated)) = 4
};
Attributes on the ``enum`` declaration do not apply to individual enumerators.
Query for this feature with ``__has_extension(enumerator_attributes)``.
'User-Specified' System Frameworks
==================================
Clang provides a mechanism by which frameworks can be built in such a way that
they will always be treated as being "system frameworks", even if they are not
present in a system framework directory. This can be useful to system
framework developers who want to be able to test building other applications
with development builds of their framework, including the manner in which the
compiler changes warning behavior for system headers.
Framework developers can opt-in to this mechanism by creating a
"``.system_framework``" file at the top-level of their framework. That is, the
framework should have contents like:
.. code-block:: none
.../TestFramework.framework
.../TestFramework.framework/.system_framework
.../TestFramework.framework/Headers
.../TestFramework.framework/Headers/TestFramework.h
...
Clang will treat the presence of this file as an indicator that the framework
should be treated as a system framework, regardless of how it was found in the
framework search path. For consistency, we recommend that such files never be
included in installed versions of the framework.
Checks for Standard Language Features
=====================================
The ``__has_feature`` macro can be used to query if certain standard language
features are enabled. The ``__has_extension`` macro can be used to query if
language features are available as an extension when compiling for a standard
which does not provide them. The features which can be tested are listed here.
Since Clang 3.4, the C++ SD-6 feature test macros are also supported.
These are macros with names of the form ``__cpp_<feature_name>``, and are
intended to be a portable way to query the supported features of the compiler.
See `the C++ status page <https://clang.llvm.org/cxx_status.html#ts>`_ for
information on the version of SD-6 supported by each Clang release, and the
macros provided by that revision of the recommendations.
C++98
-----
The features listed below are part of the C++98 standard. These features are
enabled by default when compiling C++ code.
C++ exceptions
^^^^^^^^^^^^^^
Use ``__has_feature(cxx_exceptions)`` to determine if C++ exceptions have been
enabled. For example, compiling code with ``-fno-exceptions`` disables C++
exceptions.
C++ RTTI
^^^^^^^^
Use ``__has_feature(cxx_rtti)`` to determine if C++ RTTI has been enabled. For
example, compiling code with ``-fno-rtti`` disables the use of RTTI.
C++11
-----
The features listed below are part of the C++11 standard. As a result, all
these features are enabled with the ``-std=c++11`` or ``-std=gnu++11`` option
when compiling C++ code.
C++11 SFINAE includes access control
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_access_control_sfinae)`` or
``__has_extension(cxx_access_control_sfinae)`` to determine whether
access-control errors (e.g., calling a private constructor) are considered to
be template argument deduction errors (aka SFINAE errors), per `C++ DR1170
<http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1170>`_.
C++11 alias templates
^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_alias_templates)`` or
``__has_extension(cxx_alias_templates)`` to determine if support for C++11's
alias declarations and alias templates is enabled.
C++11 alignment specifiers
^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_alignas)`` or ``__has_extension(cxx_alignas)`` to
determine if support for alignment specifiers using ``alignas`` is enabled.
Use ``__has_feature(cxx_alignof)`` or ``__has_extension(cxx_alignof)`` to
determine if support for the ``alignof`` keyword is enabled.
C++11 attributes
^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_attributes)`` or ``__has_extension(cxx_attributes)`` to
determine if support for attribute parsing with C++11's square bracket notation
is enabled.
C++11 generalized constant expressions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_constexpr)`` to determine if support for generalized
constant expressions (e.g., ``constexpr``) is enabled.
C++11 ``decltype()``
^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_decltype)`` or ``__has_extension(cxx_decltype)`` to
determine if support for the ``decltype()`` specifier is enabled. C++11's
``decltype`` does not require type-completeness of a function call expression.
Use ``__has_feature(cxx_decltype_incomplete_return_types)`` or
``__has_extension(cxx_decltype_incomplete_return_types)`` to determine if
support for this feature is enabled.
C++11 default template arguments in function templates
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_default_function_template_args)`` or
``__has_extension(cxx_default_function_template_args)`` to determine if support
for default template arguments in function templates is enabled.
C++11 ``default``\ ed functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_defaulted_functions)`` or
``__has_extension(cxx_defaulted_functions)`` to determine if support for
defaulted function definitions (with ``= default``) is enabled.
C++11 delegating constructors
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_delegating_constructors)`` to determine if support for
delegating constructors is enabled.
C++11 ``deleted`` functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_deleted_functions)`` or
``__has_extension(cxx_deleted_functions)`` to determine if support for deleted
function definitions (with ``= delete``) is enabled.
C++11 explicit conversion functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_explicit_conversions)`` to determine if support for
``explicit`` conversion functions is enabled.
C++11 generalized initializers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_generalized_initializers)`` to determine if support for
generalized initializers (using braced lists and ``std::initializer_list``) is
enabled.
C++11 implicit move constructors/assignment operators
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_implicit_moves)`` to determine if Clang will implicitly
generate move constructors and move assignment operators where needed.
C++11 inheriting constructors
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_inheriting_constructors)`` to determine if support for
inheriting constructors is enabled.
C++11 inline namespaces
^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_inline_namespaces)`` or
``__has_extension(cxx_inline_namespaces)`` to determine if support for inline
namespaces is enabled.
C++11 lambdas
^^^^^^^^^^^^^
Use ``__has_feature(cxx_lambdas)`` or ``__has_extension(cxx_lambdas)`` to
determine if support for lambdas is enabled.
C++11 local and unnamed types as template arguments
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_local_type_template_args)`` or
``__has_extension(cxx_local_type_template_args)`` to determine if support for
local and unnamed types as template arguments is enabled.
C++11 noexcept
^^^^^^^^^^^^^^
Use ``__has_feature(cxx_noexcept)`` or ``__has_extension(cxx_noexcept)`` to
determine if support for noexcept exception specifications is enabled.
C++11 in-class non-static data member initialization
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_nonstatic_member_init)`` to determine whether in-class
initialization of non-static data members is enabled.
C++11 ``nullptr``
^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_nullptr)`` or ``__has_extension(cxx_nullptr)`` to
determine if support for ``nullptr`` is enabled.
C++11 ``override control``
^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_override_control)`` or
``__has_extension(cxx_override_control)`` to determine if support for the
override control keywords is enabled.
C++11 reference-qualified functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_reference_qualified_functions)`` or
``__has_extension(cxx_reference_qualified_functions)`` to determine if support
for reference-qualified functions (e.g., member functions with ``&`` or ``&&``
applied to ``*this``) is enabled.
C++11 range-based ``for`` loop
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_range_for)`` or ``__has_extension(cxx_range_for)`` to
determine if support for the range-based for loop is enabled.
C++11 raw string literals
^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_raw_string_literals)`` to determine if support for raw
string literals (e.g., ``R"x(foo\bar)x"``) is enabled.
C++11 rvalue references
^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_rvalue_references)`` or
``__has_extension(cxx_rvalue_references)`` to determine if support for rvalue
references is enabled.
C++11 ``static_assert()``
^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_static_assert)`` or
``__has_extension(cxx_static_assert)`` to determine if support for compile-time
assertions using ``static_assert`` is enabled.
C++11 ``thread_local``
^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_thread_local)`` to determine if support for
``thread_local`` variables is enabled.
C++11 type inference
^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_auto_type)`` or ``__has_extension(cxx_auto_type)`` to
determine C++11 type inference is supported using the ``auto`` specifier. If
this is disabled, ``auto`` will instead be a storage class specifier, as in C
or C++98.
C++11 strongly typed enumerations
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_strong_enums)`` or
``__has_extension(cxx_strong_enums)`` to determine if support for strongly
typed, scoped enumerations is enabled.
C++11 trailing return type
^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_trailing_return)`` or
``__has_extension(cxx_trailing_return)`` to determine if support for the
alternate function declaration syntax with trailing return type is enabled.
C++11 Unicode string literals
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_unicode_literals)`` to determine if support for Unicode
string literals is enabled.
C++11 unrestricted unions
^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_unrestricted_unions)`` to determine if support for
unrestricted unions is enabled.
C++11 user-defined literals
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_user_literals)`` to determine if support for
user-defined literals is enabled.
C++11 variadic templates
^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_variadic_templates)`` or
``__has_extension(cxx_variadic_templates)`` to determine if support for
variadic templates is enabled.
C++14
-----
The features listed below are part of the C++14 standard. As a result, all
these features are enabled with the ``-std=C++14`` or ``-std=gnu++14`` option
when compiling C++ code.
C++14 binary literals
^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_binary_literals)`` or
``__has_extension(cxx_binary_literals)`` to determine whether
binary literals (for instance, ``0b10010``) are recognized. Clang supports this
feature as an extension in all language modes.
C++14 contextual conversions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_contextual_conversions)`` or
``__has_extension(cxx_contextual_conversions)`` to determine if the C++14 rules
are used when performing an implicit conversion for an array bound in a
*new-expression*, the operand of a *delete-expression*, an integral constant
expression, or a condition in a ``switch`` statement.
C++14 decltype(auto)
^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_decltype_auto)`` or
``__has_extension(cxx_decltype_auto)`` to determine if support
for the ``decltype(auto)`` placeholder type is enabled.
C++14 default initializers for aggregates
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_aggregate_nsdmi)`` or
``__has_extension(cxx_aggregate_nsdmi)`` to determine if support
for default initializers in aggregate members is enabled.
C++14 digit separators
^^^^^^^^^^^^^^^^^^^^^^
Use ``__cpp_digit_separators`` to determine if support for digit separators
using single quotes (for instance, ``10'000``) is enabled. At this time, there
is no corresponding ``__has_feature`` name
C++14 generalized lambda capture
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_init_captures)`` or
``__has_extension(cxx_init_captures)`` to determine if support for
lambda captures with explicit initializers is enabled
(for instance, ``[n(0)] { return ++n; }``).
C++14 generic lambdas
^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_generic_lambdas)`` or
``__has_extension(cxx_generic_lambdas)`` to determine if support for generic
(polymorphic) lambdas is enabled
(for instance, ``[] (auto x) { return x + 1; }``).
C++14 relaxed constexpr
^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_relaxed_constexpr)`` or
``__has_extension(cxx_relaxed_constexpr)`` to determine if variable
declarations, local variable modification, and control flow constructs
are permitted in ``constexpr`` functions.
C++14 return type deduction
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_return_type_deduction)`` or
``__has_extension(cxx_return_type_deduction)`` to determine if support
for return type deduction for functions (using ``auto`` as a return type)
is enabled.
C++14 runtime-sized arrays
^^^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_runtime_array)`` or
``__has_extension(cxx_runtime_array)`` to determine if support
for arrays of runtime bound (a restricted form of variable-length arrays)
is enabled.
Clang's implementation of this feature is incomplete.
C++14 variable templates
^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(cxx_variable_templates)`` or
``__has_extension(cxx_variable_templates)`` to determine if support for
templated variable declarations is enabled.
C11
---
The features listed below are part of the C11 standard. As a result, all these
features are enabled with the ``-std=c11`` or ``-std=gnu11`` option when
compiling C code. Additionally, because these features are all
backward-compatible, they are available as extensions in all language modes.
C11 alignment specifiers
^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(c_alignas)`` or ``__has_extension(c_alignas)`` to determine
if support for alignment specifiers using ``_Alignas`` is enabled.
Use ``__has_feature(c_alignof)`` or ``__has_extension(c_alignof)`` to determine
if support for the ``_Alignof`` keyword is enabled.
C11 atomic operations
^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(c_atomic)`` or ``__has_extension(c_atomic)`` to determine
if support for atomic types using ``_Atomic`` is enabled. Clang also provides
:ref:`a set of builtins <langext-__c11_atomic>` which can be used to implement
the ``<stdatomic.h>`` operations on ``_Atomic`` types. Use
``__has_include(<stdatomic.h>)`` to determine if C11's ``<stdatomic.h>`` header
is available.
Clang will use the system's ``<stdatomic.h>`` header when one is available, and
will otherwise use its own. When using its own, implementations of the atomic
operations are provided as macros. In the cases where C11 also requires a real
function, this header provides only the declaration of that function (along
with a shadowing macro implementation), and you must link to a library which
provides a definition of the function if you use it instead of the macro.
C11 generic selections
^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(c_generic_selections)`` or
``__has_extension(c_generic_selections)`` to determine if support for generic
selections is enabled.
As an extension, the C11 generic selection expression is available in all
languages supported by Clang. The syntax is the same as that given in the C11
standard.
In C, type compatibility is decided according to the rules given in the
appropriate standard, but in C++, which lacks the type compatibility rules used
in C, types are considered compatible only if they are equivalent.
C11 ``_Static_assert()``
^^^^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(c_static_assert)`` or ``__has_extension(c_static_assert)``
to determine if support for compile-time assertions using ``_Static_assert`` is
enabled.
C11 ``_Thread_local``
^^^^^^^^^^^^^^^^^^^^^
Use ``__has_feature(c_thread_local)`` or ``__has_extension(c_thread_local)``
to determine if support for ``_Thread_local`` variables is enabled.
Modules
-------
Use ``__has_feature(modules)`` to determine if Modules have been enabled.
For example, compiling code with ``-fmodules`` enables the use of Modules.
More information could be found `here <https://clang.llvm.org/docs/Modules.html>`_.
Checks for Type Trait Primitives
================================
Type trait primitives are special builtin constant expressions that can be used
by the standard C++ library to facilitate or simplify the implementation of
user-facing type traits in the <type_traits> header.
They are not intended to be used directly by user code because they are
implementation-defined and subject to change -- as such they're tied closely to
the supported set of system headers, currently:
* LLVM's own libc++
* GNU libstdc++
* The Microsoft standard C++ library
Clang supports the `GNU C++ type traits
<http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html>`_ and a subset of the
`Microsoft Visual C++ Type traits
<http://msdn.microsoft.com/en-us/library/ms177194(v=VS.100).aspx>`_.
Feature detection is supported only for some of the primitives at present. User
code should not use these checks because they bear no direct relation to the
actual set of type traits supported by the C++ standard library.
For type trait ``__X``, ``__has_extension(X)`` indicates the presence of the
type trait primitive in the compiler. A simplistic usage example as might be
seen in standard C++ headers follows:
.. code-block:: c++
#if __has_extension(is_convertible_to)
template<typename From, typename To>
struct is_convertible_to {
static const bool value = __is_convertible_to(From, To);
};
#else
// Emulate type trait for compatibility with other compilers.
#endif
The following type trait primitives are supported by Clang:
* ``__has_nothrow_assign`` (GNU, Microsoft)
* ``__has_nothrow_copy`` (GNU, Microsoft)
* ``__has_nothrow_constructor`` (GNU, Microsoft)
* ``__has_trivial_assign`` (GNU, Microsoft)
* ``__has_trivial_copy`` (GNU, Microsoft)
* ``__has_trivial_constructor`` (GNU, Microsoft)
* ``__has_trivial_destructor`` (GNU, Microsoft)
* ``__has_virtual_destructor`` (GNU, Microsoft)
* ``__is_abstract`` (GNU, Microsoft)
* ``__is_aggregate`` (GNU, Microsoft)
* ``__is_base_of`` (GNU, Microsoft)
* ``__is_class`` (GNU, Microsoft)
* ``__is_convertible_to`` (Microsoft)
* ``__is_empty`` (GNU, Microsoft)
* ``__is_enum`` (GNU, Microsoft)
* ``__is_interface_class`` (Microsoft)
* ``__is_pod`` (GNU, Microsoft)
* ``__is_polymorphic`` (GNU, Microsoft)
* ``__is_union`` (GNU, Microsoft)
* ``__is_literal(type)``: Determines whether the given type is a literal type
* ``__is_final``: Determines whether the given type is declared with a
``final`` class-virt-specifier.
* ``__underlying_type(type)``: Retrieves the underlying type for a given
``enum`` type. This trait is required to implement the C++11 standard
library.
* ``__is_trivially_assignable(totype, fromtype)``: Determines whether a value
of type ``totype`` can be assigned to from a value of type ``fromtype`` such
that no non-trivial functions are called as part of that assignment. This
trait is required to implement the C++11 standard library.
* ``__is_trivially_constructible(type, argtypes...)``: Determines whether a
value of type ``type`` can be direct-initialized with arguments of types
``argtypes...`` such that no non-trivial functions are called as part of
that initialization. This trait is required to implement the C++11 standard
library.
* ``__is_destructible`` (MSVC 2013)
* ``__is_nothrow_destructible`` (MSVC 2013)
* ``__is_nothrow_assignable`` (MSVC 2013, clang)
* ``__is_constructible`` (MSVC 2013, clang)
* ``__is_nothrow_constructible`` (MSVC 2013, clang)
* ``__is_assignable`` (MSVC 2015, clang)
* ``__reference_binds_to_temporary(T, U)`` (Clang): Determines whether a
reference of type ``T`` bound to an expression of type ``U`` would bind to a
materialized temporary object. If ``T`` is not a reference type the result
is false. Note this trait will also return false when the initialization of
``T`` from ``U`` is ill-formed.
Blocks
======
The syntax and high level language feature description is in
:doc:`BlockLanguageSpec<BlockLanguageSpec>`. Implementation and ABI details for
the clang implementation are in :doc:`Block-ABI-Apple<Block-ABI-Apple>`.
Query for this feature with ``__has_extension(blocks)``.
Objective-C Features
====================
Related result types
--------------------
According to Cocoa conventions, Objective-C methods with certain names
("``init``", "``alloc``", etc.) always return objects that are an instance of
the receiving class's type. Such methods are said to have a "related result
type", meaning that a message send to one of these methods will have the same
static type as an instance of the receiver class. For example, given the
following classes:
.. code-block:: objc
@interface NSObject
+ (id)alloc;
- (id)init;
@end
@interface NSArray : NSObject
@end
and this common initialization pattern
.. code-block:: objc
NSArray *array = [[NSArray alloc] init];
the type of the expression ``[NSArray alloc]`` is ``NSArray*`` because
``alloc`` implicitly has a related result type. Similarly, the type of the
expression ``[[NSArray alloc] init]`` is ``NSArray*``, since ``init`` has a
related result type and its receiver is known to have the type ``NSArray *``.
If neither ``alloc`` nor ``init`` had a related result type, the expressions
would have had type ``id``, as declared in the method signature.
A method with a related result type can be declared by using the type
``instancetype`` as its result type. ``instancetype`` is a contextual keyword
that is only permitted in the result type of an Objective-C method, e.g.
.. code-block:: objc
@interface A
+ (instancetype)constructAnA;
@end
The related result type can also be inferred for some methods. To determine
whether a method has an inferred related result type, the first word in the
camel-case selector (e.g., "``init``" in "``initWithObjects``") is considered,
and the method will have a related result type if its return type is compatible
with the type of its class and if:
* the first word is "``alloc``" or "``new``", and the method is a class method,
or
* the first word is "``autorelease``", "``init``", "``retain``", or "``self``",
and the method is an instance method.
If a method with a related result type is overridden by a subclass method, the
subclass method must also return a type that is compatible with the subclass
type. For example:
.. code-block:: objc
@interface NSString : NSObject
- (NSUnrelated *)init; // incorrect usage: NSUnrelated is not NSString or a superclass of NSString
@end
Related result types only affect the type of a message send or property access
via the given method. In all other respects, a method with a related result
type is treated the same way as method that returns ``id``.
Use ``__has_feature(objc_instancetype)`` to determine whether the
``instancetype`` contextual keyword is available.
Automatic reference counting
----------------------------
Clang provides support for :doc:`automated reference counting
<AutomaticReferenceCounting>` in Objective-C, which eliminates the need
for manual ``retain``/``release``/``autorelease`` message sends. There are three
feature macros associated with automatic reference counting:
``__has_feature(objc_arc)`` indicates the availability of automated reference
counting in general, while ``__has_feature(objc_arc_weak)`` indicates that
automated reference counting also includes support for ``__weak`` pointers to
Objective-C objects. ``__has_feature(objc_arc_fields)`` indicates that C structs
are allowed to have fields that are pointers to Objective-C objects managed by
automatic reference counting.
.. _objc-weak:
Weak references
---------------
Clang supports ARC-style weak and unsafe references in Objective-C even
outside of ARC mode. Weak references must be explicitly enabled with
the ``-fobjc-weak`` option; use ``__has_feature((objc_arc_weak))``
to test whether they are enabled. Unsafe references are enabled
unconditionally. ARC-style weak and unsafe references cannot be used
when Objective-C garbage collection is enabled.
Except as noted below, the language rules for the ``__weak`` and
``__unsafe_unretained`` qualifiers (and the ``weak`` and
``unsafe_unretained`` property attributes) are just as laid out
in the :doc:`ARC specification <AutomaticReferenceCounting>`.
In particular, note that some classes do not support forming weak
references to their instances, and note that special care must be
taken when storing weak references in memory where initialization
and deinitialization are outside the responsibility of the compiler
(such as in ``malloc``-ed memory).
Loading from a ``__weak`` variable always implicitly retains the
loaded value. In non-ARC modes, this retain is normally balanced
by an implicit autorelease. This autorelease can be suppressed
by performing the load in the receiver position of a ``-retain``
message send (e.g. ``[weakReference retain]``); note that this performs
only a single retain (the retain done when primitively loading from
the weak reference).
For the most part, ``__unsafe_unretained`` in non-ARC modes is just the
default behavior of variables and therefore is not needed. However,
it does have an effect on the semantics of block captures: normally,
copying a block which captures an Objective-C object or block pointer
causes the captured pointer to be retained or copied, respectively,
but that behavior is suppressed when the captured variable is qualified
with ``__unsafe_unretained``.
Note that the ``__weak`` qualifier formerly meant the GC qualifier in
all non-ARC modes and was silently ignored outside of GC modes. It now
means the ARC-style qualifier in all non-GC modes and is no longer
allowed if not enabled by either ``-fobjc-arc`` or ``-fobjc-weak``.
It is expected that ``-fobjc-weak`` will eventually be enabled by default
in all non-GC Objective-C modes.
.. _objc-fixed-enum:
Enumerations with a fixed underlying type
-----------------------------------------
Clang provides support for C++11 enumerations with a fixed underlying type
within Objective-C. For example, one can write an enumeration type as:
.. code-block:: c++
typedef enum : unsigned char { Red, Green, Blue } Color;
This specifies that the underlying type, which is used to store the enumeration
value, is ``unsigned char``.
Use ``__has_feature(objc_fixed_enum)`` to determine whether support for fixed
underlying types is available in Objective-C.
Interoperability with C++11 lambdas
-----------------------------------
Clang provides interoperability between C++11 lambdas and blocks-based APIs, by
permitting a lambda to be implicitly converted to a block pointer with the
corresponding signature. For example, consider an API such as ``NSArray``'s
array-sorting method:
.. code-block:: objc
- (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr;
``NSComparator`` is simply a typedef for the block pointer ``NSComparisonResult
(^)(id, id)``, and parameters of this type are generally provided with block
literals as arguments. However, one can also use a C++11 lambda so long as it
provides the same signature (in this case, accepting two parameters of type
``id`` and returning an ``NSComparisonResult``):
.. code-block:: objc
NSArray *array = @[@"string 1", @"string 21", @"string 12", @"String 11",
@"String 02"];
const NSStringCompareOptions comparisonOptions
= NSCaseInsensitiveSearch | NSNumericSearch |
NSWidthInsensitiveSearch | NSForcedOrderingSearch;
NSLocale *currentLocale = [NSLocale currentLocale];
NSArray *sorted
= [array sortedArrayUsingComparator:[=](id s1, id s2) -> NSComparisonResult {
NSRange string1Range = NSMakeRange(0, [s1 length]);
return [s1 compare:s2 options:comparisonOptions
range:string1Range locale:currentLocale];
}];
NSLog(@"sorted: %@", sorted);
This code relies on an implicit conversion from the type of the lambda
expression (an unnamed, local class type called the *closure type*) to the
corresponding block pointer type. The conversion itself is expressed by a
conversion operator in that closure type that produces a block pointer with the
same signature as the lambda itself, e.g.,
.. code-block:: objc
operator NSComparisonResult (^)(id, id)() const;
This conversion function returns a new block that simply forwards the two
parameters to the lambda object (which it captures by copy), then returns the
result. The returned block is first copied (with ``Block_copy``) and then
autoreleased. As an optimization, if a lambda expression is immediately
converted to a block pointer (as in the first example, above), then the block
is not copied and autoreleased: rather, it is given the same lifetime as a
block literal written at that point in the program, which avoids the overhead
of copying a block to the heap in the common case.
The conversion from a lambda to a block pointer is only available in
Objective-C++, and not in C++ with blocks, due to its use of Objective-C memory
management (autorelease).
Object Literals and Subscripting
--------------------------------
Clang provides support for :doc:`Object Literals and Subscripting
<ObjectiveCLiterals>` in Objective-C, which simplifies common Objective-C
programming patterns, makes programs more concise, and improves the safety of
container creation. There are several feature macros associated with object
literals and subscripting: ``__has_feature(objc_array_literals)`` tests the
availability of array literals; ``__has_feature(objc_dictionary_literals)``
tests the availability of dictionary literals;
``__has_feature(objc_subscripting)`` tests the availability of object
subscripting.
Objective-C Autosynthesis of Properties
---------------------------------------
Clang provides support for autosynthesis of declared properties. Using this
feature, clang provides default synthesis of those properties not declared
@dynamic and not having user provided backing getter and setter methods.
``__has_feature(objc_default_synthesize_properties)`` checks for availability
of this feature in version of clang being used.
.. _langext-objc-retain-release:
Objective-C retaining behavior attributes
-----------------------------------------
In Objective-C, functions and methods are generally assumed to follow the
`Cocoa Memory Management
<http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html>`_
conventions for ownership of object arguments and
return values. However, there are exceptions, and so Clang provides attributes
to allow these exceptions to be documented. This are used by ARC and the
`static analyzer <https://clang-analyzer.llvm.org>`_ Some exceptions may be
better described using the ``objc_method_family`` attribute instead.
**Usage**: The ``ns_returns_retained``, ``ns_returns_not_retained``,
``ns_returns_autoreleased``, ``cf_returns_retained``, and
``cf_returns_not_retained`` attributes can be placed on methods and functions
that return Objective-C or CoreFoundation objects. They are commonly placed at
the end of a function prototype or method declaration:
.. code-block:: objc
id foo() __attribute__((ns_returns_retained));
- (NSString *)bar:(int)x __attribute__((ns_returns_retained));
The ``*_returns_retained`` attributes specify that the returned object has a +1
retain count. The ``*_returns_not_retained`` attributes specify that the return
object has a +0 retain count, even if the normal convention for its selector
would be +1. ``ns_returns_autoreleased`` specifies that the returned object is
+0, but is guaranteed to live at least as long as the next flush of an
autorelease pool.
**Usage**: The ``ns_consumed`` and ``cf_consumed`` attributes can be placed on
an parameter declaration; they specify that the argument is expected to have a
+1 retain count, which will be balanced in some way by the function or method.
The ``ns_consumes_self`` attribute can only be placed on an Objective-C
method; it specifies that the method expects its ``self`` parameter to have a
+1 retain count, which it will balance in some way.
.. code-block:: objc
void foo(__attribute__((ns_consumed)) NSString *string);
- (void) bar __attribute__((ns_consumes_self));
- (void) baz:(id) __attribute__((ns_consumed)) x;
Further examples of these attributes are available in the static analyzer's `list of annotations for analysis
<https://clang-analyzer.llvm.org/annotations.html#cocoa_mem>`_.
Query for these features with ``__has_attribute(ns_consumed)``,
``__has_attribute(ns_returns_retained)``, etc.
Objective-C @available
----------------------
It is possible to use the newest SDK but still build a program that can run on
older versions of macOS and iOS by passing ``-mmacosx-version-min=`` /
``-miphoneos-version-min=``.
Before LLVM 5.0, when calling a function that exists only in the OS that's
newer than the target OS (as determined by the minimum deployment version),
programmers had to carefully check if the function exists at runtime, using
null checks for weakly-linked C functions, ``+class`` for Objective-C classes,
and ``-respondsToSelector:`` or ``+instancesRespondToSelector:`` for
Objective-C methods. If such a check was missed, the program would compile
fine, run fine on newer systems, but crash on older systems.
As of LLVM 5.0, ``-Wunguarded-availability`` uses the `availability attributes
<https://clang.llvm.org/docs/AttributeReference.html#availability>`_ together
with the new ``@available()`` keyword to assist with this issue.
When a method that's introduced in the OS newer than the target OS is called, a
-Wunguarded-availability warning is emitted if that call is not guarded:
.. code-block:: objc
void my_fun(NSSomeClass* var) {
// If fancyNewMethod was added in e.g. macOS 10.12, but the code is
// built with -mmacosx-version-min=10.11, then this unconditional call
// will emit a -Wunguarded-availability warning:
[var fancyNewMethod];
}
To fix the warning and to avoid the crash on macOS 10.11, wrap it in
``if(@available())``:
.. code-block:: objc
void my_fun(NSSomeClass* var) {
if (@available(macOS 10.12, *)) {
[var fancyNewMethod];
} else {
// Put fallback behavior for old macOS versions (and for non-mac
// platforms) here.
}
}
The ``*`` is required and means that platforms not explicitly listed will take
the true branch, and the compiler will emit ``-Wunguarded-availability``
warnings for unlisted platforms based on those platform's deployment target.
More than one platform can be listed in ``@available()``:
.. code-block:: objc
void my_fun(NSSomeClass* var) {
if (@available(macOS 10.12, iOS 10, *)) {
[var fancyNewMethod];
}
}
If the caller of ``my_fun()`` already checks that ``my_fun()`` is only called
on 10.12, then add an `availability attribute
<https://clang.llvm.org/docs/AttributeReference.html#availability>`_ to it,
which will also suppress the warning and require that calls to my_fun() are
checked:
.. code-block:: objc
API_AVAILABLE(macos(10.12)) void my_fun(NSSomeClass* var) {
[var fancyNewMethod]; // Now ok.
}
``@available()`` is only available in Objective-C code. To use the feature
in C and C++ code, use the ``__builtin_available()`` spelling instead.
If existing code uses null checks or ``-respondsToSelector:``, it should
be changed to use ``@available()`` (or ``__builtin_available``) instead.
``-Wunguarded-availability`` is disabled by default, but
``-Wunguarded-availability-new``, which only emits this warning for APIs
that have been introduced in macOS >= 10.13, iOS >= 11, watchOS >= 4 and
tvOS >= 11, is enabled by default.
.. _langext-overloading:
Objective-C++ ABI: protocol-qualifier mangling of parameters
------------------------------------------------------------
Starting with LLVM 3.4, Clang produces a new mangling for parameters whose
type is a qualified-``id`` (e.g., ``id<Foo>``). This mangling allows such
parameters to be differentiated from those with the regular unqualified ``id``
type.
This was a non-backward compatible mangling change to the ABI. This change
allows proper overloading, and also prevents mangling conflicts with template
parameters of protocol-qualified type.
Query the presence of this new mangling with
``__has_feature(objc_protocol_qualifier_mangling)``.
Initializer lists for complex numbers in C
==========================================
clang supports an extension which allows the following in C:
.. code-block:: c++
#include <math.h>
#include <complex.h>
complex float x = { 1.0f, INFINITY }; // Init to (1, Inf)
This construct is useful because there is no way to separately initialize the
real and imaginary parts of a complex variable in standard C, given that clang
does not support ``_Imaginary``. (Clang also supports the ``__real__`` and
``__imag__`` extensions from gcc, which help in some cases, but are not usable
in static initializers.)
Note that this extension does not allow eliding the braces; the meaning of the
following two lines is different:
.. code-block:: c++
complex float x[] = { { 1.0f, 1.0f } }; // [0] = (1, 1)
complex float x[] = { 1.0f, 1.0f }; // [0] = (1, 0), [1] = (1, 0)
This extension also works in C++ mode, as far as that goes, but does not apply
to the C++ ``std::complex``. (In C++11, list initialization allows the same
syntax to be used with ``std::complex`` with the same meaning.)
Builtin Functions
=================
Clang supports a number of builtin library functions with the same syntax as
GCC, including things like ``__builtin_nan``, ``__builtin_constant_p``,
``__builtin_choose_expr``, ``__builtin_types_compatible_p``,
``__builtin_assume_aligned``, ``__sync_fetch_and_add``, etc. In addition to
the GCC builtins, Clang supports a number of builtins that GCC does not, which
are listed here.
Please note that Clang does not and will not support all of the GCC builtins
for vector operations. Instead of using builtins, you should use the functions
defined in target-specific header files like ``<xmmintrin.h>``, which define
portable wrappers for these. Many of the Clang versions of these functions are
implemented directly in terms of :ref:`extended vector support
<langext-vectors>` instead of builtins, in order to reduce the number of
builtins that we need to implement.
``__builtin_assume``
------------------------------
``__builtin_assume`` is used to provide the optimizer with a boolean
invariant that is defined to be true.
**Syntax**:
.. code-block:: c++
__builtin_assume(bool)
**Example of Use**:
.. code-block:: c++
int foo(int x) {
__builtin_assume(x != 0);
// The optimizer may short-circuit this check using the invariant.
if (x == 0)
return do_something();
return do_something_else();
}
**Description**:
The boolean argument to this function is defined to be true. The optimizer may
analyze the form of the expression provided as the argument and deduce from
that information used to optimize the program. If the condition is violated
during execution, the behavior is undefined. The argument itself is never
evaluated, so any side effects of the expression will be discarded.
Query for this feature with ``__has_builtin(__builtin_assume)``.
``__builtin_readcyclecounter``
------------------------------
``__builtin_readcyclecounter`` is used to access the cycle counter register (or
a similar low-latency, high-accuracy clock) on those targets that support it.
**Syntax**:
.. code-block:: c++
__builtin_readcyclecounter()
**Example of Use**:
.. code-block:: c++
unsigned long long t0 = __builtin_readcyclecounter();
do_something();
unsigned long long t1 = __builtin_readcyclecounter();
unsigned long long cycles_to_do_something = t1 - t0; // assuming no overflow
**Description**:
The ``__builtin_readcyclecounter()`` builtin returns the cycle counter value,
which may be either global or process/thread-specific depending on the target.
As the backing counters often overflow quickly (on the order of seconds) this
should only be used for timing small intervals. When not supported by the
target, the return value is always zero. This builtin takes no arguments and
produces an unsigned long long result.
Query for this feature with ``__has_builtin(__builtin_readcyclecounter)``. Note
that even if present, its use may depend on run-time privilege or other OS
controlled state.
.. _langext-__builtin_shufflevector:
``__builtin_shufflevector``
---------------------------
``__builtin_shufflevector`` is used to express generic vector
permutation/shuffle/swizzle operations. This builtin is also very important
for the implementation of various target-specific header files like
``<xmmintrin.h>``.
**Syntax**:
.. code-block:: c++
__builtin_shufflevector(vec1, vec2, index1, index2, ...)
**Examples**:
.. code-block:: c++
// identity operation - return 4-element vector v1.
__builtin_shufflevector(v1, v1, 0, 1, 2, 3)
// "Splat" element 0 of V1 into a 4-element result.
__builtin_shufflevector(V1, V1, 0, 0, 0, 0)
// Reverse 4-element vector V1.
__builtin_shufflevector(V1, V1, 3, 2, 1, 0)
// Concatenate every other element of 4-element vectors V1 and V2.
__builtin_shufflevector(V1, V2, 0, 2, 4, 6)
// Concatenate every other element of 8-element vectors V1 and V2.
__builtin_shufflevector(V1, V2, 0, 2, 4, 6, 8, 10, 12, 14)
// Shuffle v1 with some elements being undefined
__builtin_shufflevector(v1, v1, 3, -1, 1, -1)
**Description**:
The first two arguments to ``__builtin_shufflevector`` are vectors that have
the same element type. The remaining arguments are a list of integers that
specify the elements indices of the first two vectors that should be extracted
and returned in a new vector. These element indices are numbered sequentially
starting with the first vector, continuing into the second vector. Thus, if
``vec1`` is a 4-element vector, index 5 would refer to the second element of
``vec2``. An index of -1 can be used to indicate that the corresponding element
in the returned vector is a don't care and can be optimized by the backend.
The result of ``__builtin_shufflevector`` is a vector with the same element
type as ``vec1``/``vec2`` but that has an element count equal to the number of
indices specified.
Query for this feature with ``__has_builtin(__builtin_shufflevector)``.
.. _langext-__builtin_convertvector:
``__builtin_convertvector``
---------------------------
``__builtin_convertvector`` is used to express generic vector
type-conversion operations. The input vector and the output vector
type must have the same number of elements.
**Syntax**:
.. code-block:: c++
__builtin_convertvector(src_vec, dst_vec_type)
**Examples**:
.. code-block:: c++
typedef double vector4double __attribute__((__vector_size__(32)));
typedef float vector4float __attribute__((__vector_size__(16)));
typedef short vector4short __attribute__((__vector_size__(8)));
vector4float vf; vector4short vs;
// convert from a vector of 4 floats to a vector of 4 doubles.
__builtin_convertvector(vf, vector4double)
// equivalent to:
(vector4double) { (double) vf[0], (double) vf[1], (double) vf[2], (double) vf[3] }
// convert from a vector of 4 shorts to a vector of 4 floats.
__builtin_convertvector(vs, vector4float)
// equivalent to:
(vector4float) { (float) vs[0], (float) vs[1], (float) vs[2], (float) vs[3] }
**Description**:
The first argument to ``__builtin_convertvector`` is a vector, and the second
argument is a vector type with the same number of elements as the first
argument.
The result of ``__builtin_convertvector`` is a vector with the same element
type as the second argument, with a value defined in terms of the action of a
C-style cast applied to each element of the first argument.
Query for this feature with ``__has_builtin(__builtin_convertvector)``.
``__builtin_bitreverse``
------------------------
* ``__builtin_bitreverse8``
* ``__builtin_bitreverse16``
* ``__builtin_bitreverse32``
* ``__builtin_bitreverse64``
**Syntax**:
.. code-block:: c++
__builtin_bitreverse32(x)
**Examples**:
.. code-block:: c++
uint8_t rev_x = __builtin_bitreverse8(x);
uint16_t rev_x = __builtin_bitreverse16(x);
uint32_t rev_y = __builtin_bitreverse32(y);
uint64_t rev_z = __builtin_bitreverse64(z);
**Description**:
The '``__builtin_bitreverse``' family of builtins is used to reverse
the bitpattern of an integer value; for example ``0b10110110`` becomes
``0b01101101``.
``__builtin_rotateleft``
------------------------
* ``__builtin_rotateleft8``
* ``__builtin_rotateleft16``
* ``__builtin_rotateleft32``
* ``__builtin_rotateleft64``
**Syntax**:
.. code-block:: c++
__builtin_rotateleft32(x, y)
**Examples**:
.. code-block:: c++
uint8_t rot_x = __builtin_rotateleft8(x, y);
uint16_t rot_x = __builtin_rotateleft16(x, y);
uint32_t rot_x = __builtin_rotateleft32(x, y);
uint64_t rot_x = __builtin_rotateleft64(x, y);
**Description**:
The '``__builtin_rotateleft``' family of builtins is used to rotate
the bits in the first argument by the amount in the second argument.
For example, ``0b10000110`` rotated left by 11 becomes ``0b00110100``.
The shift value is treated as an unsigned amount modulo the size of
the arguments. Both arguments and the result have the bitwidth specified
by the name of the builtin.
``__builtin_rotateright``
_------------------------
* ``__builtin_rotateright8``
* ``__builtin_rotateright16``
* ``__builtin_rotateright32``
* ``__builtin_rotateright64``
**Syntax**:
.. code-block:: c++
__builtin_rotateright32(x, y)
**Examples**:
.. code-block:: c++
uint8_t rot_x = __builtin_rotateright8(x, y);
uint16_t rot_x = __builtin_rotateright16(x, y);
uint32_t rot_x = __builtin_rotateright32(x, y);
uint64_t rot_x = __builtin_rotateright64(x, y);
**Description**:
The '``__builtin_rotateright``' family of builtins is used to rotate
the bits in the first argument by the amount in the second argument.
For example, ``0b10000110`` rotated right by 3 becomes ``0b11010000``.
The shift value is treated as an unsigned amount modulo the size of
the arguments. Both arguments and the result have the bitwidth specified
by the name of the builtin.
``__builtin_unreachable``
-------------------------
``__builtin_unreachable`` is used to indicate that a specific point in the
program cannot be reached, even if the compiler might otherwise think it can.
This is useful to improve optimization and eliminates certain warnings. For
example, without the ``__builtin_unreachable`` in the example below, the
compiler assumes that the inline asm can fall through and prints a "function
declared '``noreturn``' should not return" warning.
**Syntax**:
.. code-block:: c++
__builtin_unreachable()
**Example of use**:
.. code-block:: c++
void myabort(void) __attribute__((noreturn));
void myabort(void) {
asm("int3");
__builtin_unreachable();
}
**Description**:
The ``__builtin_unreachable()`` builtin has completely undefined behavior.
Since it has undefined behavior, it is a statement that it is never reached and
the optimizer can take advantage of this to produce better code. This builtin
takes no arguments and produces a void result.
Query for this feature with ``__has_builtin(__builtin_unreachable)``.
``__builtin_unpredictable``
---------------------------
``__builtin_unpredictable`` is used to indicate that a branch condition is
unpredictable by hardware mechanisms such as branch prediction logic.
**Syntax**:
.. code-block:: c++
__builtin_unpredictable(long long)
**Example of use**:
.. code-block:: c++
if (__builtin_unpredictable(x > 0)) {
foo();
}
**Description**:
The ``__builtin_unpredictable()`` builtin is expected to be used with control
flow conditions such as in ``if`` and ``switch`` statements.
Query for this feature with ``__has_builtin(__builtin_unpredictable)``.
``__sync_swap``
---------------
``__sync_swap`` is used to atomically swap integers or pointers in memory.
**Syntax**:
.. code-block:: c++
type __sync_swap(type *ptr, type value, ...)
**Example of Use**:
.. code-block:: c++
int old_value = __sync_swap(&value, new_value);
**Description**:
The ``__sync_swap()`` builtin extends the existing ``__sync_*()`` family of
atomic intrinsics to allow code to atomically swap the current value with the
new value. More importantly, it helps developers write more efficient and
correct code by avoiding expensive loops around
``__sync_bool_compare_and_swap()`` or relying on the platform specific
implementation details of ``__sync_lock_test_and_set()``. The
``__sync_swap()`` builtin is a full barrier.
``__builtin_addressof``
-----------------------
``__builtin_addressof`` performs the functionality of the built-in ``&``
operator, ignoring any ``operator&`` overload. This is useful in constant
expressions in C++11, where there is no other way to take the address of an
object that overloads ``operator&``.
**Example of use**:
.. code-block:: c++
template<typename T> constexpr T *addressof(T &value) {
return __builtin_addressof(value);
}
``__builtin_operator_new`` and ``__builtin_operator_delete``
------------------------------------------------------------
``__builtin_operator_new`` allocates memory just like a non-placement non-class
*new-expression*. This is exactly like directly calling the normal
non-placement ``::operator new``, except that it allows certain optimizations
that the C++ standard does not permit for a direct function call to
``::operator new`` (in particular, removing ``new`` / ``delete`` pairs and
merging allocations).
Likewise, ``__builtin_operator_delete`` deallocates memory just like a
non-class *delete-expression*, and is exactly like directly calling the normal
``::operator delete``, except that it permits optimizations. Only the unsized
form of ``__builtin_operator_delete`` is currently available.
These builtins are intended for use in the implementation of ``std::allocator``
and other similar allocation libraries, and are only available in C++.
Multiprecision Arithmetic Builtins
----------------------------------
Clang provides a set of builtins which expose multiprecision arithmetic in a
manner amenable to C. They all have the following form:
.. code-block:: c
unsigned x = ..., y = ..., carryin = ..., carryout;
unsigned sum = __builtin_addc(x, y, carryin, &carryout);
Thus one can form a multiprecision addition chain in the following manner:
.. code-block:: c
unsigned *x, *y, *z, carryin=0, carryout;
z[0] = __builtin_addc(x[0], y[0], carryin, &carryout);
carryin = carryout;
z[1] = __builtin_addc(x[1], y[1], carryin, &carryout);
carryin = carryout;
z[2] = __builtin_addc(x[2], y[2], carryin, &carryout);
carryin = carryout;
z[3] = __builtin_addc(x[3], y[3], carryin, &carryout);
The complete list of builtins are:
.. code-block:: c
unsigned char __builtin_addcb (unsigned char x, unsigned char y, unsigned char carryin, unsigned char *carryout);
unsigned short __builtin_addcs (unsigned short x, unsigned short y, unsigned short carryin, unsigned short *carryout);
unsigned __builtin_addc (unsigned x, unsigned y, unsigned carryin, unsigned *carryout);
unsigned long __builtin_addcl (unsigned long x, unsigned long y, unsigned long carryin, unsigned long *carryout);
unsigned long long __builtin_addcll(unsigned long long x, unsigned long long y, unsigned long long carryin, unsigned long long *carryout);
unsigned char __builtin_subcb (unsigned char x, unsigned char y, unsigned char carryin, unsigned char *carryout);
unsigned short __builtin_subcs (unsigned short x, unsigned short y, unsigned short carryin, unsigned short *carryout);
unsigned __builtin_subc (unsigned x, unsigned y, unsigned carryin, unsigned *carryout);
unsigned long __builtin_subcl (unsigned long x, unsigned long y, unsigned long carryin, unsigned long *carryout);
unsigned long long __builtin_subcll(unsigned long long x, unsigned long long y, unsigned long long carryin, unsigned long long *carryout);
Checked Arithmetic Builtins
---------------------------
Clang provides a set of builtins that implement checked arithmetic for security
critical applications in a manner that is fast and easily expressable in C. As
an example of their usage:
.. code-block:: c
errorcode_t security_critical_application(...) {
unsigned x, y, result;
...
if (__builtin_mul_overflow(x, y, &result))
return kErrorCodeHackers;
...
use_multiply(result);
...
}
Clang provides the following checked arithmetic builtins:
.. code-block:: c
bool __builtin_add_overflow (type1 x, type2 y, type3 *sum);
bool __builtin_sub_overflow (type1 x, type2 y, type3 *diff);
bool __builtin_mul_overflow (type1 x, type2 y, type3 *prod);
bool __builtin_uadd_overflow (unsigned x, unsigned y, unsigned *sum);
bool __builtin_uaddl_overflow (unsigned long x, unsigned long y, unsigned long *sum);
bool __builtin_uaddll_overflow(unsigned long long x, unsigned long long y, unsigned long long *sum);
bool __builtin_usub_overflow (unsigned x, unsigned y, unsigned *diff);
bool __builtin_usubl_overflow (unsigned long x, unsigned long y, unsigned long *diff);
bool __builtin_usubll_overflow(unsigned long long x, unsigned long long y, unsigned long long *diff);
bool __builtin_umul_overflow (unsigned x, unsigned y, unsigned *prod);
bool __builtin_umull_overflow (unsigned long x, unsigned long y, unsigned long *prod);
bool __builtin_umulll_overflow(unsigned long long x, unsigned long long y, unsigned long long *prod);
bool __builtin_sadd_overflow (int x, int y, int *sum);
bool __builtin_saddl_overflow (long x, long y, long *sum);
bool __builtin_saddll_overflow(long long x, long long y, long long *sum);
bool __builtin_ssub_overflow (int x, int y, int *diff);
bool __builtin_ssubl_overflow (long x, long y, long *diff);
bool __builtin_ssubll_overflow(long long x, long long y, long long *diff);
bool __builtin_smul_overflow (int x, int y, int *prod);
bool __builtin_smull_overflow (long x, long y, long *prod);
bool __builtin_smulll_overflow(long long x, long long y, long long *prod);
Each builtin performs the specified mathematical operation on the
first two arguments and stores the result in the third argument. If
possible, the result will be equal to mathematically-correct result
and the builtin will return 0. Otherwise, the builtin will return
1 and the result will be equal to the unique value that is equivalent
to the mathematically-correct result modulo two raised to the *k*
power, where *k* is the number of bits in the result type. The
behavior of these builtins is well-defined for all argument values.
The first three builtins work generically for operands of any integer type,
including boolean types. The operands need not have the same type as each
other, or as the result. The other builtins may implicitly promote or
convert their operands before performing the operation.
Query for this feature with ``__has_builtin(__builtin_add_overflow)``, etc.
Floating point builtins
---------------------------------------
``__builtin_canonicalize``
--------------------------
.. code-block:: c
double __builtin_canonicalize(double);
float __builtin_canonicalizef(float);
long double__builtin_canonicalizel(long double);
Returns the platform specific canonical encoding of a floating point
number. This canonicalization is useful for implementing certain
numeric primitives such as frexp. See `LLVM canonicalize intrinsic
<https://llvm.org/docs/LangRef.html#llvm-canonicalize-intrinsic>`_ for
more information on the semantics.
String builtins
---------------
Clang provides constant expression evaluation support for builtins forms of
the following functions from the C standard library ``<string.h>`` header:
* ``memchr``
* ``memcmp``
* ``strchr``
* ``strcmp``
* ``strlen``
* ``strncmp``
* ``wcschr``
* ``wcscmp``
* ``wcslen``
* ``wcsncmp``
* ``wmemchr``
* ``wmemcmp``
In each case, the builtin form has the name of the C library function prefixed
by ``__builtin_``. Example:
.. code-block:: c
void *p = __builtin_memchr("foobar", 'b', 5);
In addition to the above, one further builtin is provided:
.. code-block:: c
char *__builtin_char_memchr(const char *haystack, int needle, size_t size);
``__builtin_char_memchr(a, b, c)`` is identical to
``(char*)__builtin_memchr(a, b, c)`` except that its use is permitted within
constant expressions in C++11 onwards (where a cast from ``void*`` to ``char*``
is disallowed in general).
Support for constant expression evaluation for the above builtins be detected
with ``__has_feature(cxx_constexpr_string_builtins)``.
Atomic Min/Max builtins with memory ordering
--------------------------------------------
There are two atomic builtins with min/max in-memory comparison and swap.
The syntax and semantics are similar to GCC-compatible __atomic_* builtins.
* ``__atomic_fetch_min``
* ``__atomic_fetch_max``
The builtins work with signed and unsigned integers and require to specify memory ordering.
The return value is the original value that was stored in memory before comparison.
Example:
.. code-block:: c
unsigned int val = __atomic_fetch_min(unsigned int *pi, unsigned int ui, __ATOMIC_RELAXED);
The third argument is one of the memory ordering specifiers ``__ATOMIC_RELAXED``,
``__ATOMIC_CONSUME``, ``__ATOMIC_ACQUIRE``, ``__ATOMIC_RELEASE``,
``__ATOMIC_ACQ_REL``, or ``__ATOMIC_SEQ_CST`` following C++11 memory model semantics.
In terms or aquire-release ordering barriers these two operations are always
considered as operations with *load-store* semantics, even when the original value
is not actually modified after comparison.
.. _langext-__c11_atomic:
__c11_atomic builtins
---------------------
Clang provides a set of builtins which are intended to be used to implement
C11's ``<stdatomic.h>`` header. These builtins provide the semantics of the
``_explicit`` form of the corresponding C11 operation, and are named with a
``__c11_`` prefix. The supported operations, and the differences from
the corresponding C11 operations, are:
* ``__c11_atomic_init``
* ``__c11_atomic_thread_fence``
* ``__c11_atomic_signal_fence``
* ``__c11_atomic_is_lock_free`` (The argument is the size of the
``_Atomic(...)`` object, instead of its address)
* ``__c11_atomic_store``
* ``__c11_atomic_load``
* ``__c11_atomic_exchange``
* ``__c11_atomic_compare_exchange_strong``
* ``__c11_atomic_compare_exchange_weak``
* ``__c11_atomic_fetch_add``
* ``__c11_atomic_fetch_sub``
* ``__c11_atomic_fetch_and``
* ``__c11_atomic_fetch_or``
* ``__c11_atomic_fetch_xor``
The macros ``__ATOMIC_RELAXED``, ``__ATOMIC_CONSUME``, ``__ATOMIC_ACQUIRE``,
``__ATOMIC_RELEASE``, ``__ATOMIC_ACQ_REL``, and ``__ATOMIC_SEQ_CST`` are
provided, with values corresponding to the enumerators of C11's
``memory_order`` enumeration.
(Note that Clang additionally provides GCC-compatible ``__atomic_*``
builtins and OpenCL 2.0 ``__opencl_atomic_*`` builtins. The OpenCL 2.0
atomic builtins are an explicit form of the corresponding OpenCL 2.0
builtin function, and are named with a ``__opencl_`` prefix. The macros
``__OPENCL_MEMORY_SCOPE_WORK_ITEM``, ``__OPENCL_MEMORY_SCOPE_WORK_GROUP``,
``__OPENCL_MEMORY_SCOPE_DEVICE``, ``__OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES``,
and ``__OPENCL_MEMORY_SCOPE_SUB_GROUP`` are provided, with values
corresponding to the enumerators of OpenCL's ``memory_scope`` enumeration.)
Low-level ARM exclusive memory builtins
---------------------------------------
Clang provides overloaded builtins giving direct access to the three key ARM
instructions for implementing atomic operations.
.. code-block:: c
T __builtin_arm_ldrex(const volatile T *addr);
T __builtin_arm_ldaex(const volatile T *addr);
int __builtin_arm_strex(T val, volatile T *addr);
int __builtin_arm_stlex(T val, volatile T *addr);
void __builtin_arm_clrex(void);
The types ``T`` currently supported are:
* Integer types with width at most 64 bits (or 128 bits on AArch64).
* Floating-point types
* Pointer types.
Note that the compiler does not guarantee it will not insert stores which clear
the exclusive monitor in between an ``ldrex`` type operation and its paired
``strex``. In practice this is only usually a risk when the extra store is on
the same cache line as the variable being modified and Clang will only insert
stack stores on its own, so it is best not to use these operations on variables
with automatic storage duration.
Also, loads and stores may be implicit in code written between the ``ldrex`` and
``strex``. Clang will not necessarily mitigate the effects of these either, so
care should be exercised.
For these reasons the higher level atomic primitives should be preferred where
possible.
Non-temporal load/store builtins
--------------------------------
Clang provides overloaded builtins allowing generation of non-temporal memory
accesses.
.. code-block:: c
T __builtin_nontemporal_load(T *addr);
void __builtin_nontemporal_store(T value, T *addr);
The types ``T`` currently supported are:
* Integer types.
* Floating-point types.
* Vector types.
Note that the compiler does not guarantee that non-temporal loads or stores
will be used.
C++ Coroutines support builtins
--------------------------------
.. warning::
This is a work in progress. Compatibility across Clang/LLVM releases is not
guaranteed.
Clang provides experimental builtins to support C++ Coroutines as defined by
http://wg21.link/P0057. The following four are intended to be used by the
standard library to implement `std::experimental::coroutine_handle` type.
**Syntax**:
.. code-block:: c
void __builtin_coro_resume(void *addr);
void __builtin_coro_destroy(void *addr);
bool __builtin_coro_done(void *addr);
void *__builtin_coro_promise(void *addr, int alignment, bool from_promise)
**Example of use**:
.. code-block:: c++
template <> struct coroutine_handle<void> {
void resume() const { __builtin_coro_resume(ptr); }
void destroy() const { __builtin_coro_destroy(ptr); }
bool done() const { return __builtin_coro_done(ptr); }
// ...
protected:
void *ptr;
};
template <typename Promise> struct coroutine_handle : coroutine_handle<> {
// ...
Promise &promise() const {
return *reinterpret_cast<Promise *>(
__builtin_coro_promise(ptr, alignof(Promise), /*from-promise=*/false));
}
static coroutine_handle from_promise(Promise &promise) {
coroutine_handle p;
p.ptr = __builtin_coro_promise(&promise, alignof(Promise),
/*from-promise=*/true);
return p;
}
};
Other coroutine builtins are either for internal clang use or for use during
development of the coroutine feature. See `Coroutines in LLVM
<https://llvm.org/docs/Coroutines.html#intrinsics>`_ for
more information on their semantics. Note that builtins matching the intrinsics
that take token as the first parameter (llvm.coro.begin, llvm.coro.alloc,
llvm.coro.free and llvm.coro.suspend) omit the token parameter and fill it to
an appropriate value during the emission.
**Syntax**:
.. code-block:: c
size_t __builtin_coro_size()
void *__builtin_coro_frame()
void *__builtin_coro_free(void *coro_frame)
void *__builtin_coro_id(int align, void *promise, void *fnaddr, void *parts)
bool __builtin_coro_alloc()
void *__builtin_coro_begin(void *memory)
void __builtin_coro_end(void *coro_frame, bool unwind)
char __builtin_coro_suspend(bool final)
bool __builtin_coro_param(void *original, void *copy)
Note that there is no builtin matching the `llvm.coro.save` intrinsic. LLVM
automatically will insert one if the first argument to `llvm.coro.suspend` is
token `none`. If a user calls `__builin_suspend`, clang will insert `token none`
as the first argument to the intrinsic.
Non-standard C++11 Attributes
=============================
Clang's non-standard C++11 attributes live in the ``clang`` attribute
namespace.
Clang supports GCC's ``gnu`` attribute namespace. All GCC attributes which
are accepted with the ``__attribute__((foo))`` syntax are also accepted as
``[[gnu::foo]]``. This only extends to attributes which are specified by GCC
(see the list of `GCC function attributes
<http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html>`_, `GCC variable
attributes <http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html>`_, and
`GCC type attributes
<http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html>`_). As with the GCC
implementation, these attributes must appertain to the *declarator-id* in a
declaration, which means they must go either at the start of the declaration or
immediately after the name being declared.
For example, this applies the GNU ``unused`` attribute to ``a`` and ``f``, and
also applies the GNU ``noreturn`` attribute to ``f``.
.. code-block:: c++
[[gnu::unused]] int a, f [[gnu::noreturn]] ();
Target-Specific Extensions
==========================
Clang supports some language features conditionally on some targets.
ARM/AArch64 Language Extensions
-------------------------------
Memory Barrier Intrinsics
^^^^^^^^^^^^^^^^^^^^^^^^^
Clang implements the ``__dmb``, ``__dsb`` and ``__isb`` intrinsics as defined
in the `ARM C Language Extensions Release 2.0
<http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053c/IHI0053C_acle_2_0.pdf>`_.
Note that these intrinsics are implemented as motion barriers that block
reordering of memory accesses and side effect instructions. Other instructions
like simple arithmetic may be reordered around the intrinsic. If you expect to
have no reordering at all, use inline assembly instead.
X86/X86-64 Language Extensions
------------------------------
The X86 backend has these language extensions:
Memory references to specified segments
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Annotating a pointer with address space #256 causes it to be code generated
relative to the X86 GS segment register, address space #257 causes it to be
relative to the X86 FS segment, and address space #258 causes it to be
relative to the X86 SS segment. Note that this is a very very low-level
feature that should only be used if you know what you're doing (for example in
an OS kernel).
Here is an example:
.. code-block:: c++
#define GS_RELATIVE __attribute__((address_space(256)))
int foo(int GS_RELATIVE *P) {
return *P;
}
Which compiles to (on X86-32):
.. code-block:: gas
_foo:
movl 4(%esp), %eax
movl %gs:(%eax), %eax
ret
Extensions for Static Analysis
==============================
Clang supports additional attributes that are useful for documenting program
invariants and rules for static analysis tools, such as the `Clang Static
Analyzer <https://clang-analyzer.llvm.org/>`_. These attributes are documented
in the analyzer's `list of source-level annotations
<https://clang-analyzer.llvm.org/annotations.html>`_.
Extensions for Dynamic Analysis
===============================
Use ``__has_feature(address_sanitizer)`` to check if the code is being built
with :doc:`AddressSanitizer`.
Use ``__has_feature(thread_sanitizer)`` to check if the code is being built
with :doc:`ThreadSanitizer`.
Use ``__has_feature(memory_sanitizer)`` to check if the code is being built
with :doc:`MemorySanitizer`.
Use ``__has_feature(safe_stack)`` to check if the code is being built
with :doc:`SafeStack`.
Extensions for selectively disabling optimization
=================================================
Clang provides a mechanism for selectively disabling optimizations in functions
and methods.
To disable optimizations in a single function definition, the GNU-style or C++11
non-standard attribute ``optnone`` can be used.
.. code-block:: c++
// The following functions will not be optimized.
// GNU-style attribute
__attribute__((optnone)) int foo() {
// ... code
}
// C++11 attribute
[[clang::optnone]] int bar() {
// ... code
}
To facilitate disabling optimization for a range of function definitions, a
range-based pragma is provided. Its syntax is ``#pragma clang optimize``
followed by ``off`` or ``on``.
All function definitions in the region between an ``off`` and the following
``on`` will be decorated with the ``optnone`` attribute unless doing so would
conflict with explicit attributes already present on the function (e.g. the
ones that control inlining).
.. code-block:: c++
#pragma clang optimize off
// This function will be decorated with optnone.
int foo() {
// ... code
}
// optnone conflicts with always_inline, so bar() will not be decorated.
__attribute__((always_inline)) int bar() {
// ... code
}
#pragma clang optimize on
If no ``on`` is found to close an ``off`` region, the end of the region is the
end of the compilation unit.
Note that a stray ``#pragma clang optimize on`` does not selectively enable
additional optimizations when compiling at low optimization levels. This feature
can only be used to selectively disable optimizations.
The pragma has an effect on functions only at the point of their definition; for
function templates, this means that the state of the pragma at the point of an
instantiation is not necessarily relevant. Consider the following example:
.. code-block:: c++
template<typename T> T twice(T t) {
return 2 * t;
}
#pragma clang optimize off
template<typename T> T thrice(T t) {
return 3 * t;
}
int container(int a, int b) {
return twice(a) + thrice(b);
}
#pragma clang optimize on
In this example, the definition of the template function ``twice`` is outside
the pragma region, whereas the definition of ``thrice`` is inside the region.
The ``container`` function is also in the region and will not be optimized, but
it causes the instantiation of ``twice`` and ``thrice`` with an ``int`` type; of
these two instantiations, ``twice`` will be optimized (because its definition
was outside the region) and ``thrice`` will not be optimized.
Extensions for loop hint optimizations
======================================
The ``#pragma clang loop`` directive is used to specify hints for optimizing the
subsequent for, while, do-while, or c++11 range-based for loop. The directive
provides options for vectorization, interleaving, unrolling and
distribution. Loop hints can be specified before any loop and will be ignored if
the optimization is not safe to apply.
Vectorization and Interleaving
------------------------------
A vectorized loop performs multiple iterations of the original loop
in parallel using vector instructions. The instruction set of the target
processor determines which vector instructions are available and their vector
widths. This restricts the types of loops that can be vectorized. The vectorizer
automatically determines if the loop is safe and profitable to vectorize. A
vector instruction cost model is used to select the vector width.
Interleaving multiple loop iterations allows modern processors to further
improve instruction-level parallelism (ILP) using advanced hardware features,
such as multiple execution units and out-of-order execution. The vectorizer uses
a cost model that depends on the register pressure and generated code size to
select the interleaving count.
Vectorization is enabled by ``vectorize(enable)`` and interleaving is enabled
by ``interleave(enable)``. This is useful when compiling with ``-Os`` to
manually enable vectorization or interleaving.
.. code-block:: c++
#pragma clang loop vectorize(enable)
#pragma clang loop interleave(enable)
for(...) {
...
}
The vector width is specified by ``vectorize_width(_value_)`` and the interleave
count is specified by ``interleave_count(_value_)``, where
_value_ is a positive integer. This is useful for specifying the optimal
width/count of the set of target architectures supported by your application.
.. code-block:: c++
#pragma clang loop vectorize_width(2)
#pragma clang loop interleave_count(2)
for(...) {
...
}
Specifying a width/count of 1 disables the optimization, and is equivalent to
``vectorize(disable)`` or ``interleave(disable)``.
Loop Unrolling
--------------
Unrolling a loop reduces the loop control overhead and exposes more
opportunities for ILP. Loops can be fully or partially unrolled. Full unrolling
eliminates the loop and replaces it with an enumerated sequence of loop
iterations. Full unrolling is only possible if the loop trip count is known at
compile time. Partial unrolling replicates the loop body within the loop and
reduces the trip count.
If ``unroll(enable)`` is specified the unroller will attempt to fully unroll the
loop if the trip count is known at compile time. If the fully unrolled code size
is greater than an internal limit the loop will be partially unrolled up to this
limit. If the trip count is not known at compile time the loop will be partially
unrolled with a heuristically chosen unroll factor.
.. code-block:: c++
#pragma clang loop unroll(enable)
for(...) {
...
}
If ``unroll(full)`` is specified the unroller will attempt to fully unroll the
loop if the trip count is known at compile time identically to
``unroll(enable)``. However, with ``unroll(full)`` the loop will not be unrolled
if the loop count is not known at compile time.
.. code-block:: c++
#pragma clang loop unroll(full)
for(...) {
...
}
The unroll count can be specified explicitly with ``unroll_count(_value_)`` where
_value_ is a positive integer. If this value is greater than the trip count the
loop will be fully unrolled. Otherwise the loop is partially unrolled subject
to the same code size limit as with ``unroll(enable)``.
.. code-block:: c++
#pragma clang loop unroll_count(8)
for(...) {
...
}
Unrolling of a loop can be prevented by specifying ``unroll(disable)``.
Loop Distribution
-----------------
Loop Distribution allows splitting a loop into multiple loops. This is
beneficial for example when the entire loop cannot be vectorized but some of the
resulting loops can.
If ``distribute(enable))`` is specified and the loop has memory dependencies
that inhibit vectorization, the compiler will attempt to isolate the offending
operations into a new loop. This optimization is not enabled by default, only
loops marked with the pragma are considered.
.. code-block:: c++
#pragma clang loop distribute(enable)
for (i = 0; i < N; ++i) {
S1: A[i + 1] = A[i] + B[i];
S2: C[i] = D[i] * E[i];
}
This loop will be split into two loops between statements S1 and S2. The
second loop containing S2 will be vectorized.
Loop Distribution is currently not enabled by default in the optimizer because
it can hurt performance in some cases. For example, instruction-level
parallelism could be reduced by sequentializing the execution of the
statements S1 and S2 above.
If Loop Distribution is turned on globally with
``-mllvm -enable-loop-distribution``, specifying ``distribute(disable)`` can
be used the disable it on a per-loop basis.
Additional Information
----------------------
For convenience multiple loop hints can be specified on a single line.
.. code-block:: c++
#pragma clang loop vectorize_width(4) interleave_count(8)
for(...) {
...
}
If an optimization cannot be applied any hints that apply to it will be ignored.
For example, the hint ``vectorize_width(4)`` is ignored if the loop is not
proven safe to vectorize. To identify and diagnose optimization issues use
`-Rpass`, `-Rpass-missed`, and `-Rpass-analysis` command line options. See the
user guide for details.
Extensions to specify floating-point flags
====================================================
The ``#pragma clang fp`` pragma allows floating-point options to be specified
for a section of the source code. This pragma can only appear at file scope or
at the start of a compound statement (excluding comments). When using within a
compound statement, the pragma is active within the scope of the compound
statement.
Currently, only FP contraction can be controlled with the pragma. ``#pragma
clang fp contract`` specifies whether the compiler should contract a multiply
and an addition (or subtraction) into a fused FMA operation when supported by
the target.
The pragma can take three values: ``on``, ``fast`` and ``off``. The ``on``
option is identical to using ``#pragma STDC FP_CONTRACT(ON)`` and it allows
fusion as specified the language standard. The ``fast`` option allows fusiong
in cases when the language standard does not make this possible (e.g. across
statements in C)
.. code-block:: c++
for(...) {
#pragma clang fp contract(fast)
a = b[i] * c[i];
d[i] += a;
}
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 "scope" of ``#pragma clang attribute`` that attributes
can be added to. The ``#pragma clang attribute (...)`` variation adds an
attribute to that scope, and the ``#pragma clang attribute pop`` variation pops
the scope. You can also use ``#pragma clang attribute push (...)``, which is a
shorthand for when you want to add one attribute to a new scope. 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.
Because multiple push directives can be nested, if you're writing a macro that
expands to ``_Pragma("clang attribute")`` it's good hygiene (though not
required) to add a namespace to your push/pop directives. A pop directive with a
namespace will pop the innermost push that has that same namespace. This will
ensure that another macro's ``pop`` won't inadvertently pop your attribute. Note
that an ``pop`` without a namespace will pop the innermost ``push`` without a
namespace. ``push``es with a namespace can only be popped by ``pop`` with the
same namespace. For instance:
.. code-block:: c++
#define ASSUME_NORETURN_BEGIN _Pragma("clang attribute AssumeNoreturn.push ([[noreturn]], apply_to = function)")
#define ASSUME_NORETURN_END _Pragma("clang attribute AssumeNoreturn.pop")
#define ASSUME_UNAVAILABLE_BEGIN _Pragma("clang attribute Unavailable.push (__attribute__((unavailable)), apply_to=function)")
#define ASSUME_UNAVAILABLE_END _Pragma("clang attribute Unavailable.pop")
ASSUME_NORETURN_BEGIN
ASSUME_UNAVAILABLE_BEGIN
void function(); // function has [[noreturn]] and __attribute__((unavailable))
ASSUME_NORETURN_END
void other_function(); // function has __attribute__((unavailable))
ASSUME_UNAVAILABLE_END
Without the namespaces on the macros, ``other_function`` will be annotated with
``[[noreturn]]`` instead of ``__attribute__((unavailable))``. This may seem like
a contrived example, but its very possible for this kind of situation to appear
in real code if the pragmas are spread out across a large file. You can test if
your version of clang supports namespaces on ``#pragma clang attribute`` with
``__has_extension(pragma_clang_attribute_namespaces)``.
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.
Specifying section names for global objects (#pragma clang section)
===================================================================
The ``#pragma clang section`` directive provides a means to assign section-names
to global variables, functions and static variables.
The section names can be specified as:
.. code-block:: c++
#pragma clang section bss="myBSS" data="myData" rodata="myRodata" text="myText"
The section names can be reverted back to default name by supplying an empty
string to the section kind, for example:
.. code-block:: c++
#pragma clang section bss="" data="" text="" rodata=""
The ``#pragma clang section`` directive obeys the following rules:
* The pragma applies to all global variable, statics and function declarations
from the pragma to the end of the translation unit.
* The pragma clang section is enabled automatically, without need of any flags.
* This feature is only defined to work sensibly for ELF targets.
* If section name is specified through _attribute_((section("myname"))), then
the attribute name gains precedence.
* Global variables that are initialized to zero will be placed in the named
bss section, if one is present.
* The ``#pragma clang section`` directive does not does try to infer section-kind
from the name. For example, naming a section "``.bss.mySec``" does NOT mean
it will be a bss section name.
* The decision about which section-kind applies to each global is taken in the back-end.
Once the section-kind is known, appropriate section name, as specified by the user using
``#pragma clang section`` directive, is applied to that global.
Specifying Linker Options on ELF Targets
========================================
The ``#pragma comment(lib, ...)`` directive is supported on all ELF targets.
The second parameter is the library name (without the traditional Unix prefix of
``lib``). This allows you to provide an implicit link of dependent libraries.
Index: vendor/clang/dist-release_80/docs/OpenMPSupport.rst
===================================================================
--- vendor/clang/dist-release_80/docs/OpenMPSupport.rst (revision 343795)
+++ vendor/clang/dist-release_80/docs/OpenMPSupport.rst (revision 343796)
@@ -1,138 +1,128 @@
.. raw:: html
<style type="text/css">
.none { background-color: #FFCCCC }
.partial { background-color: #FFFF99 }
.good { background-color: #CCFF99 }
</style>
.. role:: none
.. role:: partial
.. role:: good
.. contents::
:local:
==================
OpenMP Support
==================
-Clang fully supports OpenMP 4.5. Clang supports offloading to X86_64, AArch64,
-PPC64[LE] and has `basic support for Cuda devices`_.
+Clang supports the following OpenMP 5.0 features
-Standalone directives
-=====================
+* The `reduction`-based clauses in the `task` and `target`-based directives.
-* #pragma omp [for] simd: :good:`Complete`.
+* Support relational-op != (not-equal) as one of the canonical forms of random
+ access iterator.
-* #pragma omp declare simd: :partial:`Partial`. We support parsing/semantic
- analysis + generation of special attributes for X86 target, but still
- missing the LLVM pass for vectorization.
+* Support for mapping of the lambdas in target regions.
-* #pragma omp taskloop [simd]: :good:`Complete`.
+* Parsing/sema analysis for the requires directive.
-* #pragma omp target [enter|exit] data: :good:`Complete`.
+* Nested declare target directives.
-* #pragma omp target update: :good:`Complete`.
+* Make the `this` pointer implicitly mapped as `map(this[:1])`.
-* #pragma omp target: :good:`Complete`.
+* The `close` *map-type-modifier*.
-* #pragma omp declare target: :good:`Complete`.
+Clang fully supports OpenMP 4.5. Clang supports offloading to X86_64, AArch64,
+PPC64[LE] and has `basic support for Cuda devices`_.
-* #pragma omp teams: :good:`Complete`.
+* #pragma omp declare simd: :partial:`Partial`. We support parsing/semantic
+ analysis + generation of special attributes for X86 target, but still
+ missing the LLVM pass for vectorization.
-* #pragma omp distribute [simd]: :good:`Complete`.
+In addition, the LLVM OpenMP runtime `libomp` supports the OpenMP Tools
+Interface (OMPT) on x86, x86_64, AArch64, and PPC64 on Linux, Windows, and macOS.
-* #pragma omp distribute parallel for [simd]: :good:`Complete`.
+General improvements
+--------------------
+- New collapse clause scheme to avoid expensive remainder operations.
+ Compute loop index variables after collapsing a loop nest via the
+ collapse clause by replacing the expensive remainder operation with
+ multiplications and additions.
-Combined directives
-===================
-
-* #pragma omp parallel for simd: :good:`Complete`.
-
-* #pragma omp target parallel: :good:`Complete`.
-
-* #pragma omp target parallel for [simd]: :good:`Complete`.
-
-* #pragma omp target simd: :good:`Complete`.
-
-* #pragma omp target teams: :good:`Complete`.
-
-* #pragma omp teams distribute [simd]: :good:`Complete`.
-
-* #pragma omp target teams distribute [simd]: :good:`Complete`.
-
-* #pragma omp teams distribute parallel for [simd]: :good:`Complete`.
-
-* #pragma omp target teams distribute parallel for [simd]: :good:`Complete`.
-
-Clang does not support any constructs/updates from OpenMP 5.0 except
-for `reduction`-based clauses in the `task` and `target`-based directives.
-
-In addition, the LLVM OpenMP runtime `libomp` supports the OpenMP Tools
-Interface (OMPT) on x86, x86_64, AArch64, and PPC64 on Linux, Windows, and mac OS.
+- The default schedules for the `distribute` and `for` constructs in a
+ parallel region and in SPMD mode have changed to ensure coalesced
+ accesses. For the `distribute` construct, a static schedule is used
+ with a chunk size equal to the number of threads per team (default
+ value of threads or as specified by the `thread_limit` clause if
+ present). For the `for` construct, the schedule is static with chunk
+ size of one.
+
+- Simplified SPMD code generation for `distribute parallel for` when
+ the new default schedules are applicable.
.. _basic support for Cuda devices:
Cuda devices support
====================
Directives execution modes
--------------------------
Clang code generation for target regions supports two modes: the SPMD and
non-SPMD modes. Clang chooses one of these two modes automatically based on the
way directives and clauses on those directives are used. The SPMD mode uses a
simplified set of runtime functions thus increasing performance at the cost of
supporting some OpenMP features. The non-SPMD mode is the most generic mode and
supports all currently available OpenMP features. The compiler will always
attempt to use the SPMD mode wherever possible. SPMD mode will not be used if:
- The target region contains an `if()` clause that refers to a `parallel`
directive.
- The target region contains a `parallel` directive with a `num_threads()`
clause.
- The target region contains user code (other than OpenMP-specific
directives) in between the `target` and the `parallel` directives.
Data-sharing modes
------------------
Clang supports two data-sharing models for Cuda devices: `Generic` and `Cuda`
modes. The default mode is `Generic`. `Cuda` mode can give an additional
performance and can be activated using the `-fopenmp-cuda-mode` flag. In
`Generic` mode all local variables that can be shared in the parallel regions
are stored in the global memory. In `Cuda` mode local variables are not shared
between the threads and it is user responsibility to share the required data
between the threads in the parallel regions.
Collapsed loop nest counter
---------------------------
When using the collapse clause on a loop nest the default behaviour is to
automatically extend the representation of the loop counter to 64 bits for
the cases where the sizes of the collapsed loops are not known at compile
time. To prevent this conservative choice and use at most 32 bits,
compile your program with the `-fopenmp-optimistic-collapse`.
Features not supported or with limited support for Cuda devices
---------------------------------------------------------------
- Cancellation constructs are not supported.
- Doacross loop nest is not supported.
- User-defined reductions are supported only for trivial types.
- Nested parallelism: inner parallel regions are executed sequentially.
- Static linking of libraries containing device code is not supported yet.
- Automatic translation of math functions in target regions to device-specific
math functions is not implemented yet.
- Debug information for OpenMP target regions is not supported yet.
Index: vendor/clang/dist-release_80/docs/ReleaseNotes.rst
===================================================================
--- vendor/clang/dist-release_80/docs/ReleaseNotes.rst (revision 343795)
+++ vendor/clang/dist-release_80/docs/ReleaseNotes.rst (revision 343796)
@@ -1,399 +1,431 @@
=======================================
Clang 8.0.0 (In-Progress) Release Notes
=======================================
.. contents::
:local:
:depth: 2
Written by the `LLVM Team <https://llvm.org/>`_
.. warning::
These are in-progress notes for the upcoming Clang 8 release.
Release notes for previous releases can be found on
`the Download Page <https://releases.llvm.org/download.html>`_.
Introduction
============
This document contains the release notes for the Clang C/C++/Objective-C
frontend, part of the LLVM Compiler Infrastructure, release 8.0.0. Here we
describe the status of Clang in some detail, including major
improvements from the previous release and new feature work. For the
general LLVM release notes, see `the LLVM
documentation <https://llvm.org/docs/ReleaseNotes.html>`_. All LLVM
releases may be downloaded from the `LLVM releases web
site <https://llvm.org/releases/>`_.
For more information about Clang or LLVM, including information about the
latest release, please see the `Clang Web Site <https://clang.llvm.org>`_ or the
`LLVM Web Site <https://llvm.org>`_.
Note that if you are reading this file from a Subversion checkout or the
main Clang web page, this document applies to the *next* release, not
the current one. To see the release notes for a specific release, please
see the `releases page <https://llvm.org/releases/>`_.
What's New in Clang 8.0.0?
==========================
Some of the major new features and improvements to Clang are listed
here. Generic improvements to Clang as a whole or to its underlying
infrastructure are described first, followed by language-specific
sections with improvements to Clang's support for those languages.
Major New Features
------------------
- Clang supports use of a profile remapping file, which permits
profile data captured for one version of a program to be applied
when building another version where symbols have changed (for
example, due to renaming a class or namespace).
See the :doc:`UsersManual` for details.
Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- ``-Wextra-semi-stmt`` is a new diagnostic that diagnoses extra semicolons,
much like ``-Wextra-semi``. This new diagnostic diagnoses all *unnecessary*
null statements (expression statements without an expression), unless: the
semicolon directly follows a macro that was expanded to nothing or if the
semicolon is within the macro itself. This applies to macros defined in system
headers as well as user-defined macros.
.. code-block:: c++
#define MACRO(x) int x;
#define NULLMACRO(varname)
void test() {
; // <- warning: ';' with no preceding expression is a null statement
while (true)
; // OK, it is needed.
switch (my_enum) {
case E1:
// stuff
break;
case E2:
; // OK, it is needed.
}
MACRO(v0;) // Extra semicolon, but within macro, so ignored.
MACRO(v1); // <- warning: ';' with no preceding expression is a null statement
NULLMACRO(v2); // ignored, NULLMACRO expanded to nothing.
}
- ``-Wempty-init-stmt`` is a new diagnostic that diagnoses empty init-statements
of ``if``, ``switch``, ``range-based for``, unless: the semicolon directly
follows a macro that was expanded to nothing or if the semicolon is within the
macro itself (both macros from system headers, and normal macros). This
diagnostic is in the ``-Wextra-semi-stmt`` group and is enabled in
``-Wextra``.
.. code-block:: c++
void test() {
if(; // <- warning: init-statement of 'if' is a null statement
true)
;
switch (; // <- warning: init-statement of 'switch' is a null statement
x) {
...
}
for (; // <- warning: init-statement of 'range-based for' is a null statement
int y : S())
;
}
Non-comprehensive list of changes in this release
-------------------------------------------------
- The experimental feature Pretokenized Headers (PTH) was removed in its
entirely from Clang. The feature did not properly work with about 1/3 of the
possible tokens available and was unmaintained.
- The internals of libc++ include directory detection on MacOS have changed.
Instead of running a search based on the ``-resource-dir`` flag, the search
is now based on the path of the compiler in the filesystem. The default
behaviour should not change. However, if you override ``-resource-dir``
manually and rely on the old behaviour you will need to add appropriate
compiler flags for finding the corresponding libc++ include directory.
+- The integrated assembler is used now by default for all MIPS targets.
+
+- Improved support for MIPS N32 ABI and MIPS R6 target triples.
+
New Compiler Flags
------------------
- ``-fprofile-filter-files=[regexes]`` and ``-fprofile-exclude-files=[regexes]``.
Clang has now options to filter or exclude some files when
instrumenting for gcov-based profiling.
See the :doc:`UsersManual` for details.
+- When using a custom stack alignment, the ``stackrealign`` attribute is now
+ implicitly set on the main function.
+
+- Emission of ``R_MIPS_JALR`` and ``R_MICROMIPS_JALR`` relocations can now
+ be controlled by the ``-mrelax-pic-calls`` and ``-mno-relax-pic-calls``
+ options.
+
- ...
Deprecated Compiler Flags
-------------------------
The following options are deprecated and ignored. They will be removed in
future versions of Clang.
- ...
Modified Compiler Flags
-----------------------
- As of clang 8, `alignof` and `_Alignof` return the ABI alignment of a type,
as opposed to the preferred alignment. `__alignof` still returns the
preferred alignment. `-fclang-abi-compat=7` (and previous) will make
`alignof` and `_Alignof` return preferred alignment again.
New Pragmas in Clang
--------------------
- Clang now supports adding multiple `#pragma clang attribute` attributes into
a scope of pushed attributes.
Attribute Changes in Clang
--------------------------
- ...
Windows Support
---------------
- clang-cl now supports the use of the precompiled header options /Yc and /Yu
without the filename argument. When these options are used without the
filename, a `#pragma hdrstop` inside the source marks the end of the
precompiled code.
- clang-cl has a new command-line option, ``/Zc:dllexportInlines-``, similar to
``-fvisibility-inlines-hidden`` on non-Windows, that makes class-level
`dllexport` and `dllimport` attributes not apply to inline member functions.
This can significantly reduce compile and link times. See the `User's Manual
<UsersManual.html#the-zc-dllexportinlines-option>`_ for more info.
+
+- For MinGW, ``-municode`` now correctly defines ``UNICODE`` during
+ preprocessing.
+
+- For MinGW, clang now produces vtables and RTTI for dllexported classes
+ without key functions. This fixes building Qt in debug mode.
+
+- Allow using Address Sanitizer and Undefined Behaviour Sanitizer on MinGW.
+
- ...
C Language Changes in Clang
---------------------------
- ...
...
C11 Feature Support
^^^^^^^^^^^^^^^^^^^
...
C++ Language Changes in Clang
-----------------------------
- ...
C++1z Feature Support
^^^^^^^^^^^^^^^^^^^^^
...
Objective-C Language Changes in Clang
-------------------------------------
...
OpenCL C Language Changes in Clang
----------------------------------
...
ABI Changes in Clang
--------------------
- `_Alignof` and `alignof` now return the ABI alignment of a type, as opposed
to the preferred alignment.
- This is more in keeping with the language of the standards, as well as
being compatible with gcc
- `__alignof` and `__alignof__` still return the preferred alignment of
a type
- This shouldn't break any ABI except for things that explicitly ask for
`alignas(alignof(T))`.
- If you have interfaces that break with this change, you may wish to switch
to `alignas(__alignof(T))`, instead of using the `-fclang-abi-compat`
switch.
OpenMP Support in Clang
----------------------------------
-- Support relational-op != (not-equal) as one of the canonical forms of random
- access iterator.
+- OpenMP 5.0 features
-- Added support for mapping of the lambdas in target regions.
+ - Support relational-op != (not-equal) as one of the canonical forms of random
+ access iterator.
+ - Added support for mapping of the lambdas in target regions.
+ - Added parsing/sema analysis for the requires directive.
+ - Support nested declare target directives.
+ - Make the `this` pointer implicitly mapped as `map(this[:1])`.
+ - Added the `close` *map-type-modifier*.
-- Added parsing/sema analysis for OpenMP 5.0 requires directive.
-
- Various bugfixes and improvements.
New features supported for Cuda devices:
- Added support for the reductions across the teams.
- Extended number of constructs that can be executed in SPMD mode.
- Fixed support for lastprivate/reduction variables in SPMD constructs.
+
+- New collapse clause scheme to avoid expensive remainder operations.
+
+- New default schedule for distribute and parallel constructs.
+
+- Simplified code generation for distribute and parallel in SPMD mode.
+
+- Flag (``-fopenmp_optimistic_collapse``) for user to limit collapsed
+ loop counter width when safe to do so.
- General performance improvement.
CUDA Support in Clang
---------------------
Internal API Changes
--------------------
These are major API changes that have happened since the 7.0.0 release of
Clang. If upgrading an external codebase that uses Clang as a library,
this section should help get you past the largest hurdles of upgrading.
- ...
AST Matchers
------------
- ...
clang-format
------------
- ...
libclang
--------
...
Static Analyzer
---------------
- ...
...
.. _release-notes-ubsan:
Undefined Behavior Sanitizer (UBSan)
------------------------------------
* The Implicit Conversion Sanitizer (``-fsanitize=implicit-conversion``) group
was extended. One more type of issues is caught - implicit integer sign change.
(``-fsanitize=implicit-integer-sign-change``).
This makes the Implicit Conversion Sanitizer feature-complete,
with only missing piece being bitfield handling.
While there is a ``-Wsign-conversion`` diagnostic group that catches this kind
of issues, it is both noisy, and does not catch **all** the cases.
.. code-block:: c++
bool consume(unsigned int val);
void test(int val) {
(void)consume(val); // If the value was negative, it is now large positive.
(void)consume((unsigned int)val); // OK, the conversion is explicit.
}
Like some other ``-fsanitize=integer`` checks, these issues are **not**
undefined behaviour. But they are not *always* intentional, and are somewhat
hard to track down. This group is **not** enabled by ``-fsanitize=undefined``,
but the ``-fsanitize=implicit-integer-sign-change`` check
is enabled by ``-fsanitize=integer``.
(as is ``-fsanitize=implicit-integer-truncation`` check)
* The Implicit Conversion Sanitizer (``-fsanitize=implicit-conversion``) has
learned to sanitize compound assignment operators.
* ``alignment`` check has learned to sanitize the assume_aligned-like attributes:
.. code-block:: c++
typedef char **__attribute__((align_value(1024))) aligned_char;
struct ac_struct {
aligned_char a;
};
char **load_from_ac_struct(struct ac_struct *x) {
return x->a; // <- check that loaded 'a' is aligned
}
char **passthrough(__attribute__((align_value(1024))) char **x) {
return x; // <- check the pointer passed as function argument
}
char **__attribute__((alloc_align(2)))
alloc_align(int size, unsigned long alignment);
char **caller(int size) {
return alloc_align(size, 1024); // <- check returned pointer
}
char **__attribute__((assume_aligned(1024))) get_ptr();
char **caller2() {
return get_ptr(); // <- check returned pointer
}
void *caller3(char **x) {
return __builtin_assume_aligned(x, 1024); // <- check returned pointer
}
void *caller4(char **x, unsigned long offset) {
return __builtin_assume_aligned(x, 1024, offset); // <- check returned pointer accounting for the offest
}
void process(char *data, int width) {
#pragma omp for simd aligned(data : 1024) // <- aligned clause will be checked.
for (int x = 0; x < width; x++)
data[x] *= data[x];
}
Core Analysis Improvements
==========================
- ...
New Issues Found
================
- ...
Python Binding Changes
----------------------
The following methods have been added:
- ...
Significant Known Problems
==========================
Additional Information
======================
A wide variety of additional information is available on the `Clang web
page <https://clang.llvm.org/>`_. The web page contains versions of the
API documentation which are up-to-date with the Subversion version of
the source code. You can access versions of these documents specific to
this release by going into the "``clang/docs/``" directory in the Clang
tree.
If you have any questions or comments about Clang, please feel free to
contact us via the `mailing
list <https://lists.llvm.org/mailman/listinfo/cfe-dev>`_.
Index: vendor/clang/dist-release_80/include/clang/Basic/BuiltinsAArch64.def
===================================================================
--- vendor/clang/dist-release_80/include/clang/Basic/BuiltinsAArch64.def (revision 343795)
+++ vendor/clang/dist-release_80/include/clang/Basic/BuiltinsAArch64.def (revision 343796)
@@ -1,213 +1,213 @@
//==- BuiltinsAArch64.def - AArch64 Builtin function database ----*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the AArch64-specific builtin function database. Users of
// this file must define the BUILTIN macro to make use of this information.
//
//===----------------------------------------------------------------------===//
// The format of this database matches clang/Basic/Builtins.def.
#if defined(BUILTIN) && !defined(LANGBUILTIN)
# define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS)
#endif
#if defined(BUILTIN) && !defined(TARGET_HEADER_BUILTIN)
# define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANG, FEATURE) BUILTIN(ID, TYPE, ATTRS)
#endif
// In libgcc
BUILTIN(__clear_cache, "vv*v*", "i")
BUILTIN(__builtin_arm_ldrex, "v.", "t")
BUILTIN(__builtin_arm_ldaex, "v.", "t")
BUILTIN(__builtin_arm_strex, "i.", "t")
BUILTIN(__builtin_arm_stlex, "i.", "t")
BUILTIN(__builtin_arm_clrex, "v", "")
// Bit manipulation
BUILTIN(__builtin_arm_rbit, "UiUi", "nc")
-BUILTIN(__builtin_arm_rbit64, "LUiLUi", "nc")
+BUILTIN(__builtin_arm_rbit64, "WUiWUi", "nc")
// HINT
BUILTIN(__builtin_arm_nop, "v", "")
BUILTIN(__builtin_arm_yield, "v", "")
BUILTIN(__builtin_arm_wfe, "v", "")
BUILTIN(__builtin_arm_wfi, "v", "")
BUILTIN(__builtin_arm_sev, "v", "")
BUILTIN(__builtin_arm_sevl, "v", "")
// CRC32
BUILTIN(__builtin_arm_crc32b, "UiUiUc", "nc")
BUILTIN(__builtin_arm_crc32cb, "UiUiUc", "nc")
BUILTIN(__builtin_arm_crc32h, "UiUiUs", "nc")
BUILTIN(__builtin_arm_crc32ch, "UiUiUs", "nc")
BUILTIN(__builtin_arm_crc32w, "UiUiUi", "nc")
BUILTIN(__builtin_arm_crc32cw, "UiUiUi", "nc")
-BUILTIN(__builtin_arm_crc32d, "UiUiLUi", "nc")
-BUILTIN(__builtin_arm_crc32cd, "UiUiLUi", "nc")
+BUILTIN(__builtin_arm_crc32d, "UiUiWUi", "nc")
+BUILTIN(__builtin_arm_crc32cd, "UiUiWUi", "nc")
// Memory barrier
BUILTIN(__builtin_arm_dmb, "vUi", "nc")
BUILTIN(__builtin_arm_dsb, "vUi", "nc")
BUILTIN(__builtin_arm_isb, "vUi", "nc")
// Prefetch
BUILTIN(__builtin_arm_prefetch, "vvC*UiUiUiUi", "nc")
// System Registers
BUILTIN(__builtin_arm_rsr, "UicC*", "nc")
-BUILTIN(__builtin_arm_rsr64, "LUicC*", "nc")
+BUILTIN(__builtin_arm_rsr64, "WUicC*", "nc")
BUILTIN(__builtin_arm_rsrp, "v*cC*", "nc")
BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
-BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc")
+BUILTIN(__builtin_arm_wsr64, "vcC*WUi", "nc")
BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
// MSVC
LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES)
LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES)
LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES)
LANGBUILTIN(__sev, "v", "", ALL_MS_LANGUAGES)
LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES)
// MSVC intrinsics for volatile but non-acquire/release loads and stores
LANGBUILTIN(__iso_volatile_load8, "ccCD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__iso_volatile_load16, "ssCD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__iso_volatile_load32, "iiCD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__iso_volatile_load64, "LLiLLiCD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__iso_volatile_store8, "vcD*c", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__iso_volatile_store16, "vsD*s", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__iso_volatile_store32, "viD*i", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__iso_volatile_store64, "vLLiD*LLi", "n", ALL_MS_LANGUAGES)
TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanForward64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAdd, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeSub64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedExchange64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_acq, "ccD*cc", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_nf, "ccD*cc", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange8_rel, "ccD*cc", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_acq, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_nf, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange16_rel, "ssD*ss", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_acq, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_nf, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange_rel, "LiLiD*LiLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_acq, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_nf, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedCompareExchange64_rel, "LLiLLiD*LLiLLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedOr64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedXor64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd8_acq, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd8_nf, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd8_rel, "ccD*c", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd16_acq, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd16_nf, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd16_rel, "ssD*s", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd_acq, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd_nf, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd_rel, "LiLiD*Li", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64_acq, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64_nf, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedAnd64_rel, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_acq, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_nf, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement16_rel, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement_acq, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement_nf, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement_rel, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_acq, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_nf, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedIncrement64_rel, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_acq, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_nf, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement16_rel, "ssD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement_acq, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement_nf, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement_rel, "LiLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_acq, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_nf, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_InterlockedDecrement64_rel, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__getReg, "ULLii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_ReadStatusReg, "ii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_WriteStatusReg, "vii", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
#undef BUILTIN
#undef LANGBUILTIN
#undef TARGET_HEADER_BUILTIN
Index: vendor/clang/dist-release_80/include/clang/Basic/Features.def
===================================================================
--- vendor/clang/dist-release_80/include/clang/Basic/Features.def (revision 343795)
+++ vendor/clang/dist-release_80/include/clang/Basic/Features.def (revision 343796)
@@ -1,252 +1,252 @@
//===--- Features.def - Features and Extensions database --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines features exposed via __has_feature and extensions exposed
// via __has_extension. Users of this file must either define the FEATURE or
// EXTENSION macros (or both) to make use of this information. Note that these
// macros expect the following declarations to be available for the Predicate:
//
// const LangOptions &LangOpts;
// const Preprocessor &PP;
//
// The Predicate field dictates the conditions under which the feature or
// extension will be made available.
//
// FEATURE(...) should be used to advertise support for standard language
// features, whereas EXTENSION(...) should be used for clang extensions. Note
// that many of the identifiers in this file don't follow this rule for backward
// compatibility reasons.
//
//===----------------------------------------------------------------------===//
#if !defined(FEATURE) && !defined(EXTENSION)
# error Define either the FEATURE or EXTENSION macro to handle features
#endif
#ifndef FEATURE
#define FEATURE(Name, Predicate)
#endif
#ifndef EXTENSION
#define EXTENSION(Name, Predicate)
#endif
FEATURE(address_sanitizer,
LangOpts.Sanitize.hasOneOf(SanitizerKind::Address |
SanitizerKind::KernelAddress))
FEATURE(hwaddress_sanitizer,
LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress |
SanitizerKind::KernelHWAddress))
FEATURE(xray_instrument, LangOpts.XRayInstrument)
FEATURE(undefined_behavior_sanitizer,
LangOpts.Sanitize.hasOneOf(SanitizerKind::Undefined))
FEATURE(assume_nonnull, true)
FEATURE(attribute_analyzer_noreturn, true)
FEATURE(attribute_availability, true)
FEATURE(attribute_availability_with_message, true)
FEATURE(attribute_availability_app_extension, true)
FEATURE(attribute_availability_with_version_underscores, true)
FEATURE(attribute_availability_tvos, true)
FEATURE(attribute_availability_watchos, true)
FEATURE(attribute_availability_with_strict, true)
FEATURE(attribute_availability_with_replacement, true)
FEATURE(attribute_availability_in_templates, true)
FEATURE(attribute_availability_swift, true)
FEATURE(attribute_cf_returns_not_retained, true)
FEATURE(attribute_cf_returns_retained, true)
FEATURE(attribute_cf_returns_on_parameters, true)
FEATURE(attribute_deprecated_with_message, true)
FEATURE(attribute_deprecated_with_replacement, true)
FEATURE(attribute_ext_vector_type, true)
FEATURE(attribute_ns_returns_not_retained, true)
FEATURE(attribute_ns_returns_retained, true)
FEATURE(attribute_ns_consumes_self, true)
FEATURE(attribute_ns_consumed, true)
FEATURE(attribute_cf_consumed, true)
FEATURE(attribute_objc_ivar_unused, true)
FEATURE(attribute_objc_method_family, true)
FEATURE(attribute_overloadable, true)
FEATURE(attribute_unavailable_with_message, true)
FEATURE(attribute_unused_on_fields, true)
FEATURE(attribute_diagnose_if_objc, true)
FEATURE(blocks, LangOpts.Blocks)
FEATURE(c_thread_safety_attributes, true)
FEATURE(cxx_exceptions, LangOpts.CXXExceptions)
FEATURE(cxx_rtti, LangOpts.RTTI &&LangOpts.RTTIData)
FEATURE(enumerator_attributes, true)
FEATURE(nullability, true)
FEATURE(nullability_on_arrays, true)
FEATURE(memory_sanitizer,
LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory |
SanitizerKind::KernelMemory))
FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
FEATURE(efficiency_sanitizer,
LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency))
FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
// Objective-C features
FEATURE(objc_arr, LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?
FEATURE(objc_arc, LangOpts.ObjCAutoRefCount)
FEATURE(objc_arc_fields, true)
FEATURE(objc_arc_weak, LangOpts.ObjCWeak)
FEATURE(objc_default_synthesize_properties, LangOpts.ObjC)
-FEATURE(objc_fixed_enum, true)
+FEATURE(objc_fixed_enum, LangOpts.ObjC)
FEATURE(objc_instancetype, LangOpts.ObjC)
FEATURE(objc_kindof, LangOpts.ObjC)
FEATURE(objc_modules, LangOpts.ObjC && LangOpts.Modules)
FEATURE(objc_nonfragile_abi, LangOpts.ObjCRuntime.isNonFragile())
FEATURE(objc_property_explicit_atomic, true)
FEATURE(objc_protocol_qualifier_mangling, true)
FEATURE(objc_weak_class, LangOpts.ObjCRuntime.hasWeakClassImport())
FEATURE(ownership_holds, true)
FEATURE(ownership_returns, true)
FEATURE(ownership_takes, true)
FEATURE(objc_bool, true)
FEATURE(objc_subscripting, LangOpts.ObjCRuntime.isNonFragile())
FEATURE(objc_array_literals, LangOpts.ObjC)
FEATURE(objc_dictionary_literals, LangOpts.ObjC)
FEATURE(objc_boxed_expressions, LangOpts.ObjC)
FEATURE(objc_boxed_nsvalue_expressions, LangOpts.ObjC)
FEATURE(arc_cf_code_audited, true)
FEATURE(objc_bridge_id, true)
FEATURE(objc_bridge_id_on_typedefs, true)
FEATURE(objc_generics, LangOpts.ObjC)
FEATURE(objc_generics_variance, LangOpts.ObjC)
FEATURE(objc_class_property, LangOpts.ObjC)
// C11 features
FEATURE(c_alignas, LangOpts.C11)
FEATURE(c_alignof, LangOpts.C11)
FEATURE(c_atomic, LangOpts.C11)
FEATURE(c_generic_selections, LangOpts.C11)
FEATURE(c_static_assert, LangOpts.C11)
FEATURE(c_thread_local, LangOpts.C11 &&PP.getTargetInfo().isTLSSupported())
// C++11 features
FEATURE(cxx_access_control_sfinae, LangOpts.CPlusPlus11)
FEATURE(cxx_alias_templates, LangOpts.CPlusPlus11)
FEATURE(cxx_alignas, LangOpts.CPlusPlus11)
FEATURE(cxx_alignof, LangOpts.CPlusPlus11)
FEATURE(cxx_atomic, LangOpts.CPlusPlus11)
FEATURE(cxx_attributes, LangOpts.CPlusPlus11)
FEATURE(cxx_auto_type, LangOpts.CPlusPlus11)
FEATURE(cxx_constexpr, LangOpts.CPlusPlus11)
FEATURE(cxx_constexpr_string_builtins, LangOpts.CPlusPlus11)
FEATURE(cxx_decltype, LangOpts.CPlusPlus11)
FEATURE(cxx_decltype_incomplete_return_types, LangOpts.CPlusPlus11)
FEATURE(cxx_default_function_template_args, LangOpts.CPlusPlus11)
FEATURE(cxx_defaulted_functions, LangOpts.CPlusPlus11)
FEATURE(cxx_delegating_constructors, LangOpts.CPlusPlus11)
FEATURE(cxx_deleted_functions, LangOpts.CPlusPlus11)
FEATURE(cxx_explicit_conversions, LangOpts.CPlusPlus11)
FEATURE(cxx_generalized_initializers, LangOpts.CPlusPlus11)
FEATURE(cxx_implicit_moves, LangOpts.CPlusPlus11)
FEATURE(cxx_inheriting_constructors, LangOpts.CPlusPlus11)
FEATURE(cxx_inline_namespaces, LangOpts.CPlusPlus11)
FEATURE(cxx_lambdas, LangOpts.CPlusPlus11)
FEATURE(cxx_local_type_template_args, LangOpts.CPlusPlus11)
FEATURE(cxx_nonstatic_member_init, LangOpts.CPlusPlus11)
FEATURE(cxx_noexcept, LangOpts.CPlusPlus11)
FEATURE(cxx_nullptr, LangOpts.CPlusPlus11)
FEATURE(cxx_override_control, LangOpts.CPlusPlus11)
FEATURE(cxx_range_for, LangOpts.CPlusPlus11)
FEATURE(cxx_raw_string_literals, LangOpts.CPlusPlus11)
FEATURE(cxx_reference_qualified_functions, LangOpts.CPlusPlus11)
FEATURE(cxx_rvalue_references, LangOpts.CPlusPlus11)
FEATURE(cxx_strong_enums, LangOpts.CPlusPlus11)
FEATURE(cxx_static_assert, LangOpts.CPlusPlus11)
FEATURE(cxx_thread_local,
LangOpts.CPlusPlus11 &&PP.getTargetInfo().isTLSSupported())
FEATURE(cxx_trailing_return, LangOpts.CPlusPlus11)
FEATURE(cxx_unicode_literals, LangOpts.CPlusPlus11)
FEATURE(cxx_unrestricted_unions, LangOpts.CPlusPlus11)
FEATURE(cxx_user_literals, LangOpts.CPlusPlus11)
FEATURE(cxx_variadic_templates, LangOpts.CPlusPlus11)
// C++14 features
FEATURE(cxx_aggregate_nsdmi, LangOpts.CPlusPlus14)
FEATURE(cxx_binary_literals, LangOpts.CPlusPlus14)
FEATURE(cxx_contextual_conversions, LangOpts.CPlusPlus14)
FEATURE(cxx_decltype_auto, LangOpts.CPlusPlus14)
FEATURE(cxx_generic_lambdas, LangOpts.CPlusPlus14)
FEATURE(cxx_init_captures, LangOpts.CPlusPlus14)
FEATURE(cxx_relaxed_constexpr, LangOpts.CPlusPlus14)
FEATURE(cxx_return_type_deduction, LangOpts.CPlusPlus14)
FEATURE(cxx_variable_templates, LangOpts.CPlusPlus14)
// NOTE: For features covered by SD-6, it is preferable to provide *only*
// the SD-6 macro and not a __has_feature check.
// C++ TSes
// FEATURE(cxx_runtime_arrays, LangOpts.CPlusPlusTSArrays)
// FEATURE(cxx_concepts, LangOpts.CPlusPlusTSConcepts)
// FIXME: Should this be __has_feature or __has_extension?
// FEATURE(raw_invocation_type, LangOpts.CPlusPlus)
// Type traits
// N.B. Additional type traits should not be added to the following list.
// Instead, they should be detected by has_extension.
FEATURE(has_nothrow_assign, LangOpts.CPlusPlus)
FEATURE(has_nothrow_copy, LangOpts.CPlusPlus)
FEATURE(has_nothrow_constructor, LangOpts.CPlusPlus)
FEATURE(has_trivial_assign, LangOpts.CPlusPlus)
FEATURE(has_trivial_copy, LangOpts.CPlusPlus)
FEATURE(has_trivial_constructor, LangOpts.CPlusPlus)
FEATURE(has_trivial_destructor, LangOpts.CPlusPlus)
FEATURE(has_virtual_destructor, LangOpts.CPlusPlus)
FEATURE(is_abstract, LangOpts.CPlusPlus)
FEATURE(is_base_of, LangOpts.CPlusPlus)
FEATURE(is_class, LangOpts.CPlusPlus)
FEATURE(is_constructible, LangOpts.CPlusPlus)
FEATURE(is_convertible_to, LangOpts.CPlusPlus)
FEATURE(is_empty, LangOpts.CPlusPlus)
FEATURE(is_enum, LangOpts.CPlusPlus)
FEATURE(is_final, LangOpts.CPlusPlus)
FEATURE(is_literal, LangOpts.CPlusPlus)
FEATURE(is_standard_layout, LangOpts.CPlusPlus)
FEATURE(is_pod, LangOpts.CPlusPlus)
FEATURE(is_polymorphic, LangOpts.CPlusPlus)
FEATURE(is_sealed, LangOpts.CPlusPlus &&LangOpts.MicrosoftExt)
FEATURE(is_trivial, LangOpts.CPlusPlus)
FEATURE(is_trivially_assignable, LangOpts.CPlusPlus)
FEATURE(is_trivially_constructible, LangOpts.CPlusPlus)
FEATURE(is_trivially_copyable, LangOpts.CPlusPlus)
FEATURE(is_union, LangOpts.CPlusPlus)
FEATURE(modules, LangOpts.Modules)
FEATURE(safe_stack, LangOpts.Sanitize.has(SanitizerKind::SafeStack))
FEATURE(shadow_call_stack,
LangOpts.Sanitize.has(SanitizerKind::ShadowCallStack))
FEATURE(tls, PP.getTargetInfo().isTLSSupported())
FEATURE(underlying_type, LangOpts.CPlusPlus)
// C11 features supported by other languages as extensions.
EXTENSION(c_alignas, true)
EXTENSION(c_alignof, true)
EXTENSION(c_atomic, true)
EXTENSION(c_generic_selections, true)
EXTENSION(c_static_assert, true)
EXTENSION(c_thread_local, PP.getTargetInfo().isTLSSupported())
// C++11 features supported by other languages as extensions.
EXTENSION(cxx_atomic, LangOpts.CPlusPlus)
EXTENSION(cxx_deleted_functions, LangOpts.CPlusPlus)
EXTENSION(cxx_explicit_conversions, LangOpts.CPlusPlus)
EXTENSION(cxx_inline_namespaces, LangOpts.CPlusPlus)
EXTENSION(cxx_local_type_template_args, LangOpts.CPlusPlus)
EXTENSION(cxx_nonstatic_member_init, LangOpts.CPlusPlus)
EXTENSION(cxx_override_control, LangOpts.CPlusPlus)
EXTENSION(cxx_range_for, LangOpts.CPlusPlus)
EXTENSION(cxx_reference_qualified_functions, LangOpts.CPlusPlus)
EXTENSION(cxx_rvalue_references, LangOpts.CPlusPlus)
EXTENSION(cxx_variadic_templates, LangOpts.CPlusPlus)
EXTENSION(cxx_fixed_enum, true)
// C++14 features supported by other languages as extensions.
EXTENSION(cxx_binary_literals, true)
EXTENSION(cxx_init_captures, LangOpts.CPlusPlus11)
EXTENSION(cxx_variable_templates, LangOpts.CPlusPlus)
// Miscellaneous language extensions
EXTENSION(overloadable_unmarked, true)
EXTENSION(pragma_clang_attribute_namespaces, true)
#undef EXTENSION
#undef FEATURE
Index: vendor/clang/dist-release_80/include/clang/Basic/FileManager.h
===================================================================
--- vendor/clang/dist-release_80/include/clang/Basic/FileManager.h (revision 343795)
+++ vendor/clang/dist-release_80/include/clang/Basic/FileManager.h (revision 343796)
@@ -1,289 +1,288 @@
//===--- FileManager.h - File System Probing and Caching --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Defines the clang::FileManager interface and associated types.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_FILEMANAGER_H
#define LLVM_CLANG_BASIC_FILEMANAGER_H
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/VirtualFileSystem.h"
#include <ctime>
#include <map>
#include <memory>
#include <string>
namespace llvm {
class MemoryBuffer;
} // end namespace llvm
namespace clang {
class FileSystemStatCache;
/// Cached information about one directory (either on disk or in
/// the virtual file system).
class DirectoryEntry {
friend class FileManager;
StringRef Name; // Name of the directory.
public:
StringRef getName() const { return Name; }
};
/// Cached information about one file (either on disk
/// or in the virtual file system).
///
/// If the 'File' member is valid, then this FileEntry has an open file
/// descriptor for the file.
class FileEntry {
friend class FileManager;
StringRef Name; // Name of the file.
std::string RealPathName; // Real path to the file; could be empty.
off_t Size; // File size in bytes.
time_t ModTime; // Modification time of file.
const DirectoryEntry *Dir; // Directory file lives in.
unsigned UID; // A unique (small) ID for the file.
llvm::sys::fs::UniqueID UniqueID;
bool IsNamedPipe;
bool InPCH;
bool IsValid; // Is this \c FileEntry initialized and valid?
- bool DeferredOpen; // Created by getFile(OpenFile=0); may open later.
/// The open file, if it is owned by the \p FileEntry.
mutable std::unique_ptr<llvm::vfs::File> File;
public:
FileEntry()
- : UniqueID(0, 0), IsNamedPipe(false), InPCH(false), IsValid(false),
- DeferredOpen(false) {}
+ : UniqueID(0, 0), IsNamedPipe(false), InPCH(false), IsValid(false)
+ {}
FileEntry(const FileEntry &) = delete;
FileEntry &operator=(const FileEntry &) = delete;
StringRef getName() const { return Name; }
StringRef tryGetRealPathName() const { return RealPathName; }
bool isValid() const { return IsValid; }
off_t getSize() const { return Size; }
unsigned getUID() const { return UID; }
const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; }
bool isInPCH() const { return InPCH; }
time_t getModificationTime() const { return ModTime; }
/// Return the directory the file lives in.
const DirectoryEntry *getDir() const { return Dir; }
bool operator<(const FileEntry &RHS) const { return UniqueID < RHS.UniqueID; }
/// Check whether the file is a named pipe (and thus can't be opened by
/// the native FileManager methods).
bool isNamedPipe() const { return IsNamedPipe; }
void closeFile() const {
File.reset(); // rely on destructor to close File
}
// Only for use in tests to see if deferred opens are happening, rather than
// relying on RealPathName being empty.
bool isOpenForTests() const { return File != nullptr; }
};
struct FileData;
/// Implements support for file system lookup, file system caching,
/// and directory search management.
///
/// This also handles more advanced properties, such as uniquing files based
/// on "inode", so that a file with two names (e.g. symlinked) will be treated
/// as a single file.
///
class FileManager : public RefCountedBase<FileManager> {
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
FileSystemOptions FileSystemOpts;
/// Cache for existing real directories.
std::map<llvm::sys::fs::UniqueID, DirectoryEntry> UniqueRealDirs;
/// Cache for existing real files.
std::map<llvm::sys::fs::UniqueID, FileEntry> UniqueRealFiles;
/// The virtual directories that we have allocated.
///
/// For each virtual file (e.g. foo/bar/baz.cpp), we add all of its parent
/// directories (foo/ and foo/bar/) here.
SmallVector<std::unique_ptr<DirectoryEntry>, 4> VirtualDirectoryEntries;
/// The virtual files that we have allocated.
SmallVector<std::unique_ptr<FileEntry>, 4> VirtualFileEntries;
/// A cache that maps paths to directory entries (either real or
/// virtual) we have looked up
///
/// The actual Entries for real directories/files are
/// owned by UniqueRealDirs/UniqueRealFiles above, while the Entries
/// for virtual directories/files are owned by
/// VirtualDirectoryEntries/VirtualFileEntries above.
///
llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> SeenDirEntries;
/// A cache that maps paths to file entries (either real or
/// virtual) we have looked up.
///
/// \see SeenDirEntries
llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> SeenFileEntries;
/// The canonical names of directories.
llvm::DenseMap<const DirectoryEntry *, llvm::StringRef> CanonicalDirNames;
/// Storage for canonical names that we have computed.
llvm::BumpPtrAllocator CanonicalNameStorage;
/// Each FileEntry we create is assigned a unique ID #.
///
unsigned NextFileUID;
// Statistics.
unsigned NumDirLookups, NumFileLookups;
unsigned NumDirCacheMisses, NumFileCacheMisses;
// Caching.
std::unique_ptr<FileSystemStatCache> StatCache;
bool getStatValue(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<llvm::vfs::File> *F);
/// Add all ancestors of the given path (pointing to either a file
/// or a directory) as virtual directories.
void addAncestorsAsVirtualDirs(StringRef Path);
/// Fills the RealPathName in file entry.
void fillRealPathName(FileEntry *UFE, llvm::StringRef FileName);
public:
FileManager(const FileSystemOptions &FileSystemOpts,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = nullptr);
~FileManager();
/// Installs the provided FileSystemStatCache object within
/// the FileManager.
///
/// Ownership of this object is transferred to the FileManager.
///
/// \param statCache the new stat cache to install. Ownership of this
/// object is transferred to the FileManager.
void setStatCache(std::unique_ptr<FileSystemStatCache> statCache);
/// Removes the FileSystemStatCache object from the manager.
void clearStatCache();
/// Lookup, cache, and verify the specified directory (real or
/// virtual).
///
/// This returns NULL if the directory doesn't exist.
///
/// \param CacheFailure If true and the file does not exist, we'll cache
/// the failure to find this file.
const DirectoryEntry *getDirectory(StringRef DirName,
bool CacheFailure = true);
/// Lookup, cache, and verify the specified file (real or
/// virtual).
///
/// This returns NULL if the file doesn't exist.
///
/// \param OpenFile if true and the file exists, it will be opened.
///
/// \param CacheFailure If true and the file does not exist, we'll cache
/// the failure to find this file.
const FileEntry *getFile(StringRef Filename, bool OpenFile = false,
bool CacheFailure = true);
/// Returns the current file system options
FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
IntrusiveRefCntPtr<llvm::vfs::FileSystem> getVirtualFileSystem() const {
return FS;
}
/// Retrieve a file entry for a "virtual" file that acts as
/// if there were a file with the given name on disk.
///
/// The file itself is not accessed.
const FileEntry *getVirtualFile(StringRef Filename, off_t Size,
time_t ModificationTime);
/// Open the specified file as a MemoryBuffer, returning a new
/// MemoryBuffer if successful, otherwise returning null.
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBufferForFile(const FileEntry *Entry, bool isVolatile = false,
bool ShouldCloseOpenFile = true);
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getBufferForFile(StringRef Filename, bool isVolatile = false);
/// Get the 'stat' information for the given \p Path.
///
/// If the path is relative, it will be resolved against the WorkingDir of the
/// FileManager's FileSystemOptions.
///
/// \returns false on success, true on error.
bool getNoncachedStatValue(StringRef Path, llvm::vfs::Status &Result);
/// Remove the real file \p Entry from the cache.
void invalidateCache(const FileEntry *Entry);
/// If path is not absolute and FileSystemOptions set the working
/// directory, the path is modified to be relative to the given
/// working directory.
/// \returns true if \c path changed.
bool FixupRelativePath(SmallVectorImpl<char> &path) const;
/// Makes \c Path absolute taking into account FileSystemOptions and the
/// working directory option.
/// \returns true if \c Path changed to absolute.
bool makeAbsolutePath(SmallVectorImpl<char> &Path) const;
/// Produce an array mapping from the unique IDs assigned to each
/// file to the corresponding FileEntry pointer.
void GetUniqueIDMapping(
SmallVectorImpl<const FileEntry *> &UIDToFiles) const;
/// Modifies the size and modification time of a previously created
/// FileEntry. Use with caution.
static void modifyFileEntry(FileEntry *File, off_t Size,
time_t ModificationTime);
/// Retrieve the canonical name for a given directory.
///
/// This is a very expensive operation, despite its results being cached,
/// and should only be used when the physical layout of the file system is
/// required, which is (almost) never.
StringRef getCanonicalName(const DirectoryEntry *Dir);
void PrintStats() const;
};
} // end namespace clang
#endif // LLVM_CLANG_BASIC_FILEMANAGER_H
Index: vendor/clang/dist-release_80/include/clang/Basic/TargetInfo.h
===================================================================
--- vendor/clang/dist-release_80/include/clang/Basic/TargetInfo.h (revision 343795)
+++ vendor/clang/dist-release_80/include/clang/Basic/TargetInfo.h (revision 343796)
@@ -1,1359 +1,1363 @@
//===--- TargetInfo.h - Expose information about the target -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Defines the clang::TargetInfo interface.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_TARGETINFO_H
#define LLVM_CLANG_BASIC_TARGETINFO_H
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetCXXABI.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/VersionTuple.h"
#include <cassert>
#include <string>
#include <vector>
namespace llvm {
struct fltSemantics;
}
namespace clang {
class DiagnosticsEngine;
class LangOptions;
class CodeGenOptions;
class MacroBuilder;
class QualType;
class SourceLocation;
class SourceManager;
namespace Builtin { struct Info; }
/// Exposes information about the current target.
///
class TargetInfo : public RefCountedBase<TargetInfo> {
std::shared_ptr<TargetOptions> TargetOpts;
llvm::Triple Triple;
protected:
// Target values set by the ctor of the actual target implementation. Default
// values are specified by the TargetInfo constructor.
bool BigEndian;
bool TLSSupported;
bool VLASupported;
bool NoAsmVariants; // True if {|} are normal characters.
bool HasLegalHalfType; // True if the backend supports operations on the half
// LLVM IR type.
bool HasFloat128;
+ bool HasFloat16;
unsigned char PointerWidth, PointerAlign;
unsigned char BoolWidth, BoolAlign;
unsigned char IntWidth, IntAlign;
unsigned char HalfWidth, HalfAlign;
unsigned char FloatWidth, FloatAlign;
unsigned char DoubleWidth, DoubleAlign;
unsigned char LongDoubleWidth, LongDoubleAlign, Float128Align;
unsigned char LargeArrayMinWidth, LargeArrayAlign;
unsigned char LongWidth, LongAlign;
unsigned char LongLongWidth, LongLongAlign;
// Fixed point bit widths
unsigned char ShortAccumWidth, ShortAccumAlign;
unsigned char AccumWidth, AccumAlign;
unsigned char LongAccumWidth, LongAccumAlign;
unsigned char ShortFractWidth, ShortFractAlign;
unsigned char FractWidth, FractAlign;
unsigned char LongFractWidth, LongFractAlign;
// If true, unsigned fixed point types have the same number of fractional bits
// as their signed counterparts, forcing the unsigned types to have one extra
// bit of padding. Otherwise, unsigned fixed point types have
// one more fractional bit than its corresponding signed type. This is false
// by default.
bool PaddingOnUnsignedFixedPoint;
// Fixed point integral and fractional bit sizes
// Saturated types share the same integral/fractional bits as their
// corresponding unsaturated types.
// For simplicity, the fractional bits in a _Fract type will be one less the
// width of that _Fract type. This leaves all signed _Fract types having no
// padding and unsigned _Fract types will only have 1 bit of padding after the
// sign if PaddingOnUnsignedFixedPoint is set.
unsigned char ShortAccumScale;
unsigned char AccumScale;
unsigned char LongAccumScale;
unsigned char SuitableAlign;
unsigned char DefaultAlignForAttributeAligned;
unsigned char MinGlobalAlign;
unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
unsigned short MaxVectorAlign;
unsigned short MaxTLSAlign;
unsigned short SimdDefaultAlign;
unsigned short NewAlign;
std::unique_ptr<llvm::DataLayout> DataLayout;
const char *MCountName;
const llvm::fltSemantics *HalfFormat, *FloatFormat, *DoubleFormat,
*LongDoubleFormat, *Float128Format;
unsigned char RegParmMax, SSERegParmMax;
TargetCXXABI TheCXXABI;
const LangASMap *AddrSpaceMap;
mutable StringRef PlatformName;
mutable VersionTuple PlatformMinVersion;
unsigned HasAlignMac68kSupport : 1;
unsigned RealTypeUsesObjCFPRet : 3;
unsigned ComplexLongDoubleUsesFP2Ret : 1;
unsigned HasBuiltinMSVaList : 1;
unsigned IsRenderScriptTarget : 1;
// TargetInfo Constructor. Default initializes all fields.
TargetInfo(const llvm::Triple &T);
void resetDataLayout(StringRef DL) {
DataLayout.reset(new llvm::DataLayout(DL));
}
public:
/// Construct a target for the given options.
///
/// \param Opts - The options to use to initialize the target. The target may
/// modify the options to canonicalize the target feature information to match
/// what the backend expects.
static TargetInfo *
CreateTargetInfo(DiagnosticsEngine &Diags,
const std::shared_ptr<TargetOptions> &Opts);
virtual ~TargetInfo();
/// Retrieve the target options.
TargetOptions &getTargetOpts() const {
assert(TargetOpts && "Missing target options");
return *TargetOpts;
}
///===---- Target Data Type Query Methods -------------------------------===//
enum IntType {
NoInt = 0,
SignedChar,
UnsignedChar,
SignedShort,
UnsignedShort,
SignedInt,
UnsignedInt,
SignedLong,
UnsignedLong,
SignedLongLong,
UnsignedLongLong
};
enum RealType {
NoFloat = 255,
Float = 0,
Double,
LongDouble,
Float128
};
/// The different kinds of __builtin_va_list types defined by
/// the target implementation.
enum BuiltinVaListKind {
/// typedef char* __builtin_va_list;
CharPtrBuiltinVaList = 0,
/// typedef void* __builtin_va_list;
VoidPtrBuiltinVaList,
/// __builtin_va_list as defined by the AArch64 ABI
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055a/IHI0055A_aapcs64.pdf
AArch64ABIBuiltinVaList,
/// __builtin_va_list as defined by the PNaCl ABI:
/// http://www.chromium.org/nativeclient/pnacl/bitcode-abi#TOC-Machine-Types
PNaClABIBuiltinVaList,
/// __builtin_va_list as defined by the Power ABI:
/// https://www.power.org
/// /resources/downloads/Power-Arch-32-bit-ABI-supp-1.0-Embedded.pdf
PowerABIBuiltinVaList,
/// __builtin_va_list as defined by the x86-64 ABI:
/// http://refspecs.linuxbase.org/elf/x86_64-abi-0.21.pdf
X86_64ABIBuiltinVaList,
/// __builtin_va_list as defined by ARM AAPCS ABI
/// http://infocenter.arm.com
// /help/topic/com.arm.doc.ihi0042d/IHI0042D_aapcs.pdf
AAPCSABIBuiltinVaList,
// typedef struct __va_list_tag
// {
// long __gpr;
// long __fpr;
// void *__overflow_arg_area;
// void *__reg_save_area;
// } va_list[1];
SystemZBuiltinVaList
};
protected:
IntType SizeType, IntMaxType, PtrDiffType, IntPtrType, WCharType,
WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType,
ProcessIDType;
/// Whether Objective-C's built-in boolean type should be signed char.
///
/// Otherwise, when this flag is not set, the normal built-in boolean type is
/// used.
unsigned UseSignedCharForObjCBool : 1;
/// Control whether the alignment of bit-field types is respected when laying
/// out structures. If true, then the alignment of the bit-field type will be
/// used to (a) impact the alignment of the containing structure, and (b)
/// ensure that the individual bit-field will not straddle an alignment
/// boundary.
unsigned UseBitFieldTypeAlignment : 1;
/// Whether zero length bitfields (e.g., int : 0;) force alignment of
/// the next bitfield.
///
/// If the alignment of the zero length bitfield is greater than the member
/// that follows it, `bar', `bar' will be aligned as the type of the
/// zero-length bitfield.
unsigned UseZeroLengthBitfieldAlignment : 1;
/// Whether explicit bit field alignment attributes are honored.
unsigned UseExplicitBitFieldAlignment : 1;
/// If non-zero, specifies a fixed alignment value for bitfields that follow
/// zero length bitfield, regardless of the zero length bitfield type.
unsigned ZeroLengthBitfieldBoundary;
/// Specify if mangling based on address space map should be used or
/// not for language specific address spaces
bool UseAddrSpaceMapMangling;
public:
IntType getSizeType() const { return SizeType; }
IntType getSignedSizeType() const {
switch (SizeType) {
case UnsignedShort:
return SignedShort;
case UnsignedInt:
return SignedInt;
case UnsignedLong:
return SignedLong;
case UnsignedLongLong:
return SignedLongLong;
default:
llvm_unreachable("Invalid SizeType");
}
}
IntType getIntMaxType() const { return IntMaxType; }
IntType getUIntMaxType() const {
return getCorrespondingUnsignedType(IntMaxType);
}
IntType getPtrDiffType(unsigned AddrSpace) const {
return AddrSpace == 0 ? PtrDiffType : getPtrDiffTypeV(AddrSpace);
}
IntType getUnsignedPtrDiffType(unsigned AddrSpace) const {
return getCorrespondingUnsignedType(getPtrDiffType(AddrSpace));
}
IntType getIntPtrType() const { return IntPtrType; }
IntType getUIntPtrType() const {
return getCorrespondingUnsignedType(IntPtrType);
}
IntType getWCharType() const { return WCharType; }
IntType getWIntType() const { return WIntType; }
IntType getChar16Type() const { return Char16Type; }
IntType getChar32Type() const { return Char32Type; }
IntType getInt64Type() const { return Int64Type; }
IntType getUInt64Type() const {
return getCorrespondingUnsignedType(Int64Type);
}
IntType getSigAtomicType() const { return SigAtomicType; }
IntType getProcessIDType() const { return ProcessIDType; }
static IntType getCorrespondingUnsignedType(IntType T) {
switch (T) {
case SignedChar:
return UnsignedChar;
case SignedShort:
return UnsignedShort;
case SignedInt:
return UnsignedInt;
case SignedLong:
return UnsignedLong;
case SignedLongLong:
return UnsignedLongLong;
default:
llvm_unreachable("Unexpected signed integer type");
}
}
/// In the event this target uses the same number of fractional bits for its
/// unsigned types as it does with its signed counterparts, there will be
/// exactly one bit of padding.
/// Return true if unsigned fixed point types have padding for this target.
bool doUnsignedFixedPointTypesHavePadding() const {
return PaddingOnUnsignedFixedPoint;
}
/// Return the width (in bits) of the specified integer type enum.
///
/// For example, SignedInt -> getIntWidth().
unsigned getTypeWidth(IntType T) const;
/// Return integer type with specified width.
virtual IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const;
/// Return the smallest integer type with at least the specified width.
virtual IntType getLeastIntTypeByWidth(unsigned BitWidth,
bool IsSigned) const;
/// Return floating point type with specified width.
RealType getRealTypeByWidth(unsigned BitWidth) const;
/// Return the alignment (in bits) of the specified integer type enum.
///
/// For example, SignedInt -> getIntAlign().
unsigned getTypeAlign(IntType T) const;
/// Returns true if the type is signed; false otherwise.
static bool isTypeSigned(IntType T);
/// Return the width of pointers on this target, for the
/// specified address space.
uint64_t getPointerWidth(unsigned AddrSpace) const {
return AddrSpace == 0 ? PointerWidth : getPointerWidthV(AddrSpace);
}
uint64_t getPointerAlign(unsigned AddrSpace) const {
return AddrSpace == 0 ? PointerAlign : getPointerAlignV(AddrSpace);
}
/// Return the maximum width of pointers on this target.
virtual uint64_t getMaxPointerWidth() const {
return PointerWidth;
}
/// Get integer value for null pointer.
/// \param AddrSpace address space of pointee in source language.
virtual uint64_t getNullPointerValue(LangAS AddrSpace) const { return 0; }
/// Return the size of '_Bool' and C++ 'bool' for this target, in bits.
unsigned getBoolWidth() const { return BoolWidth; }
/// Return the alignment of '_Bool' and C++ 'bool' for this target.
unsigned getBoolAlign() const { return BoolAlign; }
unsigned getCharWidth() const { return 8; } // FIXME
unsigned getCharAlign() const { return 8; } // FIXME
/// Return the size of 'signed short' and 'unsigned short' for this
/// target, in bits.
unsigned getShortWidth() const { return 16; } // FIXME
/// Return the alignment of 'signed short' and 'unsigned short' for
/// this target.
unsigned getShortAlign() const { return 16; } // FIXME
/// getIntWidth/Align - Return the size of 'signed int' and 'unsigned int' for
/// this target, in bits.
unsigned getIntWidth() const { return IntWidth; }
unsigned getIntAlign() const { return IntAlign; }
/// getLongWidth/Align - Return the size of 'signed long' and 'unsigned long'
/// for this target, in bits.
unsigned getLongWidth() const { return LongWidth; }
unsigned getLongAlign() const { return LongAlign; }
/// getLongLongWidth/Align - Return the size of 'signed long long' and
/// 'unsigned long long' for this target, in bits.
unsigned getLongLongWidth() const { return LongLongWidth; }
unsigned getLongLongAlign() const { return LongLongAlign; }
/// getShortAccumWidth/Align - Return the size of 'signed short _Accum' and
/// 'unsigned short _Accum' for this target, in bits.
unsigned getShortAccumWidth() const { return ShortAccumWidth; }
unsigned getShortAccumAlign() const { return ShortAccumAlign; }
/// getAccumWidth/Align - Return the size of 'signed _Accum' and
/// 'unsigned _Accum' for this target, in bits.
unsigned getAccumWidth() const { return AccumWidth; }
unsigned getAccumAlign() const { return AccumAlign; }
/// getLongAccumWidth/Align - Return the size of 'signed long _Accum' and
/// 'unsigned long _Accum' for this target, in bits.
unsigned getLongAccumWidth() const { return LongAccumWidth; }
unsigned getLongAccumAlign() const { return LongAccumAlign; }
/// getShortFractWidth/Align - Return the size of 'signed short _Fract' and
/// 'unsigned short _Fract' for this target, in bits.
unsigned getShortFractWidth() const { return ShortFractWidth; }
unsigned getShortFractAlign() const { return ShortFractAlign; }
/// getFractWidth/Align - Return the size of 'signed _Fract' and
/// 'unsigned _Fract' for this target, in bits.
unsigned getFractWidth() const { return FractWidth; }
unsigned getFractAlign() const { return FractAlign; }
/// getLongFractWidth/Align - Return the size of 'signed long _Fract' and
/// 'unsigned long _Fract' for this target, in bits.
unsigned getLongFractWidth() const { return LongFractWidth; }
unsigned getLongFractAlign() const { return LongFractAlign; }
/// getShortAccumScale/IBits - Return the number of fractional/integral bits
/// in a 'signed short _Accum' type.
unsigned getShortAccumScale() const { return ShortAccumScale; }
unsigned getShortAccumIBits() const {
return ShortAccumWidth - ShortAccumScale - 1;
}
/// getAccumScale/IBits - Return the number of fractional/integral bits
/// in a 'signed _Accum' type.
unsigned getAccumScale() const { return AccumScale; }
unsigned getAccumIBits() const { return AccumWidth - AccumScale - 1; }
/// getLongAccumScale/IBits - Return the number of fractional/integral bits
/// in a 'signed long _Accum' type.
unsigned getLongAccumScale() const { return LongAccumScale; }
unsigned getLongAccumIBits() const {
return LongAccumWidth - LongAccumScale - 1;
}
/// getUnsignedShortAccumScale/IBits - Return the number of
/// fractional/integral bits in a 'unsigned short _Accum' type.
unsigned getUnsignedShortAccumScale() const {
return PaddingOnUnsignedFixedPoint ? ShortAccumScale : ShortAccumScale + 1;
}
unsigned getUnsignedShortAccumIBits() const {
return PaddingOnUnsignedFixedPoint
? getShortAccumIBits()
: ShortAccumWidth - getUnsignedShortAccumScale();
}
/// getUnsignedAccumScale/IBits - Return the number of fractional/integral
/// bits in a 'unsigned _Accum' type.
unsigned getUnsignedAccumScale() const {
return PaddingOnUnsignedFixedPoint ? AccumScale : AccumScale + 1;
}
unsigned getUnsignedAccumIBits() const {
return PaddingOnUnsignedFixedPoint ? getAccumIBits()
: AccumWidth - getUnsignedAccumScale();
}
/// getUnsignedLongAccumScale/IBits - Return the number of fractional/integral
/// bits in a 'unsigned long _Accum' type.
unsigned getUnsignedLongAccumScale() const {
return PaddingOnUnsignedFixedPoint ? LongAccumScale : LongAccumScale + 1;
}
unsigned getUnsignedLongAccumIBits() const {
return PaddingOnUnsignedFixedPoint
? getLongAccumIBits()
: LongAccumWidth - getUnsignedLongAccumScale();
}
/// getShortFractScale - Return the number of fractional bits
/// in a 'signed short _Fract' type.
unsigned getShortFractScale() const { return ShortFractWidth - 1; }
/// getFractScale - Return the number of fractional bits
/// in a 'signed _Fract' type.
unsigned getFractScale() const { return FractWidth - 1; }
/// getLongFractScale - Return the number of fractional bits
/// in a 'signed long _Fract' type.
unsigned getLongFractScale() const { return LongFractWidth - 1; }
/// getUnsignedShortFractScale - Return the number of fractional bits
/// in a 'unsigned short _Fract' type.
unsigned getUnsignedShortFractScale() const {
return PaddingOnUnsignedFixedPoint ? getShortFractScale()
: getShortFractScale() + 1;
}
/// getUnsignedFractScale - Return the number of fractional bits
/// in a 'unsigned _Fract' type.
unsigned getUnsignedFractScale() const {
return PaddingOnUnsignedFixedPoint ? getFractScale() : getFractScale() + 1;
}
/// getUnsignedLongFractScale - Return the number of fractional bits
/// in a 'unsigned long _Fract' type.
unsigned getUnsignedLongFractScale() const {
return PaddingOnUnsignedFixedPoint ? getLongFractScale()
: getLongFractScale() + 1;
}
/// Determine whether the __int128 type is supported on this target.
virtual bool hasInt128Type() const {
return (getPointerWidth(0) >= 64) || getTargetOpts().ForceEnableInt128;
} // FIXME
/// Determine whether _Float16 is supported on this target.
virtual bool hasLegalHalfType() const { return HasLegalHalfType; }
/// Determine whether the __float128 type is supported on this target.
virtual bool hasFloat128Type() const { return HasFloat128; }
+
+ /// Determine whether the _Float16 type is supported on this target.
+ virtual bool hasFloat16Type() const { return HasFloat16; }
/// Return the alignment that is suitable for storing any
/// object with a fundamental alignment requirement.
unsigned getSuitableAlign() const { return SuitableAlign; }
/// Return the default alignment for __attribute__((aligned)) on
/// this target, to be used if no alignment value is specified.
unsigned getDefaultAlignForAttributeAligned() const {
return DefaultAlignForAttributeAligned;
}
/// getMinGlobalAlign - Return the minimum alignment of a global variable,
/// unless its alignment is explicitly reduced via attributes.
unsigned getMinGlobalAlign() const { return MinGlobalAlign; }
/// Return the largest alignment for which a suitably-sized allocation with
/// '::operator new(size_t)' is guaranteed to produce a correctly-aligned
/// pointer.
unsigned getNewAlign() const {
return NewAlign ? NewAlign : std::max(LongDoubleAlign, LongLongAlign);
}
/// getWCharWidth/Align - Return the size of 'wchar_t' for this target, in
/// bits.
unsigned getWCharWidth() const { return getTypeWidth(WCharType); }
unsigned getWCharAlign() const { return getTypeAlign(WCharType); }
/// getChar16Width/Align - Return the size of 'char16_t' for this target, in
/// bits.
unsigned getChar16Width() const { return getTypeWidth(Char16Type); }
unsigned getChar16Align() const { return getTypeAlign(Char16Type); }
/// getChar32Width/Align - Return the size of 'char32_t' for this target, in
/// bits.
unsigned getChar32Width() const { return getTypeWidth(Char32Type); }
unsigned getChar32Align() const { return getTypeAlign(Char32Type); }
/// getHalfWidth/Align/Format - Return the size/align/format of 'half'.
unsigned getHalfWidth() const { return HalfWidth; }
unsigned getHalfAlign() const { return HalfAlign; }
const llvm::fltSemantics &getHalfFormat() const { return *HalfFormat; }
/// getFloatWidth/Align/Format - Return the size/align/format of 'float'.
unsigned getFloatWidth() const { return FloatWidth; }
unsigned getFloatAlign() const { return FloatAlign; }
const llvm::fltSemantics &getFloatFormat() const { return *FloatFormat; }
/// getDoubleWidth/Align/Format - Return the size/align/format of 'double'.
unsigned getDoubleWidth() const { return DoubleWidth; }
unsigned getDoubleAlign() const { return DoubleAlign; }
const llvm::fltSemantics &getDoubleFormat() const { return *DoubleFormat; }
/// getLongDoubleWidth/Align/Format - Return the size/align/format of 'long
/// double'.
unsigned getLongDoubleWidth() const { return LongDoubleWidth; }
unsigned getLongDoubleAlign() const { return LongDoubleAlign; }
const llvm::fltSemantics &getLongDoubleFormat() const {
return *LongDoubleFormat;
}
/// getFloat128Width/Align/Format - Return the size/align/format of
/// '__float128'.
unsigned getFloat128Width() const { return 128; }
unsigned getFloat128Align() const { return Float128Align; }
const llvm::fltSemantics &getFloat128Format() const {
return *Float128Format;
}
/// Return true if the 'long double' type should be mangled like
/// __float128.
virtual bool useFloat128ManglingForLongDouble() const { return false; }
/// Return the value for the C99 FLT_EVAL_METHOD macro.
virtual unsigned getFloatEvalMethod() const { return 0; }
// getLargeArrayMinWidth/Align - Return the minimum array size that is
// 'large' and its alignment.
unsigned getLargeArrayMinWidth() const { return LargeArrayMinWidth; }
unsigned getLargeArrayAlign() const { return LargeArrayAlign; }
/// Return the maximum width lock-free atomic operation which will
/// ever be supported for the given target
unsigned getMaxAtomicPromoteWidth() const { return MaxAtomicPromoteWidth; }
/// Return the maximum width lock-free atomic operation which can be
/// inlined given the supported features of the given target.
unsigned getMaxAtomicInlineWidth() const { return MaxAtomicInlineWidth; }
/// Set the maximum inline or promote width lock-free atomic operation
/// for the given target.
virtual void setMaxAtomicWidth() {}
/// Returns true if the given target supports lock-free atomic
/// operations at the specified width and alignment.
virtual bool hasBuiltinAtomic(uint64_t AtomicSizeInBits,
uint64_t AlignmentInBits) const {
return AtomicSizeInBits <= AlignmentInBits &&
AtomicSizeInBits <= getMaxAtomicInlineWidth() &&
(AtomicSizeInBits <= getCharWidth() ||
llvm::isPowerOf2_64(AtomicSizeInBits / getCharWidth()));
}
/// Return the maximum vector alignment supported for the given target.
unsigned getMaxVectorAlign() const { return MaxVectorAlign; }
/// Return default simd alignment for the given target. Generally, this
/// value is type-specific, but this alignment can be used for most of the
/// types for the given target.
unsigned getSimdDefaultAlign() const { return SimdDefaultAlign; }
/// Return the size of intmax_t and uintmax_t for this target, in bits.
unsigned getIntMaxTWidth() const {
return getTypeWidth(IntMaxType);
}
// Return the size of unwind_word for this target.
virtual unsigned getUnwindWordWidth() const { return getPointerWidth(0); }
/// Return the "preferred" register width on this target.
virtual unsigned getRegisterWidth() const {
// Currently we assume the register width on the target matches the pointer
// width, we can introduce a new variable for this if/when some target wants
// it.
return PointerWidth;
}
/// Returns the name of the mcount instrumentation function.
const char *getMCountName() const {
return MCountName;
}
/// Check if the Objective-C built-in boolean type should be signed
/// char.
///
/// Otherwise, if this returns false, the normal built-in boolean type
/// should also be used for Objective-C.
bool useSignedCharForObjCBool() const {
return UseSignedCharForObjCBool;
}
void noSignedCharForObjCBool() {
UseSignedCharForObjCBool = false;
}
/// Check whether the alignment of bit-field types is respected
/// when laying out structures.
bool useBitFieldTypeAlignment() const {
return UseBitFieldTypeAlignment;
}
/// Check whether zero length bitfields should force alignment of
/// the next member.
bool useZeroLengthBitfieldAlignment() const {
return UseZeroLengthBitfieldAlignment;
}
/// Get the fixed alignment value in bits for a member that follows
/// a zero length bitfield.
unsigned getZeroLengthBitfieldBoundary() const {
return ZeroLengthBitfieldBoundary;
}
/// Check whether explicit bitfield alignment attributes should be
// honored, as in "__attribute__((aligned(2))) int b : 1;".
bool useExplicitBitFieldAlignment() const {
return UseExplicitBitFieldAlignment;
}
/// Check whether this target support '\#pragma options align=mac68k'.
bool hasAlignMac68kSupport() const {
return HasAlignMac68kSupport;
}
/// Return the user string for the specified integer type enum.
///
/// For example, SignedShort -> "short".
static const char *getTypeName(IntType T);
/// Return the constant suffix for the specified integer type enum.
///
/// For example, SignedLong -> "L".
const char *getTypeConstantSuffix(IntType T) const;
/// Return the printf format modifier for the specified
/// integer type enum.
///
/// For example, SignedLong -> "l".
static const char *getTypeFormatModifier(IntType T);
/// Check whether the given real type should use the "fpret" flavor of
/// Objective-C message passing on this target.
bool useObjCFPRetForRealType(RealType T) const {
return RealTypeUsesObjCFPRet & (1 << T);
}
/// Check whether _Complex long double should use the "fp2ret" flavor
/// of Objective-C message passing on this target.
bool useObjCFP2RetForComplexLongDouble() const {
return ComplexLongDoubleUsesFP2Ret;
}
/// Check whether llvm intrinsics such as llvm.convert.to.fp16 should be used
/// to convert to and from __fp16.
/// FIXME: This function should be removed once all targets stop using the
/// conversion intrinsics.
virtual bool useFP16ConversionIntrinsics() const {
return true;
}
/// Specify if mangling based on address space map should be used or
/// not for language specific address spaces
bool useAddressSpaceMapMangling() const {
return UseAddrSpaceMapMangling;
}
///===---- Other target property query methods --------------------------===//
/// Appends the target-specific \#define values for this
/// target set to the specified buffer.
virtual void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const = 0;
/// Return information about target-specific builtins for
/// the current primary target, and info about which builtins are non-portable
/// across the current set of primary and secondary targets.
virtual ArrayRef<Builtin::Info> getTargetBuiltins() const = 0;
/// The __builtin_clz* and __builtin_ctz* built-in
/// functions are specified to have undefined results for zero inputs, but
/// on targets that support these operations in a way that provides
/// well-defined results for zero without loss of performance, it is a good
/// idea to avoid optimizing based on that undef behavior.
virtual bool isCLZForZeroUndef() const { return true; }
/// Returns the kind of __builtin_va_list type that should be used
/// with this target.
virtual BuiltinVaListKind getBuiltinVaListKind() const = 0;
/// Returns whether or not type \c __builtin_ms_va_list type is
/// available on this target.
bool hasBuiltinMSVaList() const { return HasBuiltinMSVaList; }
/// Returns true for RenderScript.
bool isRenderScriptTarget() const { return IsRenderScriptTarget; }
/// Returns whether the passed in string is a valid clobber in an
/// inline asm statement.
///
/// This is used by Sema.
bool isValidClobber(StringRef Name) const;
/// Returns whether the passed in string is a valid register name
/// according to GCC.
///
/// This is used by Sema for inline asm statements.
virtual bool isValidGCCRegisterName(StringRef Name) const;
/// Returns the "normalized" GCC register name.
///
/// ReturnCannonical true will return the register name without any additions
/// such as "{}" or "%" in it's canonical form, for example:
/// ReturnCanonical = true and Name = "rax", will return "ax".
StringRef getNormalizedGCCRegisterName(StringRef Name,
bool ReturnCanonical = false) const;
/// Extracts a register from the passed constraint (if it is a
/// single-register constraint) and the asm label expression related to a
/// variable in the input or output list of an inline asm statement.
///
/// This function is used by Sema in order to diagnose conflicts between
/// the clobber list and the input/output lists.
virtual StringRef getConstraintRegister(StringRef Constraint,
StringRef Expression) const {
return "";
}
struct ConstraintInfo {
enum {
CI_None = 0x00,
CI_AllowsMemory = 0x01,
CI_AllowsRegister = 0x02,
CI_ReadWrite = 0x04, // "+r" output constraint (read and write).
CI_HasMatchingInput = 0x08, // This output operand has a matching input.
CI_ImmediateConstant = 0x10, // This operand must be an immediate constant
CI_EarlyClobber = 0x20, // "&" output constraint (early clobber).
};
unsigned Flags;
int TiedOperand;
struct {
int Min;
int Max;
} ImmRange;
llvm::SmallSet<int, 4> ImmSet;
std::string ConstraintStr; // constraint: "=rm"
std::string Name; // Operand name: [foo] with no []'s.
public:
ConstraintInfo(StringRef ConstraintStr, StringRef Name)
: Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()),
Name(Name.str()) {
ImmRange.Min = ImmRange.Max = 0;
}
const std::string &getConstraintStr() const { return ConstraintStr; }
const std::string &getName() const { return Name; }
bool isReadWrite() const { return (Flags & CI_ReadWrite) != 0; }
bool earlyClobber() { return (Flags & CI_EarlyClobber) != 0; }
bool allowsRegister() const { return (Flags & CI_AllowsRegister) != 0; }
bool allowsMemory() const { return (Flags & CI_AllowsMemory) != 0; }
/// Return true if this output operand has a matching
/// (tied) input operand.
bool hasMatchingInput() const { return (Flags & CI_HasMatchingInput) != 0; }
/// Return true if this input operand is a matching
/// constraint that ties it to an output operand.
///
/// If this returns true then getTiedOperand will indicate which output
/// operand this is tied to.
bool hasTiedOperand() const { return TiedOperand != -1; }
unsigned getTiedOperand() const {
assert(hasTiedOperand() && "Has no tied operand!");
return (unsigned)TiedOperand;
}
bool requiresImmediateConstant() const {
return (Flags & CI_ImmediateConstant) != 0;
}
bool isValidAsmImmediate(const llvm::APInt &Value) const {
return (Value.sge(ImmRange.Min) && Value.sle(ImmRange.Max)) ||
ImmSet.count(Value.getZExtValue()) != 0;
}
void setIsReadWrite() { Flags |= CI_ReadWrite; }
void setEarlyClobber() { Flags |= CI_EarlyClobber; }
void setAllowsMemory() { Flags |= CI_AllowsMemory; }
void setAllowsRegister() { Flags |= CI_AllowsRegister; }
void setHasMatchingInput() { Flags |= CI_HasMatchingInput; }
void setRequiresImmediate(int Min, int Max) {
Flags |= CI_ImmediateConstant;
ImmRange.Min = Min;
ImmRange.Max = Max;
}
void setRequiresImmediate(llvm::ArrayRef<int> Exacts) {
Flags |= CI_ImmediateConstant;
for (int Exact : Exacts)
ImmSet.insert(Exact);
}
void setRequiresImmediate(int Exact) {
Flags |= CI_ImmediateConstant;
ImmSet.insert(Exact);
}
void setRequiresImmediate() {
Flags |= CI_ImmediateConstant;
ImmRange.Min = INT_MIN;
ImmRange.Max = INT_MAX;
}
/// Indicate that this is an input operand that is tied to
/// the specified output operand.
///
/// Copy over the various constraint information from the output.
void setTiedOperand(unsigned N, ConstraintInfo &Output) {
Output.setHasMatchingInput();
Flags = Output.Flags;
TiedOperand = N;
// Don't copy Name or constraint string.
}
};
/// Validate register name used for global register variables.
///
/// This function returns true if the register passed in RegName can be used
/// for global register variables on this target. In addition, it returns
/// true in HasSizeMismatch if the size of the register doesn't match the
/// variable size passed in RegSize.
virtual bool validateGlobalRegisterVariable(StringRef RegName,
unsigned RegSize,
bool &HasSizeMismatch) const {
HasSizeMismatch = false;
return true;
}
// validateOutputConstraint, validateInputConstraint - Checks that
// a constraint is valid and provides information about it.
// FIXME: These should return a real error instead of just true/false.
bool validateOutputConstraint(ConstraintInfo &Info) const;
bool validateInputConstraint(MutableArrayRef<ConstraintInfo> OutputConstraints,
ConstraintInfo &info) const;
virtual bool validateOutputSize(StringRef /*Constraint*/,
unsigned /*Size*/) const {
return true;
}
virtual bool validateInputSize(StringRef /*Constraint*/,
unsigned /*Size*/) const {
return true;
}
virtual bool
validateConstraintModifier(StringRef /*Constraint*/,
char /*Modifier*/,
unsigned /*Size*/,
std::string &/*SuggestedModifier*/) const {
return true;
}
virtual bool
validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const = 0;
bool resolveSymbolicName(const char *&Name,
ArrayRef<ConstraintInfo> OutputConstraints,
unsigned &Index) const;
// Constraint parm will be left pointing at the last character of
// the constraint. In practice, it won't be changed unless the
// constraint is longer than one character.
virtual std::string convertConstraint(const char *&Constraint) const {
// 'p' defaults to 'r', but can be overridden by targets.
if (*Constraint == 'p')
return std::string("r");
return std::string(1, *Constraint);
}
/// Returns a string of target-specific clobbers, in LLVM format.
virtual const char *getClobbers() const = 0;
/// Returns true if NaN encoding is IEEE 754-2008.
/// Only MIPS allows a different encoding.
virtual bool isNan2008() const {
return true;
}
/// Returns the target triple of the primary target.
const llvm::Triple &getTriple() const {
return Triple;
}
const llvm::DataLayout &getDataLayout() const {
assert(DataLayout && "Uninitialized DataLayout!");
return *DataLayout;
}
struct GCCRegAlias {
const char * const Aliases[5];
const char * const Register;
};
struct AddlRegName {
const char * const Names[5];
const unsigned RegNum;
};
/// Does this target support "protected" visibility?
///
/// Any target which dynamic libraries will naturally support
/// something like "default" (meaning that the symbol is visible
/// outside this shared object) and "hidden" (meaning that it isn't)
/// visibilities, but "protected" is really an ELF-specific concept
/// with weird semantics designed around the convenience of dynamic
/// linker implementations. Which is not to suggest that there's
/// consistent target-independent semantics for "default" visibility
/// either; the entire thing is pretty badly mangled.
virtual bool hasProtectedVisibility() const { return true; }
/// An optional hook that targets can implement to perform semantic
/// checking on attribute((section("foo"))) specifiers.
///
/// In this case, "foo" is passed in to be checked. If the section
/// specifier is invalid, the backend should return a non-empty string
/// that indicates the problem.
///
/// This hook is a simple quality of implementation feature to catch errors
/// and give good diagnostics in cases when the assembler or code generator
/// would otherwise reject the section specifier.
///
virtual std::string isValidSectionSpecifier(StringRef SR) const {
return "";
}
/// Set forced language options.
///
/// Apply changes to the target information with respect to certain
/// language options which change the target configuration and adjust
/// the language based on the target options where applicable.
virtual void adjust(LangOptions &Opts);
/// Adjust target options based on codegen options.
virtual void adjustTargetOptions(const CodeGenOptions &CGOpts,
TargetOptions &TargetOpts) const {}
/// Initialize the map with the default set of target features for the
/// CPU this should include all legal feature strings on the target.
///
/// \return False on error (invalid features).
virtual bool initFeatureMap(llvm::StringMap<bool> &Features,
DiagnosticsEngine &Diags, StringRef CPU,
const std::vector<std::string> &FeatureVec) const;
/// Get the ABI currently in use.
virtual StringRef getABI() const { return StringRef(); }
/// Get the C++ ABI currently in use.
TargetCXXABI getCXXABI() const {
return TheCXXABI;
}
/// Target the specified CPU.
///
/// \return False on error (invalid CPU name).
virtual bool setCPU(const std::string &Name) {
return false;
}
/// Fill a SmallVectorImpl with the valid values to setCPU.
virtual void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {}
/// brief Determine whether this TargetInfo supports the given CPU name.
virtual bool isValidCPUName(StringRef Name) const {
return true;
}
/// Use the specified ABI.
///
/// \return False on error (invalid ABI name).
virtual bool setABI(const std::string &Name) {
return false;
}
/// Use the specified unit for FP math.
///
/// \return False on error (invalid unit name).
virtual bool setFPMath(StringRef Name) {
return false;
}
/// Enable or disable a specific target feature;
/// the feature name must be valid.
virtual void setFeatureEnabled(llvm::StringMap<bool> &Features,
StringRef Name,
bool Enabled) const {
Features[Name] = Enabled;
}
/// Determine whether this TargetInfo supports the given feature.
virtual bool isValidFeatureName(StringRef Feature) const {
return true;
}
/// Perform initialization based on the user configured
/// set of features (e.g., +sse4).
///
/// The list is guaranteed to have at most one entry per feature.
///
/// The target may modify the features list, to change which options are
/// passed onwards to the backend.
/// FIXME: This part should be fixed so that we can change handleTargetFeatures
/// to merely a TargetInfo initialization routine.
///
/// \return False on error.
virtual bool handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) {
return true;
}
/// Determine whether the given target has the given feature.
virtual bool hasFeature(StringRef Feature) const {
return false;
}
/// Identify whether this target supports multiversioning of functions,
/// which requires support for cpu_supports and cpu_is functionality.
bool supportsMultiVersioning() const {
return getTriple().getArch() == llvm::Triple::x86 ||
getTriple().getArch() == llvm::Triple::x86_64;
}
/// Identify whether this target supports IFuncs.
bool supportsIFunc() const { return getTriple().isOSBinFormatELF(); }
// Validate the contents of the __builtin_cpu_supports(const char*)
// argument.
virtual bool validateCpuSupports(StringRef Name) const { return false; }
// Return the target-specific priority for features/cpus/vendors so
// that they can be properly sorted for checking.
virtual unsigned multiVersionSortPriority(StringRef Name) const {
return 0;
}
// Validate the contents of the __builtin_cpu_is(const char*)
// argument.
virtual bool validateCpuIs(StringRef Name) const { return false; }
// Validate a cpu_dispatch/cpu_specific CPU option, which is a different list
// from cpu_is, since it checks via features rather than CPUs directly.
virtual bool validateCPUSpecificCPUDispatch(StringRef Name) const {
return false;
}
// Get the character to be added for mangling purposes for cpu_specific.
virtual char CPUSpecificManglingCharacter(StringRef Name) const {
llvm_unreachable(
"cpu_specific Multiversioning not implemented on this target");
}
// Get a list of the features that make up the CPU option for
// cpu_specific/cpu_dispatch so that it can be passed to llvm as optimization
// options.
virtual void getCPUSpecificCPUDispatchFeatures(
StringRef Name, llvm::SmallVectorImpl<StringRef> &Features) const {
llvm_unreachable(
"cpu_specific Multiversioning not implemented on this target");
}
// Returns maximal number of args passed in registers.
unsigned getRegParmMax() const {
assert(RegParmMax < 7 && "RegParmMax value is larger than AST can handle");
return RegParmMax;
}
/// Whether the target supports thread-local storage.
bool isTLSSupported() const {
return TLSSupported;
}
/// Return the maximum alignment (in bits) of a TLS variable
///
/// Gets the maximum alignment (in bits) of a TLS variable on this target.
/// Returns zero if there is no such constraint.
unsigned short getMaxTLSAlign() const {
return MaxTLSAlign;
}
/// Whether target supports variable-length arrays.
bool isVLASupported() const { return VLASupported; }
/// Whether the target supports SEH __try.
bool isSEHTrySupported() const {
return getTriple().isOSWindows() &&
(getTriple().getArch() == llvm::Triple::x86 ||
getTriple().getArch() == llvm::Triple::x86_64 ||
getTriple().getArch() == llvm::Triple::aarch64);
}
/// Return true if {|} are normal characters in the asm string.
///
/// If this returns false (the default), then {abc|xyz} is syntax
/// that says that when compiling for asm variant #0, "abc" should be
/// generated, but when compiling for asm variant #1, "xyz" should be
/// generated.
bool hasNoAsmVariants() const {
return NoAsmVariants;
}
/// Return the register number that __builtin_eh_return_regno would
/// return with the specified argument.
/// This corresponds with TargetLowering's getExceptionPointerRegister
/// and getExceptionSelectorRegister in the backend.
virtual int getEHDataRegisterNumber(unsigned RegNo) const {
return -1;
}
/// Return the section to use for C++ static initialization functions.
virtual const char *getStaticInitSectionSpecifier() const {
return nullptr;
}
const LangASMap &getAddressSpaceMap() const { return *AddrSpaceMap; }
/// Map from the address space field in builtin description strings to the
/// language address space.
virtual LangAS getOpenCLBuiltinAddressSpace(unsigned AS) const {
return getLangASFromTargetAS(AS);
}
/// Map from the address space field in builtin description strings to the
/// language address space.
virtual LangAS getCUDABuiltinAddressSpace(unsigned AS) const {
return getLangASFromTargetAS(AS);
}
/// Return an AST address space which can be used opportunistically
/// for constant global memory. It must be possible to convert pointers into
/// this address space to LangAS::Default. If no such address space exists,
/// this may return None, and such optimizations will be disabled.
virtual llvm::Optional<LangAS> getConstantAddressSpace() const {
return LangAS::Default;
}
/// Retrieve the name of the platform as it is used in the
/// availability attribute.
StringRef getPlatformName() const { return PlatformName; }
/// Retrieve the minimum desired version of the platform, to
/// which the program should be compiled.
VersionTuple getPlatformMinVersion() const { return PlatformMinVersion; }
bool isBigEndian() const { return BigEndian; }
bool isLittleEndian() const { return !BigEndian; }
enum CallingConvMethodType {
CCMT_Unknown,
CCMT_Member,
CCMT_NonMember
};
/// Gets the default calling convention for the given target and
/// declaration context.
virtual CallingConv getDefaultCallingConv(CallingConvMethodType MT) const {
// Not all targets will specify an explicit calling convention that we can
// express. This will always do the right thing, even though it's not
// an explicit calling convention.
return CC_C;
}
enum CallingConvCheckResult {
CCCR_OK,
CCCR_Warning,
CCCR_Ignore,
};
/// Determines whether a given calling convention is valid for the
/// target. A calling convention can either be accepted, produce a warning
/// and be substituted with the default calling convention, or (someday)
/// produce an error (such as using thiscall on a non-instance function).
virtual CallingConvCheckResult checkCallingConvention(CallingConv CC) const {
switch (CC) {
default:
return CCCR_Warning;
case CC_C:
return CCCR_OK;
}
}
enum CallingConvKind {
CCK_Default,
CCK_ClangABI4OrPS4,
CCK_MicrosoftWin64
};
virtual CallingConvKind getCallingConvKind(bool ClangABICompat4) const;
/// Controls if __builtin_longjmp / __builtin_setjmp can be lowered to
/// llvm.eh.sjlj.longjmp / llvm.eh.sjlj.setjmp.
virtual bool hasSjLjLowering() const {
return false;
}
/// Check if the target supports CFProtection branch.
virtual bool
checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const;
/// Check if the target supports CFProtection branch.
virtual bool
checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const;
/// Whether target allows to overalign ABI-specified preferred alignment
virtual bool allowsLargerPreferedTypeAlignment() const { return true; }
/// Set supported OpenCL extensions and optional core features.
virtual void setSupportedOpenCLOpts() {}
/// Set supported OpenCL extensions as written on command line
virtual void setOpenCLExtensionOpts() {
for (const auto &Ext : getTargetOpts().OpenCLExtensionsAsWritten) {
getTargetOpts().SupportedOpenCLOptions.support(Ext);
}
}
/// Get supported OpenCL extensions and optional core features.
OpenCLOptions &getSupportedOpenCLOpts() {
return getTargetOpts().SupportedOpenCLOptions;
}
/// Get const supported OpenCL extensions and optional core features.
const OpenCLOptions &getSupportedOpenCLOpts() const {
return getTargetOpts().SupportedOpenCLOptions;
}
enum OpenCLTypeKind {
OCLTK_Default,
OCLTK_ClkEvent,
OCLTK_Event,
OCLTK_Image,
OCLTK_Pipe,
OCLTK_Queue,
OCLTK_ReserveID,
OCLTK_Sampler,
};
/// Get address space for OpenCL type.
virtual LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const;
/// \returns Target specific vtbl ptr address space.
virtual unsigned getVtblPtrAddressSpace() const {
return 0;
}
/// \returns If a target requires an address within a target specific address
/// space \p AddressSpace to be converted in order to be used, then return the
/// corresponding target specific DWARF address space.
///
/// \returns Otherwise return None and no conversion will be emitted in the
/// DWARF.
virtual Optional<unsigned> getDWARFAddressSpace(unsigned AddressSpace) const {
return None;
}
/// \returns The version of the SDK which was used during the compilation if
/// one was specified, or an empty version otherwise.
const llvm::VersionTuple &getSDKVersion() const {
return getTargetOpts().SDKVersion;
}
/// Check the target is valid after it is fully initialized.
virtual bool validateTarget(DiagnosticsEngine &Diags) const {
return true;
}
protected:
virtual uint64_t getPointerWidthV(unsigned AddrSpace) const {
return PointerWidth;
}
virtual uint64_t getPointerAlignV(unsigned AddrSpace) const {
return PointerAlign;
}
virtual enum IntType getPtrDiffTypeV(unsigned AddrSpace) const {
return PtrDiffType;
}
virtual ArrayRef<const char *> getGCCRegNames() const = 0;
virtual ArrayRef<GCCRegAlias> getGCCRegAliases() const = 0;
virtual ArrayRef<AddlRegName> getGCCAddlRegNames() const {
return None;
}
private:
// Assert the values for the fractional and integral bits for each fixed point
// type follow the restrictions given in clause 6.2.6.3 of N1169.
void CheckFixedPointBits() const;
};
} // end namespace clang
#endif
Index: vendor/clang/dist-release_80/include/clang/Driver/Options.td
===================================================================
--- vendor/clang/dist-release_80/include/clang/Driver/Options.td (revision 343795)
+++ vendor/clang/dist-release_80/include/clang/Driver/Options.td (revision 343796)
@@ -1,3144 +1,3152 @@
//===--- Options.td - Options for clang -----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the options accepted by clang.
//
//===----------------------------------------------------------------------===//
// Include the common option parsing interfaces.
include "llvm/Option/OptParser.td"
/////////
// Flags
// DriverOption - The option is a "driver" option, and should not be forwarded
// to other tools.
def DriverOption : OptionFlag;
// LinkerInput - The option is a linker input.
def LinkerInput : OptionFlag;
// NoArgumentUnused - Don't report argument unused warnings for this option; this
// is useful for options like -static or -dynamic which a user may always end up
// passing, even if the platform defaults to (or only supports) that option.
def NoArgumentUnused : OptionFlag;
// Unsupported - The option is unsupported, and the driver will reject command
// lines that use it.
def Unsupported : OptionFlag;
// Ignored - The option is unsupported, and the driver will silently ignore it.
def Ignored : OptionFlag;
// CoreOption - This is considered a "core" Clang option, available in both
// clang and clang-cl modes.
def CoreOption : OptionFlag;
// CLOption - This is a cl.exe compatibility option. Options with this flag
// are made available when the driver is running in CL compatibility mode.
def CLOption : OptionFlag;
// CC1Option - This option should be accepted by clang -cc1.
def CC1Option : OptionFlag;
// CC1AsOption - This option should be accepted by clang -cc1as.
def CC1AsOption : OptionFlag;
// NoDriverOption - This option should not be accepted by the driver.
def NoDriverOption : OptionFlag;
// A short name to show in documentation. The name will be interpreted as rST.
class DocName<string name> { string DocName = name; }
// A brief description to show in documentation, interpreted as rST.
class DocBrief<code descr> { code DocBrief = descr; }
// Indicates that this group should be flattened into its parent when generating
// documentation.
class DocFlatten { bit DocFlatten = 1; }
// Indicates that this warning is ignored, but accepted with a warning for
// GCC compatibility.
class IgnoredGCCCompat : Flags<[HelpHidden]> {}
/////////
// Groups
def Action_Group : OptionGroup<"<action group>">, DocName<"Actions">,
DocBrief<[{The action to perform on the input.}]>;
// Meta-group for options which are only used for compilation,
// and not linking etc.
def CompileOnly_Group : OptionGroup<"<CompileOnly group>">,
DocName<"Compilation flags">, DocBrief<[{
Flags controlling the behavior of Clang during compilation. These flags have
no effect during actions that do not perform compilation.}]>;
def Preprocessor_Group : OptionGroup<"<Preprocessor group>">,
Group<CompileOnly_Group>,
DocName<"Preprocessor flags">, DocBrief<[{
Flags controlling the behavior of the Clang preprocessor.}]>;
def IncludePath_Group : OptionGroup<"<I/i group>">, Group<Preprocessor_Group>,
DocName<"Include path management">,
DocBrief<[{
Flags controlling how ``#include``\s are resolved to files.}]>;
def I_Group : OptionGroup<"<I group>">, Group<IncludePath_Group>, DocFlatten;
def i_Group : OptionGroup<"<i group>">, Group<IncludePath_Group>, DocFlatten;
def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>, DocFlatten;
def M_Group : OptionGroup<"<M group>">, Group<Preprocessor_Group>,
DocName<"Dependency file generation">, DocBrief<[{
Flags controlling generation of a dependency file for ``make``-like build
systems.}]>;
def d_Group : OptionGroup<"<d group>">, Group<Preprocessor_Group>,
DocName<"Dumping preprocessor state">, DocBrief<[{
Flags allowing the state of the preprocessor to be dumped in various ways.}]>;
def Diag_Group : OptionGroup<"<W/R group>">, Group<CompileOnly_Group>,
DocName<"Diagnostic flags">, DocBrief<[{
Flags controlling which warnings, errors, and remarks Clang will generate.
See the :doc:`full list of warning and remark flags <DiagnosticsReference>`.}]>;
def R_Group : OptionGroup<"<R group>">, Group<Diag_Group>, DocFlatten;
def R_value_Group : OptionGroup<"<R (with value) group>">, Group<R_Group>,
DocFlatten;
def W_Group : OptionGroup<"<W group>">, Group<Diag_Group>, DocFlatten;
def W_value_Group : OptionGroup<"<W (with value) group>">, Group<W_Group>,
DocFlatten;
def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>,
DocName<"Target-independent compilation options">;
def f_clang_Group : OptionGroup<"<f (clang-only) group>">,
Group<CompileOnly_Group>, DocFlatten;
def pedantic_Group : OptionGroup<"<pedantic group>">, Group<f_Group>,
DocFlatten;
def opencl_Group : OptionGroup<"<opencl group>">, Group<f_Group>,
DocName<"OpenCL flags">;
def m_Group : OptionGroup<"<m group>">, Group<CompileOnly_Group>,
DocName<"Target-dependent compilation options">;
// Feature groups - these take command line options that correspond directly to
// target specific features and can be translated directly from command line
// options.
def m_aarch64_Features_Group : OptionGroup<"<aarch64 features group>">,
Group<m_Group>, DocName<"AARCH64">;
def m_amdgpu_Features_Group : OptionGroup<"<amdgpu features group>">,
Group<m_Group>, DocName<"AMDGPU">;
def m_arm_Features_Group : OptionGroup<"<arm features group>">,
Group<m_Group>, DocName<"ARM">;
def m_hexagon_Features_Group : OptionGroup<"<hexagon features group>">,
Group<m_Group>, DocName<"Hexagon">;
// The features added by this group will not be added to target features.
// These are explicitly handled.
def m_hexagon_Features_HVX_Group : OptionGroup<"<hexagon features group>">,
Group<m_Group>, DocName<"Hexagon">;
def m_mips_Features_Group : OptionGroup<"<mips features group>">,
Group<m_Group>, DocName<"MIPS">;
def m_ppc_Features_Group : OptionGroup<"<ppc features group>">,
Group<m_Group>, DocName<"PowerPC">;
def m_wasm_Features_Group : OptionGroup<"<wasm features group>">,
Group<m_Group>, DocName<"WebAssembly">;
def m_x86_Features_Group : OptionGroup<"<x86 features group>">,
Group<m_Group>, Flags<[CoreOption]>, DocName<"X86">;
def m_riscv_Features_Group : OptionGroup<"<riscv features group>">,
Group<m_Group>, DocName<"RISCV">;
def m_libc_Group : OptionGroup<"<m libc group>">, Group<m_mips_Features_Group>,
Flags<[HelpHidden]>;
def O_Group : OptionGroup<"<O group>">, Group<CompileOnly_Group>,
DocName<"Optimization level">, DocBrief<[{
Flags controlling how much optimization should be performed.}]>;
def DebugInfo_Group : OptionGroup<"<g group>">, Group<CompileOnly_Group>,
DocName<"Debug information generation">, DocBrief<[{
Flags controlling how much and what kind of debug information should be
generated.}]>;
def g_Group : OptionGroup<"<g group>">, Group<DebugInfo_Group>,
DocName<"Kind and level of debug information">;
def gN_Group : OptionGroup<"<gN group>">, Group<g_Group>,
DocName<"Debug level">;
def ggdbN_Group : OptionGroup<"<ggdbN group>">, Group<gN_Group>, DocFlatten;
def gTune_Group : OptionGroup<"<gTune group>">, Group<g_Group>,
DocName<"Debugger to tune debug information for">;
def g_flags_Group : OptionGroup<"<g flags group>">, Group<DebugInfo_Group>,
DocName<"Debug information flags">;
def StaticAnalyzer_Group : OptionGroup<"<Static analyzer group>">,
DocName<"Static analyzer flags">, DocBrief<[{
Flags controlling the behavior of the Clang Static Analyzer.}]>;
// gfortran options that we recognize in the driver and pass along when
// invoking GCC to compile Fortran code.
def gfortran_Group : OptionGroup<"<gfortran group>">,
DocName<"Fortran compilation flags">, DocBrief<[{
Flags that will be passed onto the ``gfortran`` compiler when Clang is given
a Fortran input.}]>;
def Link_Group : OptionGroup<"<T/e/s/t/u group>">, DocName<"Linker flags">,
DocBrief<[{Flags that are passed on to the linker}]>;
def T_Group : OptionGroup<"<T group>">, Group<Link_Group>, DocFlatten;
def u_Group : OptionGroup<"<u group>">, Group<Link_Group>, DocFlatten;
def reserved_lib_Group : OptionGroup<"<reserved libs group>">,
Flags<[Unsupported]>;
// Temporary groups for clang options which we know we don't support,
// but don't want to verbosely warn the user about.
def clang_ignored_f_Group : OptionGroup<"<clang ignored f group>">,
Group<f_Group>, Flags<[Ignored]>;
def clang_ignored_m_Group : OptionGroup<"<clang ignored m group>">,
Group<m_Group>, Flags<[Ignored]>;
// Group for clang options in the process of deprecation.
// Please include the version that deprecated the flag as comment to allow
// easier garbage collection.
def clang_ignored_legacy_options_Group : OptionGroup<"<clang legacy flags>">,
Group<f_Group>, Flags<[Ignored]>;
// Retired with clang-5.0
def : Flag<["-"], "fslp-vectorize-aggressive">, Group<clang_ignored_legacy_options_Group>;
def : Flag<["-"], "fno-slp-vectorize-aggressive">, Group<clang_ignored_legacy_options_Group>;
// Group that ignores all gcc optimizations that won't be implemented
def clang_ignored_gcc_optimization_f_Group : OptionGroup<
"<clang_ignored_gcc_optimization_f_Group>">, Group<f_Group>, Flags<[Ignored]>;
/////////
// Options
// The internal option ID must be a valid C++ identifier and results in a
// clang::driver::options::OPT_XX enum constant for XX.
//
// We want to unambiguously be able to refer to options from the driver source
// code, for this reason the option name is mangled into an ID. This mangling
// isn't guaranteed to have an inverse, but for practical purposes it does.
//
// The mangling scheme is to ignore the leading '-', and perform the following
// substitutions:
// _ => __
// - => _
// / => _SLASH
// # => _HASH
// ? => _QUESTION
// , => _COMMA
// = => _EQ
// C++ => CXX
// . => _
// Developer Driver Options
def internal_Group : OptionGroup<"<clang internal options>">, Flags<[HelpHidden]>;
def internal_driver_Group : OptionGroup<"<clang driver internal options>">,
Group<internal_Group>, HelpText<"DRIVER OPTIONS">;
def internal_debug_Group :
OptionGroup<"<clang debug/development internal options>">,
Group<internal_Group>, HelpText<"DEBUG/DEVELOPMENT OPTIONS">;
class InternalDriverOpt : Group<internal_driver_Group>,
Flags<[DriverOption, HelpHidden]>;
def driver_mode : Joined<["--"], "driver-mode=">, Group<internal_driver_Group>,
Flags<[CoreOption, DriverOption, HelpHidden]>,
HelpText<"Set the driver mode to either 'gcc', 'g++', 'cpp', or 'cl'">;
def rsp_quoting : Joined<["--"], "rsp-quoting=">, Group<internal_driver_Group>,
Flags<[CoreOption, DriverOption, HelpHidden]>,
HelpText<"Set the rsp quoting to either 'posix', or 'windows'">;
def ccc_gcc_name : Separate<["-"], "ccc-gcc-name">, InternalDriverOpt,
HelpText<"Name for native GCC compiler">,
MetaVarName<"<gcc-path>">;
class InternalDebugOpt : Group<internal_debug_Group>,
Flags<[DriverOption, HelpHidden, CoreOption]>;
def ccc_install_dir : Separate<["-"], "ccc-install-dir">, InternalDebugOpt,
HelpText<"Simulate installation in the given directory">;
def ccc_print_phases : Flag<["-"], "ccc-print-phases">, InternalDebugOpt,
HelpText<"Dump list of actions to perform">;
def ccc_print_bindings : Flag<["-"], "ccc-print-bindings">, InternalDebugOpt,
HelpText<"Show bindings of tools to actions">;
def ccc_arcmt_check : Flag<["-"], "ccc-arcmt-check">, InternalDriverOpt,
HelpText<"Check for ARC migration issues that need manual handling">;
def ccc_arcmt_modify : Flag<["-"], "ccc-arcmt-modify">, InternalDriverOpt,
HelpText<"Apply modifications to files to conform to ARC">;
def ccc_arcmt_migrate : Separate<["-"], "ccc-arcmt-migrate">, InternalDriverOpt,
HelpText<"Apply modifications and produces temporary files that conform to ARC">;
def arcmt_migrate_report_output : Separate<["-"], "arcmt-migrate-report-output">,
HelpText<"Output path for the plist report">, Flags<[CC1Option]>;
def arcmt_migrate_emit_arc_errors : Flag<["-"], "arcmt-migrate-emit-errors">,
HelpText<"Emit ARC errors even if the migrator can fix them">,
Flags<[CC1Option]>;
def gen_reproducer: Flag<["-"], "gen-reproducer">, InternalDebugOpt,
HelpText<"Auto-generates preprocessed source files and a reproduction script">;
def _migrate : Flag<["--"], "migrate">, Flags<[DriverOption]>,
HelpText<"Run the migrator">;
def ccc_objcmt_migrate : Separate<["-"], "ccc-objcmt-migrate">,
InternalDriverOpt,
HelpText<"Apply modifications and produces temporary files to migrate to "
"modern ObjC syntax">;
def objcmt_migrate_literals : Flag<["-"], "objcmt-migrate-literals">, Flags<[CC1Option]>,
HelpText<"Enable migration to modern ObjC literals">;
def objcmt_migrate_subscripting : Flag<["-"], "objcmt-migrate-subscripting">, Flags<[CC1Option]>,
HelpText<"Enable migration to modern ObjC subscripting">;
def objcmt_migrate_property : Flag<["-"], "objcmt-migrate-property">, Flags<[CC1Option]>,
HelpText<"Enable migration to modern ObjC property">;
def objcmt_migrate_all : Flag<["-"], "objcmt-migrate-all">, Flags<[CC1Option]>,
HelpText<"Enable migration to modern ObjC">;
def objcmt_migrate_readonly_property : Flag<["-"], "objcmt-migrate-readonly-property">, Flags<[CC1Option]>,
HelpText<"Enable migration to modern ObjC readonly property">;
def objcmt_migrate_readwrite_property : Flag<["-"], "objcmt-migrate-readwrite-property">, Flags<[CC1Option]>,
HelpText<"Enable migration to modern ObjC readwrite property">;
def objcmt_migrate_property_dot_syntax : Flag<["-"], "objcmt-migrate-property-dot-syntax">, Flags<[CC1Option]>,
HelpText<"Enable migration of setter/getter messages to property-dot syntax">;
def objcmt_migrate_annotation : Flag<["-"], "objcmt-migrate-annotation">, Flags<[CC1Option]>,
HelpText<"Enable migration to property and method annotations">;
def objcmt_migrate_instancetype : Flag<["-"], "objcmt-migrate-instancetype">, Flags<[CC1Option]>,
HelpText<"Enable migration to infer instancetype for method result type">;
def objcmt_migrate_nsmacros : Flag<["-"], "objcmt-migrate-ns-macros">, Flags<[CC1Option]>,
HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">;
def objcmt_migrate_protocol_conformance : Flag<["-"], "objcmt-migrate-protocol-conformance">, Flags<[CC1Option]>,
HelpText<"Enable migration to add protocol conformance on classes">;
def objcmt_atomic_property : Flag<["-"], "objcmt-atomic-property">, Flags<[CC1Option]>,
HelpText<"Make migration to 'atomic' properties">;
def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpointer-property">, Flags<[CC1Option]>,
HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">;
def objcmt_ns_nonatomic_iosonly: Flag<["-"], "objcmt-ns-nonatomic-iosonly">, Flags<[CC1Option]>,
HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">;
def objcmt_migrate_designated_init : Flag<["-"], "objcmt-migrate-designated-init">, Flags<[CC1Option]>,
HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">;
def objcmt_whitelist_dir_path: Joined<["-"], "objcmt-whitelist-dir-path=">, Flags<[CC1Option]>,
HelpText<"Only modify files with a filename contained in the provided directory path">;
// The misspelt "white-list" [sic] alias is due for removal.
def : Joined<["-"], "objcmt-white-list-dir-path=">, Flags<[CC1Option]>,
Alias<objcmt_whitelist_dir_path>;
// Make sure all other -ccc- options are rejected.
def ccc_ : Joined<["-"], "ccc-">, Group<internal_Group>, Flags<[Unsupported]>;
// Standard Options
def _HASH_HASH_HASH : Flag<["-"], "###">, Flags<[DriverOption, CoreOption]>,
HelpText<"Print (but do not run) the commands to run for this compilation">;
def _DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>,
Flags<[DriverOption, CoreOption]>;
def A : JoinedOrSeparate<["-"], "A">, Flags<[RenderJoined]>, Group<gfortran_Group>;
def B : JoinedOrSeparate<["-"], "B">, MetaVarName<"<dir>">,
HelpText<"Add <dir> to search path for binaries and object files used implicitly">;
def CC : Flag<["-"], "CC">, Flags<[CC1Option]>, Group<Preprocessor_Group>,
HelpText<"Include comments from within macros in preprocessed output">;
def C : Flag<["-"], "C">, Flags<[CC1Option]>, Group<Preprocessor_Group>,
HelpText<"Include comments in preprocessed output">;
def D : JoinedOrSeparate<["-"], "D">, Group<Preprocessor_Group>,
Flags<[CC1Option]>, MetaVarName<"<macro>=<value>">,
HelpText<"Define <macro> to <value> (or 1 if <value> omitted)">;
def E : Flag<["-"], "E">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>,
HelpText<"Only run the preprocessor">;
def F : JoinedOrSeparate<["-"], "F">, Flags<[RenderJoined,CC1Option]>,
HelpText<"Add directory to framework include search path">;
def G : JoinedOrSeparate<["-"], "G">, Flags<[DriverOption]>, Group<m_Group>,
MetaVarName<"<size>">, HelpText<"Put objects of at most <size> bytes "
"into small data section (MIPS / Hexagon)">;
def G_EQ : Joined<["-"], "G=">, Flags<[DriverOption]>, Group<m_Group>, Alias<G>;
def H : Flag<["-"], "H">, Flags<[CC1Option]>, Group<Preprocessor_Group>,
HelpText<"Show header includes and nesting depth">;
def I_ : Flag<["-"], "I-">, Group<I_Group>,
HelpText<"Restrict all prior -I flags to double-quoted inclusion and "
"remove current directory from include path">;
def I : JoinedOrSeparate<["-"], "I">, Group<I_Group>,
Flags<[CC1Option,CC1AsOption]>, MetaVarName<"<dir>">,
HelpText<"Add directory to include search path">;
def L : JoinedOrSeparate<["-"], "L">, Flags<[RenderJoined]>, Group<Link_Group>,
MetaVarName<"<dir>">, HelpText<"Add directory to library search path">;
def MD : Flag<["-"], "MD">, Group<M_Group>,
HelpText<"Write a depfile containing user and system headers">;
def MMD : Flag<["-"], "MMD">, Group<M_Group>,
HelpText<"Write a depfile containing user headers">;
def M : Flag<["-"], "M">, Group<M_Group>,
HelpText<"Like -MD, but also implies -E and writes to stdout by default">;
def MM : Flag<["-"], "MM">, Group<M_Group>,
HelpText<"Like -MMD, but also implies -E and writes to stdout by default">;
def MF : JoinedOrSeparate<["-"], "MF">, Group<M_Group>,
HelpText<"Write depfile output from -MMD, -MD, -MM, or -M to <file>">,
MetaVarName<"<file>">;
def MG : Flag<["-"], "MG">, Group<M_Group>, Flags<[CC1Option]>,
HelpText<"Add missing headers to depfile">;
def MJ : JoinedOrSeparate<["-"], "MJ">, Group<M_Group>,
HelpText<"Write a compilation database entry per input">;
def MP : Flag<["-"], "MP">, Group<M_Group>, Flags<[CC1Option]>,
HelpText<"Create phony target for each dependency (other than main file)">;
def MQ : JoinedOrSeparate<["-"], "MQ">, Group<M_Group>, Flags<[CC1Option]>,
HelpText<"Specify name of main file output to quote in depfile">;
def MT : JoinedOrSeparate<["-"], "MT">, Group<M_Group>, Flags<[CC1Option]>,
HelpText<"Specify name of main file output in depfile">;
def MV : Flag<["-"], "MV">, Group<M_Group>, Flags<[CC1Option]>,
HelpText<"Use NMake/Jom format for the depfile">;
def Mach : Flag<["-"], "Mach">, Group<Link_Group>;
def O0 : Flag<["-"], "O0">, Group<O_Group>, Flags<[CC1Option, HelpHidden]>;
def O4 : Flag<["-"], "O4">, Group<O_Group>, Flags<[CC1Option, HelpHidden]>;
def ObjCXX : Flag<["-"], "ObjC++">, Flags<[DriverOption]>,
HelpText<"Treat source input files as Objective-C++ inputs">;
def ObjC : Flag<["-"], "ObjC">, Flags<[DriverOption]>,
HelpText<"Treat source input files as Objective-C inputs">;
def O : Joined<["-"], "O">, Group<O_Group>, Flags<[CC1Option]>;
def O_flag : Flag<["-"], "O">, Flags<[CC1Option]>, Alias<O>, AliasArgs<["2"]>;
def Ofast : Joined<["-"], "Ofast">, Group<O_Group>, Flags<[CC1Option]>;
def P : Flag<["-"], "P">, Flags<[CC1Option]>, Group<Preprocessor_Group>,
HelpText<"Disable linemarker output in -E mode">;
def Qy : Flag<["-"], "Qy">, Flags<[CC1Option]>,
HelpText<"Emit metadata containing compiler name and version">;
def Qn : Flag<["-"], "Qn">, Flags<[CC1Option]>,
HelpText<"Do not emit metadata containing compiler name and version">;
def : Flag<["-"], "fident">, Group<f_Group>, Alias<Qy>, Flags<[CC1Option]>;
def : Flag<["-"], "fno-ident">, Group<f_Group>, Alias<Qn>, Flags<[CC1Option]>;
def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[DriverOption, CoreOption]>,
HelpText<"Don't emit warning for unused driver arguments">;
def Q : Flag<["-"], "Q">, IgnoredGCCCompat;
def Rpass_EQ : Joined<["-"], "Rpass=">, Group<R_value_Group>, Flags<[CC1Option]>,
HelpText<"Report transformations performed by optimization passes whose "
"name matches the given POSIX regular expression">;
def Rpass_missed_EQ : Joined<["-"], "Rpass-missed=">, Group<R_value_Group>,
Flags<[CC1Option]>,
HelpText<"Report missed transformations by optimization passes whose "
"name matches the given POSIX regular expression">;
def Rpass_analysis_EQ : Joined<["-"], "Rpass-analysis=">, Group<R_value_Group>,
Flags<[CC1Option]>,
HelpText<"Report transformation analysis from optimization passes whose "
"name matches the given POSIX regular expression">;
def R_Joined : Joined<["-"], "R">, Group<R_Group>, Flags<[CC1Option, CoreOption]>,
MetaVarName<"<remark>">, HelpText<"Enable the specified remark">;
def S : Flag<["-"], "S">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>,
HelpText<"Only run preprocess and compilation steps">;
def Tbss : JoinedOrSeparate<["-"], "Tbss">, Group<T_Group>,
MetaVarName<"<addr>">, HelpText<"Set starting address of BSS to <addr>">;
def Tdata : JoinedOrSeparate<["-"], "Tdata">, Group<T_Group>,
MetaVarName<"<addr>">, HelpText<"Set starting address of DATA to <addr>">;
def Ttext : JoinedOrSeparate<["-"], "Ttext">, Group<T_Group>,
MetaVarName<"<addr>">, HelpText<"Set starting address of TEXT to <addr>">;
def T : JoinedOrSeparate<["-"], "T">, Group<T_Group>,
MetaVarName<"<script>">, HelpText<"Specify <script> as linker script">;
def U : JoinedOrSeparate<["-"], "U">, Group<Preprocessor_Group>,
Flags<[CC1Option]>, MetaVarName<"<macro>">, HelpText<"Undefine macro <macro>">;
def V : JoinedOrSeparate<["-"], "V">, Flags<[DriverOption, Unsupported]>;
def Wa_COMMA : CommaJoined<["-"], "Wa,">,
HelpText<"Pass the comma separated arguments in <arg> to the assembler">,
MetaVarName<"<arg>">;
def Wall : Flag<["-"], "Wall">, Group<W_Group>, Flags<[CC1Option, HelpHidden]>;
def WCL4 : Flag<["-"], "WCL4">, Group<W_Group>, Flags<[CC1Option, HelpHidden]>;
def Wdeprecated : Flag<["-"], "Wdeprecated">, Group<W_Group>, Flags<[CC1Option]>,
HelpText<"Enable warnings for deprecated constructs and define __DEPRECATED">;
def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group<W_Group>, Flags<[CC1Option]>;
def Wl_COMMA : CommaJoined<["-"], "Wl,">, Flags<[LinkerInput, RenderAsInput]>,
HelpText<"Pass the comma separated arguments in <arg> to the linker">,
MetaVarName<"<arg>">, Group<Link_Group>;
// FIXME: This is broken; these should not be Joined arguments.
def Wno_nonportable_cfstrings : Joined<["-"], "Wno-nonportable-cfstrings">, Group<W_Group>,
Flags<[CC1Option]>;
def Wnonportable_cfstrings : Joined<["-"], "Wnonportable-cfstrings">, Group<W_Group>,
Flags<[CC1Option]>;
def Wp_COMMA : CommaJoined<["-"], "Wp,">,
HelpText<"Pass the comma separated arguments in <arg> to the preprocessor">,
MetaVarName<"<arg>">, Group<Preprocessor_Group>;
def Wwrite_strings : Flag<["-"], "Wwrite-strings">, Group<W_Group>, Flags<[CC1Option, HelpHidden]>;
def Wno_write_strings : Flag<["-"], "Wno-write-strings">, Group<W_Group>, Flags<[CC1Option, HelpHidden]>;
def W_Joined : Joined<["-"], "W">, Group<W_Group>, Flags<[CC1Option, CoreOption]>,
MetaVarName<"<warning>">, HelpText<"Enable the specified warning">;
def Xanalyzer : Separate<["-"], "Xanalyzer">,
HelpText<"Pass <arg> to the static analyzer">, MetaVarName<"<arg>">,
Group<StaticAnalyzer_Group>;
def Xarch__ : JoinedAndSeparate<["-"], "Xarch_">, Flags<[DriverOption]>;
def Xassembler : Separate<["-"], "Xassembler">,
HelpText<"Pass <arg> to the assembler">, MetaVarName<"<arg>">,
Group<CompileOnly_Group>;
def Xclang : Separate<["-"], "Xclang">,
HelpText<"Pass <arg> to the clang compiler">, MetaVarName<"<arg>">,
Flags<[DriverOption, CoreOption]>, Group<CompileOnly_Group>;
def Xcuda_fatbinary : Separate<["-"], "Xcuda-fatbinary">,
HelpText<"Pass <arg> to fatbinary invocation">, MetaVarName<"<arg>">;
def Xcuda_ptxas : Separate<["-"], "Xcuda-ptxas">,
HelpText<"Pass <arg> to the ptxas assembler">, MetaVarName<"<arg>">;
def Xopenmp_target : Separate<["-"], "Xopenmp-target">,
HelpText<"Pass <arg> to the target offloading toolchain.">, MetaVarName<"<arg>">;
def Xopenmp_target_EQ : JoinedAndSeparate<["-"], "Xopenmp-target=">,
HelpText<"Pass <arg> to the target offloading toolchain identified by <triple>.">,
MetaVarName<"<triple> <arg>">;
def z : Separate<["-"], "z">, Flags<[LinkerInput, RenderAsInput]>,
HelpText<"Pass -z <arg> to the linker">, MetaVarName<"<arg>">,
Group<Link_Group>;
def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>,
HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">,
Group<Link_Group>;
def Xpreprocessor : Separate<["-"], "Xpreprocessor">, Group<Preprocessor_Group>,
HelpText<"Pass <arg> to the preprocessor">, MetaVarName<"<arg>">;
def X_Flag : Flag<["-"], "X">, Group<Link_Group>;
def X_Joined : Joined<["-"], "X">, IgnoredGCCCompat;
def Z_Flag : Flag<["-"], "Z">, Group<Link_Group>;
// FIXME: All we do with this is reject it. Remove.
def Z_Joined : Joined<["-"], "Z">;
def all__load : Flag<["-"], "all_load">;
def allowable__client : Separate<["-"], "allowable_client">;
def ansi : Flag<["-", "--"], "ansi">;
def arch__errors__fatal : Flag<["-"], "arch_errors_fatal">;
def arch : Separate<["-"], "arch">, Flags<[DriverOption]>;
def arch__only : Separate<["-"], "arch_only">;
def a : Joined<["-"], "a">;
def autocomplete : Joined<["--"], "autocomplete=">;
def bind__at__load : Flag<["-"], "bind_at_load">;
def bundle__loader : Separate<["-"], "bundle_loader">;
def bundle : Flag<["-"], "bundle">;
def b : JoinedOrSeparate<["-"], "b">, Flags<[Unsupported]>;
def cfguard : Flag<["-"], "cfguard">, Flags<[CC1Option]>,
HelpText<"Emit tables required for Windows Control Flow Guard.">;
def cl_opt_disable : Flag<["-"], "cl-opt-disable">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. This option disables all optimizations. By default optimizations are enabled.">;
def cl_strict_aliasing : Flag<["-"], "cl-strict-aliasing">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. This option is added for compatibility with OpenCL 1.0.">;
def cl_single_precision_constant : Flag<["-"], "cl-single-precision-constant">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Treat double precision floating-point constant as single precision constant.">;
def cl_finite_math_only : Flag<["-"], "cl-finite-math-only">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Allow floating-point optimizations that assume arguments and results are not NaNs or +-Inf.">;
def cl_kernel_arg_info : Flag<["-"], "cl-kernel-arg-info">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Generate kernel argument metadata.">;
def cl_unsafe_math_optimizations : Flag<["-"], "cl-unsafe-math-optimizations">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Allow unsafe floating-point optimizations. Also implies -cl-no-signed-zeros and -cl-mad-enable.">;
def cl_fast_relaxed_math : Flag<["-"], "cl-fast-relaxed-math">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Sets -cl-finite-math-only and -cl-unsafe-math-optimizations, and defines __FAST_RELAXED_MATH__.">;
def cl_mad_enable : Flag<["-"], "cl-mad-enable">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Allow use of less precise MAD computations in the generated binary.">;
def cl_no_signed_zeros : Flag<["-"], "cl-no-signed-zeros">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Allow use of less precise no signed zeros computations in the generated binary.">;
def cl_std_EQ : Joined<["-"], "cl-std=">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL language standard to compile for.">, Values<"cl,CL,cl1.1,CL1.1,cl1.2,CL1.2,cl2.0,CL2.0,c++">;
def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Allow denormals to be flushed to zero.">;
def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], "cl-fp32-correctly-rounded-divide-sqrt">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Specify that single precision floating-point divide and sqrt used in the program source are correctly rounded.">;
def cl_uniform_work_group_size : Flag<["-"], "cl-uniform-work-group-size">, Group<opencl_Group>, Flags<[CC1Option]>,
HelpText<"OpenCL only. Defines that the global work-size be a multiple of the work-group size specified to clEnqueueNDRangeKernel">;
def client__name : JoinedOrSeparate<["-"], "client_name">;
def combine : Flag<["-", "--"], "combine">, Flags<[DriverOption, Unsupported]>;
def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">;
def config : Separate<["--"], "config">, Flags<[DriverOption]>,
HelpText<"Specifies configuration file">;
def config_system_dir_EQ : Joined<["--"], "config-system-dir=">, Flags<[DriverOption, HelpHidden]>,
HelpText<"System directory for configuration files">;
def config_user_dir_EQ : Joined<["--"], "config-user-dir=">, Flags<[DriverOption, HelpHidden]>,
HelpText<"User directory for configuration files">;
def coverage : Flag<["-", "--"], "coverage">, Flags<[CoreOption]>;
def cpp_precomp : Flag<["-"], "cpp-precomp">, Group<clang_ignored_f_Group>;
def current__version : JoinedOrSeparate<["-"], "current_version">;
def cxx_isystem : JoinedOrSeparate<["-"], "cxx-isystem">, Group<clang_i_Group>,
HelpText<"Add directory to the C++ SYSTEM include search path">, Flags<[CC1Option]>,
MetaVarName<"<directory>">;
def c : Flag<["-"], "c">, Flags<[DriverOption]>, Group<Action_Group>,
HelpText<"Only run preprocess, compile, and assemble steps">;
def cuda_device_only : Flag<["--"], "cuda-device-only">,
HelpText<"Compile CUDA code for device only">;
def cuda_host_only : Flag<["--"], "cuda-host-only">,
HelpText<"Compile CUDA code for host only. Has no effect on non-CUDA "
"compilations.">;
def cuda_compile_host_device : Flag<["--"], "cuda-compile-host-device">,
HelpText<"Compile CUDA code for both host and device (default). Has no "
"effect on non-CUDA compilations.">;
def cuda_include_ptx_EQ : Joined<["--"], "cuda-include-ptx=">, Flags<[DriverOption]>,
HelpText<"Include PTX for the follwing GPU architecture (e.g. sm_35) or 'all'. May be specified more than once.">;
def no_cuda_include_ptx_EQ : Joined<["--"], "no-cuda-include-ptx=">, Flags<[DriverOption]>,
HelpText<"Do not include PTX for the follwing GPU architecture (e.g. sm_35) or 'all'. May be specified more than once.">;
def cuda_gpu_arch_EQ : Joined<["--"], "cuda-gpu-arch=">, Flags<[DriverOption]>,
HelpText<"CUDA GPU architecture (e.g. sm_35). May be specified more than once.">;
def hip_link : Flag<["--"], "hip-link">,
HelpText<"Link clang-offload-bundler bundles for HIP">;
def no_cuda_gpu_arch_EQ : Joined<["--"], "no-cuda-gpu-arch=">, Flags<[DriverOption]>,
HelpText<"Remove GPU architecture (e.g. sm_35) from the list of GPUs to compile for. "
"'all' resets the list to its default value.">;
def cuda_noopt_device_debug : Flag<["--"], "cuda-noopt-device-debug">,
HelpText<"Enable device-side debug info generation. Disables ptxas optimizations.">;
def no_cuda_version_check : Flag<["--"], "no-cuda-version-check">,
HelpText<"Don't error out if the detected version of the CUDA install is "
"too low for the requested CUDA gpu architecture.">;
def no_cuda_noopt_device_debug : Flag<["--"], "no-cuda-noopt-device-debug">;
def cuda_path_EQ : Joined<["--"], "cuda-path=">, Group<i_Group>,
HelpText<"CUDA installation path">;
def cuda_path_ignore_env : Flag<["--"], "cuda-path-ignore-env">, Group<i_Group>,
HelpText<"Ignore environment variables to detect CUDA installation">;
def ptxas_path_EQ : Joined<["--"], "ptxas-path=">, Group<i_Group>,
HelpText<"Path to ptxas (used for compiling CUDA code)">;
def fcuda_flush_denormals_to_zero : Flag<["-"], "fcuda-flush-denormals-to-zero">,
Flags<[CC1Option]>, HelpText<"Flush denormal floating point values to zero in CUDA device mode.">;
def fno_cuda_flush_denormals_to_zero : Flag<["-"], "fno-cuda-flush-denormals-to-zero">;
def fcuda_approx_transcendentals : Flag<["-"], "fcuda-approx-transcendentals">,
Flags<[CC1Option]>, HelpText<"Use approximate transcendental functions">;
def fno_cuda_approx_transcendentals : Flag<["-"], "fno-cuda-approx-transcendentals">;
def fgpu_rdc : Flag<["-"], "fgpu-rdc">, Flags<[CC1Option]>,
HelpText<"Generate relocatable device code, also known as separate compilation mode.">;
def fno_gpu_rdc : Flag<["-"], "fno-gpu-rdc">;
def : Flag<["-"], "fcuda-rdc">, Alias<fgpu_rdc>;
def : Flag<["-"], "fno-cuda-rdc">, Alias<fno_gpu_rdc>;
def fcuda_short_ptr : Flag<["-"], "fcuda-short-ptr">, Flags<[CC1Option]>,
HelpText<"Use 32-bit pointers for accessing const/local/shared address spaces.">;
def fno_cuda_short_ptr : Flag<["-"], "fno-cuda-short-ptr">;
def hip_device_lib_path_EQ : Joined<["--"], "hip-device-lib-path=">, Group<Link_Group>,
HelpText<"HIP device library path">;
def hip_device_lib_EQ : Joined<["--"], "hip-device-lib=">, Group<Link_Group>,
HelpText<"HIP device library">;
def fhip_dump_offload_linker_script : Flag<["-"], "fhip-dump-offload-linker-script">,
Group<f_Group>, Flags<[NoArgumentUnused, HelpHidden]>;
def libomptarget_nvptx_path_EQ : Joined<["--"], "libomptarget-nvptx-path=">, Group<i_Group>,
HelpText<"Path to libomptarget-nvptx libraries">;
def dA : Flag<["-"], "dA">, Group<d_Group>;
def dD : Flag<["-"], "dD">, Group<d_Group>, Flags<[CC1Option]>,
HelpText<"Print macro definitions in -E mode in addition to normal output">;
def dI : Flag<["-"], "dI">, Group<d_Group>, Flags<[CC1Option]>,
HelpText<"Print include directives in -E mode in addition to normal output">;
def dM : Flag<["-"], "dM">, Group<d_Group>, Flags<[CC1Option]>,
HelpText<"Print macro definitions in -E mode instead of normal output">;
def dead__strip : Flag<["-"], "dead_strip">;
def dependency_file : Separate<["-"], "dependency-file">, Flags<[CC1Option]>,
HelpText<"Filename (or -) to write dependency output to">;
def dependency_dot : Separate<["-"], "dependency-dot">, Flags<[CC1Option]>,
HelpText<"Filename to write DOT-formatted header dependencies to">;
def module_dependency_dir : Separate<["-"], "module-dependency-dir">,
Flags<[CC1Option]>, HelpText<"Directory to dump module dependencies to">;
def dumpmachine : Flag<["-"], "dumpmachine">;
def dumpspecs : Flag<["-"], "dumpspecs">, Flags<[Unsupported]>;
def dumpversion : Flag<["-"], "dumpversion">;
def dylib__file : Separate<["-"], "dylib_file">;
def dylinker__install__name : JoinedOrSeparate<["-"], "dylinker_install_name">;
def dylinker : Flag<["-"], "dylinker">;
def dynamiclib : Flag<["-"], "dynamiclib">;
def dynamic : Flag<["-"], "dynamic">, Flags<[NoArgumentUnused]>;
def d_Flag : Flag<["-"], "d">, Group<d_Group>;
def d_Joined : Joined<["-"], "d">, Group<d_Group>;
def emit_ast : Flag<["-"], "emit-ast">,
HelpText<"Emit Clang AST files for source inputs">;
def emit_llvm : Flag<["-"], "emit-llvm">, Flags<[CC1Option]>, Group<Action_Group>,
HelpText<"Use the LLVM representation for assembler and object files">;
def exported__symbols__list : Separate<["-"], "exported_symbols_list">;
def e : JoinedOrSeparate<["-"], "e">, Group<Link_Group>;
def fPIC : Flag<["-"], "fPIC">, Group<f_Group>;
def fno_PIC : Flag<["-"], "fno-PIC">, Group<f_Group>;
def fPIE : Flag<["-"], "fPIE">, Group<f_Group>;
def fno_PIE : Flag<["-"], "fno-PIE">, Group<f_Group>;
def faccess_control : Flag<["-"], "faccess-control">, Group<f_Group>;
def falign_functions : Flag<["-"], "falign-functions">, Group<f_Group>;
def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group<f_Group>;
def fno_align_functions: Flag<["-"], "fno-align-functions">, Group<f_Group>;
def fallow_unsupported : Flag<["-"], "fallow-unsupported">, Group<f_Group>;
def fapple_kext : Flag<["-"], "fapple-kext">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use Apple's kernel extensions ABI">;
def fapple_pragma_pack : Flag<["-"], "fapple-pragma-pack">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable Apple gcc-compatible #pragma pack handling">;
def shared_libsan : Flag<["-"], "shared-libsan">,
HelpText<"Dynamically link the sanitizer runtime">;
def static_libsan : Flag<["-"], "static-libsan">,
HelpText<"Statically link the sanitizer runtime">;
def : Flag<["-"], "shared-libasan">, Alias<shared_libsan>;
def fasm : Flag<["-"], "fasm">, Group<f_Group>;
def fasm_blocks : Flag<["-"], "fasm-blocks">, Group<f_Group>, Flags<[CC1Option]>;
def fno_asm_blocks : Flag<["-"], "fno-asm-blocks">, Group<f_Group>;
def fassume_sane_operator_new : Flag<["-"], "fassume-sane-operator-new">, Group<f_Group>;
def fastcp : Flag<["-"], "fastcp">, Group<f_Group>;
def fastf : Flag<["-"], "fastf">, Group<f_Group>;
def fast : Flag<["-"], "fast">, Group<f_Group>;
def fasynchronous_unwind_tables : Flag<["-"], "fasynchronous-unwind-tables">, Group<f_Group>;
def fdouble_square_bracket_attributes : Flag<[ "-" ], "fdouble-square-bracket-attributes">,
Group<f_Group>, Flags<[DriverOption, CC1Option]>,
HelpText<"Enable '[[]]' attributes in all C and C++ language modes">;
def fno_double_square_bracket_attributes : Flag<[ "-" ], "fno-double-square-bracket-attributes">,
Group<f_Group>, Flags<[DriverOption, CC1Option]>,
HelpText<"Disable '[[]]' attributes in all C and C++ language modes">;
def fautolink : Flag <["-"], "fautolink">, Group<f_Group>;
def fno_autolink : Flag <["-"], "fno-autolink">, Group<f_Group>,
Flags<[DriverOption, CC1Option]>,
HelpText<"Disable generation of linker directives for automatic library linking">;
// C++ Coroutines TS
def fcoroutines_ts : Flag <["-"], "fcoroutines-ts">, Group<f_Group>,
Flags<[DriverOption, CC1Option]>,
HelpText<"Enable support for the C++ Coroutines TS">;
def fno_coroutines_ts : Flag <["-"], "fno-coroutines-ts">, Group<f_Group>,
Flags<[DriverOption]>;
def fembed_bitcode_EQ : Joined<["-"], "fembed-bitcode=">,
Group<f_Group>, Flags<[DriverOption, CC1Option, CC1AsOption]>, MetaVarName<"<option>">,
HelpText<"Embed LLVM bitcode (option: off, all, bitcode, marker)">;
def fembed_bitcode : Flag<["-"], "fembed-bitcode">, Group<f_Group>,
Alias<fembed_bitcode_EQ>, AliasArgs<["all"]>,
HelpText<"Embed LLVM IR bitcode as data">;
def fembed_bitcode_marker : Flag<["-"], "fembed-bitcode-marker">,
Alias<fembed_bitcode_EQ>, AliasArgs<["marker"]>,
HelpText<"Embed placeholder LLVM IR data as a marker">;
def fgnu_inline_asm : Flag<["-"], "fgnu-inline-asm">, Group<f_Group>, Flags<[DriverOption]>;
def fno_gnu_inline_asm : Flag<["-"], "fno-gnu-inline-asm">, Group<f_Group>,
Flags<[DriverOption, CC1Option]>,
HelpText<"Disable GNU style inline asm">;
def fprofile_sample_use : Flag<["-"], "fprofile-sample-use">, Group<f_Group>,
Flags<[CoreOption]>;
def fno_profile_sample_use : Flag<["-"], "fno-profile-sample-use">, Group<f_Group>,
Flags<[CoreOption]>;
def fprofile_sample_use_EQ : Joined<["-"], "fprofile-sample-use=">,
Group<f_Group>, Flags<[DriverOption, CC1Option]>,
HelpText<"Enable sample-based profile guided optimizations">;
def fprofile_sample_accurate : Flag<["-"], "fprofile-sample-accurate">,
Group<f_Group>, Flags<[DriverOption, CC1Option]>,
HelpText<"Specifies that the sample profile is accurate">,
DocBrief<[{Specifies that the sample profile is accurate. If the sample
profile is accurate, callsites without profile samples are marked
as cold. Otherwise, treat callsites without profile samples as if
we have no profile}]>;
def fno_profile_sample_accurate : Flag<["-"], "fno-profile-sample-accurate">,
Group<f_Group>, Flags<[DriverOption]>;
def fauto_profile : Flag<["-"], "fauto-profile">, Group<f_Group>,
Alias<fprofile_sample_use>;
def fno_auto_profile : Flag<["-"], "fno-auto-profile">, Group<f_Group>,
Alias<fno_profile_sample_use>;
def fauto_profile_EQ : Joined<["-"], "fauto-profile=">,
Alias<fprofile_sample_use_EQ>;
def fauto_profile_accurate : Flag<["-"], "fauto-profile-accurate">,
Group<f_Group>, Alias<fprofile_sample_accurate>;
def fno_auto_profile_accurate : Flag<["-"], "fno-auto-profile-accurate">,
Group<f_Group>, Alias<fno_profile_sample_accurate>;
def fdebug_info_for_profiling : Flag<["-"], "fdebug-info-for-profiling">, Group<f_Group>,
Flags<[CC1Option]>,
HelpText<"Emit extra debug info to make sample profile more accurate.">;
def fno_debug_info_for_profiling : Flag<["-"], "fno-debug-info-for-profiling">, Group<f_Group>,
Flags<[DriverOption]>,
HelpText<"Do not emit extra debug info for sample profiler.">;
def fprofile_instr_generate : Flag<["-"], "fprofile-instr-generate">,
Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Generate instrumented code to collect execution counts into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">;
def fprofile_instr_generate_EQ : Joined<["-"], "fprofile-instr-generate=">,
Group<f_Group>, Flags<[CoreOption]>, MetaVarName<"<file>">,
HelpText<"Generate instrumented code to collect execution counts into <file> (overridden by LLVM_PROFILE_FILE env var)">;
def fprofile_instr_use : Flag<["-"], "fprofile-instr-use">, Group<f_Group>,
Flags<[CoreOption]>;
def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">,
Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Use instrumentation data for profile-guided optimization">;
def fprofile_remapping_file_EQ : Joined<["-"], "fprofile-remapping-file=">,
Group<f_Group>, Flags<[CC1Option, CoreOption]>, MetaVarName<"<file>">,
HelpText<"Use the remappings described in <file> to match the profile data against names in the program">;
def fprofile_remapping_file : Separate<["-"], "fprofile-remapping-file">,
Group<f_Group>, Flags<[CoreOption]>, Alias<fprofile_remapping_file_EQ>;
def fcoverage_mapping : Flag<["-"], "fcoverage-mapping">,
Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Generate coverage mapping to enable code coverage analysis">;
def fno_coverage_mapping : Flag<["-"], "fno-coverage-mapping">,
Group<f_Group>, Flags<[DriverOption, CoreOption]>,
HelpText<"Disable code coverage analysis">;
def fprofile_generate : Flag<["-"], "fprofile-generate">,
Group<f_Group>, Flags<[DriverOption]>,
HelpText<"Generate instrumented code to collect execution counts into default.profraw (overridden by LLVM_PROFILE_FILE env var)">;
def fprofile_generate_EQ : Joined<["-"], "fprofile-generate=">,
Group<f_Group>, Flags<[DriverOption]>, MetaVarName<"<directory>">,
HelpText<"Generate instrumented code to collect execution counts into <directory>/default.profraw (overridden by LLVM_PROFILE_FILE env var)">;
def fprofile_use : Flag<["-"], "fprofile-use">, Group<f_Group>,
Alias<fprofile_instr_use>;
def fprofile_use_EQ : Joined<["-"], "fprofile-use=">,
Group<f_Group>, Flags<[DriverOption]>, MetaVarName<"<pathname>">,
HelpText<"Use instrumentation data for profile-guided optimization. If pathname is a directory, it reads from <pathname>/default.profdata. Otherwise, it reads from file <pathname>.">;
def fno_profile_instr_generate : Flag<["-"], "fno-profile-instr-generate">,
Group<f_Group>, Flags<[DriverOption]>,
HelpText<"Disable generation of profile instrumentation.">;
def fno_profile_generate : Flag<["-"], "fno-profile-generate">,
Group<f_Group>, Flags<[DriverOption]>,
HelpText<"Disable generation of profile instrumentation.">;
def fno_profile_instr_use : Flag<["-"], "fno-profile-instr-use">,
Group<f_Group>, Flags<[DriverOption]>,
HelpText<"Disable using instrumentation data for profile-guided optimization">;
def fno_profile_use : Flag<["-"], "fno-profile-use">,
Alias<fno_profile_instr_use>;
def fprofile_filter_files_EQ : Joined<["-"], "fprofile-filter-files=">,
Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Instrument only functions from files where names match any regex separated by a semi-colon">;
def fprofile_exclude_files_EQ : Joined<["-"], "fprofile-exclude-files=">,
Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Instrument only functions from files where names don't match all the regexes separated by a semi-colon">;
def faddrsig : Flag<["-"], "faddrsig">, Group<f_Group>, Flags<[CoreOption, CC1Option]>,
HelpText<"Emit an address-significance table">;
def fno_addrsig : Flag<["-"], "fno-addrsig">, Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Don't emit an address-significance table">;
def fblocks : Flag<["-"], "fblocks">, Group<f_Group>, Flags<[CoreOption, CC1Option]>,
HelpText<"Enable the 'blocks' language feature">;
def fbootclasspath_EQ : Joined<["-"], "fbootclasspath=">, Group<f_Group>;
def fborland_extensions : Flag<["-"], "fborland-extensions">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Accept non-standard constructs supported by the Borland compiler">;
def fbuiltin : Flag<["-"], "fbuiltin">, Group<f_Group>, Flags<[CoreOption]>;
def fbuiltin_module_map : Flag <["-"], "fbuiltin-module-map">, Group<f_Group>,
Flags<[DriverOption]>, HelpText<"Load the clang builtins module map file.">;
def fcaret_diagnostics : Flag<["-"], "fcaret-diagnostics">, Group<f_Group>;
def fclang_abi_compat_EQ : Joined<["-"], "fclang-abi-compat=">, Group<f_clang_Group>,
Flags<[CC1Option]>, MetaVarName<"<version>">, Values<"<major>.<minor>,latest">,
HelpText<"Attempt to match the ABI of Clang <version>">;
def fclasspath_EQ : Joined<["-"], "fclasspath=">, Group<f_Group>;
def fcolor_diagnostics : Flag<["-"], "fcolor-diagnostics">, Group<f_Group>,
Flags<[CoreOption, CC1Option]>, HelpText<"Use colors in diagnostics">;
def fdiagnostics_color : Flag<["-"], "fdiagnostics-color">, Group<f_Group>,
Flags<[CoreOption, DriverOption]>;
def fdiagnostics_color_EQ : Joined<["-"], "fdiagnostics-color=">, Group<f_Group>;
def fansi_escape_codes : Flag<["-"], "fansi-escape-codes">, Group<f_Group>,
Flags<[CoreOption, CC1Option]>, HelpText<"Use ANSI escape codes for diagnostics">;
def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Treat each comma separated argument in <arg> as a documentation comment block command">,
MetaVarName<"<arg>">;
def fparse_all_comments : Flag<["-"], "fparse-all-comments">, Group<f_clang_Group>, Flags<[CC1Option]>;
def frecord_command_line : Flag<["-"], "frecord-command-line">,
Group<f_clang_Group>;
def fno_record_command_line : Flag<["-"], "fno-record-command-line">,
Group<f_clang_Group>;
def : Flag<["-"], "frecord-gcc-switches">, Alias<frecord_command_line>;
def : Flag<["-"], "fno-record-gcc-switches">, Alias<fno_record_command_line>;
def fcommon : Flag<["-"], "fcommon">, Group<f_Group>;
def fcompile_resource_EQ : Joined<["-"], "fcompile-resource=">, Group<f_Group>;
def fcomplete_member_pointers : Flag<["-"], "fcomplete-member-pointers">, Group<f_clang_Group>,
Flags<[CoreOption, CC1Option]>,
HelpText<"Require member pointer base types to be complete if they would be significant under the Microsoft ABI">;
def fno_complete_member_pointers : Flag<["-"], "fno-complete-member-pointers">, Group<f_clang_Group>,
Flags<[CoreOption]>,
HelpText<"Do not require member pointer base types to be complete if they would be significant under the Microsoft ABI">;
def fcf_runtime_abi_EQ : Joined<["-"], "fcf-runtime-abi=">, Group<f_Group>,
Flags<[CC1Option]>;
def fconstant_cfstrings : Flag<["-"], "fconstant-cfstrings">, Group<f_Group>;
def fconstant_string_class_EQ : Joined<["-"], "fconstant-string-class=">, Group<f_Group>;
def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group<f_Group>;
def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group<f_Group>;
def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit=">,
Group<f_Group>;
def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group<f_clang_Group>, Flags<[NoArgumentUnused, CoreOption]>,
HelpText<"Disable auto-generation of preprocessed source files and a script for reproduction during a clang crash">;
def fcrash_diagnostics_dir : Joined<["-"], "fcrash-diagnostics-dir=">, Group<f_clang_Group>, Flags<[NoArgumentUnused, CoreOption]>;
def fcreate_profile : Flag<["-"], "fcreate-profile">, Group<f_Group>;
def fcxx_exceptions: Flag<["-"], "fcxx-exceptions">, Group<f_Group>,
HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>;
def fcxx_modules : Flag <["-"], "fcxx-modules">, Group<f_Group>,
Flags<[DriverOption]>;
def fdebug_pass_arguments : Flag<["-"], "fdebug-pass-arguments">, Group<f_Group>;
def fdebug_pass_structure : Flag<["-"], "fdebug-pass-structure">, Group<f_Group>;
def fdepfile_entry : Joined<["-"], "fdepfile-entry=">,
Group<f_clang_Group>, Flags<[CC1Option]>;
def fdiagnostics_fixit_info : Flag<["-"], "fdiagnostics-fixit-info">, Group<f_clang_Group>;
def fdiagnostics_parseable_fixits : Flag<["-"], "fdiagnostics-parseable-fixits">, Group<f_clang_Group>,
Flags<[CoreOption, CC1Option]>, HelpText<"Print fix-its in machine parseable form">;
def fdiagnostics_print_source_range_info : Flag<["-"], "fdiagnostics-print-source-range-info">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Print source range spans in numeric form">;
def fdiagnostics_show_hotness : Flag<["-"], "fdiagnostics-show-hotness">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Enable profile hotness information in diagnostic line">;
def fdiagnostics_hotness_threshold_EQ : Joined<["-"], "fdiagnostics-hotness-threshold=">,
Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<number>">,
HelpText<"Prevent optimization remarks from being output if they do not have at least this profile count">;
def fdiagnostics_show_option : Flag<["-"], "fdiagnostics-show-option">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Print option name with mappable diagnostics">;
def fdiagnostics_show_note_include_stack : Flag<["-"], "fdiagnostics-show-note-include-stack">,
Group<f_Group>, Flags<[CC1Option]>, HelpText<"Display include stacks for diagnostic notes">;
def fdiagnostics_format_EQ : Joined<["-"], "fdiagnostics-format=">, Group<f_clang_Group>;
def fdiagnostics_show_category_EQ : Joined<["-"], "fdiagnostics-show-category=">, Group<f_clang_Group>;
def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tree">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Print a template comparison tree for differing templates">;
def fdeclspec : Flag<["-"], "fdeclspec">, Group<f_clang_Group>,
HelpText<"Allow __declspec as a keyword">, Flags<[CC1Option]>;
def fdiscard_value_names : Flag<["-"], "fdiscard-value-names">, Group<f_clang_Group>,
HelpText<"Discard value names in LLVM IR">, Flags<[DriverOption]>;
def fno_discard_value_names : Flag<["-"], "fno-discard-value-names">, Group<f_clang_Group>,
HelpText<"Do not discard value names in LLVM IR">, Flags<[DriverOption]>;
def fdollars_in_identifiers : Flag<["-"], "fdollars-in-identifiers">, Group<f_Group>,
HelpText<"Allow '$' in identifiers">, Flags<[CC1Option]>;
def fdwarf2_cfi_asm : Flag<["-"], "fdwarf2-cfi-asm">, Group<clang_ignored_f_Group>;
def fno_dwarf2_cfi_asm : Flag<["-"], "fno-dwarf2-cfi-asm">, Group<clang_ignored_f_Group>;
def fdwarf_directory_asm : Flag<["-"], "fdwarf-directory-asm">, Group<f_Group>;
def fno_dwarf_directory_asm : Flag<["-"], "fno-dwarf-directory-asm">, Group<f_Group>, Flags<[CC1Option]>;
def felide_constructors : Flag<["-"], "felide-constructors">, Group<f_Group>;
def fno_elide_type : Flag<["-"], "fno-elide-type">, Group<f_Group>,
Flags<[CC1Option]>,
HelpText<"Do not elide types when printing diagnostics">;
def feliminate_unused_debug_symbols : Flag<["-"], "feliminate-unused-debug-symbols">, Group<f_Group>;
def femit_all_decls : Flag<["-"], "femit-all-decls">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Emit all declarations, even if unused">;
def femulated_tls : Flag<["-"], "femulated-tls">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use emutls functions to access thread_local variables">;
def fno_emulated_tls : Flag<["-"], "fno-emulated-tls">, Group<f_Group>, Flags<[CC1Option]>;
def fencoding_EQ : Joined<["-"], "fencoding=">, Group<f_Group>;
def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group<f_Group>, Flags<[CoreOption]>;
def fexceptions : Flag<["-"], "fexceptions">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable support for exception handling">;
def fdwarf_exceptions : Flag<["-"], "fdwarf-exceptions">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Use DWARF style exceptions">;
def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Use SjLj style exceptions">;
def fseh_exceptions : Flag<["-"], "fseh-exceptions">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Use SEH style exceptions">;
def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">,
Group<clang_ignored_gcc_optimization_f_Group>;
def : Flag<["-"], "fexpensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>;
def : Flag<["-"], "fno-expensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>;
def fextdirs_EQ : Joined<["-"], "fextdirs=">, Group<f_Group>;
def : Flag<["-"], "fdefer-pop">, Group<clang_ignored_gcc_optimization_f_Group>;
def : Flag<["-"], "fno-defer-pop">, Group<clang_ignored_gcc_optimization_f_Group>;
def : Flag<["-"], "fextended-identifiers">, Group<clang_ignored_f_Group>;
def : Flag<["-"], "fno-extended-identifiers">, Group<f_Group>, Flags<[Unsupported]>;
def fhosted : Flag<["-"], "fhosted">, Group<f_Group>;
def fdenormal_fp_math_EQ : Joined<["-"], "fdenormal-fp-math=">, Group<f_Group>, Flags<[CC1Option]>;
def ffast_math : Flag<["-"], "ffast-math">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Allow aggressive, lossy floating-point optimizations">;
def fno_fast_math : Flag<["-"], "fno-fast-math">, Group<f_Group>;
def fmath_errno : Flag<["-"], "fmath-errno">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Require math functions to indicate errors by setting errno">;
def fno_math_errno : Flag<["-"], "fno-math-errno">, Group<f_Group>;
def fbracket_depth_EQ : Joined<["-"], "fbracket-depth=">, Group<f_Group>;
def fsignaling_math : Flag<["-"], "fsignaling-math">, Group<f_Group>;
def fno_signaling_math : Flag<["-"], "fno-signaling-math">, Group<f_Group>;
def fjump_tables : Flag<["-"], "fjump-tables">, Group<f_Group>;
def fno_jump_tables : Flag<["-"], "fno-jump-tables">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Do not use jump tables for lowering switches">;
def fforce_enable_int128 : Flag<["-"], "fforce-enable-int128">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable support for int128_t type">;
def fno_force_enable_int128 : Flag<["-"], "fno-force-enable-int128">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Disable support for int128_t type">;
def fkeep_static_consts : Flag<["-"], "fkeep-static-consts">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Keep static const variables even if unused">;
def ffixed_point : Flag<["-"], "ffixed-point">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Enable fixed point types">;
def fno_fixed_point : Flag<["-"], "fno-fixed-point">, Group<f_Group>,
HelpText<"Disable fixed point types">;
def fcxx_static_destructors : Flag<["-"], "fc++-static-destructors">,
Group<f_Group>,
HelpText<"Enable C++ static destructor registration (the default)">;
def fno_cxx_static_destructors : Flag<["-"], "fno-c++-static-destructors">,
Group<f_Group>,
Flags<[CC1Option]>,
HelpText<"Disable C++ static destructor registration">;
// Begin sanitizer flags. These should all be core options exposed in all driver
// modes.
let Flags = [CC1Option, CoreOption] in {
def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>,
MetaVarName<"<check>">,
HelpText<"Turn on runtime checks for various forms of undefined "
"or suspicious behavior. See user manual for available checks">;
def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>,
Flags<[CoreOption, DriverOption]>;
def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">,
Group<f_clang_Group>,
HelpText<"Path to blacklist file for sanitizers">;
def fno_sanitize_blacklist : Flag<["-"], "fno-sanitize-blacklist">,
Group<f_clang_Group>,
HelpText<"Don't use blacklist file for sanitizers">;
def fsanitize_coverage
: CommaJoined<["-"], "fsanitize-coverage=">,
Group<f_clang_Group>,
HelpText<"Specify the type of coverage instrumentation for Sanitizers">;
def fno_sanitize_coverage
: CommaJoined<["-"], "fno-sanitize-coverage=">,
Group<f_clang_Group>, Flags<[CoreOption, DriverOption]>,
HelpText<"Disable specified features of coverage instrumentation for "
"Sanitizers">, Values<"func,bb,edge,indirect-calls,trace-bb,trace-cmp,trace-div,trace-gep,8bit-counters,trace-pc,trace-pc-guard,no-prune,inline-8bit-counters">;
def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">,
Group<f_clang_Group>,
HelpText<"Enable origins tracking in MemorySanitizer">;
def fsanitize_memory_track_origins : Flag<["-"], "fsanitize-memory-track-origins">,
Group<f_clang_Group>,
HelpText<"Enable origins tracking in MemorySanitizer">;
def fno_sanitize_memory_track_origins : Flag<["-"], "fno-sanitize-memory-track-origins">,
Group<f_clang_Group>,
Flags<[CoreOption, DriverOption]>,
HelpText<"Disable origins tracking in MemorySanitizer">;
def fsanitize_memory_use_after_dtor : Flag<["-"], "fsanitize-memory-use-after-dtor">,
Group<f_clang_Group>,
HelpText<"Enable use-after-destroy detection in MemorySanitizer">;
def fno_sanitize_memory_use_after_dtor : Flag<["-"], "fno-sanitize-memory-use-after-dtor">,
Group<f_clang_Group>,
HelpText<"Disable use-after-destroy detection in MemorySanitizer">;
def fsanitize_address_field_padding : Joined<["-"], "fsanitize-address-field-padding=">,
Group<f_clang_Group>,
HelpText<"Level of field padding for AddressSanitizer">;
def fsanitize_address_use_after_scope : Flag<["-"], "fsanitize-address-use-after-scope">,
Group<f_clang_Group>,
HelpText<"Enable use-after-scope detection in AddressSanitizer">;
def fno_sanitize_address_use_after_scope : Flag<["-"], "fno-sanitize-address-use-after-scope">,
Group<f_clang_Group>,
Flags<[CoreOption, DriverOption]>,
HelpText<"Disable use-after-scope detection in AddressSanitizer">;
def fsanitize_address_poison_custom_array_cookie
: Flag<[ "-" ], "fsanitize-address-poison-custom-array-cookie">,
Group<f_clang_Group>,
HelpText<"Enable poisoning array cookies when using custom operator new[] in AddressSanitizer">;
def fno_sanitize_address_poison_custom_array_cookie
: Flag<[ "-" ], "fno-sanitize-address-poison-custom-array-cookie">,
Group<f_clang_Group>,
HelpText<"Disable poisoning array cookies when using custom operator new[] in AddressSanitizer">;
def fsanitize_address_globals_dead_stripping : Flag<["-"], "fsanitize-address-globals-dead-stripping">,
Group<f_clang_Group>,
HelpText<"Enable linker dead stripping of globals in AddressSanitizer">;
def fsanitize_address_use_odr_indicator
: Flag<["-"], "fsanitize-address-use-odr-indicator">,
Group<f_clang_Group>,
HelpText<"Enable ODR indicator globals to avoid false ODR violation reports in partially sanitized programs at the cost of an increase in binary size">;
def fno_sanitize_address_use_odr_indicator
: Flag<["-"], "fno-sanitize-address-use-odr-indicator">,
Group<f_clang_Group>,
HelpText<"Disable ODR indicator globals">;
def fsanitize_hwaddress_abi_EQ
: Joined<["-"], "fsanitize-hwaddress-abi=">,
Group<f_clang_Group>,
HelpText<"Select the HWAddressSanitizer ABI to target (interceptor or platform, default interceptor)">;
def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>;
def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">,
Flags<[CoreOption, DriverOption]>,
Group<f_clang_Group>;
def fsanitize_recover_EQ : CommaJoined<["-"], "fsanitize-recover=">,
Group<f_clang_Group>,
HelpText<"Enable recovery for specified sanitizers">;
def fno_sanitize_recover_EQ
: CommaJoined<["-"], "fno-sanitize-recover=">,
Group<f_clang_Group>,
Flags<[CoreOption, DriverOption]>,
HelpText<"Disable recovery for specified sanitizers">;
def fsanitize_trap_EQ : CommaJoined<["-"], "fsanitize-trap=">, Group<f_clang_Group>,
HelpText<"Enable trapping for specified sanitizers">;
def fno_sanitize_trap_EQ : CommaJoined<["-"], "fno-sanitize-trap=">, Group<f_clang_Group>,
Flags<[CoreOption, DriverOption]>,
HelpText<"Disable trapping for specified sanitizers">;
def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on-error">,
Group<f_clang_Group>;
def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-trap-on-error">,
Group<f_clang_Group>;
def fsanitize_minimal_runtime : Flag<["-"], "fsanitize-minimal-runtime">,
Group<f_clang_Group>;
def fno_sanitize_minimal_runtime : Flag<["-"], "fno-sanitize-minimal-runtime">,
Group<f_clang_Group>;
def fsanitize_link_cxx_runtime : Flag<["-"], "fsanitize-link-c++-runtime">,
Group<f_clang_Group>;
def fsanitize_cfi_cross_dso : Flag<["-"], "fsanitize-cfi-cross-dso">,
Group<f_clang_Group>,
HelpText<"Enable control flow integrity (CFI) checks for cross-DSO calls.">;
def fno_sanitize_cfi_cross_dso : Flag<["-"], "fno-sanitize-cfi-cross-dso">,
Flags<[CoreOption, DriverOption]>,
Group<f_clang_Group>,
HelpText<"Disable control flow integrity (CFI) checks for cross-DSO calls.">;
def fsanitize_cfi_icall_generalize_pointers : Flag<["-"], "fsanitize-cfi-icall-generalize-pointers">,
Group<f_clang_Group>,
HelpText<"Generalize pointers in CFI indirect call type signature checks">;
def fsanitize_stats : Flag<["-"], "fsanitize-stats">,
Group<f_clang_Group>,
HelpText<"Enable sanitizer statistics gathering.">;
def fno_sanitize_stats : Flag<["-"], "fno-sanitize-stats">,
Group<f_clang_Group>,
Flags<[CoreOption, DriverOption]>,
HelpText<"Disable sanitizer statistics gathering.">;
def fsanitize_thread_memory_access : Flag<["-"], "fsanitize-thread-memory-access">,
Group<f_clang_Group>,
HelpText<"Enable memory access instrumentation in ThreadSanitizer (default)">;
def fno_sanitize_thread_memory_access : Flag<["-"], "fno-sanitize-thread-memory-access">,
Group<f_clang_Group>,
Flags<[CoreOption, DriverOption]>,
HelpText<"Disable memory access instrumentation in ThreadSanitizer">;
def fsanitize_thread_func_entry_exit : Flag<["-"], "fsanitize-thread-func-entry-exit">,
Group<f_clang_Group>,
HelpText<"Enable function entry/exit instrumentation in ThreadSanitizer (default)">;
def fno_sanitize_thread_func_entry_exit : Flag<["-"], "fno-sanitize-thread-func-entry-exit">,
Group<f_clang_Group>,
Flags<[CoreOption, DriverOption]>,
HelpText<"Disable function entry/exit instrumentation in ThreadSanitizer">;
def fsanitize_thread_atomics : Flag<["-"], "fsanitize-thread-atomics">,
Group<f_clang_Group>,
HelpText<"Enable atomic operations instrumentation in ThreadSanitizer (default)">;
def fno_sanitize_thread_atomics : Flag<["-"], "fno-sanitize-thread-atomics">,
Group<f_clang_Group>,
Flags<[CoreOption, DriverOption]>,
HelpText<"Disable atomic operations instrumentation in ThreadSanitizer">;
def fsanitize_undefined_strip_path_components_EQ : Joined<["-"], "fsanitize-undefined-strip-path-components=">,
Group<f_clang_Group>, MetaVarName<"<number>">,
HelpText<"Strip (or keep only, if negative) a given number of path components "
"when emitting check metadata.">;
} // end -f[no-]sanitize* flags
def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">,
Group<f_Group>;
def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">,
Group<f_Group>;
def fassociative_math : Flag<["-"], "fassociative-math">, Group<f_Group>;
def fno_associative_math : Flag<["-"], "fno-associative-math">, Group<f_Group>;
def freciprocal_math :
Flag<["-"], "freciprocal-math">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Allow division operations to be reassociated">;
def fno_reciprocal_math : Flag<["-"], "fno-reciprocal-math">, Group<f_Group>;
def ffinite_math_only : Flag<["-"], "ffinite-math-only">, Group<f_Group>, Flags<[CC1Option]>;
def fno_finite_math_only : Flag<["-"], "fno-finite-math-only">, Group<f_Group>;
def fsigned_zeros : Flag<["-"], "fsigned-zeros">, Group<f_Group>;
def fno_signed_zeros :
Flag<["-"], "fno-signed-zeros">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Allow optimizations that ignore the sign of floating point zeros">;
def fhonor_nans : Flag<["-"], "fhonor-nans">, Group<f_Group>;
def fno_honor_nans : Flag<["-"], "fno-honor-nans">, Group<f_Group>;
def fhonor_infinities : Flag<["-"], "fhonor-infinities">, Group<f_Group>;
def fno_honor_infinities : Flag<["-"], "fno-honor-infinities">, Group<f_Group>;
// This option was originally misspelt "infinites" [sic].
def : Flag<["-"], "fhonor-infinites">, Alias<fhonor_infinities>;
def : Flag<["-"], "fno-honor-infinites">, Alias<fno_honor_infinities>;
def ftrapping_math : Flag<["-"], "ftrapping-math">, Group<f_Group>, Flags<[CC1Option]>;
def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group<f_Group>, Flags<[CC1Option]>;
def ffp_contract : Joined<["-"], "ffp-contract=">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)"
" | on (according to FP_CONTRACT pragma, default) | off (never fuse)">, Values<"fast,on,off">;
def fstrict_float_cast_overflow : Flag<["-"],
"fstrict-float-cast-overflow">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Assume that overflowing float-to-int casts are undefined (default)">;
def fno_strict_float_cast_overflow : Flag<["-"],
"fno-strict-float-cast-overflow">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Relax language rules and try to match the behavior of the target's native float-to-int conversion instructions">;
def ffor_scope : Flag<["-"], "ffor-scope">, Group<f_Group>;
def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>;
def frewrite_includes : Flag<["-"], "frewrite-includes">, Group<f_Group>,
Flags<[CC1Option]>;
def fno_rewrite_includes : Flag<["-"], "fno-rewrite-includes">, Group<f_Group>;
def frewrite_imports : Flag<["-"], "frewrite-imports">, Group<f_Group>,
Flags<[CC1Option]>;
def fno_rewrite_imports : Flag<["-"], "fno-rewrite-imports">, Group<f_Group>;
def fdelete_null_pointer_checks : Flag<["-"],
"fdelete-null-pointer-checks">, Group<f_Group>,
HelpText<"Treat usage of null pointers as undefined behavior.">;
def fno_delete_null_pointer_checks : Flag<["-"],
"fno-delete-null-pointer-checks">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Do not treat usage of null pointers as undefined behavior.">;
def frewrite_map_file : Separate<["-"], "frewrite-map-file">,
Group<f_Group>,
Flags<[ DriverOption, CC1Option ]>;
def frewrite_map_file_EQ : Joined<["-"], "frewrite-map-file=">,
Group<f_Group>,
Flags<[DriverOption]>;
def fuse_line_directives : Flag<["-"], "fuse-line-directives">, Group<f_Group>,
Flags<[CC1Option]>;
def fno_use_line_directives : Flag<["-"], "fno-use-line-directives">, Group<f_Group>;
def ffreestanding : Flag<["-"], "ffreestanding">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Assert that the compilation takes place in a freestanding environment">;
def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Allow GNU-extension keywords regardless of language standard">;
def fgnu89_inline : Flag<["-"], "fgnu89-inline">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use the gnu89 inline semantics">;
def fno_gnu89_inline : Flag<["-"], "fno-gnu89-inline">, Group<f_Group>;
def fgnu_runtime : Flag<["-"], "fgnu-runtime">, Group<f_Group>,
HelpText<"Generate output compatible with the standard GNU Objective-C runtime">;
def fheinous_gnu_extensions : Flag<["-"], "fheinous-gnu-extensions">, Flags<[CC1Option]>;
def filelist : Separate<["-"], "filelist">, Flags<[LinkerInput]>,
Group<Link_Group>;
def : Flag<["-"], "findirect-virtual-calls">, Alias<fapple_kext>;
def finline_functions : Flag<["-"], "finline-functions">, Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Inline suitable functions">;
def finline_hint_functions: Flag<["-"], "finline-hint-functions">, Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Inline functions which are (explicitly or implicitly) marked inline">;
def finline : Flag<["-"], "finline">, Group<clang_ignored_f_Group>;
def fexperimental_isel : Flag<["-"], "fexperimental-isel">, Group<f_clang_Group>,
HelpText<"Enables the experimental global instruction selector">;
def fexperimental_new_pass_manager : Flag<["-"], "fexperimental-new-pass-manager">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Enables an experimental new pass manager in LLVM.">;
def finput_charset_EQ : Joined<["-"], "finput-charset=">, Group<f_Group>;
def fexec_charset_EQ : Joined<["-"], "fexec-charset=">, Group<f_Group>;
def finstrument_functions : Flag<["-"], "finstrument-functions">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Generate calls to instrument function entry and exit">;
def finstrument_functions_after_inlining : Flag<["-"], "finstrument-functions-after-inlining">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Like -finstrument-functions, but insert the calls after inlining">;
def finstrument_function_entry_bare : Flag<["-"], "finstrument-function-entry-bare">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Instrument function entry only, after inlining, without arguments to the instrumentation call">;
def fcf_protection_EQ : Joined<["-"], "fcf-protection=">, Flags<[CoreOption, CC1Option]>, Group<f_Group>,
HelpText<"Instrument control-flow architecture protection. Options: return, branch, full, none.">, Values<"return,branch,full,none">;
def fcf_protection : Flag<["-"], "fcf-protection">, Group<f_Group>, Flags<[CoreOption, CC1Option]>,
Alias<fcf_protection_EQ>, AliasArgs<["full"]>,
HelpText<"Enable cf-protection in 'full' mode">;
def fxray_instrument : Flag<["-"], "fxray-instrument">, Group<f_Group>,
Flags<[CC1Option]>,
HelpText<"Generate XRay instrumentation sleds on function entry and exit">;
def fnoxray_instrument : Flag<["-"], "fno-xray-instrument">, Group<f_Group>,
Flags<[CC1Option]>;
def fxray_instruction_threshold_EQ :
JoinedOrSeparate<["-"], "fxray-instruction-threshold=">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Sets the minimum function size to instrument with XRay">;
def fxray_instruction_threshold_ :
JoinedOrSeparate<["-"], "fxray-instruction-threshold">,
Group<f_Group>, Flags<[CC1Option]>;
def fxray_always_instrument :
JoinedOrSeparate<["-"], "fxray-always-instrument=">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"DEPRECATED: Filename defining the whitelist for imbuing the 'always instrument' XRay attribute.">;
def fxray_never_instrument :
JoinedOrSeparate<["-"], "fxray-never-instrument=">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"DEPRECATED: Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.">;
def fxray_attr_list :
JoinedOrSeparate<["-"], "fxray-attr-list=">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Filename defining the list of functions/types for imbuing XRay attributes.">;
def fxray_modes :
JoinedOrSeparate<["-"], "fxray-modes=">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"List of modes to link in by default into XRay instrumented binaries.">;
def fxray_always_emit_customevents : Flag<["-"], "fxray-always-emit-customevents">, Group<f_Group>,
Flags<[CC1Option]>,
HelpText<"Determine whether to always emit __xray_customevent(...) calls even if the function it appears in is not always instrumented.">;
def fnoxray_always_emit_customevents : Flag<["-"], "fno-xray-always-emit-customevents">, Group<f_Group>,
Flags<[CC1Option]>;
def fxray_always_emit_typedevents : Flag<["-"], "fxray-always-emit-typedevents">, Group<f_Group>,
Flags<[CC1Option]>,
HelpText<"Determine whether to always emit __xray_typedevent(...) calls even if the function it appears in is not always instrumented.">;
def fnoxray_always_emit_typedevents : Flag<["-"], "fno-xray-always-emit-typedevents">, Group<f_Group>,
Flags<[CC1Option]>;
def fxray_link_deps : Flag<["-"], "fxray-link-deps">, Group<f_Group>,
Flags<[CC1Option]>,
HelpText<"Tells clang to add the link dependencies for XRay.">;
def fnoxray_link_deps : Flag<["-"], "fnoxray-link-deps">, Group<f_Group>,
Flags<[CC1Option]>;
def fxray_instrumentation_bundle :
JoinedOrSeparate<["-"], "fxray-instrumentation-bundle=">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Select which XRay instrumentation points to emit. Options: all, none, function, custom. Default is 'all'.">;
def ffine_grained_bitfield_accesses : Flag<["-"],
"ffine-grained-bitfield-accesses">, Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Use separate accesses for consecutive bitfield runs with legal widths and alignments.">;
def fno_fine_grained_bitfield_accesses : Flag<["-"],
"fno-fine-grained-bitfield-accesses">, Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Use large-integer access for consecutive bitfield runs.">;
def flat__namespace : Flag<["-"], "flat_namespace">;
def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>;
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
def flto_EQ : Joined<["-"], "flto=">, Flags<[CoreOption, CC1Option]>, Group<f_Group>,
HelpText<"Set LTO mode to either 'full' or 'thin'">, Values<"thin,full">;
def flto : Flag<["-"], "flto">, Flags<[CoreOption, CC1Option]>, Group<f_Group>,
HelpText<"Enable LTO in 'full' mode">;
def fno_lto : Flag<["-"], "fno-lto">, Group<f_Group>,
HelpText<"Disable LTO mode (default)">;
def flto_jobs_EQ : Joined<["-"], "flto-jobs=">,
Flags<[CC1Option]>, Group<f_Group>,
HelpText<"Controls the backend parallelism of -flto=thin (default "
"of 0 means the number of threads will be derived from "
"the number of CPUs detected)">;
def fthinlto_index_EQ : Joined<["-"], "fthinlto-index=">,
Flags<[CC1Option]>, Group<f_Group>,
HelpText<"Perform ThinLTO importing using provided function summary index">;
def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">,
Group<f_Group>, Flags<[DriverOption, CoreOption]>;
def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group<f_Group>,
Flags<[CC1Option, CoreOption]>, HelpText<"Allow merging of constants">;
def fmessage_length_EQ : Joined<["-"], "fmessage-length=">, Group<f_Group>;
def fms_extensions : Flag<["-"], "fms-extensions">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">;
def fms_compatibility : Flag<["-"], "fms-compatibility">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Enable full Microsoft Visual C++ compatibility">;
def fms_volatile : Joined<["-"], "fms-volatile">, Group<f_Group>, Flags<[CC1Option]>;
def fmsc_version : Joined<["-"], "fmsc-version=">, Group<f_Group>, Flags<[DriverOption, CoreOption]>,
HelpText<"Microsoft compiler version number to report in _MSC_VER (0 = don't define it (default))">;
def fms_compatibility_version
: Joined<["-"], "fms-compatibility-version=">,
Group<f_Group>,
Flags<[ CC1Option, CoreOption ]>,
HelpText<"Dot-separated value representing the Microsoft compiler "
"version number to report in _MSC_VER (0 = don't define it "
"(default))">;
def fdelayed_template_parsing : Flag<["-"], "fdelayed-template-parsing">, Group<f_Group>,
HelpText<"Parse templated function definitions at the end of the "
"translation unit">, Flags<[CC1Option, CoreOption]>;
def fms_memptr_rep_EQ : Joined<["-"], "fms-memptr-rep=">, Group<f_Group>, Flags<[CC1Option]>;
def fmodules_cache_path : Joined<["-"], "fmodules-cache-path=">, Group<i_Group>,
Flags<[DriverOption, CC1Option]>, MetaVarName<"<directory>">,
HelpText<"Specify the module cache path">;
def fmodules_user_build_path : Separate<["-"], "fmodules-user-build-path">, Group<i_Group>,
Flags<[DriverOption, CC1Option]>, MetaVarName<"<directory>">,
HelpText<"Specify the module user build path">;
def fprebuilt_module_path : Joined<["-"], "fprebuilt-module-path=">, Group<i_Group>,
Flags<[DriverOption, CC1Option]>, MetaVarName<"<directory>">,
HelpText<"Specify the prebuilt module path">;
def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, Group<i_Group>,
Flags<[CC1Option]>, MetaVarName<"<seconds>">,
HelpText<"Specify the interval (in seconds) between attempts to prune the module cache">;
def fmodules_prune_after : Joined<["-"], "fmodules-prune-after=">, Group<i_Group>,
Flags<[CC1Option]>, MetaVarName<"<seconds>">,
HelpText<"Specify the interval (in seconds) after which a module file will be considered unused">;
def fmodules_search_all : Flag <["-"], "fmodules-search-all">, Group<f_Group>,
Flags<[DriverOption, CC1Option]>,
HelpText<"Search even non-imported modules to resolve references">;
def fbuild_session_timestamp : Joined<["-"], "fbuild-session-timestamp=">,
Group<i_Group>, Flags<[CC1Option]>, MetaVarName<"<time since Epoch in seconds>">,
HelpText<"Time when the current build session started">;
def fbuild_session_file : Joined<["-"], "fbuild-session-file=">,
Group<i_Group>, MetaVarName<"<file>">,
HelpText<"Use the last modification time of <file> as the build session timestamp">;
def fmodules_validate_once_per_build_session : Flag<["-"], "fmodules-validate-once-per-build-session">,
Group<i_Group>, Flags<[CC1Option]>,
HelpText<"Don't verify input files for the modules if the module has been "
"successfully validated or loaded during this build session">;
def fmodules_disable_diagnostic_validation : Flag<["-"], "fmodules-disable-diagnostic-validation">,
Group<i_Group>, Flags<[CC1Option]>,
HelpText<"Disable validation of the diagnostic options when loading the module">;
def fmodules_validate_system_headers : Flag<["-"], "fmodules-validate-system-headers">,
Group<i_Group>, Flags<[CC1Option]>,
HelpText<"Validate the system headers that a module depends on when loading the module">;
def fno_modules_validate_system_headers : Flag<["-"], "fno-modules-validate-system-headers">,
Group<i_Group>, Flags<[DriverOption]>;
def fmodules : Flag <["-"], "fmodules">, Group<f_Group>,
Flags<[DriverOption, CC1Option]>,
HelpText<"Enable the 'modules' language feature">;
def fimplicit_module_maps : Flag <["-"], "fimplicit-module-maps">, Group<f_Group>,
Flags<[DriverOption, CC1Option]>,
HelpText<"Implicitly search the file system for module map files.">;
def fmodules_ts : Flag <["-"], "fmodules-ts">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Enable support for the C++ Modules TS">;
def fmodule_maps : Flag <["-"], "fmodule-maps">, Alias<fimplicit_module_maps>;
def fmodule_name_EQ : Joined<["-"], "fmodule-name=">, Group<f_Group>,
Flags<[DriverOption,CC1Option]>, MetaVarName<"<name>">,
HelpText<"Specify the name of the module to build">;
def fmodule_name : Separate<["-"], "fmodule-name">, Alias<fmodule_name_EQ>;
def fmodule_implementation_of : Separate<["-"], "fmodule-implementation-of">,
Flags<[CC1Option]>, Alias<fmodule_name_EQ>;
def fmodule_map_file : Joined<["-"], "fmodule-map-file=">,
Group<f_Group>, Flags<[DriverOption,CC1Option]>, MetaVarName<"<file>">,
HelpText<"Load this module map file">;
def fmodule_file : Joined<["-"], "fmodule-file=">,
Group<i_Group>, Flags<[DriverOption,CC1Option]>, MetaVarName<"[<name>=]<file>">,
HelpText<"Specify the mapping of module name to precompiled module file, or load a module file if name is omitted.">;
def fmodules_ignore_macro : Joined<["-"], "fmodules-ignore-macro=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Ignore the definition of the given macro when building and loading modules">;
def fmodules_decluse : Flag <["-"], "fmodules-decluse">, Group<f_Group>,
Flags<[DriverOption,CC1Option]>,
HelpText<"Require declaration of modules used within a module">;
def fmodules_strict_decluse : Flag <["-"], "fmodules-strict-decluse">, Group<f_Group>,
Flags<[DriverOption,CC1Option]>,
HelpText<"Like -fmodules-decluse but requires all headers to be in modules">;
def fno_modules_search_all : Flag <["-"], "fno-modules-search-all">, Group<f_Group>,
Flags<[DriverOption, CC1Option]>;
def fno_implicit_modules :
Flag <["-"], "fno-implicit-modules">,
Group<f_Group>, Flags<[DriverOption, CC1Option]>;
def fretain_comments_from_system_headers : Flag<["-"], "fretain-comments-from-system-headers">, Group<f_Group>, Flags<[CC1Option]>;
def fmudflapth : Flag<["-"], "fmudflapth">, Group<f_Group>;
def fmudflap : Flag<["-"], "fmudflap">, Group<f_Group>;
def fnested_functions : Flag<["-"], "fnested-functions">, Group<f_Group>;
def fnext_runtime : Flag<["-"], "fnext-runtime">, Group<f_Group>;
def fno_access_control : Flag<["-"], "fno-access-control">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Disable C++ access control">;
def fno_apple_pragma_pack : Flag<["-"], "fno-apple-pragma-pack">, Group<f_Group>;
def fno_asm : Flag<["-"], "fno-asm">, Group<f_Group>;
def fno_asynchronous_unwind_tables : Flag<["-"], "fno-asynchronous-unwind-tables">, Group<f_Group>;
def fno_assume_sane_operator_new : Flag<["-"], "fno-assume-sane-operator-new">, Group<f_Group>,
HelpText<"Don't assume that C++'s global operator new can't alias any pointer">,
Flags<[CC1Option]>;
def fno_blocks : Flag<["-"], "fno-blocks">, Group<f_Group>, Flags<[CoreOption]>;
def fno_borland_extensions : Flag<["-"], "fno-borland-extensions">, Group<f_Group>;
def fno_builtin : Flag<["-"], "fno-builtin">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Disable implicit builtin knowledge of functions">;
def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Disable implicit builtin knowledge of a specific function">;
def fno_caret_diagnostics : Flag<["-"], "fno-caret-diagnostics">, Group<f_Group>,
Flags<[CC1Option]>;
def fno_color_diagnostics : Flag<["-"], "fno-color-diagnostics">, Group<f_Group>,
Flags<[CoreOption, CC1Option]>;
def fno_diagnostics_color : Flag<["-"], "fno-diagnostics-color">, Group<f_Group>,
Flags<[CoreOption, DriverOption]>;
def fno_common : Flag<["-"], "fno-common">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Compile common globals like normal definitions">;
def fno_constant_cfstrings : Flag<["-"], "fno-constant-cfstrings">, Group<f_Group>,
Flags<[CC1Option]>,
HelpText<"Disable creation of CodeFoundation-type constant strings">;
def fno_cxx_exceptions: Flag<["-"], "fno-cxx-exceptions">, Group<f_Group>;
def fno_cxx_modules : Flag <["-"], "fno-cxx-modules">, Group<f_Group>,
Flags<[DriverOption]>;
def fno_diagnostics_fixit_info : Flag<["-"], "fno-diagnostics-fixit-info">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Do not include fixit information in diagnostics">;
def fno_diagnostics_show_hotness : Flag<["-"], "fno-diagnostics-show-hotness">, Group<f_Group>;
def fno_diagnostics_show_option : Flag<["-"], "fno-diagnostics-show-option">, Group<f_Group>;
def fno_diagnostics_show_note_include_stack : Flag<["-"], "fno-diagnostics-show-note-include-stack">,
Flags<[CC1Option]>, Group<f_Group>;
def fdigraphs : Flag<["-"], "fdigraphs">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable alternative token representations '<:', ':>', '<%', '%>', '%:', '%:%:' (default)">;
def fno_digraphs : Flag<["-"], "fno-digraphs">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Disallow alternative token representations '<:', ':>', '<%', '%>', '%:', '%:%:'">;
def fno_declspec : Flag<["-"], "fno-declspec">, Group<f_clang_Group>,
HelpText<"Disallow __declspec as a keyword">, Flags<[CC1Option]>;
def fno_dollars_in_identifiers : Flag<["-"], "fno-dollars-in-identifiers">, Group<f_Group>,
HelpText<"Disallow '$' in identifiers">, Flags<[CC1Option]>;
def fno_elide_constructors : Flag<["-"], "fno-elide-constructors">, Group<f_Group>,
HelpText<"Disable C++ copy constructor elision">, Flags<[CC1Option]>;
def fno_eliminate_unused_debug_symbols : Flag<["-"], "fno-eliminate-unused-debug-symbols">, Group<f_Group>;
def fno_exceptions : Flag<["-"], "fno-exceptions">, Group<f_Group>;
def fno_gnu_keywords : Flag<["-"], "fno-gnu-keywords">, Group<f_Group>, Flags<[CC1Option]>;
def fno_inline_functions : Flag<["-"], "fno-inline-functions">, Group<f_clang_Group>, Flags<[CC1Option]>;
def fno_inline : Flag<["-"], "fno-inline">, Group<f_clang_Group>, Flags<[CC1Option]>;
def fno_experimental_isel : Flag<["-"], "fno-experimental-isel">, Group<f_clang_Group>,
HelpText<"Disables the experimental global instruction selector">;
def fno_experimental_new_pass_manager : Flag<["-"], "fno-experimental-new-pass-manager">,
Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Disables an experimental new pass manager in LLVM.">;
def fveclib : Joined<["-"], "fveclib=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use the given vector functions library">, Values<"Accelerate,SVML,none">;
def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group<f_Group>,
HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>;
def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group<f_Group>,
HelpText<"Disallow merging of constants">;
def fno_modules : Flag <["-"], "fno-modules">, Group<f_Group>,
Flags<[DriverOption]>;
def fno_implicit_module_maps : Flag <["-"], "fno-implicit-module-maps">, Group<f_Group>,
Flags<[DriverOption]>;
def fno_module_maps : Flag <["-"], "fno-module-maps">, Alias<fno_implicit_module_maps>;
def fno_modules_decluse : Flag <["-"], "fno-modules-decluse">, Group<f_Group>,
Flags<[DriverOption]>;
def fno_modules_strict_decluse : Flag <["-"], "fno-strict-modules-decluse">, Group<f_Group>,
Flags<[DriverOption]>;
def fimplicit_modules : Flag <["-"], "fimplicit-modules">, Group<f_Group>,
Flags<[DriverOption]>;
def fmodule_file_deps : Flag <["-"], "fmodule-file-deps">, Group<f_Group>,
Flags<[DriverOption]>;
def fno_module_file_deps : Flag <["-"], "fno-module-file-deps">, Group<f_Group>,
Flags<[DriverOption]>;
def fno_ms_extensions : Flag<["-"], "fno-ms-extensions">, Group<f_Group>,
Flags<[CoreOption]>;
def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group<f_Group>,
Flags<[CoreOption]>;
def fno_delayed_template_parsing : Flag<["-"], "fno-delayed-template-parsing">, Group<f_Group>,
HelpText<"Disable delayed template parsing">,
Flags<[DriverOption, CoreOption]>;
def fno_objc_exceptions: Flag<["-"], "fno-objc-exceptions">, Group<f_Group>;
def fno_objc_legacy_dispatch : Flag<["-"], "fno-objc-legacy-dispatch">, Group<f_Group>;
def fno_objc_weak : Flag<["-"], "fno-objc-weak">, Group<f_Group>, Flags<[CC1Option]>;
def fno_omit_frame_pointer : Flag<["-"], "fno-omit-frame-pointer">, Group<f_Group>;
def fno_operator_names : Flag<["-"], "fno-operator-names">, Group<f_Group>,
HelpText<"Do not treat C++ operator name keywords as synonyms for operators">,
Flags<[CC1Option]>;
def fno_pascal_strings : Flag<["-"], "fno-pascal-strings">, Group<f_Group>;
def fno_rtti : Flag<["-"], "fno-rtti">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Disable generation of rtti information">;
def fno_rtti_data : Flag<["-"], "fno-rtti-data">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Control emission of RTTI data">;
def fno_short_enums : Flag<["-"], "fno-short-enums">, Group<f_Group>;
def fno_show_column : Flag<["-"], "fno-show-column">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Do not include column number on diagnostics">;
def fno_show_source_location : Flag<["-"], "fno-show-source-location">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Do not include source location information with diagnostics">;
def fdiagnostics_absolute_paths : Flag<["-"], "fdiagnostics-absolute-paths">, Group<f_Group>,
Flags<[CC1Option, CoreOption]>, HelpText<"Print absolute paths in diagnostics">;
def fno_spell_checking : Flag<["-"], "fno-spell-checking">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Disable spell-checking">;
def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group<f_Group>,
HelpText<"Disable the use of stack protectors">;
def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group<f_Group>,
Flags<[DriverOption, CoreOption]>;
def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group<f_Group>;
def fno_struct_path_tbaa : Flag<["-"], "fno-struct-path-tbaa">, Group<f_Group>;
def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group<f_Group>;
def fno_strict_vtable_pointers: Flag<["-"], "fno-strict-vtable-pointers">,
Group<f_Group>;
def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group<f_Group>;
def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Do not emit code to make initialization of local statics thread safe">;
def fno_use_cxa_atexit : Flag<["-"], "fno-use-cxa-atexit">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Don't use __cxa_atexit for calling destructors">;
def fno_register_global_dtors_with_atexit : Flag<["-"], "fno-register-global-dtors-with-atexit">, Group<f_Group>,
HelpText<"Don't use atexit or __cxa_atexit to register global destructors">;
def fno_use_init_array : Flag<["-"], "fno-use-init-array">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Don't use .init_array instead of .ctors">;
def fno_unit_at_a_time : Flag<["-"], "fno-unit-at-a-time">, Group<f_Group>;
def fno_unwind_tables : Flag<["-"], "fno-unwind-tables">, Group<f_Group>;
def fno_verbose_asm : Flag<["-"], "fno-verbose-asm">, Group<f_Group>;
def fno_working_directory : Flag<["-"], "fno-working-directory">, Group<f_Group>;
def fno_wrapv : Flag<["-"], "fno-wrapv">, Group<f_Group>;
def fno_zero_initialized_in_bss : Flag<["-"], "fno-zero-initialized-in-bss">, Group<f_Group>;
def fobjc_arc : Flag<["-"], "fobjc-arc">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Synthesize retain and release calls for Objective-C pointers">;
def fno_objc_arc : Flag<["-"], "fno-objc-arc">, Group<f_Group>;
def fobjc_convert_messages_to_runtime_calls :
Flag<["-"], "fobjc-convert-messages-to-runtime-calls">, Group<f_Group>;
def fno_objc_convert_messages_to_runtime_calls :
Flag<["-"], "fno-objc-convert-messages-to-runtime-calls">, Group<f_Group>, Flags<[CC1Option]>;
def fobjc_arc_exceptions : Flag<["-"], "fobjc-arc-exceptions">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use EH-safe code when synthesizing retains and releases in -fobjc-arc">;
def fno_objc_arc_exceptions : Flag<["-"], "fno-objc-arc-exceptions">, Group<f_Group>;
def fobjc_atdefs : Flag<["-"], "fobjc-atdefs">, Group<clang_ignored_f_Group>;
def fobjc_call_cxx_cdtors : Flag<["-"], "fobjc-call-cxx-cdtors">, Group<clang_ignored_f_Group>;
def fobjc_exceptions: Flag<["-"], "fobjc-exceptions">, Group<f_Group>,
HelpText<"Enable Objective-C exceptions">, Flags<[CC1Option]>;
def fapplication_extension : Flag<["-"], "fapplication-extension">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Restrict code to those available for App Extensions">;
def fno_application_extension : Flag<["-"], "fno-application-extension">,
Group<f_Group>;
def frelaxed_template_template_args : Flag<["-"], "frelaxed-template-template-args">,
Flags<[CC1Option]>, HelpText<"Enable C++17 relaxed template template argument matching">,
Group<f_Group>;
def fno_relaxed_template_template_args : Flag<["-"], "fno-relaxed-template-template-args">,
Group<f_Group>;
def fsized_deallocation : Flag<["-"], "fsized-deallocation">, Flags<[CC1Option]>,
HelpText<"Enable C++14 sized global deallocation functions">, Group<f_Group>;
def fno_sized_deallocation: Flag<["-"], "fno-sized-deallocation">, Group<f_Group>;
def faligned_allocation : Flag<["-"], "faligned-allocation">, Flags<[CC1Option]>,
HelpText<"Enable C++17 aligned allocation functions">, Group<f_Group>;
def fno_aligned_allocation: Flag<["-"], "fno-aligned-allocation">,
Group<f_Group>, Flags<[CC1Option]>;
def fnew_alignment_EQ : Joined<["-"], "fnew-alignment=">,
HelpText<"Specifies the largest alignment guaranteed by '::operator new(size_t)'">,
MetaVarName<"<align>">, Group<f_Group>, Flags<[CC1Option]>;
def : Separate<["-"], "fnew-alignment">, Alias<fnew_alignment_EQ>;
def : Flag<["-"], "faligned-new">, Alias<faligned_allocation>;
def : Flag<["-"], "fno-aligned-new">, Alias<fno_aligned_allocation>;
def faligned_new_EQ : Joined<["-"], "faligned-new=">;
def fobjc_legacy_dispatch : Flag<["-"], "fobjc-legacy-dispatch">, Group<f_Group>;
def fobjc_new_property : Flag<["-"], "fobjc-new-property">, Group<clang_ignored_f_Group>;
def fobjc_infer_related_result_type : Flag<["-"], "fobjc-infer-related-result-type">,
Group<f_Group>;
def fno_objc_infer_related_result_type : Flag<["-"],
"fno-objc-infer-related-result-type">, Group<f_Group>,
HelpText<
"do not infer Objective-C related result type based on method family">,
Flags<[CC1Option]>;
def fobjc_link_runtime: Flag<["-"], "fobjc-link-runtime">, Group<f_Group>;
def fobjc_weak : Flag<["-"], "fobjc-weak">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable ARC-style weak references in Objective-C">;
// Objective-C ABI options.
def fobjc_runtime_EQ : Joined<["-"], "fobjc-runtime=">, Group<f_Group>, Flags<[CC1Option, CoreOption]>,
HelpText<"Specify the target Objective-C runtime kind and version">;
def fobjc_abi_version_EQ : Joined<["-"], "fobjc-abi-version=">, Group<f_Group>;
def fobjc_nonfragile_abi_version_EQ : Joined<["-"], "fobjc-nonfragile-abi-version=">, Group<f_Group>;
def fobjc_nonfragile_abi : Flag<["-"], "fobjc-nonfragile-abi">, Group<f_Group>;
def fno_objc_nonfragile_abi : Flag<["-"], "fno-objc-nonfragile-abi">, Group<f_Group>;
def fobjc_sender_dependent_dispatch : Flag<["-"], "fobjc-sender-dependent-dispatch">, Group<f_Group>;
def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>;
def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>,
HelpText<"Parse OpenMP pragmas and generate parallel code.">;
def fno_openmp : Flag<["-"], "fno-openmp">, Group<f_Group>, Flags<[NoArgumentUnused]>;
def fopenmp_version_EQ : Joined<["-"], "fopenmp-version=">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
def fopenmp_EQ : Joined<["-"], "fopenmp=">, Group<f_Group>;
def fopenmp_use_tls : Flag<["-"], "fopenmp-use-tls">, Group<f_Group>,
Flags<[NoArgumentUnused, HelpHidden]>;
def fnoopenmp_use_tls : Flag<["-"], "fnoopenmp-use-tls">, Group<f_Group>,
Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
def fopenmp_targets_EQ : CommaJoined<["-"], "fopenmp-targets=">, Flags<[DriverOption, CC1Option]>,
HelpText<"Specify comma-separated list of triples OpenMP offloading targets to be supported">;
def fopenmp_dump_offload_linker_script : Flag<["-"], "fopenmp-dump-offload-linker-script">,
Group<f_Group>, Flags<[NoArgumentUnused, HelpHidden]>;
def fopenmp_relocatable_target : Flag<["-"], "fopenmp-relocatable-target">,
Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
def fnoopenmp_relocatable_target : Flag<["-"], "fnoopenmp-relocatable-target">,
Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
def fopenmp_simd : Flag<["-"], "fopenmp-simd">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>,
HelpText<"Emit OpenMP code only for SIMD-based constructs.">;
def fno_openmp_simd : Flag<["-"], "fno-openmp-simd">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
def fopenmp_cuda_mode : Flag<["-"], "fopenmp-cuda-mode">, Group<f_Group>,
Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
def fno_openmp_cuda_mode : Flag<["-"], "fno-openmp-cuda-mode">, Group<f_Group>,
Flags<[NoArgumentUnused, HelpHidden]>;
def fopenmp_cuda_force_full_runtime : Flag<["-"], "fopenmp-cuda-force-full-runtime">, Group<f_Group>,
Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
def fno_openmp_cuda_force_full_runtime : Flag<["-"], "fno-openmp-cuda-force-full-runtime">, Group<f_Group>,
Flags<[NoArgumentUnused, HelpHidden]>;
def fopenmp_cuda_number_of_sm_EQ : Joined<["-"], "fopenmp-cuda-number-of-sm=">, Group<f_Group>,
Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
def fopenmp_cuda_blocks_per_sm_EQ : Joined<["-"], "fopenmp-cuda-blocks-per-sm=">, Group<f_Group>,
Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
def fopenmp_optimistic_collapse : Flag<["-"], "fopenmp-optimistic-collapse">, Group<f_Group>,
Flags<[CC1Option, NoArgumentUnused, HelpHidden]>;
def fno_openmp_optimistic_collapse : Flag<["-"], "fno-openmp-optimistic-collapse">, Group<f_Group>,
Flags<[NoArgumentUnused, HelpHidden]>;
def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>;
def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>;
def fno_escaping_block_tail_calls : Flag<["-"], "fno-escaping-block-tail-calls">, Group<f_Group>, Flags<[CC1Option]>;
def fescaping_block_tail_calls : Flag<["-"], "fescaping-block-tail-calls">, Group<f_Group>;
def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">;
def force__flat__namespace : Flag<["-"], "force_flat_namespace">;
def force__load : Separate<["-"], "force_load">;
def force_addr : Joined<["-"], "fforce-addr">, Group<clang_ignored_f_Group>;
def foutput_class_dir_EQ : Joined<["-"], "foutput-class-dir=">, Group<f_Group>;
def fpack_struct : Flag<["-"], "fpack-struct">, Group<f_Group>;
def fno_pack_struct : Flag<["-"], "fno-pack-struct">, Group<f_Group>;
def fpack_struct_EQ : Joined<["-"], "fpack-struct=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Specify the default maximum struct packing alignment">;
def fmax_type_align_EQ : Joined<["-"], "fmax-type-align=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Specify the maximum alignment to enforce on pointers lacking an explicit alignment">;
def fno_max_type_align : Flag<["-"], "fno-max-type-align">, Group<f_Group>;
def fpascal_strings : Flag<["-"], "fpascal-strings">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Recognize and construct Pascal-style string literals">;
def fpcc_struct_return : Flag<["-"], "fpcc-struct-return">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Override the default ABI to return all structs on the stack">;
def fpch_preprocess : Flag<["-"], "fpch-preprocess">, Group<f_Group>;
def fpic : Flag<["-"], "fpic">, Group<f_Group>;
def fno_pic : Flag<["-"], "fno-pic">, Group<f_Group>;
def fpie : Flag<["-"], "fpie">, Group<f_Group>;
def fno_pie : Flag<["-"], "fno-pie">, Group<f_Group>;
def fplt : Flag<["-"], "fplt">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use the PLT to make function calls">;
def fno_plt : Flag<["-"], "fno-plt">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Do not use the PLT to make function calls">;
def fropi : Flag<["-"], "fropi">, Group<f_Group>;
def fno_ropi : Flag<["-"], "fno-ropi">, Group<f_Group>;
def frwpi : Flag<["-"], "frwpi">, Group<f_Group>;
def fno_rwpi : Flag<["-"], "fno-rwpi">, Group<f_Group>;
def fplugin_EQ : Joined<["-"], "fplugin=">, Group<f_Group>, Flags<[DriverOption]>, MetaVarName<"<dsopath>">,
HelpText<"Load the named plugin (dynamic shared object)">;
def fpreserve_as_comments : Flag<["-"], "fpreserve-as-comments">, Group<f_Group>;
def fno_preserve_as_comments : Flag<["-"], "fno-preserve-as-comments">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Do not preserve comments in inline assembly">;
def fprofile_arcs : Flag<["-"], "fprofile-arcs">, Group<f_Group>;
def fno_profile_arcs : Flag<["-"], "fno-profile-arcs">, Group<f_Group>;
def framework : Separate<["-"], "framework">, Flags<[LinkerInput]>;
def frandom_seed_EQ : Joined<["-"], "frandom-seed=">, Group<clang_ignored_f_Group>;
def freg_struct_return : Flag<["-"], "freg-struct-return">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Override the default ABI to return small structs in registers">;
def frtti : Flag<["-"], "frtti">, Group<f_Group>;
def : Flag<["-"], "fsched-interblock">, Group<clang_ignored_f_Group>;
def fshort_enums : Flag<["-"], "fshort-enums">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">;
def fchar8__t : Flag<["-"], "fchar8_t">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable C++ builtin type char8_t">;
def fno_char8__t : Flag<["-"], "fno-char8_t">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Disable C++ builtin type char8_t">;
def fshort_wchar : Flag<["-"], "fshort-wchar">, Group<f_Group>,
HelpText<"Force wchar_t to be a short unsigned int">;
def fno_short_wchar : Flag<["-"], "fno-short-wchar">, Group<f_Group>,
HelpText<"Force wchar_t to be an unsigned int">;
def fshow_overloads_EQ : Joined<["-"], "fshow-overloads=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Which overload candidates to show when overload resolution fails: "
"best|all; defaults to all">, Values<"best,all">;
def fshow_column : Flag<["-"], "fshow-column">, Group<f_Group>, Flags<[CC1Option]>;
def fshow_source_location : Flag<["-"], "fshow-source-location">, Group<f_Group>;
def fspell_checking : Flag<["-"], "fspell-checking">, Group<f_Group>;
def fspell_checking_limit_EQ : Joined<["-"], "fspell-checking-limit=">, Group<f_Group>;
def fsigned_bitfields : Flag<["-"], "fsigned-bitfields">, Group<f_Group>;
def fsigned_char : Flag<["-"], "fsigned-char">, Group<f_Group>;
def fno_signed_char : Flag<["-"], "fno-signed-char">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Char is unsigned">;
def fsplit_stack : Flag<["-"], "fsplit-stack">, Group<f_Group>;
def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group<f_Group>,
HelpText<"Enable stack protectors for all functions">;
def fstack_protector_strong : Flag<["-"], "fstack-protector-strong">, Group<f_Group>,
HelpText<"Enable stack protectors for some functions vulnerable to stack smashing. "
"Compared to -fstack-protector, this uses a stronger heuristic "
"that includes functions containing arrays of any size (and any type), "
"as well as any calls to alloca or the taking of an address from a local variable">;
def fstack_protector : Flag<["-"], "fstack-protector">, Group<f_Group>,
HelpText<"Enable stack protectors for some functions vulnerable to stack smashing. "
"This uses a loose heuristic which considers functions vulnerable "
"if they contain a char (or 8bit integer) array or constant sized calls to "
"alloca, which are of greater size than ssp-buffer-size (default: 8 bytes). "
"All variable sized calls to alloca are considered vulnerable">;
def ftrivial_auto_var_init : Joined<["-"], "ftrivial-auto-var-init=">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Initialize trivial automatic stack variables: uninitialized (default)"
" | pattern">, Values<"uninitialized,pattern">;
def enable_trivial_var_init_zero : Joined<["-"], "enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang">,
Flags<[CC1Option]>,
HelpText<"Trivial automatic variable initialization to zero is only here for benchmarks, it'll eventually be removed, and I'm OK with that because I'm only using it to benchmark">;
def fstandalone_debug : Flag<["-"], "fstandalone-debug">, Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Emit full debug info for all types used by the program">;
def fno_standalone_debug : Flag<["-"], "fno-standalone-debug">, Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Limit debug information produced to reduce size of debug binary">;
def flimit_debug_info : Flag<["-"], "flimit-debug-info">, Flags<[CoreOption]>, Alias<fno_standalone_debug>;
def fno_limit_debug_info : Flag<["-"], "fno-limit-debug-info">, Flags<[CoreOption]>, Alias<fstandalone_debug>;
def fdebug_macro : Flag<["-"], "fdebug-macro">, Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Emit macro debug information">;
def fno_debug_macro : Flag<["-"], "fno-debug-macro">, Group<f_Group>, Flags<[CoreOption]>,
HelpText<"Do not emit macro debug information">;
def fstrict_aliasing : Flag<["-"], "fstrict-aliasing">, Group<f_Group>,
Flags<[DriverOption, CoreOption]>;
def fstrict_enums : Flag<["-"], "fstrict-enums">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable optimizations based on the strict definition of an enum's "
"value range">;
def fstrict_vtable_pointers: Flag<["-"], "fstrict-vtable-pointers">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable optimizations based on the strict rules for overwriting "
"polymorphic C++ objects">;
def fstrict_overflow : Flag<["-"], "fstrict-overflow">, Group<f_Group>;
def fsyntax_only : Flag<["-"], "fsyntax-only">,
Flags<[DriverOption,CoreOption,CC1Option]>, Group<Action_Group>;
def ftabstop_EQ : Joined<["-"], "ftabstop=">, Group<f_Group>;
def ftemplate_depth_EQ : Joined<["-"], "ftemplate-depth=">, Group<f_Group>;
def ftemplate_depth_ : Joined<["-"], "ftemplate-depth-">, Group<f_Group>;
def ftemplate_backtrace_limit_EQ : Joined<["-"], "ftemplate-backtrace-limit=">,
Group<f_Group>;
def foperator_arrow_depth_EQ : Joined<["-"], "foperator-arrow-depth=">,
Group<f_Group>;
def fsave_optimization_record : Flag<["-"], "fsave-optimization-record">,
Group<f_Group>, HelpText<"Generate a YAML optimization record file">;
def fno_save_optimization_record : Flag<["-"], "fno-save-optimization-record">,
Group<f_Group>, Flags<[NoArgumentUnused]>;
def foptimization_record_file_EQ : Joined<["-"], "foptimization-record-file=">,
Group<f_Group>,
HelpText<"Specify the file name of any generated YAML optimization record">;
def ftest_coverage : Flag<["-"], "ftest-coverage">, Group<f_Group>;
def fvectorize : Flag<["-"], "fvectorize">, Group<f_Group>,
HelpText<"Enable the loop vectorization passes">;
def fno_vectorize : Flag<["-"], "fno-vectorize">, Group<f_Group>;
def : Flag<["-"], "ftree-vectorize">, Alias<fvectorize>;
def : Flag<["-"], "fno-tree-vectorize">, Alias<fno_vectorize>;
def fslp_vectorize : Flag<["-"], "fslp-vectorize">, Group<f_Group>,
HelpText<"Enable the superword-level parallelism vectorization passes">;
def fno_slp_vectorize : Flag<["-"], "fno-slp-vectorize">, Group<f_Group>;
def : Flag<["-"], "ftree-slp-vectorize">, Alias<fslp_vectorize>;
def : Flag<["-"], "fno-tree-slp-vectorize">, Alias<fno_slp_vectorize>;
def Wlarge_by_value_copy_def : Flag<["-"], "Wlarge-by-value-copy">,
HelpText<"Warn if a function definition returns or accepts an object larger "
"in bytes than a given value">, Flags<[HelpHidden]>;
def Wlarge_by_value_copy_EQ : Joined<["-"], "Wlarge-by-value-copy=">, Flags<[CC1Option]>;
// These "special" warning flags are effectively processed as f_Group flags by the driver:
// Just silence warnings about -Wlarger-than for now.
def Wlarger_than_EQ : Joined<["-"], "Wlarger-than=">, Group<clang_ignored_f_Group>;
def Wlarger_than_ : Joined<["-"], "Wlarger-than-">, Alias<Wlarger_than_EQ>;
def Wframe_larger_than_EQ : Joined<["-"], "Wframe-larger-than=">, Group<f_Group>, Flags<[DriverOption]>;
def : Flag<["-"], "fterminated-vtables">, Alias<fapple_kext>;
def fthreadsafe_statics : Flag<["-"], "fthreadsafe-statics">, Group<f_Group>;
def ftime_report : Flag<["-"], "ftime-report">, Group<f_Group>, Flags<[CC1Option]>;
def ftlsmodel_EQ : Joined<["-"], "ftls-model=">, Group<f_Group>, Flags<[CC1Option]>;
def ftrapv : Flag<["-"], "ftrapv">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Trap on integer overflow">;
def ftrapv_handler_EQ : Joined<["-"], "ftrapv-handler=">, Group<f_Group>,
MetaVarName<"<function name>">,
HelpText<"Specify the function to be called on overflow">;
def ftrapv_handler : Separate<["-"], "ftrapv-handler">, Group<f_Group>, Flags<[CC1Option]>;
def ftrap_function_EQ : Joined<["-"], "ftrap-function=">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Issue call to specified function rather than a trap instruction">;
def funit_at_a_time : Flag<["-"], "funit-at-a-time">, Group<f_Group>;
def funroll_loops : Flag<["-"], "funroll-loops">, Group<f_Group>,
HelpText<"Turn on loop unroller">, Flags<[CC1Option]>;
def fno_unroll_loops : Flag<["-"], "fno-unroll-loops">, Group<f_Group>,
HelpText<"Turn off loop unroller">, Flags<[CC1Option]>;
def freroll_loops : Flag<["-"], "freroll-loops">, Group<f_Group>,
HelpText<"Turn on loop reroller">, Flags<[CC1Option]>;
def fno_reroll_loops : Flag<["-"], "fno-reroll-loops">, Group<f_Group>,
HelpText<"Turn off loop reroller">;
def ftrigraphs : Flag<["-"], "ftrigraphs">, Group<f_Group>,
HelpText<"Process trigraph sequences">, Flags<[CC1Option]>;
def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
HelpText<"Do not process trigraph sequences">, Flags<[CC1Option]>;
def funsigned_bitfields : Flag<["-"], "funsigned-bitfields">, Group<f_Group>;
def funsigned_char : Flag<["-"], "funsigned-char">, Group<f_Group>;
def fno_unsigned_char : Flag<["-"], "fno-unsigned-char">;
def funwind_tables : Flag<["-"], "funwind-tables">, Group<f_Group>;
def fuse_cxa_atexit : Flag<["-"], "fuse-cxa-atexit">, Group<f_Group>;
def fregister_global_dtors_with_atexit : Flag<["-"], "fregister-global-dtors-with-atexit">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use atexit or __cxa_atexit to register global destructors">;
def fuse_init_array : Flag<["-"], "fuse-init-array">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use .init_array instead of .ctors">;
def fno_var_tracking : Flag<["-"], "fno-var-tracking">, Group<clang_ignored_f_Group>;
def fverbose_asm : Flag<["-"], "fverbose-asm">, Group<f_Group>;
def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>,
HelpText<"Set the default symbol visibility for all global declarations">, Values<"hidden,default">;
def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group<f_Group>,
HelpText<"Give inline C++ member functions hidden visibility by default">,
Flags<[CC1Option]>;
def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group<f_Group>,
HelpText<"Give global types 'default' visibility and global functions and "
"variables 'hidden' visibility by default">;
def fvisibility_global_new_delete_hidden : Flag<["-"], "fvisibility-global-new-delete-hidden">, Group<f_Group>,
HelpText<"Give global C++ operator new and delete declarations hidden visibility">, Flags<[CC1Option]>;
def fwhole_program_vtables : Flag<["-"], "fwhole-program-vtables">, Group<f_Group>,
Flags<[CoreOption, CC1Option]>,
HelpText<"Enables whole-program vtable optimization. Requires -flto">;
def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-vtables">, Group<f_Group>,
Flags<[CoreOption]>;
def fsplit_lto_unit : Flag<["-"], "fsplit-lto-unit">, Group<f_Group>,
Flags<[CoreOption, CC1Option]>,
HelpText<"Enables splitting of the LTO unit.">;
def fno_split_lto_unit : Flag<["-"], "fno-split-lto-unit">, Group<f_Group>,
Flags<[CoreOption]>;
def fforce_emit_vtables : Flag<["-"], "fforce-emit-vtables">, Group<f_Group>,
Flags<[CC1Option]>,
HelpText<"Emits more virtual tables to improve devirtualization">;
def fno_force_emit_vtables : Flag<["-"], "fno-force-emit-vtables">, Group<f_Group>,
Flags<[CoreOption]>;
def fwrapv : Flag<["-"], "fwrapv">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Treat signed integer overflow as two's complement">;
def fwritable_strings : Flag<["-"], "fwritable-strings">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Store string literals as writable data">;
def fzero_initialized_in_bss : Flag<["-"], "fzero-initialized-in-bss">, Group<f_Group>;
def ffunction_sections : Flag<["-"], "ffunction-sections">, Group<f_Group>,
Flags<[CC1Option]>,
HelpText<"Place each function in its own section (ELF Only)">;
def fno_function_sections : Flag<["-"], "fno-function-sections">,
Group<f_Group>, Flags<[CC1Option]>;
def fdata_sections : Flag <["-"], "fdata-sections">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Place each data in its own section (ELF Only)">;
def fno_data_sections : Flag <["-"], "fno-data-sections">, Group<f_Group>,
Flags<[CC1Option]>;
def fstack_size_section : Flag<["-"], "fstack-size-section">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Emit section containing metadata on function stack sizes">;
def fno_stack_size_section : Flag<["-"], "fno-stack-size-section">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Don't emit section containing metadata on function stack sizes">;
def funique_section_names : Flag <["-"], "funique-section-names">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Use unique names for text and data sections (ELF Only)">;
def fno_unique_section_names : Flag <["-"], "fno-unique-section-names">,
Group<f_Group>, Flags<[CC1Option]>;
def fstrict_return : Flag<["-"], "fstrict-return">, Group<f_Group>,
Flags<[CC1Option]>,
HelpText<"Always treat control flow paths that fall off the end of a "
"non-void function as unreachable">;
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>,
Flags<[CC1Option]>;
def fdebug_ranges_base_address: Flag <["-"], "fdebug-ranges-base-address">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Use DWARF base address selection entries in debug_ranges">;
def fno_debug_ranges_base_address: Flag <["-"], "fno-debug-ranges-base-address">, Group<f_Group>,
Flags<[CC1Option]>;
def fsplit_dwarf_inlining: Flag <["-"], "fsplit-dwarf-inlining">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF">;
def fno_split_dwarf_inlining: Flag<["-"], "fno-split-dwarf-inlining">, Group<f_Group>,
Flags<[CC1Option]>;
def fdebug_prefix_map_EQ
: Joined<["-"], "fdebug-prefix-map=">, Group<f_Group>,
Flags<[CC1Option,CC1AsOption]>,
HelpText<"remap file source paths in debug info">;
def g_Flag : Flag<["-"], "g">, Group<g_Group>,
HelpText<"Generate source-level debug information">;
def gline_tables_only : Flag<["-"], "gline-tables-only">, Group<gN_Group>,
Flags<[CoreOption]>, HelpText<"Emit debug line number tables only">;
def gline_directives_only : Flag<["-"], "gline-directives-only">, Group<gN_Group>,
Flags<[CoreOption]>, HelpText<"Emit debug line info directives only">;
def gmlt : Flag<["-"], "gmlt">, Alias<gline_tables_only>;
def g0 : Flag<["-"], "g0">, Group<gN_Group>;
def g1 : Flag<["-"], "g1">, Group<gN_Group>, Alias<gline_tables_only>;
def g2 : Flag<["-"], "g2">, Group<gN_Group>;
def g3 : Flag<["-"], "g3">, Group<gN_Group>;
def ggdb : Flag<["-"], "ggdb">, Group<gTune_Group>;
def ggdb0 : Flag<["-"], "ggdb0">, Group<ggdbN_Group>;
def ggdb1 : Flag<["-"], "ggdb1">, Group<ggdbN_Group>;
def ggdb2 : Flag<["-"], "ggdb2">, Group<ggdbN_Group>;
def ggdb3 : Flag<["-"], "ggdb3">, Group<ggdbN_Group>;
def glldb : Flag<["-"], "glldb">, Group<gTune_Group>;
def gsce : Flag<["-"], "gsce">, Group<gTune_Group>;
def gdwarf_2 : Flag<["-"], "gdwarf-2">, Group<g_Group>,
HelpText<"Generate source-level debug information with dwarf version 2">;
def gdwarf_3 : Flag<["-"], "gdwarf-3">, Group<g_Group>,
HelpText<"Generate source-level debug information with dwarf version 3">;
def gdwarf_4 : Flag<["-"], "gdwarf-4">, Group<g_Group>,
HelpText<"Generate source-level debug information with dwarf version 4">;
def gdwarf_5 : Flag<["-"], "gdwarf-5">, Group<g_Group>,
HelpText<"Generate source-level debug information with dwarf version 5">;
def gcodeview : Flag<["-"], "gcodeview">,
HelpText<"Generate CodeView debug information">,
Flags<[CC1Option, CC1AsOption, CoreOption]>;
def gcodeview_ghash : Flag<["-"], "gcodeview-ghash">,
HelpText<"Emit type record hashes in a .debug$H section">,
Flags<[CC1Option, CoreOption]>;
def gno_codeview_ghash : Flag<["-"], "gno-codeview-ghash">, Flags<[CoreOption]>;
// Equivalent to our default dwarf version. Forces usual dwarf emission when
// CodeView is enabled.
def gdwarf : Flag<["-"], "gdwarf">, Alias<gdwarf_4>, Flags<[CoreOption]>;
def gfull : Flag<["-"], "gfull">, Group<g_Group>;
def gused : Flag<["-"], "gused">, Group<g_Group>;
def gstabs : Joined<["-"], "gstabs">, Group<g_Group>, Flags<[Unsupported]>;
def gcoff : Joined<["-"], "gcoff">, Group<g_Group>, Flags<[Unsupported]>;
def gxcoff : Joined<["-"], "gxcoff">, Group<g_Group>, Flags<[Unsupported]>;
def gvms : Joined<["-"], "gvms">, Group<g_Group>, Flags<[Unsupported]>;
def gtoggle : Flag<["-"], "gtoggle">, Group<g_flags_Group>, Flags<[Unsupported]>;
def grecord_command_line : Flag<["-"], "grecord-command-line">,
Group<g_flags_Group>;
def gno_record_command_line : Flag<["-"], "gno-record-command-line">,
Group<g_flags_Group>;
def : Flag<["-"], "grecord-gcc-switches">, Alias<grecord_command_line>;
def : Flag<["-"], "gno-record-gcc-switches">, Alias<gno_record_command_line>;
def gstrict_dwarf : Flag<["-"], "gstrict-dwarf">, Group<g_flags_Group>;
def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group<g_flags_Group>;
def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>, Flags<[CoreOption]>;
def gno_column_info : Flag<["-"], "gno-column-info">, Group<g_flags_Group>, Flags<[CoreOption]>;
def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>;
def gsplit_dwarf_EQ : Joined<["-"], "gsplit-dwarf=">, Group<g_flags_Group>,
HelpText<"Set DWARF fission mode to either 'split' or 'single'">,
Values<"split,single">;
def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group<g_flags_Group>, Flags<[CC1Option]>;
def gno_gnu_pubnames : Flag<["-"], "gno-gnu-pubnames">, Group<g_flags_Group>, Flags<[CC1Option]>;
def gpubnames : Flag<["-"], "gpubnames">, Group<g_flags_Group>, Flags<[CC1Option]>;
def gno_pubnames : Flag<["-"], "gno-pubnames">, Group<g_flags_Group>, Flags<[CC1Option]>;
def gdwarf_aranges : Flag<["-"], "gdwarf-aranges">, Group<g_flags_Group>;
def gmodules : Flag <["-"], "gmodules">, Group<gN_Group>,
HelpText<"Generate debug info with external references to clang modules"
" or precompiled headers">;
def gz : Flag<["-"], "gz">, Group<g_flags_Group>,
HelpText<"DWARF debug sections compression type">;
def gz_EQ : Joined<["-"], "gz=">, Group<g_flags_Group>,
HelpText<"DWARF debug sections compression type">;
def gembed_source : Flag<["-"], "gembed-source">, Group<g_flags_Group>, Flags<[CC1Option]>,
HelpText<"Embed source text in DWARF debug sections">;
def gno_embed_source : Flag<["-"], "gno-embed-source">, Group<g_flags_Group>,
Flags<[DriverOption]>,
HelpText<"Restore the default behavior of not embedding source text in DWARF debug sections">;
def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">;
def help : Flag<["-", "--"], "help">, Flags<[CC1Option,CC1AsOption]>,
HelpText<"Display available options">;
def index_header_map : Flag<["-"], "index-header-map">, Flags<[CC1Option]>,
HelpText<"Make the next included directory (-I or -F) an indexer header map">;
def idirafter : JoinedOrSeparate<["-"], "idirafter">, Group<clang_i_Group>, Flags<[CC1Option]>,
HelpText<"Add directory to AFTER include search path">;
def iframework : JoinedOrSeparate<["-"], "iframework">, Group<clang_i_Group>, Flags<[CC1Option]>,
HelpText<"Add directory to SYSTEM framework search path">;
def iframeworkwithsysroot : JoinedOrSeparate<["-"], "iframeworkwithsysroot">,
Group<clang_i_Group>,
HelpText<"Add directory to SYSTEM framework search path, "
"absolute paths are relative to -isysroot">,
MetaVarName<"<directory>">, Flags<[CC1Option]>;
def imacros : JoinedOrSeparate<["-", "--"], "imacros">, Group<clang_i_Group>, Flags<[CC1Option]>,
HelpText<"Include macros from file before parsing">, MetaVarName<"<file>">;
def image__base : Separate<["-"], "image_base">;
def include_ : JoinedOrSeparate<["-", "--"], "include">, Group<clang_i_Group>, EnumName<"include">,
MetaVarName<"<file>">, HelpText<"Include file before parsing">, Flags<[CC1Option]>;
def include_pch : Separate<["-"], "include-pch">, Group<clang_i_Group>, Flags<[CC1Option]>,
HelpText<"Include precompiled header file">, MetaVarName<"<file>">;
def relocatable_pch : Flag<["-", "--"], "relocatable-pch">, Flags<[CC1Option]>,
HelpText<"Whether to build a relocatable precompiled header">;
def verify_pch : Flag<["-"], "verify-pch">, Group<Action_Group>, Flags<[CC1Option]>,
HelpText<"Load and verify that a pre-compiled header file is not stale">;
def init : Separate<["-"], "init">;
def install__name : Separate<["-"], "install_name">;
def iprefix : JoinedOrSeparate<["-"], "iprefix">, Group<clang_i_Group>, Flags<[CC1Option]>,
HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">, MetaVarName<"<dir>">;
def iquote : JoinedOrSeparate<["-"], "iquote">, Group<clang_i_Group>, Flags<[CC1Option]>,
HelpText<"Add directory to QUOTE include search path">, MetaVarName<"<directory>">;
def isysroot : JoinedOrSeparate<["-"], "isysroot">, Group<clang_i_Group>, Flags<[CC1Option]>,
HelpText<"Set the system root directory (usually /)">, MetaVarName<"<dir>">;
def isystem : JoinedOrSeparate<["-"], "isystem">, Group<clang_i_Group>,
Flags<[CC1Option]>,
HelpText<"Add directory to SYSTEM include search path">, MetaVarName<"<directory>">;
def isystem_after : JoinedOrSeparate<["-"], "isystem-after">,
Group<clang_i_Group>, Flags<[DriverOption]>, MetaVarName<"<directory>">,
HelpText<"Add directory to end of the SYSTEM include search path">;
def iwithprefixbefore : JoinedOrSeparate<["-"], "iwithprefixbefore">, Group<clang_i_Group>,
HelpText<"Set directory to include search path with prefix">, MetaVarName<"<dir>">,
Flags<[CC1Option]>;
def iwithprefix : JoinedOrSeparate<["-"], "iwithprefix">, Group<clang_i_Group>, Flags<[CC1Option]>,
HelpText<"Set directory to SYSTEM include search path with prefix">, MetaVarName<"<dir>">;
def iwithsysroot : JoinedOrSeparate<["-"], "iwithsysroot">, Group<clang_i_Group>,
HelpText<"Add directory to SYSTEM include search path, "
"absolute paths are relative to -isysroot">, MetaVarName<"<directory>">,
Flags<[CC1Option]>;
def ivfsoverlay : JoinedOrSeparate<["-"], "ivfsoverlay">, Group<clang_i_Group>, Flags<[CC1Option]>,
HelpText<"Overlay the virtual filesystem described by file over the real file system">;
def imultilib : Separate<["-"], "imultilib">, Group<gfortran_Group>;
def keep__private__externs : Flag<["-"], "keep_private_externs">;
def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>,
Group<Link_Group>;
def lazy__framework : Separate<["-"], "lazy_framework">, Flags<[LinkerInput]>;
def lazy__library : Separate<["-"], "lazy_library">, Flags<[LinkerInput]>;
def mlittle_endian : Flag<["-"], "mlittle-endian">, Flags<[DriverOption]>;
def EL : Flag<["-"], "EL">, Alias<mlittle_endian>;
def mbig_endian : Flag<["-"], "mbig-endian">, Flags<[DriverOption]>;
def EB : Flag<["-"], "EB">, Alias<mbig_endian>;
def m16 : Flag<["-"], "m16">, Group<m_Group>, Flags<[DriverOption, CoreOption]>;
def m32 : Flag<["-"], "m32">, Group<m_Group>, Flags<[DriverOption, CoreOption]>;
def mqdsp6_compat : Flag<["-"], "mqdsp6-compat">, Group<m_Group>, Flags<[DriverOption,CC1Option]>,
HelpText<"Enable hexagon-qdsp6 backward compatibility">;
def m64 : Flag<["-"], "m64">, Group<m_Group>, Flags<[DriverOption, CoreOption]>;
def mx32 : Flag<["-"], "mx32">, Group<m_Group>, Flags<[DriverOption, CoreOption]>;
def mabi_EQ : Joined<["-"], "mabi=">, Group<m_Group>;
def miamcu : Flag<["-"], "miamcu">, Group<m_Group>, Flags<[DriverOption, CoreOption]>,
HelpText<"Use Intel MCU ABI">;
def mno_iamcu : Flag<["-"], "mno-iamcu">, Group<m_Group>, Flags<[DriverOption, CoreOption]>;
def malign_functions_EQ : Joined<["-"], "malign-functions=">, Group<clang_ignored_m_Group>;
def malign_loops_EQ : Joined<["-"], "malign-loops=">, Group<clang_ignored_m_Group>;
def malign_jumps_EQ : Joined<["-"], "malign-jumps=">, Group<clang_ignored_m_Group>;
def mfancy_math_387 : Flag<["-"], "mfancy-math-387">, Group<clang_ignored_m_Group>;
def mlong_calls : Flag<["-"], "mlong-calls">, Group<m_Group>,
HelpText<"Generate branches with extended addressability, usually via indirect jumps.">;
def mno_long_calls : Flag<["-"], "mno-long-calls">, Group<m_Group>,
HelpText<"Restore the default behaviour of not generating long calls">;
def mexecute_only : Flag<["-"], "mexecute-only">, Group<m_arm_Features_Group>,
HelpText<"Disallow generation of data access to code sections (ARM only)">;
def mno_execute_only : Flag<["-"], "mno-execute-only">, Group<m_arm_Features_Group>,
HelpText<"Allow generation of data access to code sections (ARM only)">;
def mtp_mode_EQ : Joined<["-"], "mtp=">, Group<m_arm_Features_Group>, Values<"soft, cp15">,
HelpText<"Read thread pointer from coprocessor register (ARM only)">;
def mpure_code : Flag<["-"], "mpure-code">, Alias<mexecute_only>; // Alias for GCC compatibility
def mno_pure_code : Flag<["-"], "mno-pure-code">, Alias<mno_execute_only>;
def mtvos_version_min_EQ : Joined<["-"], "mtvos-version-min=">, Group<m_Group>;
def mappletvos_version_min_EQ : Joined<["-"], "mappletvos-version-min=">, Alias<mtvos_version_min_EQ>;
def mtvos_simulator_version_min_EQ : Joined<["-"], "mtvos-simulator-version-min=">;
def mappletvsimulator_version_min_EQ : Joined<["-"], "mappletvsimulator-version-min=">, Alias<mtvos_simulator_version_min_EQ>;
def mwatchos_version_min_EQ : Joined<["-"], "mwatchos-version-min=">, Group<m_Group>;
def mwatchos_simulator_version_min_EQ : Joined<["-"], "mwatchos-simulator-version-min=">;
def mwatchsimulator_version_min_EQ : Joined<["-"], "mwatchsimulator-version-min=">, Alias<mwatchos_simulator_version_min_EQ>;
def march_EQ : Joined<["-"], "march=">, Group<m_Group>, Flags<[CoreOption]>;
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]>;
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>;
def minline_all_stringops : Flag<["-"], "minline-all-stringops">, Group<clang_ignored_m_Group>;
def mno_inline_all_stringops : Flag<["-"], "mno-inline-all-stringops">, Group<clang_ignored_m_Group>;
def malign_double : Flag<["-"], "malign-double">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Align doubles to two words in structs (x86 only)">;
def mfloat_abi_EQ : Joined<["-"], "mfloat-abi=">, Group<m_Group>, Values<"soft,softfp,hard">;
def mfpmath_EQ : Joined<["-"], "mfpmath=">, Group<m_Group>;
def mfpu_EQ : Joined<["-"], "mfpu=">, Group<m_Group>;
def mhwdiv_EQ : Joined<["-"], "mhwdiv=">, Group<m_Group>;
def mhwmult_EQ : Joined<["-"], "mhwmult=">, Group<m_Group>;
def mglobal_merge : Flag<["-"], "mglobal-merge">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Enable merging of globals">;
def mhard_float : Flag<["-"], "mhard-float">, Group<m_Group>;
def miphoneos_version_min_EQ : Joined<["-"], "miphoneos-version-min=">, Group<m_Group>;
def mios_version_min_EQ : Joined<["-"], "mios-version-min=">,
Alias<miphoneos_version_min_EQ>, HelpText<"Set iOS deployment target">;
def mios_simulator_version_min_EQ : Joined<["-"], "mios-simulator-version-min=">;
def miphonesimulator_version_min_EQ : Joined<["-"], "miphonesimulator-version-min=">, Alias<mios_simulator_version_min_EQ>;
def mkernel : Flag<["-"], "mkernel">, Group<m_Group>;
def mlinker_version_EQ : Joined<["-"], "mlinker-version=">,
Flags<[DriverOption]>;
def mllvm : Separate<["-"], "mllvm">, Flags<[CC1Option,CC1AsOption,CoreOption]>,
HelpText<"Additional arguments to forward to LLVM's option processing">;
def mmacosx_version_min_EQ : Joined<["-"], "mmacosx-version-min=">,
Group<m_Group>, HelpText<"Set Mac OS X deployment target">;
def mmacos_version_min_EQ : Joined<["-"], "mmacos-version-min=">,
Group<m_Group>, Alias<mmacosx_version_min_EQ>;
def mms_bitfields : Flag<["-"], "mms-bitfields">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard">;
def moutline : Flag<["-"], "moutline">, Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Enable function outlining (AArch64 only)">;
def mno_outline : Flag<["-"], "mno-outline">, Group<f_clang_Group>, Flags<[CC1Option]>,
HelpText<"Disable function outlining (AArch64 only)">;
def mno_ms_bitfields : Flag<["-"], "mno-ms-bitfields">, Group<m_Group>,
HelpText<"Do not set the default structure layout to be compatible with the Microsoft compiler standard">;
def mstackrealign : Flag<["-"], "mstackrealign">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Force realign the stack at entry to every function">;
def mstack_alignment : Joined<["-"], "mstack-alignment=">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Set the stack alignment">;
def mstack_probe_size : Joined<["-"], "mstack-probe-size=">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Set the stack probe size">;
def mstack_arg_probe : Flag<["-"], "mstack-arg-probe">, Group<m_Group>,
HelpText<"Enable stack probes">;
def mno_stack_arg_probe : Flag<["-"], "mno-stack-arg-probe">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Disable stack probes which are enabled by default">;
def mthread_model : Separate<["-"], "mthread-model">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"The thread model to use, e.g. posix, single (posix by default)">, Values<"posix,single">;
def meabi : Separate<["-"], "meabi">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Set EABI type, e.g. 4, 5 or gnu (default depends on triple)">, Values<"default,4,5,gnu">;
def mno_constant_cfstrings : Flag<["-"], "mno-constant-cfstrings">, Group<m_Group>;
def mno_global_merge : Flag<["-"], "mno-global-merge">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Disable merging of globals">;
def mno_pascal_strings : Flag<["-"], "mno-pascal-strings">,
Alias<fno_pascal_strings>;
def mno_red_zone : Flag<["-"], "mno-red-zone">, Group<m_Group>;
def mno_tls_direct_seg_refs : Flag<["-"], "mno-tls-direct-seg-refs">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Disable direct TLS access through segment registers">;
def mno_relax_all : Flag<["-"], "mno-relax-all">, Group<m_Group>;
def mno_rtd: Flag<["-"], "mno-rtd">, Group<m_Group>;
def mno_soft_float : Flag<["-"], "mno-soft-float">, Group<m_Group>;
def mno_stackrealign : Flag<["-"], "mno-stackrealign">, Group<m_Group>;
def mretpoline : Flag<["-"], "mretpoline">, Group<m_Group>, Flags<[CoreOption,DriverOption]>;
def mno_retpoline : Flag<["-"], "mno-retpoline">, Group<m_Group>, Flags<[CoreOption,DriverOption]>;
def mspeculative_load_hardening : Flag<["-"], "mspeculative-load-hardening">,
Group<m_Group>, Flags<[CoreOption,CC1Option]>;
def mno_speculative_load_hardening : Flag<["-"], "mno-speculative-load-hardening">,
Group<m_Group>, Flags<[CoreOption]>;
def mrelax : Flag<["-"], "mrelax">, Group<m_riscv_Features_Group>,
HelpText<"Enable linker relaxation">;
def mno_relax : Flag<["-"], "mno-relax">, Group<m_riscv_Features_Group>,
HelpText<"Disable linker relaxation">;
def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>,
HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">;
def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group<m_arm_Features_Group>,
HelpText<"Force all memory accesses to be aligned (AArch32/AArch64 only)">;
def mstrict_align : Flag<["-"], "mstrict-align">, Alias<mno_unaligned_access>, Flags<[CC1Option,HelpHidden]>,
HelpText<"Force all memory accesses to be aligned (same as mno-unaligned-access)">;
def mno_thumb : Flag<["-"], "mno-thumb">, Group<m_arm_Features_Group>;
def mrestrict_it: Flag<["-"], "mrestrict-it">, Group<m_arm_Features_Group>,
HelpText<"Disallow generation of deprecated IT blocks for ARMv8. It is on by default for ARMv8 Thumb mode.">;
def mno_restrict_it: Flag<["-"], "mno-restrict-it">, Group<m_arm_Features_Group>,
HelpText<"Allow generation of deprecated IT blocks for ARMv8. It is off by default for ARMv8 Thumb mode">;
def marm : Flag<["-"], "marm">, Alias<mno_thumb>;
def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group<m_arm_Features_Group>,
HelpText<"Reserve the r9 register (ARM only)">;
def mno_movt : Flag<["-"], "mno-movt">, Group<m_arm_Features_Group>,
HelpText<"Disallow use of movt/movw pairs (ARM only)">;
def mcrc : Flag<["-"], "mcrc">, Group<m_Group>,
HelpText<"Allow use of CRC instructions (ARM/Mips only)">;
def mnocrc : Flag<["-"], "mnocrc">, Group<m_arm_Features_Group>,
HelpText<"Disallow use of CRC instructions (ARM only)">;
def mno_neg_immediates: Flag<["-"], "mno-neg-immediates">, Group<m_arm_Features_Group>,
HelpText<"Disallow converting instructions with negative immediates to their negation or inversion.">;
def mgeneral_regs_only : Flag<["-"], "mgeneral-regs-only">, Group<m_aarch64_Features_Group>,
HelpText<"Generate code which only uses the general purpose registers (AArch64 only)">;
def mfix_cortex_a53_835769 : Flag<["-"], "mfix-cortex-a53-835769">,
Group<m_aarch64_Features_Group>,
HelpText<"Workaround Cortex-A53 erratum 835769 (AArch64 only)">;
def mno_fix_cortex_a53_835769 : Flag<["-"], "mno-fix-cortex-a53-835769">,
Group<m_aarch64_Features_Group>,
HelpText<"Don't workaround Cortex-A53 erratum 835769 (AArch64 only)">;
foreach i = {1-7,18,20} in
def ffixed_x#i : Flag<["-"], "ffixed-x"#i>, Group<m_aarch64_Features_Group>,
HelpText<"Reserve the "#i#" register (AArch64 only)">;
foreach i = {8-15,18} in
def fcall_saved_x#i : Flag<["-"], "fcall-saved-x"#i>, Group<m_aarch64_Features_Group>,
HelpText<"Make the x"#i#" register call-saved (AArch64 only)">;
def msign_return_address_EQ : Joined<["-"], "msign-return-address=">,
Flags<[CC1Option]>, Group<m_Group>, Values<"none,all,non-leaf">,
HelpText<"Select return address signing scope">;
def mbranch_protection_EQ : Joined<["-"], "mbranch-protection=">,
HelpText<"Enforce targets of indirect branches and function returns">;
def msimd128 : Flag<["-"], "msimd128">, Group<m_wasm_Features_Group>;
def munimplemented_simd128 : Flag<["-"], "munimplemented-simd128">, Group<m_wasm_Features_Group>;
def mno_unimplemented_simd128 : Flag<["-"], "mno-unimplemented-simd128">, Group<m_wasm_Features_Group>;
def mno_simd128 : Flag<["-"], "mno-simd128">, Group<m_wasm_Features_Group>;
def mnontrapping_fptoint : Flag<["-"], "mnontrapping-fptoint">, Group<m_wasm_Features_Group>;
def mno_nontrapping_fptoint : Flag<["-"], "mno-nontrapping-fptoint">, Group<m_wasm_Features_Group>;
def msign_ext : Flag<["-"], "msign-ext">, Group<m_wasm_Features_Group>;
def mno_sign_ext : Flag<["-"], "mno-sign-ext">, Group<m_wasm_Features_Group>;
def mexception_handing : Flag<["-"], "mexception-handling">, Group<m_wasm_Features_Group>;
def mno_exception_handing : Flag<["-"], "mno-exception-handling">, Group<m_wasm_Features_Group>;
def mamdgpu_debugger_abi : Joined<["-"], "mamdgpu-debugger-abi=">,
Flags<[HelpHidden]>,
Group<m_Group>,
HelpText<"Generate additional code for specified <version> of debugger ABI (AMDGPU only)">,
MetaVarName<"<version>">;
def mcode_object_v3 : Flag<["-"], "mcode-object-v3">, Group<m_amdgpu_Features_Group>,
HelpText<"Enable code object v3 (AMDGPU only)">;
def mno_code_object_v3 : Flag<["-"], "mno-code-object-v3">, Group<m_amdgpu_Features_Group>,
HelpText<"Disable code object v3 (AMDGPU only)">;
def mxnack : Flag<["-"], "mxnack">, Group<m_amdgpu_Features_Group>,
HelpText<"Enable XNACK (AMDGPU only)">;
def mno_xnack : Flag<["-"], "mno-xnack">, Group<m_amdgpu_Features_Group>,
HelpText<"Disable XNACK (AMDGPU only)">;
def msram_ecc : Flag<["-"], "msram-ecc">, Group<m_amdgpu_Features_Group>,
HelpText<"Enable SRAM ECC (AMDGPU only)">;
def mno_sram_ecc : Flag<["-"], "mno-sram-ecc">, Group<m_amdgpu_Features_Group>,
HelpText<"Disable SRAM ECC (AMDGPU only)">;
def faltivec : Flag<["-"], "faltivec">, Group<f_Group>, Flags<[DriverOption]>;
def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>, Flags<[DriverOption]>;
def maltivec : Flag<["-"], "maltivec">, Group<m_ppc_Features_Group>;
def mno_altivec : Flag<["-"], "mno-altivec">, Group<m_ppc_Features_Group>;
def mvsx : Flag<["-"], "mvsx">, Group<m_ppc_Features_Group>;
def mno_vsx : Flag<["-"], "mno-vsx">, Group<m_ppc_Features_Group>;
def msecure_plt : Flag<["-"], "msecure-plt">, Group<m_ppc_Features_Group>;
def mpower8_vector : Flag<["-"], "mpower8-vector">,
Group<m_ppc_Features_Group>;
def mno_power8_vector : Flag<["-"], "mno-power8-vector">,
Group<m_ppc_Features_Group>;
def mpower9_vector : Flag<["-"], "mpower9-vector">,
Group<m_ppc_Features_Group>;
def mno_power9_vector : Flag<["-"], "mno-power9-vector">,
Group<m_ppc_Features_Group>;
def mpower8_crypto : Flag<["-"], "mcrypto">,
Group<m_ppc_Features_Group>;
def mnopower8_crypto : Flag<["-"], "mno-crypto">,
Group<m_ppc_Features_Group>;
def mdirect_move : Flag<["-"], "mdirect-move">,
Group<m_ppc_Features_Group>;
def mnodirect_move : Flag<["-"], "mno-direct-move">,
Group<m_ppc_Features_Group>;
def mhtm : Flag<["-"], "mhtm">, Group<m_ppc_Features_Group>;
def mno_htm : Flag<["-"], "mno-htm">, Group<m_ppc_Features_Group>;
def mfprnd : Flag<["-"], "mfprnd">, Group<m_ppc_Features_Group>;
def mno_fprnd : Flag<["-"], "mno-fprnd">, Group<m_ppc_Features_Group>;
def mcmpb : Flag<["-"], "mcmpb">, Group<m_ppc_Features_Group>;
def mno_cmpb : Flag<["-"], "mno-cmpb">, Group<m_ppc_Features_Group>;
def misel : Flag<["-"], "misel">, Group<m_ppc_Features_Group>;
def mno_isel : Flag<["-"], "mno-isel">, Group<m_ppc_Features_Group>;
def mmfocrf : Flag<["-"], "mmfocrf">, Group<m_ppc_Features_Group>;
def mmfcrf : Flag<["-"], "mmfcrf">, Alias<mmfocrf>;
def mno_mfocrf : Flag<["-"], "mno-mfocrf">, Group<m_ppc_Features_Group>;
def mno_mfcrf : Flag<["-"], "mno-mfcrf">, Alias<mno_mfocrf>;
def mpopcntd : Flag<["-"], "mpopcntd">, Group<m_ppc_Features_Group>;
def mno_popcntd : Flag<["-"], "mno-popcntd">, Group<m_ppc_Features_Group>;
def mqpx : Flag<["-"], "mqpx">, Group<m_ppc_Features_Group>;
def mno_qpx : Flag<["-"], "mno-qpx">, Group<m_ppc_Features_Group>;
def mcrbits : Flag<["-"], "mcrbits">, Group<m_ppc_Features_Group>;
def mno_crbits : Flag<["-"], "mno-crbits">, Group<m_ppc_Features_Group>;
def minvariant_function_descriptors :
Flag<["-"], "minvariant-function-descriptors">, Group<m_ppc_Features_Group>;
def mno_invariant_function_descriptors :
Flag<["-"], "mno-invariant-function-descriptors">,
Group<m_ppc_Features_Group>;
def mfloat128: Flag<["-"], "mfloat128">,
Group<m_ppc_Features_Group>;
def mno_float128 : Flag<["-"], "mno-float128">,
Group<m_ppc_Features_Group>;
def mlongcall: Flag<["-"], "mlongcall">,
Group<m_ppc_Features_Group>;
def mno_longcall : Flag<["-"], "mno-longcall">,
Group<m_ppc_Features_Group>;
def mvx : Flag<["-"], "mvx">, Group<m_Group>;
def mno_vx : Flag<["-"], "mno-vx">, Group<m_Group>;
def fzvector : Flag<["-"], "fzvector">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Enable System z vector language extension">;
def fno_zvector : Flag<["-"], "fno-zvector">, Group<f_Group>,
Flags<[CC1Option]>;
def mzvector : Flag<["-"], "mzvector">, Alias<fzvector>;
def mno_zvector : Flag<["-"], "mno-zvector">, Alias<fno_zvector>;
def mbackchain : Flag<["-"], "mbackchain">, Group<m_Group>, Flags<[DriverOption,CC1Option]>,
HelpText<"Link stack frames through backchain on System Z">;
def mno_backchain : Flag<["-"], "mno-backchain">, Group<m_Group>, Flags<[DriverOption,CC1Option]>;
def mno_warn_nonportable_cfstrings : Flag<["-"], "mno-warn-nonportable-cfstrings">, Group<m_Group>;
def mno_omit_leaf_frame_pointer : Flag<["-"], "mno-omit-leaf-frame-pointer">, Group<m_Group>;
def momit_leaf_frame_pointer : Flag<["-"], "momit-leaf-frame-pointer">, Group<m_Group>,
HelpText<"Omit frame pointer setup for leaf functions">, Flags<[CC1Option]>;
def moslib_EQ : Joined<["-"], "moslib=">, Group<m_Group>;
def mpascal_strings : Flag<["-"], "mpascal-strings">, Alias<fpascal_strings>;
def mred_zone : Flag<["-"], "mred-zone">, Group<m_Group>;
def mtls_direct_seg_refs : Flag<["-"], "mtls-direct-seg-refs">, Group<m_Group>,
HelpText<"Enable direct TLS access through segment registers (default)">;
def mregparm_EQ : Joined<["-"], "mregparm=">, Group<m_Group>;
def mrelax_all : Flag<["-"], "mrelax-all">, Group<m_Group>, Flags<[CC1Option,CC1AsOption]>,
HelpText<"(integrated-as) Relax all machine instructions">;
def mincremental_linker_compatible : Flag<["-"], "mincremental-linker-compatible">, Group<m_Group>,
Flags<[CC1Option,CC1AsOption]>,
HelpText<"(integrated-as) Emit an object file which can be used with an incremental linker">;
def mno_incremental_linker_compatible : Flag<["-"], "mno-incremental-linker-compatible">, Group<m_Group>,
HelpText<"(integrated-as) Emit an object file which cannot be used with an incremental linker">;
def mrtd : Flag<["-"], "mrtd">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Make StdCall calling convention the default">;
def msmall_data_threshold_EQ : Joined <["-"], "msmall-data-threshold=">,
Group<m_Group>, Alias<G>;
def msoft_float : Flag<["-"], "msoft-float">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Use software floating point">;
def mno_implicit_float : Flag<["-"], "mno-implicit-float">, Group<m_Group>,
HelpText<"Don't generate implicit floating point instructions">;
def mimplicit_float : Flag<["-"], "mimplicit-float">, Group<m_Group>;
def mrecip : Flag<["-"], "mrecip">, Group<m_Group>;
def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group<m_Group>, Flags<[CC1Option]>;
def mprefer_vector_width_EQ : Joined<["-"], "mprefer-vector-width=">, Group<m_Group>, Flags<[CC1Option]>,
HelpText<"Specifies preferred vector width for auto-vectorization. Defaults to 'none' which allows target specific decisions.">;
def mpie_copy_relocations : Flag<["-"], "mpie-copy-relocations">, Group<m_Group>,
Flags<[CC1Option]>,
HelpText<"Use copy relocations support for PIE builds">;
def mno_pie_copy_relocations : Flag<["-"], "mno-pie-copy-relocations">, Group<m_Group>;
def mfentry : Flag<["-"], "mfentry">, HelpText<"Insert calls to fentry at function entry (x86 only)">,
Flags<[CC1Option]>, Group<m_Group>;
def mips16 : Flag<["-"], "mips16">, Group<m_mips_Features_Group>;
def mno_mips16 : Flag<["-"], "mno-mips16">, Group<m_mips_Features_Group>;
def mmicromips : Flag<["-"], "mmicromips">, Group<m_mips_Features_Group>;
def mno_micromips : Flag<["-"], "mno-micromips">, Group<m_mips_Features_Group>;
def mxgot : Flag<["-"], "mxgot">, Group<m_mips_Features_Group>;
def mno_xgot : Flag<["-"], "mno-xgot">, Group<m_mips_Features_Group>;
def mldc1_sdc1 : Flag<["-"], "mldc1-sdc1">, Group<m_mips_Features_Group>;
def mno_ldc1_sdc1 : Flag<["-"], "mno-ldc1-sdc1">, Group<m_mips_Features_Group>;
def mcheck_zero_division : Flag<["-"], "mcheck-zero-division">,
Group<m_mips_Features_Group>;
def mno_check_zero_division : Flag<["-"], "mno-check-zero-division">,
Group<m_mips_Features_Group>;
def mcompact_branches_EQ : Joined<["-"], "mcompact-branches=">,
Group<m_mips_Features_Group>;
def mbranch_likely : Flag<["-"], "mbranch-likely">, Group<m_Group>,
IgnoredGCCCompat;
def mno_branch_likely : Flag<["-"], "mno-branch-likely">, Group<m_Group>,
IgnoredGCCCompat;
def mindirect_jump_EQ : Joined<["-"], "mindirect-jump=">,
Group<m_mips_Features_Group>,
HelpText<"Change indirect jump instructions to inhibit speculation">;
def mdsp : Flag<["-"], "mdsp">, Group<m_mips_Features_Group>;
def mno_dsp : Flag<["-"], "mno-dsp">, Group<m_mips_Features_Group>;
def mdspr2 : Flag<["-"], "mdspr2">, Group<m_mips_Features_Group>;
def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group<m_mips_Features_Group>;
def msingle_float : Flag<["-"], "msingle-float">, Group<m_mips_Features_Group>;
def mdouble_float : Flag<["-"], "mdouble-float">, Group<m_mips_Features_Group>;
def mmadd4 : Flag<["-"], "mmadd4">, Group<m_mips_Features_Group>,
HelpText<"Enable the generation of 4-operand madd.s, madd.d and related instructions.">;
def mno_madd4 : Flag<["-"], "mno-madd4">, Group<m_mips_Features_Group>,
HelpText<"Disable the generation of 4-operand madd.s, madd.d and related instructions.">;
def mmsa : Flag<["-"], "mmsa">, Group<m_mips_Features_Group>,
HelpText<"Enable MSA ASE (MIPS only)">;
def mno_msa : Flag<["-"], "mno-msa">, Group<m_mips_Features_Group>,
HelpText<"Disable MSA ASE (MIPS only)">;
def mmt : Flag<["-"], "mmt">, Group<m_mips_Features_Group>,
HelpText<"Enable MT ASE (MIPS only)">;
def mno_mt : Flag<["-"], "mno-mt">, Group<m_mips_Features_Group>,
HelpText<"Disable MT ASE (MIPS only)">;
def mfp64 : Flag<["-"], "mfp64">, Group<m_mips_Features_Group>,
HelpText<"Use 64-bit floating point registers (MIPS only)">;
def mfp32 : Flag<["-"], "mfp32">, Group<m_mips_Features_Group>,
HelpText<"Use 32-bit floating point registers (MIPS only)">;
def mgpopt : Flag<["-"], "mgpopt">, Group<m_mips_Features_Group>,
HelpText<"Use GP relative accesses for symbols known to be in a small"
" data section (MIPS)">;
def mno_gpopt : Flag<["-"], "mno-gpopt">, Group<m_mips_Features_Group>,
HelpText<"Do not use GP relative accesses for symbols known to be in a small"
" data section (MIPS)">;
def mlocal_sdata : Flag<["-"], "mlocal-sdata">,
Group<m_mips_Features_Group>,
HelpText<"Extend the -G behaviour to object local data (MIPS)">;
def mno_local_sdata : Flag<["-"], "mno-local-sdata">,
Group<m_mips_Features_Group>,
HelpText<"Do not extend the -G behaviour to object local data (MIPS)">;
def mextern_sdata : Flag<["-"], "mextern-sdata">,
Group<m_mips_Features_Group>,
HelpText<"Assume that externally defined data is in the small data if it"
" meets the -G <size> threshold (MIPS)">;
def mno_extern_sdata : Flag<["-"], "mno-extern-sdata">,
Group<m_mips_Features_Group>,
HelpText<"Do not assume that externally defined data is in the small data if"
" it meets the -G <size> threshold (MIPS)">;
def membedded_data : Flag<["-"], "membedded-data">,
Group<m_mips_Features_Group>,
HelpText<"Place constants in the .rodata section instead of the .sdata "
"section even if they meet the -G <size> threshold (MIPS)">;
def mno_embedded_data : Flag<["-"], "mno-embedded-data">,
Group<m_mips_Features_Group>,
HelpText<"Do not place constants in the .rodata section instead of the "
".sdata if they meet the -G <size> threshold (MIPS)">;
def mnan_EQ : Joined<["-"], "mnan=">, Group<m_mips_Features_Group>;
def mabs_EQ : Joined<["-"], "mabs=">, Group<m_mips_Features_Group>;
def mabicalls : Flag<["-"], "mabicalls">, Group<m_mips_Features_Group>,
HelpText<"Enable SVR4-style position-independent code (Mips only)">;
def mno_abicalls : Flag<["-"], "mno-abicalls">, Group<m_mips_Features_Group>,
HelpText<"Disable SVR4-style position-independent code (Mips only)">;
def mno_crc : Flag<["-"], "mno-crc">, Group<m_mips_Features_Group>,
HelpText<"Disallow use of CRC instructions (Mips only)">;
def mvirt : Flag<["-"], "mvirt">, Group<m_mips_Features_Group>;
def mno_virt : Flag<["-"], "mno-virt">, Group<m_mips_Features_Group>;
def mginv : Flag<["-"], "mginv">, Group<m_mips_Features_Group>;
def mno_ginv : Flag<["-"], "mno-ginv">, Group<m_mips_Features_Group>;
def mips1 : Flag<["-"], "mips1">,
Alias<march_EQ>, AliasArgs<["mips1"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips1">, Flags<[HelpHidden]>;
def mips2 : Flag<["-"], "mips2">,
Alias<march_EQ>, AliasArgs<["mips2"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips2">, Flags<[HelpHidden]>;
def mips3 : Flag<["-"], "mips3">,
Alias<march_EQ>, AliasArgs<["mips3"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips3">, Flags<[HelpHidden]>;
def mips4 : Flag<["-"], "mips4">,
Alias<march_EQ>, AliasArgs<["mips4"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips4">, Flags<[HelpHidden]>;
def mips5 : Flag<["-"], "mips5">,
Alias<march_EQ>, AliasArgs<["mips5"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips5">, Flags<[HelpHidden]>;
def mips32 : Flag<["-"], "mips32">,
Alias<march_EQ>, AliasArgs<["mips32"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips32">, Flags<[HelpHidden]>;
def mips32r2 : Flag<["-"], "mips32r2">,
Alias<march_EQ>, AliasArgs<["mips32r2"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips32r2">, Flags<[HelpHidden]>;
def mips32r3 : Flag<["-"], "mips32r3">,
Alias<march_EQ>, AliasArgs<["mips32r3"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips32r3">, Flags<[HelpHidden]>;
def mips32r5 : Flag<["-"], "mips32r5">,
Alias<march_EQ>, AliasArgs<["mips32r5"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips32r5">, Flags<[HelpHidden]>;
def mips32r6 : Flag<["-"], "mips32r6">,
Alias<march_EQ>, AliasArgs<["mips32r6"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips32r6">, Flags<[HelpHidden]>;
def mips64 : Flag<["-"], "mips64">,
Alias<march_EQ>, AliasArgs<["mips64"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips64">, Flags<[HelpHidden]>;
def mips64r2 : Flag<["-"], "mips64r2">,
Alias<march_EQ>, AliasArgs<["mips64r2"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips64r2">, Flags<[HelpHidden]>;
def mips64r3 : Flag<["-"], "mips64r3">,
Alias<march_EQ>, AliasArgs<["mips64r3"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips64r3">, Flags<[HelpHidden]>;
def mips64r5 : Flag<["-"], "mips64r5">,
Alias<march_EQ>, AliasArgs<["mips64r5"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips64r5">, Flags<[HelpHidden]>;
def mips64r6 : Flag<["-"], "mips64r6">,
Alias<march_EQ>, AliasArgs<["mips64r6"]>, Group<m_mips_Features_Group>,
HelpText<"Equivalent to -march=mips64r6">, Flags<[HelpHidden]>;
def mfpxx : Flag<["-"], "mfpxx">, Group<m_mips_Features_Group>,
HelpText<"Avoid FPU mode dependent operations when used with the O32 ABI">,
Flags<[HelpHidden]>;
def modd_spreg : Flag<["-"], "modd-spreg">, Group<m_mips_Features_Group>,
HelpText<"Enable odd single-precision floating point registers">,
Flags<[HelpHidden]>;
def mno_odd_spreg : Flag<["-"], "mno-odd-spreg">, Group<m_mips_Features_Group>,
HelpText<"Disable odd single-precision floating point registers">,
Flags<[HelpHidden]>;
+def mrelax_pic_calls : Flag<["-"], "mrelax-pic-calls">,
+ Group<m_mips_Features_Group>,
+ HelpText<"Try turning PIC calls (j{al}r{c} $25) into direct calls "
+ "(MIPS only)">, Flags<[HelpHidden]>;
+def mno_relax_pic_calls : Flag<["-"], "mno-relax-pic-calls">,
+ Group<m_mips_Features_Group>,
+ HelpText<"Do not try turning PIC calls (j{al}r{c} $25) into direct calls "
+ "(MIPS only)">, Flags<[HelpHidden]>;
def mglibc : Flag<["-"], "mglibc">, Group<m_libc_Group>, Flags<[HelpHidden]>;
def muclibc : Flag<["-"], "muclibc">, Group<m_libc_Group>, Flags<[HelpHidden]>;
def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>,
HelpText<"Provide information about a particular module file">;
def mthumb : Flag<["-"], "mthumb">, Group<m_Group>;
def mtune_EQ : Joined<["-"], "mtune=">, Group<m_Group>;
def multi__module : Flag<["-"], "multi_module">;
def multiply__defined__unused : Separate<["-"], "multiply_defined_unused">;
def multiply__defined : Separate<["-"], "multiply_defined">;
def mwarn_nonportable_cfstrings : Flag<["-"], "mwarn-nonportable-cfstrings">, Group<m_Group>;
def no_canonical_prefixes : Flag<["-"], "no-canonical-prefixes">, Flags<[HelpHidden, CoreOption]>,
HelpText<"Use relative instead of canonical paths">;
def no_cpp_precomp : Flag<["-"], "no-cpp-precomp">, Group<clang_ignored_f_Group>;
def no_integrated_cpp : Flag<["-", "--"], "no-integrated-cpp">, Flags<[DriverOption]>;
def no_pedantic : Flag<["-", "--"], "no-pedantic">, Group<pedantic_Group>;
def no__dead__strip__inits__and__terms : Flag<["-"], "no_dead_strip_inits_and_terms">;
def nobuiltininc : Flag<["-"], "nobuiltininc">, Flags<[CC1Option, CoreOption]>,
HelpText<"Disable builtin #include directories">;
def nocudainc : Flag<["-"], "nocudainc">;
def nocudalib : Flag<["-"], "nocudalib">;
def nodefaultlibs : Flag<["-"], "nodefaultlibs">;
def nofixprebinding : Flag<["-"], "nofixprebinding">;
def nolibc : Flag<["-"], "nolibc">;
def nomultidefs : Flag<["-"], "nomultidefs">;
def nopie : Flag<["-"], "nopie">;
def no_pie : Flag<["-"], "no-pie">, Alias<nopie>;
def noprebind : Flag<["-"], "noprebind">;
def noseglinkedit : Flag<["-"], "noseglinkedit">;
def nostartfiles : Flag<["-"], "nostartfiles">;
def nostdinc : Flag<["-"], "nostdinc">, Flags<[CoreOption]>;
def nostdlibinc : Flag<["-"], "nostdlibinc">;
def nostdincxx : Flag<["-"], "nostdinc++">, Flags<[CC1Option]>,
HelpText<"Disable standard #include directories for the C++ standard library">;
def nostdlib : Flag<["-"], "nostdlib">;
def nostdlibxx : Flag<["-"], "nostdlib++">;
def object : Flag<["-"], "object">;
def o : JoinedOrSeparate<["-"], "o">, Flags<[DriverOption, RenderAsInput, CC1Option, CC1AsOption]>,
HelpText<"Write output to <file>">, MetaVarName<"<file>">;
def pagezero__size : JoinedOrSeparate<["-"], "pagezero_size">;
def pass_exit_codes : Flag<["-", "--"], "pass-exit-codes">, Flags<[Unsupported]>;
def pedantic_errors : Flag<["-", "--"], "pedantic-errors">, Group<pedantic_Group>, Flags<[CC1Option]>;
def pedantic : Flag<["-", "--"], "pedantic">, Group<pedantic_Group>, Flags<[CC1Option]>;
def pg : Flag<["-"], "pg">, HelpText<"Enable mcount instrumentation">, Flags<[CC1Option]>;
def pipe : Flag<["-", "--"], "pipe">,
HelpText<"Use pipes between commands, when possible">;
def prebind__all__twolevel__modules : Flag<["-"], "prebind_all_twolevel_modules">;
def prebind : Flag<["-"], "prebind">;
def preload : Flag<["-"], "preload">;
def print_file_name_EQ : Joined<["-", "--"], "print-file-name=">,
HelpText<"Print the full library path of <file>">, MetaVarName<"<file>">;
def print_ivar_layout : Flag<["-"], "print-ivar-layout">, Flags<[CC1Option]>,
HelpText<"Enable Objective-C Ivar layout bitmap print trace">;
def print_libgcc_file_name : Flag<["-", "--"], "print-libgcc-file-name">,
HelpText<"Print the library path for the currently used compiler runtime "
"library (\"libgcc.a\" or \"libclang_rt.builtins.*.a\")">;
def print_multi_directory : Flag<["-", "--"], "print-multi-directory">;
def print_multi_lib : Flag<["-", "--"], "print-multi-lib">;
def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
Flags<[Unsupported]>;
def print_target_triple : Flag<["-", "--"], "print-target-triple">,
HelpText<"Print the normalized target triple">;
def print_effective_triple : Flag<["-", "--"], "print-effective-triple">,
HelpText<"Print the effective target triple">;
def print_prog_name_EQ : Joined<["-", "--"], "print-prog-name=">,
HelpText<"Print the full program path of <name>">, MetaVarName<"<name>">;
def print_resource_dir : Flag<["-", "--"], "print-resource-dir">,
HelpText<"Print the resource directory pathname">;
def print_search_dirs : Flag<["-", "--"], "print-search-dirs">,
HelpText<"Print the paths used for finding libraries and programs">;
def private__bundle : Flag<["-"], "private_bundle">;
def pthreads : Flag<["-"], "pthreads">;
def pthread : Flag<["-"], "pthread">, Flags<[CC1Option]>,
HelpText<"Support POSIX threads in generated code">;
def no_pthread : Flag<["-"], "no-pthread">, Flags<[CC1Option]>;
def p : Flag<["-"], "p">;
def pie : Flag<["-"], "pie">;
def read__only__relocs : Separate<["-"], "read_only_relocs">;
def remap : Flag<["-"], "remap">;
def rewrite_objc : Flag<["-"], "rewrite-objc">, Flags<[DriverOption,CC1Option]>,
HelpText<"Rewrite Objective-C source to C++">, Group<Action_Group>;
def rewrite_legacy_objc : Flag<["-"], "rewrite-legacy-objc">, Flags<[DriverOption]>,
HelpText<"Rewrite Legacy Objective-C source to C++">;
def rdynamic : Flag<["-"], "rdynamic">;
def resource_dir : Separate<["-"], "resource-dir">,
Flags<[DriverOption, CC1Option, CoreOption, HelpHidden]>,
HelpText<"The directory which holds the compiler resource files">;
def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[DriverOption, CoreOption]>,
Alias<resource_dir>;
def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>, Group<Link_Group>;
def rtlib_EQ : Joined<["-", "--"], "rtlib=">,
HelpText<"Compiler runtime library to use">;
def frtlib_add_rpath: Flag<["-"], "frtlib-add-rpath">, Flags<[NoArgumentUnused]>,
HelpText<"Add -rpath with architecture-specific resource directory to the linker flags">;
def fno_rtlib_add_rpath: Flag<["-"], "fno-rtlib-add-rpath">, Flags<[NoArgumentUnused]>,
HelpText<"Do not add -rpath with architecture-specific resource directory to the linker flags">;
def r : Flag<["-"], "r">, Flags<[LinkerInput,NoArgumentUnused]>,
Group<Link_Group>;
def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[CC1Option, DriverOption]>,
HelpText<"Save intermediate compilation results.">;
def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>,
Alias<save_temps_EQ>, AliasArgs<["cwd"]>,
HelpText<"Save intermediate compilation results">;
def save_stats_EQ : Joined<["-", "--"], "save-stats=">, Flags<[DriverOption]>,
HelpText<"Save llvm statistics.">;
def save_stats : Flag<["-", "--"], "save-stats">, Flags<[DriverOption]>,
Alias<save_stats_EQ>, AliasArgs<["cwd"]>,
HelpText<"Save llvm statistics.">;
def via_file_asm : Flag<["-", "--"], "via-file-asm">, InternalDebugOpt,
HelpText<"Write assembly to file for input to assemble jobs">;
def sectalign : MultiArg<["-"], "sectalign", 3>;
def sectcreate : MultiArg<["-"], "sectcreate", 3>;
def sectobjectsymbols : MultiArg<["-"], "sectobjectsymbols", 2>;
def sectorder : MultiArg<["-"], "sectorder", 3>;
def seg1addr : JoinedOrSeparate<["-"], "seg1addr">;
def seg__addr__table__filename : Separate<["-"], "seg_addr_table_filename">;
def seg__addr__table : Separate<["-"], "seg_addr_table">;
def segaddr : MultiArg<["-"], "segaddr", 2>;
def segcreate : MultiArg<["-"], "segcreate", 3>;
def seglinkedit : Flag<["-"], "seglinkedit">;
def segprot : MultiArg<["-"], "segprot", 3>;
def segs__read__only__addr : Separate<["-"], "segs_read_only_addr">;
def segs__read__write__addr : Separate<["-"], "segs_read_write_addr">;
def segs__read__ : Joined<["-"], "segs_read_">;
def shared_libgcc : Flag<["-"], "shared-libgcc">;
def shared : Flag<["-", "--"], "shared">;
def single__module : Flag<["-"], "single_module">;
def specs_EQ : Joined<["-", "--"], "specs=">;
def specs : Separate<["-", "--"], "specs">, Flags<[Unsupported]>;
def static_libgcc : Flag<["-"], "static-libgcc">;
def static_libstdcxx : Flag<["-"], "static-libstdc++">;
def static : Flag<["-", "--"], "static">, Flags<[NoArgumentUnused]>;
def std_default_EQ : Joined<["-"], "std-default=">;
def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>,
Group<CompileOnly_Group>, HelpText<"Language standard to compile for">,
ValuesCode<[{
const char *Values =
#define LANGSTANDARD(id, name, lang, desc, features) name ","
#define LANGSTANDARD_ALIAS(id, alias) alias ","
#include "clang/Frontend/LangStandards.def"
;
}]>;
def stdlib_EQ : Joined<["-", "--"], "stdlib=">, Flags<[CC1Option]>,
HelpText<"C++ standard library to use">, Values<"libc++,libstdc++,platform">;
def sub__library : JoinedOrSeparate<["-"], "sub_library">;
def sub__umbrella : JoinedOrSeparate<["-"], "sub_umbrella">;
def system_header_prefix : Joined<["--"], "system-header-prefix=">,
Group<clang_i_Group>, Flags<[CC1Option]>, MetaVarName<"<prefix>">,
HelpText<"Treat all #include paths starting with <prefix> as including a "
"system header.">;
def : Separate<["--"], "system-header-prefix">, Alias<system_header_prefix>;
def no_system_header_prefix : Joined<["--"], "no-system-header-prefix=">,
Group<clang_i_Group>, Flags<[CC1Option]>, MetaVarName<"<prefix>">,
HelpText<"Treat all #include paths starting with <prefix> as not including a "
"system header.">;
def : Separate<["--"], "no-system-header-prefix">, Alias<no_system_header_prefix>;
def s : Flag<["-"], "s">, Group<Link_Group>;
def target : Joined<["--"], "target=">, Flags<[DriverOption, CoreOption]>,
HelpText<"Generate code for the given target">;
def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[DriverOption]>,
HelpText<"Use the gcc toolchain at the given directory">;
def time : Flag<["-"], "time">,
HelpText<"Time individual commands">;
def traditional_cpp : Flag<["-", "--"], "traditional-cpp">, Flags<[CC1Option]>,
HelpText<"Enable some traditional CPP emulation">;
def traditional : Flag<["-", "--"], "traditional">;
def trigraphs : Flag<["-", "--"], "trigraphs">, Alias<ftrigraphs>,
HelpText<"Process trigraph sequences">;
def twolevel__namespace__hints : Flag<["-"], "twolevel_namespace_hints">;
def twolevel__namespace : Flag<["-"], "twolevel_namespace">;
def t : Flag<["-"], "t">, Group<Link_Group>;
def umbrella : Separate<["-"], "umbrella">;
def undefined : JoinedOrSeparate<["-"], "undefined">, Group<u_Group>;
def undef : Flag<["-"], "undef">, Group<u_Group>, Flags<[CC1Option]>,
HelpText<"undef all system defines">;
def unexported__symbols__list : Separate<["-"], "unexported_symbols_list">;
def u : JoinedOrSeparate<["-"], "u">, Group<u_Group>;
def v : Flag<["-"], "v">, Flags<[CC1Option, CoreOption]>,
HelpText<"Show commands to run and use verbose output">;
def verify_debug_info : Flag<["--"], "verify-debug-info">, Flags<[DriverOption]>,
HelpText<"Verify the binary representation of debug output">;
def weak_l : Joined<["-"], "weak-l">, Flags<[LinkerInput]>;
def weak__framework : Separate<["-"], "weak_framework">, Flags<[LinkerInput]>;
def weak__library : Separate<["-"], "weak_library">, Flags<[LinkerInput]>;
def weak__reference__mismatches : Separate<["-"], "weak_reference_mismatches">;
def whatsloaded : Flag<["-"], "whatsloaded">;
def whyload : Flag<["-"], "whyload">;
def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">, Flags<[CC1Option]>;
def x : JoinedOrSeparate<["-"], "x">, Flags<[DriverOption,CC1Option]>,
HelpText<"Treat subsequent input files as having type <language>">,
MetaVarName<"<language>">;
def y : Joined<["-"], "y">;
def fintegrated_as : Flag<["-"], "fintegrated-as">, Flags<[DriverOption]>,
Group<f_Group>, HelpText<"Enable the integrated assembler">;
def fno_integrated_as : Flag<["-"], "fno-integrated-as">,
Flags<[CC1Option, DriverOption]>, Group<f_Group>,
HelpText<"Disable the integrated assembler">;
def : Flag<["-"], "integrated-as">, Alias<fintegrated_as>, Flags<[DriverOption]>;
def : Flag<["-"], "no-integrated-as">, Alias<fno_integrated_as>,
Flags<[CC1Option, DriverOption]>;
def working_directory : JoinedOrSeparate<["-"], "working-directory">, Flags<[CC1Option]>,
HelpText<"Resolve file paths relative to the specified directory">;
def working_directory_EQ : Joined<["-"], "working-directory=">, Flags<[CC1Option]>,
Alias<working_directory>;
// Double dash options, which are usually an alias for one of the previous
// options.
def _mhwdiv_EQ : Joined<["--"], "mhwdiv=">, Alias<mhwdiv_EQ>;
def _mhwdiv : Separate<["--"], "mhwdiv">, Alias<mhwdiv_EQ>;
def _CLASSPATH_EQ : Joined<["--"], "CLASSPATH=">, Alias<fclasspath_EQ>;
def _CLASSPATH : Separate<["--"], "CLASSPATH">, Alias<fclasspath_EQ>;
def _all_warnings : Flag<["--"], "all-warnings">, Alias<Wall>;
def _analyze_auto : Flag<["--"], "analyze-auto">, Flags<[DriverOption]>;
def _analyzer_no_default_checks : Flag<["--"], "analyzer-no-default-checks">, Flags<[DriverOption]>;
def _analyzer_output : JoinedOrSeparate<["--"], "analyzer-output">, Flags<[DriverOption]>,
HelpText<"Static analyzer report output format (html|plist|plist-multi-file|plist-html|text).">;
def _analyze : Flag<["--"], "analyze">, Flags<[DriverOption, CoreOption]>,
HelpText<"Run the static analyzer">;
def _assemble : Flag<["--"], "assemble">, Alias<S>;
def _assert_EQ : Joined<["--"], "assert=">, Alias<A>;
def _assert : Separate<["--"], "assert">, Alias<A>;
def _bootclasspath_EQ : Joined<["--"], "bootclasspath=">, Alias<fbootclasspath_EQ>;
def _bootclasspath : Separate<["--"], "bootclasspath">, Alias<fbootclasspath_EQ>;
def _classpath_EQ : Joined<["--"], "classpath=">, Alias<fclasspath_EQ>;
def _classpath : Separate<["--"], "classpath">, Alias<fclasspath_EQ>;
def _comments_in_macros : Flag<["--"], "comments-in-macros">, Alias<CC>;
def _comments : Flag<["--"], "comments">, Alias<C>;
def _compile : Flag<["--"], "compile">, Alias<c>;
def _constant_cfstrings : Flag<["--"], "constant-cfstrings">;
def _debug_EQ : Joined<["--"], "debug=">, Alias<g_Flag>;
def _debug : Flag<["--"], "debug">, Alias<g_Flag>;
def _define_macro_EQ : Joined<["--"], "define-macro=">, Alias<D>;
def _define_macro : Separate<["--"], "define-macro">, Alias<D>;
def _dependencies : Flag<["--"], "dependencies">, Alias<M>;
def _dyld_prefix_EQ : Joined<["--"], "dyld-prefix=">;
def _dyld_prefix : Separate<["--"], "dyld-prefix">, Alias<_dyld_prefix_EQ>;
def _encoding_EQ : Joined<["--"], "encoding=">, Alias<fencoding_EQ>;
def _encoding : Separate<["--"], "encoding">, Alias<fencoding_EQ>;
def _entry : Flag<["--"], "entry">, Alias<e>;
def _extdirs_EQ : Joined<["--"], "extdirs=">, Alias<fextdirs_EQ>;
def _extdirs : Separate<["--"], "extdirs">, Alias<fextdirs_EQ>;
def _extra_warnings : Flag<["--"], "extra-warnings">, Alias<W_Joined>;
def _for_linker_EQ : Joined<["--"], "for-linker=">, Alias<Xlinker>;
def _for_linker : Separate<["--"], "for-linker">, Alias<Xlinker>;
def _force_link_EQ : Joined<["--"], "force-link=">, Alias<u>;
def _force_link : Separate<["--"], "force-link">, Alias<u>;
def _help_hidden : Flag<["--"], "help-hidden">,
HelpText<"Display help for hidden options">;
def _imacros_EQ : Joined<["--"], "imacros=">, Alias<imacros>;
def _include_barrier : Flag<["--"], "include-barrier">, Alias<I_>;
def _include_directory_after_EQ : Joined<["--"], "include-directory-after=">, Alias<idirafter>;
def _include_directory_after : Separate<["--"], "include-directory-after">, Alias<idirafter>;
def _include_directory_EQ : Joined<["--"], "include-directory=">, Alias<I>;
def _include_directory : Separate<["--"], "include-directory">, Alias<I>;
def _include_prefix_EQ : Joined<["--"], "include-prefix=">, Alias<iprefix>;
def _include_prefix : Separate<["--"], "include-prefix">, Alias<iprefix>;
def _include_with_prefix_after_EQ : Joined<["--"], "include-with-prefix-after=">, Alias<iwithprefix>;
def _include_with_prefix_after : Separate<["--"], "include-with-prefix-after">, Alias<iwithprefix>;
def _include_with_prefix_before_EQ : Joined<["--"], "include-with-prefix-before=">, Alias<iwithprefixbefore>;
def _include_with_prefix_before : Separate<["--"], "include-with-prefix-before">, Alias<iwithprefixbefore>;
def _include_with_prefix_EQ : Joined<["--"], "include-with-prefix=">, Alias<iwithprefix>;
def _include_with_prefix : Separate<["--"], "include-with-prefix">, Alias<iwithprefix>;
def _include_EQ : Joined<["--"], "include=">, Alias<include_>;
def _language_EQ : Joined<["--"], "language=">, Alias<x>;
def _language : Separate<["--"], "language">, Alias<x>;
def _library_directory_EQ : Joined<["--"], "library-directory=">, Alias<L>;
def _library_directory : Separate<["--"], "library-directory">, Alias<L>;
def _no_line_commands : Flag<["--"], "no-line-commands">, Alias<P>;
def _no_standard_includes : Flag<["--"], "no-standard-includes">, Alias<nostdinc>;
def _no_standard_libraries : Flag<["--"], "no-standard-libraries">, Alias<nostdlib>;
def _no_undefined : Flag<["--"], "no-undefined">, Flags<[LinkerInput]>;
def _no_warnings : Flag<["--"], "no-warnings">, Alias<w>;
def _optimize_EQ : Joined<["--"], "optimize=">, Alias<O>;
def _optimize : Flag<["--"], "optimize">, Alias<O>;
def _output_class_directory_EQ : Joined<["--"], "output-class-directory=">, Alias<foutput_class_dir_EQ>;
def _output_class_directory : Separate<["--"], "output-class-directory">, Alias<foutput_class_dir_EQ>;
def _output_EQ : Joined<["--"], "output=">, Alias<o>;
def _output : Separate<["--"], "output">, Alias<o>;
def _param : Separate<["--"], "param">, Group<CompileOnly_Group>;
def _param_EQ : Joined<["--"], "param=">, Alias<_param>;
def _precompile : Flag<["--"], "precompile">, Flags<[DriverOption]>,
Group<Action_Group>, HelpText<"Only precompile the input">;
def _prefix_EQ : Joined<["--"], "prefix=">, Alias<B>;
def _prefix : Separate<["--"], "prefix">, Alias<B>;
def _preprocess : Flag<["--"], "preprocess">, Alias<E>;
def _print_diagnostic_categories : Flag<["--"], "print-diagnostic-categories">;
def _print_file_name : Separate<["--"], "print-file-name">, Alias<print_file_name_EQ>;
def _print_missing_file_dependencies : Flag<["--"], "print-missing-file-dependencies">, Alias<MG>;
def _print_prog_name : Separate<["--"], "print-prog-name">, Alias<print_prog_name_EQ>;
def _profile_blocks : Flag<["--"], "profile-blocks">, Alias<a>;
def _profile : Flag<["--"], "profile">, Alias<p>;
def _resource_EQ : Joined<["--"], "resource=">, Alias<fcompile_resource_EQ>;
def _resource : Separate<["--"], "resource">, Alias<fcompile_resource_EQ>;
def _rtlib : Separate<["--"], "rtlib">, Alias<rtlib_EQ>;
def _serialize_diags : Separate<["-", "--"], "serialize-diagnostics">, Flags<[DriverOption]>,
HelpText<"Serialize compiler diagnostics to a file">;
// We give --version different semantics from -version.
def _version : Flag<["--"], "version">, Flags<[CoreOption, CC1Option]>,
HelpText<"Print version information">;
def _signed_char : Flag<["--"], "signed-char">, Alias<fsigned_char>;
def _std : Separate<["--"], "std">, Alias<std_EQ>;
def _stdlib : Separate<["--"], "stdlib">, Alias<stdlib_EQ>;
def _sysroot_EQ : Joined<["--"], "sysroot=">;
def _sysroot : Separate<["--"], "sysroot">, Alias<_sysroot_EQ>;
def _target_help : Flag<["--"], "target-help">;
def _trace_includes : Flag<["--"], "trace-includes">, Alias<H>;
def _undefine_macro_EQ : Joined<["--"], "undefine-macro=">, Alias<U>;
def _undefine_macro : Separate<["--"], "undefine-macro">, Alias<U>;
def _unsigned_char : Flag<["--"], "unsigned-char">, Alias<funsigned_char>;
def _user_dependencies : Flag<["--"], "user-dependencies">, Alias<MM>;
def _verbose : Flag<["--"], "verbose">, Alias<v>;
def _warn__EQ : Joined<["--"], "warn-=">, Alias<W_Joined>;
def _warn_ : Joined<["--"], "warn-">, Alias<W_Joined>;
def _write_dependencies : Flag<["--"], "write-dependencies">, Alias<MD>;
def _write_user_dependencies : Flag<["--"], "write-user-dependencies">, Alias<MMD>;
def _ : Joined<["--"], "">, Flags<[Unsupported]>;
// Hexagon feature flags.
def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">,
Group<m_hexagon_Features_Group>;
def mv5 : Flag<["-"], "mv5">, Group<m_hexagon_Features_Group>, Alias<mcpu_EQ>,
AliasArgs<["hexagonv5"]>;
def mv55 : Flag<["-"], "mv55">, Group<m_hexagon_Features_Group>,
Alias<mcpu_EQ>, AliasArgs<["hexagonv55"]>;
def mv60 : Flag<["-"], "mv60">, Group<m_hexagon_Features_Group>,
Alias<mcpu_EQ>, AliasArgs<["hexagonv60"]>;
def mv62 : Flag<["-"], "mv62">, Group<m_hexagon_Features_Group>,
Alias<mcpu_EQ>, AliasArgs<["hexagonv62"]>;
def mv65 : Flag<["-"], "mv65">, Group<m_hexagon_Features_Group>,
Alias<mcpu_EQ>, AliasArgs<["hexagonv65"]>;
def mv66 : Flag<["-"], "mv66">, Group<m_hexagon_Features_Group>,
Alias<mcpu_EQ>, AliasArgs<["hexagonv66"]>;
def mhexagon_hvx : Flag<["-"], "mhvx">, Group<m_hexagon_Features_HVX_Group>,
HelpText<"Enable Hexagon Vector eXtensions">;
def mhexagon_hvx_EQ : Joined<["-"], "mhvx=">,
Group<m_hexagon_Features_HVX_Group>,
HelpText<"Enable Hexagon Vector eXtensions">;
def mno_hexagon_hvx : Flag<["-"], "mno-hvx">,
Group<m_hexagon_Features_HVX_Group>,
HelpText<"Disable Hexagon Vector eXtensions">;
def mhexagon_hvx_length_EQ : Joined<["-"], "mhvx-length=">,
Group<m_hexagon_Features_HVX_Group>, HelpText<"Set Hexagon Vector Length">,
Values<"64B,128B">;
def ffixed_r19: Flag<["-"], "ffixed-r19">,
HelpText<"Reserve register r19 (Hexagon only)">;
def mmemops : Flag<["-"], "mmemops">, Group<m_hexagon_Features_Group>,
Flags<[CC1Option]>, HelpText<"Enable generation of memop instructions">;
def mno_memops : Flag<["-"], "mno-memops">, Group<m_hexagon_Features_Group>,
Flags<[CC1Option]>, HelpText<"Disable generation of memop instructions">;
def mpackets : Flag<["-"], "mpackets">, Group<m_hexagon_Features_Group>,
Flags<[CC1Option]>, HelpText<"Enable generation of instruction packets">;
def mno_packets : Flag<["-"], "mno-packets">, Group<m_hexagon_Features_Group>,
Flags<[CC1Option]>, HelpText<"Disable generation of instruction packets">;
def mnvj : Flag<["-"], "mnvj">, Group<m_hexagon_Features_Group>,
Flags<[CC1Option]>, HelpText<"Enable generation of new-value jumps">;
def mno_nvj : Flag<["-"], "mno-nvj">, Group<m_hexagon_Features_Group>,
Flags<[CC1Option]>, HelpText<"Disable generation of new-value jumps">;
def mnvs : Flag<["-"], "mnvs">, Group<m_hexagon_Features_Group>,
Flags<[CC1Option]>, HelpText<"Enable generation of new-value stores">;
def mno_nvs : Flag<["-"], "mno-nvs">, Group<m_hexagon_Features_Group>,
Flags<[CC1Option]>, HelpText<"Disable generation of new-value stores">;
// X86 feature flags
def mx87 : Flag<["-"], "mx87">, Group<m_x86_Features_Group>;
def mno_x87 : Flag<["-"], "mno-x87">, Group<m_x86_Features_Group>;
def m80387 : Flag<["-"], "m80387">, Alias<mx87>;
def mno_80387 : Flag<["-"], "mno-80387">, Alias<mno_x87>;
def mmmx : Flag<["-"], "mmmx">, Group<m_x86_Features_Group>;
def mno_mmx : Flag<["-"], "mno-mmx">, Group<m_x86_Features_Group>;
def m3dnow : Flag<["-"], "m3dnow">, Group<m_x86_Features_Group>;
def mno_3dnow : Flag<["-"], "mno-3dnow">, Group<m_x86_Features_Group>;
def m3dnowa : Flag<["-"], "m3dnowa">, Group<m_x86_Features_Group>;
def mno_3dnowa : Flag<["-"], "mno-3dnowa">, Group<m_x86_Features_Group>;
def msse : Flag<["-"], "msse">, Group<m_x86_Features_Group>;
def mno_sse : Flag<["-"], "mno-sse">, Group<m_x86_Features_Group>;
def msse2 : Flag<["-"], "msse2">, Group<m_x86_Features_Group>;
def mno_sse2 : Flag<["-"], "mno-sse2">, Group<m_x86_Features_Group>;
def msse3 : Flag<["-"], "msse3">, Group<m_x86_Features_Group>;
def mno_sse3 : Flag<["-"], "mno-sse3">, Group<m_x86_Features_Group>;
def mssse3 : Flag<["-"], "mssse3">, Group<m_x86_Features_Group>;
def mno_ssse3 : Flag<["-"], "mno-ssse3">, Group<m_x86_Features_Group>;
def msse4_1 : Flag<["-"], "msse4.1">, Group<m_x86_Features_Group>;
def mno_sse4_1 : Flag<["-"], "mno-sse4.1">, Group<m_x86_Features_Group>;
def msse4_2 : Flag<["-"], "msse4.2">, Group<m_x86_Features_Group>;
def mno_sse4_2 : Flag<["-"], "mno-sse4.2">, Group<m_x86_Features_Group>;
def msse4 : Flag<["-"], "msse4">, Alias<msse4_2>;
// -mno-sse4 turns off sse4.1 which has the effect of turning off everything
// later than 4.1. -msse4 turns on 4.2 which has the effect of turning on
// everything earlier than 4.2.
def mno_sse4 : Flag<["-"], "mno-sse4">, Alias<mno_sse4_1>;
def msse4a : Flag<["-"], "msse4a">, Group<m_x86_Features_Group>;
def mno_sse4a : Flag<["-"], "mno-sse4a">, Group<m_x86_Features_Group>;
def mavx : Flag<["-"], "mavx">, Group<m_x86_Features_Group>;
def mno_avx : Flag<["-"], "mno-avx">, Group<m_x86_Features_Group>;
def mavx2 : Flag<["-"], "mavx2">, Group<m_x86_Features_Group>;
def mno_avx2 : Flag<["-"], "mno-avx2">, Group<m_x86_Features_Group>;
def mavx512f : Flag<["-"], "mavx512f">, Group<m_x86_Features_Group>;
def mno_avx512f : Flag<["-"], "mno-avx512f">, Group<m_x86_Features_Group>;
def mavx512bitalg : Flag<["-"], "mavx512bitalg">, Group<m_x86_Features_Group>;
def mno_avx512bitalg : Flag<["-"], "mno-avx512bitalg">, Group<m_x86_Features_Group>;
def mavx512bw : Flag<["-"], "mavx512bw">, Group<m_x86_Features_Group>;
def mno_avx512bw : Flag<["-"], "mno-avx512bw">, Group<m_x86_Features_Group>;
def mavx512cd : Flag<["-"], "mavx512cd">, Group<m_x86_Features_Group>;
def mno_avx512cd : Flag<["-"], "mno-avx512cd">, Group<m_x86_Features_Group>;
def mavx512dq : Flag<["-"], "mavx512dq">, Group<m_x86_Features_Group>;
def mno_avx512dq : Flag<["-"], "mno-avx512dq">, Group<m_x86_Features_Group>;
def mavx512er : Flag<["-"], "mavx512er">, Group<m_x86_Features_Group>;
def mno_avx512er : Flag<["-"], "mno-avx512er">, Group<m_x86_Features_Group>;
def mavx512ifma : Flag<["-"], "mavx512ifma">, Group<m_x86_Features_Group>;
def mno_avx512ifma : Flag<["-"], "mno-avx512ifma">, Group<m_x86_Features_Group>;
def mavx512pf : Flag<["-"], "mavx512pf">, Group<m_x86_Features_Group>;
def mno_avx512pf : Flag<["-"], "mno-avx512pf">, Group<m_x86_Features_Group>;
def mavx512vbmi : Flag<["-"], "mavx512vbmi">, Group<m_x86_Features_Group>;
def mno_avx512vbmi : Flag<["-"], "mno-avx512vbmi">, Group<m_x86_Features_Group>;
def mavx512vbmi2 : Flag<["-"], "mavx512vbmi2">, Group<m_x86_Features_Group>;
def mno_avx512vbmi2 : Flag<["-"], "mno-avx512vbmi2">, Group<m_x86_Features_Group>;
def mavx512vl : Flag<["-"], "mavx512vl">, Group<m_x86_Features_Group>;
def mno_avx512vl : Flag<["-"], "mno-avx512vl">, Group<m_x86_Features_Group>;
def mavx512vnni : Flag<["-"], "mavx512vnni">, Group<m_x86_Features_Group>;
def mno_avx512vnni : Flag<["-"], "mno-avx512vnni">, Group<m_x86_Features_Group>;
def mavx512vpopcntdq : Flag<["-"], "mavx512vpopcntdq">, Group<m_x86_Features_Group>;
def mno_avx512vpopcntdq : Flag<["-"], "mno-avx512vpopcntdq">, Group<m_x86_Features_Group>;
def madx : Flag<["-"], "madx">, Group<m_x86_Features_Group>;
def mno_adx : Flag<["-"], "mno-adx">, Group<m_x86_Features_Group>;
def maes : Flag<["-"], "maes">, Group<m_x86_Features_Group>;
def mno_aes : Flag<["-"], "mno-aes">, Group<m_x86_Features_Group>;
def mbmi : Flag<["-"], "mbmi">, Group<m_x86_Features_Group>;
def mno_bmi : Flag<["-"], "mno-bmi">, Group<m_x86_Features_Group>;
def mbmi2 : Flag<["-"], "mbmi2">, Group<m_x86_Features_Group>;
def mno_bmi2 : Flag<["-"], "mno-bmi2">, Group<m_x86_Features_Group>;
def mcldemote : Flag<["-"], "mcldemote">, Group<m_x86_Features_Group>;
def mno_cldemote : Flag<["-"], "mno-cldemote">, Group<m_x86_Features_Group>;
def mclflushopt : Flag<["-"], "mclflushopt">, Group<m_x86_Features_Group>;
def mno_clflushopt : Flag<["-"], "mno-clflushopt">, Group<m_x86_Features_Group>;
def mclwb : Flag<["-"], "mclwb">, Group<m_x86_Features_Group>;
def mno_clwb : Flag<["-"], "mno-clwb">, Group<m_x86_Features_Group>;
def mwbnoinvd : Flag<["-"], "mwbnoinvd">, Group<m_x86_Features_Group>;
def mno_wbnoinvd : Flag<["-"], "mno-wbnoinvd">, Group<m_x86_Features_Group>;
def mclzero : Flag<["-"], "mclzero">, Group<m_x86_Features_Group>;
def mno_clzero : Flag<["-"], "mno-clzero">, Group<m_x86_Features_Group>;
def mcx16 : Flag<["-"], "mcx16">, Group<m_x86_Features_Group>;
def mno_cx16 : Flag<["-"], "mno-cx16">, Group<m_x86_Features_Group>;
def mf16c : Flag<["-"], "mf16c">, Group<m_x86_Features_Group>;
def mno_f16c : Flag<["-"], "mno-f16c">, Group<m_x86_Features_Group>;
def mfma : Flag<["-"], "mfma">, Group<m_x86_Features_Group>;
def mno_fma : Flag<["-"], "mno-fma">, Group<m_x86_Features_Group>;
def mfma4 : Flag<["-"], "mfma4">, Group<m_x86_Features_Group>;
def mno_fma4 : Flag<["-"], "mno-fma4">, Group<m_x86_Features_Group>;
def mfsgsbase : Flag<["-"], "mfsgsbase">, Group<m_x86_Features_Group>;
def mno_fsgsbase : Flag<["-"], "mno-fsgsbase">, Group<m_x86_Features_Group>;
def mfxsr : Flag<["-"], "mfxsr">, Group<m_x86_Features_Group>;
def mno_fxsr : Flag<["-"], "mno-fxsr">, Group<m_x86_Features_Group>;
def minvpcid : Flag<["-"], "minvpcid">, Group<m_x86_Features_Group>;
def mno_invpcid : Flag<["-"], "mno-invpcid">, Group<m_x86_Features_Group>;
def mgfni : Flag<["-"], "mgfni">, Group<m_x86_Features_Group>;
def mno_gfni : Flag<["-"], "mno-gfni">, Group<m_x86_Features_Group>;
def mlwp : Flag<["-"], "mlwp">, Group<m_x86_Features_Group>;
def mno_lwp : Flag<["-"], "mno-lwp">, Group<m_x86_Features_Group>;
def mlzcnt : Flag<["-"], "mlzcnt">, Group<m_x86_Features_Group>;
def mno_lzcnt : Flag<["-"], "mno-lzcnt">, Group<m_x86_Features_Group>;
def mmovbe : Flag<["-"], "mmovbe">, Group<m_x86_Features_Group>;
def mno_movbe : Flag<["-"], "mno-movbe">, Group<m_x86_Features_Group>;
def mmovdiri : Flag<["-"], "mmovdiri">, Group<m_x86_Features_Group>;
def mno_movdiri : Flag<["-"], "mno-movdiri">, Group<m_x86_Features_Group>;
def mmovdir64b : Flag<["-"], "mmovdir64b">, Group<m_x86_Features_Group>;
def mno_movdir64b : Flag<["-"], "mno-movdir64b">, Group<m_x86_Features_Group>;
def mmpx : Flag<["-"], "mmpx">, Group<m_x86_Features_Group>;
def mno_mpx : Flag<["-"], "mno-mpx">, Group<m_x86_Features_Group>;
def mmwaitx : Flag<["-"], "mmwaitx">, Group<m_x86_Features_Group>;
def mno_mwaitx : Flag<["-"], "mno-mwaitx">, Group<m_x86_Features_Group>;
def mpku : Flag<["-"], "mpku">, Group<m_x86_Features_Group>;
def mno_pku : Flag<["-"], "mno-pku">, Group<m_x86_Features_Group>;
def mpclmul : Flag<["-"], "mpclmul">, Group<m_x86_Features_Group>;
def mno_pclmul : Flag<["-"], "mno-pclmul">, Group<m_x86_Features_Group>;
def mpconfig : Flag<["-"], "mpconfig">, Group<m_x86_Features_Group>;
def mno_pconfig : Flag<["-"], "mno-pconfig">, Group<m_x86_Features_Group>;
def mpopcnt : Flag<["-"], "mpopcnt">, Group<m_x86_Features_Group>;
def mno_popcnt : Flag<["-"], "mno-popcnt">, Group<m_x86_Features_Group>;
def mprefetchwt1 : Flag<["-"], "mprefetchwt1">, Group<m_x86_Features_Group>;
def mno_prefetchwt1 : Flag<["-"], "mno-prefetchwt1">, Group<m_x86_Features_Group>;
def mprfchw : Flag<["-"], "mprfchw">, Group<m_x86_Features_Group>;
def mno_prfchw : Flag<["-"], "mno-prfchw">, Group<m_x86_Features_Group>;
def mptwrite : Flag<["-"], "mptwrite">, Group<m_x86_Features_Group>;
def mno_ptwrite : Flag<["-"], "mno-ptwrite">, Group<m_x86_Features_Group>;
def mrdpid : Flag<["-"], "mrdpid">, Group<m_x86_Features_Group>;
def mno_rdpid : Flag<["-"], "mno-rdpid">, Group<m_x86_Features_Group>;
def mrdrnd : Flag<["-"], "mrdrnd">, Group<m_x86_Features_Group>;
def mno_rdrnd : Flag<["-"], "mno-rdrnd">, Group<m_x86_Features_Group>;
def mrtm : Flag<["-"], "mrtm">, Group<m_x86_Features_Group>;
def mno_rtm : Flag<["-"], "mno-rtm">, Group<m_x86_Features_Group>;
def mrdseed : Flag<["-"], "mrdseed">, Group<m_x86_Features_Group>;
def mno_rdseed : Flag<["-"], "mno-rdseed">, Group<m_x86_Features_Group>;
def msahf : Flag<["-"], "msahf">, Group<m_x86_Features_Group>;
def mno_sahf : Flag<["-"], "mno-sahf">, Group<m_x86_Features_Group>;
def msgx : Flag<["-"], "msgx">, Group<m_x86_Features_Group>;
def mno_sgx : Flag<["-"], "mno-sgx">, Group<m_x86_Features_Group>;
def msha : Flag<["-"], "msha">, Group<m_x86_Features_Group>;
def mno_sha : Flag<["-"], "mno-sha">, Group<m_x86_Features_Group>;
def mtbm : Flag<["-"], "mtbm">, Group<m_x86_Features_Group>;
def mno_tbm : Flag<["-"], "mno-tbm">, Group<m_x86_Features_Group>;
def mvaes : Flag<["-"], "mvaes">, Group<m_x86_Features_Group>;
def mno_vaes : Flag<["-"], "mno-vaes">, Group<m_x86_Features_Group>;
def mvpclmulqdq : Flag<["-"], "mvpclmulqdq">, Group<m_x86_Features_Group>;
def mno_vpclmulqdq : Flag<["-"], "mno-vpclmulqdq">, Group<m_x86_Features_Group>;
def mwaitpkg : Flag<["-"], "mwaitpkg">, Group<m_x86_Features_Group>;
def mno_waitpkg : Flag<["-"], "mno-waitpkg">, Group<m_x86_Features_Group>;
def mxop : Flag<["-"], "mxop">, Group<m_x86_Features_Group>;
def mno_xop : Flag<["-"], "mno-xop">, Group<m_x86_Features_Group>;
def mxsave : Flag<["-"], "mxsave">, Group<m_x86_Features_Group>;
def mno_xsave : Flag<["-"], "mno-xsave">, Group<m_x86_Features_Group>;
def mxsavec : Flag<["-"], "mxsavec">, Group<m_x86_Features_Group>;
def mno_xsavec : Flag<["-"], "mno-xsavec">, Group<m_x86_Features_Group>;
def mxsaveopt : Flag<["-"], "mxsaveopt">, Group<m_x86_Features_Group>;
def mno_xsaveopt : Flag<["-"], "mno-xsaveopt">, Group<m_x86_Features_Group>;
def mxsaves : Flag<["-"], "mxsaves">, Group<m_x86_Features_Group>;
def mno_xsaves : Flag<["-"], "mno-xsaves">, Group<m_x86_Features_Group>;
def mshstk : Flag<["-"], "mshstk">, Group<m_x86_Features_Group>;
def mno_shstk : Flag<["-"], "mno-shstk">, Group<m_x86_Features_Group>;
def mretpoline_external_thunk : Flag<["-"], "mretpoline-external-thunk">, Group<m_x86_Features_Group>;
def mno_retpoline_external_thunk : Flag<["-"], "mno-retpoline-external-thunk">, Group<m_x86_Features_Group>;
// These are legacy user-facing driver-level option spellings. They are always
// aliases for options that are spelled using the more common Unix / GNU flag
// style of double-dash and equals-joined flags.
def gcc_toolchain_legacy_spelling : Separate<["-"], "gcc-toolchain">, Alias<gcc_toolchain>;
def target_legacy_spelling : Separate<["-"], "target">, Alias<target>;
// Special internal option to handle -Xlinker --no-demangle.
def Z_Xlinker__no_demangle : Flag<["-"], "Z-Xlinker-no-demangle">,
Flags<[Unsupported, NoArgumentUnused]>;
// Special internal option to allow forwarding arbitrary arguments to linker.
def Zlinker_input : Separate<["-"], "Zlinker-input">,
Flags<[Unsupported, NoArgumentUnused]>;
// Reserved library options.
def Z_reserved_lib_stdcxx : Flag<["-"], "Z-reserved-lib-stdc++">,
Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group<reserved_lib_Group>;
def Z_reserved_lib_cckext : Flag<["-"], "Z-reserved-lib-cckext">,
Flags<[LinkerInput, NoArgumentUnused, Unsupported]>, Group<reserved_lib_Group>;
// Ignored options
// FIXME: multiclasess produce suffixes, not prefixes. This is fine for now
// since it is only used in ignored options.
multiclass BooleanFFlag<string name> {
def _f : Flag<["-"], "f"#name>;
def _fno : Flag<["-"], "fno-"#name>;
}
defm : BooleanFFlag<"keep-inline-functions">, Group<clang_ignored_gcc_optimization_f_Group>;
def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<f_Group>;
def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<f_Group>, Flags<[CoreOption]>;
defm align_labels : BooleanFFlag<"align-labels">, Group<clang_ignored_gcc_optimization_f_Group>;
def falign_labels_EQ : Joined<["-"], "falign-labels=">, Group<clang_ignored_gcc_optimization_f_Group>;
defm align_loops : BooleanFFlag<"align-loops">, Group<clang_ignored_gcc_optimization_f_Group>;
def falign_loops_EQ : Joined<["-"], "falign-loops=">, Group<clang_ignored_gcc_optimization_f_Group>;
defm align_jumps : BooleanFFlag<"align-jumps">, Group<clang_ignored_gcc_optimization_f_Group>;
def falign_jumps_EQ : Joined<["-"], "falign-jumps=">, Group<clang_ignored_gcc_optimization_f_Group>;
// FIXME: This option should be supported and wired up to our diognostics, but
// ignore it for now to avoid breaking builds that use it.
def fdiagnostics_show_location_EQ : Joined<["-"], "fdiagnostics-show-location=">, Group<clang_ignored_f_Group>;
defm fcheck_new : BooleanFFlag<"check-new">, Group<clang_ignored_f_Group>;
defm caller_saves : BooleanFFlag<"caller-saves">, Group<clang_ignored_gcc_optimization_f_Group>;
defm reorder_blocks : BooleanFFlag<"reorder-blocks">, Group<clang_ignored_gcc_optimization_f_Group>;
defm eliminate_unused_debug_types : BooleanFFlag<"eliminate-unused-debug-types">, Group<clang_ignored_f_Group>;
defm branch_count_reg : BooleanFFlag<"branch-count-reg">, Group<clang_ignored_gcc_optimization_f_Group>;
defm default_inline : BooleanFFlag<"default-inline">, Group<clang_ignored_gcc_optimization_f_Group>;
defm fat_lto_objects : BooleanFFlag<"fat-lto-objects">, Group<clang_ignored_gcc_optimization_f_Group>;
defm float_store : BooleanFFlag<"float-store">, Group<clang_ignored_gcc_optimization_f_Group>;
defm friend_injection : BooleanFFlag<"friend-injection">, Group<clang_ignored_f_Group>;
defm function_attribute_list : BooleanFFlag<"function-attribute-list">, Group<clang_ignored_f_Group>;
defm gcse : BooleanFFlag<"gcse">, Group<clang_ignored_gcc_optimization_f_Group>;
defm gcse_after_reload: BooleanFFlag<"gcse-after-reload">, Group<clang_ignored_gcc_optimization_f_Group>;
defm gcse_las: BooleanFFlag<"gcse-las">, Group<clang_ignored_gcc_optimization_f_Group>;
defm gcse_sm: BooleanFFlag<"gcse-sm">, Group<clang_ignored_gcc_optimization_f_Group>;
defm gnu : BooleanFFlag<"gnu">, Group<clang_ignored_f_Group>;
defm implicit_templates : BooleanFFlag<"implicit-templates">, Group<clang_ignored_f_Group>;
defm implement_inlines : BooleanFFlag<"implement-inlines">, Group<clang_ignored_f_Group>;
defm merge_constants : BooleanFFlag<"merge-constants">, Group<clang_ignored_gcc_optimization_f_Group>;
defm modulo_sched : BooleanFFlag<"modulo-sched">, Group<clang_ignored_gcc_optimization_f_Group>;
defm modulo_sched_allow_regmoves : BooleanFFlag<"modulo-sched-allow-regmoves">,
Group<clang_ignored_gcc_optimization_f_Group>;
defm inline_functions_called_once : BooleanFFlag<"inline-functions-called-once">,
Group<clang_ignored_gcc_optimization_f_Group>;
def finline_limit_EQ : Joined<["-"], "finline-limit=">, Group<clang_ignored_gcc_optimization_f_Group>;
defm finline_limit : BooleanFFlag<"inline-limit">, Group<clang_ignored_gcc_optimization_f_Group>;
defm inline_small_functions : BooleanFFlag<"inline-small-functions">,
Group<clang_ignored_gcc_optimization_f_Group>;
defm ipa_cp : BooleanFFlag<"ipa-cp">,
Group<clang_ignored_gcc_optimization_f_Group>;
defm ivopts : BooleanFFlag<"ivopts">, Group<clang_ignored_gcc_optimization_f_Group>;
defm non_call_exceptions : BooleanFFlag<"non-call-exceptions">, Group<clang_ignored_f_Group>;
defm peel_loops : BooleanFFlag<"peel-loops">, Group<clang_ignored_gcc_optimization_f_Group>;
defm permissive : BooleanFFlag<"permissive">, Group<clang_ignored_f_Group>;
defm prefetch_loop_arrays : BooleanFFlag<"prefetch-loop-arrays">, Group<clang_ignored_gcc_optimization_f_Group>;
defm printf : BooleanFFlag<"printf">, Group<clang_ignored_f_Group>;
defm profile : BooleanFFlag<"profile">, Group<clang_ignored_f_Group>;
defm profile_correction : BooleanFFlag<"profile-correction">, Group<clang_ignored_gcc_optimization_f_Group>;
defm profile_generate_sampling : BooleanFFlag<"profile-generate-sampling">, Group<clang_ignored_f_Group>;
defm profile_reusedist : BooleanFFlag<"profile-reusedist">, Group<clang_ignored_f_Group>;
defm profile_values : BooleanFFlag<"profile-values">, Group<clang_ignored_gcc_optimization_f_Group>;
defm regs_graph : BooleanFFlag<"regs-graph">, Group<clang_ignored_f_Group>;
defm rename_registers : BooleanFFlag<"rename-registers">, Group<clang_ignored_gcc_optimization_f_Group>;
defm ripa : BooleanFFlag<"ripa">, Group<clang_ignored_f_Group>;
defm rounding_math : BooleanFFlag<"rounding-math">, Group<clang_ignored_gcc_optimization_f_Group>;
defm schedule_insns : BooleanFFlag<"schedule-insns">, Group<clang_ignored_gcc_optimization_f_Group>;
defm schedule_insns2 : BooleanFFlag<"schedule-insns2">, Group<clang_ignored_gcc_optimization_f_Group>;
defm see : BooleanFFlag<"see">, Group<clang_ignored_f_Group>;
defm signaling_nans : BooleanFFlag<"signaling-nans">, Group<clang_ignored_gcc_optimization_f_Group>;
defm single_precision_constant : BooleanFFlag<"single-precision-constant">,
Group<clang_ignored_gcc_optimization_f_Group>;
defm spec_constr_count : BooleanFFlag<"spec-constr-count">, Group<clang_ignored_f_Group>;
defm stack_check : BooleanFFlag<"stack-check">, Group<clang_ignored_f_Group>;
defm strength_reduce :
BooleanFFlag<"strength-reduce">, Group<clang_ignored_gcc_optimization_f_Group>;
defm tls_model : BooleanFFlag<"tls-model">, Group<clang_ignored_f_Group>;
defm tracer : BooleanFFlag<"tracer">, Group<clang_ignored_gcc_optimization_f_Group>;
defm tree_dce : BooleanFFlag<"tree-dce">, Group<clang_ignored_gcc_optimization_f_Group>;
defm tree_loop_im : BooleanFFlag<"tree_loop_im">, Group<clang_ignored_gcc_optimization_f_Group>;
defm tree_loop_ivcanon : BooleanFFlag<"tree_loop_ivcanon">, Group<clang_ignored_gcc_optimization_f_Group>;
defm tree_loop_linear : BooleanFFlag<"tree_loop_linear">, Group<clang_ignored_gcc_optimization_f_Group>;
defm tree_salias : BooleanFFlag<"tree-salias">, Group<clang_ignored_f_Group>;
defm tree_ter : BooleanFFlag<"tree-ter">, Group<clang_ignored_gcc_optimization_f_Group>;
defm tree_vectorizer_verbose : BooleanFFlag<"tree-vectorizer-verbose">, Group<clang_ignored_f_Group>;
defm tree_vrp : BooleanFFlag<"tree-vrp">, Group<clang_ignored_gcc_optimization_f_Group>;
defm unroll_all_loops : BooleanFFlag<"unroll-all-loops">, Group<clang_ignored_gcc_optimization_f_Group>;
defm unsafe_loop_optimizations : BooleanFFlag<"unsafe-loop-optimizations">,
Group<clang_ignored_gcc_optimization_f_Group>;
defm unswitch_loops : BooleanFFlag<"unswitch-loops">, Group<clang_ignored_gcc_optimization_f_Group>;
defm use_linker_plugin : BooleanFFlag<"use-linker-plugin">, Group<clang_ignored_gcc_optimization_f_Group>;
defm vect_cost_model : BooleanFFlag<"vect-cost-model">, Group<clang_ignored_gcc_optimization_f_Group>;
defm variable_expansion_in_unroller : BooleanFFlag<"variable-expansion-in-unroller">,
Group<clang_ignored_gcc_optimization_f_Group>;
defm web : BooleanFFlag<"web">, Group<clang_ignored_gcc_optimization_f_Group>;
defm whole_program : BooleanFFlag<"whole-program">, Group<clang_ignored_gcc_optimization_f_Group>;
defm devirtualize : BooleanFFlag<"devirtualize">, Group<clang_ignored_gcc_optimization_f_Group>;
defm devirtualize_speculatively : BooleanFFlag<"devirtualize-speculatively">,
Group<clang_ignored_gcc_optimization_f_Group>;
// Generic gfortran options.
def A_DASH : Joined<["-"], "A-">, Group<gfortran_Group>;
def J : JoinedOrSeparate<["-"], "J">, Flags<[RenderJoined]>, Group<gfortran_Group>;
def cpp : Flag<["-"], "cpp">, Group<gfortran_Group>;
def nocpp : Flag<["-"], "nocpp">, Group<gfortran_Group>;
def static_libgfortran : Flag<["-"], "static-libgfortran">, Group<gfortran_Group>;
// "f" options with values for gfortran.
def fblas_matmul_limit_EQ : Joined<["-"], "fblas-matmul-limit=">, Group<gfortran_Group>;
def fcheck_EQ : Joined<["-"], "fcheck=">, Group<gfortran_Group>;
def fcoarray_EQ : Joined<["-"], "fcoarray=">, Group<gfortran_Group>;
def fconvert_EQ : Joined<["-"], "fconvert=">, Group<gfortran_Group>;
def ffixed_line_length_VALUE : Joined<["-"], "ffixed-line-length-">, Group<gfortran_Group>;
def ffpe_trap_EQ : Joined<["-"], "ffpe-trap=">, Group<gfortran_Group>;
def ffree_line_length_VALUE : Joined<["-"], "ffree-line-length-">, Group<gfortran_Group>;
def finit_character_EQ : Joined<["-"], "finit-character=">, Group<gfortran_Group>;
def finit_integer_EQ : Joined<["-"], "finit-integer=">, Group<gfortran_Group>;
def finit_logical_EQ : Joined<["-"], "finit-logical=">, Group<gfortran_Group>;
def finit_real_EQ : Joined<["-"], "finit-real=">, Group<gfortran_Group>;
def fmax_array_constructor_EQ : Joined<["-"], "fmax-array-constructor=">, Group<gfortran_Group>;
def fmax_errors_EQ : Joined<["-"], "fmax-errors=">, Group<gfortran_Group>;
def fmax_stack_var_size_EQ : Joined<["-"], "fmax-stack-var-size=">, Group<gfortran_Group>;
def fmax_subrecord_length_EQ : Joined<["-"], "fmax-subrecord-length=">, Group<gfortran_Group>;
def frecord_marker_EQ : Joined<["-"], "frecord-marker=">, Group<gfortran_Group>;
// "f" flags for gfortran.
defm aggressive_function_elimination : BooleanFFlag<"aggressive-function-elimination">, Group<gfortran_Group>;
defm align_commons : BooleanFFlag<"align-commons">, Group<gfortran_Group>;
defm all_intrinsics : BooleanFFlag<"all-intrinsics">, Group<gfortran_Group>;
defm automatic : BooleanFFlag<"automatic">, Group<gfortran_Group>;
defm backslash : BooleanFFlag<"backslash">, Group<gfortran_Group>;
defm backtrace : BooleanFFlag<"backtrace">, Group<gfortran_Group>;
defm bounds_check : BooleanFFlag<"bounds-check">, Group<gfortran_Group>;
defm check_array_temporaries : BooleanFFlag<"check-array-temporaries">, Group<gfortran_Group>;
defm cray_pointer : BooleanFFlag<"cray-pointer">, Group<gfortran_Group>;
defm d_lines_as_code : BooleanFFlag<"d-lines-as-code">, Group<gfortran_Group>;
defm d_lines_as_comments : BooleanFFlag<"d-lines-as-comments">, Group<gfortran_Group>;
defm default_double_8 : BooleanFFlag<"default-double-8">, Group<gfortran_Group>;
defm default_integer_8 : BooleanFFlag<"default-integer-8">, Group<gfortran_Group>;
defm default_real_8 : BooleanFFlag<"default-real-8">, Group<gfortran_Group>;
defm dollar_ok : BooleanFFlag<"dollar-ok">, Group<gfortran_Group>;
defm dump_fortran_optimized : BooleanFFlag<"dump-fortran-optimized">, Group<gfortran_Group>;
defm dump_fortran_original : BooleanFFlag<"dump-fortran-original">, Group<gfortran_Group>;
defm dump_parse_tree : BooleanFFlag<"dump-parse-tree">, Group<gfortran_Group>;
defm external_blas : BooleanFFlag<"external-blas">, Group<gfortran_Group>;
defm f2c : BooleanFFlag<"f2c">, Group<gfortran_Group>;
defm fixed_form : BooleanFFlag<"fixed-form">, Group<gfortran_Group>;
defm free_form : BooleanFFlag<"free-form">, Group<gfortran_Group>;
defm frontend_optimize : BooleanFFlag<"frontend-optimize">, Group<gfortran_Group>;
defm implicit_none : BooleanFFlag<"implicit-none">, Group<gfortran_Group>;
defm init_local_zero : BooleanFFlag<"init-local-zero">, Group<gfortran_Group>;
defm integer_4_integer_8 : BooleanFFlag<"integer-4-integer-8">, Group<gfortran_Group>;
defm intrinsic_modules_path : BooleanFFlag<"intrinsic-modules-path">, Group<gfortran_Group>;
defm max_identifier_length : BooleanFFlag<"max-identifier-length">, Group<gfortran_Group>;
defm module_private : BooleanFFlag<"module-private">, Group<gfortran_Group>;
defm pack_derived : BooleanFFlag<"pack-derived">, Group<gfortran_Group>;
defm protect_parens : BooleanFFlag<"protect-parens">, Group<gfortran_Group>;
defm range_check : BooleanFFlag<"range-check">, Group<gfortran_Group>;
defm real_4_real_10 : BooleanFFlag<"real-4-real-10">, Group<gfortran_Group>;
defm real_4_real_16 : BooleanFFlag<"real-4-real-16">, Group<gfortran_Group>;
defm real_4_real_8 : BooleanFFlag<"real-4-real-8">, Group<gfortran_Group>;
defm real_8_real_10 : BooleanFFlag<"real-8-real-10">, Group<gfortran_Group>;
defm real_8_real_16 : BooleanFFlag<"real-8-real-16">, Group<gfortran_Group>;
defm real_8_real_4 : BooleanFFlag<"real-8-real-4">, Group<gfortran_Group>;
defm realloc_lhs : BooleanFFlag<"realloc-lhs">, Group<gfortran_Group>;
defm recursive : BooleanFFlag<"recursive">, Group<gfortran_Group>;
defm repack_arrays : BooleanFFlag<"repack-arrays">, Group<gfortran_Group>;
defm second_underscore : BooleanFFlag<"second-underscore">, Group<gfortran_Group>;
defm sign_zero : BooleanFFlag<"sign-zero">, Group<gfortran_Group>;
defm stack_arrays : BooleanFFlag<"stack-arrays">, Group<gfortran_Group>;
defm underscoring : BooleanFFlag<"underscoring">, Group<gfortran_Group>;
defm whole_file : BooleanFFlag<"whole-file">, Group<gfortran_Group>;
include "CC1Options.td"
include "CLCompatOptions.td"
Index: vendor/clang/dist-release_80/include/clang/Tooling/ArgumentsAdjusters.h
===================================================================
--- vendor/clang/dist-release_80/include/clang/Tooling/ArgumentsAdjusters.h (revision 343795)
+++ vendor/clang/dist-release_80/include/clang/Tooling/ArgumentsAdjusters.h (revision 343796)
@@ -1,72 +1,76 @@
//===- ArgumentsAdjusters.h - Command line arguments adjuster ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares type ArgumentsAdjuster and functions to create several
// useful argument adjusters.
// ArgumentsAdjusters modify command line arguments obtained from a compilation
// database before they are used to run a frontend action.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
#define LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include <functional>
#include <string>
#include <vector>
namespace clang {
namespace tooling {
/// A sequence of command line arguments.
using CommandLineArguments = std::vector<std::string>;
/// A prototype of a command line adjuster.
///
/// Command line argument adjuster is responsible for command line arguments
/// modification before the arguments are used to run a frontend action.
using ArgumentsAdjuster = std::function<CommandLineArguments(
const CommandLineArguments &, StringRef Filename)>;
/// Gets an argument adjuster that converts input command line arguments
/// to the "syntax check only" variant.
ArgumentsAdjuster getClangSyntaxOnlyAdjuster();
/// Gets an argument adjuster which removes output-related command line
/// arguments.
ArgumentsAdjuster getClangStripOutputAdjuster();
/// Gets an argument adjuster which removes dependency-file
/// related command line arguments.
ArgumentsAdjuster getClangStripDependencyFileAdjuster();
enum class ArgumentInsertPosition { BEGIN, END };
/// Gets an argument adjuster which inserts \p Extra arguments in the
/// specified position.
ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra,
ArgumentInsertPosition Pos);
/// Gets an argument adjuster which inserts an \p Extra argument in the
/// specified position.
ArgumentsAdjuster getInsertArgumentAdjuster(
const char *Extra,
ArgumentInsertPosition Pos = ArgumentInsertPosition::END);
+/// Gets an argument adjuster which strips plugin related command line
+/// arguments.
+ArgumentsAdjuster getStripPluginsAdjuster();
+
/// Gets an argument adjuster which adjusts the arguments in sequence
/// with the \p First adjuster and then with the \p Second one.
ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,
ArgumentsAdjuster Second);
} // namespace tooling
} // namespace clang
#endif // LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H
Index: vendor/clang/dist-release_80/lib/Basic/FileManager.cpp
===================================================================
--- vendor/clang/dist-release_80/lib/Basic/FileManager.cpp (revision 343795)
+++ vendor/clang/dist-release_80/lib/Basic/FileManager.cpp (revision 343796)
@@ -1,552 +1,539 @@
//===--- FileManager.cpp - File System Probing and Caching ----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the FileManager interface.
//
//===----------------------------------------------------------------------===//
//
// TODO: This should index all interesting directories with dirent calls.
// getdirentries ?
// opendir/readdir_r/closedir ?
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemStatCache.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <climits>
#include <cstdint>
#include <cstdlib>
#include <string>
#include <utility>
using namespace clang;
/// NON_EXISTENT_DIR - A special value distinct from null that is used to
/// represent a dir name that doesn't exist on the disk.
#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1)
/// NON_EXISTENT_FILE - A special value distinct from null that is used to
/// represent a filename that doesn't exist on the disk.
#define NON_EXISTENT_FILE reinterpret_cast<FileEntry*>((intptr_t)-1)
//===----------------------------------------------------------------------===//
// Common logic.
//===----------------------------------------------------------------------===//
FileManager::FileManager(const FileSystemOptions &FSO,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
: FS(std::move(FS)), FileSystemOpts(FSO), SeenDirEntries(64),
SeenFileEntries(64), NextFileUID(0) {
NumDirLookups = NumFileLookups = 0;
NumDirCacheMisses = NumFileCacheMisses = 0;
// If the caller doesn't provide a virtual file system, just grab the real
// file system.
if (!this->FS)
this->FS = llvm::vfs::getRealFileSystem();
}
FileManager::~FileManager() = default;
void FileManager::setStatCache(std::unique_ptr<FileSystemStatCache> statCache) {
assert(statCache && "No stat cache provided?");
StatCache = std::move(statCache);
}
void FileManager::clearStatCache() { StatCache.reset(); }
/// Retrieve the directory that the given file name resides in.
/// Filename can point to either a real file or a virtual file.
static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr,
StringRef Filename,
bool CacheFailure) {
if (Filename.empty())
return nullptr;
if (llvm::sys::path::is_separator(Filename[Filename.size() - 1]))
return nullptr; // If Filename is a directory.
StringRef DirName = llvm::sys::path::parent_path(Filename);
// Use the current directory if file has no path component.
if (DirName.empty())
DirName = ".";
return FileMgr.getDirectory(DirName, CacheFailure);
}
/// Add all ancestors of the given path (pointing to either a file or
/// a directory) as virtual directories.
void FileManager::addAncestorsAsVirtualDirs(StringRef Path) {
StringRef DirName = llvm::sys::path::parent_path(Path);
if (DirName.empty())
DirName = ".";
auto &NamedDirEnt =
*SeenDirEntries.insert(std::make_pair(DirName, nullptr)).first;
// When caching a virtual directory, we always cache its ancestors
// at the same time. Therefore, if DirName is already in the cache,
// we don't need to recurse as its ancestors must also already be in
// the cache.
if (NamedDirEnt.second && NamedDirEnt.second != NON_EXISTENT_DIR)
return;
// Add the virtual directory to the cache.
auto UDE = llvm::make_unique<DirectoryEntry>();
UDE->Name = NamedDirEnt.first();
NamedDirEnt.second = UDE.get();
VirtualDirectoryEntries.push_back(std::move(UDE));
// Recursively add the other ancestors.
addAncestorsAsVirtualDirs(DirName);
}
const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
bool CacheFailure) {
// stat doesn't like trailing separators except for root directory.
// At least, on Win32 MSVCRT, stat() cannot strip trailing '/'.
// (though it can strip '\\')
if (DirName.size() > 1 &&
DirName != llvm::sys::path::root_path(DirName) &&
llvm::sys::path::is_separator(DirName.back()))
DirName = DirName.substr(0, DirName.size()-1);
#ifdef _WIN32
// Fixing a problem with "clang C:test.c" on Windows.
// Stat("C:") does not recognize "C:" as a valid directory
std::string DirNameStr;
if (DirName.size() > 1 && DirName.back() == ':' &&
DirName.equals_lower(llvm::sys::path::root_name(DirName))) {
DirNameStr = DirName.str() + '.';
DirName = DirNameStr;
}
#endif
++NumDirLookups;
auto &NamedDirEnt =
*SeenDirEntries.insert(std::make_pair(DirName, nullptr)).first;
// See if there was already an entry in the map. Note that the map
// contains both virtual and real directories.
if (NamedDirEnt.second)
return NamedDirEnt.second == NON_EXISTENT_DIR ? nullptr
: NamedDirEnt.second;
++NumDirCacheMisses;
// By default, initialize it to invalid.
NamedDirEnt.second = NON_EXISTENT_DIR;
// Get the null-terminated directory name as stored as the key of the
// SeenDirEntries map.
StringRef InterndDirName = NamedDirEnt.first();
// Check to see if the directory exists.
FileData Data;
if (getStatValue(InterndDirName, Data, false, nullptr /*directory lookup*/)) {
// There's no real directory at the given path.
if (!CacheFailure)
SeenDirEntries.erase(DirName);
return nullptr;
}
// It exists. See if we have already opened a directory with the
// same inode (this occurs on Unix-like systems when one dir is
// symlinked to another, for example) or the same path (on
// Windows).
DirectoryEntry &UDE = UniqueRealDirs[Data.UniqueID];
NamedDirEnt.second = &UDE;
if (UDE.getName().empty()) {
// We don't have this directory yet, add it. We use the string
// key from the SeenDirEntries map as the string.
UDE.Name = InterndDirName;
}
return &UDE;
}
const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
bool CacheFailure) {
++NumFileLookups;
// See if there is already an entry in the map.
auto &NamedFileEnt =
*SeenFileEntries.insert(std::make_pair(Filename, nullptr)).first;
// See if there is already an entry in the map.
- if (NamedFileEnt.second) {
- if (NamedFileEnt.second == NON_EXISTENT_FILE)
- return nullptr;
- // Entry exists: return it *unless* it wasn't opened and open is requested.
- if (!(NamedFileEnt.second->DeferredOpen && openFile))
- return NamedFileEnt.second;
- // We previously stat()ed the file, but didn't open it: do that below.
- // FIXME: the below does other redundant work too (stats the dir and file).
- } else {
- // By default, initialize it to invalid.
- NamedFileEnt.second = NON_EXISTENT_FILE;
- }
+ if (NamedFileEnt.second)
+ return NamedFileEnt.second == NON_EXISTENT_FILE ? nullptr
+ : NamedFileEnt.second;
++NumFileCacheMisses;
+ // By default, initialize it to invalid.
+ NamedFileEnt.second = NON_EXISTENT_FILE;
+
// Get the null-terminated file name as stored as the key of the
// SeenFileEntries map.
StringRef InterndFileName = NamedFileEnt.first();
// Look up the directory for the file. When looking up something like
// sys/foo.h we'll discover all of the search directories that have a 'sys'
// subdirectory. This will let us avoid having to waste time on known-to-fail
// searches when we go to find sys/bar.h, because all the search directories
// without a 'sys' subdir will get a cached failure result.
const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename,
CacheFailure);
if (DirInfo == nullptr) { // Directory doesn't exist, file can't exist.
if (!CacheFailure)
SeenFileEntries.erase(Filename);
return nullptr;
}
// FIXME: Use the directory info to prune this, before doing the stat syscall.
// FIXME: This will reduce the # syscalls.
// Nope, there isn't. Check to see if the file exists.
std::unique_ptr<llvm::vfs::File> F;
FileData Data;
if (getStatValue(InterndFileName, Data, true, openFile ? &F : nullptr)) {
// There's no real file at the given path.
if (!CacheFailure)
SeenFileEntries.erase(Filename);
return nullptr;
}
assert((openFile || !F) && "undesired open file");
// It exists. See if we have already opened a file with the same inode.
// This occurs when one dir is symlinked to another, for example.
FileEntry &UFE = UniqueRealFiles[Data.UniqueID];
- UFE.DeferredOpen = !openFile;
NamedFileEnt.second = &UFE;
// If the name returned by getStatValue is different than Filename, re-intern
// the name.
if (Data.Name != Filename) {
auto &NamedFileEnt =
*SeenFileEntries.insert(std::make_pair(Data.Name, nullptr)).first;
if (!NamedFileEnt.second)
NamedFileEnt.second = &UFE;
else
assert(NamedFileEnt.second == &UFE &&
"filename from getStatValue() refers to wrong file");
InterndFileName = NamedFileEnt.first().data();
}
- // If we opened the file for the first time, record the resulting info.
- // Do this even if the cache entry was valid, maybe we didn't previously open.
- if (F && !UFE.File) {
- if (auto PathName = F->getName())
- fillRealPathName(&UFE, *PathName);
- UFE.File = std::move(F);
- assert(!UFE.DeferredOpen && "we just opened it!");
- }
-
if (UFE.isValid()) { // Already have an entry with this inode, return it.
// FIXME: this hack ensures that if we look up a file by a virtual path in
// the VFS that the getDir() will have the virtual path, even if we found
// the file by a 'real' path first. This is required in order to find a
// module's structure when its headers/module map are mapped in the VFS.
// We should remove this as soon as we can properly support a file having
// multiple names.
if (DirInfo != UFE.Dir && Data.IsVFSMapped)
UFE.Dir = DirInfo;
// Always update the name to use the last name by which a file was accessed.
// FIXME: Neither this nor always using the first name is correct; we want
// to switch towards a design where we return a FileName object that
// encapsulates both the name by which the file was accessed and the
// corresponding FileEntry.
UFE.Name = InterndFileName;
return &UFE;
}
// Otherwise, we don't have this file yet, add it.
UFE.Name = InterndFileName;
UFE.Size = Data.Size;
UFE.ModTime = Data.ModTime;
UFE.Dir = DirInfo;
UFE.UID = NextFileUID++;
UFE.UniqueID = Data.UniqueID;
UFE.IsNamedPipe = Data.IsNamedPipe;
UFE.InPCH = Data.InPCH;
+ UFE.File = std::move(F);
UFE.IsValid = true;
- // Note File and DeferredOpen were initialized above.
+ if (UFE.File) {
+ if (auto PathName = UFE.File->getName())
+ fillRealPathName(&UFE, *PathName);
+ }
return &UFE;
}
const FileEntry *
FileManager::getVirtualFile(StringRef Filename, off_t Size,
time_t ModificationTime) {
++NumFileLookups;
// See if there is already an entry in the map.
auto &NamedFileEnt =
*SeenFileEntries.insert(std::make_pair(Filename, nullptr)).first;
// See if there is already an entry in the map.
if (NamedFileEnt.second && NamedFileEnt.second != NON_EXISTENT_FILE)
return NamedFileEnt.second;
++NumFileCacheMisses;
// By default, initialize it to invalid.
NamedFileEnt.second = NON_EXISTENT_FILE;
addAncestorsAsVirtualDirs(Filename);
FileEntry *UFE = nullptr;
// Now that all ancestors of Filename are in the cache, the
// following call is guaranteed to find the DirectoryEntry from the
// cache.
const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename,
/*CacheFailure=*/true);
assert(DirInfo &&
"The directory of a virtual file should already be in the cache.");
// Check to see if the file exists. If so, drop the virtual file
FileData Data;
const char *InterndFileName = NamedFileEnt.first().data();
if (getStatValue(InterndFileName, Data, true, nullptr) == 0) {
Data.Size = Size;
Data.ModTime = ModificationTime;
UFE = &UniqueRealFiles[Data.UniqueID];
NamedFileEnt.second = UFE;
// If we had already opened this file, close it now so we don't
// leak the descriptor. We're not going to use the file
// descriptor anyway, since this is a virtual file.
if (UFE->File)
UFE->closeFile();
// If we already have an entry with this inode, return it.
if (UFE->isValid())
return UFE;
UFE->UniqueID = Data.UniqueID;
UFE->IsNamedPipe = Data.IsNamedPipe;
UFE->InPCH = Data.InPCH;
fillRealPathName(UFE, Data.Name);
}
if (!UFE) {
VirtualFileEntries.push_back(llvm::make_unique<FileEntry>());
UFE = VirtualFileEntries.back().get();
NamedFileEnt.second = UFE;
}
UFE->Name = InterndFileName;
UFE->Size = Size;
UFE->ModTime = ModificationTime;
UFE->Dir = DirInfo;
UFE->UID = NextFileUID++;
UFE->IsValid = true;
UFE->File.reset();
- UFE->DeferredOpen = false;
return UFE;
}
bool FileManager::FixupRelativePath(SmallVectorImpl<char> &path) const {
StringRef pathRef(path.data(), path.size());
if (FileSystemOpts.WorkingDir.empty()
|| llvm::sys::path::is_absolute(pathRef))
return false;
SmallString<128> NewPath(FileSystemOpts.WorkingDir);
llvm::sys::path::append(NewPath, pathRef);
path = NewPath;
return true;
}
bool FileManager::makeAbsolutePath(SmallVectorImpl<char> &Path) const {
bool Changed = FixupRelativePath(Path);
if (!llvm::sys::path::is_absolute(StringRef(Path.data(), Path.size()))) {
FS->makeAbsolute(Path);
Changed = true;
}
return Changed;
}
void FileManager::fillRealPathName(FileEntry *UFE, llvm::StringRef FileName) {
llvm::SmallString<128> AbsPath(FileName);
// This is not the same as `VFS::getRealPath()`, which resolves symlinks
// but can be very expensive on real file systems.
// FIXME: the semantic of RealPathName is unclear, and the name might be
// misleading. We need to clean up the interface here.
makeAbsolutePath(AbsPath);
llvm::sys::path::remove_dots(AbsPath, /*remove_dot_dot=*/true);
UFE->RealPathName = AbsPath.str();
}
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
FileManager::getBufferForFile(const FileEntry *Entry, bool isVolatile,
bool ShouldCloseOpenFile) {
uint64_t FileSize = Entry->getSize();
// If there's a high enough chance that the file have changed since we
// got its size, force a stat before opening it.
if (isVolatile)
FileSize = -1;
StringRef Filename = Entry->getName();
// If the file is already open, use the open file descriptor.
if (Entry->File) {
auto Result =
Entry->File->getBuffer(Filename, FileSize,
/*RequiresNullTerminator=*/true, isVolatile);
// FIXME: we need a set of APIs that can make guarantees about whether a
// FileEntry is open or not.
if (ShouldCloseOpenFile)
Entry->closeFile();
return Result;
}
// Otherwise, open the file.
if (FileSystemOpts.WorkingDir.empty())
return FS->getBufferForFile(Filename, FileSize,
/*RequiresNullTerminator=*/true, isVolatile);
SmallString<128> FilePath(Entry->getName());
FixupRelativePath(FilePath);
return FS->getBufferForFile(FilePath, FileSize,
/*RequiresNullTerminator=*/true, isVolatile);
}
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
FileManager::getBufferForFile(StringRef Filename, bool isVolatile) {
if (FileSystemOpts.WorkingDir.empty())
return FS->getBufferForFile(Filename, -1, true, isVolatile);
SmallString<128> FilePath(Filename);
FixupRelativePath(FilePath);
return FS->getBufferForFile(FilePath.c_str(), -1, true, isVolatile);
}
/// getStatValue - Get the 'stat' information for the specified path,
/// using the cache to accelerate it if possible. This returns true
/// if the path points to a virtual file or does not exist, or returns
/// false if it's an existent real file. If FileDescriptor is NULL,
/// do directory look-up instead of file look-up.
bool FileManager::getStatValue(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<llvm::vfs::File> *F) {
// FIXME: FileSystemOpts shouldn't be passed in here, all paths should be
// absolute!
if (FileSystemOpts.WorkingDir.empty())
return FileSystemStatCache::get(Path, Data, isFile, F,StatCache.get(), *FS);
SmallString<128> FilePath(Path);
FixupRelativePath(FilePath);
return FileSystemStatCache::get(FilePath.c_str(), Data, isFile, F,
StatCache.get(), *FS);
}
bool FileManager::getNoncachedStatValue(StringRef Path,
llvm::vfs::Status &Result) {
SmallString<128> FilePath(Path);
FixupRelativePath(FilePath);
llvm::ErrorOr<llvm::vfs::Status> S = FS->status(FilePath.c_str());
if (!S)
return true;
Result = *S;
return false;
}
void FileManager::invalidateCache(const FileEntry *Entry) {
assert(Entry && "Cannot invalidate a NULL FileEntry");
SeenFileEntries.erase(Entry->getName());
// FileEntry invalidation should not block future optimizations in the file
// caches. Possible alternatives are cache truncation (invalidate last N) or
// invalidation of the whole cache.
UniqueRealFiles.erase(Entry->getUniqueID());
}
void FileManager::GetUniqueIDMapping(
SmallVectorImpl<const FileEntry *> &UIDToFiles) const {
UIDToFiles.clear();
UIDToFiles.resize(NextFileUID);
// Map file entries
for (llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator>::const_iterator
FE = SeenFileEntries.begin(), FEEnd = SeenFileEntries.end();
FE != FEEnd; ++FE)
if (FE->getValue() && FE->getValue() != NON_EXISTENT_FILE)
UIDToFiles[FE->getValue()->getUID()] = FE->getValue();
// Map virtual file entries
for (const auto &VFE : VirtualFileEntries)
if (VFE && VFE.get() != NON_EXISTENT_FILE)
UIDToFiles[VFE->getUID()] = VFE.get();
}
void FileManager::modifyFileEntry(FileEntry *File,
off_t Size, time_t ModificationTime) {
File->Size = Size;
File->ModTime = ModificationTime;
}
StringRef FileManager::getCanonicalName(const DirectoryEntry *Dir) {
// FIXME: use llvm::sys::fs::canonical() when it gets implemented
llvm::DenseMap<const DirectoryEntry *, llvm::StringRef>::iterator Known
= CanonicalDirNames.find(Dir);
if (Known != CanonicalDirNames.end())
return Known->second;
StringRef CanonicalName(Dir->getName());
SmallString<4096> CanonicalNameBuf;
if (!FS->getRealPath(Dir->getName(), CanonicalNameBuf))
CanonicalName = StringRef(CanonicalNameBuf).copy(CanonicalNameStorage);
CanonicalDirNames.insert(std::make_pair(Dir, CanonicalName));
return CanonicalName;
}
void FileManager::PrintStats() const {
llvm::errs() << "\n*** File Manager Stats:\n";
llvm::errs() << UniqueRealFiles.size() << " real files found, "
<< UniqueRealDirs.size() << " real dirs found.\n";
llvm::errs() << VirtualFileEntries.size() << " virtual files found, "
<< VirtualDirectoryEntries.size() << " virtual dirs found.\n";
llvm::errs() << NumDirLookups << " dir lookups, "
<< NumDirCacheMisses << " dir cache misses.\n";
llvm::errs() << NumFileLookups << " file lookups, "
<< NumFileCacheMisses << " file cache misses.\n";
//llvm::errs() << PagesMapped << BytesOfPagesMapped << FSLookups;
}
Index: vendor/clang/dist-release_80/lib/Basic/TargetInfo.cpp
===================================================================
--- vendor/clang/dist-release_80/lib/Basic/TargetInfo.cpp (revision 343795)
+++ vendor/clang/dist-release_80/lib/Basic/TargetInfo.cpp (revision 343796)
@@ -1,798 +1,799 @@
//===--- TargetInfo.cpp - Information about Target machine ----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the TargetInfo and TargetInfoImpl interfaces.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetParser.h"
#include <cstdlib>
using namespace clang;
static const LangASMap DefaultAddrSpaceMap = {0};
// TargetInfo Constructor.
TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
// Set defaults. Defaults are set for a 32-bit RISC platform, like PPC or
// SPARC. These should be overridden by concrete targets as needed.
BigEndian = !T.isLittleEndian();
TLSSupported = true;
VLASupported = true;
NoAsmVariants = false;
HasLegalHalfType = false;
HasFloat128 = false;
+ HasFloat16 = false;
PointerWidth = PointerAlign = 32;
BoolWidth = BoolAlign = 8;
IntWidth = IntAlign = 32;
LongWidth = LongAlign = 32;
LongLongWidth = LongLongAlign = 64;
// Fixed point default bit widths
ShortAccumWidth = ShortAccumAlign = 16;
AccumWidth = AccumAlign = 32;
LongAccumWidth = LongAccumAlign = 64;
ShortFractWidth = ShortFractAlign = 8;
FractWidth = FractAlign = 16;
LongFractWidth = LongFractAlign = 32;
// Fixed point default integral and fractional bit sizes
// We give the _Accum 1 fewer fractional bits than their corresponding _Fract
// types by default to have the same number of fractional bits between _Accum
// and _Fract types.
PaddingOnUnsignedFixedPoint = false;
ShortAccumScale = 7;
AccumScale = 15;
LongAccumScale = 31;
SuitableAlign = 64;
DefaultAlignForAttributeAligned = 128;
MinGlobalAlign = 0;
// From the glibc documentation, on GNU systems, malloc guarantees 16-byte
// alignment on 64-bit systems and 8-byte alignment on 32-bit systems. See
// https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.html.
// This alignment guarantee also applies to Windows and Android.
if (T.isGNUEnvironment() || T.isWindowsMSVCEnvironment() || T.isAndroid())
NewAlign = Triple.isArch64Bit() ? 128 : Triple.isArch32Bit() ? 64 : 0;
else
NewAlign = 0; // Infer from basic type alignment.
HalfWidth = 16;
HalfAlign = 16;
FloatWidth = 32;
FloatAlign = 32;
DoubleWidth = 64;
DoubleAlign = 64;
LongDoubleWidth = 64;
LongDoubleAlign = 64;
Float128Align = 128;
LargeArrayMinWidth = 0;
LargeArrayAlign = 0;
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
MaxVectorAlign = 0;
MaxTLSAlign = 0;
SimdDefaultAlign = 0;
SizeType = UnsignedLong;
PtrDiffType = SignedLong;
IntMaxType = SignedLongLong;
IntPtrType = SignedLong;
WCharType = SignedInt;
WIntType = SignedInt;
Char16Type = UnsignedShort;
Char32Type = UnsignedInt;
Int64Type = SignedLongLong;
SigAtomicType = SignedInt;
ProcessIDType = SignedInt;
UseSignedCharForObjCBool = true;
UseBitFieldTypeAlignment = true;
UseZeroLengthBitfieldAlignment = false;
UseExplicitBitFieldAlignment = true;
ZeroLengthBitfieldBoundary = 0;
HalfFormat = &llvm::APFloat::IEEEhalf();
FloatFormat = &llvm::APFloat::IEEEsingle();
DoubleFormat = &llvm::APFloat::IEEEdouble();
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
Float128Format = &llvm::APFloat::IEEEquad();
MCountName = "mcount";
RegParmMax = 0;
SSERegParmMax = 0;
HasAlignMac68kSupport = false;
HasBuiltinMSVaList = false;
IsRenderScriptTarget = false;
// Default to no types using fpret.
RealTypeUsesObjCFPRet = 0;
// Default to not using fp2ret for __Complex long double
ComplexLongDoubleUsesFP2Ret = false;
// Set the C++ ABI based on the triple.
TheCXXABI.set(Triple.isKnownWindowsMSVCEnvironment()
? TargetCXXABI::Microsoft
: TargetCXXABI::GenericItanium);
// Default to an empty address space map.
AddrSpaceMap = &DefaultAddrSpaceMap;
UseAddrSpaceMapMangling = false;
// Default to an unknown platform name.
PlatformName = "unknown";
PlatformMinVersion = VersionTuple();
}
// Out of line virtual dtor for TargetInfo.
TargetInfo::~TargetInfo() {}
bool
TargetInfo::checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const {
Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=branch";
return false;
}
bool
TargetInfo::checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const {
Diags.Report(diag::err_opt_not_valid_on_target) << "cf-protection=return";
return false;
}
/// getTypeName - Return the user string for the specified integer type enum.
/// For example, SignedShort -> "short".
const char *TargetInfo::getTypeName(IntType T) {
switch (T) {
default: llvm_unreachable("not an integer!");
case SignedChar: return "signed char";
case UnsignedChar: return "unsigned char";
case SignedShort: return "short";
case UnsignedShort: return "unsigned short";
case SignedInt: return "int";
case UnsignedInt: return "unsigned int";
case SignedLong: return "long int";
case UnsignedLong: return "long unsigned int";
case SignedLongLong: return "long long int";
case UnsignedLongLong: return "long long unsigned int";
}
}
/// getTypeConstantSuffix - Return the constant suffix for the specified
/// integer type enum. For example, SignedLong -> "L".
const char *TargetInfo::getTypeConstantSuffix(IntType T) const {
switch (T) {
default: llvm_unreachable("not an integer!");
case SignedChar:
case SignedShort:
case SignedInt: return "";
case SignedLong: return "L";
case SignedLongLong: return "LL";
case UnsignedChar:
if (getCharWidth() < getIntWidth())
return "";
LLVM_FALLTHROUGH;
case UnsignedShort:
if (getShortWidth() < getIntWidth())
return "";
LLVM_FALLTHROUGH;
case UnsignedInt: return "U";
case UnsignedLong: return "UL";
case UnsignedLongLong: return "ULL";
}
}
/// getTypeFormatModifier - Return the printf format modifier for the
/// specified integer type enum. For example, SignedLong -> "l".
const char *TargetInfo::getTypeFormatModifier(IntType T) {
switch (T) {
default: llvm_unreachable("not an integer!");
case SignedChar:
case UnsignedChar: return "hh";
case SignedShort:
case UnsignedShort: return "h";
case SignedInt:
case UnsignedInt: return "";
case SignedLong:
case UnsignedLong: return "l";
case SignedLongLong:
case UnsignedLongLong: return "ll";
}
}
/// getTypeWidth - Return the width (in bits) of the specified integer type
/// enum. For example, SignedInt -> getIntWidth().
unsigned TargetInfo::getTypeWidth(IntType T) const {
switch (T) {
default: llvm_unreachable("not an integer!");
case SignedChar:
case UnsignedChar: return getCharWidth();
case SignedShort:
case UnsignedShort: return getShortWidth();
case SignedInt:
case UnsignedInt: return getIntWidth();
case SignedLong:
case UnsignedLong: return getLongWidth();
case SignedLongLong:
case UnsignedLongLong: return getLongLongWidth();
};
}
TargetInfo::IntType TargetInfo::getIntTypeByWidth(
unsigned BitWidth, bool IsSigned) const {
if (getCharWidth() == BitWidth)
return IsSigned ? SignedChar : UnsignedChar;
if (getShortWidth() == BitWidth)
return IsSigned ? SignedShort : UnsignedShort;
if (getIntWidth() == BitWidth)
return IsSigned ? SignedInt : UnsignedInt;
if (getLongWidth() == BitWidth)
return IsSigned ? SignedLong : UnsignedLong;
if (getLongLongWidth() == BitWidth)
return IsSigned ? SignedLongLong : UnsignedLongLong;
return NoInt;
}
TargetInfo::IntType TargetInfo::getLeastIntTypeByWidth(unsigned BitWidth,
bool IsSigned) const {
if (getCharWidth() >= BitWidth)
return IsSigned ? SignedChar : UnsignedChar;
if (getShortWidth() >= BitWidth)
return IsSigned ? SignedShort : UnsignedShort;
if (getIntWidth() >= BitWidth)
return IsSigned ? SignedInt : UnsignedInt;
if (getLongWidth() >= BitWidth)
return IsSigned ? SignedLong : UnsignedLong;
if (getLongLongWidth() >= BitWidth)
return IsSigned ? SignedLongLong : UnsignedLongLong;
return NoInt;
}
TargetInfo::RealType TargetInfo::getRealTypeByWidth(unsigned BitWidth) const {
if (getFloatWidth() == BitWidth)
return Float;
if (getDoubleWidth() == BitWidth)
return Double;
switch (BitWidth) {
case 96:
if (&getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended())
return LongDouble;
break;
case 128:
if (&getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble() ||
&getLongDoubleFormat() == &llvm::APFloat::IEEEquad())
return LongDouble;
if (hasFloat128Type())
return Float128;
break;
}
return NoFloat;
}
/// getTypeAlign - Return the alignment (in bits) of the specified integer type
/// enum. For example, SignedInt -> getIntAlign().
unsigned TargetInfo::getTypeAlign(IntType T) const {
switch (T) {
default: llvm_unreachable("not an integer!");
case SignedChar:
case UnsignedChar: return getCharAlign();
case SignedShort:
case UnsignedShort: return getShortAlign();
case SignedInt:
case UnsignedInt: return getIntAlign();
case SignedLong:
case UnsignedLong: return getLongAlign();
case SignedLongLong:
case UnsignedLongLong: return getLongLongAlign();
};
}
/// isTypeSigned - Return whether an integer types is signed. Returns true if
/// the type is signed; false otherwise.
bool TargetInfo::isTypeSigned(IntType T) {
switch (T) {
default: llvm_unreachable("not an integer!");
case SignedChar:
case SignedShort:
case SignedInt:
case SignedLong:
case SignedLongLong:
return true;
case UnsignedChar:
case UnsignedShort:
case UnsignedInt:
case UnsignedLong:
case UnsignedLongLong:
return false;
};
}
/// adjust - Set forced language options.
/// Apply changes to the target information with respect to certain
/// language options which change the target configuration and adjust
/// the language based on the target options where applicable.
void TargetInfo::adjust(LangOptions &Opts) {
if (Opts.NoBitFieldTypeAlign)
UseBitFieldTypeAlignment = false;
switch (Opts.WCharSize) {
default: llvm_unreachable("invalid wchar_t width");
case 0: break;
case 1: WCharType = Opts.WCharIsSigned ? SignedChar : UnsignedChar; break;
case 2: WCharType = Opts.WCharIsSigned ? SignedShort : UnsignedShort; break;
case 4: WCharType = Opts.WCharIsSigned ? SignedInt : UnsignedInt; break;
}
if (Opts.AlignDouble) {
DoubleAlign = LongLongAlign = 64;
LongDoubleAlign = 64;
}
if (Opts.OpenCL) {
// OpenCL C requires specific widths for types, irrespective of
// what these normally are for the target.
// We also define long long and long double here, although the
// OpenCL standard only mentions these as "reserved".
IntWidth = IntAlign = 32;
LongWidth = LongAlign = 64;
LongLongWidth = LongLongAlign = 128;
HalfWidth = HalfAlign = 16;
FloatWidth = FloatAlign = 32;
// Embedded 32-bit targets (OpenCL EP) might have double C type
// defined as float. Let's not override this as it might lead
// to generating illegal code that uses 64bit doubles.
if (DoubleWidth != FloatWidth) {
DoubleWidth = DoubleAlign = 64;
DoubleFormat = &llvm::APFloat::IEEEdouble();
}
LongDoubleWidth = LongDoubleAlign = 128;
unsigned MaxPointerWidth = getMaxPointerWidth();
assert(MaxPointerWidth == 32 || MaxPointerWidth == 64);
bool Is32BitArch = MaxPointerWidth == 32;
SizeType = Is32BitArch ? UnsignedInt : UnsignedLong;
PtrDiffType = Is32BitArch ? SignedInt : SignedLong;
IntPtrType = Is32BitArch ? SignedInt : SignedLong;
IntMaxType = SignedLongLong;
Int64Type = SignedLong;
HalfFormat = &llvm::APFloat::IEEEhalf();
FloatFormat = &llvm::APFloat::IEEEsingle();
LongDoubleFormat = &llvm::APFloat::IEEEquad();
}
if (Opts.NewAlignOverride)
NewAlign = Opts.NewAlignOverride * getCharWidth();
// Each unsigned fixed point type has the same number of fractional bits as
// its corresponding signed type.
PaddingOnUnsignedFixedPoint |= Opts.PaddingOnUnsignedFixedPoint;
CheckFixedPointBits();
}
bool TargetInfo::initFeatureMap(
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
const std::vector<std::string> &FeatureVec) const {
for (const auto &F : FeatureVec) {
StringRef Name = F;
// Apply the feature via the target.
bool Enabled = Name[0] == '+';
setFeatureEnabled(Features, Name.substr(1), Enabled);
}
return true;
}
TargetInfo::CallingConvKind
TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
if (getCXXABI() != TargetCXXABI::Microsoft &&
(ClangABICompat4 || getTriple().getOS() == llvm::Triple::PS4))
return CCK_ClangABI4OrPS4;
return CCK_Default;
}
LangAS TargetInfo::getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const {
switch (TK) {
case OCLTK_Image:
case OCLTK_Pipe:
return LangAS::opencl_global;
case OCLTK_Sampler:
return LangAS::opencl_constant;
default:
return LangAS::Default;
}
}
//===----------------------------------------------------------------------===//
static StringRef removeGCCRegisterPrefix(StringRef Name) {
if (Name[0] == '%' || Name[0] == '#')
Name = Name.substr(1);
return Name;
}
/// isValidClobber - Returns whether the passed in string is
/// a valid clobber in an inline asm statement. This is used by
/// Sema.
bool TargetInfo::isValidClobber(StringRef Name) const {
return (isValidGCCRegisterName(Name) ||
Name == "memory" || Name == "cc");
}
/// isValidGCCRegisterName - Returns whether the passed in string
/// is a valid register name according to GCC. This is used by Sema for
/// inline asm statements.
bool TargetInfo::isValidGCCRegisterName(StringRef Name) const {
if (Name.empty())
return false;
// Get rid of any register prefix.
Name = removeGCCRegisterPrefix(Name);
if (Name.empty())
return false;
ArrayRef<const char *> Names = getGCCRegNames();
// If we have a number it maps to an entry in the register name array.
if (isDigit(Name[0])) {
unsigned n;
if (!Name.getAsInteger(0, n))
return n < Names.size();
}
// Check register names.
if (std::find(Names.begin(), Names.end(), Name) != Names.end())
return true;
// Check any additional names that we have.
for (const AddlRegName &ARN : getGCCAddlRegNames())
for (const char *AN : ARN.Names) {
if (!AN)
break;
// Make sure the register that the additional name is for is within
// the bounds of the register names from above.
if (AN == Name && ARN.RegNum < Names.size())
return true;
}
// Now check aliases.
for (const GCCRegAlias &GRA : getGCCRegAliases())
for (const char *A : GRA.Aliases) {
if (!A)
break;
if (A == Name)
return true;
}
return false;
}
StringRef TargetInfo::getNormalizedGCCRegisterName(StringRef Name,
bool ReturnCanonical) const {
assert(isValidGCCRegisterName(Name) && "Invalid register passed in");
// Get rid of any register prefix.
Name = removeGCCRegisterPrefix(Name);
ArrayRef<const char *> Names = getGCCRegNames();
// First, check if we have a number.
if (isDigit(Name[0])) {
unsigned n;
if (!Name.getAsInteger(0, n)) {
assert(n < Names.size() && "Out of bounds register number!");
return Names[n];
}
}
// Check any additional names that we have.
for (const AddlRegName &ARN : getGCCAddlRegNames())
for (const char *AN : ARN.Names) {
if (!AN)
break;
// Make sure the register that the additional name is for is within
// the bounds of the register names from above.
if (AN == Name && ARN.RegNum < Names.size())
return ReturnCanonical ? Names[ARN.RegNum] : Name;
}
// Now check aliases.
for (const GCCRegAlias &RA : getGCCRegAliases())
for (const char *A : RA.Aliases) {
if (!A)
break;
if (A == Name)
return RA.Register;
}
return Name;
}
bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const {
const char *Name = Info.getConstraintStr().c_str();
// An output constraint must start with '=' or '+'
if (*Name != '=' && *Name != '+')
return false;
if (*Name == '+')
Info.setIsReadWrite();
Name++;
while (*Name) {
switch (*Name) {
default:
if (!validateAsmConstraint(Name, Info)) {
// FIXME: We temporarily return false
// so we can add more constraints as we hit it.
// Eventually, an unknown constraint should just be treated as 'g'.
return false;
}
break;
case '&': // early clobber.
Info.setEarlyClobber();
break;
case '%': // commutative.
// FIXME: Check that there is a another register after this one.
break;
case 'r': // general register.
Info.setAllowsRegister();
break;
case 'm': // memory operand.
case 'o': // offsetable memory operand.
case 'V': // non-offsetable memory operand.
case '<': // autodecrement memory operand.
case '>': // autoincrement memory operand.
Info.setAllowsMemory();
break;
case 'g': // general register, memory operand or immediate integer.
case 'X': // any operand.
Info.setAllowsRegister();
Info.setAllowsMemory();
break;
case ',': // multiple alternative constraint. Pass it.
// Handle additional optional '=' or '+' modifiers.
if (Name[1] == '=' || Name[1] == '+')
Name++;
break;
case '#': // Ignore as constraint.
while (Name[1] && Name[1] != ',')
Name++;
break;
case '?': // Disparage slightly code.
case '!': // Disparage severely.
case '*': // Ignore for choosing register preferences.
case 'i': // Ignore i,n,E,F as output constraints (match from the other
// chars)
case 'n':
case 'E':
case 'F':
break; // Pass them.
}
Name++;
}
// Early clobber with a read-write constraint which doesn't permit registers
// is invalid.
if (Info.earlyClobber() && Info.isReadWrite() && !Info.allowsRegister())
return false;
// If a constraint allows neither memory nor register operands it contains
// only modifiers. Reject it.
return Info.allowsMemory() || Info.allowsRegister();
}
bool TargetInfo::resolveSymbolicName(const char *&Name,
ArrayRef<ConstraintInfo> OutputConstraints,
unsigned &Index) const {
assert(*Name == '[' && "Symbolic name did not start with '['");
Name++;
const char *Start = Name;
while (*Name && *Name != ']')
Name++;
if (!*Name) {
// Missing ']'
return false;
}
std::string SymbolicName(Start, Name - Start);
for (Index = 0; Index != OutputConstraints.size(); ++Index)
if (SymbolicName == OutputConstraints[Index].getName())
return true;
return false;
}
bool TargetInfo::validateInputConstraint(
MutableArrayRef<ConstraintInfo> OutputConstraints,
ConstraintInfo &Info) const {
const char *Name = Info.ConstraintStr.c_str();
if (!*Name)
return false;
while (*Name) {
switch (*Name) {
default:
// Check if we have a matching constraint
if (*Name >= '0' && *Name <= '9') {
const char *DigitStart = Name;
while (Name[1] >= '0' && Name[1] <= '9')
Name++;
const char *DigitEnd = Name;
unsigned i;
if (StringRef(DigitStart, DigitEnd - DigitStart + 1)
.getAsInteger(10, i))
return false;
// Check if matching constraint is out of bounds.
if (i >= OutputConstraints.size()) return false;
// A number must refer to an output only operand.
if (OutputConstraints[i].isReadWrite())
return false;
// If the constraint is already tied, it must be tied to the
// same operand referenced to by the number.
if (Info.hasTiedOperand() && Info.getTiedOperand() != i)
return false;
// The constraint should have the same info as the respective
// output constraint.
Info.setTiedOperand(i, OutputConstraints[i]);
} else if (!validateAsmConstraint(Name, Info)) {
// FIXME: This error return is in place temporarily so we can
// add more constraints as we hit it. Eventually, an unknown
// constraint should just be treated as 'g'.
return false;
}
break;
case '[': {
unsigned Index = 0;
if (!resolveSymbolicName(Name, OutputConstraints, Index))
return false;
// If the constraint is already tied, it must be tied to the
// same operand referenced to by the number.
if (Info.hasTiedOperand() && Info.getTiedOperand() != Index)
return false;
// A number must refer to an output only operand.
if (OutputConstraints[Index].isReadWrite())
return false;
Info.setTiedOperand(Index, OutputConstraints[Index]);
break;
}
case '%': // commutative
// FIXME: Fail if % is used with the last operand.
break;
case 'i': // immediate integer.
break;
case 'n': // immediate integer with a known value.
Info.setRequiresImmediate();
break;
case 'I': // Various constant constraints with target-specific meanings.
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
if (!validateAsmConstraint(Name, Info))
return false;
break;
case 'r': // general register.
Info.setAllowsRegister();
break;
case 'm': // memory operand.
case 'o': // offsettable memory operand.
case 'V': // non-offsettable memory operand.
case '<': // autodecrement memory operand.
case '>': // autoincrement memory operand.
Info.setAllowsMemory();
break;
case 'g': // general register, memory operand or immediate integer.
case 'X': // any operand.
Info.setAllowsRegister();
Info.setAllowsMemory();
break;
case 'E': // immediate floating point.
case 'F': // immediate floating point.
case 'p': // address operand.
break;
case ',': // multiple alternative constraint. Ignore comma.
break;
case '#': // Ignore as constraint.
while (Name[1] && Name[1] != ',')
Name++;
break;
case '?': // Disparage slightly code.
case '!': // Disparage severely.
case '*': // Ignore for choosing register preferences.
break; // Pass them.
}
Name++;
}
return true;
}
void TargetInfo::CheckFixedPointBits() const {
// Check that the number of fractional and integral bits (and maybe sign) can
// fit into the bits given for a fixed point type.
assert(ShortAccumScale + getShortAccumIBits() + 1 <= ShortAccumWidth);
assert(AccumScale + getAccumIBits() + 1 <= AccumWidth);
assert(LongAccumScale + getLongAccumIBits() + 1 <= LongAccumWidth);
assert(getUnsignedShortAccumScale() + getUnsignedShortAccumIBits() <=
ShortAccumWidth);
assert(getUnsignedAccumScale() + getUnsignedAccumIBits() <= AccumWidth);
assert(getUnsignedLongAccumScale() + getUnsignedLongAccumIBits() <=
LongAccumWidth);
assert(getShortFractScale() + 1 <= ShortFractWidth);
assert(getFractScale() + 1 <= FractWidth);
assert(getLongFractScale() + 1 <= LongFractWidth);
assert(getUnsignedShortFractScale() <= ShortFractWidth);
assert(getUnsignedFractScale() <= FractWidth);
assert(getUnsignedLongFractScale() <= LongFractWidth);
// Each unsigned fract type has either the same number of fractional bits
// as, or one more fractional bit than, its corresponding signed fract type.
assert(getShortFractScale() == getUnsignedShortFractScale() ||
getShortFractScale() == getUnsignedShortFractScale() - 1);
assert(getFractScale() == getUnsignedFractScale() ||
getFractScale() == getUnsignedFractScale() - 1);
assert(getLongFractScale() == getUnsignedLongFractScale() ||
getLongFractScale() == getUnsignedLongFractScale() - 1);
// When arranged in order of increasing rank (see 6.3.1.3a), the number of
// fractional bits is nondecreasing for each of the following sets of
// fixed-point types:
// - signed fract types
// - unsigned fract types
// - signed accum types
// - unsigned accum types.
assert(getLongFractScale() >= getFractScale() &&
getFractScale() >= getShortFractScale());
assert(getUnsignedLongFractScale() >= getUnsignedFractScale() &&
getUnsignedFractScale() >= getUnsignedShortFractScale());
assert(LongAccumScale >= AccumScale && AccumScale >= ShortAccumScale);
assert(getUnsignedLongAccumScale() >= getUnsignedAccumScale() &&
getUnsignedAccumScale() >= getUnsignedShortAccumScale());
// When arranged in order of increasing rank (see 6.3.1.3a), the number of
// integral bits is nondecreasing for each of the following sets of
// fixed-point types:
// - signed accum types
// - unsigned accum types
assert(getLongAccumIBits() >= getAccumIBits() &&
getAccumIBits() >= getShortAccumIBits());
assert(getUnsignedLongAccumIBits() >= getUnsignedAccumIBits() &&
getUnsignedAccumIBits() >= getUnsignedShortAccumIBits());
// Each signed accum type has at least as many integral bits as its
// corresponding unsigned accum type.
assert(getShortAccumIBits() >= getUnsignedShortAccumIBits());
assert(getAccumIBits() >= getUnsignedAccumIBits());
assert(getLongAccumIBits() >= getUnsignedLongAccumIBits());
}
Index: vendor/clang/dist-release_80/lib/Basic/Targets/AArch64.cpp
===================================================================
--- vendor/clang/dist-release_80/lib/Basic/Targets/AArch64.cpp (revision 343795)
+++ vendor/clang/dist-release_80/lib/Basic/Targets/AArch64.cpp (revision 343796)
@@ -1,599 +1,600 @@
//===--- AArch64.cpp - Implement AArch64 target feature support -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements AArch64 TargetInfo objects.
//
//===----------------------------------------------------------------------===//
#include "AArch64.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
using namespace clang::targets;
const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#include "clang/Basic/BuiltinsNEON.def"
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
{#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
{#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
#include "clang/Basic/BuiltinsAArch64.def"
};
AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: TargetInfo(Triple), ABI("aapcs") {
if (getTriple().isOSOpenBSD()) {
Int64Type = SignedLongLong;
IntMaxType = SignedLongLong;
} else {
if (!getTriple().isOSDarwin() && !getTriple().isOSNetBSD())
WCharType = UnsignedInt;
Int64Type = SignedLong;
IntMaxType = SignedLong;
}
// All AArch64 implementations support ARMv8 FP, which makes half a legal type.
HasLegalHalfType = true;
+ HasFloat16 = true;
LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
MaxVectorAlign = 128;
MaxAtomicInlineWidth = 128;
MaxAtomicPromoteWidth = 128;
LongDoubleWidth = LongDoubleAlign = SuitableAlign = 128;
LongDoubleFormat = &llvm::APFloat::IEEEquad();
// Make __builtin_ms_va_list available.
HasBuiltinMSVaList = true;
// {} in inline assembly are neon specifiers, not assembly variant
// specifiers.
NoAsmVariants = true;
// AAPCS gives rules for bitfields. 7.1.7 says: "The container type
// contributes to the alignment of the containing aggregate in the same way
// a plain (non bit-field) member of that type would, without exception for
// zero-sized or anonymous bit-fields."
assert(UseBitFieldTypeAlignment && "bitfields affect type alignment");
UseZeroLengthBitfieldAlignment = true;
// AArch64 targets default to using the ARM C++ ABI.
TheCXXABI.set(TargetCXXABI::GenericAArch64);
if (Triple.getOS() == llvm::Triple::Linux)
this->MCountName = "\01_mcount";
else if (Triple.getOS() == llvm::Triple::UnknownOS)
this->MCountName =
Opts.EABIVersion == llvm::EABI::GNU ? "\01_mcount" : "mcount";
}
StringRef AArch64TargetInfo::getABI() const { return ABI; }
bool AArch64TargetInfo::setABI(const std::string &Name) {
if (Name != "aapcs" && Name != "darwinpcs")
return false;
ABI = Name;
return true;
}
bool AArch64TargetInfo::isValidCPUName(StringRef Name) const {
return Name == "generic" ||
llvm::AArch64::parseCPUArch(Name) != llvm::AArch64::ArchKind::INVALID;
}
bool AArch64TargetInfo::setCPU(const std::string &Name) {
return isValidCPUName(Name);
}
void AArch64TargetInfo::fillValidCPUList(
SmallVectorImpl<StringRef> &Values) const {
llvm::AArch64::fillValidCPUArchList(Values);
}
void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
}
void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
MacroBuilder &Builder) const {
// Also include the ARMv8.1 defines
getTargetDefinesARMV81A(Opts, Builder);
}
void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
// Target identification.
Builder.defineMacro("__aarch64__");
// For bare-metal.
if (getTriple().getOS() == llvm::Triple::UnknownOS &&
getTriple().isOSBinFormatELF())
Builder.defineMacro("__ELF__");
// Target properties.
if (!getTriple().isOSWindows()) {
Builder.defineMacro("_LP64");
Builder.defineMacro("__LP64__");
}
// ACLE predefines. Many can only have one possible value on v8 AArch64.
Builder.defineMacro("__ARM_ACLE", "200");
Builder.defineMacro("__ARM_ARCH", "8");
Builder.defineMacro("__ARM_ARCH_PROFILE", "'A'");
Builder.defineMacro("__ARM_64BIT_STATE", "1");
Builder.defineMacro("__ARM_PCS_AAPCS64", "1");
Builder.defineMacro("__ARM_ARCH_ISA_A64", "1");
Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
Builder.defineMacro("__ARM_FEATURE_FMA", "1");
Builder.defineMacro("__ARM_FEATURE_LDREX", "0xF");
Builder.defineMacro("__ARM_FEATURE_IDIV", "1"); // As specified in ACLE
Builder.defineMacro("__ARM_FEATURE_DIV"); // For backwards compatibility
Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
Builder.defineMacro("__ARM_ALIGN_MAX_STACK_PWR", "4");
// 0xe implies support for half, single and double precision operations.
Builder.defineMacro("__ARM_FP", "0xE");
// PCS specifies this for SysV variants, which is all we support. Other ABIs
// may choose __ARM_FP16_FORMAT_ALTERNATIVE.
Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
Builder.defineMacro("__ARM_FP16_ARGS", "1");
if (Opts.UnsafeFPMath)
Builder.defineMacro("__ARM_FP_FAST", "1");
Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
Twine(Opts.WCharSize ? Opts.WCharSize : 4));
Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
if (FPU & NeonMode) {
Builder.defineMacro("__ARM_NEON", "1");
// 64-bit NEON supports half, single and double precision operations.
Builder.defineMacro("__ARM_NEON_FP", "0xE");
}
if (FPU & SveMode)
Builder.defineMacro("__ARM_FEATURE_SVE", "1");
if (CRC)
Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
if (Crypto)
Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
if (Unaligned)
Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
if ((FPU & NeonMode) && HasFullFP16)
Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
if (HasFullFP16)
Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
if (HasDotProd)
Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
if ((FPU & NeonMode) && HasFP16FML)
Builder.defineMacro("__ARM_FEATURE_FP16FML", "1");
switch (ArchKind) {
default:
break;
case llvm::AArch64::ArchKind::ARMV8_1A:
getTargetDefinesARMV81A(Opts, Builder);
break;
case llvm::AArch64::ArchKind::ARMV8_2A:
getTargetDefinesARMV82A(Opts, Builder);
break;
}
// All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work.
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
}
ArrayRef<Builtin::Info> AArch64TargetInfo::getTargetBuiltins() const {
return llvm::makeArrayRef(BuiltinInfo, clang::AArch64::LastTSBuiltin -
Builtin::FirstTSBuiltin);
}
bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
return Feature == "aarch64" || Feature == "arm64" || Feature == "arm" ||
(Feature == "neon" && (FPU & NeonMode)) ||
(Feature == "sve" && (FPU & SveMode));
}
bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) {
FPU = FPUMode;
CRC = 0;
Crypto = 0;
Unaligned = 1;
HasFullFP16 = 0;
HasDotProd = 0;
HasFP16FML = 0;
ArchKind = llvm::AArch64::ArchKind::ARMV8A;
for (const auto &Feature : Features) {
if (Feature == "+neon")
FPU |= NeonMode;
if (Feature == "+sve")
FPU |= SveMode;
if (Feature == "+crc")
CRC = 1;
if (Feature == "+crypto")
Crypto = 1;
if (Feature == "+strict-align")
Unaligned = 0;
if (Feature == "+v8.1a")
ArchKind = llvm::AArch64::ArchKind::ARMV8_1A;
if (Feature == "+v8.2a")
ArchKind = llvm::AArch64::ArchKind::ARMV8_2A;
if (Feature == "+fullfp16")
HasFullFP16 = 1;
if (Feature == "+dotprod")
HasDotProd = 1;
if (Feature == "+fp16fml")
HasFP16FML = 1;
}
setDataLayout();
return true;
}
TargetInfo::CallingConvCheckResult
AArch64TargetInfo::checkCallingConvention(CallingConv CC) const {
switch (CC) {
case CC_C:
case CC_Swift:
case CC_PreserveMost:
case CC_PreserveAll:
case CC_OpenCLKernel:
case CC_AArch64VectorCall:
case CC_Win64:
return CCCR_OK;
default:
return CCCR_Warning;
}
}
bool AArch64TargetInfo::isCLZForZeroUndef() const { return false; }
TargetInfo::BuiltinVaListKind AArch64TargetInfo::getBuiltinVaListKind() const {
return TargetInfo::AArch64ABIBuiltinVaList;
}
const char *const AArch64TargetInfo::GCCRegNames[] = {
// 32-bit Integer registers
"w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", "w8", "w9", "w10", "w11",
"w12", "w13", "w14", "w15", "w16", "w17", "w18", "w19", "w20", "w21", "w22",
"w23", "w24", "w25", "w26", "w27", "w28", "w29", "w30", "wsp",
// 64-bit Integer registers
"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
"x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22",
"x23", "x24", "x25", "x26", "x27", "x28", "fp", "lr", "sp",
// 32-bit floating point regsisters
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
"s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
"s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
// 64-bit floating point regsisters
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
"d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
"d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
// Vector registers
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
"v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21", "v22",
"v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
};
ArrayRef<const char *> AArch64TargetInfo::getGCCRegNames() const {
return llvm::makeArrayRef(GCCRegNames);
}
const TargetInfo::GCCRegAlias AArch64TargetInfo::GCCRegAliases[] = {
{{"w31"}, "wsp"},
{{"x31"}, "sp"},
// GCC rN registers are aliases of xN registers.
{{"r0"}, "x0"},
{{"r1"}, "x1"},
{{"r2"}, "x2"},
{{"r3"}, "x3"},
{{"r4"}, "x4"},
{{"r5"}, "x5"},
{{"r6"}, "x6"},
{{"r7"}, "x7"},
{{"r8"}, "x8"},
{{"r9"}, "x9"},
{{"r10"}, "x10"},
{{"r11"}, "x11"},
{{"r12"}, "x12"},
{{"r13"}, "x13"},
{{"r14"}, "x14"},
{{"r15"}, "x15"},
{{"r16"}, "x16"},
{{"r17"}, "x17"},
{{"r18"}, "x18"},
{{"r19"}, "x19"},
{{"r20"}, "x20"},
{{"r21"}, "x21"},
{{"r22"}, "x22"},
{{"r23"}, "x23"},
{{"r24"}, "x24"},
{{"r25"}, "x25"},
{{"r26"}, "x26"},
{{"r27"}, "x27"},
{{"r28"}, "x28"},
{{"r29", "x29"}, "fp"},
{{"r30", "x30"}, "lr"},
// The S/D/Q and W/X registers overlap, but aren't really aliases; we
// don't want to substitute one of these for a different-sized one.
};
ArrayRef<TargetInfo::GCCRegAlias> AArch64TargetInfo::getGCCRegAliases() const {
return llvm::makeArrayRef(GCCRegAliases);
}
bool AArch64TargetInfo::validateAsmConstraint(
const char *&Name, TargetInfo::ConstraintInfo &Info) const {
switch (*Name) {
default:
return false;
case 'w': // Floating point and SIMD registers (V0-V31)
Info.setAllowsRegister();
return true;
case 'I': // Constant that can be used with an ADD instruction
case 'J': // Constant that can be used with a SUB instruction
case 'K': // Constant that can be used with a 32-bit logical instruction
case 'L': // Constant that can be used with a 64-bit logical instruction
case 'M': // Constant that can be used as a 32-bit MOV immediate
case 'N': // Constant that can be used as a 64-bit MOV immediate
case 'Y': // Floating point constant zero
case 'Z': // Integer constant zero
return true;
case 'Q': // A memory reference with base register and no offset
Info.setAllowsMemory();
return true;
case 'S': // A symbolic address
Info.setAllowsRegister();
return true;
case 'U':
// Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
// Utf: A memory address suitable for ldp/stp in TF mode.
// Usa: An absolute symbolic address.
// Ush: The high part (bits 32:12) of a pc-relative symbolic address.
llvm_unreachable("FIXME: Unimplemented support for U* constraints.");
case 'z': // Zero register, wzr or xzr
Info.setAllowsRegister();
return true;
case 'x': // Floating point and SIMD registers (V0-V15)
Info.setAllowsRegister();
return true;
}
return false;
}
bool AArch64TargetInfo::validateConstraintModifier(
StringRef Constraint, char Modifier, unsigned Size,
std::string &SuggestedModifier) const {
// Strip off constraint modifiers.
while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
Constraint = Constraint.substr(1);
switch (Constraint[0]) {
default:
return true;
case 'z':
case 'r': {
switch (Modifier) {
case 'x':
case 'w':
// For now assume that the person knows what they're
// doing with the modifier.
return true;
default:
// By default an 'r' constraint will be in the 'x'
// registers.
if (Size == 64)
return true;
SuggestedModifier = "w";
return false;
}
}
}
}
const char *AArch64TargetInfo::getClobbers() const { return ""; }
int AArch64TargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
if (RegNo == 0)
return 0;
if (RegNo == 1)
return 1;
return -1;
}
AArch64leTargetInfo::AArch64leTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: AArch64TargetInfo(Triple, Opts) {}
void AArch64leTargetInfo::setDataLayout() {
if (getTriple().isOSBinFormatMachO())
resetDataLayout("e-m:o-i64:64-i128:128-n32:64-S128");
else
resetDataLayout("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
}
void AArch64leTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__AARCH64EL__");
AArch64TargetInfo::getTargetDefines(Opts, Builder);
}
AArch64beTargetInfo::AArch64beTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: AArch64TargetInfo(Triple, Opts) {}
void AArch64beTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__AARCH64EB__");
Builder.defineMacro("__AARCH_BIG_ENDIAN");
Builder.defineMacro("__ARM_BIG_ENDIAN");
AArch64TargetInfo::getTargetDefines(Opts, Builder);
}
void AArch64beTargetInfo::setDataLayout() {
assert(!getTriple().isOSBinFormatMachO());
resetDataLayout("E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128");
}
WindowsARM64TargetInfo::WindowsARM64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: WindowsTargetInfo<AArch64leTargetInfo>(Triple, Opts), Triple(Triple) {
// This is an LLP64 platform.
// int:4, long:4, long long:8, long double:8.
IntWidth = IntAlign = 32;
LongWidth = LongAlign = 32;
DoubleAlign = LongLongAlign = 64;
LongDoubleWidth = LongDoubleAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
IntMaxType = SignedLongLong;
Int64Type = SignedLongLong;
SizeType = UnsignedLongLong;
PtrDiffType = SignedLongLong;
IntPtrType = SignedLongLong;
}
void WindowsARM64TargetInfo::setDataLayout() {
resetDataLayout("e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128");
}
TargetInfo::BuiltinVaListKind
WindowsARM64TargetInfo::getBuiltinVaListKind() const {
return TargetInfo::CharPtrBuiltinVaList;
}
TargetInfo::CallingConvCheckResult
WindowsARM64TargetInfo::checkCallingConvention(CallingConv CC) const {
switch (CC) {
case CC_X86StdCall:
case CC_X86ThisCall:
case CC_X86FastCall:
case CC_X86VectorCall:
return CCCR_Ignore;
case CC_C:
case CC_OpenCLKernel:
case CC_PreserveMost:
case CC_PreserveAll:
case CC_Swift:
case CC_Win64:
return CCCR_OK;
default:
return CCCR_Warning;
}
}
MicrosoftARM64TargetInfo::MicrosoftARM64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: WindowsARM64TargetInfo(Triple, Opts) {
TheCXXABI.set(TargetCXXABI::Microsoft);
}
void MicrosoftARM64TargetInfo::getVisualStudioDefines(
const LangOptions &Opts, MacroBuilder &Builder) const {
WindowsTargetInfo<AArch64leTargetInfo>::getVisualStudioDefines(Opts, Builder);
Builder.defineMacro("_M_ARM64", "1");
}
void MicrosoftARM64TargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
WindowsTargetInfo::getTargetDefines(Opts, Builder);
getVisualStudioDefines(Opts, Builder);
}
TargetInfo::CallingConvKind
MicrosoftARM64TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
return CCK_MicrosoftWin64;
}
MinGWARM64TargetInfo::MinGWARM64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: WindowsARM64TargetInfo(Triple, Opts) {
TheCXXABI.set(TargetCXXABI::GenericAArch64);
}
DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: DarwinTargetInfo<AArch64leTargetInfo>(Triple, Opts) {
Int64Type = SignedLongLong;
UseSignedCharForObjCBool = false;
LongDoubleWidth = LongDoubleAlign = SuitableAlign = 64;
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
TheCXXABI.set(TargetCXXABI::iOS64);
}
void DarwinAArch64TargetInfo::getOSDefines(const LangOptions &Opts,
const llvm::Triple &Triple,
MacroBuilder &Builder) const {
Builder.defineMacro("__AARCH64_SIMD__");
Builder.defineMacro("__ARM64_ARCH_8__");
Builder.defineMacro("__ARM_NEON__");
Builder.defineMacro("__LITTLE_ENDIAN__");
Builder.defineMacro("__REGISTER_PREFIX__", "");
Builder.defineMacro("__arm64", "1");
Builder.defineMacro("__arm64__", "1");
getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
}
TargetInfo::BuiltinVaListKind
DarwinAArch64TargetInfo::getBuiltinVaListKind() const {
return TargetInfo::CharPtrBuiltinVaList;
}
// 64-bit RenderScript is aarch64
RenderScript64TargetInfo::RenderScript64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: AArch64leTargetInfo(llvm::Triple("aarch64", Triple.getVendorName(),
Triple.getOSName(),
Triple.getEnvironmentName()),
Opts) {
IsRenderScriptTarget = true;
}
void RenderScript64TargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__RENDERSCRIPT__");
AArch64leTargetInfo::getTargetDefines(Opts, Builder);
}
Index: vendor/clang/dist-release_80/lib/Basic/Targets/ARM.cpp
===================================================================
--- vendor/clang/dist-release_80/lib/Basic/Targets/ARM.cpp (revision 343795)
+++ vendor/clang/dist-release_80/lib/Basic/Targets/ARM.cpp (revision 343796)
@@ -1,1105 +1,1106 @@
//===--- ARM.cpp - Implement ARM target feature support -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements ARM TargetInfo objects.
//
//===----------------------------------------------------------------------===//
#include "ARM.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetBuiltins.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
using namespace clang::targets;
void ARMTargetInfo::setABIAAPCS() {
IsAAPCS = true;
DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
const llvm::Triple &T = getTriple();
bool IsNetBSD = T.isOSNetBSD();
bool IsOpenBSD = T.isOSOpenBSD();
if (!T.isOSWindows() && !IsNetBSD && !IsOpenBSD)
WCharType = UnsignedInt;
UseBitFieldTypeAlignment = true;
ZeroLengthBitfieldBoundary = 0;
// Thumb1 add sp, #imm requires the immediate value be multiple of 4,
// so set preferred for small types to 32.
if (T.isOSBinFormatMachO()) {
resetDataLayout(BigEndian
? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
: "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
} else if (T.isOSWindows()) {
assert(!BigEndian && "Windows on ARM does not support big endian");
resetDataLayout("e"
"-m:w"
"-p:32:32"
"-i64:64"
"-v128:64:128"
"-a:0:32"
"-n32"
"-S64");
} else if (T.isOSNaCl()) {
assert(!BigEndian && "NaCl on ARM does not support big endian");
resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128");
} else {
resetDataLayout(BigEndian
? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
}
// FIXME: Enumerated types are variable width in straight AAPCS.
}
void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) {
const llvm::Triple &T = getTriple();
IsAAPCS = false;
if (IsAAPCS16)
DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
else
DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
WCharType = SignedInt;
// Do not respect the alignment of bit-field types when laying out
// structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.
UseBitFieldTypeAlignment = false;
/// gcc forces the alignment to 4 bytes, regardless of the type of the
/// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in
/// gcc.
ZeroLengthBitfieldBoundary = 32;
if (T.isOSBinFormatMachO() && IsAAPCS16) {
assert(!BigEndian && "AAPCS16 does not support big-endian");
resetDataLayout("e-m:o-p:32:32-i64:64-a:0:32-n32-S128");
} else if (T.isOSBinFormatMachO())
resetDataLayout(
BigEndian
? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
: "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
else
resetDataLayout(
BigEndian
? "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
: "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
// FIXME: Override "preferred align" for double and long long.
}
void ARMTargetInfo::setArchInfo() {
StringRef ArchName = getTriple().getArchName();
ArchISA = llvm::ARM::parseArchISA(ArchName);
CPU = llvm::ARM::getDefaultCPU(ArchName);
llvm::ARM::ArchKind AK = llvm::ARM::parseArch(ArchName);
if (AK != llvm::ARM::ArchKind::INVALID)
ArchKind = AK;
setArchInfo(ArchKind);
}
void ARMTargetInfo::setArchInfo(llvm::ARM::ArchKind Kind) {
StringRef SubArch;
// cache TargetParser info
ArchKind = Kind;
SubArch = llvm::ARM::getSubArch(ArchKind);
ArchProfile = llvm::ARM::parseArchProfile(SubArch);
ArchVersion = llvm::ARM::parseArchVersion(SubArch);
// cache CPU related strings
CPUAttr = getCPUAttr();
CPUProfile = getCPUProfile();
}
void ARMTargetInfo::setAtomic() {
// when triple does not specify a sub arch,
// then we are not using inline atomics
bool ShouldUseInlineAtomic =
(ArchISA == llvm::ARM::ISAKind::ARM && ArchVersion >= 6) ||
(ArchISA == llvm::ARM::ISAKind::THUMB && ArchVersion >= 7);
// Cortex M does not support 8 byte atomics, while general Thumb2 does.
if (ArchProfile == llvm::ARM::ProfileKind::M) {
MaxAtomicPromoteWidth = 32;
if (ShouldUseInlineAtomic)
MaxAtomicInlineWidth = 32;
} else {
MaxAtomicPromoteWidth = 64;
if (ShouldUseInlineAtomic)
MaxAtomicInlineWidth = 64;
}
}
bool ARMTargetInfo::isThumb() const {
return ArchISA == llvm::ARM::ISAKind::THUMB;
}
bool ARMTargetInfo::supportsThumb() const {
return CPUAttr.count('T') || ArchVersion >= 6;
}
bool ARMTargetInfo::supportsThumb2() const {
return CPUAttr.equals("6T2") ||
(ArchVersion >= 7 && !CPUAttr.equals("8M_BASE"));
}
StringRef ARMTargetInfo::getCPUAttr() const {
// For most sub-arches, the build attribute CPU name is enough.
// For Cortex variants, it's slightly different.
switch (ArchKind) {
default:
return llvm::ARM::getCPUAttr(ArchKind);
case llvm::ARM::ArchKind::ARMV6M:
return "6M";
case llvm::ARM::ArchKind::ARMV7S:
return "7S";
case llvm::ARM::ArchKind::ARMV7A:
return "7A";
case llvm::ARM::ArchKind::ARMV7R:
return "7R";
case llvm::ARM::ArchKind::ARMV7M:
return "7M";
case llvm::ARM::ArchKind::ARMV7EM:
return "7EM";
case llvm::ARM::ArchKind::ARMV7VE:
return "7VE";
case llvm::ARM::ArchKind::ARMV8A:
return "8A";
case llvm::ARM::ArchKind::ARMV8_1A:
return "8_1A";
case llvm::ARM::ArchKind::ARMV8_2A:
return "8_2A";
case llvm::ARM::ArchKind::ARMV8_3A:
return "8_3A";
case llvm::ARM::ArchKind::ARMV8_4A:
return "8_4A";
case llvm::ARM::ArchKind::ARMV8_5A:
return "8_5A";
case llvm::ARM::ArchKind::ARMV8MBaseline:
return "8M_BASE";
case llvm::ARM::ArchKind::ARMV8MMainline:
return "8M_MAIN";
case llvm::ARM::ArchKind::ARMV8R:
return "8R";
}
}
StringRef ARMTargetInfo::getCPUProfile() const {
switch (ArchProfile) {
case llvm::ARM::ProfileKind::A:
return "A";
case llvm::ARM::ProfileKind::R:
return "R";
case llvm::ARM::ProfileKind::M:
return "M";
default:
return "";
}
}
ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
HW_FP(0) {
bool IsOpenBSD = Triple.isOSOpenBSD();
bool IsNetBSD = Triple.isOSNetBSD();
// FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like
// environment where size_t is `unsigned long` rather than `unsigned int`
PtrDiffType = IntPtrType =
(Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
IsNetBSD)
? SignedLong
: SignedInt;
SizeType = (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
IsNetBSD)
? UnsignedLong
: UnsignedInt;
// ptrdiff_t is inconsistent on Darwin
if ((Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) &&
!Triple.isWatchABI())
PtrDiffType = SignedInt;
// Cache arch related info.
setArchInfo();
// {} in inline assembly are neon specifiers, not assembly variant
// specifiers.
NoAsmVariants = true;
// FIXME: This duplicates code from the driver that sets the -target-abi
// option - this code is used if -target-abi isn't passed and should
// be unified in some way.
if (Triple.isOSBinFormatMachO()) {
// The backend is hardwired to assume AAPCS for M-class processors, ensure
// the frontend matches that.
if (Triple.getEnvironment() == llvm::Triple::EABI ||
Triple.getOS() == llvm::Triple::UnknownOS ||
ArchProfile == llvm::ARM::ProfileKind::M) {
setABI("aapcs");
} else if (Triple.isWatchABI()) {
setABI("aapcs16");
} else {
setABI("apcs-gnu");
}
} else if (Triple.isOSWindows()) {
// FIXME: this is invalid for WindowsCE
setABI("aapcs");
} else {
// Select the default based on the platform.
switch (Triple.getEnvironment()) {
case llvm::Triple::Android:
case llvm::Triple::GNUEABI:
case llvm::Triple::GNUEABIHF:
case llvm::Triple::MuslEABI:
case llvm::Triple::MuslEABIHF:
setABI("aapcs-linux");
break;
case llvm::Triple::EABIHF:
case llvm::Triple::EABI:
setABI("aapcs");
break;
case llvm::Triple::GNU:
setABI("apcs-gnu");
break;
default:
if (IsNetBSD)
setABI("apcs-gnu");
else if (IsOpenBSD)
setABI("aapcs-linux");
else
setABI("aapcs");
break;
}
}
// ARM targets default to using the ARM C++ ABI.
TheCXXABI.set(TargetCXXABI::GenericARM);
// ARM has atomics up to 8 bytes
setAtomic();
// Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android))
MaxVectorAlign = 64;
// Do force alignment of members that follow zero length bitfields. If
// the alignment of the zero-length bitfield is greater than the member
// that follows it, `bar', `bar' will be aligned as the type of the
// zero length bitfield.
UseZeroLengthBitfieldAlignment = true;
if (Triple.getOS() == llvm::Triple::Linux ||
Triple.getOS() == llvm::Triple::UnknownOS)
this->MCountName = Opts.EABIVersion == llvm::EABI::GNU
? "\01__gnu_mcount_nc"
: "\01mcount";
}
StringRef ARMTargetInfo::getABI() const { return ABI; }
bool ARMTargetInfo::setABI(const std::string &Name) {
ABI = Name;
// The defaults (above) are for AAPCS, check if we need to change them.
//
// FIXME: We need support for -meabi... we could just mangle it into the
// name.
if (Name == "apcs-gnu" || Name == "aapcs16") {
setABIAPCS(Name == "aapcs16");
return true;
}
if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {
setABIAAPCS();
return true;
}
return false;
}
// FIXME: This should be based on Arch attributes, not CPU names.
bool ARMTargetInfo::initFeatureMap(
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
const std::vector<std::string> &FeaturesVec) const {
std::string ArchFeature;
std::vector<StringRef> TargetFeatures;
llvm::ARM::ArchKind Arch = llvm::ARM::parseArch(getTriple().getArchName());
// Map the base architecture to an appropriate target feature, so we don't
// rely on the target triple.
llvm::ARM::ArchKind CPUArch = llvm::ARM::parseCPUArch(CPU);
if (CPUArch == llvm::ARM::ArchKind::INVALID)
CPUArch = Arch;
if (CPUArch != llvm::ARM::ArchKind::INVALID) {
ArchFeature = ("+" + llvm::ARM::getArchName(CPUArch)).str();
TargetFeatures.push_back(ArchFeature);
}
// get default FPU features
unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);
llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);
// get default Extension features
unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);
llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);
for (auto Feature : TargetFeatures)
if (Feature[0] == '+')
Features[Feature.drop_front(1)] = true;
// Enable or disable thumb-mode explicitly per function to enable mixed
// ARM and Thumb code generation.
if (isThumb())
Features["thumb-mode"] = true;
else
Features["thumb-mode"] = false;
// Convert user-provided arm and thumb GNU target attributes to
// [-|+]thumb-mode target features respectively.
std::vector<std::string> UpdatedFeaturesVec(FeaturesVec);
for (auto &Feature : UpdatedFeaturesVec) {
if (Feature.compare("+arm") == 0)
Feature = "-thumb-mode";
else if (Feature.compare("+thumb") == 0)
Feature = "+thumb-mode";
}
return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
}
bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
DiagnosticsEngine &Diags) {
FPU = 0;
CRC = 0;
Crypto = 0;
DSP = 0;
Unaligned = 1;
SoftFloat = SoftFloatABI = false;
HWDiv = 0;
DotProd = 0;
+ HasFloat16 = true;
// This does not diagnose illegal cases like having both
// "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp".
uint32_t HW_FP_remove = 0;
for (const auto &Feature : Features) {
if (Feature == "+soft-float") {
SoftFloat = true;
} else if (Feature == "+soft-float-abi") {
SoftFloatABI = true;
} else if (Feature == "+vfp2") {
FPU |= VFP2FPU;
HW_FP |= HW_FP_SP | HW_FP_DP;
} else if (Feature == "+vfp3") {
FPU |= VFP3FPU;
HW_FP |= HW_FP_SP | HW_FP_DP;
} else if (Feature == "+vfp4") {
FPU |= VFP4FPU;
HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
} else if (Feature == "+fp-armv8") {
FPU |= FPARMV8;
HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
} else if (Feature == "+neon") {
FPU |= NeonFPU;
HW_FP |= HW_FP_SP | HW_FP_DP;
} else if (Feature == "+hwdiv") {
HWDiv |= HWDivThumb;
} else if (Feature == "+hwdiv-arm") {
HWDiv |= HWDivARM;
} else if (Feature == "+crc") {
CRC = 1;
} else if (Feature == "+crypto") {
Crypto = 1;
} else if (Feature == "+dsp") {
DSP = 1;
} else if (Feature == "+fp-only-sp") {
HW_FP_remove |= HW_FP_DP;
} else if (Feature == "+strict-align") {
Unaligned = 0;
} else if (Feature == "+fp16") {
HW_FP |= HW_FP_HP;
} else if (Feature == "+fullfp16") {
HasLegalHalfType = true;
} else if (Feature == "+dotprod") {
DotProd = true;
}
}
HW_FP &= ~HW_FP_remove;
switch (ArchVersion) {
case 6:
if (ArchProfile == llvm::ARM::ProfileKind::M)
LDREX = 0;
else if (ArchKind == llvm::ARM::ArchKind::ARMV6K)
LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
else
LDREX = LDREX_W;
break;
case 7:
if (ArchProfile == llvm::ARM::ProfileKind::M)
LDREX = LDREX_W | LDREX_H | LDREX_B;
else
LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
break;
case 8:
LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
}
if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
return false;
}
if (FPMath == FP_Neon)
Features.push_back("+neonfp");
else if (FPMath == FP_VFP)
Features.push_back("-neonfp");
// Remove front-end specific options which the backend handles differently.
auto Feature = std::find(Features.begin(), Features.end(), "+soft-float-abi");
if (Feature != Features.end())
Features.erase(Feature);
return true;
}
bool ARMTargetInfo::hasFeature(StringRef Feature) const {
return llvm::StringSwitch<bool>(Feature)
.Case("arm", true)
.Case("aarch32", true)
.Case("softfloat", SoftFloat)
.Case("thumb", isThumb())
.Case("neon", (FPU & NeonFPU) && !SoftFloat)
.Case("vfp", FPU && !SoftFloat)
.Case("hwdiv", HWDiv & HWDivThumb)
.Case("hwdiv-arm", HWDiv & HWDivARM)
.Default(false);
}
bool ARMTargetInfo::isValidCPUName(StringRef Name) const {
return Name == "generic" ||
llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID;
}
void ARMTargetInfo::fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {
llvm::ARM::fillValidCPUArchList(Values);
}
bool ARMTargetInfo::setCPU(const std::string &Name) {
if (Name != "generic")
setArchInfo(llvm::ARM::parseCPUArch(Name));
if (ArchKind == llvm::ARM::ArchKind::INVALID)
return false;
setAtomic();
CPU = Name;
return true;
}
bool ARMTargetInfo::setFPMath(StringRef Name) {
if (Name == "neon") {
FPMath = FP_Neon;
return true;
} else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||
Name == "vfp4") {
FPMath = FP_VFP;
return true;
}
return false;
}
void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
}
void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
MacroBuilder &Builder) const {
// Also include the ARMv8.1-A defines
getTargetDefinesARMV81A(Opts, Builder);
}
void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
// Target identification.
Builder.defineMacro("__arm");
Builder.defineMacro("__arm__");
// 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("__REGISTER_PREFIX__", "");
// Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU
// happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.
if (getTriple().isWatchABI())
Builder.defineMacro("__ARM_ARCH_7K__", "2");
if (!CPUAttr.empty())
Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");
// ACLE 6.4.1 ARM/Thumb instruction set architecture
// __ARM_ARCH is defined as an integer value indicating the current ARM ISA
Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));
if (ArchVersion >= 8) {
// ACLE 6.5.7 Crypto Extension
if (Crypto)
Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
// ACLE 6.5.8 CRC32 Extension
if (CRC)
Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
// ACLE 6.5.10 Numeric Maximum and Minimum
Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
// ACLE 6.5.9 Directed Rounding
Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
}
// __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It
// is not defined for the M-profile.
// NOTE that the default profile is assumed to be 'A'
if (CPUProfile.empty() || ArchProfile != llvm::ARM::ProfileKind::M)
Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1");
// __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original
// Thumb ISA (including v6-M and v8-M Baseline). It is set to 2 if the
// core supports the Thumb-2 ISA as found in the v6T2 architecture and all
// v7 and v8 architectures excluding v8-M Baseline.
if (supportsThumb2())
Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");
else if (supportsThumb())
Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");
// __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit
// instruction set such as ARM or Thumb.
Builder.defineMacro("__ARM_32BIT_STATE", "1");
// ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex)
// __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset.
if (!CPUProfile.empty())
Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'");
// ACLE 6.4.3 Unaligned access supported in hardware
if (Unaligned)
Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
// ACLE 6.4.4 LDREX/STREX
if (LDREX)
Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + Twine::utohexstr(LDREX));
// ACLE 6.4.5 CLZ
if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") ||
ArchVersion > 6)
Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
// ACLE 6.5.1 Hardware Floating Point
if (HW_FP)
Builder.defineMacro("__ARM_FP", "0x" + Twine::utohexstr(HW_FP));
// ACLE predefines.
Builder.defineMacro("__ARM_ACLE", "200");
// FP16 support (we currently only support IEEE format).
Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
Builder.defineMacro("__ARM_FP16_ARGS", "1");
// ACLE 6.5.3 Fused multiply-accumulate (FMA)
if (ArchVersion >= 7 && (FPU & VFP4FPU))
Builder.defineMacro("__ARM_FEATURE_FMA", "1");
// Subtarget options.
// FIXME: It's more complicated than this and we don't really support
// interworking.
// Windows on ARM does not "support" interworking
if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())
Builder.defineMacro("__THUMB_INTERWORK__");
if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
// Embedded targets on Darwin follow AAPCS, but not EABI.
// Windows on ARM follows AAPCS VFP, but does not conform to EABI.
if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows())
Builder.defineMacro("__ARM_EABI__");
Builder.defineMacro("__ARM_PCS", "1");
}
if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16")
Builder.defineMacro("__ARM_PCS_VFP", "1");
if (SoftFloat)
Builder.defineMacro("__SOFTFP__");
if (ArchKind == llvm::ARM::ArchKind::XSCALE)
Builder.defineMacro("__XSCALE__");
if (isThumb()) {
Builder.defineMacro("__THUMBEL__");
Builder.defineMacro("__thumb__");
if (supportsThumb2())
Builder.defineMacro("__thumb2__");
}
// ACLE 6.4.9 32-bit SIMD instructions
if ((CPUProfile != "M" && ArchVersion >= 6) || (CPUProfile == "M" && DSP))
Builder.defineMacro("__ARM_FEATURE_SIMD32", "1");
// ACLE 6.4.10 Hardware Integer Divide
if (((HWDiv & HWDivThumb) && isThumb()) ||
((HWDiv & HWDivARM) && !isThumb())) {
Builder.defineMacro("__ARM_FEATURE_IDIV", "1");
Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1");
}
// Note, this is always on in gcc, even though it doesn't make sense.
Builder.defineMacro("__APCS_32__");
if (FPUModeIsVFP((FPUMode)FPU)) {
Builder.defineMacro("__VFP_FP__");
if (FPU & VFP2FPU)
Builder.defineMacro("__ARM_VFPV2__");
if (FPU & VFP3FPU)
Builder.defineMacro("__ARM_VFPV3__");
if (FPU & VFP4FPU)
Builder.defineMacro("__ARM_VFPV4__");
if (FPU & FPARMV8)
Builder.defineMacro("__ARM_FPV5__");
}
// This only gets set when Neon instructions are actually available, unlike
// the VFP define, hence the soft float and arch check. This is subtly
// different from gcc, we follow the intent which was that it should be set
// when Neon instructions are actually available.
if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {
Builder.defineMacro("__ARM_NEON", "1");
Builder.defineMacro("__ARM_NEON__");
// current AArch32 NEON implementations do not support double-precision
// floating-point even when it is present in VFP.
Builder.defineMacro("__ARM_NEON_FP",
"0x" + Twine::utohexstr(HW_FP & ~HW_FP_DP));
}
Builder.defineMacro("__ARM_SIZEOF_WCHAR_T",
Twine(Opts.WCharSize ? Opts.WCharSize : 4));
Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") {
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
}
// ACLE 6.4.7 DSP instructions
if (DSP) {
Builder.defineMacro("__ARM_FEATURE_DSP", "1");
}
// ACLE 6.4.8 Saturation instructions
bool SAT = false;
if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) {
Builder.defineMacro("__ARM_FEATURE_SAT", "1");
SAT = true;
}
// ACLE 6.4.6 Q (saturation) flag
if (DSP || SAT)
Builder.defineMacro("__ARM_FEATURE_QBIT", "1");
if (Opts.UnsafeFPMath)
Builder.defineMacro("__ARM_FP_FAST", "1");
// Armv8.2-A FP16 vector intrinsic
if ((FPU & NeonFPU) && HasLegalHalfType)
Builder.defineMacro("__ARM_FEATURE_FP16_VECTOR_ARITHMETIC", "1");
// Armv8.2-A FP16 scalar intrinsics
if (HasLegalHalfType)
Builder.defineMacro("__ARM_FEATURE_FP16_SCALAR_ARITHMETIC", "1");
// Armv8.2-A dot product intrinsics
if (DotProd)
Builder.defineMacro("__ARM_FEATURE_DOTPROD", "1");
switch (ArchKind) {
default:
break;
case llvm::ARM::ArchKind::ARMV8_1A:
getTargetDefinesARMV81A(Opts, Builder);
break;
case llvm::ARM::ArchKind::ARMV8_2A:
getTargetDefinesARMV82A(Opts, Builder);
break;
}
}
const Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
{#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
#include "clang/Basic/BuiltinsNEON.def"
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
{#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
{#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
{#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
#include "clang/Basic/BuiltinsARM.def"
};
ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const {
return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin -
Builtin::FirstTSBuiltin);
}
bool ARMTargetInfo::isCLZForZeroUndef() const { return false; }
TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const {
return IsAAPCS
? AAPCSABIBuiltinVaList
: (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList
: TargetInfo::VoidPtrBuiltinVaList);
}
const char *const ARMTargetInfo::GCCRegNames[] = {
// Integer registers
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
"r12", "sp", "lr", "pc",
// Float registers
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
"s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
"s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
// Double registers
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
"d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
"d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
// Quad registers
"q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",
"q12", "q13", "q14", "q15"};
ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {
return llvm::makeArrayRef(GCCRegNames);
}
const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
{{"a1"}, "r0"}, {{"a2"}, "r1"}, {{"a3"}, "r2"}, {{"a4"}, "r3"},
{{"v1"}, "r4"}, {{"v2"}, "r5"}, {{"v3"}, "r6"}, {{"v4"}, "r7"},
{{"v5"}, "r8"}, {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"},
{{"ip"}, "r12"}, {{"r13"}, "sp"}, {{"r14"}, "lr"}, {{"r15"}, "pc"},
// The S, D and Q registers overlap, but aren't really aliases; we
// don't want to substitute one of these for a different-sized one.
};
ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {
return llvm::makeArrayRef(GCCRegAliases);
}
bool ARMTargetInfo::validateAsmConstraint(
const char *&Name, TargetInfo::ConstraintInfo &Info) const {
switch (*Name) {
default:
break;
case 'l': // r0-r7
case 'h': // r8-r15
case 't': // VFP Floating point register single precision
case 'w': // VFP Floating point register double precision
Info.setAllowsRegister();
return true;
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
// FIXME
return true;
case 'Q': // A memory address that is a single base register.
Info.setAllowsMemory();
return true;
case 'U': // a memory reference...
switch (Name[1]) {
case 'q': // ...ARMV4 ldrsb
case 'v': // ...VFP load/store (reg+constant offset)
case 'y': // ...iWMMXt load/store
case 't': // address valid for load/store opaque types wider
// than 128-bits
case 'n': // valid address for Neon doubleword vector load/store
case 'm': // valid address for Neon element and structure load/store
case 's': // valid address for non-offset loads/stores of quad-word
// values in four ARM registers
Info.setAllowsMemory();
Name++;
return true;
}
}
return false;
}
std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const {
std::string R;
switch (*Constraint) {
case 'U': // Two-character constraint; add "^" hint for later parsing.
R = std::string("^") + std::string(Constraint, 2);
Constraint++;
break;
case 'p': // 'p' should be translated to 'r' by default.
R = std::string("r");
break;
default:
return std::string(1, *Constraint);
}
return R;
}
bool ARMTargetInfo::validateConstraintModifier(
StringRef Constraint, char Modifier, unsigned Size,
std::string &SuggestedModifier) const {
bool isOutput = (Constraint[0] == '=');
bool isInOut = (Constraint[0] == '+');
// Strip off constraint modifiers.
while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
Constraint = Constraint.substr(1);
switch (Constraint[0]) {
default:
break;
case 'r': {
switch (Modifier) {
default:
return (isInOut || isOutput || Size <= 64);
case 'q':
// A register of size 32 cannot fit a vector type.
return false;
}
}
}
return true;
}
const char *ARMTargetInfo::getClobbers() const {
// FIXME: Is this really right?
return "";
}
TargetInfo::CallingConvCheckResult
ARMTargetInfo::checkCallingConvention(CallingConv CC) const {
switch (CC) {
case CC_AAPCS:
case CC_AAPCS_VFP:
case CC_Swift:
case CC_OpenCLKernel:
return CCCR_OK;
default:
return CCCR_Warning;
}
}
int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
if (RegNo == 0)
return 0;
if (RegNo == 1)
return 1;
return -1;
}
bool ARMTargetInfo::hasSjLjLowering() const { return true; }
ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: ARMTargetInfo(Triple, Opts) {}
void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__ARMEL__");
ARMTargetInfo::getTargetDefines(Opts, Builder);
}
ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: ARMTargetInfo(Triple, Opts) {}
void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__ARMEB__");
Builder.defineMacro("__ARM_BIG_ENDIAN");
ARMTargetInfo::getTargetDefines(Opts, Builder);
}
WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {
}
void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
WindowsTargetInfo<ARMleTargetInfo>::getVisualStudioDefines(Opts, Builder);
// FIXME: this is invalid for WindowsCE
Builder.defineMacro("_M_ARM_NT", "1");
Builder.defineMacro("_M_ARMT", "_M_ARM");
Builder.defineMacro("_M_THUMB", "_M_ARM");
assert((Triple.getArch() == llvm::Triple::arm ||
Triple.getArch() == llvm::Triple::thumb) &&
"invalid architecture for Windows ARM target info");
unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset));
// TODO map the complete set of values
// 31: VFPv3 40: VFPv4
Builder.defineMacro("_M_ARM_FP", "31");
}
TargetInfo::BuiltinVaListKind
WindowsARMTargetInfo::getBuiltinVaListKind() const {
return TargetInfo::CharPtrBuiltinVaList;
}
TargetInfo::CallingConvCheckResult
WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {
switch (CC) {
case CC_X86StdCall:
case CC_X86ThisCall:
case CC_X86FastCall:
case CC_X86VectorCall:
return CCCR_Ignore;
case CC_C:
case CC_OpenCLKernel:
case CC_PreserveMost:
case CC_PreserveAll:
case CC_Swift:
return CCCR_OK;
default:
return CCCR_Warning;
}
}
// Windows ARM + Itanium C++ ABI Target
ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo(
const llvm::Triple &Triple, const TargetOptions &Opts)
: WindowsARMTargetInfo(Triple, Opts) {
TheCXXABI.set(TargetCXXABI::GenericARM);
}
void ItaniumWindowsARMleTargetInfo::getTargetDefines(
const LangOptions &Opts, MacroBuilder &Builder) const {
WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
if (Opts.MSVCCompat)
WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
}
// Windows ARM, MS (C++) ABI
MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: WindowsARMTargetInfo(Triple, Opts) {
TheCXXABI.set(TargetCXXABI::Microsoft);
}
void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
}
MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: WindowsARMTargetInfo(Triple, Opts) {
TheCXXABI.set(TargetCXXABI::GenericARM);
}
void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
Builder.defineMacro("_ARM_");
}
CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: ARMleTargetInfo(Triple, Opts) {
this->WCharType = TargetInfo::UnsignedShort;
TLSSupported = false;
DoubleAlign = LongLongAlign = 64;
resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
}
void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
ARMleTargetInfo::getTargetDefines(Opts, Builder);
Builder.defineMacro("_ARM_");
Builder.defineMacro("__CYGWIN__");
Builder.defineMacro("__CYGWIN32__");
DefineStd(Builder, "unix", Opts);
if (Opts.CPlusPlus)
Builder.defineMacro("_GNU_SOURCE");
}
DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {
HasAlignMac68kSupport = true;
// iOS always has 64-bit atomic instructions.
// FIXME: This should be based off of the target features in
// ARMleTargetInfo.
MaxAtomicInlineWidth = 64;
if (Triple.isWatchABI()) {
// Darwin on iOS uses a variant of the ARM C++ ABI.
TheCXXABI.set(TargetCXXABI::WatchOS);
// BOOL should be a real boolean on the new ABI
UseSignedCharForObjCBool = false;
} else
TheCXXABI.set(TargetCXXABI::iOS);
}
void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts,
const llvm::Triple &Triple,
MacroBuilder &Builder) const {
getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
}
RenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(),
Triple.getOSName(),
Triple.getEnvironmentName()),
Opts) {
IsRenderScriptTarget = true;
LongWidth = LongAlign = 64;
}
void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__RENDERSCRIPT__");
ARMleTargetInfo::getTargetDefines(Opts, Builder);
}
Index: vendor/clang/dist-release_80/lib/Basic/Targets/OSTargets.h
===================================================================
--- vendor/clang/dist-release_80/lib/Basic/Targets/OSTargets.h (revision 343795)
+++ vendor/clang/dist-release_80/lib/Basic/Targets/OSTargets.h (revision 343796)
@@ -1,788 +1,804 @@
//===--- OSTargets.h - Declare OS target feature support --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares OS specific TargetInfo types.
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H
#define LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H
#include "Targets.h"
#include "llvm/MC/MCSectionMachO.h"
namespace clang {
namespace targets {
template <typename TgtInfo>
class LLVM_LIBRARY_VISIBILITY OSTargetInfo : public TgtInfo {
protected:
virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const = 0;
public:
OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: TgtInfo(Triple, Opts) {}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
TgtInfo::getTargetDefines(Opts, Builder);
getOSDefines(Opts, TgtInfo::getTriple(), Builder);
}
};
// CloudABI Target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY CloudABITargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
Builder.defineMacro("__CloudABI__");
Builder.defineMacro("__ELF__");
// CloudABI uses ISO/IEC 10646:2012 for wchar_t, char16_t and char32_t.
Builder.defineMacro("__STDC_ISO_10646__", "201206L");
Builder.defineMacro("__STDC_UTF_16__");
Builder.defineMacro("__STDC_UTF_32__");
}
public:
CloudABITargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {}
};
// Ananas target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY AnanasTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// Ananas defines
Builder.defineMacro("__Ananas__");
Builder.defineMacro("__ELF__");
}
public:
AnanasTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {}
};
void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
const llvm::Triple &Triple, StringRef &PlatformName,
VersionTuple &PlatformMinVersion);
template <typename Target>
class LLVM_LIBRARY_VISIBILITY DarwinTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
getDarwinDefines(Builder, Opts, Triple, this->PlatformName,
this->PlatformMinVersion);
}
public:
DarwinTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
// By default, no TLS, and we whitelist permitted architecture/OS
// combinations.
this->TLSSupported = false;
if (Triple.isMacOSX())
this->TLSSupported = !Triple.isMacOSXVersionLT(10, 7);
else if (Triple.isiOS()) {
// 64-bit iOS supported it from 8 onwards, 32-bit device from 9 onwards,
// 32-bit simulator from 10 onwards.
if (Triple.isArch64Bit())
this->TLSSupported = !Triple.isOSVersionLT(8);
else if (Triple.isArch32Bit()) {
if (!Triple.isSimulatorEnvironment())
this->TLSSupported = !Triple.isOSVersionLT(9);
else
this->TLSSupported = !Triple.isOSVersionLT(10);
}
} else if (Triple.isWatchOS()) {
if (!Triple.isSimulatorEnvironment())
this->TLSSupported = !Triple.isOSVersionLT(2);
else
this->TLSSupported = !Triple.isOSVersionLT(3);
}
this->MCountName = "\01mcount";
}
std::string isValidSectionSpecifier(StringRef SR) const override {
// Let MCSectionMachO validate this.
StringRef Segment, Section;
unsigned TAA, StubSize;
bool HasTAA;
return llvm::MCSectionMachO::ParseSectionSpecifier(SR, Segment, Section,
TAA, HasTAA, StubSize);
}
const char *getStaticInitSectionSpecifier() const override {
// FIXME: We should return 0 when building kexts.
return "__TEXT,__StaticInit,regular,pure_instructions";
}
/// Darwin does not support protected visibility. Darwin's "default"
/// is very similar to ELF's "protected"; Darwin requires a "weak"
/// attribute on declarations that can be dynamically replaced.
bool hasProtectedVisibility() const override { return false; }
TargetInfo::IntType getLeastIntTypeByWidth(unsigned BitWidth,
bool IsSigned) const final {
// Darwin uses `long long` for `int_least64_t` and `int_fast64_t`.
return BitWidth == 64
? (IsSigned ? TargetInfo::SignedLongLong
: TargetInfo::UnsignedLongLong)
: TargetInfo::getLeastIntTypeByWidth(BitWidth, IsSigned);
}
};
// DragonFlyBSD Target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY DragonFlyBSDTargetInfo
: public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// DragonFly defines; list based off of gcc output
Builder.defineMacro("__DragonFly__");
Builder.defineMacro("__DragonFly_cc_version", "100001");
Builder.defineMacro("__ELF__");
Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
Builder.defineMacro("__tune_i386__");
DefineStd(Builder, "unix", Opts);
}
public:
DragonFlyBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
switch (Triple.getArch()) {
default:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
this->MCountName = ".mcount";
break;
}
}
};
#ifndef FREEBSD_CC_VERSION
#define FREEBSD_CC_VERSION 0U
#endif
// FreeBSD Target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY FreeBSDTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// FreeBSD defines; list based off of gcc output
unsigned Release = Triple.getOSMajorVersion();
if (Release == 0U)
Release = 8U;
unsigned CCVersion = FREEBSD_CC_VERSION;
if (CCVersion == 0U)
CCVersion = Release * 100000U + 1U;
Builder.defineMacro("__FreeBSD__", Twine(Release));
Builder.defineMacro("__FreeBSD_cc_version", Twine(CCVersion));
Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
DefineStd(Builder, "unix", Opts);
Builder.defineMacro("__ELF__");
// On FreeBSD, wchar_t contains the number of the code point as
// used by the character set of the locale. These character sets are
// not necessarily a superset of ASCII.
//
// FIXME: This is wrong; the macro refers to the numerical values
// of wchar_t *literals*, which are not locale-dependent. However,
// FreeBSD systems apparently depend on us getting this wrong, and
// setting this to 1 is conforming even if all the basic source
// character literals have the same encoding as char and wchar_t.
Builder.defineMacro("__STDC_MB_MIGHT_NEQ_WC__", "1");
}
public:
FreeBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
switch (Triple.getArch()) {
default:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
this->MCountName = ".mcount";
break;
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
this->MCountName = "_mcount";
break;
case llvm::Triple::arm:
this->MCountName = "__mcount";
break;
}
}
};
// GNU/kFreeBSD Target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY KFreeBSDTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// GNU/kFreeBSD defines; list based off of gcc output
DefineStd(Builder, "unix", Opts);
Builder.defineMacro("__FreeBSD_kernel__");
Builder.defineMacro("__GLIBC__");
Builder.defineMacro("__ELF__");
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
if (Opts.CPlusPlus)
Builder.defineMacro("_GNU_SOURCE");
}
public:
KFreeBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {}
};
// Haiku Target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY HaikuTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// Haiku defines; list based off of gcc output
Builder.defineMacro("__HAIKU__");
Builder.defineMacro("__ELF__");
DefineStd(Builder, "unix", Opts);
if (this->HasFloat128)
Builder.defineMacro("__FLOAT128__");
}
public:
HaikuTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->SizeType = TargetInfo::UnsignedLong;
this->IntPtrType = TargetInfo::SignedLong;
this->PtrDiffType = TargetInfo::SignedLong;
this->ProcessIDType = TargetInfo::SignedLong;
this->TLSSupported = false;
switch (Triple.getArch()) {
default:
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
this->HasFloat128 = true;
break;
}
}
};
// Hurd target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY HurdTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// Hurd defines; list based off of gcc output.
DefineStd(Builder, "unix", Opts);
Builder.defineMacro("__GNU__");
Builder.defineMacro("__gnu_hurd__");
Builder.defineMacro("__MACH__");
Builder.defineMacro("__GLIBC__");
Builder.defineMacro("__ELF__");
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
if (Opts.CPlusPlus)
Builder.defineMacro("_GNU_SOURCE");
}
public:
HurdTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {}
};
// Minix Target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY MinixTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// Minix defines
Builder.defineMacro("__minix", "3");
Builder.defineMacro("_EM_WSIZE", "4");
Builder.defineMacro("_EM_PSIZE", "4");
Builder.defineMacro("_EM_SSIZE", "2");
Builder.defineMacro("_EM_LSIZE", "4");
Builder.defineMacro("_EM_FSIZE", "4");
Builder.defineMacro("_EM_DSIZE", "8");
Builder.defineMacro("__ELF__");
DefineStd(Builder, "unix", Opts);
}
public:
MinixTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {}
};
// Linux target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY LinuxTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// Linux defines; list based off of gcc output
DefineStd(Builder, "unix", Opts);
DefineStd(Builder, "linux", Opts);
Builder.defineMacro("__ELF__");
if (Triple.isAndroid()) {
Builder.defineMacro("__ANDROID__", "1");
unsigned Maj, Min, Rev;
Triple.getEnvironmentVersion(Maj, Min, Rev);
this->PlatformName = "android";
this->PlatformMinVersion = VersionTuple(Maj, Min, Rev);
if (Maj)
Builder.defineMacro("__ANDROID_API__", Twine(Maj));
} else {
Builder.defineMacro("__gnu_linux__");
}
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
if (Opts.CPlusPlus)
Builder.defineMacro("_GNU_SOURCE");
if (this->HasFloat128)
Builder.defineMacro("__FLOAT128__");
}
public:
LinuxTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->WIntType = TargetInfo::UnsignedInt;
switch (Triple.getArch()) {
default:
break;
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
this->MCountName = "_mcount";
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
this->HasFloat128 = true;
break;
}
}
const char *getStaticInitSectionSpecifier() const override {
return ".text.startup";
}
};
// NetBSD Target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY NetBSDTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// NetBSD defines; list based off of gcc output
Builder.defineMacro("__NetBSD__");
Builder.defineMacro("__unix__");
Builder.defineMacro("__ELF__");
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
}
public:
NetBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->MCountName = "__mcount";
}
};
// OpenBSD Target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY OpenBSDTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// OpenBSD defines; list based off of gcc output
Builder.defineMacro("__OpenBSD__");
DefineStd(Builder, "unix", Opts);
Builder.defineMacro("__ELF__");
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
if (this->HasFloat128)
Builder.defineMacro("__FLOAT128__");
}
public:
OpenBSDTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
switch (Triple.getArch()) {
case llvm::Triple::x86:
case llvm::Triple::x86_64:
this->HasFloat128 = true;
LLVM_FALLTHROUGH;
default:
this->MCountName = "__mcount";
break;
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
case llvm::Triple::ppc:
case llvm::Triple::sparcv9:
this->MCountName = "_mcount";
break;
}
}
};
// PSP Target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY PSPTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// PSP defines; list based on the output of the pspdev gcc toolchain.
Builder.defineMacro("PSP");
Builder.defineMacro("_PSP");
Builder.defineMacro("__psp__");
Builder.defineMacro("__ELF__");
}
public:
PSPTargetInfo(const llvm::Triple &Triple) : OSTargetInfo<Target>(Triple) {}
};
// PS3 PPU Target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY PS3PPUTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// PS3 PPU defines.
Builder.defineMacro("__PPC__");
Builder.defineMacro("__PPU__");
Builder.defineMacro("__CELLOS_LV2__");
Builder.defineMacro("__ELF__");
Builder.defineMacro("__LP32__");
Builder.defineMacro("_ARCH_PPC64");
Builder.defineMacro("__powerpc64__");
}
public:
PS3PPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->LongWidth = this->LongAlign = 32;
this->PointerWidth = this->PointerAlign = 32;
this->IntMaxType = TargetInfo::SignedLongLong;
this->Int64Type = TargetInfo::SignedLongLong;
this->SizeType = TargetInfo::UnsignedInt;
this->resetDataLayout("E-m:e-p:32:32-i64:64-n32:64");
}
};
template <typename Target>
class LLVM_LIBRARY_VISIBILITY PS4OSTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
Builder.defineMacro("__FreeBSD__", "9");
Builder.defineMacro("__FreeBSD_cc_version", "900001");
Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
DefineStd(Builder, "unix", Opts);
Builder.defineMacro("__ELF__");
Builder.defineMacro("__ORBIS__");
}
public:
PS4OSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->WCharType = TargetInfo::UnsignedShort;
// On PS4, TLS variable cannot be aligned to more than 32 bytes (256 bits).
this->MaxTLSAlign = 256;
// On PS4, do not honor explicit bit field alignment,
// as in "__attribute__((aligned(2))) int b : 1;".
this->UseExplicitBitFieldAlignment = false;
switch (Triple.getArch()) {
default:
case llvm::Triple::x86_64:
this->MCountName = ".mcount";
this->NewAlign = 256;
break;
}
}
};
// RTEMS Target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY RTEMSTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// RTEMS defines; list based off of gcc output
Builder.defineMacro("__rtems__");
Builder.defineMacro("__ELF__");
if (Opts.CPlusPlus)
Builder.defineMacro("_GNU_SOURCE");
}
public:
RTEMSTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
switch (Triple.getArch()) {
default:
case llvm::Triple::x86:
// this->MCountName = ".mcount";
break;
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
// this->MCountName = "_mcount";
break;
case llvm::Triple::arm:
// this->MCountName = "__mcount";
break;
}
}
};
// Solaris target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY SolarisTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
DefineStd(Builder, "sun", Opts);
DefineStd(Builder, "unix", Opts);
Builder.defineMacro("__ELF__");
Builder.defineMacro("__svr4__");
Builder.defineMacro("__SVR4");
// Solaris headers require _XOPEN_SOURCE to be set to 600 for C99 and
// newer, but to 500 for everything else. feature_test.h has a check to
// ensure that you are not using C99 with an old version of X/Open or C89
// with a new version.
if (Opts.C99)
Builder.defineMacro("_XOPEN_SOURCE", "600");
else
Builder.defineMacro("_XOPEN_SOURCE", "500");
if (Opts.CPlusPlus)
Builder.defineMacro("__C99FEATURES__");
Builder.defineMacro("_LARGEFILE_SOURCE");
Builder.defineMacro("_LARGEFILE64_SOURCE");
Builder.defineMacro("__EXTENSIONS__");
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
if (this->HasFloat128)
Builder.defineMacro("__FLOAT128__");
}
public:
SolarisTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
// FIXME: WIntType should be SignedLong
switch (Triple.getArch()) {
default:
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
this->HasFloat128 = true;
break;
}
}
};
// Windows target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY WindowsTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
Builder.defineMacro("_WIN32");
if (Triple.isArch64Bit())
Builder.defineMacro("_WIN64");
if (Triple.isWindowsGNUEnvironment())
addMinGWDefines(Triple, Opts, Builder);
}
void getVisualStudioDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
if (Opts.CPlusPlus) {
if (Opts.RTTIData)
Builder.defineMacro("_CPPRTTI");
if (Opts.CXXExceptions)
Builder.defineMacro("_CPPUNWIND");
}
if (Opts.Bool)
Builder.defineMacro("__BOOL_DEFINED");
if (!Opts.CharIsSigned)
Builder.defineMacro("_CHAR_UNSIGNED");
// FIXME: POSIXThreads isn't exactly the option this should be defined for,
// but it works for now.
if (Opts.POSIXThreads)
Builder.defineMacro("_MT");
if (Opts.MSCompatibilityVersion) {
Builder.defineMacro("_MSC_VER",
Twine(Opts.MSCompatibilityVersion / 100000));
Builder.defineMacro("_MSC_FULL_VER", Twine(Opts.MSCompatibilityVersion));
// FIXME We cannot encode the revision information into 32-bits
Builder.defineMacro("_MSC_BUILD", Twine(1));
if (Opts.CPlusPlus11 && Opts.isCompatibleWithMSVC(LangOptions::MSVC2015))
Builder.defineMacro("_HAS_CHAR16_T_LANGUAGE_SUPPORT", Twine(1));
if (Opts.isCompatibleWithMSVC(LangOptions::MSVC2015)) {
if (Opts.CPlusPlus2a)
Builder.defineMacro("_MSVC_LANG", "201704L");
else if (Opts.CPlusPlus17)
Builder.defineMacro("_MSVC_LANG", "201703L");
else if (Opts.CPlusPlus14)
Builder.defineMacro("_MSVC_LANG", "201402L");
}
}
if (Opts.MicrosoftExt) {
Builder.defineMacro("_MSC_EXTENSIONS");
if (Opts.CPlusPlus11) {
Builder.defineMacro("_RVALUE_REFERENCES_V2_SUPPORTED");
Builder.defineMacro("_RVALUE_REFERENCES_SUPPORTED");
Builder.defineMacro("_NATIVE_NULLPTR_SUPPORTED");
}
}
Builder.defineMacro("_INTEGRAL_MAX_BITS", "64");
}
public:
WindowsTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->WCharType = TargetInfo::UnsignedShort;
this->WIntType = TargetInfo::UnsignedShort;
}
};
template <typename Target>
class LLVM_LIBRARY_VISIBILITY NaClTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
if (Opts.CPlusPlus)
Builder.defineMacro("_GNU_SOURCE");
DefineStd(Builder, "unix", Opts);
Builder.defineMacro("__ELF__");
Builder.defineMacro("__native_client__");
}
public:
NaClTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->LongAlign = 32;
this->LongWidth = 32;
this->PointerAlign = 32;
this->PointerWidth = 32;
this->IntMaxType = TargetInfo::SignedLongLong;
this->Int64Type = TargetInfo::SignedLongLong;
this->DoubleAlign = 64;
this->LongDoubleWidth = 64;
this->LongDoubleAlign = 64;
this->LongLongWidth = 64;
this->LongLongAlign = 64;
this->SizeType = TargetInfo::UnsignedInt;
this->PtrDiffType = TargetInfo::SignedInt;
this->IntPtrType = TargetInfo::SignedInt;
// RegParmMax is inherited from the underlying architecture.
this->LongDoubleFormat = &llvm::APFloat::IEEEdouble();
if (Triple.getArch() == llvm::Triple::arm) {
// Handled in ARM's setABI().
} else if (Triple.getArch() == llvm::Triple::x86) {
this->resetDataLayout("e-m:e-p:32:32-i64:64-n8:16:32-S128");
} else if (Triple.getArch() == llvm::Triple::x86_64) {
this->resetDataLayout("e-m:e-p:32:32-i64:64-n8:16:32:64-S128");
} else if (Triple.getArch() == llvm::Triple::mipsel) {
// Handled on mips' setDataLayout.
} else {
assert(Triple.getArch() == llvm::Triple::le32);
this->resetDataLayout("e-p:32:32-i64:64");
}
}
};
// Fuchsia Target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY FuchsiaTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
Builder.defineMacro("__Fuchsia__");
Builder.defineMacro("__ELF__");
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
// Required by the libc++ locale support.
if (Opts.CPlusPlus)
Builder.defineMacro("_GNU_SOURCE");
}
public:
FuchsiaTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->MCountName = "__mcount";
}
};
// WebAssembly target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY WebAssemblyOSTargetInfo
: public OSTargetInfo<Target> {
+protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const final {
+ MacroBuilder &Builder) const {
// A common platform macro.
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
// Follow g++ convention and predefine _GNU_SOURCE for C++.
if (Opts.CPlusPlus)
Builder.defineMacro("_GNU_SOURCE");
}
public:
explicit WebAssemblyOSTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {
this->MCountName = "__mcount";
this->TheCXXABI.set(TargetCXXABI::WebAssembly);
}
+};
+
+// WASI target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY WASITargetInfo
+ : public WebAssemblyOSTargetInfo<Target> {
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const final {
+ WebAssemblyOSTargetInfo<Target>::getOSDefines(Opts, Triple, Builder);
+ Builder.defineMacro("__wasi__");
+ }
+
+public:
+ explicit WASITargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : WebAssemblyOSTargetInfo<Target>(Triple, Opts) {}
};
} // namespace targets
} // namespace clang
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_OSTARGETS_H
Index: vendor/clang/dist-release_80/lib/Basic/Targets/SPIR.h
===================================================================
--- vendor/clang/dist-release_80/lib/Basic/Targets/SPIR.h (revision 343795)
+++ vendor/clang/dist-release_80/lib/Basic/Targets/SPIR.h (revision 343796)
@@ -1,132 +1,133 @@
//===--- SPIR.h - Declare SPIR target feature support -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares SPIR TargetInfo objects.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
#define LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Compiler.h"
namespace clang {
namespace targets {
static const unsigned SPIRAddrSpaceMap[] = {
0, // Default
1, // opencl_global
3, // opencl_local
2, // opencl_constant
0, // opencl_private
4, // opencl_generic
0, // cuda_device
0, // cuda_constant
0 // cuda_shared
};
class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public TargetInfo {
public:
SPIRTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
: TargetInfo(Triple) {
assert(getTriple().getOS() == llvm::Triple::UnknownOS &&
"SPIR target must use unknown OS");
assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
"SPIR target must use unknown environment type");
TLSSupported = false;
VLASupported = false;
LongWidth = LongAlign = 64;
AddrSpaceMap = &SPIRAddrSpaceMap;
UseAddrSpaceMapMangling = true;
HasLegalHalfType = true;
+ HasFloat16 = true;
// Define available target features
// These must be defined in sorted order!
NoAsmVariants = true;
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
bool hasFeature(StringRef Feature) const override {
return Feature == "spir";
}
// SPIR supports the half type and the only llvm intrinsic allowed in SPIR is
// memcpy as per section 3 of the SPIR spec.
bool useFP16ConversionIntrinsics() const override { return false; }
ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; }
const char *getClobbers() const override { return ""; }
ArrayRef<const char *> getGCCRegNames() const override { return None; }
bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override {
return true;
}
ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
return None;
}
BuiltinVaListKind getBuiltinVaListKind() const override {
return TargetInfo::VoidPtrBuiltinVaList;
}
CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
return (CC == CC_SpirFunction || CC == CC_OpenCLKernel) ? CCCR_OK
: CCCR_Warning;
}
CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override {
return CC_SpirFunction;
}
void setSupportedOpenCLOpts() override {
// Assume all OpenCL extensions and optional core features are supported
// for SPIR since it is a generic target.
getSupportedOpenCLOpts().supportAll();
}
};
class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo {
public:
SPIR32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: SPIRTargetInfo(Triple, Opts) {
PointerWidth = PointerAlign = 32;
SizeType = TargetInfo::UnsignedInt;
PtrDiffType = IntPtrType = TargetInfo::SignedInt;
resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024");
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
};
class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public SPIRTargetInfo {
public:
SPIR64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: SPIRTargetInfo(Triple, Opts) {
PointerWidth = PointerAlign = 64;
SizeType = TargetInfo::UnsignedLong;
PtrDiffType = IntPtrType = TargetInfo::SignedLong;
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024");
}
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;
};
} // namespace targets
} // namespace clang
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
Index: vendor/clang/dist-release_80/lib/Basic/Targets.cpp
===================================================================
--- vendor/clang/dist-release_80/lib/Basic/Targets.cpp (revision 343795)
+++ vendor/clang/dist-release_80/lib/Basic/Targets.cpp (revision 343796)
@@ -1,662 +1,670 @@
//===--- Targets.cpp - Implement target feature support -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements construction of a TargetInfo object from a
// target triple.
//
//===----------------------------------------------------------------------===//
#include "Targets.h"
#include "Targets/AArch64.h"
#include "Targets/AMDGPU.h"
#include "Targets/ARC.h"
#include "Targets/ARM.h"
#include "Targets/AVR.h"
#include "Targets/BPF.h"
#include "Targets/Hexagon.h"
#include "Targets/Lanai.h"
#include "Targets/Le64.h"
#include "Targets/MSP430.h"
#include "Targets/Mips.h"
#include "Targets/NVPTX.h"
#include "Targets/OSTargets.h"
#include "Targets/PNaCl.h"
#include "Targets/PPC.h"
#include "Targets/RISCV.h"
#include "Targets/SPIR.h"
#include "Targets/Sparc.h"
#include "Targets/SystemZ.h"
#include "Targets/TCE.h"
#include "Targets/WebAssembly.h"
#include "Targets/X86.h"
#include "Targets/XCore.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
using namespace clang;
namespace clang {
namespace targets {
//===----------------------------------------------------------------------===//
// Common code shared among targets.
//===----------------------------------------------------------------------===//
/// DefineStd - Define a macro name and standard variants. For example if
/// MacroName is "unix", then this will define "__unix", "__unix__", and "unix"
/// when in GNU mode.
void DefineStd(MacroBuilder &Builder, StringRef MacroName,
const LangOptions &Opts) {
assert(MacroName[0] != '_' && "Identifier should be in the user's namespace");
// If in GNU mode (e.g. -std=gnu99 but not -std=c99) define the raw identifier
// in the user's namespace.
if (Opts.GNUMode)
Builder.defineMacro(MacroName);
// Define __unix.
Builder.defineMacro("__" + MacroName);
// Define __unix__.
Builder.defineMacro("__" + MacroName + "__");
}
void defineCPUMacros(MacroBuilder &Builder, StringRef CPUName, bool Tuning) {
Builder.defineMacro("__" + CPUName);
Builder.defineMacro("__" + CPUName + "__");
if (Tuning)
Builder.defineMacro("__tune_" + CPUName + "__");
}
void addCygMingDefines(const LangOptions &Opts, MacroBuilder &Builder) {
// Mingw and cygwin define __declspec(a) to __attribute__((a)). Clang
// supports __declspec natively under -fms-extensions, but we define a no-op
// __declspec macro anyway for pre-processor compatibility.
if (Opts.MicrosoftExt)
Builder.defineMacro("__declspec", "__declspec");
else
Builder.defineMacro("__declspec(a)", "__attribute__((a))");
if (!Opts.MicrosoftExt) {
// Provide macros for all the calling convention keywords. Provide both
// single and double underscore prefixed variants. These are available on
// x64 as well as x86, even though they have no effect.
const char *CCs[] = {"cdecl", "stdcall", "fastcall", "thiscall", "pascal"};
for (const char *CC : CCs) {
std::string GCCSpelling = "__attribute__((__";
GCCSpelling += CC;
GCCSpelling += "__))";
Builder.defineMacro(Twine("_") + CC, GCCSpelling);
Builder.defineMacro(Twine("__") + CC, GCCSpelling);
}
}
}
void addMinGWDefines(const llvm::Triple &Triple, const LangOptions &Opts,
MacroBuilder &Builder) {
DefineStd(Builder, "WIN32", Opts);
DefineStd(Builder, "WINNT", Opts);
if (Triple.isArch64Bit()) {
DefineStd(Builder, "WIN64", Opts);
Builder.defineMacro("__MINGW64__");
}
Builder.defineMacro("__MSVCRT__");
Builder.defineMacro("__MINGW32__");
addCygMingDefines(Opts, Builder);
}
//===----------------------------------------------------------------------===//
// Driver code
//===----------------------------------------------------------------------===//
TargetInfo *AllocateTarget(const llvm::Triple &Triple,
const TargetOptions &Opts) {
llvm::Triple::OSType os = Triple.getOS();
switch (Triple.getArch()) {
default:
return nullptr;
case llvm::Triple::arc:
return new ARCTargetInfo(Triple, Opts);
case llvm::Triple::xcore:
return new XCoreTargetInfo(Triple, Opts);
case llvm::Triple::hexagon:
return new HexagonTargetInfo(Triple, Opts);
case llvm::Triple::lanai:
return new LanaiTargetInfo(Triple, Opts);
case llvm::Triple::aarch64:
if (Triple.isOSDarwin())
return new DarwinAArch64TargetInfo(Triple, Opts);
switch (os) {
case llvm::Triple::CloudABI:
return new CloudABITargetInfo<AArch64leTargetInfo>(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<AArch64leTargetInfo>(Triple, Opts);
case llvm::Triple::Fuchsia:
return new FuchsiaTargetInfo<AArch64leTargetInfo>(Triple, Opts);
case llvm::Triple::Linux:
return new LinuxTargetInfo<AArch64leTargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<AArch64leTargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDTargetInfo<AArch64leTargetInfo>(Triple, Opts);
case llvm::Triple::Win32:
switch (Triple.getEnvironment()) {
case llvm::Triple::GNU:
return new MinGWARM64TargetInfo(Triple, Opts);
case llvm::Triple::MSVC:
default: // Assume MSVC for unknown environments
return new MicrosoftARM64TargetInfo(Triple, Opts);
}
default:
return new AArch64leTargetInfo(Triple, Opts);
}
case llvm::Triple::aarch64_be:
switch (os) {
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<AArch64beTargetInfo>(Triple, Opts);
case llvm::Triple::Fuchsia:
return new FuchsiaTargetInfo<AArch64beTargetInfo>(Triple, Opts);
case llvm::Triple::Linux:
return new LinuxTargetInfo<AArch64beTargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<AArch64beTargetInfo>(Triple, Opts);
default:
return new AArch64beTargetInfo(Triple, Opts);
}
case llvm::Triple::arm:
case llvm::Triple::thumb:
if (Triple.isOSBinFormatMachO())
return new DarwinARMTargetInfo(Triple, Opts);
switch (os) {
case llvm::Triple::CloudABI:
return new CloudABITargetInfo<ARMleTargetInfo>(Triple, Opts);
case llvm::Triple::Linux:
return new LinuxTargetInfo<ARMleTargetInfo>(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<ARMleTargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<ARMleTargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDTargetInfo<ARMleTargetInfo>(Triple, Opts);
case llvm::Triple::RTEMS:
return new RTEMSTargetInfo<ARMleTargetInfo>(Triple, Opts);
case llvm::Triple::NaCl:
return new NaClTargetInfo<ARMleTargetInfo>(Triple, Opts);
case llvm::Triple::Win32:
switch (Triple.getEnvironment()) {
case llvm::Triple::Cygnus:
return new CygwinARMTargetInfo(Triple, Opts);
case llvm::Triple::GNU:
return new MinGWARMTargetInfo(Triple, Opts);
case llvm::Triple::Itanium:
return new ItaniumWindowsARMleTargetInfo(Triple, Opts);
case llvm::Triple::MSVC:
default: // Assume MSVC for unknown environments
return new MicrosoftARMleTargetInfo(Triple, Opts);
}
default:
return new ARMleTargetInfo(Triple, Opts);
}
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
if (Triple.isOSDarwin())
return new DarwinARMTargetInfo(Triple, Opts);
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<ARMbeTargetInfo>(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<ARMbeTargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<ARMbeTargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDTargetInfo<ARMbeTargetInfo>(Triple, Opts);
case llvm::Triple::RTEMS:
return new RTEMSTargetInfo<ARMbeTargetInfo>(Triple, Opts);
case llvm::Triple::NaCl:
return new NaClTargetInfo<ARMbeTargetInfo>(Triple, Opts);
default:
return new ARMbeTargetInfo(Triple, Opts);
}
case llvm::Triple::avr:
return new AVRTargetInfo(Triple, Opts);
case llvm::Triple::bpfeb:
case llvm::Triple::bpfel:
return new BPFTargetInfo(Triple, Opts);
case llvm::Triple::msp430:
return new MSP430TargetInfo(Triple, Opts);
case llvm::Triple::mips:
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::RTEMS:
return new RTEMSTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
default:
return new MipsTargetInfo(Triple, Opts);
}
case llvm::Triple::mipsel:
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::RTEMS:
return new RTEMSTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::NaCl:
return new NaClTargetInfo<NaClMips32TargetInfo>(Triple, Opts);
default:
return new MipsTargetInfo(Triple, Opts);
}
case llvm::Triple::mips64:
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::RTEMS:
return new RTEMSTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
default:
return new MipsTargetInfo(Triple, Opts);
}
case llvm::Triple::mips64el:
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::RTEMS:
return new RTEMSTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDTargetInfo<MipsTargetInfo>(Triple, Opts);
default:
return new MipsTargetInfo(Triple, Opts);
}
case llvm::Triple::le32:
switch (os) {
case llvm::Triple::NaCl:
return new NaClTargetInfo<PNaClTargetInfo>(Triple, Opts);
default:
return nullptr;
}
case llvm::Triple::le64:
return new Le64TargetInfo(Triple, Opts);
case llvm::Triple::ppc:
if (Triple.isOSDarwin())
return new DarwinPPC32TargetInfo(Triple, Opts);
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<PPC32TargetInfo>(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<PPC32TargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<PPC32TargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDTargetInfo<PPC32TargetInfo>(Triple, Opts);
case llvm::Triple::RTEMS:
return new RTEMSTargetInfo<PPC32TargetInfo>(Triple, Opts);
default:
return new PPC32TargetInfo(Triple, Opts);
}
case llvm::Triple::ppc64:
if (Triple.isOSDarwin())
return new DarwinPPC64TargetInfo(Triple, Opts);
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<PPC64TargetInfo>(Triple, Opts);
case llvm::Triple::Lv2:
return new PS3PPUTargetInfo<PPC64TargetInfo>(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<PPC64TargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<PPC64TargetInfo>(Triple, Opts);
default:
return new PPC64TargetInfo(Triple, Opts);
}
case llvm::Triple::ppc64le:
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<PPC64TargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<PPC64TargetInfo>(Triple, Opts);
default:
return new PPC64TargetInfo(Triple, Opts);
}
case llvm::Triple::nvptx:
return new NVPTXTargetInfo(Triple, Opts, /*TargetPointerWidth=*/32);
case llvm::Triple::nvptx64:
return new NVPTXTargetInfo(Triple, Opts, /*TargetPointerWidth=*/64);
case llvm::Triple::amdgcn:
case llvm::Triple::r600:
return new AMDGPUTargetInfo(Triple, Opts);
case llvm::Triple::riscv32:
// TODO: add cases for FreeBSD, NetBSD, RTEMS once tested.
if (os == llvm::Triple::Linux)
return new LinuxTargetInfo<RISCV32TargetInfo>(Triple, Opts);
return new RISCV32TargetInfo(Triple, Opts);
case llvm::Triple::riscv64:
// TODO: add cases for FreeBSD, NetBSD, RTEMS once tested.
if (os == llvm::Triple::Linux)
return new LinuxTargetInfo<RISCV64TargetInfo>(Triple, Opts);
return new RISCV64TargetInfo(Triple, Opts);
case llvm::Triple::sparc:
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<SparcV8TargetInfo>(Triple, Opts);
case llvm::Triple::Solaris:
return new SolarisTargetInfo<SparcV8TargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<SparcV8TargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDTargetInfo<SparcV8TargetInfo>(Triple, Opts);
case llvm::Triple::RTEMS:
return new RTEMSTargetInfo<SparcV8TargetInfo>(Triple, Opts);
default:
return new SparcV8TargetInfo(Triple, Opts);
}
// The 'sparcel' architecture copies all the above cases except for Solaris.
case llvm::Triple::sparcel:
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<SparcV8elTargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<SparcV8elTargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDTargetInfo<SparcV8elTargetInfo>(Triple, Opts);
case llvm::Triple::RTEMS:
return new RTEMSTargetInfo<SparcV8elTargetInfo>(Triple, Opts);
default:
return new SparcV8elTargetInfo(Triple, Opts);
}
case llvm::Triple::sparcv9:
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<SparcV9TargetInfo>(Triple, Opts);
case llvm::Triple::Solaris:
return new SolarisTargetInfo<SparcV9TargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<SparcV9TargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDTargetInfo<SparcV9TargetInfo>(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<SparcV9TargetInfo>(Triple, Opts);
default:
return new SparcV9TargetInfo(Triple, Opts);
}
case llvm::Triple::systemz:
switch (os) {
case llvm::Triple::Linux:
return new LinuxTargetInfo<SystemZTargetInfo>(Triple, Opts);
default:
return new SystemZTargetInfo(Triple, Opts);
}
case llvm::Triple::tce:
return new TCETargetInfo(Triple, Opts);
case llvm::Triple::tcele:
return new TCELETargetInfo(Triple, Opts);
case llvm::Triple::x86:
if (Triple.isOSDarwin())
return new DarwinI386TargetInfo(Triple, Opts);
switch (os) {
case llvm::Triple::Ananas:
return new AnanasTargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::CloudABI:
return new CloudABITargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::Linux: {
switch (Triple.getEnvironment()) {
default:
return new LinuxTargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::Android:
return new AndroidX86_32TargetInfo(Triple, Opts);
}
}
case llvm::Triple::DragonFly:
return new DragonFlyBSDTargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDI386TargetInfo(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDI386TargetInfo(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::KFreeBSD:
return new KFreeBSDTargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::Minix:
return new MinixTargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::Solaris:
return new SolarisTargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::Win32: {
switch (Triple.getEnvironment()) {
case llvm::Triple::Cygnus:
return new CygwinX86_32TargetInfo(Triple, Opts);
case llvm::Triple::GNU:
return new MinGWX86_32TargetInfo(Triple, Opts);
case llvm::Triple::Itanium:
case llvm::Triple::MSVC:
default: // Assume MSVC for unknown environments
return new MicrosoftX86_32TargetInfo(Triple, Opts);
}
}
case llvm::Triple::Haiku:
return new HaikuX86_32TargetInfo(Triple, Opts);
case llvm::Triple::RTEMS:
return new RTEMSX86_32TargetInfo(Triple, Opts);
case llvm::Triple::NaCl:
return new NaClTargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::ELFIAMCU:
return new MCUX86_32TargetInfo(Triple, Opts);
case llvm::Triple::Hurd:
return new HurdTargetInfo<X86_32TargetInfo>(Triple, Opts);
default:
return new X86_32TargetInfo(Triple, Opts);
}
case llvm::Triple::x86_64:
if (Triple.isOSDarwin() || Triple.isOSBinFormatMachO())
return new DarwinX86_64TargetInfo(Triple, Opts);
switch (os) {
case llvm::Triple::Ananas:
return new AnanasTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::CloudABI:
return new CloudABITargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::Linux: {
switch (Triple.getEnvironment()) {
default:
return new LinuxTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::Android:
return new AndroidX86_64TargetInfo(Triple, Opts);
}
}
case llvm::Triple::DragonFly:
return new DragonFlyBSDTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::NetBSD:
return new NetBSDTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::OpenBSD:
return new OpenBSDX86_64TargetInfo(Triple, Opts);
case llvm::Triple::FreeBSD:
return new FreeBSDTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::Fuchsia:
return new FuchsiaTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::KFreeBSD:
return new KFreeBSDTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::Solaris:
return new SolarisTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::Win32: {
switch (Triple.getEnvironment()) {
case llvm::Triple::Cygnus:
return new CygwinX86_64TargetInfo(Triple, Opts);
case llvm::Triple::GNU:
return new MinGWX86_64TargetInfo(Triple, Opts);
case llvm::Triple::MSVC:
default: // Assume MSVC for unknown environments
return new MicrosoftX86_64TargetInfo(Triple, Opts);
}
}
case llvm::Triple::Haiku:
return new HaikuTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::NaCl:
return new NaClTargetInfo<X86_64TargetInfo>(Triple, Opts);
case llvm::Triple::PS4:
return new PS4OSTargetInfo<X86_64TargetInfo>(Triple, Opts);
default:
return new X86_64TargetInfo(Triple, Opts);
}
case llvm::Triple::spir: {
if (Triple.getOS() != llvm::Triple::UnknownOS ||
Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
return nullptr;
return new SPIR32TargetInfo(Triple, Opts);
}
case llvm::Triple::spir64: {
if (Triple.getOS() != llvm::Triple::UnknownOS ||
Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
return nullptr;
return new SPIR64TargetInfo(Triple, Opts);
}
case llvm::Triple::wasm32:
if (Triple.getSubArch() != llvm::Triple::NoSubArch ||
Triple.getVendor() != llvm::Triple::UnknownVendor ||
!Triple.isOSBinFormatWasm())
return nullptr;
- if (Triple.getOS() != llvm::Triple::UnknownOS &&
- Triple.getOS() != llvm::Triple::WASI)
- return nullptr;
- return new WebAssemblyOSTargetInfo<WebAssembly32TargetInfo>(Triple, Opts);
+ switch (Triple.getOS()) {
+ case llvm::Triple::WASI:
+ return new WASITargetInfo<WebAssembly32TargetInfo>(Triple, Opts);
+ case llvm::Triple::UnknownOS:
+ return new WebAssemblyOSTargetInfo<WebAssembly32TargetInfo>(Triple, Opts);
+ default:
+ return nullptr;
+ }
case llvm::Triple::wasm64:
if (Triple.getSubArch() != llvm::Triple::NoSubArch ||
Triple.getVendor() != llvm::Triple::UnknownVendor ||
!Triple.isOSBinFormatWasm())
return nullptr;
- if (Triple.getOS() != llvm::Triple::UnknownOS &&
- Triple.getOS() != llvm::Triple::WASI)
- return nullptr;
- return new WebAssemblyOSTargetInfo<WebAssembly64TargetInfo>(Triple, Opts);
+ switch (Triple.getOS()) {
+ case llvm::Triple::WASI:
+ return new WASITargetInfo<WebAssembly64TargetInfo>(Triple, Opts);
+ case llvm::Triple::UnknownOS:
+ return new WebAssemblyOSTargetInfo<WebAssembly64TargetInfo>(Triple, Opts);
+ default:
+ return nullptr;
+ }
case llvm::Triple::renderscript32:
return new LinuxTargetInfo<RenderScript32TargetInfo>(Triple, Opts);
case llvm::Triple::renderscript64:
return new LinuxTargetInfo<RenderScript64TargetInfo>(Triple, Opts);
}
}
} // namespace targets
} // namespace clang
using namespace clang::targets;
/// CreateTargetInfo - Return the target info object for the specified target
/// options.
TargetInfo *
TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags,
const std::shared_ptr<TargetOptions> &Opts) {
llvm::Triple Triple(Opts->Triple);
// Construct the target
std::unique_ptr<TargetInfo> Target(AllocateTarget(Triple, *Opts));
if (!Target) {
Diags.Report(diag::err_target_unknown_triple) << Triple.str();
return nullptr;
}
Target->TargetOpts = Opts;
// Set the target CPU if specified.
if (!Opts->CPU.empty() && !Target->setCPU(Opts->CPU)) {
Diags.Report(diag::err_target_unknown_cpu) << Opts->CPU;
SmallVector<StringRef, 32> ValidList;
Target->fillValidCPUList(ValidList);
if (!ValidList.empty())
Diags.Report(diag::note_valid_options) << llvm::join(ValidList, ", ");
return nullptr;
}
// Set the target ABI if specified.
if (!Opts->ABI.empty() && !Target->setABI(Opts->ABI)) {
Diags.Report(diag::err_target_unknown_abi) << Opts->ABI;
return nullptr;
}
// Set the fp math unit.
if (!Opts->FPMath.empty() && !Target->setFPMath(Opts->FPMath)) {
Diags.Report(diag::err_target_unknown_fpmath) << Opts->FPMath;
return nullptr;
}
// Compute the default target features, we need the target to handle this
// because features may have dependencies on one another.
llvm::StringMap<bool> Features;
if (!Target->initFeatureMap(Features, Diags, Opts->CPU,
Opts->FeaturesAsWritten))
return nullptr;
// Add the features to the compile options.
Opts->Features.clear();
for (const auto &F : Features)
Opts->Features.push_back((F.getValue() ? "+" : "-") + F.getKey().str());
// Sort here, so we handle the features in a predictable order. (This matters
// when we're dealing with features that overlap.)
llvm::sort(Opts->Features);
if (!Target->handleTargetFeatures(Opts->Features, Diags))
return nullptr;
Target->setSupportedOpenCLOpts();
Target->setOpenCLExtensionOpts();
Target->setMaxAtomicWidth();
if (!Target->validateTarget(Diags))
return nullptr;
Target->CheckFixedPointBits();
return Target.release();
}
Index: vendor/clang/dist-release_80/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- vendor/clang/dist-release_80/lib/Driver/ToolChains/Clang.cpp (revision 343795)
+++ vendor/clang/dist-release_80/lib/Driver/ToolChains/Clang.cpp (revision 343796)
@@ -1,6200 +1,6208 @@
//===--- LLVM.cpp - Clang+LLVM ToolChain Implementations --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "Clang.h"
#include "Arch/AArch64.h"
#include "Arch/ARM.h"
#include "Arch/Mips.h"
#include "Arch/PPC.h"
#include "Arch/RISCV.h"
#include "Arch/Sparc.h"
#include "Arch/SystemZ.h"
#include "Arch/X86.h"
#include "AMDGPU.h"
#include "CommonArgs.h"
#include "Hexagon.h"
#include "MSP430.h"
#include "InputInfo.h"
#include "PS4CPU.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
#include "clang/Driver/Distro.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "clang/Driver/XRayArgs.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/TargetParser.h"
#include "llvm/Support/YAMLParser.h"
#ifdef LLVM_ON_UNIX
#include <unistd.h> // For getuid().
#endif
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
static void CheckPreprocessingOptions(const Driver &D, const ArgList &Args) {
if (Arg *A =
Args.getLastArg(clang::driver::options::OPT_C, options::OPT_CC)) {
if (!Args.hasArg(options::OPT_E) && !Args.hasArg(options::OPT__SLASH_P) &&
!Args.hasArg(options::OPT__SLASH_EP) && !D.CCCIsCPP()) {
D.Diag(clang::diag::err_drv_argument_only_allowed_with)
<< A->getBaseArg().getAsString(Args)
<< (D.IsCLMode() ? "/E, /P or /EP" : "-E");
}
}
}
static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) {
// In gcc, only ARM checks this, but it seems reasonable to check universally.
if (Args.hasArg(options::OPT_static))
if (const Arg *A =
Args.getLastArg(options::OPT_dynamic, options::OPT_mdynamic_no_pic))
D.Diag(diag::err_drv_argument_not_allowed_with) << A->getAsString(Args)
<< "-static";
}
// Add backslashes to escape spaces and other backslashes.
// This is used for the space-separated argument list specified with
// the -dwarf-debug-flags option.
static void EscapeSpacesAndBackslashes(const char *Arg,
SmallVectorImpl<char> &Res) {
for (; *Arg; ++Arg) {
switch (*Arg) {
default:
break;
case ' ':
case '\\':
Res.push_back('\\');
break;
}
Res.push_back(*Arg);
}
}
// Quote target names for inclusion in GNU Make dependency files.
// Only the characters '$', '#', ' ', '\t' are quoted.
static void QuoteTarget(StringRef Target, SmallVectorImpl<char> &Res) {
for (unsigned i = 0, e = Target.size(); i != e; ++i) {
switch (Target[i]) {
case ' ':
case '\t':
// Escape the preceding backslashes
for (int j = i - 1; j >= 0 && Target[j] == '\\'; --j)
Res.push_back('\\');
// Escape the space/tab
Res.push_back('\\');
break;
case '$':
Res.push_back('$');
break;
case '#':
Res.push_back('\\');
break;
default:
break;
}
Res.push_back(Target[i]);
}
}
/// Apply \a Work on the current tool chain \a RegularToolChain and any other
/// offloading tool chain that is associated with the current action \a JA.
static void
forAllAssociatedToolChains(Compilation &C, const JobAction &JA,
const ToolChain &RegularToolChain,
llvm::function_ref<void(const ToolChain &)> Work) {
// Apply Work on the current/regular tool chain.
Work(RegularToolChain);
// Apply Work on all the offloading tool chains associated with the current
// action.
if (JA.isHostOffloading(Action::OFK_Cuda))
Work(*C.getSingleOffloadToolChain<Action::OFK_Cuda>());
else if (JA.isDeviceOffloading(Action::OFK_Cuda))
Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
else if (JA.isHostOffloading(Action::OFK_HIP))
Work(*C.getSingleOffloadToolChain<Action::OFK_HIP>());
else if (JA.isDeviceOffloading(Action::OFK_HIP))
Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
if (JA.isHostOffloading(Action::OFK_OpenMP)) {
auto TCs = C.getOffloadToolChains<Action::OFK_OpenMP>();
for (auto II = TCs.first, IE = TCs.second; II != IE; ++II)
Work(*II->second);
} else if (JA.isDeviceOffloading(Action::OFK_OpenMP))
Work(*C.getSingleOffloadToolChain<Action::OFK_Host>());
//
// TODO: Add support for other offloading programming models here.
//
}
/// This is a helper function for validating the optional refinement step
/// parameter in reciprocal argument strings. Return false if there is an error
/// parsing the refinement step. Otherwise, return true and set the Position
/// of the refinement step in the input string.
static bool getRefinementStep(StringRef In, const Driver &D,
const Arg &A, size_t &Position) {
const char RefinementStepToken = ':';
Position = In.find(RefinementStepToken);
if (Position != StringRef::npos) {
StringRef Option = A.getOption().getName();
StringRef RefStep = In.substr(Position + 1);
// Allow exactly one numeric character for the additional refinement
// step parameter. This is reasonable for all currently-supported
// operations and architectures because we would expect that a larger value
// of refinement steps would cause the estimate "optimization" to
// under-perform the native operation. Also, if the estimate does not
// converge quickly, it probably will not ever converge, so further
// refinement steps will not produce a better answer.
if (RefStep.size() != 1) {
D.Diag(diag::err_drv_invalid_value) << Option << RefStep;
return false;
}
char RefStepChar = RefStep[0];
if (RefStepChar < '0' || RefStepChar > '9') {
D.Diag(diag::err_drv_invalid_value) << Option << RefStep;
return false;
}
}
return true;
}
/// The -mrecip flag requires processing of many optional parameters.
static void ParseMRecip(const Driver &D, const ArgList &Args,
ArgStringList &OutStrings) {
StringRef DisabledPrefixIn = "!";
StringRef DisabledPrefixOut = "!";
StringRef EnabledPrefixOut = "";
StringRef Out = "-mrecip=";
Arg *A = Args.getLastArg(options::OPT_mrecip, options::OPT_mrecip_EQ);
if (!A)
return;
unsigned NumOptions = A->getNumValues();
if (NumOptions == 0) {
// No option is the same as "all".
OutStrings.push_back(Args.MakeArgString(Out + "all"));
return;
}
// Pass through "all", "none", or "default" with an optional refinement step.
if (NumOptions == 1) {
StringRef Val = A->getValue(0);
size_t RefStepLoc;
if (!getRefinementStep(Val, D, *A, RefStepLoc))
return;
StringRef ValBase = Val.slice(0, RefStepLoc);
if (ValBase == "all" || ValBase == "none" || ValBase == "default") {
OutStrings.push_back(Args.MakeArgString(Out + Val));
return;
}
}
// Each reciprocal type may be enabled or disabled individually.
// Check each input value for validity, concatenate them all back together,
// and pass through.
llvm::StringMap<bool> OptionStrings;
OptionStrings.insert(std::make_pair("divd", false));
OptionStrings.insert(std::make_pair("divf", false));
OptionStrings.insert(std::make_pair("vec-divd", false));
OptionStrings.insert(std::make_pair("vec-divf", false));
OptionStrings.insert(std::make_pair("sqrtd", false));
OptionStrings.insert(std::make_pair("sqrtf", false));
OptionStrings.insert(std::make_pair("vec-sqrtd", false));
OptionStrings.insert(std::make_pair("vec-sqrtf", false));
for (unsigned i = 0; i != NumOptions; ++i) {
StringRef Val = A->getValue(i);
bool IsDisabled = Val.startswith(DisabledPrefixIn);
// Ignore the disablement token for string matching.
if (IsDisabled)
Val = Val.substr(1);
size_t RefStep;
if (!getRefinementStep(Val, D, *A, RefStep))
return;
StringRef ValBase = Val.slice(0, RefStep);
llvm::StringMap<bool>::iterator OptionIter = OptionStrings.find(ValBase);
if (OptionIter == OptionStrings.end()) {
// Try again specifying float suffix.
OptionIter = OptionStrings.find(ValBase.str() + 'f');
if (OptionIter == OptionStrings.end()) {
// The input name did not match any known option string.
D.Diag(diag::err_drv_unknown_argument) << Val;
return;
}
// The option was specified without a float or double suffix.
// Make sure that the double entry was not already specified.
// The float entry will be checked below.
if (OptionStrings[ValBase.str() + 'd']) {
D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val;
return;
}
}
if (OptionIter->second == true) {
// Duplicate option specified.
D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val;
return;
}
// Mark the matched option as found. Do not allow duplicate specifiers.
OptionIter->second = true;
// If the precision was not specified, also mark the double entry as found.
if (ValBase.back() != 'f' && ValBase.back() != 'd')
OptionStrings[ValBase.str() + 'd'] = true;
// Build the output string.
StringRef Prefix = IsDisabled ? DisabledPrefixOut : EnabledPrefixOut;
Out = Args.MakeArgString(Out + Prefix + Val);
if (i != NumOptions - 1)
Out = Args.MakeArgString(Out + ",");
}
OutStrings.push_back(Args.MakeArgString(Out));
}
/// The -mprefer-vector-width option accepts either a positive integer
/// or the string "none".
static void ParseMPreferVectorWidth(const Driver &D, const ArgList &Args,
ArgStringList &CmdArgs) {
Arg *A = Args.getLastArg(options::OPT_mprefer_vector_width_EQ);
if (!A)
return;
StringRef Value = A->getValue();
if (Value == "none") {
CmdArgs.push_back("-mprefer-vector-width=none");
} else {
unsigned Width;
if (Value.getAsInteger(10, Width)) {
D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value;
return;
}
CmdArgs.push_back(Args.MakeArgString("-mprefer-vector-width=" + Value));
}
}
static void getWebAssemblyTargetFeatures(const ArgList &Args,
std::vector<StringRef> &Features) {
handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group);
}
static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple,
const ArgList &Args, ArgStringList &CmdArgs,
bool ForAS) {
const Driver &D = TC.getDriver();
std::vector<StringRef> Features;
switch (Triple.getArch()) {
default:
break;
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
mips::getMIPSTargetFeatures(D, Triple, Args, Features);
break;
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
arm::getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS);
break;
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
ppc::getPPCTargetFeatures(D, Triple, Args, Features);
break;
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
riscv::getRISCVTargetFeatures(D, Args, Features);
break;
case llvm::Triple::systemz:
systemz::getSystemZTargetFeatures(Args, Features);
break;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
aarch64::getAArch64TargetFeatures(D, Triple, Args, Features);
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
x86::getX86TargetFeatures(D, Triple, Args, Features);
break;
case llvm::Triple::hexagon:
hexagon::getHexagonTargetFeatures(D, Args, Features);
break;
case llvm::Triple::wasm32:
case llvm::Triple::wasm64:
getWebAssemblyTargetFeatures(Args, Features);
break;
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::sparcv9:
sparc::getSparcTargetFeatures(D, Args, Features);
break;
case llvm::Triple::r600:
case llvm::Triple::amdgcn:
amdgpu::getAMDGPUTargetFeatures(D, Args, Features);
break;
case llvm::Triple::msp430:
msp430::getMSP430TargetFeatures(D, Args, Features);
}
// Find the last of each feature.
llvm::StringMap<unsigned> LastOpt;
for (unsigned I = 0, N = Features.size(); I < N; ++I) {
StringRef Name = Features[I];
assert(Name[0] == '-' || Name[0] == '+');
LastOpt[Name.drop_front(1)] = I;
}
for (unsigned I = 0, N = Features.size(); I < N; ++I) {
// If this feature was overridden, ignore it.
StringRef Name = Features[I];
llvm::StringMap<unsigned>::iterator LastI = LastOpt.find(Name.drop_front(1));
assert(LastI != LastOpt.end());
unsigned Last = LastI->second;
if (Last != I)
continue;
CmdArgs.push_back("-target-feature");
CmdArgs.push_back(Name.data());
}
}
static bool
shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
const llvm::Triple &Triple) {
// We use the zero-cost exception tables for Objective-C if the non-fragile
// ABI is enabled or when compiling for x86_64 and ARM on Snow Leopard and
// later.
if (runtime.isNonFragile())
return true;
if (!Triple.isMacOSX())
return false;
return (!Triple.isMacOSXVersionLT(10, 5) &&
(Triple.getArch() == llvm::Triple::x86_64 ||
Triple.getArch() == llvm::Triple::arm));
}
/// Adds exception related arguments to the driver command arguments. There's a
/// master flag, -fexceptions and also language specific flags to enable/disable
/// C++ and Objective-C exceptions. This makes it possible to for example
/// disable C++ exceptions but enable Objective-C exceptions.
static void addExceptionArgs(const ArgList &Args, types::ID InputType,
const ToolChain &TC, bool KernelOrKext,
const ObjCRuntime &objcRuntime,
ArgStringList &CmdArgs) {
const llvm::Triple &Triple = TC.getTriple();
if (KernelOrKext) {
// -mkernel and -fapple-kext imply no exceptions, so claim exception related
// arguments now to avoid warnings about unused arguments.
Args.ClaimAllArgs(options::OPT_fexceptions);
Args.ClaimAllArgs(options::OPT_fno_exceptions);
Args.ClaimAllArgs(options::OPT_fobjc_exceptions);
Args.ClaimAllArgs(options::OPT_fno_objc_exceptions);
Args.ClaimAllArgs(options::OPT_fcxx_exceptions);
Args.ClaimAllArgs(options::OPT_fno_cxx_exceptions);
return;
}
// See if the user explicitly enabled exceptions.
bool EH = Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
false);
// Obj-C exceptions are enabled by default, regardless of -fexceptions. This
// is not necessarily sensible, but follows GCC.
if (types::isObjC(InputType) &&
Args.hasFlag(options::OPT_fobjc_exceptions,
options::OPT_fno_objc_exceptions, true)) {
CmdArgs.push_back("-fobjc-exceptions");
EH |= shouldUseExceptionTablesForObjCExceptions(objcRuntime, Triple);
}
if (types::isCXX(InputType)) {
// Disable C++ EH by default on XCore and PS4.
bool CXXExceptionsEnabled =
Triple.getArch() != llvm::Triple::xcore && !Triple.isPS4CPU();
Arg *ExceptionArg = Args.getLastArg(
options::OPT_fcxx_exceptions, options::OPT_fno_cxx_exceptions,
options::OPT_fexceptions, options::OPT_fno_exceptions);
if (ExceptionArg)
CXXExceptionsEnabled =
ExceptionArg->getOption().matches(options::OPT_fcxx_exceptions) ||
ExceptionArg->getOption().matches(options::OPT_fexceptions);
if (CXXExceptionsEnabled) {
CmdArgs.push_back("-fcxx-exceptions");
EH = true;
}
}
if (EH)
CmdArgs.push_back("-fexceptions");
}
static bool ShouldDisableAutolink(const ArgList &Args, const ToolChain &TC) {
bool Default = true;
if (TC.getTriple().isOSDarwin()) {
// The native darwin assembler doesn't support the linker_option directives,
// so we disable them if we think the .s file will be passed to it.
Default = TC.useIntegratedAs();
}
return !Args.hasFlag(options::OPT_fautolink, options::OPT_fno_autolink,
Default);
}
static bool ShouldDisableDwarfDirectory(const ArgList &Args,
const ToolChain &TC) {
bool UseDwarfDirectory =
Args.hasFlag(options::OPT_fdwarf_directory_asm,
options::OPT_fno_dwarf_directory_asm, TC.useIntegratedAs());
return !UseDwarfDirectory;
}
// Convert an arg of the form "-gN" or "-ggdbN" or one of their aliases
// to the corresponding DebugInfoKind.
static codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) {
assert(A.getOption().matches(options::OPT_gN_Group) &&
"Not a -g option that specifies a debug-info level");
if (A.getOption().matches(options::OPT_g0) ||
A.getOption().matches(options::OPT_ggdb0))
return codegenoptions::NoDebugInfo;
if (A.getOption().matches(options::OPT_gline_tables_only) ||
A.getOption().matches(options::OPT_ggdb1))
return codegenoptions::DebugLineTablesOnly;
if (A.getOption().matches(options::OPT_gline_directives_only))
return codegenoptions::DebugDirectivesOnly;
return codegenoptions::LimitedDebugInfo;
}
static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) {
switch (Triple.getArch()){
default:
return false;
case llvm::Triple::arm:
case llvm::Triple::thumb:
// ARM Darwin targets require a frame pointer to be always present to aid
// offline debugging via backtraces.
return Triple.isOSDarwin();
}
}
static bool useFramePointerForTargetByDefault(const ArgList &Args,
const llvm::Triple &Triple) {
switch (Triple.getArch()) {
case llvm::Triple::xcore:
case llvm::Triple::wasm32:
case llvm::Triple::wasm64:
// XCore never wants frame pointers, regardless of OS.
// WebAssembly never wants frame pointers.
return false;
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
return !areOptimizationsEnabled(Args);
default:
break;
}
if (Triple.isOSNetBSD()) {
return !areOptimizationsEnabled(Args);
}
if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI ||
Triple.isOSHurd()) {
switch (Triple.getArch()) {
// Don't use a frame pointer on linux if optimizing for certain targets.
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
case llvm::Triple::systemz:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
return !areOptimizationsEnabled(Args);
default:
return true;
}
}
if (Triple.isOSWindows()) {
switch (Triple.getArch()) {
case llvm::Triple::x86:
return !areOptimizationsEnabled(Args);
case llvm::Triple::x86_64:
return Triple.isOSBinFormatMachO();
case llvm::Triple::arm:
case llvm::Triple::thumb:
// Windows on ARM builds with FPO disabled to aid fast stack walking
return true;
default:
// All other supported Windows ISAs use xdata unwind information, so frame
// pointers are not generally useful.
return false;
}
}
return true;
}
static bool shouldUseFramePointer(const ArgList &Args,
const llvm::Triple &Triple) {
if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer,
options::OPT_fomit_frame_pointer))
return A->getOption().matches(options::OPT_fno_omit_frame_pointer) ||
mustUseNonLeafFramePointerForTarget(Triple);
if (Args.hasArg(options::OPT_pg))
return true;
return useFramePointerForTargetByDefault(Args, Triple);
}
static bool shouldUseLeafFramePointer(const ArgList &Args,
const llvm::Triple &Triple) {
if (Arg *A = Args.getLastArg(options::OPT_mno_omit_leaf_frame_pointer,
options::OPT_momit_leaf_frame_pointer))
return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer);
if (Args.hasArg(options::OPT_pg))
return true;
if (Triple.isPS4CPU())
return false;
return useFramePointerForTargetByDefault(Args, Triple);
}
/// Add a CC1 option to specify the debug compilation directory.
static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) {
SmallString<128> cwd;
if (!llvm::sys::fs::current_path(cwd)) {
CmdArgs.push_back("-fdebug-compilation-dir");
CmdArgs.push_back(Args.MakeArgString(cwd));
}
}
/// Add a CC1 and CC1AS option to specify the debug file path prefix map.
static void addDebugPrefixMapArg(const Driver &D, const ArgList &Args, ArgStringList &CmdArgs) {
for (const Arg *A : Args.filtered(options::OPT_fdebug_prefix_map_EQ)) {
StringRef Map = A->getValue();
if (Map.find('=') == StringRef::npos)
D.Diag(diag::err_drv_invalid_argument_to_fdebug_prefix_map) << Map;
else
CmdArgs.push_back(Args.MakeArgString("-fdebug-prefix-map=" + Map));
A->claim();
}
}
/// Vectorize at all optimization levels greater than 1 except for -Oz.
/// For -Oz the loop vectorizer is disable, while the slp vectorizer is enabled.
static bool shouldEnableVectorizerAtOLevel(const ArgList &Args, bool isSlpVec) {
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
if (A->getOption().matches(options::OPT_O4) ||
A->getOption().matches(options::OPT_Ofast))
return true;
if (A->getOption().matches(options::OPT_O0))
return false;
assert(A->getOption().matches(options::OPT_O) && "Must have a -O flag");
// Vectorize -Os.
StringRef S(A->getValue());
if (S == "s")
return true;
// Don't vectorize -Oz, unless it's the slp vectorizer.
if (S == "z")
return isSlpVec;
unsigned OptLevel = 0;
if (S.getAsInteger(10, OptLevel))
return false;
return OptLevel > 1;
}
return false;
}
/// Add -x lang to \p CmdArgs for \p Input.
static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
ArgStringList &CmdArgs) {
// When using -verify-pch, we don't want to provide the type
// 'precompiled-header' if it was inferred from the file extension
if (Args.hasArg(options::OPT_verify_pch) && Input.getType() == types::TY_PCH)
return;
CmdArgs.push_back("-x");
if (Args.hasArg(options::OPT_rewrite_objc))
CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX));
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) {
#ifdef LLVM_ON_UNIX
const char *Username = getenv("LOGNAME");
#else
const char *Username = getenv("USERNAME");
#endif
if (Username) {
// Validate that LoginName can be used in a path, and get its length.
size_t Len = 0;
for (const char *P = Username; *P; ++P, ++Len) {
if (!clang::isAlphanumeric(*P) && *P != '_') {
Username = nullptr;
break;
}
}
if (Username && Len > 0) {
Result.append(Username, Username + Len);
return;
}
}
// Fallback to user id.
#ifdef LLVM_ON_UNIX
std::string UID = llvm::utostr(getuid());
#else
// FIXME: Windows seems to have an 'SID' that might work.
std::string UID = "9999";
#endif
Result.append(UID.begin(), UID.end());
}
static void addPGOAndCoverageFlags(Compilation &C, const Driver &D,
const InputInfo &Output, const ArgList &Args,
ArgStringList &CmdArgs) {
auto *PGOGenerateArg = Args.getLastArg(options::OPT_fprofile_generate,
options::OPT_fprofile_generate_EQ,
options::OPT_fno_profile_generate);
if (PGOGenerateArg &&
PGOGenerateArg->getOption().matches(options::OPT_fno_profile_generate))
PGOGenerateArg = nullptr;
auto *ProfileGenerateArg = Args.getLastArg(
options::OPT_fprofile_instr_generate,
options::OPT_fprofile_instr_generate_EQ,
options::OPT_fno_profile_instr_generate);
if (ProfileGenerateArg &&
ProfileGenerateArg->getOption().matches(
options::OPT_fno_profile_instr_generate))
ProfileGenerateArg = nullptr;
if (PGOGenerateArg && ProfileGenerateArg)
D.Diag(diag::err_drv_argument_not_allowed_with)
<< PGOGenerateArg->getSpelling() << ProfileGenerateArg->getSpelling();
auto *ProfileUseArg = getLastProfileUseArg(Args);
if (PGOGenerateArg && ProfileUseArg)
D.Diag(diag::err_drv_argument_not_allowed_with)
<< ProfileUseArg->getSpelling() << PGOGenerateArg->getSpelling();
if (ProfileGenerateArg && ProfileUseArg)
D.Diag(diag::err_drv_argument_not_allowed_with)
<< ProfileGenerateArg->getSpelling() << ProfileUseArg->getSpelling();
if (ProfileGenerateArg) {
if (ProfileGenerateArg->getOption().matches(
options::OPT_fprofile_instr_generate_EQ))
CmdArgs.push_back(Args.MakeArgString(Twine("-fprofile-instrument-path=") +
ProfileGenerateArg->getValue()));
// The default is to use Clang Instrumentation.
CmdArgs.push_back("-fprofile-instrument=clang");
}
if (PGOGenerateArg) {
CmdArgs.push_back("-fprofile-instrument=llvm");
if (PGOGenerateArg->getOption().matches(
options::OPT_fprofile_generate_EQ)) {
SmallString<128> Path(PGOGenerateArg->getValue());
llvm::sys::path::append(Path, "default_%m.profraw");
CmdArgs.push_back(
Args.MakeArgString(Twine("-fprofile-instrument-path=") + Path));
}
}
if (ProfileUseArg) {
if (ProfileUseArg->getOption().matches(options::OPT_fprofile_instr_use_EQ))
CmdArgs.push_back(Args.MakeArgString(
Twine("-fprofile-instrument-use-path=") + ProfileUseArg->getValue()));
else if ((ProfileUseArg->getOption().matches(
options::OPT_fprofile_use_EQ) ||
ProfileUseArg->getOption().matches(
options::OPT_fprofile_instr_use))) {
SmallString<128> Path(
ProfileUseArg->getNumValues() == 0 ? "" : ProfileUseArg->getValue());
if (Path.empty() || llvm::sys::fs::is_directory(Path))
llvm::sys::path::append(Path, "default.profdata");
CmdArgs.push_back(
Args.MakeArgString(Twine("-fprofile-instrument-use-path=") + Path));
}
}
if (Args.hasArg(options::OPT_ftest_coverage) ||
Args.hasArg(options::OPT_coverage))
CmdArgs.push_back("-femit-coverage-notes");
if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
false) ||
Args.hasArg(options::OPT_coverage))
CmdArgs.push_back("-femit-coverage-data");
if (Args.hasFlag(options::OPT_fcoverage_mapping,
options::OPT_fno_coverage_mapping, false)) {
if (!ProfileGenerateArg)
D.Diag(clang::diag::err_drv_argument_only_allowed_with)
<< "-fcoverage-mapping"
<< "-fprofile-instr-generate";
CmdArgs.push_back("-fcoverage-mapping");
}
if (Args.hasArg(options::OPT_fprofile_exclude_files_EQ)) {
auto *Arg = Args.getLastArg(options::OPT_fprofile_exclude_files_EQ);
if (!Args.hasArg(options::OPT_coverage))
D.Diag(clang::diag::err_drv_argument_only_allowed_with)
<< "-fprofile-exclude-files="
<< "--coverage";
StringRef v = Arg->getValue();
CmdArgs.push_back(
Args.MakeArgString(Twine("-fprofile-exclude-files=" + v)));
}
if (Args.hasArg(options::OPT_fprofile_filter_files_EQ)) {
auto *Arg = Args.getLastArg(options::OPT_fprofile_filter_files_EQ);
if (!Args.hasArg(options::OPT_coverage))
D.Diag(clang::diag::err_drv_argument_only_allowed_with)
<< "-fprofile-filter-files="
<< "--coverage";
StringRef v = Arg->getValue();
CmdArgs.push_back(Args.MakeArgString(Twine("-fprofile-filter-files=" + v)));
}
if (C.getArgs().hasArg(options::OPT_c) ||
C.getArgs().hasArg(options::OPT_S)) {
if (Output.isFilename()) {
CmdArgs.push_back("-coverage-notes-file");
SmallString<128> OutputFilename;
if (Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o))
OutputFilename = FinalOutput->getValue();
else
OutputFilename = llvm::sys::path::filename(Output.getBaseInput());
SmallString<128> CoverageFilename = OutputFilename;
if (llvm::sys::path::is_relative(CoverageFilename)) {
SmallString<128> Pwd;
if (!llvm::sys::fs::current_path(Pwd)) {
llvm::sys::path::append(Pwd, CoverageFilename);
CoverageFilename.swap(Pwd);
}
}
llvm::sys::path::replace_extension(CoverageFilename, "gcno");
CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
// Leave -fprofile-dir= an unused argument unless .gcda emission is
// enabled. To be polite, with '-fprofile-arcs -fno-profile-arcs' consider
// the flag used. There is no -fno-profile-dir, so the user has no
// targeted way to suppress the warning.
if (Args.hasArg(options::OPT_fprofile_arcs) ||
Args.hasArg(options::OPT_coverage)) {
CmdArgs.push_back("-coverage-data-file");
if (Arg *FProfileDir = Args.getLastArg(options::OPT_fprofile_dir)) {
CoverageFilename = FProfileDir->getValue();
llvm::sys::path::append(CoverageFilename, OutputFilename);
}
llvm::sys::path::replace_extension(CoverageFilename, "gcda");
CmdArgs.push_back(Args.MakeArgString(CoverageFilename));
}
}
}
}
/// Check whether the given input tree contains any compilation actions.
static bool ContainsCompileAction(const Action *A) {
if (isa<CompileJobAction>(A) || isa<BackendJobAction>(A))
return true;
for (const auto &AI : A->inputs())
if (ContainsCompileAction(AI))
return true;
return false;
}
/// Check if -relax-all should be passed to the internal assembler.
/// This is done by default when compiling non-assembler source with -O0.
static bool UseRelaxAll(Compilation &C, const ArgList &Args) {
bool RelaxDefault = true;
if (Arg *A = Args.getLastArg(options::OPT_O_Group))
RelaxDefault = A->getOption().matches(options::OPT_O0);
if (RelaxDefault) {
RelaxDefault = false;
for (const auto &Act : C.getActions()) {
if (ContainsCompileAction(Act)) {
RelaxDefault = true;
break;
}
}
}
return Args.hasFlag(options::OPT_mrelax_all, options::OPT_mno_relax_all,
RelaxDefault);
}
// Extract the integer N from a string spelled "-dwarf-N", returning 0
// on mismatch. The StringRef input (rather than an Arg) allows
// for use by the "-Xassembler" option parser.
static unsigned DwarfVersionNum(StringRef ArgValue) {
return llvm::StringSwitch<unsigned>(ArgValue)
.Case("-gdwarf-2", 2)
.Case("-gdwarf-3", 3)
.Case("-gdwarf-4", 4)
.Case("-gdwarf-5", 5)
.Default(0);
}
static void RenderDebugEnablingArgs(const ArgList &Args, ArgStringList &CmdArgs,
codegenoptions::DebugInfoKind DebugInfoKind,
unsigned DwarfVersion,
llvm::DebuggerKind DebuggerTuning) {
switch (DebugInfoKind) {
case codegenoptions::DebugDirectivesOnly:
CmdArgs.push_back("-debug-info-kind=line-directives-only");
break;
case codegenoptions::DebugLineTablesOnly:
CmdArgs.push_back("-debug-info-kind=line-tables-only");
break;
case codegenoptions::LimitedDebugInfo:
CmdArgs.push_back("-debug-info-kind=limited");
break;
case codegenoptions::FullDebugInfo:
CmdArgs.push_back("-debug-info-kind=standalone");
break;
default:
break;
}
if (DwarfVersion > 0)
CmdArgs.push_back(
Args.MakeArgString("-dwarf-version=" + Twine(DwarfVersion)));
switch (DebuggerTuning) {
case llvm::DebuggerKind::GDB:
CmdArgs.push_back("-debugger-tuning=gdb");
break;
case llvm::DebuggerKind::LLDB:
CmdArgs.push_back("-debugger-tuning=lldb");
break;
case llvm::DebuggerKind::SCE:
CmdArgs.push_back("-debugger-tuning=sce");
break;
default:
break;
}
}
static bool checkDebugInfoOption(const Arg *A, const ArgList &Args,
const Driver &D, const ToolChain &TC) {
assert(A && "Expected non-nullptr argument.");
if (TC.supportsDebugInfoOption(A))
return true;
D.Diag(diag::warn_drv_unsupported_debug_info_opt_for_target)
<< A->getAsString(Args) << TC.getTripleString();
return false;
}
static void RenderDebugInfoCompressionArgs(const ArgList &Args,
ArgStringList &CmdArgs,
const Driver &D,
const ToolChain &TC) {
const Arg *A = Args.getLastArg(options::OPT_gz, options::OPT_gz_EQ);
if (!A)
return;
if (checkDebugInfoOption(A, Args, D, TC)) {
if (A->getOption().getID() == options::OPT_gz) {
if (llvm::zlib::isAvailable())
CmdArgs.push_back("-compress-debug-sections");
else
D.Diag(diag::warn_debug_compression_unavailable);
return;
}
StringRef Value = A->getValue();
if (Value == "none") {
CmdArgs.push_back("-compress-debug-sections=none");
} else if (Value == "zlib" || Value == "zlib-gnu") {
if (llvm::zlib::isAvailable()) {
CmdArgs.push_back(
Args.MakeArgString("-compress-debug-sections=" + Twine(Value)));
} else {
D.Diag(diag::warn_debug_compression_unavailable);
}
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
}
}
}
static const char *RelocationModelName(llvm::Reloc::Model Model) {
switch (Model) {
case llvm::Reloc::Static:
return "static";
case llvm::Reloc::PIC_:
return "pic";
case llvm::Reloc::DynamicNoPIC:
return "dynamic-no-pic";
case llvm::Reloc::ROPI:
return "ropi";
case llvm::Reloc::RWPI:
return "rwpi";
case llvm::Reloc::ROPI_RWPI:
return "ropi-rwpi";
}
llvm_unreachable("Unknown Reloc::Model kind");
}
void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
const Driver &D, const ArgList &Args,
ArgStringList &CmdArgs,
const InputInfo &Output,
const InputInfoList &Inputs) const {
Arg *A;
const bool IsIAMCU = getToolChain().getTriple().isOSIAMCU();
CheckPreprocessingOptions(D, Args);
Args.AddLastArg(CmdArgs, options::OPT_C);
Args.AddLastArg(CmdArgs, options::OPT_CC);
// Handle dependency file generation.
if ((A = Args.getLastArg(options::OPT_M, options::OPT_MM)) ||
(A = Args.getLastArg(options::OPT_MD)) ||
(A = Args.getLastArg(options::OPT_MMD))) {
// Determine the output location.
const char *DepFile;
if (Arg *MF = Args.getLastArg(options::OPT_MF)) {
DepFile = MF->getValue();
C.addFailureResultFile(DepFile, &JA);
} else if (Output.getType() == types::TY_Dependencies) {
DepFile = Output.getFilename();
} else if (A->getOption().matches(options::OPT_M) ||
A->getOption().matches(options::OPT_MM)) {
DepFile = "-";
} else {
DepFile = getDependencyFileName(Args, Inputs);
C.addFailureResultFile(DepFile, &JA);
}
CmdArgs.push_back("-dependency-file");
CmdArgs.push_back(DepFile);
// Add a default target if one wasn't specified.
if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) {
const char *DepTarget;
// If user provided -o, that is the dependency target, except
// when we are only generating a dependency file.
Arg *OutputOpt = Args.getLastArg(options::OPT_o);
if (OutputOpt && Output.getType() != types::TY_Dependencies) {
DepTarget = OutputOpt->getValue();
} else {
// Otherwise derive from the base input.
//
// FIXME: This should use the computed output file location.
SmallString<128> P(Inputs[0].getBaseInput());
llvm::sys::path::replace_extension(P, "o");
DepTarget = Args.MakeArgString(llvm::sys::path::filename(P));
}
if (!A->getOption().matches(options::OPT_MD) && !A->getOption().matches(options::OPT_MMD)) {
CmdArgs.push_back("-w");
}
CmdArgs.push_back("-MT");
SmallString<128> Quoted;
QuoteTarget(DepTarget, Quoted);
CmdArgs.push_back(Args.MakeArgString(Quoted));
}
if (A->getOption().matches(options::OPT_M) ||
A->getOption().matches(options::OPT_MD))
CmdArgs.push_back("-sys-header-deps");
if ((isa<PrecompileJobAction>(JA) &&
!Args.hasArg(options::OPT_fno_module_file_deps)) ||
Args.hasArg(options::OPT_fmodule_file_deps))
CmdArgs.push_back("-module-file-deps");
}
if (Args.hasArg(options::OPT_MG)) {
if (!A || A->getOption().matches(options::OPT_MD) ||
A->getOption().matches(options::OPT_MMD))
D.Diag(diag::err_drv_mg_requires_m_or_mm);
CmdArgs.push_back("-MG");
}
Args.AddLastArg(CmdArgs, options::OPT_MP);
Args.AddLastArg(CmdArgs, options::OPT_MV);
// Convert all -MQ <target> args to -MT <quoted target>
for (const Arg *A : Args.filtered(options::OPT_MT, options::OPT_MQ)) {
A->claim();
if (A->getOption().matches(options::OPT_MQ)) {
CmdArgs.push_back("-MT");
SmallString<128> Quoted;
QuoteTarget(A->getValue(), Quoted);
CmdArgs.push_back(Args.MakeArgString(Quoted));
// -MT flag - no change
} else {
A->render(Args, CmdArgs);
}
}
// Add offload include arguments specific for CUDA. This must happen before
// we -I or -include anything else, because we must pick up the CUDA headers
// from the particular CUDA installation, rather than from e.g.
// /usr/local/include.
if (JA.isOffloading(Action::OFK_Cuda))
getToolChain().AddCudaIncludeArgs(Args, CmdArgs);
// Add -i* options, and automatically translate to
// -include-pch/-include-pth for transparent PCH support. It's
// wonky, but we include looking for .gch so we can support seamless
// replacement into a build system already set up to be generating
// .gch files.
if (getToolChain().getDriver().IsCLMode()) {
const Arg *YcArg = Args.getLastArg(options::OPT__SLASH_Yc);
const Arg *YuArg = Args.getLastArg(options::OPT__SLASH_Yu);
if (YcArg && JA.getKind() >= Action::PrecompileJobClass &&
JA.getKind() <= Action::AssembleJobClass) {
CmdArgs.push_back(Args.MakeArgString("-building-pch-with-obj"));
}
if (YcArg || YuArg) {
StringRef ThroughHeader = YcArg ? YcArg->getValue() : YuArg->getValue();
if (!isa<PrecompileJobAction>(JA)) {
CmdArgs.push_back("-include-pch");
CmdArgs.push_back(Args.MakeArgString(D.GetClPchPath(
C, !ThroughHeader.empty()
? ThroughHeader
: llvm::sys::path::filename(Inputs[0].getBaseInput()))));
}
if (ThroughHeader.empty()) {
CmdArgs.push_back(Args.MakeArgString(
Twine("-pch-through-hdrstop-") + (YcArg ? "create" : "use")));
} else {
CmdArgs.push_back(
Args.MakeArgString(Twine("-pch-through-header=") + ThroughHeader));
}
}
}
bool RenderedImplicitInclude = false;
for (const Arg *A : Args.filtered(options::OPT_clang_i_Group)) {
if (A->getOption().matches(options::OPT_include)) {
// Handling of gcc-style gch precompiled headers.
bool IsFirstImplicitInclude = !RenderedImplicitInclude;
RenderedImplicitInclude = true;
bool FoundPCH = false;
SmallString<128> P(A->getValue());
// We want the files to have a name like foo.h.pch. Add a dummy extension
// so that replace_extension does the right thing.
P += ".dummy";
llvm::sys::path::replace_extension(P, "pch");
if (llvm::sys::fs::exists(P))
FoundPCH = true;
if (!FoundPCH) {
llvm::sys::path::replace_extension(P, "gch");
if (llvm::sys::fs::exists(P)) {
FoundPCH = true;
}
}
if (FoundPCH) {
if (IsFirstImplicitInclude) {
A->claim();
CmdArgs.push_back("-include-pch");
CmdArgs.push_back(Args.MakeArgString(P));
continue;
} else {
// Ignore the PCH if not first on command line and emit warning.
D.Diag(diag::warn_drv_pch_not_first_include) << P
<< A->getAsString(Args);
}
}
} else if (A->getOption().matches(options::OPT_isystem_after)) {
// Handling of paths which must come late. These entries are handled by
// the toolchain itself after the resource dir is inserted in the right
// search order.
// Do not claim the argument so that the use of the argument does not
// silently go unnoticed on toolchains which do not honour the option.
continue;
}
// Not translated, render as usual.
A->claim();
A->render(Args, CmdArgs);
}
Args.AddAllArgs(CmdArgs,
{options::OPT_D, options::OPT_U, options::OPT_I_Group,
options::OPT_F, options::OPT_index_header_map});
// Add -Wp, and -Xpreprocessor if using the preprocessor.
// FIXME: There is a very unfortunate problem here, some troubled
// souls abuse -Wp, to pass preprocessor options in gcc syntax. To
// really support that we would have to parse and then translate
// those options. :(
Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA,
options::OPT_Xpreprocessor);
// -I- is a deprecated GCC feature, reject it.
if (Arg *A = Args.getLastArg(options::OPT_I_))
D.Diag(diag::err_drv_I_dash_not_supported) << A->getAsString(Args);
// If we have a --sysroot, and don't have an explicit -isysroot flag, add an
// -isysroot to the CC1 invocation.
StringRef sysroot = C.getSysRoot();
if (sysroot != "") {
if (!Args.hasArg(options::OPT_isysroot)) {
CmdArgs.push_back("-isysroot");
CmdArgs.push_back(C.getArgs().MakeArgString(sysroot));
}
}
// Parse additional include paths from environment variables.
// FIXME: We should probably sink the logic for handling these from the
// frontend into the driver. It will allow deleting 4 otherwise unused flags.
// CPATH - included following the user specified includes (but prior to
// builtin and standard includes).
addDirectoryList(Args, CmdArgs, "-I", "CPATH");
// C_INCLUDE_PATH - system includes enabled when compiling C.
addDirectoryList(Args, CmdArgs, "-c-isystem", "C_INCLUDE_PATH");
// CPLUS_INCLUDE_PATH - system includes enabled when compiling C++.
addDirectoryList(Args, CmdArgs, "-cxx-isystem", "CPLUS_INCLUDE_PATH");
// OBJC_INCLUDE_PATH - system includes enabled when compiling ObjC.
addDirectoryList(Args, CmdArgs, "-objc-isystem", "OBJC_INCLUDE_PATH");
// OBJCPLUS_INCLUDE_PATH - system includes enabled when compiling ObjC++.
addDirectoryList(Args, CmdArgs, "-objcxx-isystem", "OBJCPLUS_INCLUDE_PATH");
// While adding the include arguments, we also attempt to retrieve the
// arguments of related offloading toolchains or arguments that are specific
// of an offloading programming model.
// Add C++ include arguments, if needed.
if (types::isCXX(Inputs[0].getType()))
forAllAssociatedToolChains(C, JA, getToolChain(),
[&Args, &CmdArgs](const ToolChain &TC) {
TC.AddClangCXXStdlibIncludeArgs(Args, CmdArgs);
});
// Add system include arguments for all targets but IAMCU.
if (!IsIAMCU)
forAllAssociatedToolChains(C, JA, getToolChain(),
[&Args, &CmdArgs](const ToolChain &TC) {
TC.AddClangSystemIncludeArgs(Args, CmdArgs);
});
else {
// For IAMCU add special include arguments.
getToolChain().AddIAMCUIncludeArgs(Args, CmdArgs);
}
}
// FIXME: Move to target hook.
static bool isSignedCharDefault(const llvm::Triple &Triple) {
switch (Triple.getArch()) {
default:
return true;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
if (Triple.isOSDarwin() || Triple.isOSWindows())
return true;
return false;
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
if (Triple.isOSDarwin())
return true;
return false;
case llvm::Triple::hexagon:
case llvm::Triple::ppc64le:
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
case llvm::Triple::systemz:
case llvm::Triple::xcore:
return false;
}
}
static bool isNoCommonDefault(const llvm::Triple &Triple) {
switch (Triple.getArch()) {
default:
if (Triple.isOSFuchsia())
return true;
return false;
case llvm::Triple::xcore:
case llvm::Triple::wasm32:
case llvm::Triple::wasm64:
return true;
}
}
namespace {
void RenderARMABI(const llvm::Triple &Triple, const ArgList &Args,
ArgStringList &CmdArgs) {
// Select the ABI to use.
// FIXME: Support -meabi.
// FIXME: Parts of this are duplicated in the backend, unify this somehow.
const char *ABIName = nullptr;
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
ABIName = A->getValue();
} else {
std::string CPU = getCPUName(Args, Triple, /*FromAs*/ false);
ABIName = llvm::ARM::computeDefaultTargetABI(Triple, CPU).data();
}
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
}
}
void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args,
ArgStringList &CmdArgs, bool KernelOrKext) const {
RenderARMABI(Triple, Args, CmdArgs);
// Determine floating point ABI from the options & target defaults.
arm::FloatABI ABI = arm::getARMFloatABI(getToolChain(), Args);
if (ABI == arm::FloatABI::Soft) {
// Floating point operations and argument passing are soft.
// FIXME: This changes CPP defines, we need -target-soft-float.
CmdArgs.push_back("-msoft-float");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("soft");
} else if (ABI == arm::FloatABI::SoftFP) {
// Floating point operations are hard, but argument passing is soft.
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("soft");
} else {
// Floating point operations and argument passing are hard.
assert(ABI == arm::FloatABI::Hard && "Invalid float abi!");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("hard");
}
// Forward the -mglobal-merge option for explicit control over the pass.
if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
options::OPT_mno_global_merge)) {
CmdArgs.push_back("-mllvm");
if (A->getOption().matches(options::OPT_mno_global_merge))
CmdArgs.push_back("-arm-global-merge=false");
else
CmdArgs.push_back("-arm-global-merge=true");
}
if (!Args.hasFlag(options::OPT_mimplicit_float,
options::OPT_mno_implicit_float, true))
CmdArgs.push_back("-no-implicit-float");
}
void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
const ArgList &Args, bool KernelOrKext,
ArgStringList &CmdArgs) const {
const ToolChain &TC = getToolChain();
// Add the target features
getTargetFeatures(TC, EffectiveTriple, Args, CmdArgs, false);
// Add target specific flags.
switch (TC.getArch()) {
default:
break;
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
// Use the effective triple, which takes into account the deployment target.
AddARMTargetArgs(EffectiveTriple, Args, CmdArgs, KernelOrKext);
CmdArgs.push_back("-fallow-half-arguments-and-returns");
break;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
AddAArch64TargetArgs(Args, CmdArgs);
CmdArgs.push_back("-fallow-half-arguments-and-returns");
break;
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
AddMIPSTargetArgs(Args, CmdArgs);
break;
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
AddPPCTargetArgs(Args, CmdArgs);
break;
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
AddRISCVTargetArgs(Args, CmdArgs);
break;
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::sparcv9:
AddSparcTargetArgs(Args, CmdArgs);
break;
case llvm::Triple::systemz:
AddSystemZTargetArgs(Args, CmdArgs);
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
AddX86TargetArgs(Args, CmdArgs);
break;
case llvm::Triple::lanai:
AddLanaiTargetArgs(Args, CmdArgs);
break;
case llvm::Triple::hexagon:
AddHexagonTargetArgs(Args, CmdArgs);
break;
case llvm::Triple::wasm32:
case llvm::Triple::wasm64:
AddWebAssemblyTargetArgs(Args, CmdArgs);
break;
}
}
// Parse -mbranch-protection=<protection>[+<protection>]* where
// <protection> ::= standard | none | [bti,pac-ret[+b-key,+leaf]*]
// Returns a triple of (return address signing Scope, signing key, require
// landing pads)
static std::tuple<StringRef, StringRef, bool>
ParseAArch64BranchProtection(const Driver &D, const ArgList &Args,
const Arg *A) {
StringRef Scope = "none";
StringRef Key = "a_key";
bool IndirectBranches = false;
StringRef Value = A->getValue();
// This maps onto -mbranch-protection=<scope>+<key>
if (Value.equals("standard")) {
Scope = "non-leaf";
Key = "a_key";
IndirectBranches = true;
} else if (!Value.equals("none")) {
SmallVector<StringRef, 4> BranchProtection;
StringRef(A->getValue()).split(BranchProtection, '+');
auto Protection = BranchProtection.begin();
while (Protection != BranchProtection.end()) {
if (Protection->equals("bti"))
IndirectBranches = true;
else if (Protection->equals("pac-ret")) {
Scope = "non-leaf";
while (++Protection != BranchProtection.end()) {
// Inner loop as "leaf" and "b-key" options must only appear attached
// to pac-ret.
if (Protection->equals("leaf"))
Scope = "all";
else if (Protection->equals("b-key"))
Key = "b_key";
else
break;
}
Protection--;
} else
D.Diag(diag::err_invalid_branch_protection)
<< *Protection << A->getAsString(Args);
Protection++;
}
}
return std::make_tuple(Scope, Key, IndirectBranches);
}
namespace {
void RenderAArch64ABI(const llvm::Triple &Triple, const ArgList &Args,
ArgStringList &CmdArgs) {
const char *ABIName = nullptr;
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
ABIName = A->getValue();
else if (Triple.isOSDarwin())
ABIName = "darwinpcs";
else
ABIName = "aapcs";
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
}
}
void Clang::AddAArch64TargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
Args.hasArg(options::OPT_mkernel) ||
Args.hasArg(options::OPT_fapple_kext))
CmdArgs.push_back("-disable-red-zone");
if (!Args.hasFlag(options::OPT_mimplicit_float,
options::OPT_mno_implicit_float, true))
CmdArgs.push_back("-no-implicit-float");
RenderAArch64ABI(Triple, Args, CmdArgs);
if (Arg *A = Args.getLastArg(options::OPT_mfix_cortex_a53_835769,
options::OPT_mno_fix_cortex_a53_835769)) {
CmdArgs.push_back("-mllvm");
if (A->getOption().matches(options::OPT_mfix_cortex_a53_835769))
CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
else
CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=0");
} else if (Triple.isAndroid()) {
// Enabled A53 errata (835769) workaround by default on android
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-aarch64-fix-cortex-a53-835769=1");
}
// Forward the -mglobal-merge option for explicit control over the pass.
if (Arg *A = Args.getLastArg(options::OPT_mglobal_merge,
options::OPT_mno_global_merge)) {
CmdArgs.push_back("-mllvm");
if (A->getOption().matches(options::OPT_mno_global_merge))
CmdArgs.push_back("-aarch64-enable-global-merge=false");
else
CmdArgs.push_back("-aarch64-enable-global-merge=true");
}
// Enable/disable return address signing and indirect branch targets.
if (Arg *A = Args.getLastArg(options::OPT_msign_return_address_EQ,
options::OPT_mbranch_protection_EQ)) {
const Driver &D = getToolChain().getDriver();
StringRef Scope, Key;
bool IndirectBranches;
if (A->getOption().matches(options::OPT_msign_return_address_EQ)) {
Scope = A->getValue();
if (!Scope.equals("none") && !Scope.equals("non-leaf") &&
!Scope.equals("all"))
D.Diag(diag::err_invalid_branch_protection)
<< Scope << A->getAsString(Args);
Key = "a_key";
IndirectBranches = false;
} else
std::tie(Scope, Key, IndirectBranches) =
ParseAArch64BranchProtection(D, Args, A);
CmdArgs.push_back(
Args.MakeArgString(Twine("-msign-return-address=") + Scope));
CmdArgs.push_back(
Args.MakeArgString(Twine("-msign-return-address-key=") + Key));
if (IndirectBranches)
CmdArgs.push_back("-mbranch-target-enforce");
}
}
void Clang::AddMIPSTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const Driver &D = getToolChain().getDriver();
StringRef CPUName;
StringRef ABIName;
const llvm::Triple &Triple = getToolChain().getTriple();
mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName.data());
mips::FloatABI ABI = mips::getMipsFloatABI(D, Args);
if (ABI == mips::FloatABI::Soft) {
// Floating point operations and argument passing are soft.
CmdArgs.push_back("-msoft-float");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("soft");
} else {
// Floating point operations and argument passing are hard.
assert(ABI == mips::FloatABI::Hard && "Invalid float abi!");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("hard");
}
if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) {
if (A->getOption().matches(options::OPT_mxgot)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-mxgot");
}
}
if (Arg *A = Args.getLastArg(options::OPT_mldc1_sdc1,
options::OPT_mno_ldc1_sdc1)) {
if (A->getOption().matches(options::OPT_mno_ldc1_sdc1)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-mno-ldc1-sdc1");
}
}
if (Arg *A = Args.getLastArg(options::OPT_mcheck_zero_division,
options::OPT_mno_check_zero_division)) {
if (A->getOption().matches(options::OPT_mno_check_zero_division)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-mno-check-zero-division");
}
}
if (Arg *A = Args.getLastArg(options::OPT_G)) {
StringRef v = A->getValue();
CmdArgs.push_back("-mllvm");
CmdArgs.push_back(Args.MakeArgString("-mips-ssection-threshold=" + v));
A->claim();
}
Arg *GPOpt = Args.getLastArg(options::OPT_mgpopt, options::OPT_mno_gpopt);
Arg *ABICalls =
Args.getLastArg(options::OPT_mabicalls, options::OPT_mno_abicalls);
// -mabicalls is the default for many MIPS environments, even with -fno-pic.
// -mgpopt is the default for static, -fno-pic environments but these two
// options conflict. We want to be certain that -mno-abicalls -mgpopt is
// the only case where -mllvm -mgpopt is passed.
// NOTE: We need a warning here or in the backend to warn when -mgpopt is
// passed explicitly when compiling something with -mabicalls
// (implictly) in affect. Currently the warning is in the backend.
//
// When the ABI in use is N64, we also need to determine the PIC mode that
// is in use, as -fno-pic for N64 implies -mno-abicalls.
bool NoABICalls =
ABICalls && ABICalls->getOption().matches(options::OPT_mno_abicalls);
llvm::Reloc::Model RelocationModel;
unsigned PICLevel;
bool IsPIE;
std::tie(RelocationModel, PICLevel, IsPIE) =
ParsePICArgs(getToolChain(), Args);
NoABICalls = NoABICalls ||
(RelocationModel == llvm::Reloc::Static && ABIName == "n64");
bool WantGPOpt = GPOpt && GPOpt->getOption().matches(options::OPT_mgpopt);
// We quietly ignore -mno-gpopt as the backend defaults to -mno-gpopt.
if (NoABICalls && (!GPOpt || WantGPOpt)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-mgpopt");
Arg *LocalSData = Args.getLastArg(options::OPT_mlocal_sdata,
options::OPT_mno_local_sdata);
Arg *ExternSData = Args.getLastArg(options::OPT_mextern_sdata,
options::OPT_mno_extern_sdata);
Arg *EmbeddedData = Args.getLastArg(options::OPT_membedded_data,
options::OPT_mno_embedded_data);
if (LocalSData) {
CmdArgs.push_back("-mllvm");
if (LocalSData->getOption().matches(options::OPT_mlocal_sdata)) {
CmdArgs.push_back("-mlocal-sdata=1");
} else {
CmdArgs.push_back("-mlocal-sdata=0");
}
LocalSData->claim();
}
if (ExternSData) {
CmdArgs.push_back("-mllvm");
if (ExternSData->getOption().matches(options::OPT_mextern_sdata)) {
CmdArgs.push_back("-mextern-sdata=1");
} else {
CmdArgs.push_back("-mextern-sdata=0");
}
ExternSData->claim();
}
if (EmbeddedData) {
CmdArgs.push_back("-mllvm");
if (EmbeddedData->getOption().matches(options::OPT_membedded_data)) {
CmdArgs.push_back("-membedded-data=1");
} else {
CmdArgs.push_back("-membedded-data=0");
}
EmbeddedData->claim();
}
} else if ((!ABICalls || (!NoABICalls && ABICalls)) && WantGPOpt)
D.Diag(diag::warn_drv_unsupported_gpopt) << (ABICalls ? 0 : 1);
if (GPOpt)
GPOpt->claim();
if (Arg *A = Args.getLastArg(options::OPT_mcompact_branches_EQ)) {
StringRef Val = StringRef(A->getValue());
if (mips::hasCompactBranches(CPUName)) {
if (Val == "never" || Val == "always" || Val == "optimal") {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back(Args.MakeArgString("-mips-compact-branches=" + Val));
} else
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
} else
D.Diag(diag::warn_target_unsupported_compact_branches) << CPUName;
}
+
+ if (Arg *A = Args.getLastArg(options::OPT_mrelax_pic_calls,
+ options::OPT_mno_relax_pic_calls)) {
+ if (A->getOption().matches(options::OPT_mno_relax_pic_calls)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-mips-jalr-reloc=0");
+ }
+ }
}
void Clang::AddPPCTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// Select the ABI to use.
const char *ABIName = nullptr;
if (getToolChain().getTriple().isOSLinux())
switch (getToolChain().getArch()) {
case llvm::Triple::ppc64: {
// When targeting a processor that supports QPX, or if QPX is
// specifically enabled, default to using the ABI that supports QPX (so
// long as it is not specifically disabled).
bool HasQPX = false;
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
HasQPX = A->getValue() == StringRef("a2q");
HasQPX = Args.hasFlag(options::OPT_mqpx, options::OPT_mno_qpx, HasQPX);
if (HasQPX) {
ABIName = "elfv1-qpx";
break;
}
ABIName = "elfv1";
break;
}
case llvm::Triple::ppc64le:
ABIName = "elfv2";
break;
default:
break;
}
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
// The ppc64 linux abis are all "altivec" abis by default. Accept and ignore
// the option if given as we don't have backend support for any targets
// that don't use the altivec abi.
if (StringRef(A->getValue()) != "altivec")
ABIName = A->getValue();
ppc::FloatABI FloatABI =
ppc::getPPCFloatABI(getToolChain().getDriver(), Args);
if (FloatABI == ppc::FloatABI::Soft) {
// Floating point operations and argument passing are soft.
CmdArgs.push_back("-msoft-float");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("soft");
} else {
// Floating point operations and argument passing are hard.
assert(FloatABI == ppc::FloatABI::Hard && "Invalid float abi!");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("hard");
}
if (ABIName) {
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
}
}
void Clang::AddRISCVTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// FIXME: currently defaults to the soft-float ABIs. Will need to be
// expanded to select ilp32f, ilp32d, lp64f, lp64d when appropriate.
const char *ABIName = nullptr;
const llvm::Triple &Triple = getToolChain().getTriple();
if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
ABIName = A->getValue();
else if (Triple.getArch() == llvm::Triple::riscv32)
ABIName = "ilp32";
else if (Triple.getArch() == llvm::Triple::riscv64)
ABIName = "lp64";
else
llvm_unreachable("Unexpected triple!");
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
}
void Clang::AddSparcTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
sparc::FloatABI FloatABI =
sparc::getSparcFloatABI(getToolChain().getDriver(), Args);
if (FloatABI == sparc::FloatABI::Soft) {
// Floating point operations and argument passing are soft.
CmdArgs.push_back("-msoft-float");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("soft");
} else {
// Floating point operations and argument passing are hard.
assert(FloatABI == sparc::FloatABI::Hard && "Invalid float abi!");
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("hard");
}
}
void Clang::AddSystemZTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
if (Args.hasFlag(options::OPT_mbackchain, options::OPT_mno_backchain, false))
CmdArgs.push_back("-mbackchain");
}
void Clang::AddX86TargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
Args.hasArg(options::OPT_mkernel) ||
Args.hasArg(options::OPT_fapple_kext))
CmdArgs.push_back("-disable-red-zone");
if (!Args.hasFlag(options::OPT_mtls_direct_seg_refs,
options::OPT_mno_tls_direct_seg_refs, true))
CmdArgs.push_back("-mno-tls-direct-seg-refs");
// Default to avoid implicit floating-point for kernel/kext code, but allow
// that to be overridden with -mno-soft-float.
bool NoImplicitFloat = (Args.hasArg(options::OPT_mkernel) ||
Args.hasArg(options::OPT_fapple_kext));
if (Arg *A = Args.getLastArg(
options::OPT_msoft_float, options::OPT_mno_soft_float,
options::OPT_mimplicit_float, options::OPT_mno_implicit_float)) {
const Option &O = A->getOption();
NoImplicitFloat = (O.matches(options::OPT_mno_implicit_float) ||
O.matches(options::OPT_msoft_float));
}
if (NoImplicitFloat)
CmdArgs.push_back("-no-implicit-float");
if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {
StringRef Value = A->getValue();
if (Value == "intel" || Value == "att") {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
} else {
getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
}
} else if (getToolChain().getDriver().IsCLMode()) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-x86-asm-syntax=intel");
}
// Set flags to support MCU ABI.
if (Args.hasFlag(options::OPT_miamcu, options::OPT_mno_iamcu, false)) {
CmdArgs.push_back("-mfloat-abi");
CmdArgs.push_back("soft");
CmdArgs.push_back("-mstack-alignment=4");
}
}
void Clang::AddHexagonTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CmdArgs.push_back("-mqdsp6-compat");
CmdArgs.push_back("-Wreturn-type");
if (auto G = toolchains::HexagonToolChain::getSmallDataThreshold(Args)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back(Args.MakeArgString("-hexagon-small-data-threshold=" +
Twine(G.getValue())));
}
if (!Args.hasArg(options::OPT_fno_short_enums))
CmdArgs.push_back("-fshort-enums");
if (Args.getLastArg(options::OPT_mieee_rnd_near)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-enable-hexagon-ieee-rnd-near");
}
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-machine-sink-split=0");
}
void Clang::AddLanaiTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
StringRef CPUName = A->getValue();
CmdArgs.push_back("-target-cpu");
CmdArgs.push_back(Args.MakeArgString(CPUName));
}
if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
StringRef Value = A->getValue();
// Only support mregparm=4 to support old usage. Report error for all other
// cases.
int Mregparm;
if (Value.getAsInteger(10, Mregparm)) {
if (Mregparm != 4) {
getToolChain().getDriver().Diag(
diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
}
}
}
}
void Clang::AddWebAssemblyTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// Default to "hidden" visibility.
if (!Args.hasArg(options::OPT_fvisibility_EQ,
options::OPT_fvisibility_ms_compat)) {
CmdArgs.push_back("-fvisibility");
CmdArgs.push_back("hidden");
}
}
void Clang::DumpCompilationDatabase(Compilation &C, StringRef Filename,
StringRef Target, const InputInfo &Output,
const InputInfo &Input, const ArgList &Args) const {
// If this is a dry run, do not create the compilation database file.
if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH))
return;
using llvm::yaml::escape;
const Driver &D = getToolChain().getDriver();
if (!CompilationDatabase) {
std::error_code EC;
auto File = llvm::make_unique<llvm::raw_fd_ostream>(Filename, EC, llvm::sys::fs::F_Text);
if (EC) {
D.Diag(clang::diag::err_drv_compilationdatabase) << Filename
<< EC.message();
return;
}
CompilationDatabase = std::move(File);
}
auto &CDB = *CompilationDatabase;
SmallString<128> Buf;
if (llvm::sys::fs::current_path(Buf))
Buf = ".";
CDB << "{ \"directory\": \"" << escape(Buf) << "\"";
CDB << ", \"file\": \"" << escape(Input.getFilename()) << "\"";
CDB << ", \"output\": \"" << escape(Output.getFilename()) << "\"";
CDB << ", \"arguments\": [\"" << escape(D.ClangExecutable) << "\"";
Buf = "-x";
Buf += types::getTypeName(Input.getType());
CDB << ", \"" << escape(Buf) << "\"";
if (!D.SysRoot.empty() && !Args.hasArg(options::OPT__sysroot_EQ)) {
Buf = "--sysroot=";
Buf += D.SysRoot;
CDB << ", \"" << escape(Buf) << "\"";
}
CDB << ", \"" << escape(Input.getFilename()) << "\"";
for (auto &A: Args) {
auto &O = A->getOption();
// Skip language selection, which is positional.
if (O.getID() == options::OPT_x)
continue;
// Skip writing dependency output and the compilation database itself.
if (O.getGroup().isValid() && O.getGroup().getID() == options::OPT_M_Group)
continue;
// Skip inputs.
if (O.getKind() == Option::InputClass)
continue;
// All other arguments are quoted and appended.
ArgStringList ASL;
A->render(Args, ASL);
for (auto &it: ASL)
CDB << ", \"" << escape(it) << "\"";
}
Buf = "--target=";
Buf += Target;
CDB << ", \"" << escape(Buf) << "\"]},\n";
}
static void CollectArgsForIntegratedAssembler(Compilation &C,
const ArgList &Args,
ArgStringList &CmdArgs,
const Driver &D) {
if (UseRelaxAll(C, Args))
CmdArgs.push_back("-mrelax-all");
// Only default to -mincremental-linker-compatible if we think we are
// targeting the MSVC linker.
bool DefaultIncrementalLinkerCompatible =
C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
if (Args.hasFlag(options::OPT_mincremental_linker_compatible,
options::OPT_mno_incremental_linker_compatible,
DefaultIncrementalLinkerCompatible))
CmdArgs.push_back("-mincremental-linker-compatible");
switch (C.getDefaultToolChain().getArch()) {
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
if (Arg *A = Args.getLastArg(options::OPT_mimplicit_it_EQ)) {
StringRef Value = A->getValue();
if (Value == "always" || Value == "never" || Value == "arm" ||
Value == "thumb") {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back(Args.MakeArgString("-arm-implicit-it=" + Value));
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
}
}
break;
default:
break;
}
// When passing -I arguments to the assembler we sometimes need to
// unconditionally take the next argument. For example, when parsing
// '-Wa,-I -Wa,foo' we need to accept the -Wa,foo arg after seeing the
// -Wa,-I arg and when parsing '-Wa,-I,foo' we need to accept the 'foo'
// arg after parsing the '-I' arg.
bool TakeNextArg = false;
bool UseRelaxRelocations = C.getDefaultToolChain().useRelaxRelocations();
const char *MipsTargetFeature = nullptr;
for (const Arg *A :
Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) {
A->claim();
for (StringRef Value : A->getValues()) {
if (TakeNextArg) {
CmdArgs.push_back(Value.data());
TakeNextArg = false;
continue;
}
if (C.getDefaultToolChain().getTriple().isOSBinFormatCOFF() &&
Value == "-mbig-obj")
continue; // LLVM handles bigobj automatically
switch (C.getDefaultToolChain().getArch()) {
default:
break;
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
case llvm::Triple::arm:
case llvm::Triple::armeb:
if (Value == "-mthumb")
// -mthumb has already been processed in ComputeLLVMTriple()
// recognize but skip over here.
continue;
break;
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
if (Value == "--trap") {
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("+use-tcc-in-div");
continue;
}
if (Value == "--break") {
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("-use-tcc-in-div");
continue;
}
if (Value.startswith("-msoft-float")) {
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("+soft-float");
continue;
}
if (Value.startswith("-mhard-float")) {
CmdArgs.push_back("-target-feature");
CmdArgs.push_back("-soft-float");
continue;
}
MipsTargetFeature = llvm::StringSwitch<const char *>(Value)
.Case("-mips1", "+mips1")
.Case("-mips2", "+mips2")
.Case("-mips3", "+mips3")
.Case("-mips4", "+mips4")
.Case("-mips5", "+mips5")
.Case("-mips32", "+mips32")
.Case("-mips32r2", "+mips32r2")
.Case("-mips32r3", "+mips32r3")
.Case("-mips32r5", "+mips32r5")
.Case("-mips32r6", "+mips32r6")
.Case("-mips64", "+mips64")
.Case("-mips64r2", "+mips64r2")
.Case("-mips64r3", "+mips64r3")
.Case("-mips64r5", "+mips64r5")
.Case("-mips64r6", "+mips64r6")
.Default(nullptr);
if (MipsTargetFeature)
continue;
}
if (Value == "-force_cpusubtype_ALL") {
// Do nothing, this is the default and we don't support anything else.
} else if (Value == "-L") {
CmdArgs.push_back("-msave-temp-labels");
} else if (Value == "--fatal-warnings") {
CmdArgs.push_back("-massembler-fatal-warnings");
} else if (Value == "--noexecstack") {
CmdArgs.push_back("-mnoexecstack");
} else if (Value.startswith("-compress-debug-sections") ||
Value.startswith("--compress-debug-sections") ||
Value == "-nocompress-debug-sections" ||
Value == "--nocompress-debug-sections") {
CmdArgs.push_back(Value.data());
} else if (Value == "-mrelax-relocations=yes" ||
Value == "--mrelax-relocations=yes") {
UseRelaxRelocations = true;
} else if (Value == "-mrelax-relocations=no" ||
Value == "--mrelax-relocations=no") {
UseRelaxRelocations = false;
} else if (Value.startswith("-I")) {
CmdArgs.push_back(Value.data());
// We need to consume the next argument if the current arg is a plain
// -I. The next arg will be the include directory.
if (Value == "-I")
TakeNextArg = true;
} else if (Value.startswith("-gdwarf-")) {
// "-gdwarf-N" options are not cc1as options.
unsigned DwarfVersion = DwarfVersionNum(Value);
if (DwarfVersion == 0) { // Send it onward, and let cc1as complain.
CmdArgs.push_back(Value.data());
} else {
RenderDebugEnablingArgs(Args, CmdArgs,
codegenoptions::LimitedDebugInfo,
DwarfVersion, llvm::DebuggerKind::Default);
}
} else if (Value.startswith("-mcpu") || Value.startswith("-mfpu") ||
Value.startswith("-mhwdiv") || Value.startswith("-march")) {
// Do nothing, we'll validate it later.
} else if (Value == "-defsym") {
if (A->getNumValues() != 2) {
D.Diag(diag::err_drv_defsym_invalid_format) << Value;
break;
}
const char *S = A->getValue(1);
auto Pair = StringRef(S).split('=');
auto Sym = Pair.first;
auto SVal = Pair.second;
if (Sym.empty() || SVal.empty()) {
D.Diag(diag::err_drv_defsym_invalid_format) << S;
break;
}
int64_t IVal;
if (SVal.getAsInteger(0, IVal)) {
D.Diag(diag::err_drv_defsym_invalid_symval) << SVal;
break;
}
CmdArgs.push_back(Value.data());
TakeNextArg = true;
} else if (Value == "-fdebug-compilation-dir") {
CmdArgs.push_back("-fdebug-compilation-dir");
TakeNextArg = true;
} else {
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
}
}
}
if (UseRelaxRelocations)
CmdArgs.push_back("--mrelax-relocations");
if (MipsTargetFeature != nullptr) {
CmdArgs.push_back("-target-feature");
CmdArgs.push_back(MipsTargetFeature);
}
// forward -fembed-bitcode to assmebler
if (C.getDriver().embedBitcodeEnabled() ||
C.getDriver().embedBitcodeMarkerOnly())
Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ);
}
static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
bool OFastEnabled, const ArgList &Args,
ArgStringList &CmdArgs) {
// Handle various floating point optimization flags, mapping them to the
// appropriate LLVM code generation flags. This is complicated by several
// "umbrella" flags, so we do this by stepping through the flags incrementally
// adjusting what we think is enabled/disabled, then at the end setting the
// LLVM flags based on the final state.
bool HonorINFs = true;
bool HonorNaNs = true;
// -fmath-errno is the default on some platforms, e.g. BSD-derived OSes.
bool MathErrno = TC.IsMathErrnoDefault();
bool AssociativeMath = false;
bool ReciprocalMath = false;
bool SignedZeros = true;
bool TrappingMath = true;
StringRef DenormalFPMath = "";
StringRef FPContract = "";
if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
CmdArgs.push_back("-mlimit-float-precision");
CmdArgs.push_back(A->getValue());
}
for (const Arg *A : Args) {
switch (A->getOption().getID()) {
// If this isn't an FP option skip the claim below
default: continue;
// Options controlling individual features
case options::OPT_fhonor_infinities: HonorINFs = true; break;
case options::OPT_fno_honor_infinities: HonorINFs = false; break;
case options::OPT_fhonor_nans: HonorNaNs = true; break;
case options::OPT_fno_honor_nans: HonorNaNs = false; break;
case options::OPT_fmath_errno: MathErrno = true; break;
case options::OPT_fno_math_errno: MathErrno = false; break;
case options::OPT_fassociative_math: AssociativeMath = true; break;
case options::OPT_fno_associative_math: AssociativeMath = false; break;
case options::OPT_freciprocal_math: ReciprocalMath = true; break;
case options::OPT_fno_reciprocal_math: ReciprocalMath = false; break;
case options::OPT_fsigned_zeros: SignedZeros = true; break;
case options::OPT_fno_signed_zeros: SignedZeros = false; break;
case options::OPT_ftrapping_math: TrappingMath = true; break;
case options::OPT_fno_trapping_math: TrappingMath = false; break;
case options::OPT_fdenormal_fp_math_EQ:
DenormalFPMath = A->getValue();
break;
// Validate and pass through -fp-contract option.
case options::OPT_ffp_contract: {
StringRef Val = A->getValue();
if (Val == "fast" || Val == "on" || Val == "off")
FPContract = Val;
else
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
break;
}
case options::OPT_ffinite_math_only:
HonorINFs = false;
HonorNaNs = false;
break;
case options::OPT_fno_finite_math_only:
HonorINFs = true;
HonorNaNs = true;
break;
case options::OPT_funsafe_math_optimizations:
AssociativeMath = true;
ReciprocalMath = true;
SignedZeros = false;
TrappingMath = false;
break;
case options::OPT_fno_unsafe_math_optimizations:
AssociativeMath = false;
ReciprocalMath = false;
SignedZeros = true;
TrappingMath = true;
// -fno_unsafe_math_optimizations restores default denormal handling
DenormalFPMath = "";
break;
case options::OPT_Ofast:
// If -Ofast is the optimization level, then -ffast-math should be enabled
if (!OFastEnabled)
continue;
LLVM_FALLTHROUGH;
case options::OPT_ffast_math:
HonorINFs = false;
HonorNaNs = false;
MathErrno = false;
AssociativeMath = true;
ReciprocalMath = true;
SignedZeros = false;
TrappingMath = false;
// If fast-math is set then set the fp-contract mode to fast.
FPContract = "fast";
break;
case options::OPT_fno_fast_math:
HonorINFs = true;
HonorNaNs = true;
// Turning on -ffast-math (with either flag) removes the need for
// MathErrno. However, turning *off* -ffast-math merely restores the
// toolchain default (which may be false).
MathErrno = TC.IsMathErrnoDefault();
AssociativeMath = false;
ReciprocalMath = false;
SignedZeros = true;
TrappingMath = true;
// -fno_fast_math restores default denormal and fpcontract handling
DenormalFPMath = "";
FPContract = "";
break;
}
// If we handled this option claim it
A->claim();
}
if (!HonorINFs)
CmdArgs.push_back("-menable-no-infs");
if (!HonorNaNs)
CmdArgs.push_back("-menable-no-nans");
if (MathErrno)
CmdArgs.push_back("-fmath-errno");
if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros &&
!TrappingMath)
CmdArgs.push_back("-menable-unsafe-fp-math");
if (!SignedZeros)
CmdArgs.push_back("-fno-signed-zeros");
if (AssociativeMath && !SignedZeros && !TrappingMath)
CmdArgs.push_back("-mreassociate");
if (ReciprocalMath)
CmdArgs.push_back("-freciprocal-math");
if (!TrappingMath)
CmdArgs.push_back("-fno-trapping-math");
if (!DenormalFPMath.empty())
CmdArgs.push_back(
Args.MakeArgString("-fdenormal-fp-math=" + DenormalFPMath));
if (!FPContract.empty())
CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + FPContract));
ParseMRecip(D, Args, CmdArgs);
// -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the
// individual features enabled by -ffast-math instead of the option itself as
// that's consistent with gcc's behaviour.
if (!HonorINFs && !HonorNaNs && !MathErrno && AssociativeMath &&
ReciprocalMath && !SignedZeros && !TrappingMath)
CmdArgs.push_back("-ffast-math");
// Handle __FINITE_MATH_ONLY__ similarly.
if (!HonorINFs && !HonorNaNs)
CmdArgs.push_back("-ffinite-math-only");
if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) {
CmdArgs.push_back("-mfpmath");
CmdArgs.push_back(A->getValue());
}
// Disable a codegen optimization for floating-point casts.
if (Args.hasFlag(options::OPT_fno_strict_float_cast_overflow,
options::OPT_fstrict_float_cast_overflow, false))
CmdArgs.push_back("-fno-strict-float-cast-overflow");
}
static void RenderAnalyzerOptions(const ArgList &Args, ArgStringList &CmdArgs,
const llvm::Triple &Triple,
const InputInfo &Input) {
// Enable region store model by default.
CmdArgs.push_back("-analyzer-store=region");
// Treat blocks as analysis entry points.
CmdArgs.push_back("-analyzer-opt-analyze-nested-blocks");
// Add default argument set.
if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) {
CmdArgs.push_back("-analyzer-checker=core");
CmdArgs.push_back("-analyzer-checker=apiModeling");
if (!Triple.isWindowsMSVCEnvironment()) {
CmdArgs.push_back("-analyzer-checker=unix");
} else {
// Enable "unix" checkers that also work on Windows.
CmdArgs.push_back("-analyzer-checker=unix.API");
CmdArgs.push_back("-analyzer-checker=unix.Malloc");
CmdArgs.push_back("-analyzer-checker=unix.MallocSizeof");
CmdArgs.push_back("-analyzer-checker=unix.MismatchedDeallocator");
CmdArgs.push_back("-analyzer-checker=unix.cstring.BadSizeArg");
CmdArgs.push_back("-analyzer-checker=unix.cstring.NullArg");
}
// Disable some unix checkers for PS4.
if (Triple.isPS4CPU()) {
CmdArgs.push_back("-analyzer-disable-checker=unix.API");
CmdArgs.push_back("-analyzer-disable-checker=unix.Vfork");
}
if (Triple.isOSDarwin())
CmdArgs.push_back("-analyzer-checker=osx");
CmdArgs.push_back("-analyzer-checker=deadcode");
if (types::isCXX(Input.getType()))
CmdArgs.push_back("-analyzer-checker=cplusplus");
if (!Triple.isPS4CPU()) {
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.UncheckedReturn");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp");
CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork");
}
// Default nullability checks.
CmdArgs.push_back("-analyzer-checker=nullability.NullPassedToNonnull");
CmdArgs.push_back("-analyzer-checker=nullability.NullReturnedFromNonnull");
}
// Set the output format. The default is plist, for (lame) historical reasons.
CmdArgs.push_back("-analyzer-output");
if (Arg *A = Args.getLastArg(options::OPT__analyzer_output))
CmdArgs.push_back(A->getValue());
else
CmdArgs.push_back("plist");
// Disable the presentation of standard compiler warnings when using
// --analyze. We only want to show static analyzer diagnostics or frontend
// errors.
CmdArgs.push_back("-w");
// Add -Xanalyzer arguments when running as analyzer.
Args.AddAllArgValues(CmdArgs, options::OPT_Xanalyzer);
}
static void RenderSSPOptions(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs, bool KernelOrKext) {
const llvm::Triple &EffectiveTriple = TC.getEffectiveTriple();
// NVPTX doesn't support stack protectors; from the compiler's perspective, it
// doesn't even have a stack!
if (EffectiveTriple.isNVPTX())
return;
// -stack-protector=0 is default.
unsigned StackProtectorLevel = 0;
unsigned DefaultStackProtectorLevel =
TC.GetDefaultStackProtectorLevel(KernelOrKext);
if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector,
options::OPT_fstack_protector_all,
options::OPT_fstack_protector_strong,
options::OPT_fstack_protector)) {
if (A->getOption().matches(options::OPT_fstack_protector))
StackProtectorLevel =
std::max<unsigned>(LangOptions::SSPOn, DefaultStackProtectorLevel);
else if (A->getOption().matches(options::OPT_fstack_protector_strong))
StackProtectorLevel = LangOptions::SSPStrong;
else if (A->getOption().matches(options::OPT_fstack_protector_all))
StackProtectorLevel = LangOptions::SSPReq;
} else {
StackProtectorLevel = DefaultStackProtectorLevel;
}
if (StackProtectorLevel) {
CmdArgs.push_back("-stack-protector");
CmdArgs.push_back(Args.MakeArgString(Twine(StackProtectorLevel)));
}
// --param ssp-buffer-size=
for (const Arg *A : Args.filtered(options::OPT__param)) {
StringRef Str(A->getValue());
if (Str.startswith("ssp-buffer-size=")) {
if (StackProtectorLevel) {
CmdArgs.push_back("-stack-protector-buffer-size");
// FIXME: Verify the argument is a valid integer.
CmdArgs.push_back(Args.MakeArgString(Str.drop_front(16)));
}
A->claim();
}
}
}
static void RenderTrivialAutoVarInitOptions(const Driver &D,
const ToolChain &TC,
const ArgList &Args,
ArgStringList &CmdArgs) {
auto DefaultTrivialAutoVarInit = TC.GetDefaultTrivialAutoVarInit();
StringRef TrivialAutoVarInit = "";
for (const Arg *A : Args) {
switch (A->getOption().getID()) {
default:
continue;
case options::OPT_ftrivial_auto_var_init: {
A->claim();
StringRef Val = A->getValue();
if (Val == "uninitialized" || Val == "zero" || Val == "pattern")
TrivialAutoVarInit = Val;
else
D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
break;
}
}
}
if (TrivialAutoVarInit.empty())
switch (DefaultTrivialAutoVarInit) {
case LangOptions::TrivialAutoVarInitKind::Uninitialized:
break;
case LangOptions::TrivialAutoVarInitKind::Pattern:
TrivialAutoVarInit = "pattern";
break;
case LangOptions::TrivialAutoVarInitKind::Zero:
TrivialAutoVarInit = "zero";
break;
}
if (!TrivialAutoVarInit.empty()) {
if (TrivialAutoVarInit == "zero" && !Args.hasArg(options::OPT_enable_trivial_var_init_zero))
D.Diag(diag::err_drv_trivial_auto_var_init_zero_disabled);
CmdArgs.push_back(
Args.MakeArgString("-ftrivial-auto-var-init=" + TrivialAutoVarInit));
}
}
static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs) {
const unsigned ForwardedArguments[] = {
options::OPT_cl_opt_disable,
options::OPT_cl_strict_aliasing,
options::OPT_cl_single_precision_constant,
options::OPT_cl_finite_math_only,
options::OPT_cl_kernel_arg_info,
options::OPT_cl_unsafe_math_optimizations,
options::OPT_cl_fast_relaxed_math,
options::OPT_cl_mad_enable,
options::OPT_cl_no_signed_zeros,
options::OPT_cl_denorms_are_zero,
options::OPT_cl_fp32_correctly_rounded_divide_sqrt,
options::OPT_cl_uniform_work_group_size
};
if (Arg *A = Args.getLastArg(options::OPT_cl_std_EQ)) {
std::string CLStdStr = std::string("-cl-std=") + A->getValue();
CmdArgs.push_back(Args.MakeArgString(CLStdStr));
}
for (const auto &Arg : ForwardedArguments)
if (const auto *A = Args.getLastArg(Arg))
CmdArgs.push_back(Args.MakeArgString(A->getOption().getPrefixedName()));
}
static void RenderARCMigrateToolOptions(const Driver &D, const ArgList &Args,
ArgStringList &CmdArgs) {
bool ARCMTEnabled = false;
if (!Args.hasArg(options::OPT_fno_objc_arc, options::OPT_fobjc_arc)) {
if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check,
options::OPT_ccc_arcmt_modify,
options::OPT_ccc_arcmt_migrate)) {
ARCMTEnabled = true;
switch (A->getOption().getID()) {
default: llvm_unreachable("missed a case");
case options::OPT_ccc_arcmt_check:
CmdArgs.push_back("-arcmt-check");
break;
case options::OPT_ccc_arcmt_modify:
CmdArgs.push_back("-arcmt-modify");
break;
case options::OPT_ccc_arcmt_migrate:
CmdArgs.push_back("-arcmt-migrate");
CmdArgs.push_back("-mt-migrate-directory");
CmdArgs.push_back(A->getValue());
Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output);
Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_emit_arc_errors);
break;
}
}
} else {
Args.ClaimAllArgs(options::OPT_ccc_arcmt_check);
Args.ClaimAllArgs(options::OPT_ccc_arcmt_modify);
Args.ClaimAllArgs(options::OPT_ccc_arcmt_migrate);
}
if (const Arg *A = Args.getLastArg(options::OPT_ccc_objcmt_migrate)) {
if (ARCMTEnabled)
D.Diag(diag::err_drv_argument_not_allowed_with)
<< A->getAsString(Args) << "-ccc-arcmt-migrate";
CmdArgs.push_back("-mt-migrate-directory");
CmdArgs.push_back(A->getValue());
if (!Args.hasArg(options::OPT_objcmt_migrate_literals,
options::OPT_objcmt_migrate_subscripting,
options::OPT_objcmt_migrate_property)) {
// None specified, means enable them all.
CmdArgs.push_back("-objcmt-migrate-literals");
CmdArgs.push_back("-objcmt-migrate-subscripting");
CmdArgs.push_back("-objcmt-migrate-property");
} else {
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
}
} else {
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_all);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readonly_property);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_readwrite_property);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_property_dot_syntax);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_annotation);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_instancetype);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_nsmacros);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_protocol_conformance);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_atomic_property);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_returns_innerpointer_property);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_ns_nonatomic_iosonly);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_designated_init);
Args.AddLastArg(CmdArgs, options::OPT_objcmt_whitelist_dir_path);
}
}
static void RenderBuiltinOptions(const ToolChain &TC, const llvm::Triple &T,
const ArgList &Args, ArgStringList &CmdArgs) {
// -fbuiltin is default unless -mkernel is used.
bool UseBuiltins =
Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin,
!Args.hasArg(options::OPT_mkernel));
if (!UseBuiltins)
CmdArgs.push_back("-fno-builtin");
// -ffreestanding implies -fno-builtin.
if (Args.hasArg(options::OPT_ffreestanding))
UseBuiltins = false;
// Process the -fno-builtin-* options.
for (const auto &Arg : Args) {
const Option &O = Arg->getOption();
if (!O.matches(options::OPT_fno_builtin_))
continue;
Arg->claim();
// If -fno-builtin is specified, then there's no need to pass the option to
// the frontend.
if (!UseBuiltins)
continue;
StringRef FuncName = Arg->getValue();
CmdArgs.push_back(Args.MakeArgString("-fno-builtin-" + FuncName));
}
// le32-specific flags:
// -fno-math-builtin: clang should not convert math builtins to intrinsics
// by default.
if (TC.getArch() == llvm::Triple::le32)
CmdArgs.push_back("-fno-math-builtin");
}
void Driver::getDefaultModuleCachePath(SmallVectorImpl<char> &Result) {
llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, Result);
llvm::sys::path::append(Result, "org.llvm.clang.");
appendUserToPath(Result);
llvm::sys::path::append(Result, "ModuleCache");
}
static void RenderModulesOptions(Compilation &C, const Driver &D,
const ArgList &Args, const InputInfo &Input,
const InputInfo &Output,
ArgStringList &CmdArgs, bool &HaveModules) {
// -fmodules enables the use of precompiled modules (off by default).
// Users can pass -fno-cxx-modules to turn off modules support for
// C++/Objective-C++ programs.
bool HaveClangModules = false;
if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) {
bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules,
options::OPT_fno_cxx_modules, true);
if (AllowedInCXX || !types::isCXX(Input.getType())) {
CmdArgs.push_back("-fmodules");
HaveClangModules = true;
}
}
HaveModules = HaveClangModules;
if (Args.hasArg(options::OPT_fmodules_ts)) {
CmdArgs.push_back("-fmodules-ts");
HaveModules = true;
}
// -fmodule-maps enables implicit reading of module map files. By default,
// this is enabled if we are using Clang's flavor of precompiled modules.
if (Args.hasFlag(options::OPT_fimplicit_module_maps,
options::OPT_fno_implicit_module_maps, HaveClangModules))
CmdArgs.push_back("-fimplicit-module-maps");
// -fmodules-decluse checks that modules used are declared so (off by default)
if (Args.hasFlag(options::OPT_fmodules_decluse,
options::OPT_fno_modules_decluse, false))
CmdArgs.push_back("-fmodules-decluse");
// -fmodules-strict-decluse is like -fmodule-decluse, but also checks that
// all #included headers are part of modules.
if (Args.hasFlag(options::OPT_fmodules_strict_decluse,
options::OPT_fno_modules_strict_decluse, false))
CmdArgs.push_back("-fmodules-strict-decluse");
// -fno-implicit-modules turns off implicitly compiling modules on demand.
bool ImplicitModules = false;
if (!Args.hasFlag(options::OPT_fimplicit_modules,
options::OPT_fno_implicit_modules, HaveClangModules)) {
if (HaveModules)
CmdArgs.push_back("-fno-implicit-modules");
} else if (HaveModules) {
ImplicitModules = true;
// -fmodule-cache-path specifies where our implicitly-built module files
// should be written.
SmallString<128> Path;
if (Arg *A = Args.getLastArg(options::OPT_fmodules_cache_path))
Path = A->getValue();
if (C.isForDiagnostics()) {
// When generating crash reports, we want to emit the modules along with
// the reproduction sources, so we ignore any provided module path.
Path = Output.getFilename();
llvm::sys::path::replace_extension(Path, ".cache");
llvm::sys::path::append(Path, "modules");
} else if (Path.empty()) {
// No module path was provided: use the default.
Driver::getDefaultModuleCachePath(Path);
}
const char Arg[] = "-fmodules-cache-path=";
Path.insert(Path.begin(), Arg, Arg + strlen(Arg));
CmdArgs.push_back(Args.MakeArgString(Path));
}
if (HaveModules) {
// -fprebuilt-module-path specifies where to load the prebuilt module files.
for (const Arg *A : Args.filtered(options::OPT_fprebuilt_module_path)) {
CmdArgs.push_back(Args.MakeArgString(
std::string("-fprebuilt-module-path=") + A->getValue()));
A->claim();
}
}
// -fmodule-name specifies the module that is currently being built (or
// used for header checking by -fmodule-maps).
Args.AddLastArg(CmdArgs, options::OPT_fmodule_name_EQ);
// -fmodule-map-file can be used to specify files containing module
// definitions.
Args.AddAllArgs(CmdArgs, options::OPT_fmodule_map_file);
// -fbuiltin-module-map can be used to load the clang
// builtin headers modulemap file.
if (Args.hasArg(options::OPT_fbuiltin_module_map)) {
SmallString<128> BuiltinModuleMap(D.ResourceDir);
llvm::sys::path::append(BuiltinModuleMap, "include");
llvm::sys::path::append(BuiltinModuleMap, "module.modulemap");
if (llvm::sys::fs::exists(BuiltinModuleMap))
CmdArgs.push_back(
Args.MakeArgString("-fmodule-map-file=" + BuiltinModuleMap));
}
// The -fmodule-file=<name>=<file> form specifies the mapping of module
// names to precompiled module files (the module is loaded only if used).
// The -fmodule-file=<file> form can be used to unconditionally load
// precompiled module files (whether used or not).
if (HaveModules)
Args.AddAllArgs(CmdArgs, options::OPT_fmodule_file);
else
Args.ClaimAllArgs(options::OPT_fmodule_file);
// When building modules and generating crashdumps, we need to dump a module
// dependency VFS alongside the output.
if (HaveClangModules && C.isForDiagnostics()) {
SmallString<128> VFSDir(Output.getFilename());
llvm::sys::path::replace_extension(VFSDir, ".cache");
// Add the cache directory as a temp so the crash diagnostics pick it up.
C.addTempFile(Args.MakeArgString(VFSDir));
llvm::sys::path::append(VFSDir, "vfs");
CmdArgs.push_back("-module-dependency-dir");
CmdArgs.push_back(Args.MakeArgString(VFSDir));
}
if (HaveClangModules)
Args.AddLastArg(CmdArgs, options::OPT_fmodules_user_build_path);
// Pass through all -fmodules-ignore-macro arguments.
Args.AddAllArgs(CmdArgs, options::OPT_fmodules_ignore_macro);
Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_interval);
Args.AddLastArg(CmdArgs, options::OPT_fmodules_prune_after);
Args.AddLastArg(CmdArgs, options::OPT_fbuild_session_timestamp);
if (Arg *A = Args.getLastArg(options::OPT_fbuild_session_file)) {
if (Args.hasArg(options::OPT_fbuild_session_timestamp))
D.Diag(diag::err_drv_argument_not_allowed_with)
<< A->getAsString(Args) << "-fbuild-session-timestamp";
llvm::sys::fs::file_status Status;
if (llvm::sys::fs::status(A->getValue(), Status))
D.Diag(diag::err_drv_no_such_file) << A->getValue();
CmdArgs.push_back(
Args.MakeArgString("-fbuild-session-timestamp=" +
Twine((uint64_t)Status.getLastModificationTime()
.time_since_epoch()
.count())));
}
if (Args.getLastArg(options::OPT_fmodules_validate_once_per_build_session)) {
if (!Args.getLastArg(options::OPT_fbuild_session_timestamp,
options::OPT_fbuild_session_file))
D.Diag(diag::err_drv_modules_validate_once_requires_timestamp);
Args.AddLastArg(CmdArgs,
options::OPT_fmodules_validate_once_per_build_session);
}
if (Args.hasFlag(options::OPT_fmodules_validate_system_headers,
options::OPT_fno_modules_validate_system_headers,
ImplicitModules))
CmdArgs.push_back("-fmodules-validate-system-headers");
Args.AddLastArg(CmdArgs, options::OPT_fmodules_disable_diagnostic_validation);
}
static void RenderCharacterOptions(const ArgList &Args, const llvm::Triple &T,
ArgStringList &CmdArgs) {
// -fsigned-char is default.
if (const Arg *A = Args.getLastArg(options::OPT_fsigned_char,
options::OPT_fno_signed_char,
options::OPT_funsigned_char,
options::OPT_fno_unsigned_char)) {
if (A->getOption().matches(options::OPT_funsigned_char) ||
A->getOption().matches(options::OPT_fno_signed_char)) {
CmdArgs.push_back("-fno-signed-char");
}
} else if (!isSignedCharDefault(T)) {
CmdArgs.push_back("-fno-signed-char");
}
// The default depends on the language standard.
if (const Arg *A =
Args.getLastArg(options::OPT_fchar8__t, options::OPT_fno_char8__t))
A->render(Args, CmdArgs);
if (const Arg *A = Args.getLastArg(options::OPT_fshort_wchar,
options::OPT_fno_short_wchar)) {
if (A->getOption().matches(options::OPT_fshort_wchar)) {
CmdArgs.push_back("-fwchar-type=short");
CmdArgs.push_back("-fno-signed-wchar");
} else {
bool IsARM = T.isARM() || T.isThumb() || T.isAArch64();
CmdArgs.push_back("-fwchar-type=int");
if (IsARM && !(T.isOSWindows() || T.isOSNetBSD() ||
T.isOSOpenBSD()))
CmdArgs.push_back("-fno-signed-wchar");
else
CmdArgs.push_back("-fsigned-wchar");
}
}
}
static void RenderObjCOptions(const ToolChain &TC, const Driver &D,
const llvm::Triple &T, const ArgList &Args,
ObjCRuntime &Runtime, bool InferCovariantReturns,
const InputInfo &Input, ArgStringList &CmdArgs) {
const llvm::Triple::ArchType Arch = TC.getArch();
// -fobjc-dispatch-method is only relevant with the nonfragile-abi, and legacy
// is the default. Except for deployment target of 10.5, next runtime is
// always legacy dispatch and -fno-objc-legacy-dispatch gets ignored silently.
if (Runtime.isNonFragile()) {
if (!Args.hasFlag(options::OPT_fobjc_legacy_dispatch,
options::OPT_fno_objc_legacy_dispatch,
Runtime.isLegacyDispatchDefaultForArch(Arch))) {
if (TC.UseObjCMixedDispatch())
CmdArgs.push_back("-fobjc-dispatch-method=mixed");
else
CmdArgs.push_back("-fobjc-dispatch-method=non-legacy");
}
}
// When ObjectiveC legacy runtime is in effect on MacOSX, turn on the option
// to do Array/Dictionary subscripting by default.
if (Arch == llvm::Triple::x86 && T.isMacOSX() &&
Runtime.getKind() == ObjCRuntime::FragileMacOSX && Runtime.isNeXTFamily())
CmdArgs.push_back("-fobjc-subscripting-legacy-runtime");
// Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc.
// NOTE: This logic is duplicated in ToolChains.cpp.
if (isObjCAutoRefCount(Args)) {
TC.CheckObjCARC();
CmdArgs.push_back("-fobjc-arc");
// FIXME: It seems like this entire block, and several around it should be
// wrapped in isObjC, but for now we just use it here as this is where it
// was being used previously.
if (types::isCXX(Input.getType()) && types::isObjC(Input.getType())) {
if (TC.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
CmdArgs.push_back("-fobjc-arc-cxxlib=libc++");
else
CmdArgs.push_back("-fobjc-arc-cxxlib=libstdc++");
}
// Allow the user to enable full exceptions code emission.
// We default off for Objective-C, on for Objective-C++.
if (Args.hasFlag(options::OPT_fobjc_arc_exceptions,
options::OPT_fno_objc_arc_exceptions,
/*default=*/types::isCXX(Input.getType())))
CmdArgs.push_back("-fobjc-arc-exceptions");
}
// Silence warning for full exception code emission options when explicitly
// set to use no ARC.
if (Args.hasArg(options::OPT_fno_objc_arc)) {
Args.ClaimAllArgs(options::OPT_fobjc_arc_exceptions);
Args.ClaimAllArgs(options::OPT_fno_objc_arc_exceptions);
}
// Allow the user to control whether messages can be converted to runtime
// functions.
if (types::isObjC(Input.getType())) {
auto *Arg = Args.getLastArg(
options::OPT_fobjc_convert_messages_to_runtime_calls,
options::OPT_fno_objc_convert_messages_to_runtime_calls);
if (Arg &&
Arg->getOption().matches(
options::OPT_fno_objc_convert_messages_to_runtime_calls))
CmdArgs.push_back("-fno-objc-convert-messages-to-runtime-calls");
}
// -fobjc-infer-related-result-type is the default, except in the Objective-C
// rewriter.
if (InferCovariantReturns)
CmdArgs.push_back("-fno-objc-infer-related-result-type");
// Pass down -fobjc-weak or -fno-objc-weak if present.
if (types::isObjC(Input.getType())) {
auto WeakArg =
Args.getLastArg(options::OPT_fobjc_weak, options::OPT_fno_objc_weak);
if (!WeakArg) {
// nothing to do
} else if (!Runtime.allowsWeak()) {
if (WeakArg->getOption().matches(options::OPT_fobjc_weak))
D.Diag(diag::err_objc_weak_unsupported);
} else {
WeakArg->render(Args, CmdArgs);
}
}
}
static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
ArgStringList &CmdArgs) {
bool CaretDefault = true;
bool ColumnDefault = true;
if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diagnostics_classic,
options::OPT__SLASH_diagnostics_column,
options::OPT__SLASH_diagnostics_caret)) {
switch (A->getOption().getID()) {
case options::OPT__SLASH_diagnostics_caret:
CaretDefault = true;
ColumnDefault = true;
break;
case options::OPT__SLASH_diagnostics_column:
CaretDefault = false;
ColumnDefault = true;
break;
case options::OPT__SLASH_diagnostics_classic:
CaretDefault = false;
ColumnDefault = false;
break;
}
}
// -fcaret-diagnostics is default.
if (!Args.hasFlag(options::OPT_fcaret_diagnostics,
options::OPT_fno_caret_diagnostics, CaretDefault))
CmdArgs.push_back("-fno-caret-diagnostics");
// -fdiagnostics-fixit-info is default, only pass non-default.
if (!Args.hasFlag(options::OPT_fdiagnostics_fixit_info,
options::OPT_fno_diagnostics_fixit_info))
CmdArgs.push_back("-fno-diagnostics-fixit-info");
// Enable -fdiagnostics-show-option by default.
if (Args.hasFlag(options::OPT_fdiagnostics_show_option,
options::OPT_fno_diagnostics_show_option))
CmdArgs.push_back("-fdiagnostics-show-option");
if (const Arg *A =
Args.getLastArg(options::OPT_fdiagnostics_show_category_EQ)) {
CmdArgs.push_back("-fdiagnostics-show-category");
CmdArgs.push_back(A->getValue());
}
if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness,
options::OPT_fno_diagnostics_show_hotness, false))
CmdArgs.push_back("-fdiagnostics-show-hotness");
if (const Arg *A =
Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
std::string Opt =
std::string("-fdiagnostics-hotness-threshold=") + A->getValue();
CmdArgs.push_back(Args.MakeArgString(Opt));
}
if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
CmdArgs.push_back("-fdiagnostics-format");
CmdArgs.push_back(A->getValue());
}
if (const Arg *A = Args.getLastArg(
options::OPT_fdiagnostics_show_note_include_stack,
options::OPT_fno_diagnostics_show_note_include_stack)) {
const Option &O = A->getOption();
if (O.matches(options::OPT_fdiagnostics_show_note_include_stack))
CmdArgs.push_back("-fdiagnostics-show-note-include-stack");
else
CmdArgs.push_back("-fno-diagnostics-show-note-include-stack");
}
// Color diagnostics are parsed by the driver directly from argv and later
// re-parsed to construct this job; claim any possible color diagnostic here
// to avoid warn_drv_unused_argument and diagnose bad
// OPT_fdiagnostics_color_EQ values.
for (const Arg *A : Args) {
const Option &O = A->getOption();
if (!O.matches(options::OPT_fcolor_diagnostics) &&
!O.matches(options::OPT_fdiagnostics_color) &&
!O.matches(options::OPT_fno_color_diagnostics) &&
!O.matches(options::OPT_fno_diagnostics_color) &&
!O.matches(options::OPT_fdiagnostics_color_EQ))
continue;
if (O.matches(options::OPT_fdiagnostics_color_EQ)) {
StringRef Value(A->getValue());
if (Value != "always" && Value != "never" && Value != "auto")
D.Diag(diag::err_drv_clang_unsupported)
<< ("-fdiagnostics-color=" + Value).str();
}
A->claim();
}
if (D.getDiags().getDiagnosticOptions().ShowColors)
CmdArgs.push_back("-fcolor-diagnostics");
if (Args.hasArg(options::OPT_fansi_escape_codes))
CmdArgs.push_back("-fansi-escape-codes");
if (!Args.hasFlag(options::OPT_fshow_source_location,
options::OPT_fno_show_source_location))
CmdArgs.push_back("-fno-show-source-location");
if (Args.hasArg(options::OPT_fdiagnostics_absolute_paths))
CmdArgs.push_back("-fdiagnostics-absolute-paths");
if (!Args.hasFlag(options::OPT_fshow_column, options::OPT_fno_show_column,
ColumnDefault))
CmdArgs.push_back("-fno-show-column");
if (!Args.hasFlag(options::OPT_fspell_checking,
options::OPT_fno_spell_checking))
CmdArgs.push_back("-fno-spell-checking");
}
enum class DwarfFissionKind { None, Split, Single };
static DwarfFissionKind getDebugFissionKind(const Driver &D,
const ArgList &Args, Arg *&Arg) {
Arg =
Args.getLastArg(options::OPT_gsplit_dwarf, options::OPT_gsplit_dwarf_EQ);
if (!Arg)
return DwarfFissionKind::None;
if (Arg->getOption().matches(options::OPT_gsplit_dwarf))
return DwarfFissionKind::Split;
StringRef Value = Arg->getValue();
if (Value == "split")
return DwarfFissionKind::Split;
if (Value == "single")
return DwarfFissionKind::Single;
D.Diag(diag::err_drv_unsupported_option_argument)
<< Arg->getOption().getName() << Arg->getValue();
return DwarfFissionKind::None;
}
static void RenderDebugOptions(const ToolChain &TC, const Driver &D,
const llvm::Triple &T, const ArgList &Args,
bool EmitCodeView, bool IsWindowsMSVC,
ArgStringList &CmdArgs,
codegenoptions::DebugInfoKind &DebugInfoKind,
DwarfFissionKind &DwarfFission) {
if (Args.hasFlag(options::OPT_fdebug_info_for_profiling,
options::OPT_fno_debug_info_for_profiling, false) &&
checkDebugInfoOption(
Args.getLastArg(options::OPT_fdebug_info_for_profiling), Args, D, TC))
CmdArgs.push_back("-fdebug-info-for-profiling");
// The 'g' groups options involve a somewhat intricate sequence of decisions
// about what to pass from the driver to the frontend, but by the time they
// reach cc1 they've been factored into three well-defined orthogonal choices:
// * what level of debug info to generate
// * what dwarf version to write
// * what debugger tuning to use
// This avoids having to monkey around further in cc1 other than to disable
// codeview if not running in a Windows environment. Perhaps even that
// decision should be made in the driver as well though.
unsigned DWARFVersion = 0;
llvm::DebuggerKind DebuggerTuning = TC.getDefaultDebuggerTuning();
bool SplitDWARFInlining =
Args.hasFlag(options::OPT_fsplit_dwarf_inlining,
options::OPT_fno_split_dwarf_inlining, true);
Args.ClaimAllArgs(options::OPT_g_Group);
Arg* SplitDWARFArg;
DwarfFission = getDebugFissionKind(D, Args, SplitDWARFArg);
if (DwarfFission != DwarfFissionKind::None &&
!checkDebugInfoOption(SplitDWARFArg, Args, D, TC)) {
DwarfFission = DwarfFissionKind::None;
SplitDWARFInlining = false;
}
if (const Arg *A = Args.getLastArg(options::OPT_g_Group)) {
if (checkDebugInfoOption(A, Args, D, TC)) {
// If the last option explicitly specified a debug-info level, use it.
if (A->getOption().matches(options::OPT_gN_Group)) {
DebugInfoKind = DebugLevelToInfoKind(*A);
// If you say "-gsplit-dwarf -gline-tables-only", -gsplit-dwarf loses.
// But -gsplit-dwarf is not a g_group option, hence we have to check the
// order explicitly. If -gsplit-dwarf wins, we fix DebugInfoKind later.
// This gets a bit more complicated if you've disabled inline info in
// the skeleton CUs (SplitDWARFInlining) - then there's value in
// composing split-dwarf and line-tables-only, so let those compose
// naturally in that case. And if you just turned off debug info,
// (-gsplit-dwarf -g0) - do that.
if (DwarfFission != DwarfFissionKind::None) {
if (A->getIndex() > SplitDWARFArg->getIndex()) {
if (DebugInfoKind == codegenoptions::NoDebugInfo ||
DebugInfoKind == codegenoptions::DebugDirectivesOnly ||
(DebugInfoKind == codegenoptions::DebugLineTablesOnly &&
SplitDWARFInlining))
DwarfFission = DwarfFissionKind::None;
} else if (SplitDWARFInlining)
DebugInfoKind = codegenoptions::NoDebugInfo;
}
} else {
// For any other 'g' option, use Limited.
DebugInfoKind = codegenoptions::LimitedDebugInfo;
}
} else {
DebugInfoKind = codegenoptions::LimitedDebugInfo;
}
}
// If a debugger tuning argument appeared, remember it.
if (const Arg *A =
Args.getLastArg(options::OPT_gTune_Group, options::OPT_ggdbN_Group)) {
if (checkDebugInfoOption(A, Args, D, TC)) {
if (A->getOption().matches(options::OPT_glldb))
DebuggerTuning = llvm::DebuggerKind::LLDB;
else if (A->getOption().matches(options::OPT_gsce))
DebuggerTuning = llvm::DebuggerKind::SCE;
else
DebuggerTuning = llvm::DebuggerKind::GDB;
}
}
// If a -gdwarf argument appeared, remember it.
if (const Arg *A =
Args.getLastArg(options::OPT_gdwarf_2, options::OPT_gdwarf_3,
options::OPT_gdwarf_4, options::OPT_gdwarf_5))
if (checkDebugInfoOption(A, Args, D, TC))
DWARFVersion = DwarfVersionNum(A->getSpelling());
if (const Arg *A = Args.getLastArg(options::OPT_gcodeview)) {
if (checkDebugInfoOption(A, Args, D, TC))
EmitCodeView = true;
}
// If the user asked for debug info but did not explicitly specify -gcodeview
// or -gdwarf, ask the toolchain for the default format.
if (!EmitCodeView && DWARFVersion == 0 &&
DebugInfoKind != codegenoptions::NoDebugInfo) {
switch (TC.getDefaultDebugFormat()) {
case codegenoptions::DIF_CodeView:
EmitCodeView = true;
break;
case codegenoptions::DIF_DWARF:
DWARFVersion = TC.GetDefaultDwarfVersion();
break;
}
}
// -gline-directives-only supported only for the DWARF debug info.
if (DWARFVersion == 0 && DebugInfoKind == codegenoptions::DebugDirectivesOnly)
DebugInfoKind = codegenoptions::NoDebugInfo;
// We ignore flag -gstrict-dwarf for now.
// And we handle flag -grecord-gcc-switches later with DWARFDebugFlags.
Args.ClaimAllArgs(options::OPT_g_flags_Group);
// Column info is included by default for everything except SCE and
// CodeView. Clang doesn't track end columns, just starting columns, which,
// in theory, is fine for CodeView (and PDB). In practice, however, the
// Microsoft debuggers don't handle missing end columns well, so it's better
// not to include any column info.
if (const Arg *A = Args.getLastArg(options::OPT_gcolumn_info))
(void)checkDebugInfoOption(A, Args, D, TC);
if (Args.hasFlag(options::OPT_gcolumn_info, options::OPT_gno_column_info,
/*Default=*/!EmitCodeView &&
DebuggerTuning != llvm::DebuggerKind::SCE))
CmdArgs.push_back("-dwarf-column-info");
// FIXME: Move backend command line options to the module.
// If -gline-tables-only or -gline-directives-only is the last option it wins.
if (const Arg *A = Args.getLastArg(options::OPT_gmodules))
if (checkDebugInfoOption(A, Args, D, TC)) {
if (DebugInfoKind != codegenoptions::DebugLineTablesOnly &&
DebugInfoKind != codegenoptions::DebugDirectivesOnly) {
DebugInfoKind = codegenoptions::LimitedDebugInfo;
CmdArgs.push_back("-dwarf-ext-refs");
CmdArgs.push_back("-fmodule-format=obj");
}
}
// -gsplit-dwarf should turn on -g and enable the backend dwarf
// splitting and extraction.
// FIXME: Currently only works on Linux and Fuchsia.
if (T.isOSLinux() || T.isOSFuchsia()) {
if (!SplitDWARFInlining)
CmdArgs.push_back("-fno-split-dwarf-inlining");
if (DwarfFission != DwarfFissionKind::None) {
if (DebugInfoKind == codegenoptions::NoDebugInfo)
DebugInfoKind = codegenoptions::LimitedDebugInfo;
if (DwarfFission == DwarfFissionKind::Single)
CmdArgs.push_back("-enable-split-dwarf=single");
else
CmdArgs.push_back("-enable-split-dwarf");
}
}
// After we've dealt with all combinations of things that could
// make DebugInfoKind be other than None or DebugLineTablesOnly,
// figure out if we need to "upgrade" it to standalone debug info.
// We parse these two '-f' options whether or not they will be used,
// to claim them even if you wrote "-fstandalone-debug -gline-tables-only"
bool NeedFullDebug = Args.hasFlag(options::OPT_fstandalone_debug,
options::OPT_fno_standalone_debug,
TC.GetDefaultStandaloneDebug());
if (const Arg *A = Args.getLastArg(options::OPT_fstandalone_debug))
(void)checkDebugInfoOption(A, Args, D, TC);
if (DebugInfoKind == codegenoptions::LimitedDebugInfo && NeedFullDebug)
DebugInfoKind = codegenoptions::FullDebugInfo;
if (Args.hasFlag(options::OPT_gembed_source, options::OPT_gno_embed_source,
false)) {
// Source embedding is a vendor extension to DWARF v5. By now we have
// checked if a DWARF version was stated explicitly, and have otherwise
// fallen back to the target default, so if this is still not at least 5
// we emit an error.
const Arg *A = Args.getLastArg(options::OPT_gembed_source);
if (DWARFVersion < 5)
D.Diag(diag::err_drv_argument_only_allowed_with)
<< A->getAsString(Args) << "-gdwarf-5";
else if (checkDebugInfoOption(A, Args, D, TC))
CmdArgs.push_back("-gembed-source");
}
if (EmitCodeView) {
CmdArgs.push_back("-gcodeview");
// Emit codeview type hashes if requested.
if (Args.hasFlag(options::OPT_gcodeview_ghash,
options::OPT_gno_codeview_ghash, false)) {
CmdArgs.push_back("-gcodeview-ghash");
}
}
// Adjust the debug info kind for the given toolchain.
TC.adjustDebugInfoKind(DebugInfoKind, Args);
RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DWARFVersion,
DebuggerTuning);
// -fdebug-macro turns on macro debug info generation.
if (Args.hasFlag(options::OPT_fdebug_macro, options::OPT_fno_debug_macro,
false))
if (checkDebugInfoOption(Args.getLastArg(options::OPT_fdebug_macro), Args,
D, TC))
CmdArgs.push_back("-debug-info-macro");
// -ggnu-pubnames turns on gnu style pubnames in the backend.
const auto *PubnamesArg =
Args.getLastArg(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames,
options::OPT_gpubnames, options::OPT_gno_pubnames);
if (DwarfFission != DwarfFissionKind::None ||
DebuggerTuning == llvm::DebuggerKind::LLDB ||
(PubnamesArg && checkDebugInfoOption(PubnamesArg, Args, D, TC)))
if (!PubnamesArg ||
(!PubnamesArg->getOption().matches(options::OPT_gno_gnu_pubnames) &&
!PubnamesArg->getOption().matches(options::OPT_gno_pubnames)))
CmdArgs.push_back(PubnamesArg && PubnamesArg->getOption().matches(
options::OPT_gpubnames)
? "-gpubnames"
: "-ggnu-pubnames");
if (Args.hasFlag(options::OPT_fdebug_ranges_base_address,
options::OPT_fno_debug_ranges_base_address, false)) {
CmdArgs.push_back("-fdebug-ranges-base-address");
}
// -gdwarf-aranges turns on the emission of the aranges section in the
// backend.
// Always enabled for SCE tuning.
bool NeedAranges = DebuggerTuning == llvm::DebuggerKind::SCE;
if (const Arg *A = Args.getLastArg(options::OPT_gdwarf_aranges))
NeedAranges = checkDebugInfoOption(A, Args, D, TC) || NeedAranges;
if (NeedAranges) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-generate-arange-section");
}
if (Args.hasFlag(options::OPT_fdebug_types_section,
options::OPT_fno_debug_types_section, false)) {
if (!T.isOSBinFormatELF()) {
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< Args.getLastArg(options::OPT_fdebug_types_section)
->getAsString(Args)
<< T.getTriple();
} else if (checkDebugInfoOption(
Args.getLastArg(options::OPT_fdebug_types_section), Args, D,
TC)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-generate-type-units");
}
}
// Decide how to render forward declarations of template instantiations.
// SCE wants full descriptions, others just get them in the name.
if (DebuggerTuning == llvm::DebuggerKind::SCE)
CmdArgs.push_back("-debug-forward-template-params");
// Do we need to explicitly import anonymous namespaces into the parent
// scope?
if (DebuggerTuning == llvm::DebuggerKind::SCE)
CmdArgs.push_back("-dwarf-explicit-import");
RenderDebugInfoCompressionArgs(Args, CmdArgs, D, TC);
}
void Clang::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args, const char *LinkingOutput) const {
const auto &TC = getToolChain();
const llvm::Triple &RawTriple = TC.getTriple();
const llvm::Triple &Triple = TC.getEffectiveTriple();
const std::string &TripleStr = Triple.getTriple();
bool KernelOrKext =
Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
const Driver &D = TC.getDriver();
ArgStringList CmdArgs;
// Check number of inputs for sanity. We need at least one input.
assert(Inputs.size() >= 1 && "Must have at least one input.");
// CUDA/HIP compilation may have multiple inputs (source file + results of
// device-side compilations). OpenMP device jobs also take the host IR as a
// second input. Module precompilation accepts a list of header files to
// include as part of the module. All other jobs are expected to have exactly
// one input.
bool IsCuda = JA.isOffloading(Action::OFK_Cuda);
bool IsHIP = JA.isOffloading(Action::OFK_HIP);
bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP);
bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA);
// A header module compilation doesn't have a main input file, so invent a
// fake one as a placeholder.
const char *ModuleName = [&]{
auto *ModuleNameArg = Args.getLastArg(options::OPT_fmodule_name_EQ);
return ModuleNameArg ? ModuleNameArg->getValue() : "";
}();
InputInfo HeaderModuleInput(Inputs[0].getType(), ModuleName, ModuleName);
const InputInfo &Input =
IsHeaderModulePrecompile ? HeaderModuleInput : Inputs[0];
InputInfoList ModuleHeaderInputs;
const InputInfo *CudaDeviceInput = nullptr;
const InputInfo *OpenMPDeviceInput = nullptr;
for (const InputInfo &I : Inputs) {
if (&I == &Input) {
// This is the primary input.
} else if (IsHeaderModulePrecompile &&
types::getPrecompiledType(I.getType()) == types::TY_PCH) {
types::ID Expected = HeaderModuleInput.getType();
if (I.getType() != Expected) {
D.Diag(diag::err_drv_module_header_wrong_kind)
<< I.getFilename() << types::getTypeName(I.getType())
<< types::getTypeName(Expected);
}
ModuleHeaderInputs.push_back(I);
} else if ((IsCuda || IsHIP) && !CudaDeviceInput) {
CudaDeviceInput = &I;
} else if (IsOpenMPDevice && !OpenMPDeviceInput) {
OpenMPDeviceInput = &I;
} else {
llvm_unreachable("unexpectedly given multiple inputs");
}
}
const llvm::Triple *AuxTriple = IsCuda ? TC.getAuxTriple() : nullptr;
bool IsWindowsGNU = RawTriple.isWindowsGNUEnvironment();
bool IsWindowsCygnus = RawTriple.isWindowsCygwinEnvironment();
bool IsWindowsMSVC = RawTriple.isWindowsMSVCEnvironment();
bool IsIAMCU = RawTriple.isOSIAMCU();
// Adjust IsWindowsXYZ for CUDA/HIP compilations. Even when compiling in
// device mode (i.e., getToolchain().getTriple() is NVPTX/AMDGCN, not
// Windows), we need to pass Windows-specific flags to cc1.
if (IsCuda || IsHIP) {
IsWindowsMSVC |= AuxTriple && AuxTriple->isWindowsMSVCEnvironment();
IsWindowsGNU |= AuxTriple && AuxTriple->isWindowsGNUEnvironment();
IsWindowsCygnus |= AuxTriple && AuxTriple->isWindowsCygwinEnvironment();
}
// C++ is not supported for IAMCU.
if (IsIAMCU && types::isCXX(Input.getType()))
D.Diag(diag::err_drv_clang_unsupported) << "C++ for IAMCU";
// Invoke ourselves in -cc1 mode.
//
// FIXME: Implement custom jobs for internal actions.
CmdArgs.push_back("-cc1");
// Add the "effective" target triple.
CmdArgs.push_back("-triple");
CmdArgs.push_back(Args.MakeArgString(TripleStr));
if (const Arg *MJ = Args.getLastArg(options::OPT_MJ)) {
DumpCompilationDatabase(C, MJ->getValue(), TripleStr, Output, Input, Args);
Args.ClaimAllArgs(options::OPT_MJ);
}
if (IsCuda || IsHIP) {
// We have to pass the triple of the host if compiling for a CUDA/HIP device
// and vice-versa.
std::string NormalizedTriple;
if (JA.isDeviceOffloading(Action::OFK_Cuda) ||
JA.isDeviceOffloading(Action::OFK_HIP))
NormalizedTriple = C.getSingleOffloadToolChain<Action::OFK_Host>()
->getTriple()
.normalize();
else
NormalizedTriple =
(IsCuda ? C.getSingleOffloadToolChain<Action::OFK_Cuda>()
: C.getSingleOffloadToolChain<Action::OFK_HIP>())
->getTriple()
.normalize();
CmdArgs.push_back("-aux-triple");
CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
}
if (IsOpenMPDevice) {
// We have to pass the triple of the host if compiling for an OpenMP device.
std::string NormalizedTriple =
C.getSingleOffloadToolChain<Action::OFK_Host>()
->getTriple()
.normalize();
CmdArgs.push_back("-aux-triple");
CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
}
if (Triple.isOSWindows() && (Triple.getArch() == llvm::Triple::arm ||
Triple.getArch() == llvm::Triple::thumb)) {
unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
unsigned Version;
Triple.getArchName().substr(Offset).getAsInteger(10, Version);
if (Version < 7)
D.Diag(diag::err_target_unsupported_arch) << Triple.getArchName()
<< TripleStr;
}
// Push all default warning arguments that are specific to
// the given target. These come before user provided warning options
// are provided.
TC.addClangWarningOptions(CmdArgs);
// Select the appropriate action.
RewriteKind rewriteKind = RK_None;
if (isa<AnalyzeJobAction>(JA)) {
assert(JA.getType() == types::TY_Plist && "Invalid output type.");
CmdArgs.push_back("-analyze");
} else if (isa<MigrateJobAction>(JA)) {
CmdArgs.push_back("-migrate");
} else if (isa<PreprocessJobAction>(JA)) {
if (Output.getType() == types::TY_Dependencies)
CmdArgs.push_back("-Eonly");
else {
CmdArgs.push_back("-E");
if (Args.hasArg(options::OPT_rewrite_objc) &&
!Args.hasArg(options::OPT_g_Group))
CmdArgs.push_back("-P");
}
} else if (isa<AssembleJobAction>(JA)) {
CmdArgs.push_back("-emit-obj");
CollectArgsForIntegratedAssembler(C, Args, CmdArgs, D);
// Also ignore explicit -force_cpusubtype_ALL option.
(void)Args.hasArg(options::OPT_force__cpusubtype__ALL);
} else if (isa<PrecompileJobAction>(JA)) {
if (JA.getType() == types::TY_Nothing)
CmdArgs.push_back("-fsyntax-only");
else if (JA.getType() == types::TY_ModuleFile)
CmdArgs.push_back(IsHeaderModulePrecompile
? "-emit-header-module"
: "-emit-module-interface");
else
CmdArgs.push_back("-emit-pch");
} else if (isa<VerifyPCHJobAction>(JA)) {
CmdArgs.push_back("-verify-pch");
} else {
assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) &&
"Invalid action for clang tool.");
if (JA.getType() == types::TY_Nothing) {
CmdArgs.push_back("-fsyntax-only");
} else if (JA.getType() == types::TY_LLVM_IR ||
JA.getType() == types::TY_LTO_IR) {
CmdArgs.push_back("-emit-llvm");
} else if (JA.getType() == types::TY_LLVM_BC ||
JA.getType() == types::TY_LTO_BC) {
CmdArgs.push_back("-emit-llvm-bc");
} else if (JA.getType() == types::TY_PP_Asm) {
CmdArgs.push_back("-S");
} else if (JA.getType() == types::TY_AST) {
CmdArgs.push_back("-emit-pch");
} else if (JA.getType() == types::TY_ModuleFile) {
CmdArgs.push_back("-module-file-info");
} else if (JA.getType() == types::TY_RewrittenObjC) {
CmdArgs.push_back("-rewrite-objc");
rewriteKind = RK_NonFragile;
} else if (JA.getType() == types::TY_RewrittenLegacyObjC) {
CmdArgs.push_back("-rewrite-objc");
rewriteKind = RK_Fragile;
} else {
assert(JA.getType() == types::TY_PP_Asm && "Unexpected output type!");
}
// Preserve use-list order by default when emitting bitcode, so that
// loading the bitcode up in 'opt' or 'llc' and running passes gives the
// same result as running passes here. For LTO, we don't need to preserve
// the use-list order, since serialization to bitcode is part of the flow.
if (JA.getType() == types::TY_LLVM_BC)
CmdArgs.push_back("-emit-llvm-uselists");
// Device-side jobs do not support LTO.
bool isDeviceOffloadAction = !(JA.isDeviceOffloading(Action::OFK_None) ||
JA.isDeviceOffloading(Action::OFK_Host));
if (D.isUsingLTO() && !isDeviceOffloadAction) {
Args.AddLastArg(CmdArgs, options::OPT_flto, options::OPT_flto_EQ);
// The Darwin and PS4 linkers currently use the legacy LTO API, which
// does not support LTO unit features (CFI, whole program vtable opt)
// under ThinLTO.
if (!(RawTriple.isOSDarwin() || RawTriple.isPS4()) ||
D.getLTOMode() == LTOK_Full)
CmdArgs.push_back("-flto-unit");
}
}
if (const Arg *A = Args.getLastArg(options::OPT_fthinlto_index_EQ)) {
if (!types::isLLVMIR(Input.getType()))
D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
<< "-x ir";
Args.AddLastArg(CmdArgs, options::OPT_fthinlto_index_EQ);
}
if (Args.getLastArg(options::OPT_save_temps_EQ))
Args.AddLastArg(CmdArgs, options::OPT_save_temps_EQ);
// Embed-bitcode option.
// Only white-listed flags below are allowed to be embedded.
if (C.getDriver().embedBitcodeInObject() && !C.getDriver().isUsingLTO() &&
(isa<BackendJobAction>(JA) || isa<AssembleJobAction>(JA))) {
// Add flags implied by -fembed-bitcode.
Args.AddLastArg(CmdArgs, options::OPT_fembed_bitcode_EQ);
// Disable all llvm IR level optimizations.
CmdArgs.push_back("-disable-llvm-passes");
// reject options that shouldn't be supported in bitcode
// also reject kernel/kext
static const constexpr unsigned kBitcodeOptionBlacklist[] = {
options::OPT_mkernel,
options::OPT_fapple_kext,
options::OPT_ffunction_sections,
options::OPT_fno_function_sections,
options::OPT_fdata_sections,
options::OPT_fno_data_sections,
options::OPT_funique_section_names,
options::OPT_fno_unique_section_names,
options::OPT_mrestrict_it,
options::OPT_mno_restrict_it,
options::OPT_mstackrealign,
options::OPT_mno_stackrealign,
options::OPT_mstack_alignment,
options::OPT_mcmodel_EQ,
options::OPT_mlong_calls,
options::OPT_mno_long_calls,
options::OPT_ggnu_pubnames,
options::OPT_gdwarf_aranges,
options::OPT_fdebug_types_section,
options::OPT_fno_debug_types_section,
options::OPT_fdwarf_directory_asm,
options::OPT_fno_dwarf_directory_asm,
options::OPT_mrelax_all,
options::OPT_mno_relax_all,
options::OPT_ftrap_function_EQ,
options::OPT_ffixed_r9,
options::OPT_mfix_cortex_a53_835769,
options::OPT_mno_fix_cortex_a53_835769,
options::OPT_ffixed_x18,
options::OPT_mglobal_merge,
options::OPT_mno_global_merge,
options::OPT_mred_zone,
options::OPT_mno_red_zone,
options::OPT_Wa_COMMA,
options::OPT_Xassembler,
options::OPT_mllvm,
};
for (const auto &A : Args)
if (std::find(std::begin(kBitcodeOptionBlacklist),
std::end(kBitcodeOptionBlacklist),
A->getOption().getID()) !=
std::end(kBitcodeOptionBlacklist))
D.Diag(diag::err_drv_unsupported_embed_bitcode) << A->getSpelling();
// Render the CodeGen options that need to be passed.
if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
options::OPT_fno_optimize_sibling_calls))
CmdArgs.push_back("-mdisable-tail-calls");
RenderFloatingPointOptions(TC, D, isOptimizationLevelFast(Args), Args,
CmdArgs);
// Render ABI arguments
switch (TC.getArch()) {
default: break;
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
RenderARMABI(Triple, Args, CmdArgs);
break;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
RenderAArch64ABI(Triple, Args, CmdArgs);
break;
}
// Optimization level for CodeGen.
if (const Arg *A = Args.getLastArg(options::OPT_O_Group)) {
if (A->getOption().matches(options::OPT_O4)) {
CmdArgs.push_back("-O3");
D.Diag(diag::warn_O4_is_O3);
} else {
A->render(Args, CmdArgs);
}
}
// Input/Output file.
if (Output.getType() == types::TY_Dependencies) {
// Handled with other dependency code.
} else if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
assert(Output.isNothing() && "Input output.");
}
for (const auto &II : Inputs) {
addDashXForInput(Args, II, CmdArgs);
if (II.isFilename())
CmdArgs.push_back(II.getFilename());
else
II.getInputArg().renderAsInput(Args, CmdArgs);
}
C.addCommand(llvm::make_unique<Command>(JA, *this, D.getClangProgramPath(),
CmdArgs, Inputs));
return;
}
if (C.getDriver().embedBitcodeMarkerOnly() && !C.getDriver().isUsingLTO())
CmdArgs.push_back("-fembed-bitcode=marker");
// We normally speed up the clang process a bit by skipping destructors at
// exit, but when we're generating diagnostics we can rely on some of the
// cleanup.
if (!C.isForDiagnostics())
CmdArgs.push_back("-disable-free");
#ifdef NDEBUG
const bool IsAssertBuild = false;
#else
const bool IsAssertBuild = true;
#endif
// Disable the verification pass in -asserts builds.
if (!IsAssertBuild)
CmdArgs.push_back("-disable-llvm-verifier");
// Discard value names in assert builds unless otherwise specified.
if (Args.hasFlag(options::OPT_fdiscard_value_names,
options::OPT_fno_discard_value_names, !IsAssertBuild))
CmdArgs.push_back("-discard-value-names");
// Set the main file name, so that debug info works even with
// -save-temps.
CmdArgs.push_back("-main-file-name");
CmdArgs.push_back(getBaseInputName(Args, Input));
// Some flags which affect the language (via preprocessor
// defines).
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("-static-define");
if (Args.hasArg(options::OPT_municode))
CmdArgs.push_back("-DUNICODE");
if (isa<AnalyzeJobAction>(JA))
RenderAnalyzerOptions(Args, CmdArgs, Triple, Input);
// Enable compatilibily mode to avoid analyzer-config related errors.
// Since we can't access frontend flags through hasArg, let's manually iterate
// through them.
bool FoundAnalyzerConfig = false;
for (auto Arg : Args.filtered(options::OPT_Xclang))
if (StringRef(Arg->getValue()) == "-analyzer-config") {
FoundAnalyzerConfig = true;
break;
}
if (!FoundAnalyzerConfig)
for (auto Arg : Args.filtered(options::OPT_Xanalyzer))
if (StringRef(Arg->getValue()) == "-analyzer-config") {
FoundAnalyzerConfig = true;
break;
}
if (FoundAnalyzerConfig)
CmdArgs.push_back("-analyzer-config-compatibility-mode=true");
CheckCodeGenerationOptions(D, Args);
unsigned FunctionAlignment = ParseFunctionAlignment(TC, Args);
assert(FunctionAlignment <= 31 && "function alignment will be truncated!");
if (FunctionAlignment) {
CmdArgs.push_back("-function-alignment");
CmdArgs.push_back(Args.MakeArgString(std::to_string(FunctionAlignment)));
}
llvm::Reloc::Model RelocationModel;
unsigned PICLevel;
bool IsPIE;
std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(TC, Args);
const char *RMName = RelocationModelName(RelocationModel);
if ((RelocationModel == llvm::Reloc::ROPI ||
RelocationModel == llvm::Reloc::ROPI_RWPI) &&
types::isCXX(Input.getType()) &&
!Args.hasArg(options::OPT_fallow_unsupported))
D.Diag(diag::err_drv_ropi_incompatible_with_cxx);
if (RMName) {
CmdArgs.push_back("-mrelocation-model");
CmdArgs.push_back(RMName);
}
if (PICLevel > 0) {
CmdArgs.push_back("-pic-level");
CmdArgs.push_back(PICLevel == 1 ? "1" : "2");
if (IsPIE)
CmdArgs.push_back("-pic-is-pie");
}
if (Arg *A = Args.getLastArg(options::OPT_meabi)) {
CmdArgs.push_back("-meabi");
CmdArgs.push_back(A->getValue());
}
CmdArgs.push_back("-mthread-model");
if (Arg *A = Args.getLastArg(options::OPT_mthread_model)) {
if (!TC.isThreadModelSupported(A->getValue()))
D.Diag(diag::err_drv_invalid_thread_model_for_target)
<< A->getValue() << A->getAsString(Args);
CmdArgs.push_back(A->getValue());
}
else
CmdArgs.push_back(Args.MakeArgString(TC.getThreadModel()));
Args.AddLastArg(CmdArgs, options::OPT_fveclib);
if (Args.hasFlag(options::OPT_fmerge_all_constants,
options::OPT_fno_merge_all_constants, false))
CmdArgs.push_back("-fmerge-all-constants");
if (Args.hasFlag(options::OPT_fno_delete_null_pointer_checks,
options::OPT_fdelete_null_pointer_checks, false))
CmdArgs.push_back("-fno-delete-null-pointer-checks");
// LLVM Code Generator Options.
if (Args.hasArg(options::OPT_frewrite_map_file) ||
Args.hasArg(options::OPT_frewrite_map_file_EQ)) {
for (const Arg *A : Args.filtered(options::OPT_frewrite_map_file,
options::OPT_frewrite_map_file_EQ)) {
StringRef Map = A->getValue();
if (!llvm::sys::fs::exists(Map)) {
D.Diag(diag::err_drv_no_such_file) << Map;
} else {
CmdArgs.push_back("-frewrite-map-file");
CmdArgs.push_back(A->getValue());
A->claim();
}
}
}
if (Arg *A = Args.getLastArg(options::OPT_Wframe_larger_than_EQ)) {
StringRef v = A->getValue();
CmdArgs.push_back("-mllvm");
CmdArgs.push_back(Args.MakeArgString("-warn-stack-size=" + v));
A->claim();
}
if (!Args.hasFlag(options::OPT_fjump_tables, options::OPT_fno_jump_tables,
true))
CmdArgs.push_back("-fno-jump-tables");
if (Args.hasFlag(options::OPT_fprofile_sample_accurate,
options::OPT_fno_profile_sample_accurate, false))
CmdArgs.push_back("-fprofile-sample-accurate");
if (!Args.hasFlag(options::OPT_fpreserve_as_comments,
options::OPT_fno_preserve_as_comments, true))
CmdArgs.push_back("-fno-preserve-as-comments");
if (Arg *A = Args.getLastArg(options::OPT_mregparm_EQ)) {
CmdArgs.push_back("-mregparm");
CmdArgs.push_back(A->getValue());
}
if (Arg *A = Args.getLastArg(options::OPT_fpcc_struct_return,
options::OPT_freg_struct_return)) {
if (TC.getArch() != llvm::Triple::x86) {
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getSpelling() << RawTriple.str();
} else if (A->getOption().matches(options::OPT_fpcc_struct_return)) {
CmdArgs.push_back("-fpcc-struct-return");
} else {
assert(A->getOption().matches(options::OPT_freg_struct_return));
CmdArgs.push_back("-freg-struct-return");
}
}
if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false))
CmdArgs.push_back("-fdefault-calling-conv=stdcall");
if (shouldUseFramePointer(Args, RawTriple))
CmdArgs.push_back("-mdisable-fp-elim");
if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss,
options::OPT_fno_zero_initialized_in_bss))
CmdArgs.push_back("-mno-zero-initialized-in-bss");
bool OFastEnabled = isOptimizationLevelFast(Args);
// If -Ofast is the optimization level, then -fstrict-aliasing should be
// enabled. This alias option is being used to simplify the hasFlag logic.
OptSpecifier StrictAliasingAliasOption =
OFastEnabled ? options::OPT_Ofast : options::OPT_fstrict_aliasing;
// We turn strict aliasing off by default if we're in CL mode, since MSVC
// doesn't do any TBAA.
bool TBAAOnByDefault = !D.IsCLMode();
if (!Args.hasFlag(options::OPT_fstrict_aliasing, StrictAliasingAliasOption,
options::OPT_fno_strict_aliasing, TBAAOnByDefault))
CmdArgs.push_back("-relaxed-aliasing");
if (!Args.hasFlag(options::OPT_fstruct_path_tbaa,
options::OPT_fno_struct_path_tbaa))
CmdArgs.push_back("-no-struct-path-tbaa");
if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums,
false))
CmdArgs.push_back("-fstrict-enums");
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))
CmdArgs.push_back("-fstrict-vtable-pointers");
if (Args.hasFlag(options::OPT_fforce_emit_vtables,
options::OPT_fno_force_emit_vtables,
false))
CmdArgs.push_back("-fforce-emit-vtables");
if (!Args.hasFlag(options::OPT_foptimize_sibling_calls,
options::OPT_fno_optimize_sibling_calls))
CmdArgs.push_back("-mdisable-tail-calls");
if (Args.hasFlag(options::OPT_fno_escaping_block_tail_calls,
options::OPT_fescaping_block_tail_calls, false))
CmdArgs.push_back("-fno-escaping-block-tail-calls");
Args.AddLastArg(CmdArgs, options::OPT_ffine_grained_bitfield_accesses,
options::OPT_fno_fine_grained_bitfield_accesses);
// Handle segmented stacks.
if (Args.hasArg(options::OPT_fsplit_stack))
CmdArgs.push_back("-split-stacks");
RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs);
// Decide whether to use verbose asm. Verbose assembly is the default on
// toolchains which have the integrated assembler on by default.
bool IsIntegratedAssemblerDefault = TC.IsIntegratedAssemblerDefault();
if (Args.hasFlag(options::OPT_fverbose_asm, options::OPT_fno_verbose_asm,
IsIntegratedAssemblerDefault) ||
Args.hasArg(options::OPT_dA))
CmdArgs.push_back("-masm-verbose");
if (!TC.useIntegratedAs())
CmdArgs.push_back("-no-integrated-as");
if (Args.hasArg(options::OPT_fdebug_pass_structure)) {
CmdArgs.push_back("-mdebug-pass");
CmdArgs.push_back("Structure");
}
if (Args.hasArg(options::OPT_fdebug_pass_arguments)) {
CmdArgs.push_back("-mdebug-pass");
CmdArgs.push_back("Arguments");
}
// Enable -mconstructor-aliases except on darwin, where we have to work around
// a linker bug (see <rdar://problem/7651567>), and CUDA device code, where
// aliases aren't supported.
if (!RawTriple.isOSDarwin() && !RawTriple.isNVPTX())
CmdArgs.push_back("-mconstructor-aliases");
// Darwin's kernel doesn't support guard variables; just die if we
// try to use them.
if (KernelOrKext && RawTriple.isOSDarwin())
CmdArgs.push_back("-fforbid-guard-variables");
if (Args.hasFlag(options::OPT_mms_bitfields, options::OPT_mno_ms_bitfields,
false)) {
CmdArgs.push_back("-mms-bitfields");
}
if (Args.hasFlag(options::OPT_mpie_copy_relocations,
options::OPT_mno_pie_copy_relocations,
false)) {
CmdArgs.push_back("-mpie-copy-relocations");
}
if (Args.hasFlag(options::OPT_fno_plt, options::OPT_fplt, false)) {
CmdArgs.push_back("-fno-plt");
}
// -fhosted is default.
// TODO: Audit uses of KernelOrKext and see where it'd be more appropriate to
// use Freestanding.
bool Freestanding =
Args.hasFlag(options::OPT_ffreestanding, options::OPT_fhosted, false) ||
KernelOrKext;
if (Freestanding)
CmdArgs.push_back("-ffreestanding");
// This is a coarse approximation of what llvm-gcc actually does, both
// -fasynchronous-unwind-tables and -fnon-call-exceptions interact in more
// complicated ways.
bool AsynchronousUnwindTables =
Args.hasFlag(options::OPT_fasynchronous_unwind_tables,
options::OPT_fno_asynchronous_unwind_tables,
(TC.IsUnwindTablesDefault(Args) ||
TC.getSanitizerArgs().needsUnwindTables()) &&
!Freestanding);
if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables,
AsynchronousUnwindTables))
CmdArgs.push_back("-munwind-tables");
TC.addClangTargetOptions(Args, CmdArgs, JA.getOffloadingDeviceKind());
// FIXME: Handle -mtune=.
(void)Args.hasArg(options::OPT_mtune_EQ);
if (Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {
CmdArgs.push_back("-mcode-model");
CmdArgs.push_back(A->getValue());
}
// Add the target cpu
std::string CPU = getCPUName(Args, Triple, /*FromAs*/ false);
if (!CPU.empty()) {
CmdArgs.push_back("-target-cpu");
CmdArgs.push_back(Args.MakeArgString(CPU));
}
RenderTargetOptions(Triple, Args, KernelOrKext, CmdArgs);
// These two are potentially updated by AddClangCLArgs.
codegenoptions::DebugInfoKind DebugInfoKind = codegenoptions::NoDebugInfo;
bool EmitCodeView = false;
// Add clang-cl arguments.
types::ID InputType = Input.getType();
if (D.IsCLMode())
AddClangCLArgs(Args, InputType, CmdArgs, &DebugInfoKind, &EmitCodeView);
DwarfFissionKind DwarfFission;
RenderDebugOptions(TC, D, RawTriple, Args, EmitCodeView, IsWindowsMSVC,
CmdArgs, DebugInfoKind, DwarfFission);
// Add the split debug info name to the command lines here so we
// can propagate it to the backend.
bool SplitDWARF = (DwarfFission != DwarfFissionKind::None) &&
(RawTriple.isOSLinux() || RawTriple.isOSFuchsia()) &&
(isa<AssembleJobAction>(JA) || isa<CompileJobAction>(JA) ||
isa<BackendJobAction>(JA));
const char *SplitDWARFOut;
if (SplitDWARF) {
CmdArgs.push_back("-split-dwarf-file");
SplitDWARFOut = SplitDebugName(Args, Output);
CmdArgs.push_back(SplitDWARFOut);
}
// Pass the linker version in use.
if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) {
CmdArgs.push_back("-target-linker-version");
CmdArgs.push_back(A->getValue());
}
if (!shouldUseLeafFramePointer(Args, RawTriple))
CmdArgs.push_back("-momit-leaf-frame-pointer");
// Explicitly error on some things we know we don't support and can't just
// ignore.
if (!Args.hasArg(options::OPT_fallow_unsupported)) {
Arg *Unsupported;
if (types::isCXX(InputType) && RawTriple.isOSDarwin() &&
TC.getArch() == llvm::Triple::x86) {
if ((Unsupported = Args.getLastArg(options::OPT_fapple_kext)) ||
(Unsupported = Args.getLastArg(options::OPT_mkernel)))
D.Diag(diag::err_drv_clang_unsupported_opt_cxx_darwin_i386)
<< Unsupported->getOption().getName();
}
// The faltivec option has been superseded by the maltivec option.
if ((Unsupported = Args.getLastArg(options::OPT_faltivec)))
D.Diag(diag::err_drv_clang_unsupported_opt_faltivec)
<< Unsupported->getOption().getName()
<< "please use -maltivec and include altivec.h explicitly";
if ((Unsupported = Args.getLastArg(options::OPT_fno_altivec)))
D.Diag(diag::err_drv_clang_unsupported_opt_faltivec)
<< Unsupported->getOption().getName() << "please use -mno-altivec";
}
Args.AddAllArgs(CmdArgs, options::OPT_v);
Args.AddLastArg(CmdArgs, options::OPT_H);
if (D.CCPrintHeaders && !D.CCGenDiagnostics) {
CmdArgs.push_back("-header-include-file");
CmdArgs.push_back(D.CCPrintHeadersFilename ? D.CCPrintHeadersFilename
: "-");
}
Args.AddLastArg(CmdArgs, options::OPT_P);
Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
if (D.CCLogDiagnostics && !D.CCGenDiagnostics) {
CmdArgs.push_back("-diagnostic-log-file");
CmdArgs.push_back(D.CCLogDiagnosticsFilename ? D.CCLogDiagnosticsFilename
: "-");
}
bool UseSeparateSections = isUseSeparateSections(Triple);
if (Args.hasFlag(options::OPT_ffunction_sections,
options::OPT_fno_function_sections, UseSeparateSections)) {
CmdArgs.push_back("-ffunction-sections");
}
if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections,
UseSeparateSections)) {
CmdArgs.push_back("-fdata-sections");
}
if (!Args.hasFlag(options::OPT_funique_section_names,
options::OPT_fno_unique_section_names, true))
CmdArgs.push_back("-fno-unique-section-names");
if (auto *A = Args.getLastArg(
options::OPT_finstrument_functions,
options::OPT_finstrument_functions_after_inlining,
options::OPT_finstrument_function_entry_bare))
A->render(Args, CmdArgs);
// NVPTX doesn't support PGO or coverage. There's no runtime support for
// sampling, overhead of call arc collection is way too high and there's no
// way to collect the output.
if (!Triple.isNVPTX())
addPGOAndCoverageFlags(C, D, Output, Args, CmdArgs);
if (auto *ABICompatArg = Args.getLastArg(options::OPT_fclang_abi_compat_EQ))
ABICompatArg->render(Args, CmdArgs);
// Add runtime flag for PS4 when PGO, coverage, or sanitizers are enabled.
if (RawTriple.isPS4CPU() &&
!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
PS4cpu::addProfileRTArgs(TC, Args, CmdArgs);
PS4cpu::addSanitizerArgs(TC, CmdArgs);
}
// Pass options for controlling the default header search paths.
if (Args.hasArg(options::OPT_nostdinc)) {
CmdArgs.push_back("-nostdsysteminc");
CmdArgs.push_back("-nobuiltininc");
} else {
if (Args.hasArg(options::OPT_nostdlibinc))
CmdArgs.push_back("-nostdsysteminc");
Args.AddLastArg(CmdArgs, options::OPT_nostdincxx);
Args.AddLastArg(CmdArgs, options::OPT_nobuiltininc);
}
// Pass the path to compiler resource files.
CmdArgs.push_back("-resource-dir");
CmdArgs.push_back(D.ResourceDir.c_str());
Args.AddLastArg(CmdArgs, options::OPT_working_directory);
RenderARCMigrateToolOptions(D, Args, CmdArgs);
// Add preprocessing options like -I, -D, etc. if we are using the
// preprocessor.
//
// FIXME: Support -fpreprocessed
if (types::getPreprocessedType(InputType) != types::TY_INVALID)
AddPreprocessingOptions(C, JA, D, Args, CmdArgs, Output, Inputs);
// Don't warn about "clang -c -DPIC -fPIC test.i" because libtool.m4 assumes
// that "The compiler can only warn and ignore the option if not recognized".
// When building with ccache, it will pass -D options to clang even on
// preprocessed inputs and configure concludes that -fPIC is not supported.
Args.ClaimAllArgs(options::OPT_D);
// Manually translate -O4 to -O3; let clang reject others.
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
if (A->getOption().matches(options::OPT_O4)) {
CmdArgs.push_back("-O3");
D.Diag(diag::warn_O4_is_O3);
} else {
A->render(Args, CmdArgs);
}
}
// Warn about ignored options to clang.
for (const Arg *A :
Args.filtered(options::OPT_clang_ignored_gcc_optimization_f_Group)) {
D.Diag(diag::warn_ignored_gcc_optimization) << A->getAsString(Args);
A->claim();
}
for (const Arg *A :
Args.filtered(options::OPT_clang_ignored_legacy_options_Group)) {
D.Diag(diag::warn_ignored_clang_option) << A->getAsString(Args);
A->claim();
}
claimNoWarnArgs(Args);
Args.AddAllArgs(CmdArgs, options::OPT_R_Group);
Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
CmdArgs.push_back("-pedantic");
Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
Args.AddLastArg(CmdArgs, options::OPT_w);
// Fixed point flags
if (Args.hasFlag(options::OPT_ffixed_point, options::OPT_fno_fixed_point,
/*Default=*/false))
Args.AddLastArg(CmdArgs, options::OPT_ffixed_point);
// Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
// (-ansi is equivalent to -std=c89 or -std=c++98).
//
// If a std is supplied, only add -trigraphs if it follows the
// option.
bool ImplyVCPPCXXVer = false;
if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {
if (Std->getOption().matches(options::OPT_ansi))
if (types::isCXX(InputType))
CmdArgs.push_back("-std=c++98");
else
CmdArgs.push_back("-std=c89");
else
Std->render(Args, CmdArgs);
// If -f(no-)trigraphs appears after the language standard flag, honor it.
if (Arg *A = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi,
options::OPT_ftrigraphs,
options::OPT_fno_trigraphs))
if (A != Std)
A->render(Args, CmdArgs);
} else {
// Honor -std-default.
//
// FIXME: Clang doesn't correctly handle -std= when the input language
// doesn't match. For the time being just ignore this for C++ inputs;
// eventually we want to do all the standard defaulting here instead of
// splitting it between the driver and clang -cc1.
if (!types::isCXX(InputType))
Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, "-std=",
/*Joined=*/true);
else if (IsWindowsMSVC)
ImplyVCPPCXXVer = true;
Args.AddLastArg(CmdArgs, options::OPT_ftrigraphs,
options::OPT_fno_trigraphs);
}
// GCC's behavior for -Wwrite-strings is a bit strange:
// * In C, this "warning flag" changes the types of string literals from
// 'char[N]' to 'const char[N]', and thus triggers an unrelated warning
// for the discarded qualifier.
// * In C++, this is just a normal warning flag.
//
// Implementing this warning correctly in C is hard, so we follow GCC's
// behavior for now. FIXME: Directly diagnose uses of a string literal as
// a non-const char* in C, rather than using this crude hack.
if (!types::isCXX(InputType)) {
// FIXME: This should behave just like a warning flag, and thus should also
// respect -Weverything, -Wno-everything, -Werror=write-strings, and so on.
Arg *WriteStrings =
Args.getLastArg(options::OPT_Wwrite_strings,
options::OPT_Wno_write_strings, options::OPT_w);
if (WriteStrings &&
WriteStrings->getOption().matches(options::OPT_Wwrite_strings))
CmdArgs.push_back("-fconst-strings");
}
// GCC provides a macro definition '__DEPRECATED' when -Wdeprecated is active
// during C++ compilation, which it is by default. GCC keeps this define even
// in the presence of '-w', match this behavior bug-for-bug.
if (types::isCXX(InputType) &&
Args.hasFlag(options::OPT_Wdeprecated, options::OPT_Wno_deprecated,
true)) {
CmdArgs.push_back("-fdeprecated-macro");
}
// Translate GCC's misnamer '-fasm' arguments to '-fgnu-keywords'.
if (Arg *Asm = Args.getLastArg(options::OPT_fasm, options::OPT_fno_asm)) {
if (Asm->getOption().matches(options::OPT_fasm))
CmdArgs.push_back("-fgnu-keywords");
else
CmdArgs.push_back("-fno-gnu-keywords");
}
if (ShouldDisableDwarfDirectory(Args, TC))
CmdArgs.push_back("-fno-dwarf-directory-asm");
if (ShouldDisableAutolink(Args, TC))
CmdArgs.push_back("-fno-autolink");
// Add in -fdebug-compilation-dir if necessary.
addDebugCompDirArg(Args, CmdArgs);
addDebugPrefixMapArg(D, Args, CmdArgs);
if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_,
options::OPT_ftemplate_depth_EQ)) {
CmdArgs.push_back("-ftemplate-depth");
CmdArgs.push_back(A->getValue());
}
if (Arg *A = Args.getLastArg(options::OPT_foperator_arrow_depth_EQ)) {
CmdArgs.push_back("-foperator-arrow-depth");
CmdArgs.push_back(A->getValue());
}
if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) {
CmdArgs.push_back("-fconstexpr-depth");
CmdArgs.push_back(A->getValue());
}
if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_steps_EQ)) {
CmdArgs.push_back("-fconstexpr-steps");
CmdArgs.push_back(A->getValue());
}
if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) {
CmdArgs.push_back("-fbracket-depth");
CmdArgs.push_back(A->getValue());
}
if (Arg *A = Args.getLastArg(options::OPT_Wlarge_by_value_copy_EQ,
options::OPT_Wlarge_by_value_copy_def)) {
if (A->getNumValues()) {
StringRef bytes = A->getValue();
CmdArgs.push_back(Args.MakeArgString("-Wlarge-by-value-copy=" + bytes));
} else
CmdArgs.push_back("-Wlarge-by-value-copy=64"); // default value
}
if (Args.hasArg(options::OPT_relocatable_pch))
CmdArgs.push_back("-relocatable-pch");
if (const Arg *A = Args.getLastArg(options::OPT_fcf_runtime_abi_EQ)) {
static const char *kCFABIs[] = {
"standalone", "objc", "swift", "swift-5.0", "swift-4.2", "swift-4.1",
};
if (find(kCFABIs, StringRef(A->getValue())) == std::end(kCFABIs))
D.Diag(diag::err_drv_invalid_cf_runtime_abi) << A->getValue();
else
A->render(Args, CmdArgs);
}
if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
CmdArgs.push_back("-fconstant-string-class");
CmdArgs.push_back(A->getValue());
}
if (Arg *A = Args.getLastArg(options::OPT_ftabstop_EQ)) {
CmdArgs.push_back("-ftabstop");
CmdArgs.push_back(A->getValue());
}
if (Args.hasFlag(options::OPT_fstack_size_section,
options::OPT_fno_stack_size_section, RawTriple.isPS4()))
CmdArgs.push_back("-fstack-size-section");
CmdArgs.push_back("-ferror-limit");
if (Arg *A = Args.getLastArg(options::OPT_ferror_limit_EQ))
CmdArgs.push_back(A->getValue());
else
CmdArgs.push_back("19");
if (Arg *A = Args.getLastArg(options::OPT_fmacro_backtrace_limit_EQ)) {
CmdArgs.push_back("-fmacro-backtrace-limit");
CmdArgs.push_back(A->getValue());
}
if (Arg *A = Args.getLastArg(options::OPT_ftemplate_backtrace_limit_EQ)) {
CmdArgs.push_back("-ftemplate-backtrace-limit");
CmdArgs.push_back(A->getValue());
}
if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_backtrace_limit_EQ)) {
CmdArgs.push_back("-fconstexpr-backtrace-limit");
CmdArgs.push_back(A->getValue());
}
if (Arg *A = Args.getLastArg(options::OPT_fspell_checking_limit_EQ)) {
CmdArgs.push_back("-fspell-checking-limit");
CmdArgs.push_back(A->getValue());
}
// Pass -fmessage-length=.
CmdArgs.push_back("-fmessage-length");
if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) {
CmdArgs.push_back(A->getValue());
} else {
// If -fmessage-length=N was not specified, determine whether this is a
// terminal and, if so, implicitly define -fmessage-length appropriately.
unsigned N = llvm::sys::Process::StandardErrColumns();
CmdArgs.push_back(Args.MakeArgString(Twine(N)));
}
// -fvisibility= and -fvisibility-ms-compat are of a piece.
if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ,
options::OPT_fvisibility_ms_compat)) {
if (A->getOption().matches(options::OPT_fvisibility_EQ)) {
CmdArgs.push_back("-fvisibility");
CmdArgs.push_back(A->getValue());
} else {
assert(A->getOption().matches(options::OPT_fvisibility_ms_compat));
CmdArgs.push_back("-fvisibility");
CmdArgs.push_back("hidden");
CmdArgs.push_back("-ftype-visibility");
CmdArgs.push_back("default");
}
}
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden);
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_global_new_delete_hidden);
Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);
// Forward -f (flag) options which we can pass directly.
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
Args.AddLastArg(CmdArgs, options::OPT_fdigraphs, options::OPT_fno_digraphs);
Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);
Args.AddLastArg(CmdArgs, options::OPT_femulated_tls,
options::OPT_fno_emulated_tls);
Args.AddLastArg(CmdArgs, options::OPT_fkeep_static_consts);
// AltiVec-like language extensions aren't relevant for assembling.
if (!isa<PreprocessJobAction>(JA) || Output.getType() != types::TY_PP_Asm)
Args.AddLastArg(CmdArgs, options::OPT_fzvector);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree);
Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type);
// Forward flags for OpenMP. We don't do this if the current action is an
// device offloading action other than OpenMP.
if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false) &&
(JA.isDeviceOffloading(Action::OFK_None) ||
JA.isDeviceOffloading(Action::OFK_OpenMP))) {
switch (D.getOpenMPRuntime(Args)) {
case Driver::OMPRT_OMP:
case Driver::OMPRT_IOMP5:
// Clang can generate useful OpenMP code for these two runtime libraries.
CmdArgs.push_back("-fopenmp");
// If no option regarding the use of TLS in OpenMP codegeneration is
// given, decide a default based on the target. Otherwise rely on the
// options and pass the right information to the frontend.
if (!Args.hasFlag(options::OPT_fopenmp_use_tls,
options::OPT_fnoopenmp_use_tls, /*Default=*/true))
CmdArgs.push_back("-fnoopenmp-use-tls");
Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
options::OPT_fno_openmp_simd);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_number_of_sm_EQ);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_cuda_blocks_per_sm_EQ);
if (Args.hasFlag(options::OPT_fopenmp_optimistic_collapse,
options::OPT_fno_openmp_optimistic_collapse,
/*Default=*/false))
CmdArgs.push_back("-fopenmp-optimistic-collapse");
// When in OpenMP offloading mode with NVPTX target, forward
// cuda-mode flag
if (Args.hasFlag(options::OPT_fopenmp_cuda_mode,
options::OPT_fno_openmp_cuda_mode, /*Default=*/false))
CmdArgs.push_back("-fopenmp-cuda-mode");
// When in OpenMP offloading mode with NVPTX target, check if full runtime
// is required.
if (Args.hasFlag(options::OPT_fopenmp_cuda_force_full_runtime,
options::OPT_fno_openmp_cuda_force_full_runtime,
/*Default=*/false))
CmdArgs.push_back("-fopenmp-cuda-force-full-runtime");
break;
default:
// By default, if Clang doesn't know how to generate useful OpenMP code
// for a specific runtime library, we just don't pass the '-fopenmp' flag
// down to the actual compilation.
// FIXME: It would be better to have a mode which *only* omits IR
// generation based on the OpenMP support so that we get consistent
// semantic analysis, etc.
break;
}
} else {
Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
options::OPT_fno_openmp_simd);
Args.AddAllArgs(CmdArgs, options::OPT_fopenmp_version_EQ);
}
const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
Sanitize.addArgs(TC, Args, CmdArgs, InputType);
const XRayArgs &XRay = TC.getXRayArgs();
XRay.addArgs(TC, Args, CmdArgs, InputType);
if (TC.SupportsProfiling())
Args.AddLastArg(CmdArgs, options::OPT_pg);
if (TC.SupportsProfiling())
Args.AddLastArg(CmdArgs, options::OPT_mfentry);
// -flax-vector-conversions is default.
if (!Args.hasFlag(options::OPT_flax_vector_conversions,
options::OPT_fno_lax_vector_conversions))
CmdArgs.push_back("-fno-lax-vector-conversions");
if (Args.getLastArg(options::OPT_fapple_kext) ||
(Args.hasArg(options::OPT_mkernel) && types::isCXX(InputType)))
CmdArgs.push_back("-fapple-kext");
Args.AddLastArg(CmdArgs, options::OPT_fobjc_sender_dependent_dispatch);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info);
Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits);
Args.AddLastArg(CmdArgs, options::OPT_ftime_report);
Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
if (Arg *A = Args.getLastArg(options::OPT_ftrapv_handler_EQ)) {
CmdArgs.push_back("-ftrapv-handler");
CmdArgs.push_back(A->getValue());
}
Args.AddLastArg(CmdArgs, options::OPT_ftrap_function_EQ);
// -fno-strict-overflow implies -fwrapv if it isn't disabled, but
// -fstrict-overflow won't turn off an explicitly enabled -fwrapv.
if (Arg *A = Args.getLastArg(options::OPT_fwrapv, options::OPT_fno_wrapv)) {
if (A->getOption().matches(options::OPT_fwrapv))
CmdArgs.push_back("-fwrapv");
} else if (Arg *A = Args.getLastArg(options::OPT_fstrict_overflow,
options::OPT_fno_strict_overflow)) {
if (A->getOption().matches(options::OPT_fno_strict_overflow))
CmdArgs.push_back("-fwrapv");
}
if (Arg *A = Args.getLastArg(options::OPT_freroll_loops,
options::OPT_fno_reroll_loops))
if (A->getOption().matches(options::OPT_freroll_loops))
CmdArgs.push_back("-freroll-loops");
Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
Args.AddLastArg(CmdArgs, options::OPT_funroll_loops,
options::OPT_fno_unroll_loops);
Args.AddLastArg(CmdArgs, options::OPT_pthread);
if (Args.hasFlag(options::OPT_mspeculative_load_hardening, options::OPT_mno_speculative_load_hardening,
false))
CmdArgs.push_back(Args.MakeArgString("-mspeculative-load-hardening"));
RenderSSPOptions(TC, Args, CmdArgs, KernelOrKext);
RenderTrivialAutoVarInitOptions(D, TC, Args, CmdArgs);
// Translate -mstackrealign
if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign,
false))
CmdArgs.push_back(Args.MakeArgString("-mstackrealign"));
if (Args.hasArg(options::OPT_mstack_alignment)) {
StringRef alignment = Args.getLastArgValue(options::OPT_mstack_alignment);
CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment));
}
if (Args.hasArg(options::OPT_mstack_probe_size)) {
StringRef Size = Args.getLastArgValue(options::OPT_mstack_probe_size);
if (!Size.empty())
CmdArgs.push_back(Args.MakeArgString("-mstack-probe-size=" + Size));
else
CmdArgs.push_back("-mstack-probe-size=0");
}
if (!Args.hasFlag(options::OPT_mstack_arg_probe,
options::OPT_mno_stack_arg_probe, true))
CmdArgs.push_back(Args.MakeArgString("-mno-stack-arg-probe"));
if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it,
options::OPT_mno_restrict_it)) {
if (A->getOption().matches(options::OPT_mrestrict_it)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-arm-restrict-it");
} else {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-arm-no-restrict-it");
}
} else if (Triple.isOSWindows() &&
(Triple.getArch() == llvm::Triple::arm ||
Triple.getArch() == llvm::Triple::thumb)) {
// Windows on ARM expects restricted IT blocks
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-arm-restrict-it");
}
// Forward -cl options to -cc1
RenderOpenCLOptions(Args, CmdArgs);
if (Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) {
CmdArgs.push_back(
Args.MakeArgString(Twine("-fcf-protection=") + A->getValue()));
}
// Forward -f options with positive and negative forms; we translate
// these by hand.
if (Arg *A = getLastProfileSampleUseArg(Args)) {
StringRef fname = A->getValue();
if (!llvm::sys::fs::exists(fname))
D.Diag(diag::err_drv_no_such_file) << fname;
else
A->render(Args, CmdArgs);
}
Args.AddLastArg(CmdArgs, options::OPT_fprofile_remapping_file_EQ);
RenderBuiltinOptions(TC, RawTriple, Args, CmdArgs);
if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
options::OPT_fno_assume_sane_operator_new))
CmdArgs.push_back("-fno-assume-sane-operator-new");
// -fblocks=0 is default.
if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
TC.IsBlocksDefault()) ||
(Args.hasArg(options::OPT_fgnu_runtime) &&
Args.hasArg(options::OPT_fobjc_nonfragile_abi) &&
!Args.hasArg(options::OPT_fno_blocks))) {
CmdArgs.push_back("-fblocks");
if (!Args.hasArg(options::OPT_fgnu_runtime) && !TC.hasBlocksRuntime())
CmdArgs.push_back("-fblocks-runtime-optional");
}
// -fencode-extended-block-signature=1 is default.
if (TC.IsEncodeExtendedBlockSignatureDefault())
CmdArgs.push_back("-fencode-extended-block-signature");
if (Args.hasFlag(options::OPT_fcoroutines_ts, options::OPT_fno_coroutines_ts,
false) &&
types::isCXX(InputType)) {
CmdArgs.push_back("-fcoroutines-ts");
}
Args.AddLastArg(CmdArgs, options::OPT_fdouble_square_bracket_attributes,
options::OPT_fno_double_square_bracket_attributes);
bool HaveModules = false;
RenderModulesOptions(C, D, Args, Input, Output, CmdArgs, HaveModules);
// -faccess-control is default.
if (Args.hasFlag(options::OPT_fno_access_control,
options::OPT_faccess_control, false))
CmdArgs.push_back("-fno-access-control");
// -felide-constructors is the default.
if (Args.hasFlag(options::OPT_fno_elide_constructors,
options::OPT_felide_constructors, false))
CmdArgs.push_back("-fno-elide-constructors");
ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();
if (KernelOrKext || (types::isCXX(InputType) &&
(RTTIMode == ToolChain::RM_Disabled)))
CmdArgs.push_back("-fno-rtti");
// -fshort-enums=0 is default for all architectures except Hexagon.
if (Args.hasFlag(options::OPT_fshort_enums, options::OPT_fno_short_enums,
TC.getArch() == llvm::Triple::hexagon))
CmdArgs.push_back("-fshort-enums");
RenderCharacterOptions(Args, AuxTriple ? *AuxTriple : RawTriple, CmdArgs);
// -fuse-cxa-atexit is default.
if (!Args.hasFlag(
options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
!RawTriple.isOSWindows() &&
RawTriple.getOS() != llvm::Triple::Solaris &&
TC.getArch() != llvm::Triple::xcore &&
((RawTriple.getVendor() != llvm::Triple::MipsTechnologies) ||
RawTriple.hasEnvironment())) ||
KernelOrKext)
CmdArgs.push_back("-fno-use-cxa-atexit");
if (Args.hasFlag(options::OPT_fregister_global_dtors_with_atexit,
options::OPT_fno_register_global_dtors_with_atexit,
RawTriple.isOSDarwin() && !KernelOrKext))
CmdArgs.push_back("-fregister-global-dtors-with-atexit");
// -fms-extensions=0 is default.
if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
IsWindowsMSVC))
CmdArgs.push_back("-fms-extensions");
// -fno-use-line-directives is default.
if (Args.hasFlag(options::OPT_fuse_line_directives,
options::OPT_fno_use_line_directives, false))
CmdArgs.push_back("-fuse-line-directives");
// -fms-compatibility=0 is default.
if (Args.hasFlag(options::OPT_fms_compatibility,
options::OPT_fno_ms_compatibility,
(IsWindowsMSVC &&
Args.hasFlag(options::OPT_fms_extensions,
options::OPT_fno_ms_extensions, true))))
CmdArgs.push_back("-fms-compatibility");
VersionTuple MSVT = TC.computeMSVCVersion(&D, Args);
if (!MSVT.empty())
CmdArgs.push_back(
Args.MakeArgString("-fms-compatibility-version=" + MSVT.getAsString()));
bool IsMSVC2015Compatible = MSVT.getMajor() >= 19;
if (ImplyVCPPCXXVer) {
StringRef LanguageStandard;
if (const Arg *StdArg = Args.getLastArg(options::OPT__SLASH_std)) {
LanguageStandard = llvm::StringSwitch<StringRef>(StdArg->getValue())
.Case("c++14", "-std=c++14")
.Case("c++17", "-std=c++17")
.Case("c++latest", "-std=c++2a")
.Default("");
if (LanguageStandard.empty())
D.Diag(clang::diag::warn_drv_unused_argument)
<< StdArg->getAsString(Args);
}
if (LanguageStandard.empty()) {
if (IsMSVC2015Compatible)
LanguageStandard = "-std=c++14";
else
LanguageStandard = "-std=c++11";
}
CmdArgs.push_back(LanguageStandard.data());
}
// -fno-borland-extensions is default.
if (Args.hasFlag(options::OPT_fborland_extensions,
options::OPT_fno_borland_extensions, false))
CmdArgs.push_back("-fborland-extensions");
// -fno-declspec is default, except for PS4.
if (Args.hasFlag(options::OPT_fdeclspec, options::OPT_fno_declspec,
RawTriple.isPS4()))
CmdArgs.push_back("-fdeclspec");
else if (Args.hasArg(options::OPT_fno_declspec))
CmdArgs.push_back("-fno-declspec"); // Explicitly disabling __declspec.
// -fthreadsafe-static is default, except for MSVC compatibility versions less
// than 19.
if (!Args.hasFlag(options::OPT_fthreadsafe_statics,
options::OPT_fno_threadsafe_statics,
!IsWindowsMSVC || IsMSVC2015Compatible))
CmdArgs.push_back("-fno-threadsafe-statics");
// -fno-delayed-template-parsing is default, except when targeting MSVC.
// Many old Windows SDK versions require this to parse.
// FIXME: MSVC introduced /Zc:twoPhase- to disable this behavior in their
// compiler. We should be able to disable this by default at some point.
if (Args.hasFlag(options::OPT_fdelayed_template_parsing,
options::OPT_fno_delayed_template_parsing, IsWindowsMSVC))
CmdArgs.push_back("-fdelayed-template-parsing");
// -fgnu-keywords default varies depending on language; only pass if
// specified.
if (Arg *A = Args.getLastArg(options::OPT_fgnu_keywords,
options::OPT_fno_gnu_keywords))
A->render(Args, CmdArgs);
if (Args.hasFlag(options::OPT_fgnu89_inline, options::OPT_fno_gnu89_inline,
false))
CmdArgs.push_back("-fgnu89-inline");
if (Args.hasArg(options::OPT_fno_inline))
CmdArgs.push_back("-fno-inline");
if (Arg* InlineArg = Args.getLastArg(options::OPT_finline_functions,
options::OPT_finline_hint_functions,
options::OPT_fno_inline_functions))
InlineArg->render(Args, CmdArgs);
Args.AddLastArg(CmdArgs, options::OPT_fexperimental_new_pass_manager,
options::OPT_fno_experimental_new_pass_manager);
ObjCRuntime Runtime = AddObjCRuntimeArgs(Args, CmdArgs, rewriteKind);
RenderObjCOptions(TC, D, RawTriple, Args, Runtime, rewriteKind != RK_None,
Input, CmdArgs);
if (Args.hasFlag(options::OPT_fapplication_extension,
options::OPT_fno_application_extension, false))
CmdArgs.push_back("-fapplication-extension");
// Handle GCC-style exception args.
if (!C.getDriver().IsCLMode())
addExceptionArgs(Args, InputType, TC, KernelOrKext, Runtime, CmdArgs);
// Handle exception personalities
Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions,
options::OPT_fseh_exceptions,
options::OPT_fdwarf_exceptions);
if (A) {
const Option &Opt = A->getOption();
if (Opt.matches(options::OPT_fsjlj_exceptions))
CmdArgs.push_back("-fsjlj-exceptions");
if (Opt.matches(options::OPT_fseh_exceptions))
CmdArgs.push_back("-fseh-exceptions");
if (Opt.matches(options::OPT_fdwarf_exceptions))
CmdArgs.push_back("-fdwarf-exceptions");
} else {
switch (TC.GetExceptionModel(Args)) {
default:
break;
case llvm::ExceptionHandling::DwarfCFI:
CmdArgs.push_back("-fdwarf-exceptions");
break;
case llvm::ExceptionHandling::SjLj:
CmdArgs.push_back("-fsjlj-exceptions");
break;
case llvm::ExceptionHandling::WinEH:
CmdArgs.push_back("-fseh-exceptions");
break;
}
}
// C++ "sane" operator new.
if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
options::OPT_fno_assume_sane_operator_new))
CmdArgs.push_back("-fno-assume-sane-operator-new");
// -frelaxed-template-template-args is off by default, as it is a severe
// breaking change until a corresponding change to template partial ordering
// is provided.
if (Args.hasFlag(options::OPT_frelaxed_template_template_args,
options::OPT_fno_relaxed_template_template_args, false))
CmdArgs.push_back("-frelaxed-template-template-args");
// -fsized-deallocation is off by default, as it is an ABI-breaking change for
// most platforms.
if (Args.hasFlag(options::OPT_fsized_deallocation,
options::OPT_fno_sized_deallocation, false))
CmdArgs.push_back("-fsized-deallocation");
// -faligned-allocation is on by default in C++17 onwards and otherwise off
// by default.
if (Arg *A = Args.getLastArg(options::OPT_faligned_allocation,
options::OPT_fno_aligned_allocation,
options::OPT_faligned_new_EQ)) {
if (A->getOption().matches(options::OPT_fno_aligned_allocation))
CmdArgs.push_back("-fno-aligned-allocation");
else
CmdArgs.push_back("-faligned-allocation");
}
// The default new alignment can be specified using a dedicated option or via
// a GCC-compatible option that also turns on aligned allocation.
if (Arg *A = Args.getLastArg(options::OPT_fnew_alignment_EQ,
options::OPT_faligned_new_EQ))
CmdArgs.push_back(
Args.MakeArgString(Twine("-fnew-alignment=") + A->getValue()));
// -fconstant-cfstrings is default, and may be subject to argument translation
// on Darwin.
if (!Args.hasFlag(options::OPT_fconstant_cfstrings,
options::OPT_fno_constant_cfstrings) ||
!Args.hasFlag(options::OPT_mconstant_cfstrings,
options::OPT_mno_constant_cfstrings))
CmdArgs.push_back("-fno-constant-cfstrings");
// -fno-pascal-strings is default, only pass non-default.
if (Args.hasFlag(options::OPT_fpascal_strings,
options::OPT_fno_pascal_strings, false))
CmdArgs.push_back("-fpascal-strings");
// Honor -fpack-struct= and -fpack-struct, if given. Note that
// -fno-pack-struct doesn't apply to -fpack-struct=.
if (Arg *A = Args.getLastArg(options::OPT_fpack_struct_EQ)) {
std::string PackStructStr = "-fpack-struct=";
PackStructStr += A->getValue();
CmdArgs.push_back(Args.MakeArgString(PackStructStr));
} else if (Args.hasFlag(options::OPT_fpack_struct,
options::OPT_fno_pack_struct, false)) {
CmdArgs.push_back("-fpack-struct=1");
}
// Handle -fmax-type-align=N and -fno-type-align
bool SkipMaxTypeAlign = Args.hasArg(options::OPT_fno_max_type_align);
if (Arg *A = Args.getLastArg(options::OPT_fmax_type_align_EQ)) {
if (!SkipMaxTypeAlign) {
std::string MaxTypeAlignStr = "-fmax-type-align=";
MaxTypeAlignStr += A->getValue();
CmdArgs.push_back(Args.MakeArgString(MaxTypeAlignStr));
}
} else if (RawTriple.isOSDarwin()) {
if (!SkipMaxTypeAlign) {
std::string MaxTypeAlignStr = "-fmax-type-align=16";
CmdArgs.push_back(Args.MakeArgString(MaxTypeAlignStr));
}
}
if (!Args.hasFlag(options::OPT_Qy, options::OPT_Qn, true))
CmdArgs.push_back("-Qn");
// -fcommon is the default unless compiling kernel code or the target says so
bool NoCommonDefault = KernelOrKext || isNoCommonDefault(RawTriple);
if (!Args.hasFlag(options::OPT_fcommon, options::OPT_fno_common,
!NoCommonDefault))
CmdArgs.push_back("-fno-common");
// -fsigned-bitfields is default, and clang doesn't yet support
// -funsigned-bitfields.
if (!Args.hasFlag(options::OPT_fsigned_bitfields,
options::OPT_funsigned_bitfields))
D.Diag(diag::warn_drv_clang_unsupported)
<< Args.getLastArg(options::OPT_funsigned_bitfields)->getAsString(Args);
// -fsigned-bitfields is default, and clang doesn't support -fno-for-scope.
if (!Args.hasFlag(options::OPT_ffor_scope, options::OPT_fno_for_scope))
D.Diag(diag::err_drv_clang_unsupported)
<< Args.getLastArg(options::OPT_fno_for_scope)->getAsString(Args);
// -finput_charset=UTF-8 is default. Reject others
if (Arg *inputCharset = Args.getLastArg(options::OPT_finput_charset_EQ)) {
StringRef value = inputCharset->getValue();
if (!value.equals_lower("utf-8"))
D.Diag(diag::err_drv_invalid_value) << inputCharset->getAsString(Args)
<< value;
}
// -fexec_charset=UTF-8 is default. Reject others
if (Arg *execCharset = Args.getLastArg(options::OPT_fexec_charset_EQ)) {
StringRef value = execCharset->getValue();
if (!value.equals_lower("utf-8"))
D.Diag(diag::err_drv_invalid_value) << execCharset->getAsString(Args)
<< value;
}
RenderDiagnosticsOptions(D, Args, CmdArgs);
// -fno-asm-blocks is default.
if (Args.hasFlag(options::OPT_fasm_blocks, options::OPT_fno_asm_blocks,
false))
CmdArgs.push_back("-fasm-blocks");
// -fgnu-inline-asm is default.
if (!Args.hasFlag(options::OPT_fgnu_inline_asm,
options::OPT_fno_gnu_inline_asm, true))
CmdArgs.push_back("-fno-gnu-inline-asm");
// Enable vectorization per default according to the optimization level
// selected. For optimization levels that want vectorization we use the alias
// option to simplify the hasFlag logic.
bool EnableVec = shouldEnableVectorizerAtOLevel(Args, false);
OptSpecifier VectorizeAliasOption =
EnableVec ? options::OPT_O_Group : options::OPT_fvectorize;
if (Args.hasFlag(options::OPT_fvectorize, VectorizeAliasOption,
options::OPT_fno_vectorize, EnableVec))
CmdArgs.push_back("-vectorize-loops");
// -fslp-vectorize is enabled based on the optimization level selected.
bool EnableSLPVec = shouldEnableVectorizerAtOLevel(Args, true);
OptSpecifier SLPVectAliasOption =
EnableSLPVec ? options::OPT_O_Group : options::OPT_fslp_vectorize;
if (Args.hasFlag(options::OPT_fslp_vectorize, SLPVectAliasOption,
options::OPT_fno_slp_vectorize, EnableSLPVec))
CmdArgs.push_back("-vectorize-slp");
ParseMPreferVectorWidth(D, Args, CmdArgs);
if (Arg *A = Args.getLastArg(options::OPT_fshow_overloads_EQ))
A->render(Args, CmdArgs);
if (Arg *A = Args.getLastArg(
options::OPT_fsanitize_undefined_strip_path_components_EQ))
A->render(Args, CmdArgs);
// -fdollars-in-identifiers default varies depending on platform and
// language; only pass if specified.
if (Arg *A = Args.getLastArg(options::OPT_fdollars_in_identifiers,
options::OPT_fno_dollars_in_identifiers)) {
if (A->getOption().matches(options::OPT_fdollars_in_identifiers))
CmdArgs.push_back("-fdollars-in-identifiers");
else
CmdArgs.push_back("-fno-dollars-in-identifiers");
}
// -funit-at-a-time is default, and we don't support -fno-unit-at-a-time for
// practical purposes.
if (Arg *A = Args.getLastArg(options::OPT_funit_at_a_time,
options::OPT_fno_unit_at_a_time)) {
if (A->getOption().matches(options::OPT_fno_unit_at_a_time))
D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args);
}
if (Args.hasFlag(options::OPT_fapple_pragma_pack,
options::OPT_fno_apple_pragma_pack, false))
CmdArgs.push_back("-fapple-pragma-pack");
if (Args.hasFlag(options::OPT_fsave_optimization_record,
options::OPT_foptimization_record_file_EQ,
options::OPT_fno_save_optimization_record, false)) {
CmdArgs.push_back("-opt-record-file");
const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
if (A) {
CmdArgs.push_back(A->getValue());
} else {
SmallString<128> F;
if (Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) {
if (Arg *FinalOutput = Args.getLastArg(options::OPT_o))
F = FinalOutput->getValue();
}
if (F.empty()) {
// Use the input filename.
F = llvm::sys::path::stem(Input.getBaseInput());
// If we're compiling for an offload architecture (i.e. a CUDA device),
// we need to make the file name for the device compilation different
// from the host compilation.
if (!JA.isDeviceOffloading(Action::OFK_None) &&
!JA.isDeviceOffloading(Action::OFK_Host)) {
llvm::sys::path::replace_extension(F, "");
F += Action::GetOffloadingFileNamePrefix(JA.getOffloadingDeviceKind(),
Triple.normalize());
F += "-";
F += JA.getOffloadingArch();
}
}
llvm::sys::path::replace_extension(F, "opt.yaml");
CmdArgs.push_back(Args.MakeArgString(F));
}
}
bool RewriteImports = Args.hasFlag(options::OPT_frewrite_imports,
options::OPT_fno_rewrite_imports, false);
if (RewriteImports)
CmdArgs.push_back("-frewrite-imports");
// Enable rewrite includes if the user's asked for it or if we're generating
// diagnostics.
// TODO: Once -module-dependency-dir works with -frewrite-includes it'd be
// nice to enable this when doing a crashdump for modules as well.
if (Args.hasFlag(options::OPT_frewrite_includes,
options::OPT_fno_rewrite_includes, false) ||
(C.isForDiagnostics() && !HaveModules))
CmdArgs.push_back("-frewrite-includes");
// Only allow -traditional or -traditional-cpp outside in preprocessing modes.
if (Arg *A = Args.getLastArg(options::OPT_traditional,
options::OPT_traditional_cpp)) {
if (isa<PreprocessJobAction>(JA))
CmdArgs.push_back("-traditional-cpp");
else
D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args);
}
Args.AddLastArg(CmdArgs, options::OPT_dM);
Args.AddLastArg(CmdArgs, options::OPT_dD);
// Handle serialized diagnostics.
if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) {
CmdArgs.push_back("-serialize-diagnostic-file");
CmdArgs.push_back(Args.MakeArgString(A->getValue()));
}
if (Args.hasArg(options::OPT_fretain_comments_from_system_headers))
CmdArgs.push_back("-fretain-comments-from-system-headers");
// Forward -fcomment-block-commands to -cc1.
Args.AddAllArgs(CmdArgs, options::OPT_fcomment_block_commands);
// Forward -fparse-all-comments to -cc1.
Args.AddAllArgs(CmdArgs, options::OPT_fparse_all_comments);
// Turn -fplugin=name.so into -load name.so
for (const Arg *A : Args.filtered(options::OPT_fplugin_EQ)) {
CmdArgs.push_back("-load");
CmdArgs.push_back(A->getValue());
A->claim();
}
// Setup statistics file output.
SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D);
if (!StatsFile.empty())
CmdArgs.push_back(Args.MakeArgString(Twine("-stats-file=") + StatsFile));
// Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
// parser.
// -finclude-default-header flag is for preprocessor,
// do not pass it to other cc1 commands when save-temps is enabled
if (C.getDriver().isSaveTempsEnabled() &&
!isa<PreprocessJobAction>(JA)) {
for (auto Arg : Args.filtered(options::OPT_Xclang)) {
Arg->claim();
if (StringRef(Arg->getValue()) != "-finclude-default-header")
CmdArgs.push_back(Arg->getValue());
}
}
else {
Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
}
for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
A->claim();
// We translate this by hand to the -cc1 argument, since nightly test uses
// it and developers have been trained to spell it with -mllvm. Both
// spellings are now deprecated and should be removed.
if (StringRef(A->getValue(0)) == "-disable-llvm-optzns") {
CmdArgs.push_back("-disable-llvm-optzns");
} else {
A->render(Args, CmdArgs);
}
}
// With -save-temps, we want to save the unoptimized bitcode output from the
// CompileJobAction, use -disable-llvm-passes to get pristine IR generated
// by the frontend.
// When -fembed-bitcode is enabled, optimized bitcode is emitted because it
// has slightly different breakdown between stages.
// FIXME: -fembed-bitcode -save-temps will save optimized bitcode instead of
// pristine IR generated by the frontend. Ideally, a new compile action should
// be added so both IR can be captured.
if (C.getDriver().isSaveTempsEnabled() &&
!(C.getDriver().embedBitcodeInObject() && !C.getDriver().isUsingLTO()) &&
isa<CompileJobAction>(JA))
CmdArgs.push_back("-disable-llvm-passes");
if (Output.getType() == types::TY_Dependencies) {
// Handled with other dependency code.
} else if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
assert(Output.isNothing() && "Invalid output.");
}
addDashXForInput(Args, Input, CmdArgs);
ArrayRef<InputInfo> FrontendInputs = Input;
if (IsHeaderModulePrecompile)
FrontendInputs = ModuleHeaderInputs;
else if (Input.isNothing())
FrontendInputs = {};
for (const InputInfo &Input : FrontendInputs) {
if (Input.isFilename())
CmdArgs.push_back(Input.getFilename());
else
Input.getInputArg().renderAsInput(Args, CmdArgs);
}
Args.AddAllArgs(CmdArgs, options::OPT_undef);
const char *Exec = D.getClangProgramPath();
// Optionally embed the -cc1 level arguments into the debug info or a
// section, for build analysis.
// Also record command line arguments into the debug info if
// -grecord-gcc-switches options is set on.
// By default, -gno-record-gcc-switches is set on and no recording.
auto GRecordSwitches =
Args.hasFlag(options::OPT_grecord_command_line,
options::OPT_gno_record_command_line, false);
auto FRecordSwitches =
Args.hasFlag(options::OPT_frecord_command_line,
options::OPT_fno_record_command_line, false);
if (FRecordSwitches && !Triple.isOSBinFormatELF())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args)
<< TripleStr;
if (TC.UseDwarfDebugFlags() || GRecordSwitches || FRecordSwitches) {
ArgStringList OriginalArgs;
for (const auto &Arg : Args)
Arg->render(Args, OriginalArgs);
SmallString<256> Flags;
Flags += Exec;
for (const char *OriginalArg : OriginalArgs) {
SmallString<128> EscapedArg;
EscapeSpacesAndBackslashes(OriginalArg, EscapedArg);
Flags += " ";
Flags += EscapedArg;
}
auto FlagsArgString = Args.MakeArgString(Flags);
if (TC.UseDwarfDebugFlags() || GRecordSwitches) {
CmdArgs.push_back("-dwarf-debug-flags");
CmdArgs.push_back(FlagsArgString);
}
if (FRecordSwitches) {
CmdArgs.push_back("-record-command-line");
CmdArgs.push_back(FlagsArgString);
}
}
// Host-side cuda compilation receives all device-side outputs in a single
// fatbin as Inputs[1]. Include the binary with -fcuda-include-gpubinary.
if ((IsCuda || IsHIP) && CudaDeviceInput) {
CmdArgs.push_back("-fcuda-include-gpubinary");
CmdArgs.push_back(CudaDeviceInput->getFilename());
if (Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false))
CmdArgs.push_back("-fgpu-rdc");
}
if (IsCuda) {
if (Args.hasFlag(options::OPT_fcuda_short_ptr,
options::OPT_fno_cuda_short_ptr, false))
CmdArgs.push_back("-fcuda-short-ptr");
}
// OpenMP offloading device jobs take the argument -fopenmp-host-ir-file-path
// to specify the result of the compile phase on the host, so the meaningful
// device declarations can be identified. Also, -fopenmp-is-device is passed
// along to tell the frontend that it is generating code for a device, so that
// only the relevant declarations are emitted.
if (IsOpenMPDevice) {
CmdArgs.push_back("-fopenmp-is-device");
if (OpenMPDeviceInput) {
CmdArgs.push_back("-fopenmp-host-ir-file-path");
CmdArgs.push_back(Args.MakeArgString(OpenMPDeviceInput->getFilename()));
}
}
// For all the host OpenMP offloading compile jobs we need to pass the targets
// information using -fopenmp-targets= option.
if (JA.isHostOffloading(Action::OFK_OpenMP)) {
SmallString<128> TargetInfo("-fopenmp-targets=");
Arg *Tgts = Args.getLastArg(options::OPT_fopenmp_targets_EQ);
assert(Tgts && Tgts->getNumValues() &&
"OpenMP offloading has to have targets specified.");
for (unsigned i = 0; i < Tgts->getNumValues(); ++i) {
if (i)
TargetInfo += ',';
// We need to get the string from the triple because it may be not exactly
// the same as the one we get directly from the arguments.
llvm::Triple T(Tgts->getValue(i));
TargetInfo += T.getTriple();
}
CmdArgs.push_back(Args.MakeArgString(TargetInfo.str()));
}
bool WholeProgramVTables =
Args.hasFlag(options::OPT_fwhole_program_vtables,
options::OPT_fno_whole_program_vtables, false);
if (WholeProgramVTables) {
if (!D.isUsingLTO())
D.Diag(diag::err_drv_argument_only_allowed_with)
<< "-fwhole-program-vtables"
<< "-flto";
CmdArgs.push_back("-fwhole-program-vtables");
}
bool RequiresSplitLTOUnit = WholeProgramVTables || Sanitize.needsLTO();
bool SplitLTOUnit =
Args.hasFlag(options::OPT_fsplit_lto_unit,
options::OPT_fno_split_lto_unit, RequiresSplitLTOUnit);
if (RequiresSplitLTOUnit && !SplitLTOUnit)
D.Diag(diag::err_drv_argument_not_allowed_with)
<< "-fno-split-lto-unit"
<< (WholeProgramVTables ? "-fwhole-program-vtables" : "-fsanitize=cfi");
if (SplitLTOUnit)
CmdArgs.push_back("-fsplit-lto-unit");
if (Arg *A = Args.getLastArg(options::OPT_fexperimental_isel,
options::OPT_fno_experimental_isel)) {
CmdArgs.push_back("-mllvm");
if (A->getOption().matches(options::OPT_fexperimental_isel)) {
CmdArgs.push_back("-global-isel=1");
// GISel is on by default on AArch64 -O0, so don't bother adding
// the fallback remarks for it. Other combinations will add a warning of
// some kind.
bool IsArchSupported = Triple.getArch() == llvm::Triple::aarch64;
bool IsOptLevelSupported = false;
Arg *A = Args.getLastArg(options::OPT_O_Group);
if (Triple.getArch() == llvm::Triple::aarch64) {
if (!A || A->getOption().matches(options::OPT_O0))
IsOptLevelSupported = true;
}
if (!IsArchSupported || !IsOptLevelSupported) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-global-isel-abort=2");
if (!IsArchSupported)
D.Diag(diag::warn_drv_experimental_isel_incomplete) << Triple.getArchName();
else
D.Diag(diag::warn_drv_experimental_isel_incomplete_opt);
}
} else {
CmdArgs.push_back("-global-isel=0");
}
}
if (Arg *A = Args.getLastArg(options::OPT_fforce_enable_int128,
options::OPT_fno_force_enable_int128)) {
if (A->getOption().matches(options::OPT_fforce_enable_int128))
CmdArgs.push_back("-fforce-enable-int128");
}
if (Args.hasFlag(options::OPT_fcomplete_member_pointers,
options::OPT_fno_complete_member_pointers, false))
CmdArgs.push_back("-fcomplete-member-pointers");
if (!Args.hasFlag(options::OPT_fcxx_static_destructors,
options::OPT_fno_cxx_static_destructors, true))
CmdArgs.push_back("-fno-c++-static-destructors");
if (Arg *A = Args.getLastArg(options::OPT_moutline,
options::OPT_mno_outline)) {
if (A->getOption().matches(options::OPT_moutline)) {
// We only support -moutline in AArch64 right now. If we're not compiling
// for AArch64, emit a warning and ignore the flag. Otherwise, add the
// proper mllvm flags.
if (Triple.getArch() != llvm::Triple::aarch64) {
D.Diag(diag::warn_drv_moutline_unsupported_opt) << Triple.getArchName();
} else {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-enable-machine-outliner");
}
} else {
// Disable all outlining behaviour.
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-enable-machine-outliner=never");
}
}
if (Args.hasFlag(options::OPT_faddrsig, options::OPT_fno_addrsig,
(TC.getTriple().isOSBinFormatELF() ||
TC.getTriple().isOSBinFormatCOFF()) &&
!TC.getTriple().isPS4() &&
!TC.getTriple().isOSNetBSD() &&
!Distro(D.getVFS()).IsGentoo() &&
!TC.getTriple().isAndroid() &&
TC.useIntegratedAs()))
CmdArgs.push_back("-faddrsig");
// Finally add the compile command to the compilation.
if (Args.hasArg(options::OPT__SLASH_fallback) &&
Output.getType() == types::TY_Object &&
(InputType == types::TY_C || InputType == types::TY_CXX)) {
auto CLCommand =
getCLFallback()->GetCommand(C, JA, Output, Inputs, Args, LinkingOutput);
C.addCommand(llvm::make_unique<FallbackCommand>(
JA, *this, Exec, CmdArgs, Inputs, std::move(CLCommand)));
} else if (Args.hasArg(options::OPT__SLASH_fallback) &&
isa<PrecompileJobAction>(JA)) {
// In /fallback builds, run the main compilation even if the pch generation
// fails, so that the main compilation's fallback to cl.exe runs.
C.addCommand(llvm::make_unique<ForceSuccessCommand>(JA, *this, Exec,
CmdArgs, Inputs));
} else {
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
// Make the compile command echo its inputs for /showFilenames.
if (Output.getType() == types::TY_Object &&
Args.hasFlag(options::OPT__SLASH_showFilenames,
options::OPT__SLASH_showFilenames_, false)) {
C.getJobs().getJobs().back()->setPrintInputFilenames(true);
}
if (Arg *A = Args.getLastArg(options::OPT_pg))
if (!shouldUseFramePointer(Args, Triple))
D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer"
<< A->getAsString(Args);
// Claim some arguments which clang supports automatically.
// -fpch-preprocess is used with gcc to add a special marker in the output to
// include the PCH file.
Args.ClaimAllArgs(options::OPT_fpch_preprocess);
// Claim some arguments which clang doesn't support, but we don't
// care to warn the user about.
Args.ClaimAllArgs(options::OPT_clang_ignored_f_Group);
Args.ClaimAllArgs(options::OPT_clang_ignored_m_Group);
// Disable warnings for clang -E -emit-llvm foo.c
Args.ClaimAllArgs(options::OPT_emit_llvm);
}
Clang::Clang(const ToolChain &TC)
// CAUTION! The first constructor argument ("clang") is not arbitrary,
// as it is for other tools. Some operations on a Tool actually test
// whether that tool is Clang based on the Tool's Name as a string.
: Tool("clang", "clang frontend", TC, RF_Full) {}
Clang::~Clang() {}
/// Add options related to the Objective-C runtime/ABI.
///
/// Returns true if the runtime is non-fragile.
ObjCRuntime Clang::AddObjCRuntimeArgs(const ArgList &args,
ArgStringList &cmdArgs,
RewriteKind rewriteKind) const {
// Look for the controlling runtime option.
Arg *runtimeArg =
args.getLastArg(options::OPT_fnext_runtime, options::OPT_fgnu_runtime,
options::OPT_fobjc_runtime_EQ);
// Just forward -fobjc-runtime= to the frontend. This supercedes
// options about fragility.
if (runtimeArg &&
runtimeArg->getOption().matches(options::OPT_fobjc_runtime_EQ)) {
ObjCRuntime runtime;
StringRef value = runtimeArg->getValue();
if (runtime.tryParse(value)) {
getToolChain().getDriver().Diag(diag::err_drv_unknown_objc_runtime)
<< value;
}
if ((runtime.getKind() == ObjCRuntime::GNUstep) &&
(runtime.getVersion() >= VersionTuple(2, 0)))
if (!getToolChain().getTriple().isOSBinFormatELF() &&
!getToolChain().getTriple().isOSBinFormatCOFF()) {
getToolChain().getDriver().Diag(
diag::err_drv_gnustep_objc_runtime_incompatible_binary)
<< runtime.getVersion().getMajor();
}
runtimeArg->render(args, cmdArgs);
return runtime;
}
// Otherwise, we'll need the ABI "version". Version numbers are
// slightly confusing for historical reasons:
// 1 - Traditional "fragile" ABI
// 2 - Non-fragile ABI, version 1
// 3 - Non-fragile ABI, version 2
unsigned objcABIVersion = 1;
// If -fobjc-abi-version= is present, use that to set the version.
if (Arg *abiArg = args.getLastArg(options::OPT_fobjc_abi_version_EQ)) {
StringRef value = abiArg->getValue();
if (value == "1")
objcABIVersion = 1;
else if (value == "2")
objcABIVersion = 2;
else if (value == "3")
objcABIVersion = 3;
else
getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported) << value;
} else {
// Otherwise, determine if we are using the non-fragile ABI.
bool nonFragileABIIsDefault =
(rewriteKind == RK_NonFragile ||
(rewriteKind == RK_None &&
getToolChain().IsObjCNonFragileABIDefault()));
if (args.hasFlag(options::OPT_fobjc_nonfragile_abi,
options::OPT_fno_objc_nonfragile_abi,
nonFragileABIIsDefault)) {
// Determine the non-fragile ABI version to use.
#ifdef DISABLE_DEFAULT_NONFRAGILEABI_TWO
unsigned nonFragileABIVersion = 1;
#else
unsigned nonFragileABIVersion = 2;
#endif
if (Arg *abiArg =
args.getLastArg(options::OPT_fobjc_nonfragile_abi_version_EQ)) {
StringRef value = abiArg->getValue();
if (value == "1")
nonFragileABIVersion = 1;
else if (value == "2")
nonFragileABIVersion = 2;
else
getToolChain().getDriver().Diag(diag::err_drv_clang_unsupported)
<< value;
}
objcABIVersion = 1 + nonFragileABIVersion;
} else {
objcABIVersion = 1;
}
}
// We don't actually care about the ABI version other than whether
// it's non-fragile.
bool isNonFragile = objcABIVersion != 1;
// If we have no runtime argument, ask the toolchain for its default runtime.
// However, the rewriter only really supports the Mac runtime, so assume that.
ObjCRuntime runtime;
if (!runtimeArg) {
switch (rewriteKind) {
case RK_None:
runtime = getToolChain().getDefaultObjCRuntime(isNonFragile);
break;
case RK_Fragile:
runtime = ObjCRuntime(ObjCRuntime::FragileMacOSX, VersionTuple());
break;
case RK_NonFragile:
runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple());
break;
}
// -fnext-runtime
} else if (runtimeArg->getOption().matches(options::OPT_fnext_runtime)) {
// On Darwin, make this use the default behavior for the toolchain.
if (getToolChain().getTriple().isOSDarwin()) {
runtime = getToolChain().getDefaultObjCRuntime(isNonFragile);
// Otherwise, build for a generic macosx port.
} else {
runtime = ObjCRuntime(ObjCRuntime::MacOSX, VersionTuple());
}
// -fgnu-runtime
} else {
assert(runtimeArg->getOption().matches(options::OPT_fgnu_runtime));
// Legacy behaviour is to target the gnustep runtime if we are in
// non-fragile mode or the GCC runtime in fragile mode.
if (isNonFragile)
runtime = ObjCRuntime(ObjCRuntime::GNUstep, VersionTuple(2, 0));
else
runtime = ObjCRuntime(ObjCRuntime::GCC, VersionTuple());
}
cmdArgs.push_back(
args.MakeArgString("-fobjc-runtime=" + runtime.getAsString()));
return runtime;
}
static bool maybeConsumeDash(const std::string &EH, size_t &I) {
bool HaveDash = (I + 1 < EH.size() && EH[I + 1] == '-');
I += HaveDash;
return !HaveDash;
}
namespace {
struct EHFlags {
bool Synch = false;
bool Asynch = false;
bool NoUnwindC = false;
};
} // end anonymous namespace
/// /EH controls whether to run destructor cleanups when exceptions are
/// thrown. There are three modifiers:
/// - s: Cleanup after "synchronous" exceptions, aka C++ exceptions.
/// - a: Cleanup after "asynchronous" exceptions, aka structured exceptions.
/// The 'a' modifier is unimplemented and fundamentally hard in LLVM IR.
/// - c: Assume that extern "C" functions are implicitly nounwind.
/// The default is /EHs-c-, meaning cleanups are disabled.
static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) {
EHFlags EH;
std::vector<std::string> EHArgs =
Args.getAllArgValues(options::OPT__SLASH_EH);
for (auto EHVal : EHArgs) {
for (size_t I = 0, E = EHVal.size(); I != E; ++I) {
switch (EHVal[I]) {
case 'a':
EH.Asynch = maybeConsumeDash(EHVal, I);
if (EH.Asynch)
EH.Synch = false;
continue;
case 'c':
EH.NoUnwindC = maybeConsumeDash(EHVal, I);
continue;
case 's':
EH.Synch = maybeConsumeDash(EHVal, I);
if (EH.Synch)
EH.Asynch = false;
continue;
default:
break;
}
D.Diag(clang::diag::err_drv_invalid_value) << "/EH" << EHVal;
break;
}
}
// The /GX, /GX- flags are only processed if there are not /EH flags.
// The default is that /GX is not specified.
if (EHArgs.empty() &&
Args.hasFlag(options::OPT__SLASH_GX, options::OPT__SLASH_GX_,
/*default=*/false)) {
EH.Synch = true;
EH.NoUnwindC = true;
}
return EH;
}
void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
ArgStringList &CmdArgs,
codegenoptions::DebugInfoKind *DebugInfoKind,
bool *EmitCodeView) const {
unsigned RTOptionID = options::OPT__SLASH_MT;
if (Args.hasArg(options::OPT__SLASH_LDd))
// The /LDd option implies /MTd. The dependent lib part can be overridden,
// but defining _DEBUG is sticky.
RTOptionID = options::OPT__SLASH_MTd;
if (Arg *A = Args.getLastArg(options::OPT__SLASH_M_Group))
RTOptionID = A->getOption().getID();
StringRef FlagForCRT;
switch (RTOptionID) {
case options::OPT__SLASH_MD:
if (Args.hasArg(options::OPT__SLASH_LDd))
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
CmdArgs.push_back("-D_DLL");
FlagForCRT = "--dependent-lib=msvcrt";
break;
case options::OPT__SLASH_MDd:
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
CmdArgs.push_back("-D_DLL");
FlagForCRT = "--dependent-lib=msvcrtd";
break;
case options::OPT__SLASH_MT:
if (Args.hasArg(options::OPT__SLASH_LDd))
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
CmdArgs.push_back("-flto-visibility-public-std");
FlagForCRT = "--dependent-lib=libcmt";
break;
case options::OPT__SLASH_MTd:
CmdArgs.push_back("-D_DEBUG");
CmdArgs.push_back("-D_MT");
CmdArgs.push_back("-flto-visibility-public-std");
FlagForCRT = "--dependent-lib=libcmtd";
break;
default:
llvm_unreachable("Unexpected option ID.");
}
if (Args.hasArg(options::OPT__SLASH_Zl)) {
CmdArgs.push_back("-D_VC_NODEFAULTLIB");
} else {
CmdArgs.push_back(FlagForCRT.data());
// This provides POSIX compatibility (maps 'open' to '_open'), which most
// users want. The /Za flag to cl.exe turns this off, but it's not
// implemented in clang.
CmdArgs.push_back("--dependent-lib=oldnames");
}
if (Arg *A = Args.getLastArg(options::OPT_show_includes))
A->render(Args, CmdArgs);
// This controls whether or not we emit RTTI data for polymorphic types.
if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR,
/*default=*/false))
CmdArgs.push_back("-fno-rtti-data");
// This controls whether or not we emit stack-protector instrumentation.
// In MSVC, Buffer Security Check (/GS) is on by default.
if (Args.hasFlag(options::OPT__SLASH_GS, options::OPT__SLASH_GS_,
/*default=*/true)) {
CmdArgs.push_back("-stack-protector");
CmdArgs.push_back(Args.MakeArgString(Twine(LangOptions::SSPStrong)));
}
// Emit CodeView if -Z7, -Zd, or -gline-tables-only are present.
if (Arg *DebugInfoArg =
Args.getLastArg(options::OPT__SLASH_Z7, options::OPT__SLASH_Zd,
options::OPT_gline_tables_only)) {
*EmitCodeView = true;
if (DebugInfoArg->getOption().matches(options::OPT__SLASH_Z7))
*DebugInfoKind = codegenoptions::LimitedDebugInfo;
else
*DebugInfoKind = codegenoptions::DebugLineTablesOnly;
} else {
*EmitCodeView = false;
}
const Driver &D = getToolChain().getDriver();
EHFlags EH = parseClangCLEHFlags(D, Args);
if (EH.Synch || EH.Asynch) {
if (types::isCXX(InputType))
CmdArgs.push_back("-fcxx-exceptions");
CmdArgs.push_back("-fexceptions");
}
if (types::isCXX(InputType) && EH.Synch && EH.NoUnwindC)
CmdArgs.push_back("-fexternc-nounwind");
// /EP should expand to -E -P.
if (Args.hasArg(options::OPT__SLASH_EP)) {
CmdArgs.push_back("-E");
CmdArgs.push_back("-P");
}
unsigned VolatileOptionID;
if (getToolChain().getArch() == llvm::Triple::x86_64 ||
getToolChain().getArch() == llvm::Triple::x86)
VolatileOptionID = options::OPT__SLASH_volatile_ms;
else
VolatileOptionID = options::OPT__SLASH_volatile_iso;
if (Arg *A = Args.getLastArg(options::OPT__SLASH_volatile_Group))
VolatileOptionID = A->getOption().getID();
if (VolatileOptionID == options::OPT__SLASH_volatile_ms)
CmdArgs.push_back("-fms-volatile");
if (Args.hasFlag(options::OPT__SLASH_Zc_dllexportInlines_,
options::OPT__SLASH_Zc_dllexportInlines,
false)) {
if (Args.hasArg(options::OPT__SLASH_fallback)) {
D.Diag(clang::diag::err_drv_dllexport_inlines_and_fallback);
} else {
CmdArgs.push_back("-fno-dllexport-inlines");
}
}
Arg *MostGeneralArg = Args.getLastArg(options::OPT__SLASH_vmg);
Arg *BestCaseArg = Args.getLastArg(options::OPT__SLASH_vmb);
if (MostGeneralArg && BestCaseArg)
D.Diag(clang::diag::err_drv_argument_not_allowed_with)
<< MostGeneralArg->getAsString(Args) << BestCaseArg->getAsString(Args);
if (MostGeneralArg) {
Arg *SingleArg = Args.getLastArg(options::OPT__SLASH_vms);
Arg *MultipleArg = Args.getLastArg(options::OPT__SLASH_vmm);
Arg *VirtualArg = Args.getLastArg(options::OPT__SLASH_vmv);
Arg *FirstConflict = SingleArg ? SingleArg : MultipleArg;
Arg *SecondConflict = VirtualArg ? VirtualArg : MultipleArg;
if (FirstConflict && SecondConflict && FirstConflict != SecondConflict)
D.Diag(clang::diag::err_drv_argument_not_allowed_with)
<< FirstConflict->getAsString(Args)
<< SecondConflict->getAsString(Args);
if (SingleArg)
CmdArgs.push_back("-fms-memptr-rep=single");
else if (MultipleArg)
CmdArgs.push_back("-fms-memptr-rep=multiple");
else
CmdArgs.push_back("-fms-memptr-rep=virtual");
}
// Parse the default calling convention options.
if (Arg *CCArg =
Args.getLastArg(options::OPT__SLASH_Gd, options::OPT__SLASH_Gr,
options::OPT__SLASH_Gz, options::OPT__SLASH_Gv,
options::OPT__SLASH_Gregcall)) {
unsigned DCCOptId = CCArg->getOption().getID();
const char *DCCFlag = nullptr;
bool ArchSupported = true;
llvm::Triple::ArchType Arch = getToolChain().getArch();
switch (DCCOptId) {
case options::OPT__SLASH_Gd:
DCCFlag = "-fdefault-calling-conv=cdecl";
break;
case options::OPT__SLASH_Gr:
ArchSupported = Arch == llvm::Triple::x86;
DCCFlag = "-fdefault-calling-conv=fastcall";
break;
case options::OPT__SLASH_Gz:
ArchSupported = Arch == llvm::Triple::x86;
DCCFlag = "-fdefault-calling-conv=stdcall";
break;
case options::OPT__SLASH_Gv:
ArchSupported = Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64;
DCCFlag = "-fdefault-calling-conv=vectorcall";
break;
case options::OPT__SLASH_Gregcall:
ArchSupported = Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64;
DCCFlag = "-fdefault-calling-conv=regcall";
break;
}
// MSVC doesn't warn if /Gr or /Gz is used on x64, so we don't either.
if (ArchSupported && DCCFlag)
CmdArgs.push_back(DCCFlag);
}
if (Arg *A = Args.getLastArg(options::OPT_vtordisp_mode_EQ))
A->render(Args, CmdArgs);
if (!Args.hasArg(options::OPT_fdiagnostics_format_EQ)) {
CmdArgs.push_back("-fdiagnostics-format");
if (Args.hasArg(options::OPT__SLASH_fallback))
CmdArgs.push_back("msvc-fallback");
else
CmdArgs.push_back("msvc");
}
if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
SmallVector<StringRef, 1> SplitArgs;
StringRef(A->getValue()).split(SplitArgs, ",");
bool Instrument = false;
bool NoChecks = false;
for (StringRef Arg : SplitArgs) {
if (Arg.equals_lower("cf"))
Instrument = true;
else if (Arg.equals_lower("cf-"))
Instrument = false;
else if (Arg.equals_lower("nochecks"))
NoChecks = true;
else if (Arg.equals_lower("nochecks-"))
NoChecks = false;
else
D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << Arg;
}
// Currently there's no support emitting CFG instrumentation; the flag only
// emits the table of address-taken functions.
if (Instrument || NoChecks)
CmdArgs.push_back("-cfguard");
}
}
visualstudio::Compiler *Clang::getCLFallback() const {
if (!CLFallback)
CLFallback.reset(new visualstudio::Compiler(getToolChain()));
return CLFallback.get();
}
const char *Clang::getBaseInputName(const ArgList &Args,
const InputInfo &Input) {
return Args.MakeArgString(llvm::sys::path::filename(Input.getBaseInput()));
}
const char *Clang::getBaseInputStem(const ArgList &Args,
const InputInfoList &Inputs) {
const char *Str = getBaseInputName(Args, Inputs[0]);
if (const char *End = strrchr(Str, '.'))
return Args.MakeArgString(std::string(Str, End));
return Str;
}
const char *Clang::getDependencyFileName(const ArgList &Args,
const InputInfoList &Inputs) {
// FIXME: Think about this more.
std::string Res;
if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
std::string Str(OutputOpt->getValue());
Res = Str.substr(0, Str.rfind('.'));
} else {
Res = getBaseInputStem(Args, Inputs);
}
return Args.MakeArgString(Res + ".d");
}
// Begin ClangAs
void ClangAs::AddMIPSTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
StringRef CPUName;
StringRef ABIName;
const llvm::Triple &Triple = getToolChain().getTriple();
mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName.data());
}
void ClangAs::AddX86TargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {
StringRef Value = A->getValue();
if (Value == "intel" || Value == "att") {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
} else {
getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Value;
}
}
}
void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
assert(Inputs.size() == 1 && "Unexpected number of inputs.");
const InputInfo &Input = Inputs[0];
const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
const std::string &TripleStr = Triple.getTriple();
const auto &D = getToolChain().getDriver();
// Don't warn about "clang -w -c foo.s"
Args.ClaimAllArgs(options::OPT_w);
// and "clang -emit-llvm -c foo.s"
Args.ClaimAllArgs(options::OPT_emit_llvm);
claimNoWarnArgs(Args);
// Invoke ourselves in -cc1as mode.
//
// FIXME: Implement custom jobs for internal actions.
CmdArgs.push_back("-cc1as");
// Add the "effective" target triple.
CmdArgs.push_back("-triple");
CmdArgs.push_back(Args.MakeArgString(TripleStr));
// Set the output mode, we currently only expect to be used as a real
// assembler.
CmdArgs.push_back("-filetype");
CmdArgs.push_back("obj");
// Set the main file name, so that debug info works even with
// -save-temps or preprocessed assembly.
CmdArgs.push_back("-main-file-name");
CmdArgs.push_back(Clang::getBaseInputName(Args, Input));
// Add the target cpu
std::string CPU = getCPUName(Args, Triple, /*FromAs*/ true);
if (!CPU.empty()) {
CmdArgs.push_back("-target-cpu");
CmdArgs.push_back(Args.MakeArgString(CPU));
}
// Add the target features
getTargetFeatures(getToolChain(), Triple, Args, CmdArgs, true);
// Ignore explicit -force_cpusubtype_ALL option.
(void)Args.hasArg(options::OPT_force__cpusubtype__ALL);
// Pass along any -I options so we get proper .include search paths.
Args.AddAllArgs(CmdArgs, options::OPT_I_Group);
// Determine the original source input.
const Action *SourceAction = &JA;
while (SourceAction->getKind() != Action::InputClass) {
assert(!SourceAction->getInputs().empty() && "unexpected root action!");
SourceAction = SourceAction->getInputs()[0];
}
// Forward -g and handle debug info related flags, assuming we are dealing
// with an actual assembly file.
bool WantDebug = false;
unsigned DwarfVersion = 0;
Args.ClaimAllArgs(options::OPT_g_Group);
if (Arg *A = Args.getLastArg(options::OPT_g_Group)) {
WantDebug = !A->getOption().matches(options::OPT_g0) &&
!A->getOption().matches(options::OPT_ggdb0);
if (WantDebug)
DwarfVersion = DwarfVersionNum(A->getSpelling());
}
if (DwarfVersion == 0)
DwarfVersion = getToolChain().GetDefaultDwarfVersion();
codegenoptions::DebugInfoKind DebugInfoKind = codegenoptions::NoDebugInfo;
if (SourceAction->getType() == types::TY_Asm ||
SourceAction->getType() == types::TY_PP_Asm) {
// You might think that it would be ok to set DebugInfoKind outside of
// the guard for source type, however there is a test which asserts
// that some assembler invocation receives no -debug-info-kind,
// and it's not clear whether that test is just overly restrictive.
DebugInfoKind = (WantDebug ? codegenoptions::LimitedDebugInfo
: codegenoptions::NoDebugInfo);
// Add the -fdebug-compilation-dir flag if needed.
addDebugCompDirArg(Args, CmdArgs);
addDebugPrefixMapArg(getToolChain().getDriver(), Args, CmdArgs);
// Set the AT_producer to the clang version when using the integrated
// assembler on assembly source files.
CmdArgs.push_back("-dwarf-debug-producer");
CmdArgs.push_back(Args.MakeArgString(getClangFullVersion()));
// And pass along -I options
Args.AddAllArgs(CmdArgs, options::OPT_I);
}
RenderDebugEnablingArgs(Args, CmdArgs, DebugInfoKind, DwarfVersion,
llvm::DebuggerKind::Default);
RenderDebugInfoCompressionArgs(Args, CmdArgs, D, getToolChain());
// Handle -fPIC et al -- the relocation-model affects the assembler
// for some targets.
llvm::Reloc::Model RelocationModel;
unsigned PICLevel;
bool IsPIE;
std::tie(RelocationModel, PICLevel, IsPIE) =
ParsePICArgs(getToolChain(), Args);
const char *RMName = RelocationModelName(RelocationModel);
if (RMName) {
CmdArgs.push_back("-mrelocation-model");
CmdArgs.push_back(RMName);
}
// Optionally embed the -cc1as level arguments into the debug info, for build
// analysis.
if (getToolChain().UseDwarfDebugFlags()) {
ArgStringList OriginalArgs;
for (const auto &Arg : Args)
Arg->render(Args, OriginalArgs);
SmallString<256> Flags;
const char *Exec = getToolChain().getDriver().getClangProgramPath();
Flags += Exec;
for (const char *OriginalArg : OriginalArgs) {
SmallString<128> EscapedArg;
EscapeSpacesAndBackslashes(OriginalArg, EscapedArg);
Flags += " ";
Flags += EscapedArg;
}
CmdArgs.push_back("-dwarf-debug-flags");
CmdArgs.push_back(Args.MakeArgString(Flags));
}
// FIXME: Add -static support, once we have it.
// Add target specific flags.
switch (getToolChain().getArch()) {
default:
break;
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
AddMIPSTargetArgs(Args, CmdArgs);
break;
case llvm::Triple::x86:
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
// gracefully by -cc1 (warning about unknown warning flags, etc) but -cc1as
// doesn't handle that so rather than warning about unused flags that are
// actually used, we'll lie by omission instead.
// FIXME: Stop lying and consume only the appropriate driver flags
Args.ClaimAllArgs(options::OPT_W_Group);
CollectArgsForIntegratedAssembler(C, Args, CmdArgs,
getToolChain().getDriver());
Args.AddAllArgs(CmdArgs, options::OPT_mllvm);
assert(Output.isFilename() && "Unexpected lipo output.");
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
const llvm::Triple &T = getToolChain().getTriple();
Arg *A;
if ((getDebugFissionKind(D, Args, A) == DwarfFissionKind::Split) &&
(T.isOSLinux() || T.isOSFuchsia())) {
CmdArgs.push_back("-split-dwarf-file");
CmdArgs.push_back(SplitDebugName(Args, Output));
}
assert(Input.isFilename() && "Invalid input.");
CmdArgs.push_back(Input.getFilename());
const char *Exec = getToolChain().getDriver().getClangProgramPath();
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
// Begin OffloadBundler
void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const {
// The version with only one output is expected to refer to a bundling job.
assert(isa<OffloadBundlingJobAction>(JA) && "Expecting bundling job!");
// The bundling command looks like this:
// clang-offload-bundler -type=bc
// -targets=host-triple,openmp-triple1,openmp-triple2
// -outputs=input_file
// -inputs=unbundle_file_host,unbundle_file_tgt1,unbundle_file_tgt2"
ArgStringList CmdArgs;
// Get the type.
CmdArgs.push_back(TCArgs.MakeArgString(
Twine("-type=") + types::getTypeTempSuffix(Output.getType())));
assert(JA.getInputs().size() == Inputs.size() &&
"Not have inputs for all dependence actions??");
// Get the targets.
SmallString<128> Triples;
Triples += "-targets=";
for (unsigned I = 0; I < Inputs.size(); ++I) {
if (I)
Triples += ',';
// Find ToolChain for this input.
Action::OffloadKind CurKind = Action::OFK_Host;
const ToolChain *CurTC = &getToolChain();
const Action *CurDep = JA.getInputs()[I];
if (const auto *OA = dyn_cast<OffloadAction>(CurDep)) {
CurTC = nullptr;
OA->doOnEachDependence([&](Action *A, const ToolChain *TC, const char *) {
assert(CurTC == nullptr && "Expected one dependence!");
CurKind = A->getOffloadingDeviceKind();
CurTC = TC;
});
}
Triples += Action::GetOffloadKindName(CurKind);
Triples += '-';
Triples += CurTC->getTriple().normalize();
if (CurKind == Action::OFK_HIP && CurDep->getOffloadingArch()) {
Triples += '-';
Triples += CurDep->getOffloadingArch();
}
}
CmdArgs.push_back(TCArgs.MakeArgString(Triples));
// Get bundled file command.
CmdArgs.push_back(
TCArgs.MakeArgString(Twine("-outputs=") + Output.getFilename()));
// Get unbundled files command.
SmallString<128> UB;
UB += "-inputs=";
for (unsigned I = 0; I < Inputs.size(); ++I) {
if (I)
UB += ',';
// Find ToolChain for this input.
const ToolChain *CurTC = &getToolChain();
if (const auto *OA = dyn_cast<OffloadAction>(JA.getInputs()[I])) {
CurTC = nullptr;
OA->doOnEachDependence([&](Action *, const ToolChain *TC, const char *) {
assert(CurTC == nullptr && "Expected one dependence!");
CurTC = TC;
});
}
UB += CurTC->getInputFilename(Inputs[I]);
}
CmdArgs.push_back(TCArgs.MakeArgString(UB));
// All the inputs are encoded as commands.
C.addCommand(llvm::make_unique<Command>(
JA, *this,
TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
CmdArgs, None));
}
void OffloadBundler::ConstructJobMultipleOutputs(
Compilation &C, const JobAction &JA, const InputInfoList &Outputs,
const InputInfoList &Inputs, const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const {
// The version with multiple outputs is expected to refer to a unbundling job.
auto &UA = cast<OffloadUnbundlingJobAction>(JA);
// The unbundling command looks like this:
// clang-offload-bundler -type=bc
// -targets=host-triple,openmp-triple1,openmp-triple2
// -inputs=input_file
// -outputs=unbundle_file_host,unbundle_file_tgt1,unbundle_file_tgt2"
// -unbundle
ArgStringList CmdArgs;
assert(Inputs.size() == 1 && "Expecting to unbundle a single file!");
InputInfo Input = Inputs.front();
// Get the type.
CmdArgs.push_back(TCArgs.MakeArgString(
Twine("-type=") + types::getTypeTempSuffix(Input.getType())));
// Get the targets.
SmallString<128> Triples;
Triples += "-targets=";
auto DepInfo = UA.getDependentActionsInfo();
for (unsigned I = 0; I < DepInfo.size(); ++I) {
if (I)
Triples += ',';
auto &Dep = DepInfo[I];
Triples += Action::GetOffloadKindName(Dep.DependentOffloadKind);
Triples += '-';
Triples += Dep.DependentToolChain->getTriple().normalize();
if (Dep.DependentOffloadKind == Action::OFK_HIP &&
!Dep.DependentBoundArch.empty()) {
Triples += '-';
Triples += Dep.DependentBoundArch;
}
}
CmdArgs.push_back(TCArgs.MakeArgString(Triples));
// Get bundled file command.
CmdArgs.push_back(
TCArgs.MakeArgString(Twine("-inputs=") + Input.getFilename()));
// Get unbundled files command.
SmallString<128> UB;
UB += "-outputs=";
for (unsigned I = 0; I < Outputs.size(); ++I) {
if (I)
UB += ',';
UB += DepInfo[I].DependentToolChain->getInputFilename(Outputs[I]);
}
CmdArgs.push_back(TCArgs.MakeArgString(UB));
CmdArgs.push_back("-unbundle");
// All the inputs are encoded as commands.
C.addCommand(llvm::make_unique<Command>(
JA, *this,
TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())),
CmdArgs, None));
}
Index: vendor/clang/dist-release_80/lib/Driver/ToolChains/NetBSD.cpp
===================================================================
--- vendor/clang/dist-release_80/lib/Driver/ToolChains/NetBSD.cpp (revision 343795)
+++ vendor/clang/dist-release_80/lib/Driver/ToolChains/NetBSD.cpp (revision 343796)
@@ -1,471 +1,478 @@
//===--- NetBSD.cpp - NetBSD ToolChain Implementations ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "NetBSD.h"
#include "Arch/ARM.h"
#include "Arch/Mips.h"
#include "Arch/Sparc.h"
#include "CommonArgs.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;
void netbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
claimNoWarnArgs(Args);
ArgStringList CmdArgs;
// GNU as needs different flags for creating the correct output format
// on architectures with different ABIs or optional feature sets.
switch (getToolChain().getArch()) {
case llvm::Triple::x86:
CmdArgs.push_back("--32");
break;
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb: {
StringRef MArch, MCPU;
arm::getARMArchCPUFromArgs(Args, MArch, MCPU, /*FromAs*/ true);
std::string Arch =
arm::getARMTargetCPU(MCPU, MArch, getToolChain().getTriple());
CmdArgs.push_back(Args.MakeArgString("-mcpu=" + Arch));
break;
}
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el: {
StringRef CPUName;
StringRef ABIName;
mips::getMipsCPUAndABI(Args, getToolChain().getTriple(), CPUName, ABIName);
CmdArgs.push_back("-march");
CmdArgs.push_back(CPUName.data());
CmdArgs.push_back("-mabi");
CmdArgs.push_back(mips::getGnuCompatibleMipsABIName(ABIName).data());
if (getToolChain().getTriple().isLittleEndian())
CmdArgs.push_back("-EL");
else
CmdArgs.push_back("-EB");
AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
}
case llvm::Triple::sparc:
case llvm::Triple::sparcel: {
CmdArgs.push_back("-32");
std::string CPU = getCPUName(Args, getToolChain().getTriple());
CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
}
case llvm::Triple::sparcv9: {
CmdArgs.push_back("-64");
std::string CPU = getCPUName(Args, getToolChain().getTriple());
CmdArgs.push_back(sparc::getSparcAsmModeForCPU(CPU, getToolChain().getTriple()));
AddAssemblerKPIC(getToolChain(), Args, CmdArgs);
break;
}
default:
break;
}
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
for (const auto &II : Inputs)
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as")));
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
const toolchains::NetBSD &ToolChain =
static_cast<const toolchains::NetBSD &>(getToolChain());
const Driver &D = ToolChain.getDriver();
ArgStringList CmdArgs;
if (!D.SysRoot.empty())
CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
CmdArgs.push_back("--eh-frame-hdr");
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-Bstatic");
if (Args.hasArg(options::OPT_pie)) {
Args.AddAllArgs(CmdArgs, options::OPT_pie);
CmdArgs.push_back("--no-dynamic-linker");
}
} else {
if (Args.hasArg(options::OPT_rdynamic))
CmdArgs.push_back("-export-dynamic");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-Bshareable");
} else {
Args.AddAllArgs(CmdArgs, options::OPT_pie);
CmdArgs.push_back("-dynamic-linker");
CmdArgs.push_back("/libexec/ld.elf_so");
}
}
// Many NetBSD architectures support more than one ABI.
// Determine the correct emulation for ld.
switch (ToolChain.getArch()) {
case llvm::Triple::x86:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf_i386");
break;
case llvm::Triple::arm:
case llvm::Triple::thumb:
CmdArgs.push_back("-m");
switch (ToolChain.getTriple().getEnvironment()) {
case llvm::Triple::EABI:
case llvm::Triple::GNUEABI:
CmdArgs.push_back("armelf_nbsd_eabi");
break;
case llvm::Triple::EABIHF:
case llvm::Triple::GNUEABIHF:
CmdArgs.push_back("armelf_nbsd_eabihf");
break;
default:
CmdArgs.push_back("armelf_nbsd");
break;
}
break;
case llvm::Triple::armeb:
case llvm::Triple::thumbeb:
arm::appendBE8LinkFlag(Args, CmdArgs, ToolChain.getEffectiveTriple());
CmdArgs.push_back("-m");
switch (ToolChain.getTriple().getEnvironment()) {
case llvm::Triple::EABI:
case llvm::Triple::GNUEABI:
CmdArgs.push_back("armelfb_nbsd_eabi");
break;
case llvm::Triple::EABIHF:
case llvm::Triple::GNUEABIHF:
CmdArgs.push_back("armelfb_nbsd_eabihf");
break;
default:
CmdArgs.push_back("armelfb_nbsd");
break;
}
break;
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
if (mips::hasMipsAbiArg(Args, "32")) {
CmdArgs.push_back("-m");
if (ToolChain.getArch() == llvm::Triple::mips64)
CmdArgs.push_back("elf32btsmip");
else
CmdArgs.push_back("elf32ltsmip");
} else if (mips::hasMipsAbiArg(Args, "64")) {
CmdArgs.push_back("-m");
if (ToolChain.getArch() == llvm::Triple::mips64)
CmdArgs.push_back("elf64btsmip");
else
CmdArgs.push_back("elf64ltsmip");
}
break;
case llvm::Triple::ppc:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf32ppc_nbsd");
break;
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf64ppc");
break;
case llvm::Triple::sparc:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf32_sparc");
break;
case llvm::Triple::sparcv9:
CmdArgs.push_back("-m");
CmdArgs.push_back("elf64_sparc");
break;
default:
break;
}
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
} else {
assert(Output.isNothing() && "Invalid output.");
}
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back(
Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
}
CmdArgs.push_back(
Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie)) {
CmdArgs.push_back(
Args.MakeArgString(ToolChain.GetFilePath("crtbeginS.o")));
} else {
CmdArgs.push_back(
Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
}
}
Args.AddAllArgs(CmdArgs, options::OPT_L);
Args.AddAllArgs(CmdArgs, options::OPT_T_Group);
Args.AddAllArgs(CmdArgs, options::OPT_e);
Args.AddAllArgs(CmdArgs, options::OPT_s);
Args.AddAllArgs(CmdArgs, options::OPT_t);
Args.AddAllArgs(CmdArgs, options::OPT_Z_Flag);
Args.AddAllArgs(CmdArgs, options::OPT_r);
bool NeedsSanitizerDeps = addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
bool NeedsXRayDeps = addXRayRuntime(ToolChain, Args, CmdArgs);
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
+ const SanitizerArgs &SanArgs = ToolChain.getSanitizerArgs();
+ if (SanArgs.needsSharedRt()) {
+ CmdArgs.push_back("-rpath");
+ CmdArgs.push_back(Args.MakeArgString(
+ ToolChain.getCompilerRTPath().c_str()));
+ }
+
unsigned Major, Minor, Micro;
ToolChain.getTriple().getOSVersion(Major, Minor, Micro);
bool useLibgcc = true;
if (Major >= 7 || Major == 0) {
switch (ToolChain.getArch()) {
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
case llvm::Triple::sparc:
case llvm::Triple::sparcv9:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
useLibgcc = false;
break;
default:
break;
}
}
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
addOpenMPRuntime(CmdArgs, getToolChain(), Args);
if (D.CCCIsCXX()) {
if (ToolChain.ShouldLinkCXXStdlib(Args))
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
}
if (NeedsSanitizerDeps)
linkSanitizerRuntimeDeps(getToolChain(), CmdArgs);
if (NeedsXRayDeps)
linkXRayRuntimeDeps(ToolChain, CmdArgs);
if (Args.hasArg(options::OPT_pthread))
CmdArgs.push_back("-lpthread");
CmdArgs.push_back("-lc");
if (useLibgcc) {
if (Args.hasArg(options::OPT_static)) {
// libgcc_eh depends on libc, so resolve as much as possible,
// pull in any new requirements from libc and then get the rest
// of libgcc.
CmdArgs.push_back("-lgcc_eh");
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lgcc");
} else {
CmdArgs.push_back("-lgcc");
CmdArgs.push_back("--as-needed");
CmdArgs.push_back("-lgcc_s");
CmdArgs.push_back("--no-as-needed");
}
}
}
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_pie))
CmdArgs.push_back(
Args.MakeArgString(ToolChain.GetFilePath("crtendS.o")));
else
CmdArgs.push_back(
Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
}
ToolChain.addProfileRTLibs(Args, CmdArgs);
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}
/// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly.
NetBSD::NetBSD(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
if (!Args.hasArg(options::OPT_nostdlib)) {
// When targeting a 32-bit platform, try the special directory used on
// 64-bit hosts, and only fall back to the main library directory if that
// doesn't work.
// FIXME: It'd be nicer to test if this directory exists, but I'm not sure
// what all logic is needed to emulate the '=' prefix here.
switch (Triple.getArch()) {
case llvm::Triple::x86:
getFilePaths().push_back("=/usr/lib/i386");
break;
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
switch (Triple.getEnvironment()) {
case llvm::Triple::EABI:
case llvm::Triple::GNUEABI:
getFilePaths().push_back("=/usr/lib/eabi");
break;
case llvm::Triple::EABIHF:
case llvm::Triple::GNUEABIHF:
getFilePaths().push_back("=/usr/lib/eabihf");
break;
default:
getFilePaths().push_back("=/usr/lib/oabi");
break;
}
break;
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
if (tools::mips::hasMipsAbiArg(Args, "o32"))
getFilePaths().push_back("=/usr/lib/o32");
else if (tools::mips::hasMipsAbiArg(Args, "64"))
getFilePaths().push_back("=/usr/lib/64");
break;
case llvm::Triple::ppc:
getFilePaths().push_back("=/usr/lib/powerpc");
break;
case llvm::Triple::sparc:
getFilePaths().push_back("=/usr/lib/sparc");
break;
default:
break;
}
getFilePaths().push_back("=/usr/lib");
}
}
Tool *NetBSD::buildAssembler() const {
return new tools::netbsd::Assembler(*this);
}
Tool *NetBSD::buildLinker() const { return new tools::netbsd::Linker(*this); }
ToolChain::CXXStdlibType NetBSD::GetDefaultCXXStdlibType() const {
unsigned Major, Minor, Micro;
getTriple().getOSVersion(Major, Minor, Micro);
if (Major >= 7 || Major == 0) {
switch (getArch()) {
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
case llvm::Triple::sparc:
case llvm::Triple::sparcv9:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
return ToolChain::CST_Libcxx;
default:
break;
}
}
return ToolChain::CST_Libstdcxx;
}
void NetBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
addSystemInclude(DriverArgs, CC1Args,
getDriver().SysRoot + "/usr/include/c++/");
}
void NetBSD::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
addLibStdCXXIncludePaths(getDriver().SysRoot, "/usr/include/g++", "", "", "",
"", DriverArgs, CC1Args);
}
llvm::ExceptionHandling NetBSD::GetExceptionModel(const ArgList &Args) const {
// NetBSD uses Dwarf exceptions on ARM.
llvm::Triple::ArchType TArch = getTriple().getArch();
if (TArch == llvm::Triple::arm || TArch == llvm::Triple::armeb ||
TArch == llvm::Triple::thumb || TArch == llvm::Triple::thumbeb)
return llvm::ExceptionHandling::DwarfCFI;
return llvm::ExceptionHandling::None;
}
SanitizerMask NetBSD::getSupportedSanitizers() const {
const bool IsX86 = getTriple().getArch() == llvm::Triple::x86;
const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;
SanitizerMask Res = ToolChain::getSupportedSanitizers();
if (IsX86 || IsX86_64) {
Res |= SanitizerKind::Address;
Res |= SanitizerKind::Function;
Res |= SanitizerKind::Leak;
Res |= SanitizerKind::SafeStack;
Res |= SanitizerKind::Scudo;
Res |= SanitizerKind::Vptr;
}
if (IsX86_64) {
Res |= SanitizerKind::DataFlow;
Res |= SanitizerKind::Efficiency;
Res |= SanitizerKind::Fuzzer;
Res |= SanitizerKind::FuzzerNoLink;
Res |= SanitizerKind::HWAddress;
Res |= SanitizerKind::KernelAddress;
Res |= SanitizerKind::KernelHWAddress;
Res |= SanitizerKind::KernelMemory;
Res |= SanitizerKind::Memory;
Res |= SanitizerKind::Thread;
}
return Res;
}
void NetBSD::addClangTargetOptions(const ArgList &,
ArgStringList &CC1Args,
Action::OffloadKind) const {
const SanitizerArgs &SanArgs = getSanitizerArgs();
if (SanArgs.hasAnySanitizer())
CC1Args.push_back("-D_REENTRANT");
}
Index: vendor/clang/dist-release_80/lib/Headers/opencl-c.h
===================================================================
--- vendor/clang/dist-release_80/lib/Headers/opencl-c.h (revision 343795)
+++ vendor/clang/dist-release_80/lib/Headers/opencl-c.h (revision 343796)
@@ -1,17042 +1,17042 @@
//===--- opencl-c.h - OpenCL C language builtin function header -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef _OPENCL_H_
#define _OPENCL_H_
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
#ifndef cl_khr_depth_images
#define cl_khr_depth_images
#endif //cl_khr_depth_images
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
#if __OPENCL_C_VERSION__ < CL_VERSION_2_0
#ifdef cl_khr_3d_image_writes
#pragma OPENCL EXTENSION cl_khr_3d_image_writes : enable
#endif //cl_khr_3d_image_writes
#endif //__OPENCL_C_VERSION__ < CL_VERSION_2_0
#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
#ifndef cl_intel_planar_yuv
#define cl_intel_planar_yuv
#endif // cl_intel_planar_yuv
#pragma OPENCL EXTENSION cl_intel_planar_yuv : begin
#pragma OPENCL EXTENSION cl_intel_planar_yuv : end
#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2
#define __ovld __attribute__((overloadable))
#define __conv __attribute__((convergent))
// Optimizations
#define __purefn __attribute__((pure))
#define __cnfn __attribute__((const))
// built-in scalar data types:
/**
* An unsigned 8-bit integer.
*/
typedef unsigned char uchar;
/**
* An unsigned 16-bit integer.
*/
typedef unsigned short ushort;
/**
* An unsigned 32-bit integer.
*/
typedef unsigned int uint;
/**
* An unsigned 64-bit integer.
*/
typedef unsigned long ulong;
/**
* The unsigned integer type of the result of the sizeof operator. This
* is a 32-bit unsigned integer if CL_DEVICE_ADDRESS_BITS
* defined in table 4.3 is 32-bits and is a 64-bit unsigned integer if
* CL_DEVICE_ADDRESS_BITS is 64-bits.
*/
typedef __SIZE_TYPE__ size_t;
/**
* A signed integer type that is the result of subtracting two pointers.
* This is a 32-bit signed integer if CL_DEVICE_ADDRESS_BITS
* defined in table 4.3 is 32-bits and is a 64-bit signed integer if
* CL_DEVICE_ADDRESS_BITS is 64-bits.
*/
typedef __PTRDIFF_TYPE__ ptrdiff_t;
/**
* A signed integer type with the property that any valid pointer to
* void can be converted to this type, then converted back to pointer
* to void, and the result will compare equal to the original pointer.
*/
typedef __INTPTR_TYPE__ intptr_t;
/**
* An unsigned integer type with the property that any valid pointer to
* void can be converted to this type, then converted back to pointer
* to void, and the result will compare equal to the original pointer.
*/
typedef __UINTPTR_TYPE__ uintptr_t;
// built-in vector data types:
typedef char char2 __attribute__((ext_vector_type(2)));
typedef char char3 __attribute__((ext_vector_type(3)));
typedef char char4 __attribute__((ext_vector_type(4)));
typedef char char8 __attribute__((ext_vector_type(8)));
typedef char char16 __attribute__((ext_vector_type(16)));
typedef uchar uchar2 __attribute__((ext_vector_type(2)));
typedef uchar uchar3 __attribute__((ext_vector_type(3)));
typedef uchar uchar4 __attribute__((ext_vector_type(4)));
typedef uchar uchar8 __attribute__((ext_vector_type(8)));
typedef uchar uchar16 __attribute__((ext_vector_type(16)));
typedef short short2 __attribute__((ext_vector_type(2)));
typedef short short3 __attribute__((ext_vector_type(3)));
typedef short short4 __attribute__((ext_vector_type(4)));
typedef short short8 __attribute__((ext_vector_type(8)));
typedef short short16 __attribute__((ext_vector_type(16)));
typedef ushort ushort2 __attribute__((ext_vector_type(2)));
typedef ushort ushort3 __attribute__((ext_vector_type(3)));
typedef ushort ushort4 __attribute__((ext_vector_type(4)));
typedef ushort ushort8 __attribute__((ext_vector_type(8)));
typedef ushort ushort16 __attribute__((ext_vector_type(16)));
typedef int int2 __attribute__((ext_vector_type(2)));
typedef int int3 __attribute__((ext_vector_type(3)));
typedef int int4 __attribute__((ext_vector_type(4)));
typedef int int8 __attribute__((ext_vector_type(8)));
typedef int int16 __attribute__((ext_vector_type(16)));
typedef uint uint2 __attribute__((ext_vector_type(2)));
typedef uint uint3 __attribute__((ext_vector_type(3)));
typedef uint uint4 __attribute__((ext_vector_type(4)));
typedef uint uint8 __attribute__((ext_vector_type(8)));
typedef uint uint16 __attribute__((ext_vector_type(16)));
typedef long long2 __attribute__((ext_vector_type(2)));
typedef long long3 __attribute__((ext_vector_type(3)));
typedef long long4 __attribute__((ext_vector_type(4)));
typedef long long8 __attribute__((ext_vector_type(8)));
typedef long long16 __attribute__((ext_vector_type(16)));
typedef ulong ulong2 __attribute__((ext_vector_type(2)));
typedef ulong ulong3 __attribute__((ext_vector_type(3)));
typedef ulong ulong4 __attribute__((ext_vector_type(4)));
typedef ulong ulong8 __attribute__((ext_vector_type(8)));
typedef ulong ulong16 __attribute__((ext_vector_type(16)));
typedef float float2 __attribute__((ext_vector_type(2)));
typedef float float3 __attribute__((ext_vector_type(3)));
typedef float float4 __attribute__((ext_vector_type(4)));
typedef float float8 __attribute__((ext_vector_type(8)));
typedef float float16 __attribute__((ext_vector_type(16)));
#ifdef cl_khr_fp16
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
typedef half half2 __attribute__((ext_vector_type(2)));
typedef half half3 __attribute__((ext_vector_type(3)));
typedef half half4 __attribute__((ext_vector_type(4)));
typedef half half8 __attribute__((ext_vector_type(8)));
typedef half half16 __attribute__((ext_vector_type(16)));
#endif
#ifdef cl_khr_fp64
#if __OPENCL_C_VERSION__ < CL_VERSION_1_2
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#endif
typedef double double2 __attribute__((ext_vector_type(2)));
typedef double double3 __attribute__((ext_vector_type(3)));
typedef double double4 __attribute__((ext_vector_type(4)));
typedef double double8 __attribute__((ext_vector_type(8)));
typedef double double16 __attribute__((ext_vector_type(16)));
#endif
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
#define NULL ((void*)0)
#endif
/**
* Value of maximum non-infinite single-precision floating-point
* number.
*/
#define MAXFLOAT 0x1.fffffep127f
/**
* A positive float constant expression. HUGE_VALF evaluates
* to +infinity. Used as an error value returned by the built-in
* math functions.
*/
#define HUGE_VALF (__builtin_huge_valf())
/**
* A positive double constant expression. HUGE_VAL evaluates
* to +infinity. Used as an error value returned by the built-in
* math functions.
*/
#define HUGE_VAL (__builtin_huge_val())
/**
* A constant expression of type float representing positive or
* unsigned infinity.
*/
#define INFINITY (__builtin_inff())
/**
* A constant expression of type float representing a quiet NaN.
*/
#define NAN as_float(INT_MAX)
#define FP_ILOGB0 INT_MIN
#define FP_ILOGBNAN INT_MAX
#define FLT_DIG 6
#define FLT_MANT_DIG 24
#define FLT_MAX_10_EXP +38
#define FLT_MAX_EXP +128
#define FLT_MIN_10_EXP -37
#define FLT_MIN_EXP -125
#define FLT_RADIX 2
#define FLT_MAX 0x1.fffffep127f
#define FLT_MIN 0x1.0p-126f
#define FLT_EPSILON 0x1.0p-23f
#define M_E_F 2.71828182845904523536028747135266250f
#define M_LOG2E_F 1.44269504088896340735992468100189214f
#define M_LOG10E_F 0.434294481903251827651128918916605082f
#define M_LN2_F 0.693147180559945309417232121458176568f
#define M_LN10_F 2.30258509299404568401799145468436421f
#define M_PI_F 3.14159265358979323846264338327950288f
#define M_PI_2_F 1.57079632679489661923132169163975144f
#define M_PI_4_F 0.785398163397448309615660845819875721f
#define M_1_PI_F 0.318309886183790671537767526745028724f
#define M_2_PI_F 0.636619772367581343075535053490057448f
#define M_2_SQRTPI_F 1.12837916709551257389615890312154517f
#define M_SQRT2_F 1.41421356237309504880168872420969808f
#define M_SQRT1_2_F 0.707106781186547524400844362104849039f
#define DBL_DIG 15
#define DBL_MANT_DIG 53
#define DBL_MAX_10_EXP +308
#define DBL_MAX_EXP +1024
#define DBL_MIN_10_EXP -307
#define DBL_MIN_EXP -1021
#define DBL_RADIX 2
#define DBL_MAX 0x1.fffffffffffffp1023
#define DBL_MIN 0x1.0p-1022
#define DBL_EPSILON 0x1.0p-52
#define M_E 0x1.5bf0a8b145769p+1
#define M_LOG2E 0x1.71547652b82fep+0
#define M_LOG10E 0x1.bcb7b1526e50ep-2
#define M_LN2 0x1.62e42fefa39efp-1
#define M_LN10 0x1.26bb1bbb55516p+1
#define M_PI 0x1.921fb54442d18p+1
#define M_PI_2 0x1.921fb54442d18p+0
#define M_PI_4 0x1.921fb54442d18p-1
#define M_1_PI 0x1.45f306dc9c883p-2
#define M_2_PI 0x1.45f306dc9c883p-1
#define M_2_SQRTPI 0x1.20dd750429b6dp+0
#define M_SQRT2 0x1.6a09e667f3bcdp+0
#define M_SQRT1_2 0x1.6a09e667f3bcdp-1
#ifdef cl_khr_fp16
#define HALF_DIG 3
#define HALF_MANT_DIG 11
#define HALF_MAX_10_EXP +4
#define HALF_MAX_EXP +16
#define HALF_MIN_10_EXP -4
#define HALF_MIN_EXP -13
#define HALF_RADIX 2
#define HALF_MAX ((0x1.ffcp15h))
#define HALF_MIN ((0x1.0p-14h))
#define HALF_EPSILON ((0x1.0p-10h))
#define M_E_H 2.71828182845904523536028747135266250h
#define M_LOG2E_H 1.44269504088896340735992468100189214h
#define M_LOG10E_H 0.434294481903251827651128918916605082h
#define M_LN2_H 0.693147180559945309417232121458176568h
#define M_LN10_H 2.30258509299404568401799145468436421h
#define M_PI_H 3.14159265358979323846264338327950288h
#define M_PI_2_H 1.57079632679489661923132169163975144h
#define M_PI_4_H 0.785398163397448309615660845819875721h
#define M_1_PI_H 0.318309886183790671537767526745028724h
#define M_2_PI_H 0.636619772367581343075535053490057448h
#define M_2_SQRTPI_H 1.12837916709551257389615890312154517h
#define M_SQRT2_H 1.41421356237309504880168872420969808h
#define M_SQRT1_2_H 0.707106781186547524400844362104849039h
#endif //cl_khr_fp16
#define CHAR_BIT 8
#define SCHAR_MAX 127
#define SCHAR_MIN (-128)
#define UCHAR_MAX 255
#define CHAR_MAX SCHAR_MAX
#define CHAR_MIN SCHAR_MIN
#define USHRT_MAX 65535
#define SHRT_MAX 32767
#define SHRT_MIN (-32768)
#define UINT_MAX 0xffffffff
#define INT_MAX 2147483647
#define INT_MIN (-2147483647-1)
#define ULONG_MAX 0xffffffffffffffffUL
#define LONG_MAX 0x7fffffffffffffffL
#define LONG_MIN (-0x7fffffffffffffffL-1)
// OpenCL v1.1/1.2/2.0 s6.2.3 - Explicit conversions
char __ovld __cnfn convert_char_rte(char);
char __ovld __cnfn convert_char_sat_rte(char);
char __ovld __cnfn convert_char_rtz(char);
char __ovld __cnfn convert_char_sat_rtz(char);
char __ovld __cnfn convert_char_rtp(char);
char __ovld __cnfn convert_char_sat_rtp(char);
char __ovld __cnfn convert_char_rtn(char);
char __ovld __cnfn convert_char_sat_rtn(char);
char __ovld __cnfn convert_char(char);
char __ovld __cnfn convert_char_sat(char);
char __ovld __cnfn convert_char_rte(uchar);
char __ovld __cnfn convert_char_sat_rte(uchar);
char __ovld __cnfn convert_char_rtz(uchar);
char __ovld __cnfn convert_char_sat_rtz(uchar);
char __ovld __cnfn convert_char_rtp(uchar);
char __ovld __cnfn convert_char_sat_rtp(uchar);
char __ovld __cnfn convert_char_rtn(uchar);
char __ovld __cnfn convert_char_sat_rtn(uchar);
char __ovld __cnfn convert_char(uchar);
char __ovld __cnfn convert_char_sat(uchar);
char __ovld __cnfn convert_char_rte(short);
char __ovld __cnfn convert_char_sat_rte(short);
char __ovld __cnfn convert_char_rtz(short);
char __ovld __cnfn convert_char_sat_rtz(short);
char __ovld __cnfn convert_char_rtp(short);
char __ovld __cnfn convert_char_sat_rtp(short);
char __ovld __cnfn convert_char_rtn(short);
char __ovld __cnfn convert_char_sat_rtn(short);
char __ovld __cnfn convert_char(short);
char __ovld __cnfn convert_char_sat(short);
char __ovld __cnfn convert_char_rte(ushort);
char __ovld __cnfn convert_char_sat_rte(ushort);
char __ovld __cnfn convert_char_rtz(ushort);
char __ovld __cnfn convert_char_sat_rtz(ushort);
char __ovld __cnfn convert_char_rtp(ushort);
char __ovld __cnfn convert_char_sat_rtp(ushort);
char __ovld __cnfn convert_char_rtn(ushort);
char __ovld __cnfn convert_char_sat_rtn(ushort);
char __ovld __cnfn convert_char(ushort);
char __ovld __cnfn convert_char_sat(ushort);
char __ovld __cnfn convert_char_rte(int);
char __ovld __cnfn convert_char_sat_rte(int);
char __ovld __cnfn convert_char_rtz(int);
char __ovld __cnfn convert_char_sat_rtz(int);
char __ovld __cnfn convert_char_rtp(int);
char __ovld __cnfn convert_char_sat_rtp(int);
char __ovld __cnfn convert_char_rtn(int);
char __ovld __cnfn convert_char_sat_rtn(int);
char __ovld __cnfn convert_char(int);
char __ovld __cnfn convert_char_sat(int);
char __ovld __cnfn convert_char_rte(uint);
char __ovld __cnfn convert_char_sat_rte(uint);
char __ovld __cnfn convert_char_rtz(uint);
char __ovld __cnfn convert_char_sat_rtz(uint);
char __ovld __cnfn convert_char_rtp(uint);
char __ovld __cnfn convert_char_sat_rtp(uint);
char __ovld __cnfn convert_char_rtn(uint);
char __ovld __cnfn convert_char_sat_rtn(uint);
char __ovld __cnfn convert_char(uint);
char __ovld __cnfn convert_char_sat(uint);
char __ovld __cnfn convert_char_rte(long);
char __ovld __cnfn convert_char_sat_rte(long);
char __ovld __cnfn convert_char_rtz(long);
char __ovld __cnfn convert_char_sat_rtz(long);
char __ovld __cnfn convert_char_rtp(long);
char __ovld __cnfn convert_char_sat_rtp(long);
char __ovld __cnfn convert_char_rtn(long);
char __ovld __cnfn convert_char_sat_rtn(long);
char __ovld __cnfn convert_char(long);
char __ovld __cnfn convert_char_sat(long);
char __ovld __cnfn convert_char_rte(ulong);
char __ovld __cnfn convert_char_sat_rte(ulong);
char __ovld __cnfn convert_char_rtz(ulong);
char __ovld __cnfn convert_char_sat_rtz(ulong);
char __ovld __cnfn convert_char_rtp(ulong);
char __ovld __cnfn convert_char_sat_rtp(ulong);
char __ovld __cnfn convert_char_rtn(ulong);
char __ovld __cnfn convert_char_sat_rtn(ulong);
char __ovld __cnfn convert_char(ulong);
char __ovld __cnfn convert_char_sat(ulong);
char __ovld __cnfn convert_char_rte(float);
char __ovld __cnfn convert_char_sat_rte(float);
char __ovld __cnfn convert_char_rtz(float);
char __ovld __cnfn convert_char_sat_rtz(float);
char __ovld __cnfn convert_char_rtp(float);
char __ovld __cnfn convert_char_sat_rtp(float);
char __ovld __cnfn convert_char_rtn(float);
char __ovld __cnfn convert_char_sat_rtn(float);
char __ovld __cnfn convert_char(float);
char __ovld __cnfn convert_char_sat(float);
uchar __ovld __cnfn convert_uchar_rte(char);
uchar __ovld __cnfn convert_uchar_sat_rte(char);
uchar __ovld __cnfn convert_uchar_rtz(char);
uchar __ovld __cnfn convert_uchar_sat_rtz(char);
uchar __ovld __cnfn convert_uchar_rtp(char);
uchar __ovld __cnfn convert_uchar_sat_rtp(char);
uchar __ovld __cnfn convert_uchar_rtn(char);
uchar __ovld __cnfn convert_uchar_sat_rtn(char);
uchar __ovld __cnfn convert_uchar(char);
uchar __ovld __cnfn convert_uchar_sat(char);
uchar __ovld __cnfn convert_uchar_rte(uchar);
uchar __ovld __cnfn convert_uchar_sat_rte(uchar);
uchar __ovld __cnfn convert_uchar_rtz(uchar);
uchar __ovld __cnfn convert_uchar_sat_rtz(uchar);
uchar __ovld __cnfn convert_uchar_rtp(uchar);
uchar __ovld __cnfn convert_uchar_sat_rtp(uchar);
uchar __ovld __cnfn convert_uchar_rtn(uchar);
uchar __ovld __cnfn convert_uchar_sat_rtn(uchar);
uchar __ovld __cnfn convert_uchar(uchar);
uchar __ovld __cnfn convert_uchar_sat(uchar);
uchar __ovld __cnfn convert_uchar_rte(short);
uchar __ovld __cnfn convert_uchar_sat_rte(short);
uchar __ovld __cnfn convert_uchar_rtz(short);
uchar __ovld __cnfn convert_uchar_sat_rtz(short);
uchar __ovld __cnfn convert_uchar_rtp(short);
uchar __ovld __cnfn convert_uchar_sat_rtp(short);
uchar __ovld __cnfn convert_uchar_rtn(short);
uchar __ovld __cnfn convert_uchar_sat_rtn(short);
uchar __ovld __cnfn convert_uchar(short);
uchar __ovld __cnfn convert_uchar_sat(short);
uchar __ovld __cnfn convert_uchar_rte(ushort);
uchar __ovld __cnfn convert_uchar_sat_rte(ushort);
uchar __ovld __cnfn convert_uchar_rtz(ushort);
uchar __ovld __cnfn convert_uchar_sat_rtz(ushort);
uchar __ovld __cnfn convert_uchar_rtp(ushort);
uchar __ovld __cnfn convert_uchar_sat_rtp(ushort);
uchar __ovld __cnfn convert_uchar_rtn(ushort);
uchar __ovld __cnfn convert_uchar_sat_rtn(ushort);
uchar __ovld __cnfn convert_uchar(ushort);
uchar __ovld __cnfn convert_uchar_sat(ushort);
uchar __ovld __cnfn convert_uchar_rte(int);
uchar __ovld __cnfn convert_uchar_sat_rte(int);
uchar __ovld __cnfn convert_uchar_rtz(int);
uchar __ovld __cnfn convert_uchar_sat_rtz(int);
uchar __ovld __cnfn convert_uchar_rtp(int);
uchar __ovld __cnfn convert_uchar_sat_rtp(int);
uchar __ovld __cnfn convert_uchar_rtn(int);
uchar __ovld __cnfn convert_uchar_sat_rtn(int);
uchar __ovld __cnfn convert_uchar(int);
uchar __ovld __cnfn convert_uchar_sat(int);
uchar __ovld __cnfn convert_uchar_rte(uint);
uchar __ovld __cnfn convert_uchar_sat_rte(uint);
uchar __ovld __cnfn convert_uchar_rtz(uint);
uchar __ovld __cnfn convert_uchar_sat_rtz(uint);
uchar __ovld __cnfn convert_uchar_rtp(uint);
uchar __ovld __cnfn convert_uchar_sat_rtp(uint);
uchar __ovld __cnfn convert_uchar_rtn(uint);
uchar __ovld __cnfn convert_uchar_sat_rtn(uint);
uchar __ovld __cnfn convert_uchar(uint);
uchar __ovld __cnfn convert_uchar_sat(uint);
uchar __ovld __cnfn convert_uchar_rte(long);
uchar __ovld __cnfn convert_uchar_sat_rte(long);
uchar __ovld __cnfn convert_uchar_rtz(long);
uchar __ovld __cnfn convert_uchar_sat_rtz(long);
uchar __ovld __cnfn convert_uchar_rtp(long);
uchar __ovld __cnfn convert_uchar_sat_rtp(long);
uchar __ovld __cnfn convert_uchar_rtn(long);
uchar __ovld __cnfn convert_uchar_sat_rtn(long);
uchar __ovld __cnfn convert_uchar(long);
uchar __ovld __cnfn convert_uchar_sat(long);
uchar __ovld __cnfn convert_uchar_rte(ulong);
uchar __ovld __cnfn convert_uchar_sat_rte(ulong);
uchar __ovld __cnfn convert_uchar_rtz(ulong);
uchar __ovld __cnfn convert_uchar_sat_rtz(ulong);
uchar __ovld __cnfn convert_uchar_rtp(ulong);
uchar __ovld __cnfn convert_uchar_sat_rtp(ulong);
uchar __ovld __cnfn convert_uchar_rtn(ulong);
uchar __ovld __cnfn convert_uchar_sat_rtn(ulong);
uchar __ovld __cnfn convert_uchar(ulong);
uchar __ovld __cnfn convert_uchar_sat(ulong);
uchar __ovld __cnfn convert_uchar_rte(float);
uchar __ovld __cnfn convert_uchar_sat_rte(float);
uchar __ovld __cnfn convert_uchar_rtz(float);
uchar __ovld __cnfn convert_uchar_sat_rtz(float);
uchar __ovld __cnfn convert_uchar_rtp(float);
uchar __ovld __cnfn convert_uchar_sat_rtp(float);
uchar __ovld __cnfn convert_uchar_rtn(float);
uchar __ovld __cnfn convert_uchar_sat_rtn(float);
uchar __ovld __cnfn convert_uchar(float);
uchar __ovld __cnfn convert_uchar_sat(float);
short __ovld __cnfn convert_short_rte(char);
short __ovld __cnfn convert_short_sat_rte(char);
short __ovld __cnfn convert_short_rtz(char);
short __ovld __cnfn convert_short_sat_rtz(char);
short __ovld __cnfn convert_short_rtp(char);
short __ovld __cnfn convert_short_sat_rtp(char);
short __ovld __cnfn convert_short_rtn(char);
short __ovld __cnfn convert_short_sat_rtn(char);
short __ovld __cnfn convert_short(char);
short __ovld __cnfn convert_short_sat(char);
short __ovld __cnfn convert_short_rte(uchar);
short __ovld __cnfn convert_short_sat_rte(uchar);
short __ovld __cnfn convert_short_rtz(uchar);
short __ovld __cnfn convert_short_sat_rtz(uchar);
short __ovld __cnfn convert_short_rtp(uchar);
short __ovld __cnfn convert_short_sat_rtp(uchar);
short __ovld __cnfn convert_short_rtn(uchar);
short __ovld __cnfn convert_short_sat_rtn(uchar);
short __ovld __cnfn convert_short(uchar);
short __ovld __cnfn convert_short_sat(uchar);
short __ovld __cnfn convert_short_rte(short);
short __ovld __cnfn convert_short_sat_rte(short);
short __ovld __cnfn convert_short_rtz(short);
short __ovld __cnfn convert_short_sat_rtz(short);
short __ovld __cnfn convert_short_rtp(short);
short __ovld __cnfn convert_short_sat_rtp(short);
short __ovld __cnfn convert_short_rtn(short);
short __ovld __cnfn convert_short_sat_rtn(short);
short __ovld __cnfn convert_short(short);
short __ovld __cnfn convert_short_sat(short);
short __ovld __cnfn convert_short_rte(ushort);
short __ovld __cnfn convert_short_sat_rte(ushort);
short __ovld __cnfn convert_short_rtz(ushort);
short __ovld __cnfn convert_short_sat_rtz(ushort);
short __ovld __cnfn convert_short_rtp(ushort);
short __ovld __cnfn convert_short_sat_rtp(ushort);
short __ovld __cnfn convert_short_rtn(ushort);
short __ovld __cnfn convert_short_sat_rtn(ushort);
short __ovld __cnfn convert_short(ushort);
short __ovld __cnfn convert_short_sat(ushort);
short __ovld __cnfn convert_short_rte(int);
short __ovld __cnfn convert_short_sat_rte(int);
short __ovld __cnfn convert_short_rtz(int);
short __ovld __cnfn convert_short_sat_rtz(int);
short __ovld __cnfn convert_short_rtp(int);
short __ovld __cnfn convert_short_sat_rtp(int);
short __ovld __cnfn convert_short_rtn(int);
short __ovld __cnfn convert_short_sat_rtn(int);
short __ovld __cnfn convert_short(int);
short __ovld __cnfn convert_short_sat(int);
short __ovld __cnfn convert_short_rte(uint);
short __ovld __cnfn convert_short_sat_rte(uint);
short __ovld __cnfn convert_short_rtz(uint);
short __ovld __cnfn convert_short_sat_rtz(uint);
short __ovld __cnfn convert_short_rtp(uint);
short __ovld __cnfn convert_short_sat_rtp(uint);
short __ovld __cnfn convert_short_rtn(uint);
short __ovld __cnfn convert_short_sat_rtn(uint);
short __ovld __cnfn convert_short(uint);
short __ovld __cnfn convert_short_sat(uint);
short __ovld __cnfn convert_short_rte(long);
short __ovld __cnfn convert_short_sat_rte(long);
short __ovld __cnfn convert_short_rtz(long);
short __ovld __cnfn convert_short_sat_rtz(long);
short __ovld __cnfn convert_short_rtp(long);
short __ovld __cnfn convert_short_sat_rtp(long);
short __ovld __cnfn convert_short_rtn(long);
short __ovld __cnfn convert_short_sat_rtn(long);
short __ovld __cnfn convert_short(long);
short __ovld __cnfn convert_short_sat(long);
short __ovld __cnfn convert_short_rte(ulong);
short __ovld __cnfn convert_short_sat_rte(ulong);
short __ovld __cnfn convert_short_rtz(ulong);
short __ovld __cnfn convert_short_sat_rtz(ulong);
short __ovld __cnfn convert_short_rtp(ulong);
short __ovld __cnfn convert_short_sat_rtp(ulong);
short __ovld __cnfn convert_short_rtn(ulong);
short __ovld __cnfn convert_short_sat_rtn(ulong);
short __ovld __cnfn convert_short(ulong);
short __ovld __cnfn convert_short_sat(ulong);
short __ovld __cnfn convert_short_rte(float);
short __ovld __cnfn convert_short_sat_rte(float);
short __ovld __cnfn convert_short_rtz(float);
short __ovld __cnfn convert_short_sat_rtz(float);
short __ovld __cnfn convert_short_rtp(float);
short __ovld __cnfn convert_short_sat_rtp(float);
short __ovld __cnfn convert_short_rtn(float);
short __ovld __cnfn convert_short_sat_rtn(float);
short __ovld __cnfn convert_short(float);
short __ovld __cnfn convert_short_sat(float);
ushort __ovld __cnfn convert_ushort_rte(char);
ushort __ovld __cnfn convert_ushort_sat_rte(char);
ushort __ovld __cnfn convert_ushort_rtz(char);
ushort __ovld __cnfn convert_ushort_sat_rtz(char);
ushort __ovld __cnfn convert_ushort_rtp(char);
ushort __ovld __cnfn convert_ushort_sat_rtp(char);
ushort __ovld __cnfn convert_ushort_rtn(char);
ushort __ovld __cnfn convert_ushort_sat_rtn(char);
ushort __ovld __cnfn convert_ushort(char);
ushort __ovld __cnfn convert_ushort_sat(char);
ushort __ovld __cnfn convert_ushort_rte(uchar);
ushort __ovld __cnfn convert_ushort_sat_rte(uchar);
ushort __ovld __cnfn convert_ushort_rtz(uchar);
ushort __ovld __cnfn convert_ushort_sat_rtz(uchar);
ushort __ovld __cnfn convert_ushort_rtp(uchar);
ushort __ovld __cnfn convert_ushort_sat_rtp(uchar);
ushort __ovld __cnfn convert_ushort_rtn(uchar);
ushort __ovld __cnfn convert_ushort_sat_rtn(uchar);
ushort __ovld __cnfn convert_ushort(uchar);
ushort __ovld __cnfn convert_ushort_sat(uchar);
ushort __ovld __cnfn convert_ushort_rte(short);
ushort __ovld __cnfn convert_ushort_sat_rte(short);
ushort __ovld __cnfn convert_ushort_rtz(short);
ushort __ovld __cnfn convert_ushort_sat_rtz(short);
ushort __ovld __cnfn convert_ushort_rtp(short);
ushort __ovld __cnfn convert_ushort_sat_rtp(short);
ushort __ovld __cnfn convert_ushort_rtn(short);
ushort __ovld __cnfn convert_ushort_sat_rtn(short);
ushort __ovld __cnfn convert_ushort(short);
ushort __ovld __cnfn convert_ushort_sat(short);
ushort __ovld __cnfn convert_ushort_rte(ushort);
ushort __ovld __cnfn convert_ushort_sat_rte(ushort);
ushort __ovld __cnfn convert_ushort_rtz(ushort);
ushort __ovld __cnfn convert_ushort_sat_rtz(ushort);
ushort __ovld __cnfn convert_ushort_rtp(ushort);
ushort __ovld __cnfn convert_ushort_sat_rtp(ushort);
ushort __ovld __cnfn convert_ushort_rtn(ushort);
ushort __ovld __cnfn convert_ushort_sat_rtn(ushort);
ushort __ovld __cnfn convert_ushort(ushort);
ushort __ovld __cnfn convert_ushort_sat(ushort);
ushort __ovld __cnfn convert_ushort_rte(int);
ushort __ovld __cnfn convert_ushort_sat_rte(int);
ushort __ovld __cnfn convert_ushort_rtz(int);
ushort __ovld __cnfn convert_ushort_sat_rtz(int);
ushort __ovld __cnfn convert_ushort_rtp(int);
ushort __ovld __cnfn convert_ushort_sat_rtp(int);
ushort __ovld __cnfn convert_ushort_rtn(int);
ushort __ovld __cnfn convert_ushort_sat_rtn(int);
ushort __ovld __cnfn convert_ushort(int);
ushort __ovld __cnfn convert_ushort_sat(int);
ushort __ovld __cnfn convert_ushort_rte(uint);
ushort __ovld __cnfn convert_ushort_sat_rte(uint);
ushort __ovld __cnfn convert_ushort_rtz(uint);
ushort __ovld __cnfn convert_ushort_sat_rtz(uint);
ushort __ovld __cnfn convert_ushort_rtp(uint);
ushort __ovld __cnfn convert_ushort_sat_rtp(uint);
ushort __ovld __cnfn convert_ushort_rtn(uint);
ushort __ovld __cnfn convert_ushort_sat_rtn(uint);
ushort __ovld __cnfn convert_ushort(uint);
ushort __ovld __cnfn convert_ushort_sat(uint);
ushort __ovld __cnfn convert_ushort_rte(long);
ushort __ovld __cnfn convert_ushort_sat_rte(long);
ushort __ovld __cnfn convert_ushort_rtz(long);
ushort __ovld __cnfn convert_ushort_sat_rtz(long);
ushort __ovld __cnfn convert_ushort_rtp(long);
ushort __ovld __cnfn convert_ushort_sat_rtp(long);
ushort __ovld __cnfn convert_ushort_rtn(long);
ushort __ovld __cnfn convert_ushort_sat_rtn(long);
ushort __ovld __cnfn convert_ushort(long);
ushort __ovld __cnfn convert_ushort_sat(long);
ushort __ovld __cnfn convert_ushort_rte(ulong);
ushort __ovld __cnfn convert_ushort_sat_rte(ulong);
ushort __ovld __cnfn convert_ushort_rtz(ulong);
ushort __ovld __cnfn convert_ushort_sat_rtz(ulong);
ushort __ovld __cnfn convert_ushort_rtp(ulong);
ushort __ovld __cnfn convert_ushort_sat_rtp(ulong);
ushort __ovld __cnfn convert_ushort_rtn(ulong);
ushort __ovld __cnfn convert_ushort_sat_rtn(ulong);
ushort __ovld __cnfn convert_ushort(ulong);
ushort __ovld __cnfn convert_ushort_sat(ulong);
ushort __ovld __cnfn convert_ushort_rte(float);
ushort __ovld __cnfn convert_ushort_sat_rte(float);
ushort __ovld __cnfn convert_ushort_rtz(float);
ushort __ovld __cnfn convert_ushort_sat_rtz(float);
ushort __ovld __cnfn convert_ushort_rtp(float);
ushort __ovld __cnfn convert_ushort_sat_rtp(float);
ushort __ovld __cnfn convert_ushort_rtn(float);
ushort __ovld __cnfn convert_ushort_sat_rtn(float);
ushort __ovld __cnfn convert_ushort(float);
ushort __ovld __cnfn convert_ushort_sat(float);
int __ovld __cnfn convert_int_rte(char);
int __ovld __cnfn convert_int_sat_rte(char);
int __ovld __cnfn convert_int_rtz(char);
int __ovld __cnfn convert_int_sat_rtz(char);
int __ovld __cnfn convert_int_rtp(char);
int __ovld __cnfn convert_int_sat_rtp(char);
int __ovld __cnfn convert_int_rtn(char);
int __ovld __cnfn convert_int_sat_rtn(char);
int __ovld __cnfn convert_int(char);
int __ovld __cnfn convert_int_sat(char);
int __ovld __cnfn convert_int_rte(uchar);
int __ovld __cnfn convert_int_sat_rte(uchar);
int __ovld __cnfn convert_int_rtz(uchar);
int __ovld __cnfn convert_int_sat_rtz(uchar);
int __ovld __cnfn convert_int_rtp(uchar);
int __ovld __cnfn convert_int_sat_rtp(uchar);
int __ovld __cnfn convert_int_rtn(uchar);
int __ovld __cnfn convert_int_sat_rtn(uchar);
int __ovld __cnfn convert_int(uchar);
int __ovld __cnfn convert_int_sat(uchar);
int __ovld __cnfn convert_int_rte(short);
int __ovld __cnfn convert_int_sat_rte(short);
int __ovld __cnfn convert_int_rtz(short);
int __ovld __cnfn convert_int_sat_rtz(short);
int __ovld __cnfn convert_int_rtp(short);
int __ovld __cnfn convert_int_sat_rtp(short);
int __ovld __cnfn convert_int_rtn(short);
int __ovld __cnfn convert_int_sat_rtn(short);
int __ovld __cnfn convert_int(short);
int __ovld __cnfn convert_int_sat(short);
int __ovld __cnfn convert_int_rte(ushort);
int __ovld __cnfn convert_int_sat_rte(ushort);
int __ovld __cnfn convert_int_rtz(ushort);
int __ovld __cnfn convert_int_sat_rtz(ushort);
int __ovld __cnfn convert_int_rtp(ushort);
int __ovld __cnfn convert_int_sat_rtp(ushort);
int __ovld __cnfn convert_int_rtn(ushort);
int __ovld __cnfn convert_int_sat_rtn(ushort);
int __ovld __cnfn convert_int(ushort);
int __ovld __cnfn convert_int_sat(ushort);
int __ovld __cnfn convert_int_rte(int);
int __ovld __cnfn convert_int_sat_rte(int);
int __ovld __cnfn convert_int_rtz(int);
int __ovld __cnfn convert_int_sat_rtz(int);
int __ovld __cnfn convert_int_rtp(int);
int __ovld __cnfn convert_int_sat_rtp(int);
int __ovld __cnfn convert_int_rtn(int);
int __ovld __cnfn convert_int_sat_rtn(int);
int __ovld __cnfn convert_int(int);
int __ovld __cnfn convert_int_sat(int);
int __ovld __cnfn convert_int_rte(uint);
int __ovld __cnfn convert_int_sat_rte(uint);
int __ovld __cnfn convert_int_rtz(uint);
int __ovld __cnfn convert_int_sat_rtz(uint);
int __ovld __cnfn convert_int_rtp(uint);
int __ovld __cnfn convert_int_sat_rtp(uint);
int __ovld __cnfn convert_int_rtn(uint);
int __ovld __cnfn convert_int_sat_rtn(uint);
int __ovld __cnfn convert_int(uint);
int __ovld __cnfn convert_int_sat(uint);
int __ovld __cnfn convert_int_rte(long);
int __ovld __cnfn convert_int_sat_rte(long);
int __ovld __cnfn convert_int_rtz(long);
int __ovld __cnfn convert_int_sat_rtz(long);
int __ovld __cnfn convert_int_rtp(long);
int __ovld __cnfn convert_int_sat_rtp(long);
int __ovld __cnfn convert_int_rtn(long);
int __ovld __cnfn convert_int_sat_rtn(long);
int __ovld __cnfn convert_int(long);
int __ovld __cnfn convert_int_sat(long);
int __ovld __cnfn convert_int_rte(ulong);
int __ovld __cnfn convert_int_sat_rte(ulong);
int __ovld __cnfn convert_int_rtz(ulong);
int __ovld __cnfn convert_int_sat_rtz(ulong);
int __ovld __cnfn convert_int_rtp(ulong);
int __ovld __cnfn convert_int_sat_rtp(ulong);
int __ovld __cnfn convert_int_rtn(ulong);
int __ovld __cnfn convert_int_sat_rtn(ulong);
int __ovld __cnfn convert_int(ulong);
int __ovld __cnfn convert_int_sat(ulong);
int __ovld __cnfn convert_int_rte(float);
int __ovld __cnfn convert_int_sat_rte(float);
int __ovld __cnfn convert_int_rtz(float);
int __ovld __cnfn convert_int_sat_rtz(float);
int __ovld __cnfn convert_int_rtp(float);
int __ovld __cnfn convert_int_sat_rtp(float);
int __ovld __cnfn convert_int_rtn(float);
int __ovld __cnfn convert_int_sat_rtn(float);
int __ovld __cnfn convert_int(float);
int __ovld __cnfn convert_int_sat(float);
uint __ovld __cnfn convert_uint_rte(char);
uint __ovld __cnfn convert_uint_sat_rte(char);
uint __ovld __cnfn convert_uint_rtz(char);
uint __ovld __cnfn convert_uint_sat_rtz(char);
uint __ovld __cnfn convert_uint_rtp(char);
uint __ovld __cnfn convert_uint_sat_rtp(char);
uint __ovld __cnfn convert_uint_rtn(char);
uint __ovld __cnfn convert_uint_sat_rtn(char);
uint __ovld __cnfn convert_uint(char);
uint __ovld __cnfn convert_uint_sat(char);
uint __ovld __cnfn convert_uint_rte(uchar);
uint __ovld __cnfn convert_uint_sat_rte(uchar);
uint __ovld __cnfn convert_uint_rtz(uchar);
uint __ovld __cnfn convert_uint_sat_rtz(uchar);
uint __ovld __cnfn convert_uint_rtp(uchar);
uint __ovld __cnfn convert_uint_sat_rtp(uchar);
uint __ovld __cnfn convert_uint_rtn(uchar);
uint __ovld __cnfn convert_uint_sat_rtn(uchar);
uint __ovld __cnfn convert_uint(uchar);
uint __ovld __cnfn convert_uint_sat(uchar);
uint __ovld __cnfn convert_uint_rte(short);
uint __ovld __cnfn convert_uint_sat_rte(short);
uint __ovld __cnfn convert_uint_rtz(short);
uint __ovld __cnfn convert_uint_sat_rtz(short);
uint __ovld __cnfn convert_uint_rtp(short);
uint __ovld __cnfn convert_uint_sat_rtp(short);
uint __ovld __cnfn convert_uint_rtn(short);
uint __ovld __cnfn convert_uint_sat_rtn(short);
uint __ovld __cnfn convert_uint(short);
uint __ovld __cnfn convert_uint_sat(short);
uint __ovld __cnfn convert_uint_rte(ushort);
uint __ovld __cnfn convert_uint_sat_rte(ushort);
uint __ovld __cnfn convert_uint_rtz(ushort);
uint __ovld __cnfn convert_uint_sat_rtz(ushort);
uint __ovld __cnfn convert_uint_rtp(ushort);
uint __ovld __cnfn convert_uint_sat_rtp(ushort);
uint __ovld __cnfn convert_uint_rtn(ushort);
uint __ovld __cnfn convert_uint_sat_rtn(ushort);
uint __ovld __cnfn convert_uint(ushort);
uint __ovld __cnfn convert_uint_sat(ushort);
uint __ovld __cnfn convert_uint_rte(int);
uint __ovld __cnfn convert_uint_sat_rte(int);
uint __ovld __cnfn convert_uint_rtz(int);
uint __ovld __cnfn convert_uint_sat_rtz(int);
uint __ovld __cnfn convert_uint_rtp(int);
uint __ovld __cnfn convert_uint_sat_rtp(int);
uint __ovld __cnfn convert_uint_rtn(int);
uint __ovld __cnfn convert_uint_sat_rtn(int);
uint __ovld __cnfn convert_uint(int);
uint __ovld __cnfn convert_uint_sat(int);
uint __ovld __cnfn convert_uint_rte(uint);
uint __ovld __cnfn convert_uint_sat_rte(uint);
uint __ovld __cnfn convert_uint_rtz(uint);
uint __ovld __cnfn convert_uint_sat_rtz(uint);
uint __ovld __cnfn convert_uint_rtp(uint);
uint __ovld __cnfn convert_uint_sat_rtp(uint);
uint __ovld __cnfn convert_uint_rtn(uint);
uint __ovld __cnfn convert_uint_sat_rtn(uint);
uint __ovld __cnfn convert_uint(uint);
uint __ovld __cnfn convert_uint_sat(uint);
uint __ovld __cnfn convert_uint_rte(long);
uint __ovld __cnfn convert_uint_sat_rte(long);
uint __ovld __cnfn convert_uint_rtz(long);
uint __ovld __cnfn convert_uint_sat_rtz(long);
uint __ovld __cnfn convert_uint_rtp(long);
uint __ovld __cnfn convert_uint_sat_rtp(long);
uint __ovld __cnfn convert_uint_rtn(long);
uint __ovld __cnfn convert_uint_sat_rtn(long);
uint __ovld __cnfn convert_uint(long);
uint __ovld __cnfn convert_uint_sat(long);
uint __ovld __cnfn convert_uint_rte(ulong);
uint __ovld __cnfn convert_uint_sat_rte(ulong);
uint __ovld __cnfn convert_uint_rtz(ulong);
uint __ovld __cnfn convert_uint_sat_rtz(ulong);
uint __ovld __cnfn convert_uint_rtp(ulong);
uint __ovld __cnfn convert_uint_sat_rtp(ulong);
uint __ovld __cnfn convert_uint_rtn(ulong);
uint __ovld __cnfn convert_uint_sat_rtn(ulong);
uint __ovld __cnfn convert_uint(ulong);
uint __ovld __cnfn convert_uint_sat(ulong);
uint __ovld __cnfn convert_uint_rte(float);
uint __ovld __cnfn convert_uint_sat_rte(float);
uint __ovld __cnfn convert_uint_rtz(float);
uint __ovld __cnfn convert_uint_sat_rtz(float);
uint __ovld __cnfn convert_uint_rtp(float);
uint __ovld __cnfn convert_uint_sat_rtp(float);
uint __ovld __cnfn convert_uint_rtn(float);
uint __ovld __cnfn convert_uint_sat_rtn(float);
uint __ovld __cnfn convert_uint(float);
uint __ovld __cnfn convert_uint_sat(float);
long __ovld __cnfn convert_long_rte(char);
long __ovld __cnfn convert_long_sat_rte(char);
long __ovld __cnfn convert_long_rtz(char);
long __ovld __cnfn convert_long_sat_rtz(char);
long __ovld __cnfn convert_long_rtp(char);
long __ovld __cnfn convert_long_sat_rtp(char);
long __ovld __cnfn convert_long_rtn(char);
long __ovld __cnfn convert_long_sat_rtn(char);
long __ovld __cnfn convert_long(char);
long __ovld __cnfn convert_long_sat(char);
long __ovld __cnfn convert_long_rte(uchar);
long __ovld __cnfn convert_long_sat_rte(uchar);
long __ovld __cnfn convert_long_rtz(uchar);
long __ovld __cnfn convert_long_sat_rtz(uchar);
long __ovld __cnfn convert_long_rtp(uchar);
long __ovld __cnfn convert_long_sat_rtp(uchar);
long __ovld __cnfn convert_long_rtn(uchar);
long __ovld __cnfn convert_long_sat_rtn(uchar);
long __ovld __cnfn convert_long(uchar);
long __ovld __cnfn convert_long_sat(uchar);
long __ovld __cnfn convert_long_rte(short);
long __ovld __cnfn convert_long_sat_rte(short);
long __ovld __cnfn convert_long_rtz(short);
long __ovld __cnfn convert_long_sat_rtz(short);
long __ovld __cnfn convert_long_rtp(short);
long __ovld __cnfn convert_long_sat_rtp(short);
long __ovld __cnfn convert_long_rtn(short);
long __ovld __cnfn convert_long_sat_rtn(short);
long __ovld __cnfn convert_long(short);
long __ovld __cnfn convert_long_sat(short);
long __ovld __cnfn convert_long_rte(ushort);
long __ovld __cnfn convert_long_sat_rte(ushort);
long __ovld __cnfn convert_long_rtz(ushort);
long __ovld __cnfn convert_long_sat_rtz(ushort);
long __ovld __cnfn convert_long_rtp(ushort);
long __ovld __cnfn convert_long_sat_rtp(ushort);
long __ovld __cnfn convert_long_rtn(ushort);
long __ovld __cnfn convert_long_sat_rtn(ushort);
long __ovld __cnfn convert_long(ushort);
long __ovld __cnfn convert_long_sat(ushort);
long __ovld __cnfn convert_long_rte(int);
long __ovld __cnfn convert_long_sat_rte(int);
long __ovld __cnfn convert_long_rtz(int);
long __ovld __cnfn convert_long_sat_rtz(int);
long __ovld __cnfn convert_long_rtp(int);
long __ovld __cnfn convert_long_sat_rtp(int);
long __ovld __cnfn convert_long_rtn(int);
long __ovld __cnfn convert_long_sat_rtn(int);
long __ovld __cnfn convert_long(int);
long __ovld __cnfn convert_long_sat(int);
long __ovld __cnfn convert_long_rte(uint);
long __ovld __cnfn convert_long_sat_rte(uint);
long __ovld __cnfn convert_long_rtz(uint);
long __ovld __cnfn convert_long_sat_rtz(uint);
long __ovld __cnfn convert_long_rtp(uint);
long __ovld __cnfn convert_long_sat_rtp(uint);
long __ovld __cnfn convert_long_rtn(uint);
long __ovld __cnfn convert_long_sat_rtn(uint);
long __ovld __cnfn convert_long(uint);
long __ovld __cnfn convert_long_sat(uint);
long __ovld __cnfn convert_long_rte(long);
long __ovld __cnfn convert_long_sat_rte(long);
long __ovld __cnfn convert_long_rtz(long);
long __ovld __cnfn convert_long_sat_rtz(long);
long __ovld __cnfn convert_long_rtp(long);
long __ovld __cnfn convert_long_sat_rtp(long);
long __ovld __cnfn convert_long_rtn(long);
long __ovld __cnfn convert_long_sat_rtn(long);
long __ovld __cnfn convert_long(long);
long __ovld __cnfn convert_long_sat(long);
long __ovld __cnfn convert_long_rte(ulong);
long __ovld __cnfn convert_long_sat_rte(ulong);
long __ovld __cnfn convert_long_rtz(ulong);
long __ovld __cnfn convert_long_sat_rtz(ulong);
long __ovld __cnfn convert_long_rtp(ulong);
long __ovld __cnfn convert_long_sat_rtp(ulong);
long __ovld __cnfn convert_long_rtn(ulong);
long __ovld __cnfn convert_long_sat_rtn(ulong);
long __ovld __cnfn convert_long(ulong);
long __ovld __cnfn convert_long_sat(ulong);
long __ovld __cnfn convert_long_rte(float);
long __ovld __cnfn convert_long_sat_rte(float);
long __ovld __cnfn convert_long_rtz(float);
long __ovld __cnfn convert_long_sat_rtz(float);
long __ovld __cnfn convert_long_rtp(float);
long __ovld __cnfn convert_long_sat_rtp(float);
long __ovld __cnfn convert_long_rtn(float);
long __ovld __cnfn convert_long_sat_rtn(float);
long __ovld __cnfn convert_long(float);
long __ovld __cnfn convert_long_sat(float);
ulong __ovld __cnfn convert_ulong_rte(char);
ulong __ovld __cnfn convert_ulong_sat_rte(char);
ulong __ovld __cnfn convert_ulong_rtz(char);
ulong __ovld __cnfn convert_ulong_sat_rtz(char);
ulong __ovld __cnfn convert_ulong_rtp(char);
ulong __ovld __cnfn convert_ulong_sat_rtp(char);
ulong __ovld __cnfn convert_ulong_rtn(char);
ulong __ovld __cnfn convert_ulong_sat_rtn(char);
ulong __ovld __cnfn convert_ulong(char);
ulong __ovld __cnfn convert_ulong_sat(char);
ulong __ovld __cnfn convert_ulong_rte(uchar);
ulong __ovld __cnfn convert_ulong_sat_rte(uchar);
ulong __ovld __cnfn convert_ulong_rtz(uchar);
ulong __ovld __cnfn convert_ulong_sat_rtz(uchar);
ulong __ovld __cnfn convert_ulong_rtp(uchar);
ulong __ovld __cnfn convert_ulong_sat_rtp(uchar);
ulong __ovld __cnfn convert_ulong_rtn(uchar);
ulong __ovld __cnfn convert_ulong_sat_rtn(uchar);
ulong __ovld __cnfn convert_ulong(uchar);
ulong __ovld __cnfn convert_ulong_sat(uchar);
ulong __ovld __cnfn convert_ulong_rte(short);
ulong __ovld __cnfn convert_ulong_sat_rte(short);
ulong __ovld __cnfn convert_ulong_rtz(short);
ulong __ovld __cnfn convert_ulong_sat_rtz(short);
ulong __ovld __cnfn convert_ulong_rtp(short);
ulong __ovld __cnfn convert_ulong_sat_rtp(short);
ulong __ovld __cnfn convert_ulong_rtn(short);
ulong __ovld __cnfn convert_ulong_sat_rtn(short);
ulong __ovld __cnfn convert_ulong(short);
ulong __ovld __cnfn convert_ulong_sat(short);
ulong __ovld __cnfn convert_ulong_rte(ushort);
ulong __ovld __cnfn convert_ulong_sat_rte(ushort);
ulong __ovld __cnfn convert_ulong_rtz(ushort);
ulong __ovld __cnfn convert_ulong_sat_rtz(ushort);
ulong __ovld __cnfn convert_ulong_rtp(ushort);
ulong __ovld __cnfn convert_ulong_sat_rtp(ushort);
ulong __ovld __cnfn convert_ulong_rtn(ushort);
ulong __ovld __cnfn convert_ulong_sat_rtn(ushort);
ulong __ovld __cnfn convert_ulong(ushort);
ulong __ovld __cnfn convert_ulong_sat(ushort);
ulong __ovld __cnfn convert_ulong_rte(int);
ulong __ovld __cnfn convert_ulong_sat_rte(int);
ulong __ovld __cnfn convert_ulong_rtz(int);
ulong __ovld __cnfn convert_ulong_sat_rtz(int);
ulong __ovld __cnfn convert_ulong_rtp(int);
ulong __ovld __cnfn convert_ulong_sat_rtp(int);
ulong __ovld __cnfn convert_ulong_rtn(int);
ulong __ovld __cnfn convert_ulong_sat_rtn(int);
ulong __ovld __cnfn convert_ulong(int);
ulong __ovld __cnfn convert_ulong_sat(int);
ulong __ovld __cnfn convert_ulong_rte(uint);
ulong __ovld __cnfn convert_ulong_sat_rte(uint);
ulong __ovld __cnfn convert_ulong_rtz(uint);
ulong __ovld __cnfn convert_ulong_sat_rtz(uint);
ulong __ovld __cnfn convert_ulong_rtp(uint);
ulong __ovld __cnfn convert_ulong_sat_rtp(uint);
ulong __ovld __cnfn convert_ulong_rtn(uint);
ulong __ovld __cnfn convert_ulong_sat_rtn(uint);
ulong __ovld __cnfn convert_ulong(uint);
ulong __ovld __cnfn convert_ulong_sat(uint);
ulong __ovld __cnfn convert_ulong_rte(long);
ulong __ovld __cnfn convert_ulong_sat_rte(long);
ulong __ovld __cnfn convert_ulong_rtz(long);
ulong __ovld __cnfn convert_ulong_sat_rtz(long);
ulong __ovld __cnfn convert_ulong_rtp(long);
ulong __ovld __cnfn convert_ulong_sat_rtp(long);
ulong __ovld __cnfn convert_ulong_rtn(long);
ulong __ovld __cnfn convert_ulong_sat_rtn(long);
ulong __ovld __cnfn convert_ulong(long);
ulong __ovld __cnfn convert_ulong_sat(long);
ulong __ovld __cnfn convert_ulong_rte(ulong);
ulong __ovld __cnfn convert_ulong_sat_rte(ulong);
ulong __ovld __cnfn convert_ulong_rtz(ulong);
ulong __ovld __cnfn convert_ulong_sat_rtz(ulong);
ulong __ovld __cnfn convert_ulong_rtp(ulong);
ulong __ovld __cnfn convert_ulong_sat_rtp(ulong);
ulong __ovld __cnfn convert_ulong_rtn(ulong);
ulong __ovld __cnfn convert_ulong_sat_rtn(ulong);
ulong __ovld __cnfn convert_ulong(ulong);
ulong __ovld __cnfn convert_ulong_sat(ulong);
ulong __ovld __cnfn convert_ulong_rte(float);
ulong __ovld __cnfn convert_ulong_sat_rte(float);
ulong __ovld __cnfn convert_ulong_rtz(float);
ulong __ovld __cnfn convert_ulong_sat_rtz(float);
ulong __ovld __cnfn convert_ulong_rtp(float);
ulong __ovld __cnfn convert_ulong_sat_rtp(float);
ulong __ovld __cnfn convert_ulong_rtn(float);
ulong __ovld __cnfn convert_ulong_sat_rtn(float);
ulong __ovld __cnfn convert_ulong(float);
ulong __ovld __cnfn convert_ulong_sat(float);
float __ovld __cnfn convert_float_rte(char);
float __ovld __cnfn convert_float_rtz(char);
float __ovld __cnfn convert_float_rtp(char);
float __ovld __cnfn convert_float_rtn(char);
float __ovld __cnfn convert_float(char);
float __ovld __cnfn convert_float_rte(uchar);
float __ovld __cnfn convert_float_rtz(uchar);
float __ovld __cnfn convert_float_rtp(uchar);
float __ovld __cnfn convert_float_rtn(uchar);
float __ovld __cnfn convert_float(uchar);
float __ovld __cnfn convert_float_rte(short);
float __ovld __cnfn convert_float_rtz(short);
float __ovld __cnfn convert_float_rtp(short);
float __ovld __cnfn convert_float_rtn(short);
float __ovld __cnfn convert_float(short);
float __ovld __cnfn convert_float_rte(ushort);
float __ovld __cnfn convert_float_rtz(ushort);
float __ovld __cnfn convert_float_rtp(ushort);
float __ovld __cnfn convert_float_rtn(ushort);
float __ovld __cnfn convert_float(ushort);
float __ovld __cnfn convert_float_rte(int);
float __ovld __cnfn convert_float_rtz(int);
float __ovld __cnfn convert_float_rtp(int);
float __ovld __cnfn convert_float_rtn(int);
float __ovld __cnfn convert_float(int);
float __ovld __cnfn convert_float_rte(uint);
float __ovld __cnfn convert_float_rtz(uint);
float __ovld __cnfn convert_float_rtp(uint);
float __ovld __cnfn convert_float_rtn(uint);
float __ovld __cnfn convert_float(uint);
float __ovld __cnfn convert_float_rte(long);
float __ovld __cnfn convert_float_rtz(long);
float __ovld __cnfn convert_float_rtp(long);
float __ovld __cnfn convert_float_rtn(long);
float __ovld __cnfn convert_float(long);
float __ovld __cnfn convert_float_rte(ulong);
float __ovld __cnfn convert_float_rtz(ulong);
float __ovld __cnfn convert_float_rtp(ulong);
float __ovld __cnfn convert_float_rtn(ulong);
float __ovld __cnfn convert_float(ulong);
float __ovld __cnfn convert_float_rte(float);
float __ovld __cnfn convert_float_rtz(float);
float __ovld __cnfn convert_float_rtp(float);
float __ovld __cnfn convert_float_rtn(float);
float __ovld __cnfn convert_float(float);
char2 __ovld __cnfn convert_char2_rte(char2);
char2 __ovld __cnfn convert_char2_sat_rte(char2);
char2 __ovld __cnfn convert_char2_rtz(char2);
char2 __ovld __cnfn convert_char2_sat_rtz(char2);
char2 __ovld __cnfn convert_char2_rtp(char2);
char2 __ovld __cnfn convert_char2_sat_rtp(char2);
char2 __ovld __cnfn convert_char2_rtn(char2);
char2 __ovld __cnfn convert_char2_sat_rtn(char2);
char2 __ovld __cnfn convert_char2(char2);
char2 __ovld __cnfn convert_char2_sat(char2);
char2 __ovld __cnfn convert_char2_rte(uchar2);
char2 __ovld __cnfn convert_char2_sat_rte(uchar2);
char2 __ovld __cnfn convert_char2_rtz(uchar2);
char2 __ovld __cnfn convert_char2_sat_rtz(uchar2);
char2 __ovld __cnfn convert_char2_rtp(uchar2);
char2 __ovld __cnfn convert_char2_sat_rtp(uchar2);
char2 __ovld __cnfn convert_char2_rtn(uchar2);
char2 __ovld __cnfn convert_char2_sat_rtn(uchar2);
char2 __ovld __cnfn convert_char2(uchar2);
char2 __ovld __cnfn convert_char2_sat(uchar2);
char2 __ovld __cnfn convert_char2_rte(short2);
char2 __ovld __cnfn convert_char2_sat_rte(short2);
char2 __ovld __cnfn convert_char2_rtz(short2);
char2 __ovld __cnfn convert_char2_sat_rtz(short2);
char2 __ovld __cnfn convert_char2_rtp(short2);
char2 __ovld __cnfn convert_char2_sat_rtp(short2);
char2 __ovld __cnfn convert_char2_rtn(short2);
char2 __ovld __cnfn convert_char2_sat_rtn(short2);
char2 __ovld __cnfn convert_char2(short2);
char2 __ovld __cnfn convert_char2_sat(short2);
char2 __ovld __cnfn convert_char2_rte(ushort2);
char2 __ovld __cnfn convert_char2_sat_rte(ushort2);
char2 __ovld __cnfn convert_char2_rtz(ushort2);
char2 __ovld __cnfn convert_char2_sat_rtz(ushort2);
char2 __ovld __cnfn convert_char2_rtp(ushort2);
char2 __ovld __cnfn convert_char2_sat_rtp(ushort2);
char2 __ovld __cnfn convert_char2_rtn(ushort2);
char2 __ovld __cnfn convert_char2_sat_rtn(ushort2);
char2 __ovld __cnfn convert_char2(ushort2);
char2 __ovld __cnfn convert_char2_sat(ushort2);
char2 __ovld __cnfn convert_char2_rte(int2);
char2 __ovld __cnfn convert_char2_sat_rte(int2);
char2 __ovld __cnfn convert_char2_rtz(int2);
char2 __ovld __cnfn convert_char2_sat_rtz(int2);
char2 __ovld __cnfn convert_char2_rtp(int2);
char2 __ovld __cnfn convert_char2_sat_rtp(int2);
char2 __ovld __cnfn convert_char2_rtn(int2);
char2 __ovld __cnfn convert_char2_sat_rtn(int2);
char2 __ovld __cnfn convert_char2(int2);
char2 __ovld __cnfn convert_char2_sat(int2);
char2 __ovld __cnfn convert_char2_rte(uint2);
char2 __ovld __cnfn convert_char2_sat_rte(uint2);
char2 __ovld __cnfn convert_char2_rtz(uint2);
char2 __ovld __cnfn convert_char2_sat_rtz(uint2);
char2 __ovld __cnfn convert_char2_rtp(uint2);
char2 __ovld __cnfn convert_char2_sat_rtp(uint2);
char2 __ovld __cnfn convert_char2_rtn(uint2);
char2 __ovld __cnfn convert_char2_sat_rtn(uint2);
char2 __ovld __cnfn convert_char2(uint2);
char2 __ovld __cnfn convert_char2_sat(uint2);
char2 __ovld __cnfn convert_char2_rte(long2);
char2 __ovld __cnfn convert_char2_sat_rte(long2);
char2 __ovld __cnfn convert_char2_rtz(long2);
char2 __ovld __cnfn convert_char2_sat_rtz(long2);
char2 __ovld __cnfn convert_char2_rtp(long2);
char2 __ovld __cnfn convert_char2_sat_rtp(long2);
char2 __ovld __cnfn convert_char2_rtn(long2);
char2 __ovld __cnfn convert_char2_sat_rtn(long2);
char2 __ovld __cnfn convert_char2(long2);
char2 __ovld __cnfn convert_char2_sat(long2);
char2 __ovld __cnfn convert_char2_rte(ulong2);
char2 __ovld __cnfn convert_char2_sat_rte(ulong2);
char2 __ovld __cnfn convert_char2_rtz(ulong2);
char2 __ovld __cnfn convert_char2_sat_rtz(ulong2);
char2 __ovld __cnfn convert_char2_rtp(ulong2);
char2 __ovld __cnfn convert_char2_sat_rtp(ulong2);
char2 __ovld __cnfn convert_char2_rtn(ulong2);
char2 __ovld __cnfn convert_char2_sat_rtn(ulong2);
char2 __ovld __cnfn convert_char2(ulong2);
char2 __ovld __cnfn convert_char2_sat(ulong2);
char2 __ovld __cnfn convert_char2_rte(float2);
char2 __ovld __cnfn convert_char2_sat_rte(float2);
char2 __ovld __cnfn convert_char2_rtz(float2);
char2 __ovld __cnfn convert_char2_sat_rtz(float2);
char2 __ovld __cnfn convert_char2_rtp(float2);
char2 __ovld __cnfn convert_char2_sat_rtp(float2);
char2 __ovld __cnfn convert_char2_rtn(float2);
char2 __ovld __cnfn convert_char2_sat_rtn(float2);
char2 __ovld __cnfn convert_char2(float2);
char2 __ovld __cnfn convert_char2_sat(float2);
uchar2 __ovld __cnfn convert_uchar2_rte(char2);
uchar2 __ovld __cnfn convert_uchar2_sat_rte(char2);
uchar2 __ovld __cnfn convert_uchar2_rtz(char2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtz(char2);
uchar2 __ovld __cnfn convert_uchar2_rtp(char2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtp(char2);
uchar2 __ovld __cnfn convert_uchar2_rtn(char2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtn(char2);
uchar2 __ovld __cnfn convert_uchar2(char2);
uchar2 __ovld __cnfn convert_uchar2_sat(char2);
uchar2 __ovld __cnfn convert_uchar2_rte(uchar2);
uchar2 __ovld __cnfn convert_uchar2_sat_rte(uchar2);
uchar2 __ovld __cnfn convert_uchar2_rtz(uchar2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtz(uchar2);
uchar2 __ovld __cnfn convert_uchar2_rtp(uchar2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtp(uchar2);
uchar2 __ovld __cnfn convert_uchar2_rtn(uchar2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtn(uchar2);
uchar2 __ovld __cnfn convert_uchar2(uchar2);
uchar2 __ovld __cnfn convert_uchar2_sat(uchar2);
uchar2 __ovld __cnfn convert_uchar2_rte(short2);
uchar2 __ovld __cnfn convert_uchar2_sat_rte(short2);
uchar2 __ovld __cnfn convert_uchar2_rtz(short2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtz(short2);
uchar2 __ovld __cnfn convert_uchar2_rtp(short2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtp(short2);
uchar2 __ovld __cnfn convert_uchar2_rtn(short2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtn(short2);
uchar2 __ovld __cnfn convert_uchar2(short2);
uchar2 __ovld __cnfn convert_uchar2_sat(short2);
uchar2 __ovld __cnfn convert_uchar2_rte(ushort2);
uchar2 __ovld __cnfn convert_uchar2_sat_rte(ushort2);
uchar2 __ovld __cnfn convert_uchar2_rtz(ushort2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtz(ushort2);
uchar2 __ovld __cnfn convert_uchar2_rtp(ushort2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtp(ushort2);
uchar2 __ovld __cnfn convert_uchar2_rtn(ushort2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtn(ushort2);
uchar2 __ovld __cnfn convert_uchar2(ushort2);
uchar2 __ovld __cnfn convert_uchar2_sat(ushort2);
uchar2 __ovld __cnfn convert_uchar2_rte(int2);
uchar2 __ovld __cnfn convert_uchar2_sat_rte(int2);
uchar2 __ovld __cnfn convert_uchar2_rtz(int2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtz(int2);
uchar2 __ovld __cnfn convert_uchar2_rtp(int2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtp(int2);
uchar2 __ovld __cnfn convert_uchar2_rtn(int2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtn(int2);
uchar2 __ovld __cnfn convert_uchar2(int2);
uchar2 __ovld __cnfn convert_uchar2_sat(int2);
uchar2 __ovld __cnfn convert_uchar2_rte(uint2);
uchar2 __ovld __cnfn convert_uchar2_sat_rte(uint2);
uchar2 __ovld __cnfn convert_uchar2_rtz(uint2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtz(uint2);
uchar2 __ovld __cnfn convert_uchar2_rtp(uint2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtp(uint2);
uchar2 __ovld __cnfn convert_uchar2_rtn(uint2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtn(uint2);
uchar2 __ovld __cnfn convert_uchar2(uint2);
uchar2 __ovld __cnfn convert_uchar2_sat(uint2);
uchar2 __ovld __cnfn convert_uchar2_rte(long2);
uchar2 __ovld __cnfn convert_uchar2_sat_rte(long2);
uchar2 __ovld __cnfn convert_uchar2_rtz(long2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtz(long2);
uchar2 __ovld __cnfn convert_uchar2_rtp(long2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtp(long2);
uchar2 __ovld __cnfn convert_uchar2_rtn(long2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtn(long2);
uchar2 __ovld __cnfn convert_uchar2(long2);
uchar2 __ovld __cnfn convert_uchar2_sat(long2);
uchar2 __ovld __cnfn convert_uchar2_rte(ulong2);
uchar2 __ovld __cnfn convert_uchar2_sat_rte(ulong2);
uchar2 __ovld __cnfn convert_uchar2_rtz(ulong2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtz(ulong2);
uchar2 __ovld __cnfn convert_uchar2_rtp(ulong2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtp(ulong2);
uchar2 __ovld __cnfn convert_uchar2_rtn(ulong2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtn(ulong2);
uchar2 __ovld __cnfn convert_uchar2(ulong2);
uchar2 __ovld __cnfn convert_uchar2_sat(ulong2);
uchar2 __ovld __cnfn convert_uchar2_rte(float2);
uchar2 __ovld __cnfn convert_uchar2_sat_rte(float2);
uchar2 __ovld __cnfn convert_uchar2_rtz(float2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtz(float2);
uchar2 __ovld __cnfn convert_uchar2_rtp(float2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtp(float2);
uchar2 __ovld __cnfn convert_uchar2_rtn(float2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtn(float2);
uchar2 __ovld __cnfn convert_uchar2(float2);
uchar2 __ovld __cnfn convert_uchar2_sat(float2);
short2 __ovld __cnfn convert_short2_rte(char2);
short2 __ovld __cnfn convert_short2_sat_rte(char2);
short2 __ovld __cnfn convert_short2_rtz(char2);
short2 __ovld __cnfn convert_short2_sat_rtz(char2);
short2 __ovld __cnfn convert_short2_rtp(char2);
short2 __ovld __cnfn convert_short2_sat_rtp(char2);
short2 __ovld __cnfn convert_short2_rtn(char2);
short2 __ovld __cnfn convert_short2_sat_rtn(char2);
short2 __ovld __cnfn convert_short2(char2);
short2 __ovld __cnfn convert_short2_sat(char2);
short2 __ovld __cnfn convert_short2_rte(uchar2);
short2 __ovld __cnfn convert_short2_sat_rte(uchar2);
short2 __ovld __cnfn convert_short2_rtz(uchar2);
short2 __ovld __cnfn convert_short2_sat_rtz(uchar2);
short2 __ovld __cnfn convert_short2_rtp(uchar2);
short2 __ovld __cnfn convert_short2_sat_rtp(uchar2);
short2 __ovld __cnfn convert_short2_rtn(uchar2);
short2 __ovld __cnfn convert_short2_sat_rtn(uchar2);
short2 __ovld __cnfn convert_short2(uchar2);
short2 __ovld __cnfn convert_short2_sat(uchar2);
short2 __ovld __cnfn convert_short2_rte(short2);
short2 __ovld __cnfn convert_short2_sat_rte(short2);
short2 __ovld __cnfn convert_short2_rtz(short2);
short2 __ovld __cnfn convert_short2_sat_rtz(short2);
short2 __ovld __cnfn convert_short2_rtp(short2);
short2 __ovld __cnfn convert_short2_sat_rtp(short2);
short2 __ovld __cnfn convert_short2_rtn(short2);
short2 __ovld __cnfn convert_short2_sat_rtn(short2);
short2 __ovld __cnfn convert_short2(short2);
short2 __ovld __cnfn convert_short2_sat(short2);
short2 __ovld __cnfn convert_short2_rte(ushort2);
short2 __ovld __cnfn convert_short2_sat_rte(ushort2);
short2 __ovld __cnfn convert_short2_rtz(ushort2);
short2 __ovld __cnfn convert_short2_sat_rtz(ushort2);
short2 __ovld __cnfn convert_short2_rtp(ushort2);
short2 __ovld __cnfn convert_short2_sat_rtp(ushort2);
short2 __ovld __cnfn convert_short2_rtn(ushort2);
short2 __ovld __cnfn convert_short2_sat_rtn(ushort2);
short2 __ovld __cnfn convert_short2(ushort2);
short2 __ovld __cnfn convert_short2_sat(ushort2);
short2 __ovld __cnfn convert_short2_rte(int2);
short2 __ovld __cnfn convert_short2_sat_rte(int2);
short2 __ovld __cnfn convert_short2_rtz(int2);
short2 __ovld __cnfn convert_short2_sat_rtz(int2);
short2 __ovld __cnfn convert_short2_rtp(int2);
short2 __ovld __cnfn convert_short2_sat_rtp(int2);
short2 __ovld __cnfn convert_short2_rtn(int2);
short2 __ovld __cnfn convert_short2_sat_rtn(int2);
short2 __ovld __cnfn convert_short2(int2);
short2 __ovld __cnfn convert_short2_sat(int2);
short2 __ovld __cnfn convert_short2_rte(uint2);
short2 __ovld __cnfn convert_short2_sat_rte(uint2);
short2 __ovld __cnfn convert_short2_rtz(uint2);
short2 __ovld __cnfn convert_short2_sat_rtz(uint2);
short2 __ovld __cnfn convert_short2_rtp(uint2);
short2 __ovld __cnfn convert_short2_sat_rtp(uint2);
short2 __ovld __cnfn convert_short2_rtn(uint2);
short2 __ovld __cnfn convert_short2_sat_rtn(uint2);
short2 __ovld __cnfn convert_short2(uint2);
short2 __ovld __cnfn convert_short2_sat(uint2);
short2 __ovld __cnfn convert_short2_rte(long2);
short2 __ovld __cnfn convert_short2_sat_rte(long2);
short2 __ovld __cnfn convert_short2_rtz(long2);
short2 __ovld __cnfn convert_short2_sat_rtz(long2);
short2 __ovld __cnfn convert_short2_rtp(long2);
short2 __ovld __cnfn convert_short2_sat_rtp(long2);
short2 __ovld __cnfn convert_short2_rtn(long2);
short2 __ovld __cnfn convert_short2_sat_rtn(long2);
short2 __ovld __cnfn convert_short2(long2);
short2 __ovld __cnfn convert_short2_sat(long2);
short2 __ovld __cnfn convert_short2_rte(ulong2);
short2 __ovld __cnfn convert_short2_sat_rte(ulong2);
short2 __ovld __cnfn convert_short2_rtz(ulong2);
short2 __ovld __cnfn convert_short2_sat_rtz(ulong2);
short2 __ovld __cnfn convert_short2_rtp(ulong2);
short2 __ovld __cnfn convert_short2_sat_rtp(ulong2);
short2 __ovld __cnfn convert_short2_rtn(ulong2);
short2 __ovld __cnfn convert_short2_sat_rtn(ulong2);
short2 __ovld __cnfn convert_short2(ulong2);
short2 __ovld __cnfn convert_short2_sat(ulong2);
short2 __ovld __cnfn convert_short2_rte(float2);
short2 __ovld __cnfn convert_short2_sat_rte(float2);
short2 __ovld __cnfn convert_short2_rtz(float2);
short2 __ovld __cnfn convert_short2_sat_rtz(float2);
short2 __ovld __cnfn convert_short2_rtp(float2);
short2 __ovld __cnfn convert_short2_sat_rtp(float2);
short2 __ovld __cnfn convert_short2_rtn(float2);
short2 __ovld __cnfn convert_short2_sat_rtn(float2);
short2 __ovld __cnfn convert_short2(float2);
short2 __ovld __cnfn convert_short2_sat(float2);
ushort2 __ovld __cnfn convert_ushort2_rte(char2);
ushort2 __ovld __cnfn convert_ushort2_sat_rte(char2);
ushort2 __ovld __cnfn convert_ushort2_rtz(char2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtz(char2);
ushort2 __ovld __cnfn convert_ushort2_rtp(char2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtp(char2);
ushort2 __ovld __cnfn convert_ushort2_rtn(char2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtn(char2);
ushort2 __ovld __cnfn convert_ushort2(char2);
ushort2 __ovld __cnfn convert_ushort2_sat(char2);
ushort2 __ovld __cnfn convert_ushort2_rte(uchar2);
ushort2 __ovld __cnfn convert_ushort2_sat_rte(uchar2);
ushort2 __ovld __cnfn convert_ushort2_rtz(uchar2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtz(uchar2);
ushort2 __ovld __cnfn convert_ushort2_rtp(uchar2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtp(uchar2);
ushort2 __ovld __cnfn convert_ushort2_rtn(uchar2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtn(uchar2);
ushort2 __ovld __cnfn convert_ushort2(uchar2);
ushort2 __ovld __cnfn convert_ushort2_sat(uchar2);
ushort2 __ovld __cnfn convert_ushort2_rte(short2);
ushort2 __ovld __cnfn convert_ushort2_sat_rte(short2);
ushort2 __ovld __cnfn convert_ushort2_rtz(short2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtz(short2);
ushort2 __ovld __cnfn convert_ushort2_rtp(short2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtp(short2);
ushort2 __ovld __cnfn convert_ushort2_rtn(short2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtn(short2);
ushort2 __ovld __cnfn convert_ushort2(short2);
ushort2 __ovld __cnfn convert_ushort2_sat(short2);
ushort2 __ovld __cnfn convert_ushort2_rte(ushort2);
ushort2 __ovld __cnfn convert_ushort2_sat_rte(ushort2);
ushort2 __ovld __cnfn convert_ushort2_rtz(ushort2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtz(ushort2);
ushort2 __ovld __cnfn convert_ushort2_rtp(ushort2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtp(ushort2);
ushort2 __ovld __cnfn convert_ushort2_rtn(ushort2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtn(ushort2);
ushort2 __ovld __cnfn convert_ushort2(ushort2);
ushort2 __ovld __cnfn convert_ushort2_sat(ushort2);
ushort2 __ovld __cnfn convert_ushort2_rte(int2);
ushort2 __ovld __cnfn convert_ushort2_sat_rte(int2);
ushort2 __ovld __cnfn convert_ushort2_rtz(int2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtz(int2);
ushort2 __ovld __cnfn convert_ushort2_rtp(int2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtp(int2);
ushort2 __ovld __cnfn convert_ushort2_rtn(int2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtn(int2);
ushort2 __ovld __cnfn convert_ushort2(int2);
ushort2 __ovld __cnfn convert_ushort2_sat(int2);
ushort2 __ovld __cnfn convert_ushort2_rte(uint2);
ushort2 __ovld __cnfn convert_ushort2_sat_rte(uint2);
ushort2 __ovld __cnfn convert_ushort2_rtz(uint2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtz(uint2);
ushort2 __ovld __cnfn convert_ushort2_rtp(uint2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtp(uint2);
ushort2 __ovld __cnfn convert_ushort2_rtn(uint2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtn(uint2);
ushort2 __ovld __cnfn convert_ushort2(uint2);
ushort2 __ovld __cnfn convert_ushort2_sat(uint2);
ushort2 __ovld __cnfn convert_ushort2_rte(long2);
ushort2 __ovld __cnfn convert_ushort2_sat_rte(long2);
ushort2 __ovld __cnfn convert_ushort2_rtz(long2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtz(long2);
ushort2 __ovld __cnfn convert_ushort2_rtp(long2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtp(long2);
ushort2 __ovld __cnfn convert_ushort2_rtn(long2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtn(long2);
ushort2 __ovld __cnfn convert_ushort2(long2);
ushort2 __ovld __cnfn convert_ushort2_sat(long2);
ushort2 __ovld __cnfn convert_ushort2_rte(ulong2);
ushort2 __ovld __cnfn convert_ushort2_sat_rte(ulong2);
ushort2 __ovld __cnfn convert_ushort2_rtz(ulong2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtz(ulong2);
ushort2 __ovld __cnfn convert_ushort2_rtp(ulong2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtp(ulong2);
ushort2 __ovld __cnfn convert_ushort2_rtn(ulong2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtn(ulong2);
ushort2 __ovld __cnfn convert_ushort2(ulong2);
ushort2 __ovld __cnfn convert_ushort2_sat(ulong2);
ushort2 __ovld __cnfn convert_ushort2_rte(float2);
ushort2 __ovld __cnfn convert_ushort2_sat_rte(float2);
ushort2 __ovld __cnfn convert_ushort2_rtz(float2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtz(float2);
ushort2 __ovld __cnfn convert_ushort2_rtp(float2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtp(float2);
ushort2 __ovld __cnfn convert_ushort2_rtn(float2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtn(float2);
ushort2 __ovld __cnfn convert_ushort2(float2);
ushort2 __ovld __cnfn convert_ushort2_sat(float2);
int2 __ovld __cnfn convert_int2_rte(char2);
int2 __ovld __cnfn convert_int2_sat_rte(char2);
int2 __ovld __cnfn convert_int2_rtz(char2);
int2 __ovld __cnfn convert_int2_sat_rtz(char2);
int2 __ovld __cnfn convert_int2_rtp(char2);
int2 __ovld __cnfn convert_int2_sat_rtp(char2);
int2 __ovld __cnfn convert_int2_rtn(char2);
int2 __ovld __cnfn convert_int2_sat_rtn(char2);
int2 __ovld __cnfn convert_int2(char2);
int2 __ovld __cnfn convert_int2_sat(char2);
int2 __ovld __cnfn convert_int2_rte(uchar2);
int2 __ovld __cnfn convert_int2_sat_rte(uchar2);
int2 __ovld __cnfn convert_int2_rtz(uchar2);
int2 __ovld __cnfn convert_int2_sat_rtz(uchar2);
int2 __ovld __cnfn convert_int2_rtp(uchar2);
int2 __ovld __cnfn convert_int2_sat_rtp(uchar2);
int2 __ovld __cnfn convert_int2_rtn(uchar2);
int2 __ovld __cnfn convert_int2_sat_rtn(uchar2);
int2 __ovld __cnfn convert_int2(uchar2);
int2 __ovld __cnfn convert_int2_sat(uchar2);
int2 __ovld __cnfn convert_int2_rte(short2);
int2 __ovld __cnfn convert_int2_sat_rte(short2);
int2 __ovld __cnfn convert_int2_rtz(short2);
int2 __ovld __cnfn convert_int2_sat_rtz(short2);
int2 __ovld __cnfn convert_int2_rtp(short2);
int2 __ovld __cnfn convert_int2_sat_rtp(short2);
int2 __ovld __cnfn convert_int2_rtn(short2);
int2 __ovld __cnfn convert_int2_sat_rtn(short2);
int2 __ovld __cnfn convert_int2(short2);
int2 __ovld __cnfn convert_int2_sat(short2);
int2 __ovld __cnfn convert_int2_rte(ushort2);
int2 __ovld __cnfn convert_int2_sat_rte(ushort2);
int2 __ovld __cnfn convert_int2_rtz(ushort2);
int2 __ovld __cnfn convert_int2_sat_rtz(ushort2);
int2 __ovld __cnfn convert_int2_rtp(ushort2);
int2 __ovld __cnfn convert_int2_sat_rtp(ushort2);
int2 __ovld __cnfn convert_int2_rtn(ushort2);
int2 __ovld __cnfn convert_int2_sat_rtn(ushort2);
int2 __ovld __cnfn convert_int2(ushort2);
int2 __ovld __cnfn convert_int2_sat(ushort2);
int2 __ovld __cnfn convert_int2_rte(int2);
int2 __ovld __cnfn convert_int2_sat_rte(int2);
int2 __ovld __cnfn convert_int2_rtz(int2);
int2 __ovld __cnfn convert_int2_sat_rtz(int2);
int2 __ovld __cnfn convert_int2_rtp(int2);
int2 __ovld __cnfn convert_int2_sat_rtp(int2);
int2 __ovld __cnfn convert_int2_rtn(int2);
int2 __ovld __cnfn convert_int2_sat_rtn(int2);
int2 __ovld __cnfn convert_int2(int2);
int2 __ovld __cnfn convert_int2_sat(int2);
int2 __ovld __cnfn convert_int2_rte(uint2);
int2 __ovld __cnfn convert_int2_sat_rte(uint2);
int2 __ovld __cnfn convert_int2_rtz(uint2);
int2 __ovld __cnfn convert_int2_sat_rtz(uint2);
int2 __ovld __cnfn convert_int2_rtp(uint2);
int2 __ovld __cnfn convert_int2_sat_rtp(uint2);
int2 __ovld __cnfn convert_int2_rtn(uint2);
int2 __ovld __cnfn convert_int2_sat_rtn(uint2);
int2 __ovld __cnfn convert_int2(uint2);
int2 __ovld __cnfn convert_int2_sat(uint2);
int2 __ovld __cnfn convert_int2_rte(long2);
int2 __ovld __cnfn convert_int2_sat_rte(long2);
int2 __ovld __cnfn convert_int2_rtz(long2);
int2 __ovld __cnfn convert_int2_sat_rtz(long2);
int2 __ovld __cnfn convert_int2_rtp(long2);
int2 __ovld __cnfn convert_int2_sat_rtp(long2);
int2 __ovld __cnfn convert_int2_rtn(long2);
int2 __ovld __cnfn convert_int2_sat_rtn(long2);
int2 __ovld __cnfn convert_int2(long2);
int2 __ovld __cnfn convert_int2_sat(long2);
int2 __ovld __cnfn convert_int2_rte(ulong2);
int2 __ovld __cnfn convert_int2_sat_rte(ulong2);
int2 __ovld __cnfn convert_int2_rtz(ulong2);
int2 __ovld __cnfn convert_int2_sat_rtz(ulong2);
int2 __ovld __cnfn convert_int2_rtp(ulong2);
int2 __ovld __cnfn convert_int2_sat_rtp(ulong2);
int2 __ovld __cnfn convert_int2_rtn(ulong2);
int2 __ovld __cnfn convert_int2_sat_rtn(ulong2);
int2 __ovld __cnfn convert_int2(ulong2);
int2 __ovld __cnfn convert_int2_sat(ulong2);
int2 __ovld __cnfn convert_int2_rte(float2);
int2 __ovld __cnfn convert_int2_sat_rte(float2);
int2 __ovld __cnfn convert_int2_rtz(float2);
int2 __ovld __cnfn convert_int2_sat_rtz(float2);
int2 __ovld __cnfn convert_int2_rtp(float2);
int2 __ovld __cnfn convert_int2_sat_rtp(float2);
int2 __ovld __cnfn convert_int2_rtn(float2);
int2 __ovld __cnfn convert_int2_sat_rtn(float2);
int2 __ovld __cnfn convert_int2(float2);
int2 __ovld __cnfn convert_int2_sat(float2);
uint2 __ovld __cnfn convert_uint2_rte(char2);
uint2 __ovld __cnfn convert_uint2_sat_rte(char2);
uint2 __ovld __cnfn convert_uint2_rtz(char2);
uint2 __ovld __cnfn convert_uint2_sat_rtz(char2);
uint2 __ovld __cnfn convert_uint2_rtp(char2);
uint2 __ovld __cnfn convert_uint2_sat_rtp(char2);
uint2 __ovld __cnfn convert_uint2_rtn(char2);
uint2 __ovld __cnfn convert_uint2_sat_rtn(char2);
uint2 __ovld __cnfn convert_uint2(char2);
uint2 __ovld __cnfn convert_uint2_sat(char2);
uint2 __ovld __cnfn convert_uint2_rte(uchar2);
uint2 __ovld __cnfn convert_uint2_sat_rte(uchar2);
uint2 __ovld __cnfn convert_uint2_rtz(uchar2);
uint2 __ovld __cnfn convert_uint2_sat_rtz(uchar2);
uint2 __ovld __cnfn convert_uint2_rtp(uchar2);
uint2 __ovld __cnfn convert_uint2_sat_rtp(uchar2);
uint2 __ovld __cnfn convert_uint2_rtn(uchar2);
uint2 __ovld __cnfn convert_uint2_sat_rtn(uchar2);
uint2 __ovld __cnfn convert_uint2(uchar2);
uint2 __ovld __cnfn convert_uint2_sat(uchar2);
uint2 __ovld __cnfn convert_uint2_rte(short2);
uint2 __ovld __cnfn convert_uint2_sat_rte(short2);
uint2 __ovld __cnfn convert_uint2_rtz(short2);
uint2 __ovld __cnfn convert_uint2_sat_rtz(short2);
uint2 __ovld __cnfn convert_uint2_rtp(short2);
uint2 __ovld __cnfn convert_uint2_sat_rtp(short2);
uint2 __ovld __cnfn convert_uint2_rtn(short2);
uint2 __ovld __cnfn convert_uint2_sat_rtn(short2);
uint2 __ovld __cnfn convert_uint2(short2);
uint2 __ovld __cnfn convert_uint2_sat(short2);
uint2 __ovld __cnfn convert_uint2_rte(ushort2);
uint2 __ovld __cnfn convert_uint2_sat_rte(ushort2);
uint2 __ovld __cnfn convert_uint2_rtz(ushort2);
uint2 __ovld __cnfn convert_uint2_sat_rtz(ushort2);
uint2 __ovld __cnfn convert_uint2_rtp(ushort2);
uint2 __ovld __cnfn convert_uint2_sat_rtp(ushort2);
uint2 __ovld __cnfn convert_uint2_rtn(ushort2);
uint2 __ovld __cnfn convert_uint2_sat_rtn(ushort2);
uint2 __ovld __cnfn convert_uint2(ushort2);
uint2 __ovld __cnfn convert_uint2_sat(ushort2);
uint2 __ovld __cnfn convert_uint2_rte(int2);
uint2 __ovld __cnfn convert_uint2_sat_rte(int2);
uint2 __ovld __cnfn convert_uint2_rtz(int2);
uint2 __ovld __cnfn convert_uint2_sat_rtz(int2);
uint2 __ovld __cnfn convert_uint2_rtp(int2);
uint2 __ovld __cnfn convert_uint2_sat_rtp(int2);
uint2 __ovld __cnfn convert_uint2_rtn(int2);
uint2 __ovld __cnfn convert_uint2_sat_rtn(int2);
uint2 __ovld __cnfn convert_uint2(int2);
uint2 __ovld __cnfn convert_uint2_sat(int2);
uint2 __ovld __cnfn convert_uint2_rte(uint2);
uint2 __ovld __cnfn convert_uint2_sat_rte(uint2);
uint2 __ovld __cnfn convert_uint2_rtz(uint2);
uint2 __ovld __cnfn convert_uint2_sat_rtz(uint2);
uint2 __ovld __cnfn convert_uint2_rtp(uint2);
uint2 __ovld __cnfn convert_uint2_sat_rtp(uint2);
uint2 __ovld __cnfn convert_uint2_rtn(uint2);
uint2 __ovld __cnfn convert_uint2_sat_rtn(uint2);
uint2 __ovld __cnfn convert_uint2(uint2);
uint2 __ovld __cnfn convert_uint2_sat(uint2);
uint2 __ovld __cnfn convert_uint2_rte(long2);
uint2 __ovld __cnfn convert_uint2_sat_rte(long2);
uint2 __ovld __cnfn convert_uint2_rtz(long2);
uint2 __ovld __cnfn convert_uint2_sat_rtz(long2);
uint2 __ovld __cnfn convert_uint2_rtp(long2);
uint2 __ovld __cnfn convert_uint2_sat_rtp(long2);
uint2 __ovld __cnfn convert_uint2_rtn(long2);
uint2 __ovld __cnfn convert_uint2_sat_rtn(long2);
uint2 __ovld __cnfn convert_uint2(long2);
uint2 __ovld __cnfn convert_uint2_sat(long2);
uint2 __ovld __cnfn convert_uint2_rte(ulong2);
uint2 __ovld __cnfn convert_uint2_sat_rte(ulong2);
uint2 __ovld __cnfn convert_uint2_rtz(ulong2);
uint2 __ovld __cnfn convert_uint2_sat_rtz(ulong2);
uint2 __ovld __cnfn convert_uint2_rtp(ulong2);
uint2 __ovld __cnfn convert_uint2_sat_rtp(ulong2);
uint2 __ovld __cnfn convert_uint2_rtn(ulong2);
uint2 __ovld __cnfn convert_uint2_sat_rtn(ulong2);
uint2 __ovld __cnfn convert_uint2(ulong2);
uint2 __ovld __cnfn convert_uint2_sat(ulong2);
uint2 __ovld __cnfn convert_uint2_rte(float2);
uint2 __ovld __cnfn convert_uint2_sat_rte(float2);
uint2 __ovld __cnfn convert_uint2_rtz(float2);
uint2 __ovld __cnfn convert_uint2_sat_rtz(float2);
uint2 __ovld __cnfn convert_uint2_rtp(float2);
uint2 __ovld __cnfn convert_uint2_sat_rtp(float2);
uint2 __ovld __cnfn convert_uint2_rtn(float2);
uint2 __ovld __cnfn convert_uint2_sat_rtn(float2);
uint2 __ovld __cnfn convert_uint2(float2);
uint2 __ovld __cnfn convert_uint2_sat(float2);
long2 __ovld __cnfn convert_long2_rte(char2);
long2 __ovld __cnfn convert_long2_sat_rte(char2);
long2 __ovld __cnfn convert_long2_rtz(char2);
long2 __ovld __cnfn convert_long2_sat_rtz(char2);
long2 __ovld __cnfn convert_long2_rtp(char2);
long2 __ovld __cnfn convert_long2_sat_rtp(char2);
long2 __ovld __cnfn convert_long2_rtn(char2);
long2 __ovld __cnfn convert_long2_sat_rtn(char2);
long2 __ovld __cnfn convert_long2(char2);
long2 __ovld __cnfn convert_long2_sat(char2);
long2 __ovld __cnfn convert_long2_rte(uchar2);
long2 __ovld __cnfn convert_long2_sat_rte(uchar2);
long2 __ovld __cnfn convert_long2_rtz(uchar2);
long2 __ovld __cnfn convert_long2_sat_rtz(uchar2);
long2 __ovld __cnfn convert_long2_rtp(uchar2);
long2 __ovld __cnfn convert_long2_sat_rtp(uchar2);
long2 __ovld __cnfn convert_long2_rtn(uchar2);
long2 __ovld __cnfn convert_long2_sat_rtn(uchar2);
long2 __ovld __cnfn convert_long2(uchar2);
long2 __ovld __cnfn convert_long2_sat(uchar2);
long2 __ovld __cnfn convert_long2_rte(short2);
long2 __ovld __cnfn convert_long2_sat_rte(short2);
long2 __ovld __cnfn convert_long2_rtz(short2);
long2 __ovld __cnfn convert_long2_sat_rtz(short2);
long2 __ovld __cnfn convert_long2_rtp(short2);
long2 __ovld __cnfn convert_long2_sat_rtp(short2);
long2 __ovld __cnfn convert_long2_rtn(short2);
long2 __ovld __cnfn convert_long2_sat_rtn(short2);
long2 __ovld __cnfn convert_long2(short2);
long2 __ovld __cnfn convert_long2_sat(short2);
long2 __ovld __cnfn convert_long2_rte(ushort2);
long2 __ovld __cnfn convert_long2_sat_rte(ushort2);
long2 __ovld __cnfn convert_long2_rtz(ushort2);
long2 __ovld __cnfn convert_long2_sat_rtz(ushort2);
long2 __ovld __cnfn convert_long2_rtp(ushort2);
long2 __ovld __cnfn convert_long2_sat_rtp(ushort2);
long2 __ovld __cnfn convert_long2_rtn(ushort2);
long2 __ovld __cnfn convert_long2_sat_rtn(ushort2);
long2 __ovld __cnfn convert_long2(ushort2);
long2 __ovld __cnfn convert_long2_sat(ushort2);
long2 __ovld __cnfn convert_long2_rte(int2);
long2 __ovld __cnfn convert_long2_sat_rte(int2);
long2 __ovld __cnfn convert_long2_rtz(int2);
long2 __ovld __cnfn convert_long2_sat_rtz(int2);
long2 __ovld __cnfn convert_long2_rtp(int2);
long2 __ovld __cnfn convert_long2_sat_rtp(int2);
long2 __ovld __cnfn convert_long2_rtn(int2);
long2 __ovld __cnfn convert_long2_sat_rtn(int2);
long2 __ovld __cnfn convert_long2(int2);
long2 __ovld __cnfn convert_long2_sat(int2);
long2 __ovld __cnfn convert_long2_rte(uint2);
long2 __ovld __cnfn convert_long2_sat_rte(uint2);
long2 __ovld __cnfn convert_long2_rtz(uint2);
long2 __ovld __cnfn convert_long2_sat_rtz(uint2);
long2 __ovld __cnfn convert_long2_rtp(uint2);
long2 __ovld __cnfn convert_long2_sat_rtp(uint2);
long2 __ovld __cnfn convert_long2_rtn(uint2);
long2 __ovld __cnfn convert_long2_sat_rtn(uint2);
long2 __ovld __cnfn convert_long2(uint2);
long2 __ovld __cnfn convert_long2_sat(uint2);
long2 __ovld __cnfn convert_long2_rte(long2);
long2 __ovld __cnfn convert_long2_sat_rte(long2);
long2 __ovld __cnfn convert_long2_rtz(long2);
long2 __ovld __cnfn convert_long2_sat_rtz(long2);
long2 __ovld __cnfn convert_long2_rtp(long2);
long2 __ovld __cnfn convert_long2_sat_rtp(long2);
long2 __ovld __cnfn convert_long2_rtn(long2);
long2 __ovld __cnfn convert_long2_sat_rtn(long2);
long2 __ovld __cnfn convert_long2(long2);
long2 __ovld __cnfn convert_long2_sat(long2);
long2 __ovld __cnfn convert_long2_rte(ulong2);
long2 __ovld __cnfn convert_long2_sat_rte(ulong2);
long2 __ovld __cnfn convert_long2_rtz(ulong2);
long2 __ovld __cnfn convert_long2_sat_rtz(ulong2);
long2 __ovld __cnfn convert_long2_rtp(ulong2);
long2 __ovld __cnfn convert_long2_sat_rtp(ulong2);
long2 __ovld __cnfn convert_long2_rtn(ulong2);
long2 __ovld __cnfn convert_long2_sat_rtn(ulong2);
long2 __ovld __cnfn convert_long2(ulong2);
long2 __ovld __cnfn convert_long2_sat(ulong2);
long2 __ovld __cnfn convert_long2_rte(float2);
long2 __ovld __cnfn convert_long2_sat_rte(float2);
long2 __ovld __cnfn convert_long2_rtz(float2);
long2 __ovld __cnfn convert_long2_sat_rtz(float2);
long2 __ovld __cnfn convert_long2_rtp(float2);
long2 __ovld __cnfn convert_long2_sat_rtp(float2);
long2 __ovld __cnfn convert_long2_rtn(float2);
long2 __ovld __cnfn convert_long2_sat_rtn(float2);
long2 __ovld __cnfn convert_long2(float2);
long2 __ovld __cnfn convert_long2_sat(float2);
ulong2 __ovld __cnfn convert_ulong2_rte(char2);
ulong2 __ovld __cnfn convert_ulong2_sat_rte(char2);
ulong2 __ovld __cnfn convert_ulong2_rtz(char2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtz(char2);
ulong2 __ovld __cnfn convert_ulong2_rtp(char2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtp(char2);
ulong2 __ovld __cnfn convert_ulong2_rtn(char2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtn(char2);
ulong2 __ovld __cnfn convert_ulong2(char2);
ulong2 __ovld __cnfn convert_ulong2_sat(char2);
ulong2 __ovld __cnfn convert_ulong2_rte(uchar2);
ulong2 __ovld __cnfn convert_ulong2_sat_rte(uchar2);
ulong2 __ovld __cnfn convert_ulong2_rtz(uchar2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtz(uchar2);
ulong2 __ovld __cnfn convert_ulong2_rtp(uchar2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtp(uchar2);
ulong2 __ovld __cnfn convert_ulong2_rtn(uchar2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtn(uchar2);
ulong2 __ovld __cnfn convert_ulong2(uchar2);
ulong2 __ovld __cnfn convert_ulong2_sat(uchar2);
ulong2 __ovld __cnfn convert_ulong2_rte(short2);
ulong2 __ovld __cnfn convert_ulong2_sat_rte(short2);
ulong2 __ovld __cnfn convert_ulong2_rtz(short2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtz(short2);
ulong2 __ovld __cnfn convert_ulong2_rtp(short2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtp(short2);
ulong2 __ovld __cnfn convert_ulong2_rtn(short2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtn(short2);
ulong2 __ovld __cnfn convert_ulong2(short2);
ulong2 __ovld __cnfn convert_ulong2_sat(short2);
ulong2 __ovld __cnfn convert_ulong2_rte(ushort2);
ulong2 __ovld __cnfn convert_ulong2_sat_rte(ushort2);
ulong2 __ovld __cnfn convert_ulong2_rtz(ushort2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtz(ushort2);
ulong2 __ovld __cnfn convert_ulong2_rtp(ushort2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtp(ushort2);
ulong2 __ovld __cnfn convert_ulong2_rtn(ushort2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtn(ushort2);
ulong2 __ovld __cnfn convert_ulong2(ushort2);
ulong2 __ovld __cnfn convert_ulong2_sat(ushort2);
ulong2 __ovld __cnfn convert_ulong2_rte(int2);
ulong2 __ovld __cnfn convert_ulong2_sat_rte(int2);
ulong2 __ovld __cnfn convert_ulong2_rtz(int2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtz(int2);
ulong2 __ovld __cnfn convert_ulong2_rtp(int2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtp(int2);
ulong2 __ovld __cnfn convert_ulong2_rtn(int2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtn(int2);
ulong2 __ovld __cnfn convert_ulong2(int2);
ulong2 __ovld __cnfn convert_ulong2_sat(int2);
ulong2 __ovld __cnfn convert_ulong2_rte(uint2);
ulong2 __ovld __cnfn convert_ulong2_sat_rte(uint2);
ulong2 __ovld __cnfn convert_ulong2_rtz(uint2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtz(uint2);
ulong2 __ovld __cnfn convert_ulong2_rtp(uint2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtp(uint2);
ulong2 __ovld __cnfn convert_ulong2_rtn(uint2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtn(uint2);
ulong2 __ovld __cnfn convert_ulong2(uint2);
ulong2 __ovld __cnfn convert_ulong2_sat(uint2);
ulong2 __ovld __cnfn convert_ulong2_rte(long2);
ulong2 __ovld __cnfn convert_ulong2_sat_rte(long2);
ulong2 __ovld __cnfn convert_ulong2_rtz(long2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtz(long2);
ulong2 __ovld __cnfn convert_ulong2_rtp(long2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtp(long2);
ulong2 __ovld __cnfn convert_ulong2_rtn(long2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtn(long2);
ulong2 __ovld __cnfn convert_ulong2(long2);
ulong2 __ovld __cnfn convert_ulong2_sat(long2);
ulong2 __ovld __cnfn convert_ulong2_rte(ulong2);
ulong2 __ovld __cnfn convert_ulong2_sat_rte(ulong2);
ulong2 __ovld __cnfn convert_ulong2_rtz(ulong2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtz(ulong2);
ulong2 __ovld __cnfn convert_ulong2_rtp(ulong2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtp(ulong2);
ulong2 __ovld __cnfn convert_ulong2_rtn(ulong2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtn(ulong2);
ulong2 __ovld __cnfn convert_ulong2(ulong2);
ulong2 __ovld __cnfn convert_ulong2_sat(ulong2);
ulong2 __ovld __cnfn convert_ulong2_rte(float2);
ulong2 __ovld __cnfn convert_ulong2_sat_rte(float2);
ulong2 __ovld __cnfn convert_ulong2_rtz(float2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtz(float2);
ulong2 __ovld __cnfn convert_ulong2_rtp(float2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtp(float2);
ulong2 __ovld __cnfn convert_ulong2_rtn(float2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtn(float2);
ulong2 __ovld __cnfn convert_ulong2(float2);
ulong2 __ovld __cnfn convert_ulong2_sat(float2);
float2 __ovld __cnfn convert_float2_rte(char2);
float2 __ovld __cnfn convert_float2_rtz(char2);
float2 __ovld __cnfn convert_float2_rtp(char2);
float2 __ovld __cnfn convert_float2_rtn(char2);
float2 __ovld __cnfn convert_float2(char2);
float2 __ovld __cnfn convert_float2_rte(uchar2);
float2 __ovld __cnfn convert_float2_rtz(uchar2);
float2 __ovld __cnfn convert_float2_rtp(uchar2);
float2 __ovld __cnfn convert_float2_rtn(uchar2);
float2 __ovld __cnfn convert_float2(uchar2);
float2 __ovld __cnfn convert_float2_rte(short2);
float2 __ovld __cnfn convert_float2_rtz(short2);
float2 __ovld __cnfn convert_float2_rtp(short2);
float2 __ovld __cnfn convert_float2_rtn(short2);
float2 __ovld __cnfn convert_float2(short2);
float2 __ovld __cnfn convert_float2_rte(ushort2);
float2 __ovld __cnfn convert_float2_rtz(ushort2);
float2 __ovld __cnfn convert_float2_rtp(ushort2);
float2 __ovld __cnfn convert_float2_rtn(ushort2);
float2 __ovld __cnfn convert_float2(ushort2);
float2 __ovld __cnfn convert_float2_rte(int2);
float2 __ovld __cnfn convert_float2_rtz(int2);
float2 __ovld __cnfn convert_float2_rtp(int2);
float2 __ovld __cnfn convert_float2_rtn(int2);
float2 __ovld __cnfn convert_float2(int2);
float2 __ovld __cnfn convert_float2_rte(uint2);
float2 __ovld __cnfn convert_float2_rtz(uint2);
float2 __ovld __cnfn convert_float2_rtp(uint2);
float2 __ovld __cnfn convert_float2_rtn(uint2);
float2 __ovld __cnfn convert_float2(uint2);
float2 __ovld __cnfn convert_float2_rte(long2);
float2 __ovld __cnfn convert_float2_rtz(long2);
float2 __ovld __cnfn convert_float2_rtp(long2);
float2 __ovld __cnfn convert_float2_rtn(long2);
float2 __ovld __cnfn convert_float2(long2);
float2 __ovld __cnfn convert_float2_rte(ulong2);
float2 __ovld __cnfn convert_float2_rtz(ulong2);
float2 __ovld __cnfn convert_float2_rtp(ulong2);
float2 __ovld __cnfn convert_float2_rtn(ulong2);
float2 __ovld __cnfn convert_float2(ulong2);
float2 __ovld __cnfn convert_float2_rte(float2);
float2 __ovld __cnfn convert_float2_rtz(float2);
float2 __ovld __cnfn convert_float2_rtp(float2);
float2 __ovld __cnfn convert_float2_rtn(float2);
float2 __ovld __cnfn convert_float2(float2);
char3 __ovld __cnfn convert_char3_rte(char3);
char3 __ovld __cnfn convert_char3_sat_rte(char3);
char3 __ovld __cnfn convert_char3_rtz(char3);
char3 __ovld __cnfn convert_char3_sat_rtz(char3);
char3 __ovld __cnfn convert_char3_rtp(char3);
char3 __ovld __cnfn convert_char3_sat_rtp(char3);
char3 __ovld __cnfn convert_char3_rtn(char3);
char3 __ovld __cnfn convert_char3_sat_rtn(char3);
char3 __ovld __cnfn convert_char3(char3);
char3 __ovld __cnfn convert_char3_sat(char3);
char3 __ovld __cnfn convert_char3_rte(uchar3);
char3 __ovld __cnfn convert_char3_sat_rte(uchar3);
char3 __ovld __cnfn convert_char3_rtz(uchar3);
char3 __ovld __cnfn convert_char3_sat_rtz(uchar3);
char3 __ovld __cnfn convert_char3_rtp(uchar3);
char3 __ovld __cnfn convert_char3_sat_rtp(uchar3);
char3 __ovld __cnfn convert_char3_rtn(uchar3);
char3 __ovld __cnfn convert_char3_sat_rtn(uchar3);
char3 __ovld __cnfn convert_char3(uchar3);
char3 __ovld __cnfn convert_char3_sat(uchar3);
char3 __ovld __cnfn convert_char3_rte(short3);
char3 __ovld __cnfn convert_char3_sat_rte(short3);
char3 __ovld __cnfn convert_char3_rtz(short3);
char3 __ovld __cnfn convert_char3_sat_rtz(short3);
char3 __ovld __cnfn convert_char3_rtp(short3);
char3 __ovld __cnfn convert_char3_sat_rtp(short3);
char3 __ovld __cnfn convert_char3_rtn(short3);
char3 __ovld __cnfn convert_char3_sat_rtn(short3);
char3 __ovld __cnfn convert_char3(short3);
char3 __ovld __cnfn convert_char3_sat(short3);
char3 __ovld __cnfn convert_char3_rte(ushort3);
char3 __ovld __cnfn convert_char3_sat_rte(ushort3);
char3 __ovld __cnfn convert_char3_rtz(ushort3);
char3 __ovld __cnfn convert_char3_sat_rtz(ushort3);
char3 __ovld __cnfn convert_char3_rtp(ushort3);
char3 __ovld __cnfn convert_char3_sat_rtp(ushort3);
char3 __ovld __cnfn convert_char3_rtn(ushort3);
char3 __ovld __cnfn convert_char3_sat_rtn(ushort3);
char3 __ovld __cnfn convert_char3(ushort3);
char3 __ovld __cnfn convert_char3_sat(ushort3);
char3 __ovld __cnfn convert_char3_rte(int3);
char3 __ovld __cnfn convert_char3_sat_rte(int3);
char3 __ovld __cnfn convert_char3_rtz(int3);
char3 __ovld __cnfn convert_char3_sat_rtz(int3);
char3 __ovld __cnfn convert_char3_rtp(int3);
char3 __ovld __cnfn convert_char3_sat_rtp(int3);
char3 __ovld __cnfn convert_char3_rtn(int3);
char3 __ovld __cnfn convert_char3_sat_rtn(int3);
char3 __ovld __cnfn convert_char3(int3);
char3 __ovld __cnfn convert_char3_sat(int3);
char3 __ovld __cnfn convert_char3_rte(uint3);
char3 __ovld __cnfn convert_char3_sat_rte(uint3);
char3 __ovld __cnfn convert_char3_rtz(uint3);
char3 __ovld __cnfn convert_char3_sat_rtz(uint3);
char3 __ovld __cnfn convert_char3_rtp(uint3);
char3 __ovld __cnfn convert_char3_sat_rtp(uint3);
char3 __ovld __cnfn convert_char3_rtn(uint3);
char3 __ovld __cnfn convert_char3_sat_rtn(uint3);
char3 __ovld __cnfn convert_char3(uint3);
char3 __ovld __cnfn convert_char3_sat(uint3);
char3 __ovld __cnfn convert_char3_rte(long3);
char3 __ovld __cnfn convert_char3_sat_rte(long3);
char3 __ovld __cnfn convert_char3_rtz(long3);
char3 __ovld __cnfn convert_char3_sat_rtz(long3);
char3 __ovld __cnfn convert_char3_rtp(long3);
char3 __ovld __cnfn convert_char3_sat_rtp(long3);
char3 __ovld __cnfn convert_char3_rtn(long3);
char3 __ovld __cnfn convert_char3_sat_rtn(long3);
char3 __ovld __cnfn convert_char3(long3);
char3 __ovld __cnfn convert_char3_sat(long3);
char3 __ovld __cnfn convert_char3_rte(ulong3);
char3 __ovld __cnfn convert_char3_sat_rte(ulong3);
char3 __ovld __cnfn convert_char3_rtz(ulong3);
char3 __ovld __cnfn convert_char3_sat_rtz(ulong3);
char3 __ovld __cnfn convert_char3_rtp(ulong3);
char3 __ovld __cnfn convert_char3_sat_rtp(ulong3);
char3 __ovld __cnfn convert_char3_rtn(ulong3);
char3 __ovld __cnfn convert_char3_sat_rtn(ulong3);
char3 __ovld __cnfn convert_char3(ulong3);
char3 __ovld __cnfn convert_char3_sat(ulong3);
char3 __ovld __cnfn convert_char3_rte(float3);
char3 __ovld __cnfn convert_char3_sat_rte(float3);
char3 __ovld __cnfn convert_char3_rtz(float3);
char3 __ovld __cnfn convert_char3_sat_rtz(float3);
char3 __ovld __cnfn convert_char3_rtp(float3);
char3 __ovld __cnfn convert_char3_sat_rtp(float3);
char3 __ovld __cnfn convert_char3_rtn(float3);
char3 __ovld __cnfn convert_char3_sat_rtn(float3);
char3 __ovld __cnfn convert_char3(float3);
char3 __ovld __cnfn convert_char3_sat(float3);
uchar3 __ovld __cnfn convert_uchar3_rte(char3);
uchar3 __ovld __cnfn convert_uchar3_sat_rte(char3);
uchar3 __ovld __cnfn convert_uchar3_rtz(char3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtz(char3);
uchar3 __ovld __cnfn convert_uchar3_rtp(char3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtp(char3);
uchar3 __ovld __cnfn convert_uchar3_rtn(char3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtn(char3);
uchar3 __ovld __cnfn convert_uchar3(char3);
uchar3 __ovld __cnfn convert_uchar3_sat(char3);
uchar3 __ovld __cnfn convert_uchar3_rte(uchar3);
uchar3 __ovld __cnfn convert_uchar3_sat_rte(uchar3);
uchar3 __ovld __cnfn convert_uchar3_rtz(uchar3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtz(uchar3);
uchar3 __ovld __cnfn convert_uchar3_rtp(uchar3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtp(uchar3);
uchar3 __ovld __cnfn convert_uchar3_rtn(uchar3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtn(uchar3);
uchar3 __ovld __cnfn convert_uchar3(uchar3);
uchar3 __ovld __cnfn convert_uchar3_sat(uchar3);
uchar3 __ovld __cnfn convert_uchar3_rte(short3);
uchar3 __ovld __cnfn convert_uchar3_sat_rte(short3);
uchar3 __ovld __cnfn convert_uchar3_rtz(short3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtz(short3);
uchar3 __ovld __cnfn convert_uchar3_rtp(short3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtp(short3);
uchar3 __ovld __cnfn convert_uchar3_rtn(short3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtn(short3);
uchar3 __ovld __cnfn convert_uchar3(short3);
uchar3 __ovld __cnfn convert_uchar3_sat(short3);
uchar3 __ovld __cnfn convert_uchar3_rte(ushort3);
uchar3 __ovld __cnfn convert_uchar3_sat_rte(ushort3);
uchar3 __ovld __cnfn convert_uchar3_rtz(ushort3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtz(ushort3);
uchar3 __ovld __cnfn convert_uchar3_rtp(ushort3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtp(ushort3);
uchar3 __ovld __cnfn convert_uchar3_rtn(ushort3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtn(ushort3);
uchar3 __ovld __cnfn convert_uchar3(ushort3);
uchar3 __ovld __cnfn convert_uchar3_sat(ushort3);
uchar3 __ovld __cnfn convert_uchar3_rte(int3);
uchar3 __ovld __cnfn convert_uchar3_sat_rte(int3);
uchar3 __ovld __cnfn convert_uchar3_rtz(int3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtz(int3);
uchar3 __ovld __cnfn convert_uchar3_rtp(int3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtp(int3);
uchar3 __ovld __cnfn convert_uchar3_rtn(int3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtn(int3);
uchar3 __ovld __cnfn convert_uchar3(int3);
uchar3 __ovld __cnfn convert_uchar3_sat(int3);
uchar3 __ovld __cnfn convert_uchar3_rte(uint3);
uchar3 __ovld __cnfn convert_uchar3_sat_rte(uint3);
uchar3 __ovld __cnfn convert_uchar3_rtz(uint3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtz(uint3);
uchar3 __ovld __cnfn convert_uchar3_rtp(uint3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtp(uint3);
uchar3 __ovld __cnfn convert_uchar3_rtn(uint3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtn(uint3);
uchar3 __ovld __cnfn convert_uchar3(uint3);
uchar3 __ovld __cnfn convert_uchar3_sat(uint3);
uchar3 __ovld __cnfn convert_uchar3_rte(long3);
uchar3 __ovld __cnfn convert_uchar3_sat_rte(long3);
uchar3 __ovld __cnfn convert_uchar3_rtz(long3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtz(long3);
uchar3 __ovld __cnfn convert_uchar3_rtp(long3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtp(long3);
uchar3 __ovld __cnfn convert_uchar3_rtn(long3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtn(long3);
uchar3 __ovld __cnfn convert_uchar3(long3);
uchar3 __ovld __cnfn convert_uchar3_sat(long3);
uchar3 __ovld __cnfn convert_uchar3_rte(ulong3);
uchar3 __ovld __cnfn convert_uchar3_sat_rte(ulong3);
uchar3 __ovld __cnfn convert_uchar3_rtz(ulong3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtz(ulong3);
uchar3 __ovld __cnfn convert_uchar3_rtp(ulong3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtp(ulong3);
uchar3 __ovld __cnfn convert_uchar3_rtn(ulong3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtn(ulong3);
uchar3 __ovld __cnfn convert_uchar3(ulong3);
uchar3 __ovld __cnfn convert_uchar3_sat(ulong3);
uchar3 __ovld __cnfn convert_uchar3_rte(float3);
uchar3 __ovld __cnfn convert_uchar3_sat_rte(float3);
uchar3 __ovld __cnfn convert_uchar3_rtz(float3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtz(float3);
uchar3 __ovld __cnfn convert_uchar3_rtp(float3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtp(float3);
uchar3 __ovld __cnfn convert_uchar3_rtn(float3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtn(float3);
uchar3 __ovld __cnfn convert_uchar3(float3);
uchar3 __ovld __cnfn convert_uchar3_sat(float3);
short3 __ovld __cnfn convert_short3_rte(char3);
short3 __ovld __cnfn convert_short3_sat_rte(char3);
short3 __ovld __cnfn convert_short3_rtz(char3);
short3 __ovld __cnfn convert_short3_sat_rtz(char3);
short3 __ovld __cnfn convert_short3_rtp(char3);
short3 __ovld __cnfn convert_short3_sat_rtp(char3);
short3 __ovld __cnfn convert_short3_rtn(char3);
short3 __ovld __cnfn convert_short3_sat_rtn(char3);
short3 __ovld __cnfn convert_short3(char3);
short3 __ovld __cnfn convert_short3_sat(char3);
short3 __ovld __cnfn convert_short3_rte(uchar3);
short3 __ovld __cnfn convert_short3_sat_rte(uchar3);
short3 __ovld __cnfn convert_short3_rtz(uchar3);
short3 __ovld __cnfn convert_short3_sat_rtz(uchar3);
short3 __ovld __cnfn convert_short3_rtp(uchar3);
short3 __ovld __cnfn convert_short3_sat_rtp(uchar3);
short3 __ovld __cnfn convert_short3_rtn(uchar3);
short3 __ovld __cnfn convert_short3_sat_rtn(uchar3);
short3 __ovld __cnfn convert_short3(uchar3);
short3 __ovld __cnfn convert_short3_sat(uchar3);
short3 __ovld __cnfn convert_short3_rte(short3);
short3 __ovld __cnfn convert_short3_sat_rte(short3);
short3 __ovld __cnfn convert_short3_rtz(short3);
short3 __ovld __cnfn convert_short3_sat_rtz(short3);
short3 __ovld __cnfn convert_short3_rtp(short3);
short3 __ovld __cnfn convert_short3_sat_rtp(short3);
short3 __ovld __cnfn convert_short3_rtn(short3);
short3 __ovld __cnfn convert_short3_sat_rtn(short3);
short3 __ovld __cnfn convert_short3(short3);
short3 __ovld __cnfn convert_short3_sat(short3);
short3 __ovld __cnfn convert_short3_rte(ushort3);
short3 __ovld __cnfn convert_short3_sat_rte(ushort3);
short3 __ovld __cnfn convert_short3_rtz(ushort3);
short3 __ovld __cnfn convert_short3_sat_rtz(ushort3);
short3 __ovld __cnfn convert_short3_rtp(ushort3);
short3 __ovld __cnfn convert_short3_sat_rtp(ushort3);
short3 __ovld __cnfn convert_short3_rtn(ushort3);
short3 __ovld __cnfn convert_short3_sat_rtn(ushort3);
short3 __ovld __cnfn convert_short3(ushort3);
short3 __ovld __cnfn convert_short3_sat(ushort3);
short3 __ovld __cnfn convert_short3_rte(int3);
short3 __ovld __cnfn convert_short3_sat_rte(int3);
short3 __ovld __cnfn convert_short3_rtz(int3);
short3 __ovld __cnfn convert_short3_sat_rtz(int3);
short3 __ovld __cnfn convert_short3_rtp(int3);
short3 __ovld __cnfn convert_short3_sat_rtp(int3);
short3 __ovld __cnfn convert_short3_rtn(int3);
short3 __ovld __cnfn convert_short3_sat_rtn(int3);
short3 __ovld __cnfn convert_short3(int3);
short3 __ovld __cnfn convert_short3_sat(int3);
short3 __ovld __cnfn convert_short3_rte(uint3);
short3 __ovld __cnfn convert_short3_sat_rte(uint3);
short3 __ovld __cnfn convert_short3_rtz(uint3);
short3 __ovld __cnfn convert_short3_sat_rtz(uint3);
short3 __ovld __cnfn convert_short3_rtp(uint3);
short3 __ovld __cnfn convert_short3_sat_rtp(uint3);
short3 __ovld __cnfn convert_short3_rtn(uint3);
short3 __ovld __cnfn convert_short3_sat_rtn(uint3);
short3 __ovld __cnfn convert_short3(uint3);
short3 __ovld __cnfn convert_short3_sat(uint3);
short3 __ovld __cnfn convert_short3_rte(long3);
short3 __ovld __cnfn convert_short3_sat_rte(long3);
short3 __ovld __cnfn convert_short3_rtz(long3);
short3 __ovld __cnfn convert_short3_sat_rtz(long3);
short3 __ovld __cnfn convert_short3_rtp(long3);
short3 __ovld __cnfn convert_short3_sat_rtp(long3);
short3 __ovld __cnfn convert_short3_rtn(long3);
short3 __ovld __cnfn convert_short3_sat_rtn(long3);
short3 __ovld __cnfn convert_short3(long3);
short3 __ovld __cnfn convert_short3_sat(long3);
short3 __ovld __cnfn convert_short3_rte(ulong3);
short3 __ovld __cnfn convert_short3_sat_rte(ulong3);
short3 __ovld __cnfn convert_short3_rtz(ulong3);
short3 __ovld __cnfn convert_short3_sat_rtz(ulong3);
short3 __ovld __cnfn convert_short3_rtp(ulong3);
short3 __ovld __cnfn convert_short3_sat_rtp(ulong3);
short3 __ovld __cnfn convert_short3_rtn(ulong3);
short3 __ovld __cnfn convert_short3_sat_rtn(ulong3);
short3 __ovld __cnfn convert_short3(ulong3);
short3 __ovld __cnfn convert_short3_sat(ulong3);
short3 __ovld __cnfn convert_short3_rte(float3);
short3 __ovld __cnfn convert_short3_sat_rte(float3);
short3 __ovld __cnfn convert_short3_rtz(float3);
short3 __ovld __cnfn convert_short3_sat_rtz(float3);
short3 __ovld __cnfn convert_short3_rtp(float3);
short3 __ovld __cnfn convert_short3_sat_rtp(float3);
short3 __ovld __cnfn convert_short3_rtn(float3);
short3 __ovld __cnfn convert_short3_sat_rtn(float3);
short3 __ovld __cnfn convert_short3(float3);
short3 __ovld __cnfn convert_short3_sat(float3);
ushort3 __ovld __cnfn convert_ushort3_rte(char3);
ushort3 __ovld __cnfn convert_ushort3_sat_rte(char3);
ushort3 __ovld __cnfn convert_ushort3_rtz(char3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtz(char3);
ushort3 __ovld __cnfn convert_ushort3_rtp(char3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtp(char3);
ushort3 __ovld __cnfn convert_ushort3_rtn(char3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtn(char3);
ushort3 __ovld __cnfn convert_ushort3(char3);
ushort3 __ovld __cnfn convert_ushort3_sat(char3);
ushort3 __ovld __cnfn convert_ushort3_rte(uchar3);
ushort3 __ovld __cnfn convert_ushort3_sat_rte(uchar3);
ushort3 __ovld __cnfn convert_ushort3_rtz(uchar3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtz(uchar3);
ushort3 __ovld __cnfn convert_ushort3_rtp(uchar3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtp(uchar3);
ushort3 __ovld __cnfn convert_ushort3_rtn(uchar3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtn(uchar3);
ushort3 __ovld __cnfn convert_ushort3(uchar3);
ushort3 __ovld __cnfn convert_ushort3_sat(uchar3);
ushort3 __ovld __cnfn convert_ushort3_rte(short3);
ushort3 __ovld __cnfn convert_ushort3_sat_rte(short3);
ushort3 __ovld __cnfn convert_ushort3_rtz(short3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtz(short3);
ushort3 __ovld __cnfn convert_ushort3_rtp(short3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtp(short3);
ushort3 __ovld __cnfn convert_ushort3_rtn(short3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtn(short3);
ushort3 __ovld __cnfn convert_ushort3(short3);
ushort3 __ovld __cnfn convert_ushort3_sat(short3);
ushort3 __ovld __cnfn convert_ushort3_rte(ushort3);
ushort3 __ovld __cnfn convert_ushort3_sat_rte(ushort3);
ushort3 __ovld __cnfn convert_ushort3_rtz(ushort3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtz(ushort3);
ushort3 __ovld __cnfn convert_ushort3_rtp(ushort3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtp(ushort3);
ushort3 __ovld __cnfn convert_ushort3_rtn(ushort3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtn(ushort3);
ushort3 __ovld __cnfn convert_ushort3(ushort3);
ushort3 __ovld __cnfn convert_ushort3_sat(ushort3);
ushort3 __ovld __cnfn convert_ushort3_rte(int3);
ushort3 __ovld __cnfn convert_ushort3_sat_rte(int3);
ushort3 __ovld __cnfn convert_ushort3_rtz(int3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtz(int3);
ushort3 __ovld __cnfn convert_ushort3_rtp(int3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtp(int3);
ushort3 __ovld __cnfn convert_ushort3_rtn(int3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtn(int3);
ushort3 __ovld __cnfn convert_ushort3(int3);
ushort3 __ovld __cnfn convert_ushort3_sat(int3);
ushort3 __ovld __cnfn convert_ushort3_rte(uint3);
ushort3 __ovld __cnfn convert_ushort3_sat_rte(uint3);
ushort3 __ovld __cnfn convert_ushort3_rtz(uint3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtz(uint3);
ushort3 __ovld __cnfn convert_ushort3_rtp(uint3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtp(uint3);
ushort3 __ovld __cnfn convert_ushort3_rtn(uint3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtn(uint3);
ushort3 __ovld __cnfn convert_ushort3(uint3);
ushort3 __ovld __cnfn convert_ushort3_sat(uint3);
ushort3 __ovld __cnfn convert_ushort3_rte(long3);
ushort3 __ovld __cnfn convert_ushort3_sat_rte(long3);
ushort3 __ovld __cnfn convert_ushort3_rtz(long3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtz(long3);
ushort3 __ovld __cnfn convert_ushort3_rtp(long3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtp(long3);
ushort3 __ovld __cnfn convert_ushort3_rtn(long3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtn(long3);
ushort3 __ovld __cnfn convert_ushort3(long3);
ushort3 __ovld __cnfn convert_ushort3_sat(long3);
ushort3 __ovld __cnfn convert_ushort3_rte(ulong3);
ushort3 __ovld __cnfn convert_ushort3_sat_rte(ulong3);
ushort3 __ovld __cnfn convert_ushort3_rtz(ulong3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtz(ulong3);
ushort3 __ovld __cnfn convert_ushort3_rtp(ulong3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtp(ulong3);
ushort3 __ovld __cnfn convert_ushort3_rtn(ulong3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtn(ulong3);
ushort3 __ovld __cnfn convert_ushort3(ulong3);
ushort3 __ovld __cnfn convert_ushort3_sat(ulong3);
ushort3 __ovld __cnfn convert_ushort3_rte(float3);
ushort3 __ovld __cnfn convert_ushort3_sat_rte(float3);
ushort3 __ovld __cnfn convert_ushort3_rtz(float3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtz(float3);
ushort3 __ovld __cnfn convert_ushort3_rtp(float3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtp(float3);
ushort3 __ovld __cnfn convert_ushort3_rtn(float3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtn(float3);
ushort3 __ovld __cnfn convert_ushort3(float3);
ushort3 __ovld __cnfn convert_ushort3_sat(float3);
int3 __ovld __cnfn convert_int3_rte(char3);
int3 __ovld __cnfn convert_int3_sat_rte(char3);
int3 __ovld __cnfn convert_int3_rtz(char3);
int3 __ovld __cnfn convert_int3_sat_rtz(char3);
int3 __ovld __cnfn convert_int3_rtp(char3);
int3 __ovld __cnfn convert_int3_sat_rtp(char3);
int3 __ovld __cnfn convert_int3_rtn(char3);
int3 __ovld __cnfn convert_int3_sat_rtn(char3);
int3 __ovld __cnfn convert_int3(char3);
int3 __ovld __cnfn convert_int3_sat(char3);
int3 __ovld __cnfn convert_int3_rte(uchar3);
int3 __ovld __cnfn convert_int3_sat_rte(uchar3);
int3 __ovld __cnfn convert_int3_rtz(uchar3);
int3 __ovld __cnfn convert_int3_sat_rtz(uchar3);
int3 __ovld __cnfn convert_int3_rtp(uchar3);
int3 __ovld __cnfn convert_int3_sat_rtp(uchar3);
int3 __ovld __cnfn convert_int3_rtn(uchar3);
int3 __ovld __cnfn convert_int3_sat_rtn(uchar3);
int3 __ovld __cnfn convert_int3(uchar3);
int3 __ovld __cnfn convert_int3_sat(uchar3);
int3 __ovld __cnfn convert_int3_rte(short3);
int3 __ovld __cnfn convert_int3_sat_rte(short3);
int3 __ovld __cnfn convert_int3_rtz(short3);
int3 __ovld __cnfn convert_int3_sat_rtz(short3);
int3 __ovld __cnfn convert_int3_rtp(short3);
int3 __ovld __cnfn convert_int3_sat_rtp(short3);
int3 __ovld __cnfn convert_int3_rtn(short3);
int3 __ovld __cnfn convert_int3_sat_rtn(short3);
int3 __ovld __cnfn convert_int3(short3);
int3 __ovld __cnfn convert_int3_sat(short3);
int3 __ovld __cnfn convert_int3_rte(ushort3);
int3 __ovld __cnfn convert_int3_sat_rte(ushort3);
int3 __ovld __cnfn convert_int3_rtz(ushort3);
int3 __ovld __cnfn convert_int3_sat_rtz(ushort3);
int3 __ovld __cnfn convert_int3_rtp(ushort3);
int3 __ovld __cnfn convert_int3_sat_rtp(ushort3);
int3 __ovld __cnfn convert_int3_rtn(ushort3);
int3 __ovld __cnfn convert_int3_sat_rtn(ushort3);
int3 __ovld __cnfn convert_int3(ushort3);
int3 __ovld __cnfn convert_int3_sat(ushort3);
int3 __ovld __cnfn convert_int3_rte(int3);
int3 __ovld __cnfn convert_int3_sat_rte(int3);
int3 __ovld __cnfn convert_int3_rtz(int3);
int3 __ovld __cnfn convert_int3_sat_rtz(int3);
int3 __ovld __cnfn convert_int3_rtp(int3);
int3 __ovld __cnfn convert_int3_sat_rtp(int3);
int3 __ovld __cnfn convert_int3_rtn(int3);
int3 __ovld __cnfn convert_int3_sat_rtn(int3);
int3 __ovld __cnfn convert_int3(int3);
int3 __ovld __cnfn convert_int3_sat(int3);
int3 __ovld __cnfn convert_int3_rte(uint3);
int3 __ovld __cnfn convert_int3_sat_rte(uint3);
int3 __ovld __cnfn convert_int3_rtz(uint3);
int3 __ovld __cnfn convert_int3_sat_rtz(uint3);
int3 __ovld __cnfn convert_int3_rtp(uint3);
int3 __ovld __cnfn convert_int3_sat_rtp(uint3);
int3 __ovld __cnfn convert_int3_rtn(uint3);
int3 __ovld __cnfn convert_int3_sat_rtn(uint3);
int3 __ovld __cnfn convert_int3(uint3);
int3 __ovld __cnfn convert_int3_sat(uint3);
int3 __ovld __cnfn convert_int3_rte(long3);
int3 __ovld __cnfn convert_int3_sat_rte(long3);
int3 __ovld __cnfn convert_int3_rtz(long3);
int3 __ovld __cnfn convert_int3_sat_rtz(long3);
int3 __ovld __cnfn convert_int3_rtp(long3);
int3 __ovld __cnfn convert_int3_sat_rtp(long3);
int3 __ovld __cnfn convert_int3_rtn(long3);
int3 __ovld __cnfn convert_int3_sat_rtn(long3);
int3 __ovld __cnfn convert_int3(long3);
int3 __ovld __cnfn convert_int3_sat(long3);
int3 __ovld __cnfn convert_int3_rte(ulong3);
int3 __ovld __cnfn convert_int3_sat_rte(ulong3);
int3 __ovld __cnfn convert_int3_rtz(ulong3);
int3 __ovld __cnfn convert_int3_sat_rtz(ulong3);
int3 __ovld __cnfn convert_int3_rtp(ulong3);
int3 __ovld __cnfn convert_int3_sat_rtp(ulong3);
int3 __ovld __cnfn convert_int3_rtn(ulong3);
int3 __ovld __cnfn convert_int3_sat_rtn(ulong3);
int3 __ovld __cnfn convert_int3(ulong3);
int3 __ovld __cnfn convert_int3_sat(ulong3);
int3 __ovld __cnfn convert_int3_rte(float3);
int3 __ovld __cnfn convert_int3_sat_rte(float3);
int3 __ovld __cnfn convert_int3_rtz(float3);
int3 __ovld __cnfn convert_int3_sat_rtz(float3);
int3 __ovld __cnfn convert_int3_rtp(float3);
int3 __ovld __cnfn convert_int3_sat_rtp(float3);
int3 __ovld __cnfn convert_int3_rtn(float3);
int3 __ovld __cnfn convert_int3_sat_rtn(float3);
int3 __ovld __cnfn convert_int3(float3);
int3 __ovld __cnfn convert_int3_sat(float3);
uint3 __ovld __cnfn convert_uint3_rte(char3);
uint3 __ovld __cnfn convert_uint3_sat_rte(char3);
uint3 __ovld __cnfn convert_uint3_rtz(char3);
uint3 __ovld __cnfn convert_uint3_sat_rtz(char3);
uint3 __ovld __cnfn convert_uint3_rtp(char3);
uint3 __ovld __cnfn convert_uint3_sat_rtp(char3);
uint3 __ovld __cnfn convert_uint3_rtn(char3);
uint3 __ovld __cnfn convert_uint3_sat_rtn(char3);
uint3 __ovld __cnfn convert_uint3(char3);
uint3 __ovld __cnfn convert_uint3_sat(char3);
uint3 __ovld __cnfn convert_uint3_rte(uchar3);
uint3 __ovld __cnfn convert_uint3_sat_rte(uchar3);
uint3 __ovld __cnfn convert_uint3_rtz(uchar3);
uint3 __ovld __cnfn convert_uint3_sat_rtz(uchar3);
uint3 __ovld __cnfn convert_uint3_rtp(uchar3);
uint3 __ovld __cnfn convert_uint3_sat_rtp(uchar3);
uint3 __ovld __cnfn convert_uint3_rtn(uchar3);
uint3 __ovld __cnfn convert_uint3_sat_rtn(uchar3);
uint3 __ovld __cnfn convert_uint3(uchar3);
uint3 __ovld __cnfn convert_uint3_sat(uchar3);
uint3 __ovld __cnfn convert_uint3_rte(short3);
uint3 __ovld __cnfn convert_uint3_sat_rte(short3);
uint3 __ovld __cnfn convert_uint3_rtz(short3);
uint3 __ovld __cnfn convert_uint3_sat_rtz(short3);
uint3 __ovld __cnfn convert_uint3_rtp(short3);
uint3 __ovld __cnfn convert_uint3_sat_rtp(short3);
uint3 __ovld __cnfn convert_uint3_rtn(short3);
uint3 __ovld __cnfn convert_uint3_sat_rtn(short3);
uint3 __ovld __cnfn convert_uint3(short3);
uint3 __ovld __cnfn convert_uint3_sat(short3);
uint3 __ovld __cnfn convert_uint3_rte(ushort3);
uint3 __ovld __cnfn convert_uint3_sat_rte(ushort3);
uint3 __ovld __cnfn convert_uint3_rtz(ushort3);
uint3 __ovld __cnfn convert_uint3_sat_rtz(ushort3);
uint3 __ovld __cnfn convert_uint3_rtp(ushort3);
uint3 __ovld __cnfn convert_uint3_sat_rtp(ushort3);
uint3 __ovld __cnfn convert_uint3_rtn(ushort3);
uint3 __ovld __cnfn convert_uint3_sat_rtn(ushort3);
uint3 __ovld __cnfn convert_uint3(ushort3);
uint3 __ovld __cnfn convert_uint3_sat(ushort3);
uint3 __ovld __cnfn convert_uint3_rte(int3);
uint3 __ovld __cnfn convert_uint3_sat_rte(int3);
uint3 __ovld __cnfn convert_uint3_rtz(int3);
uint3 __ovld __cnfn convert_uint3_sat_rtz(int3);
uint3 __ovld __cnfn convert_uint3_rtp(int3);
uint3 __ovld __cnfn convert_uint3_sat_rtp(int3);
uint3 __ovld __cnfn convert_uint3_rtn(int3);
uint3 __ovld __cnfn convert_uint3_sat_rtn(int3);
uint3 __ovld __cnfn convert_uint3(int3);
uint3 __ovld __cnfn convert_uint3_sat(int3);
uint3 __ovld __cnfn convert_uint3_rte(uint3);
uint3 __ovld __cnfn convert_uint3_sat_rte(uint3);
uint3 __ovld __cnfn convert_uint3_rtz(uint3);
uint3 __ovld __cnfn convert_uint3_sat_rtz(uint3);
uint3 __ovld __cnfn convert_uint3_rtp(uint3);
uint3 __ovld __cnfn convert_uint3_sat_rtp(uint3);
uint3 __ovld __cnfn convert_uint3_rtn(uint3);
uint3 __ovld __cnfn convert_uint3_sat_rtn(uint3);
uint3 __ovld __cnfn convert_uint3(uint3);
uint3 __ovld __cnfn convert_uint3_sat(uint3);
uint3 __ovld __cnfn convert_uint3_rte(long3);
uint3 __ovld __cnfn convert_uint3_sat_rte(long3);
uint3 __ovld __cnfn convert_uint3_rtz(long3);
uint3 __ovld __cnfn convert_uint3_sat_rtz(long3);
uint3 __ovld __cnfn convert_uint3_rtp(long3);
uint3 __ovld __cnfn convert_uint3_sat_rtp(long3);
uint3 __ovld __cnfn convert_uint3_rtn(long3);
uint3 __ovld __cnfn convert_uint3_sat_rtn(long3);
uint3 __ovld __cnfn convert_uint3(long3);
uint3 __ovld __cnfn convert_uint3_sat(long3);
uint3 __ovld __cnfn convert_uint3_rte(ulong3);
uint3 __ovld __cnfn convert_uint3_sat_rte(ulong3);
uint3 __ovld __cnfn convert_uint3_rtz(ulong3);
uint3 __ovld __cnfn convert_uint3_sat_rtz(ulong3);
uint3 __ovld __cnfn convert_uint3_rtp(ulong3);
uint3 __ovld __cnfn convert_uint3_sat_rtp(ulong3);
uint3 __ovld __cnfn convert_uint3_rtn(ulong3);
uint3 __ovld __cnfn convert_uint3_sat_rtn(ulong3);
uint3 __ovld __cnfn convert_uint3(ulong3);
uint3 __ovld __cnfn convert_uint3_sat(ulong3);
uint3 __ovld __cnfn convert_uint3_rte(float3);
uint3 __ovld __cnfn convert_uint3_sat_rte(float3);
uint3 __ovld __cnfn convert_uint3_rtz(float3);
uint3 __ovld __cnfn convert_uint3_sat_rtz(float3);
uint3 __ovld __cnfn convert_uint3_rtp(float3);
uint3 __ovld __cnfn convert_uint3_sat_rtp(float3);
uint3 __ovld __cnfn convert_uint3_rtn(float3);
uint3 __ovld __cnfn convert_uint3_sat_rtn(float3);
uint3 __ovld __cnfn convert_uint3(float3);
uint3 __ovld __cnfn convert_uint3_sat(float3);
long3 __ovld __cnfn convert_long3_rte(char3);
long3 __ovld __cnfn convert_long3_sat_rte(char3);
long3 __ovld __cnfn convert_long3_rtz(char3);
long3 __ovld __cnfn convert_long3_sat_rtz(char3);
long3 __ovld __cnfn convert_long3_rtp(char3);
long3 __ovld __cnfn convert_long3_sat_rtp(char3);
long3 __ovld __cnfn convert_long3_rtn(char3);
long3 __ovld __cnfn convert_long3_sat_rtn(char3);
long3 __ovld __cnfn convert_long3(char3);
long3 __ovld __cnfn convert_long3_sat(char3);
long3 __ovld __cnfn convert_long3_rte(uchar3);
long3 __ovld __cnfn convert_long3_sat_rte(uchar3);
long3 __ovld __cnfn convert_long3_rtz(uchar3);
long3 __ovld __cnfn convert_long3_sat_rtz(uchar3);
long3 __ovld __cnfn convert_long3_rtp(uchar3);
long3 __ovld __cnfn convert_long3_sat_rtp(uchar3);
long3 __ovld __cnfn convert_long3_rtn(uchar3);
long3 __ovld __cnfn convert_long3_sat_rtn(uchar3);
long3 __ovld __cnfn convert_long3(uchar3);
long3 __ovld __cnfn convert_long3_sat(uchar3);
long3 __ovld __cnfn convert_long3_rte(short3);
long3 __ovld __cnfn convert_long3_sat_rte(short3);
long3 __ovld __cnfn convert_long3_rtz(short3);
long3 __ovld __cnfn convert_long3_sat_rtz(short3);
long3 __ovld __cnfn convert_long3_rtp(short3);
long3 __ovld __cnfn convert_long3_sat_rtp(short3);
long3 __ovld __cnfn convert_long3_rtn(short3);
long3 __ovld __cnfn convert_long3_sat_rtn(short3);
long3 __ovld __cnfn convert_long3(short3);
long3 __ovld __cnfn convert_long3_sat(short3);
long3 __ovld __cnfn convert_long3_rte(ushort3);
long3 __ovld __cnfn convert_long3_sat_rte(ushort3);
long3 __ovld __cnfn convert_long3_rtz(ushort3);
long3 __ovld __cnfn convert_long3_sat_rtz(ushort3);
long3 __ovld __cnfn convert_long3_rtp(ushort3);
long3 __ovld __cnfn convert_long3_sat_rtp(ushort3);
long3 __ovld __cnfn convert_long3_rtn(ushort3);
long3 __ovld __cnfn convert_long3_sat_rtn(ushort3);
long3 __ovld __cnfn convert_long3(ushort3);
long3 __ovld __cnfn convert_long3_sat(ushort3);
long3 __ovld __cnfn convert_long3_rte(int3);
long3 __ovld __cnfn convert_long3_sat_rte(int3);
long3 __ovld __cnfn convert_long3_rtz(int3);
long3 __ovld __cnfn convert_long3_sat_rtz(int3);
long3 __ovld __cnfn convert_long3_rtp(int3);
long3 __ovld __cnfn convert_long3_sat_rtp(int3);
long3 __ovld __cnfn convert_long3_rtn(int3);
long3 __ovld __cnfn convert_long3_sat_rtn(int3);
long3 __ovld __cnfn convert_long3(int3);
long3 __ovld __cnfn convert_long3_sat(int3);
long3 __ovld __cnfn convert_long3_rte(uint3);
long3 __ovld __cnfn convert_long3_sat_rte(uint3);
long3 __ovld __cnfn convert_long3_rtz(uint3);
long3 __ovld __cnfn convert_long3_sat_rtz(uint3);
long3 __ovld __cnfn convert_long3_rtp(uint3);
long3 __ovld __cnfn convert_long3_sat_rtp(uint3);
long3 __ovld __cnfn convert_long3_rtn(uint3);
long3 __ovld __cnfn convert_long3_sat_rtn(uint3);
long3 __ovld __cnfn convert_long3(uint3);
long3 __ovld __cnfn convert_long3_sat(uint3);
long3 __ovld __cnfn convert_long3_rte(long3);
long3 __ovld __cnfn convert_long3_sat_rte(long3);
long3 __ovld __cnfn convert_long3_rtz(long3);
long3 __ovld __cnfn convert_long3_sat_rtz(long3);
long3 __ovld __cnfn convert_long3_rtp(long3);
long3 __ovld __cnfn convert_long3_sat_rtp(long3);
long3 __ovld __cnfn convert_long3_rtn(long3);
long3 __ovld __cnfn convert_long3_sat_rtn(long3);
long3 __ovld __cnfn convert_long3(long3);
long3 __ovld __cnfn convert_long3_sat(long3);
long3 __ovld __cnfn convert_long3_rte(ulong3);
long3 __ovld __cnfn convert_long3_sat_rte(ulong3);
long3 __ovld __cnfn convert_long3_rtz(ulong3);
long3 __ovld __cnfn convert_long3_sat_rtz(ulong3);
long3 __ovld __cnfn convert_long3_rtp(ulong3);
long3 __ovld __cnfn convert_long3_sat_rtp(ulong3);
long3 __ovld __cnfn convert_long3_rtn(ulong3);
long3 __ovld __cnfn convert_long3_sat_rtn(ulong3);
long3 __ovld __cnfn convert_long3(ulong3);
long3 __ovld __cnfn convert_long3_sat(ulong3);
long3 __ovld __cnfn convert_long3_rte(float3);
long3 __ovld __cnfn convert_long3_sat_rte(float3);
long3 __ovld __cnfn convert_long3_rtz(float3);
long3 __ovld __cnfn convert_long3_sat_rtz(float3);
long3 __ovld __cnfn convert_long3_rtp(float3);
long3 __ovld __cnfn convert_long3_sat_rtp(float3);
long3 __ovld __cnfn convert_long3_rtn(float3);
long3 __ovld __cnfn convert_long3_sat_rtn(float3);
long3 __ovld __cnfn convert_long3(float3);
long3 __ovld __cnfn convert_long3_sat(float3);
ulong3 __ovld __cnfn convert_ulong3_rte(char3);
ulong3 __ovld __cnfn convert_ulong3_sat_rte(char3);
ulong3 __ovld __cnfn convert_ulong3_rtz(char3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtz(char3);
ulong3 __ovld __cnfn convert_ulong3_rtp(char3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtp(char3);
ulong3 __ovld __cnfn convert_ulong3_rtn(char3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtn(char3);
ulong3 __ovld __cnfn convert_ulong3(char3);
ulong3 __ovld __cnfn convert_ulong3_sat(char3);
ulong3 __ovld __cnfn convert_ulong3_rte(uchar3);
ulong3 __ovld __cnfn convert_ulong3_sat_rte(uchar3);
ulong3 __ovld __cnfn convert_ulong3_rtz(uchar3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtz(uchar3);
ulong3 __ovld __cnfn convert_ulong3_rtp(uchar3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtp(uchar3);
ulong3 __ovld __cnfn convert_ulong3_rtn(uchar3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtn(uchar3);
ulong3 __ovld __cnfn convert_ulong3(uchar3);
ulong3 __ovld __cnfn convert_ulong3_sat(uchar3);
ulong3 __ovld __cnfn convert_ulong3_rte(short3);
ulong3 __ovld __cnfn convert_ulong3_sat_rte(short3);
ulong3 __ovld __cnfn convert_ulong3_rtz(short3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtz(short3);
ulong3 __ovld __cnfn convert_ulong3_rtp(short3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtp(short3);
ulong3 __ovld __cnfn convert_ulong3_rtn(short3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtn(short3);
ulong3 __ovld __cnfn convert_ulong3(short3);
ulong3 __ovld __cnfn convert_ulong3_sat(short3);
ulong3 __ovld __cnfn convert_ulong3_rte(ushort3);
ulong3 __ovld __cnfn convert_ulong3_sat_rte(ushort3);
ulong3 __ovld __cnfn convert_ulong3_rtz(ushort3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtz(ushort3);
ulong3 __ovld __cnfn convert_ulong3_rtp(ushort3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtp(ushort3);
ulong3 __ovld __cnfn convert_ulong3_rtn(ushort3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtn(ushort3);
ulong3 __ovld __cnfn convert_ulong3(ushort3);
ulong3 __ovld __cnfn convert_ulong3_sat(ushort3);
ulong3 __ovld __cnfn convert_ulong3_rte(int3);
ulong3 __ovld __cnfn convert_ulong3_sat_rte(int3);
ulong3 __ovld __cnfn convert_ulong3_rtz(int3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtz(int3);
ulong3 __ovld __cnfn convert_ulong3_rtp(int3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtp(int3);
ulong3 __ovld __cnfn convert_ulong3_rtn(int3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtn(int3);
ulong3 __ovld __cnfn convert_ulong3(int3);
ulong3 __ovld __cnfn convert_ulong3_sat(int3);
ulong3 __ovld __cnfn convert_ulong3_rte(uint3);
ulong3 __ovld __cnfn convert_ulong3_sat_rte(uint3);
ulong3 __ovld __cnfn convert_ulong3_rtz(uint3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtz(uint3);
ulong3 __ovld __cnfn convert_ulong3_rtp(uint3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtp(uint3);
ulong3 __ovld __cnfn convert_ulong3_rtn(uint3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtn(uint3);
ulong3 __ovld __cnfn convert_ulong3(uint3);
ulong3 __ovld __cnfn convert_ulong3_sat(uint3);
ulong3 __ovld __cnfn convert_ulong3_rte(long3);
ulong3 __ovld __cnfn convert_ulong3_sat_rte(long3);
ulong3 __ovld __cnfn convert_ulong3_rtz(long3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtz(long3);
ulong3 __ovld __cnfn convert_ulong3_rtp(long3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtp(long3);
ulong3 __ovld __cnfn convert_ulong3_rtn(long3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtn(long3);
ulong3 __ovld __cnfn convert_ulong3(long3);
ulong3 __ovld __cnfn convert_ulong3_sat(long3);
ulong3 __ovld __cnfn convert_ulong3_rte(ulong3);
ulong3 __ovld __cnfn convert_ulong3_sat_rte(ulong3);
ulong3 __ovld __cnfn convert_ulong3_rtz(ulong3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtz(ulong3);
ulong3 __ovld __cnfn convert_ulong3_rtp(ulong3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtp(ulong3);
ulong3 __ovld __cnfn convert_ulong3_rtn(ulong3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtn(ulong3);
ulong3 __ovld __cnfn convert_ulong3(ulong3);
ulong3 __ovld __cnfn convert_ulong3_sat(ulong3);
ulong3 __ovld __cnfn convert_ulong3_rte(float3);
ulong3 __ovld __cnfn convert_ulong3_sat_rte(float3);
ulong3 __ovld __cnfn convert_ulong3_rtz(float3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtz(float3);
ulong3 __ovld __cnfn convert_ulong3_rtp(float3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtp(float3);
ulong3 __ovld __cnfn convert_ulong3_rtn(float3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtn(float3);
ulong3 __ovld __cnfn convert_ulong3(float3);
ulong3 __ovld __cnfn convert_ulong3_sat(float3);
float3 __ovld __cnfn convert_float3_rte(char3);
float3 __ovld __cnfn convert_float3_rtz(char3);
float3 __ovld __cnfn convert_float3_rtp(char3);
float3 __ovld __cnfn convert_float3_rtn(char3);
float3 __ovld __cnfn convert_float3(char3);
float3 __ovld __cnfn convert_float3_rte(uchar3);
float3 __ovld __cnfn convert_float3_rtz(uchar3);
float3 __ovld __cnfn convert_float3_rtp(uchar3);
float3 __ovld __cnfn convert_float3_rtn(uchar3);
float3 __ovld __cnfn convert_float3(uchar3);
float3 __ovld __cnfn convert_float3_rte(short3);
float3 __ovld __cnfn convert_float3_rtz(short3);
float3 __ovld __cnfn convert_float3_rtp(short3);
float3 __ovld __cnfn convert_float3_rtn(short3);
float3 __ovld __cnfn convert_float3(short3);
float3 __ovld __cnfn convert_float3_rte(ushort3);
float3 __ovld __cnfn convert_float3_rtz(ushort3);
float3 __ovld __cnfn convert_float3_rtp(ushort3);
float3 __ovld __cnfn convert_float3_rtn(ushort3);
float3 __ovld __cnfn convert_float3(ushort3);
float3 __ovld __cnfn convert_float3_rte(int3);
float3 __ovld __cnfn convert_float3_rtz(int3);
float3 __ovld __cnfn convert_float3_rtp(int3);
float3 __ovld __cnfn convert_float3_rtn(int3);
float3 __ovld __cnfn convert_float3(int3);
float3 __ovld __cnfn convert_float3_rte(uint3);
float3 __ovld __cnfn convert_float3_rtz(uint3);
float3 __ovld __cnfn convert_float3_rtp(uint3);
float3 __ovld __cnfn convert_float3_rtn(uint3);
float3 __ovld __cnfn convert_float3(uint3);
float3 __ovld __cnfn convert_float3_rte(long3);
float3 __ovld __cnfn convert_float3_rtz(long3);
float3 __ovld __cnfn convert_float3_rtp(long3);
float3 __ovld __cnfn convert_float3_rtn(long3);
float3 __ovld __cnfn convert_float3(long3);
float3 __ovld __cnfn convert_float3_rte(ulong3);
float3 __ovld __cnfn convert_float3_rtz(ulong3);
float3 __ovld __cnfn convert_float3_rtp(ulong3);
float3 __ovld __cnfn convert_float3_rtn(ulong3);
float3 __ovld __cnfn convert_float3(ulong3);
float3 __ovld __cnfn convert_float3_rte(float3);
float3 __ovld __cnfn convert_float3_rtz(float3);
float3 __ovld __cnfn convert_float3_rtp(float3);
float3 __ovld __cnfn convert_float3_rtn(float3);
float3 __ovld __cnfn convert_float3(float3);
char4 __ovld __cnfn convert_char4_rte(char4);
char4 __ovld __cnfn convert_char4_sat_rte(char4);
char4 __ovld __cnfn convert_char4_rtz(char4);
char4 __ovld __cnfn convert_char4_sat_rtz(char4);
char4 __ovld __cnfn convert_char4_rtp(char4);
char4 __ovld __cnfn convert_char4_sat_rtp(char4);
char4 __ovld __cnfn convert_char4_rtn(char4);
char4 __ovld __cnfn convert_char4_sat_rtn(char4);
char4 __ovld __cnfn convert_char4(char4);
char4 __ovld __cnfn convert_char4_sat(char4);
char4 __ovld __cnfn convert_char4_rte(uchar4);
char4 __ovld __cnfn convert_char4_sat_rte(uchar4);
char4 __ovld __cnfn convert_char4_rtz(uchar4);
char4 __ovld __cnfn convert_char4_sat_rtz(uchar4);
char4 __ovld __cnfn convert_char4_rtp(uchar4);
char4 __ovld __cnfn convert_char4_sat_rtp(uchar4);
char4 __ovld __cnfn convert_char4_rtn(uchar4);
char4 __ovld __cnfn convert_char4_sat_rtn(uchar4);
char4 __ovld __cnfn convert_char4(uchar4);
char4 __ovld __cnfn convert_char4_sat(uchar4);
char4 __ovld __cnfn convert_char4_rte(short4);
char4 __ovld __cnfn convert_char4_sat_rte(short4);
char4 __ovld __cnfn convert_char4_rtz(short4);
char4 __ovld __cnfn convert_char4_sat_rtz(short4);
char4 __ovld __cnfn convert_char4_rtp(short4);
char4 __ovld __cnfn convert_char4_sat_rtp(short4);
char4 __ovld __cnfn convert_char4_rtn(short4);
char4 __ovld __cnfn convert_char4_sat_rtn(short4);
char4 __ovld __cnfn convert_char4(short4);
char4 __ovld __cnfn convert_char4_sat(short4);
char4 __ovld __cnfn convert_char4_rte(ushort4);
char4 __ovld __cnfn convert_char4_sat_rte(ushort4);
char4 __ovld __cnfn convert_char4_rtz(ushort4);
char4 __ovld __cnfn convert_char4_sat_rtz(ushort4);
char4 __ovld __cnfn convert_char4_rtp(ushort4);
char4 __ovld __cnfn convert_char4_sat_rtp(ushort4);
char4 __ovld __cnfn convert_char4_rtn(ushort4);
char4 __ovld __cnfn convert_char4_sat_rtn(ushort4);
char4 __ovld __cnfn convert_char4(ushort4);
char4 __ovld __cnfn convert_char4_sat(ushort4);
char4 __ovld __cnfn convert_char4_rte(int4);
char4 __ovld __cnfn convert_char4_sat_rte(int4);
char4 __ovld __cnfn convert_char4_rtz(int4);
char4 __ovld __cnfn convert_char4_sat_rtz(int4);
char4 __ovld __cnfn convert_char4_rtp(int4);
char4 __ovld __cnfn convert_char4_sat_rtp(int4);
char4 __ovld __cnfn convert_char4_rtn(int4);
char4 __ovld __cnfn convert_char4_sat_rtn(int4);
char4 __ovld __cnfn convert_char4(int4);
char4 __ovld __cnfn convert_char4_sat(int4);
char4 __ovld __cnfn convert_char4_rte(uint4);
char4 __ovld __cnfn convert_char4_sat_rte(uint4);
char4 __ovld __cnfn convert_char4_rtz(uint4);
char4 __ovld __cnfn convert_char4_sat_rtz(uint4);
char4 __ovld __cnfn convert_char4_rtp(uint4);
char4 __ovld __cnfn convert_char4_sat_rtp(uint4);
char4 __ovld __cnfn convert_char4_rtn(uint4);
char4 __ovld __cnfn convert_char4_sat_rtn(uint4);
char4 __ovld __cnfn convert_char4(uint4);
char4 __ovld __cnfn convert_char4_sat(uint4);
char4 __ovld __cnfn convert_char4_rte(long4);
char4 __ovld __cnfn convert_char4_sat_rte(long4);
char4 __ovld __cnfn convert_char4_rtz(long4);
char4 __ovld __cnfn convert_char4_sat_rtz(long4);
char4 __ovld __cnfn convert_char4_rtp(long4);
char4 __ovld __cnfn convert_char4_sat_rtp(long4);
char4 __ovld __cnfn convert_char4_rtn(long4);
char4 __ovld __cnfn convert_char4_sat_rtn(long4);
char4 __ovld __cnfn convert_char4(long4);
char4 __ovld __cnfn convert_char4_sat(long4);
char4 __ovld __cnfn convert_char4_rte(ulong4);
char4 __ovld __cnfn convert_char4_sat_rte(ulong4);
char4 __ovld __cnfn convert_char4_rtz(ulong4);
char4 __ovld __cnfn convert_char4_sat_rtz(ulong4);
char4 __ovld __cnfn convert_char4_rtp(ulong4);
char4 __ovld __cnfn convert_char4_sat_rtp(ulong4);
char4 __ovld __cnfn convert_char4_rtn(ulong4);
char4 __ovld __cnfn convert_char4_sat_rtn(ulong4);
char4 __ovld __cnfn convert_char4(ulong4);
char4 __ovld __cnfn convert_char4_sat(ulong4);
char4 __ovld __cnfn convert_char4_rte(float4);
char4 __ovld __cnfn convert_char4_sat_rte(float4);
char4 __ovld __cnfn convert_char4_rtz(float4);
char4 __ovld __cnfn convert_char4_sat_rtz(float4);
char4 __ovld __cnfn convert_char4_rtp(float4);
char4 __ovld __cnfn convert_char4_sat_rtp(float4);
char4 __ovld __cnfn convert_char4_rtn(float4);
char4 __ovld __cnfn convert_char4_sat_rtn(float4);
char4 __ovld __cnfn convert_char4(float4);
char4 __ovld __cnfn convert_char4_sat(float4);
uchar4 __ovld __cnfn convert_uchar4_rte(char4);
uchar4 __ovld __cnfn convert_uchar4_sat_rte(char4);
uchar4 __ovld __cnfn convert_uchar4_rtz(char4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtz(char4);
uchar4 __ovld __cnfn convert_uchar4_rtp(char4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtp(char4);
uchar4 __ovld __cnfn convert_uchar4_rtn(char4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtn(char4);
uchar4 __ovld __cnfn convert_uchar4(char4);
uchar4 __ovld __cnfn convert_uchar4_sat(char4);
uchar4 __ovld __cnfn convert_uchar4_rte(uchar4);
uchar4 __ovld __cnfn convert_uchar4_sat_rte(uchar4);
uchar4 __ovld __cnfn convert_uchar4_rtz(uchar4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtz(uchar4);
uchar4 __ovld __cnfn convert_uchar4_rtp(uchar4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtp(uchar4);
uchar4 __ovld __cnfn convert_uchar4_rtn(uchar4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtn(uchar4);
uchar4 __ovld __cnfn convert_uchar4(uchar4);
uchar4 __ovld __cnfn convert_uchar4_sat(uchar4);
uchar4 __ovld __cnfn convert_uchar4_rte(short4);
uchar4 __ovld __cnfn convert_uchar4_sat_rte(short4);
uchar4 __ovld __cnfn convert_uchar4_rtz(short4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtz(short4);
uchar4 __ovld __cnfn convert_uchar4_rtp(short4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtp(short4);
uchar4 __ovld __cnfn convert_uchar4_rtn(short4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtn(short4);
uchar4 __ovld __cnfn convert_uchar4(short4);
uchar4 __ovld __cnfn convert_uchar4_sat(short4);
uchar4 __ovld __cnfn convert_uchar4_rte(ushort4);
uchar4 __ovld __cnfn convert_uchar4_sat_rte(ushort4);
uchar4 __ovld __cnfn convert_uchar4_rtz(ushort4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtz(ushort4);
uchar4 __ovld __cnfn convert_uchar4_rtp(ushort4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtp(ushort4);
uchar4 __ovld __cnfn convert_uchar4_rtn(ushort4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtn(ushort4);
uchar4 __ovld __cnfn convert_uchar4(ushort4);
uchar4 __ovld __cnfn convert_uchar4_sat(ushort4);
uchar4 __ovld __cnfn convert_uchar4_rte(int4);
uchar4 __ovld __cnfn convert_uchar4_sat_rte(int4);
uchar4 __ovld __cnfn convert_uchar4_rtz(int4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtz(int4);
uchar4 __ovld __cnfn convert_uchar4_rtp(int4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtp(int4);
uchar4 __ovld __cnfn convert_uchar4_rtn(int4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtn(int4);
uchar4 __ovld __cnfn convert_uchar4(int4);
uchar4 __ovld __cnfn convert_uchar4_sat(int4);
uchar4 __ovld __cnfn convert_uchar4_rte(uint4);
uchar4 __ovld __cnfn convert_uchar4_sat_rte(uint4);
uchar4 __ovld __cnfn convert_uchar4_rtz(uint4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtz(uint4);
uchar4 __ovld __cnfn convert_uchar4_rtp(uint4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtp(uint4);
uchar4 __ovld __cnfn convert_uchar4_rtn(uint4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtn(uint4);
uchar4 __ovld __cnfn convert_uchar4(uint4);
uchar4 __ovld __cnfn convert_uchar4_sat(uint4);
uchar4 __ovld __cnfn convert_uchar4_rte(long4);
uchar4 __ovld __cnfn convert_uchar4_sat_rte(long4);
uchar4 __ovld __cnfn convert_uchar4_rtz(long4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtz(long4);
uchar4 __ovld __cnfn convert_uchar4_rtp(long4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtp(long4);
uchar4 __ovld __cnfn convert_uchar4_rtn(long4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtn(long4);
uchar4 __ovld __cnfn convert_uchar4(long4);
uchar4 __ovld __cnfn convert_uchar4_sat(long4);
uchar4 __ovld __cnfn convert_uchar4_rte(ulong4);
uchar4 __ovld __cnfn convert_uchar4_sat_rte(ulong4);
uchar4 __ovld __cnfn convert_uchar4_rtz(ulong4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtz(ulong4);
uchar4 __ovld __cnfn convert_uchar4_rtp(ulong4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtp(ulong4);
uchar4 __ovld __cnfn convert_uchar4_rtn(ulong4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtn(ulong4);
uchar4 __ovld __cnfn convert_uchar4(ulong4);
uchar4 __ovld __cnfn convert_uchar4_sat(ulong4);
uchar4 __ovld __cnfn convert_uchar4_rte(float4);
uchar4 __ovld __cnfn convert_uchar4_sat_rte(float4);
uchar4 __ovld __cnfn convert_uchar4_rtz(float4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtz(float4);
uchar4 __ovld __cnfn convert_uchar4_rtp(float4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtp(float4);
uchar4 __ovld __cnfn convert_uchar4_rtn(float4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtn(float4);
uchar4 __ovld __cnfn convert_uchar4(float4);
uchar4 __ovld __cnfn convert_uchar4_sat(float4);
short4 __ovld __cnfn convert_short4_rte(char4);
short4 __ovld __cnfn convert_short4_sat_rte(char4);
short4 __ovld __cnfn convert_short4_rtz(char4);
short4 __ovld __cnfn convert_short4_sat_rtz(char4);
short4 __ovld __cnfn convert_short4_rtp(char4);
short4 __ovld __cnfn convert_short4_sat_rtp(char4);
short4 __ovld __cnfn convert_short4_rtn(char4);
short4 __ovld __cnfn convert_short4_sat_rtn(char4);
short4 __ovld __cnfn convert_short4(char4);
short4 __ovld __cnfn convert_short4_sat(char4);
short4 __ovld __cnfn convert_short4_rte(uchar4);
short4 __ovld __cnfn convert_short4_sat_rte(uchar4);
short4 __ovld __cnfn convert_short4_rtz(uchar4);
short4 __ovld __cnfn convert_short4_sat_rtz(uchar4);
short4 __ovld __cnfn convert_short4_rtp(uchar4);
short4 __ovld __cnfn convert_short4_sat_rtp(uchar4);
short4 __ovld __cnfn convert_short4_rtn(uchar4);
short4 __ovld __cnfn convert_short4_sat_rtn(uchar4);
short4 __ovld __cnfn convert_short4(uchar4);
short4 __ovld __cnfn convert_short4_sat(uchar4);
short4 __ovld __cnfn convert_short4_rte(short4);
short4 __ovld __cnfn convert_short4_sat_rte(short4);
short4 __ovld __cnfn convert_short4_rtz(short4);
short4 __ovld __cnfn convert_short4_sat_rtz(short4);
short4 __ovld __cnfn convert_short4_rtp(short4);
short4 __ovld __cnfn convert_short4_sat_rtp(short4);
short4 __ovld __cnfn convert_short4_rtn(short4);
short4 __ovld __cnfn convert_short4_sat_rtn(short4);
short4 __ovld __cnfn convert_short4(short4);
short4 __ovld __cnfn convert_short4_sat(short4);
short4 __ovld __cnfn convert_short4_rte(ushort4);
short4 __ovld __cnfn convert_short4_sat_rte(ushort4);
short4 __ovld __cnfn convert_short4_rtz(ushort4);
short4 __ovld __cnfn convert_short4_sat_rtz(ushort4);
short4 __ovld __cnfn convert_short4_rtp(ushort4);
short4 __ovld __cnfn convert_short4_sat_rtp(ushort4);
short4 __ovld __cnfn convert_short4_rtn(ushort4);
short4 __ovld __cnfn convert_short4_sat_rtn(ushort4);
short4 __ovld __cnfn convert_short4(ushort4);
short4 __ovld __cnfn convert_short4_sat(ushort4);
short4 __ovld __cnfn convert_short4_rte(int4);
short4 __ovld __cnfn convert_short4_sat_rte(int4);
short4 __ovld __cnfn convert_short4_rtz(int4);
short4 __ovld __cnfn convert_short4_sat_rtz(int4);
short4 __ovld __cnfn convert_short4_rtp(int4);
short4 __ovld __cnfn convert_short4_sat_rtp(int4);
short4 __ovld __cnfn convert_short4_rtn(int4);
short4 __ovld __cnfn convert_short4_sat_rtn(int4);
short4 __ovld __cnfn convert_short4(int4);
short4 __ovld __cnfn convert_short4_sat(int4);
short4 __ovld __cnfn convert_short4_rte(uint4);
short4 __ovld __cnfn convert_short4_sat_rte(uint4);
short4 __ovld __cnfn convert_short4_rtz(uint4);
short4 __ovld __cnfn convert_short4_sat_rtz(uint4);
short4 __ovld __cnfn convert_short4_rtp(uint4);
short4 __ovld __cnfn convert_short4_sat_rtp(uint4);
short4 __ovld __cnfn convert_short4_rtn(uint4);
short4 __ovld __cnfn convert_short4_sat_rtn(uint4);
short4 __ovld __cnfn convert_short4(uint4);
short4 __ovld __cnfn convert_short4_sat(uint4);
short4 __ovld __cnfn convert_short4_rte(long4);
short4 __ovld __cnfn convert_short4_sat_rte(long4);
short4 __ovld __cnfn convert_short4_rtz(long4);
short4 __ovld __cnfn convert_short4_sat_rtz(long4);
short4 __ovld __cnfn convert_short4_rtp(long4);
short4 __ovld __cnfn convert_short4_sat_rtp(long4);
short4 __ovld __cnfn convert_short4_rtn(long4);
short4 __ovld __cnfn convert_short4_sat_rtn(long4);
short4 __ovld __cnfn convert_short4(long4);
short4 __ovld __cnfn convert_short4_sat(long4);
short4 __ovld __cnfn convert_short4_rte(ulong4);
short4 __ovld __cnfn convert_short4_sat_rte(ulong4);
short4 __ovld __cnfn convert_short4_rtz(ulong4);
short4 __ovld __cnfn convert_short4_sat_rtz(ulong4);
short4 __ovld __cnfn convert_short4_rtp(ulong4);
short4 __ovld __cnfn convert_short4_sat_rtp(ulong4);
short4 __ovld __cnfn convert_short4_rtn(ulong4);
short4 __ovld __cnfn convert_short4_sat_rtn(ulong4);
short4 __ovld __cnfn convert_short4(ulong4);
short4 __ovld __cnfn convert_short4_sat(ulong4);
short4 __ovld __cnfn convert_short4_rte(float4);
short4 __ovld __cnfn convert_short4_sat_rte(float4);
short4 __ovld __cnfn convert_short4_rtz(float4);
short4 __ovld __cnfn convert_short4_sat_rtz(float4);
short4 __ovld __cnfn convert_short4_rtp(float4);
short4 __ovld __cnfn convert_short4_sat_rtp(float4);
short4 __ovld __cnfn convert_short4_rtn(float4);
short4 __ovld __cnfn convert_short4_sat_rtn(float4);
short4 __ovld __cnfn convert_short4(float4);
short4 __ovld __cnfn convert_short4_sat(float4);
ushort4 __ovld __cnfn convert_ushort4_rte(char4);
ushort4 __ovld __cnfn convert_ushort4_sat_rte(char4);
ushort4 __ovld __cnfn convert_ushort4_rtz(char4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtz(char4);
ushort4 __ovld __cnfn convert_ushort4_rtp(char4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtp(char4);
ushort4 __ovld __cnfn convert_ushort4_rtn(char4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtn(char4);
ushort4 __ovld __cnfn convert_ushort4(char4);
ushort4 __ovld __cnfn convert_ushort4_sat(char4);
ushort4 __ovld __cnfn convert_ushort4_rte(uchar4);
ushort4 __ovld __cnfn convert_ushort4_sat_rte(uchar4);
ushort4 __ovld __cnfn convert_ushort4_rtz(uchar4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtz(uchar4);
ushort4 __ovld __cnfn convert_ushort4_rtp(uchar4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtp(uchar4);
ushort4 __ovld __cnfn convert_ushort4_rtn(uchar4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtn(uchar4);
ushort4 __ovld __cnfn convert_ushort4(uchar4);
ushort4 __ovld __cnfn convert_ushort4_sat(uchar4);
ushort4 __ovld __cnfn convert_ushort4_rte(short4);
ushort4 __ovld __cnfn convert_ushort4_sat_rte(short4);
ushort4 __ovld __cnfn convert_ushort4_rtz(short4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtz(short4);
ushort4 __ovld __cnfn convert_ushort4_rtp(short4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtp(short4);
ushort4 __ovld __cnfn convert_ushort4_rtn(short4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtn(short4);
ushort4 __ovld __cnfn convert_ushort4(short4);
ushort4 __ovld __cnfn convert_ushort4_sat(short4);
ushort4 __ovld __cnfn convert_ushort4_rte(ushort4);
ushort4 __ovld __cnfn convert_ushort4_sat_rte(ushort4);
ushort4 __ovld __cnfn convert_ushort4_rtz(ushort4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtz(ushort4);
ushort4 __ovld __cnfn convert_ushort4_rtp(ushort4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtp(ushort4);
ushort4 __ovld __cnfn convert_ushort4_rtn(ushort4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtn(ushort4);
ushort4 __ovld __cnfn convert_ushort4(ushort4);
ushort4 __ovld __cnfn convert_ushort4_sat(ushort4);
ushort4 __ovld __cnfn convert_ushort4_rte(int4);
ushort4 __ovld __cnfn convert_ushort4_sat_rte(int4);
ushort4 __ovld __cnfn convert_ushort4_rtz(int4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtz(int4);
ushort4 __ovld __cnfn convert_ushort4_rtp(int4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtp(int4);
ushort4 __ovld __cnfn convert_ushort4_rtn(int4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtn(int4);
ushort4 __ovld __cnfn convert_ushort4(int4);
ushort4 __ovld __cnfn convert_ushort4_sat(int4);
ushort4 __ovld __cnfn convert_ushort4_rte(uint4);
ushort4 __ovld __cnfn convert_ushort4_sat_rte(uint4);
ushort4 __ovld __cnfn convert_ushort4_rtz(uint4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtz(uint4);
ushort4 __ovld __cnfn convert_ushort4_rtp(uint4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtp(uint4);
ushort4 __ovld __cnfn convert_ushort4_rtn(uint4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtn(uint4);
ushort4 __ovld __cnfn convert_ushort4(uint4);
ushort4 __ovld __cnfn convert_ushort4_sat(uint4);
ushort4 __ovld __cnfn convert_ushort4_rte(long4);
ushort4 __ovld __cnfn convert_ushort4_sat_rte(long4);
ushort4 __ovld __cnfn convert_ushort4_rtz(long4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtz(long4);
ushort4 __ovld __cnfn convert_ushort4_rtp(long4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtp(long4);
ushort4 __ovld __cnfn convert_ushort4_rtn(long4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtn(long4);
ushort4 __ovld __cnfn convert_ushort4(long4);
ushort4 __ovld __cnfn convert_ushort4_sat(long4);
ushort4 __ovld __cnfn convert_ushort4_rte(ulong4);
ushort4 __ovld __cnfn convert_ushort4_sat_rte(ulong4);
ushort4 __ovld __cnfn convert_ushort4_rtz(ulong4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtz(ulong4);
ushort4 __ovld __cnfn convert_ushort4_rtp(ulong4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtp(ulong4);
ushort4 __ovld __cnfn convert_ushort4_rtn(ulong4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtn(ulong4);
ushort4 __ovld __cnfn convert_ushort4(ulong4);
ushort4 __ovld __cnfn convert_ushort4_sat(ulong4);
ushort4 __ovld __cnfn convert_ushort4_rte(float4);
ushort4 __ovld __cnfn convert_ushort4_sat_rte(float4);
ushort4 __ovld __cnfn convert_ushort4_rtz(float4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtz(float4);
ushort4 __ovld __cnfn convert_ushort4_rtp(float4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtp(float4);
ushort4 __ovld __cnfn convert_ushort4_rtn(float4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtn(float4);
ushort4 __ovld __cnfn convert_ushort4(float4);
ushort4 __ovld __cnfn convert_ushort4_sat(float4);
int4 __ovld __cnfn convert_int4_rte(char4);
int4 __ovld __cnfn convert_int4_sat_rte(char4);
int4 __ovld __cnfn convert_int4_rtz(char4);
int4 __ovld __cnfn convert_int4_sat_rtz(char4);
int4 __ovld __cnfn convert_int4_rtp(char4);
int4 __ovld __cnfn convert_int4_sat_rtp(char4);
int4 __ovld __cnfn convert_int4_rtn(char4);
int4 __ovld __cnfn convert_int4_sat_rtn(char4);
int4 __ovld __cnfn convert_int4(char4);
int4 __ovld __cnfn convert_int4_sat(char4);
int4 __ovld __cnfn convert_int4_rte(uchar4);
int4 __ovld __cnfn convert_int4_sat_rte(uchar4);
int4 __ovld __cnfn convert_int4_rtz(uchar4);
int4 __ovld __cnfn convert_int4_sat_rtz(uchar4);
int4 __ovld __cnfn convert_int4_rtp(uchar4);
int4 __ovld __cnfn convert_int4_sat_rtp(uchar4);
int4 __ovld __cnfn convert_int4_rtn(uchar4);
int4 __ovld __cnfn convert_int4_sat_rtn(uchar4);
int4 __ovld __cnfn convert_int4(uchar4);
int4 __ovld __cnfn convert_int4_sat(uchar4);
int4 __ovld __cnfn convert_int4_rte(short4);
int4 __ovld __cnfn convert_int4_sat_rte(short4);
int4 __ovld __cnfn convert_int4_rtz(short4);
int4 __ovld __cnfn convert_int4_sat_rtz(short4);
int4 __ovld __cnfn convert_int4_rtp(short4);
int4 __ovld __cnfn convert_int4_sat_rtp(short4);
int4 __ovld __cnfn convert_int4_rtn(short4);
int4 __ovld __cnfn convert_int4_sat_rtn(short4);
int4 __ovld __cnfn convert_int4(short4);
int4 __ovld __cnfn convert_int4_sat(short4);
int4 __ovld __cnfn convert_int4_rte(ushort4);
int4 __ovld __cnfn convert_int4_sat_rte(ushort4);
int4 __ovld __cnfn convert_int4_rtz(ushort4);
int4 __ovld __cnfn convert_int4_sat_rtz(ushort4);
int4 __ovld __cnfn convert_int4_rtp(ushort4);
int4 __ovld __cnfn convert_int4_sat_rtp(ushort4);
int4 __ovld __cnfn convert_int4_rtn(ushort4);
int4 __ovld __cnfn convert_int4_sat_rtn(ushort4);
int4 __ovld __cnfn convert_int4(ushort4);
int4 __ovld __cnfn convert_int4_sat(ushort4);
int4 __ovld __cnfn convert_int4_rte(int4);
int4 __ovld __cnfn convert_int4_sat_rte(int4);
int4 __ovld __cnfn convert_int4_rtz(int4);
int4 __ovld __cnfn convert_int4_sat_rtz(int4);
int4 __ovld __cnfn convert_int4_rtp(int4);
int4 __ovld __cnfn convert_int4_sat_rtp(int4);
int4 __ovld __cnfn convert_int4_rtn(int4);
int4 __ovld __cnfn convert_int4_sat_rtn(int4);
int4 __ovld __cnfn convert_int4(int4);
int4 __ovld __cnfn convert_int4_sat(int4);
int4 __ovld __cnfn convert_int4_rte(uint4);
int4 __ovld __cnfn convert_int4_sat_rte(uint4);
int4 __ovld __cnfn convert_int4_rtz(uint4);
int4 __ovld __cnfn convert_int4_sat_rtz(uint4);
int4 __ovld __cnfn convert_int4_rtp(uint4);
int4 __ovld __cnfn convert_int4_sat_rtp(uint4);
int4 __ovld __cnfn convert_int4_rtn(uint4);
int4 __ovld __cnfn convert_int4_sat_rtn(uint4);
int4 __ovld __cnfn convert_int4(uint4);
int4 __ovld __cnfn convert_int4_sat(uint4);
int4 __ovld __cnfn convert_int4_rte(long4);
int4 __ovld __cnfn convert_int4_sat_rte(long4);
int4 __ovld __cnfn convert_int4_rtz(long4);
int4 __ovld __cnfn convert_int4_sat_rtz(long4);
int4 __ovld __cnfn convert_int4_rtp(long4);
int4 __ovld __cnfn convert_int4_sat_rtp(long4);
int4 __ovld __cnfn convert_int4_rtn(long4);
int4 __ovld __cnfn convert_int4_sat_rtn(long4);
int4 __ovld __cnfn convert_int4(long4);
int4 __ovld __cnfn convert_int4_sat(long4);
int4 __ovld __cnfn convert_int4_rte(ulong4);
int4 __ovld __cnfn convert_int4_sat_rte(ulong4);
int4 __ovld __cnfn convert_int4_rtz(ulong4);
int4 __ovld __cnfn convert_int4_sat_rtz(ulong4);
int4 __ovld __cnfn convert_int4_rtp(ulong4);
int4 __ovld __cnfn convert_int4_sat_rtp(ulong4);
int4 __ovld __cnfn convert_int4_rtn(ulong4);
int4 __ovld __cnfn convert_int4_sat_rtn(ulong4);
int4 __ovld __cnfn convert_int4(ulong4);
int4 __ovld __cnfn convert_int4_sat(ulong4);
int4 __ovld __cnfn convert_int4_rte(float4);
int4 __ovld __cnfn convert_int4_sat_rte(float4);
int4 __ovld __cnfn convert_int4_rtz(float4);
int4 __ovld __cnfn convert_int4_sat_rtz(float4);
int4 __ovld __cnfn convert_int4_rtp(float4);
int4 __ovld __cnfn convert_int4_sat_rtp(float4);
int4 __ovld __cnfn convert_int4_rtn(float4);
int4 __ovld __cnfn convert_int4_sat_rtn(float4);
int4 __ovld __cnfn convert_int4(float4);
int4 __ovld __cnfn convert_int4_sat(float4);
uint4 __ovld __cnfn convert_uint4_rte(char4);
uint4 __ovld __cnfn convert_uint4_sat_rte(char4);
uint4 __ovld __cnfn convert_uint4_rtz(char4);
uint4 __ovld __cnfn convert_uint4_sat_rtz(char4);
uint4 __ovld __cnfn convert_uint4_rtp(char4);
uint4 __ovld __cnfn convert_uint4_sat_rtp(char4);
uint4 __ovld __cnfn convert_uint4_rtn(char4);
uint4 __ovld __cnfn convert_uint4_sat_rtn(char4);
uint4 __ovld __cnfn convert_uint4(char4);
uint4 __ovld __cnfn convert_uint4_sat(char4);
uint4 __ovld __cnfn convert_uint4_rte(uchar4);
uint4 __ovld __cnfn convert_uint4_sat_rte(uchar4);
uint4 __ovld __cnfn convert_uint4_rtz(uchar4);
uint4 __ovld __cnfn convert_uint4_sat_rtz(uchar4);
uint4 __ovld __cnfn convert_uint4_rtp(uchar4);
uint4 __ovld __cnfn convert_uint4_sat_rtp(uchar4);
uint4 __ovld __cnfn convert_uint4_rtn(uchar4);
uint4 __ovld __cnfn convert_uint4_sat_rtn(uchar4);
uint4 __ovld __cnfn convert_uint4(uchar4);
uint4 __ovld __cnfn convert_uint4_sat(uchar4);
uint4 __ovld __cnfn convert_uint4_rte(short4);
uint4 __ovld __cnfn convert_uint4_sat_rte(short4);
uint4 __ovld __cnfn convert_uint4_rtz(short4);
uint4 __ovld __cnfn convert_uint4_sat_rtz(short4);
uint4 __ovld __cnfn convert_uint4_rtp(short4);
uint4 __ovld __cnfn convert_uint4_sat_rtp(short4);
uint4 __ovld __cnfn convert_uint4_rtn(short4);
uint4 __ovld __cnfn convert_uint4_sat_rtn(short4);
uint4 __ovld __cnfn convert_uint4(short4);
uint4 __ovld __cnfn convert_uint4_sat(short4);
uint4 __ovld __cnfn convert_uint4_rte(ushort4);
uint4 __ovld __cnfn convert_uint4_sat_rte(ushort4);
uint4 __ovld __cnfn convert_uint4_rtz(ushort4);
uint4 __ovld __cnfn convert_uint4_sat_rtz(ushort4);
uint4 __ovld __cnfn convert_uint4_rtp(ushort4);
uint4 __ovld __cnfn convert_uint4_sat_rtp(ushort4);
uint4 __ovld __cnfn convert_uint4_rtn(ushort4);
uint4 __ovld __cnfn convert_uint4_sat_rtn(ushort4);
uint4 __ovld __cnfn convert_uint4(ushort4);
uint4 __ovld __cnfn convert_uint4_sat(ushort4);
uint4 __ovld __cnfn convert_uint4_rte(int4);
uint4 __ovld __cnfn convert_uint4_sat_rte(int4);
uint4 __ovld __cnfn convert_uint4_rtz(int4);
uint4 __ovld __cnfn convert_uint4_sat_rtz(int4);
uint4 __ovld __cnfn convert_uint4_rtp(int4);
uint4 __ovld __cnfn convert_uint4_sat_rtp(int4);
uint4 __ovld __cnfn convert_uint4_rtn(int4);
uint4 __ovld __cnfn convert_uint4_sat_rtn(int4);
uint4 __ovld __cnfn convert_uint4(int4);
uint4 __ovld __cnfn convert_uint4_sat(int4);
uint4 __ovld __cnfn convert_uint4_rte(uint4);
uint4 __ovld __cnfn convert_uint4_sat_rte(uint4);
uint4 __ovld __cnfn convert_uint4_rtz(uint4);
uint4 __ovld __cnfn convert_uint4_sat_rtz(uint4);
uint4 __ovld __cnfn convert_uint4_rtp(uint4);
uint4 __ovld __cnfn convert_uint4_sat_rtp(uint4);
uint4 __ovld __cnfn convert_uint4_rtn(uint4);
uint4 __ovld __cnfn convert_uint4_sat_rtn(uint4);
uint4 __ovld __cnfn convert_uint4(uint4);
uint4 __ovld __cnfn convert_uint4_sat(uint4);
uint4 __ovld __cnfn convert_uint4_rte(long4);
uint4 __ovld __cnfn convert_uint4_sat_rte(long4);
uint4 __ovld __cnfn convert_uint4_rtz(long4);
uint4 __ovld __cnfn convert_uint4_sat_rtz(long4);
uint4 __ovld __cnfn convert_uint4_rtp(long4);
uint4 __ovld __cnfn convert_uint4_sat_rtp(long4);
uint4 __ovld __cnfn convert_uint4_rtn(long4);
uint4 __ovld __cnfn convert_uint4_sat_rtn(long4);
uint4 __ovld __cnfn convert_uint4(long4);
uint4 __ovld __cnfn convert_uint4_sat(long4);
uint4 __ovld __cnfn convert_uint4_rte(ulong4);
uint4 __ovld __cnfn convert_uint4_sat_rte(ulong4);
uint4 __ovld __cnfn convert_uint4_rtz(ulong4);
uint4 __ovld __cnfn convert_uint4_sat_rtz(ulong4);
uint4 __ovld __cnfn convert_uint4_rtp(ulong4);
uint4 __ovld __cnfn convert_uint4_sat_rtp(ulong4);
uint4 __ovld __cnfn convert_uint4_rtn(ulong4);
uint4 __ovld __cnfn convert_uint4_sat_rtn(ulong4);
uint4 __ovld __cnfn convert_uint4(ulong4);
uint4 __ovld __cnfn convert_uint4_sat(ulong4);
uint4 __ovld __cnfn convert_uint4_rte(float4);
uint4 __ovld __cnfn convert_uint4_sat_rte(float4);
uint4 __ovld __cnfn convert_uint4_rtz(float4);
uint4 __ovld __cnfn convert_uint4_sat_rtz(float4);
uint4 __ovld __cnfn convert_uint4_rtp(float4);
uint4 __ovld __cnfn convert_uint4_sat_rtp(float4);
uint4 __ovld __cnfn convert_uint4_rtn(float4);
uint4 __ovld __cnfn convert_uint4_sat_rtn(float4);
uint4 __ovld __cnfn convert_uint4(float4);
uint4 __ovld __cnfn convert_uint4_sat(float4);
long4 __ovld __cnfn convert_long4_rte(char4);
long4 __ovld __cnfn convert_long4_sat_rte(char4);
long4 __ovld __cnfn convert_long4_rtz(char4);
long4 __ovld __cnfn convert_long4_sat_rtz(char4);
long4 __ovld __cnfn convert_long4_rtp(char4);
long4 __ovld __cnfn convert_long4_sat_rtp(char4);
long4 __ovld __cnfn convert_long4_rtn(char4);
long4 __ovld __cnfn convert_long4_sat_rtn(char4);
long4 __ovld __cnfn convert_long4(char4);
long4 __ovld __cnfn convert_long4_sat(char4);
long4 __ovld __cnfn convert_long4_rte(uchar4);
long4 __ovld __cnfn convert_long4_sat_rte(uchar4);
long4 __ovld __cnfn convert_long4_rtz(uchar4);
long4 __ovld __cnfn convert_long4_sat_rtz(uchar4);
long4 __ovld __cnfn convert_long4_rtp(uchar4);
long4 __ovld __cnfn convert_long4_sat_rtp(uchar4);
long4 __ovld __cnfn convert_long4_rtn(uchar4);
long4 __ovld __cnfn convert_long4_sat_rtn(uchar4);
long4 __ovld __cnfn convert_long4(uchar4);
long4 __ovld __cnfn convert_long4_sat(uchar4);
long4 __ovld __cnfn convert_long4_rte(short4);
long4 __ovld __cnfn convert_long4_sat_rte(short4);
long4 __ovld __cnfn convert_long4_rtz(short4);
long4 __ovld __cnfn convert_long4_sat_rtz(short4);
long4 __ovld __cnfn convert_long4_rtp(short4);
long4 __ovld __cnfn convert_long4_sat_rtp(short4);
long4 __ovld __cnfn convert_long4_rtn(short4);
long4 __ovld __cnfn convert_long4_sat_rtn(short4);
long4 __ovld __cnfn convert_long4(short4);
long4 __ovld __cnfn convert_long4_sat(short4);
long4 __ovld __cnfn convert_long4_rte(ushort4);
long4 __ovld __cnfn convert_long4_sat_rte(ushort4);
long4 __ovld __cnfn convert_long4_rtz(ushort4);
long4 __ovld __cnfn convert_long4_sat_rtz(ushort4);
long4 __ovld __cnfn convert_long4_rtp(ushort4);
long4 __ovld __cnfn convert_long4_sat_rtp(ushort4);
long4 __ovld __cnfn convert_long4_rtn(ushort4);
long4 __ovld __cnfn convert_long4_sat_rtn(ushort4);
long4 __ovld __cnfn convert_long4(ushort4);
long4 __ovld __cnfn convert_long4_sat(ushort4);
long4 __ovld __cnfn convert_long4_rte(int4);
long4 __ovld __cnfn convert_long4_sat_rte(int4);
long4 __ovld __cnfn convert_long4_rtz(int4);
long4 __ovld __cnfn convert_long4_sat_rtz(int4);
long4 __ovld __cnfn convert_long4_rtp(int4);
long4 __ovld __cnfn convert_long4_sat_rtp(int4);
long4 __ovld __cnfn convert_long4_rtn(int4);
long4 __ovld __cnfn convert_long4_sat_rtn(int4);
long4 __ovld __cnfn convert_long4(int4);
long4 __ovld __cnfn convert_long4_sat(int4);
long4 __ovld __cnfn convert_long4_rte(uint4);
long4 __ovld __cnfn convert_long4_sat_rte(uint4);
long4 __ovld __cnfn convert_long4_rtz(uint4);
long4 __ovld __cnfn convert_long4_sat_rtz(uint4);
long4 __ovld __cnfn convert_long4_rtp(uint4);
long4 __ovld __cnfn convert_long4_sat_rtp(uint4);
long4 __ovld __cnfn convert_long4_rtn(uint4);
long4 __ovld __cnfn convert_long4_sat_rtn(uint4);
long4 __ovld __cnfn convert_long4(uint4);
long4 __ovld __cnfn convert_long4_sat(uint4);
long4 __ovld __cnfn convert_long4_rte(long4);
long4 __ovld __cnfn convert_long4_sat_rte(long4);
long4 __ovld __cnfn convert_long4_rtz(long4);
long4 __ovld __cnfn convert_long4_sat_rtz(long4);
long4 __ovld __cnfn convert_long4_rtp(long4);
long4 __ovld __cnfn convert_long4_sat_rtp(long4);
long4 __ovld __cnfn convert_long4_rtn(long4);
long4 __ovld __cnfn convert_long4_sat_rtn(long4);
long4 __ovld __cnfn convert_long4(long4);
long4 __ovld __cnfn convert_long4_sat(long4);
long4 __ovld __cnfn convert_long4_rte(ulong4);
long4 __ovld __cnfn convert_long4_sat_rte(ulong4);
long4 __ovld __cnfn convert_long4_rtz(ulong4);
long4 __ovld __cnfn convert_long4_sat_rtz(ulong4);
long4 __ovld __cnfn convert_long4_rtp(ulong4);
long4 __ovld __cnfn convert_long4_sat_rtp(ulong4);
long4 __ovld __cnfn convert_long4_rtn(ulong4);
long4 __ovld __cnfn convert_long4_sat_rtn(ulong4);
long4 __ovld __cnfn convert_long4(ulong4);
long4 __ovld __cnfn convert_long4_sat(ulong4);
long4 __ovld __cnfn convert_long4_rte(float4);
long4 __ovld __cnfn convert_long4_sat_rte(float4);
long4 __ovld __cnfn convert_long4_rtz(float4);
long4 __ovld __cnfn convert_long4_sat_rtz(float4);
long4 __ovld __cnfn convert_long4_rtp(float4);
long4 __ovld __cnfn convert_long4_sat_rtp(float4);
long4 __ovld __cnfn convert_long4_rtn(float4);
long4 __ovld __cnfn convert_long4_sat_rtn(float4);
long4 __ovld __cnfn convert_long4(float4);
long4 __ovld __cnfn convert_long4_sat(float4);
ulong4 __ovld __cnfn convert_ulong4_rte(char4);
ulong4 __ovld __cnfn convert_ulong4_sat_rte(char4);
ulong4 __ovld __cnfn convert_ulong4_rtz(char4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtz(char4);
ulong4 __ovld __cnfn convert_ulong4_rtp(char4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtp(char4);
ulong4 __ovld __cnfn convert_ulong4_rtn(char4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtn(char4);
ulong4 __ovld __cnfn convert_ulong4(char4);
ulong4 __ovld __cnfn convert_ulong4_sat(char4);
ulong4 __ovld __cnfn convert_ulong4_rte(uchar4);
ulong4 __ovld __cnfn convert_ulong4_sat_rte(uchar4);
ulong4 __ovld __cnfn convert_ulong4_rtz(uchar4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtz(uchar4);
ulong4 __ovld __cnfn convert_ulong4_rtp(uchar4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtp(uchar4);
ulong4 __ovld __cnfn convert_ulong4_rtn(uchar4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtn(uchar4);
ulong4 __ovld __cnfn convert_ulong4(uchar4);
ulong4 __ovld __cnfn convert_ulong4_sat(uchar4);
ulong4 __ovld __cnfn convert_ulong4_rte(short4);
ulong4 __ovld __cnfn convert_ulong4_sat_rte(short4);
ulong4 __ovld __cnfn convert_ulong4_rtz(short4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtz(short4);
ulong4 __ovld __cnfn convert_ulong4_rtp(short4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtp(short4);
ulong4 __ovld __cnfn convert_ulong4_rtn(short4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtn(short4);
ulong4 __ovld __cnfn convert_ulong4(short4);
ulong4 __ovld __cnfn convert_ulong4_sat(short4);
ulong4 __ovld __cnfn convert_ulong4_rte(ushort4);
ulong4 __ovld __cnfn convert_ulong4_sat_rte(ushort4);
ulong4 __ovld __cnfn convert_ulong4_rtz(ushort4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtz(ushort4);
ulong4 __ovld __cnfn convert_ulong4_rtp(ushort4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtp(ushort4);
ulong4 __ovld __cnfn convert_ulong4_rtn(ushort4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtn(ushort4);
ulong4 __ovld __cnfn convert_ulong4(ushort4);
ulong4 __ovld __cnfn convert_ulong4_sat(ushort4);
ulong4 __ovld __cnfn convert_ulong4_rte(int4);
ulong4 __ovld __cnfn convert_ulong4_sat_rte(int4);
ulong4 __ovld __cnfn convert_ulong4_rtz(int4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtz(int4);
ulong4 __ovld __cnfn convert_ulong4_rtp(int4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtp(int4);
ulong4 __ovld __cnfn convert_ulong4_rtn(int4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtn(int4);
ulong4 __ovld __cnfn convert_ulong4(int4);
ulong4 __ovld __cnfn convert_ulong4_sat(int4);
ulong4 __ovld __cnfn convert_ulong4_rte(uint4);
ulong4 __ovld __cnfn convert_ulong4_sat_rte(uint4);
ulong4 __ovld __cnfn convert_ulong4_rtz(uint4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtz(uint4);
ulong4 __ovld __cnfn convert_ulong4_rtp(uint4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtp(uint4);
ulong4 __ovld __cnfn convert_ulong4_rtn(uint4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtn(uint4);
ulong4 __ovld __cnfn convert_ulong4(uint4);
ulong4 __ovld __cnfn convert_ulong4_sat(uint4);
ulong4 __ovld __cnfn convert_ulong4_rte(long4);
ulong4 __ovld __cnfn convert_ulong4_sat_rte(long4);
ulong4 __ovld __cnfn convert_ulong4_rtz(long4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtz(long4);
ulong4 __ovld __cnfn convert_ulong4_rtp(long4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtp(long4);
ulong4 __ovld __cnfn convert_ulong4_rtn(long4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtn(long4);
ulong4 __ovld __cnfn convert_ulong4(long4);
ulong4 __ovld __cnfn convert_ulong4_sat(long4);
ulong4 __ovld __cnfn convert_ulong4_rte(ulong4);
ulong4 __ovld __cnfn convert_ulong4_sat_rte(ulong4);
ulong4 __ovld __cnfn convert_ulong4_rtz(ulong4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtz(ulong4);
ulong4 __ovld __cnfn convert_ulong4_rtp(ulong4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtp(ulong4);
ulong4 __ovld __cnfn convert_ulong4_rtn(ulong4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtn(ulong4);
ulong4 __ovld __cnfn convert_ulong4(ulong4);
ulong4 __ovld __cnfn convert_ulong4_sat(ulong4);
ulong4 __ovld __cnfn convert_ulong4_rte(float4);
ulong4 __ovld __cnfn convert_ulong4_sat_rte(float4);
ulong4 __ovld __cnfn convert_ulong4_rtz(float4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtz(float4);
ulong4 __ovld __cnfn convert_ulong4_rtp(float4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtp(float4);
ulong4 __ovld __cnfn convert_ulong4_rtn(float4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtn(float4);
ulong4 __ovld __cnfn convert_ulong4(float4);
ulong4 __ovld __cnfn convert_ulong4_sat(float4);
float4 __ovld __cnfn convert_float4_rte(char4);
float4 __ovld __cnfn convert_float4_rtz(char4);
float4 __ovld __cnfn convert_float4_rtp(char4);
float4 __ovld __cnfn convert_float4_rtn(char4);
float4 __ovld __cnfn convert_float4(char4);
float4 __ovld __cnfn convert_float4_rte(uchar4);
float4 __ovld __cnfn convert_float4_rtz(uchar4);
float4 __ovld __cnfn convert_float4_rtp(uchar4);
float4 __ovld __cnfn convert_float4_rtn(uchar4);
float4 __ovld __cnfn convert_float4(uchar4);
float4 __ovld __cnfn convert_float4_rte(short4);
float4 __ovld __cnfn convert_float4_rtz(short4);
float4 __ovld __cnfn convert_float4_rtp(short4);
float4 __ovld __cnfn convert_float4_rtn(short4);
float4 __ovld __cnfn convert_float4(short4);
float4 __ovld __cnfn convert_float4_rte(ushort4);
float4 __ovld __cnfn convert_float4_rtz(ushort4);
float4 __ovld __cnfn convert_float4_rtp(ushort4);
float4 __ovld __cnfn convert_float4_rtn(ushort4);
float4 __ovld __cnfn convert_float4(ushort4);
float4 __ovld __cnfn convert_float4_rte(int4);
float4 __ovld __cnfn convert_float4_rtz(int4);
float4 __ovld __cnfn convert_float4_rtp(int4);
float4 __ovld __cnfn convert_float4_rtn(int4);
float4 __ovld __cnfn convert_float4(int4);
float4 __ovld __cnfn convert_float4_rte(uint4);
float4 __ovld __cnfn convert_float4_rtz(uint4);
float4 __ovld __cnfn convert_float4_rtp(uint4);
float4 __ovld __cnfn convert_float4_rtn(uint4);
float4 __ovld __cnfn convert_float4(uint4);
float4 __ovld __cnfn convert_float4_rte(long4);
float4 __ovld __cnfn convert_float4_rtz(long4);
float4 __ovld __cnfn convert_float4_rtp(long4);
float4 __ovld __cnfn convert_float4_rtn(long4);
float4 __ovld __cnfn convert_float4(long4);
float4 __ovld __cnfn convert_float4_rte(ulong4);
float4 __ovld __cnfn convert_float4_rtz(ulong4);
float4 __ovld __cnfn convert_float4_rtp(ulong4);
float4 __ovld __cnfn convert_float4_rtn(ulong4);
float4 __ovld __cnfn convert_float4(ulong4);
float4 __ovld __cnfn convert_float4_rte(float4);
float4 __ovld __cnfn convert_float4_rtz(float4);
float4 __ovld __cnfn convert_float4_rtp(float4);
float4 __ovld __cnfn convert_float4_rtn(float4);
float4 __ovld __cnfn convert_float4(float4);
char8 __ovld __cnfn convert_char8_rte(char8);
char8 __ovld __cnfn convert_char8_sat_rte(char8);
char8 __ovld __cnfn convert_char8_rtz(char8);
char8 __ovld __cnfn convert_char8_sat_rtz(char8);
char8 __ovld __cnfn convert_char8_rtp(char8);
char8 __ovld __cnfn convert_char8_sat_rtp(char8);
char8 __ovld __cnfn convert_char8_rtn(char8);
char8 __ovld __cnfn convert_char8_sat_rtn(char8);
char8 __ovld __cnfn convert_char8(char8);
char8 __ovld __cnfn convert_char8_sat(char8);
char8 __ovld __cnfn convert_char8_rte(uchar8);
char8 __ovld __cnfn convert_char8_sat_rte(uchar8);
char8 __ovld __cnfn convert_char8_rtz(uchar8);
char8 __ovld __cnfn convert_char8_sat_rtz(uchar8);
char8 __ovld __cnfn convert_char8_rtp(uchar8);
char8 __ovld __cnfn convert_char8_sat_rtp(uchar8);
char8 __ovld __cnfn convert_char8_rtn(uchar8);
char8 __ovld __cnfn convert_char8_sat_rtn(uchar8);
char8 __ovld __cnfn convert_char8(uchar8);
char8 __ovld __cnfn convert_char8_sat(uchar8);
char8 __ovld __cnfn convert_char8_rte(short8);
char8 __ovld __cnfn convert_char8_sat_rte(short8);
char8 __ovld __cnfn convert_char8_rtz(short8);
char8 __ovld __cnfn convert_char8_sat_rtz(short8);
char8 __ovld __cnfn convert_char8_rtp(short8);
char8 __ovld __cnfn convert_char8_sat_rtp(short8);
char8 __ovld __cnfn convert_char8_rtn(short8);
char8 __ovld __cnfn convert_char8_sat_rtn(short8);
char8 __ovld __cnfn convert_char8(short8);
char8 __ovld __cnfn convert_char8_sat(short8);
char8 __ovld __cnfn convert_char8_rte(ushort8);
char8 __ovld __cnfn convert_char8_sat_rte(ushort8);
char8 __ovld __cnfn convert_char8_rtz(ushort8);
char8 __ovld __cnfn convert_char8_sat_rtz(ushort8);
char8 __ovld __cnfn convert_char8_rtp(ushort8);
char8 __ovld __cnfn convert_char8_sat_rtp(ushort8);
char8 __ovld __cnfn convert_char8_rtn(ushort8);
char8 __ovld __cnfn convert_char8_sat_rtn(ushort8);
char8 __ovld __cnfn convert_char8(ushort8);
char8 __ovld __cnfn convert_char8_sat(ushort8);
char8 __ovld __cnfn convert_char8_rte(int8);
char8 __ovld __cnfn convert_char8_sat_rte(int8);
char8 __ovld __cnfn convert_char8_rtz(int8);
char8 __ovld __cnfn convert_char8_sat_rtz(int8);
char8 __ovld __cnfn convert_char8_rtp(int8);
char8 __ovld __cnfn convert_char8_sat_rtp(int8);
char8 __ovld __cnfn convert_char8_rtn(int8);
char8 __ovld __cnfn convert_char8_sat_rtn(int8);
char8 __ovld __cnfn convert_char8(int8);
char8 __ovld __cnfn convert_char8_sat(int8);
char8 __ovld __cnfn convert_char8_rte(uint8);
char8 __ovld __cnfn convert_char8_sat_rte(uint8);
char8 __ovld __cnfn convert_char8_rtz(uint8);
char8 __ovld __cnfn convert_char8_sat_rtz(uint8);
char8 __ovld __cnfn convert_char8_rtp(uint8);
char8 __ovld __cnfn convert_char8_sat_rtp(uint8);
char8 __ovld __cnfn convert_char8_rtn(uint8);
char8 __ovld __cnfn convert_char8_sat_rtn(uint8);
char8 __ovld __cnfn convert_char8(uint8);
char8 __ovld __cnfn convert_char8_sat(uint8);
char8 __ovld __cnfn convert_char8_rte(long8);
char8 __ovld __cnfn convert_char8_sat_rte(long8);
char8 __ovld __cnfn convert_char8_rtz(long8);
char8 __ovld __cnfn convert_char8_sat_rtz(long8);
char8 __ovld __cnfn convert_char8_rtp(long8);
char8 __ovld __cnfn convert_char8_sat_rtp(long8);
char8 __ovld __cnfn convert_char8_rtn(long8);
char8 __ovld __cnfn convert_char8_sat_rtn(long8);
char8 __ovld __cnfn convert_char8(long8);
char8 __ovld __cnfn convert_char8_sat(long8);
char8 __ovld __cnfn convert_char8_rte(ulong8);
char8 __ovld __cnfn convert_char8_sat_rte(ulong8);
char8 __ovld __cnfn convert_char8_rtz(ulong8);
char8 __ovld __cnfn convert_char8_sat_rtz(ulong8);
char8 __ovld __cnfn convert_char8_rtp(ulong8);
char8 __ovld __cnfn convert_char8_sat_rtp(ulong8);
char8 __ovld __cnfn convert_char8_rtn(ulong8);
char8 __ovld __cnfn convert_char8_sat_rtn(ulong8);
char8 __ovld __cnfn convert_char8(ulong8);
char8 __ovld __cnfn convert_char8_sat(ulong8);
char8 __ovld __cnfn convert_char8_rte(float8);
char8 __ovld __cnfn convert_char8_sat_rte(float8);
char8 __ovld __cnfn convert_char8_rtz(float8);
char8 __ovld __cnfn convert_char8_sat_rtz(float8);
char8 __ovld __cnfn convert_char8_rtp(float8);
char8 __ovld __cnfn convert_char8_sat_rtp(float8);
char8 __ovld __cnfn convert_char8_rtn(float8);
char8 __ovld __cnfn convert_char8_sat_rtn(float8);
char8 __ovld __cnfn convert_char8(float8);
char8 __ovld __cnfn convert_char8_sat(float8);
uchar8 __ovld __cnfn convert_uchar8_rte(char8);
uchar8 __ovld __cnfn convert_uchar8_sat_rte(char8);
uchar8 __ovld __cnfn convert_uchar8_rtz(char8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtz(char8);
uchar8 __ovld __cnfn convert_uchar8_rtp(char8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtp(char8);
uchar8 __ovld __cnfn convert_uchar8_rtn(char8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtn(char8);
uchar8 __ovld __cnfn convert_uchar8(char8);
uchar8 __ovld __cnfn convert_uchar8_sat(char8);
uchar8 __ovld __cnfn convert_uchar8_rte(uchar8);
uchar8 __ovld __cnfn convert_uchar8_sat_rte(uchar8);
uchar8 __ovld __cnfn convert_uchar8_rtz(uchar8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtz(uchar8);
uchar8 __ovld __cnfn convert_uchar8_rtp(uchar8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtp(uchar8);
uchar8 __ovld __cnfn convert_uchar8_rtn(uchar8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtn(uchar8);
uchar8 __ovld __cnfn convert_uchar8(uchar8);
uchar8 __ovld __cnfn convert_uchar8_sat(uchar8);
uchar8 __ovld __cnfn convert_uchar8_rte(short8);
uchar8 __ovld __cnfn convert_uchar8_sat_rte(short8);
uchar8 __ovld __cnfn convert_uchar8_rtz(short8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtz(short8);
uchar8 __ovld __cnfn convert_uchar8_rtp(short8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtp(short8);
uchar8 __ovld __cnfn convert_uchar8_rtn(short8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtn(short8);
uchar8 __ovld __cnfn convert_uchar8(short8);
uchar8 __ovld __cnfn convert_uchar8_sat(short8);
uchar8 __ovld __cnfn convert_uchar8_rte(ushort8);
uchar8 __ovld __cnfn convert_uchar8_sat_rte(ushort8);
uchar8 __ovld __cnfn convert_uchar8_rtz(ushort8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtz(ushort8);
uchar8 __ovld __cnfn convert_uchar8_rtp(ushort8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtp(ushort8);
uchar8 __ovld __cnfn convert_uchar8_rtn(ushort8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtn(ushort8);
uchar8 __ovld __cnfn convert_uchar8(ushort8);
uchar8 __ovld __cnfn convert_uchar8_sat(ushort8);
uchar8 __ovld __cnfn convert_uchar8_rte(int8);
uchar8 __ovld __cnfn convert_uchar8_sat_rte(int8);
uchar8 __ovld __cnfn convert_uchar8_rtz(int8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtz(int8);
uchar8 __ovld __cnfn convert_uchar8_rtp(int8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtp(int8);
uchar8 __ovld __cnfn convert_uchar8_rtn(int8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtn(int8);
uchar8 __ovld __cnfn convert_uchar8(int8);
uchar8 __ovld __cnfn convert_uchar8_sat(int8);
uchar8 __ovld __cnfn convert_uchar8_rte(uint8);
uchar8 __ovld __cnfn convert_uchar8_sat_rte(uint8);
uchar8 __ovld __cnfn convert_uchar8_rtz(uint8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtz(uint8);
uchar8 __ovld __cnfn convert_uchar8_rtp(uint8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtp(uint8);
uchar8 __ovld __cnfn convert_uchar8_rtn(uint8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtn(uint8);
uchar8 __ovld __cnfn convert_uchar8(uint8);
uchar8 __ovld __cnfn convert_uchar8_sat(uint8);
uchar8 __ovld __cnfn convert_uchar8_rte(long8);
uchar8 __ovld __cnfn convert_uchar8_sat_rte(long8);
uchar8 __ovld __cnfn convert_uchar8_rtz(long8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtz(long8);
uchar8 __ovld __cnfn convert_uchar8_rtp(long8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtp(long8);
uchar8 __ovld __cnfn convert_uchar8_rtn(long8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtn(long8);
uchar8 __ovld __cnfn convert_uchar8(long8);
uchar8 __ovld __cnfn convert_uchar8_sat(long8);
uchar8 __ovld __cnfn convert_uchar8_rte(ulong8);
uchar8 __ovld __cnfn convert_uchar8_sat_rte(ulong8);
uchar8 __ovld __cnfn convert_uchar8_rtz(ulong8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtz(ulong8);
uchar8 __ovld __cnfn convert_uchar8_rtp(ulong8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtp(ulong8);
uchar8 __ovld __cnfn convert_uchar8_rtn(ulong8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtn(ulong8);
uchar8 __ovld __cnfn convert_uchar8(ulong8);
uchar8 __ovld __cnfn convert_uchar8_sat(ulong8);
uchar8 __ovld __cnfn convert_uchar8_rte(float8);
uchar8 __ovld __cnfn convert_uchar8_sat_rte(float8);
uchar8 __ovld __cnfn convert_uchar8_rtz(float8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtz(float8);
uchar8 __ovld __cnfn convert_uchar8_rtp(float8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtp(float8);
uchar8 __ovld __cnfn convert_uchar8_rtn(float8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtn(float8);
uchar8 __ovld __cnfn convert_uchar8(float8);
uchar8 __ovld __cnfn convert_uchar8_sat(float8);
short8 __ovld __cnfn convert_short8_rte(char8);
short8 __ovld __cnfn convert_short8_sat_rte(char8);
short8 __ovld __cnfn convert_short8_rtz(char8);
short8 __ovld __cnfn convert_short8_sat_rtz(char8);
short8 __ovld __cnfn convert_short8_rtp(char8);
short8 __ovld __cnfn convert_short8_sat_rtp(char8);
short8 __ovld __cnfn convert_short8_rtn(char8);
short8 __ovld __cnfn convert_short8_sat_rtn(char8);
short8 __ovld __cnfn convert_short8(char8);
short8 __ovld __cnfn convert_short8_sat(char8);
short8 __ovld __cnfn convert_short8_rte(uchar8);
short8 __ovld __cnfn convert_short8_sat_rte(uchar8);
short8 __ovld __cnfn convert_short8_rtz(uchar8);
short8 __ovld __cnfn convert_short8_sat_rtz(uchar8);
short8 __ovld __cnfn convert_short8_rtp(uchar8);
short8 __ovld __cnfn convert_short8_sat_rtp(uchar8);
short8 __ovld __cnfn convert_short8_rtn(uchar8);
short8 __ovld __cnfn convert_short8_sat_rtn(uchar8);
short8 __ovld __cnfn convert_short8(uchar8);
short8 __ovld __cnfn convert_short8_sat(uchar8);
short8 __ovld __cnfn convert_short8_rte(short8);
short8 __ovld __cnfn convert_short8_sat_rte(short8);
short8 __ovld __cnfn convert_short8_rtz(short8);
short8 __ovld __cnfn convert_short8_sat_rtz(short8);
short8 __ovld __cnfn convert_short8_rtp(short8);
short8 __ovld __cnfn convert_short8_sat_rtp(short8);
short8 __ovld __cnfn convert_short8_rtn(short8);
short8 __ovld __cnfn convert_short8_sat_rtn(short8);
short8 __ovld __cnfn convert_short8(short8);
short8 __ovld __cnfn convert_short8_sat(short8);
short8 __ovld __cnfn convert_short8_rte(ushort8);
short8 __ovld __cnfn convert_short8_sat_rte(ushort8);
short8 __ovld __cnfn convert_short8_rtz(ushort8);
short8 __ovld __cnfn convert_short8_sat_rtz(ushort8);
short8 __ovld __cnfn convert_short8_rtp(ushort8);
short8 __ovld __cnfn convert_short8_sat_rtp(ushort8);
short8 __ovld __cnfn convert_short8_rtn(ushort8);
short8 __ovld __cnfn convert_short8_sat_rtn(ushort8);
short8 __ovld __cnfn convert_short8(ushort8);
short8 __ovld __cnfn convert_short8_sat(ushort8);
short8 __ovld __cnfn convert_short8_rte(int8);
short8 __ovld __cnfn convert_short8_sat_rte(int8);
short8 __ovld __cnfn convert_short8_rtz(int8);
short8 __ovld __cnfn convert_short8_sat_rtz(int8);
short8 __ovld __cnfn convert_short8_rtp(int8);
short8 __ovld __cnfn convert_short8_sat_rtp(int8);
short8 __ovld __cnfn convert_short8_rtn(int8);
short8 __ovld __cnfn convert_short8_sat_rtn(int8);
short8 __ovld __cnfn convert_short8(int8);
short8 __ovld __cnfn convert_short8_sat(int8);
short8 __ovld __cnfn convert_short8_rte(uint8);
short8 __ovld __cnfn convert_short8_sat_rte(uint8);
short8 __ovld __cnfn convert_short8_rtz(uint8);
short8 __ovld __cnfn convert_short8_sat_rtz(uint8);
short8 __ovld __cnfn convert_short8_rtp(uint8);
short8 __ovld __cnfn convert_short8_sat_rtp(uint8);
short8 __ovld __cnfn convert_short8_rtn(uint8);
short8 __ovld __cnfn convert_short8_sat_rtn(uint8);
short8 __ovld __cnfn convert_short8(uint8);
short8 __ovld __cnfn convert_short8_sat(uint8);
short8 __ovld __cnfn convert_short8_rte(long8);
short8 __ovld __cnfn convert_short8_sat_rte(long8);
short8 __ovld __cnfn convert_short8_rtz(long8);
short8 __ovld __cnfn convert_short8_sat_rtz(long8);
short8 __ovld __cnfn convert_short8_rtp(long8);
short8 __ovld __cnfn convert_short8_sat_rtp(long8);
short8 __ovld __cnfn convert_short8_rtn(long8);
short8 __ovld __cnfn convert_short8_sat_rtn(long8);
short8 __ovld __cnfn convert_short8(long8);
short8 __ovld __cnfn convert_short8_sat(long8);
short8 __ovld __cnfn convert_short8_rte(ulong8);
short8 __ovld __cnfn convert_short8_sat_rte(ulong8);
short8 __ovld __cnfn convert_short8_rtz(ulong8);
short8 __ovld __cnfn convert_short8_sat_rtz(ulong8);
short8 __ovld __cnfn convert_short8_rtp(ulong8);
short8 __ovld __cnfn convert_short8_sat_rtp(ulong8);
short8 __ovld __cnfn convert_short8_rtn(ulong8);
short8 __ovld __cnfn convert_short8_sat_rtn(ulong8);
short8 __ovld __cnfn convert_short8(ulong8);
short8 __ovld __cnfn convert_short8_sat(ulong8);
short8 __ovld __cnfn convert_short8_rte(float8);
short8 __ovld __cnfn convert_short8_sat_rte(float8);
short8 __ovld __cnfn convert_short8_rtz(float8);
short8 __ovld __cnfn convert_short8_sat_rtz(float8);
short8 __ovld __cnfn convert_short8_rtp(float8);
short8 __ovld __cnfn convert_short8_sat_rtp(float8);
short8 __ovld __cnfn convert_short8_rtn(float8);
short8 __ovld __cnfn convert_short8_sat_rtn(float8);
short8 __ovld __cnfn convert_short8(float8);
short8 __ovld __cnfn convert_short8_sat(float8);
ushort8 __ovld __cnfn convert_ushort8_rte(char8);
ushort8 __ovld __cnfn convert_ushort8_sat_rte(char8);
ushort8 __ovld __cnfn convert_ushort8_rtz(char8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtz(char8);
ushort8 __ovld __cnfn convert_ushort8_rtp(char8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtp(char8);
ushort8 __ovld __cnfn convert_ushort8_rtn(char8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtn(char8);
ushort8 __ovld __cnfn convert_ushort8(char8);
ushort8 __ovld __cnfn convert_ushort8_sat(char8);
ushort8 __ovld __cnfn convert_ushort8_rte(uchar8);
ushort8 __ovld __cnfn convert_ushort8_sat_rte(uchar8);
ushort8 __ovld __cnfn convert_ushort8_rtz(uchar8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtz(uchar8);
ushort8 __ovld __cnfn convert_ushort8_rtp(uchar8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtp(uchar8);
ushort8 __ovld __cnfn convert_ushort8_rtn(uchar8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtn(uchar8);
ushort8 __ovld __cnfn convert_ushort8(uchar8);
ushort8 __ovld __cnfn convert_ushort8_sat(uchar8);
ushort8 __ovld __cnfn convert_ushort8_rte(short8);
ushort8 __ovld __cnfn convert_ushort8_sat_rte(short8);
ushort8 __ovld __cnfn convert_ushort8_rtz(short8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtz(short8);
ushort8 __ovld __cnfn convert_ushort8_rtp(short8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtp(short8);
ushort8 __ovld __cnfn convert_ushort8_rtn(short8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtn(short8);
ushort8 __ovld __cnfn convert_ushort8(short8);
ushort8 __ovld __cnfn convert_ushort8_sat(short8);
ushort8 __ovld __cnfn convert_ushort8_rte(ushort8);
ushort8 __ovld __cnfn convert_ushort8_sat_rte(ushort8);
ushort8 __ovld __cnfn convert_ushort8_rtz(ushort8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtz(ushort8);
ushort8 __ovld __cnfn convert_ushort8_rtp(ushort8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtp(ushort8);
ushort8 __ovld __cnfn convert_ushort8_rtn(ushort8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtn(ushort8);
ushort8 __ovld __cnfn convert_ushort8(ushort8);
ushort8 __ovld __cnfn convert_ushort8_sat(ushort8);
ushort8 __ovld __cnfn convert_ushort8_rte(int8);
ushort8 __ovld __cnfn convert_ushort8_sat_rte(int8);
ushort8 __ovld __cnfn convert_ushort8_rtz(int8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtz(int8);
ushort8 __ovld __cnfn convert_ushort8_rtp(int8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtp(int8);
ushort8 __ovld __cnfn convert_ushort8_rtn(int8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtn(int8);
ushort8 __ovld __cnfn convert_ushort8(int8);
ushort8 __ovld __cnfn convert_ushort8_sat(int8);
ushort8 __ovld __cnfn convert_ushort8_rte(uint8);
ushort8 __ovld __cnfn convert_ushort8_sat_rte(uint8);
ushort8 __ovld __cnfn convert_ushort8_rtz(uint8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtz(uint8);
ushort8 __ovld __cnfn convert_ushort8_rtp(uint8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtp(uint8);
ushort8 __ovld __cnfn convert_ushort8_rtn(uint8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtn(uint8);
ushort8 __ovld __cnfn convert_ushort8(uint8);
ushort8 __ovld __cnfn convert_ushort8_sat(uint8);
ushort8 __ovld __cnfn convert_ushort8_rte(long8);
ushort8 __ovld __cnfn convert_ushort8_sat_rte(long8);
ushort8 __ovld __cnfn convert_ushort8_rtz(long8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtz(long8);
ushort8 __ovld __cnfn convert_ushort8_rtp(long8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtp(long8);
ushort8 __ovld __cnfn convert_ushort8_rtn(long8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtn(long8);
ushort8 __ovld __cnfn convert_ushort8(long8);
ushort8 __ovld __cnfn convert_ushort8_sat(long8);
ushort8 __ovld __cnfn convert_ushort8_rte(ulong8);
ushort8 __ovld __cnfn convert_ushort8_sat_rte(ulong8);
ushort8 __ovld __cnfn convert_ushort8_rtz(ulong8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtz(ulong8);
ushort8 __ovld __cnfn convert_ushort8_rtp(ulong8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtp(ulong8);
ushort8 __ovld __cnfn convert_ushort8_rtn(ulong8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtn(ulong8);
ushort8 __ovld __cnfn convert_ushort8(ulong8);
ushort8 __ovld __cnfn convert_ushort8_sat(ulong8);
ushort8 __ovld __cnfn convert_ushort8_rte(float8);
ushort8 __ovld __cnfn convert_ushort8_sat_rte(float8);
ushort8 __ovld __cnfn convert_ushort8_rtz(float8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtz(float8);
ushort8 __ovld __cnfn convert_ushort8_rtp(float8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtp(float8);
ushort8 __ovld __cnfn convert_ushort8_rtn(float8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtn(float8);
ushort8 __ovld __cnfn convert_ushort8(float8);
ushort8 __ovld __cnfn convert_ushort8_sat(float8);
int8 __ovld __cnfn convert_int8_rte(char8);
int8 __ovld __cnfn convert_int8_sat_rte(char8);
int8 __ovld __cnfn convert_int8_rtz(char8);
int8 __ovld __cnfn convert_int8_sat_rtz(char8);
int8 __ovld __cnfn convert_int8_rtp(char8);
int8 __ovld __cnfn convert_int8_sat_rtp(char8);
int8 __ovld __cnfn convert_int8_rtn(char8);
int8 __ovld __cnfn convert_int8_sat_rtn(char8);
int8 __ovld __cnfn convert_int8(char8);
int8 __ovld __cnfn convert_int8_sat(char8);
int8 __ovld __cnfn convert_int8_rte(uchar8);
int8 __ovld __cnfn convert_int8_sat_rte(uchar8);
int8 __ovld __cnfn convert_int8_rtz(uchar8);
int8 __ovld __cnfn convert_int8_sat_rtz(uchar8);
int8 __ovld __cnfn convert_int8_rtp(uchar8);
int8 __ovld __cnfn convert_int8_sat_rtp(uchar8);
int8 __ovld __cnfn convert_int8_rtn(uchar8);
int8 __ovld __cnfn convert_int8_sat_rtn(uchar8);
int8 __ovld __cnfn convert_int8(uchar8);
int8 __ovld __cnfn convert_int8_sat(uchar8);
int8 __ovld __cnfn convert_int8_rte(short8);
int8 __ovld __cnfn convert_int8_sat_rte(short8);
int8 __ovld __cnfn convert_int8_rtz(short8);
int8 __ovld __cnfn convert_int8_sat_rtz(short8);
int8 __ovld __cnfn convert_int8_rtp(short8);
int8 __ovld __cnfn convert_int8_sat_rtp(short8);
int8 __ovld __cnfn convert_int8_rtn(short8);
int8 __ovld __cnfn convert_int8_sat_rtn(short8);
int8 __ovld __cnfn convert_int8(short8);
int8 __ovld __cnfn convert_int8_sat(short8);
int8 __ovld __cnfn convert_int8_rte(ushort8);
int8 __ovld __cnfn convert_int8_sat_rte(ushort8);
int8 __ovld __cnfn convert_int8_rtz(ushort8);
int8 __ovld __cnfn convert_int8_sat_rtz(ushort8);
int8 __ovld __cnfn convert_int8_rtp(ushort8);
int8 __ovld __cnfn convert_int8_sat_rtp(ushort8);
int8 __ovld __cnfn convert_int8_rtn(ushort8);
int8 __ovld __cnfn convert_int8_sat_rtn(ushort8);
int8 __ovld __cnfn convert_int8(ushort8);
int8 __ovld __cnfn convert_int8_sat(ushort8);
int8 __ovld __cnfn convert_int8_rte(int8);
int8 __ovld __cnfn convert_int8_sat_rte(int8);
int8 __ovld __cnfn convert_int8_rtz(int8);
int8 __ovld __cnfn convert_int8_sat_rtz(int8);
int8 __ovld __cnfn convert_int8_rtp(int8);
int8 __ovld __cnfn convert_int8_sat_rtp(int8);
int8 __ovld __cnfn convert_int8_rtn(int8);
int8 __ovld __cnfn convert_int8_sat_rtn(int8);
int8 __ovld __cnfn convert_int8(int8);
int8 __ovld __cnfn convert_int8_sat(int8);
int8 __ovld __cnfn convert_int8_rte(uint8);
int8 __ovld __cnfn convert_int8_sat_rte(uint8);
int8 __ovld __cnfn convert_int8_rtz(uint8);
int8 __ovld __cnfn convert_int8_sat_rtz(uint8);
int8 __ovld __cnfn convert_int8_rtp(uint8);
int8 __ovld __cnfn convert_int8_sat_rtp(uint8);
int8 __ovld __cnfn convert_int8_rtn(uint8);
int8 __ovld __cnfn convert_int8_sat_rtn(uint8);
int8 __ovld __cnfn convert_int8(uint8);
int8 __ovld __cnfn convert_int8_sat(uint8);
int8 __ovld __cnfn convert_int8_rte(long8);
int8 __ovld __cnfn convert_int8_sat_rte(long8);
int8 __ovld __cnfn convert_int8_rtz(long8);
int8 __ovld __cnfn convert_int8_sat_rtz(long8);
int8 __ovld __cnfn convert_int8_rtp(long8);
int8 __ovld __cnfn convert_int8_sat_rtp(long8);
int8 __ovld __cnfn convert_int8_rtn(long8);
int8 __ovld __cnfn convert_int8_sat_rtn(long8);
int8 __ovld __cnfn convert_int8(long8);
int8 __ovld __cnfn convert_int8_sat(long8);
int8 __ovld __cnfn convert_int8_rte(ulong8);
int8 __ovld __cnfn convert_int8_sat_rte(ulong8);
int8 __ovld __cnfn convert_int8_rtz(ulong8);
int8 __ovld __cnfn convert_int8_sat_rtz(ulong8);
int8 __ovld __cnfn convert_int8_rtp(ulong8);
int8 __ovld __cnfn convert_int8_sat_rtp(ulong8);
int8 __ovld __cnfn convert_int8_rtn(ulong8);
int8 __ovld __cnfn convert_int8_sat_rtn(ulong8);
int8 __ovld __cnfn convert_int8(ulong8);
int8 __ovld __cnfn convert_int8_sat(ulong8);
int8 __ovld __cnfn convert_int8_rte(float8);
int8 __ovld __cnfn convert_int8_sat_rte(float8);
int8 __ovld __cnfn convert_int8_rtz(float8);
int8 __ovld __cnfn convert_int8_sat_rtz(float8);
int8 __ovld __cnfn convert_int8_rtp(float8);
int8 __ovld __cnfn convert_int8_sat_rtp(float8);
int8 __ovld __cnfn convert_int8_rtn(float8);
int8 __ovld __cnfn convert_int8_sat_rtn(float8);
int8 __ovld __cnfn convert_int8(float8);
int8 __ovld __cnfn convert_int8_sat(float8);
uint8 __ovld __cnfn convert_uint8_rte(char8);
uint8 __ovld __cnfn convert_uint8_sat_rte(char8);
uint8 __ovld __cnfn convert_uint8_rtz(char8);
uint8 __ovld __cnfn convert_uint8_sat_rtz(char8);
uint8 __ovld __cnfn convert_uint8_rtp(char8);
uint8 __ovld __cnfn convert_uint8_sat_rtp(char8);
uint8 __ovld __cnfn convert_uint8_rtn(char8);
uint8 __ovld __cnfn convert_uint8_sat_rtn(char8);
uint8 __ovld __cnfn convert_uint8(char8);
uint8 __ovld __cnfn convert_uint8_sat(char8);
uint8 __ovld __cnfn convert_uint8_rte(uchar8);
uint8 __ovld __cnfn convert_uint8_sat_rte(uchar8);
uint8 __ovld __cnfn convert_uint8_rtz(uchar8);
uint8 __ovld __cnfn convert_uint8_sat_rtz(uchar8);
uint8 __ovld __cnfn convert_uint8_rtp(uchar8);
uint8 __ovld __cnfn convert_uint8_sat_rtp(uchar8);
uint8 __ovld __cnfn convert_uint8_rtn(uchar8);
uint8 __ovld __cnfn convert_uint8_sat_rtn(uchar8);
uint8 __ovld __cnfn convert_uint8(uchar8);
uint8 __ovld __cnfn convert_uint8_sat(uchar8);
uint8 __ovld __cnfn convert_uint8_rte(short8);
uint8 __ovld __cnfn convert_uint8_sat_rte(short8);
uint8 __ovld __cnfn convert_uint8_rtz(short8);
uint8 __ovld __cnfn convert_uint8_sat_rtz(short8);
uint8 __ovld __cnfn convert_uint8_rtp(short8);
uint8 __ovld __cnfn convert_uint8_sat_rtp(short8);
uint8 __ovld __cnfn convert_uint8_rtn(short8);
uint8 __ovld __cnfn convert_uint8_sat_rtn(short8);
uint8 __ovld __cnfn convert_uint8(short8);
uint8 __ovld __cnfn convert_uint8_sat(short8);
uint8 __ovld __cnfn convert_uint8_rte(ushort8);
uint8 __ovld __cnfn convert_uint8_sat_rte(ushort8);
uint8 __ovld __cnfn convert_uint8_rtz(ushort8);
uint8 __ovld __cnfn convert_uint8_sat_rtz(ushort8);
uint8 __ovld __cnfn convert_uint8_rtp(ushort8);
uint8 __ovld __cnfn convert_uint8_sat_rtp(ushort8);
uint8 __ovld __cnfn convert_uint8_rtn(ushort8);
uint8 __ovld __cnfn convert_uint8_sat_rtn(ushort8);
uint8 __ovld __cnfn convert_uint8(ushort8);
uint8 __ovld __cnfn convert_uint8_sat(ushort8);
uint8 __ovld __cnfn convert_uint8_rte(int8);
uint8 __ovld __cnfn convert_uint8_sat_rte(int8);
uint8 __ovld __cnfn convert_uint8_rtz(int8);
uint8 __ovld __cnfn convert_uint8_sat_rtz(int8);
uint8 __ovld __cnfn convert_uint8_rtp(int8);
uint8 __ovld __cnfn convert_uint8_sat_rtp(int8);
uint8 __ovld __cnfn convert_uint8_rtn(int8);
uint8 __ovld __cnfn convert_uint8_sat_rtn(int8);
uint8 __ovld __cnfn convert_uint8(int8);
uint8 __ovld __cnfn convert_uint8_sat(int8);
uint8 __ovld __cnfn convert_uint8_rte(uint8);
uint8 __ovld __cnfn convert_uint8_sat_rte(uint8);
uint8 __ovld __cnfn convert_uint8_rtz(uint8);
uint8 __ovld __cnfn convert_uint8_sat_rtz(uint8);
uint8 __ovld __cnfn convert_uint8_rtp(uint8);
uint8 __ovld __cnfn convert_uint8_sat_rtp(uint8);
uint8 __ovld __cnfn convert_uint8_rtn(uint8);
uint8 __ovld __cnfn convert_uint8_sat_rtn(uint8);
uint8 __ovld __cnfn convert_uint8(uint8);
uint8 __ovld __cnfn convert_uint8_sat(uint8);
uint8 __ovld __cnfn convert_uint8_rte(long8);
uint8 __ovld __cnfn convert_uint8_sat_rte(long8);
uint8 __ovld __cnfn convert_uint8_rtz(long8);
uint8 __ovld __cnfn convert_uint8_sat_rtz(long8);
uint8 __ovld __cnfn convert_uint8_rtp(long8);
uint8 __ovld __cnfn convert_uint8_sat_rtp(long8);
uint8 __ovld __cnfn convert_uint8_rtn(long8);
uint8 __ovld __cnfn convert_uint8_sat_rtn(long8);
uint8 __ovld __cnfn convert_uint8(long8);
uint8 __ovld __cnfn convert_uint8_sat(long8);
uint8 __ovld __cnfn convert_uint8_rte(ulong8);
uint8 __ovld __cnfn convert_uint8_sat_rte(ulong8);
uint8 __ovld __cnfn convert_uint8_rtz(ulong8);
uint8 __ovld __cnfn convert_uint8_sat_rtz(ulong8);
uint8 __ovld __cnfn convert_uint8_rtp(ulong8);
uint8 __ovld __cnfn convert_uint8_sat_rtp(ulong8);
uint8 __ovld __cnfn convert_uint8_rtn(ulong8);
uint8 __ovld __cnfn convert_uint8_sat_rtn(ulong8);
uint8 __ovld __cnfn convert_uint8(ulong8);
uint8 __ovld __cnfn convert_uint8_sat(ulong8);
uint8 __ovld __cnfn convert_uint8_rte(float8);
uint8 __ovld __cnfn convert_uint8_sat_rte(float8);
uint8 __ovld __cnfn convert_uint8_rtz(float8);
uint8 __ovld __cnfn convert_uint8_sat_rtz(float8);
uint8 __ovld __cnfn convert_uint8_rtp(float8);
uint8 __ovld __cnfn convert_uint8_sat_rtp(float8);
uint8 __ovld __cnfn convert_uint8_rtn(float8);
uint8 __ovld __cnfn convert_uint8_sat_rtn(float8);
uint8 __ovld __cnfn convert_uint8(float8);
uint8 __ovld __cnfn convert_uint8_sat(float8);
long8 __ovld __cnfn convert_long8_rte(char8);
long8 __ovld __cnfn convert_long8_sat_rte(char8);
long8 __ovld __cnfn convert_long8_rtz(char8);
long8 __ovld __cnfn convert_long8_sat_rtz(char8);
long8 __ovld __cnfn convert_long8_rtp(char8);
long8 __ovld __cnfn convert_long8_sat_rtp(char8);
long8 __ovld __cnfn convert_long8_rtn(char8);
long8 __ovld __cnfn convert_long8_sat_rtn(char8);
long8 __ovld __cnfn convert_long8(char8);
long8 __ovld __cnfn convert_long8_sat(char8);
long8 __ovld __cnfn convert_long8_rte(uchar8);
long8 __ovld __cnfn convert_long8_sat_rte(uchar8);
long8 __ovld __cnfn convert_long8_rtz(uchar8);
long8 __ovld __cnfn convert_long8_sat_rtz(uchar8);
long8 __ovld __cnfn convert_long8_rtp(uchar8);
long8 __ovld __cnfn convert_long8_sat_rtp(uchar8);
long8 __ovld __cnfn convert_long8_rtn(uchar8);
long8 __ovld __cnfn convert_long8_sat_rtn(uchar8);
long8 __ovld __cnfn convert_long8(uchar8);
long8 __ovld __cnfn convert_long8_sat(uchar8);
long8 __ovld __cnfn convert_long8_rte(short8);
long8 __ovld __cnfn convert_long8_sat_rte(short8);
long8 __ovld __cnfn convert_long8_rtz(short8);
long8 __ovld __cnfn convert_long8_sat_rtz(short8);
long8 __ovld __cnfn convert_long8_rtp(short8);
long8 __ovld __cnfn convert_long8_sat_rtp(short8);
long8 __ovld __cnfn convert_long8_rtn(short8);
long8 __ovld __cnfn convert_long8_sat_rtn(short8);
long8 __ovld __cnfn convert_long8(short8);
long8 __ovld __cnfn convert_long8_sat(short8);
long8 __ovld __cnfn convert_long8_rte(ushort8);
long8 __ovld __cnfn convert_long8_sat_rte(ushort8);
long8 __ovld __cnfn convert_long8_rtz(ushort8);
long8 __ovld __cnfn convert_long8_sat_rtz(ushort8);
long8 __ovld __cnfn convert_long8_rtp(ushort8);
long8 __ovld __cnfn convert_long8_sat_rtp(ushort8);
long8 __ovld __cnfn convert_long8_rtn(ushort8);
long8 __ovld __cnfn convert_long8_sat_rtn(ushort8);
long8 __ovld __cnfn convert_long8(ushort8);
long8 __ovld __cnfn convert_long8_sat(ushort8);
long8 __ovld __cnfn convert_long8_rte(int8);
long8 __ovld __cnfn convert_long8_sat_rte(int8);
long8 __ovld __cnfn convert_long8_rtz(int8);
long8 __ovld __cnfn convert_long8_sat_rtz(int8);
long8 __ovld __cnfn convert_long8_rtp(int8);
long8 __ovld __cnfn convert_long8_sat_rtp(int8);
long8 __ovld __cnfn convert_long8_rtn(int8);
long8 __ovld __cnfn convert_long8_sat_rtn(int8);
long8 __ovld __cnfn convert_long8(int8);
long8 __ovld __cnfn convert_long8_sat(int8);
long8 __ovld __cnfn convert_long8_rte(uint8);
long8 __ovld __cnfn convert_long8_sat_rte(uint8);
long8 __ovld __cnfn convert_long8_rtz(uint8);
long8 __ovld __cnfn convert_long8_sat_rtz(uint8);
long8 __ovld __cnfn convert_long8_rtp(uint8);
long8 __ovld __cnfn convert_long8_sat_rtp(uint8);
long8 __ovld __cnfn convert_long8_rtn(uint8);
long8 __ovld __cnfn convert_long8_sat_rtn(uint8);
long8 __ovld __cnfn convert_long8(uint8);
long8 __ovld __cnfn convert_long8_sat(uint8);
long8 __ovld __cnfn convert_long8_rte(long8);
long8 __ovld __cnfn convert_long8_sat_rte(long8);
long8 __ovld __cnfn convert_long8_rtz(long8);
long8 __ovld __cnfn convert_long8_sat_rtz(long8);
long8 __ovld __cnfn convert_long8_rtp(long8);
long8 __ovld __cnfn convert_long8_sat_rtp(long8);
long8 __ovld __cnfn convert_long8_rtn(long8);
long8 __ovld __cnfn convert_long8_sat_rtn(long8);
long8 __ovld __cnfn convert_long8(long8);
long8 __ovld __cnfn convert_long8_sat(long8);
long8 __ovld __cnfn convert_long8_rte(ulong8);
long8 __ovld __cnfn convert_long8_sat_rte(ulong8);
long8 __ovld __cnfn convert_long8_rtz(ulong8);
long8 __ovld __cnfn convert_long8_sat_rtz(ulong8);
long8 __ovld __cnfn convert_long8_rtp(ulong8);
long8 __ovld __cnfn convert_long8_sat_rtp(ulong8);
long8 __ovld __cnfn convert_long8_rtn(ulong8);
long8 __ovld __cnfn convert_long8_sat_rtn(ulong8);
long8 __ovld __cnfn convert_long8(ulong8);
long8 __ovld __cnfn convert_long8_sat(ulong8);
long8 __ovld __cnfn convert_long8_rte(float8);
long8 __ovld __cnfn convert_long8_sat_rte(float8);
long8 __ovld __cnfn convert_long8_rtz(float8);
long8 __ovld __cnfn convert_long8_sat_rtz(float8);
long8 __ovld __cnfn convert_long8_rtp(float8);
long8 __ovld __cnfn convert_long8_sat_rtp(float8);
long8 __ovld __cnfn convert_long8_rtn(float8);
long8 __ovld __cnfn convert_long8_sat_rtn(float8);
long8 __ovld __cnfn convert_long8(float8);
long8 __ovld __cnfn convert_long8_sat(float8);
ulong8 __ovld __cnfn convert_ulong8_rte(char8);
ulong8 __ovld __cnfn convert_ulong8_sat_rte(char8);
ulong8 __ovld __cnfn convert_ulong8_rtz(char8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtz(char8);
ulong8 __ovld __cnfn convert_ulong8_rtp(char8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtp(char8);
ulong8 __ovld __cnfn convert_ulong8_rtn(char8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtn(char8);
ulong8 __ovld __cnfn convert_ulong8(char8);
ulong8 __ovld __cnfn convert_ulong8_sat(char8);
ulong8 __ovld __cnfn convert_ulong8_rte(uchar8);
ulong8 __ovld __cnfn convert_ulong8_sat_rte(uchar8);
ulong8 __ovld __cnfn convert_ulong8_rtz(uchar8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtz(uchar8);
ulong8 __ovld __cnfn convert_ulong8_rtp(uchar8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtp(uchar8);
ulong8 __ovld __cnfn convert_ulong8_rtn(uchar8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtn(uchar8);
ulong8 __ovld __cnfn convert_ulong8(uchar8);
ulong8 __ovld __cnfn convert_ulong8_sat(uchar8);
ulong8 __ovld __cnfn convert_ulong8_rte(short8);
ulong8 __ovld __cnfn convert_ulong8_sat_rte(short8);
ulong8 __ovld __cnfn convert_ulong8_rtz(short8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtz(short8);
ulong8 __ovld __cnfn convert_ulong8_rtp(short8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtp(short8);
ulong8 __ovld __cnfn convert_ulong8_rtn(short8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtn(short8);
ulong8 __ovld __cnfn convert_ulong8(short8);
ulong8 __ovld __cnfn convert_ulong8_sat(short8);
ulong8 __ovld __cnfn convert_ulong8_rte(ushort8);
ulong8 __ovld __cnfn convert_ulong8_sat_rte(ushort8);
ulong8 __ovld __cnfn convert_ulong8_rtz(ushort8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtz(ushort8);
ulong8 __ovld __cnfn convert_ulong8_rtp(ushort8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtp(ushort8);
ulong8 __ovld __cnfn convert_ulong8_rtn(ushort8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtn(ushort8);
ulong8 __ovld __cnfn convert_ulong8(ushort8);
ulong8 __ovld __cnfn convert_ulong8_sat(ushort8);
ulong8 __ovld __cnfn convert_ulong8_rte(int8);
ulong8 __ovld __cnfn convert_ulong8_sat_rte(int8);
ulong8 __ovld __cnfn convert_ulong8_rtz(int8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtz(int8);
ulong8 __ovld __cnfn convert_ulong8_rtp(int8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtp(int8);
ulong8 __ovld __cnfn convert_ulong8_rtn(int8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtn(int8);
ulong8 __ovld __cnfn convert_ulong8(int8);
ulong8 __ovld __cnfn convert_ulong8_sat(int8);
ulong8 __ovld __cnfn convert_ulong8_rte(uint8);
ulong8 __ovld __cnfn convert_ulong8_sat_rte(uint8);
ulong8 __ovld __cnfn convert_ulong8_rtz(uint8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtz(uint8);
ulong8 __ovld __cnfn convert_ulong8_rtp(uint8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtp(uint8);
ulong8 __ovld __cnfn convert_ulong8_rtn(uint8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtn(uint8);
ulong8 __ovld __cnfn convert_ulong8(uint8);
ulong8 __ovld __cnfn convert_ulong8_sat(uint8);
ulong8 __ovld __cnfn convert_ulong8_rte(long8);
ulong8 __ovld __cnfn convert_ulong8_sat_rte(long8);
ulong8 __ovld __cnfn convert_ulong8_rtz(long8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtz(long8);
ulong8 __ovld __cnfn convert_ulong8_rtp(long8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtp(long8);
ulong8 __ovld __cnfn convert_ulong8_rtn(long8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtn(long8);
ulong8 __ovld __cnfn convert_ulong8(long8);
ulong8 __ovld __cnfn convert_ulong8_sat(long8);
ulong8 __ovld __cnfn convert_ulong8_rte(ulong8);
ulong8 __ovld __cnfn convert_ulong8_sat_rte(ulong8);
ulong8 __ovld __cnfn convert_ulong8_rtz(ulong8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtz(ulong8);
ulong8 __ovld __cnfn convert_ulong8_rtp(ulong8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtp(ulong8);
ulong8 __ovld __cnfn convert_ulong8_rtn(ulong8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtn(ulong8);
ulong8 __ovld __cnfn convert_ulong8(ulong8);
ulong8 __ovld __cnfn convert_ulong8_sat(ulong8);
ulong8 __ovld __cnfn convert_ulong8_rte(float8);
ulong8 __ovld __cnfn convert_ulong8_sat_rte(float8);
ulong8 __ovld __cnfn convert_ulong8_rtz(float8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtz(float8);
ulong8 __ovld __cnfn convert_ulong8_rtp(float8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtp(float8);
ulong8 __ovld __cnfn convert_ulong8_rtn(float8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtn(float8);
ulong8 __ovld __cnfn convert_ulong8(float8);
ulong8 __ovld __cnfn convert_ulong8_sat(float8);
float8 __ovld __cnfn convert_float8_rte(char8);
float8 __ovld __cnfn convert_float8_rtz(char8);
float8 __ovld __cnfn convert_float8_rtp(char8);
float8 __ovld __cnfn convert_float8_rtn(char8);
float8 __ovld __cnfn convert_float8(char8);
float8 __ovld __cnfn convert_float8_rte(uchar8);
float8 __ovld __cnfn convert_float8_rtz(uchar8);
float8 __ovld __cnfn convert_float8_rtp(uchar8);
float8 __ovld __cnfn convert_float8_rtn(uchar8);
float8 __ovld __cnfn convert_float8(uchar8);
float8 __ovld __cnfn convert_float8_rte(short8);
float8 __ovld __cnfn convert_float8_rtz(short8);
float8 __ovld __cnfn convert_float8_rtp(short8);
float8 __ovld __cnfn convert_float8_rtn(short8);
float8 __ovld __cnfn convert_float8(short8);
float8 __ovld __cnfn convert_float8_rte(ushort8);
float8 __ovld __cnfn convert_float8_rtz(ushort8);
float8 __ovld __cnfn convert_float8_rtp(ushort8);
float8 __ovld __cnfn convert_float8_rtn(ushort8);
float8 __ovld __cnfn convert_float8(ushort8);
float8 __ovld __cnfn convert_float8_rte(int8);
float8 __ovld __cnfn convert_float8_rtz(int8);
float8 __ovld __cnfn convert_float8_rtp(int8);
float8 __ovld __cnfn convert_float8_rtn(int8);
float8 __ovld __cnfn convert_float8(int8);
float8 __ovld __cnfn convert_float8_rte(uint8);
float8 __ovld __cnfn convert_float8_rtz(uint8);
float8 __ovld __cnfn convert_float8_rtp(uint8);
float8 __ovld __cnfn convert_float8_rtn(uint8);
float8 __ovld __cnfn convert_float8(uint8);
float8 __ovld __cnfn convert_float8_rte(long8);
float8 __ovld __cnfn convert_float8_rtz(long8);
float8 __ovld __cnfn convert_float8_rtp(long8);
float8 __ovld __cnfn convert_float8_rtn(long8);
float8 __ovld __cnfn convert_float8(long8);
float8 __ovld __cnfn convert_float8_rte(ulong8);
float8 __ovld __cnfn convert_float8_rtz(ulong8);
float8 __ovld __cnfn convert_float8_rtp(ulong8);
float8 __ovld __cnfn convert_float8_rtn(ulong8);
float8 __ovld __cnfn convert_float8(ulong8);
float8 __ovld __cnfn convert_float8_rte(float8);
float8 __ovld __cnfn convert_float8_rtz(float8);
float8 __ovld __cnfn convert_float8_rtp(float8);
float8 __ovld __cnfn convert_float8_rtn(float8);
float8 __ovld __cnfn convert_float8(float8);
char16 __ovld __cnfn convert_char16_rte(char16);
char16 __ovld __cnfn convert_char16_sat_rte(char16);
char16 __ovld __cnfn convert_char16_rtz(char16);
char16 __ovld __cnfn convert_char16_sat_rtz(char16);
char16 __ovld __cnfn convert_char16_rtp(char16);
char16 __ovld __cnfn convert_char16_sat_rtp(char16);
char16 __ovld __cnfn convert_char16_rtn(char16);
char16 __ovld __cnfn convert_char16_sat_rtn(char16);
char16 __ovld __cnfn convert_char16(char16);
char16 __ovld __cnfn convert_char16_sat(char16);
char16 __ovld __cnfn convert_char16_rte(uchar16);
char16 __ovld __cnfn convert_char16_sat_rte(uchar16);
char16 __ovld __cnfn convert_char16_rtz(uchar16);
char16 __ovld __cnfn convert_char16_sat_rtz(uchar16);
char16 __ovld __cnfn convert_char16_rtp(uchar16);
char16 __ovld __cnfn convert_char16_sat_rtp(uchar16);
char16 __ovld __cnfn convert_char16_rtn(uchar16);
char16 __ovld __cnfn convert_char16_sat_rtn(uchar16);
char16 __ovld __cnfn convert_char16(uchar16);
char16 __ovld __cnfn convert_char16_sat(uchar16);
char16 __ovld __cnfn convert_char16_rte(short16);
char16 __ovld __cnfn convert_char16_sat_rte(short16);
char16 __ovld __cnfn convert_char16_rtz(short16);
char16 __ovld __cnfn convert_char16_sat_rtz(short16);
char16 __ovld __cnfn convert_char16_rtp(short16);
char16 __ovld __cnfn convert_char16_sat_rtp(short16);
char16 __ovld __cnfn convert_char16_rtn(short16);
char16 __ovld __cnfn convert_char16_sat_rtn(short16);
char16 __ovld __cnfn convert_char16(short16);
char16 __ovld __cnfn convert_char16_sat(short16);
char16 __ovld __cnfn convert_char16_rte(ushort16);
char16 __ovld __cnfn convert_char16_sat_rte(ushort16);
char16 __ovld __cnfn convert_char16_rtz(ushort16);
char16 __ovld __cnfn convert_char16_sat_rtz(ushort16);
char16 __ovld __cnfn convert_char16_rtp(ushort16);
char16 __ovld __cnfn convert_char16_sat_rtp(ushort16);
char16 __ovld __cnfn convert_char16_rtn(ushort16);
char16 __ovld __cnfn convert_char16_sat_rtn(ushort16);
char16 __ovld __cnfn convert_char16(ushort16);
char16 __ovld __cnfn convert_char16_sat(ushort16);
char16 __ovld __cnfn convert_char16_rte(int16);
char16 __ovld __cnfn convert_char16_sat_rte(int16);
char16 __ovld __cnfn convert_char16_rtz(int16);
char16 __ovld __cnfn convert_char16_sat_rtz(int16);
char16 __ovld __cnfn convert_char16_rtp(int16);
char16 __ovld __cnfn convert_char16_sat_rtp(int16);
char16 __ovld __cnfn convert_char16_rtn(int16);
char16 __ovld __cnfn convert_char16_sat_rtn(int16);
char16 __ovld __cnfn convert_char16(int16);
char16 __ovld __cnfn convert_char16_sat(int16);
char16 __ovld __cnfn convert_char16_rte(uint16);
char16 __ovld __cnfn convert_char16_sat_rte(uint16);
char16 __ovld __cnfn convert_char16_rtz(uint16);
char16 __ovld __cnfn convert_char16_sat_rtz(uint16);
char16 __ovld __cnfn convert_char16_rtp(uint16);
char16 __ovld __cnfn convert_char16_sat_rtp(uint16);
char16 __ovld __cnfn convert_char16_rtn(uint16);
char16 __ovld __cnfn convert_char16_sat_rtn(uint16);
char16 __ovld __cnfn convert_char16(uint16);
char16 __ovld __cnfn convert_char16_sat(uint16);
char16 __ovld __cnfn convert_char16_rte(long16);
char16 __ovld __cnfn convert_char16_sat_rte(long16);
char16 __ovld __cnfn convert_char16_rtz(long16);
char16 __ovld __cnfn convert_char16_sat_rtz(long16);
char16 __ovld __cnfn convert_char16_rtp(long16);
char16 __ovld __cnfn convert_char16_sat_rtp(long16);
char16 __ovld __cnfn convert_char16_rtn(long16);
char16 __ovld __cnfn convert_char16_sat_rtn(long16);
char16 __ovld __cnfn convert_char16(long16);
char16 __ovld __cnfn convert_char16_sat(long16);
char16 __ovld __cnfn convert_char16_rte(ulong16);
char16 __ovld __cnfn convert_char16_sat_rte(ulong16);
char16 __ovld __cnfn convert_char16_rtz(ulong16);
char16 __ovld __cnfn convert_char16_sat_rtz(ulong16);
char16 __ovld __cnfn convert_char16_rtp(ulong16);
char16 __ovld __cnfn convert_char16_sat_rtp(ulong16);
char16 __ovld __cnfn convert_char16_rtn(ulong16);
char16 __ovld __cnfn convert_char16_sat_rtn(ulong16);
char16 __ovld __cnfn convert_char16(ulong16);
char16 __ovld __cnfn convert_char16_sat(ulong16);
char16 __ovld __cnfn convert_char16_rte(float16);
char16 __ovld __cnfn convert_char16_sat_rte(float16);
char16 __ovld __cnfn convert_char16_rtz(float16);
char16 __ovld __cnfn convert_char16_sat_rtz(float16);
char16 __ovld __cnfn convert_char16_rtp(float16);
char16 __ovld __cnfn convert_char16_sat_rtp(float16);
char16 __ovld __cnfn convert_char16_rtn(float16);
char16 __ovld __cnfn convert_char16_sat_rtn(float16);
char16 __ovld __cnfn convert_char16(float16);
char16 __ovld __cnfn convert_char16_sat(float16);
uchar16 __ovld __cnfn convert_uchar16_rte(char16);
uchar16 __ovld __cnfn convert_uchar16_sat_rte(char16);
uchar16 __ovld __cnfn convert_uchar16_rtz(char16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtz(char16);
uchar16 __ovld __cnfn convert_uchar16_rtp(char16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtp(char16);
uchar16 __ovld __cnfn convert_uchar16_rtn(char16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtn(char16);
uchar16 __ovld __cnfn convert_uchar16(char16);
uchar16 __ovld __cnfn convert_uchar16_sat(char16);
uchar16 __ovld __cnfn convert_uchar16_rte(uchar16);
uchar16 __ovld __cnfn convert_uchar16_sat_rte(uchar16);
uchar16 __ovld __cnfn convert_uchar16_rtz(uchar16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtz(uchar16);
uchar16 __ovld __cnfn convert_uchar16_rtp(uchar16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtp(uchar16);
uchar16 __ovld __cnfn convert_uchar16_rtn(uchar16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtn(uchar16);
uchar16 __ovld __cnfn convert_uchar16(uchar16);
uchar16 __ovld __cnfn convert_uchar16_sat(uchar16);
uchar16 __ovld __cnfn convert_uchar16_rte(short16);
uchar16 __ovld __cnfn convert_uchar16_sat_rte(short16);
uchar16 __ovld __cnfn convert_uchar16_rtz(short16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtz(short16);
uchar16 __ovld __cnfn convert_uchar16_rtp(short16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtp(short16);
uchar16 __ovld __cnfn convert_uchar16_rtn(short16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtn(short16);
uchar16 __ovld __cnfn convert_uchar16(short16);
uchar16 __ovld __cnfn convert_uchar16_sat(short16);
uchar16 __ovld __cnfn convert_uchar16_rte(ushort16);
uchar16 __ovld __cnfn convert_uchar16_sat_rte(ushort16);
uchar16 __ovld __cnfn convert_uchar16_rtz(ushort16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtz(ushort16);
uchar16 __ovld __cnfn convert_uchar16_rtp(ushort16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtp(ushort16);
uchar16 __ovld __cnfn convert_uchar16_rtn(ushort16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtn(ushort16);
uchar16 __ovld __cnfn convert_uchar16(ushort16);
uchar16 __ovld __cnfn convert_uchar16_sat(ushort16);
uchar16 __ovld __cnfn convert_uchar16_rte(int16);
uchar16 __ovld __cnfn convert_uchar16_sat_rte(int16);
uchar16 __ovld __cnfn convert_uchar16_rtz(int16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtz(int16);
uchar16 __ovld __cnfn convert_uchar16_rtp(int16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtp(int16);
uchar16 __ovld __cnfn convert_uchar16_rtn(int16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtn(int16);
uchar16 __ovld __cnfn convert_uchar16(int16);
uchar16 __ovld __cnfn convert_uchar16_sat(int16);
uchar16 __ovld __cnfn convert_uchar16_rte(uint16);
uchar16 __ovld __cnfn convert_uchar16_sat_rte(uint16);
uchar16 __ovld __cnfn convert_uchar16_rtz(uint16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtz(uint16);
uchar16 __ovld __cnfn convert_uchar16_rtp(uint16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtp(uint16);
uchar16 __ovld __cnfn convert_uchar16_rtn(uint16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtn(uint16);
uchar16 __ovld __cnfn convert_uchar16(uint16);
uchar16 __ovld __cnfn convert_uchar16_sat(uint16);
uchar16 __ovld __cnfn convert_uchar16_rte(long16);
uchar16 __ovld __cnfn convert_uchar16_sat_rte(long16);
uchar16 __ovld __cnfn convert_uchar16_rtz(long16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtz(long16);
uchar16 __ovld __cnfn convert_uchar16_rtp(long16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtp(long16);
uchar16 __ovld __cnfn convert_uchar16_rtn(long16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtn(long16);
uchar16 __ovld __cnfn convert_uchar16(long16);
uchar16 __ovld __cnfn convert_uchar16_sat(long16);
uchar16 __ovld __cnfn convert_uchar16_rte(ulong16);
uchar16 __ovld __cnfn convert_uchar16_sat_rte(ulong16);
uchar16 __ovld __cnfn convert_uchar16_rtz(ulong16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtz(ulong16);
uchar16 __ovld __cnfn convert_uchar16_rtp(ulong16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtp(ulong16);
uchar16 __ovld __cnfn convert_uchar16_rtn(ulong16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtn(ulong16);
uchar16 __ovld __cnfn convert_uchar16(ulong16);
uchar16 __ovld __cnfn convert_uchar16_sat(ulong16);
uchar16 __ovld __cnfn convert_uchar16_rte(float16);
uchar16 __ovld __cnfn convert_uchar16_sat_rte(float16);
uchar16 __ovld __cnfn convert_uchar16_rtz(float16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtz(float16);
uchar16 __ovld __cnfn convert_uchar16_rtp(float16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtp(float16);
uchar16 __ovld __cnfn convert_uchar16_rtn(float16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtn(float16);
uchar16 __ovld __cnfn convert_uchar16(float16);
uchar16 __ovld __cnfn convert_uchar16_sat(float16);
short16 __ovld __cnfn convert_short16_rte(char16);
short16 __ovld __cnfn convert_short16_sat_rte(char16);
short16 __ovld __cnfn convert_short16_rtz(char16);
short16 __ovld __cnfn convert_short16_sat_rtz(char16);
short16 __ovld __cnfn convert_short16_rtp(char16);
short16 __ovld __cnfn convert_short16_sat_rtp(char16);
short16 __ovld __cnfn convert_short16_rtn(char16);
short16 __ovld __cnfn convert_short16_sat_rtn(char16);
short16 __ovld __cnfn convert_short16(char16);
short16 __ovld __cnfn convert_short16_sat(char16);
short16 __ovld __cnfn convert_short16_rte(uchar16);
short16 __ovld __cnfn convert_short16_sat_rte(uchar16);
short16 __ovld __cnfn convert_short16_rtz(uchar16);
short16 __ovld __cnfn convert_short16_sat_rtz(uchar16);
short16 __ovld __cnfn convert_short16_rtp(uchar16);
short16 __ovld __cnfn convert_short16_sat_rtp(uchar16);
short16 __ovld __cnfn convert_short16_rtn(uchar16);
short16 __ovld __cnfn convert_short16_sat_rtn(uchar16);
short16 __ovld __cnfn convert_short16(uchar16);
short16 __ovld __cnfn convert_short16_sat(uchar16);
short16 __ovld __cnfn convert_short16_rte(short16);
short16 __ovld __cnfn convert_short16_sat_rte(short16);
short16 __ovld __cnfn convert_short16_rtz(short16);
short16 __ovld __cnfn convert_short16_sat_rtz(short16);
short16 __ovld __cnfn convert_short16_rtp(short16);
short16 __ovld __cnfn convert_short16_sat_rtp(short16);
short16 __ovld __cnfn convert_short16_rtn(short16);
short16 __ovld __cnfn convert_short16_sat_rtn(short16);
short16 __ovld __cnfn convert_short16(short16);
short16 __ovld __cnfn convert_short16_sat(short16);
short16 __ovld __cnfn convert_short16_rte(ushort16);
short16 __ovld __cnfn convert_short16_sat_rte(ushort16);
short16 __ovld __cnfn convert_short16_rtz(ushort16);
short16 __ovld __cnfn convert_short16_sat_rtz(ushort16);
short16 __ovld __cnfn convert_short16_rtp(ushort16);
short16 __ovld __cnfn convert_short16_sat_rtp(ushort16);
short16 __ovld __cnfn convert_short16_rtn(ushort16);
short16 __ovld __cnfn convert_short16_sat_rtn(ushort16);
short16 __ovld __cnfn convert_short16(ushort16);
short16 __ovld __cnfn convert_short16_sat(ushort16);
short16 __ovld __cnfn convert_short16_rte(int16);
short16 __ovld __cnfn convert_short16_sat_rte(int16);
short16 __ovld __cnfn convert_short16_rtz(int16);
short16 __ovld __cnfn convert_short16_sat_rtz(int16);
short16 __ovld __cnfn convert_short16_rtp(int16);
short16 __ovld __cnfn convert_short16_sat_rtp(int16);
short16 __ovld __cnfn convert_short16_rtn(int16);
short16 __ovld __cnfn convert_short16_sat_rtn(int16);
short16 __ovld __cnfn convert_short16(int16);
short16 __ovld __cnfn convert_short16_sat(int16);
short16 __ovld __cnfn convert_short16_rte(uint16);
short16 __ovld __cnfn convert_short16_sat_rte(uint16);
short16 __ovld __cnfn convert_short16_rtz(uint16);
short16 __ovld __cnfn convert_short16_sat_rtz(uint16);
short16 __ovld __cnfn convert_short16_rtp(uint16);
short16 __ovld __cnfn convert_short16_sat_rtp(uint16);
short16 __ovld __cnfn convert_short16_rtn(uint16);
short16 __ovld __cnfn convert_short16_sat_rtn(uint16);
short16 __ovld __cnfn convert_short16(uint16);
short16 __ovld __cnfn convert_short16_sat(uint16);
short16 __ovld __cnfn convert_short16_rte(long16);
short16 __ovld __cnfn convert_short16_sat_rte(long16);
short16 __ovld __cnfn convert_short16_rtz(long16);
short16 __ovld __cnfn convert_short16_sat_rtz(long16);
short16 __ovld __cnfn convert_short16_rtp(long16);
short16 __ovld __cnfn convert_short16_sat_rtp(long16);
short16 __ovld __cnfn convert_short16_rtn(long16);
short16 __ovld __cnfn convert_short16_sat_rtn(long16);
short16 __ovld __cnfn convert_short16(long16);
short16 __ovld __cnfn convert_short16_sat(long16);
short16 __ovld __cnfn convert_short16_rte(ulong16);
short16 __ovld __cnfn convert_short16_sat_rte(ulong16);
short16 __ovld __cnfn convert_short16_rtz(ulong16);
short16 __ovld __cnfn convert_short16_sat_rtz(ulong16);
short16 __ovld __cnfn convert_short16_rtp(ulong16);
short16 __ovld __cnfn convert_short16_sat_rtp(ulong16);
short16 __ovld __cnfn convert_short16_rtn(ulong16);
short16 __ovld __cnfn convert_short16_sat_rtn(ulong16);
short16 __ovld __cnfn convert_short16(ulong16);
short16 __ovld __cnfn convert_short16_sat(ulong16);
short16 __ovld __cnfn convert_short16_rte(float16);
short16 __ovld __cnfn convert_short16_sat_rte(float16);
short16 __ovld __cnfn convert_short16_rtz(float16);
short16 __ovld __cnfn convert_short16_sat_rtz(float16);
short16 __ovld __cnfn convert_short16_rtp(float16);
short16 __ovld __cnfn convert_short16_sat_rtp(float16);
short16 __ovld __cnfn convert_short16_rtn(float16);
short16 __ovld __cnfn convert_short16_sat_rtn(float16);
short16 __ovld __cnfn convert_short16(float16);
short16 __ovld __cnfn convert_short16_sat(float16);
ushort16 __ovld __cnfn convert_ushort16_rte(char16);
ushort16 __ovld __cnfn convert_ushort16_sat_rte(char16);
ushort16 __ovld __cnfn convert_ushort16_rtz(char16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtz(char16);
ushort16 __ovld __cnfn convert_ushort16_rtp(char16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtp(char16);
ushort16 __ovld __cnfn convert_ushort16_rtn(char16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtn(char16);
ushort16 __ovld __cnfn convert_ushort16(char16);
ushort16 __ovld __cnfn convert_ushort16_sat(char16);
ushort16 __ovld __cnfn convert_ushort16_rte(uchar16);
ushort16 __ovld __cnfn convert_ushort16_sat_rte(uchar16);
ushort16 __ovld __cnfn convert_ushort16_rtz(uchar16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtz(uchar16);
ushort16 __ovld __cnfn convert_ushort16_rtp(uchar16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtp(uchar16);
ushort16 __ovld __cnfn convert_ushort16_rtn(uchar16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtn(uchar16);
ushort16 __ovld __cnfn convert_ushort16(uchar16);
ushort16 __ovld __cnfn convert_ushort16_sat(uchar16);
ushort16 __ovld __cnfn convert_ushort16_rte(short16);
ushort16 __ovld __cnfn convert_ushort16_sat_rte(short16);
ushort16 __ovld __cnfn convert_ushort16_rtz(short16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtz(short16);
ushort16 __ovld __cnfn convert_ushort16_rtp(short16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtp(short16);
ushort16 __ovld __cnfn convert_ushort16_rtn(short16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtn(short16);
ushort16 __ovld __cnfn convert_ushort16(short16);
ushort16 __ovld __cnfn convert_ushort16_sat(short16);
ushort16 __ovld __cnfn convert_ushort16_rte(ushort16);
ushort16 __ovld __cnfn convert_ushort16_sat_rte(ushort16);
ushort16 __ovld __cnfn convert_ushort16_rtz(ushort16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtz(ushort16);
ushort16 __ovld __cnfn convert_ushort16_rtp(ushort16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtp(ushort16);
ushort16 __ovld __cnfn convert_ushort16_rtn(ushort16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtn(ushort16);
ushort16 __ovld __cnfn convert_ushort16(ushort16);
ushort16 __ovld __cnfn convert_ushort16_sat(ushort16);
ushort16 __ovld __cnfn convert_ushort16_rte(int16);
ushort16 __ovld __cnfn convert_ushort16_sat_rte(int16);
ushort16 __ovld __cnfn convert_ushort16_rtz(int16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtz(int16);
ushort16 __ovld __cnfn convert_ushort16_rtp(int16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtp(int16);
ushort16 __ovld __cnfn convert_ushort16_rtn(int16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtn(int16);
ushort16 __ovld __cnfn convert_ushort16(int16);
ushort16 __ovld __cnfn convert_ushort16_sat(int16);
ushort16 __ovld __cnfn convert_ushort16_rte(uint16);
ushort16 __ovld __cnfn convert_ushort16_sat_rte(uint16);
ushort16 __ovld __cnfn convert_ushort16_rtz(uint16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtz(uint16);
ushort16 __ovld __cnfn convert_ushort16_rtp(uint16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtp(uint16);
ushort16 __ovld __cnfn convert_ushort16_rtn(uint16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtn(uint16);
ushort16 __ovld __cnfn convert_ushort16(uint16);
ushort16 __ovld __cnfn convert_ushort16_sat(uint16);
ushort16 __ovld __cnfn convert_ushort16_rte(long16);
ushort16 __ovld __cnfn convert_ushort16_sat_rte(long16);
ushort16 __ovld __cnfn convert_ushort16_rtz(long16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtz(long16);
ushort16 __ovld __cnfn convert_ushort16_rtp(long16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtp(long16);
ushort16 __ovld __cnfn convert_ushort16_rtn(long16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtn(long16);
ushort16 __ovld __cnfn convert_ushort16(long16);
ushort16 __ovld __cnfn convert_ushort16_sat(long16);
ushort16 __ovld __cnfn convert_ushort16_rte(ulong16);
ushort16 __ovld __cnfn convert_ushort16_sat_rte(ulong16);
ushort16 __ovld __cnfn convert_ushort16_rtz(ulong16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtz(ulong16);
ushort16 __ovld __cnfn convert_ushort16_rtp(ulong16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtp(ulong16);
ushort16 __ovld __cnfn convert_ushort16_rtn(ulong16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtn(ulong16);
ushort16 __ovld __cnfn convert_ushort16(ulong16);
ushort16 __ovld __cnfn convert_ushort16_sat(ulong16);
ushort16 __ovld __cnfn convert_ushort16_rte(float16);
ushort16 __ovld __cnfn convert_ushort16_sat_rte(float16);
ushort16 __ovld __cnfn convert_ushort16_rtz(float16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtz(float16);
ushort16 __ovld __cnfn convert_ushort16_rtp(float16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtp(float16);
ushort16 __ovld __cnfn convert_ushort16_rtn(float16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtn(float16);
ushort16 __ovld __cnfn convert_ushort16(float16);
ushort16 __ovld __cnfn convert_ushort16_sat(float16);
int16 __ovld __cnfn convert_int16_rte(char16);
int16 __ovld __cnfn convert_int16_sat_rte(char16);
int16 __ovld __cnfn convert_int16_rtz(char16);
int16 __ovld __cnfn convert_int16_sat_rtz(char16);
int16 __ovld __cnfn convert_int16_rtp(char16);
int16 __ovld __cnfn convert_int16_sat_rtp(char16);
int16 __ovld __cnfn convert_int16_rtn(char16);
int16 __ovld __cnfn convert_int16_sat_rtn(char16);
int16 __ovld __cnfn convert_int16(char16);
int16 __ovld __cnfn convert_int16_sat(char16);
int16 __ovld __cnfn convert_int16_rte(uchar16);
int16 __ovld __cnfn convert_int16_sat_rte(uchar16);
int16 __ovld __cnfn convert_int16_rtz(uchar16);
int16 __ovld __cnfn convert_int16_sat_rtz(uchar16);
int16 __ovld __cnfn convert_int16_rtp(uchar16);
int16 __ovld __cnfn convert_int16_sat_rtp(uchar16);
int16 __ovld __cnfn convert_int16_rtn(uchar16);
int16 __ovld __cnfn convert_int16_sat_rtn(uchar16);
int16 __ovld __cnfn convert_int16(uchar16);
int16 __ovld __cnfn convert_int16_sat(uchar16);
int16 __ovld __cnfn convert_int16_rte(short16);
int16 __ovld __cnfn convert_int16_sat_rte(short16);
int16 __ovld __cnfn convert_int16_rtz(short16);
int16 __ovld __cnfn convert_int16_sat_rtz(short16);
int16 __ovld __cnfn convert_int16_rtp(short16);
int16 __ovld __cnfn convert_int16_sat_rtp(short16);
int16 __ovld __cnfn convert_int16_rtn(short16);
int16 __ovld __cnfn convert_int16_sat_rtn(short16);
int16 __ovld __cnfn convert_int16(short16);
int16 __ovld __cnfn convert_int16_sat(short16);
int16 __ovld __cnfn convert_int16_rte(ushort16);
int16 __ovld __cnfn convert_int16_sat_rte(ushort16);
int16 __ovld __cnfn convert_int16_rtz(ushort16);
int16 __ovld __cnfn convert_int16_sat_rtz(ushort16);
int16 __ovld __cnfn convert_int16_rtp(ushort16);
int16 __ovld __cnfn convert_int16_sat_rtp(ushort16);
int16 __ovld __cnfn convert_int16_rtn(ushort16);
int16 __ovld __cnfn convert_int16_sat_rtn(ushort16);
int16 __ovld __cnfn convert_int16(ushort16);
int16 __ovld __cnfn convert_int16_sat(ushort16);
int16 __ovld __cnfn convert_int16_rte(int16);
int16 __ovld __cnfn convert_int16_sat_rte(int16);
int16 __ovld __cnfn convert_int16_rtz(int16);
int16 __ovld __cnfn convert_int16_sat_rtz(int16);
int16 __ovld __cnfn convert_int16_rtp(int16);
int16 __ovld __cnfn convert_int16_sat_rtp(int16);
int16 __ovld __cnfn convert_int16_rtn(int16);
int16 __ovld __cnfn convert_int16_sat_rtn(int16);
int16 __ovld __cnfn convert_int16(int16);
int16 __ovld __cnfn convert_int16_sat(int16);
int16 __ovld __cnfn convert_int16_rte(uint16);
int16 __ovld __cnfn convert_int16_sat_rte(uint16);
int16 __ovld __cnfn convert_int16_rtz(uint16);
int16 __ovld __cnfn convert_int16_sat_rtz(uint16);
int16 __ovld __cnfn convert_int16_rtp(uint16);
int16 __ovld __cnfn convert_int16_sat_rtp(uint16);
int16 __ovld __cnfn convert_int16_rtn(uint16);
int16 __ovld __cnfn convert_int16_sat_rtn(uint16);
int16 __ovld __cnfn convert_int16(uint16);
int16 __ovld __cnfn convert_int16_sat(uint16);
int16 __ovld __cnfn convert_int16_rte(long16);
int16 __ovld __cnfn convert_int16_sat_rte(long16);
int16 __ovld __cnfn convert_int16_rtz(long16);
int16 __ovld __cnfn convert_int16_sat_rtz(long16);
int16 __ovld __cnfn convert_int16_rtp(long16);
int16 __ovld __cnfn convert_int16_sat_rtp(long16);
int16 __ovld __cnfn convert_int16_rtn(long16);
int16 __ovld __cnfn convert_int16_sat_rtn(long16);
int16 __ovld __cnfn convert_int16(long16);
int16 __ovld __cnfn convert_int16_sat(long16);
int16 __ovld __cnfn convert_int16_rte(ulong16);
int16 __ovld __cnfn convert_int16_sat_rte(ulong16);
int16 __ovld __cnfn convert_int16_rtz(ulong16);
int16 __ovld __cnfn convert_int16_sat_rtz(ulong16);
int16 __ovld __cnfn convert_int16_rtp(ulong16);
int16 __ovld __cnfn convert_int16_sat_rtp(ulong16);
int16 __ovld __cnfn convert_int16_rtn(ulong16);
int16 __ovld __cnfn convert_int16_sat_rtn(ulong16);
int16 __ovld __cnfn convert_int16(ulong16);
int16 __ovld __cnfn convert_int16_sat(ulong16);
int16 __ovld __cnfn convert_int16_rte(float16);
int16 __ovld __cnfn convert_int16_sat_rte(float16);
int16 __ovld __cnfn convert_int16_rtz(float16);
int16 __ovld __cnfn convert_int16_sat_rtz(float16);
int16 __ovld __cnfn convert_int16_rtp(float16);
int16 __ovld __cnfn convert_int16_sat_rtp(float16);
int16 __ovld __cnfn convert_int16_rtn(float16);
int16 __ovld __cnfn convert_int16_sat_rtn(float16);
int16 __ovld __cnfn convert_int16(float16);
int16 __ovld __cnfn convert_int16_sat(float16);
uint16 __ovld __cnfn convert_uint16_rte(char16);
uint16 __ovld __cnfn convert_uint16_sat_rte(char16);
uint16 __ovld __cnfn convert_uint16_rtz(char16);
uint16 __ovld __cnfn convert_uint16_sat_rtz(char16);
uint16 __ovld __cnfn convert_uint16_rtp(char16);
uint16 __ovld __cnfn convert_uint16_sat_rtp(char16);
uint16 __ovld __cnfn convert_uint16_rtn(char16);
uint16 __ovld __cnfn convert_uint16_sat_rtn(char16);
uint16 __ovld __cnfn convert_uint16(char16);
uint16 __ovld __cnfn convert_uint16_sat(char16);
uint16 __ovld __cnfn convert_uint16_rte(uchar16);
uint16 __ovld __cnfn convert_uint16_sat_rte(uchar16);
uint16 __ovld __cnfn convert_uint16_rtz(uchar16);
uint16 __ovld __cnfn convert_uint16_sat_rtz(uchar16);
uint16 __ovld __cnfn convert_uint16_rtp(uchar16);
uint16 __ovld __cnfn convert_uint16_sat_rtp(uchar16);
uint16 __ovld __cnfn convert_uint16_rtn(uchar16);
uint16 __ovld __cnfn convert_uint16_sat_rtn(uchar16);
uint16 __ovld __cnfn convert_uint16(uchar16);
uint16 __ovld __cnfn convert_uint16_sat(uchar16);
uint16 __ovld __cnfn convert_uint16_rte(short16);
uint16 __ovld __cnfn convert_uint16_sat_rte(short16);
uint16 __ovld __cnfn convert_uint16_rtz(short16);
uint16 __ovld __cnfn convert_uint16_sat_rtz(short16);
uint16 __ovld __cnfn convert_uint16_rtp(short16);
uint16 __ovld __cnfn convert_uint16_sat_rtp(short16);
uint16 __ovld __cnfn convert_uint16_rtn(short16);
uint16 __ovld __cnfn convert_uint16_sat_rtn(short16);
uint16 __ovld __cnfn convert_uint16(short16);
uint16 __ovld __cnfn convert_uint16_sat(short16);
uint16 __ovld __cnfn convert_uint16_rte(ushort16);
uint16 __ovld __cnfn convert_uint16_sat_rte(ushort16);
uint16 __ovld __cnfn convert_uint16_rtz(ushort16);
uint16 __ovld __cnfn convert_uint16_sat_rtz(ushort16);
uint16 __ovld __cnfn convert_uint16_rtp(ushort16);
uint16 __ovld __cnfn convert_uint16_sat_rtp(ushort16);
uint16 __ovld __cnfn convert_uint16_rtn(ushort16);
uint16 __ovld __cnfn convert_uint16_sat_rtn(ushort16);
uint16 __ovld __cnfn convert_uint16(ushort16);
uint16 __ovld __cnfn convert_uint16_sat(ushort16);
uint16 __ovld __cnfn convert_uint16_rte(int16);
uint16 __ovld __cnfn convert_uint16_sat_rte(int16);
uint16 __ovld __cnfn convert_uint16_rtz(int16);
uint16 __ovld __cnfn convert_uint16_sat_rtz(int16);
uint16 __ovld __cnfn convert_uint16_rtp(int16);
uint16 __ovld __cnfn convert_uint16_sat_rtp(int16);
uint16 __ovld __cnfn convert_uint16_rtn(int16);
uint16 __ovld __cnfn convert_uint16_sat_rtn(int16);
uint16 __ovld __cnfn convert_uint16(int16);
uint16 __ovld __cnfn convert_uint16_sat(int16);
uint16 __ovld __cnfn convert_uint16_rte(uint16);
uint16 __ovld __cnfn convert_uint16_sat_rte(uint16);
uint16 __ovld __cnfn convert_uint16_rtz(uint16);
uint16 __ovld __cnfn convert_uint16_sat_rtz(uint16);
uint16 __ovld __cnfn convert_uint16_rtp(uint16);
uint16 __ovld __cnfn convert_uint16_sat_rtp(uint16);
uint16 __ovld __cnfn convert_uint16_rtn(uint16);
uint16 __ovld __cnfn convert_uint16_sat_rtn(uint16);
uint16 __ovld __cnfn convert_uint16(uint16);
uint16 __ovld __cnfn convert_uint16_sat(uint16);
uint16 __ovld __cnfn convert_uint16_rte(long16);
uint16 __ovld __cnfn convert_uint16_sat_rte(long16);
uint16 __ovld __cnfn convert_uint16_rtz(long16);
uint16 __ovld __cnfn convert_uint16_sat_rtz(long16);
uint16 __ovld __cnfn convert_uint16_rtp(long16);
uint16 __ovld __cnfn convert_uint16_sat_rtp(long16);
uint16 __ovld __cnfn convert_uint16_rtn(long16);
uint16 __ovld __cnfn convert_uint16_sat_rtn(long16);
uint16 __ovld __cnfn convert_uint16(long16);
uint16 __ovld __cnfn convert_uint16_sat(long16);
uint16 __ovld __cnfn convert_uint16_rte(ulong16);
uint16 __ovld __cnfn convert_uint16_sat_rte(ulong16);
uint16 __ovld __cnfn convert_uint16_rtz(ulong16);
uint16 __ovld __cnfn convert_uint16_sat_rtz(ulong16);
uint16 __ovld __cnfn convert_uint16_rtp(ulong16);
uint16 __ovld __cnfn convert_uint16_sat_rtp(ulong16);
uint16 __ovld __cnfn convert_uint16_rtn(ulong16);
uint16 __ovld __cnfn convert_uint16_sat_rtn(ulong16);
uint16 __ovld __cnfn convert_uint16(ulong16);
uint16 __ovld __cnfn convert_uint16_sat(ulong16);
uint16 __ovld __cnfn convert_uint16_rte(float16);
uint16 __ovld __cnfn convert_uint16_sat_rte(float16);
uint16 __ovld __cnfn convert_uint16_rtz(float16);
uint16 __ovld __cnfn convert_uint16_sat_rtz(float16);
uint16 __ovld __cnfn convert_uint16_rtp(float16);
uint16 __ovld __cnfn convert_uint16_sat_rtp(float16);
uint16 __ovld __cnfn convert_uint16_rtn(float16);
uint16 __ovld __cnfn convert_uint16_sat_rtn(float16);
uint16 __ovld __cnfn convert_uint16(float16);
uint16 __ovld __cnfn convert_uint16_sat(float16);
long16 __ovld __cnfn convert_long16_rte(char16);
long16 __ovld __cnfn convert_long16_sat_rte(char16);
long16 __ovld __cnfn convert_long16_rtz(char16);
long16 __ovld __cnfn convert_long16_sat_rtz(char16);
long16 __ovld __cnfn convert_long16_rtp(char16);
long16 __ovld __cnfn convert_long16_sat_rtp(char16);
long16 __ovld __cnfn convert_long16_rtn(char16);
long16 __ovld __cnfn convert_long16_sat_rtn(char16);
long16 __ovld __cnfn convert_long16(char16);
long16 __ovld __cnfn convert_long16_sat(char16);
long16 __ovld __cnfn convert_long16_rte(uchar16);
long16 __ovld __cnfn convert_long16_sat_rte(uchar16);
long16 __ovld __cnfn convert_long16_rtz(uchar16);
long16 __ovld __cnfn convert_long16_sat_rtz(uchar16);
long16 __ovld __cnfn convert_long16_rtp(uchar16);
long16 __ovld __cnfn convert_long16_sat_rtp(uchar16);
long16 __ovld __cnfn convert_long16_rtn(uchar16);
long16 __ovld __cnfn convert_long16_sat_rtn(uchar16);
long16 __ovld __cnfn convert_long16(uchar16);
long16 __ovld __cnfn convert_long16_sat(uchar16);
long16 __ovld __cnfn convert_long16_rte(short16);
long16 __ovld __cnfn convert_long16_sat_rte(short16);
long16 __ovld __cnfn convert_long16_rtz(short16);
long16 __ovld __cnfn convert_long16_sat_rtz(short16);
long16 __ovld __cnfn convert_long16_rtp(short16);
long16 __ovld __cnfn convert_long16_sat_rtp(short16);
long16 __ovld __cnfn convert_long16_rtn(short16);
long16 __ovld __cnfn convert_long16_sat_rtn(short16);
long16 __ovld __cnfn convert_long16(short16);
long16 __ovld __cnfn convert_long16_sat(short16);
long16 __ovld __cnfn convert_long16_rte(ushort16);
long16 __ovld __cnfn convert_long16_sat_rte(ushort16);
long16 __ovld __cnfn convert_long16_rtz(ushort16);
long16 __ovld __cnfn convert_long16_sat_rtz(ushort16);
long16 __ovld __cnfn convert_long16_rtp(ushort16);
long16 __ovld __cnfn convert_long16_sat_rtp(ushort16);
long16 __ovld __cnfn convert_long16_rtn(ushort16);
long16 __ovld __cnfn convert_long16_sat_rtn(ushort16);
long16 __ovld __cnfn convert_long16(ushort16);
long16 __ovld __cnfn convert_long16_sat(ushort16);
long16 __ovld __cnfn convert_long16_rte(int16);
long16 __ovld __cnfn convert_long16_sat_rte(int16);
long16 __ovld __cnfn convert_long16_rtz(int16);
long16 __ovld __cnfn convert_long16_sat_rtz(int16);
long16 __ovld __cnfn convert_long16_rtp(int16);
long16 __ovld __cnfn convert_long16_sat_rtp(int16);
long16 __ovld __cnfn convert_long16_rtn(int16);
long16 __ovld __cnfn convert_long16_sat_rtn(int16);
long16 __ovld __cnfn convert_long16(int16);
long16 __ovld __cnfn convert_long16_sat(int16);
long16 __ovld __cnfn convert_long16_rte(uint16);
long16 __ovld __cnfn convert_long16_sat_rte(uint16);
long16 __ovld __cnfn convert_long16_rtz(uint16);
long16 __ovld __cnfn convert_long16_sat_rtz(uint16);
long16 __ovld __cnfn convert_long16_rtp(uint16);
long16 __ovld __cnfn convert_long16_sat_rtp(uint16);
long16 __ovld __cnfn convert_long16_rtn(uint16);
long16 __ovld __cnfn convert_long16_sat_rtn(uint16);
long16 __ovld __cnfn convert_long16(uint16);
long16 __ovld __cnfn convert_long16_sat(uint16);
long16 __ovld __cnfn convert_long16_rte(long16);
long16 __ovld __cnfn convert_long16_sat_rte(long16);
long16 __ovld __cnfn convert_long16_rtz(long16);
long16 __ovld __cnfn convert_long16_sat_rtz(long16);
long16 __ovld __cnfn convert_long16_rtp(long16);
long16 __ovld __cnfn convert_long16_sat_rtp(long16);
long16 __ovld __cnfn convert_long16_rtn(long16);
long16 __ovld __cnfn convert_long16_sat_rtn(long16);
long16 __ovld __cnfn convert_long16(long16);
long16 __ovld __cnfn convert_long16_sat(long16);
long16 __ovld __cnfn convert_long16_rte(ulong16);
long16 __ovld __cnfn convert_long16_sat_rte(ulong16);
long16 __ovld __cnfn convert_long16_rtz(ulong16);
long16 __ovld __cnfn convert_long16_sat_rtz(ulong16);
long16 __ovld __cnfn convert_long16_rtp(ulong16);
long16 __ovld __cnfn convert_long16_sat_rtp(ulong16);
long16 __ovld __cnfn convert_long16_rtn(ulong16);
long16 __ovld __cnfn convert_long16_sat_rtn(ulong16);
long16 __ovld __cnfn convert_long16(ulong16);
long16 __ovld __cnfn convert_long16_sat(ulong16);
long16 __ovld __cnfn convert_long16_rte(float16);
long16 __ovld __cnfn convert_long16_sat_rte(float16);
long16 __ovld __cnfn convert_long16_rtz(float16);
long16 __ovld __cnfn convert_long16_sat_rtz(float16);
long16 __ovld __cnfn convert_long16_rtp(float16);
long16 __ovld __cnfn convert_long16_sat_rtp(float16);
long16 __ovld __cnfn convert_long16_rtn(float16);
long16 __ovld __cnfn convert_long16_sat_rtn(float16);
long16 __ovld __cnfn convert_long16(float16);
long16 __ovld __cnfn convert_long16_sat(float16);
ulong16 __ovld __cnfn convert_ulong16_rte(char16);
ulong16 __ovld __cnfn convert_ulong16_sat_rte(char16);
ulong16 __ovld __cnfn convert_ulong16_rtz(char16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtz(char16);
ulong16 __ovld __cnfn convert_ulong16_rtp(char16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtp(char16);
ulong16 __ovld __cnfn convert_ulong16_rtn(char16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtn(char16);
ulong16 __ovld __cnfn convert_ulong16(char16);
ulong16 __ovld __cnfn convert_ulong16_sat(char16);
ulong16 __ovld __cnfn convert_ulong16_rte(uchar16);
ulong16 __ovld __cnfn convert_ulong16_sat_rte(uchar16);
ulong16 __ovld __cnfn convert_ulong16_rtz(uchar16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtz(uchar16);
ulong16 __ovld __cnfn convert_ulong16_rtp(uchar16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtp(uchar16);
ulong16 __ovld __cnfn convert_ulong16_rtn(uchar16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtn(uchar16);
ulong16 __ovld __cnfn convert_ulong16(uchar16);
ulong16 __ovld __cnfn convert_ulong16_sat(uchar16);
ulong16 __ovld __cnfn convert_ulong16_rte(short16);
ulong16 __ovld __cnfn convert_ulong16_sat_rte(short16);
ulong16 __ovld __cnfn convert_ulong16_rtz(short16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtz(short16);
ulong16 __ovld __cnfn convert_ulong16_rtp(short16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtp(short16);
ulong16 __ovld __cnfn convert_ulong16_rtn(short16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtn(short16);
ulong16 __ovld __cnfn convert_ulong16(short16);
ulong16 __ovld __cnfn convert_ulong16_sat(short16);
ulong16 __ovld __cnfn convert_ulong16_rte(ushort16);
ulong16 __ovld __cnfn convert_ulong16_sat_rte(ushort16);
ulong16 __ovld __cnfn convert_ulong16_rtz(ushort16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtz(ushort16);
ulong16 __ovld __cnfn convert_ulong16_rtp(ushort16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtp(ushort16);
ulong16 __ovld __cnfn convert_ulong16_rtn(ushort16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtn(ushort16);
ulong16 __ovld __cnfn convert_ulong16(ushort16);
ulong16 __ovld __cnfn convert_ulong16_sat(ushort16);
ulong16 __ovld __cnfn convert_ulong16_rte(int16);
ulong16 __ovld __cnfn convert_ulong16_sat_rte(int16);
ulong16 __ovld __cnfn convert_ulong16_rtz(int16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtz(int16);
ulong16 __ovld __cnfn convert_ulong16_rtp(int16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtp(int16);
ulong16 __ovld __cnfn convert_ulong16_rtn(int16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtn(int16);
ulong16 __ovld __cnfn convert_ulong16(int16);
ulong16 __ovld __cnfn convert_ulong16_sat(int16);
ulong16 __ovld __cnfn convert_ulong16_rte(uint16);
ulong16 __ovld __cnfn convert_ulong16_sat_rte(uint16);
ulong16 __ovld __cnfn convert_ulong16_rtz(uint16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtz(uint16);
ulong16 __ovld __cnfn convert_ulong16_rtp(uint16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtp(uint16);
ulong16 __ovld __cnfn convert_ulong16_rtn(uint16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtn(uint16);
ulong16 __ovld __cnfn convert_ulong16(uint16);
ulong16 __ovld __cnfn convert_ulong16_sat(uint16);
ulong16 __ovld __cnfn convert_ulong16_rte(long16);
ulong16 __ovld __cnfn convert_ulong16_sat_rte(long16);
ulong16 __ovld __cnfn convert_ulong16_rtz(long16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtz(long16);
ulong16 __ovld __cnfn convert_ulong16_rtp(long16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtp(long16);
ulong16 __ovld __cnfn convert_ulong16_rtn(long16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtn(long16);
ulong16 __ovld __cnfn convert_ulong16(long16);
ulong16 __ovld __cnfn convert_ulong16_sat(long16);
ulong16 __ovld __cnfn convert_ulong16_rte(ulong16);
ulong16 __ovld __cnfn convert_ulong16_sat_rte(ulong16);
ulong16 __ovld __cnfn convert_ulong16_rtz(ulong16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtz(ulong16);
ulong16 __ovld __cnfn convert_ulong16_rtp(ulong16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtp(ulong16);
ulong16 __ovld __cnfn convert_ulong16_rtn(ulong16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtn(ulong16);
ulong16 __ovld __cnfn convert_ulong16(ulong16);
ulong16 __ovld __cnfn convert_ulong16_sat(ulong16);
ulong16 __ovld __cnfn convert_ulong16_rte(float16);
ulong16 __ovld __cnfn convert_ulong16_sat_rte(float16);
ulong16 __ovld __cnfn convert_ulong16_rtz(float16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtz(float16);
ulong16 __ovld __cnfn convert_ulong16_rtp(float16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtp(float16);
ulong16 __ovld __cnfn convert_ulong16_rtn(float16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtn(float16);
ulong16 __ovld __cnfn convert_ulong16(float16);
ulong16 __ovld __cnfn convert_ulong16_sat(float16);
float16 __ovld __cnfn convert_float16_rte(char16);
float16 __ovld __cnfn convert_float16_rtz(char16);
float16 __ovld __cnfn convert_float16_rtp(char16);
float16 __ovld __cnfn convert_float16_rtn(char16);
float16 __ovld __cnfn convert_float16(char16);
float16 __ovld __cnfn convert_float16_rte(uchar16);
float16 __ovld __cnfn convert_float16_rtz(uchar16);
float16 __ovld __cnfn convert_float16_rtp(uchar16);
float16 __ovld __cnfn convert_float16_rtn(uchar16);
float16 __ovld __cnfn convert_float16(uchar16);
float16 __ovld __cnfn convert_float16_rte(short16);
float16 __ovld __cnfn convert_float16_rtz(short16);
float16 __ovld __cnfn convert_float16_rtp(short16);
float16 __ovld __cnfn convert_float16_rtn(short16);
float16 __ovld __cnfn convert_float16(short16);
float16 __ovld __cnfn convert_float16_rte(ushort16);
float16 __ovld __cnfn convert_float16_rtz(ushort16);
float16 __ovld __cnfn convert_float16_rtp(ushort16);
float16 __ovld __cnfn convert_float16_rtn(ushort16);
float16 __ovld __cnfn convert_float16(ushort16);
float16 __ovld __cnfn convert_float16_rte(int16);
float16 __ovld __cnfn convert_float16_rtz(int16);
float16 __ovld __cnfn convert_float16_rtp(int16);
float16 __ovld __cnfn convert_float16_rtn(int16);
float16 __ovld __cnfn convert_float16(int16);
float16 __ovld __cnfn convert_float16_rte(uint16);
float16 __ovld __cnfn convert_float16_rtz(uint16);
float16 __ovld __cnfn convert_float16_rtp(uint16);
float16 __ovld __cnfn convert_float16_rtn(uint16);
float16 __ovld __cnfn convert_float16(uint16);
float16 __ovld __cnfn convert_float16_rte(long16);
float16 __ovld __cnfn convert_float16_rtz(long16);
float16 __ovld __cnfn convert_float16_rtp(long16);
float16 __ovld __cnfn convert_float16_rtn(long16);
float16 __ovld __cnfn convert_float16(long16);
float16 __ovld __cnfn convert_float16_rte(ulong16);
float16 __ovld __cnfn convert_float16_rtz(ulong16);
float16 __ovld __cnfn convert_float16_rtp(ulong16);
float16 __ovld __cnfn convert_float16_rtn(ulong16);
float16 __ovld __cnfn convert_float16(ulong16);
float16 __ovld __cnfn convert_float16_rte(float16);
float16 __ovld __cnfn convert_float16_rtz(float16);
float16 __ovld __cnfn convert_float16_rtp(float16);
float16 __ovld __cnfn convert_float16_rtn(float16);
float16 __ovld __cnfn convert_float16(float16);
// Conversions with double data type parameters or return value.
#ifdef cl_khr_fp64
char __ovld __cnfn convert_char(double);
char __ovld __cnfn convert_char_rte(double);
char __ovld __cnfn convert_char_rtn(double);
char __ovld __cnfn convert_char_rtp(double);
char __ovld __cnfn convert_char_rtz(double);
char __ovld __cnfn convert_char_sat(double);
char __ovld __cnfn convert_char_sat_rte(double);
char __ovld __cnfn convert_char_sat_rtn(double);
char __ovld __cnfn convert_char_sat_rtp(double);
char __ovld __cnfn convert_char_sat_rtz(double);
char2 __ovld __cnfn convert_char2(double2);
char2 __ovld __cnfn convert_char2_rte(double2);
char2 __ovld __cnfn convert_char2_rtn(double2);
char2 __ovld __cnfn convert_char2_rtp(double2);
char2 __ovld __cnfn convert_char2_rtz(double2);
char2 __ovld __cnfn convert_char2_sat(double2);
char2 __ovld __cnfn convert_char2_sat_rte(double2);
char2 __ovld __cnfn convert_char2_sat_rtn(double2);
char2 __ovld __cnfn convert_char2_sat_rtp(double2);
char2 __ovld __cnfn convert_char2_sat_rtz(double2);
char3 __ovld __cnfn convert_char3(double3);
char3 __ovld __cnfn convert_char3_rte(double3);
char3 __ovld __cnfn convert_char3_rtn(double3);
char3 __ovld __cnfn convert_char3_rtp(double3);
char3 __ovld __cnfn convert_char3_rtz(double3);
char3 __ovld __cnfn convert_char3_sat(double3);
char3 __ovld __cnfn convert_char3_sat_rte(double3);
char3 __ovld __cnfn convert_char3_sat_rtn(double3);
char3 __ovld __cnfn convert_char3_sat_rtp(double3);
char3 __ovld __cnfn convert_char3_sat_rtz(double3);
char4 __ovld __cnfn convert_char4(double4);
char4 __ovld __cnfn convert_char4_rte(double4);
char4 __ovld __cnfn convert_char4_rtn(double4);
char4 __ovld __cnfn convert_char4_rtp(double4);
char4 __ovld __cnfn convert_char4_rtz(double4);
char4 __ovld __cnfn convert_char4_sat(double4);
char4 __ovld __cnfn convert_char4_sat_rte(double4);
char4 __ovld __cnfn convert_char4_sat_rtn(double4);
char4 __ovld __cnfn convert_char4_sat_rtp(double4);
char4 __ovld __cnfn convert_char4_sat_rtz(double4);
char8 __ovld __cnfn convert_char8(double8);
char8 __ovld __cnfn convert_char8_rte(double8);
char8 __ovld __cnfn convert_char8_rtn(double8);
char8 __ovld __cnfn convert_char8_rtp(double8);
char8 __ovld __cnfn convert_char8_rtz(double8);
char8 __ovld __cnfn convert_char8_sat(double8);
char8 __ovld __cnfn convert_char8_sat_rte(double8);
char8 __ovld __cnfn convert_char8_sat_rtn(double8);
char8 __ovld __cnfn convert_char8_sat_rtp(double8);
char8 __ovld __cnfn convert_char8_sat_rtz(double8);
char16 __ovld __cnfn convert_char16(double16);
char16 __ovld __cnfn convert_char16_rte(double16);
char16 __ovld __cnfn convert_char16_rtn(double16);
char16 __ovld __cnfn convert_char16_rtp(double16);
char16 __ovld __cnfn convert_char16_rtz(double16);
char16 __ovld __cnfn convert_char16_sat(double16);
char16 __ovld __cnfn convert_char16_sat_rte(double16);
char16 __ovld __cnfn convert_char16_sat_rtn(double16);
char16 __ovld __cnfn convert_char16_sat_rtp(double16);
char16 __ovld __cnfn convert_char16_sat_rtz(double16);
uchar __ovld __cnfn convert_uchar(double);
uchar __ovld __cnfn convert_uchar_rte(double);
uchar __ovld __cnfn convert_uchar_rtn(double);
uchar __ovld __cnfn convert_uchar_rtp(double);
uchar __ovld __cnfn convert_uchar_rtz(double);
uchar __ovld __cnfn convert_uchar_sat(double);
uchar __ovld __cnfn convert_uchar_sat_rte(double);
uchar __ovld __cnfn convert_uchar_sat_rtn(double);
uchar __ovld __cnfn convert_uchar_sat_rtp(double);
uchar __ovld __cnfn convert_uchar_sat_rtz(double);
uchar2 __ovld __cnfn convert_uchar2(double2);
uchar2 __ovld __cnfn convert_uchar2_rte(double2);
uchar2 __ovld __cnfn convert_uchar2_rtn(double2);
uchar2 __ovld __cnfn convert_uchar2_rtp(double2);
uchar2 __ovld __cnfn convert_uchar2_rtz(double2);
uchar2 __ovld __cnfn convert_uchar2_sat(double2);
uchar2 __ovld __cnfn convert_uchar2_sat_rte(double2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtn(double2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtp(double2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtz(double2);
uchar3 __ovld __cnfn convert_uchar3(double3);
uchar3 __ovld __cnfn convert_uchar3_rte(double3);
uchar3 __ovld __cnfn convert_uchar3_rtn(double3);
uchar3 __ovld __cnfn convert_uchar3_rtp(double3);
uchar3 __ovld __cnfn convert_uchar3_rtz(double3);
uchar3 __ovld __cnfn convert_uchar3_sat(double3);
uchar3 __ovld __cnfn convert_uchar3_sat_rte(double3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtn(double3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtp(double3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtz(double3);
uchar4 __ovld __cnfn convert_uchar4(double4);
uchar4 __ovld __cnfn convert_uchar4_rte(double4);
uchar4 __ovld __cnfn convert_uchar4_rtn(double4);
uchar4 __ovld __cnfn convert_uchar4_rtp(double4);
uchar4 __ovld __cnfn convert_uchar4_rtz(double4);
uchar4 __ovld __cnfn convert_uchar4_sat(double4);
uchar4 __ovld __cnfn convert_uchar4_sat_rte(double4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtn(double4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtp(double4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtz(double4);
uchar8 __ovld __cnfn convert_uchar8(double8);
uchar8 __ovld __cnfn convert_uchar8_rte(double8);
uchar8 __ovld __cnfn convert_uchar8_rtn(double8);
uchar8 __ovld __cnfn convert_uchar8_rtp(double8);
uchar8 __ovld __cnfn convert_uchar8_rtz(double8);
uchar8 __ovld __cnfn convert_uchar8_sat(double8);
uchar8 __ovld __cnfn convert_uchar8_sat_rte(double8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtn(double8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtp(double8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtz(double8);
uchar16 __ovld __cnfn convert_uchar16(double16);
uchar16 __ovld __cnfn convert_uchar16_rte(double16);
uchar16 __ovld __cnfn convert_uchar16_rtn(double16);
uchar16 __ovld __cnfn convert_uchar16_rtp(double16);
uchar16 __ovld __cnfn convert_uchar16_rtz(double16);
uchar16 __ovld __cnfn convert_uchar16_sat(double16);
uchar16 __ovld __cnfn convert_uchar16_sat_rte(double16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtn(double16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtp(double16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtz(double16);
short __ovld __cnfn convert_short(double);
short __ovld __cnfn convert_short_rte(double);
short __ovld __cnfn convert_short_rtn(double);
short __ovld __cnfn convert_short_rtp(double);
short __ovld __cnfn convert_short_rtz(double);
short __ovld __cnfn convert_short_sat(double);
short __ovld __cnfn convert_short_sat_rte(double);
short __ovld __cnfn convert_short_sat_rtn(double);
short __ovld __cnfn convert_short_sat_rtp(double);
short __ovld __cnfn convert_short_sat_rtz(double);
short2 __ovld __cnfn convert_short2(double2);
short2 __ovld __cnfn convert_short2_rte(double2);
short2 __ovld __cnfn convert_short2_rtn(double2);
short2 __ovld __cnfn convert_short2_rtp(double2);
short2 __ovld __cnfn convert_short2_rtz(double2);
short2 __ovld __cnfn convert_short2_sat(double2);
short2 __ovld __cnfn convert_short2_sat_rte(double2);
short2 __ovld __cnfn convert_short2_sat_rtn(double2);
short2 __ovld __cnfn convert_short2_sat_rtp(double2);
short2 __ovld __cnfn convert_short2_sat_rtz(double2);
short3 __ovld __cnfn convert_short3(double3);
short3 __ovld __cnfn convert_short3_rte(double3);
short3 __ovld __cnfn convert_short3_rtn(double3);
short3 __ovld __cnfn convert_short3_rtp(double3);
short3 __ovld __cnfn convert_short3_rtz(double3);
short3 __ovld __cnfn convert_short3_sat(double3);
short3 __ovld __cnfn convert_short3_sat_rte(double3);
short3 __ovld __cnfn convert_short3_sat_rtn(double3);
short3 __ovld __cnfn convert_short3_sat_rtp(double3);
short3 __ovld __cnfn convert_short3_sat_rtz(double3);
short4 __ovld __cnfn convert_short4(double4);
short4 __ovld __cnfn convert_short4_rte(double4);
short4 __ovld __cnfn convert_short4_rtn(double4);
short4 __ovld __cnfn convert_short4_rtp(double4);
short4 __ovld __cnfn convert_short4_rtz(double4);
short4 __ovld __cnfn convert_short4_sat(double4);
short4 __ovld __cnfn convert_short4_sat_rte(double4);
short4 __ovld __cnfn convert_short4_sat_rtn(double4);
short4 __ovld __cnfn convert_short4_sat_rtp(double4);
short4 __ovld __cnfn convert_short4_sat_rtz(double4);
short8 __ovld __cnfn convert_short8(double8);
short8 __ovld __cnfn convert_short8_rte(double8);
short8 __ovld __cnfn convert_short8_rtn(double8);
short8 __ovld __cnfn convert_short8_rtp(double8);
short8 __ovld __cnfn convert_short8_rtz(double8);
short8 __ovld __cnfn convert_short8_sat(double8);
short8 __ovld __cnfn convert_short8_sat_rte(double8);
short8 __ovld __cnfn convert_short8_sat_rtn(double8);
short8 __ovld __cnfn convert_short8_sat_rtp(double8);
short8 __ovld __cnfn convert_short8_sat_rtz(double8);
short16 __ovld __cnfn convert_short16(double16);
short16 __ovld __cnfn convert_short16_rte(double16);
short16 __ovld __cnfn convert_short16_rtn(double16);
short16 __ovld __cnfn convert_short16_rtp(double16);
short16 __ovld __cnfn convert_short16_rtz(double16);
short16 __ovld __cnfn convert_short16_sat(double16);
short16 __ovld __cnfn convert_short16_sat_rte(double16);
short16 __ovld __cnfn convert_short16_sat_rtn(double16);
short16 __ovld __cnfn convert_short16_sat_rtp(double16);
short16 __ovld __cnfn convert_short16_sat_rtz(double16);
ushort __ovld __cnfn convert_ushort(double);
ushort __ovld __cnfn convert_ushort_rte(double);
ushort __ovld __cnfn convert_ushort_rtn(double);
ushort __ovld __cnfn convert_ushort_rtp(double);
ushort __ovld __cnfn convert_ushort_rtz(double);
ushort __ovld __cnfn convert_ushort_sat(double);
ushort __ovld __cnfn convert_ushort_sat_rte(double);
ushort __ovld __cnfn convert_ushort_sat_rtn(double);
ushort __ovld __cnfn convert_ushort_sat_rtp(double);
ushort __ovld __cnfn convert_ushort_sat_rtz(double);
ushort2 __ovld __cnfn convert_ushort2(double2);
ushort2 __ovld __cnfn convert_ushort2_rte(double2);
ushort2 __ovld __cnfn convert_ushort2_rtn(double2);
ushort2 __ovld __cnfn convert_ushort2_rtp(double2);
ushort2 __ovld __cnfn convert_ushort2_rtz(double2);
ushort2 __ovld __cnfn convert_ushort2_sat(double2);
ushort2 __ovld __cnfn convert_ushort2_sat_rte(double2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtn(double2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtp(double2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtz(double2);
ushort3 __ovld __cnfn convert_ushort3(double3);
ushort3 __ovld __cnfn convert_ushort3_rte(double3);
ushort3 __ovld __cnfn convert_ushort3_rtn(double3);
ushort3 __ovld __cnfn convert_ushort3_rtp(double3);
ushort3 __ovld __cnfn convert_ushort3_rtz(double3);
ushort3 __ovld __cnfn convert_ushort3_sat(double3);
ushort3 __ovld __cnfn convert_ushort3_sat_rte(double3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtn(double3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtp(double3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtz(double3);
ushort4 __ovld __cnfn convert_ushort4(double4);
ushort4 __ovld __cnfn convert_ushort4_rte(double4);
ushort4 __ovld __cnfn convert_ushort4_rtn(double4);
ushort4 __ovld __cnfn convert_ushort4_rtp(double4);
ushort4 __ovld __cnfn convert_ushort4_rtz(double4);
ushort4 __ovld __cnfn convert_ushort4_sat(double4);
ushort4 __ovld __cnfn convert_ushort4_sat_rte(double4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtn(double4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtp(double4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtz(double4);
ushort8 __ovld __cnfn convert_ushort8(double8);
ushort8 __ovld __cnfn convert_ushort8_rte(double8);
ushort8 __ovld __cnfn convert_ushort8_rtn(double8);
ushort8 __ovld __cnfn convert_ushort8_rtp(double8);
ushort8 __ovld __cnfn convert_ushort8_rtz(double8);
ushort8 __ovld __cnfn convert_ushort8_sat(double8);
ushort8 __ovld __cnfn convert_ushort8_sat_rte(double8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtn(double8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtp(double8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtz(double8);
ushort16 __ovld __cnfn convert_ushort16(double16);
ushort16 __ovld __cnfn convert_ushort16_rte(double16);
ushort16 __ovld __cnfn convert_ushort16_rtn(double16);
ushort16 __ovld __cnfn convert_ushort16_rtp(double16);
ushort16 __ovld __cnfn convert_ushort16_rtz(double16);
ushort16 __ovld __cnfn convert_ushort16_sat(double16);
ushort16 __ovld __cnfn convert_ushort16_sat_rte(double16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtn(double16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtp(double16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtz(double16);
int __ovld __cnfn convert_int(double);
int __ovld __cnfn convert_int_rte(double);
int __ovld __cnfn convert_int_rtn(double);
int __ovld __cnfn convert_int_rtp(double);
int __ovld __cnfn convert_int_rtz(double);
int __ovld __cnfn convert_int_sat(double);
int __ovld __cnfn convert_int_sat_rte(double);
int __ovld __cnfn convert_int_sat_rtn(double);
int __ovld __cnfn convert_int_sat_rtp(double);
int __ovld __cnfn convert_int_sat_rtz(double);
int2 __ovld __cnfn convert_int2(double2);
int2 __ovld __cnfn convert_int2_rte(double2);
int2 __ovld __cnfn convert_int2_rtn(double2);
int2 __ovld __cnfn convert_int2_rtp(double2);
int2 __ovld __cnfn convert_int2_rtz(double2);
int2 __ovld __cnfn convert_int2_sat(double2);
int2 __ovld __cnfn convert_int2_sat_rte(double2);
int2 __ovld __cnfn convert_int2_sat_rtn(double2);
int2 __ovld __cnfn convert_int2_sat_rtp(double2);
int2 __ovld __cnfn convert_int2_sat_rtz(double2);
int3 __ovld __cnfn convert_int3(double3);
int3 __ovld __cnfn convert_int3_rte(double3);
int3 __ovld __cnfn convert_int3_rtn(double3);
int3 __ovld __cnfn convert_int3_rtp(double3);
int3 __ovld __cnfn convert_int3_rtz(double3);
int3 __ovld __cnfn convert_int3_sat(double3);
int3 __ovld __cnfn convert_int3_sat_rte(double3);
int3 __ovld __cnfn convert_int3_sat_rtn(double3);
int3 __ovld __cnfn convert_int3_sat_rtp(double3);
int3 __ovld __cnfn convert_int3_sat_rtz(double3);
int4 __ovld __cnfn convert_int4(double4);
int4 __ovld __cnfn convert_int4_rte(double4);
int4 __ovld __cnfn convert_int4_rtn(double4);
int4 __ovld __cnfn convert_int4_rtp(double4);
int4 __ovld __cnfn convert_int4_rtz(double4);
int4 __ovld __cnfn convert_int4_sat(double4);
int4 __ovld __cnfn convert_int4_sat_rte(double4);
int4 __ovld __cnfn convert_int4_sat_rtn(double4);
int4 __ovld __cnfn convert_int4_sat_rtp(double4);
int4 __ovld __cnfn convert_int4_sat_rtz(double4);
int8 __ovld __cnfn convert_int8(double8);
int8 __ovld __cnfn convert_int8_rte(double8);
int8 __ovld __cnfn convert_int8_rtn(double8);
int8 __ovld __cnfn convert_int8_rtp(double8);
int8 __ovld __cnfn convert_int8_rtz(double8);
int8 __ovld __cnfn convert_int8_sat(double8);
int8 __ovld __cnfn convert_int8_sat_rte(double8);
int8 __ovld __cnfn convert_int8_sat_rtn(double8);
int8 __ovld __cnfn convert_int8_sat_rtp(double8);
int8 __ovld __cnfn convert_int8_sat_rtz(double8);
int16 __ovld __cnfn convert_int16(double16);
int16 __ovld __cnfn convert_int16_rte(double16);
int16 __ovld __cnfn convert_int16_rtn(double16);
int16 __ovld __cnfn convert_int16_rtp(double16);
int16 __ovld __cnfn convert_int16_rtz(double16);
int16 __ovld __cnfn convert_int16_sat(double16);
int16 __ovld __cnfn convert_int16_sat_rte(double16);
int16 __ovld __cnfn convert_int16_sat_rtn(double16);
int16 __ovld __cnfn convert_int16_sat_rtp(double16);
int16 __ovld __cnfn convert_int16_sat_rtz(double16);
uint __ovld __cnfn convert_uint(double);
uint __ovld __cnfn convert_uint_rte(double);
uint __ovld __cnfn convert_uint_rtn(double);
uint __ovld __cnfn convert_uint_rtp(double);
uint __ovld __cnfn convert_uint_rtz(double);
uint __ovld __cnfn convert_uint_sat(double);
uint __ovld __cnfn convert_uint_sat_rte(double);
uint __ovld __cnfn convert_uint_sat_rtn(double);
uint __ovld __cnfn convert_uint_sat_rtp(double);
uint __ovld __cnfn convert_uint_sat_rtz(double);
uint2 __ovld __cnfn convert_uint2(double2);
uint2 __ovld __cnfn convert_uint2_rte(double2);
uint2 __ovld __cnfn convert_uint2_rtn(double2);
uint2 __ovld __cnfn convert_uint2_rtp(double2);
uint2 __ovld __cnfn convert_uint2_rtz(double2);
uint2 __ovld __cnfn convert_uint2_sat(double2);
uint2 __ovld __cnfn convert_uint2_sat_rte(double2);
uint2 __ovld __cnfn convert_uint2_sat_rtn(double2);
uint2 __ovld __cnfn convert_uint2_sat_rtp(double2);
uint2 __ovld __cnfn convert_uint2_sat_rtz(double2);
uint3 __ovld __cnfn convert_uint3(double3);
uint3 __ovld __cnfn convert_uint3_rte(double3);
uint3 __ovld __cnfn convert_uint3_rtn(double3);
uint3 __ovld __cnfn convert_uint3_rtp(double3);
uint3 __ovld __cnfn convert_uint3_rtz(double3);
uint3 __ovld __cnfn convert_uint3_sat(double3);
uint3 __ovld __cnfn convert_uint3_sat_rte(double3);
uint3 __ovld __cnfn convert_uint3_sat_rtn(double3);
uint3 __ovld __cnfn convert_uint3_sat_rtp(double3);
uint3 __ovld __cnfn convert_uint3_sat_rtz(double3);
uint4 __ovld __cnfn convert_uint4(double4);
uint4 __ovld __cnfn convert_uint4_rte(double4);
uint4 __ovld __cnfn convert_uint4_rtn(double4);
uint4 __ovld __cnfn convert_uint4_rtp(double4);
uint4 __ovld __cnfn convert_uint4_rtz(double4);
uint4 __ovld __cnfn convert_uint4_sat(double4);
uint4 __ovld __cnfn convert_uint4_sat_rte(double4);
uint4 __ovld __cnfn convert_uint4_sat_rtn(double4);
uint4 __ovld __cnfn convert_uint4_sat_rtp(double4);
uint4 __ovld __cnfn convert_uint4_sat_rtz(double4);
uint8 __ovld __cnfn convert_uint8(double8);
uint8 __ovld __cnfn convert_uint8_rte(double8);
uint8 __ovld __cnfn convert_uint8_rtn(double8);
uint8 __ovld __cnfn convert_uint8_rtp(double8);
uint8 __ovld __cnfn convert_uint8_rtz(double8);
uint8 __ovld __cnfn convert_uint8_sat(double8);
uint8 __ovld __cnfn convert_uint8_sat_rte(double8);
uint8 __ovld __cnfn convert_uint8_sat_rtn(double8);
uint8 __ovld __cnfn convert_uint8_sat_rtp(double8);
uint8 __ovld __cnfn convert_uint8_sat_rtz(double8);
uint16 __ovld __cnfn convert_uint16(double16);
uint16 __ovld __cnfn convert_uint16_rte(double16);
uint16 __ovld __cnfn convert_uint16_rtn(double16);
uint16 __ovld __cnfn convert_uint16_rtp(double16);
uint16 __ovld __cnfn convert_uint16_rtz(double16);
uint16 __ovld __cnfn convert_uint16_sat(double16);
uint16 __ovld __cnfn convert_uint16_sat_rte(double16);
uint16 __ovld __cnfn convert_uint16_sat_rtn(double16);
uint16 __ovld __cnfn convert_uint16_sat_rtp(double16);
uint16 __ovld __cnfn convert_uint16_sat_rtz(double16);
long __ovld __cnfn convert_long(double);
long __ovld __cnfn convert_long_rte(double);
long __ovld __cnfn convert_long_rtn(double);
long __ovld __cnfn convert_long_rtp(double);
long __ovld __cnfn convert_long_rtz(double);
long __ovld __cnfn convert_long_sat(double);
long __ovld __cnfn convert_long_sat_rte(double);
long __ovld __cnfn convert_long_sat_rtn(double);
long __ovld __cnfn convert_long_sat_rtp(double);
long __ovld __cnfn convert_long_sat_rtz(double);
long2 __ovld __cnfn convert_long2(double2);
long2 __ovld __cnfn convert_long2_rte(double2);
long2 __ovld __cnfn convert_long2_rtn(double2);
long2 __ovld __cnfn convert_long2_rtp(double2);
long2 __ovld __cnfn convert_long2_rtz(double2);
long2 __ovld __cnfn convert_long2_sat(double2);
long2 __ovld __cnfn convert_long2_sat_rte(double2);
long2 __ovld __cnfn convert_long2_sat_rtn(double2);
long2 __ovld __cnfn convert_long2_sat_rtp(double2);
long2 __ovld __cnfn convert_long2_sat_rtz(double2);
long3 __ovld __cnfn convert_long3(double3);
long3 __ovld __cnfn convert_long3_rte(double3);
long3 __ovld __cnfn convert_long3_rtn(double3);
long3 __ovld __cnfn convert_long3_rtp(double3);
long3 __ovld __cnfn convert_long3_rtz(double3);
long3 __ovld __cnfn convert_long3_sat(double3);
long3 __ovld __cnfn convert_long3_sat_rte(double3);
long3 __ovld __cnfn convert_long3_sat_rtn(double3);
long3 __ovld __cnfn convert_long3_sat_rtp(double3);
long3 __ovld __cnfn convert_long3_sat_rtz(double3);
long4 __ovld __cnfn convert_long4(double4);
long4 __ovld __cnfn convert_long4_rte(double4);
long4 __ovld __cnfn convert_long4_rtn(double4);
long4 __ovld __cnfn convert_long4_rtp(double4);
long4 __ovld __cnfn convert_long4_rtz(double4);
long4 __ovld __cnfn convert_long4_sat(double4);
long4 __ovld __cnfn convert_long4_sat_rte(double4);
long4 __ovld __cnfn convert_long4_sat_rtn(double4);
long4 __ovld __cnfn convert_long4_sat_rtp(double4);
long4 __ovld __cnfn convert_long4_sat_rtz(double4);
long8 __ovld __cnfn convert_long8(double8);
long8 __ovld __cnfn convert_long8_rte(double8);
long8 __ovld __cnfn convert_long8_rtn(double8);
long8 __ovld __cnfn convert_long8_rtp(double8);
long8 __ovld __cnfn convert_long8_rtz(double8);
long8 __ovld __cnfn convert_long8_sat(double8);
long8 __ovld __cnfn convert_long8_sat_rte(double8);
long8 __ovld __cnfn convert_long8_sat_rtn(double8);
long8 __ovld __cnfn convert_long8_sat_rtp(double8);
long8 __ovld __cnfn convert_long8_sat_rtz(double8);
long16 __ovld __cnfn convert_long16(double16);
long16 __ovld __cnfn convert_long16_rte(double16);
long16 __ovld __cnfn convert_long16_rtn(double16);
long16 __ovld __cnfn convert_long16_rtp(double16);
long16 __ovld __cnfn convert_long16_rtz(double16);
long16 __ovld __cnfn convert_long16_sat(double16);
long16 __ovld __cnfn convert_long16_sat_rte(double16);
long16 __ovld __cnfn convert_long16_sat_rtn(double16);
long16 __ovld __cnfn convert_long16_sat_rtp(double16);
long16 __ovld __cnfn convert_long16_sat_rtz(double16);
ulong __ovld __cnfn convert_ulong(double);
ulong __ovld __cnfn convert_ulong_rte(double);
ulong __ovld __cnfn convert_ulong_rtn(double);
ulong __ovld __cnfn convert_ulong_rtp(double);
ulong __ovld __cnfn convert_ulong_rtz(double);
ulong __ovld __cnfn convert_ulong_sat(double);
ulong __ovld __cnfn convert_ulong_sat_rte(double);
ulong __ovld __cnfn convert_ulong_sat_rtn(double);
ulong __ovld __cnfn convert_ulong_sat_rtp(double);
ulong __ovld __cnfn convert_ulong_sat_rtz(double);
ulong2 __ovld __cnfn convert_ulong2(double2);
ulong2 __ovld __cnfn convert_ulong2_rte(double2);
ulong2 __ovld __cnfn convert_ulong2_rtn(double2);
ulong2 __ovld __cnfn convert_ulong2_rtp(double2);
ulong2 __ovld __cnfn convert_ulong2_rtz(double2);
ulong2 __ovld __cnfn convert_ulong2_sat(double2);
ulong2 __ovld __cnfn convert_ulong2_sat_rte(double2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtn(double2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtp(double2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtz(double2);
ulong3 __ovld __cnfn convert_ulong3(double3);
ulong3 __ovld __cnfn convert_ulong3_rte(double3);
ulong3 __ovld __cnfn convert_ulong3_rtn(double3);
ulong3 __ovld __cnfn convert_ulong3_rtp(double3);
ulong3 __ovld __cnfn convert_ulong3_rtz(double3);
ulong3 __ovld __cnfn convert_ulong3_sat(double3);
ulong3 __ovld __cnfn convert_ulong3_sat_rte(double3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtn(double3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtp(double3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtz(double3);
ulong4 __ovld __cnfn convert_ulong4(double4);
ulong4 __ovld __cnfn convert_ulong4_rte(double4);
ulong4 __ovld __cnfn convert_ulong4_rtn(double4);
ulong4 __ovld __cnfn convert_ulong4_rtp(double4);
ulong4 __ovld __cnfn convert_ulong4_rtz(double4);
ulong4 __ovld __cnfn convert_ulong4_sat(double4);
ulong4 __ovld __cnfn convert_ulong4_sat_rte(double4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtn(double4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtp(double4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtz(double4);
ulong8 __ovld __cnfn convert_ulong8(double8);
ulong8 __ovld __cnfn convert_ulong8_rte(double8);
ulong8 __ovld __cnfn convert_ulong8_rtn(double8);
ulong8 __ovld __cnfn convert_ulong8_rtp(double8);
ulong8 __ovld __cnfn convert_ulong8_rtz(double8);
ulong8 __ovld __cnfn convert_ulong8_sat(double8);
ulong8 __ovld __cnfn convert_ulong8_sat_rte(double8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtn(double8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtp(double8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtz(double8);
ulong16 __ovld __cnfn convert_ulong16(double16);
ulong16 __ovld __cnfn convert_ulong16_rte(double16);
ulong16 __ovld __cnfn convert_ulong16_rtn(double16);
ulong16 __ovld __cnfn convert_ulong16_rtp(double16);
ulong16 __ovld __cnfn convert_ulong16_rtz(double16);
ulong16 __ovld __cnfn convert_ulong16_sat(double16);
ulong16 __ovld __cnfn convert_ulong16_sat_rte(double16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtn(double16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtp(double16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtz(double16);
float __ovld __cnfn convert_float(double);
float __ovld __cnfn convert_float_rte(double);
float __ovld __cnfn convert_float_rtn(double);
float __ovld __cnfn convert_float_rtp(double);
float __ovld __cnfn convert_float_rtz(double);
float2 __ovld __cnfn convert_float2(double2);
float2 __ovld __cnfn convert_float2_rte(double2);
float2 __ovld __cnfn convert_float2_rtn(double2);
float2 __ovld __cnfn convert_float2_rtp(double2);
float2 __ovld __cnfn convert_float2_rtz(double2);
float3 __ovld __cnfn convert_float3(double3);
float3 __ovld __cnfn convert_float3_rte(double3);
float3 __ovld __cnfn convert_float3_rtn(double3);
float3 __ovld __cnfn convert_float3_rtp(double3);
float3 __ovld __cnfn convert_float3_rtz(double3);
float4 __ovld __cnfn convert_float4(double4);
float4 __ovld __cnfn convert_float4_rte(double4);
float4 __ovld __cnfn convert_float4_rtn(double4);
float4 __ovld __cnfn convert_float4_rtp(double4);
float4 __ovld __cnfn convert_float4_rtz(double4);
float8 __ovld __cnfn convert_float8(double8);
float8 __ovld __cnfn convert_float8_rte(double8);
float8 __ovld __cnfn convert_float8_rtn(double8);
float8 __ovld __cnfn convert_float8_rtp(double8);
float8 __ovld __cnfn convert_float8_rtz(double8);
float16 __ovld __cnfn convert_float16(double16);
float16 __ovld __cnfn convert_float16_rte(double16);
float16 __ovld __cnfn convert_float16_rtn(double16);
float16 __ovld __cnfn convert_float16_rtp(double16);
float16 __ovld __cnfn convert_float16_rtz(double16);
double __ovld __cnfn convert_double(char);
double __ovld __cnfn convert_double(double);
double __ovld __cnfn convert_double(float);
double __ovld __cnfn convert_double(int);
double __ovld __cnfn convert_double(long);
double __ovld __cnfn convert_double(short);
double __ovld __cnfn convert_double(uchar);
double __ovld __cnfn convert_double(uint);
double __ovld __cnfn convert_double(ulong);
double __ovld __cnfn convert_double(ushort);
double __ovld __cnfn convert_double_rte(char);
double __ovld __cnfn convert_double_rte(double);
double __ovld __cnfn convert_double_rte(float);
double __ovld __cnfn convert_double_rte(int);
double __ovld __cnfn convert_double_rte(long);
double __ovld __cnfn convert_double_rte(short);
double __ovld __cnfn convert_double_rte(uchar);
double __ovld __cnfn convert_double_rte(uint);
double __ovld __cnfn convert_double_rte(ulong);
double __ovld __cnfn convert_double_rte(ushort);
double __ovld __cnfn convert_double_rtn(char);
double __ovld __cnfn convert_double_rtn(double);
double __ovld __cnfn convert_double_rtn(float);
double __ovld __cnfn convert_double_rtn(int);
double __ovld __cnfn convert_double_rtn(long);
double __ovld __cnfn convert_double_rtn(short);
double __ovld __cnfn convert_double_rtn(uchar);
double __ovld __cnfn convert_double_rtn(uint);
double __ovld __cnfn convert_double_rtn(ulong);
double __ovld __cnfn convert_double_rtn(ushort);
double __ovld __cnfn convert_double_rtp(char);
double __ovld __cnfn convert_double_rtp(double);
double __ovld __cnfn convert_double_rtp(float);
double __ovld __cnfn convert_double_rtp(int);
double __ovld __cnfn convert_double_rtp(long);
double __ovld __cnfn convert_double_rtp(short);
double __ovld __cnfn convert_double_rtp(uchar);
double __ovld __cnfn convert_double_rtp(uint);
double __ovld __cnfn convert_double_rtp(ulong);
double __ovld __cnfn convert_double_rtp(ushort);
double __ovld __cnfn convert_double_rtz(char);
double __ovld __cnfn convert_double_rtz(double);
double __ovld __cnfn convert_double_rtz(float);
double __ovld __cnfn convert_double_rtz(int);
double __ovld __cnfn convert_double_rtz(long);
double __ovld __cnfn convert_double_rtz(short);
double __ovld __cnfn convert_double_rtz(uchar);
double __ovld __cnfn convert_double_rtz(uint);
double __ovld __cnfn convert_double_rtz(ulong);
double __ovld __cnfn convert_double_rtz(ushort);
double2 __ovld __cnfn convert_double2(char2);
double2 __ovld __cnfn convert_double2(double2);
double2 __ovld __cnfn convert_double2(float2);
double2 __ovld __cnfn convert_double2(int2);
double2 __ovld __cnfn convert_double2(long2);
double2 __ovld __cnfn convert_double2(short2);
double2 __ovld __cnfn convert_double2(uchar2);
double2 __ovld __cnfn convert_double2(uint2);
double2 __ovld __cnfn convert_double2(ulong2);
double2 __ovld __cnfn convert_double2(ushort2);
double2 __ovld __cnfn convert_double2_rte(char2);
double2 __ovld __cnfn convert_double2_rte(double2);
double2 __ovld __cnfn convert_double2_rte(float2);
double2 __ovld __cnfn convert_double2_rte(int2);
double2 __ovld __cnfn convert_double2_rte(long2);
double2 __ovld __cnfn convert_double2_rte(short2);
double2 __ovld __cnfn convert_double2_rte(uchar2);
double2 __ovld __cnfn convert_double2_rte(uint2);
double2 __ovld __cnfn convert_double2_rte(ulong2);
double2 __ovld __cnfn convert_double2_rte(ushort2);
double2 __ovld __cnfn convert_double2_rtn(char2);
double2 __ovld __cnfn convert_double2_rtn(double2);
double2 __ovld __cnfn convert_double2_rtn(float2);
double2 __ovld __cnfn convert_double2_rtn(int2);
double2 __ovld __cnfn convert_double2_rtn(long2);
double2 __ovld __cnfn convert_double2_rtn(short2);
double2 __ovld __cnfn convert_double2_rtn(uchar2);
double2 __ovld __cnfn convert_double2_rtn(uint2);
double2 __ovld __cnfn convert_double2_rtn(ulong2);
double2 __ovld __cnfn convert_double2_rtn(ushort2);
double2 __ovld __cnfn convert_double2_rtp(char2);
double2 __ovld __cnfn convert_double2_rtp(double2);
double2 __ovld __cnfn convert_double2_rtp(float2);
double2 __ovld __cnfn convert_double2_rtp(int2);
double2 __ovld __cnfn convert_double2_rtp(long2);
double2 __ovld __cnfn convert_double2_rtp(short2);
double2 __ovld __cnfn convert_double2_rtp(uchar2);
double2 __ovld __cnfn convert_double2_rtp(uint2);
double2 __ovld __cnfn convert_double2_rtp(ulong2);
double2 __ovld __cnfn convert_double2_rtp(ushort2);
double2 __ovld __cnfn convert_double2_rtz(char2);
double2 __ovld __cnfn convert_double2_rtz(double2);
double2 __ovld __cnfn convert_double2_rtz(float2);
double2 __ovld __cnfn convert_double2_rtz(int2);
double2 __ovld __cnfn convert_double2_rtz(long2);
double2 __ovld __cnfn convert_double2_rtz(short2);
double2 __ovld __cnfn convert_double2_rtz(uchar2);
double2 __ovld __cnfn convert_double2_rtz(uint2);
double2 __ovld __cnfn convert_double2_rtz(ulong2);
double2 __ovld __cnfn convert_double2_rtz(ushort2);
double3 __ovld __cnfn convert_double3(char3);
double3 __ovld __cnfn convert_double3(double3);
double3 __ovld __cnfn convert_double3(float3);
double3 __ovld __cnfn convert_double3(int3);
double3 __ovld __cnfn convert_double3(long3);
double3 __ovld __cnfn convert_double3(short3);
double3 __ovld __cnfn convert_double3(uchar3);
double3 __ovld __cnfn convert_double3(uint3);
double3 __ovld __cnfn convert_double3(ulong3);
double3 __ovld __cnfn convert_double3(ushort3);
double3 __ovld __cnfn convert_double3_rte(char3);
double3 __ovld __cnfn convert_double3_rte(double3);
double3 __ovld __cnfn convert_double3_rte(float3);
double3 __ovld __cnfn convert_double3_rte(int3);
double3 __ovld __cnfn convert_double3_rte(long3);
double3 __ovld __cnfn convert_double3_rte(short3);
double3 __ovld __cnfn convert_double3_rte(uchar3);
double3 __ovld __cnfn convert_double3_rte(uint3);
double3 __ovld __cnfn convert_double3_rte(ulong3);
double3 __ovld __cnfn convert_double3_rte(ushort3);
double3 __ovld __cnfn convert_double3_rtn(char3);
double3 __ovld __cnfn convert_double3_rtn(double3);
double3 __ovld __cnfn convert_double3_rtn(float3);
double3 __ovld __cnfn convert_double3_rtn(int3);
double3 __ovld __cnfn convert_double3_rtn(long3);
double3 __ovld __cnfn convert_double3_rtn(short3);
double3 __ovld __cnfn convert_double3_rtn(uchar3);
double3 __ovld __cnfn convert_double3_rtn(uint3);
double3 __ovld __cnfn convert_double3_rtn(ulong3);
double3 __ovld __cnfn convert_double3_rtn(ushort3);
double3 __ovld __cnfn convert_double3_rtp(char3);
double3 __ovld __cnfn convert_double3_rtp(double3);
double3 __ovld __cnfn convert_double3_rtp(float3);
double3 __ovld __cnfn convert_double3_rtp(int3);
double3 __ovld __cnfn convert_double3_rtp(long3);
double3 __ovld __cnfn convert_double3_rtp(short3);
double3 __ovld __cnfn convert_double3_rtp(uchar3);
double3 __ovld __cnfn convert_double3_rtp(uint3);
double3 __ovld __cnfn convert_double3_rtp(ulong3);
double3 __ovld __cnfn convert_double3_rtp(ushort3);
double3 __ovld __cnfn convert_double3_rtz(char3);
double3 __ovld __cnfn convert_double3_rtz(double3);
double3 __ovld __cnfn convert_double3_rtz(float3);
double3 __ovld __cnfn convert_double3_rtz(int3);
double3 __ovld __cnfn convert_double3_rtz(long3);
double3 __ovld __cnfn convert_double3_rtz(short3);
double3 __ovld __cnfn convert_double3_rtz(uchar3);
double3 __ovld __cnfn convert_double3_rtz(uint3);
double3 __ovld __cnfn convert_double3_rtz(ulong3);
double3 __ovld __cnfn convert_double3_rtz(ushort3);
double4 __ovld __cnfn convert_double4(char4);
double4 __ovld __cnfn convert_double4(double4);
double4 __ovld __cnfn convert_double4(float4);
double4 __ovld __cnfn convert_double4(int4);
double4 __ovld __cnfn convert_double4(long4);
double4 __ovld __cnfn convert_double4(short4);
double4 __ovld __cnfn convert_double4(uchar4);
double4 __ovld __cnfn convert_double4(uint4);
double4 __ovld __cnfn convert_double4(ulong4);
double4 __ovld __cnfn convert_double4(ushort4);
double4 __ovld __cnfn convert_double4_rte(char4);
double4 __ovld __cnfn convert_double4_rte(double4);
double4 __ovld __cnfn convert_double4_rte(float4);
double4 __ovld __cnfn convert_double4_rte(int4);
double4 __ovld __cnfn convert_double4_rte(long4);
double4 __ovld __cnfn convert_double4_rte(short4);
double4 __ovld __cnfn convert_double4_rte(uchar4);
double4 __ovld __cnfn convert_double4_rte(uint4);
double4 __ovld __cnfn convert_double4_rte(ulong4);
double4 __ovld __cnfn convert_double4_rte(ushort4);
double4 __ovld __cnfn convert_double4_rtn(char4);
double4 __ovld __cnfn convert_double4_rtn(double4);
double4 __ovld __cnfn convert_double4_rtn(float4);
double4 __ovld __cnfn convert_double4_rtn(int4);
double4 __ovld __cnfn convert_double4_rtn(long4);
double4 __ovld __cnfn convert_double4_rtn(short4);
double4 __ovld __cnfn convert_double4_rtn(uchar4);
double4 __ovld __cnfn convert_double4_rtn(uint4);
double4 __ovld __cnfn convert_double4_rtn(ulong4);
double4 __ovld __cnfn convert_double4_rtn(ushort4);
double4 __ovld __cnfn convert_double4_rtp(char4);
double4 __ovld __cnfn convert_double4_rtp(double4);
double4 __ovld __cnfn convert_double4_rtp(float4);
double4 __ovld __cnfn convert_double4_rtp(int4);
double4 __ovld __cnfn convert_double4_rtp(long4);
double4 __ovld __cnfn convert_double4_rtp(short4);
double4 __ovld __cnfn convert_double4_rtp(uchar4);
double4 __ovld __cnfn convert_double4_rtp(uint4);
double4 __ovld __cnfn convert_double4_rtp(ulong4);
double4 __ovld __cnfn convert_double4_rtp(ushort4);
double4 __ovld __cnfn convert_double4_rtz(char4);
double4 __ovld __cnfn convert_double4_rtz(double4);
double4 __ovld __cnfn convert_double4_rtz(float4);
double4 __ovld __cnfn convert_double4_rtz(int4);
double4 __ovld __cnfn convert_double4_rtz(long4);
double4 __ovld __cnfn convert_double4_rtz(short4);
double4 __ovld __cnfn convert_double4_rtz(uchar4);
double4 __ovld __cnfn convert_double4_rtz(uint4);
double4 __ovld __cnfn convert_double4_rtz(ulong4);
double4 __ovld __cnfn convert_double4_rtz(ushort4);
double8 __ovld __cnfn convert_double8(char8);
double8 __ovld __cnfn convert_double8(double8);
double8 __ovld __cnfn convert_double8(float8);
double8 __ovld __cnfn convert_double8(int8);
double8 __ovld __cnfn convert_double8(long8);
double8 __ovld __cnfn convert_double8(short8);
double8 __ovld __cnfn convert_double8(uchar8);
double8 __ovld __cnfn convert_double8(uint8);
double8 __ovld __cnfn convert_double8(ulong8);
double8 __ovld __cnfn convert_double8(ushort8);
double8 __ovld __cnfn convert_double8_rte(char8);
double8 __ovld __cnfn convert_double8_rte(double8);
double8 __ovld __cnfn convert_double8_rte(float8);
double8 __ovld __cnfn convert_double8_rte(int8);
double8 __ovld __cnfn convert_double8_rte(long8);
double8 __ovld __cnfn convert_double8_rte(short8);
double8 __ovld __cnfn convert_double8_rte(uchar8);
double8 __ovld __cnfn convert_double8_rte(uint8);
double8 __ovld __cnfn convert_double8_rte(ulong8);
double8 __ovld __cnfn convert_double8_rte(ushort8);
double8 __ovld __cnfn convert_double8_rtn(char8);
double8 __ovld __cnfn convert_double8_rtn(double8);
double8 __ovld __cnfn convert_double8_rtn(float8);
double8 __ovld __cnfn convert_double8_rtn(int8);
double8 __ovld __cnfn convert_double8_rtn(long8);
double8 __ovld __cnfn convert_double8_rtn(short8);
double8 __ovld __cnfn convert_double8_rtn(uchar8);
double8 __ovld __cnfn convert_double8_rtn(uint8);
double8 __ovld __cnfn convert_double8_rtn(ulong8);
double8 __ovld __cnfn convert_double8_rtn(ushort8);
double8 __ovld __cnfn convert_double8_rtp(char8);
double8 __ovld __cnfn convert_double8_rtp(double8);
double8 __ovld __cnfn convert_double8_rtp(float8);
double8 __ovld __cnfn convert_double8_rtp(int8);
double8 __ovld __cnfn convert_double8_rtp(long8);
double8 __ovld __cnfn convert_double8_rtp(short8);
double8 __ovld __cnfn convert_double8_rtp(uchar8);
double8 __ovld __cnfn convert_double8_rtp(uint8);
double8 __ovld __cnfn convert_double8_rtp(ulong8);
double8 __ovld __cnfn convert_double8_rtp(ushort8);
double8 __ovld __cnfn convert_double8_rtz(char8);
double8 __ovld __cnfn convert_double8_rtz(double8);
double8 __ovld __cnfn convert_double8_rtz(float8);
double8 __ovld __cnfn convert_double8_rtz(int8);
double8 __ovld __cnfn convert_double8_rtz(long8);
double8 __ovld __cnfn convert_double8_rtz(short8);
double8 __ovld __cnfn convert_double8_rtz(uchar8);
double8 __ovld __cnfn convert_double8_rtz(uint8);
double8 __ovld __cnfn convert_double8_rtz(ulong8);
double8 __ovld __cnfn convert_double8_rtz(ushort8);
double16 __ovld __cnfn convert_double16(char16);
double16 __ovld __cnfn convert_double16(double16);
double16 __ovld __cnfn convert_double16(float16);
double16 __ovld __cnfn convert_double16(int16);
double16 __ovld __cnfn convert_double16(long16);
double16 __ovld __cnfn convert_double16(short16);
double16 __ovld __cnfn convert_double16(uchar16);
double16 __ovld __cnfn convert_double16(uint16);
double16 __ovld __cnfn convert_double16(ulong16);
double16 __ovld __cnfn convert_double16(ushort16);
double16 __ovld __cnfn convert_double16_rte(char16);
double16 __ovld __cnfn convert_double16_rte(double16);
double16 __ovld __cnfn convert_double16_rte(float16);
double16 __ovld __cnfn convert_double16_rte(int16);
double16 __ovld __cnfn convert_double16_rte(long16);
double16 __ovld __cnfn convert_double16_rte(short16);
double16 __ovld __cnfn convert_double16_rte(uchar16);
double16 __ovld __cnfn convert_double16_rte(uint16);
double16 __ovld __cnfn convert_double16_rte(ulong16);
double16 __ovld __cnfn convert_double16_rte(ushort16);
double16 __ovld __cnfn convert_double16_rtn(char16);
double16 __ovld __cnfn convert_double16_rtn(double16);
double16 __ovld __cnfn convert_double16_rtn(float16);
double16 __ovld __cnfn convert_double16_rtn(int16);
double16 __ovld __cnfn convert_double16_rtn(long16);
double16 __ovld __cnfn convert_double16_rtn(short16);
double16 __ovld __cnfn convert_double16_rtn(uchar16);
double16 __ovld __cnfn convert_double16_rtn(uint16);
double16 __ovld __cnfn convert_double16_rtn(ulong16);
double16 __ovld __cnfn convert_double16_rtn(ushort16);
double16 __ovld __cnfn convert_double16_rtp(char16);
double16 __ovld __cnfn convert_double16_rtp(double16);
double16 __ovld __cnfn convert_double16_rtp(float16);
double16 __ovld __cnfn convert_double16_rtp(int16);
double16 __ovld __cnfn convert_double16_rtp(long16);
double16 __ovld __cnfn convert_double16_rtp(short16);
double16 __ovld __cnfn convert_double16_rtp(uchar16);
double16 __ovld __cnfn convert_double16_rtp(uint16);
double16 __ovld __cnfn convert_double16_rtp(ulong16);
double16 __ovld __cnfn convert_double16_rtp(ushort16);
double16 __ovld __cnfn convert_double16_rtz(char16);
double16 __ovld __cnfn convert_double16_rtz(double16);
double16 __ovld __cnfn convert_double16_rtz(float16);
double16 __ovld __cnfn convert_double16_rtz(int16);
double16 __ovld __cnfn convert_double16_rtz(long16);
double16 __ovld __cnfn convert_double16_rtz(short16);
double16 __ovld __cnfn convert_double16_rtz(uchar16);
double16 __ovld __cnfn convert_double16_rtz(uint16);
double16 __ovld __cnfn convert_double16_rtz(ulong16);
double16 __ovld __cnfn convert_double16_rtz(ushort16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
// Convert half types to non-double types.
uchar __ovld __cnfn convert_uchar(half);
uchar __ovld __cnfn convert_uchar_rte(half);
uchar __ovld __cnfn convert_uchar_rtp(half);
uchar __ovld __cnfn convert_uchar_rtn(half);
uchar __ovld __cnfn convert_uchar_rtz(half);
uchar __ovld __cnfn convert_uchar_sat(half);
uchar __ovld __cnfn convert_uchar_sat_rte(half);
uchar __ovld __cnfn convert_uchar_sat_rtp(half);
uchar __ovld __cnfn convert_uchar_sat_rtn(half);
uchar __ovld __cnfn convert_uchar_sat_rtz(half);
uchar2 __ovld __cnfn convert_uchar2(half2);
uchar2 __ovld __cnfn convert_uchar2_rte(half2);
uchar2 __ovld __cnfn convert_uchar2_rtp(half2);
uchar2 __ovld __cnfn convert_uchar2_rtn(half2);
uchar2 __ovld __cnfn convert_uchar2_rtz(half2);
uchar2 __ovld __cnfn convert_uchar2_sat(half2);
uchar2 __ovld __cnfn convert_uchar2_sat_rte(half2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtp(half2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtn(half2);
uchar2 __ovld __cnfn convert_uchar2_sat_rtz(half2);
uchar3 __ovld __cnfn convert_uchar3(half3);
uchar3 __ovld __cnfn convert_uchar3_rte(half3);
uchar3 __ovld __cnfn convert_uchar3_rtp(half3);
uchar3 __ovld __cnfn convert_uchar3_rtn(half3);
uchar3 __ovld __cnfn convert_uchar3_rtz(half3);
uchar3 __ovld __cnfn convert_uchar3_sat(half3);
uchar3 __ovld __cnfn convert_uchar3_sat_rte(half3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtp(half3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtn(half3);
uchar3 __ovld __cnfn convert_uchar3_sat_rtz(half3);
uchar4 __ovld __cnfn convert_uchar4(half4);
uchar4 __ovld __cnfn convert_uchar4_rte(half4);
uchar4 __ovld __cnfn convert_uchar4_rtp(half4);
uchar4 __ovld __cnfn convert_uchar4_rtn(half4);
uchar4 __ovld __cnfn convert_uchar4_rtz(half4);
uchar4 __ovld __cnfn convert_uchar4_sat(half4);
uchar4 __ovld __cnfn convert_uchar4_sat_rte(half4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtp(half4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtn(half4);
uchar4 __ovld __cnfn convert_uchar4_sat_rtz(half4);
uchar8 __ovld __cnfn convert_uchar8(half8);
uchar8 __ovld __cnfn convert_uchar8_rte(half8);
uchar8 __ovld __cnfn convert_uchar8_rtp(half8);
uchar8 __ovld __cnfn convert_uchar8_rtn(half8);
uchar8 __ovld __cnfn convert_uchar8_rtz(half8);
uchar8 __ovld __cnfn convert_uchar8_sat(half8);
uchar8 __ovld __cnfn convert_uchar8_sat_rte(half8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtp(half8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtn(half8);
uchar8 __ovld __cnfn convert_uchar8_sat_rtz(half8);
uchar16 __ovld __cnfn convert_uchar16(half16);
uchar16 __ovld __cnfn convert_uchar16_rte(half16);
uchar16 __ovld __cnfn convert_uchar16_rtp(half16);
uchar16 __ovld __cnfn convert_uchar16_rtn(half16);
uchar16 __ovld __cnfn convert_uchar16_rtz(half16);
uchar16 __ovld __cnfn convert_uchar16_sat(half16);
uchar16 __ovld __cnfn convert_uchar16_sat_rte(half16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtp(half16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtn(half16);
uchar16 __ovld __cnfn convert_uchar16_sat_rtz(half16);
ushort __ovld __cnfn convert_ushort(half);
ushort __ovld __cnfn convert_ushort_rte(half);
ushort __ovld __cnfn convert_ushort_rtp(half);
ushort __ovld __cnfn convert_ushort_rtn(half);
ushort __ovld __cnfn convert_ushort_rtz(half);
ushort __ovld __cnfn convert_ushort_sat(half);
ushort __ovld __cnfn convert_ushort_sat_rte(half);
ushort __ovld __cnfn convert_ushort_sat_rtp(half);
ushort __ovld __cnfn convert_ushort_sat_rtn(half);
ushort __ovld __cnfn convert_ushort_sat_rtz(half);
ushort2 __ovld __cnfn convert_ushort2(half2);
ushort2 __ovld __cnfn convert_ushort2_rte(half2);
ushort2 __ovld __cnfn convert_ushort2_rtp(half2);
ushort2 __ovld __cnfn convert_ushort2_rtn(half2);
ushort2 __ovld __cnfn convert_ushort2_rtz(half2);
ushort2 __ovld __cnfn convert_ushort2_sat(half2);
ushort2 __ovld __cnfn convert_ushort2_sat_rte(half2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtp(half2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtn(half2);
ushort2 __ovld __cnfn convert_ushort2_sat_rtz(half2);
ushort3 __ovld __cnfn convert_ushort3(half3);
ushort3 __ovld __cnfn convert_ushort3_rte(half3);
ushort3 __ovld __cnfn convert_ushort3_rtp(half3);
ushort3 __ovld __cnfn convert_ushort3_rtn(half3);
ushort3 __ovld __cnfn convert_ushort3_rtz(half3);
ushort3 __ovld __cnfn convert_ushort3_sat(half3);
ushort3 __ovld __cnfn convert_ushort3_sat_rte(half3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtp(half3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtn(half3);
ushort3 __ovld __cnfn convert_ushort3_sat_rtz(half3);
ushort4 __ovld __cnfn convert_ushort4(half4);
ushort4 __ovld __cnfn convert_ushort4_rte(half4);
ushort4 __ovld __cnfn convert_ushort4_rtp(half4);
ushort4 __ovld __cnfn convert_ushort4_rtn(half4);
ushort4 __ovld __cnfn convert_ushort4_rtz(half4);
ushort4 __ovld __cnfn convert_ushort4_sat(half4);
ushort4 __ovld __cnfn convert_ushort4_sat_rte(half4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtp(half4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtn(half4);
ushort4 __ovld __cnfn convert_ushort4_sat_rtz(half4);
ushort8 __ovld __cnfn convert_ushort8(half8);
ushort8 __ovld __cnfn convert_ushort8_rte(half8);
ushort8 __ovld __cnfn convert_ushort8_rtp(half8);
ushort8 __ovld __cnfn convert_ushort8_rtn(half8);
ushort8 __ovld __cnfn convert_ushort8_rtz(half8);
ushort8 __ovld __cnfn convert_ushort8_sat(half8);
ushort8 __ovld __cnfn convert_ushort8_sat_rte(half8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtp(half8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtn(half8);
ushort8 __ovld __cnfn convert_ushort8_sat_rtz(half8);
ushort16 __ovld __cnfn convert_ushort16(half16);
ushort16 __ovld __cnfn convert_ushort16_rte(half16);
ushort16 __ovld __cnfn convert_ushort16_rtp(half16);
ushort16 __ovld __cnfn convert_ushort16_rtn(half16);
ushort16 __ovld __cnfn convert_ushort16_rtz(half16);
ushort16 __ovld __cnfn convert_ushort16_sat(half16);
ushort16 __ovld __cnfn convert_ushort16_sat_rte(half16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtp(half16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtn(half16);
ushort16 __ovld __cnfn convert_ushort16_sat_rtz(half16);
uint __ovld __cnfn convert_uint(half);
uint __ovld __cnfn convert_uint_rte(half);
uint __ovld __cnfn convert_uint_rtp(half);
uint __ovld __cnfn convert_uint_rtn(half);
uint __ovld __cnfn convert_uint_rtz(half);
uint __ovld __cnfn convert_uint_sat(half);
uint __ovld __cnfn convert_uint_sat_rte(half);
uint __ovld __cnfn convert_uint_sat_rtp(half);
uint __ovld __cnfn convert_uint_sat_rtn(half);
uint __ovld __cnfn convert_uint_sat_rtz(half);
uint2 __ovld __cnfn convert_uint2(half2);
uint2 __ovld __cnfn convert_uint2_rte(half2);
uint2 __ovld __cnfn convert_uint2_rtp(half2);
uint2 __ovld __cnfn convert_uint2_rtn(half2);
uint2 __ovld __cnfn convert_uint2_rtz(half2);
uint2 __ovld __cnfn convert_uint2_sat(half2);
uint2 __ovld __cnfn convert_uint2_sat_rte(half2);
uint2 __ovld __cnfn convert_uint2_sat_rtp(half2);
uint2 __ovld __cnfn convert_uint2_sat_rtn(half2);
uint2 __ovld __cnfn convert_uint2_sat_rtz(half2);
uint3 __ovld __cnfn convert_uint3(half3);
uint3 __ovld __cnfn convert_uint3_rte(half3);
uint3 __ovld __cnfn convert_uint3_rtp(half3);
uint3 __ovld __cnfn convert_uint3_rtn(half3);
uint3 __ovld __cnfn convert_uint3_rtz(half3);
uint3 __ovld __cnfn convert_uint3_sat(half3);
uint3 __ovld __cnfn convert_uint3_sat_rte(half3);
uint3 __ovld __cnfn convert_uint3_sat_rtp(half3);
uint3 __ovld __cnfn convert_uint3_sat_rtn(half3);
uint3 __ovld __cnfn convert_uint3_sat_rtz(half3);
uint4 __ovld __cnfn convert_uint4(half4);
uint4 __ovld __cnfn convert_uint4_rte(half4);
uint4 __ovld __cnfn convert_uint4_rtp(half4);
uint4 __ovld __cnfn convert_uint4_rtn(half4);
uint4 __ovld __cnfn convert_uint4_rtz(half4);
uint4 __ovld __cnfn convert_uint4_sat(half4);
uint4 __ovld __cnfn convert_uint4_sat_rte(half4);
uint4 __ovld __cnfn convert_uint4_sat_rtp(half4);
uint4 __ovld __cnfn convert_uint4_sat_rtn(half4);
uint4 __ovld __cnfn convert_uint4_sat_rtz(half4);
uint8 __ovld __cnfn convert_uint8(half8);
uint8 __ovld __cnfn convert_uint8_rte(half8);
uint8 __ovld __cnfn convert_uint8_rtp(half8);
uint8 __ovld __cnfn convert_uint8_rtn(half8);
uint8 __ovld __cnfn convert_uint8_rtz(half8);
uint8 __ovld __cnfn convert_uint8_sat(half8);
uint8 __ovld __cnfn convert_uint8_sat_rte(half8);
uint8 __ovld __cnfn convert_uint8_sat_rtp(half8);
uint8 __ovld __cnfn convert_uint8_sat_rtn(half8);
uint8 __ovld __cnfn convert_uint8_sat_rtz(half8);
uint16 __ovld __cnfn convert_uint16(half16);
uint16 __ovld __cnfn convert_uint16_rte(half16);
uint16 __ovld __cnfn convert_uint16_rtp(half16);
uint16 __ovld __cnfn convert_uint16_rtn(half16);
uint16 __ovld __cnfn convert_uint16_rtz(half16);
uint16 __ovld __cnfn convert_uint16_sat(half16);
uint16 __ovld __cnfn convert_uint16_sat_rte(half16);
uint16 __ovld __cnfn convert_uint16_sat_rtp(half16);
uint16 __ovld __cnfn convert_uint16_sat_rtn(half16);
uint16 __ovld __cnfn convert_uint16_sat_rtz(half16);
ulong __ovld __cnfn convert_ulong(half);
ulong __ovld __cnfn convert_ulong_rte(half);
ulong __ovld __cnfn convert_ulong_rtp(half);
ulong __ovld __cnfn convert_ulong_rtn(half);
ulong __ovld __cnfn convert_ulong_rtz(half);
ulong __ovld __cnfn convert_ulong_sat(half);
ulong __ovld __cnfn convert_ulong_sat_rte(half);
ulong __ovld __cnfn convert_ulong_sat_rtp(half);
ulong __ovld __cnfn convert_ulong_sat_rtn(half);
ulong __ovld __cnfn convert_ulong_sat_rtz(half);
ulong2 __ovld __cnfn convert_ulong2(half2);
ulong2 __ovld __cnfn convert_ulong2_rte(half2);
ulong2 __ovld __cnfn convert_ulong2_rtp(half2);
ulong2 __ovld __cnfn convert_ulong2_rtn(half2);
ulong2 __ovld __cnfn convert_ulong2_rtz(half2);
ulong2 __ovld __cnfn convert_ulong2_sat(half2);
ulong2 __ovld __cnfn convert_ulong2_sat_rte(half2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtp(half2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtn(half2);
ulong2 __ovld __cnfn convert_ulong2_sat_rtz(half2);
ulong3 __ovld __cnfn convert_ulong3(half3);
ulong3 __ovld __cnfn convert_ulong3_rte(half3);
ulong3 __ovld __cnfn convert_ulong3_rtp(half3);
ulong3 __ovld __cnfn convert_ulong3_rtn(half3);
ulong3 __ovld __cnfn convert_ulong3_rtz(half3);
ulong3 __ovld __cnfn convert_ulong3_sat(half3);
ulong3 __ovld __cnfn convert_ulong3_sat_rte(half3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtp(half3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtn(half3);
ulong3 __ovld __cnfn convert_ulong3_sat_rtz(half3);
ulong4 __ovld __cnfn convert_ulong4(half4);
ulong4 __ovld __cnfn convert_ulong4_rte(half4);
ulong4 __ovld __cnfn convert_ulong4_rtp(half4);
ulong4 __ovld __cnfn convert_ulong4_rtn(half4);
ulong4 __ovld __cnfn convert_ulong4_rtz(half4);
ulong4 __ovld __cnfn convert_ulong4_sat(half4);
ulong4 __ovld __cnfn convert_ulong4_sat_rte(half4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtp(half4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtn(half4);
ulong4 __ovld __cnfn convert_ulong4_sat_rtz(half4);
ulong8 __ovld __cnfn convert_ulong8(half8);
ulong8 __ovld __cnfn convert_ulong8_rte(half8);
ulong8 __ovld __cnfn convert_ulong8_rtp(half8);
ulong8 __ovld __cnfn convert_ulong8_rtn(half8);
ulong8 __ovld __cnfn convert_ulong8_rtz(half8);
ulong8 __ovld __cnfn convert_ulong8_sat(half8);
ulong8 __ovld __cnfn convert_ulong8_sat_rte(half8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtp(half8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtn(half8);
ulong8 __ovld __cnfn convert_ulong8_sat_rtz(half8);
ulong16 __ovld __cnfn convert_ulong16(half16);
ulong16 __ovld __cnfn convert_ulong16_rte(half16);
ulong16 __ovld __cnfn convert_ulong16_rtp(half16);
ulong16 __ovld __cnfn convert_ulong16_rtn(half16);
ulong16 __ovld __cnfn convert_ulong16_rtz(half16);
ulong16 __ovld __cnfn convert_ulong16_sat(half16);
ulong16 __ovld __cnfn convert_ulong16_sat_rte(half16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtp(half16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtn(half16);
ulong16 __ovld __cnfn convert_ulong16_sat_rtz(half16);
char __ovld __cnfn convert_char(half);
char __ovld __cnfn convert_char_rte(half);
char __ovld __cnfn convert_char_rtp(half);
char __ovld __cnfn convert_char_rtn(half);
char __ovld __cnfn convert_char_rtz(half);
char __ovld __cnfn convert_char_sat(half);
char __ovld __cnfn convert_char_sat_rte(half);
char __ovld __cnfn convert_char_sat_rtp(half);
char __ovld __cnfn convert_char_sat_rtn(half);
char __ovld __cnfn convert_char_sat_rtz(half);
char2 __ovld __cnfn convert_char2(half2);
char2 __ovld __cnfn convert_char2_rte(half2);
char2 __ovld __cnfn convert_char2_rtp(half2);
char2 __ovld __cnfn convert_char2_rtn(half2);
char2 __ovld __cnfn convert_char2_rtz(half2);
char2 __ovld __cnfn convert_char2_sat(half2);
char2 __ovld __cnfn convert_char2_sat_rte(half2);
char2 __ovld __cnfn convert_char2_sat_rtp(half2);
char2 __ovld __cnfn convert_char2_sat_rtn(half2);
char2 __ovld __cnfn convert_char2_sat_rtz(half2);
char3 __ovld __cnfn convert_char3(half3);
char3 __ovld __cnfn convert_char3_rte(half3);
char3 __ovld __cnfn convert_char3_rtp(half3);
char3 __ovld __cnfn convert_char3_rtn(half3);
char3 __ovld __cnfn convert_char3_rtz(half3);
char3 __ovld __cnfn convert_char3_sat(half3);
char3 __ovld __cnfn convert_char3_sat_rte(half3);
char3 __ovld __cnfn convert_char3_sat_rtp(half3);
char3 __ovld __cnfn convert_char3_sat_rtn(half3);
char3 __ovld __cnfn convert_char3_sat_rtz(half3);
char4 __ovld __cnfn convert_char4(half4);
char4 __ovld __cnfn convert_char4_rte(half4);
char4 __ovld __cnfn convert_char4_rtp(half4);
char4 __ovld __cnfn convert_char4_rtn(half4);
char4 __ovld __cnfn convert_char4_rtz(half4);
char4 __ovld __cnfn convert_char4_sat(half4);
char4 __ovld __cnfn convert_char4_sat_rte(half4);
char4 __ovld __cnfn convert_char4_sat_rtp(half4);
char4 __ovld __cnfn convert_char4_sat_rtn(half4);
char4 __ovld __cnfn convert_char4_sat_rtz(half4);
char8 __ovld __cnfn convert_char8(half8);
char8 __ovld __cnfn convert_char8_rte(half8);
char8 __ovld __cnfn convert_char8_rtp(half8);
char8 __ovld __cnfn convert_char8_rtn(half8);
char8 __ovld __cnfn convert_char8_rtz(half8);
char8 __ovld __cnfn convert_char8_sat(half8);
char8 __ovld __cnfn convert_char8_sat_rte(half8);
char8 __ovld __cnfn convert_char8_sat_rtp(half8);
char8 __ovld __cnfn convert_char8_sat_rtn(half8);
char8 __ovld __cnfn convert_char8_sat_rtz(half8);
char16 __ovld __cnfn convert_char16(half16);
char16 __ovld __cnfn convert_char16_rte(half16);
char16 __ovld __cnfn convert_char16_rtp(half16);
char16 __ovld __cnfn convert_char16_rtn(half16);
char16 __ovld __cnfn convert_char16_rtz(half16);
char16 __ovld __cnfn convert_char16_sat(half16);
char16 __ovld __cnfn convert_char16_sat_rte(half16);
char16 __ovld __cnfn convert_char16_sat_rtp(half16);
char16 __ovld __cnfn convert_char16_sat_rtn(half16);
char16 __ovld __cnfn convert_char16_sat_rtz(half16);
short __ovld __cnfn convert_short(half);
short __ovld __cnfn convert_short_rte(half);
short __ovld __cnfn convert_short_rtp(half);
short __ovld __cnfn convert_short_rtn(half);
short __ovld __cnfn convert_short_rtz(half);
short __ovld __cnfn convert_short_sat(half);
short __ovld __cnfn convert_short_sat_rte(half);
short __ovld __cnfn convert_short_sat_rtp(half);
short __ovld __cnfn convert_short_sat_rtn(half);
short __ovld __cnfn convert_short_sat_rtz(half);
short2 __ovld __cnfn convert_short2(half2);
short2 __ovld __cnfn convert_short2_rte(half2);
short2 __ovld __cnfn convert_short2_rtp(half2);
short2 __ovld __cnfn convert_short2_rtn(half2);
short2 __ovld __cnfn convert_short2_rtz(half2);
short2 __ovld __cnfn convert_short2_sat(half2);
short2 __ovld __cnfn convert_short2_sat_rte(half2);
short2 __ovld __cnfn convert_short2_sat_rtp(half2);
short2 __ovld __cnfn convert_short2_sat_rtn(half2);
short2 __ovld __cnfn convert_short2_sat_rtz(half2);
short3 __ovld __cnfn convert_short3(half3);
short3 __ovld __cnfn convert_short3_rte(half3);
short3 __ovld __cnfn convert_short3_rtp(half3);
short3 __ovld __cnfn convert_short3_rtn(half3);
short3 __ovld __cnfn convert_short3_rtz(half3);
short3 __ovld __cnfn convert_short3_sat(half3);
short3 __ovld __cnfn convert_short3_sat_rte(half3);
short3 __ovld __cnfn convert_short3_sat_rtp(half3);
short3 __ovld __cnfn convert_short3_sat_rtn(half3);
short3 __ovld __cnfn convert_short3_sat_rtz(half3);
short4 __ovld __cnfn convert_short4(half4);
short4 __ovld __cnfn convert_short4_rte(half4);
short4 __ovld __cnfn convert_short4_rtp(half4);
short4 __ovld __cnfn convert_short4_rtn(half4);
short4 __ovld __cnfn convert_short4_rtz(half4);
short4 __ovld __cnfn convert_short4_sat(half4);
short4 __ovld __cnfn convert_short4_sat_rte(half4);
short4 __ovld __cnfn convert_short4_sat_rtp(half4);
short4 __ovld __cnfn convert_short4_sat_rtn(half4);
short4 __ovld __cnfn convert_short4_sat_rtz(half4);
short8 __ovld __cnfn convert_short8(half8);
short8 __ovld __cnfn convert_short8_rte(half8);
short8 __ovld __cnfn convert_short8_rtp(half8);
short8 __ovld __cnfn convert_short8_rtn(half8);
short8 __ovld __cnfn convert_short8_rtz(half8);
short8 __ovld __cnfn convert_short8_sat(half8);
short8 __ovld __cnfn convert_short8_sat_rte(half8);
short8 __ovld __cnfn convert_short8_sat_rtp(half8);
short8 __ovld __cnfn convert_short8_sat_rtn(half8);
short8 __ovld __cnfn convert_short8_sat_rtz(half8);
short16 __ovld __cnfn convert_short16(half16);
short16 __ovld __cnfn convert_short16_rte(half16);
short16 __ovld __cnfn convert_short16_rtp(half16);
short16 __ovld __cnfn convert_short16_rtn(half16);
short16 __ovld __cnfn convert_short16_rtz(half16);
short16 __ovld __cnfn convert_short16_sat(half16);
short16 __ovld __cnfn convert_short16_sat_rte(half16);
short16 __ovld __cnfn convert_short16_sat_rtp(half16);
short16 __ovld __cnfn convert_short16_sat_rtn(half16);
short16 __ovld __cnfn convert_short16_sat_rtz(half16);
int __ovld __cnfn convert_int(half);
int __ovld __cnfn convert_int_rte(half);
int __ovld __cnfn convert_int_rtp(half);
int __ovld __cnfn convert_int_rtn(half);
int __ovld __cnfn convert_int_rtz(half);
int __ovld __cnfn convert_int_sat(half);
int __ovld __cnfn convert_int_sat_rte(half);
int __ovld __cnfn convert_int_sat_rtp(half);
int __ovld __cnfn convert_int_sat_rtn(half);
int __ovld __cnfn convert_int_sat_rtz(half);
int2 __ovld __cnfn convert_int2(half2);
int2 __ovld __cnfn convert_int2_rte(half2);
int2 __ovld __cnfn convert_int2_rtp(half2);
int2 __ovld __cnfn convert_int2_rtn(half2);
int2 __ovld __cnfn convert_int2_rtz(half2);
int2 __ovld __cnfn convert_int2_sat(half2);
int2 __ovld __cnfn convert_int2_sat_rte(half2);
int2 __ovld __cnfn convert_int2_sat_rtp(half2);
int2 __ovld __cnfn convert_int2_sat_rtn(half2);
int2 __ovld __cnfn convert_int2_sat_rtz(half2);
int3 __ovld __cnfn convert_int3(half3);
int3 __ovld __cnfn convert_int3_rte(half3);
int3 __ovld __cnfn convert_int3_rtp(half3);
int3 __ovld __cnfn convert_int3_rtn(half3);
int3 __ovld __cnfn convert_int3_rtz(half3);
int3 __ovld __cnfn convert_int3_sat(half3);
int3 __ovld __cnfn convert_int3_sat_rte(half3);
int3 __ovld __cnfn convert_int3_sat_rtp(half3);
int3 __ovld __cnfn convert_int3_sat_rtn(half3);
int3 __ovld __cnfn convert_int3_sat_rtz(half3);
int4 __ovld __cnfn convert_int4(half4);
int4 __ovld __cnfn convert_int4_rte(half4);
int4 __ovld __cnfn convert_int4_rtp(half4);
int4 __ovld __cnfn convert_int4_rtn(half4);
int4 __ovld __cnfn convert_int4_rtz(half4);
int4 __ovld __cnfn convert_int4_sat(half4);
int4 __ovld __cnfn convert_int4_sat_rte(half4);
int4 __ovld __cnfn convert_int4_sat_rtp(half4);
int4 __ovld __cnfn convert_int4_sat_rtn(half4);
int4 __ovld __cnfn convert_int4_sat_rtz(half4);
int8 __ovld __cnfn convert_int8(half8);
int8 __ovld __cnfn convert_int8_rte(half8);
int8 __ovld __cnfn convert_int8_rtp(half8);
int8 __ovld __cnfn convert_int8_rtn(half8);
int8 __ovld __cnfn convert_int8_rtz(half8);
int8 __ovld __cnfn convert_int8_sat(half8);
int8 __ovld __cnfn convert_int8_sat_rte(half8);
int8 __ovld __cnfn convert_int8_sat_rtp(half8);
int8 __ovld __cnfn convert_int8_sat_rtn(half8);
int8 __ovld __cnfn convert_int8_sat_rtz(half8);
int16 __ovld __cnfn convert_int16(half16);
int16 __ovld __cnfn convert_int16_rte(half16);
int16 __ovld __cnfn convert_int16_rtp(half16);
int16 __ovld __cnfn convert_int16_rtn(half16);
int16 __ovld __cnfn convert_int16_rtz(half16);
int16 __ovld __cnfn convert_int16_sat(half16);
int16 __ovld __cnfn convert_int16_sat_rte(half16);
int16 __ovld __cnfn convert_int16_sat_rtp(half16);
int16 __ovld __cnfn convert_int16_sat_rtn(half16);
int16 __ovld __cnfn convert_int16_sat_rtz(half16);
long __ovld __cnfn convert_long(half);
long __ovld __cnfn convert_long_rte(half);
long __ovld __cnfn convert_long_rtp(half);
long __ovld __cnfn convert_long_rtn(half);
long __ovld __cnfn convert_long_rtz(half);
long __ovld __cnfn convert_long_sat(half);
long __ovld __cnfn convert_long_sat_rte(half);
long __ovld __cnfn convert_long_sat_rtp(half);
long __ovld __cnfn convert_long_sat_rtn(half);
long __ovld __cnfn convert_long_sat_rtz(half);
long2 __ovld __cnfn convert_long2(half2);
long2 __ovld __cnfn convert_long2_rte(half2);
long2 __ovld __cnfn convert_long2_rtp(half2);
long2 __ovld __cnfn convert_long2_rtn(half2);
long2 __ovld __cnfn convert_long2_rtz(half2);
long2 __ovld __cnfn convert_long2_sat(half2);
long2 __ovld __cnfn convert_long2_sat_rte(half2);
long2 __ovld __cnfn convert_long2_sat_rtp(half2);
long2 __ovld __cnfn convert_long2_sat_rtn(half2);
long2 __ovld __cnfn convert_long2_sat_rtz(half2);
long3 __ovld __cnfn convert_long3(half3);
long3 __ovld __cnfn convert_long3_rte(half3);
long3 __ovld __cnfn convert_long3_rtp(half3);
long3 __ovld __cnfn convert_long3_rtn(half3);
long3 __ovld __cnfn convert_long3_rtz(half3);
long3 __ovld __cnfn convert_long3_sat(half3);
long3 __ovld __cnfn convert_long3_sat_rte(half3);
long3 __ovld __cnfn convert_long3_sat_rtp(half3);
long3 __ovld __cnfn convert_long3_sat_rtn(half3);
long3 __ovld __cnfn convert_long3_sat_rtz(half3);
long4 __ovld __cnfn convert_long4(half4);
long4 __ovld __cnfn convert_long4_rte(half4);
long4 __ovld __cnfn convert_long4_rtp(half4);
long4 __ovld __cnfn convert_long4_rtn(half4);
long4 __ovld __cnfn convert_long4_rtz(half4);
long4 __ovld __cnfn convert_long4_sat(half4);
long4 __ovld __cnfn convert_long4_sat_rte(half4);
long4 __ovld __cnfn convert_long4_sat_rtp(half4);
long4 __ovld __cnfn convert_long4_sat_rtn(half4);
long4 __ovld __cnfn convert_long4_sat_rtz(half4);
long8 __ovld __cnfn convert_long8(half8);
long8 __ovld __cnfn convert_long8_rte(half8);
long8 __ovld __cnfn convert_long8_rtp(half8);
long8 __ovld __cnfn convert_long8_rtn(half8);
long8 __ovld __cnfn convert_long8_rtz(half8);
long8 __ovld __cnfn convert_long8_sat(half8);
long8 __ovld __cnfn convert_long8_sat_rte(half8);
long8 __ovld __cnfn convert_long8_sat_rtp(half8);
long8 __ovld __cnfn convert_long8_sat_rtn(half8);
long8 __ovld __cnfn convert_long8_sat_rtz(half8);
long16 __ovld __cnfn convert_long16(half16);
long16 __ovld __cnfn convert_long16_rte(half16);
long16 __ovld __cnfn convert_long16_rtp(half16);
long16 __ovld __cnfn convert_long16_rtn(half16);
long16 __ovld __cnfn convert_long16_rtz(half16);
long16 __ovld __cnfn convert_long16_sat(half16);
long16 __ovld __cnfn convert_long16_sat_rte(half16);
long16 __ovld __cnfn convert_long16_sat_rtp(half16);
long16 __ovld __cnfn convert_long16_sat_rtn(half16);
long16 __ovld __cnfn convert_long16_sat_rtz(half16);
float __ovld __cnfn convert_float(half);
float __ovld __cnfn convert_float_rte(half);
float __ovld __cnfn convert_float_rtp(half);
float __ovld __cnfn convert_float_rtn(half);
float __ovld __cnfn convert_float_rtz(half);
float2 __ovld __cnfn convert_float2(half2);
float2 __ovld __cnfn convert_float2_rte(half2);
float2 __ovld __cnfn convert_float2_rtp(half2);
float2 __ovld __cnfn convert_float2_rtn(half2);
float2 __ovld __cnfn convert_float2_rtz(half2);
float3 __ovld __cnfn convert_float3(half3);
float3 __ovld __cnfn convert_float3_rte(half3);
float3 __ovld __cnfn convert_float3_rtp(half3);
float3 __ovld __cnfn convert_float3_rtn(half3);
float3 __ovld __cnfn convert_float3_rtz(half3);
float4 __ovld __cnfn convert_float4(half4);
float4 __ovld __cnfn convert_float4_rte(half4);
float4 __ovld __cnfn convert_float4_rtp(half4);
float4 __ovld __cnfn convert_float4_rtn(half4);
float4 __ovld __cnfn convert_float4_rtz(half4);
float8 __ovld __cnfn convert_float8(half8);
float8 __ovld __cnfn convert_float8_rte(half8);
float8 __ovld __cnfn convert_float8_rtp(half8);
float8 __ovld __cnfn convert_float8_rtn(half8);
float8 __ovld __cnfn convert_float8_rtz(half8);
float16 __ovld __cnfn convert_float16(half16);
float16 __ovld __cnfn convert_float16_rte(half16);
float16 __ovld __cnfn convert_float16_rtp(half16);
float16 __ovld __cnfn convert_float16_rtn(half16);
float16 __ovld __cnfn convert_float16_rtz(half16);
// Convert non-double types to half types.
half __ovld __cnfn convert_half(uchar);
half __ovld __cnfn convert_half(ushort);
half __ovld __cnfn convert_half(uint);
half __ovld __cnfn convert_half(ulong);
half __ovld __cnfn convert_half(char);
half __ovld __cnfn convert_half(short);
half __ovld __cnfn convert_half(int);
half __ovld __cnfn convert_half(long);
half __ovld __cnfn convert_half(float);
half __ovld __cnfn convert_half(half);
half __ovld __cnfn convert_half_rte(uchar);
half __ovld __cnfn convert_half_rte(ushort);
half __ovld __cnfn convert_half_rte(uint);
half __ovld __cnfn convert_half_rte(ulong);
half __ovld __cnfn convert_half_rte(char);
half __ovld __cnfn convert_half_rte(short);
half __ovld __cnfn convert_half_rte(int);
half __ovld __cnfn convert_half_rte(long);
half __ovld __cnfn convert_half_rte(float);
half __ovld __cnfn convert_half_rte(half);
half __ovld __cnfn convert_half_rtp(uchar);
half __ovld __cnfn convert_half_rtp(ushort);
half __ovld __cnfn convert_half_rtp(uint);
half __ovld __cnfn convert_half_rtp(ulong);
half __ovld __cnfn convert_half_rtp(char);
half __ovld __cnfn convert_half_rtp(short);
half __ovld __cnfn convert_half_rtp(int);
half __ovld __cnfn convert_half_rtp(long);
half __ovld __cnfn convert_half_rtp(float);
half __ovld __cnfn convert_half_rtp(half);
half __ovld __cnfn convert_half_rtn(uchar);
half __ovld __cnfn convert_half_rtn(ushort);
half __ovld __cnfn convert_half_rtn(uint);
half __ovld __cnfn convert_half_rtn(ulong);
half __ovld __cnfn convert_half_rtn(char);
half __ovld __cnfn convert_half_rtn(short);
half __ovld __cnfn convert_half_rtn(int);
half __ovld __cnfn convert_half_rtn(long);
half __ovld __cnfn convert_half_rtn(float);
half __ovld __cnfn convert_half_rtn(half);
half __ovld __cnfn convert_half_rtz(uchar);
half __ovld __cnfn convert_half_rtz(ushort);
half __ovld __cnfn convert_half_rtz(uint);
half __ovld __cnfn convert_half_rtz(ulong);
half __ovld __cnfn convert_half_rtz(char);
half __ovld __cnfn convert_half_rtz(short);
half __ovld __cnfn convert_half_rtz(int);
half __ovld __cnfn convert_half_rtz(long);
half __ovld __cnfn convert_half_rtz(float);
half __ovld __cnfn convert_half_rtz(half);
half2 __ovld __cnfn convert_half2(char2);
half2 __ovld __cnfn convert_half2(uchar2);
half2 __ovld __cnfn convert_half2(short2);
half2 __ovld __cnfn convert_half2(ushort2);
half2 __ovld __cnfn convert_half2(int2);
half2 __ovld __cnfn convert_half2(uint2);
half2 __ovld __cnfn convert_half2(long2);
half2 __ovld __cnfn convert_half2(ulong2);
half2 __ovld __cnfn convert_half2(float2);
half2 __ovld __cnfn convert_half2(half2);
half2 __ovld __cnfn convert_half2_rte(char2);
half2 __ovld __cnfn convert_half2_rte(uchar2);
half2 __ovld __cnfn convert_half2_rte(short2);
half2 __ovld __cnfn convert_half2_rte(ushort2);
half2 __ovld __cnfn convert_half2_rte(int2);
half2 __ovld __cnfn convert_half2_rte(uint2);
half2 __ovld __cnfn convert_half2_rte(long2);
half2 __ovld __cnfn convert_half2_rte(ulong2);
half2 __ovld __cnfn convert_half2_rte(float2);
half2 __ovld __cnfn convert_half2_rte(half2);
half2 __ovld __cnfn convert_half2_rtp(char2);
half2 __ovld __cnfn convert_half2_rtp(uchar2);
half2 __ovld __cnfn convert_half2_rtp(short2);
half2 __ovld __cnfn convert_half2_rtp(ushort2);
half2 __ovld __cnfn convert_half2_rtp(int2);
half2 __ovld __cnfn convert_half2_rtp(uint2);
half2 __ovld __cnfn convert_half2_rtp(long2);
half2 __ovld __cnfn convert_half2_rtp(ulong2);
half2 __ovld __cnfn convert_half2_rtp(float2);
half2 __ovld __cnfn convert_half2_rtp(half2);
half2 __ovld __cnfn convert_half2_rtn(char2);
half2 __ovld __cnfn convert_half2_rtn(uchar2);
half2 __ovld __cnfn convert_half2_rtn(short2);
half2 __ovld __cnfn convert_half2_rtn(ushort2);
half2 __ovld __cnfn convert_half2_rtn(int2);
half2 __ovld __cnfn convert_half2_rtn(uint2);
half2 __ovld __cnfn convert_half2_rtn(long2);
half2 __ovld __cnfn convert_half2_rtn(ulong2);
half2 __ovld __cnfn convert_half2_rtn(float2);
half2 __ovld __cnfn convert_half2_rtn(half2);
half2 __ovld __cnfn convert_half2_rtz(char2);
half2 __ovld __cnfn convert_half2_rtz(uchar2);
half2 __ovld __cnfn convert_half2_rtz(short2);
half2 __ovld __cnfn convert_half2_rtz(ushort2);
half2 __ovld __cnfn convert_half2_rtz(int2);
half2 __ovld __cnfn convert_half2_rtz(uint2);
half2 __ovld __cnfn convert_half2_rtz(long2);
half2 __ovld __cnfn convert_half2_rtz(ulong2);
half2 __ovld __cnfn convert_half2_rtz(float2);
half2 __ovld __cnfn convert_half2_rtz(half2);
half3 __ovld __cnfn convert_half3(char3);
half3 __ovld __cnfn convert_half3(uchar3);
half3 __ovld __cnfn convert_half3(short3);
half3 __ovld __cnfn convert_half3(ushort3);
half3 __ovld __cnfn convert_half3(int3);
half3 __ovld __cnfn convert_half3(uint3);
half3 __ovld __cnfn convert_half3(long3);
half3 __ovld __cnfn convert_half3(ulong3);
half3 __ovld __cnfn convert_half3(float3);
half3 __ovld __cnfn convert_half3(half3);
half3 __ovld __cnfn convert_half3_rte(char3);
half3 __ovld __cnfn convert_half3_rte(uchar3);
half3 __ovld __cnfn convert_half3_rte(short3);
half3 __ovld __cnfn convert_half3_rte(ushort3);
half3 __ovld __cnfn convert_half3_rte(int3);
half3 __ovld __cnfn convert_half3_rte(uint3);
half3 __ovld __cnfn convert_half3_rte(long3);
half3 __ovld __cnfn convert_half3_rte(ulong3);
half3 __ovld __cnfn convert_half3_rte(float3);
half3 __ovld __cnfn convert_half3_rte(half3);
half3 __ovld __cnfn convert_half3_rtp(char3);
half3 __ovld __cnfn convert_half3_rtp(uchar3);
half3 __ovld __cnfn convert_half3_rtp(short3);
half3 __ovld __cnfn convert_half3_rtp(ushort3);
half3 __ovld __cnfn convert_half3_rtp(int3);
half3 __ovld __cnfn convert_half3_rtp(uint3);
half3 __ovld __cnfn convert_half3_rtp(long3);
half3 __ovld __cnfn convert_half3_rtp(ulong3);
half3 __ovld __cnfn convert_half3_rtp(float3);
half3 __ovld __cnfn convert_half3_rtp(half3);
half3 __ovld __cnfn convert_half3_rtn(char3);
half3 __ovld __cnfn convert_half3_rtn(uchar3);
half3 __ovld __cnfn convert_half3_rtn(short3);
half3 __ovld __cnfn convert_half3_rtn(ushort3);
half3 __ovld __cnfn convert_half3_rtn(int3);
half3 __ovld __cnfn convert_half3_rtn(uint3);
half3 __ovld __cnfn convert_half3_rtn(long3);
half3 __ovld __cnfn convert_half3_rtn(ulong3);
half3 __ovld __cnfn convert_half3_rtn(float3);
half3 __ovld __cnfn convert_half3_rtn(half3);
half3 __ovld __cnfn convert_half3_rtz(char3);
half3 __ovld __cnfn convert_half3_rtz(uchar3);
half3 __ovld __cnfn convert_half3_rtz(short3);
half3 __ovld __cnfn convert_half3_rtz(ushort3);
half3 __ovld __cnfn convert_half3_rtz(int3);
half3 __ovld __cnfn convert_half3_rtz(uint3);
half3 __ovld __cnfn convert_half3_rtz(long3);
half3 __ovld __cnfn convert_half3_rtz(ulong3);
half3 __ovld __cnfn convert_half3_rtz(float3);
half3 __ovld __cnfn convert_half3_rtz(half3);
half4 __ovld __cnfn convert_half4(char4);
half4 __ovld __cnfn convert_half4(uchar4);
half4 __ovld __cnfn convert_half4(short4);
half4 __ovld __cnfn convert_half4(ushort4);
half4 __ovld __cnfn convert_half4(int4);
half4 __ovld __cnfn convert_half4(uint4);
half4 __ovld __cnfn convert_half4(long4);
half4 __ovld __cnfn convert_half4(ulong4);
half4 __ovld __cnfn convert_half4(float4);
half4 __ovld __cnfn convert_half4(half4);
half4 __ovld __cnfn convert_half4_rte(char4);
half4 __ovld __cnfn convert_half4_rte(uchar4);
half4 __ovld __cnfn convert_half4_rte(short4);
half4 __ovld __cnfn convert_half4_rte(ushort4);
half4 __ovld __cnfn convert_half4_rte(int4);
half4 __ovld __cnfn convert_half4_rte(uint4);
half4 __ovld __cnfn convert_half4_rte(long4);
half4 __ovld __cnfn convert_half4_rte(ulong4);
half4 __ovld __cnfn convert_half4_rte(float4);
half4 __ovld __cnfn convert_half4_rte(half4);
half4 __ovld __cnfn convert_half4_rtp(char4);
half4 __ovld __cnfn convert_half4_rtp(uchar4);
half4 __ovld __cnfn convert_half4_rtp(short4);
half4 __ovld __cnfn convert_half4_rtp(ushort4);
half4 __ovld __cnfn convert_half4_rtp(int4);
half4 __ovld __cnfn convert_half4_rtp(uint4);
half4 __ovld __cnfn convert_half4_rtp(long4);
half4 __ovld __cnfn convert_half4_rtp(ulong4);
half4 __ovld __cnfn convert_half4_rtp(float4);
half4 __ovld __cnfn convert_half4_rtp(half4);
half4 __ovld __cnfn convert_half4_rtn(char4);
half4 __ovld __cnfn convert_half4_rtn(uchar4);
half4 __ovld __cnfn convert_half4_rtn(short4);
half4 __ovld __cnfn convert_half4_rtn(ushort4);
half4 __ovld __cnfn convert_half4_rtn(int4);
half4 __ovld __cnfn convert_half4_rtn(uint4);
half4 __ovld __cnfn convert_half4_rtn(long4);
half4 __ovld __cnfn convert_half4_rtn(ulong4);
half4 __ovld __cnfn convert_half4_rtn(float4);
half4 __ovld __cnfn convert_half4_rtn(half4);
half4 __ovld __cnfn convert_half4_rtz(char4);
half4 __ovld __cnfn convert_half4_rtz(uchar4);
half4 __ovld __cnfn convert_half4_rtz(short4);
half4 __ovld __cnfn convert_half4_rtz(ushort4);
half4 __ovld __cnfn convert_half4_rtz(int4);
half4 __ovld __cnfn convert_half4_rtz(uint4);
half4 __ovld __cnfn convert_half4_rtz(long4);
half4 __ovld __cnfn convert_half4_rtz(ulong4);
half4 __ovld __cnfn convert_half4_rtz(float4);
half4 __ovld __cnfn convert_half4_rtz(half4);
half8 __ovld __cnfn convert_half8(char8);
half8 __ovld __cnfn convert_half8(uchar8);
half8 __ovld __cnfn convert_half8(short8);
half8 __ovld __cnfn convert_half8(ushort8);
half8 __ovld __cnfn convert_half8(int8);
half8 __ovld __cnfn convert_half8(uint8);
half8 __ovld __cnfn convert_half8(long8);
half8 __ovld __cnfn convert_half8(ulong8);
half8 __ovld __cnfn convert_half8(float8);
half8 __ovld __cnfn convert_half8(half8);
half8 __ovld __cnfn convert_half8_rte(char8);
half8 __ovld __cnfn convert_half8_rte(uchar8);
half8 __ovld __cnfn convert_half8_rte(short8);
half8 __ovld __cnfn convert_half8_rte(ushort8);
half8 __ovld __cnfn convert_half8_rte(int8);
half8 __ovld __cnfn convert_half8_rte(uint8);
half8 __ovld __cnfn convert_half8_rte(long8);
half8 __ovld __cnfn convert_half8_rte(ulong8);
half8 __ovld __cnfn convert_half8_rte(float8);
half8 __ovld __cnfn convert_half8_rte(half8);
half8 __ovld __cnfn convert_half8_rtp(char8);
half8 __ovld __cnfn convert_half8_rtp(uchar8);
half8 __ovld __cnfn convert_half8_rtp(short8);
half8 __ovld __cnfn convert_half8_rtp(ushort8);
half8 __ovld __cnfn convert_half8_rtp(int8);
half8 __ovld __cnfn convert_half8_rtp(uint8);
half8 __ovld __cnfn convert_half8_rtp(long8);
half8 __ovld __cnfn convert_half8_rtp(ulong8);
half8 __ovld __cnfn convert_half8_rtp(float8);
half8 __ovld __cnfn convert_half8_rtp(half8);
half8 __ovld __cnfn convert_half8_rtn(char8);
half8 __ovld __cnfn convert_half8_rtn(uchar8);
half8 __ovld __cnfn convert_half8_rtn(short8);
half8 __ovld __cnfn convert_half8_rtn(ushort8);
half8 __ovld __cnfn convert_half8_rtn(int8);
half8 __ovld __cnfn convert_half8_rtn(uint8);
half8 __ovld __cnfn convert_half8_rtn(long8);
half8 __ovld __cnfn convert_half8_rtn(ulong8);
half8 __ovld __cnfn convert_half8_rtn(float8);
half8 __ovld __cnfn convert_half8_rtn(half8);
half8 __ovld __cnfn convert_half8_rtz(char8);
half8 __ovld __cnfn convert_half8_rtz(uchar8);
half8 __ovld __cnfn convert_half8_rtz(short8);
half8 __ovld __cnfn convert_half8_rtz(ushort8);
half8 __ovld __cnfn convert_half8_rtz(int8);
half8 __ovld __cnfn convert_half8_rtz(uint8);
half8 __ovld __cnfn convert_half8_rtz(long8);
half8 __ovld __cnfn convert_half8_rtz(ulong8);
half8 __ovld __cnfn convert_half8_rtz(float8);
half8 __ovld __cnfn convert_half8_rtz(half8);
half16 __ovld __cnfn convert_half16(char16);
half16 __ovld __cnfn convert_half16(uchar16);
half16 __ovld __cnfn convert_half16(short16);
half16 __ovld __cnfn convert_half16(ushort16);
half16 __ovld __cnfn convert_half16(int16);
half16 __ovld __cnfn convert_half16(uint16);
half16 __ovld __cnfn convert_half16(long16);
half16 __ovld __cnfn convert_half16(ulong16);
half16 __ovld __cnfn convert_half16(float16);
half16 __ovld __cnfn convert_half16(half16);
half16 __ovld __cnfn convert_half16_rte(char16);
half16 __ovld __cnfn convert_half16_rte(uchar16);
half16 __ovld __cnfn convert_half16_rte(short16);
half16 __ovld __cnfn convert_half16_rte(ushort16);
half16 __ovld __cnfn convert_half16_rte(int16);
half16 __ovld __cnfn convert_half16_rte(uint16);
half16 __ovld __cnfn convert_half16_rte(long16);
half16 __ovld __cnfn convert_half16_rte(ulong16);
half16 __ovld __cnfn convert_half16_rte(float16);
half16 __ovld __cnfn convert_half16_rte(half16);
half16 __ovld __cnfn convert_half16_rtp(char16);
half16 __ovld __cnfn convert_half16_rtp(uchar16);
half16 __ovld __cnfn convert_half16_rtp(short16);
half16 __ovld __cnfn convert_half16_rtp(ushort16);
half16 __ovld __cnfn convert_half16_rtp(int16);
half16 __ovld __cnfn convert_half16_rtp(uint16);
half16 __ovld __cnfn convert_half16_rtp(long16);
half16 __ovld __cnfn convert_half16_rtp(ulong16);
half16 __ovld __cnfn convert_half16_rtp(float16);
half16 __ovld __cnfn convert_half16_rtp(half16);
half16 __ovld __cnfn convert_half16_rtn(char16);
half16 __ovld __cnfn convert_half16_rtn(uchar16);
half16 __ovld __cnfn convert_half16_rtn(short16);
half16 __ovld __cnfn convert_half16_rtn(ushort16);
half16 __ovld __cnfn convert_half16_rtn(int16);
half16 __ovld __cnfn convert_half16_rtn(uint16);
half16 __ovld __cnfn convert_half16_rtn(long16);
half16 __ovld __cnfn convert_half16_rtn(ulong16);
half16 __ovld __cnfn convert_half16_rtn(float16);
half16 __ovld __cnfn convert_half16_rtn(half16);
half16 __ovld __cnfn convert_half16_rtz(char16);
half16 __ovld __cnfn convert_half16_rtz(uchar16);
half16 __ovld __cnfn convert_half16_rtz(short16);
half16 __ovld __cnfn convert_half16_rtz(ushort16);
half16 __ovld __cnfn convert_half16_rtz(int16);
half16 __ovld __cnfn convert_half16_rtz(uint16);
half16 __ovld __cnfn convert_half16_rtz(long16);
half16 __ovld __cnfn convert_half16_rtz(ulong16);
half16 __ovld __cnfn convert_half16_rtz(float16);
half16 __ovld __cnfn convert_half16_rtz(half16);
// Convert half types to double types.
#ifdef cl_khr_fp64
double __ovld __cnfn convert_double(half);
double __ovld __cnfn convert_double_rte(half);
double __ovld __cnfn convert_double_rtp(half);
double __ovld __cnfn convert_double_rtn(half);
double __ovld __cnfn convert_double_rtz(half);
double2 __ovld __cnfn convert_double2(half2);
double2 __ovld __cnfn convert_double2_rte(half2);
double2 __ovld __cnfn convert_double2_rtp(half2);
double2 __ovld __cnfn convert_double2_rtn(half2);
double2 __ovld __cnfn convert_double2_rtz(half2);
double3 __ovld __cnfn convert_double3(half3);
double3 __ovld __cnfn convert_double3_rte(half3);
double3 __ovld __cnfn convert_double3_rtp(half3);
double3 __ovld __cnfn convert_double3_rtn(half3);
double3 __ovld __cnfn convert_double3_rtz(half3);
double4 __ovld __cnfn convert_double4(half4);
double4 __ovld __cnfn convert_double4_rte(half4);
double4 __ovld __cnfn convert_double4_rtp(half4);
double4 __ovld __cnfn convert_double4_rtn(half4);
double4 __ovld __cnfn convert_double4_rtz(half4);
double8 __ovld __cnfn convert_double8(half8);
double8 __ovld __cnfn convert_double8_rte(half8);
double8 __ovld __cnfn convert_double8_rtp(half8);
double8 __ovld __cnfn convert_double8_rtn(half8);
double8 __ovld __cnfn convert_double8_rtz(half8);
double16 __ovld __cnfn convert_double16(half16);
double16 __ovld __cnfn convert_double16_rte(half16);
double16 __ovld __cnfn convert_double16_rtp(half16);
double16 __ovld __cnfn convert_double16_rtn(half16);
double16 __ovld __cnfn convert_double16_rtz(half16);
// Convert double types to half types.
half __ovld __cnfn convert_half(double);
half __ovld __cnfn convert_half_rte(double);
half __ovld __cnfn convert_half_rtp(double);
half __ovld __cnfn convert_half_rtn(double);
half __ovld __cnfn convert_half_rtz(double);
half2 __ovld __cnfn convert_half2(double2);
half2 __ovld __cnfn convert_half2_rte(double2);
half2 __ovld __cnfn convert_half2_rtp(double2);
half2 __ovld __cnfn convert_half2_rtn(double2);
half2 __ovld __cnfn convert_half2_rtz(double2);
half3 __ovld __cnfn convert_half3(double3);
half3 __ovld __cnfn convert_half3_rte(double3);
half3 __ovld __cnfn convert_half3_rtp(double3);
half3 __ovld __cnfn convert_half3_rtn(double3);
half3 __ovld __cnfn convert_half3_rtz(double3);
half4 __ovld __cnfn convert_half4(double4);
half4 __ovld __cnfn convert_half4_rte(double4);
half4 __ovld __cnfn convert_half4_rtp(double4);
half4 __ovld __cnfn convert_half4_rtn(double4);
half4 __ovld __cnfn convert_half4_rtz(double4);
half8 __ovld __cnfn convert_half8(double8);
half8 __ovld __cnfn convert_half8_rte(double8);
half8 __ovld __cnfn convert_half8_rtp(double8);
half8 __ovld __cnfn convert_half8_rtn(double8);
half8 __ovld __cnfn convert_half8_rtz(double8);
half16 __ovld __cnfn convert_half16(double16);
half16 __ovld __cnfn convert_half16_rte(double16);
half16 __ovld __cnfn convert_half16_rtp(double16);
half16 __ovld __cnfn convert_half16_rtn(double16);
half16 __ovld __cnfn convert_half16_rtz(double16);
#endif //cl_khr_fp64
#endif // cl_khr_fp16
/**
* OpenCL v1.1/1.2/2.0 s6.2.4.2 - as_type operators
* Reinterprets a data type as another data type of the same size
*/
#define as_char(x) __builtin_astype((x), char)
#define as_char2(x) __builtin_astype((x), char2)
#define as_char3(x) __builtin_astype((x), char3)
#define as_char4(x) __builtin_astype((x), char4)
#define as_char8(x) __builtin_astype((x), char8)
#define as_char16(x) __builtin_astype((x), char16)
#define as_uchar(x) __builtin_astype((x), uchar)
#define as_uchar2(x) __builtin_astype((x), uchar2)
#define as_uchar3(x) __builtin_astype((x), uchar3)
#define as_uchar4(x) __builtin_astype((x), uchar4)
#define as_uchar8(x) __builtin_astype((x), uchar8)
#define as_uchar16(x) __builtin_astype((x), uchar16)
#define as_short(x) __builtin_astype((x), short)
#define as_short2(x) __builtin_astype((x), short2)
#define as_short3(x) __builtin_astype((x), short3)
#define as_short4(x) __builtin_astype((x), short4)
#define as_short8(x) __builtin_astype((x), short8)
#define as_short16(x) __builtin_astype((x), short16)
#define as_ushort(x) __builtin_astype((x), ushort)
#define as_ushort2(x) __builtin_astype((x), ushort2)
#define as_ushort3(x) __builtin_astype((x), ushort3)
#define as_ushort4(x) __builtin_astype((x), ushort4)
#define as_ushort8(x) __builtin_astype((x), ushort8)
#define as_ushort16(x) __builtin_astype((x), ushort16)
#define as_int(x) __builtin_astype((x), int)
#define as_int2(x) __builtin_astype((x), int2)
#define as_int3(x) __builtin_astype((x), int3)
#define as_int4(x) __builtin_astype((x), int4)
#define as_int8(x) __builtin_astype((x), int8)
#define as_int16(x) __builtin_astype((x), int16)
#define as_uint(x) __builtin_astype((x), uint)
#define as_uint2(x) __builtin_astype((x), uint2)
#define as_uint3(x) __builtin_astype((x), uint3)
#define as_uint4(x) __builtin_astype((x), uint4)
#define as_uint8(x) __builtin_astype((x), uint8)
#define as_uint16(x) __builtin_astype((x), uint16)
#define as_long(x) __builtin_astype((x), long)
#define as_long2(x) __builtin_astype((x), long2)
#define as_long3(x) __builtin_astype((x), long3)
#define as_long4(x) __builtin_astype((x), long4)
#define as_long8(x) __builtin_astype((x), long8)
#define as_long16(x) __builtin_astype((x), long16)
#define as_ulong(x) __builtin_astype((x), ulong)
#define as_ulong2(x) __builtin_astype((x), ulong2)
#define as_ulong3(x) __builtin_astype((x), ulong3)
#define as_ulong4(x) __builtin_astype((x), ulong4)
#define as_ulong8(x) __builtin_astype((x), ulong8)
#define as_ulong16(x) __builtin_astype((x), ulong16)
#define as_float(x) __builtin_astype((x), float)
#define as_float2(x) __builtin_astype((x), float2)
#define as_float3(x) __builtin_astype((x), float3)
#define as_float4(x) __builtin_astype((x), float4)
#define as_float8(x) __builtin_astype((x), float8)
#define as_float16(x) __builtin_astype((x), float16)
#ifdef cl_khr_fp64
#define as_double(x) __builtin_astype((x), double)
#define as_double2(x) __builtin_astype((x), double2)
#define as_double3(x) __builtin_astype((x), double3)
#define as_double4(x) __builtin_astype((x), double4)
#define as_double8(x) __builtin_astype((x), double8)
#define as_double16(x) __builtin_astype((x), double16)
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
#define as_half(x) __builtin_astype((x), half)
#define as_half2(x) __builtin_astype((x), half2)
#define as_half3(x) __builtin_astype((x), half3)
#define as_half4(x) __builtin_astype((x), half4)
#define as_half8(x) __builtin_astype((x), half8)
#define as_half16(x) __builtin_astype((x), half16)
#endif //cl_khr_fp16
// OpenCL v1.1 s6.9, v1.2/2.0 s6.10 - Function qualifiers
#define __kernel_exec(X, typen) __kernel \
__attribute__((work_group_size_hint(X, 1, 1))) \
__attribute__((vec_type_hint(typen)))
#define kernel_exec(X, typen) __kernel \
__attribute__((work_group_size_hint(X, 1, 1))) \
__attribute__((vec_type_hint(typen)))
// OpenCL v1.1 s6.11.1, v1.2 s6.12.1, v2.0 s6.13.1 - Work-item Functions
/**
* Returns the number of dimensions in use. This is the
* value given to the work_dim argument specified in
* clEnqueueNDRangeKernel.
* For clEnqueueTask, this returns 1.
*/
uint __ovld __cnfn get_work_dim(void);
/**
* Returns the number of global work-items specified for
* dimension identified by dimindx. This value is given by
* the global_work_size argument to
* clEnqueueNDRangeKernel. Valid values of dimindx
* are 0 to get_work_dim() - 1. For other values of
* dimindx, get_global_size() returns 1.
* For clEnqueueTask, this always returns 1.
*/
size_t __ovld __cnfn get_global_size(uint dimindx);
/**
* Returns the unique global work-item ID value for
* dimension identified by dimindx. The global work-item
* ID specifies the work-item ID based on the number of
* global work-items specified to execute the kernel. Valid
* values of dimindx are 0 to get_work_dim() - 1. For
* other values of dimindx, get_global_id() returns 0.
* For clEnqueueTask, this returns 0.
*/
size_t __ovld __cnfn get_global_id(uint dimindx);
/**
* Returns the number of local work-items specified in
* dimension identified by dimindx. This value is given by
* the local_work_size argument to
* clEnqueueNDRangeKernel if local_work_size is not
* NULL; otherwise the OpenCL implementation chooses
* an appropriate local_work_size value which is returned
* by this function. Valid values of dimindx are 0 to
* get_work_dim() - 1. For other values of dimindx,
* get_local_size() returns 1.
* For clEnqueueTask, this always returns 1.
*/
size_t __ovld __cnfn get_local_size(uint dimindx);
/**
* Returns the unique local work-item ID i.e. a work-item
* within a specific work-group for dimension identified by
* dimindx. Valid values of dimindx are 0 to
* get_work_dim() - 1. For other values of dimindx,
* get_local_id() returns 0.
* For clEnqueueTask, this returns 0.
*/
size_t __ovld __cnfn get_local_id(uint dimindx);
/**
* Returns the number of work-groups that will execute a
* kernel for dimension identified by dimindx.
* Valid values of dimindx are 0 to get_work_dim() - 1.
* For other values of dimindx, get_num_groups () returns
* 1.
* For clEnqueueTask, this always returns 1.
*/
size_t __ovld __cnfn get_num_groups(uint dimindx);
/**
* get_group_id returns the work-group ID which is a
* number from 0 .. get_num_groups(dimindx) - 1.
* Valid values of dimindx are 0 to get_work_dim() - 1.
* For other values, get_group_id() returns 0.
* For clEnqueueTask, this returns 0.
*/
size_t __ovld __cnfn get_group_id(uint dimindx);
/**
* get_global_offset returns the offset values specified in
* global_work_offset argument to
* clEnqueueNDRangeKernel.
* Valid values of dimindx are 0 to get_work_dim() - 1.
* For other values, get_global_offset() returns 0.
* For clEnqueueTask, this returns 0.
*/
size_t __ovld __cnfn get_global_offset(uint dimindx);
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
size_t __ovld get_enqueued_local_size(uint dimindx);
size_t __ovld get_global_linear_id(void);
size_t __ovld get_local_linear_id(void);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
// OpenCL v1.1 s6.11.2, v1.2 s6.12.2, v2.0 s6.13.2 - Math functions
/**
* Arc cosine function.
*/
float __ovld __cnfn acos(float);
float2 __ovld __cnfn acos(float2);
float3 __ovld __cnfn acos(float3);
float4 __ovld __cnfn acos(float4);
float8 __ovld __cnfn acos(float8);
float16 __ovld __cnfn acos(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn acos(double);
double2 __ovld __cnfn acos(double2);
double3 __ovld __cnfn acos(double3);
double4 __ovld __cnfn acos(double4);
double8 __ovld __cnfn acos(double8);
double16 __ovld __cnfn acos(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn acos(half);
half2 __ovld __cnfn acos(half2);
half3 __ovld __cnfn acos(half3);
half4 __ovld __cnfn acos(half4);
half8 __ovld __cnfn acos(half8);
half16 __ovld __cnfn acos(half16);
#endif //cl_khr_fp16
/**
* Inverse hyperbolic cosine.
*/
float __ovld __cnfn acosh(float);
float2 __ovld __cnfn acosh(float2);
float3 __ovld __cnfn acosh(float3);
float4 __ovld __cnfn acosh(float4);
float8 __ovld __cnfn acosh(float8);
float16 __ovld __cnfn acosh(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn acosh(double);
double2 __ovld __cnfn acosh(double2);
double3 __ovld __cnfn acosh(double3);
double4 __ovld __cnfn acosh(double4);
double8 __ovld __cnfn acosh(double8);
double16 __ovld __cnfn acosh(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn acosh(half);
half2 __ovld __cnfn acosh(half2);
half3 __ovld __cnfn acosh(half3);
half4 __ovld __cnfn acosh(half4);
half8 __ovld __cnfn acosh(half8);
half16 __ovld __cnfn acosh(half16);
#endif //cl_khr_fp16
/**
* Compute acos (x) / PI.
*/
float __ovld __cnfn acospi(float x);
float2 __ovld __cnfn acospi(float2 x);
float3 __ovld __cnfn acospi(float3 x);
float4 __ovld __cnfn acospi(float4 x);
float8 __ovld __cnfn acospi(float8 x);
float16 __ovld __cnfn acospi(float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn acospi(double x);
double2 __ovld __cnfn acospi(double2 x);
double3 __ovld __cnfn acospi(double3 x);
double4 __ovld __cnfn acospi(double4 x);
double8 __ovld __cnfn acospi(double8 x);
double16 __ovld __cnfn acospi(double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn acospi(half x);
half2 __ovld __cnfn acospi(half2 x);
half3 __ovld __cnfn acospi(half3 x);
half4 __ovld __cnfn acospi(half4 x);
half8 __ovld __cnfn acospi(half8 x);
half16 __ovld __cnfn acospi(half16 x);
#endif //cl_khr_fp16
/**
* Arc sine function.
*/
float __ovld __cnfn asin(float);
float2 __ovld __cnfn asin(float2);
float3 __ovld __cnfn asin(float3);
float4 __ovld __cnfn asin(float4);
float8 __ovld __cnfn asin(float8);
float16 __ovld __cnfn asin(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn asin(double);
double2 __ovld __cnfn asin(double2);
double3 __ovld __cnfn asin(double3);
double4 __ovld __cnfn asin(double4);
double8 __ovld __cnfn asin(double8);
double16 __ovld __cnfn asin(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn asin(half);
half2 __ovld __cnfn asin(half2);
half3 __ovld __cnfn asin(half3);
half4 __ovld __cnfn asin(half4);
half8 __ovld __cnfn asin(half8);
half16 __ovld __cnfn asin(half16);
#endif //cl_khr_fp16
/**
* Inverse hyperbolic sine.
*/
float __ovld __cnfn asinh(float);
float2 __ovld __cnfn asinh(float2);
float3 __ovld __cnfn asinh(float3);
float4 __ovld __cnfn asinh(float4);
float8 __ovld __cnfn asinh(float8);
float16 __ovld __cnfn asinh(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn asinh(double);
double2 __ovld __cnfn asinh(double2);
double3 __ovld __cnfn asinh(double3);
double4 __ovld __cnfn asinh(double4);
double8 __ovld __cnfn asinh(double8);
double16 __ovld __cnfn asinh(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn asinh(half);
half2 __ovld __cnfn asinh(half2);
half3 __ovld __cnfn asinh(half3);
half4 __ovld __cnfn asinh(half4);
half8 __ovld __cnfn asinh(half8);
half16 __ovld __cnfn asinh(half16);
#endif //cl_khr_fp16
/**
* Compute asin (x) / PI.
*/
float __ovld __cnfn asinpi(float x);
float2 __ovld __cnfn asinpi(float2 x);
float3 __ovld __cnfn asinpi(float3 x);
float4 __ovld __cnfn asinpi(float4 x);
float8 __ovld __cnfn asinpi(float8 x);
float16 __ovld __cnfn asinpi(float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn asinpi(double x);
double2 __ovld __cnfn asinpi(double2 x);
double3 __ovld __cnfn asinpi(double3 x);
double4 __ovld __cnfn asinpi(double4 x);
double8 __ovld __cnfn asinpi(double8 x);
double16 __ovld __cnfn asinpi(double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn asinpi(half x);
half2 __ovld __cnfn asinpi(half2 x);
half3 __ovld __cnfn asinpi(half3 x);
half4 __ovld __cnfn asinpi(half4 x);
half8 __ovld __cnfn asinpi(half8 x);
half16 __ovld __cnfn asinpi(half16 x);
#endif //cl_khr_fp16
/**
* Arc tangent function.
*/
float __ovld __cnfn atan(float y_over_x);
float2 __ovld __cnfn atan(float2 y_over_x);
float3 __ovld __cnfn atan(float3 y_over_x);
float4 __ovld __cnfn atan(float4 y_over_x);
float8 __ovld __cnfn atan(float8 y_over_x);
float16 __ovld __cnfn atan(float16 y_over_x);
#ifdef cl_khr_fp64
double __ovld __cnfn atan(double y_over_x);
double2 __ovld __cnfn atan(double2 y_over_x);
double3 __ovld __cnfn atan(double3 y_over_x);
double4 __ovld __cnfn atan(double4 y_over_x);
double8 __ovld __cnfn atan(double8 y_over_x);
double16 __ovld __cnfn atan(double16 y_over_x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn atan(half y_over_x);
half2 __ovld __cnfn atan(half2 y_over_x);
half3 __ovld __cnfn atan(half3 y_over_x);
half4 __ovld __cnfn atan(half4 y_over_x);
half8 __ovld __cnfn atan(half8 y_over_x);
half16 __ovld __cnfn atan(half16 y_over_x);
#endif //cl_khr_fp16
/**
* Arc tangent of y / x.
*/
float __ovld __cnfn atan2(float y, float x);
float2 __ovld __cnfn atan2(float2 y, float2 x);
float3 __ovld __cnfn atan2(float3 y, float3 x);
float4 __ovld __cnfn atan2(float4 y, float4 x);
float8 __ovld __cnfn atan2(float8 y, float8 x);
float16 __ovld __cnfn atan2(float16 y, float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn atan2(double y, double x);
double2 __ovld __cnfn atan2(double2 y, double2 x);
double3 __ovld __cnfn atan2(double3 y, double3 x);
double4 __ovld __cnfn atan2(double4 y, double4 x);
double8 __ovld __cnfn atan2(double8 y, double8 x);
double16 __ovld __cnfn atan2(double16 y, double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn atan2(half y, half x);
half2 __ovld __cnfn atan2(half2 y, half2 x);
half3 __ovld __cnfn atan2(half3 y, half3 x);
half4 __ovld __cnfn atan2(half4 y, half4 x);
half8 __ovld __cnfn atan2(half8 y, half8 x);
half16 __ovld __cnfn atan2(half16 y, half16 x);
#endif //cl_khr_fp16
/**
* Hyperbolic arc tangent.
*/
float __ovld __cnfn atanh(float);
float2 __ovld __cnfn atanh(float2);
float3 __ovld __cnfn atanh(float3);
float4 __ovld __cnfn atanh(float4);
float8 __ovld __cnfn atanh(float8);
float16 __ovld __cnfn atanh(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn atanh(double);
double2 __ovld __cnfn atanh(double2);
double3 __ovld __cnfn atanh(double3);
double4 __ovld __cnfn atanh(double4);
double8 __ovld __cnfn atanh(double8);
double16 __ovld __cnfn atanh(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn atanh(half);
half2 __ovld __cnfn atanh(half2);
half3 __ovld __cnfn atanh(half3);
half4 __ovld __cnfn atanh(half4);
half8 __ovld __cnfn atanh(half8);
half16 __ovld __cnfn atanh(half16);
#endif //cl_khr_fp16
/**
* Compute atan (x) / PI.
*/
float __ovld __cnfn atanpi(float x);
float2 __ovld __cnfn atanpi(float2 x);
float3 __ovld __cnfn atanpi(float3 x);
float4 __ovld __cnfn atanpi(float4 x);
float8 __ovld __cnfn atanpi(float8 x);
float16 __ovld __cnfn atanpi(float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn atanpi(double x);
double2 __ovld __cnfn atanpi(double2 x);
double3 __ovld __cnfn atanpi(double3 x);
double4 __ovld __cnfn atanpi(double4 x);
double8 __ovld __cnfn atanpi(double8 x);
double16 __ovld __cnfn atanpi(double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn atanpi(half x);
half2 __ovld __cnfn atanpi(half2 x);
half3 __ovld __cnfn atanpi(half3 x);
half4 __ovld __cnfn atanpi(half4 x);
half8 __ovld __cnfn atanpi(half8 x);
half16 __ovld __cnfn atanpi(half16 x);
#endif //cl_khr_fp16
/**
* Compute atan2 (y, x) / PI.
*/
float __ovld __cnfn atan2pi(float y, float x);
float2 __ovld __cnfn atan2pi(float2 y, float2 x);
float3 __ovld __cnfn atan2pi(float3 y, float3 x);
float4 __ovld __cnfn atan2pi(float4 y, float4 x);
float8 __ovld __cnfn atan2pi(float8 y, float8 x);
float16 __ovld __cnfn atan2pi(float16 y, float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn atan2pi(double y, double x);
double2 __ovld __cnfn atan2pi(double2 y, double2 x);
double3 __ovld __cnfn atan2pi(double3 y, double3 x);
double4 __ovld __cnfn atan2pi(double4 y, double4 x);
double8 __ovld __cnfn atan2pi(double8 y, double8 x);
double16 __ovld __cnfn atan2pi(double16 y, double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn atan2pi(half y, half x);
half2 __ovld __cnfn atan2pi(half2 y, half2 x);
half3 __ovld __cnfn atan2pi(half3 y, half3 x);
half4 __ovld __cnfn atan2pi(half4 y, half4 x);
half8 __ovld __cnfn atan2pi(half8 y, half8 x);
half16 __ovld __cnfn atan2pi(half16 y, half16 x);
#endif //cl_khr_fp16
/**
* Compute cube-root.
*/
float __ovld __cnfn cbrt(float);
float2 __ovld __cnfn cbrt(float2);
float3 __ovld __cnfn cbrt(float3);
float4 __ovld __cnfn cbrt(float4);
float8 __ovld __cnfn cbrt(float8);
float16 __ovld __cnfn cbrt(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn cbrt(double);
double2 __ovld __cnfn cbrt(double2);
double3 __ovld __cnfn cbrt(double3);
double4 __ovld __cnfn cbrt(double4);
double8 __ovld __cnfn cbrt(double8);
double16 __ovld __cnfn cbrt(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn cbrt(half);
half2 __ovld __cnfn cbrt(half2);
half3 __ovld __cnfn cbrt(half3);
half4 __ovld __cnfn cbrt(half4);
half8 __ovld __cnfn cbrt(half8);
half16 __ovld __cnfn cbrt(half16);
#endif //cl_khr_fp16
/**
* Round to integral value using the round to positive
* infinity rounding mode.
*/
float __ovld __cnfn ceil(float);
float2 __ovld __cnfn ceil(float2);
float3 __ovld __cnfn ceil(float3);
float4 __ovld __cnfn ceil(float4);
float8 __ovld __cnfn ceil(float8);
float16 __ovld __cnfn ceil(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn ceil(double);
double2 __ovld __cnfn ceil(double2);
double3 __ovld __cnfn ceil(double3);
double4 __ovld __cnfn ceil(double4);
double8 __ovld __cnfn ceil(double8);
double16 __ovld __cnfn ceil(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn ceil(half);
half2 __ovld __cnfn ceil(half2);
half3 __ovld __cnfn ceil(half3);
half4 __ovld __cnfn ceil(half4);
half8 __ovld __cnfn ceil(half8);
half16 __ovld __cnfn ceil(half16);
#endif //cl_khr_fp16
/**
* Returns x with its sign changed to match the sign of y.
*/
float __ovld __cnfn copysign(float x, float y);
float2 __ovld __cnfn copysign(float2 x, float2 y);
float3 __ovld __cnfn copysign(float3 x, float3 y);
float4 __ovld __cnfn copysign(float4 x, float4 y);
float8 __ovld __cnfn copysign(float8 x, float8 y);
float16 __ovld __cnfn copysign(float16 x, float16 y);
#ifdef cl_khr_fp64
double __ovld __cnfn copysign(double x, double y);
double2 __ovld __cnfn copysign(double2 x, double2 y);
double3 __ovld __cnfn copysign(double3 x, double3 y);
double4 __ovld __cnfn copysign(double4 x, double4 y);
double8 __ovld __cnfn copysign(double8 x, double8 y);
double16 __ovld __cnfn copysign(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn copysign(half x, half y);
half2 __ovld __cnfn copysign(half2 x, half2 y);
half3 __ovld __cnfn copysign(half3 x, half3 y);
half4 __ovld __cnfn copysign(half4 x, half4 y);
half8 __ovld __cnfn copysign(half8 x, half8 y);
half16 __ovld __cnfn copysign(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Compute cosine.
*/
float __ovld __cnfn cos(float);
float2 __ovld __cnfn cos(float2);
float3 __ovld __cnfn cos(float3);
float4 __ovld __cnfn cos(float4);
float8 __ovld __cnfn cos(float8);
float16 __ovld __cnfn cos(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn cos(double);
double2 __ovld __cnfn cos(double2);
double3 __ovld __cnfn cos(double3);
double4 __ovld __cnfn cos(double4);
double8 __ovld __cnfn cos(double8);
double16 __ovld __cnfn cos(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn cos(half);
half2 __ovld __cnfn cos(half2);
half3 __ovld __cnfn cos(half3);
half4 __ovld __cnfn cos(half4);
half8 __ovld __cnfn cos(half8);
half16 __ovld __cnfn cos(half16);
#endif //cl_khr_fp16
/**
* Compute hyperbolic cosine.
*/
float __ovld __cnfn cosh(float);
float2 __ovld __cnfn cosh(float2);
float3 __ovld __cnfn cosh(float3);
float4 __ovld __cnfn cosh(float4);
float8 __ovld __cnfn cosh(float8);
float16 __ovld __cnfn cosh(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn cosh(double);
double2 __ovld __cnfn cosh(double2);
double3 __ovld __cnfn cosh(double3);
double4 __ovld __cnfn cosh(double4);
double8 __ovld __cnfn cosh(double8);
double16 __ovld __cnfn cosh(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn cosh(half);
half2 __ovld __cnfn cosh(half2);
half3 __ovld __cnfn cosh(half3);
half4 __ovld __cnfn cosh(half4);
half8 __ovld __cnfn cosh(half8);
half16 __ovld __cnfn cosh(half16);
#endif //cl_khr_fp16
/**
* Compute cos (PI * x).
*/
float __ovld __cnfn cospi(float x);
float2 __ovld __cnfn cospi(float2 x);
float3 __ovld __cnfn cospi(float3 x);
float4 __ovld __cnfn cospi(float4 x);
float8 __ovld __cnfn cospi(float8 x);
float16 __ovld __cnfn cospi(float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn cospi(double x);
double2 __ovld __cnfn cospi(double2 x);
double3 __ovld __cnfn cospi(double3 x);
double4 __ovld __cnfn cospi(double4 x);
double8 __ovld __cnfn cospi(double8 x);
double16 __ovld __cnfn cospi(double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn cospi(half x);
half2 __ovld __cnfn cospi(half2 x);
half3 __ovld __cnfn cospi(half3 x);
half4 __ovld __cnfn cospi(half4 x);
half8 __ovld __cnfn cospi(half8 x);
half16 __ovld __cnfn cospi(half16 x);
#endif //cl_khr_fp16
/**
* Complementary error function.
*/
float __ovld __cnfn erfc(float);
float2 __ovld __cnfn erfc(float2);
float3 __ovld __cnfn erfc(float3);
float4 __ovld __cnfn erfc(float4);
float8 __ovld __cnfn erfc(float8);
float16 __ovld __cnfn erfc(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn erfc(double);
double2 __ovld __cnfn erfc(double2);
double3 __ovld __cnfn erfc(double3);
double4 __ovld __cnfn erfc(double4);
double8 __ovld __cnfn erfc(double8);
double16 __ovld __cnfn erfc(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn erfc(half);
half2 __ovld __cnfn erfc(half2);
half3 __ovld __cnfn erfc(half3);
half4 __ovld __cnfn erfc(half4);
half8 __ovld __cnfn erfc(half8);
half16 __ovld __cnfn erfc(half16);
#endif //cl_khr_fp16
/**
* Error function encountered in integrating the
* normal distribution.
*/
float __ovld __cnfn erf(float);
float2 __ovld __cnfn erf(float2);
float3 __ovld __cnfn erf(float3);
float4 __ovld __cnfn erf(float4);
float8 __ovld __cnfn erf(float8);
float16 __ovld __cnfn erf(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn erf(double);
double2 __ovld __cnfn erf(double2);
double3 __ovld __cnfn erf(double3);
double4 __ovld __cnfn erf(double4);
double8 __ovld __cnfn erf(double8);
double16 __ovld __cnfn erf(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn erf(half);
half2 __ovld __cnfn erf(half2);
half3 __ovld __cnfn erf(half3);
half4 __ovld __cnfn erf(half4);
half8 __ovld __cnfn erf(half8);
half16 __ovld __cnfn erf(half16);
#endif //cl_khr_fp16
/**
* Compute the base e exponential function of x.
*/
float __ovld __cnfn exp(float x);
float2 __ovld __cnfn exp(float2 x);
float3 __ovld __cnfn exp(float3 x);
float4 __ovld __cnfn exp(float4 x);
float8 __ovld __cnfn exp(float8 x);
float16 __ovld __cnfn exp(float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn exp(double x);
double2 __ovld __cnfn exp(double2 x);
double3 __ovld __cnfn exp(double3 x);
double4 __ovld __cnfn exp(double4 x);
double8 __ovld __cnfn exp(double8 x);
double16 __ovld __cnfn exp(double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn exp(half x);
half2 __ovld __cnfn exp(half2 x);
half3 __ovld __cnfn exp(half3 x);
half4 __ovld __cnfn exp(half4 x);
half8 __ovld __cnfn exp(half8 x);
half16 __ovld __cnfn exp(half16 x);
#endif //cl_khr_fp16
/**
* Exponential base 2 function.
*/
float __ovld __cnfn exp2(float);
float2 __ovld __cnfn exp2(float2);
float3 __ovld __cnfn exp2(float3);
float4 __ovld __cnfn exp2(float4);
float8 __ovld __cnfn exp2(float8);
float16 __ovld __cnfn exp2(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn exp2(double);
double2 __ovld __cnfn exp2(double2);
double3 __ovld __cnfn exp2(double3);
double4 __ovld __cnfn exp2(double4);
double8 __ovld __cnfn exp2(double8);
double16 __ovld __cnfn exp2(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn exp2(half);
half2 __ovld __cnfn exp2(half2);
half3 __ovld __cnfn exp2(half3);
half4 __ovld __cnfn exp2(half4);
half8 __ovld __cnfn exp2(half8);
half16 __ovld __cnfn exp2(half16);
#endif //cl_khr_fp16
/**
* Exponential base 10 function.
*/
float __ovld __cnfn exp10(float);
float2 __ovld __cnfn exp10(float2);
float3 __ovld __cnfn exp10(float3);
float4 __ovld __cnfn exp10(float4);
float8 __ovld __cnfn exp10(float8);
float16 __ovld __cnfn exp10(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn exp10(double);
double2 __ovld __cnfn exp10(double2);
double3 __ovld __cnfn exp10(double3);
double4 __ovld __cnfn exp10(double4);
double8 __ovld __cnfn exp10(double8);
double16 __ovld __cnfn exp10(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn exp10(half);
half2 __ovld __cnfn exp10(half2);
half3 __ovld __cnfn exp10(half3);
half4 __ovld __cnfn exp10(half4);
half8 __ovld __cnfn exp10(half8);
half16 __ovld __cnfn exp10(half16);
#endif //cl_khr_fp16
/**
* Compute e^x- 1.0.
*/
float __ovld __cnfn expm1(float x);
float2 __ovld __cnfn expm1(float2 x);
float3 __ovld __cnfn expm1(float3 x);
float4 __ovld __cnfn expm1(float4 x);
float8 __ovld __cnfn expm1(float8 x);
float16 __ovld __cnfn expm1(float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn expm1(double x);
double2 __ovld __cnfn expm1(double2 x);
double3 __ovld __cnfn expm1(double3 x);
double4 __ovld __cnfn expm1(double4 x);
double8 __ovld __cnfn expm1(double8 x);
double16 __ovld __cnfn expm1(double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn expm1(half x);
half2 __ovld __cnfn expm1(half2 x);
half3 __ovld __cnfn expm1(half3 x);
half4 __ovld __cnfn expm1(half4 x);
half8 __ovld __cnfn expm1(half8 x);
half16 __ovld __cnfn expm1(half16 x);
#endif //cl_khr_fp16
/**
* Compute absolute value of a floating-point number.
*/
float __ovld __cnfn fabs(float);
float2 __ovld __cnfn fabs(float2);
float3 __ovld __cnfn fabs(float3);
float4 __ovld __cnfn fabs(float4);
float8 __ovld __cnfn fabs(float8);
float16 __ovld __cnfn fabs(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn fabs(double);
double2 __ovld __cnfn fabs(double2);
double3 __ovld __cnfn fabs(double3);
double4 __ovld __cnfn fabs(double4);
double8 __ovld __cnfn fabs(double8);
double16 __ovld __cnfn fabs(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn fabs(half);
half2 __ovld __cnfn fabs(half2);
half3 __ovld __cnfn fabs(half3);
half4 __ovld __cnfn fabs(half4);
half8 __ovld __cnfn fabs(half8);
half16 __ovld __cnfn fabs(half16);
#endif //cl_khr_fp16
/**
* x - y if x > y, +0 if x is less than or equal to y.
*/
float __ovld __cnfn fdim(float x, float y);
float2 __ovld __cnfn fdim(float2 x, float2 y);
float3 __ovld __cnfn fdim(float3 x, float3 y);
float4 __ovld __cnfn fdim(float4 x, float4 y);
float8 __ovld __cnfn fdim(float8 x, float8 y);
float16 __ovld __cnfn fdim(float16 x, float16 y);
#ifdef cl_khr_fp64
double __ovld __cnfn fdim(double x, double y);
double2 __ovld __cnfn fdim(double2 x, double2 y);
double3 __ovld __cnfn fdim(double3 x, double3 y);
double4 __ovld __cnfn fdim(double4 x, double4 y);
double8 __ovld __cnfn fdim(double8 x, double8 y);
double16 __ovld __cnfn fdim(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn fdim(half x, half y);
half2 __ovld __cnfn fdim(half2 x, half2 y);
half3 __ovld __cnfn fdim(half3 x, half3 y);
half4 __ovld __cnfn fdim(half4 x, half4 y);
half8 __ovld __cnfn fdim(half8 x, half8 y);
half16 __ovld __cnfn fdim(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Round to integral value using the round to -ve
* infinity rounding mode.
*/
float __ovld __cnfn floor(float);
float2 __ovld __cnfn floor(float2);
float3 __ovld __cnfn floor(float3);
float4 __ovld __cnfn floor(float4);
float8 __ovld __cnfn floor(float8);
float16 __ovld __cnfn floor(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn floor(double);
double2 __ovld __cnfn floor(double2);
double3 __ovld __cnfn floor(double3);
double4 __ovld __cnfn floor(double4);
double8 __ovld __cnfn floor(double8);
double16 __ovld __cnfn floor(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn floor(half);
half2 __ovld __cnfn floor(half2);
half3 __ovld __cnfn floor(half3);
half4 __ovld __cnfn floor(half4);
half8 __ovld __cnfn floor(half8);
half16 __ovld __cnfn floor(half16);
#endif //cl_khr_fp16
/**
* Returns the correctly rounded floating-point
* representation of the sum of c with the infinitely
* precise product of a and b. Rounding of
* intermediate products shall not occur. Edge case
* behavior is per the IEEE 754-2008 standard.
*/
float __ovld __cnfn fma(float a, float b, float c);
float2 __ovld __cnfn fma(float2 a, float2 b, float2 c);
float3 __ovld __cnfn fma(float3 a, float3 b, float3 c);
float4 __ovld __cnfn fma(float4 a, float4 b, float4 c);
float8 __ovld __cnfn fma(float8 a, float8 b, float8 c);
float16 __ovld __cnfn fma(float16 a, float16 b, float16 c);
#ifdef cl_khr_fp64
double __ovld __cnfn fma(double a, double b, double c);
double2 __ovld __cnfn fma(double2 a, double2 b, double2 c);
double3 __ovld __cnfn fma(double3 a, double3 b, double3 c);
double4 __ovld __cnfn fma(double4 a, double4 b, double4 c);
double8 __ovld __cnfn fma(double8 a, double8 b, double8 c);
double16 __ovld __cnfn fma(double16 a, double16 b, double16 c);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn fma(half a, half b, half c);
half2 __ovld __cnfn fma(half2 a, half2 b, half2 c);
half3 __ovld __cnfn fma(half3 a, half3 b, half3 c);
half4 __ovld __cnfn fma(half4 a, half4 b, half4 c);
half8 __ovld __cnfn fma(half8 a, half8 b, half8 c);
half16 __ovld __cnfn fma(half16 a, half16 b, half16 c);
#endif //cl_khr_fp16
/**
* Returns y if x < y, otherwise it returns x. If one
* argument is a NaN, fmax() returns the other
* argument. If both arguments are NaNs, fmax()
* returns a NaN.
*/
float __ovld __cnfn fmax(float x, float y);
float2 __ovld __cnfn fmax(float2 x, float2 y);
float3 __ovld __cnfn fmax(float3 x, float3 y);
float4 __ovld __cnfn fmax(float4 x, float4 y);
float8 __ovld __cnfn fmax(float8 x, float8 y);
float16 __ovld __cnfn fmax(float16 x, float16 y);
float2 __ovld __cnfn fmax(float2 x, float y);
float3 __ovld __cnfn fmax(float3 x, float y);
float4 __ovld __cnfn fmax(float4 x, float y);
float8 __ovld __cnfn fmax(float8 x, float y);
float16 __ovld __cnfn fmax(float16 x, float y);
#ifdef cl_khr_fp64
double __ovld __cnfn fmax(double x, double y);
double2 __ovld __cnfn fmax(double2 x, double2 y);
double3 __ovld __cnfn fmax(double3 x, double3 y);
double4 __ovld __cnfn fmax(double4 x, double4 y);
double8 __ovld __cnfn fmax(double8 x, double8 y);
double16 __ovld __cnfn fmax(double16 x, double16 y);
double2 __ovld __cnfn fmax(double2 x, double y);
double3 __ovld __cnfn fmax(double3 x, double y);
double4 __ovld __cnfn fmax(double4 x, double y);
double8 __ovld __cnfn fmax(double8 x, double y);
double16 __ovld __cnfn fmax(double16 x, double y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn fmax(half x, half y);
half2 __ovld __cnfn fmax(half2 x, half2 y);
half3 __ovld __cnfn fmax(half3 x, half3 y);
half4 __ovld __cnfn fmax(half4 x, half4 y);
half8 __ovld __cnfn fmax(half8 x, half8 y);
half16 __ovld __cnfn fmax(half16 x, half16 y);
half2 __ovld __cnfn fmax(half2 x, half y);
half3 __ovld __cnfn fmax(half3 x, half y);
half4 __ovld __cnfn fmax(half4 x, half y);
half8 __ovld __cnfn fmax(half8 x, half y);
half16 __ovld __cnfn fmax(half16 x, half y);
#endif //cl_khr_fp16
/**
* Returns y if y < x, otherwise it returns x. If one
* argument is a NaN, fmin() returns the other
* argument. If both arguments are NaNs, fmin()
* returns a NaN.
*/
float __ovld __cnfn fmin(float x, float y);
float2 __ovld __cnfn fmin(float2 x, float2 y);
float3 __ovld __cnfn fmin(float3 x, float3 y);
float4 __ovld __cnfn fmin(float4 x, float4 y);
float8 __ovld __cnfn fmin(float8 x, float8 y);
float16 __ovld __cnfn fmin(float16 x, float16 y);
float2 __ovld __cnfn fmin(float2 x, float y);
float3 __ovld __cnfn fmin(float3 x, float y);
float4 __ovld __cnfn fmin(float4 x, float y);
float8 __ovld __cnfn fmin(float8 x, float y);
float16 __ovld __cnfn fmin(float16 x, float y);
#ifdef cl_khr_fp64
double __ovld __cnfn fmin(double x, double y);
double2 __ovld __cnfn fmin(double2 x, double2 y);
double3 __ovld __cnfn fmin(double3 x, double3 y);
double4 __ovld __cnfn fmin(double4 x, double4 y);
double8 __ovld __cnfn fmin(double8 x, double8 y);
double16 __ovld __cnfn fmin(double16 x, double16 y);
double2 __ovld __cnfn fmin(double2 x, double y);
double3 __ovld __cnfn fmin(double3 x, double y);
double4 __ovld __cnfn fmin(double4 x, double y);
double8 __ovld __cnfn fmin(double8 x, double y);
double16 __ovld __cnfn fmin(double16 x, double y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn fmin(half x, half y);
half2 __ovld __cnfn fmin(half2 x, half2 y);
half3 __ovld __cnfn fmin(half3 x, half3 y);
half4 __ovld __cnfn fmin(half4 x, half4 y);
half8 __ovld __cnfn fmin(half8 x, half8 y);
half16 __ovld __cnfn fmin(half16 x, half16 y);
half2 __ovld __cnfn fmin(half2 x, half y);
half3 __ovld __cnfn fmin(half3 x, half y);
half4 __ovld __cnfn fmin(half4 x, half y);
half8 __ovld __cnfn fmin(half8 x, half y);
half16 __ovld __cnfn fmin(half16 x, half y);
#endif //cl_khr_fp16
/**
* Modulus. Returns x - y * trunc (x/y).
*/
float __ovld __cnfn fmod(float x, float y);
float2 __ovld __cnfn fmod(float2 x, float2 y);
float3 __ovld __cnfn fmod(float3 x, float3 y);
float4 __ovld __cnfn fmod(float4 x, float4 y);
float8 __ovld __cnfn fmod(float8 x, float8 y);
float16 __ovld __cnfn fmod(float16 x, float16 y);
#ifdef cl_khr_fp64
double __ovld __cnfn fmod(double x, double y);
double2 __ovld __cnfn fmod(double2 x, double2 y);
double3 __ovld __cnfn fmod(double3 x, double3 y);
double4 __ovld __cnfn fmod(double4 x, double4 y);
double8 __ovld __cnfn fmod(double8 x, double8 y);
double16 __ovld __cnfn fmod(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn fmod(half x, half y);
half2 __ovld __cnfn fmod(half2 x, half2 y);
half3 __ovld __cnfn fmod(half3 x, half3 y);
half4 __ovld __cnfn fmod(half4 x, half4 y);
half8 __ovld __cnfn fmod(half8 x, half8 y);
half16 __ovld __cnfn fmod(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Returns fmin(x - floor (x), 0x1.fffffep-1f ).
* floor(x) is returned in iptr.
*/
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
float __ovld fract(float x, float *iptr);
float2 __ovld fract(float2 x, float2 *iptr);
float3 __ovld fract(float3 x, float3 *iptr);
float4 __ovld fract(float4 x, float4 *iptr);
float8 __ovld fract(float8 x, float8 *iptr);
float16 __ovld fract(float16 x, float16 *iptr);
#ifdef cl_khr_fp64
double __ovld fract(double x, double *iptr);
double2 __ovld fract(double2 x, double2 *iptr);
double3 __ovld fract(double3 x, double3 *iptr);
double4 __ovld fract(double4 x, double4 *iptr);
double8 __ovld fract(double8 x, double8 *iptr);
double16 __ovld fract(double16 x, double16 *iptr);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld fract(half x, half *iptr);
half2 __ovld fract(half2 x, half2 *iptr);
half3 __ovld fract(half3 x, half3 *iptr);
half4 __ovld fract(half4 x, half4 *iptr);
half8 __ovld fract(half8 x, half8 *iptr);
half16 __ovld fract(half16 x, half16 *iptr);
#endif //cl_khr_fp16
#else
float __ovld fract(float x, __global float *iptr);
float2 __ovld fract(float2 x, __global float2 *iptr);
float3 __ovld fract(float3 x, __global float3 *iptr);
float4 __ovld fract(float4 x, __global float4 *iptr);
float8 __ovld fract(float8 x, __global float8 *iptr);
float16 __ovld fract(float16 x, __global float16 *iptr);
float __ovld fract(float x, __local float *iptr);
float2 __ovld fract(float2 x, __local float2 *iptr);
float3 __ovld fract(float3 x, __local float3 *iptr);
float4 __ovld fract(float4 x, __local float4 *iptr);
float8 __ovld fract(float8 x, __local float8 *iptr);
float16 __ovld fract(float16 x, __local float16 *iptr);
float __ovld fract(float x, __private float *iptr);
float2 __ovld fract(float2 x, __private float2 *iptr);
float3 __ovld fract(float3 x, __private float3 *iptr);
float4 __ovld fract(float4 x, __private float4 *iptr);
float8 __ovld fract(float8 x, __private float8 *iptr);
float16 __ovld fract(float16 x, __private float16 *iptr);
#ifdef cl_khr_fp64
double __ovld fract(double x, __global double *iptr);
double2 __ovld fract(double2 x, __global double2 *iptr);
double3 __ovld fract(double3 x, __global double3 *iptr);
double4 __ovld fract(double4 x, __global double4 *iptr);
double8 __ovld fract(double8 x, __global double8 *iptr);
double16 __ovld fract(double16 x, __global double16 *iptr);
double __ovld fract(double x, __local double *iptr);
double2 __ovld fract(double2 x, __local double2 *iptr);
double3 __ovld fract(double3 x, __local double3 *iptr);
double4 __ovld fract(double4 x, __local double4 *iptr);
double8 __ovld fract(double8 x, __local double8 *iptr);
double16 __ovld fract(double16 x, __local double16 *iptr);
double __ovld fract(double x, __private double *iptr);
double2 __ovld fract(double2 x, __private double2 *iptr);
double3 __ovld fract(double3 x, __private double3 *iptr);
double4 __ovld fract(double4 x, __private double4 *iptr);
double8 __ovld fract(double8 x, __private double8 *iptr);
double16 __ovld fract(double16 x, __private double16 *iptr);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld fract(half x, __global half *iptr);
half2 __ovld fract(half2 x, __global half2 *iptr);
half3 __ovld fract(half3 x, __global half3 *iptr);
half4 __ovld fract(half4 x, __global half4 *iptr);
half8 __ovld fract(half8 x, __global half8 *iptr);
half16 __ovld fract(half16 x, __global half16 *iptr);
half __ovld fract(half x, __local half *iptr);
half2 __ovld fract(half2 x, __local half2 *iptr);
half3 __ovld fract(half3 x, __local half3 *iptr);
half4 __ovld fract(half4 x, __local half4 *iptr);
half8 __ovld fract(half8 x, __local half8 *iptr);
half16 __ovld fract(half16 x, __local half16 *iptr);
half __ovld fract(half x, __private half *iptr);
half2 __ovld fract(half2 x, __private half2 *iptr);
half3 __ovld fract(half3 x, __private half3 *iptr);
half4 __ovld fract(half4 x, __private half4 *iptr);
half8 __ovld fract(half8 x, __private half8 *iptr);
half16 __ovld fract(half16 x, __private half16 *iptr);
#endif //cl_khr_fp16
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Extract mantissa and exponent from x. For each
* component the mantissa returned is a float with
* magnitude in the interval [1/2, 1) or 0. Each
* component of x equals mantissa returned * 2^exp.
*/
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
float __ovld frexp(float x, int *exp);
float2 __ovld frexp(float2 x, int2 *exp);
float3 __ovld frexp(float3 x, int3 *exp);
float4 __ovld frexp(float4 x, int4 *exp);
float8 __ovld frexp(float8 x, int8 *exp);
float16 __ovld frexp(float16 x, int16 *exp);
#ifdef cl_khr_fp64
double __ovld frexp(double x, int *exp);
double2 __ovld frexp(double2 x, int2 *exp);
double3 __ovld frexp(double3 x, int3 *exp);
double4 __ovld frexp(double4 x, int4 *exp);
double8 __ovld frexp(double8 x, int8 *exp);
double16 __ovld frexp(double16 x, int16 *exp);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld frexp(half x, int *exp);
half2 __ovld frexp(half2 x, int2 *exp);
half3 __ovld frexp(half3 x, int3 *exp);
half4 __ovld frexp(half4 x, int4 *exp);
half8 __ovld frexp(half8 x, int8 *exp);
half16 __ovld frexp(half16 x, int16 *exp);
#endif //cl_khr_fp16
#else
float __ovld frexp(float x, __global int *exp);
float2 __ovld frexp(float2 x, __global int2 *exp);
float3 __ovld frexp(float3 x, __global int3 *exp);
float4 __ovld frexp(float4 x, __global int4 *exp);
float8 __ovld frexp(float8 x, __global int8 *exp);
float16 __ovld frexp(float16 x, __global int16 *exp);
float __ovld frexp(float x, __local int *exp);
float2 __ovld frexp(float2 x, __local int2 *exp);
float3 __ovld frexp(float3 x, __local int3 *exp);
float4 __ovld frexp(float4 x, __local int4 *exp);
float8 __ovld frexp(float8 x, __local int8 *exp);
float16 __ovld frexp(float16 x, __local int16 *exp);
float __ovld frexp(float x, __private int *exp);
float2 __ovld frexp(float2 x, __private int2 *exp);
float3 __ovld frexp(float3 x, __private int3 *exp);
float4 __ovld frexp(float4 x, __private int4 *exp);
float8 __ovld frexp(float8 x, __private int8 *exp);
float16 __ovld frexp(float16 x, __private int16 *exp);
#ifdef cl_khr_fp64
double __ovld frexp(double x, __global int *exp);
double2 __ovld frexp(double2 x, __global int2 *exp);
double3 __ovld frexp(double3 x, __global int3 *exp);
double4 __ovld frexp(double4 x, __global int4 *exp);
double8 __ovld frexp(double8 x, __global int8 *exp);
double16 __ovld frexp(double16 x, __global int16 *exp);
double __ovld frexp(double x, __local int *exp);
double2 __ovld frexp(double2 x, __local int2 *exp);
double3 __ovld frexp(double3 x, __local int3 *exp);
double4 __ovld frexp(double4 x, __local int4 *exp);
double8 __ovld frexp(double8 x, __local int8 *exp);
double16 __ovld frexp(double16 x, __local int16 *exp);
double __ovld frexp(double x, __private int *exp);
double2 __ovld frexp(double2 x, __private int2 *exp);
double3 __ovld frexp(double3 x, __private int3 *exp);
double4 __ovld frexp(double4 x, __private int4 *exp);
double8 __ovld frexp(double8 x, __private int8 *exp);
double16 __ovld frexp(double16 x, __private int16 *exp);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld frexp(half x, __global int *exp);
half2 __ovld frexp(half2 x, __global int2 *exp);
half3 __ovld frexp(half3 x, __global int3 *exp);
half4 __ovld frexp(half4 x, __global int4 *exp);
half8 __ovld frexp(half8 x, __global int8 *exp);
half16 __ovld frexp(half16 x, __global int16 *exp);
half __ovld frexp(half x, __local int *exp);
half2 __ovld frexp(half2 x, __local int2 *exp);
half3 __ovld frexp(half3 x, __local int3 *exp);
half4 __ovld frexp(half4 x, __local int4 *exp);
half8 __ovld frexp(half8 x, __local int8 *exp);
half16 __ovld frexp(half16 x, __local int16 *exp);
half __ovld frexp(half x, __private int *exp);
half2 __ovld frexp(half2 x, __private int2 *exp);
half3 __ovld frexp(half3 x, __private int3 *exp);
half4 __ovld frexp(half4 x, __private int4 *exp);
half8 __ovld frexp(half8 x, __private int8 *exp);
half16 __ovld frexp(half16 x, __private int16 *exp);
#endif //cl_khr_fp16
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Compute the value of the square root of x^2 + y^2
* without undue overflow or underflow.
*/
float __ovld __cnfn hypot(float x, float y);
float2 __ovld __cnfn hypot(float2 x, float2 y);
float3 __ovld __cnfn hypot(float3 x, float3 y);
float4 __ovld __cnfn hypot(float4 x, float4 y);
float8 __ovld __cnfn hypot(float8 x, float8 y);
float16 __ovld __cnfn hypot(float16 x, float16 y);
#ifdef cl_khr_fp64
double __ovld __cnfn hypot(double x, double y);
double2 __ovld __cnfn hypot(double2 x, double2 y);
double3 __ovld __cnfn hypot(double3 x, double3 y);
double4 __ovld __cnfn hypot(double4 x, double4 y);
double8 __ovld __cnfn hypot(double8 x, double8 y);
double16 __ovld __cnfn hypot(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn hypot(half x, half y);
half2 __ovld __cnfn hypot(half2 x, half2 y);
half3 __ovld __cnfn hypot(half3 x, half3 y);
half4 __ovld __cnfn hypot(half4 x, half4 y);
half8 __ovld __cnfn hypot(half8 x, half8 y);
half16 __ovld __cnfn hypot(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Return the exponent as an integer value.
*/
int __ovld __cnfn ilogb(float x);
int2 __ovld __cnfn ilogb(float2 x);
int3 __ovld __cnfn ilogb(float3 x);
int4 __ovld __cnfn ilogb(float4 x);
int8 __ovld __cnfn ilogb(float8 x);
int16 __ovld __cnfn ilogb(float16 x);
#ifdef cl_khr_fp64
int __ovld __cnfn ilogb(double x);
int2 __ovld __cnfn ilogb(double2 x);
int3 __ovld __cnfn ilogb(double3 x);
int4 __ovld __cnfn ilogb(double4 x);
int8 __ovld __cnfn ilogb(double8 x);
int16 __ovld __cnfn ilogb(double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn ilogb(half x);
int2 __ovld __cnfn ilogb(half2 x);
int3 __ovld __cnfn ilogb(half3 x);
int4 __ovld __cnfn ilogb(half4 x);
int8 __ovld __cnfn ilogb(half8 x);
int16 __ovld __cnfn ilogb(half16 x);
#endif //cl_khr_fp16
/**
* Multiply x by 2 to the power n.
*/
float __ovld __cnfn ldexp(float x, int n);
float2 __ovld __cnfn ldexp(float2 x, int2 n);
float3 __ovld __cnfn ldexp(float3 x, int3 n);
float4 __ovld __cnfn ldexp(float4 x, int4 n);
float8 __ovld __cnfn ldexp(float8 x, int8 n);
float16 __ovld __cnfn ldexp(float16 x, int16 n);
float2 __ovld __cnfn ldexp(float2 x, int n);
float3 __ovld __cnfn ldexp(float3 x, int n);
float4 __ovld __cnfn ldexp(float4 x, int n);
float8 __ovld __cnfn ldexp(float8 x, int n);
float16 __ovld __cnfn ldexp(float16 x, int n);
#ifdef cl_khr_fp64
double __ovld __cnfn ldexp(double x, int n);
double2 __ovld __cnfn ldexp(double2 x, int2 n);
double3 __ovld __cnfn ldexp(double3 x, int3 n);
double4 __ovld __cnfn ldexp(double4 x, int4 n);
double8 __ovld __cnfn ldexp(double8 x, int8 n);
double16 __ovld __cnfn ldexp(double16 x, int16 n);
double2 __ovld __cnfn ldexp(double2 x, int n);
double3 __ovld __cnfn ldexp(double3 x, int n);
double4 __ovld __cnfn ldexp(double4 x, int n);
double8 __ovld __cnfn ldexp(double8 x, int n);
double16 __ovld __cnfn ldexp(double16 x, int n);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn ldexp(half x, int n);
half2 __ovld __cnfn ldexp(half2 x, int2 n);
half3 __ovld __cnfn ldexp(half3 x, int3 n);
half4 __ovld __cnfn ldexp(half4 x, int4 n);
half8 __ovld __cnfn ldexp(half8 x, int8 n);
half16 __ovld __cnfn ldexp(half16 x, int16 n);
half2 __ovld __cnfn ldexp(half2 x, int n);
half3 __ovld __cnfn ldexp(half3 x, int n);
half4 __ovld __cnfn ldexp(half4 x, int n);
half8 __ovld __cnfn ldexp(half8 x, int n);
half16 __ovld __cnfn ldexp(half16 x, int n);
#endif //cl_khr_fp16
/**
* Log gamma function. Returns the natural
* logarithm of the absolute value of the gamma
* function. The sign of the gamma function is
* returned in the signp argument of lgamma_r.
*/
float __ovld __cnfn lgamma(float x);
float2 __ovld __cnfn lgamma(float2 x);
float3 __ovld __cnfn lgamma(float3 x);
float4 __ovld __cnfn lgamma(float4 x);
float8 __ovld __cnfn lgamma(float8 x);
float16 __ovld __cnfn lgamma(float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn lgamma(double x);
double2 __ovld __cnfn lgamma(double2 x);
double3 __ovld __cnfn lgamma(double3 x);
double4 __ovld __cnfn lgamma(double4 x);
double8 __ovld __cnfn lgamma(double8 x);
double16 __ovld __cnfn lgamma(double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn lgamma(half x);
half2 __ovld __cnfn lgamma(half2 x);
half3 __ovld __cnfn lgamma(half3 x);
half4 __ovld __cnfn lgamma(half4 x);
half8 __ovld __cnfn lgamma(half8 x);
half16 __ovld __cnfn lgamma(half16 x);
#endif //cl_khr_fp16
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
float __ovld lgamma_r(float x, int *signp);
float2 __ovld lgamma_r(float2 x, int2 *signp);
float3 __ovld lgamma_r(float3 x, int3 *signp);
float4 __ovld lgamma_r(float4 x, int4 *signp);
float8 __ovld lgamma_r(float8 x, int8 *signp);
float16 __ovld lgamma_r(float16 x, int16 *signp);
#ifdef cl_khr_fp64
double __ovld lgamma_r(double x, int *signp);
double2 __ovld lgamma_r(double2 x, int2 *signp);
double3 __ovld lgamma_r(double3 x, int3 *signp);
double4 __ovld lgamma_r(double4 x, int4 *signp);
double8 __ovld lgamma_r(double8 x, int8 *signp);
double16 __ovld lgamma_r(double16 x, int16 *signp);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld lgamma_r(half x, int *signp);
half2 __ovld lgamma_r(half2 x, int2 *signp);
half3 __ovld lgamma_r(half3 x, int3 *signp);
half4 __ovld lgamma_r(half4 x, int4 *signp);
half8 __ovld lgamma_r(half8 x, int8 *signp);
half16 __ovld lgamma_r(half16 x, int16 *signp);
#endif //cl_khr_fp16
#else
float __ovld lgamma_r(float x, __global int *signp);
float2 __ovld lgamma_r(float2 x, __global int2 *signp);
float3 __ovld lgamma_r(float3 x, __global int3 *signp);
float4 __ovld lgamma_r(float4 x, __global int4 *signp);
float8 __ovld lgamma_r(float8 x, __global int8 *signp);
float16 __ovld lgamma_r(float16 x, __global int16 *signp);
float __ovld lgamma_r(float x, __local int *signp);
float2 __ovld lgamma_r(float2 x, __local int2 *signp);
float3 __ovld lgamma_r(float3 x, __local int3 *signp);
float4 __ovld lgamma_r(float4 x, __local int4 *signp);
float8 __ovld lgamma_r(float8 x, __local int8 *signp);
float16 __ovld lgamma_r(float16 x, __local int16 *signp);
float __ovld lgamma_r(float x, __private int *signp);
float2 __ovld lgamma_r(float2 x, __private int2 *signp);
float3 __ovld lgamma_r(float3 x, __private int3 *signp);
float4 __ovld lgamma_r(float4 x, __private int4 *signp);
float8 __ovld lgamma_r(float8 x, __private int8 *signp);
float16 __ovld lgamma_r(float16 x, __private int16 *signp);
#ifdef cl_khr_fp64
double __ovld lgamma_r(double x, __global int *signp);
double2 __ovld lgamma_r(double2 x, __global int2 *signp);
double3 __ovld lgamma_r(double3 x, __global int3 *signp);
double4 __ovld lgamma_r(double4 x, __global int4 *signp);
double8 __ovld lgamma_r(double8 x, __global int8 *signp);
double16 __ovld lgamma_r(double16 x, __global int16 *signp);
double __ovld lgamma_r(double x, __local int *signp);
double2 __ovld lgamma_r(double2 x, __local int2 *signp);
double3 __ovld lgamma_r(double3 x, __local int3 *signp);
double4 __ovld lgamma_r(double4 x, __local int4 *signp);
double8 __ovld lgamma_r(double8 x, __local int8 *signp);
double16 __ovld lgamma_r(double16 x, __local int16 *signp);
double __ovld lgamma_r(double x, __private int *signp);
double2 __ovld lgamma_r(double2 x, __private int2 *signp);
double3 __ovld lgamma_r(double3 x, __private int3 *signp);
double4 __ovld lgamma_r(double4 x, __private int4 *signp);
double8 __ovld lgamma_r(double8 x, __private int8 *signp);
double16 __ovld lgamma_r(double16 x, __private int16 *signp);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld lgamma_r(half x, __global int *signp);
half2 __ovld lgamma_r(half2 x, __global int2 *signp);
half3 __ovld lgamma_r(half3 x, __global int3 *signp);
half4 __ovld lgamma_r(half4 x, __global int4 *signp);
half8 __ovld lgamma_r(half8 x, __global int8 *signp);
half16 __ovld lgamma_r(half16 x, __global int16 *signp);
half __ovld lgamma_r(half x, __local int *signp);
half2 __ovld lgamma_r(half2 x, __local int2 *signp);
half3 __ovld lgamma_r(half3 x, __local int3 *signp);
half4 __ovld lgamma_r(half4 x, __local int4 *signp);
half8 __ovld lgamma_r(half8 x, __local int8 *signp);
half16 __ovld lgamma_r(half16 x, __local int16 *signp);
half __ovld lgamma_r(half x, __private int *signp);
half2 __ovld lgamma_r(half2 x, __private int2 *signp);
half3 __ovld lgamma_r(half3 x, __private int3 *signp);
half4 __ovld lgamma_r(half4 x, __private int4 *signp);
half8 __ovld lgamma_r(half8 x, __private int8 *signp);
half16 __ovld lgamma_r(half16 x, __private int16 *signp);
#endif //cl_khr_fp16
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Compute natural logarithm.
*/
float __ovld __cnfn log(float);
float2 __ovld __cnfn log(float2);
float3 __ovld __cnfn log(float3);
float4 __ovld __cnfn log(float4);
float8 __ovld __cnfn log(float8);
float16 __ovld __cnfn log(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn log(double);
double2 __ovld __cnfn log(double2);
double3 __ovld __cnfn log(double3);
double4 __ovld __cnfn log(double4);
double8 __ovld __cnfn log(double8);
double16 __ovld __cnfn log(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn log(half);
half2 __ovld __cnfn log(half2);
half3 __ovld __cnfn log(half3);
half4 __ovld __cnfn log(half4);
half8 __ovld __cnfn log(half8);
half16 __ovld __cnfn log(half16);
#endif //cl_khr_fp16
/**
* Compute a base 2 logarithm.
*/
float __ovld __cnfn log2(float);
float2 __ovld __cnfn log2(float2);
float3 __ovld __cnfn log2(float3);
float4 __ovld __cnfn log2(float4);
float8 __ovld __cnfn log2(float8);
float16 __ovld __cnfn log2(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn log2(double);
double2 __ovld __cnfn log2(double2);
double3 __ovld __cnfn log2(double3);
double4 __ovld __cnfn log2(double4);
double8 __ovld __cnfn log2(double8);
double16 __ovld __cnfn log2(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn log2(half);
half2 __ovld __cnfn log2(half2);
half3 __ovld __cnfn log2(half3);
half4 __ovld __cnfn log2(half4);
half8 __ovld __cnfn log2(half8);
half16 __ovld __cnfn log2(half16);
#endif //cl_khr_fp16
/**
* Compute a base 10 logarithm.
*/
float __ovld __cnfn log10(float);
float2 __ovld __cnfn log10(float2);
float3 __ovld __cnfn log10(float3);
float4 __ovld __cnfn log10(float4);
float8 __ovld __cnfn log10(float8);
float16 __ovld __cnfn log10(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn log10(double);
double2 __ovld __cnfn log10(double2);
double3 __ovld __cnfn log10(double3);
double4 __ovld __cnfn log10(double4);
double8 __ovld __cnfn log10(double8);
double16 __ovld __cnfn log10(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn log10(half);
half2 __ovld __cnfn log10(half2);
half3 __ovld __cnfn log10(half3);
half4 __ovld __cnfn log10(half4);
half8 __ovld __cnfn log10(half8);
half16 __ovld __cnfn log10(half16);
#endif //cl_khr_fp16
/**
* Compute a base e logarithm of (1.0 + x).
*/
float __ovld __cnfn log1p(float x);
float2 __ovld __cnfn log1p(float2 x);
float3 __ovld __cnfn log1p(float3 x);
float4 __ovld __cnfn log1p(float4 x);
float8 __ovld __cnfn log1p(float8 x);
float16 __ovld __cnfn log1p(float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn log1p(double x);
double2 __ovld __cnfn log1p(double2 x);
double3 __ovld __cnfn log1p(double3 x);
double4 __ovld __cnfn log1p(double4 x);
double8 __ovld __cnfn log1p(double8 x);
double16 __ovld __cnfn log1p(double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn log1p(half x);
half2 __ovld __cnfn log1p(half2 x);
half3 __ovld __cnfn log1p(half3 x);
half4 __ovld __cnfn log1p(half4 x);
half8 __ovld __cnfn log1p(half8 x);
half16 __ovld __cnfn log1p(half16 x);
#endif //cl_khr_fp16
/**
* Compute the exponent of x, which is the integral
* part of logr | x |.
*/
float __ovld __cnfn logb(float x);
float2 __ovld __cnfn logb(float2 x);
float3 __ovld __cnfn logb(float3 x);
float4 __ovld __cnfn logb(float4 x);
float8 __ovld __cnfn logb(float8 x);
float16 __ovld __cnfn logb(float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn logb(double x);
double2 __ovld __cnfn logb(double2 x);
double3 __ovld __cnfn logb(double3 x);
double4 __ovld __cnfn logb(double4 x);
double8 __ovld __cnfn logb(double8 x);
double16 __ovld __cnfn logb(double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn logb(half x);
half2 __ovld __cnfn logb(half2 x);
half3 __ovld __cnfn logb(half3 x);
half4 __ovld __cnfn logb(half4 x);
half8 __ovld __cnfn logb(half8 x);
half16 __ovld __cnfn logb(half16 x);
#endif //cl_khr_fp16
/**
* mad approximates a * b + c. Whether or how the
* product of a * b is rounded and how supernormal or
* subnormal intermediate products are handled is not
* defined. mad is intended to be used where speed is
* preferred over accuracy.
*/
float __ovld __cnfn mad(float a, float b, float c);
float2 __ovld __cnfn mad(float2 a, float2 b, float2 c);
float3 __ovld __cnfn mad(float3 a, float3 b, float3 c);
float4 __ovld __cnfn mad(float4 a, float4 b, float4 c);
float8 __ovld __cnfn mad(float8 a, float8 b, float8 c);
float16 __ovld __cnfn mad(float16 a, float16 b, float16 c);
#ifdef cl_khr_fp64
double __ovld __cnfn mad(double a, double b, double c);
double2 __ovld __cnfn mad(double2 a, double2 b, double2 c);
double3 __ovld __cnfn mad(double3 a, double3 b, double3 c);
double4 __ovld __cnfn mad(double4 a, double4 b, double4 c);
double8 __ovld __cnfn mad(double8 a, double8 b, double8 c);
double16 __ovld __cnfn mad(double16 a, double16 b, double16 c);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn mad(half a, half b, half c);
half2 __ovld __cnfn mad(half2 a, half2 b, half2 c);
half3 __ovld __cnfn mad(half3 a, half3 b, half3 c);
half4 __ovld __cnfn mad(half4 a, half4 b, half4 c);
half8 __ovld __cnfn mad(half8 a, half8 b, half8 c);
half16 __ovld __cnfn mad(half16 a, half16 b, half16 c);
#endif //cl_khr_fp16
/**
* Returns x if | x | > | y |, y if | y | > | x |, otherwise
* fmax(x, y).
*/
float __ovld __cnfn maxmag(float x, float y);
float2 __ovld __cnfn maxmag(float2 x, float2 y);
float3 __ovld __cnfn maxmag(float3 x, float3 y);
float4 __ovld __cnfn maxmag(float4 x, float4 y);
float8 __ovld __cnfn maxmag(float8 x, float8 y);
float16 __ovld __cnfn maxmag(float16 x, float16 y);
#ifdef cl_khr_fp64
double __ovld __cnfn maxmag(double x, double y);
double2 __ovld __cnfn maxmag(double2 x, double2 y);
double3 __ovld __cnfn maxmag(double3 x, double3 y);
double4 __ovld __cnfn maxmag(double4 x, double4 y);
double8 __ovld __cnfn maxmag(double8 x, double8 y);
double16 __ovld __cnfn maxmag(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn maxmag(half x, half y);
half2 __ovld __cnfn maxmag(half2 x, half2 y);
half3 __ovld __cnfn maxmag(half3 x, half3 y);
half4 __ovld __cnfn maxmag(half4 x, half4 y);
half8 __ovld __cnfn maxmag(half8 x, half8 y);
half16 __ovld __cnfn maxmag(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Returns x if | x | < | y |, y if | y | < | x |, otherwise
* fmin(x, y).
*/
float __ovld __cnfn minmag(float x, float y);
float2 __ovld __cnfn minmag(float2 x, float2 y);
float3 __ovld __cnfn minmag(float3 x, float3 y);
float4 __ovld __cnfn minmag(float4 x, float4 y);
float8 __ovld __cnfn minmag(float8 x, float8 y);
float16 __ovld __cnfn minmag(float16 x, float16 y);
#ifdef cl_khr_fp64
double __ovld __cnfn minmag(double x, double y);
double2 __ovld __cnfn minmag(double2 x, double2 y);
double3 __ovld __cnfn minmag(double3 x, double3 y);
double4 __ovld __cnfn minmag(double4 x, double4 y);
double8 __ovld __cnfn minmag(double8 x, double8 y);
double16 __ovld __cnfn minmag(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn minmag(half x, half y);
half2 __ovld __cnfn minmag(half2 x, half2 y);
half3 __ovld __cnfn minmag(half3 x, half3 y);
half4 __ovld __cnfn minmag(half4 x, half4 y);
half8 __ovld __cnfn minmag(half8 x, half8 y);
half16 __ovld __cnfn minmag(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Decompose a floating-point number. The modf
* function breaks the argument x into integral and
* fractional parts, each of which has the same sign as
* the argument. It stores the integral part in the object
* pointed to by iptr.
*/
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
float __ovld modf(float x, float *iptr);
float2 __ovld modf(float2 x, float2 *iptr);
float3 __ovld modf(float3 x, float3 *iptr);
float4 __ovld modf(float4 x, float4 *iptr);
float8 __ovld modf(float8 x, float8 *iptr);
float16 __ovld modf(float16 x, float16 *iptr);
#ifdef cl_khr_fp64
double __ovld modf(double x, double *iptr);
double2 __ovld modf(double2 x, double2 *iptr);
double3 __ovld modf(double3 x, double3 *iptr);
double4 __ovld modf(double4 x, double4 *iptr);
double8 __ovld modf(double8 x, double8 *iptr);
double16 __ovld modf(double16 x, double16 *iptr);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld modf(half x, half *iptr);
half2 __ovld modf(half2 x, half2 *iptr);
half3 __ovld modf(half3 x, half3 *iptr);
half4 __ovld modf(half4 x, half4 *iptr);
half8 __ovld modf(half8 x, half8 *iptr);
half16 __ovld modf(half16 x, half16 *iptr);
#endif //cl_khr_fp16
#else
float __ovld modf(float x, __global float *iptr);
float2 __ovld modf(float2 x, __global float2 *iptr);
float3 __ovld modf(float3 x, __global float3 *iptr);
float4 __ovld modf(float4 x, __global float4 *iptr);
float8 __ovld modf(float8 x, __global float8 *iptr);
float16 __ovld modf(float16 x, __global float16 *iptr);
float __ovld modf(float x, __local float *iptr);
float2 __ovld modf(float2 x, __local float2 *iptr);
float3 __ovld modf(float3 x, __local float3 *iptr);
float4 __ovld modf(float4 x, __local float4 *iptr);
float8 __ovld modf(float8 x, __local float8 *iptr);
float16 __ovld modf(float16 x, __local float16 *iptr);
float __ovld modf(float x, __private float *iptr);
float2 __ovld modf(float2 x, __private float2 *iptr);
float3 __ovld modf(float3 x, __private float3 *iptr);
float4 __ovld modf(float4 x, __private float4 *iptr);
float8 __ovld modf(float8 x, __private float8 *iptr);
float16 __ovld modf(float16 x, __private float16 *iptr);
#ifdef cl_khr_fp64
double __ovld modf(double x, __global double *iptr);
double2 __ovld modf(double2 x, __global double2 *iptr);
double3 __ovld modf(double3 x, __global double3 *iptr);
double4 __ovld modf(double4 x, __global double4 *iptr);
double8 __ovld modf(double8 x, __global double8 *iptr);
double16 __ovld modf(double16 x, __global double16 *iptr);
double __ovld modf(double x, __local double *iptr);
double2 __ovld modf(double2 x, __local double2 *iptr);
double3 __ovld modf(double3 x, __local double3 *iptr);
double4 __ovld modf(double4 x, __local double4 *iptr);
double8 __ovld modf(double8 x, __local double8 *iptr);
double16 __ovld modf(double16 x, __local double16 *iptr);
double __ovld modf(double x, __private double *iptr);
double2 __ovld modf(double2 x, __private double2 *iptr);
double3 __ovld modf(double3 x, __private double3 *iptr);
double4 __ovld modf(double4 x, __private double4 *iptr);
double8 __ovld modf(double8 x, __private double8 *iptr);
double16 __ovld modf(double16 x, __private double16 *iptr);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld modf(half x, __global half *iptr);
half2 __ovld modf(half2 x, __global half2 *iptr);
half3 __ovld modf(half3 x, __global half3 *iptr);
half4 __ovld modf(half4 x, __global half4 *iptr);
half8 __ovld modf(half8 x, __global half8 *iptr);
half16 __ovld modf(half16 x, __global half16 *iptr);
half __ovld modf(half x, __local half *iptr);
half2 __ovld modf(half2 x, __local half2 *iptr);
half3 __ovld modf(half3 x, __local half3 *iptr);
half4 __ovld modf(half4 x, __local half4 *iptr);
half8 __ovld modf(half8 x, __local half8 *iptr);
half16 __ovld modf(half16 x, __local half16 *iptr);
half __ovld modf(half x, __private half *iptr);
half2 __ovld modf(half2 x, __private half2 *iptr);
half3 __ovld modf(half3 x, __private half3 *iptr);
half4 __ovld modf(half4 x, __private half4 *iptr);
half8 __ovld modf(half8 x, __private half8 *iptr);
half16 __ovld modf(half16 x, __private half16 *iptr);
#endif //cl_khr_fp16
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Returns a quiet NaN. The nancode may be placed
* in the significand of the resulting NaN.
*/
float __ovld __cnfn nan(uint nancode);
float2 __ovld __cnfn nan(uint2 nancode);
float3 __ovld __cnfn nan(uint3 nancode);
float4 __ovld __cnfn nan(uint4 nancode);
float8 __ovld __cnfn nan(uint8 nancode);
float16 __ovld __cnfn nan(uint16 nancode);
#ifdef cl_khr_fp64
double __ovld __cnfn nan(ulong nancode);
double2 __ovld __cnfn nan(ulong2 nancode);
double3 __ovld __cnfn nan(ulong3 nancode);
double4 __ovld __cnfn nan(ulong4 nancode);
double8 __ovld __cnfn nan(ulong8 nancode);
double16 __ovld __cnfn nan(ulong16 nancode);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn nan(ushort nancode);
half2 __ovld __cnfn nan(ushort2 nancode);
half3 __ovld __cnfn nan(ushort3 nancode);
half4 __ovld __cnfn nan(ushort4 nancode);
half8 __ovld __cnfn nan(ushort8 nancode);
half16 __ovld __cnfn nan(ushort16 nancode);
#endif //cl_khr_fp16
/**
* Computes the next representable single-precision
* floating-point value following x in the direction of
* y. Thus, if y is less than x, nextafter() returns the
* largest representable floating-point number less
* than x.
*/
float __ovld __cnfn nextafter(float x, float y);
float2 __ovld __cnfn nextafter(float2 x, float2 y);
float3 __ovld __cnfn nextafter(float3 x, float3 y);
float4 __ovld __cnfn nextafter(float4 x, float4 y);
float8 __ovld __cnfn nextafter(float8 x, float8 y);
float16 __ovld __cnfn nextafter(float16 x, float16 y);
#ifdef cl_khr_fp64
double __ovld __cnfn nextafter(double x, double y);
double2 __ovld __cnfn nextafter(double2 x, double2 y);
double3 __ovld __cnfn nextafter(double3 x, double3 y);
double4 __ovld __cnfn nextafter(double4 x, double4 y);
double8 __ovld __cnfn nextafter(double8 x, double8 y);
double16 __ovld __cnfn nextafter(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn nextafter(half x, half y);
half2 __ovld __cnfn nextafter(half2 x, half2 y);
half3 __ovld __cnfn nextafter(half3 x, half3 y);
half4 __ovld __cnfn nextafter(half4 x, half4 y);
half8 __ovld __cnfn nextafter(half8 x, half8 y);
half16 __ovld __cnfn nextafter(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Compute x to the power y.
*/
float __ovld __cnfn pow(float x, float y);
float2 __ovld __cnfn pow(float2 x, float2 y);
float3 __ovld __cnfn pow(float3 x, float3 y);
float4 __ovld __cnfn pow(float4 x, float4 y);
float8 __ovld __cnfn pow(float8 x, float8 y);
float16 __ovld __cnfn pow(float16 x, float16 y);
#ifdef cl_khr_fp64
double __ovld __cnfn pow(double x, double y);
double2 __ovld __cnfn pow(double2 x, double2 y);
double3 __ovld __cnfn pow(double3 x, double3 y);
double4 __ovld __cnfn pow(double4 x, double4 y);
double8 __ovld __cnfn pow(double8 x, double8 y);
double16 __ovld __cnfn pow(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn pow(half x, half y);
half2 __ovld __cnfn pow(half2 x, half2 y);
half3 __ovld __cnfn pow(half3 x, half3 y);
half4 __ovld __cnfn pow(half4 x, half4 y);
half8 __ovld __cnfn pow(half8 x, half8 y);
half16 __ovld __cnfn pow(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Compute x to the power y, where y is an integer.
*/
float __ovld __cnfn pown(float x, int y);
float2 __ovld __cnfn pown(float2 x, int2 y);
float3 __ovld __cnfn pown(float3 x, int3 y);
float4 __ovld __cnfn pown(float4 x, int4 y);
float8 __ovld __cnfn pown(float8 x, int8 y);
float16 __ovld __cnfn pown(float16 x, int16 y);
#ifdef cl_khr_fp64
double __ovld __cnfn pown(double x, int y);
double2 __ovld __cnfn pown(double2 x, int2 y);
double3 __ovld __cnfn pown(double3 x, int3 y);
double4 __ovld __cnfn pown(double4 x, int4 y);
double8 __ovld __cnfn pown(double8 x, int8 y);
double16 __ovld __cnfn pown(double16 x, int16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn pown(half x, int y);
half2 __ovld __cnfn pown(half2 x, int2 y);
half3 __ovld __cnfn pown(half3 x, int3 y);
half4 __ovld __cnfn pown(half4 x, int4 y);
half8 __ovld __cnfn pown(half8 x, int8 y);
half16 __ovld __cnfn pown(half16 x, int16 y);
#endif //cl_khr_fp16
/**
* Compute x to the power y, where x is >= 0.
*/
float __ovld __cnfn powr(float x, float y);
float2 __ovld __cnfn powr(float2 x, float2 y);
float3 __ovld __cnfn powr(float3 x, float3 y);
float4 __ovld __cnfn powr(float4 x, float4 y);
float8 __ovld __cnfn powr(float8 x, float8 y);
float16 __ovld __cnfn powr(float16 x, float16 y);
#ifdef cl_khr_fp64
double __ovld __cnfn powr(double x, double y);
double2 __ovld __cnfn powr(double2 x, double2 y);
double3 __ovld __cnfn powr(double3 x, double3 y);
double4 __ovld __cnfn powr(double4 x, double4 y);
double8 __ovld __cnfn powr(double8 x, double8 y);
double16 __ovld __cnfn powr(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn powr(half x, half y);
half2 __ovld __cnfn powr(half2 x, half2 y);
half3 __ovld __cnfn powr(half3 x, half3 y);
half4 __ovld __cnfn powr(half4 x, half4 y);
half8 __ovld __cnfn powr(half8 x, half8 y);
half16 __ovld __cnfn powr(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Compute the value r such that r = x - n*y, where n
* is the integer nearest the exact value of x/y. If there
* are two integers closest to x/y, n shall be the even
* one. If r is zero, it is given the same sign as x.
*/
float __ovld __cnfn remainder(float x, float y);
float2 __ovld __cnfn remainder(float2 x, float2 y);
float3 __ovld __cnfn remainder(float3 x, float3 y);
float4 __ovld __cnfn remainder(float4 x, float4 y);
float8 __ovld __cnfn remainder(float8 x, float8 y);
float16 __ovld __cnfn remainder(float16 x, float16 y);
#ifdef cl_khr_fp64
double __ovld __cnfn remainder(double x, double y);
double2 __ovld __cnfn remainder(double2 x, double2 y);
double3 __ovld __cnfn remainder(double3 x, double3 y);
double4 __ovld __cnfn remainder(double4 x, double4 y);
double8 __ovld __cnfn remainder(double8 x, double8 y);
double16 __ovld __cnfn remainder(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn remainder(half x, half y);
half2 __ovld __cnfn remainder(half2 x, half2 y);
half3 __ovld __cnfn remainder(half3 x, half3 y);
half4 __ovld __cnfn remainder(half4 x, half4 y);
half8 __ovld __cnfn remainder(half8 x, half8 y);
half16 __ovld __cnfn remainder(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* The remquo function computes the value r such
* that r = x - n*y, where n is the integer nearest the
* exact value of x/y. If there are two integers closest
* to x/y, n shall be the even one. If r is zero, it is
* given the same sign as x. This is the same value
* that is returned by the remainder function.
* remquo also calculates the lower seven bits of the
* integral quotient x/y, and gives that value the same
* sign as x/y. It stores this signed value in the object
* pointed to by quo.
*/
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
float __ovld remquo(float x, float y, int *quo);
float2 __ovld remquo(float2 x, float2 y, int2 *quo);
float3 __ovld remquo(float3 x, float3 y, int3 *quo);
float4 __ovld remquo(float4 x, float4 y, int4 *quo);
float8 __ovld remquo(float8 x, float8 y, int8 *quo);
float16 __ovld remquo(float16 x, float16 y, int16 *quo);
#ifdef cl_khr_fp64
double __ovld remquo(double x, double y, int *quo);
double2 __ovld remquo(double2 x, double2 y, int2 *quo);
double3 __ovld remquo(double3 x, double3 y, int3 *quo);
double4 __ovld remquo(double4 x, double4 y, int4 *quo);
double8 __ovld remquo(double8 x, double8 y, int8 *quo);
double16 __ovld remquo(double16 x, double16 y, int16 *quo);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld remquo(half x, half y, int *quo);
half2 __ovld remquo(half2 x, half2 y, int2 *quo);
half3 __ovld remquo(half3 x, half3 y, int3 *quo);
half4 __ovld remquo(half4 x, half4 y, int4 *quo);
half8 __ovld remquo(half8 x, half8 y, int8 *quo);
half16 __ovld remquo(half16 x, half16 y, int16 *quo);
#endif //cl_khr_fp16
#else
float __ovld remquo(float x, float y, __global int *quo);
float2 __ovld remquo(float2 x, float2 y, __global int2 *quo);
float3 __ovld remquo(float3 x, float3 y, __global int3 *quo);
float4 __ovld remquo(float4 x, float4 y, __global int4 *quo);
float8 __ovld remquo(float8 x, float8 y, __global int8 *quo);
float16 __ovld remquo(float16 x, float16 y, __global int16 *quo);
float __ovld remquo(float x, float y, __local int *quo);
float2 __ovld remquo(float2 x, float2 y, __local int2 *quo);
float3 __ovld remquo(float3 x, float3 y, __local int3 *quo);
float4 __ovld remquo(float4 x, float4 y, __local int4 *quo);
float8 __ovld remquo(float8 x, float8 y, __local int8 *quo);
float16 __ovld remquo(float16 x, float16 y, __local int16 *quo);
float __ovld remquo(float x, float y, __private int *quo);
float2 __ovld remquo(float2 x, float2 y, __private int2 *quo);
float3 __ovld remquo(float3 x, float3 y, __private int3 *quo);
float4 __ovld remquo(float4 x, float4 y, __private int4 *quo);
float8 __ovld remquo(float8 x, float8 y, __private int8 *quo);
float16 __ovld remquo(float16 x, float16 y, __private int16 *quo);
#ifdef cl_khr_fp64
double __ovld remquo(double x, double y, __global int *quo);
double2 __ovld remquo(double2 x, double2 y, __global int2 *quo);
double3 __ovld remquo(double3 x, double3 y, __global int3 *quo);
double4 __ovld remquo(double4 x, double4 y, __global int4 *quo);
double8 __ovld remquo(double8 x, double8 y, __global int8 *quo);
double16 __ovld remquo(double16 x, double16 y, __global int16 *quo);
double __ovld remquo(double x, double y, __local int *quo);
double2 __ovld remquo(double2 x, double2 y, __local int2 *quo);
double3 __ovld remquo(double3 x, double3 y, __local int3 *quo);
double4 __ovld remquo(double4 x, double4 y, __local int4 *quo);
double8 __ovld remquo(double8 x, double8 y, __local int8 *quo);
double16 __ovld remquo(double16 x, double16 y, __local int16 *quo);
double __ovld remquo(double x, double y, __private int *quo);
double2 __ovld remquo(double2 x, double2 y, __private int2 *quo);
double3 __ovld remquo(double3 x, double3 y, __private int3 *quo);
double4 __ovld remquo(double4 x, double4 y, __private int4 *quo);
double8 __ovld remquo(double8 x, double8 y, __private int8 *quo);
double16 __ovld remquo(double16 x, double16 y, __private int16 *quo);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld remquo(half x, half y, __global int *quo);
half2 __ovld remquo(half2 x, half2 y, __global int2 *quo);
half3 __ovld remquo(half3 x, half3 y, __global int3 *quo);
half4 __ovld remquo(half4 x, half4 y, __global int4 *quo);
half8 __ovld remquo(half8 x, half8 y, __global int8 *quo);
half16 __ovld remquo(half16 x, half16 y, __global int16 *quo);
half __ovld remquo(half x, half y, __local int *quo);
half2 __ovld remquo(half2 x, half2 y, __local int2 *quo);
half3 __ovld remquo(half3 x, half3 y, __local int3 *quo);
half4 __ovld remquo(half4 x, half4 y, __local int4 *quo);
half8 __ovld remquo(half8 x, half8 y, __local int8 *quo);
half16 __ovld remquo(half16 x, half16 y, __local int16 *quo);
half __ovld remquo(half x, half y, __private int *quo);
half2 __ovld remquo(half2 x, half2 y, __private int2 *quo);
half3 __ovld remquo(half3 x, half3 y, __private int3 *quo);
half4 __ovld remquo(half4 x, half4 y, __private int4 *quo);
half8 __ovld remquo(half8 x, half8 y, __private int8 *quo);
half16 __ovld remquo(half16 x, half16 y, __private int16 *quo);
#endif //cl_khr_fp16
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Round to integral value (using round to nearest
* even rounding mode) in floating-point format.
* Refer to section 7.1 for description of rounding
* modes.
*/
float __ovld __cnfn rint(float);
float2 __ovld __cnfn rint(float2);
float3 __ovld __cnfn rint(float3);
float4 __ovld __cnfn rint(float4);
float8 __ovld __cnfn rint(float8);
float16 __ovld __cnfn rint(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn rint(double);
double2 __ovld __cnfn rint(double2);
double3 __ovld __cnfn rint(double3);
double4 __ovld __cnfn rint(double4);
double8 __ovld __cnfn rint(double8);
double16 __ovld __cnfn rint(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn rint(half);
half2 __ovld __cnfn rint(half2);
half3 __ovld __cnfn rint(half3);
half4 __ovld __cnfn rint(half4);
half8 __ovld __cnfn rint(half8);
half16 __ovld __cnfn rint(half16);
#endif //cl_khr_fp16
/**
* Compute x to the power 1/y.
*/
float __ovld __cnfn rootn(float x, int y);
float2 __ovld __cnfn rootn(float2 x, int2 y);
float3 __ovld __cnfn rootn(float3 x, int3 y);
float4 __ovld __cnfn rootn(float4 x, int4 y);
float8 __ovld __cnfn rootn(float8 x, int8 y);
float16 __ovld __cnfn rootn(float16 x, int16 y);
#ifdef cl_khr_fp64
double __ovld __cnfn rootn(double x, int y);
double2 __ovld __cnfn rootn(double2 x, int2 y);
double3 __ovld __cnfn rootn(double3 x, int3 y);
double4 __ovld __cnfn rootn(double4 x, int4 y);
double8 __ovld __cnfn rootn(double8 x, int8 y);
double16 __ovld __cnfn rootn(double16 x, int16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn rootn(half x, int y);
half2 __ovld __cnfn rootn(half2 x, int2 y);
half3 __ovld __cnfn rootn(half3 x, int3 y);
half4 __ovld __cnfn rootn(half4 x, int4 y);
half8 __ovld __cnfn rootn(half8 x, int8 y);
half16 __ovld __cnfn rootn(half16 x, int16 y);
#endif //cl_khr_fp16
/**
* Return the integral value nearest to x rounding
* halfway cases away from zero, regardless of the
* current rounding direction.
*/
float __ovld __cnfn round(float x);
float2 __ovld __cnfn round(float2 x);
float3 __ovld __cnfn round(float3 x);
float4 __ovld __cnfn round(float4 x);
float8 __ovld __cnfn round(float8 x);
float16 __ovld __cnfn round(float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn round(double x);
double2 __ovld __cnfn round(double2 x);
double3 __ovld __cnfn round(double3 x);
double4 __ovld __cnfn round(double4 x);
double8 __ovld __cnfn round(double8 x);
double16 __ovld __cnfn round(double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn round(half x);
half2 __ovld __cnfn round(half2 x);
half3 __ovld __cnfn round(half3 x);
half4 __ovld __cnfn round(half4 x);
half8 __ovld __cnfn round(half8 x);
half16 __ovld __cnfn round(half16 x);
#endif //cl_khr_fp16
/**
* Compute inverse square root.
*/
float __ovld __cnfn rsqrt(float);
float2 __ovld __cnfn rsqrt(float2);
float3 __ovld __cnfn rsqrt(float3);
float4 __ovld __cnfn rsqrt(float4);
float8 __ovld __cnfn rsqrt(float8);
float16 __ovld __cnfn rsqrt(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn rsqrt(double);
double2 __ovld __cnfn rsqrt(double2);
double3 __ovld __cnfn rsqrt(double3);
double4 __ovld __cnfn rsqrt(double4);
double8 __ovld __cnfn rsqrt(double8);
double16 __ovld __cnfn rsqrt(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn rsqrt(half);
half2 __ovld __cnfn rsqrt(half2);
half3 __ovld __cnfn rsqrt(half3);
half4 __ovld __cnfn rsqrt(half4);
half8 __ovld __cnfn rsqrt(half8);
half16 __ovld __cnfn rsqrt(half16);
#endif //cl_khr_fp16
/**
* Compute sine.
*/
float __ovld __cnfn sin(float);
float2 __ovld __cnfn sin(float2);
float3 __ovld __cnfn sin(float3);
float4 __ovld __cnfn sin(float4);
float8 __ovld __cnfn sin(float8);
float16 __ovld __cnfn sin(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn sin(double);
double2 __ovld __cnfn sin(double2);
double3 __ovld __cnfn sin(double3);
double4 __ovld __cnfn sin(double4);
double8 __ovld __cnfn sin(double8);
double16 __ovld __cnfn sin(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn sin(half);
half2 __ovld __cnfn sin(half2);
half3 __ovld __cnfn sin(half3);
half4 __ovld __cnfn sin(half4);
half8 __ovld __cnfn sin(half8);
half16 __ovld __cnfn sin(half16);
#endif //cl_khr_fp16
/**
* Compute sine and cosine of x. The computed sine
* is the return value and computed cosine is returned
* in cosval.
*/
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
float __ovld sincos(float x, float *cosval);
float2 __ovld sincos(float2 x, float2 *cosval);
float3 __ovld sincos(float3 x, float3 *cosval);
float4 __ovld sincos(float4 x, float4 *cosval);
float8 __ovld sincos(float8 x, float8 *cosval);
float16 __ovld sincos(float16 x, float16 *cosval);
#ifdef cl_khr_fp64
double __ovld sincos(double x, double *cosval);
double2 __ovld sincos(double2 x, double2 *cosval);
double3 __ovld sincos(double3 x, double3 *cosval);
double4 __ovld sincos(double4 x, double4 *cosval);
double8 __ovld sincos(double8 x, double8 *cosval);
double16 __ovld sincos(double16 x, double16 *cosval);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld sincos(half x, half *cosval);
half2 __ovld sincos(half2 x, half2 *cosval);
half3 __ovld sincos(half3 x, half3 *cosval);
half4 __ovld sincos(half4 x, half4 *cosval);
half8 __ovld sincos(half8 x, half8 *cosval);
half16 __ovld sincos(half16 x, half16 *cosval);
#endif //cl_khr_fp16
#else
float __ovld sincos(float x, __global float *cosval);
float2 __ovld sincos(float2 x, __global float2 *cosval);
float3 __ovld sincos(float3 x, __global float3 *cosval);
float4 __ovld sincos(float4 x, __global float4 *cosval);
float8 __ovld sincos(float8 x, __global float8 *cosval);
float16 __ovld sincos(float16 x, __global float16 *cosval);
float __ovld sincos(float x, __local float *cosval);
float2 __ovld sincos(float2 x, __local float2 *cosval);
float3 __ovld sincos(float3 x, __local float3 *cosval);
float4 __ovld sincos(float4 x, __local float4 *cosval);
float8 __ovld sincos(float8 x, __local float8 *cosval);
float16 __ovld sincos(float16 x, __local float16 *cosval);
float __ovld sincos(float x, __private float *cosval);
float2 __ovld sincos(float2 x, __private float2 *cosval);
float3 __ovld sincos(float3 x, __private float3 *cosval);
float4 __ovld sincos(float4 x, __private float4 *cosval);
float8 __ovld sincos(float8 x, __private float8 *cosval);
float16 __ovld sincos(float16 x, __private float16 *cosval);
#ifdef cl_khr_fp64
double __ovld sincos(double x, __global double *cosval);
double2 __ovld sincos(double2 x, __global double2 *cosval);
double3 __ovld sincos(double3 x, __global double3 *cosval);
double4 __ovld sincos(double4 x, __global double4 *cosval);
double8 __ovld sincos(double8 x, __global double8 *cosval);
double16 __ovld sincos(double16 x, __global double16 *cosval);
double __ovld sincos(double x, __local double *cosval);
double2 __ovld sincos(double2 x, __local double2 *cosval);
double3 __ovld sincos(double3 x, __local double3 *cosval);
double4 __ovld sincos(double4 x, __local double4 *cosval);
double8 __ovld sincos(double8 x, __local double8 *cosval);
double16 __ovld sincos(double16 x, __local double16 *cosval);
double __ovld sincos(double x, __private double *cosval);
double2 __ovld sincos(double2 x, __private double2 *cosval);
double3 __ovld sincos(double3 x, __private double3 *cosval);
double4 __ovld sincos(double4 x, __private double4 *cosval);
double8 __ovld sincos(double8 x, __private double8 *cosval);
double16 __ovld sincos(double16 x, __private double16 *cosval);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld sincos(half x, __global half *cosval);
half2 __ovld sincos(half2 x, __global half2 *cosval);
half3 __ovld sincos(half3 x, __global half3 *cosval);
half4 __ovld sincos(half4 x, __global half4 *cosval);
half8 __ovld sincos(half8 x, __global half8 *cosval);
half16 __ovld sincos(half16 x, __global half16 *cosval);
half __ovld sincos(half x, __local half *cosval);
half2 __ovld sincos(half2 x, __local half2 *cosval);
half3 __ovld sincos(half3 x, __local half3 *cosval);
half4 __ovld sincos(half4 x, __local half4 *cosval);
half8 __ovld sincos(half8 x, __local half8 *cosval);
half16 __ovld sincos(half16 x, __local half16 *cosval);
half __ovld sincos(half x, __private half *cosval);
half2 __ovld sincos(half2 x, __private half2 *cosval);
half3 __ovld sincos(half3 x, __private half3 *cosval);
half4 __ovld sincos(half4 x, __private half4 *cosval);
half8 __ovld sincos(half8 x, __private half8 *cosval);
half16 __ovld sincos(half16 x, __private half16 *cosval);
#endif //cl_khr_fp16
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Compute hyperbolic sine.
*/
float __ovld __cnfn sinh(float);
float2 __ovld __cnfn sinh(float2);
float3 __ovld __cnfn sinh(float3);
float4 __ovld __cnfn sinh(float4);
float8 __ovld __cnfn sinh(float8);
float16 __ovld __cnfn sinh(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn sinh(double);
double2 __ovld __cnfn sinh(double2);
double3 __ovld __cnfn sinh(double3);
double4 __ovld __cnfn sinh(double4);
double8 __ovld __cnfn sinh(double8);
double16 __ovld __cnfn sinh(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn sinh(half);
half2 __ovld __cnfn sinh(half2);
half3 __ovld __cnfn sinh(half3);
half4 __ovld __cnfn sinh(half4);
half8 __ovld __cnfn sinh(half8);
half16 __ovld __cnfn sinh(half16);
#endif //cl_khr_fp16
/**
* Compute sin (PI * x).
*/
float __ovld __cnfn sinpi(float x);
float2 __ovld __cnfn sinpi(float2 x);
float3 __ovld __cnfn sinpi(float3 x);
float4 __ovld __cnfn sinpi(float4 x);
float8 __ovld __cnfn sinpi(float8 x);
float16 __ovld __cnfn sinpi(float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn sinpi(double x);
double2 __ovld __cnfn sinpi(double2 x);
double3 __ovld __cnfn sinpi(double3 x);
double4 __ovld __cnfn sinpi(double4 x);
double8 __ovld __cnfn sinpi(double8 x);
double16 __ovld __cnfn sinpi(double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn sinpi(half x);
half2 __ovld __cnfn sinpi(half2 x);
half3 __ovld __cnfn sinpi(half3 x);
half4 __ovld __cnfn sinpi(half4 x);
half8 __ovld __cnfn sinpi(half8 x);
half16 __ovld __cnfn sinpi(half16 x);
#endif //cl_khr_fp16
/**
* Compute square root.
*/
float __ovld __cnfn sqrt(float);
float2 __ovld __cnfn sqrt(float2);
float3 __ovld __cnfn sqrt(float3);
float4 __ovld __cnfn sqrt(float4);
float8 __ovld __cnfn sqrt(float8);
float16 __ovld __cnfn sqrt(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn sqrt(double);
double2 __ovld __cnfn sqrt(double2);
double3 __ovld __cnfn sqrt(double3);
double4 __ovld __cnfn sqrt(double4);
double8 __ovld __cnfn sqrt(double8);
double16 __ovld __cnfn sqrt(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn sqrt(half);
half2 __ovld __cnfn sqrt(half2);
half3 __ovld __cnfn sqrt(half3);
half4 __ovld __cnfn sqrt(half4);
half8 __ovld __cnfn sqrt(half8);
half16 __ovld __cnfn sqrt(half16);
#endif //cl_khr_fp16
/**
* Compute tangent.
*/
float __ovld __cnfn tan(float);
float2 __ovld __cnfn tan(float2);
float3 __ovld __cnfn tan(float3);
float4 __ovld __cnfn tan(float4);
float8 __ovld __cnfn tan(float8);
float16 __ovld __cnfn tan(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn tan(double);
double2 __ovld __cnfn tan(double2);
double3 __ovld __cnfn tan(double3);
double4 __ovld __cnfn tan(double4);
double8 __ovld __cnfn tan(double8);
double16 __ovld __cnfn tan(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn tan(half);
half2 __ovld __cnfn tan(half2);
half3 __ovld __cnfn tan(half3);
half4 __ovld __cnfn tan(half4);
half8 __ovld __cnfn tan(half8);
half16 __ovld __cnfn tan(half16);
#endif //cl_khr_fp16
/**
* Compute hyperbolic tangent.
*/
float __ovld __cnfn tanh(float);
float2 __ovld __cnfn tanh(float2);
float3 __ovld __cnfn tanh(float3);
float4 __ovld __cnfn tanh(float4);
float8 __ovld __cnfn tanh(float8);
float16 __ovld __cnfn tanh(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn tanh(double);
double2 __ovld __cnfn tanh(double2);
double3 __ovld __cnfn tanh(double3);
double4 __ovld __cnfn tanh(double4);
double8 __ovld __cnfn tanh(double8);
double16 __ovld __cnfn tanh(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn tanh(half);
half2 __ovld __cnfn tanh(half2);
half3 __ovld __cnfn tanh(half3);
half4 __ovld __cnfn tanh(half4);
half8 __ovld __cnfn tanh(half8);
half16 __ovld __cnfn tanh(half16);
#endif //cl_khr_fp16
/**
* Compute tan (PI * x).
*/
float __ovld __cnfn tanpi(float x);
float2 __ovld __cnfn tanpi(float2 x);
float3 __ovld __cnfn tanpi(float3 x);
float4 __ovld __cnfn tanpi(float4 x);
float8 __ovld __cnfn tanpi(float8 x);
float16 __ovld __cnfn tanpi(float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn tanpi(double x);
double2 __ovld __cnfn tanpi(double2 x);
double3 __ovld __cnfn tanpi(double3 x);
double4 __ovld __cnfn tanpi(double4 x);
double8 __ovld __cnfn tanpi(double8 x);
double16 __ovld __cnfn tanpi(double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn tanpi(half x);
half2 __ovld __cnfn tanpi(half2 x);
half3 __ovld __cnfn tanpi(half3 x);
half4 __ovld __cnfn tanpi(half4 x);
half8 __ovld __cnfn tanpi(half8 x);
half16 __ovld __cnfn tanpi(half16 x);
#endif //cl_khr_fp16
/**
* Compute the gamma function.
*/
float __ovld __cnfn tgamma(float);
float2 __ovld __cnfn tgamma(float2);
float3 __ovld __cnfn tgamma(float3);
float4 __ovld __cnfn tgamma(float4);
float8 __ovld __cnfn tgamma(float8);
float16 __ovld __cnfn tgamma(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn tgamma(double);
double2 __ovld __cnfn tgamma(double2);
double3 __ovld __cnfn tgamma(double3);
double4 __ovld __cnfn tgamma(double4);
double8 __ovld __cnfn tgamma(double8);
double16 __ovld __cnfn tgamma(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn tgamma(half);
half2 __ovld __cnfn tgamma(half2);
half3 __ovld __cnfn tgamma(half3);
half4 __ovld __cnfn tgamma(half4);
half8 __ovld __cnfn tgamma(half8);
half16 __ovld __cnfn tgamma(half16);
#endif //cl_khr_fp16
/**
* Round to integral value using the round to zero
* rounding mode.
*/
float __ovld __cnfn trunc(float);
float2 __ovld __cnfn trunc(float2);
float3 __ovld __cnfn trunc(float3);
float4 __ovld __cnfn trunc(float4);
float8 __ovld __cnfn trunc(float8);
float16 __ovld __cnfn trunc(float16);
#ifdef cl_khr_fp64
double __ovld __cnfn trunc(double);
double2 __ovld __cnfn trunc(double2);
double3 __ovld __cnfn trunc(double3);
double4 __ovld __cnfn trunc(double4);
double8 __ovld __cnfn trunc(double8);
double16 __ovld __cnfn trunc(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn trunc(half);
half2 __ovld __cnfn trunc(half2);
half3 __ovld __cnfn trunc(half3);
half4 __ovld __cnfn trunc(half4);
half8 __ovld __cnfn trunc(half8);
half16 __ovld __cnfn trunc(half16);
#endif //cl_khr_fp16
/**
* Compute cosine. x must be in the range -2^16 ... +2^16.
*/
float __ovld __cnfn half_cos(float x);
float2 __ovld __cnfn half_cos(float2 x);
float3 __ovld __cnfn half_cos(float3 x);
float4 __ovld __cnfn half_cos(float4 x);
float8 __ovld __cnfn half_cos(float8 x);
float16 __ovld __cnfn half_cos(float16 x);
/**
* Compute x / y.
*/
float __ovld __cnfn half_divide(float x, float y);
float2 __ovld __cnfn half_divide(float2 x, float2 y);
float3 __ovld __cnfn half_divide(float3 x, float3 y);
float4 __ovld __cnfn half_divide(float4 x, float4 y);
float8 __ovld __cnfn half_divide(float8 x, float8 y);
float16 __ovld __cnfn half_divide(float16 x, float16 y);
/**
* Compute the base- e exponential of x.
*/
float __ovld __cnfn half_exp(float x);
float2 __ovld __cnfn half_exp(float2 x);
float3 __ovld __cnfn half_exp(float3 x);
float4 __ovld __cnfn half_exp(float4 x);
float8 __ovld __cnfn half_exp(float8 x);
float16 __ovld __cnfn half_exp(float16 x);
/**
* Compute the base- 2 exponential of x.
*/
float __ovld __cnfn half_exp2(float x);
float2 __ovld __cnfn half_exp2(float2 x);
float3 __ovld __cnfn half_exp2(float3 x);
float4 __ovld __cnfn half_exp2(float4 x);
float8 __ovld __cnfn half_exp2(float8 x);
float16 __ovld __cnfn half_exp2(float16 x);
/**
* Compute the base- 10 exponential of x.
*/
float __ovld __cnfn half_exp10(float x);
float2 __ovld __cnfn half_exp10(float2 x);
float3 __ovld __cnfn half_exp10(float3 x);
float4 __ovld __cnfn half_exp10(float4 x);
float8 __ovld __cnfn half_exp10(float8 x);
float16 __ovld __cnfn half_exp10(float16 x);
/**
* Compute natural logarithm.
*/
float __ovld __cnfn half_log(float x);
float2 __ovld __cnfn half_log(float2 x);
float3 __ovld __cnfn half_log(float3 x);
float4 __ovld __cnfn half_log(float4 x);
float8 __ovld __cnfn half_log(float8 x);
float16 __ovld __cnfn half_log(float16 x);
/**
* Compute a base 2 logarithm.
*/
float __ovld __cnfn half_log2(float x);
float2 __ovld __cnfn half_log2(float2 x);
float3 __ovld __cnfn half_log2(float3 x);
float4 __ovld __cnfn half_log2(float4 x);
float8 __ovld __cnfn half_log2(float8 x);
float16 __ovld __cnfn half_log2(float16 x);
/**
* Compute a base 10 logarithm.
*/
float __ovld __cnfn half_log10(float x);
float2 __ovld __cnfn half_log10(float2 x);
float3 __ovld __cnfn half_log10(float3 x);
float4 __ovld __cnfn half_log10(float4 x);
float8 __ovld __cnfn half_log10(float8 x);
float16 __ovld __cnfn half_log10(float16 x);
/**
* Compute x to the power y, where x is >= 0.
*/
float __ovld __cnfn half_powr(float x, float y);
float2 __ovld __cnfn half_powr(float2 x, float2 y);
float3 __ovld __cnfn half_powr(float3 x, float3 y);
float4 __ovld __cnfn half_powr(float4 x, float4 y);
float8 __ovld __cnfn half_powr(float8 x, float8 y);
float16 __ovld __cnfn half_powr(float16 x, float16 y);
/**
* Compute reciprocal.
*/
float __ovld __cnfn half_recip(float x);
float2 __ovld __cnfn half_recip(float2 x);
float3 __ovld __cnfn half_recip(float3 x);
float4 __ovld __cnfn half_recip(float4 x);
float8 __ovld __cnfn half_recip(float8 x);
float16 __ovld __cnfn half_recip(float16 x);
/**
* Compute inverse square root.
*/
float __ovld __cnfn half_rsqrt(float x);
float2 __ovld __cnfn half_rsqrt(float2 x);
float3 __ovld __cnfn half_rsqrt(float3 x);
float4 __ovld __cnfn half_rsqrt(float4 x);
float8 __ovld __cnfn half_rsqrt(float8 x);
float16 __ovld __cnfn half_rsqrt(float16 x);
/**
* Compute sine. x must be in the range -2^16 ... +2^16.
*/
float __ovld __cnfn half_sin(float x);
float2 __ovld __cnfn half_sin(float2 x);
float3 __ovld __cnfn half_sin(float3 x);
float4 __ovld __cnfn half_sin(float4 x);
float8 __ovld __cnfn half_sin(float8 x);
float16 __ovld __cnfn half_sin(float16 x);
/**
* Compute square root.
*/
float __ovld __cnfn half_sqrt(float x);
float2 __ovld __cnfn half_sqrt(float2 x);
float3 __ovld __cnfn half_sqrt(float3 x);
float4 __ovld __cnfn half_sqrt(float4 x);
float8 __ovld __cnfn half_sqrt(float8 x);
float16 __ovld __cnfn half_sqrt(float16 x);
/**
* Compute tangent. x must be in the range -216 ... +216.
*/
float __ovld __cnfn half_tan(float x);
float2 __ovld __cnfn half_tan(float2 x);
float3 __ovld __cnfn half_tan(float3 x);
float4 __ovld __cnfn half_tan(float4 x);
float8 __ovld __cnfn half_tan(float8 x);
float16 __ovld __cnfn half_tan(float16 x);
/**
* Compute cosine over an implementation-defined range.
* The maximum error is implementation-defined.
*/
float __ovld __cnfn native_cos(float x);
float2 __ovld __cnfn native_cos(float2 x);
float3 __ovld __cnfn native_cos(float3 x);
float4 __ovld __cnfn native_cos(float4 x);
float8 __ovld __cnfn native_cos(float8 x);
float16 __ovld __cnfn native_cos(float16 x);
/**
* Compute x / y over an implementation-defined range.
* The maximum error is implementation-defined.
*/
float __ovld __cnfn native_divide(float x, float y);
float2 __ovld __cnfn native_divide(float2 x, float2 y);
float3 __ovld __cnfn native_divide(float3 x, float3 y);
float4 __ovld __cnfn native_divide(float4 x, float4 y);
float8 __ovld __cnfn native_divide(float8 x, float8 y);
float16 __ovld __cnfn native_divide(float16 x, float16 y);
/**
* Compute the base- e exponential of x over an
* implementation-defined range. The maximum error is
* implementation-defined.
*/
float __ovld __cnfn native_exp(float x);
float2 __ovld __cnfn native_exp(float2 x);
float3 __ovld __cnfn native_exp(float3 x);
float4 __ovld __cnfn native_exp(float4 x);
float8 __ovld __cnfn native_exp(float8 x);
float16 __ovld __cnfn native_exp(float16 x);
/**
* Compute the base- 2 exponential of x over an
* implementation-defined range. The maximum error is
* implementation-defined.
*/
float __ovld __cnfn native_exp2(float x);
float2 __ovld __cnfn native_exp2(float2 x);
float3 __ovld __cnfn native_exp2(float3 x);
float4 __ovld __cnfn native_exp2(float4 x);
float8 __ovld __cnfn native_exp2(float8 x);
float16 __ovld __cnfn native_exp2(float16 x);
/**
* Compute the base- 10 exponential of x over an
* implementation-defined range. The maximum error is
* implementation-defined.
*/
float __ovld __cnfn native_exp10(float x);
float2 __ovld __cnfn native_exp10(float2 x);
float3 __ovld __cnfn native_exp10(float3 x);
float4 __ovld __cnfn native_exp10(float4 x);
float8 __ovld __cnfn native_exp10(float8 x);
float16 __ovld __cnfn native_exp10(float16 x);
/**
* Compute natural logarithm over an implementationdefined
* range. The maximum error is implementation
* defined.
*/
float __ovld __cnfn native_log(float x);
float2 __ovld __cnfn native_log(float2 x);
float3 __ovld __cnfn native_log(float3 x);
float4 __ovld __cnfn native_log(float4 x);
float8 __ovld __cnfn native_log(float8 x);
float16 __ovld __cnfn native_log(float16 x);
/**
* Compute a base 2 logarithm over an implementationdefined
* range. The maximum error is implementationdefined.
*/
float __ovld __cnfn native_log2(float x);
float2 __ovld __cnfn native_log2(float2 x);
float3 __ovld __cnfn native_log2(float3 x);
float4 __ovld __cnfn native_log2(float4 x);
float8 __ovld __cnfn native_log2(float8 x);
float16 __ovld __cnfn native_log2(float16 x);
/**
* Compute a base 10 logarithm over an implementationdefined
* range. The maximum error is implementationdefined.
*/
float __ovld __cnfn native_log10(float x);
float2 __ovld __cnfn native_log10(float2 x);
float3 __ovld __cnfn native_log10(float3 x);
float4 __ovld __cnfn native_log10(float4 x);
float8 __ovld __cnfn native_log10(float8 x);
float16 __ovld __cnfn native_log10(float16 x);
/**
* Compute x to the power y, where x is >= 0. The range of
* x and y are implementation-defined. The maximum error
* is implementation-defined.
*/
float __ovld __cnfn native_powr(float x, float y);
float2 __ovld __cnfn native_powr(float2 x, float2 y);
float3 __ovld __cnfn native_powr(float3 x, float3 y);
float4 __ovld __cnfn native_powr(float4 x, float4 y);
float8 __ovld __cnfn native_powr(float8 x, float8 y);
float16 __ovld __cnfn native_powr(float16 x, float16 y);
/**
* Compute reciprocal over an implementation-defined
* range. The maximum error is implementation-defined.
*/
float __ovld __cnfn native_recip(float x);
float2 __ovld __cnfn native_recip(float2 x);
float3 __ovld __cnfn native_recip(float3 x);
float4 __ovld __cnfn native_recip(float4 x);
float8 __ovld __cnfn native_recip(float8 x);
float16 __ovld __cnfn native_recip(float16 x);
/**
* Compute inverse square root over an implementationdefined
* range. The maximum error is implementationdefined.
*/
float __ovld __cnfn native_rsqrt(float x);
float2 __ovld __cnfn native_rsqrt(float2 x);
float3 __ovld __cnfn native_rsqrt(float3 x);
float4 __ovld __cnfn native_rsqrt(float4 x);
float8 __ovld __cnfn native_rsqrt(float8 x);
float16 __ovld __cnfn native_rsqrt(float16 x);
/**
* Compute sine over an implementation-defined range.
* The maximum error is implementation-defined.
*/
float __ovld __cnfn native_sin(float x);
float2 __ovld __cnfn native_sin(float2 x);
float3 __ovld __cnfn native_sin(float3 x);
float4 __ovld __cnfn native_sin(float4 x);
float8 __ovld __cnfn native_sin(float8 x);
float16 __ovld __cnfn native_sin(float16 x);
/**
* Compute square root over an implementation-defined
* range. The maximum error is implementation-defined.
*/
float __ovld __cnfn native_sqrt(float x);
float2 __ovld __cnfn native_sqrt(float2 x);
float3 __ovld __cnfn native_sqrt(float3 x);
float4 __ovld __cnfn native_sqrt(float4 x);
float8 __ovld __cnfn native_sqrt(float8 x);
float16 __ovld __cnfn native_sqrt(float16 x);
/**
* Compute tangent over an implementation-defined range.
* The maximum error is implementation-defined.
*/
float __ovld __cnfn native_tan(float x);
float2 __ovld __cnfn native_tan(float2 x);
float3 __ovld __cnfn native_tan(float3 x);
float4 __ovld __cnfn native_tan(float4 x);
float8 __ovld __cnfn native_tan(float8 x);
float16 __ovld __cnfn native_tan(float16 x);
// OpenCL v1.1 s6.11.3, v1.2 s6.12.3, v2.0 s6.13.3 - Integer Functions
/**
* Returns | x |.
*/
uchar __ovld __cnfn abs(char x);
uchar __ovld __cnfn abs(uchar x);
uchar2 __ovld __cnfn abs(char2 x);
uchar2 __ovld __cnfn abs(uchar2 x);
uchar3 __ovld __cnfn abs(char3 x);
uchar3 __ovld __cnfn abs(uchar3 x);
uchar4 __ovld __cnfn abs(char4 x);
uchar4 __ovld __cnfn abs(uchar4 x);
uchar8 __ovld __cnfn abs(char8 x);
uchar8 __ovld __cnfn abs(uchar8 x);
uchar16 __ovld __cnfn abs(char16 x);
uchar16 __ovld __cnfn abs(uchar16 x);
ushort __ovld __cnfn abs(short x);
ushort __ovld __cnfn abs(ushort x);
ushort2 __ovld __cnfn abs(short2 x);
ushort2 __ovld __cnfn abs(ushort2 x);
ushort3 __ovld __cnfn abs(short3 x);
ushort3 __ovld __cnfn abs(ushort3 x);
ushort4 __ovld __cnfn abs(short4 x);
ushort4 __ovld __cnfn abs(ushort4 x);
ushort8 __ovld __cnfn abs(short8 x);
ushort8 __ovld __cnfn abs(ushort8 x);
ushort16 __ovld __cnfn abs(short16 x);
ushort16 __ovld __cnfn abs(ushort16 x);
uint __ovld __cnfn abs(int x);
uint __ovld __cnfn abs(uint x);
uint2 __ovld __cnfn abs(int2 x);
uint2 __ovld __cnfn abs(uint2 x);
uint3 __ovld __cnfn abs(int3 x);
uint3 __ovld __cnfn abs(uint3 x);
uint4 __ovld __cnfn abs(int4 x);
uint4 __ovld __cnfn abs(uint4 x);
uint8 __ovld __cnfn abs(int8 x);
uint8 __ovld __cnfn abs(uint8 x);
uint16 __ovld __cnfn abs(int16 x);
uint16 __ovld __cnfn abs(uint16 x);
ulong __ovld __cnfn abs(long x);
ulong __ovld __cnfn abs(ulong x);
ulong2 __ovld __cnfn abs(long2 x);
ulong2 __ovld __cnfn abs(ulong2 x);
ulong3 __ovld __cnfn abs(long3 x);
ulong3 __ovld __cnfn abs(ulong3 x);
ulong4 __ovld __cnfn abs(long4 x);
ulong4 __ovld __cnfn abs(ulong4 x);
ulong8 __ovld __cnfn abs(long8 x);
ulong8 __ovld __cnfn abs(ulong8 x);
ulong16 __ovld __cnfn abs(long16 x);
ulong16 __ovld __cnfn abs(ulong16 x);
/**
* Returns | x - y | without modulo overflow.
*/
uchar __ovld __cnfn abs_diff(char x, char y);
uchar __ovld __cnfn abs_diff(uchar x, uchar y);
uchar2 __ovld __cnfn abs_diff(char2 x, char2 y);
uchar2 __ovld __cnfn abs_diff(uchar2 x, uchar2 y);
uchar3 __ovld __cnfn abs_diff(char3 x, char3 y);
uchar3 __ovld __cnfn abs_diff(uchar3 x, uchar3 y);
uchar4 __ovld __cnfn abs_diff(char4 x, char4 y);
uchar4 __ovld __cnfn abs_diff(uchar4 x, uchar4 y);
uchar8 __ovld __cnfn abs_diff(char8 x, char8 y);
uchar8 __ovld __cnfn abs_diff(uchar8 x, uchar8 y);
uchar16 __ovld __cnfn abs_diff(char16 x, char16 y);
uchar16 __ovld __cnfn abs_diff(uchar16 x, uchar16 y);
ushort __ovld __cnfn abs_diff(short x, short y);
ushort __ovld __cnfn abs_diff(ushort x, ushort y);
ushort2 __ovld __cnfn abs_diff(short2 x, short2 y);
ushort2 __ovld __cnfn abs_diff(ushort2 x, ushort2 y);
ushort3 __ovld __cnfn abs_diff(short3 x, short3 y);
ushort3 __ovld __cnfn abs_diff(ushort3 x, ushort3 y);
ushort4 __ovld __cnfn abs_diff(short4 x, short4 y);
ushort4 __ovld __cnfn abs_diff(ushort4 x, ushort4 y);
ushort8 __ovld __cnfn abs_diff(short8 x, short8 y);
ushort8 __ovld __cnfn abs_diff(ushort8 x, ushort8 y);
ushort16 __ovld __cnfn abs_diff(short16 x, short16 y);
ushort16 __ovld __cnfn abs_diff(ushort16 x, ushort16 y);
uint __ovld __cnfn abs_diff(int x, int y);
uint __ovld __cnfn abs_diff(uint x, uint y);
uint2 __ovld __cnfn abs_diff(int2 x, int2 y);
uint2 __ovld __cnfn abs_diff(uint2 x, uint2 y);
uint3 __ovld __cnfn abs_diff(int3 x, int3 y);
uint3 __ovld __cnfn abs_diff(uint3 x, uint3 y);
uint4 __ovld __cnfn abs_diff(int4 x, int4 y);
uint4 __ovld __cnfn abs_diff(uint4 x, uint4 y);
uint8 __ovld __cnfn abs_diff(int8 x, int8 y);
uint8 __ovld __cnfn abs_diff(uint8 x, uint8 y);
uint16 __ovld __cnfn abs_diff(int16 x, int16 y);
uint16 __ovld __cnfn abs_diff(uint16 x, uint16 y);
ulong __ovld __cnfn abs_diff(long x, long y);
ulong __ovld __cnfn abs_diff(ulong x, ulong y);
ulong2 __ovld __cnfn abs_diff(long2 x, long2 y);
ulong2 __ovld __cnfn abs_diff(ulong2 x, ulong2 y);
ulong3 __ovld __cnfn abs_diff(long3 x, long3 y);
ulong3 __ovld __cnfn abs_diff(ulong3 x, ulong3 y);
ulong4 __ovld __cnfn abs_diff(long4 x, long4 y);
ulong4 __ovld __cnfn abs_diff(ulong4 x, ulong4 y);
ulong8 __ovld __cnfn abs_diff(long8 x, long8 y);
ulong8 __ovld __cnfn abs_diff(ulong8 x, ulong8 y);
ulong16 __ovld __cnfn abs_diff(long16 x, long16 y);
ulong16 __ovld __cnfn abs_diff(ulong16 x, ulong16 y);
/**
* Returns x + y and saturates the result.
*/
char __ovld __cnfn add_sat(char x, char y);
uchar __ovld __cnfn add_sat(uchar x, uchar y);
char2 __ovld __cnfn add_sat(char2 x, char2 y);
uchar2 __ovld __cnfn add_sat(uchar2 x, uchar2 y);
char3 __ovld __cnfn add_sat(char3 x, char3 y);
uchar3 __ovld __cnfn add_sat(uchar3 x, uchar3 y);
char4 __ovld __cnfn add_sat(char4 x, char4 y);
uchar4 __ovld __cnfn add_sat(uchar4 x, uchar4 y);
char8 __ovld __cnfn add_sat(char8 x, char8 y);
uchar8 __ovld __cnfn add_sat(uchar8 x, uchar8 y);
char16 __ovld __cnfn add_sat(char16 x, char16 y);
uchar16 __ovld __cnfn add_sat(uchar16 x, uchar16 y);
short __ovld __cnfn add_sat(short x, short y);
ushort __ovld __cnfn add_sat(ushort x, ushort y);
short2 __ovld __cnfn add_sat(short2 x, short2 y);
ushort2 __ovld __cnfn add_sat(ushort2 x, ushort2 y);
short3 __ovld __cnfn add_sat(short3 x, short3 y);
ushort3 __ovld __cnfn add_sat(ushort3 x, ushort3 y);
short4 __ovld __cnfn add_sat(short4 x, short4 y);
ushort4 __ovld __cnfn add_sat(ushort4 x, ushort4 y);
short8 __ovld __cnfn add_sat(short8 x, short8 y);
ushort8 __ovld __cnfn add_sat(ushort8 x, ushort8 y);
short16 __ovld __cnfn add_sat(short16 x, short16 y);
ushort16 __ovld __cnfn add_sat(ushort16 x, ushort16 y);
int __ovld __cnfn add_sat(int x, int y);
uint __ovld __cnfn add_sat(uint x, uint y);
int2 __ovld __cnfn add_sat(int2 x, int2 y);
uint2 __ovld __cnfn add_sat(uint2 x, uint2 y);
int3 __ovld __cnfn add_sat(int3 x, int3 y);
uint3 __ovld __cnfn add_sat(uint3 x, uint3 y);
int4 __ovld __cnfn add_sat(int4 x, int4 y);
uint4 __ovld __cnfn add_sat(uint4 x, uint4 y);
int8 __ovld __cnfn add_sat(int8 x, int8 y);
uint8 __ovld __cnfn add_sat(uint8 x, uint8 y);
int16 __ovld __cnfn add_sat(int16 x, int16 y);
uint16 __ovld __cnfn add_sat(uint16 x, uint16 y);
long __ovld __cnfn add_sat(long x, long y);
ulong __ovld __cnfn add_sat(ulong x, ulong y);
long2 __ovld __cnfn add_sat(long2 x, long2 y);
ulong2 __ovld __cnfn add_sat(ulong2 x, ulong2 y);
long3 __ovld __cnfn add_sat(long3 x, long3 y);
ulong3 __ovld __cnfn add_sat(ulong3 x, ulong3 y);
long4 __ovld __cnfn add_sat(long4 x, long4 y);
ulong4 __ovld __cnfn add_sat(ulong4 x, ulong4 y);
long8 __ovld __cnfn add_sat(long8 x, long8 y);
ulong8 __ovld __cnfn add_sat(ulong8 x, ulong8 y);
long16 __ovld __cnfn add_sat(long16 x, long16 y);
ulong16 __ovld __cnfn add_sat(ulong16 x, ulong16 y);
/**
* Returns (x + y) >> 1. The intermediate sum does
* not modulo overflow.
*/
char __ovld __cnfn hadd(char x, char y);
uchar __ovld __cnfn hadd(uchar x, uchar y);
char2 __ovld __cnfn hadd(char2 x, char2 y);
uchar2 __ovld __cnfn hadd(uchar2 x, uchar2 y);
char3 __ovld __cnfn hadd(char3 x, char3 y);
uchar3 __ovld __cnfn hadd(uchar3 x, uchar3 y);
char4 __ovld __cnfn hadd(char4 x, char4 y);
uchar4 __ovld __cnfn hadd(uchar4 x, uchar4 y);
char8 __ovld __cnfn hadd(char8 x, char8 y);
uchar8 __ovld __cnfn hadd(uchar8 x, uchar8 y);
char16 __ovld __cnfn hadd(char16 x, char16 y);
uchar16 __ovld __cnfn hadd(uchar16 x, uchar16 y);
short __ovld __cnfn hadd(short x, short y);
ushort __ovld __cnfn hadd(ushort x, ushort y);
short2 __ovld __cnfn hadd(short2 x, short2 y);
ushort2 __ovld __cnfn hadd(ushort2 x, ushort2 y);
short3 __ovld __cnfn hadd(short3 x, short3 y);
ushort3 __ovld __cnfn hadd(ushort3 x, ushort3 y);
short4 __ovld __cnfn hadd(short4 x, short4 y);
ushort4 __ovld __cnfn hadd(ushort4 x, ushort4 y);
short8 __ovld __cnfn hadd(short8 x, short8 y);
ushort8 __ovld __cnfn hadd(ushort8 x, ushort8 y);
short16 __ovld __cnfn hadd(short16 x, short16 y);
ushort16 __ovld __cnfn hadd(ushort16 x, ushort16 y);
int __ovld __cnfn hadd(int x, int y);
uint __ovld __cnfn hadd(uint x, uint y);
int2 __ovld __cnfn hadd(int2 x, int2 y);
uint2 __ovld __cnfn hadd(uint2 x, uint2 y);
int3 __ovld __cnfn hadd(int3 x, int3 y);
uint3 __ovld __cnfn hadd(uint3 x, uint3 y);
int4 __ovld __cnfn hadd(int4 x, int4 y);
uint4 __ovld __cnfn hadd(uint4 x, uint4 y);
int8 __ovld __cnfn hadd(int8 x, int8 y);
uint8 __ovld __cnfn hadd(uint8 x, uint8 y);
int16 __ovld __cnfn hadd(int16 x, int16 y);
uint16 __ovld __cnfn hadd(uint16 x, uint16 y);
long __ovld __cnfn hadd(long x, long y);
ulong __ovld __cnfn hadd(ulong x, ulong y);
long2 __ovld __cnfn hadd(long2 x, long2 y);
ulong2 __ovld __cnfn hadd(ulong2 x, ulong2 y);
long3 __ovld __cnfn hadd(long3 x, long3 y);
ulong3 __ovld __cnfn hadd(ulong3 x, ulong3 y);
long4 __ovld __cnfn hadd(long4 x, long4 y);
ulong4 __ovld __cnfn hadd(ulong4 x, ulong4 y);
long8 __ovld __cnfn hadd(long8 x, long8 y);
ulong8 __ovld __cnfn hadd(ulong8 x, ulong8 y);
long16 __ovld __cnfn hadd(long16 x, long16 y);
ulong16 __ovld __cnfn hadd(ulong16 x, ulong16 y);
/**
* Returns (x + y + 1) >> 1. The intermediate sum
* does not modulo overflow.
*/
char __ovld __cnfn rhadd(char x, char y);
uchar __ovld __cnfn rhadd(uchar x, uchar y);
char2 __ovld __cnfn rhadd(char2 x, char2 y);
uchar2 __ovld __cnfn rhadd(uchar2 x, uchar2 y);
char3 __ovld __cnfn rhadd(char3 x, char3 y);
uchar3 __ovld __cnfn rhadd(uchar3 x, uchar3 y);
char4 __ovld __cnfn rhadd(char4 x, char4 y);
uchar4 __ovld __cnfn rhadd(uchar4 x, uchar4 y);
char8 __ovld __cnfn rhadd(char8 x, char8 y);
uchar8 __ovld __cnfn rhadd(uchar8 x, uchar8 y);
char16 __ovld __cnfn rhadd(char16 x, char16 y);
uchar16 __ovld __cnfn rhadd(uchar16 x, uchar16 y);
short __ovld __cnfn rhadd(short x, short y);
ushort __ovld __cnfn rhadd(ushort x, ushort y);
short2 __ovld __cnfn rhadd(short2 x, short2 y);
ushort2 __ovld __cnfn rhadd(ushort2 x, ushort2 y);
short3 __ovld __cnfn rhadd(short3 x, short3 y);
ushort3 __ovld __cnfn rhadd(ushort3 x, ushort3 y);
short4 __ovld __cnfn rhadd(short4 x, short4 y);
ushort4 __ovld __cnfn rhadd(ushort4 x, ushort4 y);
short8 __ovld __cnfn rhadd(short8 x, short8 y);
ushort8 __ovld __cnfn rhadd(ushort8 x, ushort8 y);
short16 __ovld __cnfn rhadd(short16 x, short16 y);
ushort16 __ovld __cnfn rhadd(ushort16 x, ushort16 y);
int __ovld __cnfn rhadd(int x, int y);
uint __ovld __cnfn rhadd(uint x, uint y);
int2 __ovld __cnfn rhadd(int2 x, int2 y);
uint2 __ovld __cnfn rhadd(uint2 x, uint2 y);
int3 __ovld __cnfn rhadd(int3 x, int3 y);
uint3 __ovld __cnfn rhadd(uint3 x, uint3 y);
int4 __ovld __cnfn rhadd(int4 x, int4 y);
uint4 __ovld __cnfn rhadd(uint4 x, uint4 y);
int8 __ovld __cnfn rhadd(int8 x, int8 y);
uint8 __ovld __cnfn rhadd(uint8 x, uint8 y);
int16 __ovld __cnfn rhadd(int16 x, int16 y);
uint16 __ovld __cnfn rhadd(uint16 x, uint16 y);
long __ovld __cnfn rhadd(long x, long y);
ulong __ovld __cnfn rhadd(ulong x, ulong y);
long2 __ovld __cnfn rhadd(long2 x, long2 y);
ulong2 __ovld __cnfn rhadd(ulong2 x, ulong2 y);
long3 __ovld __cnfn rhadd(long3 x, long3 y);
ulong3 __ovld __cnfn rhadd(ulong3 x, ulong3 y);
long4 __ovld __cnfn rhadd(long4 x, long4 y);
ulong4 __ovld __cnfn rhadd(ulong4 x, ulong4 y);
long8 __ovld __cnfn rhadd(long8 x, long8 y);
ulong8 __ovld __cnfn rhadd(ulong8 x, ulong8 y);
long16 __ovld __cnfn rhadd(long16 x, long16 y);
ulong16 __ovld __cnfn rhadd(ulong16 x, ulong16 y);
/**
* Returns min(max(x, minval), maxval).
* Results are undefined if minval > maxval.
*/
char __ovld __cnfn clamp(char x, char minval, char maxval);
uchar __ovld __cnfn clamp(uchar x, uchar minval, uchar maxval);
char2 __ovld __cnfn clamp(char2 x, char2 minval, char2 maxval);
uchar2 __ovld __cnfn clamp(uchar2 x, uchar2 minval, uchar2 maxval);
char3 __ovld __cnfn clamp(char3 x, char3 minval, char3 maxval);
uchar3 __ovld __cnfn clamp(uchar3 x, uchar3 minval, uchar3 maxval);
char4 __ovld __cnfn clamp(char4 x, char4 minval, char4 maxval);
uchar4 __ovld __cnfn clamp(uchar4 x, uchar4 minval, uchar4 maxval);
char8 __ovld __cnfn clamp(char8 x, char8 minval, char8 maxval);
uchar8 __ovld __cnfn clamp(uchar8 x, uchar8 minval, uchar8 maxval);
char16 __ovld __cnfn clamp(char16 x, char16 minval, char16 maxval);
uchar16 __ovld __cnfn clamp(uchar16 x, uchar16 minval, uchar16 maxval);
short __ovld __cnfn clamp(short x, short minval, short maxval);
ushort __ovld __cnfn clamp(ushort x, ushort minval, ushort maxval);
short2 __ovld __cnfn clamp(short2 x, short2 minval, short2 maxval);
ushort2 __ovld __cnfn clamp(ushort2 x, ushort2 minval, ushort2 maxval);
short3 __ovld __cnfn clamp(short3 x, short3 minval, short3 maxval);
ushort3 __ovld __cnfn clamp(ushort3 x, ushort3 minval, ushort3 maxval);
short4 __ovld __cnfn clamp(short4 x, short4 minval, short4 maxval);
ushort4 __ovld __cnfn clamp(ushort4 x, ushort4 minval, ushort4 maxval);
short8 __ovld __cnfn clamp(short8 x, short8 minval, short8 maxval);
ushort8 __ovld __cnfn clamp(ushort8 x, ushort8 minval, ushort8 maxval);
short16 __ovld __cnfn clamp(short16 x, short16 minval, short16 maxval);
ushort16 __ovld __cnfn clamp(ushort16 x, ushort16 minval, ushort16 maxval);
int __ovld __cnfn clamp(int x, int minval, int maxval);
uint __ovld __cnfn clamp(uint x, uint minval, uint maxval);
int2 __ovld __cnfn clamp(int2 x, int2 minval, int2 maxval);
uint2 __ovld __cnfn clamp(uint2 x, uint2 minval, uint2 maxval);
int3 __ovld __cnfn clamp(int3 x, int3 minval, int3 maxval);
uint3 __ovld __cnfn clamp(uint3 x, uint3 minval, uint3 maxval);
int4 __ovld __cnfn clamp(int4 x, int4 minval, int4 maxval);
uint4 __ovld __cnfn clamp(uint4 x, uint4 minval, uint4 maxval);
int8 __ovld __cnfn clamp(int8 x, int8 minval, int8 maxval);
uint8 __ovld __cnfn clamp(uint8 x, uint8 minval, uint8 maxval);
int16 __ovld __cnfn clamp(int16 x, int16 minval, int16 maxval);
uint16 __ovld __cnfn clamp(uint16 x, uint16 minval, uint16 maxval);
long __ovld __cnfn clamp(long x, long minval, long maxval);
ulong __ovld __cnfn clamp(ulong x, ulong minval, ulong maxval);
long2 __ovld __cnfn clamp(long2 x, long2 minval, long2 maxval);
ulong2 __ovld __cnfn clamp(ulong2 x, ulong2 minval, ulong2 maxval);
long3 __ovld __cnfn clamp(long3 x, long3 minval, long3 maxval);
ulong3 __ovld __cnfn clamp(ulong3 x, ulong3 minval, ulong3 maxval);
long4 __ovld __cnfn clamp(long4 x, long4 minval, long4 maxval);
ulong4 __ovld __cnfn clamp(ulong4 x, ulong4 minval, ulong4 maxval);
long8 __ovld __cnfn clamp(long8 x, long8 minval, long8 maxval);
ulong8 __ovld __cnfn clamp(ulong8 x, ulong8 minval, ulong8 maxval);
long16 __ovld __cnfn clamp(long16 x, long16 minval, long16 maxval);
ulong16 __ovld __cnfn clamp(ulong16 x, ulong16 minval, ulong16 maxval);
char __ovld __cnfn clamp(char x, char minval, char maxval);
uchar __ovld __cnfn clamp(uchar x, uchar minval, uchar maxval);
char2 __ovld __cnfn clamp(char2 x, char minval, char maxval);
uchar2 __ovld __cnfn clamp(uchar2 x, uchar minval, uchar maxval);
char3 __ovld __cnfn clamp(char3 x, char minval, char maxval);
uchar3 __ovld __cnfn clamp(uchar3 x, uchar minval, uchar maxval);
char4 __ovld __cnfn clamp(char4 x, char minval, char maxval);
uchar4 __ovld __cnfn clamp(uchar4 x, uchar minval, uchar maxval);
char8 __ovld __cnfn clamp(char8 x, char minval, char maxval);
uchar8 __ovld __cnfn clamp(uchar8 x, uchar minval, uchar maxval);
char16 __ovld __cnfn clamp(char16 x, char minval, char maxval);
uchar16 __ovld __cnfn clamp(uchar16 x, uchar minval, uchar maxval);
short __ovld __cnfn clamp(short x, short minval, short maxval);
ushort __ovld __cnfn clamp(ushort x, ushort minval, ushort maxval);
short2 __ovld __cnfn clamp(short2 x, short minval, short maxval);
ushort2 __ovld __cnfn clamp(ushort2 x, ushort minval, ushort maxval);
short3 __ovld __cnfn clamp(short3 x, short minval, short maxval);
ushort3 __ovld __cnfn clamp(ushort3 x, ushort minval, ushort maxval);
short4 __ovld __cnfn clamp(short4 x, short minval, short maxval);
ushort4 __ovld __cnfn clamp(ushort4 x, ushort minval, ushort maxval);
short8 __ovld __cnfn clamp(short8 x, short minval, short maxval);
ushort8 __ovld __cnfn clamp(ushort8 x, ushort minval, ushort maxval);
short16 __ovld __cnfn clamp(short16 x, short minval, short maxval);
ushort16 __ovld __cnfn clamp(ushort16 x, ushort minval, ushort maxval);
int __ovld __cnfn clamp(int x, int minval, int maxval);
uint __ovld __cnfn clamp(uint x, uint minval, uint maxval);
int2 __ovld __cnfn clamp(int2 x, int minval, int maxval);
uint2 __ovld __cnfn clamp(uint2 x, uint minval, uint maxval);
int3 __ovld __cnfn clamp(int3 x, int minval, int maxval);
uint3 __ovld __cnfn clamp(uint3 x, uint minval, uint maxval);
int4 __ovld __cnfn clamp(int4 x, int minval, int maxval);
uint4 __ovld __cnfn clamp(uint4 x, uint minval, uint maxval);
int8 __ovld __cnfn clamp(int8 x, int minval, int maxval);
uint8 __ovld __cnfn clamp(uint8 x, uint minval, uint maxval);
int16 __ovld __cnfn clamp(int16 x, int minval, int maxval);
uint16 __ovld __cnfn clamp(uint16 x, uint minval, uint maxval);
long __ovld __cnfn clamp(long x, long minval, long maxval);
ulong __ovld __cnfn clamp(ulong x, ulong minval, ulong maxval);
long2 __ovld __cnfn clamp(long2 x, long minval, long maxval);
ulong2 __ovld __cnfn clamp(ulong2 x, ulong minval, ulong maxval);
long3 __ovld __cnfn clamp(long3 x, long minval, long maxval);
ulong3 __ovld __cnfn clamp(ulong3 x, ulong minval, ulong maxval);
long4 __ovld __cnfn clamp(long4 x, long minval, long maxval);
ulong4 __ovld __cnfn clamp(ulong4 x, ulong minval, ulong maxval);
long8 __ovld __cnfn clamp(long8 x, long minval, long maxval);
ulong8 __ovld __cnfn clamp(ulong8 x, ulong minval, ulong maxval);
long16 __ovld __cnfn clamp(long16 x, long minval, long maxval);
ulong16 __ovld __cnfn clamp(ulong16 x, ulong minval, ulong maxval);
/**
* Returns the number of leading 0-bits in x, starting
* at the most significant bit position.
*/
char __ovld __cnfn clz(char x);
uchar __ovld __cnfn clz(uchar x);
char2 __ovld __cnfn clz(char2 x);
uchar2 __ovld __cnfn clz(uchar2 x);
char3 __ovld __cnfn clz(char3 x);
uchar3 __ovld __cnfn clz(uchar3 x);
char4 __ovld __cnfn clz(char4 x);
uchar4 __ovld __cnfn clz(uchar4 x);
char8 __ovld __cnfn clz(char8 x);
uchar8 __ovld __cnfn clz(uchar8 x);
char16 __ovld __cnfn clz(char16 x);
uchar16 __ovld __cnfn clz(uchar16 x);
short __ovld __cnfn clz(short x);
ushort __ovld __cnfn clz(ushort x);
short2 __ovld __cnfn clz(short2 x);
ushort2 __ovld __cnfn clz(ushort2 x);
short3 __ovld __cnfn clz(short3 x);
ushort3 __ovld __cnfn clz(ushort3 x);
short4 __ovld __cnfn clz(short4 x);
ushort4 __ovld __cnfn clz(ushort4 x);
short8 __ovld __cnfn clz(short8 x);
ushort8 __ovld __cnfn clz(ushort8 x);
short16 __ovld __cnfn clz(short16 x);
ushort16 __ovld __cnfn clz(ushort16 x);
int __ovld __cnfn clz(int x);
uint __ovld __cnfn clz(uint x);
int2 __ovld __cnfn clz(int2 x);
uint2 __ovld __cnfn clz(uint2 x);
int3 __ovld __cnfn clz(int3 x);
uint3 __ovld __cnfn clz(uint3 x);
int4 __ovld __cnfn clz(int4 x);
uint4 __ovld __cnfn clz(uint4 x);
int8 __ovld __cnfn clz(int8 x);
uint8 __ovld __cnfn clz(uint8 x);
int16 __ovld __cnfn clz(int16 x);
uint16 __ovld __cnfn clz(uint16 x);
long __ovld __cnfn clz(long x);
ulong __ovld __cnfn clz(ulong x);
long2 __ovld __cnfn clz(long2 x);
ulong2 __ovld __cnfn clz(ulong2 x);
long3 __ovld __cnfn clz(long3 x);
ulong3 __ovld __cnfn clz(ulong3 x);
long4 __ovld __cnfn clz(long4 x);
ulong4 __ovld __cnfn clz(ulong4 x);
long8 __ovld __cnfn clz(long8 x);
ulong8 __ovld __cnfn clz(ulong8 x);
long16 __ovld __cnfn clz(long16 x);
ulong16 __ovld __cnfn clz(ulong16 x);
/**
* Returns the count of trailing 0-bits in x. If x is 0,
* returns the size in bits of the type of x or
* component type of x, if x is a vector.
*/
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
char __ovld ctz(char x);
uchar __ovld ctz(uchar x);
char2 __ovld ctz(char2 x);
uchar2 __ovld ctz(uchar2 x);
char3 __ovld ctz(char3 x);
uchar3 __ovld ctz(uchar3 x);
char4 __ovld ctz(char4 x);
uchar4 __ovld ctz(uchar4 x);
char8 __ovld ctz(char8 x);
uchar8 __ovld ctz(uchar8 x);
char16 __ovld ctz(char16 x);
uchar16 __ovld ctz(uchar16 x);
short __ovld ctz(short x);
ushort __ovld ctz(ushort x);
short2 __ovld ctz(short2 x);
ushort2 __ovld ctz(ushort2 x);
short3 __ovld ctz(short3 x);
ushort3 __ovld ctz(ushort3 x);
short4 __ovld ctz(short4 x);
ushort4 __ovld ctz(ushort4 x);
short8 __ovld ctz(short8 x);
ushort8 __ovld ctz(ushort8 x);
short16 __ovld ctz(short16 x);
ushort16 __ovld ctz(ushort16 x);
int __ovld ctz(int x);
uint __ovld ctz(uint x);
int2 __ovld ctz(int2 x);
uint2 __ovld ctz(uint2 x);
int3 __ovld ctz(int3 x);
uint3 __ovld ctz(uint3 x);
int4 __ovld ctz(int4 x);
uint4 __ovld ctz(uint4 x);
int8 __ovld ctz(int8 x);
uint8 __ovld ctz(uint8 x);
int16 __ovld ctz(int16 x);
uint16 __ovld ctz(uint16 x);
long __ovld ctz(long x);
ulong __ovld ctz(ulong x);
long2 __ovld ctz(long2 x);
ulong2 __ovld ctz(ulong2 x);
long3 __ovld ctz(long3 x);
ulong3 __ovld ctz(ulong3 x);
long4 __ovld ctz(long4 x);
ulong4 __ovld ctz(ulong4 x);
long8 __ovld ctz(long8 x);
ulong8 __ovld ctz(ulong8 x);
long16 __ovld ctz(long16 x);
ulong16 __ovld ctz(ulong16 x);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Returns mul_hi(a, b) + c.
*/
char __ovld __cnfn mad_hi(char a, char b, char c);
uchar __ovld __cnfn mad_hi(uchar a, uchar b, uchar c);
char2 __ovld __cnfn mad_hi(char2 a, char2 b, char2 c);
uchar2 __ovld __cnfn mad_hi(uchar2 a, uchar2 b, uchar2 c);
char3 __ovld __cnfn mad_hi(char3 a, char3 b, char3 c);
uchar3 __ovld __cnfn mad_hi(uchar3 a, uchar3 b, uchar3 c);
char4 __ovld __cnfn mad_hi(char4 a, char4 b, char4 c);
uchar4 __ovld __cnfn mad_hi(uchar4 a, uchar4 b, uchar4 c);
char8 __ovld __cnfn mad_hi(char8 a, char8 b, char8 c);
uchar8 __ovld __cnfn mad_hi(uchar8 a, uchar8 b, uchar8 c);
char16 __ovld __cnfn mad_hi(char16 a, char16 b, char16 c);
uchar16 __ovld __cnfn mad_hi(uchar16 a, uchar16 b, uchar16 c);
short __ovld __cnfn mad_hi(short a, short b, short c);
ushort __ovld __cnfn mad_hi(ushort a, ushort b, ushort c);
short2 __ovld __cnfn mad_hi(short2 a, short2 b, short2 c);
ushort2 __ovld __cnfn mad_hi(ushort2 a, ushort2 b, ushort2 c);
short3 __ovld __cnfn mad_hi(short3 a, short3 b, short3 c);
ushort3 __ovld __cnfn mad_hi(ushort3 a, ushort3 b, ushort3 c);
short4 __ovld __cnfn mad_hi(short4 a, short4 b, short4 c);
ushort4 __ovld __cnfn mad_hi(ushort4 a, ushort4 b, ushort4 c);
short8 __ovld __cnfn mad_hi(short8 a, short8 b, short8 c);
ushort8 __ovld __cnfn mad_hi(ushort8 a, ushort8 b, ushort8 c);
short16 __ovld __cnfn mad_hi(short16 a, short16 b, short16 c);
ushort16 __ovld __cnfn mad_hi(ushort16 a, ushort16 b, ushort16 c);
int __ovld __cnfn mad_hi(int a, int b, int c);
uint __ovld __cnfn mad_hi(uint a, uint b, uint c);
int2 __ovld __cnfn mad_hi(int2 a, int2 b, int2 c);
uint2 __ovld __cnfn mad_hi(uint2 a, uint2 b, uint2 c);
int3 __ovld __cnfn mad_hi(int3 a, int3 b, int3 c);
uint3 __ovld __cnfn mad_hi(uint3 a, uint3 b, uint3 c);
int4 __ovld __cnfn mad_hi(int4 a, int4 b, int4 c);
uint4 __ovld __cnfn mad_hi(uint4 a, uint4 b, uint4 c);
int8 __ovld __cnfn mad_hi(int8 a, int8 b, int8 c);
uint8 __ovld __cnfn mad_hi(uint8 a, uint8 b, uint8 c);
int16 __ovld __cnfn mad_hi(int16 a, int16 b, int16 c);
uint16 __ovld __cnfn mad_hi(uint16 a, uint16 b, uint16 c);
long __ovld __cnfn mad_hi(long a, long b, long c);
ulong __ovld __cnfn mad_hi(ulong a, ulong b, ulong c);
long2 __ovld __cnfn mad_hi(long2 a, long2 b, long2 c);
ulong2 __ovld __cnfn mad_hi(ulong2 a, ulong2 b, ulong2 c);
long3 __ovld __cnfn mad_hi(long3 a, long3 b, long3 c);
ulong3 __ovld __cnfn mad_hi(ulong3 a, ulong3 b, ulong3 c);
long4 __ovld __cnfn mad_hi(long4 a, long4 b, long4 c);
ulong4 __ovld __cnfn mad_hi(ulong4 a, ulong4 b, ulong4 c);
long8 __ovld __cnfn mad_hi(long8 a, long8 b, long8 c);
ulong8 __ovld __cnfn mad_hi(ulong8 a, ulong8 b, ulong8 c);
long16 __ovld __cnfn mad_hi(long16 a, long16 b, long16 c);
ulong16 __ovld __cnfn mad_hi(ulong16 a, ulong16 b, ulong16 c);
/**
* Returns a * b + c and saturates the result.
*/
char __ovld __cnfn mad_sat(char a, char b, char c);
uchar __ovld __cnfn mad_sat(uchar a, uchar b, uchar c);
char2 __ovld __cnfn mad_sat(char2 a, char2 b, char2 c);
uchar2 __ovld __cnfn mad_sat(uchar2 a, uchar2 b, uchar2 c);
char3 __ovld __cnfn mad_sat(char3 a, char3 b, char3 c);
uchar3 __ovld __cnfn mad_sat(uchar3 a, uchar3 b, uchar3 c);
char4 __ovld __cnfn mad_sat(char4 a, char4 b, char4 c);
uchar4 __ovld __cnfn mad_sat(uchar4 a, uchar4 b, uchar4 c);
char8 __ovld __cnfn mad_sat(char8 a, char8 b, char8 c);
uchar8 __ovld __cnfn mad_sat(uchar8 a, uchar8 b, uchar8 c);
char16 __ovld __cnfn mad_sat(char16 a, char16 b, char16 c);
uchar16 __ovld __cnfn mad_sat(uchar16 a, uchar16 b, uchar16 c);
short __ovld __cnfn mad_sat(short a, short b, short c);
ushort __ovld __cnfn mad_sat(ushort a, ushort b, ushort c);
short2 __ovld __cnfn mad_sat(short2 a, short2 b, short2 c);
ushort2 __ovld __cnfn mad_sat(ushort2 a, ushort2 b, ushort2 c);
short3 __ovld __cnfn mad_sat(short3 a, short3 b, short3 c);
ushort3 __ovld __cnfn mad_sat(ushort3 a, ushort3 b, ushort3 c);
short4 __ovld __cnfn mad_sat(short4 a, short4 b, short4 c);
ushort4 __ovld __cnfn mad_sat(ushort4 a, ushort4 b, ushort4 c);
short8 __ovld __cnfn mad_sat(short8 a, short8 b, short8 c);
ushort8 __ovld __cnfn mad_sat(ushort8 a, ushort8 b, ushort8 c);
short16 __ovld __cnfn mad_sat(short16 a, short16 b, short16 c);
ushort16 __ovld __cnfn mad_sat(ushort16 a, ushort16 b, ushort16 c);
int __ovld __cnfn mad_sat(int a, int b, int c);
uint __ovld __cnfn mad_sat(uint a, uint b, uint c);
int2 __ovld __cnfn mad_sat(int2 a, int2 b, int2 c);
uint2 __ovld __cnfn mad_sat(uint2 a, uint2 b, uint2 c);
int3 __ovld __cnfn mad_sat(int3 a, int3 b, int3 c);
uint3 __ovld __cnfn mad_sat(uint3 a, uint3 b, uint3 c);
int4 __ovld __cnfn mad_sat(int4 a, int4 b, int4 c);
uint4 __ovld __cnfn mad_sat(uint4 a, uint4 b, uint4 c);
int8 __ovld __cnfn mad_sat(int8 a, int8 b, int8 c);
uint8 __ovld __cnfn mad_sat(uint8 a, uint8 b, uint8 c);
int16 __ovld __cnfn mad_sat(int16 a, int16 b, int16 c);
uint16 __ovld __cnfn mad_sat(uint16 a, uint16 b, uint16 c);
long __ovld __cnfn mad_sat(long a, long b, long c);
ulong __ovld __cnfn mad_sat(ulong a, ulong b, ulong c);
long2 __ovld __cnfn mad_sat(long2 a, long2 b, long2 c);
ulong2 __ovld __cnfn mad_sat(ulong2 a, ulong2 b, ulong2 c);
long3 __ovld __cnfn mad_sat(long3 a, long3 b, long3 c);
ulong3 __ovld __cnfn mad_sat(ulong3 a, ulong3 b, ulong3 c);
long4 __ovld __cnfn mad_sat(long4 a, long4 b, long4 c);
ulong4 __ovld __cnfn mad_sat(ulong4 a, ulong4 b, ulong4 c);
long8 __ovld __cnfn mad_sat(long8 a, long8 b, long8 c);
ulong8 __ovld __cnfn mad_sat(ulong8 a, ulong8 b, ulong8 c);
long16 __ovld __cnfn mad_sat(long16 a, long16 b, long16 c);
ulong16 __ovld __cnfn mad_sat(ulong16 a, ulong16 b, ulong16 c);
/**
* Returns y if x < y, otherwise it returns x.
*/
char __ovld __cnfn max(char x, char y);
uchar __ovld __cnfn max(uchar x, uchar y);
char2 __ovld __cnfn max(char2 x, char2 y);
uchar2 __ovld __cnfn max(uchar2 x, uchar2 y);
char3 __ovld __cnfn max(char3 x, char3 y);
uchar3 __ovld __cnfn max(uchar3 x, uchar3 y);
char4 __ovld __cnfn max(char4 x, char4 y);
uchar4 __ovld __cnfn max(uchar4 x, uchar4 y);
char8 __ovld __cnfn max(char8 x, char8 y);
uchar8 __ovld __cnfn max(uchar8 x, uchar8 y);
char16 __ovld __cnfn max(char16 x, char16 y);
uchar16 __ovld __cnfn max(uchar16 x, uchar16 y);
short __ovld __cnfn max(short x, short y);
ushort __ovld __cnfn max(ushort x, ushort y);
short2 __ovld __cnfn max(short2 x, short2 y);
ushort2 __ovld __cnfn max(ushort2 x, ushort2 y);
short3 __ovld __cnfn max(short3 x, short3 y);
ushort3 __ovld __cnfn max(ushort3 x, ushort3 y);
short4 __ovld __cnfn max(short4 x, short4 y);
ushort4 __ovld __cnfn max(ushort4 x, ushort4 y);
short8 __ovld __cnfn max(short8 x, short8 y);
ushort8 __ovld __cnfn max(ushort8 x, ushort8 y);
short16 __ovld __cnfn max(short16 x, short16 y);
ushort16 __ovld __cnfn max(ushort16 x, ushort16 y);
int __ovld __cnfn max(int x, int y);
uint __ovld __cnfn max(uint x, uint y);
int2 __ovld __cnfn max(int2 x, int2 y);
uint2 __ovld __cnfn max(uint2 x, uint2 y);
int3 __ovld __cnfn max(int3 x, int3 y);
uint3 __ovld __cnfn max(uint3 x, uint3 y);
int4 __ovld __cnfn max(int4 x, int4 y);
uint4 __ovld __cnfn max(uint4 x, uint4 y);
int8 __ovld __cnfn max(int8 x, int8 y);
uint8 __ovld __cnfn max(uint8 x, uint8 y);
int16 __ovld __cnfn max(int16 x, int16 y);
uint16 __ovld __cnfn max(uint16 x, uint16 y);
long __ovld __cnfn max(long x, long y);
ulong __ovld __cnfn max(ulong x, ulong y);
long2 __ovld __cnfn max(long2 x, long2 y);
ulong2 __ovld __cnfn max(ulong2 x, ulong2 y);
long3 __ovld __cnfn max(long3 x, long3 y);
ulong3 __ovld __cnfn max(ulong3 x, ulong3 y);
long4 __ovld __cnfn max(long4 x, long4 y);
ulong4 __ovld __cnfn max(ulong4 x, ulong4 y);
long8 __ovld __cnfn max(long8 x, long8 y);
ulong8 __ovld __cnfn max(ulong8 x, ulong8 y);
long16 __ovld __cnfn max(long16 x, long16 y);
ulong16 __ovld __cnfn max(ulong16 x, ulong16 y);
char __ovld __cnfn max(char x, char y);
uchar __ovld __cnfn max(uchar x, uchar y);
char2 __ovld __cnfn max(char2 x, char y);
uchar2 __ovld __cnfn max(uchar2 x, uchar y);
char3 __ovld __cnfn max(char3 x, char y);
uchar3 __ovld __cnfn max(uchar3 x, uchar y);
char4 __ovld __cnfn max(char4 x, char y);
uchar4 __ovld __cnfn max(uchar4 x, uchar y);
char8 __ovld __cnfn max(char8 x, char y);
uchar8 __ovld __cnfn max(uchar8 x, uchar y);
char16 __ovld __cnfn max(char16 x, char y);
uchar16 __ovld __cnfn max(uchar16 x, uchar y);
short __ovld __cnfn max(short x, short y);
ushort __ovld __cnfn max(ushort x, ushort y);
short2 __ovld __cnfn max(short2 x, short y);
ushort2 __ovld __cnfn max(ushort2 x, ushort y);
short3 __ovld __cnfn max(short3 x, short y);
ushort3 __ovld __cnfn max(ushort3 x, ushort y);
short4 __ovld __cnfn max(short4 x, short y);
ushort4 __ovld __cnfn max(ushort4 x, ushort y);
short8 __ovld __cnfn max(short8 x, short y);
ushort8 __ovld __cnfn max(ushort8 x, ushort y);
short16 __ovld __cnfn max(short16 x, short y);
ushort16 __ovld __cnfn max(ushort16 x, ushort y);
int __ovld __cnfn max(int x, int y);
uint __ovld __cnfn max(uint x, uint y);
int2 __ovld __cnfn max(int2 x, int y);
uint2 __ovld __cnfn max(uint2 x, uint y);
int3 __ovld __cnfn max(int3 x, int y);
uint3 __ovld __cnfn max(uint3 x, uint y);
int4 __ovld __cnfn max(int4 x, int y);
uint4 __ovld __cnfn max(uint4 x, uint y);
int8 __ovld __cnfn max(int8 x, int y);
uint8 __ovld __cnfn max(uint8 x, uint y);
int16 __ovld __cnfn max(int16 x, int y);
uint16 __ovld __cnfn max(uint16 x, uint y);
long __ovld __cnfn max(long x, long y);
ulong __ovld __cnfn max(ulong x, ulong y);
long2 __ovld __cnfn max(long2 x, long y);
ulong2 __ovld __cnfn max(ulong2 x, ulong y);
long3 __ovld __cnfn max(long3 x, long y);
ulong3 __ovld __cnfn max(ulong3 x, ulong y);
long4 __ovld __cnfn max(long4 x, long y);
ulong4 __ovld __cnfn max(ulong4 x, ulong y);
long8 __ovld __cnfn max(long8 x, long y);
ulong8 __ovld __cnfn max(ulong8 x, ulong y);
long16 __ovld __cnfn max(long16 x, long y);
ulong16 __ovld __cnfn max(ulong16 x, ulong y);
/**
* Returns y if y < x, otherwise it returns x.
*/
char __ovld __cnfn min(char x, char y);
uchar __ovld __cnfn min(uchar x, uchar y);
char2 __ovld __cnfn min(char2 x, char2 y);
uchar2 __ovld __cnfn min(uchar2 x, uchar2 y);
char3 __ovld __cnfn min(char3 x, char3 y);
uchar3 __ovld __cnfn min(uchar3 x, uchar3 y);
char4 __ovld __cnfn min(char4 x, char4 y);
uchar4 __ovld __cnfn min(uchar4 x, uchar4 y);
char8 __ovld __cnfn min(char8 x, char8 y);
uchar8 __ovld __cnfn min(uchar8 x, uchar8 y);
char16 __ovld __cnfn min(char16 x, char16 y);
uchar16 __ovld __cnfn min(uchar16 x, uchar16 y);
short __ovld __cnfn min(short x, short y);
ushort __ovld __cnfn min(ushort x, ushort y);
short2 __ovld __cnfn min(short2 x, short2 y);
ushort2 __ovld __cnfn min(ushort2 x, ushort2 y);
short3 __ovld __cnfn min(short3 x, short3 y);
ushort3 __ovld __cnfn min(ushort3 x, ushort3 y);
short4 __ovld __cnfn min(short4 x, short4 y);
ushort4 __ovld __cnfn min(ushort4 x, ushort4 y);
short8 __ovld __cnfn min(short8 x, short8 y);
ushort8 __ovld __cnfn min(ushort8 x, ushort8 y);
short16 __ovld __cnfn min(short16 x, short16 y);
ushort16 __ovld __cnfn min(ushort16 x, ushort16 y);
int __ovld __cnfn min(int x, int y);
uint __ovld __cnfn min(uint x, uint y);
int2 __ovld __cnfn min(int2 x, int2 y);
uint2 __ovld __cnfn min(uint2 x, uint2 y);
int3 __ovld __cnfn min(int3 x, int3 y);
uint3 __ovld __cnfn min(uint3 x, uint3 y);
int4 __ovld __cnfn min(int4 x, int4 y);
uint4 __ovld __cnfn min(uint4 x, uint4 y);
int8 __ovld __cnfn min(int8 x, int8 y);
uint8 __ovld __cnfn min(uint8 x, uint8 y);
int16 __ovld __cnfn min(int16 x, int16 y);
uint16 __ovld __cnfn min(uint16 x, uint16 y);
long __ovld __cnfn min(long x, long y);
ulong __ovld __cnfn min(ulong x, ulong y);
long2 __ovld __cnfn min(long2 x, long2 y);
ulong2 __ovld __cnfn min(ulong2 x, ulong2 y);
long3 __ovld __cnfn min(long3 x, long3 y);
ulong3 __ovld __cnfn min(ulong3 x, ulong3 y);
long4 __ovld __cnfn min(long4 x, long4 y);
ulong4 __ovld __cnfn min(ulong4 x, ulong4 y);
long8 __ovld __cnfn min(long8 x, long8 y);
ulong8 __ovld __cnfn min(ulong8 x, ulong8 y);
long16 __ovld __cnfn min(long16 x, long16 y);
ulong16 __ovld __cnfn min(ulong16 x, ulong16 y);
char __ovld __cnfn min(char x, char y);
uchar __ovld __cnfn min(uchar x, uchar y);
char2 __ovld __cnfn min(char2 x, char y);
uchar2 __ovld __cnfn min(uchar2 x, uchar y);
char3 __ovld __cnfn min(char3 x, char y);
uchar3 __ovld __cnfn min(uchar3 x, uchar y);
char4 __ovld __cnfn min(char4 x, char y);
uchar4 __ovld __cnfn min(uchar4 x, uchar y);
char8 __ovld __cnfn min(char8 x, char y);
uchar8 __ovld __cnfn min(uchar8 x, uchar y);
char16 __ovld __cnfn min(char16 x, char y);
uchar16 __ovld __cnfn min(uchar16 x, uchar y);
short __ovld __cnfn min(short x, short y);
ushort __ovld __cnfn min(ushort x, ushort y);
short2 __ovld __cnfn min(short2 x, short y);
ushort2 __ovld __cnfn min(ushort2 x, ushort y);
short3 __ovld __cnfn min(short3 x, short y);
ushort3 __ovld __cnfn min(ushort3 x, ushort y);
short4 __ovld __cnfn min(short4 x, short y);
ushort4 __ovld __cnfn min(ushort4 x, ushort y);
short8 __ovld __cnfn min(short8 x, short y);
ushort8 __ovld __cnfn min(ushort8 x, ushort y);
short16 __ovld __cnfn min(short16 x, short y);
ushort16 __ovld __cnfn min(ushort16 x, ushort y);
int __ovld __cnfn min(int x, int y);
uint __ovld __cnfn min(uint x, uint y);
int2 __ovld __cnfn min(int2 x, int y);
uint2 __ovld __cnfn min(uint2 x, uint y);
int3 __ovld __cnfn min(int3 x, int y);
uint3 __ovld __cnfn min(uint3 x, uint y);
int4 __ovld __cnfn min(int4 x, int y);
uint4 __ovld __cnfn min(uint4 x, uint y);
int8 __ovld __cnfn min(int8 x, int y);
uint8 __ovld __cnfn min(uint8 x, uint y);
int16 __ovld __cnfn min(int16 x, int y);
uint16 __ovld __cnfn min(uint16 x, uint y);
long __ovld __cnfn min(long x, long y);
ulong __ovld __cnfn min(ulong x, ulong y);
long2 __ovld __cnfn min(long2 x, long y);
ulong2 __ovld __cnfn min(ulong2 x, ulong y);
long3 __ovld __cnfn min(long3 x, long y);
ulong3 __ovld __cnfn min(ulong3 x, ulong y);
long4 __ovld __cnfn min(long4 x, long y);
ulong4 __ovld __cnfn min(ulong4 x, ulong y);
long8 __ovld __cnfn min(long8 x, long y);
ulong8 __ovld __cnfn min(ulong8 x, ulong y);
long16 __ovld __cnfn min(long16 x, long y);
ulong16 __ovld __cnfn min(ulong16 x, ulong y);
/**
* Computes x * y and returns the high half of the
* product of x and y.
*/
char __ovld __cnfn mul_hi(char x, char y);
uchar __ovld __cnfn mul_hi(uchar x, uchar y);
char2 __ovld __cnfn mul_hi(char2 x, char2 y);
uchar2 __ovld __cnfn mul_hi(uchar2 x, uchar2 y);
char3 __ovld __cnfn mul_hi(char3 x, char3 y);
uchar3 __ovld __cnfn mul_hi(uchar3 x, uchar3 y);
char4 __ovld __cnfn mul_hi(char4 x, char4 y);
uchar4 __ovld __cnfn mul_hi(uchar4 x, uchar4 y);
char8 __ovld __cnfn mul_hi(char8 x, char8 y);
uchar8 __ovld __cnfn mul_hi(uchar8 x, uchar8 y);
char16 __ovld __cnfn mul_hi(char16 x, char16 y);
uchar16 __ovld __cnfn mul_hi(uchar16 x, uchar16 y);
short __ovld __cnfn mul_hi(short x, short y);
ushort __ovld __cnfn mul_hi(ushort x, ushort y);
short2 __ovld __cnfn mul_hi(short2 x, short2 y);
ushort2 __ovld __cnfn mul_hi(ushort2 x, ushort2 y);
short3 __ovld __cnfn mul_hi(short3 x, short3 y);
ushort3 __ovld __cnfn mul_hi(ushort3 x, ushort3 y);
short4 __ovld __cnfn mul_hi(short4 x, short4 y);
ushort4 __ovld __cnfn mul_hi(ushort4 x, ushort4 y);
short8 __ovld __cnfn mul_hi(short8 x, short8 y);
ushort8 __ovld __cnfn mul_hi(ushort8 x, ushort8 y);
short16 __ovld __cnfn mul_hi(short16 x, short16 y);
ushort16 __ovld __cnfn mul_hi(ushort16 x, ushort16 y);
int __ovld __cnfn mul_hi(int x, int y);
uint __ovld __cnfn mul_hi(uint x, uint y);
int2 __ovld __cnfn mul_hi(int2 x, int2 y);
uint2 __ovld __cnfn mul_hi(uint2 x, uint2 y);
int3 __ovld __cnfn mul_hi(int3 x, int3 y);
uint3 __ovld __cnfn mul_hi(uint3 x, uint3 y);
int4 __ovld __cnfn mul_hi(int4 x, int4 y);
uint4 __ovld __cnfn mul_hi(uint4 x, uint4 y);
int8 __ovld __cnfn mul_hi(int8 x, int8 y);
uint8 __ovld __cnfn mul_hi(uint8 x, uint8 y);
int16 __ovld __cnfn mul_hi(int16 x, int16 y);
uint16 __ovld __cnfn mul_hi(uint16 x, uint16 y);
long __ovld __cnfn mul_hi(long x, long y);
ulong __ovld __cnfn mul_hi(ulong x, ulong y);
long2 __ovld __cnfn mul_hi(long2 x, long2 y);
ulong2 __ovld __cnfn mul_hi(ulong2 x, ulong2 y);
long3 __ovld __cnfn mul_hi(long3 x, long3 y);
ulong3 __ovld __cnfn mul_hi(ulong3 x, ulong3 y);
long4 __ovld __cnfn mul_hi(long4 x, long4 y);
ulong4 __ovld __cnfn mul_hi(ulong4 x, ulong4 y);
long8 __ovld __cnfn mul_hi(long8 x, long8 y);
ulong8 __ovld __cnfn mul_hi(ulong8 x, ulong8 y);
long16 __ovld __cnfn mul_hi(long16 x, long16 y);
ulong16 __ovld __cnfn mul_hi(ulong16 x, ulong16 y);
/**
* For each element in v, the bits are shifted left by
* the number of bits given by the corresponding
* element in i (subject to usual shift modulo rules
* described in section 6.3). Bits shifted off the left
* side of the element are shifted back in from the
* right.
*/
char __ovld __cnfn rotate(char v, char i);
uchar __ovld __cnfn rotate(uchar v, uchar i);
char2 __ovld __cnfn rotate(char2 v, char2 i);
uchar2 __ovld __cnfn rotate(uchar2 v, uchar2 i);
char3 __ovld __cnfn rotate(char3 v, char3 i);
uchar3 __ovld __cnfn rotate(uchar3 v, uchar3 i);
char4 __ovld __cnfn rotate(char4 v, char4 i);
uchar4 __ovld __cnfn rotate(uchar4 v, uchar4 i);
char8 __ovld __cnfn rotate(char8 v, char8 i);
uchar8 __ovld __cnfn rotate(uchar8 v, uchar8 i);
char16 __ovld __cnfn rotate(char16 v, char16 i);
uchar16 __ovld __cnfn rotate(uchar16 v, uchar16 i);
short __ovld __cnfn rotate(short v, short i);
ushort __ovld __cnfn rotate(ushort v, ushort i);
short2 __ovld __cnfn rotate(short2 v, short2 i);
ushort2 __ovld __cnfn rotate(ushort2 v, ushort2 i);
short3 __ovld __cnfn rotate(short3 v, short3 i);
ushort3 __ovld __cnfn rotate(ushort3 v, ushort3 i);
short4 __ovld __cnfn rotate(short4 v, short4 i);
ushort4 __ovld __cnfn rotate(ushort4 v, ushort4 i);
short8 __ovld __cnfn rotate(short8 v, short8 i);
ushort8 __ovld __cnfn rotate(ushort8 v, ushort8 i);
short16 __ovld __cnfn rotate(short16 v, short16 i);
ushort16 __ovld __cnfn rotate(ushort16 v, ushort16 i);
int __ovld __cnfn rotate(int v, int i);
uint __ovld __cnfn rotate(uint v, uint i);
int2 __ovld __cnfn rotate(int2 v, int2 i);
uint2 __ovld __cnfn rotate(uint2 v, uint2 i);
int3 __ovld __cnfn rotate(int3 v, int3 i);
uint3 __ovld __cnfn rotate(uint3 v, uint3 i);
int4 __ovld __cnfn rotate(int4 v, int4 i);
uint4 __ovld __cnfn rotate(uint4 v, uint4 i);
int8 __ovld __cnfn rotate(int8 v, int8 i);
uint8 __ovld __cnfn rotate(uint8 v, uint8 i);
int16 __ovld __cnfn rotate(int16 v, int16 i);
uint16 __ovld __cnfn rotate(uint16 v, uint16 i);
long __ovld __cnfn rotate(long v, long i);
ulong __ovld __cnfn rotate(ulong v, ulong i);
long2 __ovld __cnfn rotate(long2 v, long2 i);
ulong2 __ovld __cnfn rotate(ulong2 v, ulong2 i);
long3 __ovld __cnfn rotate(long3 v, long3 i);
ulong3 __ovld __cnfn rotate(ulong3 v, ulong3 i);
long4 __ovld __cnfn rotate(long4 v, long4 i);
ulong4 __ovld __cnfn rotate(ulong4 v, ulong4 i);
long8 __ovld __cnfn rotate(long8 v, long8 i);
ulong8 __ovld __cnfn rotate(ulong8 v, ulong8 i);
long16 __ovld __cnfn rotate(long16 v, long16 i);
ulong16 __ovld __cnfn rotate(ulong16 v, ulong16 i);
/**
* Returns x - y and saturates the result.
*/
char __ovld __cnfn sub_sat(char x, char y);
uchar __ovld __cnfn sub_sat(uchar x, uchar y);
char2 __ovld __cnfn sub_sat(char2 x, char2 y);
uchar2 __ovld __cnfn sub_sat(uchar2 x, uchar2 y);
char3 __ovld __cnfn sub_sat(char3 x, char3 y);
uchar3 __ovld __cnfn sub_sat(uchar3 x, uchar3 y);
char4 __ovld __cnfn sub_sat(char4 x, char4 y);
uchar4 __ovld __cnfn sub_sat(uchar4 x, uchar4 y);
char8 __ovld __cnfn sub_sat(char8 x, char8 y);
uchar8 __ovld __cnfn sub_sat(uchar8 x, uchar8 y);
char16 __ovld __cnfn sub_sat(char16 x, char16 y);
uchar16 __ovld __cnfn sub_sat(uchar16 x, uchar16 y);
short __ovld __cnfn sub_sat(short x, short y);
ushort __ovld __cnfn sub_sat(ushort x, ushort y);
short2 __ovld __cnfn sub_sat(short2 x, short2 y);
ushort2 __ovld __cnfn sub_sat(ushort2 x, ushort2 y);
short3 __ovld __cnfn sub_sat(short3 x, short3 y);
ushort3 __ovld __cnfn sub_sat(ushort3 x, ushort3 y);
short4 __ovld __cnfn sub_sat(short4 x, short4 y);
ushort4 __ovld __cnfn sub_sat(ushort4 x, ushort4 y);
short8 __ovld __cnfn sub_sat(short8 x, short8 y);
ushort8 __ovld __cnfn sub_sat(ushort8 x, ushort8 y);
short16 __ovld __cnfn sub_sat(short16 x, short16 y);
ushort16 __ovld __cnfn sub_sat(ushort16 x, ushort16 y);
int __ovld __cnfn sub_sat(int x, int y);
uint __ovld __cnfn sub_sat(uint x, uint y);
int2 __ovld __cnfn sub_sat(int2 x, int2 y);
uint2 __ovld __cnfn sub_sat(uint2 x, uint2 y);
int3 __ovld __cnfn sub_sat(int3 x, int3 y);
uint3 __ovld __cnfn sub_sat(uint3 x, uint3 y);
int4 __ovld __cnfn sub_sat(int4 x, int4 y);
uint4 __ovld __cnfn sub_sat(uint4 x, uint4 y);
int8 __ovld __cnfn sub_sat(int8 x, int8 y);
uint8 __ovld __cnfn sub_sat(uint8 x, uint8 y);
int16 __ovld __cnfn sub_sat(int16 x, int16 y);
uint16 __ovld __cnfn sub_sat(uint16 x, uint16 y);
long __ovld __cnfn sub_sat(long x, long y);
ulong __ovld __cnfn sub_sat(ulong x, ulong y);
long2 __ovld __cnfn sub_sat(long2 x, long2 y);
ulong2 __ovld __cnfn sub_sat(ulong2 x, ulong2 y);
long3 __ovld __cnfn sub_sat(long3 x, long3 y);
ulong3 __ovld __cnfn sub_sat(ulong3 x, ulong3 y);
long4 __ovld __cnfn sub_sat(long4 x, long4 y);
ulong4 __ovld __cnfn sub_sat(ulong4 x, ulong4 y);
long8 __ovld __cnfn sub_sat(long8 x, long8 y);
ulong8 __ovld __cnfn sub_sat(ulong8 x, ulong8 y);
long16 __ovld __cnfn sub_sat(long16 x, long16 y);
ulong16 __ovld __cnfn sub_sat(ulong16 x, ulong16 y);
/**
* result[i] = ((short)hi[i] << 8) | lo[i]
* result[i] = ((ushort)hi[i] << 8) | lo[i]
*/
short __ovld __cnfn upsample(char hi, uchar lo);
ushort __ovld __cnfn upsample(uchar hi, uchar lo);
short2 __ovld __cnfn upsample(char2 hi, uchar2 lo);
short3 __ovld __cnfn upsample(char3 hi, uchar3 lo);
short4 __ovld __cnfn upsample(char4 hi, uchar4 lo);
short8 __ovld __cnfn upsample(char8 hi, uchar8 lo);
short16 __ovld __cnfn upsample(char16 hi, uchar16 lo);
ushort2 __ovld __cnfn upsample(uchar2 hi, uchar2 lo);
ushort3 __ovld __cnfn upsample(uchar3 hi, uchar3 lo);
ushort4 __ovld __cnfn upsample(uchar4 hi, uchar4 lo);
ushort8 __ovld __cnfn upsample(uchar8 hi, uchar8 lo);
ushort16 __ovld __cnfn upsample(uchar16 hi, uchar16 lo);
/**
* result[i] = ((int)hi[i] << 16) | lo[i]
* result[i] = ((uint)hi[i] << 16) | lo[i]
*/
int __ovld __cnfn upsample(short hi, ushort lo);
uint __ovld __cnfn upsample(ushort hi, ushort lo);
int2 __ovld __cnfn upsample(short2 hi, ushort2 lo);
int3 __ovld __cnfn upsample(short3 hi, ushort3 lo);
int4 __ovld __cnfn upsample(short4 hi, ushort4 lo);
int8 __ovld __cnfn upsample(short8 hi, ushort8 lo);
int16 __ovld __cnfn upsample(short16 hi, ushort16 lo);
uint2 __ovld __cnfn upsample(ushort2 hi, ushort2 lo);
uint3 __ovld __cnfn upsample(ushort3 hi, ushort3 lo);
uint4 __ovld __cnfn upsample(ushort4 hi, ushort4 lo);
uint8 __ovld __cnfn upsample(ushort8 hi, ushort8 lo);
uint16 __ovld __cnfn upsample(ushort16 hi, ushort16 lo);
/**
* result[i] = ((long)hi[i] << 32) | lo[i]
* result[i] = ((ulong)hi[i] << 32) | lo[i]
*/
long __ovld __cnfn upsample(int hi, uint lo);
ulong __ovld __cnfn upsample(uint hi, uint lo);
long2 __ovld __cnfn upsample(int2 hi, uint2 lo);
long3 __ovld __cnfn upsample(int3 hi, uint3 lo);
long4 __ovld __cnfn upsample(int4 hi, uint4 lo);
long8 __ovld __cnfn upsample(int8 hi, uint8 lo);
long16 __ovld __cnfn upsample(int16 hi, uint16 lo);
ulong2 __ovld __cnfn upsample(uint2 hi, uint2 lo);
ulong3 __ovld __cnfn upsample(uint3 hi, uint3 lo);
ulong4 __ovld __cnfn upsample(uint4 hi, uint4 lo);
ulong8 __ovld __cnfn upsample(uint8 hi, uint8 lo);
ulong16 __ovld __cnfn upsample(uint16 hi, uint16 lo);
/*
* popcount(x): returns the number of set bit in x
*/
char __ovld __cnfn popcount(char x);
uchar __ovld __cnfn popcount(uchar x);
char2 __ovld __cnfn popcount(char2 x);
uchar2 __ovld __cnfn popcount(uchar2 x);
char3 __ovld __cnfn popcount(char3 x);
uchar3 __ovld __cnfn popcount(uchar3 x);
char4 __ovld __cnfn popcount(char4 x);
uchar4 __ovld __cnfn popcount(uchar4 x);
char8 __ovld __cnfn popcount(char8 x);
uchar8 __ovld __cnfn popcount(uchar8 x);
char16 __ovld __cnfn popcount(char16 x);
uchar16 __ovld __cnfn popcount(uchar16 x);
short __ovld __cnfn popcount(short x);
ushort __ovld __cnfn popcount(ushort x);
short2 __ovld __cnfn popcount(short2 x);
ushort2 __ovld __cnfn popcount(ushort2 x);
short3 __ovld __cnfn popcount(short3 x);
ushort3 __ovld __cnfn popcount(ushort3 x);
short4 __ovld __cnfn popcount(short4 x);
ushort4 __ovld __cnfn popcount(ushort4 x);
short8 __ovld __cnfn popcount(short8 x);
ushort8 __ovld __cnfn popcount(ushort8 x);
short16 __ovld __cnfn popcount(short16 x);
ushort16 __ovld __cnfn popcount(ushort16 x);
int __ovld __cnfn popcount(int x);
uint __ovld __cnfn popcount(uint x);
int2 __ovld __cnfn popcount(int2 x);
uint2 __ovld __cnfn popcount(uint2 x);
int3 __ovld __cnfn popcount(int3 x);
uint3 __ovld __cnfn popcount(uint3 x);
int4 __ovld __cnfn popcount(int4 x);
uint4 __ovld __cnfn popcount(uint4 x);
int8 __ovld __cnfn popcount(int8 x);
uint8 __ovld __cnfn popcount(uint8 x);
int16 __ovld __cnfn popcount(int16 x);
uint16 __ovld __cnfn popcount(uint16 x);
long __ovld __cnfn popcount(long x);
ulong __ovld __cnfn popcount(ulong x);
long2 __ovld __cnfn popcount(long2 x);
ulong2 __ovld __cnfn popcount(ulong2 x);
long3 __ovld __cnfn popcount(long3 x);
ulong3 __ovld __cnfn popcount(ulong3 x);
long4 __ovld __cnfn popcount(long4 x);
ulong4 __ovld __cnfn popcount(ulong4 x);
long8 __ovld __cnfn popcount(long8 x);
ulong8 __ovld __cnfn popcount(ulong8 x);
long16 __ovld __cnfn popcount(long16 x);
ulong16 __ovld __cnfn popcount(ulong16 x);
/**
* Multiply two 24-bit integer values x and y and add
* the 32-bit integer result to the 32-bit integer z.
* Refer to definition of mul24 to see how the 24-bit
* integer multiplication is performed.
*/
int __ovld __cnfn mad24(int x, int y, int z);
uint __ovld __cnfn mad24(uint x, uint y, uint z);
int2 __ovld __cnfn mad24(int2 x, int2 y, int2 z);
uint2 __ovld __cnfn mad24(uint2 x, uint2 y, uint2 z);
int3 __ovld __cnfn mad24(int3 x, int3 y, int3 z);
uint3 __ovld __cnfn mad24(uint3 x, uint3 y, uint3 z);
int4 __ovld __cnfn mad24(int4 x, int4 y, int4 z);
uint4 __ovld __cnfn mad24(uint4 x, uint4 y, uint4 z);
int8 __ovld __cnfn mad24(int8 x, int8 y, int8 z);
uint8 __ovld __cnfn mad24(uint8 x, uint8 y, uint8 z);
int16 __ovld __cnfn mad24(int16 x, int16 y, int16 z);
uint16 __ovld __cnfn mad24(uint16 x, uint16 y, uint16 z);
/**
* Multiply two 24-bit integer values x and y. x and y
* are 32-bit integers but only the low 24-bits are used
* to perform the multiplication. mul24 should only
* be used when values in x and y are in the range [-
* 2^23, 2^23-1] if x and y are signed integers and in the
* range [0, 2^24-1] if x and y are unsigned integers. If
* x and y are not in this range, the multiplication
* result is implementation-defined.
*/
int __ovld __cnfn mul24(int x, int y);
uint __ovld __cnfn mul24(uint x, uint y);
int2 __ovld __cnfn mul24(int2 x, int2 y);
uint2 __ovld __cnfn mul24(uint2 x, uint2 y);
int3 __ovld __cnfn mul24(int3 x, int3 y);
uint3 __ovld __cnfn mul24(uint3 x, uint3 y);
int4 __ovld __cnfn mul24(int4 x, int4 y);
uint4 __ovld __cnfn mul24(uint4 x, uint4 y);
int8 __ovld __cnfn mul24(int8 x, int8 y);
uint8 __ovld __cnfn mul24(uint8 x, uint8 y);
int16 __ovld __cnfn mul24(int16 x, int16 y);
uint16 __ovld __cnfn mul24(uint16 x, uint16 y);
// OpenCL v1.1 s6.11.4, v1.2 s6.12.4, v2.0 s6.13.4 - Common Functions
/**
* Returns fmin(fmax(x, minval), maxval).
* Results are undefined if minval > maxval.
*/
float __ovld __cnfn clamp(float x, float minval, float maxval);
float2 __ovld __cnfn clamp(float2 x, float2 minval, float2 maxval);
float3 __ovld __cnfn clamp(float3 x, float3 minval, float3 maxval);
float4 __ovld __cnfn clamp(float4 x, float4 minval, float4 maxval);
float8 __ovld __cnfn clamp(float8 x, float8 minval, float8 maxval);
float16 __ovld __cnfn clamp(float16 x, float16 minval, float16 maxval);
float2 __ovld __cnfn clamp(float2 x, float minval, float maxval);
float3 __ovld __cnfn clamp(float3 x, float minval, float maxval);
float4 __ovld __cnfn clamp(float4 x, float minval, float maxval);
float8 __ovld __cnfn clamp(float8 x, float minval, float maxval);
float16 __ovld __cnfn clamp(float16 x, float minval, float maxval);
#ifdef cl_khr_fp64
double __ovld __cnfn clamp(double x, double minval, double maxval);
double2 __ovld __cnfn clamp(double2 x, double2 minval, double2 maxval);
double3 __ovld __cnfn clamp(double3 x, double3 minval, double3 maxval);
double4 __ovld __cnfn clamp(double4 x, double4 minval, double4 maxval);
double8 __ovld __cnfn clamp(double8 x, double8 minval, double8 maxval);
double16 __ovld __cnfn clamp(double16 x, double16 minval, double16 maxval);
double2 __ovld __cnfn clamp(double2 x, double minval, double maxval);
double3 __ovld __cnfn clamp(double3 x, double minval, double maxval);
double4 __ovld __cnfn clamp(double4 x, double minval, double maxval);
double8 __ovld __cnfn clamp(double8 x, double minval, double maxval);
double16 __ovld __cnfn clamp(double16 x, double minval, double maxval);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn clamp(half x, half minval, half maxval);
half2 __ovld __cnfn clamp(half2 x, half2 minval, half2 maxval);
half3 __ovld __cnfn clamp(half3 x, half3 minval, half3 maxval);
half4 __ovld __cnfn clamp(half4 x, half4 minval, half4 maxval);
half8 __ovld __cnfn clamp(half8 x, half8 minval, half8 maxval);
half16 __ovld __cnfn clamp(half16 x, half16 minval, half16 maxval);
half2 __ovld __cnfn clamp(half2 x, half minval, half maxval);
half3 __ovld __cnfn clamp(half3 x, half minval, half maxval);
half4 __ovld __cnfn clamp(half4 x, half minval, half maxval);
half8 __ovld __cnfn clamp(half8 x, half minval, half maxval);
half16 __ovld __cnfn clamp(half16 x, half minval, half maxval);
#endif //cl_khr_fp16
/**
* Converts radians to degrees, i.e. (180 / PI) *
* radians.
*/
float __ovld __cnfn degrees(float radians);
float2 __ovld __cnfn degrees(float2 radians);
float3 __ovld __cnfn degrees(float3 radians);
float4 __ovld __cnfn degrees(float4 radians);
float8 __ovld __cnfn degrees(float8 radians);
float16 __ovld __cnfn degrees(float16 radians);
#ifdef cl_khr_fp64
double __ovld __cnfn degrees(double radians);
double2 __ovld __cnfn degrees(double2 radians);
double3 __ovld __cnfn degrees(double3 radians);
double4 __ovld __cnfn degrees(double4 radians);
double8 __ovld __cnfn degrees(double8 radians);
double16 __ovld __cnfn degrees(double16 radians);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn degrees(half radians);
half2 __ovld __cnfn degrees(half2 radians);
half3 __ovld __cnfn degrees(half3 radians);
half4 __ovld __cnfn degrees(half4 radians);
half8 __ovld __cnfn degrees(half8 radians);
half16 __ovld __cnfn degrees(half16 radians);
#endif //cl_khr_fp16
/**
* Returns y if x < y, otherwise it returns x. If x and y
* are infinite or NaN, the return values are undefined.
*/
float __ovld __cnfn max(float x, float y);
float2 __ovld __cnfn max(float2 x, float2 y);
float3 __ovld __cnfn max(float3 x, float3 y);
float4 __ovld __cnfn max(float4 x, float4 y);
float8 __ovld __cnfn max(float8 x, float8 y);
float16 __ovld __cnfn max(float16 x, float16 y);
float2 __ovld __cnfn max(float2 x, float y);
float3 __ovld __cnfn max(float3 x, float y);
float4 __ovld __cnfn max(float4 x, float y);
float8 __ovld __cnfn max(float8 x, float y);
float16 __ovld __cnfn max(float16 x, float y);
#ifdef cl_khr_fp64
double __ovld __cnfn max(double x, double y);
double2 __ovld __cnfn max(double2 x, double2 y);
double3 __ovld __cnfn max(double3 x, double3 y);
double4 __ovld __cnfn max(double4 x, double4 y);
double8 __ovld __cnfn max(double8 x, double8 y);
double16 __ovld __cnfn max(double16 x, double16 y);
double2 __ovld __cnfn max(double2 x, double y);
double3 __ovld __cnfn max(double3 x, double y);
double4 __ovld __cnfn max(double4 x, double y);
double8 __ovld __cnfn max(double8 x, double y);
double16 __ovld __cnfn max(double16 x, double y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn max(half x, half y);
half2 __ovld __cnfn max(half2 x, half2 y);
half3 __ovld __cnfn max(half3 x, half3 y);
half4 __ovld __cnfn max(half4 x, half4 y);
half8 __ovld __cnfn max(half8 x, half8 y);
half16 __ovld __cnfn max(half16 x, half16 y);
half2 __ovld __cnfn max(half2 x, half y);
half3 __ovld __cnfn max(half3 x, half y);
half4 __ovld __cnfn max(half4 x, half y);
half8 __ovld __cnfn max(half8 x, half y);
half16 __ovld __cnfn max(half16 x, half y);
#endif //cl_khr_fp16
/**
* Returns y if y < x, otherwise it returns x. If x and y
* are infinite or NaN, the return values are undefined.
*/
float __ovld __cnfn min(float x, float y);
float2 __ovld __cnfn min(float2 x, float2 y);
float3 __ovld __cnfn min(float3 x, float3 y);
float4 __ovld __cnfn min(float4 x, float4 y);
float8 __ovld __cnfn min(float8 x, float8 y);
float16 __ovld __cnfn min(float16 x, float16 y);
float2 __ovld __cnfn min(float2 x, float y);
float3 __ovld __cnfn min(float3 x, float y);
float4 __ovld __cnfn min(float4 x, float y);
float8 __ovld __cnfn min(float8 x, float y);
float16 __ovld __cnfn min(float16 x, float y);
#ifdef cl_khr_fp64
double __ovld __cnfn min(double x, double y);
double2 __ovld __cnfn min(double2 x, double2 y);
double3 __ovld __cnfn min(double3 x, double3 y);
double4 __ovld __cnfn min(double4 x, double4 y);
double8 __ovld __cnfn min(double8 x, double8 y);
double16 __ovld __cnfn min(double16 x, double16 y);
double2 __ovld __cnfn min(double2 x, double y);
double3 __ovld __cnfn min(double3 x, double y);
double4 __ovld __cnfn min(double4 x, double y);
double8 __ovld __cnfn min(double8 x, double y);
double16 __ovld __cnfn min(double16 x, double y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn min(half x, half y);
half2 __ovld __cnfn min(half2 x, half2 y);
half3 __ovld __cnfn min(half3 x, half3 y);
half4 __ovld __cnfn min(half4 x, half4 y);
half8 __ovld __cnfn min(half8 x, half8 y);
half16 __ovld __cnfn min(half16 x, half16 y);
half2 __ovld __cnfn min(half2 x, half y);
half3 __ovld __cnfn min(half3 x, half y);
half4 __ovld __cnfn min(half4 x, half y);
half8 __ovld __cnfn min(half8 x, half y);
half16 __ovld __cnfn min(half16 x, half y);
#endif //cl_khr_fp16
/**
* Returns the linear blend of x & y implemented as:
* x + (y - x) * a
* a must be a value in the range 0.0 ... 1.0. If a is not
* in the range 0.0 ... 1.0, the return values are
* undefined.
*/
float __ovld __cnfn mix(float x, float y, float a);
float2 __ovld __cnfn mix(float2 x, float2 y, float2 a);
float3 __ovld __cnfn mix(float3 x, float3 y, float3 a);
float4 __ovld __cnfn mix(float4 x, float4 y, float4 a);
float8 __ovld __cnfn mix(float8 x, float8 y, float8 a);
float16 __ovld __cnfn mix(float16 x, float16 y, float16 a);
float2 __ovld __cnfn mix(float2 x, float2 y, float a);
float3 __ovld __cnfn mix(float3 x, float3 y, float a);
float4 __ovld __cnfn mix(float4 x, float4 y, float a);
float8 __ovld __cnfn mix(float8 x, float8 y, float a);
float16 __ovld __cnfn mix(float16 x, float16 y, float a);
#ifdef cl_khr_fp64
double __ovld __cnfn mix(double x, double y, double a);
double2 __ovld __cnfn mix(double2 x, double2 y, double2 a);
double3 __ovld __cnfn mix(double3 x, double3 y, double3 a);
double4 __ovld __cnfn mix(double4 x, double4 y, double4 a);
double8 __ovld __cnfn mix(double8 x, double8 y, double8 a);
double16 __ovld __cnfn mix(double16 x, double16 y, double16 a);
double2 __ovld __cnfn mix(double2 x, double2 y, double a);
double3 __ovld __cnfn mix(double3 x, double3 y, double a);
double4 __ovld __cnfn mix(double4 x, double4 y, double a);
double8 __ovld __cnfn mix(double8 x, double8 y, double a);
double16 __ovld __cnfn mix(double16 x, double16 y, double a);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn mix(half x, half y, half a);
half2 __ovld __cnfn mix(half2 x, half2 y, half2 a);
half3 __ovld __cnfn mix(half3 x, half3 y, half3 a);
half4 __ovld __cnfn mix(half4 x, half4 y, half4 a);
half8 __ovld __cnfn mix(half8 x, half8 y, half8 a);
half16 __ovld __cnfn mix(half16 x, half16 y, half16 a);
half2 __ovld __cnfn mix(half2 x, half2 y, half a);
half3 __ovld __cnfn mix(half3 x, half3 y, half a);
half4 __ovld __cnfn mix(half4 x, half4 y, half a);
half8 __ovld __cnfn mix(half8 x, half8 y, half a);
half16 __ovld __cnfn mix(half16 x, half16 y, half a);
#endif //cl_khr_fp16
/**
* Converts degrees to radians, i.e. (PI / 180) *
* degrees.
*/
float __ovld __cnfn radians(float degrees);
float2 __ovld __cnfn radians(float2 degrees);
float3 __ovld __cnfn radians(float3 degrees);
float4 __ovld __cnfn radians(float4 degrees);
float8 __ovld __cnfn radians(float8 degrees);
float16 __ovld __cnfn radians(float16 degrees);
#ifdef cl_khr_fp64
double __ovld __cnfn radians(double degrees);
double2 __ovld __cnfn radians(double2 degrees);
double3 __ovld __cnfn radians(double3 degrees);
double4 __ovld __cnfn radians(double4 degrees);
double8 __ovld __cnfn radians(double8 degrees);
double16 __ovld __cnfn radians(double16 degrees);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn radians(half degrees);
half2 __ovld __cnfn radians(half2 degrees);
half3 __ovld __cnfn radians(half3 degrees);
half4 __ovld __cnfn radians(half4 degrees);
half8 __ovld __cnfn radians(half8 degrees);
half16 __ovld __cnfn radians(half16 degrees);
#endif //cl_khr_fp16
/**
* Returns 0.0 if x < edge, otherwise it returns 1.0.
*/
float __ovld __cnfn step(float edge, float x);
float2 __ovld __cnfn step(float2 edge, float2 x);
float3 __ovld __cnfn step(float3 edge, float3 x);
float4 __ovld __cnfn step(float4 edge, float4 x);
float8 __ovld __cnfn step(float8 edge, float8 x);
float16 __ovld __cnfn step(float16 edge, float16 x);
float2 __ovld __cnfn step(float edge, float2 x);
float3 __ovld __cnfn step(float edge, float3 x);
float4 __ovld __cnfn step(float edge, float4 x);
float8 __ovld __cnfn step(float edge, float8 x);
float16 __ovld __cnfn step(float edge, float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn step(double edge, double x);
double2 __ovld __cnfn step(double2 edge, double2 x);
double3 __ovld __cnfn step(double3 edge, double3 x);
double4 __ovld __cnfn step(double4 edge, double4 x);
double8 __ovld __cnfn step(double8 edge, double8 x);
double16 __ovld __cnfn step(double16 edge, double16 x);
double2 __ovld __cnfn step(double edge, double2 x);
double3 __ovld __cnfn step(double edge, double3 x);
double4 __ovld __cnfn step(double edge, double4 x);
double8 __ovld __cnfn step(double edge, double8 x);
double16 __ovld __cnfn step(double edge, double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn step(half edge, half x);
half2 __ovld __cnfn step(half2 edge, half2 x);
half3 __ovld __cnfn step(half3 edge, half3 x);
half4 __ovld __cnfn step(half4 edge, half4 x);
half8 __ovld __cnfn step(half8 edge, half8 x);
half16 __ovld __cnfn step(half16 edge, half16 x);
half __ovld __cnfn step(half edge, half x);
half2 __ovld __cnfn step(half edge, half2 x);
half3 __ovld __cnfn step(half edge, half3 x);
half4 __ovld __cnfn step(half edge, half4 x);
half8 __ovld __cnfn step(half edge, half8 x);
half16 __ovld __cnfn step(half edge, half16 x);
#endif //cl_khr_fp16
/**
* Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and
* performs smooth Hermite interpolation between 0
* and 1when edge0 < x < edge1. This is useful in
* cases where you would want a threshold function
* with a smooth transition.
* This is equivalent to:
* gentype t;
* t = clamp ((x - edge0) / (edge1 - edge0), 0, 1);
* return t * t * (3 - 2 * t);
* Results are undefined if edge0 >= edge1 or if x,
* edge0 or edge1 is a NaN.
*/
float __ovld __cnfn smoothstep(float edge0, float edge1, float x);
float2 __ovld __cnfn smoothstep(float2 edge0, float2 edge1, float2 x);
float3 __ovld __cnfn smoothstep(float3 edge0, float3 edge1, float3 x);
float4 __ovld __cnfn smoothstep(float4 edge0, float4 edge1, float4 x);
float8 __ovld __cnfn smoothstep(float8 edge0, float8 edge1, float8 x);
float16 __ovld __cnfn smoothstep(float16 edge0, float16 edge1, float16 x);
float2 __ovld __cnfn smoothstep(float edge0, float edge1, float2 x);
float3 __ovld __cnfn smoothstep(float edge0, float edge1, float3 x);
float4 __ovld __cnfn smoothstep(float edge0, float edge1, float4 x);
float8 __ovld __cnfn smoothstep(float edge0, float edge1, float8 x);
float16 __ovld __cnfn smoothstep(float edge0, float edge1, float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn smoothstep(double edge0, double edge1, double x);
double2 __ovld __cnfn smoothstep(double2 edge0, double2 edge1, double2 x);
double3 __ovld __cnfn smoothstep(double3 edge0, double3 edge1, double3 x);
double4 __ovld __cnfn smoothstep(double4 edge0, double4 edge1, double4 x);
double8 __ovld __cnfn smoothstep(double8 edge0, double8 edge1, double8 x);
double16 __ovld __cnfn smoothstep(double16 edge0, double16 edge1, double16 x);
double2 __ovld __cnfn smoothstep(double edge0, double edge1, double2 x);
double3 __ovld __cnfn smoothstep(double edge0, double edge1, double3 x);
double4 __ovld __cnfn smoothstep(double edge0, double edge1, double4 x);
double8 __ovld __cnfn smoothstep(double edge0, double edge1, double8 x);
double16 __ovld __cnfn smoothstep(double edge0, double edge1, double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn smoothstep(half edge0, half edge1, half x);
half2 __ovld __cnfn smoothstep(half2 edge0, half2 edge1, half2 x);
half3 __ovld __cnfn smoothstep(half3 edge0, half3 edge1, half3 x);
half4 __ovld __cnfn smoothstep(half4 edge0, half4 edge1, half4 x);
half8 __ovld __cnfn smoothstep(half8 edge0, half8 edge1, half8 x);
half16 __ovld __cnfn smoothstep(half16 edge0, half16 edge1, half16 x);
half __ovld __cnfn smoothstep(half edge0, half edge1, half x);
half2 __ovld __cnfn smoothstep(half edge0, half edge1, half2 x);
half3 __ovld __cnfn smoothstep(half edge0, half edge1, half3 x);
half4 __ovld __cnfn smoothstep(half edge0, half edge1, half4 x);
half8 __ovld __cnfn smoothstep(half edge0, half edge1, half8 x);
half16 __ovld __cnfn smoothstep(half edge0, half edge1, half16 x);
#endif //cl_khr_fp16
/**
* Returns 1.0 if x > 0, -0.0 if x = -0.0, +0.0 if x =
* +0.0, or -1.0 if x < 0. Returns 0.0 if x is a NaN.
*/
float __ovld __cnfn sign(float x);
float2 __ovld __cnfn sign(float2 x);
float3 __ovld __cnfn sign(float3 x);
float4 __ovld __cnfn sign(float4 x);
float8 __ovld __cnfn sign(float8 x);
float16 __ovld __cnfn sign(float16 x);
#ifdef cl_khr_fp64
double __ovld __cnfn sign(double x);
double2 __ovld __cnfn sign(double2 x);
double3 __ovld __cnfn sign(double3 x);
double4 __ovld __cnfn sign(double4 x);
double8 __ovld __cnfn sign(double8 x);
double16 __ovld __cnfn sign(double16 x);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn sign(half x);
half2 __ovld __cnfn sign(half2 x);
half3 __ovld __cnfn sign(half3 x);
half4 __ovld __cnfn sign(half4 x);
half8 __ovld __cnfn sign(half8 x);
half16 __ovld __cnfn sign(half16 x);
#endif //cl_khr_fp16
// OpenCL v1.1 s6.11.5, v1.2 s6.12.5, v2.0 s6.13.5 - Geometric Functions
/**
* Returns the cross product of p0.xyz and p1.xyz. The
* w component of float4 result returned will be 0.0.
*/
float4 __ovld __cnfn cross(float4 p0, float4 p1);
float3 __ovld __cnfn cross(float3 p0, float3 p1);
#ifdef cl_khr_fp64
double4 __ovld __cnfn cross(double4 p0, double4 p1);
double3 __ovld __cnfn cross(double3 p0, double3 p1);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half4 __ovld __cnfn cross(half4 p0, half4 p1);
half3 __ovld __cnfn cross(half3 p0, half3 p1);
#endif //cl_khr_fp16
/**
* Compute dot product.
*/
float __ovld __cnfn dot(float p0, float p1);
float __ovld __cnfn dot(float2 p0, float2 p1);
float __ovld __cnfn dot(float3 p0, float3 p1);
float __ovld __cnfn dot(float4 p0, float4 p1);
#ifdef cl_khr_fp64
double __ovld __cnfn dot(double p0, double p1);
double __ovld __cnfn dot(double2 p0, double2 p1);
double __ovld __cnfn dot(double3 p0, double3 p1);
double __ovld __cnfn dot(double4 p0, double4 p1);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn dot(half p0, half p1);
half __ovld __cnfn dot(half2 p0, half2 p1);
half __ovld __cnfn dot(half3 p0, half3 p1);
half __ovld __cnfn dot(half4 p0, half4 p1);
#endif //cl_khr_fp16
/**
* Returns the distance between p0 and p1. This is
* calculated as length(p0 - p1).
*/
float __ovld __cnfn distance(float p0, float p1);
float __ovld __cnfn distance(float2 p0, float2 p1);
float __ovld __cnfn distance(float3 p0, float3 p1);
float __ovld __cnfn distance(float4 p0, float4 p1);
#ifdef cl_khr_fp64
double __ovld __cnfn distance(double p0, double p1);
double __ovld __cnfn distance(double2 p0, double2 p1);
double __ovld __cnfn distance(double3 p0, double3 p1);
double __ovld __cnfn distance(double4 p0, double4 p1);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn distance(half p0, half p1);
half __ovld __cnfn distance(half2 p0, half2 p1);
half __ovld __cnfn distance(half3 p0, half3 p1);
half __ovld __cnfn distance(half4 p0, half4 p1);
#endif //cl_khr_fp16
/**
* Return the length of vector p, i.e.,
* sqrt(p.x2 + p.y 2 + ...)
*/
float __ovld __cnfn length(float p);
float __ovld __cnfn length(float2 p);
float __ovld __cnfn length(float3 p);
float __ovld __cnfn length(float4 p);
#ifdef cl_khr_fp64
double __ovld __cnfn length(double p);
double __ovld __cnfn length(double2 p);
double __ovld __cnfn length(double3 p);
double __ovld __cnfn length(double4 p);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn length(half p);
half __ovld __cnfn length(half2 p);
half __ovld __cnfn length(half3 p);
half __ovld __cnfn length(half4 p);
#endif //cl_khr_fp16
/**
* Returns a vector in the same direction as p but with a
* length of 1.
*/
float __ovld __cnfn normalize(float p);
float2 __ovld __cnfn normalize(float2 p);
float3 __ovld __cnfn normalize(float3 p);
float4 __ovld __cnfn normalize(float4 p);
#ifdef cl_khr_fp64
double __ovld __cnfn normalize(double p);
double2 __ovld __cnfn normalize(double2 p);
double3 __ovld __cnfn normalize(double3 p);
double4 __ovld __cnfn normalize(double4 p);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn normalize(half p);
half2 __ovld __cnfn normalize(half2 p);
half3 __ovld __cnfn normalize(half3 p);
half4 __ovld __cnfn normalize(half4 p);
#endif //cl_khr_fp16
/**
* Returns fast_length(p0 - p1).
*/
float __ovld __cnfn fast_distance(float p0, float p1);
float __ovld __cnfn fast_distance(float2 p0, float2 p1);
float __ovld __cnfn fast_distance(float3 p0, float3 p1);
float __ovld __cnfn fast_distance(float4 p0, float4 p1);
#ifdef cl_khr_fp16
half __ovld __cnfn fast_distance(half p0, half p1);
half __ovld __cnfn fast_distance(half2 p0, half2 p1);
half __ovld __cnfn fast_distance(half3 p0, half3 p1);
half __ovld __cnfn fast_distance(half4 p0, half4 p1);
#endif //cl_khr_fp16
/**
* Returns the length of vector p computed as:
* half_sqrt(p.x2 + p.y2 + ...)
*/
float __ovld __cnfn fast_length(float p);
float __ovld __cnfn fast_length(float2 p);
float __ovld __cnfn fast_length(float3 p);
float __ovld __cnfn fast_length(float4 p);
#ifdef cl_khr_fp16
half __ovld __cnfn fast_length(half p);
half __ovld __cnfn fast_length(half2 p);
half __ovld __cnfn fast_length(half3 p);
half __ovld __cnfn fast_length(half4 p);
#endif //cl_khr_fp16
/**
* Returns a vector in the same direction as p but with a
* length of 1. fast_normalize is computed as:
* p * half_rsqrt (p.x^2 + p.y^2 + ... )
* The result shall be within 8192 ulps error from the
* infinitely precise result of
* if (all(p == 0.0f))
* result = p;
* else
* result = p / sqrt (p.x^2 + p.y^2 + ...);
* with the following exceptions:
* 1) If the sum of squares is greater than FLT_MAX
* then the value of the floating-point values in the
* result vector are undefined.
* 2) If the sum of squares is less than FLT_MIN then
* the implementation may return back p.
* 3) If the device is in "denorms are flushed to zero"
* mode, individual operand elements with magnitude
* less than sqrt(FLT_MIN) may be flushed to zero
* before proceeding with the calculation.
*/
float __ovld __cnfn fast_normalize(float p);
float2 __ovld __cnfn fast_normalize(float2 p);
float3 __ovld __cnfn fast_normalize(float3 p);
float4 __ovld __cnfn fast_normalize(float4 p);
#ifdef cl_khr_fp16
half __ovld __cnfn fast_normalize(half p);
half2 __ovld __cnfn fast_normalize(half2 p);
half3 __ovld __cnfn fast_normalize(half3 p);
half4 __ovld __cnfn fast_normalize(half4 p);
#endif //cl_khr_fp16
// OpenCL v1.1 s6.11.6, v1.2 s6.12.6, v2.0 s6.13.6 - Relational Functions
/**
* intn isequal (floatn x, floatn y)
* Returns the component-wise compare of x == y.
*/
int __ovld __cnfn isequal(float x, float y);
int2 __ovld __cnfn isequal(float2 x, float2 y);
int3 __ovld __cnfn isequal(float3 x, float3 y);
int4 __ovld __cnfn isequal(float4 x, float4 y);
int8 __ovld __cnfn isequal(float8 x, float8 y);
int16 __ovld __cnfn isequal(float16 x, float16 y);
#ifdef cl_khr_fp64
int __ovld __cnfn isequal(double x, double y);
long2 __ovld __cnfn isequal(double2 x, double2 y);
long3 __ovld __cnfn isequal(double3 x, double3 y);
long4 __ovld __cnfn isequal(double4 x, double4 y);
long8 __ovld __cnfn isequal(double8 x, double8 y);
long16 __ovld __cnfn isequal(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn isequal(half x, half y);
short2 __ovld __cnfn isequal(half2 x, half2 y);
short3 __ovld __cnfn isequal(half3 x, half3 y);
short4 __ovld __cnfn isequal(half4 x, half4 y);
short8 __ovld __cnfn isequal(half8 x, half8 y);
short16 __ovld __cnfn isequal(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Returns the component-wise compare of x != y.
*/
int __ovld __cnfn isnotequal(float x, float y);
int2 __ovld __cnfn isnotequal(float2 x, float2 y);
int3 __ovld __cnfn isnotequal(float3 x, float3 y);
int4 __ovld __cnfn isnotequal(float4 x, float4 y);
int8 __ovld __cnfn isnotequal(float8 x, float8 y);
int16 __ovld __cnfn isnotequal(float16 x, float16 y);
#ifdef cl_khr_fp64
int __ovld __cnfn isnotequal(double x, double y);
long2 __ovld __cnfn isnotequal(double2 x, double2 y);
long3 __ovld __cnfn isnotequal(double3 x, double3 y);
long4 __ovld __cnfn isnotequal(double4 x, double4 y);
long8 __ovld __cnfn isnotequal(double8 x, double8 y);
long16 __ovld __cnfn isnotequal(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn isnotequal(half x, half y);
short2 __ovld __cnfn isnotequal(half2 x, half2 y);
short3 __ovld __cnfn isnotequal(half3 x, half3 y);
short4 __ovld __cnfn isnotequal(half4 x, half4 y);
short8 __ovld __cnfn isnotequal(half8 x, half8 y);
short16 __ovld __cnfn isnotequal(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Returns the component-wise compare of x > y.
*/
int __ovld __cnfn isgreater(float x, float y);
int2 __ovld __cnfn isgreater(float2 x, float2 y);
int3 __ovld __cnfn isgreater(float3 x, float3 y);
int4 __ovld __cnfn isgreater(float4 x, float4 y);
int8 __ovld __cnfn isgreater(float8 x, float8 y);
int16 __ovld __cnfn isgreater(float16 x, float16 y);
#ifdef cl_khr_fp64
int __ovld __cnfn isgreater(double x, double y);
long2 __ovld __cnfn isgreater(double2 x, double2 y);
long3 __ovld __cnfn isgreater(double3 x, double3 y);
long4 __ovld __cnfn isgreater(double4 x, double4 y);
long8 __ovld __cnfn isgreater(double8 x, double8 y);
long16 __ovld __cnfn isgreater(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn isgreater(half x, half y);
short2 __ovld __cnfn isgreater(half2 x, half2 y);
short3 __ovld __cnfn isgreater(half3 x, half3 y);
short4 __ovld __cnfn isgreater(half4 x, half4 y);
short8 __ovld __cnfn isgreater(half8 x, half8 y);
short16 __ovld __cnfn isgreater(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Returns the component-wise compare of x >= y.
*/
int __ovld __cnfn isgreaterequal(float x, float y);
int2 __ovld __cnfn isgreaterequal(float2 x, float2 y);
int3 __ovld __cnfn isgreaterequal(float3 x, float3 y);
int4 __ovld __cnfn isgreaterequal(float4 x, float4 y);
int8 __ovld __cnfn isgreaterequal(float8 x, float8 y);
int16 __ovld __cnfn isgreaterequal(float16 x, float16 y);
#ifdef cl_khr_fp64
int __ovld __cnfn isgreaterequal(double x, double y);
long2 __ovld __cnfn isgreaterequal(double2 x, double2 y);
long3 __ovld __cnfn isgreaterequal(double3 x, double3 y);
long4 __ovld __cnfn isgreaterequal(double4 x, double4 y);
long8 __ovld __cnfn isgreaterequal(double8 x, double8 y);
long16 __ovld __cnfn isgreaterequal(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn isgreaterequal(half x, half y);
short2 __ovld __cnfn isgreaterequal(half2 x, half2 y);
short3 __ovld __cnfn isgreaterequal(half3 x, half3 y);
short4 __ovld __cnfn isgreaterequal(half4 x, half4 y);
short8 __ovld __cnfn isgreaterequal(half8 x, half8 y);
short16 __ovld __cnfn isgreaterequal(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Returns the component-wise compare of x < y.
*/
int __ovld __cnfn isless(float x, float y);
int2 __ovld __cnfn isless(float2 x, float2 y);
int3 __ovld __cnfn isless(float3 x, float3 y);
int4 __ovld __cnfn isless(float4 x, float4 y);
int8 __ovld __cnfn isless(float8 x, float8 y);
int16 __ovld __cnfn isless(float16 x, float16 y);
#ifdef cl_khr_fp64
int __ovld __cnfn isless(double x, double y);
long2 __ovld __cnfn isless(double2 x, double2 y);
long3 __ovld __cnfn isless(double3 x, double3 y);
long4 __ovld __cnfn isless(double4 x, double4 y);
long8 __ovld __cnfn isless(double8 x, double8 y);
long16 __ovld __cnfn isless(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn isless(half x, half y);
short2 __ovld __cnfn isless(half2 x, half2 y);
short3 __ovld __cnfn isless(half3 x, half3 y);
short4 __ovld __cnfn isless(half4 x, half4 y);
short8 __ovld __cnfn isless(half8 x, half8 y);
short16 __ovld __cnfn isless(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Returns the component-wise compare of x <= y.
*/
int __ovld __cnfn islessequal(float x, float y);
int2 __ovld __cnfn islessequal(float2 x, float2 y);
int3 __ovld __cnfn islessequal(float3 x, float3 y);
int4 __ovld __cnfn islessequal(float4 x, float4 y);
int8 __ovld __cnfn islessequal(float8 x, float8 y);
int16 __ovld __cnfn islessequal(float16 x, float16 y);
#ifdef cl_khr_fp64
int __ovld __cnfn islessequal(double x, double y);
long2 __ovld __cnfn islessequal(double2 x, double2 y);
long3 __ovld __cnfn islessequal(double3 x, double3 y);
long4 __ovld __cnfn islessequal(double4 x, double4 y);
long8 __ovld __cnfn islessequal(double8 x, double8 y);
long16 __ovld __cnfn islessequal(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn islessequal(half x, half y);
short2 __ovld __cnfn islessequal(half2 x, half2 y);
short3 __ovld __cnfn islessequal(half3 x, half3 y);
short4 __ovld __cnfn islessequal(half4 x, half4 y);
short8 __ovld __cnfn islessequal(half8 x, half8 y);
short16 __ovld __cnfn islessequal(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Returns the component-wise compare of
* (x < y) || (x > y) .
*/
int __ovld __cnfn islessgreater(float x, float y);
int2 __ovld __cnfn islessgreater(float2 x, float2 y);
int3 __ovld __cnfn islessgreater(float3 x, float3 y);
int4 __ovld __cnfn islessgreater(float4 x, float4 y);
int8 __ovld __cnfn islessgreater(float8 x, float8 y);
int16 __ovld __cnfn islessgreater(float16 x, float16 y);
#ifdef cl_khr_fp64
int __ovld __cnfn islessgreater(double x, double y);
long2 __ovld __cnfn islessgreater(double2 x, double2 y);
long3 __ovld __cnfn islessgreater(double3 x, double3 y);
long4 __ovld __cnfn islessgreater(double4 x, double4 y);
long8 __ovld __cnfn islessgreater(double8 x, double8 y);
long16 __ovld __cnfn islessgreater(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn islessgreater(half x, half y);
short2 __ovld __cnfn islessgreater(half2 x, half2 y);
short3 __ovld __cnfn islessgreater(half3 x, half3 y);
short4 __ovld __cnfn islessgreater(half4 x, half4 y);
short8 __ovld __cnfn islessgreater(half8 x, half8 y);
short16 __ovld __cnfn islessgreater(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Test for finite value.
*/
int __ovld __cnfn isfinite(float);
int2 __ovld __cnfn isfinite(float2);
int3 __ovld __cnfn isfinite(float3);
int4 __ovld __cnfn isfinite(float4);
int8 __ovld __cnfn isfinite(float8);
int16 __ovld __cnfn isfinite(float16);
#ifdef cl_khr_fp64
int __ovld __cnfn isfinite(double);
long2 __ovld __cnfn isfinite(double2);
long3 __ovld __cnfn isfinite(double3);
long4 __ovld __cnfn isfinite(double4);
long8 __ovld __cnfn isfinite(double8);
long16 __ovld __cnfn isfinite(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn isfinite(half);
short2 __ovld __cnfn isfinite(half2);
short3 __ovld __cnfn isfinite(half3);
short4 __ovld __cnfn isfinite(half4);
short8 __ovld __cnfn isfinite(half8);
short16 __ovld __cnfn isfinite(half16);
#endif //cl_khr_fp16
/**
* Test for infinity value (+ve or -ve) .
*/
int __ovld __cnfn isinf(float);
int2 __ovld __cnfn isinf(float2);
int3 __ovld __cnfn isinf(float3);
int4 __ovld __cnfn isinf(float4);
int8 __ovld __cnfn isinf(float8);
int16 __ovld __cnfn isinf(float16);
#ifdef cl_khr_fp64
int __ovld __cnfn isinf(double);
long2 __ovld __cnfn isinf(double2);
long3 __ovld __cnfn isinf(double3);
long4 __ovld __cnfn isinf(double4);
long8 __ovld __cnfn isinf(double8);
long16 __ovld __cnfn isinf(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn isinf(half);
short2 __ovld __cnfn isinf(half2);
short3 __ovld __cnfn isinf(half3);
short4 __ovld __cnfn isinf(half4);
short8 __ovld __cnfn isinf(half8);
short16 __ovld __cnfn isinf(half16);
#endif //cl_khr_fp16
/**
* Test for a NaN.
*/
int __ovld __cnfn isnan(float);
int2 __ovld __cnfn isnan(float2);
int3 __ovld __cnfn isnan(float3);
int4 __ovld __cnfn isnan(float4);
int8 __ovld __cnfn isnan(float8);
int16 __ovld __cnfn isnan(float16);
#ifdef cl_khr_fp64
int __ovld __cnfn isnan(double);
long2 __ovld __cnfn isnan(double2);
long3 __ovld __cnfn isnan(double3);
long4 __ovld __cnfn isnan(double4);
long8 __ovld __cnfn isnan(double8);
long16 __ovld __cnfn isnan(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn isnan(half);
short2 __ovld __cnfn isnan(half2);
short3 __ovld __cnfn isnan(half3);
short4 __ovld __cnfn isnan(half4);
short8 __ovld __cnfn isnan(half8);
short16 __ovld __cnfn isnan(half16);
#endif //cl_khr_fp16
/**
* Test for a normal value.
*/
int __ovld __cnfn isnormal(float);
int2 __ovld __cnfn isnormal(float2);
int3 __ovld __cnfn isnormal(float3);
int4 __ovld __cnfn isnormal(float4);
int8 __ovld __cnfn isnormal(float8);
int16 __ovld __cnfn isnormal(float16);
#ifdef cl_khr_fp64
int __ovld __cnfn isnormal(double);
long2 __ovld __cnfn isnormal(double2);
long3 __ovld __cnfn isnormal(double3);
long4 __ovld __cnfn isnormal(double4);
long8 __ovld __cnfn isnormal(double8);
long16 __ovld __cnfn isnormal(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn isnormal(half);
short2 __ovld __cnfn isnormal(half2);
short3 __ovld __cnfn isnormal(half3);
short4 __ovld __cnfn isnormal(half4);
short8 __ovld __cnfn isnormal(half8);
short16 __ovld __cnfn isnormal(half16);
#endif //cl_khr_fp16
/**
* Test if arguments are ordered. isordered() takes
* arguments x and y, and returns the result
* isequal(x, x) && isequal(y, y).
*/
int __ovld __cnfn isordered(float x, float y);
int2 __ovld __cnfn isordered(float2 x, float2 y);
int3 __ovld __cnfn isordered(float3 x, float3 y);
int4 __ovld __cnfn isordered(float4 x, float4 y);
int8 __ovld __cnfn isordered(float8 x, float8 y);
int16 __ovld __cnfn isordered(float16 x, float16 y);
#ifdef cl_khr_fp64
int __ovld __cnfn isordered(double x, double y);
long2 __ovld __cnfn isordered(double2 x, double2 y);
long3 __ovld __cnfn isordered(double3 x, double3 y);
long4 __ovld __cnfn isordered(double4 x, double4 y);
long8 __ovld __cnfn isordered(double8 x, double8 y);
long16 __ovld __cnfn isordered(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn isordered(half x, half y);
short2 __ovld __cnfn isordered(half2 x, half2 y);
short3 __ovld __cnfn isordered(half3 x, half3 y);
short4 __ovld __cnfn isordered(half4 x, half4 y);
short8 __ovld __cnfn isordered(half8 x, half8 y);
short16 __ovld __cnfn isordered(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Test if arguments are unordered. isunordered()
* takes arguments x and y, returning non-zero if x or y
* is NaN, and zero otherwise.
*/
int __ovld __cnfn isunordered(float x, float y);
int2 __ovld __cnfn isunordered(float2 x, float2 y);
int3 __ovld __cnfn isunordered(float3 x, float3 y);
int4 __ovld __cnfn isunordered(float4 x, float4 y);
int8 __ovld __cnfn isunordered(float8 x, float8 y);
int16 __ovld __cnfn isunordered(float16 x, float16 y);
#ifdef cl_khr_fp64
int __ovld __cnfn isunordered(double x, double y);
long2 __ovld __cnfn isunordered(double2 x, double2 y);
long3 __ovld __cnfn isunordered(double3 x, double3 y);
long4 __ovld __cnfn isunordered(double4 x, double4 y);
long8 __ovld __cnfn isunordered(double8 x, double8 y);
long16 __ovld __cnfn isunordered(double16 x, double16 y);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn isunordered(half x, half y);
short2 __ovld __cnfn isunordered(half2 x, half2 y);
short3 __ovld __cnfn isunordered(half3 x, half3 y);
short4 __ovld __cnfn isunordered(half4 x, half4 y);
short8 __ovld __cnfn isunordered(half8 x, half8 y);
short16 __ovld __cnfn isunordered(half16 x, half16 y);
#endif //cl_khr_fp16
/**
* Test for sign bit. The scalar version of the function
* returns a 1 if the sign bit in the float is set else returns
* 0. The vector version of the function returns the
* following for each component in floatn: a -1 if the
* sign bit in the float is set else returns 0.
*/
int __ovld __cnfn signbit(float);
int2 __ovld __cnfn signbit(float2);
int3 __ovld __cnfn signbit(float3);
int4 __ovld __cnfn signbit(float4);
int8 __ovld __cnfn signbit(float8);
int16 __ovld __cnfn signbit(float16);
#ifdef cl_khr_fp64
int __ovld __cnfn signbit(double);
long2 __ovld __cnfn signbit(double2);
long3 __ovld __cnfn signbit(double3);
long4 __ovld __cnfn signbit(double4);
long8 __ovld __cnfn signbit(double8);
long16 __ovld __cnfn signbit(double16);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
int __ovld __cnfn signbit(half);
short2 __ovld __cnfn signbit(half2);
short3 __ovld __cnfn signbit(half3);
short4 __ovld __cnfn signbit(half4);
short8 __ovld __cnfn signbit(half8);
short16 __ovld __cnfn signbit(half16);
#endif //cl_khr_fp16
/**
* Returns 1 if the most significant bit in any component
* of x is set; otherwise returns 0.
*/
int __ovld __cnfn any(char x);
int __ovld __cnfn any(char2 x);
int __ovld __cnfn any(char3 x);
int __ovld __cnfn any(char4 x);
int __ovld __cnfn any(char8 x);
int __ovld __cnfn any(char16 x);
int __ovld __cnfn any(short x);
int __ovld __cnfn any(short2 x);
int __ovld __cnfn any(short3 x);
int __ovld __cnfn any(short4 x);
int __ovld __cnfn any(short8 x);
int __ovld __cnfn any(short16 x);
int __ovld __cnfn any(int x);
int __ovld __cnfn any(int2 x);
int __ovld __cnfn any(int3 x);
int __ovld __cnfn any(int4 x);
int __ovld __cnfn any(int8 x);
int __ovld __cnfn any(int16 x);
int __ovld __cnfn any(long x);
int __ovld __cnfn any(long2 x);
int __ovld __cnfn any(long3 x);
int __ovld __cnfn any(long4 x);
int __ovld __cnfn any(long8 x);
int __ovld __cnfn any(long16 x);
/**
* Returns 1 if the most significant bit in all components
* of x is set; otherwise returns 0.
*/
int __ovld __cnfn all(char x);
int __ovld __cnfn all(char2 x);
int __ovld __cnfn all(char3 x);
int __ovld __cnfn all(char4 x);
int __ovld __cnfn all(char8 x);
int __ovld __cnfn all(char16 x);
int __ovld __cnfn all(short x);
int __ovld __cnfn all(short2 x);
int __ovld __cnfn all(short3 x);
int __ovld __cnfn all(short4 x);
int __ovld __cnfn all(short8 x);
int __ovld __cnfn all(short16 x);
int __ovld __cnfn all(int x);
int __ovld __cnfn all(int2 x);
int __ovld __cnfn all(int3 x);
int __ovld __cnfn all(int4 x);
int __ovld __cnfn all(int8 x);
int __ovld __cnfn all(int16 x);
int __ovld __cnfn all(long x);
int __ovld __cnfn all(long2 x);
int __ovld __cnfn all(long3 x);
int __ovld __cnfn all(long4 x);
int __ovld __cnfn all(long8 x);
int __ovld __cnfn all(long16 x);
/**
* Each bit of the result is the corresponding bit of a if
* the corresponding bit of c is 0. Otherwise it is the
* corresponding bit of b.
*/
char __ovld __cnfn bitselect(char a, char b, char c);
uchar __ovld __cnfn bitselect(uchar a, uchar b, uchar c);
char2 __ovld __cnfn bitselect(char2 a, char2 b, char2 c);
uchar2 __ovld __cnfn bitselect(uchar2 a, uchar2 b, uchar2 c);
char3 __ovld __cnfn bitselect(char3 a, char3 b, char3 c);
uchar3 __ovld __cnfn bitselect(uchar3 a, uchar3 b, uchar3 c);
char4 __ovld __cnfn bitselect(char4 a, char4 b, char4 c);
uchar4 __ovld __cnfn bitselect(uchar4 a, uchar4 b, uchar4 c);
char8 __ovld __cnfn bitselect(char8 a, char8 b, char8 c);
uchar8 __ovld __cnfn bitselect(uchar8 a, uchar8 b, uchar8 c);
char16 __ovld __cnfn bitselect(char16 a, char16 b, char16 c);
uchar16 __ovld __cnfn bitselect(uchar16 a, uchar16 b, uchar16 c);
short __ovld __cnfn bitselect(short a, short b, short c);
ushort __ovld __cnfn bitselect(ushort a, ushort b, ushort c);
short2 __ovld __cnfn bitselect(short2 a, short2 b, short2 c);
ushort2 __ovld __cnfn bitselect(ushort2 a, ushort2 b, ushort2 c);
short3 __ovld __cnfn bitselect(short3 a, short3 b, short3 c);
ushort3 __ovld __cnfn bitselect(ushort3 a, ushort3 b, ushort3 c);
short4 __ovld __cnfn bitselect(short4 a, short4 b, short4 c);
ushort4 __ovld __cnfn bitselect(ushort4 a, ushort4 b, ushort4 c);
short8 __ovld __cnfn bitselect(short8 a, short8 b, short8 c);
ushort8 __ovld __cnfn bitselect(ushort8 a, ushort8 b, ushort8 c);
short16 __ovld __cnfn bitselect(short16 a, short16 b, short16 c);
ushort16 __ovld __cnfn bitselect(ushort16 a, ushort16 b, ushort16 c);
int __ovld __cnfn bitselect(int a, int b, int c);
uint __ovld __cnfn bitselect(uint a, uint b, uint c);
int2 __ovld __cnfn bitselect(int2 a, int2 b, int2 c);
uint2 __ovld __cnfn bitselect(uint2 a, uint2 b, uint2 c);
int3 __ovld __cnfn bitselect(int3 a, int3 b, int3 c);
uint3 __ovld __cnfn bitselect(uint3 a, uint3 b, uint3 c);
int4 __ovld __cnfn bitselect(int4 a, int4 b, int4 c);
uint4 __ovld __cnfn bitselect(uint4 a, uint4 b, uint4 c);
int8 __ovld __cnfn bitselect(int8 a, int8 b, int8 c);
uint8 __ovld __cnfn bitselect(uint8 a, uint8 b, uint8 c);
int16 __ovld __cnfn bitselect(int16 a, int16 b, int16 c);
uint16 __ovld __cnfn bitselect(uint16 a, uint16 b, uint16 c);
long __ovld __cnfn bitselect(long a, long b, long c);
ulong __ovld __cnfn bitselect(ulong a, ulong b, ulong c);
long2 __ovld __cnfn bitselect(long2 a, long2 b, long2 c);
ulong2 __ovld __cnfn bitselect(ulong2 a, ulong2 b, ulong2 c);
long3 __ovld __cnfn bitselect(long3 a, long3 b, long3 c);
ulong3 __ovld __cnfn bitselect(ulong3 a, ulong3 b, ulong3 c);
long4 __ovld __cnfn bitselect(long4 a, long4 b, long4 c);
ulong4 __ovld __cnfn bitselect(ulong4 a, ulong4 b, ulong4 c);
long8 __ovld __cnfn bitselect(long8 a, long8 b, long8 c);
ulong8 __ovld __cnfn bitselect(ulong8 a, ulong8 b, ulong8 c);
long16 __ovld __cnfn bitselect(long16 a, long16 b, long16 c);
ulong16 __ovld __cnfn bitselect(ulong16 a, ulong16 b, ulong16 c);
float __ovld __cnfn bitselect(float a, float b, float c);
float2 __ovld __cnfn bitselect(float2 a, float2 b, float2 c);
float3 __ovld __cnfn bitselect(float3 a, float3 b, float3 c);
float4 __ovld __cnfn bitselect(float4 a, float4 b, float4 c);
float8 __ovld __cnfn bitselect(float8 a, float8 b, float8 c);
float16 __ovld __cnfn bitselect(float16 a, float16 b, float16 c);
#ifdef cl_khr_fp64
double __ovld __cnfn bitselect(double a, double b, double c);
double2 __ovld __cnfn bitselect(double2 a, double2 b, double2 c);
double3 __ovld __cnfn bitselect(double3 a, double3 b, double3 c);
double4 __ovld __cnfn bitselect(double4 a, double4 b, double4 c);
double8 __ovld __cnfn bitselect(double8 a, double8 b, double8 c);
double16 __ovld __cnfn bitselect(double16 a, double16 b, double16 c);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn bitselect(half a, half b, half c);
half2 __ovld __cnfn bitselect(half2 a, half2 b, half2 c);
half3 __ovld __cnfn bitselect(half3 a, half3 b, half3 c);
half4 __ovld __cnfn bitselect(half4 a, half4 b, half4 c);
half8 __ovld __cnfn bitselect(half8 a, half8 b, half8 c);
half16 __ovld __cnfn bitselect(half16 a, half16 b, half16 c);
#endif //cl_khr_fp16
/**
* For each component of a vector type,
* result[i] = if MSB of c[i] is set ? b[i] : a[i].
* For a scalar type, result = c ? b : a.
* b and a must have the same type.
* c must have the same number of elements and bits as a.
*/
char __ovld __cnfn select(char a, char b, char c);
uchar __ovld __cnfn select(uchar a, uchar b, char c);
char2 __ovld __cnfn select(char2 a, char2 b, char2 c);
uchar2 __ovld __cnfn select(uchar2 a, uchar2 b, char2 c);
char3 __ovld __cnfn select(char3 a, char3 b, char3 c);
uchar3 __ovld __cnfn select(uchar3 a, uchar3 b, char3 c);
char4 __ovld __cnfn select(char4 a, char4 b, char4 c);
uchar4 __ovld __cnfn select(uchar4 a, uchar4 b, char4 c);
char8 __ovld __cnfn select(char8 a, char8 b, char8 c);
uchar8 __ovld __cnfn select(uchar8 a, uchar8 b, char8 c);
char16 __ovld __cnfn select(char16 a, char16 b, char16 c);
uchar16 __ovld __cnfn select(uchar16 a, uchar16 b, char16 c);
short __ovld __cnfn select(short a, short b, short c);
ushort __ovld __cnfn select(ushort a, ushort b, short c);
short2 __ovld __cnfn select(short2 a, short2 b, short2 c);
ushort2 __ovld __cnfn select(ushort2 a, ushort2 b, short2 c);
short3 __ovld __cnfn select(short3 a, short3 b, short3 c);
ushort3 __ovld __cnfn select(ushort3 a, ushort3 b, short3 c);
short4 __ovld __cnfn select(short4 a, short4 b, short4 c);
ushort4 __ovld __cnfn select(ushort4 a, ushort4 b, short4 c);
short8 __ovld __cnfn select(short8 a, short8 b, short8 c);
ushort8 __ovld __cnfn select(ushort8 a, ushort8 b, short8 c);
short16 __ovld __cnfn select(short16 a, short16 b, short16 c);
ushort16 __ovld __cnfn select(ushort16 a, ushort16 b, short16 c);
int __ovld __cnfn select(int a, int b, int c);
uint __ovld __cnfn select(uint a, uint b, int c);
int2 __ovld __cnfn select(int2 a, int2 b, int2 c);
uint2 __ovld __cnfn select(uint2 a, uint2 b, int2 c);
int3 __ovld __cnfn select(int3 a, int3 b, int3 c);
uint3 __ovld __cnfn select(uint3 a, uint3 b, int3 c);
int4 __ovld __cnfn select(int4 a, int4 b, int4 c);
uint4 __ovld __cnfn select(uint4 a, uint4 b, int4 c);
int8 __ovld __cnfn select(int8 a, int8 b, int8 c);
uint8 __ovld __cnfn select(uint8 a, uint8 b, int8 c);
int16 __ovld __cnfn select(int16 a, int16 b, int16 c);
uint16 __ovld __cnfn select(uint16 a, uint16 b, int16 c);
float __ovld __cnfn select(float a, float b, int c);
float2 __ovld __cnfn select(float2 a, float2 b, int2 c);
float3 __ovld __cnfn select(float3 a, float3 b, int3 c);
float4 __ovld __cnfn select(float4 a, float4 b, int4 c);
float8 __ovld __cnfn select(float8 a, float8 b, int8 c);
float16 __ovld __cnfn select(float16 a, float16 b, int16 c);
long __ovld __cnfn select(long a, long b, long c);
ulong __ovld __cnfn select(ulong a, ulong b, long c);
long2 __ovld __cnfn select(long2 a, long2 b, long2 c);
ulong2 __ovld __cnfn select(ulong2 a, ulong2 b, long2 c);
long3 __ovld __cnfn select(long3 a, long3 b, long3 c);
ulong3 __ovld __cnfn select(ulong3 a, ulong3 b, long3 c);
long4 __ovld __cnfn select(long4 a, long4 b, long4 c);
ulong4 __ovld __cnfn select(ulong4 a, ulong4 b, long4 c);
long8 __ovld __cnfn select(long8 a, long8 b, long8 c);
ulong8 __ovld __cnfn select(ulong8 a, ulong8 b, long8 c);
long16 __ovld __cnfn select(long16 a, long16 b, long16 c);
ulong16 __ovld __cnfn select(ulong16 a, ulong16 b, long16 c);
char __ovld __cnfn select(char a, char b, uchar c);
uchar __ovld __cnfn select(uchar a, uchar b, uchar c);
char2 __ovld __cnfn select(char2 a, char2 b, uchar2 c);
uchar2 __ovld __cnfn select(uchar2 a, uchar2 b, uchar2 c);
char3 __ovld __cnfn select(char3 a, char3 b, uchar3 c);
uchar3 __ovld __cnfn select(uchar3 a, uchar3 b, uchar3 c);
char4 __ovld __cnfn select(char4 a, char4 b, uchar4 c);
uchar4 __ovld __cnfn select(uchar4 a, uchar4 b, uchar4 c);
char8 __ovld __cnfn select(char8 a, char8 b, uchar8 c);
uchar8 __ovld __cnfn select(uchar8 a, uchar8 b, uchar8 c);
char16 __ovld __cnfn select(char16 a, char16 b, uchar16 c);
uchar16 __ovld __cnfn select(uchar16 a, uchar16 b, uchar16 c);
short __ovld __cnfn select(short a, short b, ushort c);
ushort __ovld __cnfn select(ushort a, ushort b, ushort c);
short2 __ovld __cnfn select(short2 a, short2 b, ushort2 c);
ushort2 __ovld __cnfn select(ushort2 a, ushort2 b, ushort2 c);
short3 __ovld __cnfn select(short3 a, short3 b, ushort3 c);
ushort3 __ovld __cnfn select(ushort3 a, ushort3 b, ushort3 c);
short4 __ovld __cnfn select(short4 a, short4 b, ushort4 c);
ushort4 __ovld __cnfn select(ushort4 a, ushort4 b, ushort4 c);
short8 __ovld __cnfn select(short8 a, short8 b, ushort8 c);
ushort8 __ovld __cnfn select(ushort8 a, ushort8 b, ushort8 c);
short16 __ovld __cnfn select(short16 a, short16 b, ushort16 c);
ushort16 __ovld __cnfn select(ushort16 a, ushort16 b, ushort16 c);
int __ovld __cnfn select(int a, int b, uint c);
uint __ovld __cnfn select(uint a, uint b, uint c);
int2 __ovld __cnfn select(int2 a, int2 b, uint2 c);
uint2 __ovld __cnfn select(uint2 a, uint2 b, uint2 c);
int3 __ovld __cnfn select(int3 a, int3 b, uint3 c);
uint3 __ovld __cnfn select(uint3 a, uint3 b, uint3 c);
int4 __ovld __cnfn select(int4 a, int4 b, uint4 c);
uint4 __ovld __cnfn select(uint4 a, uint4 b, uint4 c);
int8 __ovld __cnfn select(int8 a, int8 b, uint8 c);
uint8 __ovld __cnfn select(uint8 a, uint8 b, uint8 c);
int16 __ovld __cnfn select(int16 a, int16 b, uint16 c);
uint16 __ovld __cnfn select(uint16 a, uint16 b, uint16 c);
float __ovld __cnfn select(float a, float b, uint c);
float2 __ovld __cnfn select(float2 a, float2 b, uint2 c);
float3 __ovld __cnfn select(float3 a, float3 b, uint3 c);
float4 __ovld __cnfn select(float4 a, float4 b, uint4 c);
float8 __ovld __cnfn select(float8 a, float8 b, uint8 c);
float16 __ovld __cnfn select(float16 a, float16 b, uint16 c);
long __ovld __cnfn select(long a, long b, ulong c);
ulong __ovld __cnfn select(ulong a, ulong b, ulong c);
long2 __ovld __cnfn select(long2 a, long2 b, ulong2 c);
ulong2 __ovld __cnfn select(ulong2 a, ulong2 b, ulong2 c);
long3 __ovld __cnfn select(long3 a, long3 b, ulong3 c);
ulong3 __ovld __cnfn select(ulong3 a, ulong3 b, ulong3 c);
long4 __ovld __cnfn select(long4 a, long4 b, ulong4 c);
ulong4 __ovld __cnfn select(ulong4 a, ulong4 b, ulong4 c);
long8 __ovld __cnfn select(long8 a, long8 b, ulong8 c);
ulong8 __ovld __cnfn select(ulong8 a, ulong8 b, ulong8 c);
long16 __ovld __cnfn select(long16 a, long16 b, ulong16 c);
ulong16 __ovld __cnfn select(ulong16 a, ulong16 b, ulong16 c);
#ifdef cl_khr_fp64
double __ovld __cnfn select(double a, double b, long c);
double2 __ovld __cnfn select(double2 a, double2 b, long2 c);
double3 __ovld __cnfn select(double3 a, double3 b, long3 c);
double4 __ovld __cnfn select(double4 a, double4 b, long4 c);
double8 __ovld __cnfn select(double8 a, double8 b, long8 c);
double16 __ovld __cnfn select(double16 a, double16 b, long16 c);
double __ovld __cnfn select(double a, double b, ulong c);
double2 __ovld __cnfn select(double2 a, double2 b, ulong2 c);
double3 __ovld __cnfn select(double3 a, double3 b, ulong3 c);
double4 __ovld __cnfn select(double4 a, double4 b, ulong4 c);
double8 __ovld __cnfn select(double8 a, double8 b, ulong8 c);
double16 __ovld __cnfn select(double16 a, double16 b, ulong16 c);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __cnfn select(half a, half b, short c);
half2 __ovld __cnfn select(half2 a, half2 b, short2 c);
half3 __ovld __cnfn select(half3 a, half3 b, short3 c);
half4 __ovld __cnfn select(half4 a, half4 b, short4 c);
half8 __ovld __cnfn select(half8 a, half8 b, short8 c);
half16 __ovld __cnfn select(half16 a, half16 b, short16 c);
half __ovld __cnfn select(half a, half b, ushort c);
half2 __ovld __cnfn select(half2 a, half2 b, ushort2 c);
half3 __ovld __cnfn select(half3 a, half3 b, ushort3 c);
half4 __ovld __cnfn select(half4 a, half4 b, ushort4 c);
half8 __ovld __cnfn select(half8 a, half8 b, ushort8 c);
half16 __ovld __cnfn select(half16 a, half16 b, ushort16 c);
#endif //cl_khr_fp16
// OpenCL v1.1 s6.11.7, v1.2 s6.12.7, v2.0 s6.13.7 - Vector Data Load and Store Functions
// OpenCL extensions v1.1 s9.6.6, v1.2 s9.5.6, v2.0 s9.4.6 - Vector Data Load and Store Functions for Half Type
/**
* Use generic type gentype to indicate the built-in data types
* char, uchar, short, ushort, int, uint, long, ulong, float,
* double or half.
*
* vloadn return sizeof (gentypen) bytes of data read from address (p + (offset * n)).
*
* vstoren write sizeof (gentypen) bytes given by data to address (p + (offset * n)).
*
* The address computed as (p + (offset * n)) must be
* 8-bit aligned if gentype is char, uchar;
* 16-bit aligned if gentype is short, ushort, half;
* 32-bit aligned if gentype is int, uint, float;
* 64-bit aligned if gentype is long, ulong, double.
*/
char2 __ovld vload2(size_t offset, const __constant char *p);
uchar2 __ovld vload2(size_t offset, const __constant uchar *p);
short2 __ovld vload2(size_t offset, const __constant short *p);
ushort2 __ovld vload2(size_t offset, const __constant ushort *p);
int2 __ovld vload2(size_t offset, const __constant int *p);
uint2 __ovld vload2(size_t offset, const __constant uint *p);
long2 __ovld vload2(size_t offset, const __constant long *p);
ulong2 __ovld vload2(size_t offset, const __constant ulong *p);
float2 __ovld vload2(size_t offset, const __constant float *p);
char3 __ovld vload3(size_t offset, const __constant char *p);
uchar3 __ovld vload3(size_t offset, const __constant uchar *p);
short3 __ovld vload3(size_t offset, const __constant short *p);
ushort3 __ovld vload3(size_t offset, const __constant ushort *p);
int3 __ovld vload3(size_t offset, const __constant int *p);
uint3 __ovld vload3(size_t offset, const __constant uint *p);
long3 __ovld vload3(size_t offset, const __constant long *p);
ulong3 __ovld vload3(size_t offset, const __constant ulong *p);
float3 __ovld vload3(size_t offset, const __constant float *p);
char4 __ovld vload4(size_t offset, const __constant char *p);
uchar4 __ovld vload4(size_t offset, const __constant uchar *p);
short4 __ovld vload4(size_t offset, const __constant short *p);
ushort4 __ovld vload4(size_t offset, const __constant ushort *p);
int4 __ovld vload4(size_t offset, const __constant int *p);
uint4 __ovld vload4(size_t offset, const __constant uint *p);
long4 __ovld vload4(size_t offset, const __constant long *p);
ulong4 __ovld vload4(size_t offset, const __constant ulong *p);
float4 __ovld vload4(size_t offset, const __constant float *p);
char8 __ovld vload8(size_t offset, const __constant char *p);
uchar8 __ovld vload8(size_t offset, const __constant uchar *p);
short8 __ovld vload8(size_t offset, const __constant short *p);
ushort8 __ovld vload8(size_t offset, const __constant ushort *p);
int8 __ovld vload8(size_t offset, const __constant int *p);
uint8 __ovld vload8(size_t offset, const __constant uint *p);
long8 __ovld vload8(size_t offset, const __constant long *p);
ulong8 __ovld vload8(size_t offset, const __constant ulong *p);
float8 __ovld vload8(size_t offset, const __constant float *p);
char16 __ovld vload16(size_t offset, const __constant char *p);
uchar16 __ovld vload16(size_t offset, const __constant uchar *p);
short16 __ovld vload16(size_t offset, const __constant short *p);
ushort16 __ovld vload16(size_t offset, const __constant ushort *p);
int16 __ovld vload16(size_t offset, const __constant int *p);
uint16 __ovld vload16(size_t offset, const __constant uint *p);
long16 __ovld vload16(size_t offset, const __constant long *p);
ulong16 __ovld vload16(size_t offset, const __constant ulong *p);
float16 __ovld vload16(size_t offset, const __constant float *p);
#ifdef cl_khr_fp64
double2 __ovld vload2(size_t offset, const __constant double *p);
double3 __ovld vload3(size_t offset, const __constant double *p);
double4 __ovld vload4(size_t offset, const __constant double *p);
double8 __ovld vload8(size_t offset, const __constant double *p);
double16 __ovld vload16(size_t offset, const __constant double *p);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld vload(size_t offset, const __constant half *p);
half2 __ovld vload2(size_t offset, const __constant half *p);
half3 __ovld vload3(size_t offset, const __constant half *p);
half4 __ovld vload4(size_t offset, const __constant half *p);
half8 __ovld vload8(size_t offset, const __constant half *p);
half16 __ovld vload16(size_t offset, const __constant half *p);
#endif //cl_khr_fp16
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
char2 __ovld vload2(size_t offset, const char *p);
uchar2 __ovld vload2(size_t offset, const uchar *p);
short2 __ovld vload2(size_t offset, const short *p);
ushort2 __ovld vload2(size_t offset, const ushort *p);
int2 __ovld vload2(size_t offset, const int *p);
uint2 __ovld vload2(size_t offset, const uint *p);
long2 __ovld vload2(size_t offset, const long *p);
ulong2 __ovld vload2(size_t offset, const ulong *p);
float2 __ovld vload2(size_t offset, const float *p);
char3 __ovld vload3(size_t offset, const char *p);
uchar3 __ovld vload3(size_t offset, const uchar *p);
short3 __ovld vload3(size_t offset, const short *p);
ushort3 __ovld vload3(size_t offset, const ushort *p);
int3 __ovld vload3(size_t offset, const int *p);
uint3 __ovld vload3(size_t offset, const uint *p);
long3 __ovld vload3(size_t offset, const long *p);
ulong3 __ovld vload3(size_t offset, const ulong *p);
float3 __ovld vload3(size_t offset, const float *p);
char4 __ovld vload4(size_t offset, const char *p);
uchar4 __ovld vload4(size_t offset, const uchar *p);
short4 __ovld vload4(size_t offset, const short *p);
ushort4 __ovld vload4(size_t offset, const ushort *p);
int4 __ovld vload4(size_t offset, const int *p);
uint4 __ovld vload4(size_t offset, const uint *p);
long4 __ovld vload4(size_t offset, const long *p);
ulong4 __ovld vload4(size_t offset, const ulong *p);
float4 __ovld vload4(size_t offset, const float *p);
char8 __ovld vload8(size_t offset, const char *p);
uchar8 __ovld vload8(size_t offset, const uchar *p);
short8 __ovld vload8(size_t offset, const short *p);
ushort8 __ovld vload8(size_t offset, const ushort *p);
int8 __ovld vload8(size_t offset, const int *p);
uint8 __ovld vload8(size_t offset, const uint *p);
long8 __ovld vload8(size_t offset, const long *p);
ulong8 __ovld vload8(size_t offset, const ulong *p);
float8 __ovld vload8(size_t offset, const float *p);
char16 __ovld vload16(size_t offset, const char *p);
uchar16 __ovld vload16(size_t offset, const uchar *p);
short16 __ovld vload16(size_t offset, const short *p);
ushort16 __ovld vload16(size_t offset, const ushort *p);
int16 __ovld vload16(size_t offset, const int *p);
uint16 __ovld vload16(size_t offset, const uint *p);
long16 __ovld vload16(size_t offset, const long *p);
ulong16 __ovld vload16(size_t offset, const ulong *p);
float16 __ovld vload16(size_t offset, const float *p);
#ifdef cl_khr_fp64
double2 __ovld vload2(size_t offset, const double *p);
double3 __ovld vload3(size_t offset, const double *p);
double4 __ovld vload4(size_t offset, const double *p);
double8 __ovld vload8(size_t offset, const double *p);
double16 __ovld vload16(size_t offset, const double *p);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld vload(size_t offset, const half *p);
half2 __ovld vload2(size_t offset, const half *p);
half3 __ovld vload3(size_t offset, const half *p);
half4 __ovld vload4(size_t offset, const half *p);
half8 __ovld vload8(size_t offset, const half *p);
half16 __ovld vload16(size_t offset, const half *p);
#endif //cl_khr_fp16
#else
char2 __ovld vload2(size_t offset, const __global char *p);
uchar2 __ovld vload2(size_t offset, const __global uchar *p);
short2 __ovld vload2(size_t offset, const __global short *p);
ushort2 __ovld vload2(size_t offset, const __global ushort *p);
int2 __ovld vload2(size_t offset, const __global int *p);
uint2 __ovld vload2(size_t offset, const __global uint *p);
long2 __ovld vload2(size_t offset, const __global long *p);
ulong2 __ovld vload2(size_t offset, const __global ulong *p);
float2 __ovld vload2(size_t offset, const __global float *p);
char3 __ovld vload3(size_t offset, const __global char *p);
uchar3 __ovld vload3(size_t offset, const __global uchar *p);
short3 __ovld vload3(size_t offset, const __global short *p);
ushort3 __ovld vload3(size_t offset, const __global ushort *p);
int3 __ovld vload3(size_t offset, const __global int *p);
uint3 __ovld vload3(size_t offset, const __global uint *p);
long3 __ovld vload3(size_t offset, const __global long *p);
ulong3 __ovld vload3(size_t offset, const __global ulong *p);
float3 __ovld vload3(size_t offset, const __global float *p);
char4 __ovld vload4(size_t offset, const __global char *p);
uchar4 __ovld vload4(size_t offset, const __global uchar *p);
short4 __ovld vload4(size_t offset, const __global short *p);
ushort4 __ovld vload4(size_t offset, const __global ushort *p);
int4 __ovld vload4(size_t offset, const __global int *p);
uint4 __ovld vload4(size_t offset, const __global uint *p);
long4 __ovld vload4(size_t offset, const __global long *p);
ulong4 __ovld vload4(size_t offset, const __global ulong *p);
float4 __ovld vload4(size_t offset, const __global float *p);
char8 __ovld vload8(size_t offset, const __global char *p);
uchar8 __ovld vload8(size_t offset, const __global uchar *p);
short8 __ovld vload8(size_t offset, const __global short *p);
ushort8 __ovld vload8(size_t offset, const __global ushort *p);
int8 __ovld vload8(size_t offset, const __global int *p);
uint8 __ovld vload8(size_t offset, const __global uint *p);
long8 __ovld vload8(size_t offset, const __global long *p);
ulong8 __ovld vload8(size_t offset, const __global ulong *p);
float8 __ovld vload8(size_t offset, const __global float *p);
char16 __ovld vload16(size_t offset, const __global char *p);
uchar16 __ovld vload16(size_t offset, const __global uchar *p);
short16 __ovld vload16(size_t offset, const __global short *p);
ushort16 __ovld vload16(size_t offset, const __global ushort *p);
int16 __ovld vload16(size_t offset, const __global int *p);
uint16 __ovld vload16(size_t offset, const __global uint *p);
long16 __ovld vload16(size_t offset, const __global long *p);
ulong16 __ovld vload16(size_t offset, const __global ulong *p);
float16 __ovld vload16(size_t offset, const __global float *p);
char2 __ovld vload2(size_t offset, const __local char *p);
uchar2 __ovld vload2(size_t offset, const __local uchar *p);
short2 __ovld vload2(size_t offset, const __local short *p);
ushort2 __ovld vload2(size_t offset, const __local ushort *p);
int2 __ovld vload2(size_t offset, const __local int *p);
uint2 __ovld vload2(size_t offset, const __local uint *p);
long2 __ovld vload2(size_t offset, const __local long *p);
ulong2 __ovld vload2(size_t offset, const __local ulong *p);
float2 __ovld vload2(size_t offset, const __local float *p);
char3 __ovld vload3(size_t offset, const __local char *p);
uchar3 __ovld vload3(size_t offset, const __local uchar *p);
short3 __ovld vload3(size_t offset, const __local short *p);
ushort3 __ovld vload3(size_t offset, const __local ushort *p);
int3 __ovld vload3(size_t offset, const __local int *p);
uint3 __ovld vload3(size_t offset, const __local uint *p);
long3 __ovld vload3(size_t offset, const __local long *p);
ulong3 __ovld vload3(size_t offset, const __local ulong *p);
float3 __ovld vload3(size_t offset, const __local float *p);
char4 __ovld vload4(size_t offset, const __local char *p);
uchar4 __ovld vload4(size_t offset, const __local uchar *p);
short4 __ovld vload4(size_t offset, const __local short *p);
ushort4 __ovld vload4(size_t offset, const __local ushort *p);
int4 __ovld vload4(size_t offset, const __local int *p);
uint4 __ovld vload4(size_t offset, const __local uint *p);
long4 __ovld vload4(size_t offset, const __local long *p);
ulong4 __ovld vload4(size_t offset, const __local ulong *p);
float4 __ovld vload4(size_t offset, const __local float *p);
char8 __ovld vload8(size_t offset, const __local char *p);
uchar8 __ovld vload8(size_t offset, const __local uchar *p);
short8 __ovld vload8(size_t offset, const __local short *p);
ushort8 __ovld vload8(size_t offset, const __local ushort *p);
int8 __ovld vload8(size_t offset, const __local int *p);
uint8 __ovld vload8(size_t offset, const __local uint *p);
long8 __ovld vload8(size_t offset, const __local long *p);
ulong8 __ovld vload8(size_t offset, const __local ulong *p);
float8 __ovld vload8(size_t offset, const __local float *p);
char16 __ovld vload16(size_t offset, const __local char *p);
uchar16 __ovld vload16(size_t offset, const __local uchar *p);
short16 __ovld vload16(size_t offset, const __local short *p);
ushort16 __ovld vload16(size_t offset, const __local ushort *p);
int16 __ovld vload16(size_t offset, const __local int *p);
uint16 __ovld vload16(size_t offset, const __local uint *p);
long16 __ovld vload16(size_t offset, const __local long *p);
ulong16 __ovld vload16(size_t offset, const __local ulong *p);
float16 __ovld vload16(size_t offset, const __local float *p);
char2 __ovld vload2(size_t offset, const __private char *p);
uchar2 __ovld vload2(size_t offset, const __private uchar *p);
short2 __ovld vload2(size_t offset, const __private short *p);
ushort2 __ovld vload2(size_t offset, const __private ushort *p);
int2 __ovld vload2(size_t offset, const __private int *p);
uint2 __ovld vload2(size_t offset, const __private uint *p);
long2 __ovld vload2(size_t offset, const __private long *p);
ulong2 __ovld vload2(size_t offset, const __private ulong *p);
float2 __ovld vload2(size_t offset, const __private float *p);
char3 __ovld vload3(size_t offset, const __private char *p);
uchar3 __ovld vload3(size_t offset, const __private uchar *p);
short3 __ovld vload3(size_t offset, const __private short *p);
ushort3 __ovld vload3(size_t offset, const __private ushort *p);
int3 __ovld vload3(size_t offset, const __private int *p);
uint3 __ovld vload3(size_t offset, const __private uint *p);
long3 __ovld vload3(size_t offset, const __private long *p);
ulong3 __ovld vload3(size_t offset, const __private ulong *p);
float3 __ovld vload3(size_t offset, const __private float *p);
char4 __ovld vload4(size_t offset, const __private char *p);
uchar4 __ovld vload4(size_t offset, const __private uchar *p);
short4 __ovld vload4(size_t offset, const __private short *p);
ushort4 __ovld vload4(size_t offset, const __private ushort *p);
int4 __ovld vload4(size_t offset, const __private int *p);
uint4 __ovld vload4(size_t offset, const __private uint *p);
long4 __ovld vload4(size_t offset, const __private long *p);
ulong4 __ovld vload4(size_t offset, const __private ulong *p);
float4 __ovld vload4(size_t offset, const __private float *p);
char8 __ovld vload8(size_t offset, const __private char *p);
uchar8 __ovld vload8(size_t offset, const __private uchar *p);
short8 __ovld vload8(size_t offset, const __private short *p);
ushort8 __ovld vload8(size_t offset, const __private ushort *p);
int8 __ovld vload8(size_t offset, const __private int *p);
uint8 __ovld vload8(size_t offset, const __private uint *p);
long8 __ovld vload8(size_t offset, const __private long *p);
ulong8 __ovld vload8(size_t offset, const __private ulong *p);
float8 __ovld vload8(size_t offset, const __private float *p);
char16 __ovld vload16(size_t offset, const __private char *p);
uchar16 __ovld vload16(size_t offset, const __private uchar *p);
short16 __ovld vload16(size_t offset, const __private short *p);
ushort16 __ovld vload16(size_t offset, const __private ushort *p);
int16 __ovld vload16(size_t offset, const __private int *p);
uint16 __ovld vload16(size_t offset, const __private uint *p);
long16 __ovld vload16(size_t offset, const __private long *p);
ulong16 __ovld vload16(size_t offset, const __private ulong *p);
float16 __ovld vload16(size_t offset, const __private float *p);
#ifdef cl_khr_fp64
double2 __ovld vload2(size_t offset, const __global double *p);
double3 __ovld vload3(size_t offset, const __global double *p);
double4 __ovld vload4(size_t offset, const __global double *p);
double8 __ovld vload8(size_t offset, const __global double *p);
double16 __ovld vload16(size_t offset, const __global double *p);
double2 __ovld vload2(size_t offset, const __local double *p);
double3 __ovld vload3(size_t offset, const __local double *p);
double4 __ovld vload4(size_t offset, const __local double *p);
double8 __ovld vload8(size_t offset, const __local double *p);
double16 __ovld vload16(size_t offset, const __local double *p);
double2 __ovld vload2(size_t offset, const __private double *p);
double3 __ovld vload3(size_t offset, const __private double *p);
double4 __ovld vload4(size_t offset, const __private double *p);
double8 __ovld vload8(size_t offset, const __private double *p);
double16 __ovld vload16(size_t offset, const __private double *p);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld vload(size_t offset, const __global half *p);
half2 __ovld vload2(size_t offset, const __global half *p);
half3 __ovld vload3(size_t offset, const __global half *p);
half4 __ovld vload4(size_t offset, const __global half *p);
half8 __ovld vload8(size_t offset, const __global half *p);
half16 __ovld vload16(size_t offset, const __global half *p);
half __ovld vload(size_t offset, const __local half *p);
half2 __ovld vload2(size_t offset, const __local half *p);
half3 __ovld vload3(size_t offset, const __local half *p);
half4 __ovld vload4(size_t offset, const __local half *p);
half8 __ovld vload8(size_t offset, const __local half *p);
half16 __ovld vload16(size_t offset, const __local half *p);
half __ovld vload(size_t offset, const __private half *p);
half2 __ovld vload2(size_t offset, const __private half *p);
half3 __ovld vload3(size_t offset, const __private half *p);
half4 __ovld vload4(size_t offset, const __private half *p);
half8 __ovld vload8(size_t offset, const __private half *p);
half16 __ovld vload16(size_t offset, const __private half *p);
#endif //cl_khr_fp16
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
void __ovld vstore2(char2 data, size_t offset, char *p);
void __ovld vstore2(uchar2 data, size_t offset, uchar *p);
void __ovld vstore2(short2 data, size_t offset, short *p);
void __ovld vstore2(ushort2 data, size_t offset, ushort *p);
void __ovld vstore2(int2 data, size_t offset, int *p);
void __ovld vstore2(uint2 data, size_t offset, uint *p);
void __ovld vstore2(long2 data, size_t offset, long *p);
void __ovld vstore2(ulong2 data, size_t offset, ulong *p);
void __ovld vstore2(float2 data, size_t offset, float *p);
void __ovld vstore3(char3 data, size_t offset, char *p);
void __ovld vstore3(uchar3 data, size_t offset, uchar *p);
void __ovld vstore3(short3 data, size_t offset, short *p);
void __ovld vstore3(ushort3 data, size_t offset, ushort *p);
void __ovld vstore3(int3 data, size_t offset, int *p);
void __ovld vstore3(uint3 data, size_t offset, uint *p);
void __ovld vstore3(long3 data, size_t offset, long *p);
void __ovld vstore3(ulong3 data, size_t offset, ulong *p);
void __ovld vstore3(float3 data, size_t offset, float *p);
void __ovld vstore4(char4 data, size_t offset, char *p);
void __ovld vstore4(uchar4 data, size_t offset, uchar *p);
void __ovld vstore4(short4 data, size_t offset, short *p);
void __ovld vstore4(ushort4 data, size_t offset, ushort *p);
void __ovld vstore4(int4 data, size_t offset, int *p);
void __ovld vstore4(uint4 data, size_t offset, uint *p);
void __ovld vstore4(long4 data, size_t offset, long *p);
void __ovld vstore4(ulong4 data, size_t offset, ulong *p);
void __ovld vstore4(float4 data, size_t offset, float *p);
void __ovld vstore8(char8 data, size_t offset, char *p);
void __ovld vstore8(uchar8 data, size_t offset, uchar *p);
void __ovld vstore8(short8 data, size_t offset, short *p);
void __ovld vstore8(ushort8 data, size_t offset, ushort *p);
void __ovld vstore8(int8 data, size_t offset, int *p);
void __ovld vstore8(uint8 data, size_t offset, uint *p);
void __ovld vstore8(long8 data, size_t offset, long *p);
void __ovld vstore8(ulong8 data, size_t offset, ulong *p);
void __ovld vstore8(float8 data, size_t offset, float *p);
void __ovld vstore16(char16 data, size_t offset, char *p);
void __ovld vstore16(uchar16 data, size_t offset, uchar *p);
void __ovld vstore16(short16 data, size_t offset, short *p);
void __ovld vstore16(ushort16 data, size_t offset, ushort *p);
void __ovld vstore16(int16 data, size_t offset, int *p);
void __ovld vstore16(uint16 data, size_t offset, uint *p);
void __ovld vstore16(long16 data, size_t offset, long *p);
void __ovld vstore16(ulong16 data, size_t offset, ulong *p);
void __ovld vstore16(float16 data, size_t offset, float *p);
#ifdef cl_khr_fp64
void __ovld vstore2(double2 data, size_t offset, double *p);
void __ovld vstore3(double3 data, size_t offset, double *p);
void __ovld vstore4(double4 data, size_t offset, double *p);
void __ovld vstore8(double8 data, size_t offset, double *p);
void __ovld vstore16(double16 data, size_t offset, double *p);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
void __ovld vstore(half data, size_t offset, half *p);
void __ovld vstore2(half2 data, size_t offset, half *p);
void __ovld vstore3(half3 data, size_t offset, half *p);
void __ovld vstore4(half4 data, size_t offset, half *p);
void __ovld vstore8(half8 data, size_t offset, half *p);
void __ovld vstore16(half16 data, size_t offset, half *p);
#endif //cl_khr_fp16
#else
void __ovld vstore2(char2 data, size_t offset, __global char *p);
void __ovld vstore2(uchar2 data, size_t offset, __global uchar *p);
void __ovld vstore2(short2 data, size_t offset, __global short *p);
void __ovld vstore2(ushort2 data, size_t offset, __global ushort *p);
void __ovld vstore2(int2 data, size_t offset, __global int *p);
void __ovld vstore2(uint2 data, size_t offset, __global uint *p);
void __ovld vstore2(long2 data, size_t offset, __global long *p);
void __ovld vstore2(ulong2 data, size_t offset, __global ulong *p);
void __ovld vstore2(float2 data, size_t offset, __global float *p);
void __ovld vstore3(char3 data, size_t offset, __global char *p);
void __ovld vstore3(uchar3 data, size_t offset, __global uchar *p);
void __ovld vstore3(short3 data, size_t offset, __global short *p);
void __ovld vstore3(ushort3 data, size_t offset, __global ushort *p);
void __ovld vstore3(int3 data, size_t offset, __global int *p);
void __ovld vstore3(uint3 data, size_t offset, __global uint *p);
void __ovld vstore3(long3 data, size_t offset, __global long *p);
void __ovld vstore3(ulong3 data, size_t offset, __global ulong *p);
void __ovld vstore3(float3 data, size_t offset, __global float *p);
void __ovld vstore4(char4 data, size_t offset, __global char *p);
void __ovld vstore4(uchar4 data, size_t offset, __global uchar *p);
void __ovld vstore4(short4 data, size_t offset, __global short *p);
void __ovld vstore4(ushort4 data, size_t offset, __global ushort *p);
void __ovld vstore4(int4 data, size_t offset, __global int *p);
void __ovld vstore4(uint4 data, size_t offset, __global uint *p);
void __ovld vstore4(long4 data, size_t offset, __global long *p);
void __ovld vstore4(ulong4 data, size_t offset, __global ulong *p);
void __ovld vstore4(float4 data, size_t offset, __global float *p);
void __ovld vstore8(char8 data, size_t offset, __global char *p);
void __ovld vstore8(uchar8 data, size_t offset, __global uchar *p);
void __ovld vstore8(short8 data, size_t offset, __global short *p);
void __ovld vstore8(ushort8 data, size_t offset, __global ushort *p);
void __ovld vstore8(int8 data, size_t offset, __global int *p);
void __ovld vstore8(uint8 data, size_t offset, __global uint *p);
void __ovld vstore8(long8 data, size_t offset, __global long *p);
void __ovld vstore8(ulong8 data, size_t offset, __global ulong *p);
void __ovld vstore8(float8 data, size_t offset, __global float *p);
void __ovld vstore16(char16 data, size_t offset, __global char *p);
void __ovld vstore16(uchar16 data, size_t offset, __global uchar *p);
void __ovld vstore16(short16 data, size_t offset, __global short *p);
void __ovld vstore16(ushort16 data, size_t offset, __global ushort *p);
void __ovld vstore16(int16 data, size_t offset, __global int *p);
void __ovld vstore16(uint16 data, size_t offset, __global uint *p);
void __ovld vstore16(long16 data, size_t offset, __global long *p);
void __ovld vstore16(ulong16 data, size_t offset, __global ulong *p);
void __ovld vstore16(float16 data, size_t offset, __global float *p);
void __ovld vstore2(char2 data, size_t offset, __local char *p);
void __ovld vstore2(uchar2 data, size_t offset, __local uchar *p);
void __ovld vstore2(short2 data, size_t offset, __local short *p);
void __ovld vstore2(ushort2 data, size_t offset, __local ushort *p);
void __ovld vstore2(int2 data, size_t offset, __local int *p);
void __ovld vstore2(uint2 data, size_t offset, __local uint *p);
void __ovld vstore2(long2 data, size_t offset, __local long *p);
void __ovld vstore2(ulong2 data, size_t offset, __local ulong *p);
void __ovld vstore2(float2 data, size_t offset, __local float *p);
void __ovld vstore3(char3 data, size_t offset, __local char *p);
void __ovld vstore3(uchar3 data, size_t offset, __local uchar *p);
void __ovld vstore3(short3 data, size_t offset, __local short *p);
void __ovld vstore3(ushort3 data, size_t offset, __local ushort *p);
void __ovld vstore3(int3 data, size_t offset, __local int *p);
void __ovld vstore3(uint3 data, size_t offset, __local uint *p);
void __ovld vstore3(long3 data, size_t offset, __local long *p);
void __ovld vstore3(ulong3 data, size_t offset, __local ulong *p);
void __ovld vstore3(float3 data, size_t offset, __local float *p);
void __ovld vstore4(char4 data, size_t offset, __local char *p);
void __ovld vstore4(uchar4 data, size_t offset, __local uchar *p);
void __ovld vstore4(short4 data, size_t offset, __local short *p);
void __ovld vstore4(ushort4 data, size_t offset, __local ushort *p);
void __ovld vstore4(int4 data, size_t offset, __local int *p);
void __ovld vstore4(uint4 data, size_t offset, __local uint *p);
void __ovld vstore4(long4 data, size_t offset, __local long *p);
void __ovld vstore4(ulong4 data, size_t offset, __local ulong *p);
void __ovld vstore4(float4 data, size_t offset, __local float *p);
void __ovld vstore8(char8 data, size_t offset, __local char *p);
void __ovld vstore8(uchar8 data, size_t offset, __local uchar *p);
void __ovld vstore8(short8 data, size_t offset, __local short *p);
void __ovld vstore8(ushort8 data, size_t offset, __local ushort *p);
void __ovld vstore8(int8 data, size_t offset, __local int *p);
void __ovld vstore8(uint8 data, size_t offset, __local uint *p);
void __ovld vstore8(long8 data, size_t offset, __local long *p);
void __ovld vstore8(ulong8 data, size_t offset, __local ulong *p);
void __ovld vstore8(float8 data, size_t offset, __local float *p);
void __ovld vstore16(char16 data, size_t offset, __local char *p);
void __ovld vstore16(uchar16 data, size_t offset, __local uchar *p);
void __ovld vstore16(short16 data, size_t offset, __local short *p);
void __ovld vstore16(ushort16 data, size_t offset, __local ushort *p);
void __ovld vstore16(int16 data, size_t offset, __local int *p);
void __ovld vstore16(uint16 data, size_t offset, __local uint *p);
void __ovld vstore16(long16 data, size_t offset, __local long *p);
void __ovld vstore16(ulong16 data, size_t offset, __local ulong *p);
void __ovld vstore16(float16 data, size_t offset, __local float *p);
void __ovld vstore2(char2 data, size_t offset, __private char *p);
void __ovld vstore2(uchar2 data, size_t offset, __private uchar *p);
void __ovld vstore2(short2 data, size_t offset, __private short *p);
void __ovld vstore2(ushort2 data, size_t offset, __private ushort *p);
void __ovld vstore2(int2 data, size_t offset, __private int *p);
void __ovld vstore2(uint2 data, size_t offset, __private uint *p);
void __ovld vstore2(long2 data, size_t offset, __private long *p);
void __ovld vstore2(ulong2 data, size_t offset, __private ulong *p);
void __ovld vstore2(float2 data, size_t offset, __private float *p);
void __ovld vstore3(char3 data, size_t offset, __private char *p);
void __ovld vstore3(uchar3 data, size_t offset, __private uchar *p);
void __ovld vstore3(short3 data, size_t offset, __private short *p);
void __ovld vstore3(ushort3 data, size_t offset, __private ushort *p);
void __ovld vstore3(int3 data, size_t offset, __private int *p);
void __ovld vstore3(uint3 data, size_t offset, __private uint *p);
void __ovld vstore3(long3 data, size_t offset, __private long *p);
void __ovld vstore3(ulong3 data, size_t offset, __private ulong *p);
void __ovld vstore3(float3 data, size_t offset, __private float *p);
void __ovld vstore4(char4 data, size_t offset, __private char *p);
void __ovld vstore4(uchar4 data, size_t offset, __private uchar *p);
void __ovld vstore4(short4 data, size_t offset, __private short *p);
void __ovld vstore4(ushort4 data, size_t offset, __private ushort *p);
void __ovld vstore4(int4 data, size_t offset, __private int *p);
void __ovld vstore4(uint4 data, size_t offset, __private uint *p);
void __ovld vstore4(long4 data, size_t offset, __private long *p);
void __ovld vstore4(ulong4 data, size_t offset, __private ulong *p);
void __ovld vstore4(float4 data, size_t offset, __private float *p);
void __ovld vstore8(char8 data, size_t offset, __private char *p);
void __ovld vstore8(uchar8 data, size_t offset, __private uchar *p);
void __ovld vstore8(short8 data, size_t offset, __private short *p);
void __ovld vstore8(ushort8 data, size_t offset, __private ushort *p);
void __ovld vstore8(int8 data, size_t offset, __private int *p);
void __ovld vstore8(uint8 data, size_t offset, __private uint *p);
void __ovld vstore8(long8 data, size_t offset, __private long *p);
void __ovld vstore8(ulong8 data, size_t offset, __private ulong *p);
void __ovld vstore8(float8 data, size_t offset, __private float *p);
void __ovld vstore16(char16 data, size_t offset, __private char *p);
void __ovld vstore16(uchar16 data, size_t offset, __private uchar *p);
void __ovld vstore16(short16 data, size_t offset, __private short *p);
void __ovld vstore16(ushort16 data, size_t offset, __private ushort *p);
void __ovld vstore16(int16 data, size_t offset, __private int *p);
void __ovld vstore16(uint16 data, size_t offset, __private uint *p);
void __ovld vstore16(long16 data, size_t offset, __private long *p);
void __ovld vstore16(ulong16 data, size_t offset, __private ulong *p);
void __ovld vstore16(float16 data, size_t offset, __private float *p);
#ifdef cl_khr_fp64
void __ovld vstore2(double2 data, size_t offset, __global double *p);
void __ovld vstore3(double3 data, size_t offset, __global double *p);
void __ovld vstore4(double4 data, size_t offset, __global double *p);
void __ovld vstore8(double8 data, size_t offset, __global double *p);
void __ovld vstore16(double16 data, size_t offset, __global double *p);
void __ovld vstore2(double2 data, size_t offset, __local double *p);
void __ovld vstore3(double3 data, size_t offset, __local double *p);
void __ovld vstore4(double4 data, size_t offset, __local double *p);
void __ovld vstore8(double8 data, size_t offset, __local double *p);
void __ovld vstore16(double16 data, size_t offset, __local double *p);
void __ovld vstore2(double2 data, size_t offset, __private double *p);
void __ovld vstore3(double3 data, size_t offset, __private double *p);
void __ovld vstore4(double4 data, size_t offset, __private double *p);
void __ovld vstore8(double8 data, size_t offset, __private double *p);
void __ovld vstore16(double16 data, size_t offset, __private double *p);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
void __ovld vstore(half data, size_t offset, __global half *p);
void __ovld vstore2(half2 data, size_t offset, __global half *p);
void __ovld vstore3(half3 data, size_t offset, __global half *p);
void __ovld vstore4(half4 data, size_t offset, __global half *p);
void __ovld vstore8(half8 data, size_t offset, __global half *p);
void __ovld vstore16(half16 data, size_t offset, __global half *p);
void __ovld vstore(half data, size_t offset, __local half *p);
void __ovld vstore2(half2 data, size_t offset, __local half *p);
void __ovld vstore3(half3 data, size_t offset, __local half *p);
void __ovld vstore4(half4 data, size_t offset, __local half *p);
void __ovld vstore8(half8 data, size_t offset, __local half *p);
void __ovld vstore16(half16 data, size_t offset, __local half *p);
void __ovld vstore(half data, size_t offset, __private half *p);
void __ovld vstore2(half2 data, size_t offset, __private half *p);
void __ovld vstore3(half3 data, size_t offset, __private half *p);
void __ovld vstore4(half4 data, size_t offset, __private half *p);
void __ovld vstore8(half8 data, size_t offset, __private half *p);
void __ovld vstore16(half16 data, size_t offset, __private half *p);
#endif //cl_khr_fp16
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Read sizeof (half) bytes of data from address
* (p + offset). The data read is interpreted as a
* half value. The half value is converted to a
* float value and the float value is returned.
* The read address computed as (p + offset)
* must be 16-bit aligned.
*/
float __ovld vload_half(size_t offset, const __constant half *p);
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
float __ovld vload_half(size_t offset, const half *p);
#else
float __ovld vload_half(size_t offset, const __global half *p);
float __ovld vload_half(size_t offset, const __local half *p);
float __ovld vload_half(size_t offset, const __private half *p);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Read sizeof (halfn) bytes of data from address
* (p + (offset * n)). The data read is interpreted
* as a halfn value. The halfn value read is
* converted to a floatn value and the floatn
* value is returned. The read address computed
* as (p + (offset * n)) must be 16-bit aligned.
*/
float2 __ovld vload_half2(size_t offset, const __constant half *p);
float3 __ovld vload_half3(size_t offset, const __constant half *p);
float4 __ovld vload_half4(size_t offset, const __constant half *p);
float8 __ovld vload_half8(size_t offset, const __constant half *p);
float16 __ovld vload_half16(size_t offset, const __constant half *p);
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
float2 __ovld vload_half2(size_t offset, const half *p);
float3 __ovld vload_half3(size_t offset, const half *p);
float4 __ovld vload_half4(size_t offset, const half *p);
float8 __ovld vload_half8(size_t offset, const half *p);
float16 __ovld vload_half16(size_t offset, const half *p);
#else
float2 __ovld vload_half2(size_t offset, const __global half *p);
float3 __ovld vload_half3(size_t offset, const __global half *p);
float4 __ovld vload_half4(size_t offset, const __global half *p);
float8 __ovld vload_half8(size_t offset, const __global half *p);
float16 __ovld vload_half16(size_t offset, const __global half *p);
float2 __ovld vload_half2(size_t offset, const __local half *p);
float3 __ovld vload_half3(size_t offset, const __local half *p);
float4 __ovld vload_half4(size_t offset, const __local half *p);
float8 __ovld vload_half8(size_t offset, const __local half *p);
float16 __ovld vload_half16(size_t offset, const __local half *p);
float2 __ovld vload_half2(size_t offset, const __private half *p);
float3 __ovld vload_half3(size_t offset, const __private half *p);
float4 __ovld vload_half4(size_t offset, const __private half *p);
float8 __ovld vload_half8(size_t offset, const __private half *p);
float16 __ovld vload_half16(size_t offset, const __private half *p);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* The float value given by data is first
* converted to a half value using the appropriate
* rounding mode. The half value is then written
* to address computed as (p + offset). The
* address computed as (p + offset) must be 16-
* bit aligned.
* vstore_half use the current rounding mode.
* The default current rounding mode is round to
* nearest even.
*/
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
void __ovld vstore_half(float data, size_t offset, half *p);
void __ovld vstore_half_rte(float data, size_t offset, half *p);
void __ovld vstore_half_rtz(float data, size_t offset, half *p);
void __ovld vstore_half_rtp(float data, size_t offset, half *p);
void __ovld vstore_half_rtn(float data, size_t offset, half *p);
#ifdef cl_khr_fp64
void __ovld vstore_half(double data, size_t offset, half *p);
void __ovld vstore_half_rte(double data, size_t offset, half *p);
void __ovld vstore_half_rtz(double data, size_t offset, half *p);
void __ovld vstore_half_rtp(double data, size_t offset, half *p);
void __ovld vstore_half_rtn(double data, size_t offset, half *p);
#endif //cl_khr_fp64
#else
void __ovld vstore_half(float data, size_t offset, __global half *p);
void __ovld vstore_half_rte(float data, size_t offset, __global half *p);
void __ovld vstore_half_rtz(float data, size_t offset, __global half *p);
void __ovld vstore_half_rtp(float data, size_t offset, __global half *p);
void __ovld vstore_half_rtn(float data, size_t offset, __global half *p);
void __ovld vstore_half(float data, size_t offset, __local half *p);
void __ovld vstore_half_rte(float data, size_t offset, __local half *p);
void __ovld vstore_half_rtz(float data, size_t offset, __local half *p);
void __ovld vstore_half_rtp(float data, size_t offset, __local half *p);
void __ovld vstore_half_rtn(float data, size_t offset, __local half *p);
void __ovld vstore_half(float data, size_t offset, __private half *p);
void __ovld vstore_half_rte(float data, size_t offset, __private half *p);
void __ovld vstore_half_rtz(float data, size_t offset, __private half *p);
void __ovld vstore_half_rtp(float data, size_t offset, __private half *p);
void __ovld vstore_half_rtn(float data, size_t offset, __private half *p);
#ifdef cl_khr_fp64
void __ovld vstore_half(double data, size_t offset, __global half *p);
void __ovld vstore_half_rte(double data, size_t offset, __global half *p);
void __ovld vstore_half_rtz(double data, size_t offset, __global half *p);
void __ovld vstore_half_rtp(double data, size_t offset, __global half *p);
void __ovld vstore_half_rtn(double data, size_t offset, __global half *p);
void __ovld vstore_half(double data, size_t offset, __local half *p);
void __ovld vstore_half_rte(double data, size_t offset, __local half *p);
void __ovld vstore_half_rtz(double data, size_t offset, __local half *p);
void __ovld vstore_half_rtp(double data, size_t offset, __local half *p);
void __ovld vstore_half_rtn(double data, size_t offset, __local half *p);
void __ovld vstore_half(double data, size_t offset, __private half *p);
void __ovld vstore_half_rte(double data, size_t offset, __private half *p);
void __ovld vstore_half_rtz(double data, size_t offset, __private half *p);
void __ovld vstore_half_rtp(double data, size_t offset, __private half *p);
void __ovld vstore_half_rtn(double data, size_t offset, __private half *p);
#endif //cl_khr_fp64
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* The floatn value given by data is converted to
* a halfn value using the appropriate rounding
* mode. The halfn value is then written to
* address computed as (p + (offset * n)). The
* address computed as (p + (offset * n)) must be
* 16-bit aligned.
* vstore_halfn uses the current rounding mode.
* The default current rounding mode is round to
* nearest even.
*/
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
void __ovld vstore_half2(float2 data, size_t offset, half *p);
void __ovld vstore_half3(float3 data, size_t offset, half *p);
void __ovld vstore_half4(float4 data, size_t offset, half *p);
void __ovld vstore_half8(float8 data, size_t offset, half *p);
void __ovld vstore_half16(float16 data, size_t offset, half *p);
void __ovld vstore_half2_rte(float2 data, size_t offset, half *p);
void __ovld vstore_half3_rte(float3 data, size_t offset, half *p);
void __ovld vstore_half4_rte(float4 data, size_t offset, half *p);
void __ovld vstore_half8_rte(float8 data, size_t offset, half *p);
void __ovld vstore_half16_rte(float16 data, size_t offset, half *p);
void __ovld vstore_half2_rtz(float2 data, size_t offset, half *p);
void __ovld vstore_half3_rtz(float3 data, size_t offset, half *p);
void __ovld vstore_half4_rtz(float4 data, size_t offset, half *p);
void __ovld vstore_half8_rtz(float8 data, size_t offset, half *p);
void __ovld vstore_half16_rtz(float16 data, size_t offset, half *p);
void __ovld vstore_half2_rtp(float2 data, size_t offset, half *p);
void __ovld vstore_half3_rtp(float3 data, size_t offset, half *p);
void __ovld vstore_half4_rtp(float4 data, size_t offset, half *p);
void __ovld vstore_half8_rtp(float8 data, size_t offset, half *p);
void __ovld vstore_half16_rtp(float16 data, size_t offset, half *p);
void __ovld vstore_half2_rtn(float2 data, size_t offset, half *p);
void __ovld vstore_half3_rtn(float3 data, size_t offset, half *p);
void __ovld vstore_half4_rtn(float4 data, size_t offset, half *p);
void __ovld vstore_half8_rtn(float8 data, size_t offset, half *p);
void __ovld vstore_half16_rtn(float16 data, size_t offset, half *p);
#ifdef cl_khr_fp64
void __ovld vstore_half2(double2 data, size_t offset, half *p);
void __ovld vstore_half3(double3 data, size_t offset, half *p);
void __ovld vstore_half4(double4 data, size_t offset, half *p);
void __ovld vstore_half8(double8 data, size_t offset, half *p);
void __ovld vstore_half16(double16 data, size_t offset, half *p);
void __ovld vstore_half2_rte(double2 data, size_t offset, half *p);
void __ovld vstore_half3_rte(double3 data, size_t offset, half *p);
void __ovld vstore_half4_rte(double4 data, size_t offset, half *p);
void __ovld vstore_half8_rte(double8 data, size_t offset, half *p);
void __ovld vstore_half16_rte(double16 data, size_t offset, half *p);
void __ovld vstore_half2_rtz(double2 data, size_t offset, half *p);
void __ovld vstore_half3_rtz(double3 data, size_t offset, half *p);
void __ovld vstore_half4_rtz(double4 data, size_t offset, half *p);
void __ovld vstore_half8_rtz(double8 data, size_t offset, half *p);
void __ovld vstore_half16_rtz(double16 data, size_t offset, half *p);
void __ovld vstore_half2_rtp(double2 data, size_t offset, half *p);
void __ovld vstore_half3_rtp(double3 data, size_t offset, half *p);
void __ovld vstore_half4_rtp(double4 data, size_t offset, half *p);
void __ovld vstore_half8_rtp(double8 data, size_t offset, half *p);
void __ovld vstore_half16_rtp(double16 data, size_t offset, half *p);
void __ovld vstore_half2_rtn(double2 data, size_t offset, half *p);
void __ovld vstore_half3_rtn(double3 data, size_t offset, half *p);
void __ovld vstore_half4_rtn(double4 data, size_t offset, half *p);
void __ovld vstore_half8_rtn(double8 data, size_t offset, half *p);
void __ovld vstore_half16_rtn(double16 data, size_t offset, half *p);
#endif //cl_khr_fp64
#else
void __ovld vstore_half2(float2 data, size_t offset, __global half *p);
void __ovld vstore_half3(float3 data, size_t offset, __global half *p);
void __ovld vstore_half4(float4 data, size_t offset, __global half *p);
void __ovld vstore_half8(float8 data, size_t offset, __global half *p);
void __ovld vstore_half16(float16 data, size_t offset, __global half *p);
void __ovld vstore_half2_rte(float2 data, size_t offset, __global half *p);
void __ovld vstore_half3_rte(float3 data, size_t offset, __global half *p);
void __ovld vstore_half4_rte(float4 data, size_t offset, __global half *p);
void __ovld vstore_half8_rte(float8 data, size_t offset, __global half *p);
void __ovld vstore_half16_rte(float16 data, size_t offset, __global half *p);
void __ovld vstore_half2_rtz(float2 data, size_t offset, __global half *p);
void __ovld vstore_half3_rtz(float3 data, size_t offset, __global half *p);
void __ovld vstore_half4_rtz(float4 data, size_t offset, __global half *p);
void __ovld vstore_half8_rtz(float8 data, size_t offset, __global half *p);
void __ovld vstore_half16_rtz(float16 data, size_t offset, __global half *p);
void __ovld vstore_half2_rtp(float2 data, size_t offset, __global half *p);
void __ovld vstore_half3_rtp(float3 data, size_t offset, __global half *p);
void __ovld vstore_half4_rtp(float4 data, size_t offset, __global half *p);
void __ovld vstore_half8_rtp(float8 data, size_t offset, __global half *p);
void __ovld vstore_half16_rtp(float16 data, size_t offset, __global half *p);
void __ovld vstore_half2_rtn(float2 data, size_t offset, __global half *p);
void __ovld vstore_half3_rtn(float3 data, size_t offset, __global half *p);
void __ovld vstore_half4_rtn(float4 data, size_t offset, __global half *p);
void __ovld vstore_half8_rtn(float8 data, size_t offset, __global half *p);
void __ovld vstore_half16_rtn(float16 data, size_t offset, __global half *p);
void __ovld vstore_half2(float2 data, size_t offset, __local half *p);
void __ovld vstore_half3(float3 data, size_t offset, __local half *p);
void __ovld vstore_half4(float4 data, size_t offset, __local half *p);
void __ovld vstore_half8(float8 data, size_t offset, __local half *p);
void __ovld vstore_half16(float16 data, size_t offset, __local half *p);
void __ovld vstore_half2_rte(float2 data, size_t offset, __local half *p);
void __ovld vstore_half3_rte(float3 data, size_t offset, __local half *p);
void __ovld vstore_half4_rte(float4 data, size_t offset, __local half *p);
void __ovld vstore_half8_rte(float8 data, size_t offset, __local half *p);
void __ovld vstore_half16_rte(float16 data, size_t offset, __local half *p);
void __ovld vstore_half2_rtz(float2 data, size_t offset, __local half *p);
void __ovld vstore_half3_rtz(float3 data, size_t offset, __local half *p);
void __ovld vstore_half4_rtz(float4 data, size_t offset, __local half *p);
void __ovld vstore_half8_rtz(float8 data, size_t offset, __local half *p);
void __ovld vstore_half16_rtz(float16 data, size_t offset, __local half *p);
void __ovld vstore_half2_rtp(float2 data, size_t offset, __local half *p);
void __ovld vstore_half3_rtp(float3 data, size_t offset, __local half *p);
void __ovld vstore_half4_rtp(float4 data, size_t offset, __local half *p);
void __ovld vstore_half8_rtp(float8 data, size_t offset, __local half *p);
void __ovld vstore_half16_rtp(float16 data, size_t offset, __local half *p);
void __ovld vstore_half2_rtn(float2 data, size_t offset, __local half *p);
void __ovld vstore_half3_rtn(float3 data, size_t offset, __local half *p);
void __ovld vstore_half4_rtn(float4 data, size_t offset, __local half *p);
void __ovld vstore_half8_rtn(float8 data, size_t offset, __local half *p);
void __ovld vstore_half16_rtn(float16 data, size_t offset, __local half *p);
void __ovld vstore_half2(float2 data, size_t offset, __private half *p);
void __ovld vstore_half3(float3 data, size_t offset, __private half *p);
void __ovld vstore_half4(float4 data, size_t offset, __private half *p);
void __ovld vstore_half8(float8 data, size_t offset, __private half *p);
void __ovld vstore_half16(float16 data, size_t offset, __private half *p);
void __ovld vstore_half2_rte(float2 data, size_t offset, __private half *p);
void __ovld vstore_half3_rte(float3 data, size_t offset, __private half *p);
void __ovld vstore_half4_rte(float4 data, size_t offset, __private half *p);
void __ovld vstore_half8_rte(float8 data, size_t offset, __private half *p);
void __ovld vstore_half16_rte(float16 data, size_t offset, __private half *p);
void __ovld vstore_half2_rtz(float2 data, size_t offset, __private half *p);
void __ovld vstore_half3_rtz(float3 data, size_t offset, __private half *p);
void __ovld vstore_half4_rtz(float4 data, size_t offset, __private half *p);
void __ovld vstore_half8_rtz(float8 data, size_t offset, __private half *p);
void __ovld vstore_half16_rtz(float16 data, size_t offset, __private half *p);
void __ovld vstore_half2_rtp(float2 data, size_t offset, __private half *p);
void __ovld vstore_half3_rtp(float3 data, size_t offset, __private half *p);
void __ovld vstore_half4_rtp(float4 data, size_t offset, __private half *p);
void __ovld vstore_half8_rtp(float8 data, size_t offset, __private half *p);
void __ovld vstore_half16_rtp(float16 data, size_t offset, __private half *p);
void __ovld vstore_half2_rtn(float2 data, size_t offset, __private half *p);
void __ovld vstore_half3_rtn(float3 data, size_t offset, __private half *p);
void __ovld vstore_half4_rtn(float4 data, size_t offset, __private half *p);
void __ovld vstore_half8_rtn(float8 data, size_t offset, __private half *p);
void __ovld vstore_half16_rtn(float16 data, size_t offset, __private half *p);
#ifdef cl_khr_fp64
void __ovld vstore_half2(double2 data, size_t offset, __global half *p);
void __ovld vstore_half3(double3 data, size_t offset, __global half *p);
void __ovld vstore_half4(double4 data, size_t offset, __global half *p);
void __ovld vstore_half8(double8 data, size_t offset, __global half *p);
void __ovld vstore_half16(double16 data, size_t offset, __global half *p);
void __ovld vstore_half2_rte(double2 data, size_t offset, __global half *p);
void __ovld vstore_half3_rte(double3 data, size_t offset, __global half *p);
void __ovld vstore_half4_rte(double4 data, size_t offset, __global half *p);
void __ovld vstore_half8_rte(double8 data, size_t offset, __global half *p);
void __ovld vstore_half16_rte(double16 data, size_t offset, __global half *p);
void __ovld vstore_half2_rtz(double2 data, size_t offset, __global half *p);
void __ovld vstore_half3_rtz(double3 data, size_t offset, __global half *p);
void __ovld vstore_half4_rtz(double4 data, size_t offset, __global half *p);
void __ovld vstore_half8_rtz(double8 data, size_t offset, __global half *p);
void __ovld vstore_half16_rtz(double16 data, size_t offset, __global half *p);
void __ovld vstore_half2_rtp(double2 data, size_t offset, __global half *p);
void __ovld vstore_half3_rtp(double3 data, size_t offset, __global half *p);
void __ovld vstore_half4_rtp(double4 data, size_t offset, __global half *p);
void __ovld vstore_half8_rtp(double8 data, size_t offset, __global half *p);
void __ovld vstore_half16_rtp(double16 data, size_t offset, __global half *p);
void __ovld vstore_half2_rtn(double2 data, size_t offset, __global half *p);
void __ovld vstore_half3_rtn(double3 data, size_t offset, __global half *p);
void __ovld vstore_half4_rtn(double4 data, size_t offset, __global half *p);
void __ovld vstore_half8_rtn(double8 data, size_t offset, __global half *p);
void __ovld vstore_half16_rtn(double16 data, size_t offset, __global half *p);
void __ovld vstore_half2(double2 data, size_t offset, __local half *p);
void __ovld vstore_half3(double3 data, size_t offset, __local half *p);
void __ovld vstore_half4(double4 data, size_t offset, __local half *p);
void __ovld vstore_half8(double8 data, size_t offset, __local half *p);
void __ovld vstore_half16(double16 data, size_t offset, __local half *p);
void __ovld vstore_half2_rte(double2 data, size_t offset, __local half *p);
void __ovld vstore_half3_rte(double3 data, size_t offset, __local half *p);
void __ovld vstore_half4_rte(double4 data, size_t offset, __local half *p);
void __ovld vstore_half8_rte(double8 data, size_t offset, __local half *p);
void __ovld vstore_half16_rte(double16 data, size_t offset, __local half *p);
void __ovld vstore_half2_rtz(double2 data, size_t offset, __local half *p);
void __ovld vstore_half3_rtz(double3 data, size_t offset, __local half *p);
void __ovld vstore_half4_rtz(double4 data, size_t offset, __local half *p);
void __ovld vstore_half8_rtz(double8 data, size_t offset, __local half *p);
void __ovld vstore_half16_rtz(double16 data, size_t offset, __local half *p);
void __ovld vstore_half2_rtp(double2 data, size_t offset, __local half *p);
void __ovld vstore_half3_rtp(double3 data, size_t offset, __local half *p);
void __ovld vstore_half4_rtp(double4 data, size_t offset, __local half *p);
void __ovld vstore_half8_rtp(double8 data, size_t offset, __local half *p);
void __ovld vstore_half16_rtp(double16 data, size_t offset, __local half *p);
void __ovld vstore_half2_rtn(double2 data, size_t offset, __local half *p);
void __ovld vstore_half3_rtn(double3 data, size_t offset, __local half *p);
void __ovld vstore_half4_rtn(double4 data, size_t offset, __local half *p);
void __ovld vstore_half8_rtn(double8 data, size_t offset, __local half *p);
void __ovld vstore_half16_rtn(double16 data, size_t offset, __local half *p);
void __ovld vstore_half2(double2 data, size_t offset, __private half *p);
void __ovld vstore_half3(double3 data, size_t offset, __private half *p);
void __ovld vstore_half4(double4 data, size_t offset, __private half *p);
void __ovld vstore_half8(double8 data, size_t offset, __private half *p);
void __ovld vstore_half16(double16 data, size_t offset, __private half *p);
void __ovld vstore_half2_rte(double2 data, size_t offset, __private half *p);
void __ovld vstore_half3_rte(double3 data, size_t offset, __private half *p);
void __ovld vstore_half4_rte(double4 data, size_t offset, __private half *p);
void __ovld vstore_half8_rte(double8 data, size_t offset, __private half *p);
void __ovld vstore_half16_rte(double16 data, size_t offset, __private half *p);
void __ovld vstore_half2_rtz(double2 data, size_t offset, __private half *p);
void __ovld vstore_half3_rtz(double3 data, size_t offset, __private half *p);
void __ovld vstore_half4_rtz(double4 data, size_t offset, __private half *p);
void __ovld vstore_half8_rtz(double8 data, size_t offset, __private half *p);
void __ovld vstore_half16_rtz(double16 data, size_t offset, __private half *p);
void __ovld vstore_half2_rtp(double2 data, size_t offset, __private half *p);
void __ovld vstore_half3_rtp(double3 data, size_t offset, __private half *p);
void __ovld vstore_half4_rtp(double4 data, size_t offset, __private half *p);
void __ovld vstore_half8_rtp(double8 data, size_t offset, __private half *p);
void __ovld vstore_half16_rtp(double16 data, size_t offset, __private half *p);
void __ovld vstore_half2_rtn(double2 data, size_t offset, __private half *p);
void __ovld vstore_half3_rtn(double3 data, size_t offset, __private half *p);
void __ovld vstore_half4_rtn(double4 data, size_t offset, __private half *p);
void __ovld vstore_half8_rtn(double8 data, size_t offset, __private half *p);
void __ovld vstore_half16_rtn(double16 data, size_t offset, __private half *p);
#endif //cl_khr_fp64
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* For n = 1, 2, 4, 8 and 16 read sizeof (halfn)
* bytes of data from address (p + (offset * n)).
* The data read is interpreted as a halfn value.
* The halfn value read is converted to a floatn
* value and the floatn value is returned.
* The address computed as (p + (offset * n))
* must be aligned to sizeof (halfn) bytes.
* For n = 3, vloada_half3 reads a half3 from
* address (p + (offset * 4)) and returns a float3.
* The address computed as (p + (offset * 4))
* must be aligned to sizeof (half) * 4 bytes.
*/
float __ovld vloada_half(size_t offset, const __constant half *p);
float2 __ovld vloada_half2(size_t offset, const __constant half *p);
float3 __ovld vloada_half3(size_t offset, const __constant half *p);
float4 __ovld vloada_half4(size_t offset, const __constant half *p);
float8 __ovld vloada_half8(size_t offset, const __constant half *p);
float16 __ovld vloada_half16(size_t offset, const __constant half *p);
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
float __ovld vloada_half(size_t offset, const half *p);
float2 __ovld vloada_half2(size_t offset, const half *p);
float3 __ovld vloada_half3(size_t offset, const half *p);
float4 __ovld vloada_half4(size_t offset, const half *p);
float8 __ovld vloada_half8(size_t offset, const half *p);
float16 __ovld vloada_half16(size_t offset, const half *p);
#else
float __ovld vloada_half(size_t offset, const __global half *p);
float2 __ovld vloada_half2(size_t offset, const __global half *p);
float3 __ovld vloada_half3(size_t offset, const __global half *p);
float4 __ovld vloada_half4(size_t offset, const __global half *p);
float8 __ovld vloada_half8(size_t offset, const __global half *p);
float16 __ovld vloada_half16(size_t offset, const __global half *p);
float __ovld vloada_half(size_t offset, const __local half *p);
float2 __ovld vloada_half2(size_t offset, const __local half *p);
float3 __ovld vloada_half3(size_t offset, const __local half *p);
float4 __ovld vloada_half4(size_t offset, const __local half *p);
float8 __ovld vloada_half8(size_t offset, const __local half *p);
float16 __ovld vloada_half16(size_t offset, const __local half *p);
float __ovld vloada_half(size_t offset, const __private half *p);
float2 __ovld vloada_half2(size_t offset, const __private half *p);
float3 __ovld vloada_half3(size_t offset, const __private half *p);
float4 __ovld vloada_half4(size_t offset, const __private half *p);
float8 __ovld vloada_half8(size_t offset, const __private half *p);
float16 __ovld vloada_half16(size_t offset, const __private half *p);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* The floatn value given by data is converted to
* a halfn value using the appropriate rounding
* mode.
* For n = 1, 2, 4, 8 and 16, the halfn value is
* written to the address computed as (p + (offset
* * n)). The address computed as (p + (offset *
* n)) must be aligned to sizeof (halfn) bytes.
* For n = 3, the half3 value is written to the
* address computed as (p + (offset * 4)). The
* address computed as (p + (offset * 4)) must be
* aligned to sizeof (half) * 4 bytes.
* vstorea_halfn uses the current rounding
* mode. The default current rounding mode is
* round to nearest even.
*/
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
void __ovld vstorea_half(float data, size_t offset, half *p);
void __ovld vstorea_half2(float2 data, size_t offset, half *p);
void __ovld vstorea_half3(float3 data, size_t offset, half *p);
void __ovld vstorea_half4(float4 data, size_t offset, half *p);
void __ovld vstorea_half8(float8 data, size_t offset, half *p);
void __ovld vstorea_half16(float16 data, size_t offset, half *p);
void __ovld vstorea_half_rte(float data, size_t offset, half *p);
void __ovld vstorea_half2_rte(float2 data, size_t offset, half *p);
void __ovld vstorea_half3_rte(float3 data, size_t offset, half *p);
void __ovld vstorea_half4_rte(float4 data, size_t offset, half *p);
void __ovld vstorea_half8_rte(float8 data, size_t offset, half *p);
void __ovld vstorea_half16_rte(float16 data, size_t offset, half *p);
void __ovld vstorea_half_rtz(float data, size_t offset, half *p);
void __ovld vstorea_half2_rtz(float2 data, size_t offset, half *p);
void __ovld vstorea_half3_rtz(float3 data, size_t offset, half *p);
void __ovld vstorea_half4_rtz(float4 data, size_t offset, half *p);
void __ovld vstorea_half8_rtz(float8 data, size_t offset, half *p);
void __ovld vstorea_half16_rtz(float16 data, size_t offset, half *p);
void __ovld vstorea_half_rtp(float data, size_t offset, half *p);
void __ovld vstorea_half2_rtp(float2 data, size_t offset, half *p);
void __ovld vstorea_half3_rtp(float3 data, size_t offset, half *p);
void __ovld vstorea_half4_rtp(float4 data, size_t offset, half *p);
void __ovld vstorea_half8_rtp(float8 data, size_t offset, half *p);
void __ovld vstorea_half16_rtp(float16 data, size_t offset, half *p);
void __ovld vstorea_half_rtn(float data, size_t offset, half *p);
void __ovld vstorea_half2_rtn(float2 data, size_t offset, half *p);
void __ovld vstorea_half3_rtn(float3 data, size_t offset, half *p);
void __ovld vstorea_half4_rtn(float4 data, size_t offset, half *p);
void __ovld vstorea_half8_rtn(float8 data, size_t offset, half *p);
void __ovld vstorea_half16_rtn(float16 data, size_t offset, half *p);
#ifdef cl_khr_fp64
void __ovld vstorea_half(double data, size_t offset, half *p);
void __ovld vstorea_half2(double2 data, size_t offset, half *p);
void __ovld vstorea_half3(double3 data, size_t offset, half *p);
void __ovld vstorea_half4(double4 data, size_t offset, half *p);
void __ovld vstorea_half8(double8 data, size_t offset, half *p);
void __ovld vstorea_half16(double16 data, size_t offset, half *p);
void __ovld vstorea_half_rte(double data, size_t offset, half *p);
void __ovld vstorea_half2_rte(double2 data, size_t offset, half *p);
void __ovld vstorea_half3_rte(double3 data, size_t offset, half *p);
void __ovld vstorea_half4_rte(double4 data, size_t offset, half *p);
void __ovld vstorea_half8_rte(double8 data, size_t offset, half *p);
void __ovld vstorea_half16_rte(double16 data, size_t offset, half *p);
void __ovld vstorea_half_rtz(double data, size_t offset, half *p);
void __ovld vstorea_half2_rtz(double2 data, size_t offset, half *p);
void __ovld vstorea_half3_rtz(double3 data, size_t offset, half *p);
void __ovld vstorea_half4_rtz(double4 data, size_t offset, half *p);
void __ovld vstorea_half8_rtz(double8 data, size_t offset, half *p);
void __ovld vstorea_half16_rtz(double16 data, size_t offset, half *p);
void __ovld vstorea_half_rtp(double data, size_t offset, half *p);
void __ovld vstorea_half2_rtp(double2 data, size_t offset, half *p);
void __ovld vstorea_half3_rtp(double3 data, size_t offset, half *p);
void __ovld vstorea_half4_rtp(double4 data, size_t offset, half *p);
void __ovld vstorea_half8_rtp(double8 data, size_t offset, half *p);
void __ovld vstorea_half16_rtp(double16 data, size_t offset, half *p);
void __ovld vstorea_half_rtn(double data, size_t offset, half *p);
void __ovld vstorea_half2_rtn(double2 data, size_t offset, half *p);
void __ovld vstorea_half3_rtn(double3 data, size_t offset, half *p);
void __ovld vstorea_half4_rtn(double4 data, size_t offset, half *p);
void __ovld vstorea_half8_rtn(double8 data, size_t offset, half *p);
void __ovld vstorea_half16_rtn(double16 data, size_t offset, half *p);
#endif //cl_khr_fp64
#else
void __ovld vstorea_half(float data, size_t offset, __global half *p);
void __ovld vstorea_half2(float2 data, size_t offset, __global half *p);
void __ovld vstorea_half3(float3 data, size_t offset, __global half *p);
void __ovld vstorea_half4(float4 data, size_t offset, __global half *p);
void __ovld vstorea_half8(float8 data, size_t offset, __global half *p);
void __ovld vstorea_half16(float16 data, size_t offset, __global half *p);
void __ovld vstorea_half_rte(float data, size_t offset, __global half *p);
void __ovld vstorea_half2_rte(float2 data, size_t offset, __global half *p);
void __ovld vstorea_half3_rte(float3 data, size_t offset, __global half *p);
void __ovld vstorea_half4_rte(float4 data, size_t offset, __global half *p);
void __ovld vstorea_half8_rte(float8 data, size_t offset, __global half *p);
void __ovld vstorea_half16_rte(float16 data, size_t offset, __global half *p);
void __ovld vstorea_half_rtz(float data, size_t offset, __global half *p);
void __ovld vstorea_half2_rtz(float2 data, size_t offset, __global half *p);
void __ovld vstorea_half3_rtz(float3 data, size_t offset, __global half *p);
void __ovld vstorea_half4_rtz(float4 data, size_t offset, __global half *p);
void __ovld vstorea_half8_rtz(float8 data, size_t offset, __global half *p);
void __ovld vstorea_half16_rtz(float16 data, size_t offset, __global half *p);
void __ovld vstorea_half_rtp(float data, size_t offset, __global half *p);
void __ovld vstorea_half2_rtp(float2 data, size_t offset, __global half *p);
void __ovld vstorea_half3_rtp(float3 data, size_t offset, __global half *p);
void __ovld vstorea_half4_rtp(float4 data, size_t offset, __global half *p);
void __ovld vstorea_half8_rtp(float8 data, size_t offset, __global half *p);
void __ovld vstorea_half16_rtp(float16 data, size_t offset, __global half *p);
void __ovld vstorea_half_rtn(float data, size_t offset, __global half *p);
void __ovld vstorea_half2_rtn(float2 data, size_t offset, __global half *p);
void __ovld vstorea_half3_rtn(float3 data, size_t offset, __global half *p);
void __ovld vstorea_half4_rtn(float4 data, size_t offset, __global half *p);
void __ovld vstorea_half8_rtn(float8 data, size_t offset, __global half *p);
void __ovld vstorea_half16_rtn(float16 data, size_t offset, __global half *p);
void __ovld vstorea_half(float data, size_t offset, __local half *p);
void __ovld vstorea_half2(float2 data, size_t offset, __local half *p);
void __ovld vstorea_half3(float3 data, size_t offset, __local half *p);
void __ovld vstorea_half4(float4 data, size_t offset, __local half *p);
void __ovld vstorea_half8(float8 data, size_t offset, __local half *p);
void __ovld vstorea_half16(float16 data, size_t offset, __local half *p);
void __ovld vstorea_half_rte(float data, size_t offset, __local half *p);
void __ovld vstorea_half2_rte(float2 data, size_t offset, __local half *p);
void __ovld vstorea_half3_rte(float3 data, size_t offset, __local half *p);
void __ovld vstorea_half4_rte(float4 data, size_t offset, __local half *p);
void __ovld vstorea_half8_rte(float8 data, size_t offset, __local half *p);
void __ovld vstorea_half16_rte(float16 data, size_t offset, __local half *p);
void __ovld vstorea_half_rtz(float data, size_t offset, __local half *p);
void __ovld vstorea_half2_rtz(float2 data, size_t offset, __local half *p);
void __ovld vstorea_half3_rtz(float3 data, size_t offset, __local half *p);
void __ovld vstorea_half4_rtz(float4 data, size_t offset, __local half *p);
void __ovld vstorea_half8_rtz(float8 data, size_t offset, __local half *p);
void __ovld vstorea_half16_rtz(float16 data, size_t offset, __local half *p);
void __ovld vstorea_half_rtp(float data, size_t offset, __local half *p);
void __ovld vstorea_half2_rtp(float2 data, size_t offset, __local half *p);
void __ovld vstorea_half3_rtp(float3 data, size_t offset, __local half *p);
void __ovld vstorea_half4_rtp(float4 data, size_t offset, __local half *p);
void __ovld vstorea_half8_rtp(float8 data, size_t offset, __local half *p);
void __ovld vstorea_half16_rtp(float16 data, size_t offset, __local half *p);
void __ovld vstorea_half_rtn(float data, size_t offset, __local half *p);
void __ovld vstorea_half2_rtn(float2 data, size_t offset, __local half *p);
void __ovld vstorea_half3_rtn(float3 data, size_t offset, __local half *p);
void __ovld vstorea_half4_rtn(float4 data, size_t offset, __local half *p);
void __ovld vstorea_half8_rtn(float8 data, size_t offset, __local half *p);
void __ovld vstorea_half16_rtn(float16 data, size_t offset, __local half *p);
void __ovld vstorea_half(float data, size_t offset, __private half *p);
void __ovld vstorea_half2(float2 data, size_t offset, __private half *p);
void __ovld vstorea_half3(float3 data, size_t offset, __private half *p);
void __ovld vstorea_half4(float4 data, size_t offset, __private half *p);
void __ovld vstorea_half8(float8 data, size_t offset, __private half *p);
void __ovld vstorea_half16(float16 data, size_t offset, __private half *p);
void __ovld vstorea_half_rte(float data, size_t offset, __private half *p);
void __ovld vstorea_half2_rte(float2 data, size_t offset, __private half *p);
void __ovld vstorea_half3_rte(float3 data, size_t offset, __private half *p);
void __ovld vstorea_half4_rte(float4 data, size_t offset, __private half *p);
void __ovld vstorea_half8_rte(float8 data, size_t offset, __private half *p);
void __ovld vstorea_half16_rte(float16 data, size_t offset, __private half *p);
void __ovld vstorea_half_rtz(float data, size_t offset, __private half *p);
void __ovld vstorea_half2_rtz(float2 data, size_t offset, __private half *p);
void __ovld vstorea_half3_rtz(float3 data, size_t offset, __private half *p);
void __ovld vstorea_half4_rtz(float4 data, size_t offset, __private half *p);
void __ovld vstorea_half8_rtz(float8 data, size_t offset, __private half *p);
void __ovld vstorea_half16_rtz(float16 data, size_t offset, __private half *p);
void __ovld vstorea_half_rtp(float data, size_t offset, __private half *p);
void __ovld vstorea_half2_rtp(float2 data, size_t offset, __private half *p);
void __ovld vstorea_half3_rtp(float3 data, size_t offset, __private half *p);
void __ovld vstorea_half4_rtp(float4 data, size_t offset, __private half *p);
void __ovld vstorea_half8_rtp(float8 data, size_t offset, __private half *p);
void __ovld vstorea_half16_rtp(float16 data, size_t offset, __private half *p);
void __ovld vstorea_half_rtn(float data, size_t offset, __private half *p);
void __ovld vstorea_half2_rtn(float2 data, size_t offset, __private half *p);
void __ovld vstorea_half3_rtn(float3 data, size_t offset, __private half *p);
void __ovld vstorea_half4_rtn(float4 data, size_t offset, __private half *p);
void __ovld vstorea_half8_rtn(float8 data, size_t offset, __private half *p);
void __ovld vstorea_half16_rtn(float16 data, size_t offset, __private half *p);
#ifdef cl_khr_fp64
void __ovld vstorea_half(double data, size_t offset, __global half *p);
void __ovld vstorea_half2(double2 data, size_t offset, __global half *p);
void __ovld vstorea_half3(double3 data, size_t offset, __global half *p);
void __ovld vstorea_half4(double4 data, size_t offset, __global half *p);
void __ovld vstorea_half8(double8 data, size_t offset, __global half *p);
void __ovld vstorea_half16(double16 data, size_t offset, __global half *p);
void __ovld vstorea_half_rte(double data, size_t offset, __global half *p);
void __ovld vstorea_half2_rte(double2 data, size_t offset, __global half *p);
void __ovld vstorea_half3_rte(double3 data, size_t offset, __global half *p);
void __ovld vstorea_half4_rte(double4 data, size_t offset, __global half *p);
void __ovld vstorea_half8_rte(double8 data, size_t offset, __global half *p);
void __ovld vstorea_half16_rte(double16 data, size_t offset, __global half *p);
void __ovld vstorea_half_rtz(double data, size_t offset, __global half *p);
void __ovld vstorea_half2_rtz(double2 data, size_t offset, __global half *p);
void __ovld vstorea_half3_rtz(double3 data, size_t offset, __global half *p);
void __ovld vstorea_half4_rtz(double4 data, size_t offset, __global half *p);
void __ovld vstorea_half8_rtz(double8 data, size_t offset, __global half *p);
void __ovld vstorea_half16_rtz(double16 data, size_t offset, __global half *p);
void __ovld vstorea_half_rtp(double data, size_t offset, __global half *p);
void __ovld vstorea_half2_rtp(double2 data, size_t offset, __global half *p);
void __ovld vstorea_half3_rtp(double3 data, size_t offset, __global half *p);
void __ovld vstorea_half4_rtp(double4 data, size_t offset, __global half *p);
void __ovld vstorea_half8_rtp(double8 data, size_t offset, __global half *p);
void __ovld vstorea_half16_rtp(double16 data, size_t offset, __global half *p);
void __ovld vstorea_half_rtn(double data, size_t offset, __global half *p);
void __ovld vstorea_half2_rtn(double2 data, size_t offset, __global half *p);
void __ovld vstorea_half3_rtn(double3 data, size_t offset, __global half *p);
void __ovld vstorea_half4_rtn(double4 data, size_t offset, __global half *p);
void __ovld vstorea_half8_rtn(double8 data, size_t offset, __global half *p);
void __ovld vstorea_half16_rtn(double16 data, size_t offset, __global half *p);
void __ovld vstorea_half(double data, size_t offset, __local half *p);
void __ovld vstorea_half2(double2 data, size_t offset, __local half *p);
void __ovld vstorea_half3(double3 data, size_t offset, __local half *p);
void __ovld vstorea_half4(double4 data, size_t offset, __local half *p);
void __ovld vstorea_half8(double8 data, size_t offset, __local half *p);
void __ovld vstorea_half16(double16 data, size_t offset, __local half *p);
void __ovld vstorea_half_rte(double data, size_t offset, __local half *p);
void __ovld vstorea_half2_rte(double2 data, size_t offset, __local half *p);
void __ovld vstorea_half3_rte(double3 data, size_t offset, __local half *p);
void __ovld vstorea_half4_rte(double4 data, size_t offset, __local half *p);
void __ovld vstorea_half8_rte(double8 data, size_t offset, __local half *p);
void __ovld vstorea_half16_rte(double16 data, size_t offset, __local half *p);
void __ovld vstorea_half_rtz(double data, size_t offset, __local half *p);
void __ovld vstorea_half2_rtz(double2 data, size_t offset, __local half *p);
void __ovld vstorea_half3_rtz(double3 data, size_t offset, __local half *p);
void __ovld vstorea_half4_rtz(double4 data, size_t offset, __local half *p);
void __ovld vstorea_half8_rtz(double8 data, size_t offset, __local half *p);
void __ovld vstorea_half16_rtz(double16 data, size_t offset, __local half *p);
void __ovld vstorea_half_rtp(double data, size_t offset, __local half *p);
void __ovld vstorea_half2_rtp(double2 data, size_t offset, __local half *p);
void __ovld vstorea_half3_rtp(double3 data, size_t offset, __local half *p);
void __ovld vstorea_half4_rtp(double4 data, size_t offset, __local half *p);
void __ovld vstorea_half8_rtp(double8 data, size_t offset, __local half *p);
void __ovld vstorea_half16_rtp(double16 data, size_t offset, __local half *p);
void __ovld vstorea_half_rtn(double data, size_t offset, __local half *p);
void __ovld vstorea_half2_rtn(double2 data, size_t offset, __local half *p);
void __ovld vstorea_half3_rtn(double3 data, size_t offset, __local half *p);
void __ovld vstorea_half4_rtn(double4 data, size_t offset, __local half *p);
void __ovld vstorea_half8_rtn(double8 data, size_t offset, __local half *p);
void __ovld vstorea_half16_rtn(double16 data, size_t offset, __local half *p);
void __ovld vstorea_half(double data, size_t offset, __private half *p);
void __ovld vstorea_half2(double2 data, size_t offset, __private half *p);
void __ovld vstorea_half3(double3 data, size_t offset, __private half *p);
void __ovld vstorea_half4(double4 data, size_t offset, __private half *p);
void __ovld vstorea_half8(double8 data, size_t offset, __private half *p);
void __ovld vstorea_half16(double16 data, size_t offset, __private half *p);
void __ovld vstorea_half_rte(double data, size_t offset, __private half *p);
void __ovld vstorea_half2_rte(double2 data, size_t offset, __private half *p);
void __ovld vstorea_half3_rte(double3 data, size_t offset, __private half *p);
void __ovld vstorea_half4_rte(double4 data, size_t offset, __private half *p);
void __ovld vstorea_half8_rte(double8 data, size_t offset, __private half *p);
void __ovld vstorea_half16_rte(double16 data, size_t offset, __private half *p);
void __ovld vstorea_half_rtz(double data, size_t offset, __private half *p);
void __ovld vstorea_half2_rtz(double2 data, size_t offset, __private half *p);
void __ovld vstorea_half3_rtz(double3 data, size_t offset, __private half *p);
void __ovld vstorea_half4_rtz(double4 data, size_t offset, __private half *p);
void __ovld vstorea_half8_rtz(double8 data, size_t offset, __private half *p);
void __ovld vstorea_half16_rtz(double16 data, size_t offset, __private half *p);
void __ovld vstorea_half_rtp(double data, size_t offset, __private half *p);
void __ovld vstorea_half2_rtp(double2 data, size_t offset, __private half *p);
void __ovld vstorea_half3_rtp(double3 data, size_t offset, __private half *p);
void __ovld vstorea_half4_rtp(double4 data, size_t offset, __private half *p);
void __ovld vstorea_half8_rtp(double8 data, size_t offset, __private half *p);
void __ovld vstorea_half16_rtp(double16 data, size_t offset, __private half *p);
void __ovld vstorea_half_rtn(double data, size_t offset, __private half *p);
void __ovld vstorea_half2_rtn(double2 data,size_t offset, __private half *p);
void __ovld vstorea_half3_rtn(double3 data,size_t offset, __private half *p);
void __ovld vstorea_half4_rtn(double4 data,size_t offset, __private half *p);
void __ovld vstorea_half8_rtn(double8 data,size_t offset, __private half *p);
void __ovld vstorea_half16_rtn(double16 data,size_t offset, __private half *p);
#endif //cl_khr_fp64
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
// OpenCL v1.1 s6.11.8, v1.2 s6.12.8, v2.0 s6.13.8 - Synchronization Functions
// Flag type and values for barrier, mem_fence, read_mem_fence, write_mem_fence
typedef uint cl_mem_fence_flags;
/**
* Queue a memory fence to ensure correct
* ordering of memory operations to local memory
*/
#define CLK_LOCAL_MEM_FENCE 0x01
/**
* Queue a memory fence to ensure correct
* ordering of memory operations to global memory
*/
#define CLK_GLOBAL_MEM_FENCE 0x02
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Queue a memory fence to ensure correct ordering of memory
* operations between work-items of a work-group to
* image memory.
*/
#define CLK_IMAGE_MEM_FENCE 0x04
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* All work-items in a work-group executing the kernel
* on a processor must execute this function before any
* are allowed to continue execution beyond the barrier.
* This function must be encountered by all work-items in
* a work-group executing the kernel.
* If barrier is inside a conditional statement, then all
* work-items must enter the conditional if any work-item
* enters the conditional statement and executes the
* barrier.
* If barrer is inside a loop, all work-items must execute
* the barrier for each iteration of the loop before any are
* allowed to continue execution beyond the barrier.
* The barrier function also queues a memory fence
* (reads and writes) to ensure correct ordering of
* memory operations to local or global memory.
* The flags argument specifies the memory address space
* and can be set to a combination of the following literal
* values.
* CLK_LOCAL_MEM_FENCE - The barrier function
* will either flush any variables stored in local memory
* or queue a memory fence to ensure correct ordering of
* memory operations to local memory.
* CLK_GLOBAL_MEM_FENCE - The barrier function
* will queue a memory fence to ensure correct ordering
* of memory operations to global memory. This can be
* useful when work-items, for example, write to buffer or
* image objects and then want to read the updated data.
*/
void __ovld __conv barrier(cl_mem_fence_flags flags);
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
typedef enum memory_scope {
memory_scope_work_item = __OPENCL_MEMORY_SCOPE_WORK_ITEM,
memory_scope_work_group = __OPENCL_MEMORY_SCOPE_WORK_GROUP,
memory_scope_device = __OPENCL_MEMORY_SCOPE_DEVICE,
memory_scope_all_svm_devices = __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES,
#if defined(cl_intel_subgroups) || defined(cl_khr_subgroups)
memory_scope_sub_group = __OPENCL_MEMORY_SCOPE_SUB_GROUP
#endif
} memory_scope;
void __ovld __conv work_group_barrier(cl_mem_fence_flags flags, memory_scope scope);
void __ovld __conv work_group_barrier(cl_mem_fence_flags flags);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
// OpenCL v1.1 s6.11.9, v1.2 s6.12.9 - Explicit Memory Fence Functions
/**
* Orders loads and stores of a work-item
* executing a kernel. This means that loads
* and stores preceding the mem_fence will
* be committed to memory before any loads
* and stores following the mem_fence.
* The flags argument specifies the memory
* address space and can be set to a
* combination of the following literal
* values:
* CLK_LOCAL_MEM_FENCE
* CLK_GLOBAL_MEM_FENCE.
*/
void __ovld mem_fence(cl_mem_fence_flags flags);
/**
* Read memory barrier that orders only
* loads.
* The flags argument specifies the memory
* address space and can be set to a
* combination of the following literal
* values:
* CLK_LOCAL_MEM_FENCE
* CLK_GLOBAL_MEM_FENCE.
*/
void __ovld read_mem_fence(cl_mem_fence_flags flags);
/**
* Write memory barrier that orders only
* stores.
* The flags argument specifies the memory
* address space and can be set to a
* combination of the following literal
* values:
* CLK_LOCAL_MEM_FENCE
* CLK_GLOBAL_MEM_FENCE.
*/
void __ovld write_mem_fence(cl_mem_fence_flags flags);
// OpenCL v2.0 s6.13.9 - Address Space Qualifier Functions
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
cl_mem_fence_flags __ovld get_fence(const void *ptr);
cl_mem_fence_flags __ovld get_fence(void *ptr);
/**
* Builtin functions to_global, to_local, and to_private need to be declared as Clang builtin functions
* and checked in Sema since they should be declared as
* addr gentype* to_addr (gentype*);
* where gentype is builtin type or user defined type.
*/
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
// OpenCL v1.1 s6.11.10, v1.2 s6.12.10, v2.0 s6.13.10 - Async Copies from Global to Local Memory, Local to Global Memory, and Prefetch
/**
* event_t async_work_group_copy (
* __global gentype *dst,
* const __local gentype *src,
* size_t num_elements,
* event_t event)
* Perform an async copy of num_elements
* gentype elements from src to dst. The async
* copy is performed by all work-items in a workgroup
* and this built-in function must therefore
* be encountered by all work-items in a workgroup
* executing the kernel with the same
* argument values; otherwise the results are
* undefined.
* Returns an event object that can be used by
* wait_group_events to wait for the async copy
* to finish. The event argument can also be used
* to associate the async_work_group_copy with
* a previous async copy allowing an event to be
* shared by multiple async copies; otherwise event
* should be zero.
* If event argument is non-zero, the event object
* supplied in event argument will be returned.
* This function does not perform any implicit
* synchronization of source data such as using a
* barrier before performing the copy.
*/
event_t __ovld async_work_group_copy(__local char *dst, const __global char *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local uchar *dst, const __global uchar *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local short *dst, const __global short *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local ushort *dst, const __global ushort *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local int *dst, const __global int *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local uint *dst, const __global uint *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local long *dst, const __global long *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local ulong *dst, const __global ulong *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local float *dst, const __global float *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local char2 *dst, const __global char2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local uchar2 *dst, const __global uchar2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local short2 *dst, const __global short2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local ushort2 *dst, const __global ushort2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local int2 *dst, const __global int2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local uint2 *dst, const __global uint2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local long2 *dst, const __global long2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local ulong2 *dst, const __global ulong2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local float2 *dst, const __global float2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local char3 *dst, const __global char3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local uchar3 *dst, const __global uchar3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local short3 *dst, const __global short3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local ushort3 *dst, const __global ushort3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local int3 *dst, const __global int3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local uint3 *dst, const __global uint3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local long3 *dst, const __global long3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local ulong3 *dst, const __global ulong3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local float3 *dst, const __global float3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local char4 *dst, const __global char4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local uchar4 *dst, const __global uchar4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local short4 *dst, const __global short4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local ushort4 *dst, const __global ushort4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local int4 *dst, const __global int4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local uint4 *dst, const __global uint4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local long4 *dst, const __global long4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local ulong4 *dst, const __global ulong4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local float4 *dst, const __global float4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local char8 *dst, const __global char8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local uchar8 *dst, const __global uchar8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local short8 *dst, const __global short8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local ushort8 *dst, const __global ushort8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local int8 *dst, const __global int8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local uint8 *dst, const __global uint8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local long8 *dst, const __global long8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local ulong8 *dst, const __global ulong8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local float8 *dst, const __global float8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local char16 *dst, const __global char16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local uchar16 *dst, const __global uchar16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local short16 *dst, const __global short16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local ushort16 *dst, const __global ushort16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local int16 *dst, const __global int16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local uint16 *dst, const __global uint16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local long16 *dst, const __global long16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local ulong16 *dst, const __global ulong16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local float16 *dst, const __global float16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global char *dst, const __local char *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global uchar *dst, const __local uchar *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global short *dst, const __local short *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global ushort *dst, const __local ushort *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global int *dst, const __local int *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global uint *dst, const __local uint *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global long *dst, const __local long *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global ulong *dst, const __local ulong *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global float *dst, const __local float *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global char2 *dst, const __local char2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global uchar2 *dst, const __local uchar2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global short2 *dst, const __local short2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global ushort2 *dst, const __local ushort2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global int2 *dst, const __local int2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global uint2 *dst, const __local uint2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global long2 *dst, const __local long2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global ulong2 *dst, const __local ulong2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global float2 *dst, const __local float2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global char3 *dst, const __local char3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global uchar3 *dst, const __local uchar3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global short3 *dst, const __local short3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global ushort3 *dst, const __local ushort3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global int3 *dst, const __local int3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global uint3 *dst, const __local uint3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global long3 *dst, const __local long3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global ulong3 *dst, const __local ulong3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global float3 *dst, const __local float3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global char4 *dst, const __local char4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global uchar4 *dst, const __local uchar4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global short4 *dst, const __local short4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global ushort4 *dst, const __local ushort4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global int4 *dst, const __local int4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global uint4 *dst, const __local uint4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global long4 *dst, const __local long4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global ulong4 *dst, const __local ulong4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global float4 *dst, const __local float4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global char8 *dst, const __local char8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global uchar8 *dst, const __local uchar8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global short8 *dst, const __local short8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global ushort8 *dst, const __local ushort8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global int8 *dst, const __local int8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global uint8 *dst, const __local uint8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global long8 *dst, const __local long8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global ulong8 *dst, const __local ulong8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global float8 *dst, const __local float8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global char16 *dst, const __local char16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global uchar16 *dst, const __local uchar16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global short16 *dst, const __local short16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global ushort16 *dst, const __local ushort16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global int16 *dst, const __local int16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global uint16 *dst, const __local uint16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global long16 *dst, const __local long16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global ulong16 *dst, const __local ulong16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global float16 *dst, const __local float16 *src, size_t num_elements, event_t event);
#ifdef cl_khr_fp64
event_t __ovld async_work_group_copy(__local double *dst, const __global double *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local double2 *dst, const __global double2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local double3 *dst, const __global double3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local double4 *dst, const __global double4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local double8 *dst, const __global double8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local double16 *dst, const __global double16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global double *dst, const __local double *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global double2 *dst, const __local double2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global double3 *dst, const __local double3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global double4 *dst, const __local double4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global double8 *dst, const __local double8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global double16 *dst, const __local double16 *src, size_t num_elements, event_t event);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
event_t __ovld async_work_group_copy(__local half *dst, const __global half *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local half2 *dst, const __global half2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local half3 *dst, const __global half3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local half4 *dst, const __global half4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local half8 *dst, const __global half8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__local half16 *dst, const __global half16 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global half *dst, const __local half *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global half2 *dst, const __local half2 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global half3 *dst, const __local half3 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global half4 *dst, const __local half4 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global half8 *dst, const __local half8 *src, size_t num_elements, event_t event);
event_t __ovld async_work_group_copy(__global half16 *dst, const __local half16 *src, size_t num_elements, event_t event);
#endif //cl_khr_fp16
/**
* Perform an async gather of num_elements
* gentype elements from src to dst. The
* src_stride is the stride in elements for each
* gentype element read from src. The dst_stride
* is the stride in elements for each gentype
* element written to dst. The async gather is
* performed by all work-items in a work-group.
* This built-in function must therefore be
* encountered by all work-items in a work-group
* executing the kernel with the same argument
* values; otherwise the results are undefined.
* Returns an event object that can be used by
* wait_group_events to wait for the async copy
* to finish. The event argument can also be used
* to associate the
* async_work_group_strided_copy with a
* previous async copy allowing an event to be
* shared by multiple async copies; otherwise event
* should be zero.
* If event argument is non-zero, the event object
* supplied in event argument will be returned.
* This function does not perform any implicit
* synchronization of source data such as using a
* barrier before performing the copy.
*/
event_t __ovld async_work_group_strided_copy(__local char *dst, const __global char *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local uchar *dst, const __global uchar *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local short *dst, const __global short *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local ushort *dst, const __global ushort *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local int *dst, const __global int *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local uint *dst, const __global uint *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local long *dst, const __global long *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local ulong *dst, const __global ulong *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local float *dst, const __global float *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local char2 *dst, const __global char2 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local uchar2 *dst, const __global uchar2 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local short2 *dst, const __global short2 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local ushort2 *dst, const __global ushort2 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local int2 *dst, const __global int2 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local uint2 *dst, const __global uint2 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local long2 *dst, const __global long2 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local ulong2 *dst, const __global ulong2 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local float2 *dst, const __global float2 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local char3 *dst, const __global char3 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local uchar3 *dst, const __global uchar3 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local short3 *dst, const __global short3 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local ushort3 *dst, const __global ushort3 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local int3 *dst, const __global int3 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local uint3 *dst, const __global uint3 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local long3 *dst, const __global long3 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local ulong3 *dst, const __global ulong3 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local float3 *dst, const __global float3 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local char4 *dst, const __global char4 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local uchar4 *dst, const __global uchar4 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local short4 *dst, const __global short4 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local ushort4 *dst, const __global ushort4 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local int4 *dst, const __global int4 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local uint4 *dst, const __global uint4 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local long4 *dst, const __global long4 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local ulong4 *dst, const __global ulong4 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local float4 *dst, const __global float4 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local char8 *dst, const __global char8 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local uchar8 *dst, const __global uchar8 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local short8 *dst, const __global short8 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local ushort8 *dst, const __global ushort8 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local int8 *dst, const __global int8 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local uint8 *dst, const __global uint8 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local long8 *dst, const __global long8 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local ulong8 *dst, const __global ulong8 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local float8 *dst, const __global float8 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local char16 *dst, const __global char16 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local uchar16 *dst, const __global uchar16 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local short16 *dst, const __global short16 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local ushort16 *dst, const __global ushort16 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local int16 *dst, const __global int16 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local uint16 *dst, const __global uint16 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local long16 *dst, const __global long16 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local ulong16 *dst, const __global ulong16 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local float16 *dst, const __global float16 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global char *dst, const __local char *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global uchar *dst, const __local uchar *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global short *dst, const __local short *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global ushort *dst, const __local ushort *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global int *dst, const __local int *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global uint *dst, const __local uint *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global long *dst, const __local long *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global ulong *dst, const __local ulong *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global float *dst, const __local float *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global char2 *dst, const __local char2 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global uchar2 *dst, const __local uchar2 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global short2 *dst, const __local short2 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global ushort2 *dst, const __local ushort2 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global int2 *dst, const __local int2 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global uint2 *dst, const __local uint2 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global long2 *dst, const __local long2 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global ulong2 *dst, const __local ulong2 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global float2 *dst, const __local float2 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global char3 *dst, const __local char3 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global uchar3 *dst, const __local uchar3 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global short3 *dst, const __local short3 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global ushort3 *dst, const __local ushort3 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global int3 *dst, const __local int3 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global uint3 *dst, const __local uint3 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global long3 *dst, const __local long3 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global ulong3 *dst, const __local ulong3 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global float3 *dst, const __local float3 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global char4 *dst, const __local char4 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global uchar4 *dst, const __local uchar4 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global short4 *dst, const __local short4 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global ushort4 *dst, const __local ushort4 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global int4 *dst, const __local int4 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global uint4 *dst, const __local uint4 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global long4 *dst, const __local long4 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global ulong4 *dst, const __local ulong4 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global float4 *dst, const __local float4 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global char8 *dst, const __local char8 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global uchar8 *dst, const __local uchar8 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global short8 *dst, const __local short8 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global ushort8 *dst, const __local ushort8 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global int8 *dst, const __local int8 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global uint8 *dst, const __local uint8 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global long8 *dst, const __local long8 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global ulong8 *dst, const __local ulong8 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global float8 *dst, const __local float8 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global char16 *dst, const __local char16 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global uchar16 *dst, const __local uchar16 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global short16 *dst, const __local short16 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global ushort16 *dst, const __local ushort16 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global int16 *dst, const __local int16 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global uint16 *dst, const __local uint16 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global long16 *dst, const __local long16 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global ulong16 *dst, const __local ulong16 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global float16 *dst, const __local float16 *src, size_t num_elements, size_t dst_stride, event_t event);
#ifdef cl_khr_fp64
event_t __ovld async_work_group_strided_copy(__local double *dst, const __global double *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local double2 *dst, const __global double2 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local double3 *dst, const __global double3 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local double4 *dst, const __global double4 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local double8 *dst, const __global double8 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local double16 *dst, const __global double16 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global double *dst, const __local double *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global double2 *dst, const __local double2 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global double3 *dst, const __local double3 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global double4 *dst, const __local double4 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global double8 *dst, const __local double8 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global double16 *dst, const __local double16 *src, size_t num_elements, size_t dst_stride, event_t event);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
event_t __ovld async_work_group_strided_copy(__local half *dst, const __global half *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local half2 *dst, const __global half2 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local half3 *dst, const __global half3 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local half4 *dst, const __global half4 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local half8 *dst, const __global half8 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__local half16 *dst, const __global half16 *src, size_t num_elements, size_t src_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global half *dst, const __local half *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global half2 *dst, const __local half2 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global half3 *dst, const __local half3 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global half4 *dst, const __local half4 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global half8 *dst, const __local half8 *src, size_t num_elements, size_t dst_stride, event_t event);
event_t __ovld async_work_group_strided_copy(__global half16 *dst, const __local half16 *src, size_t num_elements, size_t dst_stride, event_t event);
#endif //cl_khr_fp16
/**
* Wait for events that identify the
* async_work_group_copy operations to
* complete. The event objects specified in
* event_list will be released after the wait is
* performed.
* This function must be encountered by all workitems
* in a work-group executing the kernel with
* the same num_events and event objects specified
* in event_list; otherwise the results are undefined.
*/
void __ovld wait_group_events(int num_events, event_t *event_list);
/**
* Prefetch num_elements * sizeof(gentype)
* bytes into the global cache. The prefetch
* instruction is applied to a work-item in a workgroup
* and does not affect the functional
* behavior of the kernel.
*/
void __ovld prefetch(const __global char *p, size_t num_elements);
void __ovld prefetch(const __global uchar *p, size_t num_elements);
void __ovld prefetch(const __global short *p, size_t num_elements);
void __ovld prefetch(const __global ushort *p, size_t num_elements);
void __ovld prefetch(const __global int *p, size_t num_elements);
void __ovld prefetch(const __global uint *p, size_t num_elements);
void __ovld prefetch(const __global long *p, size_t num_elements);
void __ovld prefetch(const __global ulong *p, size_t num_elements);
void __ovld prefetch(const __global float *p, size_t num_elements);
void __ovld prefetch(const __global char2 *p, size_t num_elements);
void __ovld prefetch(const __global uchar2 *p, size_t num_elements);
void __ovld prefetch(const __global short2 *p, size_t num_elements);
void __ovld prefetch(const __global ushort2 *p, size_t num_elements);
void __ovld prefetch(const __global int2 *p, size_t num_elements);
void __ovld prefetch(const __global uint2 *p, size_t num_elements);
void __ovld prefetch(const __global long2 *p, size_t num_elements);
void __ovld prefetch(const __global ulong2 *p, size_t num_elements);
void __ovld prefetch(const __global float2 *p, size_t num_elements);
void __ovld prefetch(const __global char3 *p, size_t num_elements);
void __ovld prefetch(const __global uchar3 *p, size_t num_elements);
void __ovld prefetch(const __global short3 *p, size_t num_elements);
void __ovld prefetch(const __global ushort3 *p, size_t num_elements);
void __ovld prefetch(const __global int3 *p, size_t num_elements);
void __ovld prefetch(const __global uint3 *p, size_t num_elements);
void __ovld prefetch(const __global long3 *p, size_t num_elements);
void __ovld prefetch(const __global ulong3 *p, size_t num_elements);
void __ovld prefetch(const __global float3 *p, size_t num_elements);
void __ovld prefetch(const __global char4 *p, size_t num_elements);
void __ovld prefetch(const __global uchar4 *p, size_t num_elements);
void __ovld prefetch(const __global short4 *p, size_t num_elements);
void __ovld prefetch(const __global ushort4 *p, size_t num_elements);
void __ovld prefetch(const __global int4 *p, size_t num_elements);
void __ovld prefetch(const __global uint4 *p, size_t num_elements);
void __ovld prefetch(const __global long4 *p, size_t num_elements);
void __ovld prefetch(const __global ulong4 *p, size_t num_elements);
void __ovld prefetch(const __global float4 *p, size_t num_elements);
void __ovld prefetch(const __global char8 *p, size_t num_elements);
void __ovld prefetch(const __global uchar8 *p, size_t num_elements);
void __ovld prefetch(const __global short8 *p, size_t num_elements);
void __ovld prefetch(const __global ushort8 *p, size_t num_elements);
void __ovld prefetch(const __global int8 *p, size_t num_elements);
void __ovld prefetch(const __global uint8 *p, size_t num_elements);
void __ovld prefetch(const __global long8 *p, size_t num_elements);
void __ovld prefetch(const __global ulong8 *p, size_t num_elements);
void __ovld prefetch(const __global float8 *p, size_t num_elements);
void __ovld prefetch(const __global char16 *p, size_t num_elements);
void __ovld prefetch(const __global uchar16 *p, size_t num_elements);
void __ovld prefetch(const __global short16 *p, size_t num_elements);
void __ovld prefetch(const __global ushort16 *p, size_t num_elements);
void __ovld prefetch(const __global int16 *p, size_t num_elements);
void __ovld prefetch(const __global uint16 *p, size_t num_elements);
void __ovld prefetch(const __global long16 *p, size_t num_elements);
void __ovld prefetch(const __global ulong16 *p, size_t num_elements);
void __ovld prefetch(const __global float16 *p, size_t num_elements);
#ifdef cl_khr_fp64
void __ovld prefetch(const __global double *p, size_t num_elements);
void __ovld prefetch(const __global double2 *p, size_t num_elements);
void __ovld prefetch(const __global double3 *p, size_t num_elements);
void __ovld prefetch(const __global double4 *p, size_t num_elements);
void __ovld prefetch(const __global double8 *p, size_t num_elements);
void __ovld prefetch(const __global double16 *p, size_t num_elements);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
void __ovld prefetch(const __global half *p, size_t num_elements);
void __ovld prefetch(const __global half2 *p, size_t num_elements);
void __ovld prefetch(const __global half3 *p, size_t num_elements);
void __ovld prefetch(const __global half4 *p, size_t num_elements);
void __ovld prefetch(const __global half8 *p, size_t num_elements);
void __ovld prefetch(const __global half16 *p, size_t num_elements);
#endif // cl_khr_fp16
// OpenCL v1.1 s6.11.1, v1.2 s6.12.11 - Atomic Functions
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable
#pragma OPENCL EXTENSION cl_khr_int64_extended_atomics : enable
#endif
/**
* Read the 32-bit value (referred to as old)
* stored at location pointed by p. Compute
* (old + val) and store result at location
* pointed by p. The function returns old.
*/
int __ovld atomic_add(volatile __global int *p, int val);
unsigned int __ovld atomic_add(volatile __global unsigned int *p, unsigned int val);
int __ovld atomic_add(volatile __local int *p, int val);
unsigned int __ovld atomic_add(volatile __local unsigned int *p, unsigned int val);
#if defined(cl_khr_global_int32_base_atomics)
int __ovld atom_add(volatile __global int *p, int val);
unsigned int __ovld atom_add(volatile __global unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_local_int32_base_atomics)
int __ovld atom_add(volatile __local int *p, int val);
unsigned int __ovld atom_add(volatile __local unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_int64_base_atomics)
long __ovld atom_add(volatile __global long *p, long val);
unsigned long __ovld atom_add(volatile __global unsigned long *p, unsigned long val);
long __ovld atom_add(volatile __local long *p, long val);
unsigned long __ovld atom_add(volatile __local unsigned long *p, unsigned long val);
#endif
/**
* Read the 32-bit value (referred to as old) stored at location pointed by p.
* Compute (old - val) and store result at location pointed by p. The function
* returns old.
*/
int __ovld atomic_sub(volatile __global int *p, int val);
unsigned int __ovld atomic_sub(volatile __global unsigned int *p, unsigned int val);
int __ovld atomic_sub(volatile __local int *p, int val);
unsigned int __ovld atomic_sub(volatile __local unsigned int *p, unsigned int val);
#if defined(cl_khr_global_int32_base_atomics)
int __ovld atom_sub(volatile __global int *p, int val);
unsigned int __ovld atom_sub(volatile __global unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_local_int32_base_atomics)
int __ovld atom_sub(volatile __local int *p, int val);
unsigned int __ovld atom_sub(volatile __local unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_int64_base_atomics)
long __ovld atom_sub(volatile __global long *p, long val);
unsigned long __ovld atom_sub(volatile __global unsigned long *p, unsigned long val);
long __ovld atom_sub(volatile __local long *p, long val);
unsigned long __ovld atom_sub(volatile __local unsigned long *p, unsigned long val);
#endif
/**
* Swaps the old value stored at location p
* with new value given by val. Returns old
* value.
*/
int __ovld atomic_xchg(volatile __global int *p, int val);
unsigned int __ovld atomic_xchg(volatile __global unsigned int *p, unsigned int val);
int __ovld atomic_xchg(volatile __local int *p, int val);
unsigned int __ovld atomic_xchg(volatile __local unsigned int *p, unsigned int val);
float __ovld atomic_xchg(volatile __global float *p, float val);
float __ovld atomic_xchg(volatile __local float *p, float val);
#if defined(cl_khr_global_int32_base_atomics)
int __ovld atom_xchg(volatile __global int *p, int val);
unsigned int __ovld atom_xchg(volatile __global unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_local_int32_base_atomics)
int __ovld atom_xchg(volatile __local int *p, int val);
unsigned int __ovld atom_xchg(volatile __local unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_int64_base_atomics)
long __ovld atom_xchg(volatile __global long *p, long val);
long __ovld atom_xchg(volatile __local long *p, long val);
unsigned long __ovld atom_xchg(volatile __global unsigned long *p, unsigned long val);
unsigned long __ovld atom_xchg(volatile __local unsigned long *p, unsigned long val);
#endif
/**
* Read the 32-bit value (referred to as old)
* stored at location pointed by p. Compute
* (old + 1) and store result at location
* pointed by p. The function returns old.
*/
int __ovld atomic_inc(volatile __global int *p);
unsigned int __ovld atomic_inc(volatile __global unsigned int *p);
int __ovld atomic_inc(volatile __local int *p);
unsigned int __ovld atomic_inc(volatile __local unsigned int *p);
#if defined(cl_khr_global_int32_base_atomics)
int __ovld atom_inc(volatile __global int *p);
unsigned int __ovld atom_inc(volatile __global unsigned int *p);
#endif
#if defined(cl_khr_local_int32_base_atomics)
int __ovld atom_inc(volatile __local int *p);
unsigned int __ovld atom_inc(volatile __local unsigned int *p);
#endif
#if defined(cl_khr_int64_base_atomics)
long __ovld atom_inc(volatile __global long *p);
unsigned long __ovld atom_inc(volatile __global unsigned long *p);
long __ovld atom_inc(volatile __local long *p);
unsigned long __ovld atom_inc(volatile __local unsigned long *p);
#endif
/**
* Read the 32-bit value (referred to as old)
* stored at location pointed by p. Compute
* (old - 1) and store result at location
* pointed by p. The function returns old.
*/
int __ovld atomic_dec(volatile __global int *p);
unsigned int __ovld atomic_dec(volatile __global unsigned int *p);
int __ovld atomic_dec(volatile __local int *p);
unsigned int __ovld atomic_dec(volatile __local unsigned int *p);
#if defined(cl_khr_global_int32_base_atomics)
int __ovld atom_dec(volatile __global int *p);
unsigned int __ovld atom_dec(volatile __global unsigned int *p);
#endif
#if defined(cl_khr_local_int32_base_atomics)
int __ovld atom_dec(volatile __local int *p);
unsigned int __ovld atom_dec(volatile __local unsigned int *p);
#endif
#if defined(cl_khr_int64_base_atomics)
long __ovld atom_dec(volatile __global long *p);
unsigned long __ovld atom_dec(volatile __global unsigned long *p);
long __ovld atom_dec(volatile __local long *p);
unsigned long __ovld atom_dec(volatile __local unsigned long *p);
#endif
/**
* Read the 32-bit value (referred to as old)
* stored at location pointed by p. Compute
* (old == cmp) ? val : old and store result at
* location pointed by p. The function
* returns old.
*/
int __ovld atomic_cmpxchg(volatile __global int *p, int cmp, int val);
unsigned int __ovld atomic_cmpxchg(volatile __global unsigned int *p, unsigned int cmp, unsigned int val);
int __ovld atomic_cmpxchg(volatile __local int *p, int cmp, int val);
unsigned int __ovld atomic_cmpxchg(volatile __local unsigned int *p, unsigned int cmp, unsigned int val);
#if defined(cl_khr_global_int32_base_atomics)
int __ovld atom_cmpxchg(volatile __global int *p, int cmp, int val);
unsigned int __ovld atom_cmpxchg(volatile __global unsigned int *p, unsigned int cmp, unsigned int val);
#endif
#if defined(cl_khr_local_int32_base_atomics)
int __ovld atom_cmpxchg(volatile __local int *p, int cmp, int val);
unsigned int __ovld atom_cmpxchg(volatile __local unsigned int *p, unsigned int cmp, unsigned int val);
#endif
#if defined(cl_khr_int64_base_atomics)
long __ovld atom_cmpxchg(volatile __global long *p, long cmp, long val);
unsigned long __ovld atom_cmpxchg(volatile __global unsigned long *p, unsigned long cmp, unsigned long val);
long __ovld atom_cmpxchg(volatile __local long *p, long cmp, long val);
unsigned long __ovld atom_cmpxchg(volatile __local unsigned long *p, unsigned long cmp, unsigned long val);
#endif
/**
* Read the 32-bit value (referred to as old)
* stored at location pointed by p. Compute
* min(old, val) and store minimum value at
* location pointed by p. The function
* returns old.
*/
int __ovld atomic_min(volatile __global int *p, int val);
unsigned int __ovld atomic_min(volatile __global unsigned int *p, unsigned int val);
int __ovld atomic_min(volatile __local int *p, int val);
unsigned int __ovld atomic_min(volatile __local unsigned int *p, unsigned int val);
#if defined(cl_khr_global_int32_extended_atomics)
int __ovld atom_min(volatile __global int *p, int val);
unsigned int __ovld atom_min(volatile __global unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_local_int32_extended_atomics)
int __ovld atom_min(volatile __local int *p, int val);
unsigned int __ovld atom_min(volatile __local unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_int64_extended_atomics)
long __ovld atom_min(volatile __global long *p, long val);
unsigned long __ovld atom_min(volatile __global unsigned long *p, unsigned long val);
long __ovld atom_min(volatile __local long *p, long val);
unsigned long __ovld atom_min(volatile __local unsigned long *p, unsigned long val);
#endif
/**
* Read the 32-bit value (referred to as old)
* stored at location pointed by p. Compute
* max(old, val) and store maximum value at
* location pointed by p. The function
* returns old.
*/
int __ovld atomic_max(volatile __global int *p, int val);
unsigned int __ovld atomic_max(volatile __global unsigned int *p, unsigned int val);
int __ovld atomic_max(volatile __local int *p, int val);
unsigned int __ovld atomic_max(volatile __local unsigned int *p, unsigned int val);
#if defined(cl_khr_global_int32_extended_atomics)
int __ovld atom_max(volatile __global int *p, int val);
unsigned int __ovld atom_max(volatile __global unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_local_int32_extended_atomics)
int __ovld atom_max(volatile __local int *p, int val);
unsigned int __ovld atom_max(volatile __local unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_int64_extended_atomics)
long __ovld atom_max(volatile __global long *p, long val);
unsigned long __ovld atom_max(volatile __global unsigned long *p, unsigned long val);
long __ovld atom_max(volatile __local long *p, long val);
unsigned long __ovld atom_max(volatile __local unsigned long *p, unsigned long val);
#endif
/**
* Read the 32-bit value (referred to as old)
* stored at location pointed by p. Compute
* (old & val) and store result at location
* pointed by p. The function returns old.
*/
int __ovld atomic_and(volatile __global int *p, int val);
unsigned int __ovld atomic_and(volatile __global unsigned int *p, unsigned int val);
int __ovld atomic_and(volatile __local int *p, int val);
unsigned int __ovld atomic_and(volatile __local unsigned int *p, unsigned int val);
#if defined(cl_khr_global_int32_extended_atomics)
int __ovld atom_and(volatile __global int *p, int val);
unsigned int __ovld atom_and(volatile __global unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_local_int32_extended_atomics)
int __ovld atom_and(volatile __local int *p, int val);
unsigned int __ovld atom_and(volatile __local unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_int64_extended_atomics)
long __ovld atom_and(volatile __global long *p, long val);
unsigned long __ovld atom_and(volatile __global unsigned long *p, unsigned long val);
long __ovld atom_and(volatile __local long *p, long val);
unsigned long __ovld atom_and(volatile __local unsigned long *p, unsigned long val);
#endif
/**
* Read the 32-bit value (referred to as old)
* stored at location pointed by p. Compute
* (old | val) and store result at location
* pointed by p. The function returns old.
*/
int __ovld atomic_or(volatile __global int *p, int val);
unsigned int __ovld atomic_or(volatile __global unsigned int *p, unsigned int val);
int __ovld atomic_or(volatile __local int *p, int val);
unsigned int __ovld atomic_or(volatile __local unsigned int *p, unsigned int val);
#if defined(cl_khr_global_int32_extended_atomics)
int __ovld atom_or(volatile __global int *p, int val);
unsigned int __ovld atom_or(volatile __global unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_local_int32_extended_atomics)
int __ovld atom_or(volatile __local int *p, int val);
unsigned int __ovld atom_or(volatile __local unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_int64_extended_atomics)
long __ovld atom_or(volatile __global long *p, long val);
unsigned long __ovld atom_or(volatile __global unsigned long *p, unsigned long val);
long __ovld atom_or(volatile __local long *p, long val);
unsigned long __ovld atom_or(volatile __local unsigned long *p, unsigned long val);
#endif
/**
* Read the 32-bit value (referred to as old)
* stored at location pointed by p. Compute
* (old ^ val) and store result at location
* pointed by p. The function returns old.
*/
int __ovld atomic_xor(volatile __global int *p, int val);
unsigned int __ovld atomic_xor(volatile __global unsigned int *p, unsigned int val);
int __ovld atomic_xor(volatile __local int *p, int val);
unsigned int __ovld atomic_xor(volatile __local unsigned int *p, unsigned int val);
#if defined(cl_khr_global_int32_extended_atomics)
int __ovld atom_xor(volatile __global int *p, int val);
unsigned int __ovld atom_xor(volatile __global unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_local_int32_extended_atomics)
int __ovld atom_xor(volatile __local int *p, int val);
unsigned int __ovld atom_xor(volatile __local unsigned int *p, unsigned int val);
#endif
#if defined(cl_khr_int64_extended_atomics)
long __ovld atom_xor(volatile __global long *p, long val);
unsigned long __ovld atom_xor(volatile __global unsigned long *p, unsigned long val);
long __ovld atom_xor(volatile __local long *p, long val);
unsigned long __ovld atom_xor(volatile __local unsigned long *p, unsigned long val);
#endif
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : disable
#pragma OPENCL EXTENSION cl_khr_int64_extended_atomics : disable
#endif
// OpenCL v2.0 s6.13.11 - Atomics Functions
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
#ifndef ATOMIC_VAR_INIT
#define ATOMIC_VAR_INIT(x) (x)
#endif //ATOMIC_VAR_INIT
#define ATOMIC_FLAG_INIT 0
// enum values aligned with what clang uses in EmitAtomicExpr()
typedef enum memory_order
{
memory_order_relaxed = __ATOMIC_RELAXED,
memory_order_acquire = __ATOMIC_ACQUIRE,
memory_order_release = __ATOMIC_RELEASE,
memory_order_acq_rel = __ATOMIC_ACQ_REL,
memory_order_seq_cst = __ATOMIC_SEQ_CST
} memory_order;
// double atomics support requires extensions cl_khr_int64_base_atomics and cl_khr_int64_extended_atomics
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable
#pragma OPENCL EXTENSION cl_khr_int64_extended_atomics : enable
#endif
// atomic_init()
void __ovld atomic_init(volatile atomic_int *object, int value);
void __ovld atomic_init(volatile atomic_uint *object, uint value);
void __ovld atomic_init(volatile atomic_float *object, float value);
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
void __ovld atomic_init(volatile atomic_long *object, long value);
void __ovld atomic_init(volatile atomic_ulong *object, ulong value);
#ifdef cl_khr_fp64
void __ovld atomic_init(volatile atomic_double *object, double value);
#endif //cl_khr_fp64
#endif
// atomic_work_item_fence()
void __ovld atomic_work_item_fence(cl_mem_fence_flags flags, memory_order order, memory_scope scope);
// atomic_fetch()
int __ovld atomic_fetch_add(volatile atomic_int *object, int operand);
int __ovld atomic_fetch_add_explicit(volatile atomic_int *object, int operand, memory_order order);
int __ovld atomic_fetch_add_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_add(volatile atomic_uint *object, uint operand);
uint __ovld atomic_fetch_add_explicit(volatile atomic_uint *object, uint operand, memory_order order);
uint __ovld atomic_fetch_add_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
int __ovld atomic_fetch_sub(volatile atomic_int *object, int operand);
int __ovld atomic_fetch_sub_explicit(volatile atomic_int *object, int operand, memory_order order);
int __ovld atomic_fetch_sub_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_sub(volatile atomic_uint *object, uint operand);
uint __ovld atomic_fetch_sub_explicit(volatile atomic_uint *object, uint operand, memory_order order);
uint __ovld atomic_fetch_sub_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
int __ovld atomic_fetch_or(volatile atomic_int *object, int operand);
int __ovld atomic_fetch_or_explicit(volatile atomic_int *object, int operand, memory_order order);
int __ovld atomic_fetch_or_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_or(volatile atomic_uint *object, uint operand);
uint __ovld atomic_fetch_or_explicit(volatile atomic_uint *object, uint operand, memory_order order);
uint __ovld atomic_fetch_or_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
int __ovld atomic_fetch_xor(volatile atomic_int *object, int operand);
int __ovld atomic_fetch_xor_explicit(volatile atomic_int *object, int operand, memory_order order);
int __ovld atomic_fetch_xor_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_xor(volatile atomic_uint *object, uint operand);
uint __ovld atomic_fetch_xor_explicit(volatile atomic_uint *object, uint operand, memory_order order);
uint __ovld atomic_fetch_xor_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
int __ovld atomic_fetch_and(volatile atomic_int *object, int operand);
int __ovld atomic_fetch_and_explicit(volatile atomic_int *object, int operand, memory_order order);
int __ovld atomic_fetch_and_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_and(volatile atomic_uint *object, uint operand);
uint __ovld atomic_fetch_and_explicit(volatile atomic_uint *object, uint operand, memory_order order);
uint __ovld atomic_fetch_and_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
int __ovld atomic_fetch_min(volatile atomic_int *object, int operand);
int __ovld atomic_fetch_min_explicit(volatile atomic_int *object, int operand, memory_order order);
int __ovld atomic_fetch_min_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_min(volatile atomic_uint *object, uint operand);
uint __ovld atomic_fetch_min_explicit(volatile atomic_uint *object, uint operand, memory_order order);
uint __ovld atomic_fetch_min_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_min(volatile atomic_uint *object, int operand);
uint __ovld atomic_fetch_min_explicit(volatile atomic_uint *object, int operand, memory_order order);
uint __ovld atomic_fetch_min_explicit(volatile atomic_uint *object, int operand, memory_order order, memory_scope scope);
int __ovld atomic_fetch_max(volatile atomic_int *object, int operand);
int __ovld atomic_fetch_max_explicit(volatile atomic_int *object, int operand, memory_order order);
int __ovld atomic_fetch_max_explicit(volatile atomic_int *object, int operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_max(volatile atomic_uint *object, uint operand);
uint __ovld atomic_fetch_max_explicit(volatile atomic_uint *object, uint operand, memory_order order);
uint __ovld atomic_fetch_max_explicit(volatile atomic_uint *object, uint operand, memory_order order, memory_scope scope);
uint __ovld atomic_fetch_max(volatile atomic_uint *object, int operand);
uint __ovld atomic_fetch_max_explicit(volatile atomic_uint *object, int operand, memory_order order);
uint __ovld atomic_fetch_max_explicit(volatile atomic_uint *object, int operand, memory_order order, memory_scope scope);
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
long __ovld atomic_fetch_add(volatile atomic_long *object, long operand);
long __ovld atomic_fetch_add_explicit(volatile atomic_long *object, long operand, memory_order order);
long __ovld atomic_fetch_add_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_add(volatile atomic_ulong *object, ulong operand);
ulong __ovld atomic_fetch_add_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
ulong __ovld atomic_fetch_add_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
long __ovld atomic_fetch_sub(volatile atomic_long *object, long operand);
long __ovld atomic_fetch_sub_explicit(volatile atomic_long *object, long operand, memory_order order);
long __ovld atomic_fetch_sub_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_sub(volatile atomic_ulong *object, ulong operand);
ulong __ovld atomic_fetch_sub_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
ulong __ovld atomic_fetch_sub_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
long __ovld atomic_fetch_or(volatile atomic_long *object, long operand);
long __ovld atomic_fetch_or_explicit(volatile atomic_long *object, long operand, memory_order order);
long __ovld atomic_fetch_or_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_or(volatile atomic_ulong *object, ulong operand);
ulong __ovld atomic_fetch_or_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
ulong __ovld atomic_fetch_or_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
long __ovld atomic_fetch_xor(volatile atomic_long *object, long operand);
long __ovld atomic_fetch_xor_explicit(volatile atomic_long *object, long operand, memory_order order);
long __ovld atomic_fetch_xor_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_xor(volatile atomic_ulong *object, ulong operand);
ulong __ovld atomic_fetch_xor_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
ulong __ovld atomic_fetch_xor_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
long __ovld atomic_fetch_and(volatile atomic_long *object, long operand);
long __ovld atomic_fetch_and_explicit(volatile atomic_long *object, long operand, memory_order order);
long __ovld atomic_fetch_and_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_and(volatile atomic_ulong *object, ulong operand);
ulong __ovld atomic_fetch_and_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
ulong __ovld atomic_fetch_and_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
long __ovld atomic_fetch_min(volatile atomic_long *object, long operand);
long __ovld atomic_fetch_min_explicit(volatile atomic_long *object, long operand, memory_order order);
long __ovld atomic_fetch_min_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_min(volatile atomic_ulong *object, ulong operand);
ulong __ovld atomic_fetch_min_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
ulong __ovld atomic_fetch_min_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_min(volatile atomic_ulong *object, long operand);
ulong __ovld atomic_fetch_min_explicit(volatile atomic_ulong *object, long operand, memory_order order);
ulong __ovld atomic_fetch_min_explicit(volatile atomic_ulong *object, long operand, memory_order order, memory_scope scope);
long __ovld atomic_fetch_max(volatile atomic_long *object, long operand);
long __ovld atomic_fetch_max_explicit(volatile atomic_long *object, long operand, memory_order order);
long __ovld atomic_fetch_max_explicit(volatile atomic_long *object, long operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_max(volatile atomic_ulong *object, ulong operand);
ulong __ovld atomic_fetch_max_explicit(volatile atomic_ulong *object, ulong operand, memory_order order);
ulong __ovld atomic_fetch_max_explicit(volatile atomic_ulong *object, ulong operand, memory_order order, memory_scope scope);
ulong __ovld atomic_fetch_max(volatile atomic_ulong *object, long operand);
ulong __ovld atomic_fetch_max_explicit(volatile atomic_ulong *object, long operand, memory_order order);
ulong __ovld atomic_fetch_max_explicit(volatile atomic_ulong *object, long operand, memory_order order, memory_scope scope);
#endif //defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
// OpenCL v2.0 s6.13.11.7.5:
// add/sub: atomic type argument can be uintptr_t/intptr_t, value type argument can be ptrdiff_t.
// or/xor/and/min/max: atomic type argument can be intptr_t/uintptr_t, value type argument can be intptr_t/uintptr_t.
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
uintptr_t __ovld atomic_fetch_add(volatile atomic_uintptr_t *object, ptrdiff_t operand);
uintptr_t __ovld atomic_fetch_add_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order);
uintptr_t __ovld atomic_fetch_add_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order, memory_scope scope);
uintptr_t __ovld atomic_fetch_sub(volatile atomic_uintptr_t *object, ptrdiff_t operand);
uintptr_t __ovld atomic_fetch_sub_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order);
uintptr_t __ovld atomic_fetch_sub_explicit(volatile atomic_uintptr_t *object, ptrdiff_t operand, memory_order order, memory_scope scope);
uintptr_t __ovld atomic_fetch_or(volatile atomic_uintptr_t *object, intptr_t operand);
uintptr_t __ovld atomic_fetch_or_explicit(volatile atomic_uintptr_t *object, intptr_t operand, memory_order order);
uintptr_t __ovld atomic_fetch_or_explicit(volatile atomic_uintptr_t *object, intptr_t operand, memory_order order, memory_scope scope);
uintptr_t __ovld atomic_fetch_xor(volatile atomic_uintptr_t *object, intptr_t operand);
uintptr_t __ovld atomic_fetch_xor_explicit(volatile atomic_uintptr_t *object, intptr_t operand, memory_order order);
uintptr_t __ovld atomic_fetch_xor_explicit(volatile atomic_uintptr_t *object, intptr_t operand, memory_order order, memory_scope scope);
uintptr_t __ovld atomic_fetch_and(volatile atomic_uintptr_t *object, intptr_t operand);
uintptr_t __ovld atomic_fetch_and_explicit(volatile atomic_uintptr_t *object, intptr_t operand, memory_order order);
uintptr_t __ovld atomic_fetch_and_explicit(volatile atomic_uintptr_t *object, intptr_t operand, memory_order order, memory_scope scope);
uintptr_t __ovld atomic_fetch_min(volatile atomic_uintptr_t *object, intptr_t opermax);
uintptr_t __ovld atomic_fetch_min_explicit(volatile atomic_uintptr_t *object, intptr_t opermax, memory_order minder);
uintptr_t __ovld atomic_fetch_min_explicit(volatile atomic_uintptr_t *object, intptr_t opermax, memory_order minder, memory_scope scope);
uintptr_t __ovld atomic_fetch_max(volatile atomic_uintptr_t *object, intptr_t opermax);
uintptr_t __ovld atomic_fetch_max_explicit(volatile atomic_uintptr_t *object, intptr_t opermax, memory_order minder);
uintptr_t __ovld atomic_fetch_max_explicit(volatile atomic_uintptr_t *object, intptr_t opermax, memory_order minder, memory_scope scope);
intptr_t __ovld atomic_fetch_or(volatile atomic_intptr_t *object, uintptr_t operand);
intptr_t __ovld atomic_fetch_or_explicit(volatile atomic_intptr_t *object, uintptr_t operand, memory_order order);
intptr_t __ovld atomic_fetch_or_explicit(volatile atomic_intptr_t *object, uintptr_t operand, memory_order order, memory_scope scope);
intptr_t __ovld atomic_fetch_xor(volatile atomic_intptr_t *object, uintptr_t operand);
intptr_t __ovld atomic_fetch_xor_explicit(volatile atomic_intptr_t *object, uintptr_t operand, memory_order order);
intptr_t __ovld atomic_fetch_xor_explicit(volatile atomic_intptr_t *object, uintptr_t operand, memory_order order, memory_scope scope);
intptr_t __ovld atomic_fetch_and(volatile atomic_intptr_t *object, uintptr_t operand);
intptr_t __ovld atomic_fetch_and_explicit(volatile atomic_intptr_t *object, uintptr_t operand, memory_order order);
intptr_t __ovld atomic_fetch_and_explicit(volatile atomic_intptr_t *object, uintptr_t operand, memory_order order, memory_scope scope);
intptr_t __ovld atomic_fetch_min(volatile atomic_intptr_t *object, uintptr_t opermax);
intptr_t __ovld atomic_fetch_min_explicit(volatile atomic_intptr_t *object, uintptr_t opermax, memory_order minder);
intptr_t __ovld atomic_fetch_min_explicit(volatile atomic_intptr_t *object, uintptr_t opermax, memory_order minder, memory_scope scope);
intptr_t __ovld atomic_fetch_max(volatile atomic_intptr_t *object, uintptr_t opermax);
intptr_t __ovld atomic_fetch_max_explicit(volatile atomic_intptr_t *object, uintptr_t opermax, memory_order minder);
intptr_t __ovld atomic_fetch_max_explicit(volatile atomic_intptr_t *object, uintptr_t opermax, memory_order minder, memory_scope scope);
#endif
// atomic_store()
void __ovld atomic_store(volatile atomic_int *object, int desired);
void __ovld atomic_store_explicit(volatile atomic_int *object, int desired, memory_order order);
void __ovld atomic_store_explicit(volatile atomic_int *object, int desired, memory_order order, memory_scope scope);
void __ovld atomic_store(volatile atomic_uint *object, uint desired);
void __ovld atomic_store_explicit(volatile atomic_uint *object, uint desired, memory_order order);
void __ovld atomic_store_explicit(volatile atomic_uint *object, uint desired, memory_order order, memory_scope scope);
void __ovld atomic_store(volatile atomic_float *object, float desired);
void __ovld atomic_store_explicit(volatile atomic_float *object, float desired, memory_order order);
void __ovld atomic_store_explicit(volatile atomic_float *object, float desired, memory_order order, memory_scope scope);
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
#ifdef cl_khr_fp64
void __ovld atomic_store(volatile atomic_double *object, double desired);
void __ovld atomic_store_explicit(volatile atomic_double *object, double desired, memory_order order);
void __ovld atomic_store_explicit(volatile atomic_double *object, double desired, memory_order order, memory_scope scope);
#endif //cl_khr_fp64
void __ovld atomic_store(volatile atomic_long *object, long desired);
void __ovld atomic_store_explicit(volatile atomic_long *object, long desired, memory_order order);
void __ovld atomic_store_explicit(volatile atomic_long *object, long desired, memory_order order, memory_scope scope);
void __ovld atomic_store(volatile atomic_ulong *object, ulong desired);
void __ovld atomic_store_explicit(volatile atomic_ulong *object, ulong desired, memory_order order);
void __ovld atomic_store_explicit(volatile atomic_ulong *object, ulong desired, memory_order order, memory_scope scope);
#endif
// atomic_load()
int __ovld atomic_load(volatile atomic_int *object);
int __ovld atomic_load_explicit(volatile atomic_int *object, memory_order order);
int __ovld atomic_load_explicit(volatile atomic_int *object, memory_order order, memory_scope scope);
uint __ovld atomic_load(volatile atomic_uint *object);
uint __ovld atomic_load_explicit(volatile atomic_uint *object, memory_order order);
uint __ovld atomic_load_explicit(volatile atomic_uint *object, memory_order order, memory_scope scope);
float __ovld atomic_load(volatile atomic_float *object);
float __ovld atomic_load_explicit(volatile atomic_float *object, memory_order order);
float __ovld atomic_load_explicit(volatile atomic_float *object, memory_order order, memory_scope scope);
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
#ifdef cl_khr_fp64
double __ovld atomic_load(volatile atomic_double *object);
double __ovld atomic_load_explicit(volatile atomic_double *object, memory_order order);
double __ovld atomic_load_explicit(volatile atomic_double *object, memory_order order, memory_scope scope);
#endif //cl_khr_fp64
long __ovld atomic_load(volatile atomic_long *object);
long __ovld atomic_load_explicit(volatile atomic_long *object, memory_order order);
long __ovld atomic_load_explicit(volatile atomic_long *object, memory_order order, memory_scope scope);
ulong __ovld atomic_load(volatile atomic_ulong *object);
ulong __ovld atomic_load_explicit(volatile atomic_ulong *object, memory_order order);
ulong __ovld atomic_load_explicit(volatile atomic_ulong *object, memory_order order, memory_scope scope);
#endif
// atomic_exchange()
int __ovld atomic_exchange(volatile atomic_int *object, int desired);
int __ovld atomic_exchange_explicit(volatile atomic_int *object, int desired, memory_order order);
int __ovld atomic_exchange_explicit(volatile atomic_int *object, int desired, memory_order order, memory_scope scope);
uint __ovld atomic_exchange(volatile atomic_uint *object, uint desired);
uint __ovld atomic_exchange_explicit(volatile atomic_uint *object, uint desired, memory_order order);
uint __ovld atomic_exchange_explicit(volatile atomic_uint *object, uint desired, memory_order order, memory_scope scope);
float __ovld atomic_exchange(volatile atomic_float *object, float desired);
float __ovld atomic_exchange_explicit(volatile atomic_float *object, float desired, memory_order order);
float __ovld atomic_exchange_explicit(volatile atomic_float *object, float desired, memory_order order, memory_scope scope);
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
#ifdef cl_khr_fp64
double __ovld atomic_exchange(volatile atomic_double *object, double desired);
double __ovld atomic_exchange_explicit(volatile atomic_double *object, double desired, memory_order order);
double __ovld atomic_exchange_explicit(volatile atomic_double *object, double desired, memory_order order, memory_scope scope);
#endif //cl_khr_fp64
long __ovld atomic_exchange(volatile atomic_long *object, long desired);
long __ovld atomic_exchange_explicit(volatile atomic_long *object, long desired, memory_order order);
long __ovld atomic_exchange_explicit(volatile atomic_long *object, long desired, memory_order order, memory_scope scope);
ulong __ovld atomic_exchange(volatile atomic_ulong *object, ulong desired);
ulong __ovld atomic_exchange_explicit(volatile atomic_ulong *object, ulong desired, memory_order order);
ulong __ovld atomic_exchange_explicit(volatile atomic_ulong *object, ulong desired, memory_order order, memory_scope scope);
#endif
// atomic_compare_exchange_strong() and atomic_compare_exchange_weak()
bool __ovld atomic_compare_exchange_strong(volatile atomic_int *object, int *expected, int desired);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_int *object, int *expected,
int desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_int *object, int *expected,
int desired, memory_order success, memory_order failure, memory_scope scope);
bool __ovld atomic_compare_exchange_strong(volatile atomic_uint *object, uint *expected, uint desired);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_uint *object, uint *expected,
uint desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_uint *object, uint *expected,
uint desired, memory_order success, memory_order failure, memory_scope scope);
bool __ovld atomic_compare_exchange_weak(volatile atomic_int *object, int *expected, int desired);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_int *object, int *expected,
int desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_int *object, int *expected,
int desired, memory_order success, memory_order failure, memory_scope scope);
bool __ovld atomic_compare_exchange_weak(volatile atomic_uint *object, uint *expected, uint desired);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_uint *object, uint *expected,
uint desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_uint *object, uint *expected,
uint desired, memory_order success, memory_order failure, memory_scope scope);
bool __ovld atomic_compare_exchange_strong(volatile atomic_float *object, float *expected, float desired);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_float *object, float *expected,
float desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_float *object, float *expected,
float desired, memory_order success, memory_order failure, memory_scope scope);
bool __ovld atomic_compare_exchange_weak(volatile atomic_float *object, float *expected, float desired);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_float *object, float *expected,
float desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_float *object, float *expected,
float desired, memory_order success, memory_order failure, memory_scope scope);
#if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics)
#ifdef cl_khr_fp64
bool __ovld atomic_compare_exchange_strong(volatile atomic_double *object, double *expected, double desired);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_double *object, double *expected,
double desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_double *object, double *expected,
double desired, memory_order success, memory_order failure, memory_scope scope);
bool __ovld atomic_compare_exchange_weak(volatile atomic_double *object, double *expected, double desired);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_double *object, double *expected,
double desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_double *object, double *expected,
double desired, memory_order success, memory_order failure, memory_scope scope);
#endif //cl_khr_fp64
bool __ovld atomic_compare_exchange_strong(volatile atomic_long *object, long *expected, long desired);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_long *object, long *expected,
long desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_long *object, long *expected,
long desired, memory_order success, memory_order failure, memory_scope scope);
bool __ovld atomic_compare_exchange_weak(volatile atomic_long *object, long *expected, long desired);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_long *object, long *expected,
long desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_long *object, long *expected,
long desired, memory_order success, memory_order failure, memory_scope scope);
bool __ovld atomic_compare_exchange_strong(volatile atomic_ulong *object, ulong *expected, ulong desired);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_ulong *object, ulong *expected,
ulong desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_strong_explicit(volatile atomic_ulong *object, ulong *expected,
ulong desired, memory_order success, memory_order failure, memory_scope scope);
bool __ovld atomic_compare_exchange_weak(volatile atomic_ulong *object, ulong *expected, ulong desired);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_ulong *object, ulong *expected,
ulong desired, memory_order success, memory_order failure);
bool __ovld atomic_compare_exchange_weak_explicit(volatile atomic_ulong *object, ulong *expected,
ulong desired, memory_order success, memory_order failure, memory_scope scope);
#endif
// atomic_flag_test_and_set() and atomic_flag_clear()
bool __ovld atomic_flag_test_and_set(volatile atomic_flag *object);
bool __ovld atomic_flag_test_and_set_explicit(volatile atomic_flag *object, memory_order order);
bool __ovld atomic_flag_test_and_set_explicit(volatile atomic_flag *object, memory_order order, memory_scope scope);
void __ovld atomic_flag_clear(volatile atomic_flag *object);
void __ovld atomic_flag_clear_explicit(volatile atomic_flag *object, memory_order order);
void __ovld atomic_flag_clear_explicit(volatile atomic_flag *object, memory_order order, memory_scope scope);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
// OpenCL v1.1 s6.11.12, v1.2 s6.12.12, v2.0 s6.13.12 - Miscellaneous Vector Functions
/**
* The shuffle and shuffle2 built-in functions construct
* a permutation of elements from one or two input
* vectors respectively that are of the same type,
* returning a vector with the same element type as the
* input and length that is the same as the shuffle mask.
* The size of each element in the mask must match the
* size of each element in the result. For shuffle, only
* the ilogb(2m-1) least significant bits of each mask
* element are considered. For shuffle2, only the
* ilogb(2m-1)+1 least significant bits of each mask
* element are considered. Other bits in the mask shall
* be ignored.
* The elements of the input vectors are numbered from
* left to right across one or both of the vectors. For this
* purpose, the number of elements in a vector is given
* by vec_step(gentypem). The shuffle mask operand
* specifies, for each element of the result vector, which
* element of the one or two input vectors the result
* element gets.
* Examples:
* uint4 mask = (uint4)(3, 2,
* 1, 0);
* float4 a;
* float4 r = shuffle(a, mask);
* // r.s0123 = a.wzyx
* uint8 mask = (uint8)(0, 1, 2, 3,
* 4, 5, 6, 7);
* float4 a, b;
* float8 r = shuffle2(a, b, mask);
* // r.s0123 = a.xyzw
* // r.s4567 = b.xyzw
* uint4 mask;
* float8 a;
* float4 b;
* b = shuffle(a, mask);
* Examples that are not valid are:
* uint8 mask;
* short16 a;
* short8 b;
* b = shuffle(a, mask); <- not valid
*/
char2 __ovld __cnfn shuffle(char2 x, uchar2 mask);
char2 __ovld __cnfn shuffle(char4 x, uchar2 mask);
char2 __ovld __cnfn shuffle(char8 x, uchar2 mask);
char2 __ovld __cnfn shuffle(char16 x, uchar2 mask);
uchar2 __ovld __cnfn shuffle(uchar2 x, uchar2 mask);
uchar2 __ovld __cnfn shuffle(uchar4 x, uchar2 mask);
uchar2 __ovld __cnfn shuffle(uchar8 x, uchar2 mask);
uchar2 __ovld __cnfn shuffle(uchar16 x, uchar2 mask);
short2 __ovld __cnfn shuffle(short2 x, ushort2 mask);
short2 __ovld __cnfn shuffle(short4 x, ushort2 mask);
short2 __ovld __cnfn shuffle(short8 x, ushort2 mask);
short2 __ovld __cnfn shuffle(short16 x, ushort2 mask);
ushort2 __ovld __cnfn shuffle(ushort2 x, ushort2 mask);
ushort2 __ovld __cnfn shuffle(ushort4 x, ushort2 mask);
ushort2 __ovld __cnfn shuffle(ushort8 x, ushort2 mask);
ushort2 __ovld __cnfn shuffle(ushort16 x, ushort2 mask);
int2 __ovld __cnfn shuffle(int2 x, uint2 mask);
int2 __ovld __cnfn shuffle(int4 x, uint2 mask);
int2 __ovld __cnfn shuffle(int8 x, uint2 mask);
int2 __ovld __cnfn shuffle(int16 x, uint2 mask);
uint2 __ovld __cnfn shuffle(uint2 x, uint2 mask);
uint2 __ovld __cnfn shuffle(uint4 x, uint2 mask);
uint2 __ovld __cnfn shuffle(uint8 x, uint2 mask);
uint2 __ovld __cnfn shuffle(uint16 x, uint2 mask);
long2 __ovld __cnfn shuffle(long2 x, ulong2 mask);
long2 __ovld __cnfn shuffle(long4 x, ulong2 mask);
long2 __ovld __cnfn shuffle(long8 x, ulong2 mask);
long2 __ovld __cnfn shuffle(long16 x, ulong2 mask);
ulong2 __ovld __cnfn shuffle(ulong2 x, ulong2 mask);
ulong2 __ovld __cnfn shuffle(ulong4 x, ulong2 mask);
ulong2 __ovld __cnfn shuffle(ulong8 x, ulong2 mask);
ulong2 __ovld __cnfn shuffle(ulong16 x, ulong2 mask);
float2 __ovld __cnfn shuffle(float2 x, uint2 mask);
float2 __ovld __cnfn shuffle(float4 x, uint2 mask);
float2 __ovld __cnfn shuffle(float8 x, uint2 mask);
float2 __ovld __cnfn shuffle(float16 x, uint2 mask);
char4 __ovld __cnfn shuffle(char2 x, uchar4 mask);
char4 __ovld __cnfn shuffle(char4 x, uchar4 mask);
char4 __ovld __cnfn shuffle(char8 x, uchar4 mask);
char4 __ovld __cnfn shuffle(char16 x, uchar4 mask);
uchar4 __ovld __cnfn shuffle(uchar2 x, uchar4 mask);
uchar4 __ovld __cnfn shuffle(uchar4 x, uchar4 mask);
uchar4 __ovld __cnfn shuffle(uchar8 x, uchar4 mask);
uchar4 __ovld __cnfn shuffle(uchar16 x, uchar4 mask);
short4 __ovld __cnfn shuffle(short2 x, ushort4 mask);
short4 __ovld __cnfn shuffle(short4 x, ushort4 mask);
short4 __ovld __cnfn shuffle(short8 x, ushort4 mask);
short4 __ovld __cnfn shuffle(short16 x, ushort4 mask);
ushort4 __ovld __cnfn shuffle(ushort2 x, ushort4 mask);
ushort4 __ovld __cnfn shuffle(ushort4 x, ushort4 mask);
ushort4 __ovld __cnfn shuffle(ushort8 x, ushort4 mask);
ushort4 __ovld __cnfn shuffle(ushort16 x, ushort4 mask);
int4 __ovld __cnfn shuffle(int2 x, uint4 mask);
int4 __ovld __cnfn shuffle(int4 x, uint4 mask);
int4 __ovld __cnfn shuffle(int8 x, uint4 mask);
int4 __ovld __cnfn shuffle(int16 x, uint4 mask);
uint4 __ovld __cnfn shuffle(uint2 x, uint4 mask);
uint4 __ovld __cnfn shuffle(uint4 x, uint4 mask);
uint4 __ovld __cnfn shuffle(uint8 x, uint4 mask);
uint4 __ovld __cnfn shuffle(uint16 x, uint4 mask);
long4 __ovld __cnfn shuffle(long2 x, ulong4 mask);
long4 __ovld __cnfn shuffle(long4 x, ulong4 mask);
long4 __ovld __cnfn shuffle(long8 x, ulong4 mask);
long4 __ovld __cnfn shuffle(long16 x, ulong4 mask);
ulong4 __ovld __cnfn shuffle(ulong2 x, ulong4 mask);
ulong4 __ovld __cnfn shuffle(ulong4 x, ulong4 mask);
ulong4 __ovld __cnfn shuffle(ulong8 x, ulong4 mask);
ulong4 __ovld __cnfn shuffle(ulong16 x, ulong4 mask);
float4 __ovld __cnfn shuffle(float2 x, uint4 mask);
float4 __ovld __cnfn shuffle(float4 x, uint4 mask);
float4 __ovld __cnfn shuffle(float8 x, uint4 mask);
float4 __ovld __cnfn shuffle(float16 x, uint4 mask);
char8 __ovld __cnfn shuffle(char2 x, uchar8 mask);
char8 __ovld __cnfn shuffle(char4 x, uchar8 mask);
char8 __ovld __cnfn shuffle(char8 x, uchar8 mask);
char8 __ovld __cnfn shuffle(char16 x, uchar8 mask);
uchar8 __ovld __cnfn shuffle(uchar2 x, uchar8 mask);
uchar8 __ovld __cnfn shuffle(uchar4 x, uchar8 mask);
uchar8 __ovld __cnfn shuffle(uchar8 x, uchar8 mask);
uchar8 __ovld __cnfn shuffle(uchar16 x, uchar8 mask);
short8 __ovld __cnfn shuffle(short2 x, ushort8 mask);
short8 __ovld __cnfn shuffle(short4 x, ushort8 mask);
short8 __ovld __cnfn shuffle(short8 x, ushort8 mask);
short8 __ovld __cnfn shuffle(short16 x, ushort8 mask);
ushort8 __ovld __cnfn shuffle(ushort2 x, ushort8 mask);
ushort8 __ovld __cnfn shuffle(ushort4 x, ushort8 mask);
ushort8 __ovld __cnfn shuffle(ushort8 x, ushort8 mask);
ushort8 __ovld __cnfn shuffle(ushort16 x, ushort8 mask);
int8 __ovld __cnfn shuffle(int2 x, uint8 mask);
int8 __ovld __cnfn shuffle(int4 x, uint8 mask);
int8 __ovld __cnfn shuffle(int8 x, uint8 mask);
int8 __ovld __cnfn shuffle(int16 x, uint8 mask);
uint8 __ovld __cnfn shuffle(uint2 x, uint8 mask);
uint8 __ovld __cnfn shuffle(uint4 x, uint8 mask);
uint8 __ovld __cnfn shuffle(uint8 x, uint8 mask);
uint8 __ovld __cnfn shuffle(uint16 x, uint8 mask);
long8 __ovld __cnfn shuffle(long2 x, ulong8 mask);
long8 __ovld __cnfn shuffle(long4 x, ulong8 mask);
long8 __ovld __cnfn shuffle(long8 x, ulong8 mask);
long8 __ovld __cnfn shuffle(long16 x, ulong8 mask);
ulong8 __ovld __cnfn shuffle(ulong2 x, ulong8 mask);
ulong8 __ovld __cnfn shuffle(ulong4 x, ulong8 mask);
ulong8 __ovld __cnfn shuffle(ulong8 x, ulong8 mask);
ulong8 __ovld __cnfn shuffle(ulong16 x, ulong8 mask);
float8 __ovld __cnfn shuffle(float2 x, uint8 mask);
float8 __ovld __cnfn shuffle(float4 x, uint8 mask);
float8 __ovld __cnfn shuffle(float8 x, uint8 mask);
float8 __ovld __cnfn shuffle(float16 x, uint8 mask);
char16 __ovld __cnfn shuffle(char2 x, uchar16 mask);
char16 __ovld __cnfn shuffle(char4 x, uchar16 mask);
char16 __ovld __cnfn shuffle(char8 x, uchar16 mask);
char16 __ovld __cnfn shuffle(char16 x, uchar16 mask);
uchar16 __ovld __cnfn shuffle(uchar2 x, uchar16 mask);
uchar16 __ovld __cnfn shuffle(uchar4 x, uchar16 mask);
uchar16 __ovld __cnfn shuffle(uchar8 x, uchar16 mask);
uchar16 __ovld __cnfn shuffle(uchar16 x, uchar16 mask);
short16 __ovld __cnfn shuffle(short2 x, ushort16 mask);
short16 __ovld __cnfn shuffle(short4 x, ushort16 mask);
short16 __ovld __cnfn shuffle(short8 x, ushort16 mask);
short16 __ovld __cnfn shuffle(short16 x, ushort16 mask);
ushort16 __ovld __cnfn shuffle(ushort2 x, ushort16 mask);
ushort16 __ovld __cnfn shuffle(ushort4 x, ushort16 mask);
ushort16 __ovld __cnfn shuffle(ushort8 x, ushort16 mask);
ushort16 __ovld __cnfn shuffle(ushort16 x, ushort16 mask);
int16 __ovld __cnfn shuffle(int2 x, uint16 mask);
int16 __ovld __cnfn shuffle(int4 x, uint16 mask);
int16 __ovld __cnfn shuffle(int8 x, uint16 mask);
int16 __ovld __cnfn shuffle(int16 x, uint16 mask);
uint16 __ovld __cnfn shuffle(uint2 x, uint16 mask);
uint16 __ovld __cnfn shuffle(uint4 x, uint16 mask);
uint16 __ovld __cnfn shuffle(uint8 x, uint16 mask);
uint16 __ovld __cnfn shuffle(uint16 x, uint16 mask);
long16 __ovld __cnfn shuffle(long2 x, ulong16 mask);
long16 __ovld __cnfn shuffle(long4 x, ulong16 mask);
long16 __ovld __cnfn shuffle(long8 x, ulong16 mask);
long16 __ovld __cnfn shuffle(long16 x, ulong16 mask);
ulong16 __ovld __cnfn shuffle(ulong2 x, ulong16 mask);
ulong16 __ovld __cnfn shuffle(ulong4 x, ulong16 mask);
ulong16 __ovld __cnfn shuffle(ulong8 x, ulong16 mask);
ulong16 __ovld __cnfn shuffle(ulong16 x, ulong16 mask);
float16 __ovld __cnfn shuffle(float2 x, uint16 mask);
float16 __ovld __cnfn shuffle(float4 x, uint16 mask);
float16 __ovld __cnfn shuffle(float8 x, uint16 mask);
float16 __ovld __cnfn shuffle(float16 x, uint16 mask);
#ifdef cl_khr_fp64
double2 __ovld __cnfn shuffle(double2 x, ulong2 mask);
double2 __ovld __cnfn shuffle(double4 x, ulong2 mask);
double2 __ovld __cnfn shuffle(double8 x, ulong2 mask);
double2 __ovld __cnfn shuffle(double16 x, ulong2 mask);
double4 __ovld __cnfn shuffle(double2 x, ulong4 mask);
double4 __ovld __cnfn shuffle(double4 x, ulong4 mask);
double4 __ovld __cnfn shuffle(double8 x, ulong4 mask);
double4 __ovld __cnfn shuffle(double16 x, ulong4 mask);
double8 __ovld __cnfn shuffle(double2 x, ulong8 mask);
double8 __ovld __cnfn shuffle(double4 x, ulong8 mask);
double8 __ovld __cnfn shuffle(double8 x, ulong8 mask);
double8 __ovld __cnfn shuffle(double16 x, ulong8 mask);
double16 __ovld __cnfn shuffle(double2 x, ulong16 mask);
double16 __ovld __cnfn shuffle(double4 x, ulong16 mask);
double16 __ovld __cnfn shuffle(double8 x, ulong16 mask);
double16 __ovld __cnfn shuffle(double16 x, ulong16 mask);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half2 __ovld __cnfn shuffle(half2 x, ushort2 mask);
half2 __ovld __cnfn shuffle(half4 x, ushort2 mask);
half2 __ovld __cnfn shuffle(half8 x, ushort2 mask);
half2 __ovld __cnfn shuffle(half16 x, ushort2 mask);
half4 __ovld __cnfn shuffle(half2 x, ushort4 mask);
half4 __ovld __cnfn shuffle(half4 x, ushort4 mask);
half4 __ovld __cnfn shuffle(half8 x, ushort4 mask);
half4 __ovld __cnfn shuffle(half16 x, ushort4 mask);
half8 __ovld __cnfn shuffle(half2 x, ushort8 mask);
half8 __ovld __cnfn shuffle(half4 x, ushort8 mask);
half8 __ovld __cnfn shuffle(half8 x, ushort8 mask);
half8 __ovld __cnfn shuffle(half16 x, ushort8 mask);
half16 __ovld __cnfn shuffle(half2 x, ushort16 mask);
half16 __ovld __cnfn shuffle(half4 x, ushort16 mask);
half16 __ovld __cnfn shuffle(half8 x, ushort16 mask);
half16 __ovld __cnfn shuffle(half16 x, ushort16 mask);
#endif //cl_khr_fp16
char2 __ovld __cnfn shuffle2(char2 x, char2 y, uchar2 mask);
char2 __ovld __cnfn shuffle2(char4 x, char4 y, uchar2 mask);
char2 __ovld __cnfn shuffle2(char8 x, char8 y, uchar2 mask);
char2 __ovld __cnfn shuffle2(char16 x, char16 y, uchar2 mask);
uchar2 __ovld __cnfn shuffle2(uchar2 x, uchar2 y, uchar2 mask);
uchar2 __ovld __cnfn shuffle2(uchar4 x, uchar4 y, uchar2 mask);
uchar2 __ovld __cnfn shuffle2(uchar8 x, uchar8 y, uchar2 mask);
uchar2 __ovld __cnfn shuffle2(uchar16 x, uchar16 y, uchar2 mask);
short2 __ovld __cnfn shuffle2(short2 x, short2 y, ushort2 mask);
short2 __ovld __cnfn shuffle2(short4 x, short4 y, ushort2 mask);
short2 __ovld __cnfn shuffle2(short8 x, short8 y, ushort2 mask);
short2 __ovld __cnfn shuffle2(short16 x, short16 y, ushort2 mask);
ushort2 __ovld __cnfn shuffle2(ushort2 x, ushort2 y, ushort2 mask);
ushort2 __ovld __cnfn shuffle2(ushort4 x, ushort4 y, ushort2 mask);
ushort2 __ovld __cnfn shuffle2(ushort8 x, ushort8 y, ushort2 mask);
ushort2 __ovld __cnfn shuffle2(ushort16 x, ushort16 y, ushort2 mask);
int2 __ovld __cnfn shuffle2(int2 x, int2 y, uint2 mask);
int2 __ovld __cnfn shuffle2(int4 x, int4 y, uint2 mask);
int2 __ovld __cnfn shuffle2(int8 x, int8 y, uint2 mask);
int2 __ovld __cnfn shuffle2(int16 x, int16 y, uint2 mask);
uint2 __ovld __cnfn shuffle2(uint2 x, uint2 y, uint2 mask);
uint2 __ovld __cnfn shuffle2(uint4 x, uint4 y, uint2 mask);
uint2 __ovld __cnfn shuffle2(uint8 x, uint8 y, uint2 mask);
uint2 __ovld __cnfn shuffle2(uint16 x, uint16 y, uint2 mask);
long2 __ovld __cnfn shuffle2(long2 x, long2 y, ulong2 mask);
long2 __ovld __cnfn shuffle2(long4 x, long4 y, ulong2 mask);
long2 __ovld __cnfn shuffle2(long8 x, long8 y, ulong2 mask);
long2 __ovld __cnfn shuffle2(long16 x, long16 y, ulong2 mask);
ulong2 __ovld __cnfn shuffle2(ulong2 x, ulong2 y, ulong2 mask);
ulong2 __ovld __cnfn shuffle2(ulong4 x, ulong4 y, ulong2 mask);
ulong2 __ovld __cnfn shuffle2(ulong8 x, ulong8 y, ulong2 mask);
ulong2 __ovld __cnfn shuffle2(ulong16 x, ulong16 y, ulong2 mask);
float2 __ovld __cnfn shuffle2(float2 x, float2 y, uint2 mask);
float2 __ovld __cnfn shuffle2(float4 x, float4 y, uint2 mask);
float2 __ovld __cnfn shuffle2(float8 x, float8 y, uint2 mask);
float2 __ovld __cnfn shuffle2(float16 x, float16 y, uint2 mask);
char4 __ovld __cnfn shuffle2(char2 x, char2 y, uchar4 mask);
char4 __ovld __cnfn shuffle2(char4 x, char4 y, uchar4 mask);
char4 __ovld __cnfn shuffle2(char8 x, char8 y, uchar4 mask);
char4 __ovld __cnfn shuffle2(char16 x, char16 y, uchar4 mask);
uchar4 __ovld __cnfn shuffle2(uchar2 x, uchar2 y, uchar4 mask);
uchar4 __ovld __cnfn shuffle2(uchar4 x, uchar4 y, uchar4 mask);
uchar4 __ovld __cnfn shuffle2(uchar8 x, uchar8 y, uchar4 mask);
uchar4 __ovld __cnfn shuffle2(uchar16 x, uchar16 y, uchar4 mask);
short4 __ovld __cnfn shuffle2(short2 x, short2 y, ushort4 mask);
short4 __ovld __cnfn shuffle2(short4 x, short4 y, ushort4 mask);
short4 __ovld __cnfn shuffle2(short8 x, short8 y, ushort4 mask);
short4 __ovld __cnfn shuffle2(short16 x, short16 y, ushort4 mask);
ushort4 __ovld __cnfn shuffle2(ushort2 x, ushort2 y, ushort4 mask);
ushort4 __ovld __cnfn shuffle2(ushort4 x, ushort4 y, ushort4 mask);
ushort4 __ovld __cnfn shuffle2(ushort8 x, ushort8 y, ushort4 mask);
ushort4 __ovld __cnfn shuffle2(ushort16 x, ushort16 y, ushort4 mask);
int4 __ovld __cnfn shuffle2(int2 x, int2 y, uint4 mask);
int4 __ovld __cnfn shuffle2(int4 x, int4 y, uint4 mask);
int4 __ovld __cnfn shuffle2(int8 x, int8 y, uint4 mask);
int4 __ovld __cnfn shuffle2(int16 x, int16 y, uint4 mask);
uint4 __ovld __cnfn shuffle2(uint2 x, uint2 y, uint4 mask);
uint4 __ovld __cnfn shuffle2(uint4 x, uint4 y, uint4 mask);
uint4 __ovld __cnfn shuffle2(uint8 x, uint8 y, uint4 mask);
uint4 __ovld __cnfn shuffle2(uint16 x, uint16 y, uint4 mask);
long4 __ovld __cnfn shuffle2(long2 x, long2 y, ulong4 mask);
long4 __ovld __cnfn shuffle2(long4 x, long4 y, ulong4 mask);
long4 __ovld __cnfn shuffle2(long8 x, long8 y, ulong4 mask);
long4 __ovld __cnfn shuffle2(long16 x, long16 y, ulong4 mask);
ulong4 __ovld __cnfn shuffle2(ulong2 x, ulong2 y, ulong4 mask);
ulong4 __ovld __cnfn shuffle2(ulong4 x, ulong4 y, ulong4 mask);
ulong4 __ovld __cnfn shuffle2(ulong8 x, ulong8 y, ulong4 mask);
ulong4 __ovld __cnfn shuffle2(ulong16 x, ulong16 y, ulong4 mask);
float4 __ovld __cnfn shuffle2(float2 x, float2 y, uint4 mask);
float4 __ovld __cnfn shuffle2(float4 x, float4 y, uint4 mask);
float4 __ovld __cnfn shuffle2(float8 x, float8 y, uint4 mask);
float4 __ovld __cnfn shuffle2(float16 x, float16 y, uint4 mask);
char8 __ovld __cnfn shuffle2(char2 x, char2 y, uchar8 mask);
char8 __ovld __cnfn shuffle2(char4 x, char4 y, uchar8 mask);
char8 __ovld __cnfn shuffle2(char8 x, char8 y, uchar8 mask);
char8 __ovld __cnfn shuffle2(char16 x, char16 y, uchar8 mask);
uchar8 __ovld __cnfn shuffle2(uchar2 x, uchar2 y, uchar8 mask);
uchar8 __ovld __cnfn shuffle2(uchar4 x, uchar4 y, uchar8 mask);
uchar8 __ovld __cnfn shuffle2(uchar8 x, uchar8 y, uchar8 mask);
uchar8 __ovld __cnfn shuffle2(uchar16 x, uchar16 y, uchar8 mask);
short8 __ovld __cnfn shuffle2(short2 x, short2 y, ushort8 mask);
short8 __ovld __cnfn shuffle2(short4 x, short4 y, ushort8 mask);
short8 __ovld __cnfn shuffle2(short8 x, short8 y, ushort8 mask);
short8 __ovld __cnfn shuffle2(short16 x, short16 y, ushort8 mask);
ushort8 __ovld __cnfn shuffle2(ushort2 x, ushort2 y, ushort8 mask);
ushort8 __ovld __cnfn shuffle2(ushort4 x, ushort4 y, ushort8 mask);
ushort8 __ovld __cnfn shuffle2(ushort8 x, ushort8 y, ushort8 mask);
ushort8 __ovld __cnfn shuffle2(ushort16 x, ushort16 y, ushort8 mask);
int8 __ovld __cnfn shuffle2(int2 x, int2 y, uint8 mask);
int8 __ovld __cnfn shuffle2(int4 x, int4 y, uint8 mask);
int8 __ovld __cnfn shuffle2(int8 x, int8 y, uint8 mask);
int8 __ovld __cnfn shuffle2(int16 x, int16 y, uint8 mask);
uint8 __ovld __cnfn shuffle2(uint2 x, uint2 y, uint8 mask);
uint8 __ovld __cnfn shuffle2(uint4 x, uint4 y, uint8 mask);
uint8 __ovld __cnfn shuffle2(uint8 x, uint8 y, uint8 mask);
uint8 __ovld __cnfn shuffle2(uint16 x, uint16 y, uint8 mask);
long8 __ovld __cnfn shuffle2(long2 x, long2 y, ulong8 mask);
long8 __ovld __cnfn shuffle2(long4 x, long4 y, ulong8 mask);
long8 __ovld __cnfn shuffle2(long8 x, long8 y, ulong8 mask);
long8 __ovld __cnfn shuffle2(long16 x, long16 y, ulong8 mask);
ulong8 __ovld __cnfn shuffle2(ulong2 x, ulong2 y, ulong8 mask);
ulong8 __ovld __cnfn shuffle2(ulong4 x, ulong4 y, ulong8 mask);
ulong8 __ovld __cnfn shuffle2(ulong8 x, ulong8 y, ulong8 mask);
ulong8 __ovld __cnfn shuffle2(ulong16 x, ulong16 y, ulong8 mask);
float8 __ovld __cnfn shuffle2(float2 x, float2 y, uint8 mask);
float8 __ovld __cnfn shuffle2(float4 x, float4 y, uint8 mask);
float8 __ovld __cnfn shuffle2(float8 x, float8 y, uint8 mask);
float8 __ovld __cnfn shuffle2(float16 x, float16 y, uint8 mask);
char16 __ovld __cnfn shuffle2(char2 x, char2 y, uchar16 mask);
char16 __ovld __cnfn shuffle2(char4 x, char4 y, uchar16 mask);
char16 __ovld __cnfn shuffle2(char8 x, char8 y, uchar16 mask);
char16 __ovld __cnfn shuffle2(char16 x, char16 y, uchar16 mask);
uchar16 __ovld __cnfn shuffle2(uchar2 x, uchar2 y, uchar16 mask);
uchar16 __ovld __cnfn shuffle2(uchar4 x, uchar4 y, uchar16 mask);
uchar16 __ovld __cnfn shuffle2(uchar8 x, uchar8 y, uchar16 mask);
uchar16 __ovld __cnfn shuffle2(uchar16 x, uchar16 y, uchar16 mask);
short16 __ovld __cnfn shuffle2(short2 x, short2 y, ushort16 mask);
short16 __ovld __cnfn shuffle2(short4 x, short4 y, ushort16 mask);
short16 __ovld __cnfn shuffle2(short8 x, short8 y, ushort16 mask);
short16 __ovld __cnfn shuffle2(short16 x, short16 y, ushort16 mask);
ushort16 __ovld __cnfn shuffle2(ushort2 x, ushort2 y, ushort16 mask);
ushort16 __ovld __cnfn shuffle2(ushort4 x, ushort4 y, ushort16 mask);
ushort16 __ovld __cnfn shuffle2(ushort8 x, ushort8 y, ushort16 mask);
ushort16 __ovld __cnfn shuffle2(ushort16 x, ushort16 y, ushort16 mask);
int16 __ovld __cnfn shuffle2(int2 x, int2 y, uint16 mask);
int16 __ovld __cnfn shuffle2(int4 x, int4 y, uint16 mask);
int16 __ovld __cnfn shuffle2(int8 x, int8 y, uint16 mask);
int16 __ovld __cnfn shuffle2(int16 x, int16 y, uint16 mask);
uint16 __ovld __cnfn shuffle2(uint2 x, uint2 y, uint16 mask);
uint16 __ovld __cnfn shuffle2(uint4 x, uint4 y, uint16 mask);
uint16 __ovld __cnfn shuffle2(uint8 x, uint8 y, uint16 mask);
uint16 __ovld __cnfn shuffle2(uint16 x, uint16 y, uint16 mask);
long16 __ovld __cnfn shuffle2(long2 x, long2 y, ulong16 mask);
long16 __ovld __cnfn shuffle2(long4 x, long4 y, ulong16 mask);
long16 __ovld __cnfn shuffle2(long8 x, long8 y, ulong16 mask);
long16 __ovld __cnfn shuffle2(long16 x, long16 y, ulong16 mask);
ulong16 __ovld __cnfn shuffle2(ulong2 x, ulong2 y, ulong16 mask);
ulong16 __ovld __cnfn shuffle2(ulong4 x, ulong4 y, ulong16 mask);
ulong16 __ovld __cnfn shuffle2(ulong8 x, ulong8 y, ulong16 mask);
ulong16 __ovld __cnfn shuffle2(ulong16 x, ulong16 y, ulong16 mask);
float16 __ovld __cnfn shuffle2(float2 x, float2 y, uint16 mask);
float16 __ovld __cnfn shuffle2(float4 x, float4 y, uint16 mask);
float16 __ovld __cnfn shuffle2(float8 x, float8 y, uint16 mask);
float16 __ovld __cnfn shuffle2(float16 x, float16 y, uint16 mask);
#ifdef cl_khr_fp64
double2 __ovld __cnfn shuffle2(double2 x, double2 y, ulong2 mask);
double2 __ovld __cnfn shuffle2(double4 x, double4 y, ulong2 mask);
double2 __ovld __cnfn shuffle2(double8 x, double8 y, ulong2 mask);
double2 __ovld __cnfn shuffle2(double16 x, double16 y, ulong2 mask);
double4 __ovld __cnfn shuffle2(double2 x, double2 y, ulong4 mask);
double4 __ovld __cnfn shuffle2(double4 x, double4 y, ulong4 mask);
double4 __ovld __cnfn shuffle2(double8 x, double8 y, ulong4 mask);
double4 __ovld __cnfn shuffle2(double16 x, double16 y, ulong4 mask);
double8 __ovld __cnfn shuffle2(double2 x, double2 y, ulong8 mask);
double8 __ovld __cnfn shuffle2(double4 x, double4 y, ulong8 mask);
double8 __ovld __cnfn shuffle2(double8 x, double8 y, ulong8 mask);
double8 __ovld __cnfn shuffle2(double16 x, double16 y, ulong8 mask);
double16 __ovld __cnfn shuffle2(double2 x, double2 y, ulong16 mask);
double16 __ovld __cnfn shuffle2(double4 x, double4 y, ulong16 mask);
double16 __ovld __cnfn shuffle2(double8 x, double8 y, ulong16 mask);
double16 __ovld __cnfn shuffle2(double16 x, double16 y, ulong16 mask);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half2 __ovld __cnfn shuffle2(half2 x, half2 y, ushort2 mask);
half2 __ovld __cnfn shuffle2(half4 x, half4 y, ushort2 mask);
half2 __ovld __cnfn shuffle2(half8 x, half8 y, ushort2 mask);
half2 __ovld __cnfn shuffle2(half16 x, half16 y, ushort2 mask);
half4 __ovld __cnfn shuffle2(half2 x, half2 y, ushort4 mask);
half4 __ovld __cnfn shuffle2(half4 x, half4 y, ushort4 mask);
half4 __ovld __cnfn shuffle2(half8 x, half8 y, ushort4 mask);
half4 __ovld __cnfn shuffle2(half16 x, half16 y, ushort4 mask);
half8 __ovld __cnfn shuffle2(half2 x, half2 y, ushort8 mask);
half8 __ovld __cnfn shuffle2(half4 x, half4 y, ushort8 mask);
half8 __ovld __cnfn shuffle2(half8 x, half8 y, ushort8 mask);
half8 __ovld __cnfn shuffle2(half16 x, half16 y, ushort8 mask);
half16 __ovld __cnfn shuffle2(half2 x, half2 y, ushort16 mask);
half16 __ovld __cnfn shuffle2(half4 x, half4 y, ushort16 mask);
half16 __ovld __cnfn shuffle2(half8 x, half8 y, ushort16 mask);
half16 __ovld __cnfn shuffle2(half16 x, half16 y, ushort16 mask);
#endif //cl_khr_fp16
#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
// OpenCL v1.2 s6.12.13, v2.0 s6.13.13 - printf
-int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
+int printf(__constant const char* st, ...);
#endif
// OpenCL v1.1 s6.11.3, v1.2 s6.12.14, v2.0 s6.13.14 - Image Read and Write Functions
// These values need to match the runtime equivalent
//
// Addressing Mode.
//
#define CLK_ADDRESS_NONE 0
#define CLK_ADDRESS_CLAMP_TO_EDGE 2
#define CLK_ADDRESS_CLAMP 4
#define CLK_ADDRESS_REPEAT 6
#define CLK_ADDRESS_MIRRORED_REPEAT 8
//
// Coordination Normalization
//
#define CLK_NORMALIZED_COORDS_FALSE 0
#define CLK_NORMALIZED_COORDS_TRUE 1
//
// Filtering Mode.
//
#define CLK_FILTER_NEAREST 0x10
#define CLK_FILTER_LINEAR 0x20
#ifdef cl_khr_gl_msaa_sharing
#pragma OPENCL EXTENSION cl_khr_gl_msaa_sharing : enable
#endif //cl_khr_gl_msaa_sharing
/**
* Use the coordinate (coord.xy) to do an element lookup in
* the 2D image object specified by image.
*
* Use the coordinate (coord.x, coord.y, coord.z) to do
* an element lookup in the 3D image object specified
* by image. coord.w is ignored.
*
* Use the coordinate (coord.z) to index into the
* 2D image array object specified by image_array
* and (coord.x, coord.y) to do an element lookup in
* the 2D image object specified by image.
*
* Use the coordinate (x) to do an element lookup in
* the 1D image object specified by image.
*
* Use the coordinate (coord.y) to index into the
* 1D image array object specified by image_array
* and (coord.x) to do an element lookup in
* the 1D image object specified by image.
*
* Use the coordinate (cood.xy) and sample to do an
* element lookup in the 2D multi-sample image specified
* by image.
*
* Use coord.xy and sample to do an element
* lookup in the 2D multi-sample image layer
* identified by index coord.z in the 2D multi-sample
* image array specified by image.
*
* For mipmap images, use the mip-level specified by
* the Level-of-Detail (lod) or use gradients for LOD
* computation.
*
* read_imagef returns floating-point values in the
* range [0.0 ... 1.0] for image objects created with
* image_channel_data_type set to one of the predefined
* packed formats or CL_UNORM_INT8, or
* CL_UNORM_INT16.
*
* read_imagef returns floating-point values in the
* range [-1.0 ... 1.0] for image objects created with
* image_channel_data_type set to CL_SNORM_INT8,
* or CL_SNORM_INT16.
*
* read_imagef returns floating-point values for image
* objects created with image_channel_data_type set to
* CL_HALF_FLOAT or CL_FLOAT.
*
* read_imagei and read_imageui return
* unnormalized signed integer and unsigned integer
* values respectively. Each channel will be stored in a
* 32-bit integer.
*
* read_imagei can only be used with image objects
* created with image_channel_data_type set to one of
* the following values:
* CL_SIGNED_INT8,
* CL_SIGNED_INT16 and
* CL_SIGNED_INT32.
* If the image_channel_data_type is not one of the
* above values, the values returned by read_imagei
* are undefined.
*
* read_imageui can only be used with image objects
* created with image_channel_data_type set to one of
* the following values:
* CL_UNSIGNED_INT8,
* CL_UNSIGNED_INT16 and
* CL_UNSIGNED_INT32.
* If the image_channel_data_type is not one of the
* above values, the values returned by read_imageui
* are undefined.
*
* The read_image{i|ui} calls support a nearest filter
* only. The filter_mode specified in sampler
* must be set to CLK_FILTER_NEAREST; otherwise
* the values returned are undefined.
* The read_image{f|i|ui} calls that take
* integer coordinates must use a sampler with
* normalized coordinates set to
* CLK_NORMALIZED_COORDS_FALSE and
* addressing mode set to
* CLK_ADDRESS_CLAMP_TO_EDGE,
* CLK_ADDRESS_CLAMP or CLK_ADDRESS_NONE;
* otherwise the values returned are undefined.
*
* Values returned by read_imagef for image objects
* with image_channel_data_type values not specified
* in the description above are undefined.
*/
float4 __purefn __ovld read_imagef(read_only image2d_t image, sampler_t sampler, int2 coord);
float4 __purefn __ovld read_imagef(read_only image2d_t image, sampler_t sampler, float2 coord);
int4 __purefn __ovld read_imagei(read_only image2d_t image, sampler_t sampler, int2 coord);
int4 __purefn __ovld read_imagei(read_only image2d_t image, sampler_t sampler, float2 coord);
uint4 __purefn __ovld read_imageui(read_only image2d_t image, sampler_t sampler, int2 coord);
uint4 __purefn __ovld read_imageui(read_only image2d_t image, sampler_t sampler, float2 coord);
float4 __purefn __ovld read_imagef(read_only image3d_t image, sampler_t sampler, int4 coord);
float4 __purefn __ovld read_imagef(read_only image3d_t image, sampler_t sampler, float4 coord);
int4 __purefn __ovld read_imagei(read_only image3d_t image, sampler_t sampler, int4 coord);
int4 __purefn __ovld read_imagei(read_only image3d_t image, sampler_t sampler, float4 coord);
uint4 __purefn __ovld read_imageui(read_only image3d_t image, sampler_t sampler, int4 coord);
uint4 __purefn __ovld read_imageui(read_only image3d_t image, sampler_t sampler, float4 coord);
#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
float4 __purefn __ovld read_imagef(read_only image2d_array_t image_array, sampler_t sampler, int4 coord);
float4 __purefn __ovld read_imagef(read_only image2d_array_t image_array, sampler_t sampler, float4 coord);
int4 __purefn __ovld read_imagei(read_only image2d_array_t image_array, sampler_t sampler, int4 coord);
int4 __purefn __ovld read_imagei(read_only image2d_array_t image_array, sampler_t sampler, float4 coord);
uint4 __purefn __ovld read_imageui(read_only image2d_array_t image_array, sampler_t sampler, int4 coord);
uint4 __purefn __ovld read_imageui(read_only image2d_array_t image_array, sampler_t sampler, float4 coord);
#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2
float4 __purefn __ovld read_imagef(read_only image1d_t image, sampler_t sampler, int coord);
float4 __purefn __ovld read_imagef(read_only image1d_t image, sampler_t sampler, float coord);
int4 __purefn __ovld read_imagei(read_only image1d_t image, sampler_t sampler, int coord);
int4 __purefn __ovld read_imagei(read_only image1d_t image, sampler_t sampler, float coord);
uint4 __purefn __ovld read_imageui(read_only image1d_t image, sampler_t sampler, int coord);
uint4 __purefn __ovld read_imageui(read_only image1d_t image, sampler_t sampler, float coord);
#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
float4 __purefn __ovld read_imagef(read_only image1d_array_t image_array, sampler_t sampler, int2 coord);
float4 __purefn __ovld read_imagef(read_only image1d_array_t image_array, sampler_t sampler, float2 coord);
int4 __purefn __ovld read_imagei(read_only image1d_array_t image_array, sampler_t sampler, int2 coord);
int4 __purefn __ovld read_imagei(read_only image1d_array_t image_array, sampler_t sampler, float2 coord);
uint4 __purefn __ovld read_imageui(read_only image1d_array_t image_array, sampler_t sampler, int2 coord);
uint4 __purefn __ovld read_imageui(read_only image1d_array_t image_array, sampler_t sampler, float2 coord);
#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2
#ifdef cl_khr_depth_images
float __purefn __ovld read_imagef(read_only image2d_depth_t image, sampler_t sampler, float2 coord);
float __purefn __ovld read_imagef(read_only image2d_depth_t image, sampler_t sampler, int2 coord);
float __purefn __ovld read_imagef(read_only image2d_array_depth_t image, sampler_t sampler, float4 coord);
float __purefn __ovld read_imagef(read_only image2d_array_depth_t image, sampler_t sampler, int4 coord);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
float4 __purefn __ovld read_imagef(read_only image2d_msaa_t image, int2 coord, int sample);
int4 __purefn __ovld read_imagei(read_only image2d_msaa_t image, int2 coord, int sample);
uint4 __purefn __ovld read_imageui(read_only image2d_msaa_t image, int2 coord, int sample);
float __purefn __ovld read_imagef(read_only image2d_msaa_depth_t image, int2 coord, int sample);
float4 __purefn __ovld read_imagef(read_only image2d_array_msaa_t image, int4 coord, int sample);
int4 __purefn __ovld read_imagei(read_only image2d_array_msaa_t image, int4 coord, int sample);
uint4 __purefn __ovld read_imageui(read_only image2d_array_msaa_t image, int4 coord, int sample);
float __purefn __ovld read_imagef(read_only image2d_array_msaa_depth_t image, int4 coord, int sample);
#endif //cl_khr_gl_msaa_sharing
// OpenCL Extension v2.0 s9.18 - Mipmaps
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
#ifdef cl_khr_mipmap_image
float4 __purefn __ovld read_imagef(read_only image1d_t image, sampler_t sampler, float coord, float lod);
int4 __purefn __ovld read_imagei(read_only image1d_t image, sampler_t sampler, float coord, float lod);
uint4 __purefn __ovld read_imageui(read_only image1d_t image, sampler_t sampler, float coord, float lod);
float4 __purefn __ovld read_imagef(read_only image1d_array_t image_array, sampler_t sampler, float2 coord, float lod);
int4 __purefn __ovld read_imagei(read_only image1d_array_t image_array, sampler_t sampler, float2 coord, float lod);
uint4 __purefn __ovld read_imageui(read_only image1d_array_t image_array, sampler_t sampler, float2 coord, float lod);
float4 __purefn __ovld read_imagef(read_only image2d_t image, sampler_t sampler, float2 coord, float lod);
int4 __purefn __ovld read_imagei(read_only image2d_t image, sampler_t sampler, float2 coord, float lod);
uint4 __purefn __ovld read_imageui(read_only image2d_t image, sampler_t sampler, float2 coord, float lod);
float __purefn __ovld read_imagef(read_only image2d_depth_t image, sampler_t sampler, float2 coord, float lod);
float4 __purefn __ovld read_imagef(read_only image2d_array_t image_array, sampler_t sampler, float4 coord, float lod);
int4 __purefn __ovld read_imagei(read_only image2d_array_t image_array, sampler_t sampler, float4 coord, float lod);
uint4 __purefn __ovld read_imageui(read_only image2d_array_t image_array, sampler_t sampler, float4 coord, float lod);
float __purefn __ovld read_imagef(read_only image2d_array_depth_t image, sampler_t sampler, float4 coord, float lod);
float4 __purefn __ovld read_imagef(read_only image3d_t image, sampler_t sampler, float4 coord, float lod);
int4 __purefn __ovld read_imagei(read_only image3d_t image, sampler_t sampler, float4 coord, float lod);
uint4 __purefn __ovld read_imageui(read_only image3d_t image, sampler_t sampler, float4 coord, float lod);
float4 __purefn __ovld read_imagef(read_only image1d_t image, sampler_t sampler, float coord, float gradientX, float gradientY);
int4 __purefn __ovld read_imagei(read_only image1d_t image, sampler_t sampler, float coord, float gradientX, float gradientY);
uint4 __purefn __ovld read_imageui(read_only image1d_t image, sampler_t sampler, float coord, float gradientX, float gradientY);
float4 __purefn __ovld read_imagef(read_only image1d_array_t image_array, sampler_t sampler, float2 coord, float gradientX, float gradientY);
int4 __purefn __ovld read_imagei(read_only image1d_array_t image_array, sampler_t sampler, float2 coord, float gradientX, float gradientY);
uint4 __purefn __ovld read_imageui(read_only image1d_array_t image_array, sampler_t sampler, float2 coord, float gradientX, float gradientY);
float4 __purefn __ovld read_imagef(read_only image2d_t image, sampler_t sampler, float2 coord, float2 gradientX, float2 gradientY);
int4 __purefn __ovld read_imagei(read_only image2d_t image, sampler_t sampler, float2 coord, float2 gradientX, float2 gradientY);
uint4 __purefn __ovld read_imageui(read_only image2d_t image, sampler_t sampler, float2 coord, float2 gradientX, float2 gradientY);
float __purefn __ovld read_imagef(read_only image2d_depth_t image, sampler_t sampler, float2 coord, float2 gradientX, float2 gradientY);
float4 __purefn __ovld read_imagef(read_only image2d_array_t image_array, sampler_t sampler, float4 coord, float2 gradientX, float2 gradientY);
int4 __purefn __ovld read_imagei(read_only image2d_array_t image_array, sampler_t sampler, float4 coord, float2 gradientX, float2 gradientY);
uint4 __purefn __ovld read_imageui(read_only image2d_array_t image_array, sampler_t sampler, float4 coord, float2 gradientX, float2 gradientY);
float __purefn __ovld read_imagef(read_only image2d_array_depth_t image, sampler_t sampler, float4 coord, float2 gradientX, float2 gradientY);
float4 __purefn __ovld read_imagef(read_only image3d_t image, sampler_t sampler, float4 coord, float4 gradientX, float4 gradientY);
int4 __purefn __ovld read_imagei(read_only image3d_t image, sampler_t sampler, float4 coord, float4 gradientX, float4 gradientY);
uint4 __purefn __ovld read_imageui(read_only image3d_t image, sampler_t sampler, float4 coord, float4 gradientX, float4 gradientY);
float4 __purefn __ovld read_imagef(read_only image1d_t image, sampler_t sampler, float coord, float lod);
int4 __purefn __ovld read_imagei(read_only image1d_t image, sampler_t sampler, float coord, float lod);
uint4 __purefn __ovld read_imageui(read_only image1d_t image, sampler_t sampler, float coord, float lod);
float4 __purefn __ovld read_imagef(read_only image1d_array_t image_array, sampler_t sampler, float2 coord, float lod);
int4 __purefn __ovld read_imagei(read_only image1d_array_t image_array, sampler_t sampler, float2 coord, float lod);
uint4 __purefn __ovld read_imageui(read_only image1d_array_t image_array, sampler_t sampler, float2 coord, float lod);
float4 __purefn __ovld read_imagef(read_only image2d_t image, sampler_t sampler, float2 coord, float lod);
int4 __purefn __ovld read_imagei(read_only image2d_t image, sampler_t sampler, float2 coord, float lod);
uint4 __purefn __ovld read_imageui(read_only image2d_t image, sampler_t sampler, float2 coord, float lod);
float __purefn __ovld read_imagef(read_only image2d_depth_t image, sampler_t sampler, float2 coord, float lod);
float4 __purefn __ovld read_imagef(read_only image2d_array_t image_array, sampler_t sampler, float4 coord, float lod);
int4 __purefn __ovld read_imagei(read_only image2d_array_t image_array, sampler_t sampler, float4 coord, float lod);
uint4 __purefn __ovld read_imageui(read_only image2d_array_t image_array, sampler_t sampler, float4 coord, float lod);
float __purefn __ovld read_imagef(read_only image2d_array_depth_t image, sampler_t sampler, float4 coord, float lod);
float4 __purefn __ovld read_imagef(read_only image3d_t image, sampler_t sampler, float4 coord, float lod);
int4 __purefn __ovld read_imagei(read_only image3d_t image, sampler_t sampler, float4 coord, float lod);
uint4 __purefn __ovld read_imageui(read_only image3d_t image, sampler_t sampler, float4 coord, float lod);
#endif //cl_khr_mipmap_image
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
/**
* Sampler-less Image Access
*/
float4 __purefn __ovld read_imagef(read_only image1d_t image, int coord);
int4 __purefn __ovld read_imagei(read_only image1d_t image, int coord);
uint4 __purefn __ovld read_imageui(read_only image1d_t image, int coord);
float4 __purefn __ovld read_imagef(read_only image1d_buffer_t image, int coord);
int4 __purefn __ovld read_imagei(read_only image1d_buffer_t image, int coord);
uint4 __purefn __ovld read_imageui(read_only image1d_buffer_t image, int coord);
float4 __purefn __ovld read_imagef(read_only image1d_array_t image, int2 coord);
int4 __purefn __ovld read_imagei(read_only image1d_array_t image, int2 coord);
uint4 __purefn __ovld read_imageui(read_only image1d_array_t image, int2 coord);
float4 __purefn __ovld read_imagef(read_only image2d_t image, int2 coord);
int4 __purefn __ovld read_imagei(read_only image2d_t image, int2 coord);
uint4 __purefn __ovld read_imageui(read_only image2d_t image, int2 coord);
float4 __purefn __ovld read_imagef(read_only image2d_array_t image, int4 coord);
int4 __purefn __ovld read_imagei(read_only image2d_array_t image, int4 coord);
uint4 __purefn __ovld read_imageui(read_only image2d_array_t image, int4 coord);
#ifdef cl_khr_depth_images
float __purefn __ovld read_imagef(read_only image2d_depth_t image, int2 coord);
float __purefn __ovld read_imagef(read_only image2d_array_depth_t image, int4 coord);
#endif //cl_khr_depth_images
float4 __purefn __ovld read_imagef(read_only image3d_t image, int4 coord);
int4 __purefn __ovld read_imagei(read_only image3d_t image, int4 coord);
uint4 __purefn __ovld read_imageui(read_only image3d_t image, int4 coord);
#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2
// Image read functions returning half4 type
#ifdef cl_khr_fp16
half4 __purefn __ovld read_imageh(read_only image1d_t image, sampler_t sampler, int coord);
half4 __purefn __ovld read_imageh(read_only image1d_t image, sampler_t sampler, float coord);
half4 __purefn __ovld read_imageh(read_only image2d_t image, sampler_t sampler, int2 coord);
half4 __purefn __ovld read_imageh(read_only image2d_t image, sampler_t sampler, float2 coord);
half4 __purefn __ovld read_imageh(read_only image3d_t image, sampler_t sampler, int4 coord);
half4 __purefn __ovld read_imageh(read_only image3d_t image, sampler_t sampler, float4 coord);
#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2
half4 __purefn __ovld read_imageh(read_only image1d_array_t image, sampler_t sampler, int2 coord);
half4 __purefn __ovld read_imageh(read_only image1d_array_t image, sampler_t sampler, float2 coord);
half4 __purefn __ovld read_imageh(read_only image2d_array_t image, sampler_t sampler, int4 coord);
half4 __purefn __ovld read_imageh(read_only image2d_array_t image, sampler_t sampler, float4 coord);
/**
* Sampler-less Image Access
*/
half4 __purefn __ovld read_imageh(read_only image1d_t image, int coord);
half4 __purefn __ovld read_imageh(read_only image2d_t image, int2 coord);
half4 __purefn __ovld read_imageh(read_only image3d_t image, int4 coord);
half4 __purefn __ovld read_imageh(read_only image1d_array_t image, int2 coord);
half4 __purefn __ovld read_imageh(read_only image2d_array_t image, int4 coord);
half4 __purefn __ovld read_imageh(read_only image1d_buffer_t image, int coord);
#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2
#endif //cl_khr_fp16
// Image read functions for read_write images
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
float4 __purefn __ovld read_imagef(read_write image1d_t image, int coord);
int4 __purefn __ovld read_imagei(read_write image1d_t image, int coord);
uint4 __purefn __ovld read_imageui(read_write image1d_t image, int coord);
float4 __purefn __ovld read_imagef(read_write image1d_buffer_t image, int coord);
int4 __purefn __ovld read_imagei(read_write image1d_buffer_t image, int coord);
uint4 __purefn __ovld read_imageui(read_write image1d_buffer_t image, int coord);
float4 __purefn __ovld read_imagef(read_write image1d_array_t image, int2 coord);
int4 __purefn __ovld read_imagei(read_write image1d_array_t image, int2 coord);
uint4 __purefn __ovld read_imageui(read_write image1d_array_t image, int2 coord);
float4 __purefn __ovld read_imagef(read_write image2d_t image, int2 coord);
int4 __purefn __ovld read_imagei(read_write image2d_t image, int2 coord);
uint4 __purefn __ovld read_imageui(read_write image2d_t image, int2 coord);
float4 __purefn __ovld read_imagef(read_write image2d_array_t image, int4 coord);
int4 __purefn __ovld read_imagei(read_write image2d_array_t image, int4 coord);
uint4 __purefn __ovld read_imageui(read_write image2d_array_t image, int4 coord);
float4 __purefn __ovld read_imagef(read_write image3d_t image, int4 coord);
int4 __purefn __ovld read_imagei(read_write image3d_t image, int4 coord);
uint4 __purefn __ovld read_imageui(read_write image3d_t image, int4 coord);
#ifdef cl_khr_depth_images
float __purefn __ovld read_imagef(read_write image2d_depth_t image, int2 coord);
float __purefn __ovld read_imagef(read_write image2d_array_depth_t image, int4 coord);
#endif //cl_khr_depth_images
#if cl_khr_gl_msaa_sharing
float4 __purefn __ovld read_imagef(read_write image2d_msaa_t image, int2 coord, int sample);
int4 __purefn __ovld read_imagei(read_write image2d_msaa_t image, int2 coord, int sample);
uint4 __purefn __ovld read_imageui(read_write image2d_msaa_t image, int2 coord, int sample);
float4 __purefn __ovld read_imagef(read_write image2d_array_msaa_t image, int4 coord, int sample);
int4 __purefn __ovld read_imagei(read_write image2d_array_msaa_t image, int4 coord, int sample);
uint4 __purefn __ovld read_imageui(read_write image2d_array_msaa_t image, int4 coord, int sample);
float __purefn __ovld read_imagef(read_write image2d_msaa_depth_t image, int2 coord, int sample);
float __purefn __ovld read_imagef(read_write image2d_array_msaa_depth_t image, int4 coord, int sample);
#endif //cl_khr_gl_msaa_sharing
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
#ifdef cl_khr_mipmap_image
float4 __purefn __ovld read_imagef(read_write image1d_t image, sampler_t sampler, float coord, float lod);
int4 __purefn __ovld read_imagei(read_write image1d_t image, sampler_t sampler, float coord, float lod);
uint4 __purefn __ovld read_imageui(read_write image1d_t image, sampler_t sampler, float coord, float lod);
float4 __purefn __ovld read_imagef(read_write image1d_array_t image_array, sampler_t sampler, float2 coord, float lod);
int4 __purefn __ovld read_imagei(read_write image1d_array_t image_array, sampler_t sampler, float2 coord, float lod);
uint4 __purefn __ovld read_imageui(read_write image1d_array_t image_array, sampler_t sampler, float2 coord, float lod);
float4 __purefn __ovld read_imagef(read_write image2d_t image, sampler_t sampler, float2 coord, float lod);
int4 __purefn __ovld read_imagei(read_write image2d_t image, sampler_t sampler, float2 coord, float lod);
uint4 __purefn __ovld read_imageui(read_write image2d_t image, sampler_t sampler, float2 coord, float lod);
float __purefn __ovld read_imagef(read_write image2d_depth_t image, sampler_t sampler, float2 coord, float lod);
float4 __purefn __ovld read_imagef(read_write image2d_array_t image_array, sampler_t sampler, float4 coord, float lod);
int4 __purefn __ovld read_imagei(read_write image2d_array_t image_array, sampler_t sampler, float4 coord, float lod);
uint4 __purefn __ovld read_imageui(read_write image2d_array_t image_array, sampler_t sampler, float4 coord, float lod);
float __purefn __ovld read_imagef(read_write image2d_array_depth_t image, sampler_t sampler, float4 coord, float lod);
float4 __purefn __ovld read_imagef(read_write image3d_t image, sampler_t sampler, float4 coord, float lod);
int4 __purefn __ovld read_imagei(read_write image3d_t image, sampler_t sampler, float4 coord, float lod);
uint4 __purefn __ovld read_imageui(read_write image3d_t image, sampler_t sampler, float4 coord, float lod);
float4 __purefn __ovld read_imagef(read_write image1d_t image, sampler_t sampler, float coord, float gradientX, float gradientY);
int4 __purefn __ovld read_imagei(read_write image1d_t image, sampler_t sampler, float coord, float gradientX, float gradientY);
uint4 __purefn __ovld read_imageui(read_write image1d_t image, sampler_t sampler, float coord, float gradientX, float gradientY);
float4 __purefn __ovld read_imagef(read_write image1d_array_t image_array, sampler_t sampler, float2 coord, float gradientX, float gradientY);
int4 __purefn __ovld read_imagei(read_write image1d_array_t image_array, sampler_t sampler, float2 coord, float gradientX, float gradientY);
uint4 __purefn __ovld read_imageui(read_write image1d_array_t image_array, sampler_t sampler, float2 coord, float gradientX, float gradientY);
float4 __purefn __ovld read_imagef(read_write image2d_t image, sampler_t sampler, float2 coord, float2 gradientX, float2 gradientY);
int4 __purefn __ovld read_imagei(read_write image2d_t image, sampler_t sampler, float2 coord, float2 gradientX, float2 gradientY);
uint4 __purefn __ovld read_imageui(read_write image2d_t image, sampler_t sampler, float2 coord, float2 gradientX, float2 gradientY);
float __purefn __ovld read_imagef(read_write image2d_depth_t image, sampler_t sampler, float2 coord, float2 gradientX, float2 gradientY);
float4 __purefn __ovld read_imagef(read_write image2d_array_t image_array, sampler_t sampler, float4 coord, float2 gradientX, float2 gradientY);
int4 __purefn __ovld read_imagei(read_write image2d_array_t image_array, sampler_t sampler, float4 coord, float2 gradientX, float2 gradientY);
uint4 __purefn __ovld read_imageui(read_write image2d_array_t image_array, sampler_t sampler, float4 coord, float2 gradientX, float2 gradientY);
float __purefn __ovld read_imagef(read_write image2d_array_depth_t image, sampler_t sampler, float4 coord, float2 gradientX, float2 gradientY);
float4 __purefn __ovld read_imagef(read_write image3d_t image, sampler_t sampler, float4 coord, float4 gradientX, float4 gradientY);
int4 __purefn __ovld read_imagei(read_write image3d_t image, sampler_t sampler, float4 coord, float4 gradientX, float4 gradientY);
uint4 __purefn __ovld read_imageui(read_write image3d_t image, sampler_t sampler, float4 coord, float4 gradientX, float4 gradientY);
float4 __purefn __ovld read_imagef(read_write image1d_t image, sampler_t sampler, float coord, float lod);
int4 __purefn __ovld read_imagei(read_write image1d_t image, sampler_t sampler, float coord, float lod);
uint4 __purefn __ovld read_imageui(read_write image1d_t image, sampler_t sampler, float coord, float lod);
float4 __purefn __ovld read_imagef(read_write image1d_array_t image_array, sampler_t sampler, float2 coord, float lod);
int4 __purefn __ovld read_imagei(read_write image1d_array_t image_array, sampler_t sampler, float2 coord, float lod);
uint4 __purefn __ovld read_imageui(read_write image1d_array_t image_array, sampler_t sampler, float2 coord, float lod);
float4 __purefn __ovld read_imagef(read_write image2d_t image, sampler_t sampler, float2 coord, float lod);
int4 __purefn __ovld read_imagei(read_write image2d_t image, sampler_t sampler, float2 coord, float lod);
uint4 __purefn __ovld read_imageui(read_write image2d_t image, sampler_t sampler, float2 coord, float lod);
float __purefn __ovld read_imagef(read_write image2d_depth_t image, sampler_t sampler, float2 coord, float lod);
float4 __purefn __ovld read_imagef(read_write image2d_array_t image_array, sampler_t sampler, float4 coord, float lod);
int4 __purefn __ovld read_imagei(read_write image2d_array_t image_array, sampler_t sampler, float4 coord, float lod);
uint4 __purefn __ovld read_imageui(read_write image2d_array_t image_array, sampler_t sampler, float4 coord, float lod);
float __purefn __ovld read_imagef(read_write image2d_array_depth_t image, sampler_t sampler, float4 coord, float lod);
float4 __purefn __ovld read_imagef(read_write image3d_t image, sampler_t sampler, float4 coord, float lod);
int4 __purefn __ovld read_imagei(read_write image3d_t image, sampler_t sampler, float4 coord, float lod);
uint4 __purefn __ovld read_imageui(read_write image3d_t image, sampler_t sampler, float4 coord, float lod);
#endif //cl_khr_mipmap_image
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
// Image read functions returning half4 type
#ifdef cl_khr_fp16
half4 __purefn __ovld read_imageh(read_write image1d_t image, int coord);
half4 __purefn __ovld read_imageh(read_write image2d_t image, int2 coord);
half4 __purefn __ovld read_imageh(read_write image3d_t image, int4 coord);
half4 __purefn __ovld read_imageh(read_write image1d_array_t image, int2 coord);
half4 __purefn __ovld read_imageh(read_write image2d_array_t image, int4 coord);
half4 __purefn __ovld read_imageh(read_write image1d_buffer_t image, int coord);
#endif //cl_khr_fp16
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Write color value to location specified by coordinate
* (coord.x, coord.y) in the 2D image object specified by image.
* (coord.x, coord.y) are considered to be unnormalized coordinates
* and must be in the range 0 ... image width - 1, and 0
* ... image height - 1.
* Write color value to location specified by coordinate
* (coord.x, coord.y) in the 2D image object specified by index
* (coord.z) of the 2D image array object image_array.
* (coord.x, coord.y) are considered to be unnormalized
* coordinates and must be in the range 0 ... image width
* - 1.
*
* Write color value to location specified by coordinate
* (coord) in the 1D image (buffer) object specified by image.
* coord is considered to be unnormalized coordinates
* and must be in the range 0 ... image width - 1.
*
* Write color value to location specified by coordinate
* (coord.x) in the 1D image object specified by index
* (coord.y) of the 1D image array object image_array.
* x is considered to be unnormalized coordinates
* and must be in the range 0 ... image width - 1.
*
* Write color value to location specified by coordinate
* (coord.x, coord.y, coord.z) in the 3D image object specified by image.
* coord.x & coord.y are considered to be unnormalized coordinates
* and must be in the range 0 ... image width - 1, and 0
* ... image height - 1.
*
* For mipmap images, use mip-level specified by lod.
*
* Appropriate data format conversion to the specified
* image format is done before writing the color value.
*
* write_imagef can only be used with image objects
* created with image_channel_data_type set to one of
* the pre-defined packed formats or set to
* CL_SNORM_INT8, CL_UNORM_INT8,
* CL_SNORM_INT16, CL_UNORM_INT16,
* CL_HALF_FLOAT or CL_FLOAT. Appropriate data
* format conversion will be done to convert channel
* data from a floating-point value to actual data format
* in which the channels are stored.
*
* write_imagei can only be used with image objects
* created with image_channel_data_type set to one of
* the following values:
* CL_SIGNED_INT8,
* CL_SIGNED_INT16 and
* CL_SIGNED_INT32.
*
* write_imageui can only be used with image objects
* created with image_channel_data_type set to one of
* the following values:
* CL_UNSIGNED_INT8,
* CL_UNSIGNED_INT16 and
* CL_UNSIGNED_INT32.
*
* The behavior of write_imagef, write_imagei and
* write_imageui for image objects created with
* image_channel_data_type values not specified in
* the description above or with (x, y) coordinate
* values that are not in the range (0 ... image width -1,
* 0 ... image height - 1), respectively, is undefined.
*/
void __ovld write_imagef(write_only image2d_t image, int2 coord, float4 color);
void __ovld write_imagei(write_only image2d_t image, int2 coord, int4 color);
void __ovld write_imageui(write_only image2d_t image, int2 coord, uint4 color);
void __ovld write_imagef(write_only image2d_array_t image_array, int4 coord, float4 color);
void __ovld write_imagei(write_only image2d_array_t image_array, int4 coord, int4 color);
void __ovld write_imageui(write_only image2d_array_t image_array, int4 coord, uint4 color);
void __ovld write_imagef(write_only image1d_t image, int coord, float4 color);
void __ovld write_imagei(write_only image1d_t image, int coord, int4 color);
void __ovld write_imageui(write_only image1d_t image, int coord, uint4 color);
void __ovld write_imagef(write_only image1d_buffer_t image, int coord, float4 color);
void __ovld write_imagei(write_only image1d_buffer_t image, int coord, int4 color);
void __ovld write_imageui(write_only image1d_buffer_t image, int coord, uint4 color);
void __ovld write_imagef(write_only image1d_array_t image_array, int2 coord, float4 color);
void __ovld write_imagei(write_only image1d_array_t image_array, int2 coord, int4 color);
void __ovld write_imageui(write_only image1d_array_t image_array, int2 coord, uint4 color);
#ifdef cl_khr_3d_image_writes
void __ovld write_imagef(write_only image3d_t image, int4 coord, float4 color);
void __ovld write_imagei(write_only image3d_t image, int4 coord, int4 color);
void __ovld write_imageui(write_only image3d_t image, int4 coord, uint4 color);
#endif
#ifdef cl_khr_depth_images
void __ovld write_imagef(write_only image2d_depth_t image, int2 coord, float color);
void __ovld write_imagef(write_only image2d_array_depth_t image, int4 coord, float color);
#endif //cl_khr_depth_images
// OpenCL Extension v2.0 s9.18 - Mipmaps
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
#ifdef cl_khr_mipmap_image
void __ovld write_imagef(write_only image1d_t image, int coord, int lod, float4 color);
void __ovld write_imagei(write_only image1d_t image, int coord, int lod, int4 color);
void __ovld write_imageui(write_only image1d_t image, int coord, int lod, uint4 color);
void __ovld write_imagef(write_only image1d_array_t image_array, int2 coord, int lod, float4 color);
void __ovld write_imagei(write_only image1d_array_t image_array, int2 coord, int lod, int4 color);
void __ovld write_imageui(write_only image1d_array_t image_array, int2 coord, int lod, uint4 color);
void __ovld write_imagef(write_only image2d_t image, int2 coord, int lod, float4 color);
void __ovld write_imagei(write_only image2d_t image, int2 coord, int lod, int4 color);
void __ovld write_imageui(write_only image2d_t image, int2 coord, int lod, uint4 color);
void __ovld write_imagef(write_only image2d_array_t image_array, int4 coord, int lod, float4 color);
void __ovld write_imagei(write_only image2d_array_t image_array, int4 coord, int lod, int4 color);
void __ovld write_imageui(write_only image2d_array_t image_array, int4 coord, int lod, uint4 color);
void __ovld write_imagef(write_only image2d_depth_t image, int2 coord, int lod, float color);
void __ovld write_imagef(write_only image2d_array_depth_t image, int4 coord, int lod, float color);
#ifdef cl_khr_3d_image_writes
void __ovld write_imagef(write_only image3d_t image, int4 coord, int lod, float4 color);
void __ovld write_imagei(write_only image3d_t image, int4 coord, int lod, int4 color);
void __ovld write_imageui(write_only image3d_t image, int4 coord, int lod, uint4 color);
#endif
#endif //cl_khr_mipmap_image
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
// Image write functions for half4 type
#ifdef cl_khr_fp16
void __ovld write_imageh(write_only image1d_t image, int coord, half4 color);
void __ovld write_imageh(write_only image2d_t image, int2 coord, half4 color);
#ifdef cl_khr_3d_image_writes
void __ovld write_imageh(write_only image3d_t image, int4 coord, half4 color);
#endif
void __ovld write_imageh(write_only image1d_array_t image, int2 coord, half4 color);
void __ovld write_imageh(write_only image2d_array_t image, int4 coord, half4 color);
void __ovld write_imageh(write_only image1d_buffer_t image, int coord, half4 color);
#endif //cl_khr_fp16
// Image write functions for read_write images
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
void __ovld write_imagef(read_write image2d_t image, int2 coord, float4 color);
void __ovld write_imagei(read_write image2d_t image, int2 coord, int4 color);
void __ovld write_imageui(read_write image2d_t image, int2 coord, uint4 color);
void __ovld write_imagef(read_write image2d_array_t image_array, int4 coord, float4 color);
void __ovld write_imagei(read_write image2d_array_t image_array, int4 coord, int4 color);
void __ovld write_imageui(read_write image2d_array_t image_array, int4 coord, uint4 color);
void __ovld write_imagef(read_write image1d_t image, int coord, float4 color);
void __ovld write_imagei(read_write image1d_t image, int coord, int4 color);
void __ovld write_imageui(read_write image1d_t image, int coord, uint4 color);
void __ovld write_imagef(read_write image1d_buffer_t image, int coord, float4 color);
void __ovld write_imagei(read_write image1d_buffer_t image, int coord, int4 color);
void __ovld write_imageui(read_write image1d_buffer_t image, int coord, uint4 color);
void __ovld write_imagef(read_write image1d_array_t image_array, int2 coord, float4 color);
void __ovld write_imagei(read_write image1d_array_t image_array, int2 coord, int4 color);
void __ovld write_imageui(read_write image1d_array_t image_array, int2 coord, uint4 color);
#ifdef cl_khr_3d_image_writes
void __ovld write_imagef(read_write image3d_t image, int4 coord, float4 color);
void __ovld write_imagei(read_write image3d_t image, int4 coord, int4 color);
void __ovld write_imageui(read_write image3d_t image, int4 coord, uint4 color);
#endif
#ifdef cl_khr_depth_images
void __ovld write_imagef(read_write image2d_depth_t image, int2 coord, float color);
void __ovld write_imagef(read_write image2d_array_depth_t image, int4 coord, float color);
#endif //cl_khr_depth_images
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
#ifdef cl_khr_mipmap_image
void __ovld write_imagef(read_write image1d_t image, int coord, int lod, float4 color);
void __ovld write_imagei(read_write image1d_t image, int coord, int lod, int4 color);
void __ovld write_imageui(read_write image1d_t image, int coord, int lod, uint4 color);
void __ovld write_imagef(read_write image1d_array_t image_array, int2 coord, int lod, float4 color);
void __ovld write_imagei(read_write image1d_array_t image_array, int2 coord, int lod, int4 color);
void __ovld write_imageui(read_write image1d_array_t image_array, int2 coord, int lod, uint4 color);
void __ovld write_imagef(read_write image2d_t image, int2 coord, int lod, float4 color);
void __ovld write_imagei(read_write image2d_t image, int2 coord, int lod, int4 color);
void __ovld write_imageui(read_write image2d_t image, int2 coord, int lod, uint4 color);
void __ovld write_imagef(read_write image2d_array_t image_array, int4 coord, int lod, float4 color);
void __ovld write_imagei(read_write image2d_array_t image_array, int4 coord, int lod, int4 color);
void __ovld write_imageui(read_write image2d_array_t image_array, int4 coord, int lod, uint4 color);
void __ovld write_imagef(read_write image2d_depth_t image, int2 coord, int lod, float color);
void __ovld write_imagef(read_write image2d_array_depth_t image, int4 coord, int lod, float color);
#ifdef cl_khr_3d_image_writes
void __ovld write_imagef(read_write image3d_t image, int4 coord, int lod, float4 color);
void __ovld write_imagei(read_write image3d_t image, int4 coord, int lod, int4 color);
void __ovld write_imageui(read_write image3d_t image, int4 coord, int lod, uint4 color);
#endif
#endif //cl_khr_mipmap_image
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
// Image write functions for half4 type
#ifdef cl_khr_fp16
void __ovld write_imageh(read_write image1d_t image, int coord, half4 color);
void __ovld write_imageh(read_write image2d_t image, int2 coord, half4 color);
#ifdef cl_khr_3d_image_writes
void __ovld write_imageh(read_write image3d_t image, int4 coord, half4 color);
#endif
void __ovld write_imageh(read_write image1d_array_t image, int2 coord, half4 color);
void __ovld write_imageh(read_write image2d_array_t image, int4 coord, half4 color);
void __ovld write_imageh(read_write image1d_buffer_t image, int coord, half4 color);
#endif //cl_khr_fp16
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
// Note: In OpenCL v1.0/1.1/1.2, image argument of image query builtin functions does not have
// access qualifier, which by default assume read_only access qualifier. Image query builtin
// functions with write_only image argument should also be declared.
/**
* Return the image width in pixels.
*
*/
int __ovld __cnfn get_image_width(read_only image1d_t image);
int __ovld __cnfn get_image_width(read_only image1d_buffer_t image);
int __ovld __cnfn get_image_width(read_only image2d_t image);
#ifdef cl_khr_3d_image_writes
int __ovld __cnfn get_image_width(read_only image3d_t image);
#endif
int __ovld __cnfn get_image_width(read_only image1d_array_t image);
int __ovld __cnfn get_image_width(read_only image2d_array_t image);
#ifdef cl_khr_depth_images
int __ovld __cnfn get_image_width(read_only image2d_depth_t image);
int __ovld __cnfn get_image_width(read_only image2d_array_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int __ovld __cnfn get_image_width(read_only image2d_msaa_t image);
int __ovld __cnfn get_image_width(read_only image2d_msaa_depth_t image);
int __ovld __cnfn get_image_width(read_only image2d_array_msaa_t image);
int __ovld __cnfn get_image_width(read_only image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
int __ovld __cnfn get_image_width(write_only image1d_t image);
int __ovld __cnfn get_image_width(write_only image1d_buffer_t image);
int __ovld __cnfn get_image_width(write_only image2d_t image);
#ifdef cl_khr_3d_image_writes
int __ovld __cnfn get_image_width(write_only image3d_t image);
#endif
int __ovld __cnfn get_image_width(write_only image1d_array_t image);
int __ovld __cnfn get_image_width(write_only image2d_array_t image);
#ifdef cl_khr_depth_images
int __ovld __cnfn get_image_width(write_only image2d_depth_t image);
int __ovld __cnfn get_image_width(write_only image2d_array_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int __ovld __cnfn get_image_width(write_only image2d_msaa_t image);
int __ovld __cnfn get_image_width(write_only image2d_msaa_depth_t image);
int __ovld __cnfn get_image_width(write_only image2d_array_msaa_t image);
int __ovld __cnfn get_image_width(write_only image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
int __ovld __cnfn get_image_width(read_write image1d_t image);
int __ovld __cnfn get_image_width(read_write image1d_buffer_t image);
int __ovld __cnfn get_image_width(read_write image2d_t image);
int __ovld __cnfn get_image_width(read_write image3d_t image);
int __ovld __cnfn get_image_width(read_write image1d_array_t image);
int __ovld __cnfn get_image_width(read_write image2d_array_t image);
#ifdef cl_khr_depth_images
int __ovld __cnfn get_image_width(read_write image2d_depth_t image);
int __ovld __cnfn get_image_width(read_write image2d_array_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int __ovld __cnfn get_image_width(read_write image2d_msaa_t image);
int __ovld __cnfn get_image_width(read_write image2d_msaa_depth_t image);
int __ovld __cnfn get_image_width(read_write image2d_array_msaa_t image);
int __ovld __cnfn get_image_width(read_write image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Return the image height in pixels.
*/
int __ovld __cnfn get_image_height(read_only image2d_t image);
int __ovld __cnfn get_image_height(read_only image3d_t image);
int __ovld __cnfn get_image_height(read_only image2d_array_t image);
#ifdef cl_khr_depth_images
int __ovld __cnfn get_image_height(read_only image2d_depth_t image);
int __ovld __cnfn get_image_height(read_only image2d_array_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int __ovld __cnfn get_image_height(read_only image2d_msaa_t image);
int __ovld __cnfn get_image_height(read_only image2d_msaa_depth_t image);
int __ovld __cnfn get_image_height(read_only image2d_array_msaa_t image);
int __ovld __cnfn get_image_height(read_only image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
int __ovld __cnfn get_image_height(write_only image2d_t image);
#ifdef cl_khr_3d_image_writes
int __ovld __cnfn get_image_height(write_only image3d_t image);
#endif
int __ovld __cnfn get_image_height(write_only image2d_array_t image);
#ifdef cl_khr_depth_images
int __ovld __cnfn get_image_height(write_only image2d_depth_t image);
int __ovld __cnfn get_image_height(write_only image2d_array_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int __ovld __cnfn get_image_height(write_only image2d_msaa_t image);
int __ovld __cnfn get_image_height(write_only image2d_msaa_depth_t image);
int __ovld __cnfn get_image_height(write_only image2d_array_msaa_t image);
int __ovld __cnfn get_image_height(write_only image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
int __ovld __cnfn get_image_height(read_write image2d_t image);
int __ovld __cnfn get_image_height(read_write image3d_t image);
int __ovld __cnfn get_image_height(read_write image2d_array_t image);
#ifdef cl_khr_depth_images
int __ovld __cnfn get_image_height(read_write image2d_depth_t image);
int __ovld __cnfn get_image_height(read_write image2d_array_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int __ovld __cnfn get_image_height(read_write image2d_msaa_t image);
int __ovld __cnfn get_image_height(read_write image2d_msaa_depth_t image);
int __ovld __cnfn get_image_height(read_write image2d_array_msaa_t image);
int __ovld __cnfn get_image_height(read_write image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Return the image depth in pixels.
*/
int __ovld __cnfn get_image_depth(read_only image3d_t image);
#ifdef cl_khr_3d_image_writes
int __ovld __cnfn get_image_depth(write_only image3d_t image);
#endif
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
int __ovld __cnfn get_image_depth(read_write image3d_t image);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
// OpenCL Extension v2.0 s9.18 - Mipmaps
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
#ifdef cl_khr_mipmap_image
/**
* Return the image miplevels.
*/
int __ovld get_image_num_mip_levels(read_only image1d_t image);
int __ovld get_image_num_mip_levels(read_only image2d_t image);
int __ovld get_image_num_mip_levels(read_only image3d_t image);
int __ovld get_image_num_mip_levels(write_only image1d_t image);
int __ovld get_image_num_mip_levels(write_only image2d_t image);
#ifdef cl_khr_3d_image_writes
int __ovld get_image_num_mip_levels(write_only image3d_t image);
#endif
int __ovld get_image_num_mip_levels(read_write image1d_t image);
int __ovld get_image_num_mip_levels(read_write image2d_t image);
int __ovld get_image_num_mip_levels(read_write image3d_t image);
int __ovld get_image_num_mip_levels(read_only image1d_array_t image);
int __ovld get_image_num_mip_levels(read_only image2d_array_t image);
int __ovld get_image_num_mip_levels(read_only image2d_array_depth_t image);
int __ovld get_image_num_mip_levels(read_only image2d_depth_t image);
int __ovld get_image_num_mip_levels(write_only image1d_array_t image);
int __ovld get_image_num_mip_levels(write_only image2d_array_t image);
int __ovld get_image_num_mip_levels(write_only image2d_array_depth_t image);
int __ovld get_image_num_mip_levels(write_only image2d_depth_t image);
int __ovld get_image_num_mip_levels(read_write image1d_array_t image);
int __ovld get_image_num_mip_levels(read_write image2d_array_t image);
int __ovld get_image_num_mip_levels(read_write image2d_array_depth_t image);
int __ovld get_image_num_mip_levels(read_write image2d_depth_t image);
#endif //cl_khr_mipmap_image
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Return the channel data type. Valid values are:
* CLK_SNORM_INT8
* CLK_SNORM_INT16
* CLK_UNORM_INT8
* CLK_UNORM_INT16
* CLK_UNORM_SHORT_565
* CLK_UNORM_SHORT_555
* CLK_UNORM_SHORT_101010
* CLK_SIGNED_INT8
* CLK_SIGNED_INT16
* CLK_SIGNED_INT32
* CLK_UNSIGNED_INT8
* CLK_UNSIGNED_INT16
* CLK_UNSIGNED_INT32
* CLK_HALF_FLOAT
* CLK_FLOAT
*/
//
// Channel Datatype.
//
#define CLK_SNORM_INT8 0x10D0
#define CLK_SNORM_INT16 0x10D1
#define CLK_UNORM_INT8 0x10D2
#define CLK_UNORM_INT16 0x10D3
#define CLK_UNORM_SHORT_565 0x10D4
#define CLK_UNORM_SHORT_555 0x10D5
#define CLK_UNORM_INT_101010 0x10D6
#define CLK_SIGNED_INT8 0x10D7
#define CLK_SIGNED_INT16 0x10D8
#define CLK_SIGNED_INT32 0x10D9
#define CLK_UNSIGNED_INT8 0x10DA
#define CLK_UNSIGNED_INT16 0x10DB
#define CLK_UNSIGNED_INT32 0x10DC
#define CLK_HALF_FLOAT 0x10DD
#define CLK_FLOAT 0x10DE
#define CLK_UNORM_INT24 0x10DF
int __ovld __cnfn get_image_channel_data_type(read_only image1d_t image);
int __ovld __cnfn get_image_channel_data_type(read_only image1d_buffer_t image);
int __ovld __cnfn get_image_channel_data_type(read_only image2d_t image);
int __ovld __cnfn get_image_channel_data_type(read_only image3d_t image);
int __ovld __cnfn get_image_channel_data_type(read_only image1d_array_t image);
int __ovld __cnfn get_image_channel_data_type(read_only image2d_array_t image);
#ifdef cl_khr_depth_images
int __ovld __cnfn get_image_channel_data_type(read_only image2d_depth_t image);
int __ovld __cnfn get_image_channel_data_type(read_only image2d_array_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int __ovld __cnfn get_image_channel_data_type(read_only image2d_msaa_t image);
int __ovld __cnfn get_image_channel_data_type(read_only image2d_msaa_depth_t image);
int __ovld __cnfn get_image_channel_data_type(read_only image2d_array_msaa_t image);
int __ovld __cnfn get_image_channel_data_type(read_only image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
int __ovld __cnfn get_image_channel_data_type(write_only image1d_t image);
int __ovld __cnfn get_image_channel_data_type(write_only image1d_buffer_t image);
int __ovld __cnfn get_image_channel_data_type(write_only image2d_t image);
#ifdef cl_khr_3d_image_writes
int __ovld __cnfn get_image_channel_data_type(write_only image3d_t image);
#endif
int __ovld __cnfn get_image_channel_data_type(write_only image1d_array_t image);
int __ovld __cnfn get_image_channel_data_type(write_only image2d_array_t image);
#ifdef cl_khr_depth_images
int __ovld __cnfn get_image_channel_data_type(write_only image2d_depth_t image);
int __ovld __cnfn get_image_channel_data_type(write_only image2d_array_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int __ovld __cnfn get_image_channel_data_type(write_only image2d_msaa_t image);
int __ovld __cnfn get_image_channel_data_type(write_only image2d_msaa_depth_t image);
int __ovld __cnfn get_image_channel_data_type(write_only image2d_array_msaa_t image);
int __ovld __cnfn get_image_channel_data_type(write_only image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
int __ovld __cnfn get_image_channel_data_type(read_write image1d_t image);
int __ovld __cnfn get_image_channel_data_type(read_write image1d_buffer_t image);
int __ovld __cnfn get_image_channel_data_type(read_write image2d_t image);
int __ovld __cnfn get_image_channel_data_type(read_write image3d_t image);
int __ovld __cnfn get_image_channel_data_type(read_write image1d_array_t image);
int __ovld __cnfn get_image_channel_data_type(read_write image2d_array_t image);
#ifdef cl_khr_depth_images
int __ovld __cnfn get_image_channel_data_type(read_write image2d_depth_t image);
int __ovld __cnfn get_image_channel_data_type(read_write image2d_array_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int __ovld __cnfn get_image_channel_data_type(read_write image2d_msaa_t image);
int __ovld __cnfn get_image_channel_data_type(read_write image2d_msaa_depth_t image);
int __ovld __cnfn get_image_channel_data_type(read_write image2d_array_msaa_t image);
int __ovld __cnfn get_image_channel_data_type(read_write image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Return the image channel order. Valid values are:
* CLK_A
* CLK_R
* CLK_Rx
* CLK_RG
* CLK_RGx
* CLK_RA
* CLK_RGB
* CLK_RGBx
* CLK_RGBA
* CLK_ARGB
* CLK_BGRA
* CLK_INTENSITY
* CLK_LUMINANCE
*/
// Channel order, numbering must be aligned with cl_channel_order in cl.h
//
#define CLK_R 0x10B0
#define CLK_A 0x10B1
#define CLK_RG 0x10B2
#define CLK_RA 0x10B3
#define CLK_RGB 0x10B4
#define CLK_RGBA 0x10B5
#define CLK_BGRA 0x10B6
#define CLK_ARGB 0x10B7
#define CLK_INTENSITY 0x10B8
#define CLK_LUMINANCE 0x10B9
#define CLK_Rx 0x10BA
#define CLK_RGx 0x10BB
#define CLK_RGBx 0x10BC
#define CLK_DEPTH 0x10BD
#define CLK_DEPTH_STENCIL 0x10BE
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
#define CLK_sRGB 0x10BF
#define CLK_sRGBx 0x10C0
#define CLK_sRGBA 0x10C1
#define CLK_sBGRA 0x10C2
#define CLK_ABGR 0x10C3
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
int __ovld __cnfn get_image_channel_order(read_only image1d_t image);
int __ovld __cnfn get_image_channel_order(read_only image1d_buffer_t image);
int __ovld __cnfn get_image_channel_order(read_only image2d_t image);
int __ovld __cnfn get_image_channel_order(read_only image3d_t image);
int __ovld __cnfn get_image_channel_order(read_only image1d_array_t image);
int __ovld __cnfn get_image_channel_order(read_only image2d_array_t image);
#ifdef cl_khr_depth_images
int __ovld __cnfn get_image_channel_order(read_only image2d_depth_t image);
int __ovld __cnfn get_image_channel_order(read_only image2d_array_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int __ovld __cnfn get_image_channel_order(read_only image2d_msaa_t image);
int __ovld __cnfn get_image_channel_order(read_only image2d_msaa_depth_t image);
int __ovld __cnfn get_image_channel_order(read_only image2d_array_msaa_t image);
int __ovld __cnfn get_image_channel_order(read_only image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
int __ovld __cnfn get_image_channel_order(write_only image1d_t image);
int __ovld __cnfn get_image_channel_order(write_only image1d_buffer_t image);
int __ovld __cnfn get_image_channel_order(write_only image2d_t image);
#ifdef cl_khr_3d_image_writes
int __ovld __cnfn get_image_channel_order(write_only image3d_t image);
#endif
int __ovld __cnfn get_image_channel_order(write_only image1d_array_t image);
int __ovld __cnfn get_image_channel_order(write_only image2d_array_t image);
#ifdef cl_khr_depth_images
int __ovld __cnfn get_image_channel_order(write_only image2d_depth_t image);
int __ovld __cnfn get_image_channel_order(write_only image2d_array_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int __ovld __cnfn get_image_channel_order(write_only image2d_msaa_t image);
int __ovld __cnfn get_image_channel_order(write_only image2d_msaa_depth_t image);
int __ovld __cnfn get_image_channel_order(write_only image2d_array_msaa_t image);
int __ovld __cnfn get_image_channel_order(write_only image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
int __ovld __cnfn get_image_channel_order(read_write image1d_t image);
int __ovld __cnfn get_image_channel_order(read_write image1d_buffer_t image);
int __ovld __cnfn get_image_channel_order(read_write image2d_t image);
int __ovld __cnfn get_image_channel_order(read_write image3d_t image);
int __ovld __cnfn get_image_channel_order(read_write image1d_array_t image);
int __ovld __cnfn get_image_channel_order(read_write image2d_array_t image);
#ifdef cl_khr_depth_images
int __ovld __cnfn get_image_channel_order(read_write image2d_depth_t image);
int __ovld __cnfn get_image_channel_order(read_write image2d_array_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int __ovld __cnfn get_image_channel_order(read_write image2d_msaa_t image);
int __ovld __cnfn get_image_channel_order(read_write image2d_msaa_depth_t image);
int __ovld __cnfn get_image_channel_order(read_write image2d_array_msaa_t image);
int __ovld __cnfn get_image_channel_order(read_write image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Return the 2D image width and height as an int2
* type. The width is returned in the x component, and
* the height in the y component.
*/
int2 __ovld __cnfn get_image_dim(read_only image2d_t image);
int2 __ovld __cnfn get_image_dim(read_only image2d_array_t image);
#ifdef cl_khr_depth_images
int2 __ovld __cnfn get_image_dim(read_only image2d_array_depth_t image);
int2 __ovld __cnfn get_image_dim(read_only image2d_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int2 __ovld __cnfn get_image_dim(read_only image2d_msaa_t image);
int2 __ovld __cnfn get_image_dim(read_only image2d_msaa_depth_t image);
int2 __ovld __cnfn get_image_dim(read_only image2d_array_msaa_t image);
int2 __ovld __cnfn get_image_dim(read_only image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
int2 __ovld __cnfn get_image_dim(write_only image2d_t image);
int2 __ovld __cnfn get_image_dim(write_only image2d_array_t image);
#ifdef cl_khr_depth_images
int2 __ovld __cnfn get_image_dim(write_only image2d_array_depth_t image);
int2 __ovld __cnfn get_image_dim(write_only image2d_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int2 __ovld __cnfn get_image_dim(write_only image2d_msaa_t image);
int2 __ovld __cnfn get_image_dim(write_only image2d_msaa_depth_t image);
int2 __ovld __cnfn get_image_dim(write_only image2d_array_msaa_t image);
int2 __ovld __cnfn get_image_dim(write_only image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
int2 __ovld __cnfn get_image_dim(read_write image2d_t image);
int2 __ovld __cnfn get_image_dim(read_write image2d_array_t image);
#ifdef cl_khr_depth_images
int2 __ovld __cnfn get_image_dim(read_write image2d_array_depth_t image);
int2 __ovld __cnfn get_image_dim(read_write image2d_depth_t image);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
int2 __ovld __cnfn get_image_dim(read_write image2d_msaa_t image);
int2 __ovld __cnfn get_image_dim(read_write image2d_msaa_depth_t image);
int2 __ovld __cnfn get_image_dim(read_write image2d_array_msaa_t image);
int2 __ovld __cnfn get_image_dim(read_write image2d_array_msaa_depth_t image);
#endif //cl_khr_gl_msaa_sharing
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Return the 3D image width, height, and depth as an
* int4 type. The width is returned in the x
* component, height in the y component, depth in the z
* component and the w component is 0.
*/
int4 __ovld __cnfn get_image_dim(read_only image3d_t image);
#ifdef cl_khr_3d_image_writes
int4 __ovld __cnfn get_image_dim(write_only image3d_t image);
#endif
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
int4 __ovld __cnfn get_image_dim(read_write image3d_t image);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Return the image array size.
*/
size_t __ovld __cnfn get_image_array_size(read_only image1d_array_t image_array);
size_t __ovld __cnfn get_image_array_size(read_only image2d_array_t image_array);
#ifdef cl_khr_depth_images
size_t __ovld __cnfn get_image_array_size(read_only image2d_array_depth_t image_array);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
size_t __ovld __cnfn get_image_array_size(read_only image2d_array_msaa_t image_array);
size_t __ovld __cnfn get_image_array_size(read_only image2d_array_msaa_depth_t image_array);
#endif //cl_khr_gl_msaa_sharing
size_t __ovld __cnfn get_image_array_size(write_only image1d_array_t image_array);
size_t __ovld __cnfn get_image_array_size(write_only image2d_array_t image_array);
#ifdef cl_khr_depth_images
size_t __ovld __cnfn get_image_array_size(write_only image2d_array_depth_t image_array);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
size_t __ovld __cnfn get_image_array_size(write_only image2d_array_msaa_t image_array);
size_t __ovld __cnfn get_image_array_size(write_only image2d_array_msaa_depth_t image_array);
#endif //cl_khr_gl_msaa_sharing
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
size_t __ovld __cnfn get_image_array_size(read_write image1d_array_t image_array);
size_t __ovld __cnfn get_image_array_size(read_write image2d_array_t image_array);
#ifdef cl_khr_depth_images
size_t __ovld __cnfn get_image_array_size(read_write image2d_array_depth_t image_array);
#endif //cl_khr_depth_images
#if defined(cl_khr_gl_msaa_sharing)
size_t __ovld __cnfn get_image_array_size(read_write image2d_array_msaa_t image_array);
size_t __ovld __cnfn get_image_array_size(read_write image2d_array_msaa_depth_t image_array);
#endif //cl_khr_gl_msaa_sharing
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
/**
* Return the number of samples associated with image
*/
#if defined(cl_khr_gl_msaa_sharing)
int __ovld get_image_num_samples(read_only image2d_msaa_t image);
int __ovld get_image_num_samples(read_only image2d_msaa_depth_t image);
int __ovld get_image_num_samples(read_only image2d_array_msaa_depth_t image);
int __ovld get_image_num_samples(read_only image2d_array_msaa_t image);
int __ovld get_image_num_samples(read_only image2d_array_msaa_depth_t image);
int __ovld get_image_num_samples(write_only image2d_msaa_t image);
int __ovld get_image_num_samples(write_only image2d_msaa_depth_t image);
int __ovld get_image_num_samples(write_only image2d_array_msaa_depth_t image);
int __ovld get_image_num_samples(write_only image2d_array_msaa_t image);
int __ovld get_image_num_samples(write_only image2d_array_msaa_depth_t image);
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
int __ovld get_image_num_samples(read_write image2d_msaa_t image);
int __ovld get_image_num_samples(read_write image2d_msaa_depth_t image);
int __ovld get_image_num_samples(read_write image2d_array_msaa_depth_t image);
int __ovld get_image_num_samples(read_write image2d_array_msaa_t image);
int __ovld get_image_num_samples(read_write image2d_array_msaa_depth_t image);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
#endif
// OpenCL v2.0 s6.13.15 - Work-group Functions
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
int __ovld __conv work_group_all(int predicate);
int __ovld __conv work_group_any(int predicate);
#ifdef cl_khr_fp16
half __ovld __conv work_group_broadcast(half a, size_t local_id);
half __ovld __conv work_group_broadcast(half a, size_t x, size_t y);
half __ovld __conv work_group_broadcast(half a, size_t x, size_t y, size_t z);
#endif
int __ovld __conv work_group_broadcast(int a, size_t local_id);
int __ovld __conv work_group_broadcast(int a, size_t x, size_t y);
int __ovld __conv work_group_broadcast(int a, size_t x, size_t y, size_t z);
uint __ovld __conv work_group_broadcast(uint a, size_t local_id);
uint __ovld __conv work_group_broadcast(uint a, size_t x, size_t y);
uint __ovld __conv work_group_broadcast(uint a, size_t x, size_t y, size_t z);
long __ovld __conv work_group_broadcast(long a, size_t local_id);
long __ovld __conv work_group_broadcast(long a, size_t x, size_t y);
long __ovld __conv work_group_broadcast(long a, size_t x, size_t y, size_t z);
ulong __ovld __conv work_group_broadcast(ulong a, size_t local_id);
ulong __ovld __conv work_group_broadcast(ulong a, size_t x, size_t y);
ulong __ovld __conv work_group_broadcast(ulong a, size_t x, size_t y, size_t z);
float __ovld __conv work_group_broadcast(float a, size_t local_id);
float __ovld __conv work_group_broadcast(float a, size_t x, size_t y);
float __ovld __conv work_group_broadcast(float a, size_t x, size_t y, size_t z);
#ifdef cl_khr_fp64
double __ovld __conv work_group_broadcast(double a, size_t local_id);
double __ovld __conv work_group_broadcast(double a, size_t x, size_t y);
double __ovld __conv work_group_broadcast(double a, size_t x, size_t y, size_t z);
#endif //cl_khr_fp64
#ifdef cl_khr_fp16
half __ovld __conv work_group_reduce_add(half x);
half __ovld __conv work_group_reduce_min(half x);
half __ovld __conv work_group_reduce_max(half x);
half __ovld __conv work_group_scan_exclusive_add(half x);
half __ovld __conv work_group_scan_exclusive_min(half x);
half __ovld __conv work_group_scan_exclusive_max(half x);
half __ovld __conv work_group_scan_inclusive_add(half x);
half __ovld __conv work_group_scan_inclusive_min(half x);
half __ovld __conv work_group_scan_inclusive_max(half x);
#endif
int __ovld __conv work_group_reduce_add(int x);
int __ovld __conv work_group_reduce_min(int x);
int __ovld __conv work_group_reduce_max(int x);
int __ovld __conv work_group_scan_exclusive_add(int x);
int __ovld __conv work_group_scan_exclusive_min(int x);
int __ovld __conv work_group_scan_exclusive_max(int x);
int __ovld __conv work_group_scan_inclusive_add(int x);
int __ovld __conv work_group_scan_inclusive_min(int x);
int __ovld __conv work_group_scan_inclusive_max(int x);
uint __ovld __conv work_group_reduce_add(uint x);
uint __ovld __conv work_group_reduce_min(uint x);
uint __ovld __conv work_group_reduce_max(uint x);
uint __ovld __conv work_group_scan_exclusive_add(uint x);
uint __ovld __conv work_group_scan_exclusive_min(uint x);
uint __ovld __conv work_group_scan_exclusive_max(uint x);
uint __ovld __conv work_group_scan_inclusive_add(uint x);
uint __ovld __conv work_group_scan_inclusive_min(uint x);
uint __ovld __conv work_group_scan_inclusive_max(uint x);
long __ovld __conv work_group_reduce_add(long x);
long __ovld __conv work_group_reduce_min(long x);
long __ovld __conv work_group_reduce_max(long x);
long __ovld __conv work_group_scan_exclusive_add(long x);
long __ovld __conv work_group_scan_exclusive_min(long x);
long __ovld __conv work_group_scan_exclusive_max(long x);
long __ovld __conv work_group_scan_inclusive_add(long x);
long __ovld __conv work_group_scan_inclusive_min(long x);
long __ovld __conv work_group_scan_inclusive_max(long x);
ulong __ovld __conv work_group_reduce_add(ulong x);
ulong __ovld __conv work_group_reduce_min(ulong x);
ulong __ovld __conv work_group_reduce_max(ulong x);
ulong __ovld __conv work_group_scan_exclusive_add(ulong x);
ulong __ovld __conv work_group_scan_exclusive_min(ulong x);
ulong __ovld __conv work_group_scan_exclusive_max(ulong x);
ulong __ovld __conv work_group_scan_inclusive_add(ulong x);
ulong __ovld __conv work_group_scan_inclusive_min(ulong x);
ulong __ovld __conv work_group_scan_inclusive_max(ulong x);
float __ovld __conv work_group_reduce_add(float x);
float __ovld __conv work_group_reduce_min(float x);
float __ovld __conv work_group_reduce_max(float x);
float __ovld __conv work_group_scan_exclusive_add(float x);
float __ovld __conv work_group_scan_exclusive_min(float x);
float __ovld __conv work_group_scan_exclusive_max(float x);
float __ovld __conv work_group_scan_inclusive_add(float x);
float __ovld __conv work_group_scan_inclusive_min(float x);
float __ovld __conv work_group_scan_inclusive_max(float x);
#ifdef cl_khr_fp64
double __ovld __conv work_group_reduce_add(double x);
double __ovld __conv work_group_reduce_min(double x);
double __ovld __conv work_group_reduce_max(double x);
double __ovld __conv work_group_scan_exclusive_add(double x);
double __ovld __conv work_group_scan_exclusive_min(double x);
double __ovld __conv work_group_scan_exclusive_max(double x);
double __ovld __conv work_group_scan_inclusive_add(double x);
double __ovld __conv work_group_scan_inclusive_min(double x);
double __ovld __conv work_group_scan_inclusive_max(double x);
#endif //cl_khr_fp64
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
// OpenCL v2.0 s6.13.16 - Pipe Functions
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
#define CLK_NULL_RESERVE_ID (__builtin_astype(((void*)(__SIZE_MAX__)), reserve_id_t))
bool __ovld is_valid_reserve_id(reserve_id_t reserve_id);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
// OpenCL v2.0 s6.13.17 - Enqueue Kernels
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
#define CL_COMPLETE 0x0
#define CL_RUNNING 0x1
#define CL_SUBMITTED 0x2
#define CL_QUEUED 0x3
#define CLK_SUCCESS 0
#define CLK_ENQUEUE_FAILURE -101
#define CLK_INVALID_QUEUE -102
#define CLK_INVALID_NDRANGE -160
#define CLK_INVALID_EVENT_WAIT_LIST -57
#define CLK_DEVICE_QUEUE_FULL -161
#define CLK_INVALID_ARG_SIZE -51
#define CLK_EVENT_ALLOCATION_FAILURE -100
#define CLK_OUT_OF_RESOURCES -5
#define CLK_NULL_QUEUE 0
#define CLK_NULL_EVENT (__builtin_astype(((void*)(__SIZE_MAX__)), clk_event_t))
// execution model related definitions
#define CLK_ENQUEUE_FLAGS_NO_WAIT 0x0
#define CLK_ENQUEUE_FLAGS_WAIT_KERNEL 0x1
#define CLK_ENQUEUE_FLAGS_WAIT_WORK_GROUP 0x2
typedef int kernel_enqueue_flags_t;
typedef int clk_profiling_info;
// Profiling info name (see capture_event_profiling_info)
#define CLK_PROFILING_COMMAND_EXEC_TIME 0x1
#define MAX_WORK_DIM 3
typedef struct {
unsigned int workDimension;
size_t globalWorkOffset[MAX_WORK_DIM];
size_t globalWorkSize[MAX_WORK_DIM];
size_t localWorkSize[MAX_WORK_DIM];
} ndrange_t;
ndrange_t __ovld ndrange_1D(size_t);
ndrange_t __ovld ndrange_1D(size_t, size_t);
ndrange_t __ovld ndrange_1D(size_t, size_t, size_t);
ndrange_t __ovld ndrange_2D(const size_t[2]);
ndrange_t __ovld ndrange_2D(const size_t[2], const size_t[2]);
ndrange_t __ovld ndrange_2D(const size_t[2], const size_t[2], const size_t[2]);
ndrange_t __ovld ndrange_3D(const size_t[3]);
ndrange_t __ovld ndrange_3D(const size_t[3], const size_t[3]);
ndrange_t __ovld ndrange_3D(const size_t[3], const size_t[3], const size_t[3]);
int __ovld enqueue_marker(queue_t, uint, const __private clk_event_t*, __private clk_event_t*);
void __ovld retain_event(clk_event_t);
void __ovld release_event(clk_event_t);
clk_event_t __ovld create_user_event(void);
void __ovld set_user_event_status(clk_event_t e, int state);
bool __ovld is_valid_event (clk_event_t event);
void __ovld capture_event_profiling_info(clk_event_t, clk_profiling_info, __global void* value);
queue_t __ovld get_default_queue(void);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
// OpenCL Extension v2.0 s9.17 - Sub-groups
#if defined(cl_intel_subgroups) || defined(cl_khr_subgroups)
// Shared Sub Group Functions
uint __ovld get_sub_group_size(void);
uint __ovld get_max_sub_group_size(void);
uint __ovld get_num_sub_groups(void);
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
uint __ovld get_enqueued_num_sub_groups(void);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
uint __ovld get_sub_group_id(void);
uint __ovld get_sub_group_local_id(void);
void __ovld __conv sub_group_barrier(cl_mem_fence_flags flags);
#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0
void __ovld __conv sub_group_barrier(cl_mem_fence_flags flags, memory_scope scope);
#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0
int __ovld __conv sub_group_all(int predicate);
int __ovld __conv sub_group_any(int predicate);
int __ovld __conv sub_group_broadcast(int x, uint sub_group_local_id);
uint __ovld __conv sub_group_broadcast(uint x, uint sub_group_local_id);
long __ovld __conv sub_group_broadcast(long x, uint sub_group_local_id);
ulong __ovld __conv sub_group_broadcast(ulong x, uint sub_group_local_id);
float __ovld __conv sub_group_broadcast(float x, uint sub_group_local_id);
int __ovld __conv sub_group_reduce_add(int x);
uint __ovld __conv sub_group_reduce_add(uint x);
long __ovld __conv sub_group_reduce_add(long x);
ulong __ovld __conv sub_group_reduce_add(ulong x);
float __ovld __conv sub_group_reduce_add(float x);
int __ovld __conv sub_group_reduce_min(int x);
uint __ovld __conv sub_group_reduce_min(uint x);
long __ovld __conv sub_group_reduce_min(long x);
ulong __ovld __conv sub_group_reduce_min(ulong x);
float __ovld __conv sub_group_reduce_min(float x);
int __ovld __conv sub_group_reduce_max(int x);
uint __ovld __conv sub_group_reduce_max(uint x);
long __ovld __conv sub_group_reduce_max(long x);
ulong __ovld __conv sub_group_reduce_max(ulong x);
float __ovld __conv sub_group_reduce_max(float x);
int __ovld __conv sub_group_scan_exclusive_add(int x);
uint __ovld __conv sub_group_scan_exclusive_add(uint x);
long __ovld __conv sub_group_scan_exclusive_add(long x);
ulong __ovld __conv sub_group_scan_exclusive_add(ulong x);
float __ovld __conv sub_group_scan_exclusive_add(float x);
int __ovld __conv sub_group_scan_exclusive_min(int x);
uint __ovld __conv sub_group_scan_exclusive_min(uint x);
long __ovld __conv sub_group_scan_exclusive_min(long x);
ulong __ovld __conv sub_group_scan_exclusive_min(ulong x);
float __ovld __conv sub_group_scan_exclusive_min(float x);
int __ovld __conv sub_group_scan_exclusive_max(int x);
uint __ovld __conv sub_group_scan_exclusive_max(uint x);
long __ovld __conv sub_group_scan_exclusive_max(long x);
ulong __ovld __conv sub_group_scan_exclusive_max(ulong x);
float __ovld __conv sub_group_scan_exclusive_max(float x);
int __ovld __conv sub_group_scan_inclusive_add(int x);
uint __ovld __conv sub_group_scan_inclusive_add(uint x);
long __ovld __conv sub_group_scan_inclusive_add(long x);
ulong __ovld __conv sub_group_scan_inclusive_add(ulong x);
float __ovld __conv sub_group_scan_inclusive_add(float x);
int __ovld __conv sub_group_scan_inclusive_min(int x);
uint __ovld __conv sub_group_scan_inclusive_min(uint x);
long __ovld __conv sub_group_scan_inclusive_min(long x);
ulong __ovld __conv sub_group_scan_inclusive_min(ulong x);
float __ovld __conv sub_group_scan_inclusive_min(float x);
int __ovld __conv sub_group_scan_inclusive_max(int x);
uint __ovld __conv sub_group_scan_inclusive_max(uint x);
long __ovld __conv sub_group_scan_inclusive_max(long x);
ulong __ovld __conv sub_group_scan_inclusive_max(ulong x);
float __ovld __conv sub_group_scan_inclusive_max(float x);
#ifdef cl_khr_fp16
half __ovld __conv sub_group_broadcast(half x, uint sub_group_local_id);
half __ovld __conv sub_group_reduce_add(half x);
half __ovld __conv sub_group_reduce_min(half x);
half __ovld __conv sub_group_reduce_max(half x);
half __ovld __conv sub_group_scan_exclusive_add(half x);
half __ovld __conv sub_group_scan_exclusive_min(half x);
half __ovld __conv sub_group_scan_exclusive_max(half x);
half __ovld __conv sub_group_scan_inclusive_add(half x);
half __ovld __conv sub_group_scan_inclusive_min(half x);
half __ovld __conv sub_group_scan_inclusive_max(half x);
#endif //cl_khr_fp16
#ifdef cl_khr_fp64
double __ovld __conv sub_group_broadcast(double x, uint sub_group_local_id);
double __ovld __conv sub_group_reduce_add(double x);
double __ovld __conv sub_group_reduce_min(double x);
double __ovld __conv sub_group_reduce_max(double x);
double __ovld __conv sub_group_scan_exclusive_add(double x);
double __ovld __conv sub_group_scan_exclusive_min(double x);
double __ovld __conv sub_group_scan_exclusive_max(double x);
double __ovld __conv sub_group_scan_inclusive_add(double x);
double __ovld __conv sub_group_scan_inclusive_min(double x);
double __ovld __conv sub_group_scan_inclusive_max(double x);
#endif //cl_khr_fp64
#endif //cl_khr_subgroups cl_intel_subgroups
#if defined(cl_intel_subgroups)
// Intel-Specific Sub Group Functions
float __ovld __conv intel_sub_group_shuffle( float x, uint c );
float2 __ovld __conv intel_sub_group_shuffle( float2 x, uint c );
float3 __ovld __conv intel_sub_group_shuffle( float3 x, uint c );
float4 __ovld __conv intel_sub_group_shuffle( float4 x, uint c );
float8 __ovld __conv intel_sub_group_shuffle( float8 x, uint c );
float16 __ovld __conv intel_sub_group_shuffle( float16 x, uint c );
int __ovld __conv intel_sub_group_shuffle( int x, uint c );
int2 __ovld __conv intel_sub_group_shuffle( int2 x, uint c );
int3 __ovld __conv intel_sub_group_shuffle( int3 x, uint c );
int4 __ovld __conv intel_sub_group_shuffle( int4 x, uint c );
int8 __ovld __conv intel_sub_group_shuffle( int8 x, uint c );
int16 __ovld __conv intel_sub_group_shuffle( int16 x, uint c );
uint __ovld __conv intel_sub_group_shuffle( uint x, uint c );
uint2 __ovld __conv intel_sub_group_shuffle( uint2 x, uint c );
uint3 __ovld __conv intel_sub_group_shuffle( uint3 x, uint c );
uint4 __ovld __conv intel_sub_group_shuffle( uint4 x, uint c );
uint8 __ovld __conv intel_sub_group_shuffle( uint8 x, uint c );
uint16 __ovld __conv intel_sub_group_shuffle( uint16 x, uint c );
long __ovld __conv intel_sub_group_shuffle( long x, uint c );
ulong __ovld __conv intel_sub_group_shuffle( ulong x, uint c );
float __ovld __conv intel_sub_group_shuffle_down( float cur, float next, uint c );
float2 __ovld __conv intel_sub_group_shuffle_down( float2 cur, float2 next, uint c );
float3 __ovld __conv intel_sub_group_shuffle_down( float3 cur, float3 next, uint c );
float4 __ovld __conv intel_sub_group_shuffle_down( float4 cur, float4 next, uint c );
float8 __ovld __conv intel_sub_group_shuffle_down( float8 cur, float8 next, uint c );
float16 __ovld __conv intel_sub_group_shuffle_down( float16 cur, float16 next, uint c );
int __ovld __conv intel_sub_group_shuffle_down( int cur, int next, uint c );
int2 __ovld __conv intel_sub_group_shuffle_down( int2 cur, int2 next, uint c );
int3 __ovld __conv intel_sub_group_shuffle_down( int3 cur, int3 next, uint c );
int4 __ovld __conv intel_sub_group_shuffle_down( int4 cur, int4 next, uint c );
int8 __ovld __conv intel_sub_group_shuffle_down( int8 cur, int8 next, uint c );
int16 __ovld __conv intel_sub_group_shuffle_down( int16 cur, int16 next, uint c );
uint __ovld __conv intel_sub_group_shuffle_down( uint cur, uint next, uint c );
uint2 __ovld __conv intel_sub_group_shuffle_down( uint2 cur, uint2 next, uint c );
uint3 __ovld __conv intel_sub_group_shuffle_down( uint3 cur, uint3 next, uint c );
uint4 __ovld __conv intel_sub_group_shuffle_down( uint4 cur, uint4 next, uint c );
uint8 __ovld __conv intel_sub_group_shuffle_down( uint8 cur, uint8 next, uint c );
uint16 __ovld __conv intel_sub_group_shuffle_down( uint16 cur, uint16 next, uint c );
long __ovld __conv intel_sub_group_shuffle_down( long prev, long cur, uint c );
ulong __ovld __conv intel_sub_group_shuffle_down( ulong prev, ulong cur, uint c );
float __ovld __conv intel_sub_group_shuffle_up( float prev, float cur, uint c );
float2 __ovld __conv intel_sub_group_shuffle_up( float2 prev, float2 cur, uint c );
float3 __ovld __conv intel_sub_group_shuffle_up( float3 prev, float3 cur, uint c );
float4 __ovld __conv intel_sub_group_shuffle_up( float4 prev, float4 cur, uint c );
float8 __ovld __conv intel_sub_group_shuffle_up( float8 prev, float8 cur, uint c );
float16 __ovld __conv intel_sub_group_shuffle_up( float16 prev, float16 cur, uint c );
int __ovld __conv intel_sub_group_shuffle_up( int prev, int cur, uint c );
int2 __ovld __conv intel_sub_group_shuffle_up( int2 prev, int2 cur, uint c );
int3 __ovld __conv intel_sub_group_shuffle_up( int3 prev, int3 cur, uint c );
int4 __ovld __conv intel_sub_group_shuffle_up( int4 prev, int4 cur, uint c );
int8 __ovld __conv intel_sub_group_shuffle_up( int8 prev, int8 cur, uint c );
int16 __ovld __conv intel_sub_group_shuffle_up( int16 prev, int16 cur, uint c );
uint __ovld __conv intel_sub_group_shuffle_up( uint prev, uint cur, uint c );
uint2 __ovld __conv intel_sub_group_shuffle_up( uint2 prev, uint2 cur, uint c );
uint3 __ovld __conv intel_sub_group_shuffle_up( uint3 prev, uint3 cur, uint c );
uint4 __ovld __conv intel_sub_group_shuffle_up( uint4 prev, uint4 cur, uint c );
uint8 __ovld __conv intel_sub_group_shuffle_up( uint8 prev, uint8 cur, uint c );
uint16 __ovld __conv intel_sub_group_shuffle_up( uint16 prev, uint16 cur, uint c );
long __ovld __conv intel_sub_group_shuffle_up( long prev, long cur, uint c );
ulong __ovld __conv intel_sub_group_shuffle_up( ulong prev, ulong cur, uint c );
float __ovld __conv intel_sub_group_shuffle_xor( float x, uint c );
float2 __ovld __conv intel_sub_group_shuffle_xor( float2 x, uint c );
float3 __ovld __conv intel_sub_group_shuffle_xor( float3 x, uint c );
float4 __ovld __conv intel_sub_group_shuffle_xor( float4 x, uint c );
float8 __ovld __conv intel_sub_group_shuffle_xor( float8 x, uint c );
float16 __ovld __conv intel_sub_group_shuffle_xor( float16 x, uint c );
int __ovld __conv intel_sub_group_shuffle_xor( int x, uint c );
int2 __ovld __conv intel_sub_group_shuffle_xor( int2 x, uint c );
int3 __ovld __conv intel_sub_group_shuffle_xor( int3 x, uint c );
int4 __ovld __conv intel_sub_group_shuffle_xor( int4 x, uint c );
int8 __ovld __conv intel_sub_group_shuffle_xor( int8 x, uint c );
int16 __ovld __conv intel_sub_group_shuffle_xor( int16 x, uint c );
uint __ovld __conv intel_sub_group_shuffle_xor( uint x, uint c );
uint2 __ovld __conv intel_sub_group_shuffle_xor( uint2 x, uint c );
uint3 __ovld __conv intel_sub_group_shuffle_xor( uint3 x, uint c );
uint4 __ovld __conv intel_sub_group_shuffle_xor( uint4 x, uint c );
uint8 __ovld __conv intel_sub_group_shuffle_xor( uint8 x, uint c );
uint16 __ovld __conv intel_sub_group_shuffle_xor( uint16 x, uint c );
long __ovld __conv intel_sub_group_shuffle_xor( long x, uint c );
ulong __ovld __conv intel_sub_group_shuffle_xor( ulong x, uint c );
uint __ovld __conv intel_sub_group_block_read( read_only image2d_t image, int2 coord );
uint2 __ovld __conv intel_sub_group_block_read2( read_only image2d_t image, int2 coord );
uint4 __ovld __conv intel_sub_group_block_read4( read_only image2d_t image, int2 coord );
uint8 __ovld __conv intel_sub_group_block_read8( read_only image2d_t image, int2 coord );
#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
uint __ovld __conv intel_sub_group_block_read(read_write image2d_t image, int2 coord);
uint2 __ovld __conv intel_sub_group_block_read2(read_write image2d_t image, int2 coord);
uint4 __ovld __conv intel_sub_group_block_read4(read_write image2d_t image, int2 coord);
uint8 __ovld __conv intel_sub_group_block_read8(read_write image2d_t image, int2 coord);
#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
uint __ovld __conv intel_sub_group_block_read( const __global uint* p );
uint2 __ovld __conv intel_sub_group_block_read2( const __global uint* p );
uint4 __ovld __conv intel_sub_group_block_read4( const __global uint* p );
uint8 __ovld __conv intel_sub_group_block_read8( const __global uint* p );
void __ovld __conv intel_sub_group_block_write(write_only image2d_t image, int2 coord, uint data);
void __ovld __conv intel_sub_group_block_write2(write_only image2d_t image, int2 coord, uint2 data);
void __ovld __conv intel_sub_group_block_write4(write_only image2d_t image, int2 coord, uint4 data);
void __ovld __conv intel_sub_group_block_write8(write_only image2d_t image, int2 coord, uint8 data);
#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
void __ovld __conv intel_sub_group_block_write(read_write image2d_t image, int2 coord, uint data);
void __ovld __conv intel_sub_group_block_write2(read_write image2d_t image, int2 coord, uint2 data);
void __ovld __conv intel_sub_group_block_write4(read_write image2d_t image, int2 coord, uint4 data);
void __ovld __conv intel_sub_group_block_write8(read_write image2d_t image, int2 coord, uint8 data);
#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
void __ovld __conv intel_sub_group_block_write( __global uint* p, uint data );
void __ovld __conv intel_sub_group_block_write2( __global uint* p, uint2 data );
void __ovld __conv intel_sub_group_block_write4( __global uint* p, uint4 data );
void __ovld __conv intel_sub_group_block_write8( __global uint* p, uint8 data );
#ifdef cl_khr_fp16
half __ovld __conv intel_sub_group_shuffle( half x, uint c );
half __ovld __conv intel_sub_group_shuffle_down( half prev, half cur, uint c );
half __ovld __conv intel_sub_group_shuffle_up( half prev, half cur, uint c );
half __ovld __conv intel_sub_group_shuffle_xor( half x, uint c );
#endif
#if defined(cl_khr_fp64)
double __ovld __conv intel_sub_group_shuffle( double x, uint c );
double __ovld __conv intel_sub_group_shuffle_down( double prev, double cur, uint c );
double __ovld __conv intel_sub_group_shuffle_up( double prev, double cur, uint c );
double __ovld __conv intel_sub_group_shuffle_xor( double x, uint c );
#endif
#endif //cl_intel_subgroups
#if defined(cl_intel_subgroups_short)
short __ovld __conv intel_sub_group_broadcast( short x, uint sub_group_local_id );
short2 __ovld __conv intel_sub_group_broadcast( short2 x, uint sub_group_local_id );
short3 __ovld __conv intel_sub_group_broadcast( short3 x, uint sub_group_local_id );
short4 __ovld __conv intel_sub_group_broadcast( short4 x, uint sub_group_local_id );
short8 __ovld __conv intel_sub_group_broadcast( short8 x, uint sub_group_local_id );
ushort __ovld __conv intel_sub_group_broadcast( ushort x, uint sub_group_local_id );
ushort2 __ovld __conv intel_sub_group_broadcast( ushort2 x, uint sub_group_local_id );
ushort3 __ovld __conv intel_sub_group_broadcast( ushort3 x, uint sub_group_local_id );
ushort4 __ovld __conv intel_sub_group_broadcast( ushort4 x, uint sub_group_local_id );
ushort8 __ovld __conv intel_sub_group_broadcast( ushort8 x, uint sub_group_local_id );
short __ovld __conv intel_sub_group_shuffle( short x, uint c );
short2 __ovld __conv intel_sub_group_shuffle( short2 x, uint c );
short3 __ovld __conv intel_sub_group_shuffle( short3 x, uint c );
short4 __ovld __conv intel_sub_group_shuffle( short4 x, uint c );
short8 __ovld __conv intel_sub_group_shuffle( short8 x, uint c );
short16 __ovld __conv intel_sub_group_shuffle( short16 x, uint c);
ushort __ovld __conv intel_sub_group_shuffle( ushort x, uint c );
ushort2 __ovld __conv intel_sub_group_shuffle( ushort2 x, uint c );
ushort3 __ovld __conv intel_sub_group_shuffle( ushort3 x, uint c );
ushort4 __ovld __conv intel_sub_group_shuffle( ushort4 x, uint c );
ushort8 __ovld __conv intel_sub_group_shuffle( ushort8 x, uint c );
ushort16 __ovld __conv intel_sub_group_shuffle( ushort16 x, uint c );
short __ovld __conv intel_sub_group_shuffle_down( short cur, short next, uint c );
short2 __ovld __conv intel_sub_group_shuffle_down( short2 cur, short2 next, uint c );
short3 __ovld __conv intel_sub_group_shuffle_down( short3 cur, short3 next, uint c );
short4 __ovld __conv intel_sub_group_shuffle_down( short4 cur, short4 next, uint c );
short8 __ovld __conv intel_sub_group_shuffle_down( short8 cur, short8 next, uint c );
short16 __ovld __conv intel_sub_group_shuffle_down( short16 cur, short16 next, uint c );
ushort __ovld __conv intel_sub_group_shuffle_down( ushort cur, ushort next, uint c );
ushort2 __ovld __conv intel_sub_group_shuffle_down( ushort2 cur, ushort2 next, uint c );
ushort3 __ovld __conv intel_sub_group_shuffle_down( ushort3 cur, ushort3 next, uint c );
ushort4 __ovld __conv intel_sub_group_shuffle_down( ushort4 cur, ushort4 next, uint c );
ushort8 __ovld __conv intel_sub_group_shuffle_down( ushort8 cur, ushort8 next, uint c );
ushort16 __ovld __conv intel_sub_group_shuffle_down( ushort16 cur, ushort16 next, uint c );
short __ovld __conv intel_sub_group_shuffle_up( short cur, short next, uint c );
short2 __ovld __conv intel_sub_group_shuffle_up( short2 cur, short2 next, uint c );
short3 __ovld __conv intel_sub_group_shuffle_up( short3 cur, short3 next, uint c );
short4 __ovld __conv intel_sub_group_shuffle_up( short4 cur, short4 next, uint c );
short8 __ovld __conv intel_sub_group_shuffle_up( short8 cur, short8 next, uint c );
short16 __ovld __conv intel_sub_group_shuffle_up( short16 cur, short16 next, uint c );
ushort __ovld __conv intel_sub_group_shuffle_up( ushort cur, ushort next, uint c );
ushort2 __ovld __conv intel_sub_group_shuffle_up( ushort2 cur, ushort2 next, uint c );
ushort3 __ovld __conv intel_sub_group_shuffle_up( ushort3 cur, ushort3 next, uint c );
ushort4 __ovld __conv intel_sub_group_shuffle_up( ushort4 cur, ushort4 next, uint c );
ushort8 __ovld __conv intel_sub_group_shuffle_up( ushort8 cur, ushort8 next, uint c );
ushort16 __ovld __conv intel_sub_group_shuffle_up( ushort16 cur, ushort16 next, uint c );
short __ovld __conv intel_sub_group_shuffle_xor( short x, uint c );
short2 __ovld __conv intel_sub_group_shuffle_xor( short2 x, uint c );
short3 __ovld __conv intel_sub_group_shuffle_xor( short3 x, uint c );
short4 __ovld __conv intel_sub_group_shuffle_xor( short4 x, uint c );
short8 __ovld __conv intel_sub_group_shuffle_xor( short8 x, uint c );
short16 __ovld __conv intel_sub_group_shuffle_xor( short16 x, uint c );
ushort __ovld __conv intel_sub_group_shuffle_xor( ushort x, uint c );
ushort2 __ovld __conv intel_sub_group_shuffle_xor( ushort2 x, uint c );
ushort3 __ovld __conv intel_sub_group_shuffle_xor( ushort3 x, uint c );
ushort4 __ovld __conv intel_sub_group_shuffle_xor( ushort4 x, uint c );
ushort8 __ovld __conv intel_sub_group_shuffle_xor( ushort8 x, uint c );
ushort16 __ovld __conv intel_sub_group_shuffle_xor( ushort16 x, uint c );
short __ovld __conv intel_sub_group_reduce_add( short x );
ushort __ovld __conv intel_sub_group_reduce_add( ushort x );
short __ovld __conv intel_sub_group_reduce_min( short x );
ushort __ovld __conv intel_sub_group_reduce_min( ushort x );
short __ovld __conv intel_sub_group_reduce_max( short x );
ushort __ovld __conv intel_sub_group_reduce_max( ushort x );
short __ovld __conv intel_sub_group_scan_exclusive_add( short x );
ushort __ovld __conv intel_sub_group_scan_exclusive_add( ushort x );
short __ovld __conv intel_sub_group_scan_exclusive_min( short x );
ushort __ovld __conv intel_sub_group_scan_exclusive_min( ushort x );
short __ovld __conv intel_sub_group_scan_exclusive_max( short x );
ushort __ovld __conv intel_sub_group_scan_exclusive_max( ushort x );
short __ovld __conv intel_sub_group_scan_inclusive_add( short x );
ushort __ovld __conv intel_sub_group_scan_inclusive_add( ushort x );
short __ovld __conv intel_sub_group_scan_inclusive_min( short x );
ushort __ovld __conv intel_sub_group_scan_inclusive_min( ushort x );
short __ovld __conv intel_sub_group_scan_inclusive_max( short x );
ushort __ovld __conv intel_sub_group_scan_inclusive_max( ushort x );
uint __ovld __conv intel_sub_group_block_read_ui( read_only image2d_t image, int2 byte_coord );
uint2 __ovld __conv intel_sub_group_block_read_ui2( read_only image2d_t image, int2 byte_coord );
uint4 __ovld __conv intel_sub_group_block_read_ui4( read_only image2d_t image, int2 byte_coord );
uint8 __ovld __conv intel_sub_group_block_read_ui8( read_only image2d_t image, int2 byte_coord );
#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
uint __ovld __conv intel_sub_group_block_read_ui( read_write image2d_t image, int2 byte_coord );
uint2 __ovld __conv intel_sub_group_block_read_ui2( read_write image2d_t image, int2 byte_coord );
uint4 __ovld __conv intel_sub_group_block_read_ui4( read_write image2d_t image, int2 byte_coord );
uint8 __ovld __conv intel_sub_group_block_read_ui8( read_write image2d_t image, int2 byte_coord );
#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
uint __ovld __conv intel_sub_group_block_read_ui( const __global uint* p );
uint2 __ovld __conv intel_sub_group_block_read_ui2( const __global uint* p );
uint4 __ovld __conv intel_sub_group_block_read_ui4( const __global uint* p );
uint8 __ovld __conv intel_sub_group_block_read_ui8( const __global uint* p );
void __ovld __conv intel_sub_group_block_write_ui( read_only image2d_t image, int2 byte_coord, uint data );
void __ovld __conv intel_sub_group_block_write_ui2( read_only image2d_t image, int2 byte_coord, uint2 data );
void __ovld __conv intel_sub_group_block_write_ui4( read_only image2d_t image, int2 byte_coord, uint4 data );
void __ovld __conv intel_sub_group_block_write_ui8( read_only image2d_t image, int2 byte_coord, uint8 data );
#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
void __ovld __conv intel_sub_group_block_write_ui( read_write image2d_t image, int2 byte_coord, uint data );
void __ovld __conv intel_sub_group_block_write_ui2( read_write image2d_t image, int2 byte_coord, uint2 data );
void __ovld __conv intel_sub_group_block_write_ui4( read_write image2d_t image, int2 byte_coord, uint4 data );
void __ovld __conv intel_sub_group_block_write_ui8( read_write image2d_t image, int2 byte_coord, uint8 data );
#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
void __ovld __conv intel_sub_group_block_write_ui( __global uint* p, uint data );
void __ovld __conv intel_sub_group_block_write_ui2( __global uint* p, uint2 data );
void __ovld __conv intel_sub_group_block_write_ui4( __global uint* p, uint4 data );
void __ovld __conv intel_sub_group_block_write_ui8( __global uint* p, uint8 data );
ushort __ovld __conv intel_sub_group_block_read_us( read_only image2d_t image, int2 coord );
ushort2 __ovld __conv intel_sub_group_block_read_us2( read_only image2d_t image, int2 coord );
ushort4 __ovld __conv intel_sub_group_block_read_us4( read_only image2d_t image, int2 coord );
ushort8 __ovld __conv intel_sub_group_block_read_us8( read_only image2d_t image, int2 coord );
#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
ushort __ovld __conv intel_sub_group_block_read_us(read_write image2d_t image, int2 coord);
ushort2 __ovld __conv intel_sub_group_block_read_us2(read_write image2d_t image, int2 coord);
ushort4 __ovld __conv intel_sub_group_block_read_us4(read_write image2d_t image, int2 coord);
ushort8 __ovld __conv intel_sub_group_block_read_us8(read_write image2d_t image, int2 coord);
#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
ushort __ovld __conv intel_sub_group_block_read_us( const __global ushort* p );
ushort2 __ovld __conv intel_sub_group_block_read_us2( const __global ushort* p );
ushort4 __ovld __conv intel_sub_group_block_read_us4( const __global ushort* p );
ushort8 __ovld __conv intel_sub_group_block_read_us8( const __global ushort* p );
void __ovld __conv intel_sub_group_block_write_us(write_only image2d_t image, int2 coord, ushort data);
void __ovld __conv intel_sub_group_block_write_us2(write_only image2d_t image, int2 coord, ushort2 data);
void __ovld __conv intel_sub_group_block_write_us4(write_only image2d_t image, int2 coord, ushort4 data);
void __ovld __conv intel_sub_group_block_write_us8(write_only image2d_t image, int2 coord, ushort8 data);
#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
void __ovld __conv intel_sub_group_block_write_us(read_write image2d_t image, int2 coord, ushort data);
void __ovld __conv intel_sub_group_block_write_us2(read_write image2d_t image, int2 coord, ushort2 data);
void __ovld __conv intel_sub_group_block_write_us4(read_write image2d_t image, int2 coord, ushort4 data);
void __ovld __conv intel_sub_group_block_write_us8(read_write image2d_t image, int2 coord, ushort8 data);
#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0)
void __ovld __conv intel_sub_group_block_write_us( __global ushort* p, ushort data );
void __ovld __conv intel_sub_group_block_write_us2( __global ushort* p, ushort2 data );
void __ovld __conv intel_sub_group_block_write_us4( __global ushort* p, ushort4 data );
void __ovld __conv intel_sub_group_block_write_us8( __global ushort* p, ushort8 data );
#endif // cl_intel_subgroups_short
#ifdef cl_intel_device_side_avc_motion_estimation
#pragma OPENCL EXTENSION cl_intel_device_side_avc_motion_estimation : begin
#define CLK_AVC_ME_MAJOR_16x16_INTEL 0x0
#define CLK_AVC_ME_MAJOR_16x8_INTEL 0x1
#define CLK_AVC_ME_MAJOR_8x16_INTEL 0x2
#define CLK_AVC_ME_MAJOR_8x8_INTEL 0x3
#define CLK_AVC_ME_MINOR_8x8_INTEL 0x0
#define CLK_AVC_ME_MINOR_8x4_INTEL 0x1
#define CLK_AVC_ME_MINOR_4x8_INTEL 0x2
#define CLK_AVC_ME_MINOR_4x4_INTEL 0x3
#define CLK_AVC_ME_MAJOR_FORWARD_INTEL 0x0
#define CLK_AVC_ME_MAJOR_BACKWARD_INTEL 0x1
#define CLK_AVC_ME_MAJOR_BIDIRECTIONAL_INTEL 0x2
#define CLK_AVC_ME_PARTITION_MASK_ALL_INTEL 0x0
#define CLK_AVC_ME_PARTITION_MASK_16x16_INTEL 0x7E
#define CLK_AVC_ME_PARTITION_MASK_16x8_INTEL 0x7D
#define CLK_AVC_ME_PARTITION_MASK_8x16_INTEL 0x7B
#define CLK_AVC_ME_PARTITION_MASK_8x8_INTEL 0x77
#define CLK_AVC_ME_PARTITION_MASK_8x4_INTEL 0x6F
#define CLK_AVC_ME_PARTITION_MASK_4x8_INTEL 0x5F
#define CLK_AVC_ME_PARTITION_MASK_4x4_INTEL 0x3F
#define CLK_AVC_ME_SLICE_TYPE_PRED_INTEL 0x0
#define CLK_AVC_ME_SLICE_TYPE_BPRED_INTEL 0x1
#define CLK_AVC_ME_SLICE_TYPE_INTRA_INTEL 0x2
#define CLK_AVC_ME_SEARCH_WINDOW_EXHAUSTIVE_INTEL 0x0
#define CLK_AVC_ME_SEARCH_WINDOW_SMALL_INTEL 0x1
#define CLK_AVC_ME_SEARCH_WINDOW_TINY_INTEL 0x2
#define CLK_AVC_ME_SEARCH_WINDOW_EXTRA_TINY_INTEL 0x3
#define CLK_AVC_ME_SEARCH_WINDOW_DIAMOND_INTEL 0x4
#define CLK_AVC_ME_SEARCH_WINDOW_LARGE_DIAMOND_INTEL 0x5
#define CLK_AVC_ME_SEARCH_WINDOW_RESERVED0_INTEL 0x6
#define CLK_AVC_ME_SEARCH_WINDOW_RESERVED1_INTEL 0x7
#define CLK_AVC_ME_SEARCH_WINDOW_CUSTOM_INTEL 0x8
#define CLK_AVC_ME_SAD_ADJUST_MODE_NONE_INTEL 0x0
#define CLK_AVC_ME_SAD_ADJUST_MODE_HAAR_INTEL 0x2
#define CLK_AVC_ME_SUBPIXEL_MODE_INTEGER_INTEL 0x0
#define CLK_AVC_ME_SUBPIXEL_MODE_HPEL_INTEL 0x1
#define CLK_AVC_ME_SUBPIXEL_MODE_QPEL_INTEL 0x3
#define CLK_AVC_ME_COST_PRECISION_QPEL_INTEL 0x0
#define CLK_AVC_ME_COST_PRECISION_HPEL_INTEL 0x1
#define CLK_AVC_ME_COST_PRECISION_PEL_INTEL 0x2
#define CLK_AVC_ME_COST_PRECISION_DPEL_INTEL 0x3
#define CLK_AVC_ME_BIDIR_WEIGHT_QUARTER_INTEL 0x10
#define CLK_AVC_ME_BIDIR_WEIGHT_THIRD_INTEL 0x15
#define CLK_AVC_ME_BIDIR_WEIGHT_HALF_INTEL 0x20
#define CLK_AVC_ME_BIDIR_WEIGHT_TWO_THIRD_INTEL 0x2B
#define CLK_AVC_ME_BIDIR_WEIGHT_THREE_QUARTER_INTEL 0x30
#define CLK_AVC_ME_BORDER_REACHED_LEFT_INTEL 0x0
#define CLK_AVC_ME_BORDER_REACHED_RIGHT_INTEL 0x2
#define CLK_AVC_ME_BORDER_REACHED_TOP_INTEL 0x4
#define CLK_AVC_ME_BORDER_REACHED_BOTTOM_INTEL 0x8
#define CLK_AVC_ME_INTRA_16x16_INTEL 0x0
#define CLK_AVC_ME_INTRA_8x8_INTEL 0x1
#define CLK_AVC_ME_INTRA_4x4_INTEL 0x2
#define CLK_AVC_ME_SKIP_BLOCK_PARTITION_16x16_INTEL 0x0
#define CLK_AVC_ME_SKIP_BLOCK_PARTITION_8x8_INTEL 0x4000
#define CLK_AVC_ME_SKIP_BLOCK_16x16_FORWARD_ENABLE_INTEL (0x1 << 24)
#define CLK_AVC_ME_SKIP_BLOCK_16x16_BACKWARD_ENABLE_INTEL (0x2 << 24)
#define CLK_AVC_ME_SKIP_BLOCK_16x16_DUAL_ENABLE_INTEL (0x3 << 24)
#define CLK_AVC_ME_SKIP_BLOCK_8x8_FORWARD_ENABLE_INTEL (0x55 << 24)
#define CLK_AVC_ME_SKIP_BLOCK_8x8_BACKWARD_ENABLE_INTEL (0xAA << 24)
#define CLK_AVC_ME_SKIP_BLOCK_8x8_DUAL_ENABLE_INTEL (0xFF << 24)
#define CLK_AVC_ME_SKIP_BLOCK_8x8_0_FORWARD_ENABLE_INTEL (0x1 << 24)
#define CLK_AVC_ME_SKIP_BLOCK_8x8_0_BACKWARD_ENABLE_INTEL (0x2 << 24)
#define CLK_AVC_ME_SKIP_BLOCK_8x8_1_FORWARD_ENABLE_INTEL (0x1 << 26)
#define CLK_AVC_ME_SKIP_BLOCK_8x8_1_BACKWARD_ENABLE_INTEL (0x2 << 26)
#define CLK_AVC_ME_SKIP_BLOCK_8x8_2_FORWARD_ENABLE_INTEL (0x1 << 28)
#define CLK_AVC_ME_SKIP_BLOCK_8x8_2_BACKWARD_ENABLE_INTEL (0x2 << 28)
#define CLK_AVC_ME_SKIP_BLOCK_8x8_3_FORWARD_ENABLE_INTEL (0x1 << 30)
#define CLK_AVC_ME_SKIP_BLOCK_8x8_3_BACKWARD_ENABLE_INTEL (0x2 << 30)
#define CLK_AVC_ME_BLOCK_BASED_SKIP_4x4_INTEL 0x00
#define CLK_AVC_ME_BLOCK_BASED_SKIP_8x8_INTEL 0x80
#define CLK_AVC_ME_INTRA_LUMA_PARTITION_MASK_ALL_INTEL 0x0
#define CLK_AVC_ME_INTRA_LUMA_PARTITION_MASK_16x16_INTEL 0x6
#define CLK_AVC_ME_INTRA_LUMA_PARTITION_MASK_8x8_INTEL 0x5
#define CLK_AVC_ME_INTRA_LUMA_PARTITION_MASK_4x4_INTEL 0x3
#define CLK_AVC_ME_INTRA_NEIGHBOR_LEFT_MASK_ENABLE_INTEL 0x60
#define CLK_AVC_ME_INTRA_NEIGHBOR_UPPER_MASK_ENABLE_INTEL 0x10
#define CLK_AVC_ME_INTRA_NEIGHBOR_UPPER_RIGHT_MASK_ENABLE_INTEL 0x8
#define CLK_AVC_ME_INTRA_NEIGHBOR_UPPER_LEFT_MASK_ENABLE_INTEL 0x4
#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_VERTICAL_INTEL 0x0
#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_HORIZONTAL_INTEL 0x1
#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_DC_INTEL 0x2
#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_DIAGONAL_DOWN_LEFT_INTEL 0x3
#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_DIAGONAL_DOWN_RIGHT_INTEL 0x4
#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_PLANE_INTEL 0x4
#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_VERTICAL_RIGHT_INTEL 0x5
#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_HORIZONTAL_DOWN_INTEL 0x6
#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_VERTICAL_LEFT_INTEL 0x7
#define CLK_AVC_ME_LUMA_PREDICTOR_MODE_HORIZONTAL_UP_INTEL 0x8
#define CLK_AVC_ME_CHROMA_PREDICTOR_MODE_DC_INTEL 0x0
#define CLK_AVC_ME_CHROMA_PREDICTOR_MODE_HORIZONTAL_INTEL 0x1
#define CLK_AVC_ME_CHROMA_PREDICTOR_MODE_VERTICAL_INTEL 0x2
#define CLK_AVC_ME_CHROMA_PREDICTOR_MODE_PLANE_INTEL 0x3
#define CLK_AVC_ME_FRAME_FORWARD_INTEL 0x1
#define CLK_AVC_ME_FRAME_BACKWARD_INTEL 0x2
#define CLK_AVC_ME_FRAME_DUAL_INTEL 0x3
#define CLK_AVC_ME_INTERLACED_SCAN_TOP_FIELD_INTEL 0x0
#define CLK_AVC_ME_INTERLACED_SCAN_BOTTOM_FIELD_INTEL 0x1
#define CLK_AVC_ME_INITIALIZE_INTEL 0x0
#define CLK_AVC_IME_PAYLOAD_INITIALIZE_INTEL 0x0
#define CLK_AVC_REF_PAYLOAD_INITIALIZE_INTEL 0x0
#define CLK_AVC_SIC_PAYLOAD_INITIALIZE_INTEL 0x0
#define CLK_AVC_IME_RESULT_INITIALIZE_INTEL 0x0
#define CLK_AVC_REF_RESULT_INITIALIZE_INTEL 0x0
#define CLK_AVC_SIC_RESULT_INITIALIZE_INTEL 0x0
#define CLK_AVC_IME_RESULT_SINGLE_REFERENCE_STREAMOUT_INITIALIZE_INTEL 0x0
#define CLK_AVC_IME_RESULT_SINGLE_REFERENCE_STREAMIN_INITIALIZE_INTEL 0x0
#define CLK_AVC_IME_RESULT_DUAL_REFERENCE_STREAMOUT_INITIALIZE_INTEL 0x0
#define CLK_AVC_IME_RESULT_DUAL_REFERENCE_STREAMIN_INITIALIZE_INTEL 0x0
// MCE built-in functions
uchar __ovld
intel_sub_group_avc_mce_get_default_inter_base_multi_reference_penalty(
uchar slice_type, uchar qp);
ulong __ovld intel_sub_group_avc_mce_get_default_inter_shape_penalty(
uchar slice_type, uchar qp);
uchar __ovld intel_sub_group_avc_mce_get_default_inter_direction_penalty(
uchar slice_type, uchar qp);
uint __ovld intel_sub_group_avc_mce_get_default_intra_luma_shape_penalty(
uchar slice_type, uchar qp);
uint2 __ovld
intel_sub_group_avc_mce_get_default_inter_motion_vector_cost_table(
uchar slice_type, uchar qp);
uchar __ovld intel_sub_group_avc_mce_get_default_intra_luma_mode_penalty(
uchar slice_type, uchar qp);
uint2 __ovld intel_sub_group_avc_mce_get_default_high_penalty_cost_table();
uint2 __ovld intel_sub_group_avc_mce_get_default_medium_penalty_cost_table();
uint2 __ovld intel_sub_group_avc_mce_get_default_low_penalty_cost_table();
uint __ovld intel_sub_group_avc_mce_get_default_non_dc_luma_intra_penalty();
uchar __ovld
intel_sub_group_avc_mce_get_default_intra_chroma_mode_base_penalty();
intel_sub_group_avc_mce_payload_t __ovld
intel_sub_group_avc_mce_set_inter_base_multi_reference_penalty(
uchar reference_base_penalty, intel_sub_group_avc_mce_payload_t payload);
intel_sub_group_avc_mce_payload_t __ovld
intel_sub_group_avc_mce_set_inter_shape_penalty(
ulong packed_shape_penalty, intel_sub_group_avc_mce_payload_t payload);
intel_sub_group_avc_mce_payload_t __ovld
intel_sub_group_avc_mce_set_inter_direction_penalty(
uchar direction_cost, intel_sub_group_avc_mce_payload_t payload);
intel_sub_group_avc_mce_payload_t __ovld
intel_sub_group_avc_mce_set_motion_vector_cost_function(
ulong packed_cost_center_delta, uint2 packed_cost_table,
uchar cost_precision, intel_sub_group_avc_mce_payload_t payload);
intel_sub_group_avc_mce_payload_t __ovld
intel_sub_group_avc_mce_set_ac_only_haar(
intel_sub_group_avc_mce_payload_t payload);
intel_sub_group_avc_mce_payload_t __ovld
intel_sub_group_avc_mce_set_source_interlaced_field_polarity(
uchar src_field_polarity, intel_sub_group_avc_mce_payload_t payload);
intel_sub_group_avc_mce_payload_t __ovld
intel_sub_group_avc_mce_set_single_reference_interlaced_field_polarity(
uchar ref_field_polarity, intel_sub_group_avc_mce_payload_t payload);
intel_sub_group_avc_mce_payload_t __ovld
intel_sub_group_avc_mce_set_dual_reference_interlaced_field_polarities(
uchar fwd_ref_field_polarity, uchar bwd_ref_field_polarity,
intel_sub_group_avc_mce_payload_t payload);
ulong __ovld intel_sub_group_avc_mce_get_motion_vectors(
intel_sub_group_avc_mce_result_t result);
ushort __ovld intel_sub_group_avc_mce_get_inter_distortions(
intel_sub_group_avc_mce_result_t result);
ushort __ovld intel_sub_group_avc_mce_get_best_inter_distortion(
intel_sub_group_avc_mce_result_t result);
uchar __ovld intel_sub_group_avc_mce_get_inter_major_shape(
intel_sub_group_avc_mce_result_t result);
uchar __ovld intel_sub_group_avc_mce_get_inter_minor_shapes(
intel_sub_group_avc_mce_result_t result);
uchar __ovld intel_sub_group_avc_mce_get_inter_directions(
intel_sub_group_avc_mce_result_t result);
uchar __ovld intel_sub_group_avc_mce_get_inter_motion_vector_count(
intel_sub_group_avc_mce_result_t result);
uint __ovld intel_sub_group_avc_mce_get_inter_reference_ids(
intel_sub_group_avc_mce_result_t result);
uchar __ovld
intel_sub_group_avc_mce_get_inter_reference_interlaced_field_polarities(
uint packed_reference_ids, uint packed_reference_parameter_field_polarities,
intel_sub_group_avc_mce_result_t result);
// IME built-in functions
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_initialize(
ushort2 src_coord, uchar partition_mask, uchar sad_adjustment);
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_set_single_reference(
short2 ref_offset, uchar search_window_config,
intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_set_dual_reference(
short2 fwd_ref_offset, short2 bwd_ref_offset, uchar search_window_config,
intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_set_max_motion_vector_count(
uchar max_motion_vector_count, intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_set_unidirectional_mix_disable(
intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_set_early_search_termination_threshold(
uchar threshold, intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_set_weighted_sad(
uint packed_sad_weights, intel_sub_group_avc_ime_payload_t payload);
__attribute__((deprecated("If you use the latest Intel driver, please use "
"intel_sub_group_avc_ime_ref_window_size instead",
"intel_sub_group_avc_ime_ref_window_size")))
ushort2 __ovld
intel_sub_group_ime_ref_window_size(uchar search_window_config, char dual_ref);
ushort2 __ovld intel_sub_group_avc_ime_ref_window_size(
uchar search_window_config, char dual_ref);
short2 __ovld intel_sub_group_avc_ime_adjust_ref_offset(
short2 ref_offset, ushort2 src_coord, ushort2 ref_window_size,
ushort2 image_size);
intel_sub_group_avc_ime_result_t __ovld
intel_sub_group_avc_ime_evaluate_with_single_reference(
read_only image2d_t src_image, read_only image2d_t ref_image,
sampler_t vme_media_sampler, intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ime_result_t __ovld
intel_sub_group_avc_ime_evaluate_with_dual_reference(
read_only image2d_t src_image, read_only image2d_t fwd_ref_image,
read_only image2d_t bwd_ref_image, sampler_t vme_media_sampler,
intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ime_result_single_reference_streamout_t __ovld
intel_sub_group_avc_ime_evaluate_with_single_reference_streamout(
read_only image2d_t src_image, read_only image2d_t ref_image,
sampler_t vme_media_sampler, intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ime_result_dual_reference_streamout_t __ovld
intel_sub_group_avc_ime_evaluate_with_dual_reference_streamout(
read_only image2d_t src_image, read_only image2d_t fwd_ref_image,
read_only image2d_t bwd_ref_image, sampler_t vme_media_sampler,
intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ime_result_t __ovld
intel_sub_group_avc_ime_evaluate_with_single_reference_streamin(
read_only image2d_t src_image, read_only image2d_t ref_image,
sampler_t vme_media_sampler, intel_sub_group_avc_ime_payload_t payload,
intel_sub_group_avc_ime_single_reference_streamin_t streamin_components);
intel_sub_group_avc_ime_result_t __ovld
intel_sub_group_avc_ime_evaluate_with_dual_reference_streamin(
read_only image2d_t src_image, read_only image2d_t fwd_ref_image,
read_only image2d_t bwd_ref_image, sampler_t vme_media_sampler,
intel_sub_group_avc_ime_payload_t payload,
intel_sub_group_avc_ime_dual_reference_streamin_t streamin_components);
intel_sub_group_avc_ime_result_single_reference_streamout_t __ovld
intel_sub_group_avc_ime_evaluate_with_single_reference_streaminout(
read_only image2d_t src_image, read_only image2d_t ref_image,
sampler_t vme_media_sampler, intel_sub_group_avc_ime_payload_t payload,
intel_sub_group_avc_ime_single_reference_streamin_t streamin_components);
intel_sub_group_avc_ime_result_dual_reference_streamout_t __ovld
intel_sub_group_avc_ime_evaluate_with_dual_reference_streaminout(
read_only image2d_t src_image, read_only image2d_t fwd_ref_image,
read_only image2d_t bwd_ref_image, sampler_t vme_media_sampler,
intel_sub_group_avc_ime_payload_t payload,
intel_sub_group_avc_ime_dual_reference_streamin_t streamin_components);
intel_sub_group_avc_ime_single_reference_streamin_t __ovld
intel_sub_group_avc_ime_get_single_reference_streamin(
intel_sub_group_avc_ime_result_single_reference_streamout_t result);
intel_sub_group_avc_ime_dual_reference_streamin_t __ovld
intel_sub_group_avc_ime_get_dual_reference_streamin(
intel_sub_group_avc_ime_result_dual_reference_streamout_t result);
intel_sub_group_avc_ime_result_t __ovld
intel_sub_group_avc_ime_strip_single_reference_streamout(
intel_sub_group_avc_ime_result_single_reference_streamout_t result);
intel_sub_group_avc_ime_result_t __ovld
intel_sub_group_avc_ime_strip_dual_reference_streamout(
intel_sub_group_avc_ime_result_dual_reference_streamout_t result);
uint __ovld intel_sub_group_avc_ime_get_streamout_major_shape_motion_vectors(
intel_sub_group_avc_ime_result_single_reference_streamout_t result,
uchar major_shape);
ushort __ovld intel_sub_group_avc_ime_get_streamout_major_shape_distortions(
intel_sub_group_avc_ime_result_single_reference_streamout_t result,
uchar major_shape);
uchar __ovld intel_sub_group_avc_ime_get_streamout_major_shape_reference_ids(
intel_sub_group_avc_ime_result_single_reference_streamout_t result,
uchar major_shape);
uint __ovld intel_sub_group_avc_ime_get_streamout_major_shape_motion_vectors(
intel_sub_group_avc_ime_result_dual_reference_streamout_t result,
uchar major_shape, uchar direction);
ushort __ovld intel_sub_group_avc_ime_get_streamout_major_shape_distortions(
intel_sub_group_avc_ime_result_dual_reference_streamout_t result,
uchar major_shape, uchar direction);
uchar __ovld intel_sub_group_avc_ime_get_streamout_major_shape_reference_ids(
intel_sub_group_avc_ime_result_dual_reference_streamout_t result,
uchar major_shape, uchar direction);
uchar __ovld intel_sub_group_avc_ime_get_border_reached(
uchar image_select, intel_sub_group_avc_ime_result_t result);
uchar __ovld intel_sub_group_avc_ime_get_truncated_search_indication(
intel_sub_group_avc_ime_result_t result);
uchar __ovld
intel_sub_group_avc_ime_get_unidirectional_early_search_termination(
intel_sub_group_avc_ime_result_t result);
uint __ovld intel_sub_group_avc_ime_get_weighting_pattern_minimum_motion_vector(
intel_sub_group_avc_ime_result_t result);
ushort __ovld intel_sub_group_avc_ime_get_weighting_pattern_minimum_distortion(
intel_sub_group_avc_ime_result_t result);
// REF built-in functions
intel_sub_group_avc_ref_payload_t __ovld
intel_sub_group_avc_fme_initialize(
ushort2 src_coord, ulong motion_vectors, uchar major_shapes,
uchar minor_shapes, uchar directions, uchar pixel_resolution,
uchar sad_adjustment);
intel_sub_group_avc_ref_payload_t __ovld
intel_sub_group_avc_bme_initialize(
ushort2 src_coord, ulong motion_vectors, uchar major_shapes,
uchar minor_shapes, uchar directions, uchar pixel_resolution,
uchar bidirectional_weight, uchar sad_adjustment);
intel_sub_group_avc_ref_payload_t __ovld
intel_sub_group_avc_ref_set_bidirectional_mix_disable(
intel_sub_group_avc_ref_payload_t payload);
intel_sub_group_avc_ref_payload_t __ovld
intel_sub_group_avc_ref_set_bilinear_filter_enable(
intel_sub_group_avc_ref_payload_t payload);
intel_sub_group_avc_ref_result_t __ovld
intel_sub_group_avc_ref_evaluate_with_single_reference(
read_only image2d_t src_image, read_only image2d_t ref_image,
sampler_t vme_media_sampler, intel_sub_group_avc_ref_payload_t payload);
intel_sub_group_avc_ref_result_t __ovld
intel_sub_group_avc_ref_evaluate_with_dual_reference(
read_only image2d_t src_image, read_only image2d_t fwd_ref_image,
read_only image2d_t bwd_ref_image, sampler_t vme_media_sampler,
intel_sub_group_avc_ref_payload_t payload);
intel_sub_group_avc_ref_result_t __ovld
intel_sub_group_avc_ref_evaluate_with_multi_reference(
read_only image2d_t src_image, uint packed_reference_ids,
sampler_t vme_media_sampler, intel_sub_group_avc_ref_payload_t payload);
intel_sub_group_avc_ref_result_t __ovld
intel_sub_group_avc_ref_evaluate_with_multi_reference(
read_only image2d_t src_image, uint packed_reference_ids,
uchar packed_reference_field_polarities, sampler_t vme_media_sampler,
intel_sub_group_avc_ref_payload_t payload);
// SIC built-in functions
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_initialize(
ushort2 src_coord);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_configure_skc(
uint skip_block_partition_type, uint skip_motion_vector_mask,
ulong motion_vectors, uchar bidirectional_weight, uchar skip_sad_adjustment,
intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_configure_ipe(
uchar luma_intra_partition_mask, uchar intra_neighbour_availabilty,
uchar left_edge_luma_pixels, uchar upper_left_corner_luma_pixel,
uchar upper_edge_luma_pixels, uchar upper_right_edge_luma_pixels,
uchar intra_sad_adjustment, intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_configure_ipe(
uchar luma_intra_partition_mask, uchar intra_neighbour_availabilty,
uchar left_edge_luma_pixels, uchar upper_left_corner_luma_pixel,
uchar upper_edge_luma_pixels, uchar upper_right_edge_luma_pixels,
ushort left_edge_chroma_pixels, ushort upper_left_corner_chroma_pixel,
ushort upper_edge_chroma_pixels, uchar intra_sad_adjustment,
intel_sub_group_avc_sic_payload_t payload);
uint __ovld
intel_sub_group_avc_sic_get_motion_vector_mask(
uint skip_block_partition_type, uchar direction);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_set_intra_luma_shape_penalty(
uint packed_shape_cost, intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_set_intra_luma_mode_cost_function(
uchar luma_mode_penalty, uint luma_packed_neighbor_modes,
uint luma_packed_non_dc_penalty, intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_set_intra_chroma_mode_cost_function(
uchar chroma_mode_penalty, intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_set_skc_bilinear_filter_enable(
intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_set_skc_forward_transform_enable(
ulong packed_sad_coefficients, intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_set_block_based_raw_skip_sad(
uchar block_based_skip_type,
intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_sic_result_t __ovld
intel_sub_group_avc_sic_evaluate_ipe(
read_only image2d_t src_image, sampler_t vme_media_sampler,
intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_sic_result_t __ovld
intel_sub_group_avc_sic_evaluate_with_single_reference(
read_only image2d_t src_image, read_only image2d_t ref_image,
sampler_t vme_media_sampler, intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_sic_result_t __ovld
intel_sub_group_avc_sic_evaluate_with_dual_reference(
read_only image2d_t src_image, read_only image2d_t fwd_ref_image,
read_only image2d_t bwd_ref_image, sampler_t vme_media_sampler,
intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_sic_result_t __ovld
intel_sub_group_avc_sic_evaluate_with_multi_reference(
read_only image2d_t src_image, uint packed_reference_ids,
sampler_t vme_media_sampler, intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_sic_result_t __ovld
intel_sub_group_avc_sic_evaluate_with_multi_reference(
read_only image2d_t src_image, uint packed_reference_ids,
uchar packed_reference_field_polarities, sampler_t vme_media_sampler,
intel_sub_group_avc_sic_payload_t payload);
uchar __ovld intel_sub_group_avc_sic_get_ipe_luma_shape(
intel_sub_group_avc_sic_result_t result);
ushort __ovld intel_sub_group_avc_sic_get_best_ipe_luma_distortion(
intel_sub_group_avc_sic_result_t result);
ushort __ovld intel_sub_group_avc_sic_get_best_ipe_chroma_distortion(
intel_sub_group_avc_sic_result_t result);
ulong __ovld intel_sub_group_avc_sic_get_packed_ipe_luma_modes(
intel_sub_group_avc_sic_result_t result);
uchar __ovld intel_sub_group_avc_sic_get_ipe_chroma_mode(
intel_sub_group_avc_sic_result_t result);
uint __ovld intel_sub_group_avc_sic_get_packed_skc_luma_count_threshold(
intel_sub_group_avc_sic_result_t result);
ulong __ovld intel_sub_group_avc_sic_get_packed_skc_luma_sum_threshold(
intel_sub_group_avc_sic_result_t result);
ushort __ovld intel_sub_group_avc_sic_get_inter_raw_sads(
intel_sub_group_avc_sic_result_t result);
// Wrappers
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_set_inter_base_multi_reference_penalty(
uchar reference_base_penalty, intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ref_payload_t __ovld
intel_sub_group_avc_ref_set_inter_base_multi_reference_penalty(
uchar reference_base_penalty, intel_sub_group_avc_ref_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_set_inter_base_multi_reference_penalty(
uchar reference_base_penalty, intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_set_inter_shape_penalty(
ulong packed_shape_cost, intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ref_payload_t __ovld
intel_sub_group_avc_ref_set_inter_shape_penalty(
ulong packed_shape_cost, intel_sub_group_avc_ref_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_set_inter_shape_penalty(
ulong packed_shape_cost, intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_set_inter_direction_penalty(
uchar direction_cost, intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ref_payload_t __ovld
intel_sub_group_avc_ref_set_inter_direction_penalty(
uchar direction_cost, intel_sub_group_avc_ref_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_set_inter_direction_penalty(
uchar direction_cost, intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_set_motion_vector_cost_function(
ulong packed_cost_center_delta, uint2 packed_cost_table,
uchar cost_precision, intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ref_payload_t __ovld
intel_sub_group_avc_ref_set_motion_vector_cost_function(
ulong packed_cost_center_delta, uint2 packed_cost_table,
uchar cost_precision, intel_sub_group_avc_ref_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_set_motion_vector_cost_function(
ulong packed_cost_center_delta, uint2 packed_cost_table,
uchar cost_precision, intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_set_source_interlaced_field_polarity(
uchar src_field_polarity, intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ref_payload_t __ovld
intel_sub_group_avc_ref_set_source_interlaced_field_polarity(
uchar src_field_polarity, intel_sub_group_avc_ref_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_set_source_interlaced_field_polarity(
uchar src_field_polarity, intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_set_single_reference_interlaced_field_polarity(
uchar ref_field_polarity, intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ref_payload_t __ovld
intel_sub_group_avc_ref_set_single_reference_interlaced_field_polarity(
uchar ref_field_polarity, intel_sub_group_avc_ref_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_set_single_reference_interlaced_field_polarity(
uchar ref_field_polarity, intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_set_dual_reference_interlaced_field_polarities(
uchar fwd_ref_field_polarity, uchar bwd_ref_field_polarity,
intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ref_payload_t __ovld
intel_sub_group_avc_ref_set_dual_reference_interlaced_field_polarities(
uchar fwd_ref_field_polarity, uchar bwd_ref_field_polarity,
intel_sub_group_avc_ref_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_set_dual_reference_interlaced_field_polarities(
uchar fwd_ref_field_polarity, uchar bwd_ref_field_polarity,
intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_ime_set_ac_only_haar(
intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ref_payload_t __ovld
intel_sub_group_avc_ref_set_ac_only_haar(
intel_sub_group_avc_ref_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_sic_set_ac_only_haar(
intel_sub_group_avc_sic_payload_t payload);
ulong __ovld intel_sub_group_avc_ime_get_motion_vectors(
intel_sub_group_avc_ime_result_t result);
ulong __ovld intel_sub_group_avc_ref_get_motion_vectors(
intel_sub_group_avc_ref_result_t result);
ushort __ovld intel_sub_group_avc_ime_get_inter_distortions(
intel_sub_group_avc_ime_result_t result);
ushort __ovld intel_sub_group_avc_ref_get_inter_distortions(
intel_sub_group_avc_ref_result_t result);
ushort __ovld intel_sub_group_avc_sic_get_inter_distortions(
intel_sub_group_avc_sic_result_t result);
ushort __ovld intel_sub_group_avc_ime_get_best_inter_distortion(
intel_sub_group_avc_ime_result_t result);
ushort __ovld intel_sub_group_avc_ref_get_best_inter_distortion(
intel_sub_group_avc_ref_result_t result);
uchar __ovld intel_sub_group_avc_ime_get_inter_major_shape(
intel_sub_group_avc_ime_result_t result);
uchar __ovld intel_sub_group_avc_ref_get_inter_major_shape(
intel_sub_group_avc_ref_result_t result);
uchar __ovld intel_sub_group_avc_ime_get_inter_minor_shapes(
intel_sub_group_avc_ime_result_t result);
uchar __ovld intel_sub_group_avc_ref_get_inter_minor_shapes(
intel_sub_group_avc_ref_result_t result);
uchar __ovld intel_sub_group_avc_ime_get_inter_directions(
intel_sub_group_avc_ime_result_t result);
uchar __ovld intel_sub_group_avc_ref_get_inter_directions(
intel_sub_group_avc_ref_result_t result);
uchar __ovld intel_sub_group_avc_ime_get_inter_motion_vector_count(
intel_sub_group_avc_ime_result_t result);
uchar __ovld intel_sub_group_avc_ref_get_inter_motion_vector_count(
intel_sub_group_avc_ref_result_t result);
uint __ovld intel_sub_group_avc_ime_get_inter_reference_ids(
intel_sub_group_avc_ime_result_t result);
uint __ovld intel_sub_group_avc_ref_get_inter_reference_ids(
intel_sub_group_avc_ref_result_t result);
uchar __ovld
intel_sub_group_avc_ime_get_inter_reference_interlaced_field_polarities(
uint packed_reference_ids, uint packed_reference_parameter_field_polarities,
intel_sub_group_avc_ime_result_t result);
uchar __ovld
intel_sub_group_avc_ref_get_inter_reference_interlaced_field_polarities(
uint packed_reference_ids, uint packed_reference_parameter_field_polarities,
intel_sub_group_avc_ref_result_t result);
// Type conversion functions
intel_sub_group_avc_mce_payload_t __ovld
intel_sub_group_avc_ime_convert_to_mce_payload(
intel_sub_group_avc_ime_payload_t payload);
intel_sub_group_avc_ime_payload_t __ovld
intel_sub_group_avc_mce_convert_to_ime_payload(
intel_sub_group_avc_mce_payload_t payload);
intel_sub_group_avc_mce_payload_t __ovld
intel_sub_group_avc_ref_convert_to_mce_payload(
intel_sub_group_avc_ref_payload_t payload);
intel_sub_group_avc_ref_payload_t __ovld
intel_sub_group_avc_mce_convert_to_ref_payload(
intel_sub_group_avc_mce_payload_t payload);
intel_sub_group_avc_mce_payload_t __ovld
intel_sub_group_avc_sic_convert_to_mce_payload(
intel_sub_group_avc_sic_payload_t payload);
intel_sub_group_avc_sic_payload_t __ovld
intel_sub_group_avc_mce_convert_to_sic_payload(
intel_sub_group_avc_mce_payload_t payload);
intel_sub_group_avc_mce_result_t __ovld
intel_sub_group_avc_ime_convert_to_mce_result(
intel_sub_group_avc_ime_result_t result);
intel_sub_group_avc_ime_result_t __ovld
intel_sub_group_avc_mce_convert_to_ime_result(
intel_sub_group_avc_mce_result_t result);
intel_sub_group_avc_mce_result_t __ovld
intel_sub_group_avc_ref_convert_to_mce_result(
intel_sub_group_avc_ref_result_t result);
intel_sub_group_avc_ref_result_t __ovld
intel_sub_group_avc_mce_convert_to_ref_result(
intel_sub_group_avc_mce_result_t result);
intel_sub_group_avc_mce_result_t __ovld
intel_sub_group_avc_sic_convert_to_mce_result(
intel_sub_group_avc_sic_result_t result);
intel_sub_group_avc_sic_result_t __ovld
intel_sub_group_avc_mce_convert_to_sic_result(
intel_sub_group_avc_mce_result_t result);
#pragma OPENCL EXTENSION cl_intel_device_side_avc_motion_estimation : end
#endif // cl_intel_device_side_avc_motion_estimation
#ifdef cl_amd_media_ops
uint __ovld amd_bitalign(uint a, uint b, uint c);
uint2 __ovld amd_bitalign(uint2 a, uint2 b, uint2 c);
uint3 __ovld amd_bitalign(uint3 a, uint3 b, uint3 c);
uint4 __ovld amd_bitalign(uint4 a, uint4 b, uint4 c);
uint8 __ovld amd_bitalign(uint8 a, uint8 b, uint8 c);
uint16 __ovld amd_bitalign(uint16 a, uint16 b, uint16 c);
uint __ovld amd_bytealign(uint a, uint b, uint c);
uint2 __ovld amd_bytealign(uint2 a, uint2 b, uint2 c);
uint3 __ovld amd_bytealign(uint3 a, uint3 b, uint3 c);
uint4 __ovld amd_bytealign(uint4 a, uint4 b, uint4 c);
uint8 __ovld amd_bytealign(uint8 a, uint8 b, uint8 c);
uint16 __ovld amd_bytealign(uint16 a, uint16 b, uint16 c);
uint __ovld amd_lerp(uint a, uint b, uint c);
uint2 __ovld amd_lerp(uint2 a, uint2 b, uint2 c);
uint3 __ovld amd_lerp(uint3 a, uint3 b, uint3 c);
uint4 __ovld amd_lerp(uint4 a, uint4 b, uint4 c);
uint8 __ovld amd_lerp(uint8 a, uint8 b, uint8 c);
uint16 __ovld amd_lerp(uint16 a, uint16 b, uint16 c);
uint __ovld amd_pack(float4 v);
uint __ovld amd_sad4(uint4 x, uint4 y, uint z);
uint __ovld amd_sadhi(uint a, uint b, uint c);
uint2 __ovld amd_sadhi(uint2 a, uint2 b, uint2 c);
uint3 __ovld amd_sadhi(uint3 a, uint3 b, uint3 c);
uint4 __ovld amd_sadhi(uint4 a, uint4 b, uint4 c);
uint8 __ovld amd_sadhi(uint8 a, uint8 b, uint8 c);
uint16 __ovld amd_sadhi(uint16 a, uint16 b, uint16 c);
uint __ovld amd_sad(uint a, uint b, uint c);
uint2 __ovld amd_sad(uint2 a, uint2 b, uint2 c);
uint3 __ovld amd_sad(uint3 a, uint3 b, uint3 c);
uint4 __ovld amd_sad(uint4 a, uint4 b, uint4 c);
uint8 __ovld amd_sad(uint8 a, uint8 b, uint8 c);
uint16 __ovld amd_sad(uint16 a, uint16 b, uint16 c);
float __ovld amd_unpack0(uint a);
float2 __ovld amd_unpack0(uint2 a);
float3 __ovld amd_unpack0(uint3 a);
float4 __ovld amd_unpack0(uint4 a);
float8 __ovld amd_unpack0(uint8 a);
float16 __ovld amd_unpack0(uint16 a);
float __ovld amd_unpack1(uint a);
float2 __ovld amd_unpack1(uint2 a);
float3 __ovld amd_unpack1(uint3 a);
float4 __ovld amd_unpack1(uint4 a);
float8 __ovld amd_unpack1(uint8 a);
float16 __ovld amd_unpack1(uint16 a);
float __ovld amd_unpack2(uint a);
float2 __ovld amd_unpack2(uint2 a);
float3 __ovld amd_unpack2(uint3 a);
float4 __ovld amd_unpack2(uint4 a);
float8 __ovld amd_unpack2(uint8 a);
float16 __ovld amd_unpack2(uint16 a);
float __ovld amd_unpack3(uint a);
float2 __ovld amd_unpack3(uint2 a);
float3 __ovld amd_unpack3(uint3 a);
float4 __ovld amd_unpack3(uint4 a);
float8 __ovld amd_unpack3(uint8 a);
float16 __ovld amd_unpack3(uint16 a);
#endif // cl_amd_media_ops
#ifdef cl_amd_media_ops2
int __ovld amd_bfe(int src0, uint src1, uint src2);
int2 __ovld amd_bfe(int2 src0, uint2 src1, uint2 src2);
int3 __ovld amd_bfe(int3 src0, uint3 src1, uint3 src2);
int4 __ovld amd_bfe(int4 src0, uint4 src1, uint4 src2);
int8 __ovld amd_bfe(int8 src0, uint8 src1, uint8 src2);
int16 __ovld amd_bfe(int16 src0, uint16 src1, uint16 src2);
uint __ovld amd_bfe(uint src0, uint src1, uint src2);
uint2 __ovld amd_bfe(uint2 src0, uint2 src1, uint2 src2);
uint3 __ovld amd_bfe(uint3 src0, uint3 src1, uint3 src2);
uint4 __ovld amd_bfe(uint4 src0, uint4 src1, uint4 src2);
uint8 __ovld amd_bfe(uint8 src0, uint8 src1, uint8 src2);
uint16 __ovld amd_bfe(uint16 src0, uint16 src1, uint16 src2);
uint __ovld amd_bfm(uint src0, uint src1);
uint2 __ovld amd_bfm(uint2 src0, uint2 src1);
uint3 __ovld amd_bfm(uint3 src0, uint3 src1);
uint4 __ovld amd_bfm(uint4 src0, uint4 src1);
uint8 __ovld amd_bfm(uint8 src0, uint8 src1);
uint16 __ovld amd_bfm(uint16 src0, uint16 src1);
float __ovld amd_max3(float src0, float src1, float src2);
float2 __ovld amd_max3(float2 src0, float2 src1, float2 src2);
float3 __ovld amd_max3(float3 src0, float3 src1, float3 src2);
float4 __ovld amd_max3(float4 src0, float4 src1, float4 src2);
float8 __ovld amd_max3(float8 src0, float8 src1, float8 src2);
float16 __ovld amd_max3(float16 src0, float16 src1, float16 src2);
int __ovld amd_max3(int src0, int src1, int src2);
int2 __ovld amd_max3(int2 src0, int2 src1, int2 src2);
int3 __ovld amd_max3(int3 src0, int3 src1, int3 src2);
int4 __ovld amd_max3(int4 src0, int4 src1, int4 src2);
int8 __ovld amd_max3(int8 src0, int8 src1, int8 src2);
int16 __ovld amd_max3(int16 src0, int16 src1, int16 src2);
uint __ovld amd_max3(uint src0, uint src1, uint src2);
uint2 __ovld amd_max3(uint2 src0, uint2 src1, uint2 src2);
uint3 __ovld amd_max3(uint3 src0, uint3 src1, uint3 src2);
uint4 __ovld amd_max3(uint4 src0, uint4 src1, uint4 src2);
uint8 __ovld amd_max3(uint8 src0, uint8 src1, uint8 src2);
uint16 __ovld amd_max3(uint16 src0, uint16 src1, uint16 src2);
float __ovld amd_median3(float src0, float src1, float src2);
float2 __ovld amd_median3(float2 src0, float2 src1, float2 src2);
float3 __ovld amd_median3(float3 src0, float3 src1, float3 src2);
float4 __ovld amd_median3(float4 src0, float4 src1, float4 src2);
float8 __ovld amd_median3(float8 src0, float8 src1, float8 src2);
float16 __ovld amd_median3(float16 src0, float16 src1, float16 src2);
int __ovld amd_median3(int src0, int src1, int src2);
int2 __ovld amd_median3(int2 src0, int2 src1, int2 src2);
int3 __ovld amd_median3(int3 src0, int3 src1, int3 src2);
int4 __ovld amd_median3(int4 src0, int4 src1, int4 src2);
int8 __ovld amd_median3(int8 src0, int8 src1, int8 src2);
int16 __ovld amd_median3(int16 src0, int16 src1, int16 src2);
uint __ovld amd_median3(uint src0, uint src1, uint src2);
uint2 __ovld amd_median3(uint2 src0, uint2 src1, uint2 src2);
uint3 __ovld amd_median3(uint3 src0, uint3 src1, uint3 src2);
uint4 __ovld amd_median3(uint4 src0, uint4 src1, uint4 src2);
uint8 __ovld amd_median3(uint8 src0, uint8 src1, uint8 src2);
uint16 __ovld amd_median3(uint16 src0, uint16 src1, uint16 src2);
float __ovld amd_min3(float src0, float src1, float src);
float2 __ovld amd_min3(float2 src0, float2 src1, float2 src);
float3 __ovld amd_min3(float3 src0, float3 src1, float3 src);
float4 __ovld amd_min3(float4 src0, float4 src1, float4 src);
float8 __ovld amd_min3(float8 src0, float8 src1, float8 src);
float16 __ovld amd_min3(float16 src0, float16 src1, float16 src);
int __ovld amd_min3(int src0, int src1, int src2);
int2 __ovld amd_min3(int2 src0, int2 src1, int2 src2);
int3 __ovld amd_min3(int3 src0, int3 src1, int3 src2);
int4 __ovld amd_min3(int4 src0, int4 src1, int4 src2);
int8 __ovld amd_min3(int8 src0, int8 src1, int8 src2);
int16 __ovld amd_min3(int16 src0, int16 src1, int16 src2);
uint __ovld amd_min3(uint src0, uint src1, uint src2);
uint2 __ovld amd_min3(uint2 src0, uint2 src1, uint2 src2);
uint3 __ovld amd_min3(uint3 src0, uint3 src1, uint3 src2);
uint4 __ovld amd_min3(uint4 src0, uint4 src1, uint4 src2);
uint8 __ovld amd_min3(uint8 src0, uint8 src1, uint8 src2);
uint16 __ovld amd_min3(uint16 src0, uint16 src1, uint16 src2);
ulong __ovld amd_mqsad(ulong src0, uint src1, ulong src2);
ulong2 __ovld amd_mqsad(ulong2 src0, uint2 src1, ulong2 src2);
ulong3 __ovld amd_mqsad(ulong3 src0, uint3 src1, ulong3 src2);
ulong4 __ovld amd_mqsad(ulong4 src0, uint4 src1, ulong4 src2);
ulong8 __ovld amd_mqsad(ulong8 src0, uint8 src1, ulong8 src2);
ulong16 __ovld amd_mqsad(ulong16 src0, uint16 src1, ulong16 src2);
ulong __ovld amd_qsad(ulong src0, uint src1, ulong src2);
ulong2 __ovld amd_qsad(ulong2 src0, uint2 src1, ulong2 src2);
ulong3 __ovld amd_qsad(ulong3 src0, uint3 src1, ulong3 src2);
ulong4 __ovld amd_qsad(ulong4 src0, uint4 src1, ulong4 src2);
ulong8 __ovld amd_qsad(ulong8 src0, uint8 src1, ulong8 src2);
ulong16 __ovld amd_qsad(ulong16 src0, uint16 src1, ulong16 src2);
uint __ovld amd_msad(uint src0, uint src1, uint src2);
uint2 __ovld amd_msad(uint2 src0, uint2 src1, uint2 src2);
uint3 __ovld amd_msad(uint3 src0, uint3 src1, uint3 src2);
uint4 __ovld amd_msad(uint4 src0, uint4 src1, uint4 src2);
uint8 __ovld amd_msad(uint8 src0, uint8 src1, uint8 src2);
uint16 __ovld amd_msad(uint16 src0, uint16 src1, uint16 src2);
uint __ovld amd_sadd(uint src0, uint src1, uint src2);
uint2 __ovld amd_sadd(uint2 src0, uint2 src1, uint2 src2);
uint3 __ovld amd_sadd(uint3 src0, uint3 src1, uint3 src2);
uint4 __ovld amd_sadd(uint4 src0, uint4 src1, uint4 src2);
uint8 __ovld amd_sadd(uint8 src0, uint8 src1, uint8 src2);
uint16 __ovld amd_sadd(uint16 src0, uint16 src1, uint16 src2);
uint __ovld amd_sadw(uint src0, uint src1, uint src2);
uint2 __ovld amd_sadw(uint2 src0, uint2 src1, uint2 src2);
uint3 __ovld amd_sadw(uint3 src0, uint3 src1, uint3 src2);
uint4 __ovld amd_sadw(uint4 src0, uint4 src1, uint4 src2);
uint8 __ovld amd_sadw(uint8 src0, uint8 src1, uint8 src2);
uint16 __ovld amd_sadw(uint16 src0, uint16 src1, uint16 src2);
#endif // cl_amd_media_ops2
// Disable any extensions we may have enabled previously.
#pragma OPENCL EXTENSION all : disable
#undef __cnfn
#undef __ovld
#endif //_OPENCL_H_
Index: vendor/clang/dist-release_80/lib/Lex/LiteralSupport.cpp
===================================================================
--- vendor/clang/dist-release_80/lib/Lex/LiteralSupport.cpp (revision 343795)
+++ vendor/clang/dist-release_80/lib/Lex/LiteralSupport.cpp (revision 343796)
@@ -1,1893 +1,1894 @@
//===--- LiteralSupport.cpp - Code to parse and process literals ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the NumericLiteralParser, CharLiteralParser, and
// StringLiteralParser interfaces.
//
//===----------------------------------------------------------------------===//
#include "clang/Lex/LiteralSupport.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Token.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
using namespace clang;
static unsigned getCharWidth(tok::TokenKind kind, const TargetInfo &Target) {
switch (kind) {
default: llvm_unreachable("Unknown token type!");
case tok::char_constant:
case tok::string_literal:
case tok::utf8_char_constant:
case tok::utf8_string_literal:
return Target.getCharWidth();
case tok::wide_char_constant:
case tok::wide_string_literal:
return Target.getWCharWidth();
case tok::utf16_char_constant:
case tok::utf16_string_literal:
return Target.getChar16Width();
case tok::utf32_char_constant:
case tok::utf32_string_literal:
return Target.getChar32Width();
}
}
static CharSourceRange MakeCharSourceRange(const LangOptions &Features,
FullSourceLoc TokLoc,
const char *TokBegin,
const char *TokRangeBegin,
const char *TokRangeEnd) {
SourceLocation Begin =
Lexer::AdvanceToTokenCharacter(TokLoc, TokRangeBegin - TokBegin,
TokLoc.getManager(), Features);
SourceLocation End =
Lexer::AdvanceToTokenCharacter(Begin, TokRangeEnd - TokRangeBegin,
TokLoc.getManager(), Features);
return CharSourceRange::getCharRange(Begin, End);
}
/// Produce a diagnostic highlighting some portion of a literal.
///
/// Emits the diagnostic \p DiagID, highlighting the range of characters from
/// \p TokRangeBegin (inclusive) to \p TokRangeEnd (exclusive), which must be
/// a substring of a spelling buffer for the token beginning at \p TokBegin.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags,
const LangOptions &Features, FullSourceLoc TokLoc,
const char *TokBegin, const char *TokRangeBegin,
const char *TokRangeEnd, unsigned DiagID) {
SourceLocation Begin =
Lexer::AdvanceToTokenCharacter(TokLoc, TokRangeBegin - TokBegin,
TokLoc.getManager(), Features);
return Diags->Report(Begin, DiagID) <<
MakeCharSourceRange(Features, TokLoc, TokBegin, TokRangeBegin, TokRangeEnd);
}
/// ProcessCharEscape - Parse a standard C escape sequence, which can occur in
/// either a character or a string literal.
static unsigned ProcessCharEscape(const char *ThisTokBegin,
const char *&ThisTokBuf,
const char *ThisTokEnd, bool &HadError,
FullSourceLoc Loc, unsigned CharWidth,
DiagnosticsEngine *Diags,
const LangOptions &Features) {
const char *EscapeBegin = ThisTokBuf;
// Skip the '\' char.
++ThisTokBuf;
// We know that this character can't be off the end of the buffer, because
// that would have been \", which would not have been the end of string.
unsigned ResultChar = *ThisTokBuf++;
switch (ResultChar) {
// These map to themselves.
case '\\': case '\'': case '"': case '?': break;
// These have fixed mappings.
case 'a':
// TODO: K&R: the meaning of '\\a' is different in traditional C
ResultChar = 7;
break;
case 'b':
ResultChar = 8;
break;
case 'e':
if (Diags)
Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
diag::ext_nonstandard_escape) << "e";
ResultChar = 27;
break;
case 'E':
if (Diags)
Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
diag::ext_nonstandard_escape) << "E";
ResultChar = 27;
break;
case 'f':
ResultChar = 12;
break;
case 'n':
ResultChar = 10;
break;
case 'r':
ResultChar = 13;
break;
case 't':
ResultChar = 9;
break;
case 'v':
ResultChar = 11;
break;
case 'x': { // Hex escape.
ResultChar = 0;
if (ThisTokBuf == ThisTokEnd || !isHexDigit(*ThisTokBuf)) {
if (Diags)
Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
diag::err_hex_escape_no_digits) << "x";
HadError = true;
break;
}
// Hex escapes are a maximal series of hex digits.
bool Overflow = false;
for (; ThisTokBuf != ThisTokEnd; ++ThisTokBuf) {
int CharVal = llvm::hexDigitValue(ThisTokBuf[0]);
if (CharVal == -1) break;
// About to shift out a digit?
if (ResultChar & 0xF0000000)
Overflow = true;
ResultChar <<= 4;
ResultChar |= CharVal;
}
// See if any bits will be truncated when evaluated as a character.
if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) {
Overflow = true;
ResultChar &= ~0U >> (32-CharWidth);
}
// Check for overflow.
if (Overflow && Diags) // Too many digits to fit in
Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
diag::err_escape_too_large) << 0;
break;
}
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7': {
// Octal escapes.
--ThisTokBuf;
ResultChar = 0;
// Octal escapes are a series of octal digits with maximum length 3.
// "\0123" is a two digit sequence equal to "\012" "3".
unsigned NumDigits = 0;
do {
ResultChar <<= 3;
ResultChar |= *ThisTokBuf++ - '0';
++NumDigits;
} while (ThisTokBuf != ThisTokEnd && NumDigits < 3 &&
ThisTokBuf[0] >= '0' && ThisTokBuf[0] <= '7');
// Check for overflow. Reject '\777', but not L'\777'.
if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) {
if (Diags)
Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
diag::err_escape_too_large) << 1;
ResultChar &= ~0U >> (32-CharWidth);
}
break;
}
// Otherwise, these are not valid escapes.
case '(': case '{': case '[': case '%':
// GCC accepts these as extensions. We warn about them as such though.
if (Diags)
Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
diag::ext_nonstandard_escape)
<< std::string(1, ResultChar);
break;
default:
if (!Diags)
break;
if (isPrintable(ResultChar))
Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
diag::ext_unknown_escape)
<< std::string(1, ResultChar);
else
Diag(Diags, Features, Loc, ThisTokBegin, EscapeBegin, ThisTokBuf,
diag::ext_unknown_escape)
<< "x" + llvm::utohexstr(ResultChar);
break;
}
return ResultChar;
}
static void appendCodePoint(unsigned Codepoint,
llvm::SmallVectorImpl<char> &Str) {
char ResultBuf[4];
char *ResultPtr = ResultBuf;
bool Res = llvm::ConvertCodePointToUTF8(Codepoint, ResultPtr);
(void)Res;
assert(Res && "Unexpected conversion failure");
Str.append(ResultBuf, ResultPtr);
}
void clang::expandUCNs(SmallVectorImpl<char> &Buf, StringRef Input) {
for (StringRef::iterator I = Input.begin(), E = Input.end(); I != E; ++I) {
if (*I != '\\') {
Buf.push_back(*I);
continue;
}
++I;
assert(*I == 'u' || *I == 'U');
unsigned NumHexDigits;
if (*I == 'u')
NumHexDigits = 4;
else
NumHexDigits = 8;
assert(I + NumHexDigits <= E);
uint32_t CodePoint = 0;
for (++I; NumHexDigits != 0; ++I, --NumHexDigits) {
unsigned Value = llvm::hexDigitValue(*I);
assert(Value != -1U);
CodePoint <<= 4;
CodePoint += Value;
}
appendCodePoint(CodePoint, Buf);
--I;
}
}
/// ProcessUCNEscape - Read the Universal Character Name, check constraints and
/// return the UTF32.
static bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
const char *ThisTokEnd,
uint32_t &UcnVal, unsigned short &UcnLen,
FullSourceLoc Loc, DiagnosticsEngine *Diags,
const LangOptions &Features,
bool in_char_string_literal = false) {
const char *UcnBegin = ThisTokBuf;
// Skip the '\u' char's.
ThisTokBuf += 2;
if (ThisTokBuf == ThisTokEnd || !isHexDigit(*ThisTokBuf)) {
if (Diags)
Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf,
diag::err_hex_escape_no_digits) << StringRef(&ThisTokBuf[-1], 1);
return false;
}
UcnLen = (ThisTokBuf[-1] == 'u' ? 4 : 8);
unsigned short UcnLenSave = UcnLen;
for (; ThisTokBuf != ThisTokEnd && UcnLenSave; ++ThisTokBuf, UcnLenSave--) {
int CharVal = llvm::hexDigitValue(ThisTokBuf[0]);
if (CharVal == -1) break;
UcnVal <<= 4;
UcnVal |= CharVal;
}
// If we didn't consume the proper number of digits, there is a problem.
if (UcnLenSave) {
if (Diags)
Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf,
diag::err_ucn_escape_incomplete);
return false;
}
// Check UCN constraints (C99 6.4.3p2) [C++11 lex.charset p2]
if ((0xD800 <= UcnVal && UcnVal <= 0xDFFF) || // surrogate codepoints
UcnVal > 0x10FFFF) { // maximum legal UTF32 value
if (Diags)
Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf,
diag::err_ucn_escape_invalid);
return false;
}
// C++11 allows UCNs that refer to control characters and basic source
// characters inside character and string literals
if (UcnVal < 0xa0 &&
(UcnVal != 0x24 && UcnVal != 0x40 && UcnVal != 0x60)) { // $, @, `
bool IsError = (!Features.CPlusPlus11 || !in_char_string_literal);
if (Diags) {
char BasicSCSChar = UcnVal;
if (UcnVal >= 0x20 && UcnVal < 0x7f)
Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf,
IsError ? diag::err_ucn_escape_basic_scs :
diag::warn_cxx98_compat_literal_ucn_escape_basic_scs)
<< StringRef(&BasicSCSChar, 1);
else
Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf,
IsError ? diag::err_ucn_control_character :
diag::warn_cxx98_compat_literal_ucn_control_character);
}
if (IsError)
return false;
}
if (!Features.CPlusPlus && !Features.C99 && Diags)
Diag(Diags, Features, Loc, ThisTokBegin, UcnBegin, ThisTokBuf,
diag::warn_ucn_not_valid_in_c89_literal);
return true;
}
/// MeasureUCNEscape - Determine the number of bytes within the resulting string
/// which this UCN will occupy.
static int MeasureUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
const char *ThisTokEnd, unsigned CharByteWidth,
const LangOptions &Features, bool &HadError) {
// UTF-32: 4 bytes per escape.
if (CharByteWidth == 4)
return 4;
uint32_t UcnVal = 0;
unsigned short UcnLen = 0;
FullSourceLoc Loc;
if (!ProcessUCNEscape(ThisTokBegin, ThisTokBuf, ThisTokEnd, UcnVal,
UcnLen, Loc, nullptr, Features, true)) {
HadError = true;
return 0;
}
// UTF-16: 2 bytes for BMP, 4 bytes otherwise.
if (CharByteWidth == 2)
return UcnVal <= 0xFFFF ? 2 : 4;
// UTF-8.
if (UcnVal < 0x80)
return 1;
if (UcnVal < 0x800)
return 2;
if (UcnVal < 0x10000)
return 3;
return 4;
}
/// EncodeUCNEscape - Read the Universal Character Name, check constraints and
/// convert the UTF32 to UTF8 or UTF16. This is a subroutine of
/// StringLiteralParser. When we decide to implement UCN's for identifiers,
/// we will likely rework our support for UCN's.
static void EncodeUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
const char *ThisTokEnd,
char *&ResultBuf, bool &HadError,
FullSourceLoc Loc, unsigned CharByteWidth,
DiagnosticsEngine *Diags,
const LangOptions &Features) {
typedef uint32_t UTF32;
UTF32 UcnVal = 0;
unsigned short UcnLen = 0;
if (!ProcessUCNEscape(ThisTokBegin, ThisTokBuf, ThisTokEnd, UcnVal, UcnLen,
Loc, Diags, Features, true)) {
HadError = true;
return;
}
assert((CharByteWidth == 1 || CharByteWidth == 2 || CharByteWidth == 4) &&
"only character widths of 1, 2, or 4 bytes supported");
(void)UcnLen;
assert((UcnLen== 4 || UcnLen== 8) && "only ucn length of 4 or 8 supported");
if (CharByteWidth == 4) {
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
llvm::UTF32 *ResultPtr = reinterpret_cast<llvm::UTF32*>(ResultBuf);
*ResultPtr = UcnVal;
ResultBuf += 4;
return;
}
if (CharByteWidth == 2) {
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
llvm::UTF16 *ResultPtr = reinterpret_cast<llvm::UTF16*>(ResultBuf);
if (UcnVal <= (UTF32)0xFFFF) {
*ResultPtr = UcnVal;
ResultBuf += 2;
return;
}
// Convert to UTF16.
UcnVal -= 0x10000;
*ResultPtr = 0xD800 + (UcnVal >> 10);
*(ResultPtr+1) = 0xDC00 + (UcnVal & 0x3FF);
ResultBuf += 4;
return;
}
assert(CharByteWidth == 1 && "UTF-8 encoding is only for 1 byte characters");
// Now that we've parsed/checked the UCN, we convert from UTF32->UTF8.
// The conversion below was inspired by:
// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
// First, we determine how many bytes the result will require.
typedef uint8_t UTF8;
unsigned short bytesToWrite = 0;
if (UcnVal < (UTF32)0x80)
bytesToWrite = 1;
else if (UcnVal < (UTF32)0x800)
bytesToWrite = 2;
else if (UcnVal < (UTF32)0x10000)
bytesToWrite = 3;
else
bytesToWrite = 4;
const unsigned byteMask = 0xBF;
const unsigned byteMark = 0x80;
// Once the bits are split out into bytes of UTF8, this is a mask OR-ed
// into the first byte, depending on how many bytes follow.
static const UTF8 firstByteMark[5] = {
0x00, 0x00, 0xC0, 0xE0, 0xF0
};
// Finally, we write the bytes into ResultBuf.
ResultBuf += bytesToWrite;
switch (bytesToWrite) { // note: everything falls through.
case 4:
*--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6;
LLVM_FALLTHROUGH;
case 3:
*--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6;
LLVM_FALLTHROUGH;
case 2:
*--ResultBuf = (UTF8)((UcnVal | byteMark) & byteMask); UcnVal >>= 6;
LLVM_FALLTHROUGH;
case 1:
*--ResultBuf = (UTF8) (UcnVal | firstByteMark[bytesToWrite]);
}
// Update the buffer.
ResultBuf += bytesToWrite;
}
/// integer-constant: [C99 6.4.4.1]
/// decimal-constant integer-suffix
/// octal-constant integer-suffix
/// hexadecimal-constant integer-suffix
/// binary-literal integer-suffix [GNU, C++1y]
/// user-defined-integer-literal: [C++11 lex.ext]
/// decimal-literal ud-suffix
/// octal-literal ud-suffix
/// hexadecimal-literal ud-suffix
/// binary-literal ud-suffix [GNU, C++1y]
/// decimal-constant:
/// nonzero-digit
/// decimal-constant digit
/// octal-constant:
/// 0
/// octal-constant octal-digit
/// hexadecimal-constant:
/// hexadecimal-prefix hexadecimal-digit
/// hexadecimal-constant hexadecimal-digit
/// hexadecimal-prefix: one of
/// 0x 0X
/// binary-literal:
/// 0b binary-digit
/// 0B binary-digit
/// binary-literal binary-digit
/// integer-suffix:
/// unsigned-suffix [long-suffix]
/// unsigned-suffix [long-long-suffix]
/// long-suffix [unsigned-suffix]
/// long-long-suffix [unsigned-sufix]
/// nonzero-digit:
/// 1 2 3 4 5 6 7 8 9
/// octal-digit:
/// 0 1 2 3 4 5 6 7
/// hexadecimal-digit:
/// 0 1 2 3 4 5 6 7 8 9
/// a b c d e f
/// A B C D E F
/// binary-digit:
/// 0
/// 1
/// unsigned-suffix: one of
/// u U
/// long-suffix: one of
/// l L
/// long-long-suffix: one of
/// ll LL
///
/// floating-constant: [C99 6.4.4.2]
/// TODO: add rules...
///
NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
SourceLocation TokLoc,
Preprocessor &PP)
: PP(PP), ThisTokBegin(TokSpelling.begin()), ThisTokEnd(TokSpelling.end()) {
// This routine assumes that the range begin/end matches the regex for integer
// and FP constants (specifically, the 'pp-number' regex), and assumes that
// the byte at "*end" is both valid and not part of the regex. Because of
// this, it doesn't have to check for 'overscan' in various places.
assert(!isPreprocessingNumberBody(*ThisTokEnd) && "didn't maximally munch?");
s = DigitsBegin = ThisTokBegin;
saw_exponent = false;
saw_period = false;
saw_ud_suffix = false;
saw_fixed_point_suffix = false;
isLong = false;
isUnsigned = false;
isLongLong = false;
isHalf = false;
isFloat = false;
isImaginary = false;
isFloat16 = false;
isFloat128 = false;
MicrosoftInteger = 0;
isFract = false;
isAccum = false;
hadError = false;
if (*s == '0') { // parse radix
ParseNumberStartingWithZero(TokLoc);
if (hadError)
return;
} else { // the first digit is non-zero
radix = 10;
s = SkipDigits(s);
if (s == ThisTokEnd) {
// Done.
} else {
ParseDecimalOrOctalCommon(TokLoc);
if (hadError)
return;
}
}
SuffixBegin = s;
checkSeparator(TokLoc, s, CSK_AfterDigits);
// Initial scan to lookahead for fixed point suffix.
if (PP.getLangOpts().FixedPoint) {
for (const char *c = s; c != ThisTokEnd; ++c) {
if (*c == 'r' || *c == 'k' || *c == 'R' || *c == 'K') {
saw_fixed_point_suffix = true;
break;
}
}
}
// Parse the suffix. At this point we can classify whether we have an FP or
// integer constant.
bool isFPConstant = isFloatingLiteral();
// Loop over all of the characters of the suffix. If we see something bad,
// we break out of the loop.
for (; s != ThisTokEnd; ++s) {
switch (*s) {
case 'R':
case 'r':
if (!PP.getLangOpts().FixedPoint) break;
if (isFract || isAccum) break;
if (!(saw_period || saw_exponent)) break;
isFract = true;
continue;
case 'K':
case 'k':
if (!PP.getLangOpts().FixedPoint) break;
if (isFract || isAccum) break;
if (!(saw_period || saw_exponent)) break;
isAccum = true;
continue;
case 'h': // FP Suffix for "half".
case 'H':
// OpenCL Extension v1.2 s9.5 - h or H suffix for half type.
if (!(PP.getLangOpts().Half || PP.getLangOpts().FixedPoint)) break;
if (isIntegerLiteral()) break; // Error for integer constant.
if (isHalf || isFloat || isLong) break; // HH, FH, LH invalid.
isHalf = true;
continue; // Success.
case 'f': // FP Suffix for "float"
case 'F':
if (!isFPConstant) break; // Error for integer constant.
if (isHalf || isFloat || isLong || isFloat128)
break; // HF, FF, LF, QF invalid.
- if (s + 2 < ThisTokEnd && s[1] == '1' && s[2] == '6') {
- s += 2; // success, eat up 2 characters.
- isFloat16 = true;
- continue;
+ if (PP.getTargetInfo().hasFloat16Type() && s + 2 < ThisTokEnd &&
+ s[1] == '1' && s[2] == '6') {
+ s += 2; // success, eat up 2 characters.
+ isFloat16 = true;
+ continue;
}
isFloat = true;
continue; // Success.
case 'q': // FP Suffix for "__float128"
case 'Q':
if (!isFPConstant) break; // Error for integer constant.
if (isHalf || isFloat || isLong || isFloat128)
break; // HQ, FQ, LQ, QQ invalid.
isFloat128 = true;
continue; // Success.
case 'u':
case 'U':
if (isFPConstant) break; // Error for floating constant.
if (isUnsigned) break; // Cannot be repeated.
isUnsigned = true;
continue; // Success.
case 'l':
case 'L':
if (isLong || isLongLong) break; // Cannot be repeated.
if (isHalf || isFloat || isFloat128) break; // LH, LF, LQ invalid.
// Check for long long. The L's need to be adjacent and the same case.
if (s[1] == s[0]) {
assert(s + 1 < ThisTokEnd && "didn't maximally munch?");
if (isFPConstant) break; // long long invalid for floats.
isLongLong = true;
++s; // Eat both of them.
} else {
isLong = true;
}
continue; // Success.
case 'i':
case 'I':
if (PP.getLangOpts().MicrosoftExt) {
if (isLong || isLongLong || MicrosoftInteger)
break;
if (!isFPConstant) {
// Allow i8, i16, i32, and i64.
switch (s[1]) {
case '8':
s += 2; // i8 suffix
MicrosoftInteger = 8;
break;
case '1':
if (s[2] == '6') {
s += 3; // i16 suffix
MicrosoftInteger = 16;
}
break;
case '3':
if (s[2] == '2') {
s += 3; // i32 suffix
MicrosoftInteger = 32;
}
break;
case '6':
if (s[2] == '4') {
s += 3; // i64 suffix
MicrosoftInteger = 64;
}
break;
default:
break;
}
}
if (MicrosoftInteger) {
assert(s <= ThisTokEnd && "didn't maximally munch?");
break;
}
}
LLVM_FALLTHROUGH;
case 'j':
case 'J':
if (isImaginary) break; // Cannot be repeated.
isImaginary = true;
continue; // Success.
}
// If we reached here, there was an error or a ud-suffix.
break;
}
// "i", "if", and "il" are user-defined suffixes in C++1y.
if (s != ThisTokEnd || isImaginary) {
// FIXME: Don't bother expanding UCNs if !tok.hasUCN().
expandUCNs(UDSuffixBuf, StringRef(SuffixBegin, ThisTokEnd - SuffixBegin));
if (isValidUDSuffix(PP.getLangOpts(), UDSuffixBuf)) {
if (!isImaginary) {
// Any suffix pieces we might have parsed are actually part of the
// ud-suffix.
isLong = false;
isUnsigned = false;
isLongLong = false;
isFloat = false;
isFloat16 = false;
isHalf = false;
isImaginary = false;
MicrosoftInteger = 0;
saw_fixed_point_suffix = false;
isFract = false;
isAccum = false;
}
saw_ud_suffix = true;
return;
}
if (s != ThisTokEnd) {
// Report an error if there are any.
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, SuffixBegin - ThisTokBegin),
diag::err_invalid_suffix_constant)
<< StringRef(SuffixBegin, ThisTokEnd - SuffixBegin) << isFPConstant;
hadError = true;
}
}
if (!hadError && saw_fixed_point_suffix) {
assert(isFract || isAccum);
}
}
/// ParseDecimalOrOctalCommon - This method is called for decimal or octal
/// numbers. It issues an error for illegal digits, and handles floating point
/// parsing. If it detects a floating point number, the radix is set to 10.
void NumericLiteralParser::ParseDecimalOrOctalCommon(SourceLocation TokLoc){
assert((radix == 8 || radix == 10) && "Unexpected radix");
// If we have a hex digit other than 'e' (which denotes a FP exponent) then
// the code is using an incorrect base.
if (isHexDigit(*s) && *s != 'e' && *s != 'E' &&
!isValidUDSuffix(PP.getLangOpts(), StringRef(s, ThisTokEnd - s))) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin),
diag::err_invalid_digit) << StringRef(s, 1) << (radix == 8 ? 1 : 0);
hadError = true;
return;
}
if (*s == '.') {
checkSeparator(TokLoc, s, CSK_AfterDigits);
s++;
radix = 10;
saw_period = true;
checkSeparator(TokLoc, s, CSK_BeforeDigits);
s = SkipDigits(s); // Skip suffix.
}
if (*s == 'e' || *s == 'E') { // exponent
checkSeparator(TokLoc, s, CSK_AfterDigits);
const char *Exponent = s;
s++;
radix = 10;
saw_exponent = true;
if (s != ThisTokEnd && (*s == '+' || *s == '-')) s++; // sign
const char *first_non_digit = SkipDigits(s);
if (containsDigits(s, first_non_digit)) {
checkSeparator(TokLoc, s, CSK_BeforeDigits);
s = first_non_digit;
} else {
if (!hadError) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin),
diag::err_exponent_has_no_digits);
hadError = true;
}
return;
}
}
}
/// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved
/// suffixes as ud-suffixes, because the diagnostic experience is better if we
/// treat it as an invalid suffix.
bool NumericLiteralParser::isValidUDSuffix(const LangOptions &LangOpts,
StringRef Suffix) {
if (!LangOpts.CPlusPlus11 || Suffix.empty())
return false;
// By C++11 [lex.ext]p10, ud-suffixes starting with an '_' are always valid.
if (Suffix[0] == '_')
return true;
// In C++11, there are no library suffixes.
if (!LangOpts.CPlusPlus14)
return false;
// In C++14, "s", "h", "min", "ms", "us", and "ns" are used in the library.
// Per tweaked N3660, "il", "i", and "if" are also used in the library.
// In C++2a "d" and "y" are used in the library.
return llvm::StringSwitch<bool>(Suffix)
.Cases("h", "min", "s", true)
.Cases("ms", "us", "ns", true)
.Cases("il", "i", "if", true)
.Cases("d", "y", LangOpts.CPlusPlus2a)
.Default(false);
}
void NumericLiteralParser::checkSeparator(SourceLocation TokLoc,
const char *Pos,
CheckSeparatorKind IsAfterDigits) {
if (IsAfterDigits == CSK_AfterDigits) {
if (Pos == ThisTokBegin)
return;
--Pos;
} else if (Pos == ThisTokEnd)
return;
if (isDigitSeparator(*Pos)) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Pos - ThisTokBegin),
diag::err_digit_separator_not_between_digits)
<< IsAfterDigits;
hadError = true;
}
}
/// ParseNumberStartingWithZero - This method is called when the first character
/// of the number is found to be a zero. This means it is either an octal
/// number (like '04') or a hex number ('0x123a') a binary number ('0b1010') or
/// a floating point number (01239.123e4). Eat the prefix, determining the
/// radix etc.
void NumericLiteralParser::ParseNumberStartingWithZero(SourceLocation TokLoc) {
assert(s[0] == '0' && "Invalid method call");
s++;
int c1 = s[0];
// Handle a hex number like 0x1234.
if ((c1 == 'x' || c1 == 'X') && (isHexDigit(s[1]) || s[1] == '.')) {
s++;
assert(s < ThisTokEnd && "didn't maximally munch?");
radix = 16;
DigitsBegin = s;
s = SkipHexDigits(s);
bool HasSignificandDigits = containsDigits(DigitsBegin, s);
if (s == ThisTokEnd) {
// Done.
} else if (*s == '.') {
s++;
saw_period = true;
const char *floatDigitsBegin = s;
s = SkipHexDigits(s);
if (containsDigits(floatDigitsBegin, s))
HasSignificandDigits = true;
if (HasSignificandDigits)
checkSeparator(TokLoc, floatDigitsBegin, CSK_BeforeDigits);
}
if (!HasSignificandDigits) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin),
diag::err_hex_constant_requires)
<< PP.getLangOpts().CPlusPlus << 1;
hadError = true;
return;
}
// A binary exponent can appear with or with a '.'. If dotted, the
// binary exponent is required.
if (*s == 'p' || *s == 'P') {
checkSeparator(TokLoc, s, CSK_AfterDigits);
const char *Exponent = s;
s++;
saw_exponent = true;
if (s != ThisTokEnd && (*s == '+' || *s == '-')) s++; // sign
const char *first_non_digit = SkipDigits(s);
if (!containsDigits(s, first_non_digit)) {
if (!hadError) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, Exponent-ThisTokBegin),
diag::err_exponent_has_no_digits);
hadError = true;
}
return;
}
checkSeparator(TokLoc, s, CSK_BeforeDigits);
s = first_non_digit;
if (!PP.getLangOpts().HexFloats)
PP.Diag(TokLoc, PP.getLangOpts().CPlusPlus
? diag::ext_hex_literal_invalid
: diag::ext_hex_constant_invalid);
else if (PP.getLangOpts().CPlusPlus17)
PP.Diag(TokLoc, diag::warn_cxx17_hex_literal);
} else if (saw_period) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s - ThisTokBegin),
diag::err_hex_constant_requires)
<< PP.getLangOpts().CPlusPlus << 0;
hadError = true;
}
return;
}
// Handle simple binary numbers 0b01010
if ((c1 == 'b' || c1 == 'B') && (s[1] == '0' || s[1] == '1')) {
// 0b101010 is a C++1y / GCC extension.
PP.Diag(TokLoc,
PP.getLangOpts().CPlusPlus14
? diag::warn_cxx11_compat_binary_literal
: PP.getLangOpts().CPlusPlus
? diag::ext_binary_literal_cxx14
: diag::ext_binary_literal);
++s;
assert(s < ThisTokEnd && "didn't maximally munch?");
radix = 2;
DigitsBegin = s;
s = SkipBinaryDigits(s);
if (s == ThisTokEnd) {
// Done.
} else if (isHexDigit(*s) &&
!isValidUDSuffix(PP.getLangOpts(),
StringRef(s, ThisTokEnd - s))) {
PP.Diag(PP.AdvanceToTokenCharacter(TokLoc, s-ThisTokBegin),
diag::err_invalid_digit) << StringRef(s, 1) << 2;
hadError = true;
}
// Other suffixes will be diagnosed by the caller.
return;
}
// For now, the radix is set to 8. If we discover that we have a
// floating point constant, the radix will change to 10. Octal floating
// point constants are not permitted (only decimal and hexadecimal).
radix = 8;
DigitsBegin = s;
s = SkipOctalDigits(s);
if (s == ThisTokEnd)
return; // Done, simple octal number like 01234
// If we have some other non-octal digit that *is* a decimal digit, see if
// this is part of a floating point number like 094.123 or 09e1.
if (isDigit(*s)) {
const char *EndDecimal = SkipDigits(s);
if (EndDecimal[0] == '.' || EndDecimal[0] == 'e' || EndDecimal[0] == 'E') {
s = EndDecimal;
radix = 10;
}
}
ParseDecimalOrOctalCommon(TokLoc);
}
static bool alwaysFitsInto64Bits(unsigned Radix, unsigned NumDigits) {
switch (Radix) {
case 2:
return NumDigits <= 64;
case 8:
return NumDigits <= 64 / 3; // Digits are groups of 3 bits.
case 10:
return NumDigits <= 19; // floor(log10(2^64))
case 16:
return NumDigits <= 64 / 4; // Digits are groups of 4 bits.
default:
llvm_unreachable("impossible Radix");
}
}
/// GetIntegerValue - Convert this numeric literal value to an APInt that
/// matches Val's input width. If there is an overflow, set Val to the low bits
/// of the result and return true. Otherwise, return false.
bool NumericLiteralParser::GetIntegerValue(llvm::APInt &Val) {
// Fast path: Compute a conservative bound on the maximum number of
// bits per digit in this radix. If we can't possibly overflow a
// uint64 based on that bound then do the simple conversion to
// integer. This avoids the expensive overflow checking below, and
// handles the common cases that matter (small decimal integers and
// hex/octal values which don't overflow).
const unsigned NumDigits = SuffixBegin - DigitsBegin;
if (alwaysFitsInto64Bits(radix, NumDigits)) {
uint64_t N = 0;
for (const char *Ptr = DigitsBegin; Ptr != SuffixBegin; ++Ptr)
if (!isDigitSeparator(*Ptr))
N = N * radix + llvm::hexDigitValue(*Ptr);
// This will truncate the value to Val's input width. Simply check
// for overflow by comparing.
Val = N;
return Val.getZExtValue() != N;
}
Val = 0;
const char *Ptr = DigitsBegin;
llvm::APInt RadixVal(Val.getBitWidth(), radix);
llvm::APInt CharVal(Val.getBitWidth(), 0);
llvm::APInt OldVal = Val;
bool OverflowOccurred = false;
while (Ptr < SuffixBegin) {
if (isDigitSeparator(*Ptr)) {
++Ptr;
continue;
}
unsigned C = llvm::hexDigitValue(*Ptr++);
// If this letter is out of bound for this radix, reject it.
assert(C < radix && "NumericLiteralParser ctor should have rejected this");
CharVal = C;
// Add the digit to the value in the appropriate radix. If adding in digits
// made the value smaller, then this overflowed.
OldVal = Val;
// Multiply by radix, did overflow occur on the multiply?
Val *= RadixVal;
OverflowOccurred |= Val.udiv(RadixVal) != OldVal;
// Add value, did overflow occur on the value?
// (a + b) ult b <=> overflow
Val += CharVal;
OverflowOccurred |= Val.ult(CharVal);
}
return OverflowOccurred;
}
llvm::APFloat::opStatus
NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) {
using llvm::APFloat;
unsigned n = std::min(SuffixBegin - ThisTokBegin, ThisTokEnd - ThisTokBegin);
llvm::SmallString<16> Buffer;
StringRef Str(ThisTokBegin, n);
if (Str.find('\'') != StringRef::npos) {
Buffer.reserve(n);
std::remove_copy_if(Str.begin(), Str.end(), std::back_inserter(Buffer),
&isDigitSeparator);
Str = Buffer;
}
return Result.convertFromString(Str, APFloat::rmNearestTiesToEven);
}
static inline bool IsExponentPart(char c) {
return c == 'p' || c == 'P' || c == 'e' || c == 'E';
}
bool NumericLiteralParser::GetFixedPointValue(llvm::APInt &StoreVal, unsigned Scale) {
assert(radix == 16 || radix == 10);
// Find how many digits are needed to store the whole literal.
unsigned NumDigits = SuffixBegin - DigitsBegin;
if (saw_period) --NumDigits;
// Initial scan of the exponent if it exists
bool ExpOverflowOccurred = false;
bool NegativeExponent = false;
const char *ExponentBegin;
uint64_t Exponent = 0;
int64_t BaseShift = 0;
if (saw_exponent) {
const char *Ptr = DigitsBegin;
while (!IsExponentPart(*Ptr)) ++Ptr;
ExponentBegin = Ptr;
++Ptr;
NegativeExponent = *Ptr == '-';
if (NegativeExponent) ++Ptr;
unsigned NumExpDigits = SuffixBegin - Ptr;
if (alwaysFitsInto64Bits(radix, NumExpDigits)) {
llvm::StringRef ExpStr(Ptr, NumExpDigits);
llvm::APInt ExpInt(/*numBits=*/64, ExpStr, /*radix=*/10);
Exponent = ExpInt.getZExtValue();
} else {
ExpOverflowOccurred = true;
}
if (NegativeExponent) BaseShift -= Exponent;
else BaseShift += Exponent;
}
// Number of bits needed for decimal literal is
// ceil(NumDigits * log2(10)) Integral part
// + Scale Fractional part
// + ceil(Exponent * log2(10)) Exponent
// --------------------------------------------------
// ceil((NumDigits + Exponent) * log2(10)) + Scale
//
// But for simplicity in handling integers, we can round up log2(10) to 4,
// making:
// 4 * (NumDigits + Exponent) + Scale
//
// Number of digits needed for hexadecimal literal is
// 4 * NumDigits Integral part
// + Scale Fractional part
// + Exponent Exponent
// --------------------------------------------------
// (4 * NumDigits) + Scale + Exponent
uint64_t NumBitsNeeded;
if (radix == 10)
NumBitsNeeded = 4 * (NumDigits + Exponent) + Scale;
else
NumBitsNeeded = 4 * NumDigits + Exponent + Scale;
if (NumBitsNeeded > std::numeric_limits<unsigned>::max())
ExpOverflowOccurred = true;
llvm::APInt Val(static_cast<unsigned>(NumBitsNeeded), 0, /*isSigned=*/false);
bool FoundDecimal = false;
int64_t FractBaseShift = 0;
const char *End = saw_exponent ? ExponentBegin : SuffixBegin;
for (const char *Ptr = DigitsBegin; Ptr < End; ++Ptr) {
if (*Ptr == '.') {
FoundDecimal = true;
continue;
}
// Normal reading of an integer
unsigned C = llvm::hexDigitValue(*Ptr);
assert(C < radix && "NumericLiteralParser ctor should have rejected this");
Val *= radix;
Val += C;
if (FoundDecimal)
// Keep track of how much we will need to adjust this value by from the
// number of digits past the radix point.
--FractBaseShift;
}
// For a radix of 16, we will be multiplying by 2 instead of 16.
if (radix == 16) FractBaseShift *= 4;
BaseShift += FractBaseShift;
Val <<= Scale;
uint64_t Base = (radix == 16) ? 2 : 10;
if (BaseShift > 0) {
for (int64_t i = 0; i < BaseShift; ++i) {
Val *= Base;
}
} else if (BaseShift < 0) {
for (int64_t i = BaseShift; i < 0 && !Val.isNullValue(); ++i)
Val = Val.udiv(Base);
}
bool IntOverflowOccurred = false;
auto MaxVal = llvm::APInt::getMaxValue(StoreVal.getBitWidth());
if (Val.getBitWidth() > StoreVal.getBitWidth()) {
IntOverflowOccurred |= Val.ugt(MaxVal.zext(Val.getBitWidth()));
StoreVal = Val.trunc(StoreVal.getBitWidth());
} else if (Val.getBitWidth() < StoreVal.getBitWidth()) {
IntOverflowOccurred |= Val.zext(MaxVal.getBitWidth()).ugt(MaxVal);
StoreVal = Val.zext(StoreVal.getBitWidth());
} else {
StoreVal = Val;
}
return IntOverflowOccurred || ExpOverflowOccurred;
}
/// \verbatim
/// user-defined-character-literal: [C++11 lex.ext]
/// character-literal ud-suffix
/// ud-suffix:
/// identifier
/// character-literal: [C++11 lex.ccon]
/// ' c-char-sequence '
/// u' c-char-sequence '
/// U' c-char-sequence '
/// L' c-char-sequence '
/// u8' c-char-sequence ' [C++1z lex.ccon]
/// c-char-sequence:
/// c-char
/// c-char-sequence c-char
/// c-char:
/// any member of the source character set except the single-quote ',
/// backslash \, or new-line character
/// escape-sequence
/// universal-character-name
/// escape-sequence:
/// simple-escape-sequence
/// octal-escape-sequence
/// hexadecimal-escape-sequence
/// simple-escape-sequence:
/// one of \' \" \? \\ \a \b \f \n \r \t \v
/// octal-escape-sequence:
/// \ octal-digit
/// \ octal-digit octal-digit
/// \ octal-digit octal-digit octal-digit
/// hexadecimal-escape-sequence:
/// \x hexadecimal-digit
/// hexadecimal-escape-sequence hexadecimal-digit
/// universal-character-name: [C++11 lex.charset]
/// \u hex-quad
/// \U hex-quad hex-quad
/// hex-quad:
/// hex-digit hex-digit hex-digit hex-digit
/// \endverbatim
///
CharLiteralParser::CharLiteralParser(const char *begin, const char *end,
SourceLocation Loc, Preprocessor &PP,
tok::TokenKind kind) {
// At this point we know that the character matches the regex "(L|u|U)?'.*'".
HadError = false;
Kind = kind;
const char *TokBegin = begin;
// Skip over wide character determinant.
if (Kind != tok::char_constant)
++begin;
if (Kind == tok::utf8_char_constant)
++begin;
// Skip over the entry quote.
assert(begin[0] == '\'' && "Invalid token lexed");
++begin;
// Remove an optional ud-suffix.
if (end[-1] != '\'') {
const char *UDSuffixEnd = end;
do {
--end;
} while (end[-1] != '\'');
// FIXME: Don't bother with this if !tok.hasUCN().
expandUCNs(UDSuffixBuf, StringRef(end, UDSuffixEnd - end));
UDSuffixOffset = end - TokBegin;
}
// Trim the ending quote.
assert(end != begin && "Invalid token lexed");
--end;
// FIXME: The "Value" is an uint64_t so we can handle char literals of
// up to 64-bits.
// FIXME: This extensively assumes that 'char' is 8-bits.
assert(PP.getTargetInfo().getCharWidth() == 8 &&
"Assumes char is 8 bits");
assert(PP.getTargetInfo().getIntWidth() <= 64 &&
(PP.getTargetInfo().getIntWidth() & 7) == 0 &&
"Assumes sizeof(int) on target is <= 64 and a multiple of char");
assert(PP.getTargetInfo().getWCharWidth() <= 64 &&
"Assumes sizeof(wchar) on target is <= 64");
SmallVector<uint32_t, 4> codepoint_buffer;
codepoint_buffer.resize(end - begin);
uint32_t *buffer_begin = &codepoint_buffer.front();
uint32_t *buffer_end = buffer_begin + codepoint_buffer.size();
// Unicode escapes representing characters that cannot be correctly
// represented in a single code unit are disallowed in character literals
// by this implementation.
uint32_t largest_character_for_kind;
if (tok::wide_char_constant == Kind) {
largest_character_for_kind =
0xFFFFFFFFu >> (32-PP.getTargetInfo().getWCharWidth());
} else if (tok::utf8_char_constant == Kind) {
largest_character_for_kind = 0x7F;
} else if (tok::utf16_char_constant == Kind) {
largest_character_for_kind = 0xFFFF;
} else if (tok::utf32_char_constant == Kind) {
largest_character_for_kind = 0x10FFFF;
} else {
largest_character_for_kind = 0x7Fu;
}
while (begin != end) {
// Is this a span of non-escape characters?
if (begin[0] != '\\') {
char const *start = begin;
do {
++begin;
} while (begin != end && *begin != '\\');
char const *tmp_in_start = start;
uint32_t *tmp_out_start = buffer_begin;
llvm::ConversionResult res =
llvm::ConvertUTF8toUTF32(reinterpret_cast<llvm::UTF8 const **>(&start),
reinterpret_cast<llvm::UTF8 const *>(begin),
&buffer_begin, buffer_end, llvm::strictConversion);
if (res != llvm::conversionOK) {
// If we see bad encoding for unprefixed character literals, warn and
// simply copy the byte values, for compatibility with gcc and
// older versions of clang.
bool NoErrorOnBadEncoding = isAscii();
unsigned Msg = diag::err_bad_character_encoding;
if (NoErrorOnBadEncoding)
Msg = diag::warn_bad_character_encoding;
PP.Diag(Loc, Msg);
if (NoErrorOnBadEncoding) {
start = tmp_in_start;
buffer_begin = tmp_out_start;
for (; start != begin; ++start, ++buffer_begin)
*buffer_begin = static_cast<uint8_t>(*start);
} else {
HadError = true;
}
} else {
for (; tmp_out_start < buffer_begin; ++tmp_out_start) {
if (*tmp_out_start > largest_character_for_kind) {
HadError = true;
PP.Diag(Loc, diag::err_character_too_large);
}
}
}
continue;
}
// Is this a Universal Character Name escape?
if (begin[1] == 'u' || begin[1] == 'U') {
unsigned short UcnLen = 0;
if (!ProcessUCNEscape(TokBegin, begin, end, *buffer_begin, UcnLen,
FullSourceLoc(Loc, PP.getSourceManager()),
&PP.getDiagnostics(), PP.getLangOpts(), true)) {
HadError = true;
} else if (*buffer_begin > largest_character_for_kind) {
HadError = true;
PP.Diag(Loc, diag::err_character_too_large);
}
++buffer_begin;
continue;
}
unsigned CharWidth = getCharWidth(Kind, PP.getTargetInfo());
uint64_t result =
ProcessCharEscape(TokBegin, begin, end, HadError,
FullSourceLoc(Loc,PP.getSourceManager()),
CharWidth, &PP.getDiagnostics(), PP.getLangOpts());
*buffer_begin++ = result;
}
unsigned NumCharsSoFar = buffer_begin - &codepoint_buffer.front();
if (NumCharsSoFar > 1) {
if (isWide())
PP.Diag(Loc, diag::warn_extraneous_char_constant);
else if (isAscii() && NumCharsSoFar == 4)
PP.Diag(Loc, diag::ext_four_char_character_literal);
else if (isAscii())
PP.Diag(Loc, diag::ext_multichar_character_literal);
else
PP.Diag(Loc, diag::err_multichar_utf_character_literal);
IsMultiChar = true;
} else {
IsMultiChar = false;
}
llvm::APInt LitVal(PP.getTargetInfo().getIntWidth(), 0);
// Narrow character literals act as though their value is concatenated
// in this implementation, but warn on overflow.
bool multi_char_too_long = false;
if (isAscii() && isMultiChar()) {
LitVal = 0;
for (size_t i = 0; i < NumCharsSoFar; ++i) {
// check for enough leading zeros to shift into
multi_char_too_long |= (LitVal.countLeadingZeros() < 8);
LitVal <<= 8;
LitVal = LitVal + (codepoint_buffer[i] & 0xFF);
}
} else if (NumCharsSoFar > 0) {
// otherwise just take the last character
LitVal = buffer_begin[-1];
}
if (!HadError && multi_char_too_long) {
PP.Diag(Loc, diag::warn_char_constant_too_large);
}
// Transfer the value from APInt to uint64_t
Value = LitVal.getZExtValue();
// If this is a single narrow character, sign extend it (e.g. '\xFF' is "-1")
// if 'char' is signed for this target (C99 6.4.4.4p10). Note that multiple
// character constants are not sign extended in the this implementation:
// '\xFF\xFF' = 65536 and '\x0\xFF' = 255, which matches GCC.
if (isAscii() && NumCharsSoFar == 1 && (Value & 128) &&
PP.getLangOpts().CharIsSigned)
Value = (signed char)Value;
}
/// \verbatim
/// string-literal: [C++0x lex.string]
/// encoding-prefix " [s-char-sequence] "
/// encoding-prefix R raw-string
/// encoding-prefix:
/// u8
/// u
/// U
/// L
/// s-char-sequence:
/// s-char
/// s-char-sequence s-char
/// s-char:
/// any member of the source character set except the double-quote ",
/// backslash \, or new-line character
/// escape-sequence
/// universal-character-name
/// raw-string:
/// " d-char-sequence ( r-char-sequence ) d-char-sequence "
/// r-char-sequence:
/// r-char
/// r-char-sequence r-char
/// r-char:
/// any member of the source character set, except a right parenthesis )
/// followed by the initial d-char-sequence (which may be empty)
/// followed by a double quote ".
/// d-char-sequence:
/// d-char
/// d-char-sequence d-char
/// d-char:
/// any member of the basic source character set except:
/// space, the left parenthesis (, the right parenthesis ),
/// the backslash \, and the control characters representing horizontal
/// tab, vertical tab, form feed, and newline.
/// escape-sequence: [C++0x lex.ccon]
/// simple-escape-sequence
/// octal-escape-sequence
/// hexadecimal-escape-sequence
/// simple-escape-sequence:
/// one of \' \" \? \\ \a \b \f \n \r \t \v
/// octal-escape-sequence:
/// \ octal-digit
/// \ octal-digit octal-digit
/// \ octal-digit octal-digit octal-digit
/// hexadecimal-escape-sequence:
/// \x hexadecimal-digit
/// hexadecimal-escape-sequence hexadecimal-digit
/// universal-character-name:
/// \u hex-quad
/// \U hex-quad hex-quad
/// hex-quad:
/// hex-digit hex-digit hex-digit hex-digit
/// \endverbatim
///
StringLiteralParser::
StringLiteralParser(ArrayRef<Token> StringToks,
Preprocessor &PP, bool Complain)
: SM(PP.getSourceManager()), Features(PP.getLangOpts()),
Target(PP.getTargetInfo()), Diags(Complain ? &PP.getDiagnostics() :nullptr),
MaxTokenLength(0), SizeBound(0), CharByteWidth(0), Kind(tok::unknown),
ResultPtr(ResultBuf.data()), hadError(false), Pascal(false) {
init(StringToks);
}
void StringLiteralParser::init(ArrayRef<Token> StringToks){
// The literal token may have come from an invalid source location (e.g. due
// to a PCH error), in which case the token length will be 0.
if (StringToks.empty() || StringToks[0].getLength() < 2)
return DiagnoseLexingError(SourceLocation());
// Scan all of the string portions, remember the max individual token length,
// computing a bound on the concatenated string length, and see whether any
// piece is a wide-string. If any of the string portions is a wide-string
// literal, the result is a wide-string literal [C99 6.4.5p4].
assert(!StringToks.empty() && "expected at least one token");
MaxTokenLength = StringToks[0].getLength();
assert(StringToks[0].getLength() >= 2 && "literal token is invalid!");
SizeBound = StringToks[0].getLength()-2; // -2 for "".
Kind = StringToks[0].getKind();
hadError = false;
// Implement Translation Phase #6: concatenation of string literals
/// (C99 5.1.1.2p1). The common case is only one string fragment.
for (unsigned i = 1; i != StringToks.size(); ++i) {
if (StringToks[i].getLength() < 2)
return DiagnoseLexingError(StringToks[i].getLocation());
// The string could be shorter than this if it needs cleaning, but this is a
// reasonable bound, which is all we need.
assert(StringToks[i].getLength() >= 2 && "literal token is invalid!");
SizeBound += StringToks[i].getLength()-2; // -2 for "".
// Remember maximum string piece length.
if (StringToks[i].getLength() > MaxTokenLength)
MaxTokenLength = StringToks[i].getLength();
// Remember if we see any wide or utf-8/16/32 strings.
// Also check for illegal concatenations.
if (StringToks[i].isNot(Kind) && StringToks[i].isNot(tok::string_literal)) {
if (isAscii()) {
Kind = StringToks[i].getKind();
} else {
if (Diags)
Diags->Report(StringToks[i].getLocation(),
diag::err_unsupported_string_concat);
hadError = true;
}
}
}
// Include space for the null terminator.
++SizeBound;
// TODO: K&R warning: "traditional C rejects string constant concatenation"
// Get the width in bytes of char/wchar_t/char16_t/char32_t
CharByteWidth = getCharWidth(Kind, Target);
assert((CharByteWidth & 7) == 0 && "Assumes character size is byte multiple");
CharByteWidth /= 8;
// The output buffer size needs to be large enough to hold wide characters.
// This is a worst-case assumption which basically corresponds to L"" "long".
SizeBound *= CharByteWidth;
// Size the temporary buffer to hold the result string data.
ResultBuf.resize(SizeBound);
// Likewise, but for each string piece.
SmallString<512> TokenBuf;
TokenBuf.resize(MaxTokenLength);
// Loop over all the strings, getting their spelling, and expanding them to
// wide strings as appropriate.
ResultPtr = &ResultBuf[0]; // Next byte to fill in.
Pascal = false;
SourceLocation UDSuffixTokLoc;
for (unsigned i = 0, e = StringToks.size(); i != e; ++i) {
const char *ThisTokBuf = &TokenBuf[0];
// Get the spelling of the token, which eliminates trigraphs, etc. We know
// that ThisTokBuf points to a buffer that is big enough for the whole token
// and 'spelled' tokens can only shrink.
bool StringInvalid = false;
unsigned ThisTokLen =
Lexer::getSpelling(StringToks[i], ThisTokBuf, SM, Features,
&StringInvalid);
if (StringInvalid)
return DiagnoseLexingError(StringToks[i].getLocation());
const char *ThisTokBegin = ThisTokBuf;
const char *ThisTokEnd = ThisTokBuf+ThisTokLen;
// Remove an optional ud-suffix.
if (ThisTokEnd[-1] != '"') {
const char *UDSuffixEnd = ThisTokEnd;
do {
--ThisTokEnd;
} while (ThisTokEnd[-1] != '"');
StringRef UDSuffix(ThisTokEnd, UDSuffixEnd - ThisTokEnd);
if (UDSuffixBuf.empty()) {
if (StringToks[i].hasUCN())
expandUCNs(UDSuffixBuf, UDSuffix);
else
UDSuffixBuf.assign(UDSuffix);
UDSuffixToken = i;
UDSuffixOffset = ThisTokEnd - ThisTokBuf;
UDSuffixTokLoc = StringToks[i].getLocation();
} else {
SmallString<32> ExpandedUDSuffix;
if (StringToks[i].hasUCN()) {
expandUCNs(ExpandedUDSuffix, UDSuffix);
UDSuffix = ExpandedUDSuffix;
}
// C++11 [lex.ext]p8: At the end of phase 6, if a string literal is the
// result of a concatenation involving at least one user-defined-string-
// literal, all the participating user-defined-string-literals shall
// have the same ud-suffix.
if (UDSuffixBuf != UDSuffix) {
if (Diags) {
SourceLocation TokLoc = StringToks[i].getLocation();
Diags->Report(TokLoc, diag::err_string_concat_mixed_suffix)
<< UDSuffixBuf << UDSuffix
<< SourceRange(UDSuffixTokLoc, UDSuffixTokLoc)
<< SourceRange(TokLoc, TokLoc);
}
hadError = true;
}
}
}
// Strip the end quote.
--ThisTokEnd;
// TODO: Input character set mapping support.
// Skip marker for wide or unicode strings.
if (ThisTokBuf[0] == 'L' || ThisTokBuf[0] == 'u' || ThisTokBuf[0] == 'U') {
++ThisTokBuf;
// Skip 8 of u8 marker for utf8 strings.
if (ThisTokBuf[0] == '8')
++ThisTokBuf;
}
// Check for raw string
if (ThisTokBuf[0] == 'R') {
ThisTokBuf += 2; // skip R"
const char *Prefix = ThisTokBuf;
while (ThisTokBuf[0] != '(')
++ThisTokBuf;
++ThisTokBuf; // skip '('
// Remove same number of characters from the end
ThisTokEnd -= ThisTokBuf - Prefix;
assert(ThisTokEnd >= ThisTokBuf && "malformed raw string literal");
// C++14 [lex.string]p4: A source-file new-line in a raw string literal
// results in a new-line in the resulting execution string-literal.
StringRef RemainingTokenSpan(ThisTokBuf, ThisTokEnd - ThisTokBuf);
while (!RemainingTokenSpan.empty()) {
// Split the string literal on \r\n boundaries.
size_t CRLFPos = RemainingTokenSpan.find("\r\n");
StringRef BeforeCRLF = RemainingTokenSpan.substr(0, CRLFPos);
StringRef AfterCRLF = RemainingTokenSpan.substr(CRLFPos);
// Copy everything before the \r\n sequence into the string literal.
if (CopyStringFragment(StringToks[i], ThisTokBegin, BeforeCRLF))
hadError = true;
// Point into the \n inside the \r\n sequence and operate on the
// remaining portion of the literal.
RemainingTokenSpan = AfterCRLF.substr(1);
}
} else {
if (ThisTokBuf[0] != '"') {
// The file may have come from PCH and then changed after loading the
// PCH; Fail gracefully.
return DiagnoseLexingError(StringToks[i].getLocation());
}
++ThisTokBuf; // skip "
// Check if this is a pascal string
if (Features.PascalStrings && ThisTokBuf + 1 != ThisTokEnd &&
ThisTokBuf[0] == '\\' && ThisTokBuf[1] == 'p') {
// If the \p sequence is found in the first token, we have a pascal string
// Otherwise, if we already have a pascal string, ignore the first \p
if (i == 0) {
++ThisTokBuf;
Pascal = true;
} else if (Pascal)
ThisTokBuf += 2;
}
while (ThisTokBuf != ThisTokEnd) {
// Is this a span of non-escape characters?
if (ThisTokBuf[0] != '\\') {
const char *InStart = ThisTokBuf;
do {
++ThisTokBuf;
} while (ThisTokBuf != ThisTokEnd && ThisTokBuf[0] != '\\');
// Copy the character span over.
if (CopyStringFragment(StringToks[i], ThisTokBegin,
StringRef(InStart, ThisTokBuf - InStart)))
hadError = true;
continue;
}
// Is this a Universal Character Name escape?
if (ThisTokBuf[1] == 'u' || ThisTokBuf[1] == 'U') {
EncodeUCNEscape(ThisTokBegin, ThisTokBuf, ThisTokEnd,
ResultPtr, hadError,
FullSourceLoc(StringToks[i].getLocation(), SM),
CharByteWidth, Diags, Features);
continue;
}
// Otherwise, this is a non-UCN escape character. Process it.
unsigned ResultChar =
ProcessCharEscape(ThisTokBegin, ThisTokBuf, ThisTokEnd, hadError,
FullSourceLoc(StringToks[i].getLocation(), SM),
CharByteWidth*8, Diags, Features);
if (CharByteWidth == 4) {
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
llvm::UTF32 *ResultWidePtr = reinterpret_cast<llvm::UTF32*>(ResultPtr);
*ResultWidePtr = ResultChar;
ResultPtr += 4;
} else if (CharByteWidth == 2) {
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
llvm::UTF16 *ResultWidePtr = reinterpret_cast<llvm::UTF16*>(ResultPtr);
*ResultWidePtr = ResultChar & 0xFFFF;
ResultPtr += 2;
} else {
assert(CharByteWidth == 1 && "Unexpected char width");
*ResultPtr++ = ResultChar & 0xFF;
}
}
}
}
if (Pascal) {
if (CharByteWidth == 4) {
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
llvm::UTF32 *ResultWidePtr = reinterpret_cast<llvm::UTF32*>(ResultBuf.data());
ResultWidePtr[0] = GetNumStringChars() - 1;
} else if (CharByteWidth == 2) {
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
llvm::UTF16 *ResultWidePtr = reinterpret_cast<llvm::UTF16*>(ResultBuf.data());
ResultWidePtr[0] = GetNumStringChars() - 1;
} else {
assert(CharByteWidth == 1 && "Unexpected char width");
ResultBuf[0] = GetNumStringChars() - 1;
}
// Verify that pascal strings aren't too large.
if (GetStringLength() > 256) {
if (Diags)
Diags->Report(StringToks.front().getLocation(),
diag::err_pascal_string_too_long)
<< SourceRange(StringToks.front().getLocation(),
StringToks.back().getLocation());
hadError = true;
return;
}
} else if (Diags) {
// Complain if this string literal has too many characters.
unsigned MaxChars = Features.CPlusPlus? 65536 : Features.C99 ? 4095 : 509;
if (GetNumStringChars() > MaxChars)
Diags->Report(StringToks.front().getLocation(),
diag::ext_string_too_long)
<< GetNumStringChars() << MaxChars
<< (Features.CPlusPlus ? 2 : Features.C99 ? 1 : 0)
<< SourceRange(StringToks.front().getLocation(),
StringToks.back().getLocation());
}
}
static const char *resyncUTF8(const char *Err, const char *End) {
if (Err == End)
return End;
End = Err + std::min<unsigned>(llvm::getNumBytesForUTF8(*Err), End-Err);
while (++Err != End && (*Err & 0xC0) == 0x80)
;
return Err;
}
/// This function copies from Fragment, which is a sequence of bytes
/// within Tok's contents (which begin at TokBegin) into ResultPtr.
/// Performs widening for multi-byte characters.
bool StringLiteralParser::CopyStringFragment(const Token &Tok,
const char *TokBegin,
StringRef Fragment) {
const llvm::UTF8 *ErrorPtrTmp;
if (ConvertUTF8toWide(CharByteWidth, Fragment, ResultPtr, ErrorPtrTmp))
return false;
// If we see bad encoding for unprefixed string literals, warn and
// simply copy the byte values, for compatibility with gcc and older
// versions of clang.
bool NoErrorOnBadEncoding = isAscii();
if (NoErrorOnBadEncoding) {
memcpy(ResultPtr, Fragment.data(), Fragment.size());
ResultPtr += Fragment.size();
}
if (Diags) {
const char *ErrorPtr = reinterpret_cast<const char *>(ErrorPtrTmp);
FullSourceLoc SourceLoc(Tok.getLocation(), SM);
const DiagnosticBuilder &Builder =
Diag(Diags, Features, SourceLoc, TokBegin,
ErrorPtr, resyncUTF8(ErrorPtr, Fragment.end()),
NoErrorOnBadEncoding ? diag::warn_bad_string_encoding
: diag::err_bad_string_encoding);
const char *NextStart = resyncUTF8(ErrorPtr, Fragment.end());
StringRef NextFragment(NextStart, Fragment.end()-NextStart);
// Decode into a dummy buffer.
SmallString<512> Dummy;
Dummy.reserve(Fragment.size() * CharByteWidth);
char *Ptr = Dummy.data();
while (!ConvertUTF8toWide(CharByteWidth, NextFragment, Ptr, ErrorPtrTmp)) {
const char *ErrorPtr = reinterpret_cast<const char *>(ErrorPtrTmp);
NextStart = resyncUTF8(ErrorPtr, Fragment.end());
Builder << MakeCharSourceRange(Features, SourceLoc, TokBegin,
ErrorPtr, NextStart);
NextFragment = StringRef(NextStart, Fragment.end()-NextStart);
}
}
return !NoErrorOnBadEncoding;
}
void StringLiteralParser::DiagnoseLexingError(SourceLocation Loc) {
hadError = true;
if (Diags)
Diags->Report(Loc, diag::err_lexing_string);
}
/// getOffsetOfStringByte - This function returns the offset of the
/// specified byte of the string data represented by Token. This handles
/// advancing over escape sequences in the string.
unsigned StringLiteralParser::getOffsetOfStringByte(const Token &Tok,
unsigned ByteNo) const {
// Get the spelling of the token.
SmallString<32> SpellingBuffer;
SpellingBuffer.resize(Tok.getLength());
bool StringInvalid = false;
const char *SpellingPtr = &SpellingBuffer[0];
unsigned TokLen = Lexer::getSpelling(Tok, SpellingPtr, SM, Features,
&StringInvalid);
if (StringInvalid)
return 0;
const char *SpellingStart = SpellingPtr;
const char *SpellingEnd = SpellingPtr+TokLen;
// Handle UTF-8 strings just like narrow strings.
if (SpellingPtr[0] == 'u' && SpellingPtr[1] == '8')
SpellingPtr += 2;
assert(SpellingPtr[0] != 'L' && SpellingPtr[0] != 'u' &&
SpellingPtr[0] != 'U' && "Doesn't handle wide or utf strings yet");
// For raw string literals, this is easy.
if (SpellingPtr[0] == 'R') {
assert(SpellingPtr[1] == '"' && "Should be a raw string literal!");
// Skip 'R"'.
SpellingPtr += 2;
while (*SpellingPtr != '(') {
++SpellingPtr;
assert(SpellingPtr < SpellingEnd && "Missing ( for raw string literal");
}
// Skip '('.
++SpellingPtr;
return SpellingPtr - SpellingStart + ByteNo;
}
// Skip over the leading quote
assert(SpellingPtr[0] == '"' && "Should be a string literal!");
++SpellingPtr;
// Skip over bytes until we find the offset we're looking for.
while (ByteNo) {
assert(SpellingPtr < SpellingEnd && "Didn't find byte offset!");
// Step over non-escapes simply.
if (*SpellingPtr != '\\') {
++SpellingPtr;
--ByteNo;
continue;
}
// Otherwise, this is an escape character. Advance over it.
bool HadError = false;
if (SpellingPtr[1] == 'u' || SpellingPtr[1] == 'U') {
const char *EscapePtr = SpellingPtr;
unsigned Len = MeasureUCNEscape(SpellingStart, SpellingPtr, SpellingEnd,
1, Features, HadError);
if (Len > ByteNo) {
// ByteNo is somewhere within the escape sequence.
SpellingPtr = EscapePtr;
break;
}
ByteNo -= Len;
} else {
ProcessCharEscape(SpellingStart, SpellingPtr, SpellingEnd, HadError,
FullSourceLoc(Tok.getLocation(), SM),
CharByteWidth*8, Diags, Features);
--ByteNo;
}
assert(!HadError && "This method isn't valid on erroneous strings");
}
return SpellingPtr-SpellingStart;
}
/// Determine whether a suffix is a valid ud-suffix. We avoid treating reserved
/// suffixes as ud-suffixes, because the diagnostic experience is better if we
/// treat it as an invalid suffix.
bool StringLiteralParser::isValidUDSuffix(const LangOptions &LangOpts,
StringRef Suffix) {
return NumericLiteralParser::isValidUDSuffix(LangOpts, Suffix) ||
Suffix == "sv";
}
Index: vendor/clang/dist-release_80/lib/Sema/SemaCodeComplete.cpp
===================================================================
--- vendor/clang/dist-release_80/lib/Sema/SemaCodeComplete.cpp (revision 343795)
+++ vendor/clang/dist-release_80/lib/Sema/SemaCodeComplete.cpp (revision 343796)
@@ -1,8402 +1,8403 @@
//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the code-completion semantic actions.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/QualTypeNames.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Path.h"
#include <list>
#include <map>
#include <vector>
using namespace clang;
using namespace sema;
namespace {
/// A container of code-completion results.
class ResultBuilder {
public:
/// The type of a name-lookup filter, which can be provided to the
/// name-lookup routines to specify which declarations should be included in
/// the result set (when it returns true) and which declarations should be
/// filtered out (returns false).
typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
typedef CodeCompletionResult Result;
private:
/// The actual results we have found.
std::vector<Result> Results;
/// A record of all of the declarations we have found and placed
/// into the result set, used to ensure that no declaration ever gets into
/// the result set twice.
llvm::SmallPtrSet<const Decl *, 16> AllDeclsFound;
typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
/// An entry in the shadow map, which is optimized to store
/// a single (declaration, index) mapping (the common case) but
/// can also store a list of (declaration, index) mappings.
class ShadowMapEntry {
typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
/// Contains either the solitary NamedDecl * or a vector
/// of (declaration, index) pairs.
llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector *> DeclOrVector;
/// When the entry contains a single declaration, this is
/// the index associated with that entry.
unsigned SingleDeclIndex;
public:
ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) {}
void Add(const NamedDecl *ND, unsigned Index) {
if (DeclOrVector.isNull()) {
// 0 - > 1 elements: just set the single element information.
DeclOrVector = ND;
SingleDeclIndex = Index;
return;
}
if (const NamedDecl *PrevND =
DeclOrVector.dyn_cast<const NamedDecl *>()) {
// 1 -> 2 elements: create the vector of results and push in the
// existing declaration.
DeclIndexPairVector *Vec = new DeclIndexPairVector;
Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
DeclOrVector = Vec;
}
// Add the new element to the end of the vector.
DeclOrVector.get<DeclIndexPairVector *>()->push_back(
DeclIndexPair(ND, Index));
}
void Destroy() {
if (DeclIndexPairVector *Vec =
DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
delete Vec;
DeclOrVector = ((NamedDecl *)nullptr);
}
}
// Iteration.
class iterator;
iterator begin() const;
iterator end() const;
};
/// A mapping from declaration names to the declarations that have
/// this name within a particular scope and their index within the list of
/// results.
typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
/// The semantic analysis object for which results are being
/// produced.
Sema &SemaRef;
/// The allocator used to allocate new code-completion strings.
CodeCompletionAllocator &Allocator;
CodeCompletionTUInfo &CCTUInfo;
/// If non-NULL, a filter function used to remove any code-completion
/// results that are not desirable.
LookupFilter Filter;
/// Whether we should allow declarations as
/// nested-name-specifiers that would otherwise be filtered out.
bool AllowNestedNameSpecifiers;
/// If set, the type that we would prefer our resulting value
/// declarations to have.
///
/// Closely matching the preferred type gives a boost to a result's
/// priority.
CanQualType PreferredType;
/// A list of shadow maps, which is used to model name hiding at
/// different levels of, e.g., the inheritance hierarchy.
std::list<ShadowMap> ShadowMaps;
/// If we're potentially referring to a C++ member function, the set
/// of qualifiers applied to the object type.
Qualifiers ObjectTypeQualifiers;
/// Whether the \p ObjectTypeQualifiers field is active.
bool HasObjectTypeQualifiers;
/// The selector that we prefer.
Selector PreferredSelector;
/// The completion context in which we are gathering results.
CodeCompletionContext CompletionContext;
/// If we are in an instance method definition, the \@implementation
/// object.
ObjCImplementationDecl *ObjCImplementation;
void AdjustResultPriorityForDecl(Result &R);
void MaybeAddConstructorResults(Result R);
public:
explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo,
const CodeCompletionContext &CompletionContext,
LookupFilter Filter = nullptr)
: SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
Filter(Filter), AllowNestedNameSpecifiers(false),
HasObjectTypeQualifiers(false), CompletionContext(CompletionContext),
ObjCImplementation(nullptr) {
// If this is an Objective-C instance method definition, dig out the
// corresponding implementation.
switch (CompletionContext.getKind()) {
case CodeCompletionContext::CCC_Expression:
case CodeCompletionContext::CCC_ObjCMessageReceiver:
case CodeCompletionContext::CCC_ParenthesizedExpression:
case CodeCompletionContext::CCC_Statement:
case CodeCompletionContext::CCC_Recovery:
if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
if (Method->isInstanceMethod())
if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
ObjCImplementation = Interface->getImplementation();
break;
default:
break;
}
}
/// Determine the priority for a reference to the given declaration.
unsigned getBasePriority(const NamedDecl *D);
/// Whether we should include code patterns in the completion
/// results.
bool includeCodePatterns() const {
return SemaRef.CodeCompleter &&
SemaRef.CodeCompleter->includeCodePatterns();
}
/// Set the filter used for code-completion results.
void setFilter(LookupFilter Filter) { this->Filter = Filter; }
Result *data() { return Results.empty() ? nullptr : &Results.front(); }
unsigned size() const { return Results.size(); }
bool empty() const { return Results.empty(); }
/// Specify the preferred type.
void setPreferredType(QualType T) {
PreferredType = SemaRef.Context.getCanonicalType(T);
}
/// Set the cv-qualifiers on the object type, for us in filtering
/// calls to member functions.
///
/// When there are qualifiers in this set, they will be used to filter
/// out member functions that aren't available (because there will be a
/// cv-qualifier mismatch) or prefer functions with an exact qualifier
/// match.
void setObjectTypeQualifiers(Qualifiers Quals) {
ObjectTypeQualifiers = Quals;
HasObjectTypeQualifiers = true;
}
/// Set the preferred selector.
///
/// When an Objective-C method declaration result is added, and that
/// method's selector matches this preferred selector, we give that method
/// a slight priority boost.
void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; }
/// Retrieve the code-completion context for which results are
/// being collected.
const CodeCompletionContext &getCompletionContext() const {
return CompletionContext;
}
/// Specify whether nested-name-specifiers are allowed.
void allowNestedNameSpecifiers(bool Allow = true) {
AllowNestedNameSpecifiers = Allow;
}
/// Return the semantic analysis object for which we are collecting
/// code completion results.
Sema &getSema() const { return SemaRef; }
/// Retrieve the allocator used to allocate code completion strings.
CodeCompletionAllocator &getAllocator() const { return Allocator; }
CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
/// Determine whether the given declaration is at all interesting
/// as a code-completion result.
///
/// \param ND the declaration that we are inspecting.
///
/// \param AsNestedNameSpecifier will be set true if this declaration is
/// only interesting when it is a nested-name-specifier.
bool isInterestingDecl(const NamedDecl *ND,
bool &AsNestedNameSpecifier) const;
/// Check whether the result is hidden by the Hiding declaration.
///
/// \returns true if the result is hidden and cannot be found, false if
/// the hidden result could still be found. When false, \p R may be
/// modified to describe how the result can be found (e.g., via extra
/// qualification).
bool CheckHiddenResult(Result &R, DeclContext *CurContext,
const NamedDecl *Hiding);
/// Add a new result to this result set (if it isn't already in one
/// of the shadow maps), or replace an existing result (for, e.g., a
/// redeclaration).
///
/// \param R the result to add (if it is unique).
///
/// \param CurContext the context in which this result will be named.
void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
/// Add a new result to this result set, where we already know
/// the hiding declaration (if any).
///
/// \param R the result to add (if it is unique).
///
/// \param CurContext the context in which this result will be named.
///
/// \param Hiding the declaration that hides the result.
///
/// \param InBaseClass whether the result was found in a base
/// class of the searched context.
void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
bool InBaseClass);
/// Add a new non-declaration result to this result set.
void AddResult(Result R);
/// Enter into a new scope.
void EnterNewScope();
/// Exit from the current scope.
void ExitScope();
/// Ignore this declaration, if it is seen again.
void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
/// Add a visited context.
void addVisitedContext(DeclContext *Ctx) {
CompletionContext.addVisitedContext(Ctx);
}
/// \name Name lookup predicates
///
/// These predicates can be passed to the name lookup functions to filter the
/// results of name lookup. All of the predicates have the same type, so that
///
//@{
bool IsOrdinaryName(const NamedDecl *ND) const;
bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
bool IsIntegralConstantValue(const NamedDecl *ND) const;
bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
bool IsNestedNameSpecifier(const NamedDecl *ND) const;
bool IsEnum(const NamedDecl *ND) const;
bool IsClassOrStruct(const NamedDecl *ND) const;
bool IsUnion(const NamedDecl *ND) const;
bool IsNamespace(const NamedDecl *ND) const;
bool IsNamespaceOrAlias(const NamedDecl *ND) const;
bool IsType(const NamedDecl *ND) const;
bool IsMember(const NamedDecl *ND) const;
bool IsObjCIvar(const NamedDecl *ND) const;
bool IsObjCMessageReceiver(const NamedDecl *ND) const;
bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
bool IsObjCCollection(const NamedDecl *ND) const;
bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
//@}
};
} // namespace
class ResultBuilder::ShadowMapEntry::iterator {
llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
unsigned SingleDeclIndex;
public:
typedef DeclIndexPair value_type;
typedef value_type reference;
typedef std::ptrdiff_t difference_type;
typedef std::input_iterator_tag iterator_category;
class pointer {
DeclIndexPair Value;
public:
pointer(const DeclIndexPair &Value) : Value(Value) {}
const DeclIndexPair *operator->() const { return &Value; }
};
iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
iterator(const NamedDecl *SingleDecl, unsigned Index)
: DeclOrIterator(SingleDecl), SingleDeclIndex(Index) {}
iterator(const DeclIndexPair *Iterator)
: DeclOrIterator(Iterator), SingleDeclIndex(0) {}
iterator &operator++() {
if (DeclOrIterator.is<const NamedDecl *>()) {
DeclOrIterator = (NamedDecl *)nullptr;
SingleDeclIndex = 0;
return *this;
}
const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair *>();
++I;
DeclOrIterator = I;
return *this;
}
/*iterator operator++(int) {
iterator tmp(*this);
++(*this);
return tmp;
}*/
reference operator*() const {
if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
return reference(ND, SingleDeclIndex);
return *DeclOrIterator.get<const DeclIndexPair *>();
}
pointer operator->() const { return pointer(**this); }
friend bool operator==(const iterator &X, const iterator &Y) {
return X.DeclOrIterator.getOpaqueValue() ==
Y.DeclOrIterator.getOpaqueValue() &&
X.SingleDeclIndex == Y.SingleDeclIndex;
}
friend bool operator!=(const iterator &X, const iterator &Y) {
return !(X == Y);
}
};
ResultBuilder::ShadowMapEntry::iterator
ResultBuilder::ShadowMapEntry::begin() const {
if (DeclOrVector.isNull())
return iterator();
if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
return iterator(ND, SingleDeclIndex);
return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
}
ResultBuilder::ShadowMapEntry::iterator
ResultBuilder::ShadowMapEntry::end() const {
if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
return iterator();
return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
}
/// Compute the qualification required to get from the current context
/// (\p CurContext) to the target context (\p TargetContext).
///
/// \param Context the AST context in which the qualification will be used.
///
/// \param CurContext the context where an entity is being named, which is
/// typically based on the current scope.
///
/// \param TargetContext the context in which the named entity actually
/// resides.
///
/// \returns a nested name specifier that refers into the target context, or
/// NULL if no qualification is needed.
static NestedNameSpecifier *
getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
const DeclContext *TargetContext) {
SmallVector<const DeclContext *, 4> TargetParents;
for (const DeclContext *CommonAncestor = TargetContext;
CommonAncestor && !CommonAncestor->Encloses(CurContext);
CommonAncestor = CommonAncestor->getLookupParent()) {
if (CommonAncestor->isTransparentContext() ||
CommonAncestor->isFunctionOrMethod())
continue;
TargetParents.push_back(CommonAncestor);
}
NestedNameSpecifier *Result = nullptr;
while (!TargetParents.empty()) {
const DeclContext *Parent = TargetParents.pop_back_val();
if (const auto *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
if (!Namespace->getIdentifier())
continue;
Result = NestedNameSpecifier::Create(Context, Result, Namespace);
} else if (const auto *TD = dyn_cast<TagDecl>(Parent))
Result = NestedNameSpecifier::Create(
Context, Result, false, Context.getTypeDeclType(TD).getTypePtr());
}
return Result;
}
/// Determine whether \p Id is a name reserved for the implementation (C99
/// 7.1.3, C++ [lib.global.names]).
static bool isReservedName(const IdentifierInfo *Id,
bool doubleUnderscoreOnly = false) {
if (Id->getLength() < 2)
return false;
const char *Name = Id->getNameStart();
return Name[0] == '_' &&
(Name[1] == '_' ||
(Name[1] >= 'A' && Name[1] <= 'Z' && !doubleUnderscoreOnly));
}
// Some declarations have reserved names that we don't want to ever show.
// Filter out names reserved for the implementation if they come from a
// system header.
static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
const IdentifierInfo *Id = ND->getIdentifier();
if (!Id)
return false;
// Ignore reserved names for compiler provided decls.
if (isReservedName(Id) && ND->getLocation().isInvalid())
return true;
// For system headers ignore only double-underscore names.
// This allows for system headers providing private symbols with a single
// underscore.
if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
SemaRef.SourceMgr.isInSystemHeader(
SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
return true;
return false;
}
bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
bool &AsNestedNameSpecifier) const {
AsNestedNameSpecifier = false;
auto *Named = ND;
ND = ND->getUnderlyingDecl();
// Skip unnamed entities.
if (!ND->getDeclName())
return false;
// Friend declarations and declarations introduced due to friends are never
// added as results.
if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
return false;
// Class template (partial) specializations are never added as results.
if (isa<ClassTemplateSpecializationDecl>(ND) ||
isa<ClassTemplatePartialSpecializationDecl>(ND))
return false;
// Using declarations themselves are never added as results.
if (isa<UsingDecl>(ND))
return false;
if (shouldIgnoreDueToReservedName(ND, SemaRef))
return false;
if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
(isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace &&
Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr))
AsNestedNameSpecifier = true;
// Filter out any unwanted results.
if (Filter && !(this->*Filter)(Named)) {
// Check whether it is interesting as a nested-name-specifier.
if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
IsNestedNameSpecifier(ND) &&
(Filter != &ResultBuilder::IsMember ||
(isa<CXXRecordDecl>(ND) &&
cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
AsNestedNameSpecifier = true;
return true;
}
return false;
}
// ... then it must be interesting!
return true;
}
bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
const NamedDecl *Hiding) {
// In C, there is no way to refer to a hidden name.
// FIXME: This isn't true; we can find a tag name hidden by an ordinary
// name if we introduce the tag type.
if (!SemaRef.getLangOpts().CPlusPlus)
return true;
const DeclContext *HiddenCtx =
R.Declaration->getDeclContext()->getRedeclContext();
// There is no way to qualify a name declared in a function or method.
if (HiddenCtx->isFunctionOrMethod())
return true;
if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
return true;
// We can refer to the result with the appropriate qualification. Do it.
R.Hidden = true;
R.QualifierIsInformative = false;
if (!R.Qualifier)
R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext,
R.Declaration->getDeclContext());
return false;
}
/// A simplified classification of types used to determine whether two
/// types are "similar enough" when adjusting priorities.
SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
switch (T->getTypeClass()) {
case Type::Builtin:
switch (cast<BuiltinType>(T)->getKind()) {
case BuiltinType::Void:
return STC_Void;
case BuiltinType::NullPtr:
return STC_Pointer;
case BuiltinType::Overload:
case BuiltinType::Dependent:
return STC_Other;
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
return STC_ObjectiveC;
default:
return STC_Arithmetic;
}
case Type::Complex:
return STC_Arithmetic;
case Type::Pointer:
return STC_Pointer;
case Type::BlockPointer:
return STC_Block;
case Type::LValueReference:
case Type::RValueReference:
return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
case Type::ConstantArray:
case Type::IncompleteArray:
case Type::VariableArray:
case Type::DependentSizedArray:
return STC_Array;
case Type::DependentSizedExtVector:
case Type::Vector:
case Type::ExtVector:
return STC_Arithmetic;
case Type::FunctionProto:
case Type::FunctionNoProto:
return STC_Function;
case Type::Record:
return STC_Record;
case Type::Enum:
return STC_Arithmetic;
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
return STC_ObjectiveC;
default:
return STC_Other;
}
}
/// Get the type that a given expression will have if this declaration
/// is used as an expression in its "typical" code-completion form.
QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
ND = ND->getUnderlyingDecl();
if (const auto *Type = dyn_cast<TypeDecl>(ND))
return C.getTypeDeclType(Type);
if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
return C.getObjCInterfaceType(Iface);
QualType T;
if (const FunctionDecl *Function = ND->getAsFunction())
T = Function->getCallResultType();
else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND))
T = Method->getSendResultType();
else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND))
T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND))
T = Property->getType();
else if (const auto *Value = dyn_cast<ValueDecl>(ND))
T = Value->getType();
- else
+
+ if (T.isNull())
return QualType();
// Dig through references, function pointers, and block pointers to
// get down to the likely type of an expression when the entity is
// used.
do {
if (const auto *Ref = T->getAs<ReferenceType>()) {
T = Ref->getPointeeType();
continue;
}
if (const auto *Pointer = T->getAs<PointerType>()) {
if (Pointer->getPointeeType()->isFunctionType()) {
T = Pointer->getPointeeType();
continue;
}
break;
}
if (const auto *Block = T->getAs<BlockPointerType>()) {
T = Block->getPointeeType();
continue;
}
if (const auto *Function = T->getAs<FunctionType>()) {
T = Function->getReturnType();
continue;
}
break;
} while (true);
return T;
}
unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
if (!ND)
return CCP_Unlikely;
// Context-based decisions.
const DeclContext *LexicalDC = ND->getLexicalDeclContext();
if (LexicalDC->isFunctionOrMethod()) {
// _cmd is relatively rare
if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
if (ImplicitParam->getIdentifier() &&
ImplicitParam->getIdentifier()->isStr("_cmd"))
return CCP_ObjC_cmd;
return CCP_LocalDeclaration;
}
const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
// Explicit destructor calls are very rare.
if (isa<CXXDestructorDecl>(ND))
return CCP_Unlikely;
// Explicit operator and conversion function calls are also very rare.
auto DeclNameKind = ND->getDeclName().getNameKind();
if (DeclNameKind == DeclarationName::CXXOperatorName ||
DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
DeclNameKind == DeclarationName::CXXConversionFunctionName)
return CCP_Unlikely;
return CCP_MemberDeclaration;
}
// Content-based decisions.
if (isa<EnumConstantDecl>(ND))
return CCP_Constant;
// Use CCP_Type for type declarations unless we're in a statement, Objective-C
// message receiver, or parenthesized expression context. There, it's as
// likely that the user will want to write a type as other declarations.
if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
!(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
CompletionContext.getKind() ==
CodeCompletionContext::CCC_ObjCMessageReceiver ||
CompletionContext.getKind() ==
CodeCompletionContext::CCC_ParenthesizedExpression))
return CCP_Type;
return CCP_Declaration;
}
void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
// If this is an Objective-C method declaration whose selector matches our
// preferred selector, give it a priority boost.
if (!PreferredSelector.isNull())
if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
if (PreferredSelector == Method->getSelector())
R.Priority += CCD_SelectorMatch;
// If we have a preferred type, adjust the priority for results with exactly-
// matching or nearly-matching types.
if (!PreferredType.isNull()) {
QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
if (!T.isNull()) {
CanQualType TC = SemaRef.Context.getCanonicalType(T);
// Check for exactly-matching types (modulo qualifiers).
if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
R.Priority /= CCF_ExactTypeMatch;
// Check for nearly-matching types, based on classification of each.
else if ((getSimplifiedTypeClass(PreferredType) ==
getSimplifiedTypeClass(TC)) &&
!(PreferredType->isEnumeralType() && TC->isEnumeralType()))
R.Priority /= CCF_SimilarTypeMatch;
}
}
}
DeclContext::lookup_result getConstructors(ASTContext &Context,
const CXXRecordDecl *Record) {
QualType RecordTy = Context.getTypeDeclType(Record);
DeclarationName ConstructorName =
Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(RecordTy));
return Record->lookup(ConstructorName);
}
void ResultBuilder::MaybeAddConstructorResults(Result R) {
if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
!CompletionContext.wantConstructorResults())
return;
const NamedDecl *D = R.Declaration;
const CXXRecordDecl *Record = nullptr;
if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Record = ClassTemplate->getTemplatedDecl();
else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
// Skip specializations and partial specializations.
if (isa<ClassTemplateSpecializationDecl>(Record))
return;
} else {
// There are no constructors here.
return;
}
Record = Record->getDefinition();
if (!Record)
return;
for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) {
R.Declaration = Ctor;
R.CursorKind = getCursorKindForDecl(R.Declaration);
Results.push_back(R);
}
}
static bool isConstructor(const Decl *ND) {
if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
ND = Tmpl->getTemplatedDecl();
return isa<CXXConstructorDecl>(ND);
}
void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
assert(!ShadowMaps.empty() && "Must enter into a results scope");
if (R.Kind != Result::RK_Declaration) {
// For non-declaration results, just add the result.
Results.push_back(R);
return;
}
// Look through using declarations.
if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
CodeCompletionResult Result(Using->getTargetDecl(),
getBasePriority(Using->getTargetDecl()),
R.Qualifier);
Result.ShadowDecl = Using;
MaybeAddResult(Result, CurContext);
return;
}
const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
unsigned IDNS = CanonDecl->getIdentifierNamespace();
bool AsNestedNameSpecifier = false;
if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
return;
// C++ constructors are never found by name lookup.
if (isConstructor(R.Declaration))
return;
ShadowMap &SMap = ShadowMaps.back();
ShadowMapEntry::iterator I, IEnd;
ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
if (NamePos != SMap.end()) {
I = NamePos->second.begin();
IEnd = NamePos->second.end();
}
for (; I != IEnd; ++I) {
const NamedDecl *ND = I->first;
unsigned Index = I->second;
if (ND->getCanonicalDecl() == CanonDecl) {
// This is a redeclaration. Always pick the newer declaration.
Results[Index].Declaration = R.Declaration;
// We're done.
return;
}
}
// This is a new declaration in this scope. However, check whether this
// declaration name is hidden by a similarly-named declaration in an outer
// scope.
std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
--SMEnd;
for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
ShadowMapEntry::iterator I, IEnd;
ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
if (NamePos != SM->end()) {
I = NamePos->second.begin();
IEnd = NamePos->second.end();
}
for (; I != IEnd; ++I) {
// A tag declaration does not hide a non-tag declaration.
if (I->first->hasTagIdentifierNamespace() &&
(IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
continue;
// Protocols are in distinct namespaces from everything else.
if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) ||
(IDNS & Decl::IDNS_ObjCProtocol)) &&
I->first->getIdentifierNamespace() != IDNS)
continue;
// The newly-added result is hidden by an entry in the shadow map.
if (CheckHiddenResult(R, CurContext, I->first))
return;
break;
}
}
// Make sure that any given declaration only shows up in the result set once.
if (!AllDeclsFound.insert(CanonDecl).second)
return;
// If the filter is for nested-name-specifiers, then this result starts a
// nested-name-specifier.
if (AsNestedNameSpecifier) {
R.StartsNestedNameSpecifier = true;
R.Priority = CCP_NestedNameSpecifier;
} else
AdjustResultPriorityForDecl(R);
// If this result is supposed to have an informative qualifier, add one.
if (R.QualifierIsInformative && !R.Qualifier &&
!R.StartsNestedNameSpecifier) {
const DeclContext *Ctx = R.Declaration->getDeclContext();
if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
R.Qualifier =
NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
R.Qualifier = NestedNameSpecifier::Create(
SemaRef.Context, nullptr, false,
SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
else
R.QualifierIsInformative = false;
}
// Insert this result into the set of results and into the current shadow
// map.
SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Results.push_back(R);
if (!AsNestedNameSpecifier)
MaybeAddConstructorResults(R);
}
static void setInBaseClass(ResultBuilder::Result &R) {
R.Priority += CCD_InBaseClass;
R.InBaseClass = true;
}
void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
NamedDecl *Hiding, bool InBaseClass = false) {
if (R.Kind != Result::RK_Declaration) {
// For non-declaration results, just add the result.
Results.push_back(R);
return;
}
// Look through using declarations.
if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
CodeCompletionResult Result(Using->getTargetDecl(),
getBasePriority(Using->getTargetDecl()),
R.Qualifier);
Result.ShadowDecl = Using;
AddResult(Result, CurContext, Hiding);
return;
}
bool AsNestedNameSpecifier = false;
if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
return;
// C++ constructors are never found by name lookup.
if (isConstructor(R.Declaration))
return;
if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
return;
// Make sure that any given declaration only shows up in the result set once.
if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
return;
// If the filter is for nested-name-specifiers, then this result starts a
// nested-name-specifier.
if (AsNestedNameSpecifier) {
R.StartsNestedNameSpecifier = true;
R.Priority = CCP_NestedNameSpecifier;
} else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
InBaseClass &&
isa<CXXRecordDecl>(
R.Declaration->getDeclContext()->getRedeclContext()))
R.QualifierIsInformative = true;
// If this result is supposed to have an informative qualifier, add one.
if (R.QualifierIsInformative && !R.Qualifier &&
!R.StartsNestedNameSpecifier) {
const DeclContext *Ctx = R.Declaration->getDeclContext();
if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx))
R.Qualifier =
NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))
R.Qualifier = NestedNameSpecifier::Create(
SemaRef.Context, nullptr, false,
SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
else
R.QualifierIsInformative = false;
}
// Adjust the priority if this result comes from a base class.
if (InBaseClass)
setInBaseClass(R);
AdjustResultPriorityForDecl(R);
if (HasObjectTypeQualifiers)
if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
if (Method->isInstance()) {
Qualifiers MethodQuals = Method->getTypeQualifiers();
if (ObjectTypeQualifiers == MethodQuals)
R.Priority += CCD_ObjectQualifierMatch;
else if (ObjectTypeQualifiers - MethodQuals) {
// The method cannot be invoked, because doing so would drop
// qualifiers.
return;
}
}
// Insert this result into the set of results.
Results.push_back(R);
if (!AsNestedNameSpecifier)
MaybeAddConstructorResults(R);
}
void ResultBuilder::AddResult(Result R) {
assert(R.Kind != Result::RK_Declaration &&
"Declaration results need more context");
Results.push_back(R);
}
/// Enter into a new scope.
void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
/// Exit from the current scope.
void ResultBuilder::ExitScope() {
for (ShadowMap::iterator E = ShadowMaps.back().begin(),
EEnd = ShadowMaps.back().end();
E != EEnd; ++E)
E->second.Destroy();
ShadowMaps.pop_back();
}
/// Determines whether this given declaration will be found by
/// ordinary name lookup.
bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
ND = ND->getUnderlyingDecl();
// If name lookup finds a local extern declaration, then we are in a
// context where it behaves like an ordinary name.
unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
if (SemaRef.getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
else if (SemaRef.getLangOpts().ObjC) {
if (isa<ObjCIvarDecl>(ND))
return true;
}
return ND->getIdentifierNamespace() & IDNS;
}
/// Determines whether this given declaration will be found by
/// ordinary name lookup but is not a type name.
bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
ND = ND->getUnderlyingDecl();
if (isa<TypeDecl>(ND))
return false;
// Objective-C interfaces names are not filtered by this method because they
// can be used in a class property expression. We can still filter out
// @class declarations though.
if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
if (!ID->getDefinition())
return false;
}
unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
if (SemaRef.getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
else if (SemaRef.getLangOpts().ObjC) {
if (isa<ObjCIvarDecl>(ND))
return true;
}
return ND->getIdentifierNamespace() & IDNS;
}
bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
if (!IsOrdinaryNonTypeName(ND))
return 0;
if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
if (VD->getType()->isIntegralOrEnumerationType())
return true;
return false;
}
/// Determines whether this given declaration will be found by
/// ordinary name lookup.
bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
ND = ND->getUnderlyingDecl();
unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
if (SemaRef.getLangOpts().CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) &&
!isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND);
}
/// Determines whether the given declaration is suitable as the
/// start of a C++ nested-name-specifier, e.g., a class or namespace.
bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
// Allow us to find class templates, too.
if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
ND = ClassTemplate->getTemplatedDecl();
return SemaRef.isAcceptableNestedNameSpecifier(ND);
}
/// Determines whether the given declaration is an enumeration.
bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
return isa<EnumDecl>(ND);
}
/// Determines whether the given declaration is a class or struct.
bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
// Allow us to find class templates, too.
if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
ND = ClassTemplate->getTemplatedDecl();
// For purposes of this check, interfaces match too.
if (const auto *RD = dyn_cast<RecordDecl>(ND))
return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct ||
RD->getTagKind() == TTK_Interface;
return false;
}
/// Determines whether the given declaration is a union.
bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
// Allow us to find class templates, too.
if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
ND = ClassTemplate->getTemplatedDecl();
if (const auto *RD = dyn_cast<RecordDecl>(ND))
return RD->getTagKind() == TTK_Union;
return false;
}
/// Determines whether the given declaration is a namespace.
bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
return isa<NamespaceDecl>(ND);
}
/// Determines whether the given declaration is a namespace or
/// namespace alias.
bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
return isa<NamespaceDecl>(ND->getUnderlyingDecl());
}
/// Determines whether the given declaration is a type.
bool ResultBuilder::IsType(const NamedDecl *ND) const {
ND = ND->getUnderlyingDecl();
return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
}
/// Determines which members of a class should be visible via
/// "." or "->". Only value declarations, nested name specifiers, and
/// using declarations thereof should show up.
bool ResultBuilder::IsMember(const NamedDecl *ND) const {
ND = ND->getUnderlyingDecl();
return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
isa<ObjCPropertyDecl>(ND);
}
static bool isObjCReceiverType(ASTContext &C, QualType T) {
T = C.getCanonicalType(T);
switch (T->getTypeClass()) {
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
return true;
case Type::Builtin:
switch (cast<BuiltinType>(T)->getKind()) {
case BuiltinType::ObjCId:
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
return true;
default:
break;
}
return false;
default:
break;
}
if (!C.getLangOpts().CPlusPlus)
return false;
// FIXME: We could perform more analysis here to determine whether a
// particular class type has any conversions to Objective-C types. For now,
// just accept all class types.
return T->isDependentType() || T->isRecordType();
}
bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
QualType T = getDeclUsageType(SemaRef.Context, ND);
if (T.isNull())
return false;
T = SemaRef.Context.getBaseElementType(T);
return isObjCReceiverType(SemaRef.Context, T);
}
bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(
const NamedDecl *ND) const {
if (IsObjCMessageReceiver(ND))
return true;
const auto *Var = dyn_cast<VarDecl>(ND);
if (!Var)
return false;
return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
}
bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
(!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
return false;
QualType T = getDeclUsageType(SemaRef.Context, ND);
if (T.isNull())
return false;
T = SemaRef.Context.getBaseElementType(T);
return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
T->isObjCIdType() ||
(SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
}
bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
return false;
}
/// Determines whether the given declaration is an Objective-C
/// instance variable.
bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
return isa<ObjCIvarDecl>(ND);
}
namespace {
/// Visible declaration consumer that adds a code-completion result
/// for each visible declaration.
class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
ResultBuilder &Results;
DeclContext *InitialLookupCtx;
// NamingClass and BaseType are used for access-checking. See
// Sema::IsSimplyAccessible for details.
CXXRecordDecl *NamingClass;
QualType BaseType;
std::vector<FixItHint> FixIts;
public:
CodeCompletionDeclConsumer(
ResultBuilder &Results, DeclContext *InitialLookupCtx,
QualType BaseType = QualType(),
std::vector<FixItHint> FixIts = std::vector<FixItHint>())
: Results(Results), InitialLookupCtx(InitialLookupCtx),
FixIts(std::move(FixIts)) {
NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx);
// If BaseType was not provided explicitly, emulate implicit 'this->'.
if (BaseType.isNull()) {
auto ThisType = Results.getSema().getCurrentThisType();
if (!ThisType.isNull()) {
assert(ThisType->isPointerType());
BaseType = ThisType->getPointeeType();
if (!NamingClass)
NamingClass = BaseType->getAsCXXRecordDecl();
}
}
this->BaseType = BaseType;
}
void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
bool InBaseClass) override {
ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
false, IsAccessible(ND, Ctx), FixIts);
Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass);
}
void EnteredContext(DeclContext *Ctx) override {
Results.addVisitedContext(Ctx);
}
private:
bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) {
// Naming class to use for access check. In most cases it was provided
// explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)),
// for unqualified lookup we fallback to the \p Ctx in which we found the
// member.
auto *NamingClass = this->NamingClass;
QualType BaseType = this->BaseType;
if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) {
if (!NamingClass)
NamingClass = Cls;
// When we emulate implicit 'this->' in an unqualified lookup, we might
// end up with an invalid naming class. In that case, we avoid emulating
// 'this->' qualifier to satisfy preconditions of the access checking.
if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() &&
!NamingClass->isDerivedFrom(Cls)) {
NamingClass = Cls;
BaseType = QualType();
}
} else {
// The decl was found outside the C++ class, so only ObjC access checks
// apply. Those do not rely on NamingClass and BaseType, so we clear them
// out.
NamingClass = nullptr;
BaseType = QualType();
}
return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType);
}
};
} // namespace
/// Add type specifiers for the current language as keyword results.
static void AddTypeSpecifierResults(const LangOptions &LangOpts,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
Results.AddResult(Result("short", CCP_Type));
Results.AddResult(Result("long", CCP_Type));
Results.AddResult(Result("signed", CCP_Type));
Results.AddResult(Result("unsigned", CCP_Type));
Results.AddResult(Result("void", CCP_Type));
Results.AddResult(Result("char", CCP_Type));
Results.AddResult(Result("int", CCP_Type));
Results.AddResult(Result("float", CCP_Type));
Results.AddResult(Result("double", CCP_Type));
Results.AddResult(Result("enum", CCP_Type));
Results.AddResult(Result("struct", CCP_Type));
Results.AddResult(Result("union", CCP_Type));
Results.AddResult(Result("const", CCP_Type));
Results.AddResult(Result("volatile", CCP_Type));
if (LangOpts.C99) {
// C99-specific
Results.AddResult(Result("_Complex", CCP_Type));
Results.AddResult(Result("_Imaginary", CCP_Type));
Results.AddResult(Result("_Bool", CCP_Type));
Results.AddResult(Result("restrict", CCP_Type));
}
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
if (LangOpts.CPlusPlus) {
// C++-specific
Results.AddResult(
Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0)));
Results.AddResult(Result("class", CCP_Type));
Results.AddResult(Result("wchar_t", CCP_Type));
// typename qualified-id
Builder.AddTypedTextChunk("typename");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("qualifier");
Builder.AddTextChunk("::");
Builder.AddPlaceholderChunk("name");
Results.AddResult(Result(Builder.TakeString()));
if (LangOpts.CPlusPlus11) {
Results.AddResult(Result("auto", CCP_Type));
Results.AddResult(Result("char16_t", CCP_Type));
Results.AddResult(Result("char32_t", CCP_Type));
Builder.AddTypedTextChunk("decltype");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
}
} else
Results.AddResult(Result("__auto_type", CCP_Type));
// GNU keywords
if (LangOpts.GNUKeywords) {
// FIXME: Enable when we actually support decimal floating point.
// Results.AddResult(Result("_Decimal32"));
// Results.AddResult(Result("_Decimal64"));
// Results.AddResult(Result("_Decimal128"));
Builder.AddTypedTextChunk("typeof");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("expression");
Results.AddResult(Result(Builder.TakeString()));
Builder.AddTypedTextChunk("typeof");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
}
// Nullability
Results.AddResult(Result("_Nonnull", CCP_Type));
Results.AddResult(Result("_Null_unspecified", CCP_Type));
Results.AddResult(Result("_Nullable", CCP_Type));
}
static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
const LangOptions &LangOpts,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
// Note: we don't suggest either "auto" or "register", because both
// are pointless as storage specifiers. Elsewhere, we suggest "auto"
// in C++0x as a type specifier.
Results.AddResult(Result("extern"));
Results.AddResult(Result("static"));
if (LangOpts.CPlusPlus11) {
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
// alignas
Builder.AddTypedTextChunk("alignas");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
Results.AddResult(Result("constexpr"));
Results.AddResult(Result("thread_local"));
}
}
static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
const LangOptions &LangOpts,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
switch (CCC) {
case Sema::PCC_Class:
case Sema::PCC_MemberTemplate:
if (LangOpts.CPlusPlus) {
Results.AddResult(Result("explicit"));
Results.AddResult(Result("friend"));
Results.AddResult(Result("mutable"));
Results.AddResult(Result("virtual"));
}
LLVM_FALLTHROUGH;
case Sema::PCC_ObjCInterface:
case Sema::PCC_ObjCImplementation:
case Sema::PCC_Namespace:
case Sema::PCC_Template:
if (LangOpts.CPlusPlus || LangOpts.C99)
Results.AddResult(Result("inline"));
break;
case Sema::PCC_ObjCInstanceVariableList:
case Sema::PCC_Expression:
case Sema::PCC_Statement:
case Sema::PCC_ForInit:
case Sema::PCC_Condition:
case Sema::PCC_RecoveryInFunction:
case Sema::PCC_Type:
case Sema::PCC_ParenthesizedExpression:
case Sema::PCC_LocalDeclarationSpecifiers:
break;
}
}
static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
static void AddObjCVisibilityResults(const LangOptions &LangOpts,
ResultBuilder &Results, bool NeedAt);
static void AddObjCImplementationResults(const LangOptions &LangOpts,
ResultBuilder &Results, bool NeedAt);
static void AddObjCInterfaceResults(const LangOptions &LangOpts,
ResultBuilder &Results, bool NeedAt);
static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
static void AddTypedefResult(ResultBuilder &Results) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Builder.AddTypedTextChunk("typedef");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("name");
Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
const LangOptions &LangOpts) {
switch (CCC) {
case Sema::PCC_Namespace:
case Sema::PCC_Class:
case Sema::PCC_ObjCInstanceVariableList:
case Sema::PCC_Template:
case Sema::PCC_MemberTemplate:
case Sema::PCC_Statement:
case Sema::PCC_RecoveryInFunction:
case Sema::PCC_Type:
case Sema::PCC_ParenthesizedExpression:
case Sema::PCC_LocalDeclarationSpecifiers:
return true;
case Sema::PCC_Expression:
case Sema::PCC_Condition:
return LangOpts.CPlusPlus;
case Sema::PCC_ObjCInterface:
case Sema::PCC_ObjCImplementation:
return false;
case Sema::PCC_ForInit:
return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99;
}
llvm_unreachable("Invalid ParserCompletionContext!");
}
static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
const Preprocessor &PP) {
PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Policy.AnonymousTagLocations = false;
Policy.SuppressStrongLifetime = true;
Policy.SuppressUnwrittenScope = true;
Policy.SuppressScope = true;
return Policy;
}
/// Retrieve a printing policy suitable for code completion.
static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
return getCompletionPrintingPolicy(S.Context, S.PP);
}
/// Retrieve the string representation of the given type as a string
/// that has the appropriate lifetime for code completion.
///
/// This routine provides a fast path where we provide constant strings for
/// common type names.
static const char *GetCompletionTypeString(QualType T, ASTContext &Context,
const PrintingPolicy &Policy,
CodeCompletionAllocator &Allocator) {
if (!T.getLocalQualifiers()) {
// Built-in type names are constant strings.
if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
return BT->getNameAsCString(Policy);
// Anonymous tag types are constant strings.
if (const TagType *TagT = dyn_cast<TagType>(T))
if (TagDecl *Tag = TagT->getDecl())
if (!Tag->hasNameForLinkage()) {
switch (Tag->getTagKind()) {
case TTK_Struct:
return "struct <anonymous>";
case TTK_Interface:
return "__interface <anonymous>";
case TTK_Class:
return "class <anonymous>";
case TTK_Union:
return "union <anonymous>";
case TTK_Enum:
return "enum <anonymous>";
}
}
}
// Slow path: format the type as a string.
std::string Result;
T.getAsStringInternal(Result, Policy);
return Allocator.CopyString(Result);
}
/// Add a completion for "this", if we're in a member function.
static void addThisCompletion(Sema &S, ResultBuilder &Results) {
QualType ThisTy = S.getCurrentThisType();
if (ThisTy.isNull())
return;
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Builder.AddResultTypeChunk(
GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator));
Builder.AddTypedTextChunk("this");
Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
ResultBuilder &Results,
const LangOptions &LangOpts) {
if (!LangOpts.CPlusPlus11)
return;
Builder.AddTypedTextChunk("static_assert");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_Comma);
Builder.AddPlaceholderChunk("message");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
static void printOverrideString(llvm::raw_ostream &OS,
CodeCompletionString *CCS) {
for (const auto &C : *CCS) {
if (C.Kind == CodeCompletionString::CK_Optional)
printOverrideString(OS, C.Optional);
else
OS << C.Text;
// Add a space after return type.
if (C.Kind == CodeCompletionString::CK_ResultType)
OS << ' ';
}
}
static void AddOverrideResults(ResultBuilder &Results,
const CodeCompletionContext &CCContext,
CodeCompletionBuilder &Builder) {
Sema &S = Results.getSema();
const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
// If not inside a class/struct/union return empty.
if (!CR)
return;
// First store overrides within current class.
// These are stored by name to make querying fast in the later step.
llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
for (auto *Method : CR->methods()) {
if (!Method->isVirtual() || !Method->getIdentifier())
continue;
Overrides[Method->getName()].push_back(Method);
}
for (const auto &Base : CR->bases()) {
const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
if (!BR)
continue;
for (auto *Method : BR->methods()) {
if (!Method->isVirtual() || !Method->getIdentifier())
continue;
const auto it = Overrides.find(Method->getName());
bool IsOverriden = false;
if (it != Overrides.end()) {
for (auto *MD : it->second) {
// If the method in current body is not an overload of this virtual
// function, then it overrides this one.
if (!S.IsOverload(MD, Method, false)) {
IsOverriden = true;
break;
}
}
}
if (!IsOverriden) {
// Generates a new CodeCompletionResult by taking this function and
// converting it into an override declaration with only one chunk in the
// final CodeCompletionString as a TypedTextChunk.
std::string OverrideSignature;
llvm::raw_string_ostream OS(OverrideSignature);
CodeCompletionResult CCR(Method, 0);
PrintingPolicy Policy =
getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
auto *CCS = CCR.createCodeCompletionStringForOverride(
S.getPreprocessor(), S.getASTContext(), Builder,
/*IncludeBriefComments=*/false, CCContext, Policy);
Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
}
}
}
}
/// Add language constructs that show up for "ordinary" names.
static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S,
Sema &SemaRef, ResultBuilder &Results) {
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
typedef CodeCompletionResult Result;
switch (CCC) {
case Sema::PCC_Namespace:
if (SemaRef.getLangOpts().CPlusPlus) {
if (Results.includeCodePatterns()) {
// namespace <identifier> { declarations }
Builder.AddTypedTextChunk("namespace");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("identifier");
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddPlaceholderChunk("declarations");
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
// namespace identifier = identifier ;
Builder.AddTypedTextChunk("namespace");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("name");
Builder.AddChunk(CodeCompletionString::CK_Equal);
Builder.AddPlaceholderChunk("namespace");
Results.AddResult(Result(Builder.TakeString()));
// Using directives
Builder.AddTypedTextChunk("using");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTextChunk("namespace");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("identifier");
Results.AddResult(Result(Builder.TakeString()));
// asm(string-literal)
Builder.AddTypedTextChunk("asm");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("string-literal");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
if (Results.includeCodePatterns()) {
// Explicit template instantiation
Builder.AddTypedTextChunk("template");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("declaration");
Results.AddResult(Result(Builder.TakeString()));
} else {
Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
}
}
if (SemaRef.getLangOpts().ObjC)
AddObjCTopLevelResults(Results, true);
AddTypedefResult(Results);
LLVM_FALLTHROUGH;
case Sema::PCC_Class:
if (SemaRef.getLangOpts().CPlusPlus) {
// Using declaration
Builder.AddTypedTextChunk("using");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("qualifier");
Builder.AddTextChunk("::");
Builder.AddPlaceholderChunk("name");
Results.AddResult(Result(Builder.TakeString()));
// using typename qualifier::name (only in a dependent context)
if (SemaRef.CurContext->isDependentContext()) {
Builder.AddTypedTextChunk("using");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTextChunk("typename");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("qualifier");
Builder.AddTextChunk("::");
Builder.AddPlaceholderChunk("name");
Results.AddResult(Result(Builder.TakeString()));
}
AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
if (CCC == Sema::PCC_Class) {
AddTypedefResult(Results);
bool IsNotInheritanceScope =
!(S->getFlags() & Scope::ClassInheritanceScope);
// public:
Builder.AddTypedTextChunk("public");
if (IsNotInheritanceScope && Results.includeCodePatterns())
Builder.AddChunk(CodeCompletionString::CK_Colon);
Results.AddResult(Result(Builder.TakeString()));
// protected:
Builder.AddTypedTextChunk("protected");
if (IsNotInheritanceScope && Results.includeCodePatterns())
Builder.AddChunk(CodeCompletionString::CK_Colon);
Results.AddResult(Result(Builder.TakeString()));
// private:
Builder.AddTypedTextChunk("private");
if (IsNotInheritanceScope && Results.includeCodePatterns())
Builder.AddChunk(CodeCompletionString::CK_Colon);
Results.AddResult(Result(Builder.TakeString()));
// FIXME: This adds override results only if we are at the first word of
// the declaration/definition. Also call this from other sides to have
// more use-cases.
AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
Builder);
}
}
LLVM_FALLTHROUGH;
case Sema::PCC_Template:
case Sema::PCC_MemberTemplate:
if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
// template < parameters >
Builder.AddTypedTextChunk("template");
Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
Builder.AddPlaceholderChunk("parameters");
Builder.AddChunk(CodeCompletionString::CK_RightAngle);
Results.AddResult(Result(Builder.TakeString()));
} else {
Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
}
AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
break;
case Sema::PCC_ObjCInterface:
AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
break;
case Sema::PCC_ObjCImplementation:
AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
break;
case Sema::PCC_ObjCInstanceVariableList:
AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
break;
case Sema::PCC_RecoveryInFunction:
case Sema::PCC_Statement: {
AddTypedefResult(Results);
if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
SemaRef.getLangOpts().CXXExceptions) {
Builder.AddTypedTextChunk("try");
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Builder.AddTextChunk("catch");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("declaration");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
if (SemaRef.getLangOpts().ObjC)
AddObjCStatementResults(Results, true);
if (Results.includeCodePatterns()) {
// if (condition) { statements }
Builder.AddTypedTextChunk("if");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
if (SemaRef.getLangOpts().CPlusPlus)
Builder.AddPlaceholderChunk("condition");
else
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
// switch (condition) { }
Builder.AddTypedTextChunk("switch");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
if (SemaRef.getLangOpts().CPlusPlus)
Builder.AddPlaceholderChunk("condition");
else
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
// Switch-specific statements.
if (SemaRef.getCurFunction() &&
!SemaRef.getCurFunction()->SwitchStack.empty()) {
// case expression:
Builder.AddTypedTextChunk("case");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_Colon);
Results.AddResult(Result(Builder.TakeString()));
// default:
Builder.AddTypedTextChunk("default");
Builder.AddChunk(CodeCompletionString::CK_Colon);
Results.AddResult(Result(Builder.TakeString()));
}
if (Results.includeCodePatterns()) {
/// while (condition) { statements }
Builder.AddTypedTextChunk("while");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
if (SemaRef.getLangOpts().CPlusPlus)
Builder.AddPlaceholderChunk("condition");
else
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
// do { statements } while ( expression );
Builder.AddTypedTextChunk("do");
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Builder.AddTextChunk("while");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
// for ( for-init-statement ; condition ; expression ) { statements }
Builder.AddTypedTextChunk("for");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Builder.AddPlaceholderChunk("init-statement");
else
Builder.AddPlaceholderChunk("init-expression");
Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Builder.AddPlaceholderChunk("condition");
Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Builder.AddPlaceholderChunk("inc-expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
if (S->getContinueParent()) {
// continue ;
Builder.AddTypedTextChunk("continue");
Results.AddResult(Result(Builder.TakeString()));
}
if (S->getBreakParent()) {
// break ;
Builder.AddTypedTextChunk("break");
Results.AddResult(Result(Builder.TakeString()));
}
// "return expression ;" or "return ;", depending on whether we
// know the function is void or not.
bool isVoid = false;
if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
isVoid = Function->getReturnType()->isVoidType();
else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
isVoid = Method->getReturnType()->isVoidType();
else if (SemaRef.getCurBlock() &&
!SemaRef.getCurBlock()->ReturnType.isNull())
isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Builder.AddTypedTextChunk("return");
if (!isVoid) {
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("expression");
}
Results.AddResult(Result(Builder.TakeString()));
// goto identifier ;
Builder.AddTypedTextChunk("goto");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("label");
Results.AddResult(Result(Builder.TakeString()));
// Using directives
Builder.AddTypedTextChunk("using");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTextChunk("namespace");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("identifier");
Results.AddResult(Result(Builder.TakeString()));
AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
}
LLVM_FALLTHROUGH;
// Fall through (for statement expressions).
case Sema::PCC_ForInit:
case Sema::PCC_Condition:
AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
// Fall through: conditions and statements can have expressions.
LLVM_FALLTHROUGH;
case Sema::PCC_ParenthesizedExpression:
if (SemaRef.getLangOpts().ObjCAutoRefCount &&
CCC == Sema::PCC_ParenthesizedExpression) {
// (__bridge <type>)<expression>
Builder.AddTypedTextChunk("__bridge");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddPlaceholderChunk("expression");
Results.AddResult(Result(Builder.TakeString()));
// (__bridge_transfer <Objective-C type>)<expression>
Builder.AddTypedTextChunk("__bridge_transfer");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("Objective-C type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddPlaceholderChunk("expression");
Results.AddResult(Result(Builder.TakeString()));
// (__bridge_retained <CF type>)<expression>
Builder.AddTypedTextChunk("__bridge_retained");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("CF type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddPlaceholderChunk("expression");
Results.AddResult(Result(Builder.TakeString()));
}
// Fall through
LLVM_FALLTHROUGH;
case Sema::PCC_Expression: {
if (SemaRef.getLangOpts().CPlusPlus) {
// 'this', if we're in a non-static member function.
addThisCompletion(SemaRef, Results);
// true
Builder.AddResultTypeChunk("bool");
Builder.AddTypedTextChunk("true");
Results.AddResult(Result(Builder.TakeString()));
// false
Builder.AddResultTypeChunk("bool");
Builder.AddTypedTextChunk("false");
Results.AddResult(Result(Builder.TakeString()));
if (SemaRef.getLangOpts().RTTI) {
// dynamic_cast < type-id > ( expression )
Builder.AddTypedTextChunk("dynamic_cast");
Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_RightAngle);
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
}
// static_cast < type-id > ( expression )
Builder.AddTypedTextChunk("static_cast");
Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_RightAngle);
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
// reinterpret_cast < type-id > ( expression )
Builder.AddTypedTextChunk("reinterpret_cast");
Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_RightAngle);
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
// const_cast < type-id > ( expression )
Builder.AddTypedTextChunk("const_cast");
Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_RightAngle);
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
if (SemaRef.getLangOpts().RTTI) {
// typeid ( expression-or-type )
Builder.AddResultTypeChunk("std::type_info");
Builder.AddTypedTextChunk("typeid");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression-or-type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
}
// new T ( ... )
Builder.AddTypedTextChunk("new");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expressions");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
// new T [ ] ( ... )
Builder.AddTypedTextChunk("new");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
Builder.AddPlaceholderChunk("size");
Builder.AddChunk(CodeCompletionString::CK_RightBracket);
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expressions");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
// delete expression
Builder.AddResultTypeChunk("void");
Builder.AddTypedTextChunk("delete");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("expression");
Results.AddResult(Result(Builder.TakeString()));
// delete [] expression
Builder.AddResultTypeChunk("void");
Builder.AddTypedTextChunk("delete");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
Builder.AddChunk(CodeCompletionString::CK_RightBracket);
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("expression");
Results.AddResult(Result(Builder.TakeString()));
if (SemaRef.getLangOpts().CXXExceptions) {
// throw expression
Builder.AddResultTypeChunk("void");
Builder.AddTypedTextChunk("throw");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("expression");
Results.AddResult(Result(Builder.TakeString()));
}
// FIXME: Rethrow?
if (SemaRef.getLangOpts().CPlusPlus11) {
// nullptr
Builder.AddResultTypeChunk("std::nullptr_t");
Builder.AddTypedTextChunk("nullptr");
Results.AddResult(Result(Builder.TakeString()));
// alignof
Builder.AddResultTypeChunk("size_t");
Builder.AddTypedTextChunk("alignof");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
// noexcept
Builder.AddResultTypeChunk("bool");
Builder.AddTypedTextChunk("noexcept");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
// sizeof... expression
Builder.AddResultTypeChunk("size_t");
Builder.AddTypedTextChunk("sizeof...");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("parameter-pack");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
}
}
if (SemaRef.getLangOpts().ObjC) {
// Add "super", if we're in an Objective-C class with a superclass.
if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
// The interface can be NULL.
if (ObjCInterfaceDecl *ID = Method->getClassInterface())
if (ID->getSuperClass()) {
std::string SuperType;
SuperType = ID->getSuperClass()->getNameAsString();
if (Method->isInstanceMethod())
SuperType += " *";
Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
Builder.AddTypedTextChunk("super");
Results.AddResult(Result(Builder.TakeString()));
}
}
AddObjCExpressionResults(Results, true);
}
if (SemaRef.getLangOpts().C11) {
// _Alignof
Builder.AddResultTypeChunk("size_t");
if (SemaRef.PP.isMacroDefined("alignof"))
Builder.AddTypedTextChunk("alignof");
else
Builder.AddTypedTextChunk("_Alignof");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
}
// sizeof expression
Builder.AddResultTypeChunk("size_t");
Builder.AddTypedTextChunk("sizeof");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression-or-type");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
break;
}
case Sema::PCC_Type:
case Sema::PCC_LocalDeclarationSpecifiers:
break;
}
if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Results.AddResult(Result("operator"));
}
/// If the given declaration has an associated type, add it as a result
/// type chunk.
static void AddResultTypeChunk(ASTContext &Context,
const PrintingPolicy &Policy,
const NamedDecl *ND, QualType BaseType,
CodeCompletionBuilder &Result) {
if (!ND)
return;
// Skip constructors and conversion functions, which have their return types
// built into their names.
if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
return;
// Determine the type of the declaration (if it has a type).
QualType T;
if (const FunctionDecl *Function = ND->getAsFunction())
T = Function->getReturnType();
else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
if (!BaseType.isNull())
T = Method->getSendResultType(BaseType);
else
T = Method->getReturnType();
} else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
T = clang::TypeName::getFullyQualifiedType(T, Context);
} else if (isa<UnresolvedUsingValueDecl>(ND)) {
/* Do nothing: ignore unresolved using declarations*/
} else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
if (!BaseType.isNull())
T = Ivar->getUsageType(BaseType);
else
T = Ivar->getType();
} else if (const auto *Value = dyn_cast<ValueDecl>(ND)) {
T = Value->getType();
} else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
if (!BaseType.isNull())
T = Property->getUsageType(BaseType);
else
T = Property->getType();
}
if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
return;
Result.AddResultTypeChunk(
GetCompletionTypeString(T, Context, Policy, Result.getAllocator()));
}
static void MaybeAddSentinel(Preprocessor &PP,
const NamedDecl *FunctionOrMethod,
CodeCompletionBuilder &Result) {
if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
if (Sentinel->getSentinel() == 0) {
if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))
Result.AddTextChunk(", nil");
else if (PP.isMacroDefined("NULL"))
Result.AddTextChunk(", NULL");
else
Result.AddTextChunk(", (void*)0");
}
}
static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
QualType &Type) {
std::string Result;
if (ObjCQuals & Decl::OBJC_TQ_In)
Result += "in ";
else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Result += "inout ";
else if (ObjCQuals & Decl::OBJC_TQ_Out)
Result += "out ";
if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Result += "bycopy ";
else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Result += "byref ";
if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Result += "oneway ";
if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
if (auto nullability = AttributedType::stripOuterNullability(Type)) {
switch (*nullability) {
case NullabilityKind::NonNull:
Result += "nonnull ";
break;
case NullabilityKind::Nullable:
Result += "nullable ";
break;
case NullabilityKind::Unspecified:
Result += "null_unspecified ";
break;
}
}
}
return Result;
}
/// Tries to find the most appropriate type location for an Objective-C
/// block placeholder.
///
/// This function ignores things like typedefs and qualifiers in order to
/// present the most relevant and accurate block placeholders in code completion
/// results.
static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
FunctionTypeLoc &Block,
FunctionProtoTypeLoc &BlockProto,
bool SuppressBlock = false) {
if (!TSInfo)
return;
TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
while (true) {
// Look through typedefs.
if (!SuppressBlock) {
if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
if (TypeSourceInfo *InnerTSInfo =
TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
continue;
}
}
// Look through qualified types
if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
TL = QualifiedTL.getUnqualifiedLoc();
continue;
}
if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
TL = AttrTL.getModifiedLoc();
continue;
}
}
// Try to get the function prototype behind the block pointer type,
// then we're done.
if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
TL = BlockPtr.getPointeeLoc().IgnoreParens();
Block = TL.getAs<FunctionTypeLoc>();
BlockProto = TL.getAs<FunctionProtoTypeLoc>();
}
break;
}
}
static std::string
formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
bool SuppressBlockName = false,
bool SuppressBlock = false,
Optional<ArrayRef<QualType>> ObjCSubsts = None);
static std::string
FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param,
bool SuppressName = false, bool SuppressBlock = false,
Optional<ArrayRef<QualType>> ObjCSubsts = None) {
bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
if (Param->getType()->isDependentType() ||
!Param->getType()->isBlockPointerType()) {
// The argument for a dependent or non-block parameter is a placeholder
// containing that parameter's type.
std::string Result;
if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Result = Param->getIdentifier()->getName();
QualType Type = Param->getType();
if (ObjCSubsts)
Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
ObjCSubstitutionContext::Parameter);
if (ObjCMethodParam) {
Result =
"(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
Result += Type.getAsString(Policy) + ")";
if (Param->getIdentifier() && !SuppressName)
Result += Param->getIdentifier()->getName();
} else {
Type.getAsStringInternal(Result, Policy);
}
return Result;
}
// The argument for a block pointer parameter is a block literal with
// the appropriate type.
FunctionTypeLoc Block;
FunctionProtoTypeLoc BlockProto;
findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
SuppressBlock);
// Try to retrieve the block type information from the property if this is a
// parameter in a setter.
if (!Block && ObjCMethodParam &&
cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
->findPropertyDecl(/*CheckOverrides=*/false))
findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
SuppressBlock);
}
if (!Block) {
// We were unable to find a FunctionProtoTypeLoc with parameter names
// for the block; just use the parameter type as a placeholder.
std::string Result;
if (!ObjCMethodParam && Param->getIdentifier())
Result = Param->getIdentifier()->getName();
QualType Type = Param->getType().getUnqualifiedType();
if (ObjCMethodParam) {
Result = Type.getAsString(Policy);
std::string Quals =
formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
if (!Quals.empty())
Result = "(" + Quals + " " + Result + ")";
if (Result.back() != ')')
Result += " ";
if (Param->getIdentifier())
Result += Param->getIdentifier()->getName();
} else {
Type.getAsStringInternal(Result, Policy);
}
return Result;
}
// We have the function prototype behind the block pointer type, as it was
// written in the source.
return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
/*SuppressBlockName=*/false, SuppressBlock,
ObjCSubsts);
}
/// Returns a placeholder string that corresponds to an Objective-C block
/// declaration.
///
/// \param BlockDecl A declaration with an Objective-C block type.
///
/// \param Block The most relevant type location for that block type.
///
/// \param SuppressBlockName Determines whether or not the name of the block
/// declaration is included in the resulting string.
static std::string
formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
bool SuppressBlockName, bool SuppressBlock,
Optional<ArrayRef<QualType>> ObjCSubsts) {
std::string Result;
QualType ResultType = Block.getTypePtr()->getReturnType();
if (ObjCSubsts)
ResultType =
ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
ObjCSubstitutionContext::Result);
if (!ResultType->isVoidType() || SuppressBlock)
ResultType.getAsStringInternal(Result, Policy);
// Format the parameter list.
std::string Params;
if (!BlockProto || Block.getNumParams() == 0) {
if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Params = "(...)";
else
Params = "(void)";
} else {
Params += "(";
for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
if (I)
Params += ", ";
Params += FormatFunctionParameter(Policy, Block.getParam(I),
/*SuppressName=*/false,
/*SuppressBlock=*/true, ObjCSubsts);
if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Params += ", ...";
}
Params += ")";
}
if (SuppressBlock) {
// Format as a parameter.
Result = Result + " (^";
if (!SuppressBlockName && BlockDecl->getIdentifier())
Result += BlockDecl->getIdentifier()->getName();
Result += ")";
Result += Params;
} else {
// Format as a block literal argument.
Result = '^' + Result;
Result += Params;
if (!SuppressBlockName && BlockDecl->getIdentifier())
Result += BlockDecl->getIdentifier()->getName();
}
return Result;
}
static std::string GetDefaultValueString(const ParmVarDecl *Param,
const SourceManager &SM,
const LangOptions &LangOpts) {
const SourceRange SrcRange = Param->getDefaultArgRange();
CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
bool Invalid = CharSrcRange.isInvalid();
if (Invalid)
return "";
StringRef srcText =
Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
if (Invalid)
return "";
if (srcText.empty() || srcText == "=") {
// Lexer can't determine the value.
// This happens if the code is incorrect (for example class is forward
// declared).
return "";
}
std::string DefValue(srcText.str());
// FIXME: remove this check if the Lexer::getSourceText value is fixed and
// this value always has (or always does not have) '=' in front of it
if (DefValue.at(0) != '=') {
// If we don't have '=' in front of value.
// Lexer returns built-in types values without '=' and user-defined types
// values with it.
return " = " + DefValue;
}
return " " + DefValue;
}
/// Add function parameter chunks to the given code completion string.
static void AddFunctionParameterChunks(Preprocessor &PP,
const PrintingPolicy &Policy,
const FunctionDecl *Function,
CodeCompletionBuilder &Result,
unsigned Start = 0,
bool InOptional = false) {
bool FirstParameter = true;
for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
const ParmVarDecl *Param = Function->getParamDecl(P);
if (Param->hasDefaultArg() && !InOptional) {
// When we see an optional default argument, put that argument and
// the remaining default arguments into a new, optional string.
CodeCompletionBuilder Opt(Result.getAllocator(),
Result.getCodeCompletionTUInfo());
if (!FirstParameter)
Opt.AddChunk(CodeCompletionString::CK_Comma);
AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Result.AddOptionalChunk(Opt.TakeString());
break;
}
if (FirstParameter)
FirstParameter = false;
else
Result.AddChunk(CodeCompletionString::CK_Comma);
InOptional = false;
// Format the placeholder string.
std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
if (Param->hasDefaultArg())
PlaceholderStr +=
GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
if (Function->isVariadic() && P == N - 1)
PlaceholderStr += ", ...";
// Add the placeholder string.
Result.AddPlaceholderChunk(
Result.getAllocator().CopyString(PlaceholderStr));
}
if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
if (Proto->isVariadic()) {
if (Proto->getNumParams() == 0)
Result.AddPlaceholderChunk("...");
MaybeAddSentinel(PP, Function, Result);
}
}
/// Add template parameter chunks to the given code completion string.
static void AddTemplateParameterChunks(
ASTContext &Context, const PrintingPolicy &Policy,
const TemplateDecl *Template, CodeCompletionBuilder &Result,
unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {
bool FirstParameter = true;
// Prefer to take the template parameter names from the first declaration of
// the template.
Template = cast<TemplateDecl>(Template->getCanonicalDecl());
TemplateParameterList *Params = Template->getTemplateParameters();
TemplateParameterList::iterator PEnd = Params->end();
if (MaxParameters)
PEnd = Params->begin() + MaxParameters;
for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;
++P) {
bool HasDefaultArg = false;
std::string PlaceholderStr;
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
if (TTP->wasDeclaredWithTypename())
PlaceholderStr = "typename";
else
PlaceholderStr = "class";
if (TTP->getIdentifier()) {
PlaceholderStr += ' ';
PlaceholderStr += TTP->getIdentifier()->getName();
}
HasDefaultArg = TTP->hasDefaultArgument();
} else if (NonTypeTemplateParmDecl *NTTP =
dyn_cast<NonTypeTemplateParmDecl>(*P)) {
if (NTTP->getIdentifier())
PlaceholderStr = NTTP->getIdentifier()->getName();
NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
HasDefaultArg = NTTP->hasDefaultArgument();
} else {
assert(isa<TemplateTemplateParmDecl>(*P));
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
// Since putting the template argument list into the placeholder would
// be very, very long, we just use an abbreviation.
PlaceholderStr = "template<...> class";
if (TTP->getIdentifier()) {
PlaceholderStr += ' ';
PlaceholderStr += TTP->getIdentifier()->getName();
}
HasDefaultArg = TTP->hasDefaultArgument();
}
if (HasDefaultArg && !InDefaultArg) {
// When we see an optional default argument, put that argument and
// the remaining default arguments into a new, optional string.
CodeCompletionBuilder Opt(Result.getAllocator(),
Result.getCodeCompletionTUInfo());
if (!FirstParameter)
Opt.AddChunk(CodeCompletionString::CK_Comma);
AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
P - Params->begin(), true);
Result.AddOptionalChunk(Opt.TakeString());
break;
}
InDefaultArg = false;
if (FirstParameter)
FirstParameter = false;
else
Result.AddChunk(CodeCompletionString::CK_Comma);
// Add the placeholder string.
Result.AddPlaceholderChunk(
Result.getAllocator().CopyString(PlaceholderStr));
}
}
/// Add a qualifier to the given code-completion string, if the
/// provided nested-name-specifier is non-NULL.
static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
NestedNameSpecifier *Qualifier,
bool QualifierIsInformative,
ASTContext &Context,
const PrintingPolicy &Policy) {
if (!Qualifier)
return;
std::string PrintedNNS;
{
llvm::raw_string_ostream OS(PrintedNNS);
Qualifier->print(OS, Policy);
}
if (QualifierIsInformative)
Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
else
Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
}
static void
AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
const FunctionDecl *Function) {
const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
if (!Proto || !Proto->getTypeQuals())
return;
// FIXME: Add ref-qualifier!
// Handle single qualifiers without copying
if (Proto->getTypeQuals().hasOnlyConst()) {
Result.AddInformativeChunk(" const");
return;
}
if (Proto->getTypeQuals().hasOnlyVolatile()) {
Result.AddInformativeChunk(" volatile");
return;
}
if (Proto->getTypeQuals().hasOnlyRestrict()) {
Result.AddInformativeChunk(" restrict");
return;
}
// Handle multiple qualifiers.
std::string QualsStr;
if (Proto->isConst())
QualsStr += " const";
if (Proto->isVolatile())
QualsStr += " volatile";
if (Proto->isRestrict())
QualsStr += " restrict";
Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
}
/// Add the name of the given declaration
static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
const NamedDecl *ND,
CodeCompletionBuilder &Result) {
DeclarationName Name = ND->getDeclName();
if (!Name)
return;
switch (Name.getNameKind()) {
case DeclarationName::CXXOperatorName: {
const char *OperatorName = nullptr;
switch (Name.getCXXOverloadedOperator()) {
case OO_None:
case OO_Conditional:
case NUM_OVERLOADED_OPERATORS:
OperatorName = "operator";
break;
#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
case OO_##Name: \
OperatorName = "operator" Spelling; \
break;
#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
#include "clang/Basic/OperatorKinds.def"
case OO_New:
OperatorName = "operator new";
break;
case OO_Delete:
OperatorName = "operator delete";
break;
case OO_Array_New:
OperatorName = "operator new[]";
break;
case OO_Array_Delete:
OperatorName = "operator delete[]";
break;
case OO_Call:
OperatorName = "operator()";
break;
case OO_Subscript:
OperatorName = "operator[]";
break;
}
Result.AddTypedTextChunk(OperatorName);
break;
}
case DeclarationName::Identifier:
case DeclarationName::CXXConversionFunctionName:
case DeclarationName::CXXDestructorName:
case DeclarationName::CXXLiteralOperatorName:
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(ND->getNameAsString()));
break;
case DeclarationName::CXXDeductionGuideName:
case DeclarationName::CXXUsingDirective:
case DeclarationName::ObjCZeroArgSelector:
case DeclarationName::ObjCOneArgSelector:
case DeclarationName::ObjCMultiArgSelector:
break;
case DeclarationName::CXXConstructorName: {
CXXRecordDecl *Record = nullptr;
QualType Ty = Name.getCXXNameType();
if (const auto *RecordTy = Ty->getAs<RecordType>())
Record = cast<CXXRecordDecl>(RecordTy->getDecl());
else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
Record = InjectedTy->getDecl();
else {
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(ND->getNameAsString()));
break;
}
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(Record->getNameAsString()));
if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Result.AddChunk(CodeCompletionString::CK_LeftAngle);
AddTemplateParameterChunks(Context, Policy, Template, Result);
Result.AddChunk(CodeCompletionString::CK_RightAngle);
}
break;
}
}
}
CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
Sema &S, const CodeCompletionContext &CCContext,
CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
bool IncludeBriefComments) {
return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
CCTUInfo, IncludeBriefComments);
}
CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
Preprocessor &PP, CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo) {
assert(Kind == RK_Macro);
CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
const MacroInfo *MI = PP.getMacroInfo(Macro);
Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
if (!MI || !MI->isFunctionLike())
return Result.TakeString();
// Format a function-like macro with placeholders for the arguments.
Result.AddChunk(CodeCompletionString::CK_LeftParen);
MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
// C99 variadic macros add __VA_ARGS__ at the end. Skip it.
if (MI->isC99Varargs()) {
--AEnd;
if (A == AEnd) {
Result.AddPlaceholderChunk("...");
}
}
for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
if (A != MI->param_begin())
Result.AddChunk(CodeCompletionString::CK_Comma);
if (MI->isVariadic() && (A + 1) == AEnd) {
SmallString<32> Arg = (*A)->getName();
if (MI->isC99Varargs())
Arg += ", ...";
else
Arg += "...";
Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
break;
}
// Non-variadic macros are simple.
Result.AddPlaceholderChunk(
Result.getAllocator().CopyString((*A)->getName()));
}
Result.AddChunk(CodeCompletionString::CK_RightParen);
return Result.TakeString();
}
/// If possible, create a new code completion string for the given
/// result.
///
/// \returns Either a new, heap-allocated code completion string describing
/// how to use this result, or NULL to indicate that the string or name of the
/// result is all that is needed.
CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,
CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
bool IncludeBriefComments) {
if (Kind == RK_Macro)
return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
if (Kind == RK_Pattern) {
Pattern->Priority = Priority;
Pattern->Availability = Availability;
if (Declaration) {
Result.addParentContext(Declaration->getDeclContext());
Pattern->ParentName = Result.getParentName();
if (const RawComment *RC =
getPatternCompletionComment(Ctx, Declaration)) {
Result.addBriefComment(RC->getBriefText(Ctx));
Pattern->BriefComment = Result.getBriefComment();
}
}
return Pattern;
}
if (Kind == RK_Keyword) {
Result.AddTypedTextChunk(Keyword);
return Result.TakeString();
}
assert(Kind == RK_Declaration && "Missed a result kind?");
return createCodeCompletionStringForDecl(
PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
}
CodeCompletionString *
CodeCompletionResult::createCodeCompletionStringForOverride(
Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
bool IncludeBriefComments, const CodeCompletionContext &CCContext,
PrintingPolicy &Policy) {
std::string OverrideSignature;
llvm::raw_string_ostream OS(OverrideSignature);
auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
/*IncludeBriefComments=*/false,
CCContext, Policy);
printOverrideString(OS, CCS);
OS << " override";
Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str()));
return Result.TakeString();
}
CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
bool IncludeBriefComments, const CodeCompletionContext &CCContext,
PrintingPolicy &Policy) {
const NamedDecl *ND = Declaration;
Result.addParentContext(ND->getDeclContext());
if (IncludeBriefComments) {
// Add documentation comment, if it exists.
if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Result.addBriefComment(RC->getBriefText(Ctx));
}
}
if (StartsNestedNameSpecifier) {
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(ND->getNameAsString()));
Result.AddTextChunk("::");
return Result.TakeString();
}
for (const auto *I : ND->specific_attrs<AnnotateAttr>())
Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
AddTypedNameChunk(Ctx, Policy, ND, Result);
Result.AddChunk(CodeCompletionString::CK_LeftParen);
AddFunctionParameterChunks(PP, Policy, Function, Result);
Result.AddChunk(CodeCompletionString::CK_RightParen);
AddFunctionTypeQualsToCompletionString(Result, Function);
return Result.TakeString();
}
if (const FunctionTemplateDecl *FunTmpl =
dyn_cast<FunctionTemplateDecl>(ND)) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
FunctionDecl *Function = FunTmpl->getTemplatedDecl();
AddTypedNameChunk(Ctx, Policy, Function, Result);
// Figure out which template parameters are deduced (or have default
// arguments).
llvm::SmallBitVector Deduced;
Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
unsigned LastDeducibleArgument;
for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
--LastDeducibleArgument) {
if (!Deduced[LastDeducibleArgument - 1]) {
// C++0x: Figure out if the template argument has a default. If so,
// the user doesn't need to type this argument.
// FIXME: We need to abstract template parameters better!
bool HasDefaultArg = false;
NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
LastDeducibleArgument - 1);
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
HasDefaultArg = TTP->hasDefaultArgument();
else if (NonTypeTemplateParmDecl *NTTP =
dyn_cast<NonTypeTemplateParmDecl>(Param))
HasDefaultArg = NTTP->hasDefaultArgument();
else {
assert(isa<TemplateTemplateParmDecl>(Param));
HasDefaultArg =
cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
}
if (!HasDefaultArg)
break;
}
}
if (LastDeducibleArgument) {
// Some of the function template arguments cannot be deduced from a
// function call, so we introduce an explicit template argument list
// containing all of the arguments up to the first deducible argument.
Result.AddChunk(CodeCompletionString::CK_LeftAngle);
AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
LastDeducibleArgument);
Result.AddChunk(CodeCompletionString::CK_RightAngle);
}
// Add the function parameters
Result.AddChunk(CodeCompletionString::CK_LeftParen);
AddFunctionParameterChunks(PP, Policy, Function, Result);
Result.AddChunk(CodeCompletionString::CK_RightParen);
AddFunctionTypeQualsToCompletionString(Result, Function);
return Result.TakeString();
}
if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(Template->getNameAsString()));
Result.AddChunk(CodeCompletionString::CK_LeftAngle);
AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Result.AddChunk(CodeCompletionString::CK_RightAngle);
return Result.TakeString();
}
if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Selector Sel = Method->getSelector();
if (Sel.isUnarySelector()) {
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
return Result.TakeString();
}
std::string SelName = Sel.getNameForSlot(0).str();
SelName += ':';
if (StartParameter == 0)
Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
else {
Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
// If there is only one parameter, and we're past it, add an empty
// typed-text chunk since there is nothing to type.
if (Method->param_size() == 1)
Result.AddTypedTextChunk("");
}
unsigned Idx = 0;
for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
PEnd = Method->param_end();
P != PEnd; (void)++P, ++Idx) {
if (Idx > 0) {
std::string Keyword;
if (Idx > StartParameter)
Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Keyword += II->getName();
Keyword += ":";
if (Idx < StartParameter || AllParametersAreInformative)
Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
else
Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
}
// If we're before the starting parameter, skip the placeholder.
if (Idx < StartParameter)
continue;
std::string Arg;
QualType ParamType = (*P)->getType();
Optional<ArrayRef<QualType>> ObjCSubsts;
if (!CCContext.getBaseType().isNull())
ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
if (ParamType->isBlockPointerType() && !DeclaringEntity)
Arg = FormatFunctionParameter(Policy, *P, true,
/*SuppressBlock=*/false, ObjCSubsts);
else {
if (ObjCSubsts)
ParamType = ParamType.substObjCTypeArgs(
Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);
Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
ParamType);
Arg += ParamType.getAsString(Policy) + ")";
if (IdentifierInfo *II = (*P)->getIdentifier())
if (DeclaringEntity || AllParametersAreInformative)
Arg += II->getName();
}
if (Method->isVariadic() && (P + 1) == PEnd)
Arg += ", ...";
if (DeclaringEntity)
Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
else if (AllParametersAreInformative)
Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
else
Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
}
if (Method->isVariadic()) {
if (Method->param_size() == 0) {
if (DeclaringEntity)
Result.AddTextChunk(", ...");
else if (AllParametersAreInformative)
Result.AddInformativeChunk(", ...");
else
Result.AddPlaceholderChunk(", ...");
}
MaybeAddSentinel(PP, Method, Result);
}
return Result.TakeString();
}
if (Qualifier)
AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Ctx, Policy);
Result.AddTypedTextChunk(
Result.getAllocator().CopyString(ND->getNameAsString()));
return Result.TakeString();
}
const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
const NamedDecl *ND) {
if (!ND)
return nullptr;
if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
return RC;
// Try to find comment from a property for ObjC methods.
const auto *M = dyn_cast<ObjCMethodDecl>(ND);
if (!M)
return nullptr;
const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
if (!PDecl)
return nullptr;
return Ctx.getRawCommentForAnyRedecl(PDecl);
}
const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
const NamedDecl *ND) {
const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
if (!M || !M->isPropertyAccessor())
return nullptr;
// Provide code completion comment for self.GetterName where
// GetterName is the getter method for a property with name
// different from the property name (declared via a property
// getter attribute.
const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
if (!PDecl)
return nullptr;
if (PDecl->getGetterName() == M->getSelector() &&
PDecl->getIdentifier() != M->getIdentifier()) {
if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
return RC;
if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
return RC;
}
return nullptr;
}
const RawComment *clang::getParameterComment(
const ASTContext &Ctx,
const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {
auto FDecl = Result.getFunction();
if (!FDecl)
return nullptr;
if (ArgIndex < FDecl->getNumParams())
return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
return nullptr;
}
/// Add function overload parameter chunks to the given code completion
/// string.
static void AddOverloadParameterChunks(ASTContext &Context,
const PrintingPolicy &Policy,
const FunctionDecl *Function,
const FunctionProtoType *Prototype,
CodeCompletionBuilder &Result,
unsigned CurrentArg, unsigned Start = 0,
bool InOptional = false) {
bool FirstParameter = true;
unsigned NumParams =
Function ? Function->getNumParams() : Prototype->getNumParams();
for (unsigned P = Start; P != NumParams; ++P) {
if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
// When we see an optional default argument, put that argument and
// the remaining default arguments into a new, optional string.
CodeCompletionBuilder Opt(Result.getAllocator(),
Result.getCodeCompletionTUInfo());
if (!FirstParameter)
Opt.AddChunk(CodeCompletionString::CK_Comma);
// Optional sections are nested.
AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
CurrentArg, P, /*InOptional=*/true);
Result.AddOptionalChunk(Opt.TakeString());
return;
}
if (FirstParameter)
FirstParameter = false;
else
Result.AddChunk(CodeCompletionString::CK_Comma);
InOptional = false;
// Format the placeholder string.
std::string Placeholder;
if (Function) {
const ParmVarDecl *Param = Function->getParamDecl(P);
Placeholder = FormatFunctionParameter(Policy, Param);
if (Param->hasDefaultArg())
Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
Context.getLangOpts());
} else {
Placeholder = Prototype->getParamType(P).getAsString(Policy);
}
if (P == CurrentArg)
Result.AddCurrentParameterChunk(
Result.getAllocator().CopyString(Placeholder));
else
Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
}
if (Prototype && Prototype->isVariadic()) {
CodeCompletionBuilder Opt(Result.getAllocator(),
Result.getCodeCompletionTUInfo());
if (!FirstParameter)
Opt.AddChunk(CodeCompletionString::CK_Comma);
if (CurrentArg < NumParams)
Opt.AddPlaceholderChunk("...");
else
Opt.AddCurrentParameterChunk("...");
Result.AddOptionalChunk(Opt.TakeString());
}
}
CodeCompletionString *
CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
// FIXME: Set priority, availability appropriately.
CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,
CXAvailability_Available);
FunctionDecl *FDecl = getFunction();
const FunctionProtoType *Proto =
dyn_cast<FunctionProtoType>(getFunctionType());
if (!FDecl && !Proto) {
// Function without a prototype. Just give the return type and a
// highlighted ellipsis.
const FunctionType *FT = getFunctionType();
Result.AddResultTypeChunk(Result.getAllocator().CopyString(
FT->getReturnType().getAsString(Policy)));
Result.AddChunk(CodeCompletionString::CK_LeftParen);
Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Result.AddChunk(CodeCompletionString::CK_RightParen);
return Result.TakeString();
}
if (FDecl) {
if (IncludeBriefComments) {
if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Result.addBriefComment(RC->getBriefText(S.getASTContext()));
}
AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Result.AddTextChunk(
Result.getAllocator().CopyString(FDecl->getNameAsString()));
} else {
Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Proto->getReturnType().getAsString(Policy)));
}
Result.AddChunk(CodeCompletionString::CK_LeftParen);
AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
CurrentArg);
Result.AddChunk(CodeCompletionString::CK_RightParen);
return Result.TakeString();
}
unsigned clang::getMacroUsagePriority(StringRef MacroName,
const LangOptions &LangOpts,
bool PreferredTypeIsPointer) {
unsigned Priority = CCP_Macro;
// Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
if (MacroName.equals("nil") || MacroName.equals("NULL") ||
MacroName.equals("Nil")) {
Priority = CCP_Constant;
if (PreferredTypeIsPointer)
Priority = Priority / CCF_SimilarTypeMatch;
}
// Treat "YES", "NO", "true", and "false" as constants.
else if (MacroName.equals("YES") || MacroName.equals("NO") ||
MacroName.equals("true") || MacroName.equals("false"))
Priority = CCP_Constant;
// Treat "bool" as a type.
else if (MacroName.equals("bool"))
Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
return Priority;
}
CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
if (!D)
return CXCursor_UnexposedDecl;
switch (D->getKind()) {
case Decl::Enum:
return CXCursor_EnumDecl;
case Decl::EnumConstant:
return CXCursor_EnumConstantDecl;
case Decl::Field:
return CXCursor_FieldDecl;
case Decl::Function:
return CXCursor_FunctionDecl;
case Decl::ObjCCategory:
return CXCursor_ObjCCategoryDecl;
case Decl::ObjCCategoryImpl:
return CXCursor_ObjCCategoryImplDecl;
case Decl::ObjCImplementation:
return CXCursor_ObjCImplementationDecl;
case Decl::ObjCInterface:
return CXCursor_ObjCInterfaceDecl;
case Decl::ObjCIvar:
return CXCursor_ObjCIvarDecl;
case Decl::ObjCMethod:
return cast<ObjCMethodDecl>(D)->isInstanceMethod()
? CXCursor_ObjCInstanceMethodDecl
: CXCursor_ObjCClassMethodDecl;
case Decl::CXXMethod:
return CXCursor_CXXMethod;
case Decl::CXXConstructor:
return CXCursor_Constructor;
case Decl::CXXDestructor:
return CXCursor_Destructor;
case Decl::CXXConversion:
return CXCursor_ConversionFunction;
case Decl::ObjCProperty:
return CXCursor_ObjCPropertyDecl;
case Decl::ObjCProtocol:
return CXCursor_ObjCProtocolDecl;
case Decl::ParmVar:
return CXCursor_ParmDecl;
case Decl::Typedef:
return CXCursor_TypedefDecl;
case Decl::TypeAlias:
return CXCursor_TypeAliasDecl;
case Decl::TypeAliasTemplate:
return CXCursor_TypeAliasTemplateDecl;
case Decl::Var:
return CXCursor_VarDecl;
case Decl::Namespace:
return CXCursor_Namespace;
case Decl::NamespaceAlias:
return CXCursor_NamespaceAlias;
case Decl::TemplateTypeParm:
return CXCursor_TemplateTypeParameter;
case Decl::NonTypeTemplateParm:
return CXCursor_NonTypeTemplateParameter;
case Decl::TemplateTemplateParm:
return CXCursor_TemplateTemplateParameter;
case Decl::FunctionTemplate:
return CXCursor_FunctionTemplate;
case Decl::ClassTemplate:
return CXCursor_ClassTemplate;
case Decl::AccessSpec:
return CXCursor_CXXAccessSpecifier;
case Decl::ClassTemplatePartialSpecialization:
return CXCursor_ClassTemplatePartialSpecialization;
case Decl::UsingDirective:
return CXCursor_UsingDirective;
case Decl::StaticAssert:
return CXCursor_StaticAssert;
case Decl::Friend:
return CXCursor_FriendDecl;
case Decl::TranslationUnit:
return CXCursor_TranslationUnit;
case Decl::Using:
case Decl::UnresolvedUsingValue:
case Decl::UnresolvedUsingTypename:
return CXCursor_UsingDeclaration;
case Decl::ObjCPropertyImpl:
switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
case ObjCPropertyImplDecl::Dynamic:
return CXCursor_ObjCDynamicDecl;
case ObjCPropertyImplDecl::Synthesize:
return CXCursor_ObjCSynthesizeDecl;
}
llvm_unreachable("Unexpected Kind!");
case Decl::Import:
return CXCursor_ModuleImportDecl;
case Decl::ObjCTypeParam:
return CXCursor_TemplateTypeParameter;
default:
if (const auto *TD = dyn_cast<TagDecl>(D)) {
switch (TD->getTagKind()) {
case TTK_Interface: // fall through
case TTK_Struct:
return CXCursor_StructDecl;
case TTK_Class:
return CXCursor_ClassDecl;
case TTK_Union:
return CXCursor_UnionDecl;
case TTK_Enum:
return CXCursor_EnumDecl;
}
}
}
return CXCursor_UnexposedDecl;
}
static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
bool LoadExternal, bool IncludeUndefined,
bool TargetTypeIsPointer = false) {
typedef CodeCompletionResult Result;
Results.EnterNewScope();
for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
MEnd = PP.macro_end(LoadExternal);
M != MEnd; ++M) {
auto MD = PP.getMacroDefinition(M->first);
if (IncludeUndefined || MD) {
MacroInfo *MI = MD.getMacroInfo();
if (MI && MI->isUsedForHeaderGuard())
continue;
Results.AddResult(
Result(M->first, MI,
getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
TargetTypeIsPointer)));
}
}
Results.ExitScope();
}
static void AddPrettyFunctionResults(const LangOptions &LangOpts,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
Results.EnterNewScope();
Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
Results.AddResult(Result("__FUNCTION__", CCP_Constant));
if (LangOpts.C99 || LangOpts.CPlusPlus11)
Results.AddResult(Result("__func__", CCP_Constant));
Results.ExitScope();
}
static void HandleCodeCompleteResults(Sema *S,
CodeCompleteConsumer *CodeCompleter,
CodeCompletionContext Context,
CodeCompletionResult *Results,
unsigned NumResults) {
if (CodeCompleter)
CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
}
static CodeCompletionContext
mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) {
switch (PCC) {
case Sema::PCC_Namespace:
return CodeCompletionContext::CCC_TopLevel;
case Sema::PCC_Class:
return CodeCompletionContext::CCC_ClassStructUnion;
case Sema::PCC_ObjCInterface:
return CodeCompletionContext::CCC_ObjCInterface;
case Sema::PCC_ObjCImplementation:
return CodeCompletionContext::CCC_ObjCImplementation;
case Sema::PCC_ObjCInstanceVariableList:
return CodeCompletionContext::CCC_ObjCIvarList;
case Sema::PCC_Template:
case Sema::PCC_MemberTemplate:
if (S.CurContext->isFileContext())
return CodeCompletionContext::CCC_TopLevel;
if (S.CurContext->isRecord())
return CodeCompletionContext::CCC_ClassStructUnion;
return CodeCompletionContext::CCC_Other;
case Sema::PCC_RecoveryInFunction:
return CodeCompletionContext::CCC_Recovery;
case Sema::PCC_ForInit:
if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
S.getLangOpts().ObjC)
return CodeCompletionContext::CCC_ParenthesizedExpression;
else
return CodeCompletionContext::CCC_Expression;
case Sema::PCC_Expression:
return CodeCompletionContext::CCC_Expression;
case Sema::PCC_Condition:
return CodeCompletionContext(CodeCompletionContext::CCC_Expression,
S.getASTContext().BoolTy);
case Sema::PCC_Statement:
return CodeCompletionContext::CCC_Statement;
case Sema::PCC_Type:
return CodeCompletionContext::CCC_Type;
case Sema::PCC_ParenthesizedExpression:
return CodeCompletionContext::CCC_ParenthesizedExpression;
case Sema::PCC_LocalDeclarationSpecifiers:
return CodeCompletionContext::CCC_Type;
}
llvm_unreachable("Invalid ParserCompletionContext!");
}
/// If we're in a C++ virtual member function, add completion results
/// that invoke the functions we override, since it's common to invoke the
/// overridden function as well as adding new functionality.
///
/// \param S The semantic analysis object for which we are generating results.
///
/// \param InContext This context in which the nested-name-specifier preceding
/// the code-completion point
static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
ResultBuilder &Results) {
// Look through blocks.
DeclContext *CurContext = S.CurContext;
while (isa<BlockDecl>(CurContext))
CurContext = CurContext->getParent();
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
if (!Method || !Method->isVirtual())
return;
// We need to have names for all of the parameters, if we're going to
// generate a forwarding call.
for (auto P : Method->parameters())
if (!P->getDeclName())
return;
PrintingPolicy Policy = getCompletionPrintingPolicy(S);
for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
continue;
// If we need a nested-name-specifier, add one now.
if (!InContext) {
NestedNameSpecifier *NNS = getRequiredQualification(
S.Context, CurContext, Overridden->getDeclContext());
if (NNS) {
std::string Str;
llvm::raw_string_ostream OS(Str);
NNS->print(OS, Policy);
Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
}
} else if (!InContext->Equals(Overridden->getDeclContext()))
continue;
Builder.AddTypedTextChunk(
Results.getAllocator().CopyString(Overridden->getNameAsString()));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
bool FirstParam = true;
for (auto P : Method->parameters()) {
if (FirstParam)
FirstParam = false;
else
Builder.AddChunk(CodeCompletionString::CK_Comma);
Builder.AddPlaceholderChunk(
Results.getAllocator().CopyString(P->getIdentifier()->getName()));
}
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(CodeCompletionResult(
Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,
CXAvailability_Available, Overridden));
Results.Ignore(Overridden);
}
}
void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
ModuleIdPath Path) {
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
typedef CodeCompletionResult Result;
if (Path.empty()) {
// Enumerate all top-level modules.
SmallVector<Module *, 8> Modules;
PP.getHeaderSearchInfo().collectAllModules(Modules);
for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString(Modules[I]->Name));
Results.AddResult(Result(
Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
Modules[I]->isAvailable() ? CXAvailability_Available
: CXAvailability_NotAvailable));
}
} else if (getLangOpts().Modules) {
// Load the named module.
Module *Mod =
PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
/*IsInclusionDirective=*/false);
// Enumerate submodules.
if (Mod) {
for (Module::submodule_iterator Sub = Mod->submodule_begin(),
SubEnd = Mod->submodule_end();
Sub != SubEnd; ++Sub) {
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString((*Sub)->Name));
Results.AddResult(Result(
Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
(*Sub)->isAvailable() ? CXAvailability_Available
: CXAvailability_NotAvailable));
}
}
}
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteOrdinaryName(Scope *S,
ParserCompletionContext CompletionContext) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
mapCodeCompletionContext(*this, CompletionContext));
Results.EnterNewScope();
// Determine how to filter results, e.g., so that the names of
// values (functions, enumerators, function templates, etc.) are
// only allowed where we can have an expression.
switch (CompletionContext) {
case PCC_Namespace:
case PCC_Class:
case PCC_ObjCInterface:
case PCC_ObjCImplementation:
case PCC_ObjCInstanceVariableList:
case PCC_Template:
case PCC_MemberTemplate:
case PCC_Type:
case PCC_LocalDeclarationSpecifiers:
Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
break;
case PCC_Statement:
case PCC_ParenthesizedExpression:
case PCC_Expression:
case PCC_ForInit:
case PCC_Condition:
if (WantTypesInContext(CompletionContext, getLangOpts()))
Results.setFilter(&ResultBuilder::IsOrdinaryName);
else
Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
if (getLangOpts().CPlusPlus)
MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
break;
case PCC_RecoveryInFunction:
// Unfiltered
break;
}
// If we are in a C++ non-static member function, check the qualifiers on
// the member function to filter/prioritize the results list.
auto ThisType = getCurrentThisType();
if (!ThisType.isNull())
Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers());
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
CodeCompleter->includeGlobals(),
CodeCompleter->loadExternal());
AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Results.ExitScope();
switch (CompletionContext) {
case PCC_ParenthesizedExpression:
case PCC_Expression:
case PCC_Statement:
case PCC_RecoveryInFunction:
if (S->getFnParent())
AddPrettyFunctionResults(getLangOpts(), Results);
break;
case PCC_Namespace:
case PCC_Class:
case PCC_ObjCInterface:
case PCC_ObjCImplementation:
case PCC_ObjCInstanceVariableList:
case PCC_Template:
case PCC_MemberTemplate:
case PCC_ForInit:
case PCC_Condition:
case PCC_Type:
case PCC_LocalDeclarationSpecifiers:
break;
}
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
ParsedType Receiver,
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression, bool IsSuper,
ResultBuilder &Results);
void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
bool AllowNonIdentifiers,
bool AllowNestedNameSpecifiers) {
typedef CodeCompletionResult Result;
ResultBuilder Results(
*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
AllowNestedNameSpecifiers
// FIXME: Try to separate codepath leading here to deduce whether we
// need an existing symbol or a new one.
? CodeCompletionContext::CCC_SymbolOrNewName
: CodeCompletionContext::CCC_NewName);
Results.EnterNewScope();
// Type qualifiers can come after names.
Results.AddResult(Result("const"));
Results.AddResult(Result("volatile"));
if (getLangOpts().C99)
Results.AddResult(Result("restrict"));
if (getLangOpts().CPlusPlus) {
if (getLangOpts().CPlusPlus11 &&
(DS.getTypeSpecType() == DeclSpec::TST_class ||
DS.getTypeSpecType() == DeclSpec::TST_struct))
Results.AddResult("final");
if (AllowNonIdentifiers) {
Results.AddResult(Result("operator"));
}
// Add nested-name-specifiers.
if (AllowNestedNameSpecifiers) {
Results.allowNestedNameSpecifiers();
Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
CodeCompleter->includeGlobals(),
CodeCompleter->loadExternal());
Results.setFilter(nullptr);
}
}
Results.ExitScope();
// If we're in a context where we might have an expression (rather than a
// declaration), and what we've seen so far is an Objective-C type that could
// be a receiver of a class message, this may be a class message send with
// the initial opening bracket '[' missing. Add appropriate completions.
if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
DS.getTypeSpecType() == DeclSpec::TST_typename &&
DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
!DS.isTypeAltiVecVector() && S &&
(S->getFlags() & Scope::DeclScope) != 0 &&
(S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==
0) {
ParsedType T = DS.getRepAsType();
if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
AddClassMessageCompletions(*this, S, T, None, false, false, Results);
}
// Note that we intentionally suppress macro results here, since we do not
// encourage using macros to produce the names of entities.
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
struct Sema::CodeCompleteExpressionData {
CodeCompleteExpressionData(QualType PreferredType = QualType())
: PreferredType(PreferredType), IntegralConstantExpression(false),
ObjCCollection(false) {}
QualType PreferredType;
bool IntegralConstantExpression;
bool ObjCCollection;
SmallVector<Decl *, 4> IgnoreDecls;
};
/// Perform code-completion in an expression context when we know what
/// type we're looking for.
void Sema::CodeCompleteExpression(Scope *S,
const CodeCompleteExpressionData &Data) {
ResultBuilder Results(
*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext(CodeCompletionContext::CCC_Expression,
Data.PreferredType));
if (Data.ObjCCollection)
Results.setFilter(&ResultBuilder::IsObjCCollection);
else if (Data.IntegralConstantExpression)
Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Results.setFilter(&ResultBuilder::IsOrdinaryName);
else
Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
if (!Data.PreferredType.isNull())
Results.setPreferredType(Data.PreferredType.getNonReferenceType());
// Ignore any declarations that we were told that we don't care about.
for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
Results.Ignore(Data.IgnoreDecls[I]);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
CodeCompleter->includeGlobals(),
CodeCompleter->loadExternal());
Results.EnterNewScope();
AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Results.ExitScope();
bool PreferredTypeIsPointer = false;
if (!Data.PreferredType.isNull())
PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() ||
Data.PreferredType->isMemberPointerType() ||
Data.PreferredType->isBlockPointerType();
if (S->getFnParent() && !Data.ObjCCollection &&
!Data.IntegralConstantExpression)
AddPrettyFunctionResults(getLangOpts(), Results);
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
PreferredTypeIsPointer);
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType) {
return CodeCompleteExpression(S, CodeCompleteExpressionData(PreferredType));
}
void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
if (E.isInvalid())
CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
else if (getLangOpts().ObjC)
CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
}
/// The set of properties that have already been added, referenced by
/// property name.
typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet;
/// Retrieve the container definition, if any?
static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
if (Interface->hasDefinition())
return Interface->getDefinition();
return Interface;
}
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
if (Protocol->hasDefinition())
return Protocol->getDefinition();
return Protocol;
}
return Container;
}
/// Adds a block invocation code completion result for the given block
/// declaration \p BD.
static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
CodeCompletionBuilder &Builder,
const NamedDecl *BD,
const FunctionTypeLoc &BlockLoc,
const FunctionProtoTypeLoc &BlockProtoLoc) {
Builder.AddResultTypeChunk(
GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
Policy, Builder.getAllocator()));
AddTypedNameChunk(Context, Policy, BD, Builder);
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
Builder.AddPlaceholderChunk("...");
} else {
for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
if (I)
Builder.AddChunk(CodeCompletionString::CK_Comma);
// Format the placeholder string.
std::string PlaceholderStr =
FormatFunctionParameter(Policy, BlockLoc.getParam(I));
if (I == N - 1 && BlockProtoLoc &&
BlockProtoLoc.getTypePtr()->isVariadic())
PlaceholderStr += ", ...";
// Add the placeholder string.
Builder.AddPlaceholderChunk(
Builder.getAllocator().CopyString(PlaceholderStr));
}
}
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
static void
AddObjCProperties(const CodeCompletionContext &CCContext,
ObjCContainerDecl *Container, bool AllowCategories,
bool AllowNullaryMethods, DeclContext *CurContext,
AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
bool IsBaseExprStatement = false,
bool IsClassProperty = false, bool InOriginalClass = true) {
typedef CodeCompletionResult Result;
// Retrieve the definition.
Container = getContainerDef(Container);
// Add properties in this container.
const auto AddProperty = [&](const ObjCPropertyDecl *P) {
if (!AddedProperties.insert(P->getIdentifier()).second)
return;
// FIXME: Provide block invocation completion for non-statement
// expressions.
if (!P->getType().getTypePtr()->isBlockPointerType() ||
!IsBaseExprStatement) {
Result R = Result(P, Results.getBasePriority(P), nullptr);
if (!InOriginalClass)
setInBaseClass(R);
Results.MaybeAddResult(R, CurContext);
return;
}
// Block setter and invocation completion is provided only when we are able
// to find the FunctionProtoTypeLoc with parameter names for the block.
FunctionTypeLoc BlockLoc;
FunctionProtoTypeLoc BlockProtoLoc;
findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
BlockProtoLoc);
if (!BlockLoc) {
Result R = Result(P, Results.getBasePriority(P), nullptr);
if (!InOriginalClass)
setInBaseClass(R);
Results.MaybeAddResult(R, CurContext);
return;
}
// The default completion result for block properties should be the block
// invocation completion when the base expression is a statement.
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
AddObjCBlockCall(Container->getASTContext(),
getCompletionPrintingPolicy(Results.getSema()), Builder, P,
BlockLoc, BlockProtoLoc);
Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));
if (!InOriginalClass)
setInBaseClass(R);
Results.MaybeAddResult(R, CurContext);
// Provide additional block setter completion iff the base expression is a
// statement and the block property is mutable.
if (!P->isReadOnly()) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
AddResultTypeChunk(Container->getASTContext(),
getCompletionPrintingPolicy(Results.getSema()), P,
CCContext.getBaseType(), Builder);
Builder.AddTypedTextChunk(
Results.getAllocator().CopyString(P->getName()));
Builder.AddChunk(CodeCompletionString::CK_Equal);
std::string PlaceholderStr = formatBlockPlaceholder(
getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
BlockProtoLoc, /*SuppressBlockName=*/true);
// Add the placeholder string.
Builder.AddPlaceholderChunk(
Builder.getAllocator().CopyString(PlaceholderStr));
// When completing blocks properties that return void the default
// property completion result should show up before the setter,
// otherwise the setter completion should show up before the default
// property completion, as we normally want to use the result of the
// call.
Result R =
Result(Builder.TakeString(), P,
Results.getBasePriority(P) +
(BlockLoc.getTypePtr()->getReturnType()->isVoidType()
? CCD_BlockPropertySetter
: -CCD_BlockPropertySetter));
if (!InOriginalClass)
setInBaseClass(R);
Results.MaybeAddResult(R, CurContext);
}
};
if (IsClassProperty) {
for (const auto *P : Container->class_properties())
AddProperty(P);
} else {
for (const auto *P : Container->instance_properties())
AddProperty(P);
}
// Add nullary methods or implicit class properties
if (AllowNullaryMethods) {
ASTContext &Context = Container->getASTContext();
PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
// Adds a method result
const auto AddMethod = [&](const ObjCMethodDecl *M) {
IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
if (!Name)
return;
if (!AddedProperties.insert(Name).second)
return;
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
Builder.AddTypedTextChunk(
Results.getAllocator().CopyString(Name->getName()));
Result R = Result(Builder.TakeString(), M,
CCP_MemberDeclaration + CCD_MethodAsProperty);
if (!InOriginalClass)
setInBaseClass(R);
Results.MaybeAddResult(R, CurContext);
};
if (IsClassProperty) {
for (const auto *M : Container->methods()) {
// Gather the class method that can be used as implicit property
// getters. Methods with arguments or methods that return void aren't
// added to the results as they can't be used as a getter.
if (!M->getSelector().isUnarySelector() ||
M->getReturnType()->isVoidType() || M->isInstanceMethod())
continue;
AddMethod(M);
}
} else {
for (auto *M : Container->methods()) {
if (M->getSelector().isUnarySelector())
AddMethod(M);
}
}
}
// Add properties in referenced protocols.
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
for (auto *P : Protocol->protocols())
AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
CurContext, AddedProperties, Results,
IsBaseExprStatement, IsClassProperty,
/*InOriginalClass*/ false);
} else if (ObjCInterfaceDecl *IFace =
dyn_cast<ObjCInterfaceDecl>(Container)) {
if (AllowCategories) {
// Look through categories.
for (auto *Cat : IFace->known_categories())
AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
CurContext, AddedProperties, Results,
IsBaseExprStatement, IsClassProperty,
InOriginalClass);
}
// Look through protocols.
for (auto *I : IFace->all_referenced_protocols())
AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
CurContext, AddedProperties, Results,
IsBaseExprStatement, IsClassProperty,
/*InOriginalClass*/ false);
// Look in the superclass.
if (IFace->getSuperClass())
AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
AllowNullaryMethods, CurContext, AddedProperties,
Results, IsBaseExprStatement, IsClassProperty,
/*InOriginalClass*/ false);
} else if (const auto *Category =
dyn_cast<ObjCCategoryDecl>(Container)) {
// Look through protocols.
for (auto *P : Category->protocols())
AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
CurContext, AddedProperties, Results,
IsBaseExprStatement, IsClassProperty,
/*InOriginalClass*/ false);
}
}
static void
AddRecordMembersCompletionResults(Sema &SemaRef, ResultBuilder &Results,
Scope *S, QualType BaseType, RecordDecl *RD,
Optional<FixItHint> AccessOpFixIt) {
// Indicate that we are performing a member access, and the cv-qualifiers
// for the base object type.
Results.setObjectTypeQualifiers(BaseType.getQualifiers());
// Access to a C/C++ class, struct, or union.
Results.allowNestedNameSpecifiers();
std::vector<FixItHint> FixIts;
if (AccessOpFixIt)
FixIts.emplace_back(AccessOpFixIt.getValue());
CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts));
SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
SemaRef.CodeCompleter->includeGlobals(),
/*IncludeDependentBases=*/true,
SemaRef.CodeCompleter->loadExternal());
if (SemaRef.getLangOpts().CPlusPlus) {
if (!Results.empty()) {
// The "template" keyword can follow "->" or "." in the grammar.
// However, we only want to suggest the template keyword if something
// is dependent.
bool IsDependent = BaseType->isDependentType();
if (!IsDependent) {
for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
if (DeclContext *Ctx = DepScope->getEntity()) {
IsDependent = Ctx->isDependentContext();
break;
}
}
if (IsDependent)
Results.AddResult(CodeCompletionResult("template"));
}
}
}
void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Expr *OtherOpBase,
SourceLocation OpLoc, bool IsArrow,
bool IsBaseExprStatement) {
if (!Base || !CodeCompleter)
return;
ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
if (ConvertedBase.isInvalid())
return;
QualType ConvertedBaseType = ConvertedBase.get()->getType();
enum CodeCompletionContext::Kind contextKind;
if (IsArrow) {
if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>())
ConvertedBaseType = Ptr->getPointeeType();
}
if (IsArrow) {
contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
} else {
if (ConvertedBaseType->isObjCObjectPointerType() ||
ConvertedBaseType->isObjCObjectOrInterfaceType()) {
contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
} else {
contextKind = CodeCompletionContext::CCC_DotMemberAccess;
}
}
CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(), CCContext,
&ResultBuilder::IsMember);
auto DoCompletion = [&](Expr *Base, bool IsArrow,
Optional<FixItHint> AccessOpFixIt) -> bool {
if (!Base)
return false;
ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
if (ConvertedBase.isInvalid())
return false;
Base = ConvertedBase.get();
QualType BaseType = Base->getType();
if (IsArrow) {
if (const PointerType *Ptr = BaseType->getAs<PointerType>())
BaseType = Ptr->getPointeeType();
else if (BaseType->isObjCObjectPointerType())
/*Do nothing*/;
else
return false;
}
if (const RecordType *Record = BaseType->getAs<RecordType>()) {
AddRecordMembersCompletionResults(*this, Results, S, BaseType,
Record->getDecl(),
std::move(AccessOpFixIt));
} else if (const auto *TST =
BaseType->getAs<TemplateSpecializationType>()) {
TemplateName TN = TST->getTemplateName();
if (const auto *TD =
dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
CXXRecordDecl *RD = TD->getTemplatedDecl();
AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
std::move(AccessOpFixIt));
}
} else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
if (auto *RD = ICNT->getDecl())
AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
std::move(AccessOpFixIt));
} else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
// Objective-C property reference.
AddedPropertiesSet AddedProperties;
if (const ObjCObjectPointerType *ObjCPtr =
BaseType->getAsObjCInterfacePointerType()) {
// Add property results based on our interface.
assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
/*AllowNullaryMethods=*/true, CurContext,
AddedProperties, Results, IsBaseExprStatement);
}
// Add properties from the protocols in a qualified interface.
for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
CurContext, AddedProperties, Results,
IsBaseExprStatement, /*IsClassProperty*/ false,
/*InOriginalClass*/ false);
} else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
(!IsArrow && BaseType->isObjCObjectType())) {
// Objective-C instance variable access.
ObjCInterfaceDecl *Class = nullptr;
if (const ObjCObjectPointerType *ObjCPtr =
BaseType->getAs<ObjCObjectPointerType>())
Class = ObjCPtr->getInterfaceDecl();
else
Class = BaseType->getAs<ObjCObjectType>()->getInterface();
// Add all ivars from this class and its superclasses.
if (Class) {
CodeCompletionDeclConsumer Consumer(Results, Class, BaseType);
Results.setFilter(&ResultBuilder::IsObjCIvar);
LookupVisibleDecls(
Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
/*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
}
}
// FIXME: How do we cope with isa?
return true;
};
Results.EnterNewScope();
bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
if (CodeCompleter->includeFixIts()) {
const CharSourceRange OpRange =
CharSourceRange::getTokenRange(OpLoc, OpLoc);
CompletionSucceded |= DoCompletion(
OtherOpBase, !IsArrow,
FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
}
Results.ExitScope();
if (!CompletionSucceded)
return;
// Hand off the results found for code completion.
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
IdentifierInfo &ClassName,
SourceLocation ClassNameLoc,
bool IsBaseExprStatement) {
IdentifierInfo *ClassNamePtr = &ClassName;
ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
if (!IFace)
return;
CodeCompletionContext CCContext(
CodeCompletionContext::CCC_ObjCPropertyAccess);
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(), CCContext,
&ResultBuilder::IsMember);
Results.EnterNewScope();
AddedPropertiesSet AddedProperties;
AddObjCProperties(CCContext, IFace, true,
/*AllowNullaryMethods=*/true, CurContext, AddedProperties,
Results, IsBaseExprStatement,
/*IsClassProperty=*/true);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
if (!CodeCompleter)
return;
ResultBuilder::LookupFilter Filter = nullptr;
enum CodeCompletionContext::Kind ContextKind =
CodeCompletionContext::CCC_Other;
switch ((DeclSpec::TST)TagSpec) {
case DeclSpec::TST_enum:
Filter = &ResultBuilder::IsEnum;
ContextKind = CodeCompletionContext::CCC_EnumTag;
break;
case DeclSpec::TST_union:
Filter = &ResultBuilder::IsUnion;
ContextKind = CodeCompletionContext::CCC_UnionTag;
break;
case DeclSpec::TST_struct:
case DeclSpec::TST_class:
case DeclSpec::TST_interface:
Filter = &ResultBuilder::IsClassOrStruct;
ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
break;
default:
llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
}
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
// First pass: look for tags.
Results.setFilter(Filter);
LookupVisibleDecls(S, LookupTagName, Consumer,
CodeCompleter->includeGlobals(),
CodeCompleter->loadExternal());
if (CodeCompleter->includeGlobals()) {
// Second pass: look for nested name specifiers.
Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
CodeCompleter->includeGlobals(),
CodeCompleter->loadExternal());
}
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
const LangOptions &LangOpts) {
if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
Results.AddResult("const");
if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
Results.AddResult("volatile");
if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
Results.AddResult("restrict");
if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
Results.AddResult("_Atomic");
if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
Results.AddResult("__unaligned");
}
void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_TypeQualifiers);
Results.EnterNewScope();
AddTypeQualifierResults(DS, Results, LangOpts);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
const VirtSpecifiers *VS) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_TypeQualifiers);
Results.EnterNewScope();
AddTypeQualifierResults(DS, Results, LangOpts);
if (LangOpts.CPlusPlus11) {
Results.AddResult("noexcept");
if (D.getContext() == DeclaratorContext::MemberContext &&
!D.isCtorOrDtor() && !D.isStaticMember()) {
if (!VS || !VS->isFinalSpecified())
Results.AddResult("final");
if (!VS || !VS->isOverrideSpecified())
Results.AddResult("override");
}
}
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteBracketDeclarator(Scope *S) {
CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
}
void Sema::CodeCompleteCase(Scope *S) {
if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
return;
SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
// Condition expression might be invalid, do not continue in this case.
if (!Switch->getCond())
return;
QualType type = Switch->getCond()->IgnoreImplicit()->getType();
if (!type->isEnumeralType()) {
CodeCompleteExpressionData Data(type);
Data.IntegralConstantExpression = true;
CodeCompleteExpression(S, Data);
return;
}
// Code-complete the cases of a switch statement over an enumeration type
// by providing the list of
EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
if (EnumDecl *Def = Enum->getDefinition())
Enum = Def;
// Determine which enumerators we have already seen in the switch statement.
// FIXME: Ideally, we would also be able to look *past* the code-completion
// token, in case we are code-completing in the middle of the switch and not
// at the end. However, we aren't able to do so at the moment.
llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
NestedNameSpecifier *Qualifier = nullptr;
for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase()) {
CaseStmt *Case = dyn_cast<CaseStmt>(SC);
if (!Case)
continue;
Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))
if (auto *Enumerator =
dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
// We look into the AST of the case statement to determine which
// enumerator was named. Alternatively, we could compute the value of
// the integral constant expression, then compare it against the
// values of each enumerator. However, value-based approach would not
// work as well with C++ templates where enumerators declared within a
// template are type- and value-dependent.
EnumeratorsSeen.insert(Enumerator);
// If this is a qualified-id, keep track of the nested-name-specifier
// so that we can reproduce it as part of code completion, e.g.,
//
// switch (TagD.getKind()) {
// case TagDecl::TK_enum:
// break;
// case XXX
//
// At the XXX, our completions are TagDecl::TK_union,
// TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
// TK_struct, and TK_class.
Qualifier = DRE->getQualifier();
}
}
if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
// If there are no prior enumerators in C++, check whether we have to
// qualify the names of the enumerators that we suggest, because they
// may not be visible in this scope.
Qualifier = getRequiredQualification(Context, CurContext, Enum);
}
// Add any enumerators that have not yet been mentioned.
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Expression);
Results.EnterNewScope();
for (auto *E : Enum->enumerators()) {
if (EnumeratorsSeen.count(E))
continue;
CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Results.AddResult(R, CurContext, nullptr, false);
}
Results.ExitScope();
if (CodeCompleter->includeMacros()) {
AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
}
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
static bool anyNullArguments(ArrayRef<Expr *> Args) {
if (Args.size() && !Args.data())
return true;
for (unsigned I = 0; I != Args.size(); ++I)
if (!Args[I])
return true;
return false;
}
typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
static void mergeCandidatesWithResults(
Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
if (!CandidateSet.empty()) {
// Sort the overload candidate set by placing the best overloads first.
std::stable_sort(
CandidateSet.begin(), CandidateSet.end(),
[&](const OverloadCandidate &X, const OverloadCandidate &Y) {
return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
CandidateSet.getKind());
});
// Add the remaining viable overload candidates as code-completion results.
for (OverloadCandidate &Candidate : CandidateSet) {
if (Candidate.Function && Candidate.Function->isDeleted())
continue;
if (Candidate.Viable)
Results.push_back(ResultCandidate(Candidate.Function));
}
}
}
/// Get the type of the Nth parameter from a given set of overload
/// candidates.
static QualType getParamType(Sema &SemaRef,
ArrayRef<ResultCandidate> Candidates, unsigned N) {
// Given the overloads 'Candidates' for a function call matching all arguments
// up to N, return the type of the Nth parameter if it is the same for all
// overload candidates.
QualType ParamType;
for (auto &Candidate : Candidates) {
if (const auto *FType = Candidate.getFunctionType())
if (const auto *Proto = dyn_cast<FunctionProtoType>(FType))
if (N < Proto->getNumParams()) {
if (ParamType.isNull())
ParamType = Proto->getParamType(N);
else if (!SemaRef.Context.hasSameUnqualifiedType(
ParamType.getNonReferenceType(),
Proto->getParamType(N).getNonReferenceType()))
// Otherwise return a default-constructed QualType.
return QualType();
}
}
return ParamType;
}
static QualType
ProduceSignatureHelp(Sema &SemaRef, Scope *S,
MutableArrayRef<ResultCandidate> Candidates,
unsigned CurrentArg, SourceLocation OpenParLoc) {
if (Candidates.empty())
return QualType();
SemaRef.CodeCompleter->ProcessOverloadCandidates(
SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
return getParamType(SemaRef, Candidates, CurrentArg);
}
QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
ArrayRef<Expr *> Args,
SourceLocation OpenParLoc) {
if (!CodeCompleter)
return QualType();
// FIXME: Provide support for variadic template functions.
// Ignore type-dependent call expressions entirely.
if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
Expr::hasAnyTypeDependentArguments(Args)) {
return QualType();
}
// Build an overload candidate set based on the functions we find.
SourceLocation Loc = Fn->getExprLoc();
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
SmallVector<ResultCandidate, 8> Results;
Expr *NakedFn = Fn->IgnoreParenCasts();
if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
AddOverloadedCallCandidates(ULE, Args, CandidateSet,
/*PartialOverloading=*/true);
else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
if (UME->hasExplicitTemplateArgs()) {
UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
TemplateArgs = &TemplateArgsBuffer;
}
// Add the base as first argument (use a nullptr if the base is implicit).
SmallVector<Expr *, 12> ArgExprs(
1, UME->isImplicitAccess() ? nullptr : UME->getBase());
ArgExprs.append(Args.begin(), Args.end());
UnresolvedSet<8> Decls;
Decls.append(UME->decls_begin(), UME->decls_end());
const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
/*SuppressUsedConversions=*/false,
/*PartialOverloading=*/true, FirstArgumentIsBase);
} else {
FunctionDecl *FD = nullptr;
if (auto *MCE = dyn_cast<MemberExpr>(NakedFn))
FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn))
FD = dyn_cast<FunctionDecl>(DRE->getDecl());
if (FD) { // We check whether it's a resolved function declaration.
if (!getLangOpts().CPlusPlus ||
!FD->getType()->getAs<FunctionProtoType>())
Results.push_back(ResultCandidate(FD));
else
AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
Args, CandidateSet,
/*SuppressUsedConversions=*/false,
/*PartialOverloading=*/true);
} else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
// If expression's type is CXXRecordDecl, it may overload the function
// call operator, so we check if it does and add them as candidates.
// A complete type is needed to lookup for member function call operators.
if (isCompleteType(Loc, NakedFn->getType())) {
DeclarationName OpName =
Context.DeclarationNames.getCXXOperatorName(OO_Call);
LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
LookupQualifiedName(R, DC);
R.suppressDiagnostics();
SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
ArgExprs.append(Args.begin(), Args.end());
AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
/*ExplicitArgs=*/nullptr,
/*SuppressUsedConversions=*/false,
/*PartialOverloading=*/true);
}
} else {
// Lastly we check whether expression's type is function pointer or
// function.
QualType T = NakedFn->getType();
if (!T->getPointeeType().isNull())
T = T->getPointeeType();
if (auto FP = T->getAs<FunctionProtoType>()) {
if (!TooManyArguments(FP->getNumParams(), Args.size(),
/*PartialOverloading=*/true) ||
FP->isVariadic())
Results.push_back(ResultCandidate(FP));
} else if (auto FT = T->getAs<FunctionType>())
// No prototype and declaration, it may be a K & R style function.
Results.push_back(ResultCandidate(FT));
}
}
mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
QualType ParamType =
ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
return !CandidateSet.empty() ? ParamType : QualType();
}
QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
SourceLocation Loc,
ArrayRef<Expr *> Args,
SourceLocation OpenParLoc) {
if (!CodeCompleter)
return QualType();
// A complete type is needed to lookup for constructors.
CXXRecordDecl *RD =
isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
if (!RD)
return Type;
// FIXME: Provide support for member initializers.
// FIXME: Provide support for variadic template constructors.
OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
for (NamedDecl *C : LookupConstructors(RD)) {
if (auto *FD = dyn_cast<FunctionDecl>(C)) {
AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
CandidateSet,
/*SuppressUsedConversions=*/false,
/*PartialOverloading=*/true);
} else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
AddTemplateOverloadCandidate(
FTD, DeclAccessPair::make(FTD, C->getAccess()),
/*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
/*SuppressUsedConversions=*/false,
/*PartialOverloading=*/true);
}
}
SmallVector<ResultCandidate, 8> Results;
mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
}
QualType Sema::ProduceCtorInitMemberSignatureHelp(
Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
if (!CodeCompleter)
return QualType();
CXXConstructorDecl *Constructor =
dyn_cast<CXXConstructorDecl>(ConstructorDecl);
if (!Constructor)
return QualType();
// FIXME: Add support for Base class constructors as well.
if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
Constructor->getParent(), SS, TemplateTypeTy, II))
return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
MemberDecl->getLocation(), ArgExprs,
OpenParLoc);
return QualType();
}
void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
if (!VD) {
CodeCompleteOrdinaryName(S, PCC_Expression);
return;
}
CodeCompleteExpressionData Data;
Data.PreferredType = VD->getType();
// Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'.
Data.IgnoreDecls.push_back(VD);
CodeCompleteExpression(S, Data);
}
void Sema::CodeCompleteReturn(Scope *S) {
QualType ResultType;
if (isa<BlockDecl>(CurContext)) {
if (BlockScopeInfo *BSI = getCurBlock())
ResultType = BSI->ReturnType;
} else if (const auto *Function = dyn_cast<FunctionDecl>(CurContext))
ResultType = Function->getReturnType();
else if (const auto *Method = dyn_cast<ObjCMethodDecl>(CurContext))
ResultType = Method->getReturnType();
if (ResultType.isNull())
CodeCompleteOrdinaryName(S, PCC_Expression);
else
CodeCompleteExpression(S, ResultType);
}
void Sema::CodeCompleteAfterIf(Scope *S) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
mapCodeCompletionContext(*this, PCC_Statement));
Results.setFilter(&ResultBuilder::IsOrdinaryName);
Results.EnterNewScope();
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
CodeCompleter->includeGlobals(),
CodeCompleter->loadExternal());
AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
// "else" block
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Builder.AddTypedTextChunk("else");
if (Results.includeCodePatterns()) {
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
}
Results.AddResult(Builder.TakeString());
// "else if" block
Builder.AddTypedTextChunk("else");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTextChunk("if");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
if (getLangOpts().CPlusPlus)
Builder.AddPlaceholderChunk("condition");
else
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
if (Results.includeCodePatterns()) {
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
}
Results.AddResult(Builder.TakeString());
Results.ExitScope();
if (S->getFnParent())
AddPrettyFunctionResults(getLangOpts(), Results);
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
static QualType getPreferredTypeOfBinaryRHS(Sema &S, Expr *LHS,
tok::TokenKind Op) {
if (!LHS)
return QualType();
QualType LHSType = LHS->getType();
if (LHSType->isPointerType()) {
if (Op == tok::plus || Op == tok::plusequal || Op == tok::minusequal)
return S.getASTContext().getPointerDiffType();
// Pointer difference is more common than subtracting an int from a pointer.
if (Op == tok::minus)
return LHSType;
}
switch (Op) {
// No way to infer the type of RHS from LHS.
case tok::comma:
return QualType();
// Prefer the type of the left operand for all of these.
// Arithmetic operations.
case tok::plus:
case tok::plusequal:
case tok::minus:
case tok::minusequal:
case tok::percent:
case tok::percentequal:
case tok::slash:
case tok::slashequal:
case tok::star:
case tok::starequal:
// Assignment.
case tok::equal:
// Comparison operators.
case tok::equalequal:
case tok::exclaimequal:
case tok::less:
case tok::lessequal:
case tok::greater:
case tok::greaterequal:
case tok::spaceship:
return LHS->getType();
// Binary shifts are often overloaded, so don't try to guess those.
case tok::greatergreater:
case tok::greatergreaterequal:
case tok::lessless:
case tok::lesslessequal:
if (LHSType->isIntegralOrEnumerationType())
return S.getASTContext().IntTy;
return QualType();
// Logical operators, assume we want bool.
case tok::ampamp:
case tok::pipepipe:
case tok::caretcaret:
return S.getASTContext().BoolTy;
// Operators often used for bit manipulation are typically used with the type
// of the left argument.
case tok::pipe:
case tok::pipeequal:
case tok::caret:
case tok::caretequal:
case tok::amp:
case tok::ampequal:
if (LHSType->isIntegralOrEnumerationType())
return LHSType;
return QualType();
// RHS should be a pointer to a member of the 'LHS' type, but we can't give
// any particular type here.
case tok::periodstar:
case tok::arrowstar:
return QualType();
default:
// FIXME(ibiryukov): handle the missing op, re-add the assertion.
// assert(false && "unhandled binary op");
return QualType();
}
}
void Sema::CodeCompleteBinaryRHS(Scope *S, Expr *LHS, tok::TokenKind Op) {
auto PreferredType = getPreferredTypeOfBinaryRHS(*this, LHS, Op);
if (!PreferredType.isNull())
CodeCompleteExpression(S, PreferredType);
else
CodeCompleteOrdinaryName(S, PCC_Expression);
}
void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
bool EnteringContext, QualType BaseType) {
if (SS.isEmpty() || !CodeCompleter)
return;
// We want to keep the scope specifier even if it's invalid (e.g. the scope
// "a::b::" is not corresponding to any context/namespace in the AST), since
// it can be useful for global code completion which have information about
// contexts/symbols that are not in the AST.
if (SS.isInvalid()) {
CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol);
CC.setCXXScopeSpecifier(SS);
HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
return;
}
// Always pretend to enter a context to ensure that a dependent type
// resolves to a dependent record.
DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
if (!Ctx)
return;
// Try to instantiate any non-dependent declaration contexts before
// we look in them.
if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
return;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Symbol);
Results.EnterNewScope();
// The "template" keyword can follow "::" in the grammar, but only
// put it into the grammar if the nested-name-specifier is dependent.
NestedNameSpecifier *NNS = SS.getScopeRep();
if (!Results.empty() && NNS->isDependent())
Results.AddResult("template");
// Add calls to overridden virtual functions, if there are any.
//
// FIXME: This isn't wonderful, because we don't know whether we're actually
// in a context that permits expressions. This is a general issue with
// qualified-id completions.
if (!EnteringContext)
MaybeAddOverrideCalls(*this, Ctx, Results);
Results.ExitScope();
if (CodeCompleter->includeNamespaceLevelDecls() ||
(!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);
LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
/*IncludeGlobalScope=*/true,
/*IncludeDependentBases=*/true,
CodeCompleter->loadExternal());
}
auto CC = Results.getCompletionContext();
CC.setCXXScopeSpecifier(SS);
HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
Results.size());
}
void Sema::CodeCompleteUsing(Scope *S) {
if (!CodeCompleter)
return;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
// This can be both a using alias or using
// declaration, in the former we expect a new name and a
// symbol in the latter case.
CodeCompletionContext::CCC_SymbolOrNewName,
&ResultBuilder::IsNestedNameSpecifier);
Results.EnterNewScope();
// If we aren't in class scope, we could see the "namespace" keyword.
if (!S->isClassScope())
Results.AddResult(CodeCompletionResult("namespace"));
// After "using", we can see anything that would start a
// nested-name-specifier.
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
CodeCompleter->includeGlobals(),
CodeCompleter->loadExternal());
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteUsingDirective(Scope *S) {
if (!CodeCompleter)
return;
// After "using namespace", we expect to see a namespace name or namespace
// alias.
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Namespace,
&ResultBuilder::IsNamespaceOrAlias);
Results.EnterNewScope();
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
CodeCompleter->includeGlobals(),
CodeCompleter->loadExternal());
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteNamespaceDecl(Scope *S) {
if (!CodeCompleter)
return;
DeclContext *Ctx = S->getEntity();
if (!S->getParent())
Ctx = Context.getTranslationUnitDecl();
bool SuppressedGlobalResults =
Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
SuppressedGlobalResults
? CodeCompletionContext::CCC_Namespace
: CodeCompletionContext::CCC_Other,
&ResultBuilder::IsNamespace);
if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
// We only want to see those namespaces that have already been defined
// within this scope, because its likely that the user is creating an
// extended namespace declaration. Keep track of the most recent
// definition of each namespace.
std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
for (DeclContext::specific_decl_iterator<NamespaceDecl>
NS(Ctx->decls_begin()),
NSEnd(Ctx->decls_end());
NS != NSEnd; ++NS)
OrigToLatest[NS->getOriginalNamespace()] = *NS;
// Add the most recent definition (or extended definition) of each
// namespace to the list of results.
Results.EnterNewScope();
for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
NS = OrigToLatest.begin(),
NSEnd = OrigToLatest.end();
NS != NSEnd; ++NS)
Results.AddResult(
CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),
nullptr),
CurContext, nullptr, false);
Results.ExitScope();
}
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
if (!CodeCompleter)
return;
// After "namespace", we expect to see a namespace or alias.
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Namespace,
&ResultBuilder::IsNamespaceOrAlias);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
CodeCompleter->includeGlobals(),
CodeCompleter->loadExternal());
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteOperatorName(Scope *S) {
if (!CodeCompleter)
return;
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Type,
&ResultBuilder::IsType);
Results.EnterNewScope();
// Add the names of overloadable operators.
#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
if (std::strcmp(Spelling, "?")) \
Results.AddResult(Result(Spelling));
#include "clang/Basic/OperatorKinds.def"
// Add any type names visible from the current scope
Results.allowNestedNameSpecifiers();
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
CodeCompleter->includeGlobals(),
CodeCompleter->loadExternal());
// Add any type specifiers
AddTypeSpecifierResults(getLangOpts(), Results);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteConstructorInitializer(
Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) {
if (!ConstructorD)
return;
AdjustDeclIfTemplate(ConstructorD);
auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
if (!Constructor)
return;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Symbol);
Results.EnterNewScope();
// Fill in any already-initialized fields or base classes.
llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
if (Initializers[I]->isBaseInitializer())
InitializedBases.insert(Context.getCanonicalType(
QualType(Initializers[I]->getBaseClass(), 0)));
else
InitializedFields.insert(
cast<FieldDecl>(Initializers[I]->getAnyMember()));
}
// Add completions for base classes.
PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
bool SawLastInitializer = Initializers.empty();
CXXRecordDecl *ClassDecl = Constructor->getParent();
auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Builder.AddTypedTextChunk(Name);
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
if (const auto *Function = dyn_cast<FunctionDecl>(ND))
AddFunctionParameterChunks(PP, Policy, Function, Builder);
else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND))
AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(),
Builder);
Builder.AddChunk(CodeCompletionString::CK_RightParen);
return Builder.TakeString();
};
auto AddDefaultCtorInit = [&](const char *Name, const char *Type,
const NamedDecl *ND) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Builder.AddTypedTextChunk(Name);
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk(Type);
Builder.AddChunk(CodeCompletionString::CK_RightParen);
if (ND) {
auto CCR = CodeCompletionResult(
Builder.TakeString(), ND,
SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration);
if (isa<FieldDecl>(ND))
CCR.CursorKind = CXCursor_MemberRef;
return Results.AddResult(CCR);
}
return Results.AddResult(CodeCompletionResult(
Builder.TakeString(),
SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration));
};
auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority,
const char *Name, const FieldDecl *FD) {
if (!RD)
return AddDefaultCtorInit(Name,
FD ? Results.getAllocator().CopyString(
FD->getType().getAsString(Policy))
: Name,
FD);
auto Ctors = getConstructors(Context, RD);
if (Ctors.begin() == Ctors.end())
return AddDefaultCtorInit(Name, Name, RD);
for (const NamedDecl *Ctor : Ctors) {
auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority);
CCR.CursorKind = getCursorKindForDecl(Ctor);
Results.AddResult(CCR);
}
};
auto AddBase = [&](const CXXBaseSpecifier &Base) {
const char *BaseName =
Results.getAllocator().CopyString(Base.getType().getAsString(Policy));
const auto *RD = Base.getType()->getAsCXXRecordDecl();
AddCtorsWithName(
RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
BaseName, nullptr);
};
auto AddField = [&](const FieldDecl *FD) {
const char *FieldName =
Results.getAllocator().CopyString(FD->getIdentifier()->getName());
const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();
AddCtorsWithName(
RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
FieldName, FD);
};
for (const auto &Base : ClassDecl->bases()) {
if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
.second) {
SawLastInitializer =
!Initializers.empty() && Initializers.back()->isBaseInitializer() &&
Context.hasSameUnqualifiedType(
Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
continue;
}
AddBase(Base);
SawLastInitializer = false;
}
// Add completions for virtual base classes.
for (const auto &Base : ClassDecl->vbases()) {
if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
.second) {
SawLastInitializer =
!Initializers.empty() && Initializers.back()->isBaseInitializer() &&
Context.hasSameUnqualifiedType(
Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
continue;
}
AddBase(Base);
SawLastInitializer = false;
}
// Add completions for members.
for (auto *Field : ClassDecl->fields()) {
if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
.second) {
SawLastInitializer = !Initializers.empty() &&
Initializers.back()->isAnyMemberInitializer() &&
Initializers.back()->getAnyMember() == Field;
continue;
}
if (!Field->getDeclName())
continue;
AddField(Field);
SawLastInitializer = false;
}
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
/// Determine whether this scope denotes a namespace.
static bool isNamespaceScope(Scope *S) {
DeclContext *DC = S->getEntity();
if (!DC)
return false;
return DC->isFileContext();
}
void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
bool AfterAmpersand) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
// Note what has already been captured.
llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
bool IncludedThis = false;
for (const auto &C : Intro.Captures) {
if (C.Kind == LCK_This) {
IncludedThis = true;
continue;
}
Known.insert(C.Id);
}
// Look for other capturable variables.
for (; S && !isNamespaceScope(S); S = S->getParent()) {
for (const auto *D : S->decls()) {
const auto *Var = dyn_cast<VarDecl>(D);
if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>())
continue;
if (Known.insert(Var->getIdentifier()).second)
Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
CurContext, nullptr, false);
}
}
// Add 'this', if it would be valid.
if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
addThisCompletion(*this, Results);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
/// Macro that optionally prepends an "@" to the string literal passed in via
/// Keyword, depending on whether NeedAt is true or false.
#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword)
static void AddObjCImplementationResults(const LangOptions &LangOpts,
ResultBuilder &Results, bool NeedAt) {
typedef CodeCompletionResult Result;
// Since we have an implementation, we can end it.
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
if (LangOpts.ObjC) {
// @dynamic
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("property");
Results.AddResult(Result(Builder.TakeString()));
// @synthesize
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("property");
Results.AddResult(Result(Builder.TakeString()));
}
}
static void AddObjCInterfaceResults(const LangOptions &LangOpts,
ResultBuilder &Results, bool NeedAt) {
typedef CodeCompletionResult Result;
// Since we have an interface or protocol, we can end it.
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
if (LangOpts.ObjC) {
// @property
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")));
// @required
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")));
// @optional
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")));
}
}
static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
typedef CodeCompletionResult Result;
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
// @class name ;
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("name");
Results.AddResult(Result(Builder.TakeString()));
if (Results.includeCodePatterns()) {
// @interface name
// FIXME: Could introduce the whole pattern, including superclasses and
// such.
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("class");
Results.AddResult(Result(Builder.TakeString()));
// @protocol name
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("protocol");
Results.AddResult(Result(Builder.TakeString()));
// @implementation name
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("class");
Results.AddResult(Result(Builder.TakeString()));
}
// @compatibility_alias name
Builder.AddTypedTextChunk(
OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("alias");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("class");
Results.AddResult(Result(Builder.TakeString()));
if (Results.getSema().getLangOpts().Modules) {
// @import name
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("module");
Results.AddResult(Result(Builder.TakeString()));
}
}
void Sema::CodeCompleteObjCAtDirective(Scope *S) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
if (isa<ObjCImplDecl>(CurContext))
AddObjCImplementationResults(getLangOpts(), Results, false);
else if (CurContext->isObjCContainer())
AddObjCInterfaceResults(getLangOpts(), Results, false);
else
AddObjCTopLevelResults(Results, false);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
typedef CodeCompletionResult Result;
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
// @encode ( type-name )
const char *EncodeType = "char[]";
if (Results.getSema().getLangOpts().CPlusPlus ||
Results.getSema().getLangOpts().ConstStrings)
EncodeType = "const char[]";
Builder.AddResultTypeChunk(EncodeType);
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("type-name");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
// @protocol ( protocol-name )
Builder.AddResultTypeChunk("Protocol *");
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("protocol-name");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
// @selector ( selector )
Builder.AddResultTypeChunk("SEL");
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("selector");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
// @"string"
Builder.AddResultTypeChunk("NSString *");
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\""));
Builder.AddPlaceholderChunk("string");
Builder.AddTextChunk("\"");
Results.AddResult(Result(Builder.TakeString()));
// @[objects, ...]
Builder.AddResultTypeChunk("NSArray *");
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "["));
Builder.AddPlaceholderChunk("objects, ...");
Builder.AddChunk(CodeCompletionString::CK_RightBracket);
Results.AddResult(Result(Builder.TakeString()));
// @{key : object, ...}
Builder.AddResultTypeChunk("NSDictionary *");
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{"));
Builder.AddPlaceholderChunk("key");
Builder.AddChunk(CodeCompletionString::CK_Colon);
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("object, ...");
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
// @(expression)
Builder.AddResultTypeChunk("id");
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
}
static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
typedef CodeCompletionResult Result;
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
if (Results.includeCodePatterns()) {
// @try { statements } @catch ( declaration ) { statements } @finally
// { statements }
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try"));
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Builder.AddTextChunk("@catch");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("parameter");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Builder.AddTextChunk("@finally");
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
// @throw
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("expression");
Results.AddResult(Result(Builder.TakeString()));
if (Results.includeCodePatterns()) {
// @synchronized ( expression ) { statements }
Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized"));
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Results.AddResult(Result(Builder.TakeString()));
}
}
static void AddObjCVisibilityResults(const LangOptions &LangOpts,
ResultBuilder &Results, bool NeedAt) {
typedef CodeCompletionResult Result;
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")));
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")));
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")));
if (LangOpts.ObjC)
Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")));
}
void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
AddObjCVisibilityResults(getLangOpts(), Results, false);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCAtStatement(Scope *S) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
AddObjCStatementResults(Results, false);
AddObjCExpressionResults(Results, false);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCAtExpression(Scope *S) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
AddObjCExpressionResults(Results, false);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
/// Determine whether the addition of the given flag to an Objective-C
/// property's attributes will cause a conflict.
static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
// Check if we've already added this flag.
if (Attributes & NewFlag)
return true;
Attributes |= NewFlag;
// Check for collisions with "readonly".
if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
(Attributes & ObjCDeclSpec::DQ_PR_readwrite))
return true;
// Check for more than one of { assign, copy, retain, strong, weak }.
unsigned AssignCopyRetMask =
Attributes &
(ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained |
ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain |
ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak);
if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
return true;
return false;
}
void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
if (!CodeCompleter)
return;
unsigned Attributes = ODS.getPropertyAttributes();
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
Results.AddResult(CodeCompletionResult("readonly"));
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
Results.AddResult(CodeCompletionResult("assign"));
if (!ObjCPropertyFlagConflicts(Attributes,
ObjCDeclSpec::DQ_PR_unsafe_unretained))
Results.AddResult(CodeCompletionResult("unsafe_unretained"));
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
Results.AddResult(CodeCompletionResult("readwrite"));
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
Results.AddResult(CodeCompletionResult("retain"));
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
Results.AddResult(CodeCompletionResult("strong"));
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
Results.AddResult(CodeCompletionResult("copy"));
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
Results.AddResult(CodeCompletionResult("nonatomic"));
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Results.AddResult(CodeCompletionResult("atomic"));
// Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Results.AddResult(CodeCompletionResult("weak"));
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
CodeCompletionBuilder Setter(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Setter.AddTypedTextChunk("setter");
Setter.AddTextChunk("=");
Setter.AddPlaceholderChunk("method");
Results.AddResult(CodeCompletionResult(Setter.TakeString()));
}
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
CodeCompletionBuilder Getter(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Getter.AddTypedTextChunk("getter");
Getter.AddTextChunk("=");
Getter.AddPlaceholderChunk("method");
Results.AddResult(CodeCompletionResult(Getter.TakeString()));
}
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
Results.AddResult(CodeCompletionResult("nonnull"));
Results.AddResult(CodeCompletionResult("nullable"));
Results.AddResult(CodeCompletionResult("null_unspecified"));
Results.AddResult(CodeCompletionResult("null_resettable"));
}
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
/// Describes the kind of Objective-C method that we want to find
/// via code completion.
enum ObjCMethodKind {
MK_Any, ///< Any kind of method, provided it means other specified criteria.
MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
MK_OneArgSelector ///< One-argument selector.
};
static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind,
ArrayRef<IdentifierInfo *> SelIdents,
bool AllowSameLength = true) {
unsigned NumSelIdents = SelIdents.size();
if (NumSelIdents > Sel.getNumArgs())
return false;
switch (WantKind) {
case MK_Any:
break;
case MK_ZeroArgSelector:
return Sel.isUnarySelector();
case MK_OneArgSelector:
return Sel.getNumArgs() == 1;
}
if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
return false;
for (unsigned I = 0; I != NumSelIdents; ++I)
if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
return false;
return true;
}
static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
ObjCMethodKind WantKind,
ArrayRef<IdentifierInfo *> SelIdents,
bool AllowSameLength = true) {
return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
AllowSameLength);
}
/// A set of selectors, which is used to avoid introducing multiple
/// completions with the same selector into the result set.
typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
/// Add all of the Objective-C methods in the given Objective-C
/// container to the set of results.
///
/// The container will be a class, protocol, category, or implementation of
/// any of the above. This mether will recurse to include methods from
/// the superclasses of classes along with their categories, protocols, and
/// implementations.
///
/// \param Container the container in which we'll look to find methods.
///
/// \param WantInstanceMethods Whether to add instance methods (only); if
/// false, this routine will add factory methods (only).
///
/// \param CurContext the context in which we're performing the lookup that
/// finds methods.
///
/// \param AllowSameLength Whether we allow a method to be added to the list
/// when it has the same number of parameters as we have selector identifiers.
///
/// \param Results the structure into which we'll add results.
static void AddObjCMethods(ObjCContainerDecl *Container,
bool WantInstanceMethods, ObjCMethodKind WantKind,
ArrayRef<IdentifierInfo *> SelIdents,
DeclContext *CurContext,
VisitedSelectorSet &Selectors, bool AllowSameLength,
ResultBuilder &Results, bool InOriginalClass = true,
bool IsRootClass = false) {
typedef CodeCompletionResult Result;
Container = getContainerDef(Container);
ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
for (ObjCMethodDecl *M : Container->methods()) {
// The instance methods on the root class can be messaged via the
// metaclass.
if (M->isInstanceMethod() == WantInstanceMethods ||
(IsRootClass && !WantInstanceMethods)) {
// Check whether the selector identifiers we've been given are a
// subset of the identifiers for this particular method.
if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
continue;
if (!Selectors.insert(M->getSelector()).second)
continue;
Result R = Result(M, Results.getBasePriority(M), nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = (WantKind != MK_Any);
if (!InOriginalClass)
setInBaseClass(R);
Results.MaybeAddResult(R, CurContext);
}
}
// Visit the protocols of protocols.
if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
if (Protocol->hasDefinition()) {
const ObjCList<ObjCProtocolDecl> &Protocols =
Protocol->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
I != E; ++I)
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
Selectors, AllowSameLength, Results, false, IsRootClass);
}
}
if (!IFace || !IFace->hasDefinition())
return;
// Add methods in protocols.
for (ObjCProtocolDecl *I : IFace->protocols())
AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
Selectors, AllowSameLength, Results, false, IsRootClass);
// Add methods in categories.
for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {
AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
CurContext, Selectors, AllowSameLength, Results,
InOriginalClass, IsRootClass);
// Add a categories protocol methods.
const ObjCList<ObjCProtocolDecl> &Protocols =
CatDecl->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
I != E; ++I)
AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
Selectors, AllowSameLength, Results, false, IsRootClass);
// Add methods in category implementations.
if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
Selectors, AllowSameLength, Results, InOriginalClass,
IsRootClass);
}
// Add methods in superclass.
// Avoid passing in IsRootClass since root classes won't have super classes.
if (IFace->getSuperClass())
AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
SelIdents, CurContext, Selectors, AllowSameLength, Results,
/*IsRootClass=*/false);
// Add methods in our implementation, if any.
if (ObjCImplementationDecl *Impl = IFace->getImplementation())
AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
Selectors, AllowSameLength, Results, InOriginalClass,
IsRootClass);
}
void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
// Try to find the interface where getters might live.
ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
if (!Class) {
if (ObjCCategoryDecl *Category =
dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Class = Category->getClassInterface();
if (!Class)
return;
}
// Find all of the potential getters.
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
VisitedSelectorSet Selectors;
AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
/*AllowSameLength=*/true, Results);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
// Try to find the interface where setters might live.
ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
if (!Class) {
if (ObjCCategoryDecl *Category =
dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Class = Category->getClassInterface();
if (!Class)
return;
}
// Find all of the potential getters.
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
VisitedSelectorSet Selectors;
AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors,
/*AllowSameLength=*/true, Results);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
bool IsParameter) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Type);
Results.EnterNewScope();
// Add context-sensitive, Objective-C parameter-passing keywords.
bool AddedInOut = false;
if ((DS.getObjCDeclQualifier() &
(ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
Results.AddResult("in");
Results.AddResult("inout");
AddedInOut = true;
}
if ((DS.getObjCDeclQualifier() &
(ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
Results.AddResult("out");
if (!AddedInOut)
Results.AddResult("inout");
}
if ((DS.getObjCDeclQualifier() &
(ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
ObjCDeclSpec::DQ_Oneway)) == 0) {
Results.AddResult("bycopy");
Results.AddResult("byref");
Results.AddResult("oneway");
}
if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
Results.AddResult("nonnull");
Results.AddResult("nullable");
Results.AddResult("null_unspecified");
}
// If we're completing the return type of an Objective-C method and the
// identifier IBAction refers to a macro, provide a completion item for
// an action, e.g.,
// IBAction)<#selector#>:(id)sender
if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
PP.isMacroDefined("IBAction")) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo(),
CCP_CodePattern, CXAvailability_Available);
Builder.AddTypedTextChunk("IBAction");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddPlaceholderChunk("selector");
Builder.AddChunk(CodeCompletionString::CK_Colon);
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("id");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("sender");
Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
// If we're completing the return type, provide 'instancetype'.
if (!IsParameter) {
Results.AddResult(CodeCompletionResult("instancetype"));
}
// Add various builtin type names and specifiers.
AddOrdinaryNameResults(PCC_Type, S, *this, Results);
Results.ExitScope();
// Add the various type names
Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
CodeCompleter->includeGlobals(),
CodeCompleter->loadExternal());
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
/// When we have an expression with type "id", we may assume
/// that it has some more-specific class type based on knowledge of
/// common uses of Objective-C. This routine returns that class type,
/// or NULL if no better result could be determined.
static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
if (!Msg)
return nullptr;
Selector Sel = Msg->getSelector();
if (Sel.isNull())
return nullptr;
IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
if (!Id)
return nullptr;
ObjCMethodDecl *Method = Msg->getMethodDecl();
if (!Method)
return nullptr;
// Determine the class that we're sending the message to.
ObjCInterfaceDecl *IFace = nullptr;
switch (Msg->getReceiverKind()) {
case ObjCMessageExpr::Class:
if (const ObjCObjectType *ObjType =
Msg->getClassReceiver()->getAs<ObjCObjectType>())
IFace = ObjType->getInterface();
break;
case ObjCMessageExpr::Instance: {
QualType T = Msg->getInstanceReceiver()->getType();
if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
IFace = Ptr->getInterfaceDecl();
break;
}
case ObjCMessageExpr::SuperInstance:
case ObjCMessageExpr::SuperClass:
break;
}
if (!IFace)
return nullptr;
ObjCInterfaceDecl *Super = IFace->getSuperClass();
if (Method->isInstanceMethod())
return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
.Case("retain", IFace)
.Case("strong", IFace)
.Case("autorelease", IFace)
.Case("copy", IFace)
.Case("copyWithZone", IFace)
.Case("mutableCopy", IFace)
.Case("mutableCopyWithZone", IFace)
.Case("awakeFromCoder", IFace)
.Case("replacementObjectFromCoder", IFace)
.Case("class", IFace)
.Case("classForCoder", IFace)
.Case("superclass", Super)
.Default(nullptr);
return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
.Case("new", IFace)
.Case("alloc", IFace)
.Case("allocWithZone", IFace)
.Case("class", IFace)
.Case("superclass", Super)
.Default(nullptr);
}
// Add a special completion for a message send to "super", which fills in the
// most likely case of forwarding all of our arguments to the superclass
// function.
///
/// \param S The semantic analysis object.
///
/// \param NeedSuperKeyword Whether we need to prefix this completion with
/// the "super" keyword. Otherwise, we just need to provide the arguments.
///
/// \param SelIdents The identifiers in the selector that have already been
/// provided as arguments for a send to "super".
///
/// \param Results The set of results to augment.
///
/// \returns the Objective-C method declaration that would be invoked by
/// this "super" completion. If NULL, no completion was added.
static ObjCMethodDecl *
AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
ArrayRef<IdentifierInfo *> SelIdents,
ResultBuilder &Results) {
ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
if (!CurMethod)
return nullptr;
ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
if (!Class)
return nullptr;
// Try to find a superclass method with the same selector.
ObjCMethodDecl *SuperMethod = nullptr;
while ((Class = Class->getSuperClass()) && !SuperMethod) {
// Check in the class
SuperMethod = Class->getMethod(CurMethod->getSelector(),
CurMethod->isInstanceMethod());
// Check in categories or class extensions.
if (!SuperMethod) {
for (const auto *Cat : Class->known_categories()) {
if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
CurMethod->isInstanceMethod())))
break;
}
}
}
if (!SuperMethod)
return nullptr;
// Check whether the superclass method has the same signature.
if (CurMethod->param_size() != SuperMethod->param_size() ||
CurMethod->isVariadic() != SuperMethod->isVariadic())
return nullptr;
for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
CurPEnd = CurMethod->param_end(),
SuperP = SuperMethod->param_begin();
CurP != CurPEnd; ++CurP, ++SuperP) {
// Make sure the parameter types are compatible.
if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
(*SuperP)->getType()))
return nullptr;
// Make sure we have a parameter name to forward!
if (!(*CurP)->getIdentifier())
return nullptr;
}
// We have a superclass method. Now, form the send-to-super completion.
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
// Give this completion a return type.
AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
Results.getCompletionContext().getBaseType(), Builder);
// If we need the "super" keyword, add it (plus some spacing).
if (NeedSuperKeyword) {
Builder.AddTypedTextChunk("super");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
}
Selector Sel = CurMethod->getSelector();
if (Sel.isUnarySelector()) {
if (NeedSuperKeyword)
Builder.AddTextChunk(
Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
else
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
} else {
ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
if (I > SelIdents.size())
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
if (I < SelIdents.size())
Builder.AddInformativeChunk(
Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
else if (NeedSuperKeyword || I > SelIdents.size()) {
Builder.AddTextChunk(
Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
(*CurP)->getIdentifier()->getName()));
} else {
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
(*CurP)->getIdentifier()->getName()));
}
}
}
Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
CCP_SuperCompletion));
return SuperMethod;
}
void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
typedef CodeCompletionResult Result;
ResultBuilder Results(
*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCMessageReceiver,
getLangOpts().CPlusPlus11
? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
: &ResultBuilder::IsObjCMessageReceiver);
CodeCompletionDeclConsumer Consumer(Results, CurContext);
Results.EnterNewScope();
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
CodeCompleter->includeGlobals(),
CodeCompleter->loadExternal());
// If we are in an Objective-C method inside a class that has a superclass,
// add "super" as an option.
if (ObjCMethodDecl *Method = getCurMethodDecl())
if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
if (Iface->getSuperClass()) {
Results.AddResult(Result("super"));
AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
}
if (getLangOpts().CPlusPlus11)
addThisCompletion(*this, Results);
Results.ExitScope();
if (CodeCompleter->includeMacros())
AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression) {
ObjCInterfaceDecl *CDecl = nullptr;
if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
// Figure out which interface we're in.
CDecl = CurMethod->getClassInterface();
if (!CDecl)
return;
// Find the superclass of this class.
CDecl = CDecl->getSuperClass();
if (!CDecl)
return;
if (CurMethod->isInstanceMethod()) {
// We are inside an instance method, which means that the message
// send [super ...] is actually calling an instance method on the
// current object.
return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
AtArgumentExpression, CDecl);
}
// Fall through to send to the superclass in CDecl.
} else {
// "super" may be the name of a type or variable. Figure out which
// it is.
IdentifierInfo *Super = getSuperIdentifier();
NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName);
if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
// "super" names an interface. Use it.
} else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
if (const ObjCObjectType *Iface =
Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
CDecl = Iface->getInterface();
} else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
// "super" names an unresolved type; we can't be more specific.
} else {
// Assume that "super" names some kind of value and parse that way.
CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
UnqualifiedId id;
id.setIdentifier(Super, SuperLoc);
ExprResult SuperExpr =
ActOnIdExpression(S, SS, TemplateKWLoc, id, false, false);
return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
SelIdents, AtArgumentExpression);
}
// Fall through
}
ParsedType Receiver;
if (CDecl)
Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
AtArgumentExpression,
/*IsSuper=*/true);
}
/// Given a set of code-completion results for the argument of a message
/// send, determine the preferred type (if any) for that argument expression.
static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
unsigned NumSelIdents) {
typedef CodeCompletionResult Result;
ASTContext &Context = Results.getSema().Context;
QualType PreferredType;
unsigned BestPriority = CCP_Unlikely * 2;
Result *ResultsData = Results.data();
for (unsigned I = 0, N = Results.size(); I != N; ++I) {
Result &R = ResultsData[I];
if (R.Kind == Result::RK_Declaration &&
isa<ObjCMethodDecl>(R.Declaration)) {
if (R.Priority <= BestPriority) {
const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
if (NumSelIdents <= Method->param_size()) {
QualType MyPreferredType =
Method->parameters()[NumSelIdents - 1]->getType();
if (R.Priority < BestPriority || PreferredType.isNull()) {
BestPriority = R.Priority;
PreferredType = MyPreferredType;
} else if (!Context.hasSameUnqualifiedType(PreferredType,
MyPreferredType)) {
PreferredType = QualType();
}
}
}
}
}
return PreferredType;
}
static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
ParsedType Receiver,
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression, bool IsSuper,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
ObjCInterfaceDecl *CDecl = nullptr;
// If the given name refers to an interface type, retrieve the
// corresponding declaration.
if (Receiver) {
QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
if (!T.isNull())
if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
CDecl = Interface->getInterface();
}
// Add all of the factory methods in this Objective-C class, its protocols,
// superclasses, categories, implementation, etc.
Results.EnterNewScope();
// If this is a send-to-super, try to add the special "super" send
// completion.
if (IsSuper) {
if (ObjCMethodDecl *SuperMethod =
AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Results.Ignore(SuperMethod);
}
// If we're inside an Objective-C method definition, prefer its selector to
// others.
if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Results.setPreferredSelector(CurMethod->getSelector());
VisitedSelectorSet Selectors;
if (CDecl)
AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,
Selectors, AtArgumentExpression, Results);
else {
// We're messaging "id" as a type; provide all class/factory methods.
// If we have an external source, load the entire class method
// pool from the AST file.
if (SemaRef.getExternalSource()) {
for (uint32_t I = 0,
N = SemaRef.getExternalSource()->GetNumExternalSelectors();
I != N; ++I) {
Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
continue;
SemaRef.ReadMethodPool(Sel);
}
}
for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
MEnd = SemaRef.MethodPool.end();
M != MEnd; ++M) {
for (ObjCMethodList *MethList = &M->second.second;
MethList && MethList->getMethod(); MethList = MethList->getNext()) {
if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
Result R(MethList->getMethod(),
Results.getBasePriority(MethList->getMethod()), nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
Results.MaybeAddResult(R, SemaRef.CurContext);
}
}
}
Results.ExitScope();
}
void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
bool IsSuper) {
QualType T = this->GetTypeFromParser(Receiver);
ResultBuilder Results(
*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,
SelIdents));
AddClassMessageCompletions(*this, S, Receiver, SelIdents,
AtArgumentExpression, IsSuper, Results);
// If we're actually at the argument expression (rather than prior to the
// selector), we're actually performing code completion for an expression.
// Determine whether we have a single, best method. If so, we can
// code-complete the expression using the corresponding parameter type as
// our preferred type, improving completion results.
if (AtArgumentExpression) {
QualType PreferredType =
getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
if (PreferredType.isNull())
CodeCompleteOrdinaryName(S, PCC_Expression);
else
CodeCompleteExpression(S, PreferredType);
return;
}
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
ArrayRef<IdentifierInfo *> SelIdents,
bool AtArgumentExpression,
ObjCInterfaceDecl *Super) {
typedef CodeCompletionResult Result;
Expr *RecExpr = static_cast<Expr *>(Receiver);
// If necessary, apply function/array conversion to the receiver.
// C99 6.7.5.3p[7,8].
if (RecExpr) {
ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
if (Conv.isInvalid()) // conversion failed. bail.
return;
RecExpr = Conv.get();
}
QualType ReceiverType = RecExpr
? RecExpr->getType()
: Super ? Context.getObjCObjectPointerType(
Context.getObjCInterfaceType(Super))
: Context.getObjCIdType();
// If we're messaging an expression with type "id" or "Class", check
// whether we know something special about the receiver that allows
// us to assume a more-specific receiver type.
if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
if (ReceiverType->isObjCClassType())
return CodeCompleteObjCClassMessage(
S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents,
AtArgumentExpression, Super);
ReceiverType =
Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace));
}
} else if (RecExpr && getLangOpts().CPlusPlus) {
ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
if (Conv.isUsable()) {
RecExpr = Conv.get();
ReceiverType = RecExpr->getType();
}
}
// Build the set of methods we can see.
ResultBuilder Results(
*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
ReceiverType, SelIdents));
Results.EnterNewScope();
// If this is a send-to-super, try to add the special "super" send
// completion.
if (Super) {
if (ObjCMethodDecl *SuperMethod =
AddSuperSendCompletion(*this, false, SelIdents, Results))
Results.Ignore(SuperMethod);
}
// If we're inside an Objective-C method definition, prefer its selector to
// others.
if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
Results.setPreferredSelector(CurMethod->getSelector());
// Keep track of the selectors we've already added.
VisitedSelectorSet Selectors;
// Handle messages to Class. This really isn't a message to an instance
// method, so we treat it the same way we would treat a message send to a
// class method.
if (ReceiverType->isObjCClassType() ||
ReceiverType->isObjCQualifiedClassType()) {
if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext,
Selectors, AtArgumentExpression, Results);
}
}
// Handle messages to a qualified ID ("id<foo>").
else if (const ObjCObjectPointerType *QualID =
ReceiverType->getAsObjCQualifiedIdType()) {
// Search protocols for instance methods.
for (auto *I : QualID->quals())
AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
AtArgumentExpression, Results);
}
// Handle messages to a pointer to interface type.
else if (const ObjCObjectPointerType *IFacePtr =
ReceiverType->getAsObjCInterfacePointerType()) {
// Search the class, its superclasses, etc., for instance methods.
AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
CurContext, Selectors, AtArgumentExpression, Results);
// Search protocols for instance methods.
for (auto *I : IFacePtr->quals())
AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
AtArgumentExpression, Results);
}
// Handle messages to "id".
else if (ReceiverType->isObjCIdType()) {
// We're messaging "id", so provide all instance methods we know
// about as code-completion results.
// If we have an external source, load the entire class method
// pool from the AST file.
if (ExternalSource) {
for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
I != N; ++I) {
Selector Sel = ExternalSource->GetExternalSelector(I);
if (Sel.isNull() || MethodPool.count(Sel))
continue;
ReadMethodPool(Sel);
}
}
for (GlobalMethodPool::iterator M = MethodPool.begin(),
MEnd = MethodPool.end();
M != MEnd; ++M) {
for (ObjCMethodList *MethList = &M->second.first;
MethList && MethList->getMethod(); MethList = MethList->getNext()) {
if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
continue;
Result R(MethList->getMethod(),
Results.getBasePriority(MethList->getMethod()), nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
Results.MaybeAddResult(R, CurContext);
}
}
}
Results.ExitScope();
// If we're actually at the argument expression (rather than prior to the
// selector), we're actually performing code completion for an expression.
// Determine whether we have a single, best method. If so, we can
// code-complete the expression using the corresponding parameter type as
// our preferred type, improving completion results.
if (AtArgumentExpression) {
QualType PreferredType =
getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
if (PreferredType.isNull())
CodeCompleteOrdinaryName(S, PCC_Expression);
else
CodeCompleteExpression(S, PreferredType);
return;
}
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCForCollection(Scope *S,
DeclGroupPtrTy IterationVar) {
CodeCompleteExpressionData Data;
Data.ObjCCollection = true;
if (IterationVar.getAsOpaquePtr()) {
DeclGroupRef DG = IterationVar.get();
for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
if (*I)
Data.IgnoreDecls.push_back(*I);
}
}
CodeCompleteExpression(S, Data);
}
void Sema::CodeCompleteObjCSelector(Scope *S,
ArrayRef<IdentifierInfo *> SelIdents) {
// If we have an external source, load the entire class method
// pool from the AST file.
if (ExternalSource) {
for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
++I) {
Selector Sel = ExternalSource->GetExternalSelector(I);
if (Sel.isNull() || MethodPool.count(Sel))
continue;
ReadMethodPool(Sel);
}
}
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_SelectorName);
Results.EnterNewScope();
for (GlobalMethodPool::iterator M = MethodPool.begin(),
MEnd = MethodPool.end();
M != MEnd; ++M) {
Selector Sel = M->first;
if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
continue;
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
if (Sel.isUnarySelector()) {
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Results.AddResult(Builder.TakeString());
continue;
}
std::string Accumulator;
for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
if (I == SelIdents.size()) {
if (!Accumulator.empty()) {
Builder.AddInformativeChunk(
Builder.getAllocator().CopyString(Accumulator));
Accumulator.clear();
}
}
Accumulator += Sel.getNameForSlot(I);
Accumulator += ':';
}
Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator));
Results.AddResult(Builder.TakeString());
}
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
/// Add all of the protocol declarations that we find in the given
/// (translation unit) context.
static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
bool OnlyForwardDeclarations,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
for (const auto *D : Ctx->decls()) {
// Record any protocols we find.
if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Results.AddResult(
Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,
nullptr, false);
}
}
void Sema::CodeCompleteObjCProtocolReferences(
ArrayRef<IdentifierLocPair> Protocols) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCProtocolName);
if (CodeCompleter->includeGlobals()) {
Results.EnterNewScope();
// Tell the result set to ignore all of the protocols we have
// already seen.
// FIXME: This doesn't work when caching code-completion results.
for (const IdentifierLocPair &Pair : Protocols)
if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second))
Results.Ignore(Protocol);
// Add all protocols.
AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
Results);
Results.ExitScope();
}
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCProtocolName);
if (CodeCompleter->includeGlobals()) {
Results.EnterNewScope();
// Add all protocols.
AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
Results);
Results.ExitScope();
}
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
/// Add all of the Objective-C interface declarations that we find in
/// the given (translation unit) context.
static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
bool OnlyForwardDeclarations,
bool OnlyUnimplemented,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;
for (const auto *D : Ctx->decls()) {
// Record any interfaces we find.
if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
(!OnlyUnimplemented || !Class->getImplementation()))
Results.AddResult(
Result(Class, Results.getBasePriority(Class), nullptr), CurContext,
nullptr, false);
}
}
void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCInterfaceName);
Results.EnterNewScope();
if (CodeCompleter->includeGlobals()) {
// Add all classes.
AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
false, Results);
}
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
SourceLocation ClassNameLoc) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCInterfaceName);
Results.EnterNewScope();
// Make sure that we ignore the class we're currently defining.
NamedDecl *CurClass =
LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Results.Ignore(CurClass);
if (CodeCompleter->includeGlobals()) {
// Add all classes.
AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
false, Results);
}
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCImplementation);
Results.EnterNewScope();
if (CodeCompleter->includeGlobals()) {
// Add all unimplemented classes.
AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
true, Results);
}
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
IdentifierInfo *ClassName,
SourceLocation ClassNameLoc) {
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCCategoryName);
// Ignore any categories we find that have already been implemented by this
// interface.
llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
NamedDecl *CurClass =
LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
if (ObjCInterfaceDecl *Class =
dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) {
for (const auto *Cat : Class->visible_categories())
CategoryNames.insert(Cat->getIdentifier());
}
// Add all of the categories we know about.
Results.EnterNewScope();
TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
for (const auto *D : TU->decls())
if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
if (CategoryNames.insert(Category->getIdentifier()).second)
Results.AddResult(
Result(Category, Results.getBasePriority(Category), nullptr),
CurContext, nullptr, false);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
IdentifierInfo *ClassName,
SourceLocation ClassNameLoc) {
typedef CodeCompletionResult Result;
// Find the corresponding interface. If we couldn't find the interface, the
// program itself is ill-formed. However, we'll try to be helpful still by
// providing the list of all of the categories we know about.
NamedDecl *CurClass =
LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
if (!Class)
return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_ObjCCategoryName);
// Add all of the categories that have have corresponding interface
// declarations in this class and any of its superclasses, except for
// already-implemented categories in the class itself.
llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
Results.EnterNewScope();
bool IgnoreImplemented = true;
while (Class) {
for (const auto *Cat : Class->visible_categories()) {
if ((!IgnoreImplemented || !Cat->getImplementation()) &&
CategoryNames.insert(Cat->getIdentifier()).second)
Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
CurContext, nullptr, false);
}
Class = Class->getSuperClass();
IgnoreImplemented = false;
}
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(), CCContext);
// Figure out where this @synthesize lives.
ObjCContainerDecl *Container =
dyn_cast_or_null<ObjCContainerDecl>(CurContext);
if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
!isa<ObjCCategoryImplDecl>(Container)))
return;
// Ignore any properties that have already been implemented.
Container = getContainerDef(Container);
for (const auto *D : Container->decls())
if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Results.Ignore(PropertyImpl->getPropertyDecl());
// Add any properties that we find.
AddedPropertiesSet AddedProperties;
Results.EnterNewScope();
if (ObjCImplementationDecl *ClassImpl =
dyn_cast<ObjCImplementationDecl>(Container))
AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
/*AllowNullaryMethods=*/false, CurContext,
AddedProperties, Results);
else
AddObjCProperties(CCContext,
cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
false, /*AllowNullaryMethods=*/false, CurContext,
AddedProperties, Results);
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCPropertySynthesizeIvar(
Scope *S, IdentifierInfo *PropertyName) {
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
// Figure out where this @synthesize lives.
ObjCContainerDecl *Container =
dyn_cast_or_null<ObjCContainerDecl>(CurContext);
if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
!isa<ObjCCategoryImplDecl>(Container)))
return;
// Figure out which interface we're looking into.
ObjCInterfaceDecl *Class = nullptr;
if (ObjCImplementationDecl *ClassImpl =
dyn_cast<ObjCImplementationDecl>(Container))
Class = ClassImpl->getClassInterface();
else
Class = cast<ObjCCategoryImplDecl>(Container)
->getCategoryDecl()
->getClassInterface();
// Determine the type of the property we're synthesizing.
QualType PropertyType = Context.getObjCIdType();
if (Class) {
if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
PropertyType =
Property->getType().getNonReferenceType().getUnqualifiedType();
// Give preference to ivars
Results.setPreferredType(PropertyType);
}
}
// Add all of the instance variables in this class and its superclasses.
Results.EnterNewScope();
bool SawSimilarlyNamedIvar = false;
std::string NameWithPrefix;
NameWithPrefix += '_';
NameWithPrefix += PropertyName->getName();
std::string NameWithSuffix = PropertyName->getName().str();
NameWithSuffix += '_';
for (; Class; Class = Class->getSuperClass()) {
for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Ivar = Ivar->getNextIvar()) {
Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
CurContext, nullptr, false);
// Determine whether we've seen an ivar with a name similar to the
// property.
if ((PropertyName == Ivar->getIdentifier() ||
NameWithPrefix == Ivar->getName() ||
NameWithSuffix == Ivar->getName())) {
SawSimilarlyNamedIvar = true;
// Reduce the priority of this result by one, to give it a slight
// advantage over other results whose names don't match so closely.
if (Results.size() &&
Results.data()[Results.size() - 1].Kind ==
CodeCompletionResult::RK_Declaration &&
Results.data()[Results.size() - 1].Declaration == Ivar)
Results.data()[Results.size() - 1].Priority--;
}
}
}
if (!SawSimilarlyNamedIvar) {
// Create ivar result _propName, that the user can use to synthesize
// an ivar of the appropriate type.
unsigned Priority = CCP_MemberDeclaration + 1;
typedef CodeCompletionResult Result;
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
Priority, CXAvailability_Available);
PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Builder.AddResultTypeChunk(
GetCompletionTypeString(PropertyType, Context, Policy, Allocator));
Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Results.AddResult(
Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl));
}
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
// Mapping from selectors to the methods that implement that selector, along
// with the "in original class" flag.
typedef llvm::DenseMap<Selector,
llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>>
KnownMethodsMap;
/// Find all of the methods that reside in the given container
/// (and its superclasses, protocols, etc.) that meet the given
/// criteria. Insert those methods into the map of known methods,
/// indexed by selector so they can be easily found.
static void FindImplementableMethods(ASTContext &Context,
ObjCContainerDecl *Container,
Optional<bool> WantInstanceMethods,
QualType ReturnType,
KnownMethodsMap &KnownMethods,
bool InOriginalClass = true) {
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
// Make sure we have a definition; that's what we'll walk.
if (!IFace->hasDefinition())
return;
IFace = IFace->getDefinition();
Container = IFace;
const ObjCList<ObjCProtocolDecl> &Protocols =
IFace->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
I != E; ++I)
FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
KnownMethods, InOriginalClass);
// Add methods from any class extensions and categories.
for (auto *Cat : IFace->visible_categories()) {
FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
KnownMethods, false);
}
// Visit the superclass.
if (IFace->getSuperClass())
FindImplementableMethods(Context, IFace->getSuperClass(),
WantInstanceMethods, ReturnType, KnownMethods,
false);
}
if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
// Recurse into protocols.
const ObjCList<ObjCProtocolDecl> &Protocols =
Category->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
I != E; ++I)
FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
KnownMethods, InOriginalClass);
// If this category is the original class, jump to the interface.
if (InOriginalClass && Category->getClassInterface())
FindImplementableMethods(Context, Category->getClassInterface(),
WantInstanceMethods, ReturnType, KnownMethods,
false);
}
if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
// Make sure we have a definition; that's what we'll walk.
if (!Protocol->hasDefinition())
return;
Protocol = Protocol->getDefinition();
Container = Protocol;
// Recurse into protocols.
const ObjCList<ObjCProtocolDecl> &Protocols =
Protocol->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
I != E; ++I)
FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
KnownMethods, false);
}
// Add methods in this container. This operation occurs last because
// we want the methods from this container to override any methods
// we've previously seen with the same selector.
for (auto *M : Container->methods()) {
if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
if (!ReturnType.isNull() &&
!Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
continue;
KnownMethods[M->getSelector()] =
KnownMethodsMap::mapped_type(M, InOriginalClass);
}
}
}
/// Add the parenthesized return or parameter type chunk to a code
/// completion string.
static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals,
ASTContext &Context,
const PrintingPolicy &Policy,
CodeCompletionBuilder &Builder) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
if (!Quals.empty())
Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Builder.AddTextChunk(
GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator()));
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
/// Determine whether the given class is or inherits from a class by
/// the given name.
static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) {
if (!Class)
return false;
if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
return true;
return InheritsFromClassNamed(Class->getSuperClass(), Name);
}
/// Add code completions for Objective-C Key-Value Coding (KVC) and
/// Key-Value Observing (KVO).
static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
bool IsInstanceMethod,
QualType ReturnType, ASTContext &Context,
VisitedSelectorSet &KnownSelectors,
ResultBuilder &Results) {
IdentifierInfo *PropName = Property->getIdentifier();
if (!PropName || PropName->getLength() == 0)
return;
PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
// Builder that will create each code completion.
typedef CodeCompletionResult Result;
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
// The selector table.
SelectorTable &Selectors = Context.Selectors;
// The property name, copied into the code completion allocation region
// on demand.
struct KeyHolder {
CodeCompletionAllocator &Allocator;
StringRef Key;
const char *CopiedKey;
KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
: Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
operator const char *() {
if (CopiedKey)
return CopiedKey;
return CopiedKey = Allocator.CopyString(Key);
}
} Key(Allocator, PropName->getName());
// The uppercased name of the property name.
std::string UpperKey = PropName->getName();
if (!UpperKey.empty())
UpperKey[0] = toUppercase(UpperKey[0]);
bool ReturnTypeMatchesProperty =
ReturnType.isNull() ||
Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
Property->getType());
bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType();
// Add the normal accessor -(type)key.
if (IsInstanceMethod &&
KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
if (ReturnType.isNull())
AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
Builder);
Builder.AddTypedTextChunk(Key);
Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCInstanceMethodDecl));
}
// If we have an integral or boolean property (or the user has provided
// an integral or boolean return type), add the accessor -(type)isKey.
if (IsInstanceMethod &&
((!ReturnType.isNull() &&
(ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
(ReturnType.isNull() && (Property->getType()->isIntegerType() ||
Property->getType()->isBooleanType())))) {
std::string SelectorName = (Twine("is") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
.second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("BOOL");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCInstanceMethodDecl));
}
}
// Add the normal mutator.
if (IsInstanceMethod && ReturnTypeMatchesVoid &&
!Property->getSetterMethodDecl()) {
std::string SelectorName = (Twine("set") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Builder.AddTypedTextChunk(":");
AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
Builder);
Builder.AddTextChunk(Key);
Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCInstanceMethodDecl));
}
}
// Indexed and unordered accessors
unsigned IndexedGetterPriority = CCP_CodePattern;
unsigned IndexedSetterPriority = CCP_CodePattern;
unsigned UnorderedGetterPriority = CCP_CodePattern;
unsigned UnorderedSetterPriority = CCP_CodePattern;
if (const auto *ObjCPointer =
Property->getType()->getAs<ObjCObjectPointerType>()) {
if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
// If this interface type is not provably derived from a known
// collection, penalize the corresponding completions.
if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
if (!InheritsFromClassNamed(IFace, "NSArray"))
IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
}
if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
if (!InheritsFromClassNamed(IFace, "NSSet"))
UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
}
}
} else {
IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
}
// Add -(NSUInteger)countOf<key>
if (IsInstanceMethod &&
(ReturnType.isNull() || ReturnType->isIntegerType())) {
std::string SelectorName = (Twine("countOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
.second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSUInteger");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Results.AddResult(
Result(Builder.TakeString(),
std::min(IndexedGetterPriority, UnorderedGetterPriority),
CXCursor_ObjCInstanceMethodDecl));
}
}
// Indexed getters
// Add -(id)objectInKeyAtIndex:(NSUInteger)index
if (IsInstanceMethod &&
(ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("id");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSUInteger");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("index");
Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
if (IsInstanceMethod &&
(ReturnType.isNull() ||
(ReturnType->isObjCObjectPointerType() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
ReturnType->getAs<ObjCObjectPointerType>()
->getInterfaceDecl()
->getName() == "NSArray"))) {
std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSArray *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSIndexSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("indexes");
Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// Add -(void)getKey:(type **)buffer range:(NSRange)inRange
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("get") + UpperKey).str();
IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
&Context.Idents.get("range")};
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("object-type");
Builder.AddTextChunk(" **");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("buffer");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTypedTextChunk("range:");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSRange");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("inRange");
Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// Mutable indexed accessors
// - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"),
&Context.Idents.get(SelectorName)};
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk("insertObject:");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("object-type");
Builder.AddTextChunk(" *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("object");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("NSUInteger");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("index");
Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("insert") + UpperKey).str();
IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
&Context.Idents.get("atIndexes")};
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSArray *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("array");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTypedTextChunk("atIndexes:");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("NSIndexSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("indexes");
Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName =
(Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSUInteger");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("index");
Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSIndexSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("indexes");
Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName =
(Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
&Context.Idents.get("withObject")};
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("NSUInteger");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("index");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTypedTextChunk("withObject:");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("id");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("object");
Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName1 =
(Twine("replace") + UpperKey + "AtIndexes").str();
std::string SelectorName2 = (Twine("with") + UpperKey).str();
IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1),
&Context.Idents.get(SelectorName2)};
if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("NSIndexSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("indexes");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSArray *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("array");
Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// Unordered getters
// - (NSEnumerator *)enumeratorOfKey
if (IsInstanceMethod &&
(ReturnType.isNull() ||
(ReturnType->isObjCObjectPointerType() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
ReturnType->getAs<ObjCObjectPointerType>()
->getInterfaceDecl()
->getName() == "NSEnumerator"))) {
std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
.second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSEnumerator *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// - (type *)memberOfKey:(type *)object
if (IsInstanceMethod &&
(ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
std::string SelectorName = (Twine("memberOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("object-type");
Builder.AddTextChunk(" *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
if (ReturnType.isNull()) {
Builder.AddPlaceholderChunk("object-type");
Builder.AddTextChunk(" *");
} else {
Builder.AddTextChunk(GetCompletionTypeString(
ReturnType, Context, Policy, Builder.getAllocator()));
}
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("object");
Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// Mutable unordered accessors
// - (void)addKeyObject:(type *)object
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName =
(Twine("add") + UpperKey + Twine("Object")).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("object-type");
Builder.AddTextChunk(" *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("object");
Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// - (void)addKey:(NSSet *)objects
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("add") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("objects");
Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// - (void)removeKeyObject:(type *)object
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName =
(Twine("remove") + UpperKey + Twine("Object")).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("object-type");
Builder.AddTextChunk(" *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("object");
Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// - (void)removeKey:(NSSet *)objects
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("remove") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("objects");
Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// - (void)intersectKey:(NSSet *)objects
if (IsInstanceMethod && ReturnTypeMatchesVoid) {
std::string SelectorName = (Twine("intersect") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("void");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSSet *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Builder.AddTextChunk("objects");
Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
CXCursor_ObjCInstanceMethodDecl));
}
}
// Key-Value Observing
// + (NSSet *)keyPathsForValuesAffectingKey
if (!IsInstanceMethod &&
(ReturnType.isNull() ||
(ReturnType->isObjCObjectPointerType() &&
ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
ReturnType->getAs<ObjCObjectPointerType>()
->getInterfaceDecl()
->getName() == "NSSet"))) {
std::string SelectorName =
(Twine("keyPathsForValuesAffecting") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
.second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("NSSet<NSString *> *");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCClassMethodDecl));
}
}
// + (BOOL)automaticallyNotifiesObserversForKey
if (!IsInstanceMethod &&
(ReturnType.isNull() || ReturnType->isIntegerType() ||
ReturnType->isBooleanType())) {
std::string SelectorName =
(Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
.second) {
if (ReturnType.isNull()) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddTextChunk("BOOL");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
}
Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
CXCursor_ObjCClassMethodDecl));
}
}
}
void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
ParsedType ReturnTy) {
// Determine the return type of the method we're declaring, if
// provided.
QualType ReturnType = GetTypeFromParser(ReturnTy);
Decl *IDecl = nullptr;
if (CurContext->isObjCContainer()) {
ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
IDecl = OCD;
}
// Determine where we should start searching for methods.
ObjCContainerDecl *SearchDecl = nullptr;
bool IsInImplementation = false;
if (Decl *D = IDecl) {
if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
SearchDecl = Impl->getClassInterface();
IsInImplementation = true;
} else if (ObjCCategoryImplDecl *CatImpl =
dyn_cast<ObjCCategoryImplDecl>(D)) {
SearchDecl = CatImpl->getCategoryDecl();
IsInImplementation = true;
} else
SearchDecl = dyn_cast<ObjCContainerDecl>(D);
}
if (!SearchDecl && S) {
if (DeclContext *DC = S->getEntity())
SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
}
if (!SearchDecl) {
HandleCodeCompleteResults(this, CodeCompleter,
CodeCompletionContext::CCC_Other, nullptr, 0);
return;
}
// Find all of the methods that we could declare/implement here.
KnownMethodsMap KnownMethods;
FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType,
KnownMethods);
// Add declarations or definitions for each of the known methods.
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
for (KnownMethodsMap::iterator M = KnownMethods.begin(),
MEnd = KnownMethods.end();
M != MEnd; ++M) {
ObjCMethodDecl *Method = M->second.getPointer();
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
// Add the '-'/'+' prefix if it wasn't provided yet.
if (!IsInstanceMethod) {
Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
}
// If the result type was not already provided, add it to the
// pattern as (type).
if (ReturnType.isNull()) {
QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
AttributedType::stripOuterNullability(ResTy);
AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context,
Policy, Builder);
}
Selector Sel = Method->getSelector();
// Add the first part of the selector to the pattern.
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
// Add parameters to the pattern.
unsigned I = 0;
for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
PEnd = Method->param_end();
P != PEnd; (void)++P, ++I) {
// Add the part of the selector name.
if (I == 0)
Builder.AddTypedTextChunk(":");
else if (I < Sel.getNumArgs()) {
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
} else
break;
// Add the parameter type.
QualType ParamType;
if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
ParamType = (*P)->getType();
else
ParamType = (*P)->getOriginalType();
ParamType = ParamType.substObjCTypeArgs(
Context, {}, ObjCSubstitutionContext::Parameter);
AttributedType::stripOuterNullability(ParamType);
AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context,
Policy, Builder);
if (IdentifierInfo *Id = (*P)->getIdentifier())
Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName()));
}
if (Method->isVariadic()) {
if (Method->param_size() > 0)
Builder.AddChunk(CodeCompletionString::CK_Comma);
Builder.AddTextChunk("...");
}
if (IsInImplementation && Results.includeCodePatterns()) {
// We will be defining the method here, so add a compound statement.
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
if (!Method->getReturnType()->isVoidType()) {
// If the result type is not void, add a return clause.
Builder.AddTextChunk("return");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("expression");
Builder.AddChunk(CodeCompletionString::CK_SemiColon);
} else
Builder.AddPlaceholderChunk("statements");
Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Builder.AddChunk(CodeCompletionString::CK_RightBrace);
}
unsigned Priority = CCP_CodePattern;
auto R = Result(Builder.TakeString(), Method, Priority);
if (!M->second.getInt())
setInBaseClass(R);
Results.AddResult(std::move(R));
}
// Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
// the properties in this class and its categories.
if (Context.getLangOpts().ObjC) {
SmallVector<ObjCContainerDecl *, 4> Containers;
Containers.push_back(SearchDecl);
VisitedSelectorSet KnownSelectors;
for (KnownMethodsMap::iterator M = KnownMethods.begin(),
MEnd = KnownMethods.end();
M != MEnd; ++M)
KnownSelectors.insert(M->first);
ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
if (!IFace)
if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
IFace = Category->getClassInterface();
if (IFace)
for (auto *Cat : IFace->visible_categories())
Containers.push_back(Cat);
if (IsInstanceMethod) {
for (unsigned I = 0, N = Containers.size(); I != N; ++I)
for (auto *P : Containers[I]->instance_properties())
AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
KnownSelectors, Results);
}
}
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteObjCMethodDeclSelector(
Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy,
ArrayRef<IdentifierInfo *> SelIdents) {
// If we have an external source, load the entire class method
// pool from the AST file.
if (ExternalSource) {
for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
++I) {
Selector Sel = ExternalSource->GetExternalSelector(I);
if (Sel.isNull() || MethodPool.count(Sel))
continue;
ReadMethodPool(Sel);
}
}
// Build the set of methods we can see.
typedef CodeCompletionResult Result;
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
if (ReturnTy)
Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Results.EnterNewScope();
for (GlobalMethodPool::iterator M = MethodPool.begin(),
MEnd = MethodPool.end();
M != MEnd; ++M) {
for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first
: &M->second.second;
MethList && MethList->getMethod(); MethList = MethList->getNext()) {
if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
continue;
if (AtParameterName) {
// Suggest parameter names we've seen before.
unsigned NumSelIdents = SelIdents.size();
if (NumSelIdents &&
NumSelIdents <= MethList->getMethod()->param_size()) {
ParmVarDecl *Param =
MethList->getMethod()->parameters()[NumSelIdents - 1];
if (Param->getIdentifier()) {
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Param->getIdentifier()->getName()));
Results.AddResult(Builder.TakeString());
}
}
continue;
}
Result R(MethList->getMethod(),
Results.getBasePriority(MethList->getMethod()), nullptr);
R.StartParameter = SelIdents.size();
R.AllParametersAreInformative = false;
R.DeclaringEntity = true;
Results.MaybeAddResult(R, CurContext);
}
}
Results.ExitScope();
if (!AtParameterName && !SelIdents.empty() &&
SelIdents.front()->getName().startswith("init")) {
for (const auto &M : PP.macros()) {
if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
continue;
Results.EnterNewScope();
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString(M.first->getName()));
Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
CXCursor_MacroDefinition));
Results.ExitScope();
}
}
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_PreprocessorDirective);
Results.EnterNewScope();
// #if <condition>
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Builder.AddTypedTextChunk("if");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("condition");
Results.AddResult(Builder.TakeString());
// #ifdef <macro>
Builder.AddTypedTextChunk("ifdef");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("macro");
Results.AddResult(Builder.TakeString());
// #ifndef <macro>
Builder.AddTypedTextChunk("ifndef");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("macro");
Results.AddResult(Builder.TakeString());
if (InConditional) {
// #elif <condition>
Builder.AddTypedTextChunk("elif");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("condition");
Results.AddResult(Builder.TakeString());
// #else
Builder.AddTypedTextChunk("else");
Results.AddResult(Builder.TakeString());
// #endif
Builder.AddTypedTextChunk("endif");
Results.AddResult(Builder.TakeString());
}
// #include "header"
Builder.AddTypedTextChunk("include");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTextChunk("\"");
Builder.AddPlaceholderChunk("header");
Builder.AddTextChunk("\"");
Results.AddResult(Builder.TakeString());
// #include <header>
Builder.AddTypedTextChunk("include");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTextChunk("<");
Builder.AddPlaceholderChunk("header");
Builder.AddTextChunk(">");
Results.AddResult(Builder.TakeString());
// #define <macro>
Builder.AddTypedTextChunk("define");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("macro");
Results.AddResult(Builder.TakeString());
// #define <macro>(<args>)
Builder.AddTypedTextChunk("define");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("macro");
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("args");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Builder.TakeString());
// #undef <macro>
Builder.AddTypedTextChunk("undef");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("macro");
Results.AddResult(Builder.TakeString());
// #line <number>
Builder.AddTypedTextChunk("line");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("number");
Results.AddResult(Builder.TakeString());
// #line <number> "filename"
Builder.AddTypedTextChunk("line");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("number");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTextChunk("\"");
Builder.AddPlaceholderChunk("filename");
Builder.AddTextChunk("\"");
Results.AddResult(Builder.TakeString());
// #error <message>
Builder.AddTypedTextChunk("error");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("message");
Results.AddResult(Builder.TakeString());
// #pragma <arguments>
Builder.AddTypedTextChunk("pragma");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("arguments");
Results.AddResult(Builder.TakeString());
if (getLangOpts().ObjC) {
// #import "header"
Builder.AddTypedTextChunk("import");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTextChunk("\"");
Builder.AddPlaceholderChunk("header");
Builder.AddTextChunk("\"");
Results.AddResult(Builder.TakeString());
// #import <header>
Builder.AddTypedTextChunk("import");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTextChunk("<");
Builder.AddPlaceholderChunk("header");
Builder.AddTextChunk(">");
Results.AddResult(Builder.TakeString());
}
// #include_next "header"
Builder.AddTypedTextChunk("include_next");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTextChunk("\"");
Builder.AddPlaceholderChunk("header");
Builder.AddTextChunk("\"");
Results.AddResult(Builder.TakeString());
// #include_next <header>
Builder.AddTypedTextChunk("include_next");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddTextChunk("<");
Builder.AddPlaceholderChunk("header");
Builder.AddTextChunk(">");
Results.AddResult(Builder.TakeString());
// #warning <message>
Builder.AddTypedTextChunk("warning");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddPlaceholderChunk("message");
Results.AddResult(Builder.TakeString());
// Note: #ident and #sccs are such crazy anachronisms that we don't provide
// completions for them. And __include_macros is a Clang-internal extension
// that we don't want to encourage anyone to use.
// FIXME: we don't support #assert or #unassert, so don't suggest them.
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction
: Sema::PCC_Namespace);
}
void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
IsDefinition ? CodeCompletionContext::CCC_MacroName
: CodeCompletionContext::CCC_MacroNameUse);
if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
// Add just the names of macros, not their arguments.
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Results.EnterNewScope();
for (Preprocessor::macro_iterator M = PP.macro_begin(),
MEnd = PP.macro_end();
M != MEnd; ++M) {
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString(M->first->getName()));
Results.AddResult(CodeCompletionResult(
Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition));
}
Results.ExitScope();
} else if (IsDefinition) {
// FIXME: Can we detect when the user just wrote an include guard above?
}
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompletePreprocessorExpression() {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_PreprocessorExpression);
if (!CodeCompleter || CodeCompleter->includeMacros())
AddMacroResults(PP, Results,
CodeCompleter ? CodeCompleter->loadExternal() : false,
true);
// defined (<macro>)
Results.EnterNewScope();
CodeCompletionBuilder Builder(Results.getAllocator(),
Results.getCodeCompletionTUInfo());
Builder.AddTypedTextChunk("defined");
Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Builder.AddPlaceholderChunk("macro");
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Builder.TakeString());
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
IdentifierInfo *Macro,
MacroInfo *MacroInfo,
unsigned Argument) {
// FIXME: In the future, we could provide "overload" results, much like we
// do for function calls.
// Now just ignore this. There will be another code-completion callback
// for the expanded tokens.
}
// This handles completion inside an #include filename, e.g. #include <foo/ba
// We look for the directory "foo" under each directory on the include path,
// list its files, and reassemble the appropriate #include.
void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
// RelDir should use /, but unescaped \ is possible on windows!
// Our completions will normalize to / for simplicity, this case is rare.
std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
// We need the native slashes for the actual file system interactions.
SmallString<128> NativeRelDir = StringRef(RelDir);
llvm::sys::path::native(NativeRelDir);
auto FS = getSourceManager().getFileManager().getVirtualFileSystem();
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_IncludedFile);
llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
// Helper: adds one file or directory completion result.
auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
SmallString<64> TypedChunk = Filename;
// Directory completion is up to the slash, e.g. <sys/
TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
auto R = SeenResults.insert(TypedChunk);
if (R.second) { // New completion
const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
*R.first = InternedTyped; // Avoid dangling StringRef.
CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo());
Builder.AddTypedTextChunk(InternedTyped);
// The result is a "Pattern", which is pretty opaque.
// We may want to include the real filename to allow smart ranking.
Results.AddResult(CodeCompletionResult(Builder.TakeString()));
}
};
// Helper: scans IncludeDir for nice files, and adds results for each.
auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem) {
llvm::SmallString<128> Dir = IncludeDir;
if (!NativeRelDir.empty())
llvm::sys::path::append(Dir, NativeRelDir);
std::error_code EC;
unsigned Count = 0;
for (auto It = FS->dir_begin(Dir, EC);
!EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
if (++Count == 2500) // If we happen to hit a huge directory,
break; // bail out early so we're not too slow.
StringRef Filename = llvm::sys::path::filename(It->path());
switch (It->type()) {
case llvm::sys::fs::file_type::directory_file:
AddCompletion(Filename, /*IsDirectory=*/true);
break;
case llvm::sys::fs::file_type::regular_file:
// Only files that really look like headers. (Except in system dirs).
if (!IsSystem) {
// Header extensions from Types.def, which we can't depend on here.
if (!(Filename.endswith_lower(".h") ||
Filename.endswith_lower(".hh") ||
Filename.endswith_lower(".hpp") ||
Filename.endswith_lower(".inc")))
break;
}
AddCompletion(Filename, /*IsDirectory=*/false);
break;
default:
break;
}
}
};
// Helper: adds results relative to IncludeDir, if possible.
auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
bool IsSystem) {
switch (IncludeDir.getLookupType()) {
case DirectoryLookup::LT_HeaderMap:
// header maps are not (currently) enumerable.
break;
case DirectoryLookup::LT_NormalDir:
AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem);
break;
case DirectoryLookup::LT_Framework:
AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem);
break;
}
};
// Finally with all our helpers, we can scan the include path.
// Do this in standard order so deduplication keeps the right file.
// (In case we decide to add more details to the results later).
const auto &S = PP.getHeaderSearchInfo();
using llvm::make_range;
if (!Angled) {
// The current directory is on the include path for "quoted" includes.
auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
if (CurFile && CurFile->getDir())
AddFilesFromIncludeDir(CurFile->getDir()->getName(), false);
for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
AddFilesFromDirLookup(D, false);
}
for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
AddFilesFromDirLookup(D, false);
for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
AddFilesFromDirLookup(D, true);
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::CodeCompleteNaturalLanguage() {
HandleCodeCompleteResults(this, CodeCompleter,
CodeCompletionContext::CCC_NaturalLanguage, nullptr,
0);
}
void Sema::CodeCompleteAvailabilityPlatformName() {
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo(),
CodeCompletionContext::CCC_Other);
Results.EnterNewScope();
static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
for (const char *Platform : llvm::makeArrayRef(Platforms)) {
Results.AddResult(CodeCompletionResult(Platform));
Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
Twine(Platform) + "ApplicationExtension")));
}
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Results.data(), Results.size());
}
void Sema::GatherGlobalCodeCompletions(
CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
SmallVectorImpl<CodeCompletionResult> &Results) {
ResultBuilder Builder(*this, Allocator, CCTUInfo,
CodeCompletionContext::CCC_Recovery);
if (!CodeCompleter || CodeCompleter->includeGlobals()) {
CodeCompletionDeclConsumer Consumer(Builder,
Context.getTranslationUnitDecl());
LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
Consumer,
!CodeCompleter || CodeCompleter->loadExternal());
}
if (!CodeCompleter || CodeCompleter->includeMacros())
AddMacroResults(PP, Builder,
CodeCompleter ? CodeCompleter->loadExternal() : false,
true);
Results.clear();
Results.insert(Results.end(), Builder.data(),
Builder.data() + Builder.size());
}
Index: vendor/clang/dist-release_80/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- vendor/clang/dist-release_80/lib/Sema/SemaDeclCXX.cpp (revision 343795)
+++ vendor/clang/dist-release_80/lib/Sema/SemaDeclCXX.cpp (revision 343796)
@@ -1,15638 +1,15639 @@
//===------ SemaDeclCXX.cpp - Semantic Analysis for C++ Declarations ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements semantic analysis for C++ declarations.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/ComparisonCategories.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include <map>
#include <set>
using namespace clang;
//===----------------------------------------------------------------------===//
// CheckDefaultArgumentVisitor
//===----------------------------------------------------------------------===//
namespace {
/// CheckDefaultArgumentVisitor - C++ [dcl.fct.default] Traverses
/// the default argument of a parameter to determine whether it
/// contains any ill-formed subexpressions. For example, this will
/// diagnose the use of local variables or parameters within the
/// default argument expression.
class CheckDefaultArgumentVisitor
: public StmtVisitor<CheckDefaultArgumentVisitor, bool> {
Expr *DefaultArg;
Sema *S;
public:
CheckDefaultArgumentVisitor(Expr *defarg, Sema *s)
: DefaultArg(defarg), S(s) {}
bool VisitExpr(Expr *Node);
bool VisitDeclRefExpr(DeclRefExpr *DRE);
bool VisitCXXThisExpr(CXXThisExpr *ThisE);
bool VisitLambdaExpr(LambdaExpr *Lambda);
bool VisitPseudoObjectExpr(PseudoObjectExpr *POE);
};
/// VisitExpr - Visit all of the children of this expression.
bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) {
bool IsInvalid = false;
for (Stmt *SubStmt : Node->children())
IsInvalid |= Visit(SubStmt);
return IsInvalid;
}
/// VisitDeclRefExpr - Visit a reference to a declaration, to
/// determine whether this declaration can be used in the default
/// argument expression.
bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) {
NamedDecl *Decl = DRE->getDecl();
if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(Decl)) {
// C++ [dcl.fct.default]p9
// Default arguments are evaluated each time the function is
// called. The order of evaluation of function arguments is
// unspecified. Consequently, parameters of a function shall not
// be used in default argument expressions, even if they are not
// evaluated. Parameters of a function declared before a default
// argument expression are in scope and can hide namespace and
// class member names.
return S->Diag(DRE->getBeginLoc(),
diag::err_param_default_argument_references_param)
<< Param->getDeclName() << DefaultArg->getSourceRange();
} else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) {
// C++ [dcl.fct.default]p7
// Local variables shall not be used in default argument
// expressions.
if (VDecl->isLocalVarDecl())
return S->Diag(DRE->getBeginLoc(),
diag::err_param_default_argument_references_local)
<< VDecl->getDeclName() << DefaultArg->getSourceRange();
}
return false;
}
/// VisitCXXThisExpr - Visit a C++ "this" expression.
bool CheckDefaultArgumentVisitor::VisitCXXThisExpr(CXXThisExpr *ThisE) {
// C++ [dcl.fct.default]p8:
// The keyword this shall not be used in a default argument of a
// member function.
return S->Diag(ThisE->getBeginLoc(),
diag::err_param_default_argument_references_this)
<< ThisE->getSourceRange();
}
bool CheckDefaultArgumentVisitor::VisitPseudoObjectExpr(PseudoObjectExpr *POE) {
bool Invalid = false;
for (PseudoObjectExpr::semantics_iterator
i = POE->semantics_begin(), e = POE->semantics_end(); i != e; ++i) {
Expr *E = *i;
// Look through bindings.
if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
E = OVE->getSourceExpr();
assert(E && "pseudo-object binding without source expression?");
}
Invalid |= Visit(E);
}
return Invalid;
}
bool CheckDefaultArgumentVisitor::VisitLambdaExpr(LambdaExpr *Lambda) {
// C++11 [expr.lambda.prim]p13:
// A lambda-expression appearing in a default argument shall not
// implicitly or explicitly capture any entity.
if (Lambda->capture_begin() == Lambda->capture_end())
return false;
return S->Diag(Lambda->getBeginLoc(), diag::err_lambda_capture_default_arg);
}
}
void
Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
const CXXMethodDecl *Method) {
// If we have an MSAny spec already, don't bother.
if (!Method || ComputedEST == EST_MSAny)
return;
const FunctionProtoType *Proto
= Method->getType()->getAs<FunctionProtoType>();
Proto = Self->ResolveExceptionSpec(CallLoc, Proto);
if (!Proto)
return;
ExceptionSpecificationType EST = Proto->getExceptionSpecType();
// If we have a throw-all spec at this point, ignore the function.
if (ComputedEST == EST_None)
return;
if (EST == EST_None && Method->hasAttr<NoThrowAttr>())
EST = EST_BasicNoexcept;
switch (EST) {
case EST_Unparsed:
case EST_Uninstantiated:
case EST_Unevaluated:
llvm_unreachable("should not see unresolved exception specs here");
// If this function can throw any exceptions, make a note of that.
case EST_MSAny:
case EST_None:
// FIXME: Whichever we see last of MSAny and None determines our result.
// We should make a consistent, order-independent choice here.
ClearExceptions();
ComputedEST = EST;
return;
case EST_NoexceptFalse:
ClearExceptions();
ComputedEST = EST_None;
return;
// FIXME: If the call to this decl is using any of its default arguments, we
// need to search them for potentially-throwing calls.
// If this function has a basic noexcept, it doesn't affect the outcome.
case EST_BasicNoexcept:
case EST_NoexceptTrue:
return;
// If we're still at noexcept(true) and there's a throw() callee,
// change to that specification.
case EST_DynamicNone:
if (ComputedEST == EST_BasicNoexcept)
ComputedEST = EST_DynamicNone;
return;
case EST_DependentNoexcept:
llvm_unreachable(
"should not generate implicit declarations for dependent cases");
case EST_Dynamic:
break;
}
assert(EST == EST_Dynamic && "EST case not considered earlier.");
assert(ComputedEST != EST_None &&
"Shouldn't collect exceptions when throw-all is guaranteed.");
ComputedEST = EST_Dynamic;
// Record the exceptions in this function's exception specification.
for (const auto &E : Proto->exceptions())
if (ExceptionsSeen.insert(Self->Context.getCanonicalType(E)).second)
Exceptions.push_back(E);
}
void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) {
if (!E || ComputedEST == EST_MSAny)
return;
// FIXME:
//
// C++0x [except.spec]p14:
// [An] implicit exception-specification specifies the type-id T if and
// only if T is allowed by the exception-specification of a function directly
// invoked by f's implicit definition; f shall allow all exceptions if any
// function it directly invokes allows all exceptions, and f shall allow no
// exceptions if every function it directly invokes allows no exceptions.
//
// Note in particular that if an implicit exception-specification is generated
// for a function containing a throw-expression, that specification can still
// be noexcept(true).
//
// Note also that 'directly invoked' is not defined in the standard, and there
// is no indication that we should only consider potentially-evaluated calls.
//
// Ultimately we should implement the intent of the standard: the exception
// specification should be the set of exceptions which can be thrown by the
// implicit definition. For now, we assume that any non-nothrow expression can
// throw any exception.
if (Self->canThrow(E))
ComputedEST = EST_None;
}
bool
Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
SourceLocation EqualLoc) {
if (RequireCompleteType(Param->getLocation(), Param->getType(),
diag::err_typecheck_decl_incomplete_type)) {
Param->setInvalidDecl();
return true;
}
// C++ [dcl.fct.default]p5
// A default argument expression is implicitly converted (clause
// 4) to the parameter type. The default argument expression has
// the same semantic constraints as the initializer expression in
// a declaration of a variable of the parameter type, using the
// copy-initialization semantics (8.5).
InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
Param);
InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(),
EqualLoc);
InitializationSequence InitSeq(*this, Entity, Kind, Arg);
ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Arg);
if (Result.isInvalid())
return true;
Arg = Result.getAs<Expr>();
CheckCompletedExpr(Arg, EqualLoc);
Arg = MaybeCreateExprWithCleanups(Arg);
// Okay: add the default argument to the parameter
Param->setDefaultArg(Arg);
// We have already instantiated this parameter; provide each of the
// instantiations with the uninstantiated default argument.
UnparsedDefaultArgInstantiationsMap::iterator InstPos
= UnparsedDefaultArgInstantiations.find(Param);
if (InstPos != UnparsedDefaultArgInstantiations.end()) {
for (unsigned I = 0, N = InstPos->second.size(); I != N; ++I)
InstPos->second[I]->setUninstantiatedDefaultArg(Arg);
// We're done tracking this parameter's instantiations.
UnparsedDefaultArgInstantiations.erase(InstPos);
}
return false;
}
/// ActOnParamDefaultArgument - Check whether the default argument
/// provided for a function parameter is well-formed. If so, attach it
/// to the parameter declaration.
void
Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc,
Expr *DefaultArg) {
if (!param || !DefaultArg)
return;
ParmVarDecl *Param = cast<ParmVarDecl>(param);
UnparsedDefaultArgLocs.erase(Param);
// Default arguments are only permitted in C++
if (!getLangOpts().CPlusPlus) {
Diag(EqualLoc, diag::err_param_default_argument)
<< DefaultArg->getSourceRange();
Param->setInvalidDecl();
return;
}
// Check for unexpanded parameter packs.
if (DiagnoseUnexpandedParameterPack(DefaultArg, UPPC_DefaultArgument)) {
Param->setInvalidDecl();
return;
}
// C++11 [dcl.fct.default]p3
// A default argument expression [...] shall not be specified for a
// parameter pack.
if (Param->isParameterPack()) {
Diag(EqualLoc, diag::err_param_default_argument_on_parameter_pack)
<< DefaultArg->getSourceRange();
return;
}
// Check that the default argument is well-formed
CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this);
if (DefaultArgChecker.Visit(DefaultArg)) {
Param->setInvalidDecl();
return;
}
SetParamDefaultArgument(Param, DefaultArg, EqualLoc);
}
/// ActOnParamUnparsedDefaultArgument - We've seen a default
/// argument for a function parameter, but we can't parse it yet
/// because we're inside a class definition. Note that this default
/// argument will be parsed later.
void Sema::ActOnParamUnparsedDefaultArgument(Decl *param,
SourceLocation EqualLoc,
SourceLocation ArgLoc) {
if (!param)
return;
ParmVarDecl *Param = cast<ParmVarDecl>(param);
Param->setUnparsedDefaultArg();
UnparsedDefaultArgLocs[Param] = ArgLoc;
}
/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
/// the default argument for the parameter param failed.
void Sema::ActOnParamDefaultArgumentError(Decl *param,
SourceLocation EqualLoc) {
if (!param)
return;
ParmVarDecl *Param = cast<ParmVarDecl>(param);
Param->setInvalidDecl();
UnparsedDefaultArgLocs.erase(Param);
Param->setDefaultArg(new(Context)
OpaqueValueExpr(EqualLoc,
Param->getType().getNonReferenceType(),
VK_RValue));
}
/// CheckExtraCXXDefaultArguments - Check for any extra default
/// arguments in the declarator, which is not a function declaration
/// or definition and therefore is not permitted to have default
/// arguments. This routine should be invoked for every declarator
/// that is not a function declaration or definition.
void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
// C++ [dcl.fct.default]p3
// A default argument expression shall be specified only in the
// parameter-declaration-clause of a function declaration or in a
// template-parameter (14.1). It shall not be specified for a
// parameter pack. If it is specified in a
// parameter-declaration-clause, it shall not occur within a
// declarator or abstract-declarator of a parameter-declaration.
bool MightBeFunction = D.isFunctionDeclarationContext();
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
DeclaratorChunk &chunk = D.getTypeObject(i);
if (chunk.Kind == DeclaratorChunk::Function) {
if (MightBeFunction) {
// This is a function declaration. It can have default arguments, but
// keep looking in case its return type is a function type with default
// arguments.
MightBeFunction = false;
continue;
}
for (unsigned argIdx = 0, e = chunk.Fun.NumParams; argIdx != e;
++argIdx) {
ParmVarDecl *Param = cast<ParmVarDecl>(chunk.Fun.Params[argIdx].Param);
if (Param->hasUnparsedDefaultArg()) {
std::unique_ptr<CachedTokens> Toks =
std::move(chunk.Fun.Params[argIdx].DefaultArgTokens);
SourceRange SR;
if (Toks->size() > 1)
SR = SourceRange((*Toks)[1].getLocation(),
Toks->back().getLocation());
else
SR = UnparsedDefaultArgLocs[Param];
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
<< SR;
} else if (Param->getDefaultArg()) {
Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
<< Param->getDefaultArg()->getSourceRange();
Param->setDefaultArg(nullptr);
}
}
} else if (chunk.Kind != DeclaratorChunk::Paren) {
MightBeFunction = false;
}
}
}
static bool functionDeclHasDefaultArgument(const FunctionDecl *FD) {
for (unsigned NumParams = FD->getNumParams(); NumParams > 0; --NumParams) {
const ParmVarDecl *PVD = FD->getParamDecl(NumParams-1);
if (!PVD->hasDefaultArg())
return false;
if (!PVD->hasInheritedDefaultArg())
return true;
}
return false;
}
/// MergeCXXFunctionDecl - Merge two declarations of the same C++
/// function, once we already know that they have the same
/// type. Subroutine of MergeFunctionDecl. Returns true if there was an
/// error, false otherwise.
bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
Scope *S) {
bool Invalid = false;
// The declaration context corresponding to the scope is the semantic
// parent, unless this is a local function declaration, in which case
// it is that surrounding function.
DeclContext *ScopeDC = New->isLocalExternDecl()
? New->getLexicalDeclContext()
: New->getDeclContext();
// Find the previous declaration for the purpose of default arguments.
FunctionDecl *PrevForDefaultArgs = Old;
for (/**/; PrevForDefaultArgs;
// Don't bother looking back past the latest decl if this is a local
// extern declaration; nothing else could work.
PrevForDefaultArgs = New->isLocalExternDecl()
? nullptr
: PrevForDefaultArgs->getPreviousDecl()) {
// Ignore hidden declarations.
if (!LookupResult::isVisible(*this, PrevForDefaultArgs))
continue;
if (S && !isDeclInScope(PrevForDefaultArgs, ScopeDC, S) &&
!New->isCXXClassMember()) {
// Ignore default arguments of old decl if they are not in
// the same scope and this is not an out-of-line definition of
// a member function.
continue;
}
if (PrevForDefaultArgs->isLocalExternDecl() != New->isLocalExternDecl()) {
// If only one of these is a local function declaration, then they are
// declared in different scopes, even though isDeclInScope may think
// they're in the same scope. (If both are local, the scope check is
// sufficient, and if neither is local, then they are in the same scope.)
continue;
}
// We found the right previous declaration.
break;
}
// C++ [dcl.fct.default]p4:
// For non-template functions, default arguments can be added in
// later declarations of a function in the same
// scope. Declarations in different scopes have completely
// distinct sets of default arguments. That is, declarations in
// inner scopes do not acquire default arguments from
// declarations in outer scopes, and vice versa. In a given
// function declaration, all parameters subsequent to a
// parameter with a default argument shall have default
// arguments supplied in this or previous declarations. A
// default argument shall not be redefined by a later
// declaration (not even to the same value).
//
// C++ [dcl.fct.default]p6:
// Except for member functions of class templates, the default arguments
// in a member function definition that appears outside of the class
// definition are added to the set of default arguments provided by the
// member function declaration in the class definition.
for (unsigned p = 0, NumParams = PrevForDefaultArgs
? PrevForDefaultArgs->getNumParams()
: 0;
p < NumParams; ++p) {
ParmVarDecl *OldParam = PrevForDefaultArgs->getParamDecl(p);
ParmVarDecl *NewParam = New->getParamDecl(p);
bool OldParamHasDfl = OldParam ? OldParam->hasDefaultArg() : false;
bool NewParamHasDfl = NewParam->hasDefaultArg();
if (OldParamHasDfl && NewParamHasDfl) {
unsigned DiagDefaultParamID =
diag::err_param_default_argument_redefinition;
// MSVC accepts that default parameters be redefined for member functions
// of template class. The new default parameter's value is ignored.
Invalid = true;
if (getLangOpts().MicrosoftExt) {
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(New);
if (MD && MD->getParent()->getDescribedClassTemplate()) {
// Merge the old default argument into the new parameter.
NewParam->setHasInheritedDefaultArg();
if (OldParam->hasUninstantiatedDefaultArg())
NewParam->setUninstantiatedDefaultArg(
OldParam->getUninstantiatedDefaultArg());
else
NewParam->setDefaultArg(OldParam->getInit());
DiagDefaultParamID = diag::ext_param_default_argument_redefinition;
Invalid = false;
}
}
// FIXME: If we knew where the '=' was, we could easily provide a fix-it
// hint here. Alternatively, we could walk the type-source information
// for NewParam to find the last source location in the type... but it
// isn't worth the effort right now. This is the kind of test case that
// is hard to get right:
// int f(int);
// void g(int (*fp)(int) = f);
// void g(int (*fp)(int) = &f);
Diag(NewParam->getLocation(), DiagDefaultParamID)
<< NewParam->getDefaultArgRange();
// Look for the function declaration where the default argument was
// actually written, which may be a declaration prior to Old.
for (auto Older = PrevForDefaultArgs;
OldParam->hasInheritedDefaultArg(); /**/) {
Older = Older->getPreviousDecl();
OldParam = Older->getParamDecl(p);
}
Diag(OldParam->getLocation(), diag::note_previous_definition)
<< OldParam->getDefaultArgRange();
} else if (OldParamHasDfl) {
// Merge the old default argument into the new parameter unless the new
// function is a friend declaration in a template class. In the latter
// case the default arguments will be inherited when the friend
// declaration will be instantiated.
if (New->getFriendObjectKind() == Decl::FOK_None ||
!New->getLexicalDeclContext()->isDependentContext()) {
// It's important to use getInit() here; getDefaultArg()
// strips off any top-level ExprWithCleanups.
NewParam->setHasInheritedDefaultArg();
if (OldParam->hasUnparsedDefaultArg())
NewParam->setUnparsedDefaultArg();
else if (OldParam->hasUninstantiatedDefaultArg())
NewParam->setUninstantiatedDefaultArg(
OldParam->getUninstantiatedDefaultArg());
else
NewParam->setDefaultArg(OldParam->getInit());
}
} else if (NewParamHasDfl) {
if (New->getDescribedFunctionTemplate()) {
// Paragraph 4, quoted above, only applies to non-template functions.
Diag(NewParam->getLocation(),
diag::err_param_default_argument_template_redecl)
<< NewParam->getDefaultArgRange();
Diag(PrevForDefaultArgs->getLocation(),
diag::note_template_prev_declaration)
<< false;
} else if (New->getTemplateSpecializationKind()
!= TSK_ImplicitInstantiation &&
New->getTemplateSpecializationKind() != TSK_Undeclared) {
// C++ [temp.expr.spec]p21:
// Default function arguments shall not be specified in a declaration
// or a definition for one of the following explicit specializations:
// - the explicit specialization of a function template;
// - the explicit specialization of a member function template;
// - the explicit specialization of a member function of a class
// template where the class template specialization to which the
// member function specialization belongs is implicitly
// instantiated.
Diag(NewParam->getLocation(), diag::err_template_spec_default_arg)
<< (New->getTemplateSpecializationKind() ==TSK_ExplicitSpecialization)
<< New->getDeclName()
<< NewParam->getDefaultArgRange();
} else if (New->getDeclContext()->isDependentContext()) {
// C++ [dcl.fct.default]p6 (DR217):
// Default arguments for a member function of a class template shall
// be specified on the initial declaration of the member function
// within the class template.
//
// Reading the tea leaves a bit in DR217 and its reference to DR205
// leads me to the conclusion that one cannot add default function
// arguments for an out-of-line definition of a member function of a
// dependent type.
int WhichKind = 2;
if (CXXRecordDecl *Record
= dyn_cast<CXXRecordDecl>(New->getDeclContext())) {
if (Record->getDescribedClassTemplate())
WhichKind = 0;
else if (isa<ClassTemplatePartialSpecializationDecl>(Record))
WhichKind = 1;
else
WhichKind = 2;
}
Diag(NewParam->getLocation(),
diag::err_param_default_argument_member_template_redecl)
<< WhichKind
<< NewParam->getDefaultArgRange();
}
}
}
// DR1344: If a default argument is added outside a class definition and that
// default argument makes the function a special member function, the program
// is ill-formed. This can only happen for constructors.
if (isa<CXXConstructorDecl>(New) &&
New->getMinRequiredArguments() < Old->getMinRequiredArguments()) {
CXXSpecialMember NewSM = getSpecialMember(cast<CXXMethodDecl>(New)),
OldSM = getSpecialMember(cast<CXXMethodDecl>(Old));
if (NewSM != OldSM) {
ParmVarDecl *NewParam = New->getParamDecl(New->getMinRequiredArguments());
assert(NewParam->hasDefaultArg());
Diag(NewParam->getLocation(), diag::err_default_arg_makes_ctor_special)
<< NewParam->getDefaultArgRange() << NewSM;
Diag(Old->getLocation(), diag::note_previous_declaration);
}
}
const FunctionDecl *Def;
// C++11 [dcl.constexpr]p1: If any declaration of a function or function
// template has a constexpr specifier then all its declarations shall
// contain the constexpr specifier.
if (New->isConstexpr() != Old->isConstexpr()) {
Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch)
<< New << New->isConstexpr();
Diag(Old->getLocation(), diag::note_previous_declaration);
Invalid = true;
} else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() &&
Old->isDefined(Def) &&
// If a friend function is inlined but does not have 'inline'
// specifier, it is a definition. Do not report attribute conflict
// in this case, redefinition will be diagnosed later.
(New->isInlineSpecified() ||
New->getFriendObjectKind() == Decl::FOK_None)) {
// C++11 [dcl.fcn.spec]p4:
// If the definition of a function appears in a translation unit before its
// first declaration as inline, the program is ill-formed.
Diag(New->getLocation(), diag::err_inline_decl_follows_def) << New;
Diag(Def->getLocation(), diag::note_previous_definition);
Invalid = true;
}
// FIXME: It's not clear what should happen if multiple declarations of a
// deduction guide have different explicitness. For now at least we simply
// reject any case where the explicitness changes.
auto *NewGuide = dyn_cast<CXXDeductionGuideDecl>(New);
if (NewGuide && NewGuide->isExplicitSpecified() !=
cast<CXXDeductionGuideDecl>(Old)->isExplicitSpecified()) {
Diag(New->getLocation(), diag::err_deduction_guide_explicit_mismatch)
<< NewGuide->isExplicitSpecified();
Diag(Old->getLocation(), diag::note_previous_declaration);
}
// C++11 [dcl.fct.default]p4: If a friend declaration specifies a default
// argument expression, that declaration shall be a definition and shall be
// the only declaration of the function or function template in the
// translation unit.
if (Old->getFriendObjectKind() == Decl::FOK_Undeclared &&
functionDeclHasDefaultArgument(Old)) {
Diag(New->getLocation(), diag::err_friend_decl_with_def_arg_redeclared);
Diag(Old->getLocation(), diag::note_previous_declaration);
Invalid = true;
}
return Invalid;
}
NamedDecl *
Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
MultiTemplateParamsArg TemplateParamLists) {
assert(D.isDecompositionDeclarator());
const DecompositionDeclarator &Decomp = D.getDecompositionDeclarator();
// The syntax only allows a decomposition declarator as a simple-declaration,
// a for-range-declaration, or a condition in Clang, but we parse it in more
// cases than that.
if (!D.mayHaveDecompositionDeclarator()) {
Diag(Decomp.getLSquareLoc(), diag::err_decomp_decl_context)
<< Decomp.getSourceRange();
return nullptr;
}
if (!TemplateParamLists.empty()) {
// FIXME: There's no rule against this, but there are also no rules that
// would actually make it usable, so we reject it for now.
Diag(TemplateParamLists.front()->getTemplateLoc(),
diag::err_decomp_decl_template);
return nullptr;
}
Diag(Decomp.getLSquareLoc(),
!getLangOpts().CPlusPlus17
? diag::ext_decomp_decl
: D.getContext() == DeclaratorContext::ConditionContext
? diag::ext_decomp_decl_cond
: diag::warn_cxx14_compat_decomp_decl)
<< Decomp.getSourceRange();
// The semantic context is always just the current context.
DeclContext *const DC = CurContext;
// C++1z [dcl.dcl]/8:
// The decl-specifier-seq shall contain only the type-specifier auto
// and cv-qualifiers.
auto &DS = D.getDeclSpec();
{
SmallVector<StringRef, 8> BadSpecifiers;
SmallVector<SourceLocation, 8> BadSpecifierLocs;
if (auto SCS = DS.getStorageClassSpec()) {
BadSpecifiers.push_back(DeclSpec::getSpecifierName(SCS));
BadSpecifierLocs.push_back(DS.getStorageClassSpecLoc());
}
if (auto TSCS = DS.getThreadStorageClassSpec()) {
BadSpecifiers.push_back(DeclSpec::getSpecifierName(TSCS));
BadSpecifierLocs.push_back(DS.getThreadStorageClassSpecLoc());
}
if (DS.isConstexprSpecified()) {
BadSpecifiers.push_back("constexpr");
BadSpecifierLocs.push_back(DS.getConstexprSpecLoc());
}
if (DS.isInlineSpecified()) {
BadSpecifiers.push_back("inline");
BadSpecifierLocs.push_back(DS.getInlineSpecLoc());
}
if (!BadSpecifiers.empty()) {
auto &&Err = Diag(BadSpecifierLocs.front(), diag::err_decomp_decl_spec);
Err << (int)BadSpecifiers.size()
<< llvm::join(BadSpecifiers.begin(), BadSpecifiers.end(), " ");
// Don't add FixItHints to remove the specifiers; we do still respect
// them when building the underlying variable.
for (auto Loc : BadSpecifierLocs)
Err << SourceRange(Loc, Loc);
}
// We can't recover from it being declared as a typedef.
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef)
return nullptr;
}
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType R = TInfo->getType();
if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
UPPC_DeclarationType))
D.setInvalidType();
// The syntax only allows a single ref-qualifier prior to the decomposition
// declarator. No other declarator chunks are permitted. Also check the type
// specifier here.
if (DS.getTypeSpecType() != DeclSpec::TST_auto ||
D.hasGroupingParens() || D.getNumTypeObjects() > 1 ||
(D.getNumTypeObjects() == 1 &&
D.getTypeObject(0).Kind != DeclaratorChunk::Reference)) {
Diag(Decomp.getLSquareLoc(),
(D.hasGroupingParens() ||
(D.getNumTypeObjects() &&
D.getTypeObject(0).Kind == DeclaratorChunk::Paren))
? diag::err_decomp_decl_parens
: diag::err_decomp_decl_type)
<< R;
// In most cases, there's no actual problem with an explicitly-specified
// type, but a function type won't work here, and ActOnVariableDeclarator
// shouldn't be called for such a type.
if (R->isFunctionType())
D.setInvalidType();
}
// Build the BindingDecls.
SmallVector<BindingDecl*, 8> Bindings;
// Build the BindingDecls.
for (auto &B : D.getDecompositionDeclarator().bindings()) {
// Check for name conflicts.
DeclarationNameInfo NameInfo(B.Name, B.NameLoc);
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
ForVisibleRedeclaration);
LookupName(Previous, S,
/*CreateBuiltins*/DC->getRedeclContext()->isTranslationUnit());
// It's not permitted to shadow a template parameter name.
if (Previous.isSingleResult() &&
Previous.getFoundDecl()->isTemplateParameter()) {
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
Previous.getFoundDecl());
Previous.clear();
}
bool ConsiderLinkage = DC->isFunctionOrMethod() &&
DS.getStorageClassSpec() == DeclSpec::SCS_extern;
FilterLookupForScope(Previous, DC, S, ConsiderLinkage,
/*AllowInlineNamespace*/false);
if (!Previous.empty()) {
auto *Old = Previous.getRepresentativeDecl();
Diag(B.NameLoc, diag::err_redefinition) << B.Name;
Diag(Old->getLocation(), diag::note_previous_definition);
}
auto *BD = BindingDecl::Create(Context, DC, B.NameLoc, B.Name);
PushOnScopeChains(BD, S, true);
Bindings.push_back(BD);
ParsingInitForAutoVars.insert(BD);
}
// There are no prior lookup results for the variable itself, because it
// is unnamed.
DeclarationNameInfo NameInfo((IdentifierInfo *)nullptr,
Decomp.getLSquareLoc());
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
ForVisibleRedeclaration);
// Build the variable that holds the non-decomposed object.
bool AddToScope = true;
NamedDecl *New =
ActOnVariableDeclarator(S, D, DC, TInfo, Previous,
MultiTemplateParamsArg(), AddToScope, Bindings);
if (AddToScope) {
S->AddDecl(New);
CurContext->addHiddenDecl(New);
}
if (isInOpenMPDeclareTargetContext())
checkDeclIsAllowedInOpenMPTarget(nullptr, New);
return New;
}
static bool checkSimpleDecomposition(
Sema &S, ArrayRef<BindingDecl *> Bindings, ValueDecl *Src,
QualType DecompType, const llvm::APSInt &NumElems, QualType ElemType,
llvm::function_ref<ExprResult(SourceLocation, Expr *, unsigned)> GetInit) {
if ((int64_t)Bindings.size() != NumElems) {
S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
<< DecompType << (unsigned)Bindings.size() << NumElems.toString(10)
<< (NumElems < Bindings.size());
return true;
}
unsigned I = 0;
for (auto *B : Bindings) {
SourceLocation Loc = B->getLocation();
ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc);
if (E.isInvalid())
return true;
E = GetInit(Loc, E.get(), I++);
if (E.isInvalid())
return true;
B->setBinding(ElemType, E.get());
}
return false;
}
static bool checkArrayLikeDecomposition(Sema &S,
ArrayRef<BindingDecl *> Bindings,
ValueDecl *Src, QualType DecompType,
const llvm::APSInt &NumElems,
QualType ElemType) {
return checkSimpleDecomposition(
S, Bindings, Src, DecompType, NumElems, ElemType,
[&](SourceLocation Loc, Expr *Base, unsigned I) -> ExprResult {
ExprResult E = S.ActOnIntegerConstant(Loc, I);
if (E.isInvalid())
return ExprError();
return S.CreateBuiltinArraySubscriptExpr(Base, Loc, E.get(), Loc);
});
}
static bool checkArrayDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
ValueDecl *Src, QualType DecompType,
const ConstantArrayType *CAT) {
return checkArrayLikeDecomposition(S, Bindings, Src, DecompType,
llvm::APSInt(CAT->getSize()),
CAT->getElementType());
}
static bool checkVectorDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
ValueDecl *Src, QualType DecompType,
const VectorType *VT) {
return checkArrayLikeDecomposition(
S, Bindings, Src, DecompType, llvm::APSInt::get(VT->getNumElements()),
S.Context.getQualifiedType(VT->getElementType(),
DecompType.getQualifiers()));
}
static bool checkComplexDecomposition(Sema &S,
ArrayRef<BindingDecl *> Bindings,
ValueDecl *Src, QualType DecompType,
const ComplexType *CT) {
return checkSimpleDecomposition(
S, Bindings, Src, DecompType, llvm::APSInt::get(2),
S.Context.getQualifiedType(CT->getElementType(),
DecompType.getQualifiers()),
[&](SourceLocation Loc, Expr *Base, unsigned I) -> ExprResult {
return S.CreateBuiltinUnaryOp(Loc, I ? UO_Imag : UO_Real, Base);
});
}
static std::string printTemplateArgs(const PrintingPolicy &PrintingPolicy,
TemplateArgumentListInfo &Args) {
SmallString<128> SS;
llvm::raw_svector_ostream OS(SS);
bool First = true;
for (auto &Arg : Args.arguments()) {
if (!First)
OS << ", ";
Arg.getArgument().print(PrintingPolicy, OS);
First = false;
}
return OS.str();
}
static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup,
SourceLocation Loc, StringRef Trait,
TemplateArgumentListInfo &Args,
unsigned DiagID) {
auto DiagnoseMissing = [&] {
if (DiagID)
S.Diag(Loc, DiagID) << printTemplateArgs(S.Context.getPrintingPolicy(),
Args);
return true;
};
// FIXME: Factor out duplication with lookupPromiseType in SemaCoroutine.
NamespaceDecl *Std = S.getStdNamespace();
if (!Std)
return DiagnoseMissing();
// Look up the trait itself, within namespace std. We can diagnose various
// problems with this lookup even if we've been asked to not diagnose a
// missing specialization, because this can only fail if the user has been
// declaring their own names in namespace std or we don't support the
// standard library implementation in use.
LookupResult Result(S, &S.PP.getIdentifierTable().get(Trait),
Loc, Sema::LookupOrdinaryName);
if (!S.LookupQualifiedName(Result, Std))
return DiagnoseMissing();
if (Result.isAmbiguous())
return true;
ClassTemplateDecl *TraitTD = Result.getAsSingle<ClassTemplateDecl>();
if (!TraitTD) {
Result.suppressDiagnostics();
NamedDecl *Found = *Result.begin();
S.Diag(Loc, diag::err_std_type_trait_not_class_template) << Trait;
S.Diag(Found->getLocation(), diag::note_declared_at);
return true;
}
// Build the template-id.
QualType TraitTy = S.CheckTemplateIdType(TemplateName(TraitTD), Loc, Args);
if (TraitTy.isNull())
return true;
if (!S.isCompleteType(Loc, TraitTy)) {
if (DiagID)
S.RequireCompleteType(
Loc, TraitTy, DiagID,
printTemplateArgs(S.Context.getPrintingPolicy(), Args));
return true;
}
CXXRecordDecl *RD = TraitTy->getAsCXXRecordDecl();
assert(RD && "specialization of class template is not a class?");
// Look up the member of the trait type.
S.LookupQualifiedName(TraitMemberLookup, RD);
return TraitMemberLookup.isAmbiguous();
}
static TemplateArgumentLoc
getTrivialIntegralTemplateArgument(Sema &S, SourceLocation Loc, QualType T,
uint64_t I) {
TemplateArgument Arg(S.Context, S.Context.MakeIntValue(I, T), T);
return S.getTrivialTemplateArgumentLoc(Arg, T, Loc);
}
static TemplateArgumentLoc
getTrivialTypeTemplateArgument(Sema &S, SourceLocation Loc, QualType T) {
return S.getTrivialTemplateArgumentLoc(TemplateArgument(T), QualType(), Loc);
}
namespace { enum class IsTupleLike { TupleLike, NotTupleLike, Error }; }
static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T,
llvm::APSInt &Size) {
EnterExpressionEvaluationContext ContextRAII(
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
DeclarationName Value = S.PP.getIdentifierInfo("value");
LookupResult R(S, Value, Loc, Sema::LookupOrdinaryName);
// Form template argument list for tuple_size<T>.
TemplateArgumentListInfo Args(Loc, Loc);
Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T));
// If there's no tuple_size specialization, it's not tuple-like.
if (lookupStdTypeTraitMember(S, R, Loc, "tuple_size", Args, /*DiagID*/0))
return IsTupleLike::NotTupleLike;
// If we get this far, we've committed to the tuple interpretation, but
// we can still fail if there actually isn't a usable ::value.
struct ICEDiagnoser : Sema::VerifyICEDiagnoser {
LookupResult &R;
TemplateArgumentListInfo &Args;
ICEDiagnoser(LookupResult &R, TemplateArgumentListInfo &Args)
: R(R), Args(Args) {}
void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) {
S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant)
<< printTemplateArgs(S.Context.getPrintingPolicy(), Args);
}
} Diagnoser(R, Args);
if (R.empty()) {
Diagnoser.diagnoseNotICE(S, Loc, SourceRange());
return IsTupleLike::Error;
}
ExprResult E =
S.BuildDeclarationNameExpr(CXXScopeSpec(), R, /*NeedsADL*/false);
if (E.isInvalid())
return IsTupleLike::Error;
E = S.VerifyIntegerConstantExpression(E.get(), &Size, Diagnoser, false);
if (E.isInvalid())
return IsTupleLike::Error;
return IsTupleLike::TupleLike;
}
/// \return std::tuple_element<I, T>::type.
static QualType getTupleLikeElementType(Sema &S, SourceLocation Loc,
unsigned I, QualType T) {
// Form template argument list for tuple_element<I, T>.
TemplateArgumentListInfo Args(Loc, Loc);
Args.addArgument(
getTrivialIntegralTemplateArgument(S, Loc, S.Context.getSizeType(), I));
Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T));
DeclarationName TypeDN = S.PP.getIdentifierInfo("type");
LookupResult R(S, TypeDN, Loc, Sema::LookupOrdinaryName);
if (lookupStdTypeTraitMember(
S, R, Loc, "tuple_element", Args,
diag::err_decomp_decl_std_tuple_element_not_specialized))
return QualType();
auto *TD = R.getAsSingle<TypeDecl>();
if (!TD) {
R.suppressDiagnostics();
S.Diag(Loc, diag::err_decomp_decl_std_tuple_element_not_specialized)
<< printTemplateArgs(S.Context.getPrintingPolicy(), Args);
if (!R.empty())
S.Diag(R.getRepresentativeDecl()->getLocation(), diag::note_declared_at);
return QualType();
}
return S.Context.getTypeDeclType(TD);
}
namespace {
struct BindingDiagnosticTrap {
Sema &S;
DiagnosticErrorTrap Trap;
BindingDecl *BD;
BindingDiagnosticTrap(Sema &S, BindingDecl *BD)
: S(S), Trap(S.Diags), BD(BD) {}
~BindingDiagnosticTrap() {
if (Trap.hasErrorOccurred())
S.Diag(BD->getLocation(), diag::note_in_binding_decl_init) << BD;
}
};
}
static bool checkTupleLikeDecomposition(Sema &S,
ArrayRef<BindingDecl *> Bindings,
VarDecl *Src, QualType DecompType,
const llvm::APSInt &TupleSize) {
if ((int64_t)Bindings.size() != TupleSize) {
S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
<< DecompType << (unsigned)Bindings.size() << TupleSize.toString(10)
<< (TupleSize < Bindings.size());
return true;
}
if (Bindings.empty())
return false;
DeclarationName GetDN = S.PP.getIdentifierInfo("get");
// [dcl.decomp]p3:
// The unqualified-id get is looked up in the scope of E by class member
// access lookup ...
LookupResult MemberGet(S, GetDN, Src->getLocation(), Sema::LookupMemberName);
bool UseMemberGet = false;
if (S.isCompleteType(Src->getLocation(), DecompType)) {
if (auto *RD = DecompType->getAsCXXRecordDecl())
S.LookupQualifiedName(MemberGet, RD);
if (MemberGet.isAmbiguous())
return true;
// ... and if that finds at least one declaration that is a function
// template whose first template parameter is a non-type parameter ...
for (NamedDecl *D : MemberGet) {
if (FunctionTemplateDecl *FTD =
dyn_cast<FunctionTemplateDecl>(D->getUnderlyingDecl())) {
TemplateParameterList *TPL = FTD->getTemplateParameters();
if (TPL->size() != 0 &&
isa<NonTypeTemplateParmDecl>(TPL->getParam(0))) {
// ... the initializer is e.get<i>().
UseMemberGet = true;
break;
}
}
}
S.FilterAcceptableTemplateNames(MemberGet);
}
unsigned I = 0;
for (auto *B : Bindings) {
BindingDiagnosticTrap Trap(S, B);
SourceLocation Loc = B->getLocation();
ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc);
if (E.isInvalid())
return true;
// e is an lvalue if the type of the entity is an lvalue reference and
// an xvalue otherwise
if (!Src->getType()->isLValueReferenceType())
E = ImplicitCastExpr::Create(S.Context, E.get()->getType(), CK_NoOp,
E.get(), nullptr, VK_XValue);
TemplateArgumentListInfo Args(Loc, Loc);
Args.addArgument(
getTrivialIntegralTemplateArgument(S, Loc, S.Context.getSizeType(), I));
if (UseMemberGet) {
// if [lookup of member get] finds at least one declaration, the
// initializer is e.get<i-1>().
E = S.BuildMemberReferenceExpr(E.get(), DecompType, Loc, false,
CXXScopeSpec(), SourceLocation(), nullptr,
MemberGet, &Args, nullptr);
if (E.isInvalid())
return true;
E = S.ActOnCallExpr(nullptr, E.get(), Loc, None, Loc);
} else {
// Otherwise, the initializer is get<i-1>(e), where get is looked up
// in the associated namespaces.
Expr *Get = UnresolvedLookupExpr::Create(
S.Context, nullptr, NestedNameSpecifierLoc(), SourceLocation(),
DeclarationNameInfo(GetDN, Loc), /*RequiresADL*/true, &Args,
UnresolvedSetIterator(), UnresolvedSetIterator());
Expr *Arg = E.get();
E = S.ActOnCallExpr(nullptr, Get, Loc, Arg, Loc);
}
if (E.isInvalid())
return true;
Expr *Init = E.get();
// Given the type T designated by std::tuple_element<i - 1, E>::type,
QualType T = getTupleLikeElementType(S, Loc, I, DecompType);
if (T.isNull())
return true;
// each vi is a variable of type "reference to T" initialized with the
// initializer, where the reference is an lvalue reference if the
// initializer is an lvalue and an rvalue reference otherwise
QualType RefType =
S.BuildReferenceType(T, E.get()->isLValue(), Loc, B->getDeclName());
if (RefType.isNull())
return true;
auto *RefVD = VarDecl::Create(
S.Context, Src->getDeclContext(), Loc, Loc,
B->getDeclName().getAsIdentifierInfo(), RefType,
S.Context.getTrivialTypeSourceInfo(T, Loc), Src->getStorageClass());
RefVD->setLexicalDeclContext(Src->getLexicalDeclContext());
RefVD->setTSCSpec(Src->getTSCSpec());
RefVD->setImplicit();
if (Src->isInlineSpecified())
RefVD->setInlineSpecified();
RefVD->getLexicalDeclContext()->addHiddenDecl(RefVD);
InitializedEntity Entity = InitializedEntity::InitializeBinding(RefVD);
InitializationKind Kind = InitializationKind::CreateCopy(Loc, Loc);
InitializationSequence Seq(S, Entity, Kind, Init);
E = Seq.Perform(S, Entity, Kind, Init);
if (E.isInvalid())
return true;
E = S.ActOnFinishFullExpr(E.get(), Loc, /*DiscardedValue*/ false);
if (E.isInvalid())
return true;
RefVD->setInit(E.get());
RefVD->checkInitIsICE();
E = S.BuildDeclarationNameExpr(CXXScopeSpec(),
DeclarationNameInfo(B->getDeclName(), Loc),
RefVD);
if (E.isInvalid())
return true;
B->setBinding(T, E.get());
I++;
}
return false;
}
/// Find the base class to decompose in a built-in decomposition of a class type.
/// This base class search is, unfortunately, not quite like any other that we
/// perform anywhere else in C++.
static DeclAccessPair findDecomposableBaseClass(Sema &S, SourceLocation Loc,
const CXXRecordDecl *RD,
CXXCastPath &BasePath) {
auto BaseHasFields = [](const CXXBaseSpecifier *Specifier,
CXXBasePath &Path) {
return Specifier->getType()->getAsCXXRecordDecl()->hasDirectFields();
};
const CXXRecordDecl *ClassWithFields = nullptr;
AccessSpecifier AS = AS_public;
if (RD->hasDirectFields())
// [dcl.decomp]p4:
// Otherwise, all of E's non-static data members shall be public direct
// members of E ...
ClassWithFields = RD;
else {
// ... or of ...
CXXBasePaths Paths;
Paths.setOrigin(const_cast<CXXRecordDecl*>(RD));
if (!RD->lookupInBases(BaseHasFields, Paths)) {
// If no classes have fields, just decompose RD itself. (This will work
// if and only if zero bindings were provided.)
return DeclAccessPair::make(const_cast<CXXRecordDecl*>(RD), AS_public);
}
CXXBasePath *BestPath = nullptr;
for (auto &P : Paths) {
if (!BestPath)
BestPath = &P;
else if (!S.Context.hasSameType(P.back().Base->getType(),
BestPath->back().Base->getType())) {
// ... the same ...
S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members)
<< false << RD << BestPath->back().Base->getType()
<< P.back().Base->getType();
return DeclAccessPair();
} else if (P.Access < BestPath->Access) {
BestPath = &P;
}
}
// ... unambiguous ...
QualType BaseType = BestPath->back().Base->getType();
if (Paths.isAmbiguous(S.Context.getCanonicalType(BaseType))) {
S.Diag(Loc, diag::err_decomp_decl_ambiguous_base)
<< RD << BaseType << S.getAmbiguousPathsDisplayString(Paths);
return DeclAccessPair();
}
// ... [accessible, implied by other rules] base class of E.
S.CheckBaseClassAccess(Loc, BaseType, S.Context.getRecordType(RD),
*BestPath, diag::err_decomp_decl_inaccessible_base);
AS = BestPath->Access;
ClassWithFields = BaseType->getAsCXXRecordDecl();
S.BuildBasePathArray(Paths, BasePath);
}
// The above search did not check whether the selected class itself has base
// classes with fields, so check that now.
CXXBasePaths Paths;
if (ClassWithFields->lookupInBases(BaseHasFields, Paths)) {
S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members)
<< (ClassWithFields == RD) << RD << ClassWithFields
<< Paths.front().back().Base->getType();
return DeclAccessPair();
}
return DeclAccessPair::make(const_cast<CXXRecordDecl*>(ClassWithFields), AS);
}
static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
ValueDecl *Src, QualType DecompType,
const CXXRecordDecl *OrigRD) {
+ if (S.RequireCompleteType(Src->getLocation(), DecompType,
+ diag::err_incomplete_type))
+ return true;
+
CXXCastPath BasePath;
DeclAccessPair BasePair =
findDecomposableBaseClass(S, Src->getLocation(), OrigRD, BasePath);
const CXXRecordDecl *RD = cast_or_null<CXXRecordDecl>(BasePair.getDecl());
if (!RD)
return true;
QualType BaseType = S.Context.getQualifiedType(S.Context.getRecordType(RD),
DecompType.getQualifiers());
auto DiagnoseBadNumberOfBindings = [&]() -> bool {
unsigned NumFields =
std::count_if(RD->field_begin(), RD->field_end(),
[](FieldDecl *FD) { return !FD->isUnnamedBitfield(); });
assert(Bindings.size() != NumFields);
S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
<< DecompType << (unsigned)Bindings.size() << NumFields
<< (NumFields < Bindings.size());
return true;
};
// all of E's non-static data members shall be [...] well-formed
// when named as e.name in the context of the structured binding,
// E shall not have an anonymous union member, ...
unsigned I = 0;
for (auto *FD : RD->fields()) {
if (FD->isUnnamedBitfield())
continue;
if (FD->isAnonymousStructOrUnion()) {
S.Diag(Src->getLocation(), diag::err_decomp_decl_anon_union_member)
<< DecompType << FD->getType()->isUnionType();
S.Diag(FD->getLocation(), diag::note_declared_at);
return true;
}
// We have a real field to bind.
if (I >= Bindings.size())
return DiagnoseBadNumberOfBindings();
auto *B = Bindings[I++];
SourceLocation Loc = B->getLocation();
// The field must be accessible in the context of the structured binding.
// We already checked that the base class is accessible.
// FIXME: Add 'const' to AccessedEntity's classes so we can remove the
// const_cast here.
S.CheckStructuredBindingMemberAccess(
Loc, const_cast<CXXRecordDecl *>(OrigRD),
DeclAccessPair::make(FD, CXXRecordDecl::MergeAccess(
BasePair.getAccess(), FD->getAccess())));
// Initialize the binding to Src.FD.
ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc);
if (E.isInvalid())
return true;
E = S.ImpCastExprToType(E.get(), BaseType, CK_UncheckedDerivedToBase,
VK_LValue, &BasePath);
if (E.isInvalid())
return true;
E = S.BuildFieldReferenceExpr(E.get(), /*IsArrow*/ false, Loc,
CXXScopeSpec(), FD,
DeclAccessPair::make(FD, FD->getAccess()),
DeclarationNameInfo(FD->getDeclName(), Loc));
if (E.isInvalid())
return true;
// If the type of the member is T, the referenced type is cv T, where cv is
// the cv-qualification of the decomposition expression.
//
// FIXME: We resolve a defect here: if the field is mutable, we do not add
// 'const' to the type of the field.
Qualifiers Q = DecompType.getQualifiers();
if (FD->isMutable())
Q.removeConst();
B->setBinding(S.BuildQualifiedType(FD->getType(), Loc, Q), E.get());
}
if (I != Bindings.size())
return DiagnoseBadNumberOfBindings();
return false;
}
void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) {
QualType DecompType = DD->getType();
// If the type of the decomposition is dependent, then so is the type of
// each binding.
if (DecompType->isDependentType()) {
for (auto *B : DD->bindings())
B->setType(Context.DependentTy);
return;
}
DecompType = DecompType.getNonReferenceType();
ArrayRef<BindingDecl*> Bindings = DD->bindings();
// C++1z [dcl.decomp]/2:
// If E is an array type [...]
// As an extension, we also support decomposition of built-in complex and
// vector types.
if (auto *CAT = Context.getAsConstantArrayType(DecompType)) {
if (checkArrayDecomposition(*this, Bindings, DD, DecompType, CAT))
DD->setInvalidDecl();
return;
}
if (auto *VT = DecompType->getAs<VectorType>()) {
if (checkVectorDecomposition(*this, Bindings, DD, DecompType, VT))
DD->setInvalidDecl();
return;
}
if (auto *CT = DecompType->getAs<ComplexType>()) {
if (checkComplexDecomposition(*this, Bindings, DD, DecompType, CT))
DD->setInvalidDecl();
return;
}
// C++1z [dcl.decomp]/3:
// if the expression std::tuple_size<E>::value is a well-formed integral
// constant expression, [...]
llvm::APSInt TupleSize(32);
switch (isTupleLike(*this, DD->getLocation(), DecompType, TupleSize)) {
case IsTupleLike::Error:
DD->setInvalidDecl();
return;
case IsTupleLike::TupleLike:
if (checkTupleLikeDecomposition(*this, Bindings, DD, DecompType, TupleSize))
DD->setInvalidDecl();
return;
case IsTupleLike::NotTupleLike:
break;
}
// C++1z [dcl.dcl]/8:
// [E shall be of array or non-union class type]
CXXRecordDecl *RD = DecompType->getAsCXXRecordDecl();
if (!RD || RD->isUnion()) {
Diag(DD->getLocation(), diag::err_decomp_decl_unbindable_type)
<< DD << !RD << DecompType;
DD->setInvalidDecl();
return;
}
// C++1z [dcl.decomp]/4:
// all of E's non-static data members shall be [...] direct members of
// E or of the same unambiguous public base class of E, ...
if (checkMemberDecomposition(*this, Bindings, DD, DecompType, RD))
DD->setInvalidDecl();
}
/// Merge the exception specifications of two variable declarations.
///
/// This is called when there's a redeclaration of a VarDecl. The function
/// checks if the redeclaration might have an exception specification and
/// validates compatibility and merges the specs if necessary.
void Sema::MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old) {
// Shortcut if exceptions are disabled.
if (!getLangOpts().CXXExceptions)
return;
assert(Context.hasSameType(New->getType(), Old->getType()) &&
"Should only be called if types are otherwise the same.");
QualType NewType = New->getType();
QualType OldType = Old->getType();
// We're only interested in pointers and references to functions, as well
// as pointers to member functions.
if (const ReferenceType *R = NewType->getAs<ReferenceType>()) {
NewType = R->getPointeeType();
OldType = OldType->getAs<ReferenceType>()->getPointeeType();
} else if (const PointerType *P = NewType->getAs<PointerType>()) {
NewType = P->getPointeeType();
OldType = OldType->getAs<PointerType>()->getPointeeType();
} else if (const MemberPointerType *M = NewType->getAs<MemberPointerType>()) {
NewType = M->getPointeeType();
OldType = OldType->getAs<MemberPointerType>()->getPointeeType();
}
if (!NewType->isFunctionProtoType())
return;
// There's lots of special cases for functions. For function pointers, system
// libraries are hopefully not as broken so that we don't need these
// workarounds.
if (CheckEquivalentExceptionSpec(
OldType->getAs<FunctionProtoType>(), Old->getLocation(),
NewType->getAs<FunctionProtoType>(), New->getLocation())) {
New->setInvalidDecl();
}
}
/// CheckCXXDefaultArguments - Verify that the default arguments for a
/// function declaration are well-formed according to C++
/// [dcl.fct.default].
void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) {
unsigned NumParams = FD->getNumParams();
unsigned p;
// Find first parameter with a default argument
for (p = 0; p < NumParams; ++p) {
ParmVarDecl *Param = FD->getParamDecl(p);
if (Param->hasDefaultArg())
break;
}
// C++11 [dcl.fct.default]p4:
// In a given function declaration, each parameter subsequent to a parameter
// with a default argument shall have a default argument supplied in this or
// a previous declaration or shall be a function parameter pack. A default
// argument shall not be redefined by a later declaration (not even to the
// same value).
unsigned LastMissingDefaultArg = 0;
for (; p < NumParams; ++p) {
ParmVarDecl *Param = FD->getParamDecl(p);
if (!Param->hasDefaultArg() && !Param->isParameterPack()) {
if (Param->isInvalidDecl())
/* We already complained about this parameter. */;
else if (Param->getIdentifier())
Diag(Param->getLocation(),
diag::err_param_default_argument_missing_name)
<< Param->getIdentifier();
else
Diag(Param->getLocation(),
diag::err_param_default_argument_missing);
LastMissingDefaultArg = p;
}
}
if (LastMissingDefaultArg > 0) {
// Some default arguments were missing. Clear out all of the
// default arguments up to (and including) the last missing
// default argument, so that we leave the function parameters
// in a semantically valid state.
for (p = 0; p <= LastMissingDefaultArg; ++p) {
ParmVarDecl *Param = FD->getParamDecl(p);
if (Param->hasDefaultArg()) {
Param->setDefaultArg(nullptr);
}
}
}
}
// CheckConstexprParameterTypes - Check whether a function's parameter types
// are all literal types. If so, return true. If not, produce a suitable
// diagnostic and return false.
static bool CheckConstexprParameterTypes(Sema &SemaRef,
const FunctionDecl *FD) {
unsigned ArgIndex = 0;
const FunctionProtoType *FT = FD->getType()->getAs<FunctionProtoType>();
for (FunctionProtoType::param_type_iterator i = FT->param_type_begin(),
e = FT->param_type_end();
i != e; ++i, ++ArgIndex) {
const ParmVarDecl *PD = FD->getParamDecl(ArgIndex);
SourceLocation ParamLoc = PD->getLocation();
if (!(*i)->isDependentType() &&
SemaRef.RequireLiteralType(ParamLoc, *i,
diag::err_constexpr_non_literal_param,
ArgIndex+1, PD->getSourceRange(),
isa<CXXConstructorDecl>(FD)))
return false;
}
return true;
}
/// Get diagnostic %select index for tag kind for
/// record diagnostic message.
/// WARNING: Indexes apply to particular diagnostics only!
///
/// \returns diagnostic %select index.
static unsigned getRecordDiagFromTagKind(TagTypeKind Tag) {
switch (Tag) {
case TTK_Struct: return 0;
case TTK_Interface: return 1;
case TTK_Class: return 2;
default: llvm_unreachable("Invalid tag kind for record diagnostic!");
}
}
// CheckConstexprFunctionDecl - Check whether a function declaration satisfies
// the requirements of a constexpr function definition or a constexpr
// constructor definition. If so, return true. If not, produce appropriate
// diagnostics and return false.
//
// This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360.
bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) {
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
if (MD && MD->isInstance()) {
// C++11 [dcl.constexpr]p4:
// The definition of a constexpr constructor shall satisfy the following
// constraints:
// - the class shall not have any virtual base classes;
const CXXRecordDecl *RD = MD->getParent();
if (RD->getNumVBases()) {
Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base)
<< isa<CXXConstructorDecl>(NewFD)
<< getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
for (const auto &I : RD->vbases())
Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here)
<< I.getSourceRange();
return false;
}
}
if (!isa<CXXConstructorDecl>(NewFD)) {
// C++11 [dcl.constexpr]p3:
// The definition of a constexpr function shall satisfy the following
// constraints:
// - it shall not be virtual;
const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD);
if (Method && Method->isVirtual()) {
Method = Method->getCanonicalDecl();
Diag(Method->getLocation(), diag::err_constexpr_virtual);
// If it's not obvious why this function is virtual, find an overridden
// function which uses the 'virtual' keyword.
const CXXMethodDecl *WrittenVirtual = Method;
while (!WrittenVirtual->isVirtualAsWritten())
WrittenVirtual = *WrittenVirtual->begin_overridden_methods();
if (WrittenVirtual != Method)
Diag(WrittenVirtual->getLocation(),
diag::note_overridden_virtual_function);
return false;
}
// - its return type shall be a literal type;
QualType RT = NewFD->getReturnType();
if (!RT->isDependentType() &&
RequireLiteralType(NewFD->getLocation(), RT,
diag::err_constexpr_non_literal_return))
return false;
}
// - each of its parameter types shall be a literal type;
if (!CheckConstexprParameterTypes(*this, NewFD))
return false;
return true;
}
/// Check the given declaration statement is legal within a constexpr function
/// body. C++11 [dcl.constexpr]p3,p4, and C++1y [dcl.constexpr]p3.
///
/// \return true if the body is OK (maybe only as an extension), false if we
/// have diagnosed a problem.
static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
DeclStmt *DS, SourceLocation &Cxx1yLoc) {
// C++11 [dcl.constexpr]p3 and p4:
// The definition of a constexpr function(p3) or constructor(p4) [...] shall
// contain only
for (const auto *DclIt : DS->decls()) {
switch (DclIt->getKind()) {
case Decl::StaticAssert:
case Decl::Using:
case Decl::UsingShadow:
case Decl::UsingDirective:
case Decl::UnresolvedUsingTypename:
case Decl::UnresolvedUsingValue:
// - static_assert-declarations
// - using-declarations,
// - using-directives,
continue;
case Decl::Typedef:
case Decl::TypeAlias: {
// - typedef declarations and alias-declarations that do not define
// classes or enumerations,
const auto *TN = cast<TypedefNameDecl>(DclIt);
if (TN->getUnderlyingType()->isVariablyModifiedType()) {
// Don't allow variably-modified types in constexpr functions.
TypeLoc TL = TN->getTypeSourceInfo()->getTypeLoc();
SemaRef.Diag(TL.getBeginLoc(), diag::err_constexpr_vla)
<< TL.getSourceRange() << TL.getType()
<< isa<CXXConstructorDecl>(Dcl);
return false;
}
continue;
}
case Decl::Enum:
case Decl::CXXRecord:
// C++1y allows types to be defined, not just declared.
if (cast<TagDecl>(DclIt)->isThisDeclarationADefinition())
SemaRef.Diag(DS->getBeginLoc(),
SemaRef.getLangOpts().CPlusPlus14
? diag::warn_cxx11_compat_constexpr_type_definition
: diag::ext_constexpr_type_definition)
<< isa<CXXConstructorDecl>(Dcl);
continue;
case Decl::EnumConstant:
case Decl::IndirectField:
case Decl::ParmVar:
// These can only appear with other declarations which are banned in
// C++11 and permitted in C++1y, so ignore them.
continue;
case Decl::Var:
case Decl::Decomposition: {
// C++1y [dcl.constexpr]p3 allows anything except:
// a definition of a variable of non-literal type or of static or
// thread storage duration or for which no initialization is performed.
const auto *VD = cast<VarDecl>(DclIt);
if (VD->isThisDeclarationADefinition()) {
if (VD->isStaticLocal()) {
SemaRef.Diag(VD->getLocation(),
diag::err_constexpr_local_var_static)
<< isa<CXXConstructorDecl>(Dcl)
<< (VD->getTLSKind() == VarDecl::TLS_Dynamic);
return false;
}
if (!VD->getType()->isDependentType() &&
SemaRef.RequireLiteralType(
VD->getLocation(), VD->getType(),
diag::err_constexpr_local_var_non_literal_type,
isa<CXXConstructorDecl>(Dcl)))
return false;
if (!VD->getType()->isDependentType() &&
!VD->hasInit() && !VD->isCXXForRangeDecl()) {
SemaRef.Diag(VD->getLocation(),
diag::err_constexpr_local_var_no_init)
<< isa<CXXConstructorDecl>(Dcl);
return false;
}
}
SemaRef.Diag(VD->getLocation(),
SemaRef.getLangOpts().CPlusPlus14
? diag::warn_cxx11_compat_constexpr_local_var
: diag::ext_constexpr_local_var)
<< isa<CXXConstructorDecl>(Dcl);
continue;
}
case Decl::NamespaceAlias:
case Decl::Function:
// These are disallowed in C++11 and permitted in C++1y. Allow them
// everywhere as an extension.
if (!Cxx1yLoc.isValid())
Cxx1yLoc = DS->getBeginLoc();
continue;
default:
SemaRef.Diag(DS->getBeginLoc(), diag::err_constexpr_body_invalid_stmt)
<< isa<CXXConstructorDecl>(Dcl);
return false;
}
}
return true;
}
/// Check that the given field is initialized within a constexpr constructor.
///
/// \param Dcl The constexpr constructor being checked.
/// \param Field The field being checked. This may be a member of an anonymous
/// struct or union nested within the class being checked.
/// \param Inits All declarations, including anonymous struct/union members and
/// indirect members, for which any initialization was provided.
/// \param Diagnosed Set to true if an error is produced.
static void CheckConstexprCtorInitializer(Sema &SemaRef,
const FunctionDecl *Dcl,
FieldDecl *Field,
llvm::SmallSet<Decl*, 16> &Inits,
bool &Diagnosed) {
if (Field->isInvalidDecl())
return;
if (Field->isUnnamedBitfield())
return;
// Anonymous unions with no variant members and empty anonymous structs do not
// need to be explicitly initialized. FIXME: Anonymous structs that contain no
// indirect fields don't need initializing.
if (Field->isAnonymousStructOrUnion() &&
(Field->getType()->isUnionType()
? !Field->getType()->getAsCXXRecordDecl()->hasVariantMembers()
: Field->getType()->getAsCXXRecordDecl()->isEmpty()))
return;
if (!Inits.count(Field)) {
if (!Diagnosed) {
SemaRef.Diag(Dcl->getLocation(), diag::err_constexpr_ctor_missing_init);
Diagnosed = true;
}
SemaRef.Diag(Field->getLocation(), diag::note_constexpr_ctor_missing_init);
} else if (Field->isAnonymousStructOrUnion()) {
const RecordDecl *RD = Field->getType()->castAs<RecordType>()->getDecl();
for (auto *I : RD->fields())
// If an anonymous union contains an anonymous struct of which any member
// is initialized, all members must be initialized.
if (!RD->isUnion() || Inits.count(I))
CheckConstexprCtorInitializer(SemaRef, Dcl, I, Inits, Diagnosed);
}
}
/// Check the provided statement is allowed in a constexpr function
/// definition.
static bool
CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
SmallVectorImpl<SourceLocation> &ReturnStmts,
SourceLocation &Cxx1yLoc, SourceLocation &Cxx2aLoc) {
// - its function-body shall be [...] a compound-statement that contains only
switch (S->getStmtClass()) {
case Stmt::NullStmtClass:
// - null statements,
return true;
case Stmt::DeclStmtClass:
// - static_assert-declarations
// - using-declarations,
// - using-directives,
// - typedef declarations and alias-declarations that do not define
// classes or enumerations,
if (!CheckConstexprDeclStmt(SemaRef, Dcl, cast<DeclStmt>(S), Cxx1yLoc))
return false;
return true;
case Stmt::ReturnStmtClass:
// - and exactly one return statement;
if (isa<CXXConstructorDecl>(Dcl)) {
// C++1y allows return statements in constexpr constructors.
if (!Cxx1yLoc.isValid())
Cxx1yLoc = S->getBeginLoc();
return true;
}
ReturnStmts.push_back(S->getBeginLoc());
return true;
case Stmt::CompoundStmtClass: {
// C++1y allows compound-statements.
if (!Cxx1yLoc.isValid())
Cxx1yLoc = S->getBeginLoc();
CompoundStmt *CompStmt = cast<CompoundStmt>(S);
for (auto *BodyIt : CompStmt->body()) {
if (!CheckConstexprFunctionStmt(SemaRef, Dcl, BodyIt, ReturnStmts,
Cxx1yLoc, Cxx2aLoc))
return false;
}
return true;
}
case Stmt::AttributedStmtClass:
if (!Cxx1yLoc.isValid())
Cxx1yLoc = S->getBeginLoc();
return true;
case Stmt::IfStmtClass: {
// C++1y allows if-statements.
if (!Cxx1yLoc.isValid())
Cxx1yLoc = S->getBeginLoc();
IfStmt *If = cast<IfStmt>(S);
if (!CheckConstexprFunctionStmt(SemaRef, Dcl, If->getThen(), ReturnStmts,
Cxx1yLoc, Cxx2aLoc))
return false;
if (If->getElse() &&
!CheckConstexprFunctionStmt(SemaRef, Dcl, If->getElse(), ReturnStmts,
Cxx1yLoc, Cxx2aLoc))
return false;
return true;
}
case Stmt::WhileStmtClass:
case Stmt::DoStmtClass:
case Stmt::ForStmtClass:
case Stmt::CXXForRangeStmtClass:
case Stmt::ContinueStmtClass:
// C++1y allows all of these. We don't allow them as extensions in C++11,
// because they don't make sense without variable mutation.
if (!SemaRef.getLangOpts().CPlusPlus14)
break;
if (!Cxx1yLoc.isValid())
Cxx1yLoc = S->getBeginLoc();
for (Stmt *SubStmt : S->children())
if (SubStmt &&
!CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
Cxx1yLoc, Cxx2aLoc))
return false;
return true;
case Stmt::SwitchStmtClass:
case Stmt::CaseStmtClass:
case Stmt::DefaultStmtClass:
case Stmt::BreakStmtClass:
// C++1y allows switch-statements, and since they don't need variable
// mutation, we can reasonably allow them in C++11 as an extension.
if (!Cxx1yLoc.isValid())
Cxx1yLoc = S->getBeginLoc();
for (Stmt *SubStmt : S->children())
if (SubStmt &&
!CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
Cxx1yLoc, Cxx2aLoc))
return false;
return true;
case Stmt::CXXTryStmtClass:
if (Cxx2aLoc.isInvalid())
Cxx2aLoc = S->getBeginLoc();
for (Stmt *SubStmt : S->children()) {
if (SubStmt &&
!CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
Cxx1yLoc, Cxx2aLoc))
return false;
}
return true;
case Stmt::CXXCatchStmtClass:
// Do not bother checking the language mode (already covered by the
// try block check).
if (!CheckConstexprFunctionStmt(SemaRef, Dcl,
cast<CXXCatchStmt>(S)->getHandlerBlock(),
ReturnStmts, Cxx1yLoc, Cxx2aLoc))
return false;
return true;
default:
if (!isa<Expr>(S))
break;
// C++1y allows expression-statements.
if (!Cxx1yLoc.isValid())
Cxx1yLoc = S->getBeginLoc();
return true;
}
SemaRef.Diag(S->getBeginLoc(), diag::err_constexpr_body_invalid_stmt)
<< isa<CXXConstructorDecl>(Dcl);
return false;
}
/// Check the body for the given constexpr function declaration only contains
/// the permitted types of statement. C++11 [dcl.constexpr]p3,p4.
///
/// \return true if the body is OK, false if we have diagnosed a problem.
bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
SmallVector<SourceLocation, 4> ReturnStmts;
if (isa<CXXTryStmt>(Body)) {
// C++11 [dcl.constexpr]p3:
// The definition of a constexpr function shall satisfy the following
// constraints: [...]
// - its function-body shall be = delete, = default, or a
// compound-statement
//
// C++11 [dcl.constexpr]p4:
// In the definition of a constexpr constructor, [...]
// - its function-body shall not be a function-try-block;
//
// This restriction is lifted in C++2a, as long as inner statements also
// apply the general constexpr rules.
Diag(Body->getBeginLoc(),
!getLangOpts().CPlusPlus2a
? diag::ext_constexpr_function_try_block_cxx2a
: diag::warn_cxx17_compat_constexpr_function_try_block)
<< isa<CXXConstructorDecl>(Dcl);
}
// - its function-body shall be [...] a compound-statement that contains only
// [... list of cases ...]
//
// Note that walking the children here is enough to properly check for
// CompoundStmt and CXXTryStmt body.
SourceLocation Cxx1yLoc, Cxx2aLoc;
for (Stmt *SubStmt : Body->children()) {
if (SubStmt &&
!CheckConstexprFunctionStmt(*this, Dcl, SubStmt, ReturnStmts,
Cxx1yLoc, Cxx2aLoc))
return false;
}
if (Cxx2aLoc.isValid())
Diag(Cxx2aLoc,
getLangOpts().CPlusPlus2a
? diag::warn_cxx17_compat_constexpr_body_invalid_stmt
: diag::ext_constexpr_body_invalid_stmt_cxx2a)
<< isa<CXXConstructorDecl>(Dcl);
if (Cxx1yLoc.isValid())
Diag(Cxx1yLoc,
getLangOpts().CPlusPlus14
? diag::warn_cxx11_compat_constexpr_body_invalid_stmt
: diag::ext_constexpr_body_invalid_stmt)
<< isa<CXXConstructorDecl>(Dcl);
if (const CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(Dcl)) {
const CXXRecordDecl *RD = Constructor->getParent();
// DR1359:
// - every non-variant non-static data member and base class sub-object
// shall be initialized;
// DR1460:
// - if the class is a union having variant members, exactly one of them
// shall be initialized;
if (RD->isUnion()) {
if (Constructor->getNumCtorInitializers() == 0 &&
RD->hasVariantMembers()) {
Diag(Dcl->getLocation(), diag::err_constexpr_union_ctor_no_init);
return false;
}
} else if (!Constructor->isDependentContext() &&
!Constructor->isDelegatingConstructor()) {
assert(RD->getNumVBases() == 0 && "constexpr ctor with virtual bases");
// Skip detailed checking if we have enough initializers, and we would
// allow at most one initializer per member.
bool AnyAnonStructUnionMembers = false;
unsigned Fields = 0;
for (CXXRecordDecl::field_iterator I = RD->field_begin(),
E = RD->field_end(); I != E; ++I, ++Fields) {
if (I->isAnonymousStructOrUnion()) {
AnyAnonStructUnionMembers = true;
break;
}
}
// DR1460:
// - if the class is a union-like class, but is not a union, for each of
// its anonymous union members having variant members, exactly one of
// them shall be initialized;
if (AnyAnonStructUnionMembers ||
Constructor->getNumCtorInitializers() != RD->getNumBases() + Fields) {
// Check initialization of non-static data members. Base classes are
// always initialized so do not need to be checked. Dependent bases
// might not have initializers in the member initializer list.
llvm::SmallSet<Decl*, 16> Inits;
for (const auto *I: Constructor->inits()) {
if (FieldDecl *FD = I->getMember())
Inits.insert(FD);
else if (IndirectFieldDecl *ID = I->getIndirectMember())
Inits.insert(ID->chain_begin(), ID->chain_end());
}
bool Diagnosed = false;
for (auto *I : RD->fields())
CheckConstexprCtorInitializer(*this, Dcl, I, Inits, Diagnosed);
if (Diagnosed)
return false;
}
}
} else {
if (ReturnStmts.empty()) {
// C++1y doesn't require constexpr functions to contain a 'return'
// statement. We still do, unless the return type might be void, because
// otherwise if there's no return statement, the function cannot
// be used in a core constant expression.
bool OK = getLangOpts().CPlusPlus14 &&
(Dcl->getReturnType()->isVoidType() ||
Dcl->getReturnType()->isDependentType());
Diag(Dcl->getLocation(),
OK ? diag::warn_cxx11_compat_constexpr_body_no_return
: diag::err_constexpr_body_no_return);
if (!OK)
return false;
} else if (ReturnStmts.size() > 1) {
Diag(ReturnStmts.back(),
getLangOpts().CPlusPlus14
? diag::warn_cxx11_compat_constexpr_body_multiple_return
: diag::ext_constexpr_body_multiple_return);
for (unsigned I = 0; I < ReturnStmts.size() - 1; ++I)
Diag(ReturnStmts[I], diag::note_constexpr_body_previous_return);
}
}
// C++11 [dcl.constexpr]p5:
// if no function argument values exist such that the function invocation
// substitution would produce a constant expression, the program is
// ill-formed; no diagnostic required.
// C++11 [dcl.constexpr]p3:
// - every constructor call and implicit conversion used in initializing the
// return value shall be one of those allowed in a constant expression.
// C++11 [dcl.constexpr]p4:
// - every constructor involved in initializing non-static data members and
// base class sub-objects shall be a constexpr constructor.
SmallVector<PartialDiagnosticAt, 8> Diags;
if (!Expr::isPotentialConstantExpr(Dcl, Diags)) {
Diag(Dcl->getLocation(), diag::ext_constexpr_function_never_constant_expr)
<< isa<CXXConstructorDecl>(Dcl);
for (size_t I = 0, N = Diags.size(); I != N; ++I)
Diag(Diags[I].first, Diags[I].second);
// Don't return false here: we allow this for compatibility in
// system headers.
}
return true;
}
/// Get the class that is directly named by the current context. This is the
/// class for which an unqualified-id in this scope could name a constructor
/// or destructor.
///
/// If the scope specifier denotes a class, this will be that class.
/// If the scope specifier is empty, this will be the class whose
/// member-specification we are currently within. Otherwise, there
/// is no such class.
CXXRecordDecl *Sema::getCurrentClass(Scope *, const CXXScopeSpec *SS) {
assert(getLangOpts().CPlusPlus && "No class names in C!");
if (SS && SS->isInvalid())
return nullptr;
if (SS && SS->isNotEmpty()) {
DeclContext *DC = computeDeclContext(*SS, true);
return dyn_cast_or_null<CXXRecordDecl>(DC);
}
return dyn_cast_or_null<CXXRecordDecl>(CurContext);
}
/// isCurrentClassName - Determine whether the identifier II is the
/// name of the class type currently being defined. In the case of
/// nested classes, this will only return true if II is the name of
/// the innermost class.
bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS) {
CXXRecordDecl *CurDecl = getCurrentClass(S, SS);
return CurDecl && &II == CurDecl->getIdentifier();
}
/// Determine whether the identifier II is a typo for the name of
/// the class type currently being defined. If so, update it to the identifier
/// that should have been used.
bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) {
assert(getLangOpts().CPlusPlus && "No class names in C!");
if (!getLangOpts().SpellChecking)
return false;
CXXRecordDecl *CurDecl;
if (SS && SS->isSet() && !SS->isInvalid()) {
DeclContext *DC = computeDeclContext(*SS, true);
CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC);
} else
CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
if (CurDecl && CurDecl->getIdentifier() && II != CurDecl->getIdentifier() &&
3 * II->getName().edit_distance(CurDecl->getIdentifier()->getName())
< II->getLength()) {
II = CurDecl->getIdentifier();
return true;
}
return false;
}
/// Determine whether the given class is a base class of the given
/// class, including looking at dependent bases.
static bool findCircularInheritance(const CXXRecordDecl *Class,
const CXXRecordDecl *Current) {
SmallVector<const CXXRecordDecl*, 8> Queue;
Class = Class->getCanonicalDecl();
while (true) {
for (const auto &I : Current->bases()) {
CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
if (!Base)
continue;
Base = Base->getDefinition();
if (!Base)
continue;
if (Base->getCanonicalDecl() == Class)
return true;
Queue.push_back(Base);
}
if (Queue.empty())
return false;
Current = Queue.pop_back_val();
}
return false;
}
/// Check the validity of a C++ base class specifier.
///
/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics
/// and returns NULL otherwise.
CXXBaseSpecifier *
Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
TypeSourceInfo *TInfo,
SourceLocation EllipsisLoc) {
QualType BaseType = TInfo->getType();
// C++ [class.union]p1:
// A union shall not have base classes.
if (Class->isUnion()) {
Diag(Class->getLocation(), diag::err_base_clause_on_union)
<< SpecifierRange;
return nullptr;
}
if (EllipsisLoc.isValid() &&
!TInfo->getType()->containsUnexpandedParameterPack()) {
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
<< TInfo->getTypeLoc().getSourceRange();
EllipsisLoc = SourceLocation();
}
SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc();
if (BaseType->isDependentType()) {
// Make sure that we don't have circular inheritance among our dependent
// bases. For non-dependent bases, the check for completeness below handles
// this.
if (CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl()) {
if (BaseDecl->getCanonicalDecl() == Class->getCanonicalDecl() ||
((BaseDecl = BaseDecl->getDefinition()) &&
findCircularInheritance(Class, BaseDecl))) {
Diag(BaseLoc, diag::err_circular_inheritance)
<< BaseType << Context.getTypeDeclType(Class);
if (BaseDecl->getCanonicalDecl() != Class->getCanonicalDecl())
Diag(BaseDecl->getLocation(), diag::note_previous_decl)
<< BaseType;
return nullptr;
}
}
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
Class->getTagKind() == TTK_Class,
Access, TInfo, EllipsisLoc);
}
// Base specifiers must be record types.
if (!BaseType->isRecordType()) {
Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange;
return nullptr;
}
// C++ [class.union]p1:
// A union shall not be used as a base class.
if (BaseType->isUnionType()) {
Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange;
return nullptr;
}
// For the MS ABI, propagate DLL attributes to base class templates.
if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
if (Attr *ClassAttr = getDLLAttr(Class)) {
if (auto *BaseTemplate = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
BaseType->getAsCXXRecordDecl())) {
propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseTemplate,
BaseLoc);
}
}
}
// C++ [class.derived]p2:
// The class-name in a base-specifier shall not be an incompletely
// defined class.
if (RequireCompleteType(BaseLoc, BaseType,
diag::err_incomplete_base_class, SpecifierRange)) {
Class->setInvalidDecl();
return nullptr;
}
// If the base class is polymorphic or isn't empty, the new one is/isn't, too.
RecordDecl *BaseDecl = BaseType->getAs<RecordType>()->getDecl();
assert(BaseDecl && "Record type has no declaration");
BaseDecl = BaseDecl->getDefinition();
assert(BaseDecl && "Base type is not incomplete, but has no definition");
CXXRecordDecl *CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
assert(CXXBaseDecl && "Base type is not a C++ type");
// Microsoft docs say:
// "If a base-class has a code_seg attribute, derived classes must have the
// same attribute."
const auto *BaseCSA = CXXBaseDecl->getAttr<CodeSegAttr>();
const auto *DerivedCSA = Class->getAttr<CodeSegAttr>();
if ((DerivedCSA || BaseCSA) &&
(!BaseCSA || !DerivedCSA || BaseCSA->getName() != DerivedCSA->getName())) {
Diag(Class->getLocation(), diag::err_mismatched_code_seg_base);
Diag(CXXBaseDecl->getLocation(), diag::note_base_class_specified_here)
<< CXXBaseDecl;
return nullptr;
}
// A class which contains a flexible array member is not suitable for use as a
// base class:
// - If the layout determines that a base comes before another base,
// the flexible array member would index into the subsequent base.
// - If the layout determines that base comes before the derived class,
// the flexible array member would index into the derived class.
if (CXXBaseDecl->hasFlexibleArrayMember()) {
Diag(BaseLoc, diag::err_base_class_has_flexible_array_member)
<< CXXBaseDecl->getDeclName();
return nullptr;
}
// C++ [class]p3:
// If a class is marked final and it appears as a base-type-specifier in
// base-clause, the program is ill-formed.
if (FinalAttr *FA = CXXBaseDecl->getAttr<FinalAttr>()) {
Diag(BaseLoc, diag::err_class_marked_final_used_as_base)
<< CXXBaseDecl->getDeclName()
<< FA->isSpelledAsSealed();
Diag(CXXBaseDecl->getLocation(), diag::note_entity_declared_at)
<< CXXBaseDecl->getDeclName() << FA->getRange();
return nullptr;
}
if (BaseDecl->isInvalidDecl())
Class->setInvalidDecl();
// Create the base specifier.
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
Class->getTagKind() == TTK_Class,
Access, TInfo, EllipsisLoc);
}
/// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is
/// one entry in the base class list of a class specifier, for
/// example:
/// class foo : public bar, virtual private baz {
/// 'public bar' and 'virtual private baz' are each base-specifiers.
BaseResult
Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
ParsedAttributes &Attributes,
bool Virtual, AccessSpecifier Access,
ParsedType basetype, SourceLocation BaseLoc,
SourceLocation EllipsisLoc) {
if (!classdecl)
return true;
AdjustDeclIfTemplate(classdecl);
CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(classdecl);
if (!Class)
return true;
// We haven't yet attached the base specifiers.
Class->setIsParsingBaseSpecifiers();
// We do not support any C++11 attributes on base-specifiers yet.
// Diagnose any attributes we see.
for (const ParsedAttr &AL : Attributes) {
if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute)
continue;
Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute
? (unsigned)diag::warn_unknown_attribute_ignored
: (unsigned)diag::err_base_specifier_attribute)
<< AL.getName();
}
TypeSourceInfo *TInfo = nullptr;
GetTypeFromParser(basetype, &TInfo);
if (EllipsisLoc.isInvalid() &&
DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo,
UPPC_BaseType))
return true;
if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange,
Virtual, Access, TInfo,
EllipsisLoc))
return BaseSpec;
else
Class->setInvalidDecl();
return true;
}
/// Use small set to collect indirect bases. As this is only used
/// locally, there's no need to abstract the small size parameter.
typedef llvm::SmallPtrSet<QualType, 4> IndirectBaseSet;
/// Recursively add the bases of Type. Don't add Type itself.
static void
NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set,
const QualType &Type)
{
// Even though the incoming type is a base, it might not be
// a class -- it could be a template parm, for instance.
if (auto Rec = Type->getAs<RecordType>()) {
auto Decl = Rec->getAsCXXRecordDecl();
// Iterate over its bases.
for (const auto &BaseSpec : Decl->bases()) {
QualType Base = Context.getCanonicalType(BaseSpec.getType())
.getUnqualifiedType();
if (Set.insert(Base).second)
// If we've not already seen it, recurse.
NoteIndirectBases(Context, Set, Base);
}
}
}
/// Performs the actual work of attaching the given base class
/// specifiers to a C++ class.
bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
MutableArrayRef<CXXBaseSpecifier *> Bases) {
if (Bases.empty())
return false;
// Used to keep track of which base types we have already seen, so
// that we can properly diagnose redundant direct base types. Note
// that the key is always the unqualified canonical type of the base
// class.
std::map<QualType, CXXBaseSpecifier*, QualTypeOrdering> KnownBaseTypes;
// Used to track indirect bases so we can see if a direct base is
// ambiguous.
IndirectBaseSet IndirectBaseTypes;
// Copy non-redundant base specifiers into permanent storage.
unsigned NumGoodBases = 0;
bool Invalid = false;
for (unsigned idx = 0; idx < Bases.size(); ++idx) {
QualType NewBaseType
= Context.getCanonicalType(Bases[idx]->getType());
NewBaseType = NewBaseType.getLocalUnqualifiedType();
CXXBaseSpecifier *&KnownBase = KnownBaseTypes[NewBaseType];
if (KnownBase) {
// C++ [class.mi]p3:
// A class shall not be specified as a direct base class of a
// derived class more than once.
Diag(Bases[idx]->getBeginLoc(), diag::err_duplicate_base_class)
<< KnownBase->getType() << Bases[idx]->getSourceRange();
// Delete the duplicate base class specifier; we're going to
// overwrite its pointer later.
Context.Deallocate(Bases[idx]);
Invalid = true;
} else {
// Okay, add this new base class.
KnownBase = Bases[idx];
Bases[NumGoodBases++] = Bases[idx];
// Note this base's direct & indirect bases, if there could be ambiguity.
if (Bases.size() > 1)
NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType);
if (const RecordType *Record = NewBaseType->getAs<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
if (Class->isInterface() &&
(!RD->isInterfaceLike() ||
KnownBase->getAccessSpecifier() != AS_public)) {
// The Microsoft extension __interface does not permit bases that
// are not themselves public interfaces.
Diag(KnownBase->getBeginLoc(), diag::err_invalid_base_in_interface)
<< getRecordDiagFromTagKind(RD->getTagKind()) << RD
<< RD->getSourceRange();
Invalid = true;
}
if (RD->hasAttr<WeakAttr>())
Class->addAttr(WeakAttr::CreateImplicit(Context));
}
}
}
// Attach the remaining base class specifiers to the derived class.
Class->setBases(Bases.data(), NumGoodBases);
// Check that the only base classes that are duplicate are virtual.
for (unsigned idx = 0; idx < NumGoodBases; ++idx) {
// Check whether this direct base is inaccessible due to ambiguity.
QualType BaseType = Bases[idx]->getType();
// Skip all dependent types in templates being used as base specifiers.
// Checks below assume that the base specifier is a CXXRecord.
if (BaseType->isDependentType())
continue;
CanQualType CanonicalBase = Context.getCanonicalType(BaseType)
.getUnqualifiedType();
if (IndirectBaseTypes.count(CanonicalBase)) {
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/true);
bool found
= Class->isDerivedFrom(CanonicalBase->getAsCXXRecordDecl(), Paths);
assert(found);
(void)found;
if (Paths.isAmbiguous(CanonicalBase))
Diag(Bases[idx]->getBeginLoc(), diag::warn_inaccessible_base_class)
<< BaseType << getAmbiguousPathsDisplayString(Paths)
<< Bases[idx]->getSourceRange();
else
assert(Bases[idx]->isVirtual());
}
// Delete the base class specifier, since its data has been copied
// into the CXXRecordDecl.
Context.Deallocate(Bases[idx]);
}
return Invalid;
}
/// ActOnBaseSpecifiers - Attach the given base specifiers to the
/// class, after checking whether there are any duplicate base
/// classes.
void Sema::ActOnBaseSpecifiers(Decl *ClassDecl,
MutableArrayRef<CXXBaseSpecifier *> Bases) {
if (!ClassDecl || Bases.empty())
return;
AdjustDeclIfTemplate(ClassDecl);
AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases);
}
/// Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) {
if (!getLangOpts().CPlusPlus)
return false;
CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl();
if (!DerivedRD)
return false;
CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl();
if (!BaseRD)
return false;
// If either the base or the derived type is invalid, don't try to
// check whether one is derived from the other.
if (BaseRD->isInvalidDecl() || DerivedRD->isInvalidDecl())
return false;
// FIXME: In a modules build, do we need the entire path to be visible for us
// to be able to use the inheritance relationship?
if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined())
return false;
return DerivedRD->isDerivedFrom(BaseRD);
}
/// Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
CXXBasePaths &Paths) {
if (!getLangOpts().CPlusPlus)
return false;
CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl();
if (!DerivedRD)
return false;
CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl();
if (!BaseRD)
return false;
if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined())
return false;
return DerivedRD->isDerivedFrom(BaseRD, Paths);
}
static void BuildBasePathArray(const CXXBasePath &Path,
CXXCastPath &BasePathArray) {
// We first go backward and check if we have a virtual base.
// FIXME: It would be better if CXXBasePath had the base specifier for
// the nearest virtual base.
unsigned Start = 0;
for (unsigned I = Path.size(); I != 0; --I) {
if (Path[I - 1].Base->isVirtual()) {
Start = I - 1;
break;
}
}
// Now add all bases.
for (unsigned I = Start, E = Path.size(); I != E; ++I)
BasePathArray.push_back(const_cast<CXXBaseSpecifier*>(Path[I].Base));
}
void Sema::BuildBasePathArray(const CXXBasePaths &Paths,
CXXCastPath &BasePathArray) {
assert(BasePathArray.empty() && "Base path array must be empty!");
assert(Paths.isRecordingPaths() && "Must record paths!");
return ::BuildBasePathArray(Paths.front(), BasePathArray);
}
/// CheckDerivedToBaseConversion - Check whether the Derived-to-Base
/// conversion (where Derived and Base are class types) is
/// well-formed, meaning that the conversion is unambiguous (and
/// that all of the base classes are accessible). Returns true
/// and emits a diagnostic if the code is ill-formed, returns false
/// otherwise. Loc is the location where this routine should point to
/// if there is an error, and Range is the source range to highlight
/// if there is an error.
///
/// If either InaccessibleBaseID or AmbigiousBaseConvID are 0, then the
/// diagnostic for the respective type of error will be suppressed, but the
/// check for ill-formed code will still be performed.
bool
Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
unsigned InaccessibleBaseID,
unsigned AmbigiousBaseConvID,
SourceLocation Loc, SourceRange Range,
DeclarationName Name,
CXXCastPath *BasePath,
bool IgnoreAccess) {
// First, determine whether the path from Derived to Base is
// ambiguous. This is slightly more expensive than checking whether
// the Derived to Base conversion exists, because here we need to
// explore multiple paths to determine if there is an ambiguity.
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/false);
bool DerivationOkay = IsDerivedFrom(Loc, Derived, Base, Paths);
if (!DerivationOkay)
return true;
const CXXBasePath *Path = nullptr;
if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType()))
Path = &Paths.front();
// For MSVC compatibility, check if Derived directly inherits from Base. Clang
// warns about this hierarchy under -Winaccessible-base, but MSVC allows the
// user to access such bases.
if (!Path && getLangOpts().MSVCCompat) {
for (const CXXBasePath &PossiblePath : Paths) {
if (PossiblePath.size() == 1) {
Path = &PossiblePath;
if (AmbigiousBaseConvID)
Diag(Loc, diag::ext_ms_ambiguous_direct_base)
<< Base << Derived << Range;
break;
}
}
}
if (Path) {
if (!IgnoreAccess) {
// Check that the base class can be accessed.
switch (
CheckBaseClassAccess(Loc, Base, Derived, *Path, InaccessibleBaseID)) {
case AR_inaccessible:
return true;
case AR_accessible:
case AR_dependent:
case AR_delayed:
break;
}
}
// Build a base path if necessary.
if (BasePath)
::BuildBasePathArray(*Path, *BasePath);
return false;
}
if (AmbigiousBaseConvID) {
// We know that the derived-to-base conversion is ambiguous, and
// we're going to produce a diagnostic. Perform the derived-to-base
// search just one more time to compute all of the possible paths so
// that we can print them out. This is more expensive than any of
// the previous derived-to-base checks we've done, but at this point
// performance isn't as much of an issue.
Paths.clear();
Paths.setRecordingPaths(true);
bool StillOkay = IsDerivedFrom(Loc, Derived, Base, Paths);
assert(StillOkay && "Can only be used with a derived-to-base conversion");
(void)StillOkay;
// Build up a textual representation of the ambiguous paths, e.g.,
// D -> B -> A, that will be used to illustrate the ambiguous
// conversions in the diagnostic. We only print one of the paths
// to each base class subobject.
std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
Diag(Loc, AmbigiousBaseConvID)
<< Derived << Base << PathDisplayStr << Range << Name;
}
return true;
}
bool
Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
SourceLocation Loc, SourceRange Range,
CXXCastPath *BasePath,
bool IgnoreAccess) {
return CheckDerivedToBaseConversion(
Derived, Base, diag::err_upcast_to_inaccessible_base,
diag::err_ambiguous_derived_to_base_conv, Loc, Range, DeclarationName(),
BasePath, IgnoreAccess);
}
/// Builds a string representing ambiguous paths from a
/// specific derived class to different subobjects of the same base
/// class.
///
/// This function builds a string that can be used in error messages
/// to show the different paths that one can take through the
/// inheritance hierarchy to go from the derived class to different
/// subobjects of a base class. The result looks something like this:
/// @code
/// struct D -> struct B -> struct A
/// struct D -> struct C -> struct A
/// @endcode
std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) {
std::string PathDisplayStr;
std::set<unsigned> DisplayedPaths;
for (CXXBasePaths::paths_iterator Path = Paths.begin();
Path != Paths.end(); ++Path) {
if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) {
// We haven't displayed a path to this particular base
// class subobject yet.
PathDisplayStr += "\n ";
PathDisplayStr += Context.getTypeDeclType(Paths.getOrigin()).getAsString();
for (CXXBasePath::const_iterator Element = Path->begin();
Element != Path->end(); ++Element)
PathDisplayStr += " -> " + Element->Base->getType().getAsString();
}
}
return PathDisplayStr;
}
//===----------------------------------------------------------------------===//
// C++ class member Handling
//===----------------------------------------------------------------------===//
/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon.
bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc,
SourceLocation ColonLoc,
const ParsedAttributesView &Attrs) {
assert(Access != AS_none && "Invalid kind for syntactic access specifier!");
AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext,
ASLoc, ColonLoc);
CurContext->addHiddenDecl(ASDecl);
return ProcessAccessDeclAttributeList(ASDecl, Attrs);
}
/// CheckOverrideControl - Check C++11 override control semantics.
void Sema::CheckOverrideControl(NamedDecl *D) {
if (D->isInvalidDecl())
return;
// We only care about "override" and "final" declarations.
if (!D->hasAttr<OverrideAttr>() && !D->hasAttr<FinalAttr>())
return;
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D);
// We can't check dependent instance methods.
if (MD && MD->isInstance() &&
(MD->getParent()->hasAnyDependentBases() ||
MD->getType()->isDependentType()))
return;
if (MD && !MD->isVirtual()) {
// If we have a non-virtual method, check if if hides a virtual method.
// (In that case, it's most likely the method has the wrong type.)
SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
FindHiddenVirtualMethods(MD, OverloadedMethods);
if (!OverloadedMethods.empty()) {
if (OverrideAttr *OA = D->getAttr<OverrideAttr>()) {
Diag(OA->getLocation(),
diag::override_keyword_hides_virtual_member_function)
<< "override" << (OverloadedMethods.size() > 1);
} else if (FinalAttr *FA = D->getAttr<FinalAttr>()) {
Diag(FA->getLocation(),
diag::override_keyword_hides_virtual_member_function)
<< (FA->isSpelledAsSealed() ? "sealed" : "final")
<< (OverloadedMethods.size() > 1);
}
NoteHiddenVirtualMethods(MD, OverloadedMethods);
MD->setInvalidDecl();
return;
}
// Fall through into the general case diagnostic.
// FIXME: We might want to attempt typo correction here.
}
if (!MD || !MD->isVirtual()) {
if (OverrideAttr *OA = D->getAttr<OverrideAttr>()) {
Diag(OA->getLocation(),
diag::override_keyword_only_allowed_on_virtual_member_functions)
<< "override" << FixItHint::CreateRemoval(OA->getLocation());
D->dropAttr<OverrideAttr>();
}
if (FinalAttr *FA = D->getAttr<FinalAttr>()) {
Diag(FA->getLocation(),
diag::override_keyword_only_allowed_on_virtual_member_functions)
<< (FA->isSpelledAsSealed() ? "sealed" : "final")
<< FixItHint::CreateRemoval(FA->getLocation());
D->dropAttr<FinalAttr>();
}
return;
}
// C++11 [class.virtual]p5:
// If a function is marked with the virt-specifier override and
// does not override a member function of a base class, the program is
// ill-formed.
bool HasOverriddenMethods = MD->size_overridden_methods() != 0;
if (MD->hasAttr<OverrideAttr>() && !HasOverriddenMethods)
Diag(MD->getLocation(), diag::err_function_marked_override_not_overriding)
<< MD->getDeclName();
}
void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) {
if (D->isInvalidDecl() || D->hasAttr<OverrideAttr>())
return;
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D);
if (!MD || MD->isImplicit() || MD->hasAttr<FinalAttr>())
return;
SourceLocation Loc = MD->getLocation();
SourceLocation SpellingLoc = Loc;
if (getSourceManager().isMacroArgExpansion(Loc))
SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).getBegin();
SpellingLoc = getSourceManager().getSpellingLoc(SpellingLoc);
if (SpellingLoc.isValid() && getSourceManager().isInSystemHeader(SpellingLoc))
return;
if (MD->size_overridden_methods() > 0) {
unsigned DiagID = isa<CXXDestructorDecl>(MD)
? diag::warn_destructor_marked_not_override_overriding
: diag::warn_function_marked_not_override_overriding;
Diag(MD->getLocation(), DiagID) << MD->getDeclName();
const CXXMethodDecl *OMD = *MD->begin_overridden_methods();
Diag(OMD->getLocation(), diag::note_overridden_virtual_function);
}
}
/// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member
/// function overrides a virtual member function marked 'final', according to
/// C++11 [class.virtual]p4.
bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
const CXXMethodDecl *Old) {
FinalAttr *FA = Old->getAttr<FinalAttr>();
if (!FA)
return false;
Diag(New->getLocation(), diag::err_final_function_overridden)
<< New->getDeclName()
<< FA->isSpelledAsSealed();
Diag(Old->getLocation(), diag::note_overridden_virtual_function);
return true;
}
static bool InitializationHasSideEffects(const FieldDecl &FD) {
const Type *T = FD.getType()->getBaseElementTypeUnsafe();
// FIXME: Destruction of ObjC lifetime types has side-effects.
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
return !RD->isCompleteDefinition() ||
!RD->hasTrivialDefaultConstructor() ||
!RD->hasTrivialDestructor();
return false;
}
static const ParsedAttr *getMSPropertyAttr(const ParsedAttributesView &list) {
ParsedAttributesView::const_iterator Itr =
llvm::find_if(list, [](const ParsedAttr &AL) {
return AL.isDeclspecPropertyAttribute();
});
if (Itr != list.end())
return &*Itr;
return nullptr;
}
// Check if there is a field shadowing.
void Sema::CheckShadowInheritedFields(const SourceLocation &Loc,
DeclarationName FieldName,
const CXXRecordDecl *RD,
bool DeclIsField) {
if (Diags.isIgnored(diag::warn_shadow_field, Loc))
return;
// To record a shadowed field in a base
std::map<CXXRecordDecl*, NamedDecl*> Bases;
auto FieldShadowed = [&](const CXXBaseSpecifier *Specifier,
CXXBasePath &Path) {
const auto Base = Specifier->getType()->getAsCXXRecordDecl();
// Record an ambiguous path directly
if (Bases.find(Base) != Bases.end())
return true;
for (const auto Field : Base->lookup(FieldName)) {
if ((isa<FieldDecl>(Field) || isa<IndirectFieldDecl>(Field)) &&
Field->getAccess() != AS_private) {
assert(Field->getAccess() != AS_none);
assert(Bases.find(Base) == Bases.end());
Bases[Base] = Field;
return true;
}
}
return false;
};
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/true);
if (!RD->lookupInBases(FieldShadowed, Paths))
return;
for (const auto &P : Paths) {
auto Base = P.back().Base->getType()->getAsCXXRecordDecl();
auto It = Bases.find(Base);
// Skip duplicated bases
if (It == Bases.end())
continue;
auto BaseField = It->second;
assert(BaseField->getAccess() != AS_private);
if (AS_none !=
CXXRecordDecl::MergeAccess(P.Access, BaseField->getAccess())) {
Diag(Loc, diag::warn_shadow_field)
<< FieldName << RD << Base << DeclIsField;
Diag(BaseField->getLocation(), diag::note_shadow_field);
Bases.erase(It);
}
}
}
/// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
/// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the
/// bitfield width if there is one, 'InitExpr' specifies the initializer if
/// one has been parsed, and 'InitStyle' is set if an in-class initializer is
/// present (but parsing it has been deferred).
NamedDecl *
Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
MultiTemplateParamsArg TemplateParameterLists,
Expr *BW, const VirtSpecifiers &VS,
InClassInitStyle InitStyle) {
const DeclSpec &DS = D.getDeclSpec();
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
DeclarationName Name = NameInfo.getName();
SourceLocation Loc = NameInfo.getLoc();
// For anonymous bitfields, the location should point to the type.
if (Loc.isInvalid())
Loc = D.getBeginLoc();
Expr *BitWidth = static_cast<Expr*>(BW);
assert(isa<CXXRecordDecl>(CurContext));
assert(!DS.isFriendSpecified());
bool isFunc = D.isDeclarationOfFunction();
const ParsedAttr *MSPropertyAttr =
getMSPropertyAttr(D.getDeclSpec().getAttributes());
if (cast<CXXRecordDecl>(CurContext)->isInterface()) {
// The Microsoft extension __interface only permits public member functions
// and prohibits constructors, destructors, operators, non-public member
// functions, static methods and data members.
unsigned InvalidDecl;
bool ShowDeclName = true;
if (!isFunc &&
(DS.getStorageClassSpec() == DeclSpec::SCS_typedef || MSPropertyAttr))
InvalidDecl = 0;
else if (!isFunc)
InvalidDecl = 1;
else if (AS != AS_public)
InvalidDecl = 2;
else if (DS.getStorageClassSpec() == DeclSpec::SCS_static)
InvalidDecl = 3;
else switch (Name.getNameKind()) {
case DeclarationName::CXXConstructorName:
InvalidDecl = 4;
ShowDeclName = false;
break;
case DeclarationName::CXXDestructorName:
InvalidDecl = 5;
ShowDeclName = false;
break;
case DeclarationName::CXXOperatorName:
case DeclarationName::CXXConversionFunctionName:
InvalidDecl = 6;
break;
default:
InvalidDecl = 0;
break;
}
if (InvalidDecl) {
if (ShowDeclName)
Diag(Loc, diag::err_invalid_member_in_interface)
<< (InvalidDecl-1) << Name;
else
Diag(Loc, diag::err_invalid_member_in_interface)
<< (InvalidDecl-1) << "";
return nullptr;
}
}
// C++ 9.2p6: A member shall not be declared to have automatic storage
// duration (auto, register) or with the extern storage-class-specifier.
// C++ 7.1.1p8: The mutable specifier can be applied only to names of class
// data members and cannot be applied to names declared const or static,
// and cannot be applied to reference members.
switch (DS.getStorageClassSpec()) {
case DeclSpec::SCS_unspecified:
case DeclSpec::SCS_typedef:
case DeclSpec::SCS_static:
break;
case DeclSpec::SCS_mutable:
if (isFunc) {
Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_function);
// FIXME: It would be nicer if the keyword was ignored only for this
// declarator. Otherwise we could get follow-up errors.
D.getMutableDeclSpec().ClearStorageClassSpecs();
}
break;
default:
Diag(DS.getStorageClassSpecLoc(),
diag::err_storageclass_invalid_for_member);
D.getMutableDeclSpec().ClearStorageClassSpecs();
break;
}
bool isInstField = ((DS.getStorageClassSpec() == DeclSpec::SCS_unspecified ||
DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
!isFunc);
if (DS.isConstexprSpecified() && isInstField) {
SemaDiagnosticBuilder B =
Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr_member);
SourceLocation ConstexprLoc = DS.getConstexprSpecLoc();
if (InitStyle == ICIS_NoInit) {
B << 0 << 0;
if (D.getDeclSpec().getTypeQualifiers() & DeclSpec::TQ_const)
B << FixItHint::CreateRemoval(ConstexprLoc);
else {
B << FixItHint::CreateReplacement(ConstexprLoc, "const");
D.getMutableDeclSpec().ClearConstexprSpec();
const char *PrevSpec;
unsigned DiagID;
bool Failed = D.getMutableDeclSpec().SetTypeQual(
DeclSpec::TQ_const, ConstexprLoc, PrevSpec, DiagID, getLangOpts());
(void)Failed;
assert(!Failed && "Making a constexpr member const shouldn't fail");
}
} else {
B << 1;
const char *PrevSpec;
unsigned DiagID;
if (D.getMutableDeclSpec().SetStorageClassSpec(
*this, DeclSpec::SCS_static, ConstexprLoc, PrevSpec, DiagID,
Context.getPrintingPolicy())) {
assert(DS.getStorageClassSpec() == DeclSpec::SCS_mutable &&
"This is the only DeclSpec that should fail to be applied");
B << 1;
} else {
B << 0 << FixItHint::CreateInsertion(ConstexprLoc, "static ");
isInstField = false;
}
}
}
NamedDecl *Member;
if (isInstField) {
CXXScopeSpec &SS = D.getCXXScopeSpec();
// Data members must have identifiers for names.
if (!Name.isIdentifier()) {
Diag(Loc, diag::err_bad_variable_name)
<< Name;
return nullptr;
}
IdentifierInfo *II = Name.getAsIdentifierInfo();
// Member field could not be with "template" keyword.
// So TemplateParameterLists should be empty in this case.
if (TemplateParameterLists.size()) {
TemplateParameterList* TemplateParams = TemplateParameterLists[0];
if (TemplateParams->size()) {
// There is no such thing as a member field template.
Diag(D.getIdentifierLoc(), diag::err_template_member)
<< II
<< SourceRange(TemplateParams->getTemplateLoc(),
TemplateParams->getRAngleLoc());
} else {
// There is an extraneous 'template<>' for this member.
Diag(TemplateParams->getTemplateLoc(),
diag::err_template_member_noparams)
<< II
<< SourceRange(TemplateParams->getTemplateLoc(),
TemplateParams->getRAngleLoc());
}
return nullptr;
}
if (SS.isSet() && !SS.isInvalid()) {
// The user provided a superfluous scope specifier inside a class
// definition:
//
// class X {
// int X::member;
// };
if (DeclContext *DC = computeDeclContext(SS, false))
diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc(),
D.getName().getKind() ==
UnqualifiedIdKind::IK_TemplateId);
else
Diag(D.getIdentifierLoc(), diag::err_member_qualification)
<< Name << SS.getRange();
SS.clear();
}
if (MSPropertyAttr) {
Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D,
BitWidth, InitStyle, AS, *MSPropertyAttr);
if (!Member)
return nullptr;
isInstField = false;
} else {
Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D,
BitWidth, InitStyle, AS);
if (!Member)
return nullptr;
}
CheckShadowInheritedFields(Loc, Name, cast<CXXRecordDecl>(CurContext));
} else {
Member = HandleDeclarator(S, D, TemplateParameterLists);
if (!Member)
return nullptr;
// Non-instance-fields can't have a bitfield.
if (BitWidth) {
if (Member->isInvalidDecl()) {
// don't emit another diagnostic.
} else if (isa<VarDecl>(Member) || isa<VarTemplateDecl>(Member)) {
// C++ 9.6p3: A bit-field shall not be a static member.
// "static member 'A' cannot be a bit-field"
Diag(Loc, diag::err_static_not_bitfield)
<< Name << BitWidth->getSourceRange();
} else if (isa<TypedefDecl>(Member)) {
// "typedef member 'x' cannot be a bit-field"
Diag(Loc, diag::err_typedef_not_bitfield)
<< Name << BitWidth->getSourceRange();
} else {
// A function typedef ("typedef int f(); f a;").
// C++ 9.6p3: A bit-field shall have integral or enumeration type.
Diag(Loc, diag::err_not_integral_type_bitfield)
<< Name << cast<ValueDecl>(Member)->getType()
<< BitWidth->getSourceRange();
}
BitWidth = nullptr;
Member->setInvalidDecl();
}
NamedDecl *NonTemplateMember = Member;
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
NonTemplateMember = FunTmpl->getTemplatedDecl();
else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member))
NonTemplateMember = VarTmpl->getTemplatedDecl();
Member->setAccess(AS);
// If we have declared a member function template or static data member
// template, set the access of the templated declaration as well.
if (NonTemplateMember != Member)
NonTemplateMember->setAccess(AS);
// C++ [temp.deduct.guide]p3:
// A deduction guide [...] for a member class template [shall be
// declared] with the same access [as the template].
if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(NonTemplateMember)) {
auto *TD = DG->getDeducedTemplate();
if (AS != TD->getAccess()) {
Diag(DG->getBeginLoc(), diag::err_deduction_guide_wrong_access);
Diag(TD->getBeginLoc(), diag::note_deduction_guide_template_access)
<< TD->getAccess();
const AccessSpecDecl *LastAccessSpec = nullptr;
for (const auto *D : cast<CXXRecordDecl>(CurContext)->decls()) {
if (const auto *AccessSpec = dyn_cast<AccessSpecDecl>(D))
LastAccessSpec = AccessSpec;
}
assert(LastAccessSpec && "differing access with no access specifier");
Diag(LastAccessSpec->getBeginLoc(), diag::note_deduction_guide_access)
<< AS;
}
}
}
if (VS.isOverrideSpecified())
Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context, 0));
if (VS.isFinalSpecified())
Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context,
VS.isFinalSpelledSealed()));
if (VS.getLastLocation().isValid()) {
// Update the end location of a method that has a virt-specifiers.
if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Member))
MD->setRangeEnd(VS.getLastLocation());
}
CheckOverrideControl(Member);
assert((Name || isInstField) && "No identifier for non-field ?");
if (isInstField) {
FieldDecl *FD = cast<FieldDecl>(Member);
FieldCollector->Add(FD);
if (!Diags.isIgnored(diag::warn_unused_private_field, FD->getLocation())) {
// Remember all explicit private FieldDecls that have a name, no side
// effects and are not part of a dependent type declaration.
if (!FD->isImplicit() && FD->getDeclName() &&
FD->getAccess() == AS_private &&
!FD->hasAttr<UnusedAttr>() &&
!FD->getParent()->isDependentContext() &&
!InitializationHasSideEffects(*FD))
UnusedPrivateFields.insert(FD);
}
}
return Member;
}
namespace {
class UninitializedFieldVisitor
: public EvaluatedExprVisitor<UninitializedFieldVisitor> {
Sema &S;
// List of Decls to generate a warning on. Also remove Decls that become
// initialized.
llvm::SmallPtrSetImpl<ValueDecl*> &Decls;
// List of base classes of the record. Classes are removed after their
// initializers.
llvm::SmallPtrSetImpl<QualType> &BaseClasses;
// Vector of decls to be removed from the Decl set prior to visiting the
// nodes. These Decls may have been initialized in the prior initializer.
llvm::SmallVector<ValueDecl*, 4> DeclsToRemove;
// If non-null, add a note to the warning pointing back to the constructor.
const CXXConstructorDecl *Constructor;
// Variables to hold state when processing an initializer list. When
// InitList is true, special case initialization of FieldDecls matching
// InitListFieldDecl.
bool InitList;
FieldDecl *InitListFieldDecl;
llvm::SmallVector<unsigned, 4> InitFieldIndex;
public:
typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited;
UninitializedFieldVisitor(Sema &S,
llvm::SmallPtrSetImpl<ValueDecl*> &Decls,
llvm::SmallPtrSetImpl<QualType> &BaseClasses)
: Inherited(S.Context), S(S), Decls(Decls), BaseClasses(BaseClasses),
Constructor(nullptr), InitList(false), InitListFieldDecl(nullptr) {}
// Returns true if the use of ME is not an uninitialized use.
bool IsInitListMemberExprInitialized(MemberExpr *ME,
bool CheckReferenceOnly) {
llvm::SmallVector<FieldDecl*, 4> Fields;
bool ReferenceField = false;
while (ME) {
FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
if (!FD)
return false;
Fields.push_back(FD);
if (FD->getType()->isReferenceType())
ReferenceField = true;
ME = dyn_cast<MemberExpr>(ME->getBase()->IgnoreParenImpCasts());
}
// Binding a reference to an uninitialized field is not an
// uninitialized use.
if (CheckReferenceOnly && !ReferenceField)
return true;
llvm::SmallVector<unsigned, 4> UsedFieldIndex;
// Discard the first field since it is the field decl that is being
// initialized.
for (auto I = Fields.rbegin() + 1, E = Fields.rend(); I != E; ++I) {
UsedFieldIndex.push_back((*I)->getFieldIndex());
}
for (auto UsedIter = UsedFieldIndex.begin(),
UsedEnd = UsedFieldIndex.end(),
OrigIter = InitFieldIndex.begin(),
OrigEnd = InitFieldIndex.end();
UsedIter != UsedEnd && OrigIter != OrigEnd; ++UsedIter, ++OrigIter) {
if (*UsedIter < *OrigIter)
return true;
if (*UsedIter > *OrigIter)
break;
}
return false;
}
void HandleMemberExpr(MemberExpr *ME, bool CheckReferenceOnly,
bool AddressOf) {
if (isa<EnumConstantDecl>(ME->getMemberDecl()))
return;
// FieldME is the inner-most MemberExpr that is not an anonymous struct
// or union.
MemberExpr *FieldME = ME;
bool AllPODFields = FieldME->getType().isPODType(S.Context);
Expr *Base = ME;
while (MemberExpr *SubME =
dyn_cast<MemberExpr>(Base->IgnoreParenImpCasts())) {
if (isa<VarDecl>(SubME->getMemberDecl()))
return;
if (FieldDecl *FD = dyn_cast<FieldDecl>(SubME->getMemberDecl()))
if (!FD->isAnonymousStructOrUnion())
FieldME = SubME;
if (!FieldME->getType().isPODType(S.Context))
AllPODFields = false;
Base = SubME->getBase();
}
if (!isa<CXXThisExpr>(Base->IgnoreParenImpCasts()))
return;
if (AddressOf && AllPODFields)
return;
ValueDecl* FoundVD = FieldME->getMemberDecl();
if (ImplicitCastExpr *BaseCast = dyn_cast<ImplicitCastExpr>(Base)) {
while (isa<ImplicitCastExpr>(BaseCast->getSubExpr())) {
BaseCast = cast<ImplicitCastExpr>(BaseCast->getSubExpr());
}
if (BaseCast->getCastKind() == CK_UncheckedDerivedToBase) {
QualType T = BaseCast->getType();
if (T->isPointerType() &&
BaseClasses.count(T->getPointeeType())) {
S.Diag(FieldME->getExprLoc(), diag::warn_base_class_is_uninit)
<< T->getPointeeType() << FoundVD;
}
}
}
if (!Decls.count(FoundVD))
return;
const bool IsReference = FoundVD->getType()->isReferenceType();
if (InitList && !AddressOf && FoundVD == InitListFieldDecl) {
// Special checking for initializer lists.
if (IsInitListMemberExprInitialized(ME, CheckReferenceOnly)) {
return;
}
} else {
// Prevent double warnings on use of unbounded references.
if (CheckReferenceOnly && !IsReference)
return;
}
unsigned diag = IsReference
? diag::warn_reference_field_is_uninit
: diag::warn_field_is_uninit;
S.Diag(FieldME->getExprLoc(), diag) << FoundVD;
if (Constructor)
S.Diag(Constructor->getLocation(),
diag::note_uninit_in_this_constructor)
<< (Constructor->isDefaultConstructor() && Constructor->isImplicit());
}
void HandleValue(Expr *E, bool AddressOf) {
E = E->IgnoreParens();
if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
HandleMemberExpr(ME, false /*CheckReferenceOnly*/,
AddressOf /*AddressOf*/);
return;
}
if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
Visit(CO->getCond());
HandleValue(CO->getTrueExpr(), AddressOf);
HandleValue(CO->getFalseExpr(), AddressOf);
return;
}
if (BinaryConditionalOperator *BCO =
dyn_cast<BinaryConditionalOperator>(E)) {
Visit(BCO->getCond());
HandleValue(BCO->getFalseExpr(), AddressOf);
return;
}
if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
HandleValue(OVE->getSourceExpr(), AddressOf);
return;
}
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
switch (BO->getOpcode()) {
default:
break;
case(BO_PtrMemD):
case(BO_PtrMemI):
HandleValue(BO->getLHS(), AddressOf);
Visit(BO->getRHS());
return;
case(BO_Comma):
Visit(BO->getLHS());
HandleValue(BO->getRHS(), AddressOf);
return;
}
}
Visit(E);
}
void CheckInitListExpr(InitListExpr *ILE) {
InitFieldIndex.push_back(0);
for (auto Child : ILE->children()) {
if (InitListExpr *SubList = dyn_cast<InitListExpr>(Child)) {
CheckInitListExpr(SubList);
} else {
Visit(Child);
}
++InitFieldIndex.back();
}
InitFieldIndex.pop_back();
}
void CheckInitializer(Expr *E, const CXXConstructorDecl *FieldConstructor,
FieldDecl *Field, const Type *BaseClass) {
// Remove Decls that may have been initialized in the previous
// initializer.
for (ValueDecl* VD : DeclsToRemove)
Decls.erase(VD);
DeclsToRemove.clear();
Constructor = FieldConstructor;
InitListExpr *ILE = dyn_cast<InitListExpr>(E);
if (ILE && Field) {
InitList = true;
InitListFieldDecl = Field;
InitFieldIndex.clear();
CheckInitListExpr(ILE);
} else {
InitList = false;
Visit(E);
}
if (Field)
Decls.erase(Field);
if (BaseClass)
BaseClasses.erase(BaseClass->getCanonicalTypeInternal());
}
void VisitMemberExpr(MemberExpr *ME) {
// All uses of unbounded reference fields will warn.
HandleMemberExpr(ME, true /*CheckReferenceOnly*/, false /*AddressOf*/);
}
void VisitImplicitCastExpr(ImplicitCastExpr *E) {
if (E->getCastKind() == CK_LValueToRValue) {
HandleValue(E->getSubExpr(), false /*AddressOf*/);
return;
}
Inherited::VisitImplicitCastExpr(E);
}
void VisitCXXConstructExpr(CXXConstructExpr *E) {
if (E->getConstructor()->isCopyConstructor()) {
Expr *ArgExpr = E->getArg(0);
if (InitListExpr *ILE = dyn_cast<InitListExpr>(ArgExpr))
if (ILE->getNumInits() == 1)
ArgExpr = ILE->getInit(0);
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgExpr))
if (ICE->getCastKind() == CK_NoOp)
ArgExpr = ICE->getSubExpr();
HandleValue(ArgExpr, false /*AddressOf*/);
return;
}
Inherited::VisitCXXConstructExpr(E);
}
void VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
Expr *Callee = E->getCallee();
if (isa<MemberExpr>(Callee)) {
HandleValue(Callee, false /*AddressOf*/);
for (auto Arg : E->arguments())
Visit(Arg);
return;
}
Inherited::VisitCXXMemberCallExpr(E);
}
void VisitCallExpr(CallExpr *E) {
// Treat std::move as a use.
if (E->isCallToStdMove()) {
HandleValue(E->getArg(0), /*AddressOf=*/false);
return;
}
Inherited::VisitCallExpr(E);
}
void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
Expr *Callee = E->getCallee();
if (isa<UnresolvedLookupExpr>(Callee))
return Inherited::VisitCXXOperatorCallExpr(E);
Visit(Callee);
for (auto Arg : E->arguments())
HandleValue(Arg->IgnoreParenImpCasts(), false /*AddressOf*/);
}
void VisitBinaryOperator(BinaryOperator *E) {
// If a field assignment is detected, remove the field from the
// uninitiailized field set.
if (E->getOpcode() == BO_Assign)
if (MemberExpr *ME = dyn_cast<MemberExpr>(E->getLHS()))
if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
if (!FD->getType()->isReferenceType())
DeclsToRemove.push_back(FD);
if (E->isCompoundAssignmentOp()) {
HandleValue(E->getLHS(), false /*AddressOf*/);
Visit(E->getRHS());
return;
}
Inherited::VisitBinaryOperator(E);
}
void VisitUnaryOperator(UnaryOperator *E) {
if (E->isIncrementDecrementOp()) {
HandleValue(E->getSubExpr(), false /*AddressOf*/);
return;
}
if (E->getOpcode() == UO_AddrOf) {
if (MemberExpr *ME = dyn_cast<MemberExpr>(E->getSubExpr())) {
HandleValue(ME->getBase(), true /*AddressOf*/);
return;
}
}
Inherited::VisitUnaryOperator(E);
}
};
// Diagnose value-uses of fields to initialize themselves, e.g.
// foo(foo)
// where foo is not also a parameter to the constructor.
// Also diagnose across field uninitialized use such as
// x(y), y(x)
// TODO: implement -Wuninitialized and fold this into that framework.
static void DiagnoseUninitializedFields(
Sema &SemaRef, const CXXConstructorDecl *Constructor) {
if (SemaRef.getDiagnostics().isIgnored(diag::warn_field_is_uninit,
Constructor->getLocation())) {
return;
}
if (Constructor->isInvalidDecl())
return;
const CXXRecordDecl *RD = Constructor->getParent();
if (RD->getDescribedClassTemplate())
return;
// Holds fields that are uninitialized.
llvm::SmallPtrSet<ValueDecl*, 4> UninitializedFields;
// At the beginning, all fields are uninitialized.
for (auto *I : RD->decls()) {
if (auto *FD = dyn_cast<FieldDecl>(I)) {
UninitializedFields.insert(FD);
} else if (auto *IFD = dyn_cast<IndirectFieldDecl>(I)) {
UninitializedFields.insert(IFD->getAnonField());
}
}
llvm::SmallPtrSet<QualType, 4> UninitializedBaseClasses;
for (auto I : RD->bases())
UninitializedBaseClasses.insert(I.getType().getCanonicalType());
if (UninitializedFields.empty() && UninitializedBaseClasses.empty())
return;
UninitializedFieldVisitor UninitializedChecker(SemaRef,
UninitializedFields,
UninitializedBaseClasses);
for (const auto *FieldInit : Constructor->inits()) {
if (UninitializedFields.empty() && UninitializedBaseClasses.empty())
break;
Expr *InitExpr = FieldInit->getInit();
if (!InitExpr)
continue;
if (CXXDefaultInitExpr *Default =
dyn_cast<CXXDefaultInitExpr>(InitExpr)) {
InitExpr = Default->getExpr();
if (!InitExpr)
continue;
// In class initializers will point to the constructor.
UninitializedChecker.CheckInitializer(InitExpr, Constructor,
FieldInit->getAnyMember(),
FieldInit->getBaseClass());
} else {
UninitializedChecker.CheckInitializer(InitExpr, nullptr,
FieldInit->getAnyMember(),
FieldInit->getBaseClass());
}
}
}
} // namespace
/// Enter a new C++ default initializer scope. After calling this, the
/// caller must call \ref ActOnFinishCXXInClassMemberInitializer, even if
/// parsing or instantiating the initializer failed.
void Sema::ActOnStartCXXInClassMemberInitializer() {
// Create a synthetic function scope to represent the call to the constructor
// that notionally surrounds a use of this initializer.
PushFunctionScope();
}
/// This is invoked after parsing an in-class initializer for a
/// non-static C++ class member, and after instantiating an in-class initializer
/// in a class template. Such actions are deferred until the class is complete.
void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
SourceLocation InitLoc,
Expr *InitExpr) {
// Pop the notional constructor scope we created earlier.
PopFunctionScopeInfo(nullptr, D);
FieldDecl *FD = dyn_cast<FieldDecl>(D);
assert((isa<MSPropertyDecl>(D) || FD->getInClassInitStyle() != ICIS_NoInit) &&
"must set init style when field is created");
if (!InitExpr) {
D->setInvalidDecl();
if (FD)
FD->removeInClassInitializer();
return;
}
if (DiagnoseUnexpandedParameterPack(InitExpr, UPPC_Initializer)) {
FD->setInvalidDecl();
FD->removeInClassInitializer();
return;
}
ExprResult Init = InitExpr;
if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
InitializedEntity Entity =
InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD);
InitializationKind Kind =
FD->getInClassInitStyle() == ICIS_ListInit
? InitializationKind::CreateDirectList(InitExpr->getBeginLoc(),
InitExpr->getBeginLoc(),
InitExpr->getEndLoc())
: InitializationKind::CreateCopy(InitExpr->getBeginLoc(), InitLoc);
InitializationSequence Seq(*this, Entity, Kind, InitExpr);
Init = Seq.Perform(*this, Entity, Kind, InitExpr);
if (Init.isInvalid()) {
FD->setInvalidDecl();
return;
}
}
// C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
Init = ActOnFinishFullExpr(Init.get(), InitLoc, /*DiscardedValue*/ false);
if (Init.isInvalid()) {
FD->setInvalidDecl();
return;
}
InitExpr = Init.get();
FD->setInClassInitializer(InitExpr);
}
/// Find the direct and/or virtual base specifiers that
/// correspond to the given base type, for use in base initialization
/// within a constructor.
static bool FindBaseInitializer(Sema &SemaRef,
CXXRecordDecl *ClassDecl,
QualType BaseType,
const CXXBaseSpecifier *&DirectBaseSpec,
const CXXBaseSpecifier *&VirtualBaseSpec) {
// First, check for a direct base class.
DirectBaseSpec = nullptr;
for (const auto &Base : ClassDecl->bases()) {
if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base.getType())) {
// We found a direct base of this type. That's what we're
// initializing.
DirectBaseSpec = &Base;
break;
}
}
// Check for a virtual base class.
// FIXME: We might be able to short-circuit this if we know in advance that
// there are no virtual bases.
VirtualBaseSpec = nullptr;
if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) {
// We haven't found a base yet; search the class hierarchy for a
// virtual base class.
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
/*DetectVirtual=*/false);
if (SemaRef.IsDerivedFrom(ClassDecl->getLocation(),
SemaRef.Context.getTypeDeclType(ClassDecl),
BaseType, Paths)) {
for (CXXBasePaths::paths_iterator Path = Paths.begin();
Path != Paths.end(); ++Path) {
if (Path->back().Base->isVirtual()) {
VirtualBaseSpec = Path->back().Base;
break;
}
}
}
}
return DirectBaseSpec || VirtualBaseSpec;
}
/// Handle a C++ member initializer using braced-init-list syntax.
MemInitResult
Sema::ActOnMemInitializer(Decl *ConstructorD,
Scope *S,
CXXScopeSpec &SS,
IdentifierInfo *MemberOrBase,
ParsedType TemplateTypeTy,
const DeclSpec &DS,
SourceLocation IdLoc,
Expr *InitList,
SourceLocation EllipsisLoc) {
return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
DS, IdLoc, InitList,
EllipsisLoc);
}
/// Handle a C++ member initializer using parentheses syntax.
MemInitResult
Sema::ActOnMemInitializer(Decl *ConstructorD,
Scope *S,
CXXScopeSpec &SS,
IdentifierInfo *MemberOrBase,
ParsedType TemplateTypeTy,
const DeclSpec &DS,
SourceLocation IdLoc,
SourceLocation LParenLoc,
ArrayRef<Expr *> Args,
SourceLocation RParenLoc,
SourceLocation EllipsisLoc) {
Expr *List = ParenListExpr::Create(Context, LParenLoc, Args, RParenLoc);
return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
DS, IdLoc, List, EllipsisLoc);
}
namespace {
// Callback to only accept typo corrections that can be a valid C++ member
// intializer: either a non-static field member or a base class.
class MemInitializerValidatorCCC : public CorrectionCandidateCallback {
public:
explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl)
: ClassDecl(ClassDecl) {}
bool ValidateCandidate(const TypoCorrection &candidate) override {
if (NamedDecl *ND = candidate.getCorrectionDecl()) {
if (FieldDecl *Member = dyn_cast<FieldDecl>(ND))
return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl);
return isa<TypeDecl>(ND);
}
return false;
}
private:
CXXRecordDecl *ClassDecl;
};
}
ValueDecl *Sema::tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl,
CXXScopeSpec &SS,
ParsedType TemplateTypeTy,
IdentifierInfo *MemberOrBase) {
if (SS.getScopeRep() || TemplateTypeTy)
return nullptr;
DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase);
if (Result.empty())
return nullptr;
ValueDecl *Member;
if ((Member = dyn_cast<FieldDecl>(Result.front())) ||
(Member = dyn_cast<IndirectFieldDecl>(Result.front())))
return Member;
return nullptr;
}
/// Handle a C++ member initializer.
MemInitResult
Sema::BuildMemInitializer(Decl *ConstructorD,
Scope *S,
CXXScopeSpec &SS,
IdentifierInfo *MemberOrBase,
ParsedType TemplateTypeTy,
const DeclSpec &DS,
SourceLocation IdLoc,
Expr *Init,
SourceLocation EllipsisLoc) {
ExprResult Res = CorrectDelayedTyposInExpr(Init);
if (!Res.isUsable())
return true;
Init = Res.get();
if (!ConstructorD)
return true;
AdjustDeclIfTemplate(ConstructorD);
CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(ConstructorD);
if (!Constructor) {
// The user wrote a constructor initializer on a function that is
// not a C++ constructor. Ignore the error for now, because we may
// have more member initializers coming; we'll diagnose it just
// once in ActOnMemInitializers.
return true;
}
CXXRecordDecl *ClassDecl = Constructor->getParent();
// C++ [class.base.init]p2:
// Names in a mem-initializer-id are looked up in the scope of the
// constructor's class and, if not found in that scope, are looked
// up in the scope containing the constructor's definition.
// [Note: if the constructor's class contains a member with the
// same name as a direct or virtual base class of the class, a
// mem-initializer-id naming the member or base class and composed
// of a single identifier refers to the class member. A
// mem-initializer-id for the hidden base class may be specified
// using a qualified name. ]
// Look for a member, first.
if (ValueDecl *Member = tryLookupCtorInitMemberDecl(
ClassDecl, SS, TemplateTypeTy, MemberOrBase)) {
if (EllipsisLoc.isValid())
Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
<< MemberOrBase
<< SourceRange(IdLoc, Init->getSourceRange().getEnd());
return BuildMemberInitializer(Member, Init, IdLoc);
}
// It didn't name a member, so see if it names a class.
QualType BaseType;
TypeSourceInfo *TInfo = nullptr;
if (TemplateTypeTy) {
BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo);
} else if (DS.getTypeSpecType() == TST_decltype) {
BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
} else if (DS.getTypeSpecType() == TST_decltype_auto) {
Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid);
return true;
} else {
LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName);
LookupParsedName(R, S, &SS);
TypeDecl *TyD = R.getAsSingle<TypeDecl>();
if (!TyD) {
if (R.isAmbiguous()) return true;
// We don't want access-control diagnostics here.
R.suppressDiagnostics();
if (SS.isSet() && isDependentScopeSpecifier(SS)) {
bool NotUnknownSpecialization = false;
DeclContext *DC = computeDeclContext(SS, false);
if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(DC))
NotUnknownSpecialization = !Record->hasAnyDependentBases();
if (!NotUnknownSpecialization) {
// When the scope specifier can refer to a member of an unknown
// specialization, we take it as a type name.
BaseType = CheckTypenameType(ETK_None, SourceLocation(),
SS.getWithLocInContext(Context),
*MemberOrBase, IdLoc);
if (BaseType.isNull())
return true;
TInfo = Context.CreateTypeSourceInfo(BaseType);
DependentNameTypeLoc TL =
TInfo->getTypeLoc().castAs<DependentNameTypeLoc>();
if (!TL.isNull()) {
TL.setNameLoc(IdLoc);
TL.setElaboratedKeywordLoc(SourceLocation());
TL.setQualifierLoc(SS.getWithLocInContext(Context));
}
R.clear();
R.setLookupName(MemberOrBase);
}
}
// If no results were found, try to correct typos.
TypoCorrection Corr;
if (R.empty() && BaseType.isNull() &&
(Corr = CorrectTypo(
R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
llvm::make_unique<MemInitializerValidatorCCC>(ClassDecl),
CTK_ErrorRecovery, ClassDecl))) {
if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) {
// We have found a non-static data member with a similar
// name to what was typed; complain and initialize that
// member.
diagnoseTypo(Corr,
PDiag(diag::err_mem_init_not_member_or_class_suggest)
<< MemberOrBase << true);
return BuildMemberInitializer(Member, Init, IdLoc);
} else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) {
const CXXBaseSpecifier *DirectBaseSpec;
const CXXBaseSpecifier *VirtualBaseSpec;
if (FindBaseInitializer(*this, ClassDecl,
Context.getTypeDeclType(Type),
DirectBaseSpec, VirtualBaseSpec)) {
// We have found a direct or virtual base class with a
// similar name to what was typed; complain and initialize
// that base class.
diagnoseTypo(Corr,
PDiag(diag::err_mem_init_not_member_or_class_suggest)
<< MemberOrBase << false,
PDiag() /*Suppress note, we provide our own.*/);
const CXXBaseSpecifier *BaseSpec = DirectBaseSpec ? DirectBaseSpec
: VirtualBaseSpec;
Diag(BaseSpec->getBeginLoc(), diag::note_base_class_specified_here)
<< BaseSpec->getType() << BaseSpec->getSourceRange();
TyD = Type;
}
}
}
if (!TyD && BaseType.isNull()) {
Diag(IdLoc, diag::err_mem_init_not_member_or_class)
<< MemberOrBase << SourceRange(IdLoc,Init->getSourceRange().getEnd());
return true;
}
}
if (BaseType.isNull()) {
BaseType = Context.getTypeDeclType(TyD);
MarkAnyDeclReferenced(TyD->getLocation(), TyD, /*OdrUse=*/false);
if (SS.isSet()) {
BaseType = Context.getElaboratedType(ETK_None, SS.getScopeRep(),
BaseType);
TInfo = Context.CreateTypeSourceInfo(BaseType);
ElaboratedTypeLoc TL = TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>();
TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IdLoc);
TL.setElaboratedKeywordLoc(SourceLocation());
TL.setQualifierLoc(SS.getWithLocInContext(Context));
}
}
}
if (!TInfo)
TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc);
return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc);
}
MemInitResult
Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
SourceLocation IdLoc) {
FieldDecl *DirectMember = dyn_cast<FieldDecl>(Member);
IndirectFieldDecl *IndirectMember = dyn_cast<IndirectFieldDecl>(Member);
assert((DirectMember || IndirectMember) &&
"Member must be a FieldDecl or IndirectFieldDecl");
if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer))
return true;
if (Member->isInvalidDecl())
return true;
MultiExprArg Args;
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs());
} else if (InitListExpr *InitList = dyn_cast<InitListExpr>(Init)) {
Args = MultiExprArg(InitList->getInits(), InitList->getNumInits());
} else {
// Template instantiation doesn't reconstruct ParenListExprs for us.
Args = Init;
}
SourceRange InitRange = Init->getSourceRange();
if (Member->getType()->isDependentType() || Init->isTypeDependent()) {
// Can't check initialization for a member of dependent type or when
// any of the arguments are type-dependent expressions.
DiscardCleanupsInEvaluationContext();
} else {
bool InitList = false;
if (isa<InitListExpr>(Init)) {
InitList = true;
Args = Init;
}
// Initialize the member.
InitializedEntity MemberEntity =
DirectMember ? InitializedEntity::InitializeMember(DirectMember, nullptr)
: InitializedEntity::InitializeMember(IndirectMember,
nullptr);
InitializationKind Kind =
InitList ? InitializationKind::CreateDirectList(
IdLoc, Init->getBeginLoc(), Init->getEndLoc())
: InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
InitRange.getEnd());
InitializationSequence InitSeq(*this, MemberEntity, Kind, Args);
ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args,
nullptr);
if (MemberInit.isInvalid())
return true;
// C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin(),
/*DiscardedValue*/ false);
if (MemberInit.isInvalid())
return true;
Init = MemberInit.get();
}
if (DirectMember) {
return new (Context) CXXCtorInitializer(Context, DirectMember, IdLoc,
InitRange.getBegin(), Init,
InitRange.getEnd());
} else {
return new (Context) CXXCtorInitializer(Context, IndirectMember, IdLoc,
InitRange.getBegin(), Init,
InitRange.getEnd());
}
}
MemInitResult
Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
CXXRecordDecl *ClassDecl) {
SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin();
if (!LangOpts.CPlusPlus11)
return Diag(NameLoc, diag::err_delegating_ctor)
<< TInfo->getTypeLoc().getLocalSourceRange();
Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor);
bool InitList = true;
MultiExprArg Args = Init;
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
InitList = false;
Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs());
}
SourceRange InitRange = Init->getSourceRange();
// Initialize the object.
InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation(
QualType(ClassDecl->getTypeForDecl(), 0));
InitializationKind Kind =
InitList ? InitializationKind::CreateDirectList(
NameLoc, Init->getBeginLoc(), Init->getEndLoc())
: InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
InitRange.getEnd());
InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args);
ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind,
Args, nullptr);
if (DelegationInit.isInvalid())
return true;
assert(cast<CXXConstructExpr>(DelegationInit.get())->getConstructor() &&
"Delegating constructor with no target?");
// C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
DelegationInit = ActOnFinishFullExpr(
DelegationInit.get(), InitRange.getBegin(), /*DiscardedValue*/ false);
if (DelegationInit.isInvalid())
return true;
// If we are in a dependent context, template instantiation will
// perform this type-checking again. Just save the arguments that we
// received in a ParenListExpr.
// FIXME: This isn't quite ideal, since our ASTs don't capture all
// of the information that we have about the base
// initializer. However, deconstructing the ASTs is a dicey process,
// and this approach is far more likely to get the corner cases right.
if (CurContext->isDependentContext())
DelegationInit = Init;
return new (Context) CXXCtorInitializer(Context, TInfo, InitRange.getBegin(),
DelegationInit.getAs<Expr>(),
InitRange.getEnd());
}
MemInitResult
Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
Expr *Init, CXXRecordDecl *ClassDecl,
SourceLocation EllipsisLoc) {
SourceLocation BaseLoc
= BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin();
if (!BaseType->isDependentType() && !BaseType->isRecordType())
return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
<< BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
// C++ [class.base.init]p2:
// [...] Unless the mem-initializer-id names a nonstatic data
// member of the constructor's class or a direct or virtual base
// of that class, the mem-initializer is ill-formed. A
// mem-initializer-list can initialize a base class using any
// name that denotes that base class type.
bool Dependent = BaseType->isDependentType() || Init->isTypeDependent();
SourceRange InitRange = Init->getSourceRange();
if (EllipsisLoc.isValid()) {
// This is a pack expansion.
if (!BaseType->containsUnexpandedParameterPack()) {
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
<< SourceRange(BaseLoc, InitRange.getEnd());
EllipsisLoc = SourceLocation();
}
} else {
// Check for any unexpanded parameter packs.
if (DiagnoseUnexpandedParameterPack(BaseLoc, BaseTInfo, UPPC_Initializer))
return true;
if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer))
return true;
}
// Check for direct and virtual base classes.
const CXXBaseSpecifier *DirectBaseSpec = nullptr;
const CXXBaseSpecifier *VirtualBaseSpec = nullptr;
if (!Dependent) {
if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0),
BaseType))
return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl);
FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
VirtualBaseSpec);
// C++ [base.class.init]p2:
// Unless the mem-initializer-id names a nonstatic data member of the
// constructor's class or a direct or virtual base of that class, the
// mem-initializer is ill-formed.
if (!DirectBaseSpec && !VirtualBaseSpec) {
// If the class has any dependent bases, then it's possible that
// one of those types will resolve to the same type as
// BaseType. Therefore, just treat this as a dependent base
// class initialization. FIXME: Should we try to check the
// initialization anyway? It seems odd.
if (ClassDecl->hasAnyDependentBases())
Dependent = true;
else
return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
<< BaseType << Context.getTypeDeclType(ClassDecl)
<< BaseTInfo->getTypeLoc().getLocalSourceRange();
}
}
if (Dependent) {
DiscardCleanupsInEvaluationContext();
return new (Context) CXXCtorInitializer(Context, BaseTInfo,
/*IsVirtual=*/false,
InitRange.getBegin(), Init,
InitRange.getEnd(), EllipsisLoc);
}
// C++ [base.class.init]p2:
// If a mem-initializer-id is ambiguous because it designates both
// a direct non-virtual base class and an inherited virtual base
// class, the mem-initializer is ill-formed.
if (DirectBaseSpec && VirtualBaseSpec)
return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
<< BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();
const CXXBaseSpecifier *BaseSpec = DirectBaseSpec;
if (!BaseSpec)
BaseSpec = VirtualBaseSpec;
// Initialize the base.
bool InitList = true;
MultiExprArg Args = Init;
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
InitList = false;
Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs());
}
InitializedEntity BaseEntity =
InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec);
InitializationKind Kind =
InitList ? InitializationKind::CreateDirectList(BaseLoc)
: InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(),
InitRange.getEnd());
InitializationSequence InitSeq(*this, BaseEntity, Kind, Args);
ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, Args, nullptr);
if (BaseInit.isInvalid())
return true;
// C++11 [class.base.init]p7:
// The initialization of each base and member constitutes a
// full-expression.
BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin(),
/*DiscardedValue*/ false);
if (BaseInit.isInvalid())
return true;
// If we are in a dependent context, template instantiation will
// perform this type-checking again. Just save the arguments that we
// received in a ParenListExpr.
// FIXME: This isn't quite ideal, since our ASTs don't capture all
// of the information that we have about the base
// initializer. However, deconstructing the ASTs is a dicey process,
// and this approach is far more likely to get the corner cases right.
if (CurContext->isDependentContext())
BaseInit = Init;
return new (Context) CXXCtorInitializer(Context, BaseTInfo,
BaseSpec->isVirtual(),
InitRange.getBegin(),
BaseInit.getAs<Expr>(),
InitRange.getEnd(), EllipsisLoc);
}
// Create a static_cast\<T&&>(expr).
static Expr *CastForMoving(Sema &SemaRef, Expr *E, QualType T = QualType()) {
if (T.isNull()) T = E->getType();
QualType TargetType = SemaRef.BuildReferenceType(
T, /*SpelledAsLValue*/false, SourceLocation(), DeclarationName());
SourceLocation ExprLoc = E->getBeginLoc();
TypeSourceInfo *TargetLoc = SemaRef.Context.getTrivialTypeSourceInfo(
TargetType, ExprLoc);
return SemaRef.BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E,
SourceRange(ExprLoc, ExprLoc),
E->getSourceRange()).get();
}
/// ImplicitInitializerKind - How an implicit base or member initializer should
/// initialize its base or member.
enum ImplicitInitializerKind {
IIK_Default,
IIK_Copy,
IIK_Move,
IIK_Inherit
};
static bool
BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
ImplicitInitializerKind ImplicitInitKind,
CXXBaseSpecifier *BaseSpec,
bool IsInheritedVirtualBase,
CXXCtorInitializer *&CXXBaseInit) {
InitializedEntity InitEntity
= InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec,
IsInheritedVirtualBase);
ExprResult BaseInit;
switch (ImplicitInitKind) {
case IIK_Inherit:
case IIK_Default: {
InitializationKind InitKind
= InitializationKind::CreateDefault(Constructor->getLocation());
InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, None);
BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, None);
break;
}
case IIK_Move:
case IIK_Copy: {
bool Moving = ImplicitInitKind == IIK_Move;
ParmVarDecl *Param = Constructor->getParamDecl(0);
QualType ParamType = Param->getType().getNonReferenceType();
Expr *CopyCtorArg =
DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
SourceLocation(), Param, false,
Constructor->getLocation(), ParamType,
VK_LValue, nullptr);
SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(CopyCtorArg));
// Cast to the base class to avoid ambiguities.
QualType ArgTy =
SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(),
ParamType.getQualifiers());
if (Moving) {
CopyCtorArg = CastForMoving(SemaRef, CopyCtorArg);
}
CXXCastPath BasePath;
BasePath.push_back(BaseSpec);
CopyCtorArg = SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy,
CK_UncheckedDerivedToBase,
Moving ? VK_XValue : VK_LValue,
&BasePath).get();
InitializationKind InitKind
= InitializationKind::CreateDirect(Constructor->getLocation(),
SourceLocation(), SourceLocation());
InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, CopyCtorArg);
BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, CopyCtorArg);
break;
}
}
BaseInit = SemaRef.MaybeCreateExprWithCleanups(BaseInit);
if (BaseInit.isInvalid())
return true;
CXXBaseInit =
new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context,
SemaRef.Context.getTrivialTypeSourceInfo(BaseSpec->getType(),
SourceLocation()),
BaseSpec->isVirtual(),
SourceLocation(),
BaseInit.getAs<Expr>(),
SourceLocation(),
SourceLocation());
return false;
}
static bool RefersToRValueRef(Expr *MemRef) {
ValueDecl *Referenced = cast<MemberExpr>(MemRef)->getMemberDecl();
return Referenced->getType()->isRValueReferenceType();
}
static bool
BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
ImplicitInitializerKind ImplicitInitKind,
FieldDecl *Field, IndirectFieldDecl *Indirect,
CXXCtorInitializer *&CXXMemberInit) {
if (Field->isInvalidDecl())
return true;
SourceLocation Loc = Constructor->getLocation();
if (ImplicitInitKind == IIK_Copy || ImplicitInitKind == IIK_Move) {
bool Moving = ImplicitInitKind == IIK_Move;
ParmVarDecl *Param = Constructor->getParamDecl(0);
QualType ParamType = Param->getType().getNonReferenceType();
// Suppress copying zero-width bitfields.
if (Field->isZeroLengthBitField(SemaRef.Context))
return false;
Expr *MemberExprBase =
DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
SourceLocation(), Param, false,
Loc, ParamType, VK_LValue, nullptr);
SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(MemberExprBase));
if (Moving) {
MemberExprBase = CastForMoving(SemaRef, MemberExprBase);
}
// Build a reference to this field within the parameter.
CXXScopeSpec SS;
LookupResult MemberLookup(SemaRef, Field->getDeclName(), Loc,
Sema::LookupMemberName);
MemberLookup.addDecl(Indirect ? cast<ValueDecl>(Indirect)
: cast<ValueDecl>(Field), AS_public);
MemberLookup.resolveKind();
ExprResult CtorArg
= SemaRef.BuildMemberReferenceExpr(MemberExprBase,
ParamType, Loc,
/*IsArrow=*/false,
SS,
/*TemplateKWLoc=*/SourceLocation(),
/*FirstQualifierInScope=*/nullptr,
MemberLookup,
/*TemplateArgs=*/nullptr,
/*S*/nullptr);
if (CtorArg.isInvalid())
return true;
// C++11 [class.copy]p15:
// - if a member m has rvalue reference type T&&, it is direct-initialized
// with static_cast<T&&>(x.m);
if (RefersToRValueRef(CtorArg.get())) {
CtorArg = CastForMoving(SemaRef, CtorArg.get());
}
InitializedEntity Entity =
Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr,
/*Implicit*/ true)
: InitializedEntity::InitializeMember(Field, nullptr,
/*Implicit*/ true);
// Direct-initialize to use the copy constructor.
InitializationKind InitKind =
InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation());
Expr *CtorArgE = CtorArg.getAs<Expr>();
InitializationSequence InitSeq(SemaRef, Entity, InitKind, CtorArgE);
ExprResult MemberInit =
InitSeq.Perform(SemaRef, Entity, InitKind, MultiExprArg(&CtorArgE, 1));
MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);
if (MemberInit.isInvalid())
return true;
if (Indirect)
CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(
SemaRef.Context, Indirect, Loc, Loc, MemberInit.getAs<Expr>(), Loc);
else
CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(
SemaRef.Context, Field, Loc, Loc, MemberInit.getAs<Expr>(), Loc);
return false;
}
assert((ImplicitInitKind == IIK_Default || ImplicitInitKind == IIK_Inherit) &&
"Unhandled implicit init kind!");
QualType FieldBaseElementType =
SemaRef.Context.getBaseElementType(Field->getType());
if (FieldBaseElementType->isRecordType()) {
InitializedEntity InitEntity =
Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr,
/*Implicit*/ true)
: InitializedEntity::InitializeMember(Field, nullptr,
/*Implicit*/ true);
InitializationKind InitKind =
InitializationKind::CreateDefault(Loc);
InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, None);
ExprResult MemberInit =
InitSeq.Perform(SemaRef, InitEntity, InitKind, None);
MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);
if (MemberInit.isInvalid())
return true;
if (Indirect)
CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context,
Indirect, Loc,
Loc,
MemberInit.get(),
Loc);
else
CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context,
Field, Loc, Loc,
MemberInit.get(),
Loc);
return false;
}
if (!Field->getParent()->isUnion()) {
if (FieldBaseElementType->isReferenceType()) {
SemaRef.Diag(Constructor->getLocation(),
diag::err_uninitialized_member_in_ctor)
<< (int)Constructor->isImplicit()
<< SemaRef.Context.getTagDeclType(Constructor->getParent())
<< 0 << Field->getDeclName();
SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
return true;
}
if (FieldBaseElementType.isConstQualified()) {
SemaRef.Diag(Constructor->getLocation(),
diag::err_uninitialized_member_in_ctor)
<< (int)Constructor->isImplicit()
<< SemaRef.Context.getTagDeclType(Constructor->getParent())
<< 1 << Field->getDeclName();
SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
return true;
}
}
if (FieldBaseElementType.hasNonTrivialObjCLifetime()) {
// ARC and Weak:
// Default-initialize Objective-C pointers to NULL.
CXXMemberInit
= new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field,
Loc, Loc,
new (SemaRef.Context) ImplicitValueInitExpr(Field->getType()),
Loc);
return false;
}
// Nothing to initialize.
CXXMemberInit = nullptr;
return false;
}
namespace {
struct BaseAndFieldInfo {
Sema &S;
CXXConstructorDecl *Ctor;
bool AnyErrorsInInits;
ImplicitInitializerKind IIK;
llvm::DenseMap<const void *, CXXCtorInitializer*> AllBaseFields;
SmallVector<CXXCtorInitializer*, 8> AllToInit;
llvm::DenseMap<TagDecl*, FieldDecl*> ActiveUnionMember;
BaseAndFieldInfo(Sema &S, CXXConstructorDecl *Ctor, bool ErrorsInInits)
: S(S), Ctor(Ctor), AnyErrorsInInits(ErrorsInInits) {
bool Generated = Ctor->isImplicit() || Ctor->isDefaulted();
if (Ctor->getInheritedConstructor())
IIK = IIK_Inherit;
else if (Generated && Ctor->isCopyConstructor())
IIK = IIK_Copy;
else if (Generated && Ctor->isMoveConstructor())
IIK = IIK_Move;
else
IIK = IIK_Default;
}
bool isImplicitCopyOrMove() const {
switch (IIK) {
case IIK_Copy:
case IIK_Move:
return true;
case IIK_Default:
case IIK_Inherit:
return false;
}
llvm_unreachable("Invalid ImplicitInitializerKind!");
}
bool addFieldInitializer(CXXCtorInitializer *Init) {
AllToInit.push_back(Init);
// Check whether this initializer makes the field "used".
if (Init->getInit()->HasSideEffects(S.Context))
S.UnusedPrivateFields.remove(Init->getAnyMember());
return false;
}
bool isInactiveUnionMember(FieldDecl *Field) {
RecordDecl *Record = Field->getParent();
if (!Record->isUnion())
return false;
if (FieldDecl *Active =
ActiveUnionMember.lookup(Record->getCanonicalDecl()))
return Active != Field->getCanonicalDecl();
// In an implicit copy or move constructor, ignore any in-class initializer.
if (isImplicitCopyOrMove())
return true;
// If there's no explicit initialization, the field is active only if it
// has an in-class initializer...
if (Field->hasInClassInitializer())
return false;
// ... or it's an anonymous struct or union whose class has an in-class
// initializer.
if (!Field->isAnonymousStructOrUnion())
return true;
CXXRecordDecl *FieldRD = Field->getType()->getAsCXXRecordDecl();
return !FieldRD->hasInClassInitializer();
}
/// Determine whether the given field is, or is within, a union member
/// that is inactive (because there was an initializer given for a different
/// member of the union, or because the union was not initialized at all).
bool isWithinInactiveUnionMember(FieldDecl *Field,
IndirectFieldDecl *Indirect) {
if (!Indirect)
return isInactiveUnionMember(Field);
for (auto *C : Indirect->chain()) {
FieldDecl *Field = dyn_cast<FieldDecl>(C);
if (Field && isInactiveUnionMember(Field))
return true;
}
return false;
}
};
}
/// Determine whether the given type is an incomplete or zero-lenfgth
/// array type.
static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
if (T->isIncompleteArrayType())
return true;
while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) {
if (!ArrayT->getSize())
return true;
T = ArrayT->getElementType();
}
return false;
}
static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
FieldDecl *Field,
IndirectFieldDecl *Indirect = nullptr) {
if (Field->isInvalidDecl())
return false;
// Overwhelmingly common case: we have a direct initializer for this field.
if (CXXCtorInitializer *Init =
Info.AllBaseFields.lookup(Field->getCanonicalDecl()))
return Info.addFieldInitializer(Init);
// C++11 [class.base.init]p8:
// if the entity is a non-static data member that has a
// brace-or-equal-initializer and either
// -- the constructor's class is a union and no other variant member of that
// union is designated by a mem-initializer-id or
// -- the constructor's class is not a union, and, if the entity is a member
// of an anonymous union, no other member of that union is designated by
// a mem-initializer-id,
// the entity is initialized as specified in [dcl.init].
//
// We also apply the same rules to handle anonymous structs within anonymous
// unions.
if (Info.isWithinInactiveUnionMember(Field, Indirect))
return false;
if (Field->hasInClassInitializer() && !Info.isImplicitCopyOrMove()) {
ExprResult DIE =
SemaRef.BuildCXXDefaultInitExpr(Info.Ctor->getLocation(), Field);
if (DIE.isInvalid())
return true;
auto Entity = InitializedEntity::InitializeMember(Field, nullptr, true);
SemaRef.checkInitializerLifetime(Entity, DIE.get());
CXXCtorInitializer *Init;
if (Indirect)
Init = new (SemaRef.Context)
CXXCtorInitializer(SemaRef.Context, Indirect, SourceLocation(),
SourceLocation(), DIE.get(), SourceLocation());
else
Init = new (SemaRef.Context)
CXXCtorInitializer(SemaRef.Context, Field, SourceLocation(),
SourceLocation(), DIE.get(), SourceLocation());
return Info.addFieldInitializer(Init);
}
// Don't initialize incomplete or zero-length arrays.
if (isIncompleteOrZeroLengthArrayType(SemaRef.Context, Field->getType()))
return false;
// Don't try to build an implicit initializer if there were semantic
// errors in any of the initializers (and therefore we might be
// missing some that the user actually wrote).
if (Info.AnyErrorsInInits)
return false;
CXXCtorInitializer *Init = nullptr;
if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field,
Indirect, Init))
return true;
if (!Init)
return false;
return Info.addFieldInitializer(Init);
}
bool
Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor,
CXXCtorInitializer *Initializer) {
assert(Initializer->isDelegatingInitializer());
Constructor->setNumCtorInitializers(1);
CXXCtorInitializer **initializer =
new (Context) CXXCtorInitializer*[1];
memcpy(initializer, &Initializer, sizeof (CXXCtorInitializer*));
Constructor->setCtorInitializers(initializer);
if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) {
MarkFunctionReferenced(Initializer->getSourceLocation(), Dtor);
DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation());
}
DelegatingCtorDecls.push_back(Constructor);
DiagnoseUninitializedFields(*this, Constructor);
return false;
}
bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
ArrayRef<CXXCtorInitializer *> Initializers) {
if (Constructor->isDependentContext()) {
// Just store the initializers as written, they will be checked during
// instantiation.
if (!Initializers.empty()) {
Constructor->setNumCtorInitializers(Initializers.size());
CXXCtorInitializer **baseOrMemberInitializers =
new (Context) CXXCtorInitializer*[Initializers.size()];
memcpy(baseOrMemberInitializers, Initializers.data(),
Initializers.size() * sizeof(CXXCtorInitializer*));
Constructor->setCtorInitializers(baseOrMemberInitializers);
}
// Let template instantiation know whether we had errors.
if (AnyErrors)
Constructor->setInvalidDecl();
return false;
}
BaseAndFieldInfo Info(*this, Constructor, AnyErrors);
// We need to build the initializer AST according to order of construction
// and not what user specified in the Initializers list.
CXXRecordDecl *ClassDecl = Constructor->getParent()->getDefinition();
if (!ClassDecl)
return true;
bool HadError = false;
for (unsigned i = 0; i < Initializers.size(); i++) {
CXXCtorInitializer *Member = Initializers[i];
if (Member->isBaseInitializer())
Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
else {
Info.AllBaseFields[Member->getAnyMember()->getCanonicalDecl()] = Member;
if (IndirectFieldDecl *F = Member->getIndirectMember()) {
for (auto *C : F->chain()) {
FieldDecl *FD = dyn_cast<FieldDecl>(C);
if (FD && FD->getParent()->isUnion())
Info.ActiveUnionMember.insert(std::make_pair(
FD->getParent()->getCanonicalDecl(), FD->getCanonicalDecl()));
}
} else if (FieldDecl *FD = Member->getMember()) {
if (FD->getParent()->isUnion())
Info.ActiveUnionMember.insert(std::make_pair(
FD->getParent()->getCanonicalDecl(), FD->getCanonicalDecl()));
}
}
}
// Keep track of the direct virtual bases.
llvm::SmallPtrSet<CXXBaseSpecifier *, 16> DirectVBases;
for (auto &I : ClassDecl->bases()) {
if (I.isVirtual())
DirectVBases.insert(&I);
}
// Push virtual bases before others.
for (auto &VBase : ClassDecl->vbases()) {
if (CXXCtorInitializer *Value
= Info.AllBaseFields.lookup(VBase.getType()->getAs<RecordType>())) {
// [class.base.init]p7, per DR257:
// A mem-initializer where the mem-initializer-id names a virtual base
// class is ignored during execution of a constructor of any class that
// is not the most derived class.
if (ClassDecl->isAbstract()) {
// FIXME: Provide a fixit to remove the base specifier. This requires
// tracking the location of the associated comma for a base specifier.
Diag(Value->getSourceLocation(), diag::warn_abstract_vbase_init_ignored)
<< VBase.getType() << ClassDecl;
DiagnoseAbstractType(ClassDecl);
}
Info.AllToInit.push_back(Value);
} else if (!AnyErrors && !ClassDecl->isAbstract()) {
// [class.base.init]p8, per DR257:
// If a given [...] base class is not named by a mem-initializer-id
// [...] and the entity is not a virtual base class of an abstract
// class, then [...] the entity is default-initialized.
bool IsInheritedVirtualBase = !DirectVBases.count(&VBase);
CXXCtorInitializer *CXXBaseInit;
if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
&VBase, IsInheritedVirtualBase,
CXXBaseInit)) {
HadError = true;
continue;
}
Info.AllToInit.push_back(CXXBaseInit);
}
}
// Non-virtual bases.
for (auto &Base : ClassDecl->bases()) {
// Virtuals are in the virtual base list and already constructed.
if (Base.isVirtual())
continue;
if (CXXCtorInitializer *Value
= Info.AllBaseFields.lookup(Base.getType()->getAs<RecordType>())) {
Info.AllToInit.push_back(Value);
} else if (!AnyErrors) {
CXXCtorInitializer *CXXBaseInit;
if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
&Base, /*IsInheritedVirtualBase=*/false,
CXXBaseInit)) {
HadError = true;
continue;
}
Info.AllToInit.push_back(CXXBaseInit);
}
}
// Fields.
for (auto *Mem : ClassDecl->decls()) {
if (auto *F = dyn_cast<FieldDecl>(Mem)) {
// C++ [class.bit]p2:
// A declaration for a bit-field that omits the identifier declares an
// unnamed bit-field. Unnamed bit-fields are not members and cannot be
// initialized.
if (F->isUnnamedBitfield())
continue;
// If we're not generating the implicit copy/move constructor, then we'll
// handle anonymous struct/union fields based on their individual
// indirect fields.
if (F->isAnonymousStructOrUnion() && !Info.isImplicitCopyOrMove())
continue;
if (CollectFieldInitializer(*this, Info, F))
HadError = true;
continue;
}
// Beyond this point, we only consider default initialization.
if (Info.isImplicitCopyOrMove())
continue;
if (auto *F = dyn_cast<IndirectFieldDecl>(Mem)) {
if (F->getType()->isIncompleteArrayType()) {
assert(ClassDecl->hasFlexibleArrayMember() &&
"Incomplete array type is not valid");
continue;
}
// Initialize each field of an anonymous struct individually.
if (CollectFieldInitializer(*this, Info, F->getAnonField(), F))
HadError = true;
continue;
}
}
unsigned NumInitializers = Info.AllToInit.size();
if (NumInitializers > 0) {
Constructor->setNumCtorInitializers(NumInitializers);
CXXCtorInitializer **baseOrMemberInitializers =
new (Context) CXXCtorInitializer*[NumInitializers];
memcpy(baseOrMemberInitializers, Info.AllToInit.data(),
NumInitializers * sizeof(CXXCtorInitializer*));
Constructor->setCtorInitializers(baseOrMemberInitializers);
// Constructors implicitly reference the base and member
// destructors.
MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
Constructor->getParent());
}
return HadError;
}
static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl<const void*> &IdealInits) {
if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
const RecordDecl *RD = RT->getDecl();
if (RD->isAnonymousStructOrUnion()) {
for (auto *Field : RD->fields())
PopulateKeysForFields(Field, IdealInits);
return;
}
}
IdealInits.push_back(Field->getCanonicalDecl());
}
static const void *GetKeyForBase(ASTContext &Context, QualType BaseType) {
return Context.getCanonicalType(BaseType).getTypePtr();
}
static const void *GetKeyForMember(ASTContext &Context,
CXXCtorInitializer *Member) {
if (!Member->isAnyMemberInitializer())
return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0));
return Member->getAnyMember()->getCanonicalDecl();
}
static void DiagnoseBaseOrMemInitializerOrder(
Sema &SemaRef, const CXXConstructorDecl *Constructor,
ArrayRef<CXXCtorInitializer *> Inits) {
if (Constructor->getDeclContext()->isDependentContext())
return;
// Don't check initializers order unless the warning is enabled at the
// location of at least one initializer.
bool ShouldCheckOrder = false;
for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) {
CXXCtorInitializer *Init = Inits[InitIndex];
if (!SemaRef.Diags.isIgnored(diag::warn_initializer_out_of_order,
Init->getSourceLocation())) {
ShouldCheckOrder = true;
break;
}
}
if (!ShouldCheckOrder)
return;
// Build the list of bases and members in the order that they'll
// actually be initialized. The explicit initializers should be in
// this same order but may be missing things.
SmallVector<const void*, 32> IdealInitKeys;
const CXXRecordDecl *ClassDecl = Constructor->getParent();
// 1. Virtual bases.
for (const auto &VBase : ClassDecl->vbases())
IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, VBase.getType()));
// 2. Non-virtual bases.
for (const auto &Base : ClassDecl->bases()) {
if (Base.isVirtual())
continue;
IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, Base.getType()));
}
// 3. Direct fields.
for (auto *Field : ClassDecl->fields()) {
if (Field->isUnnamedBitfield())
continue;
PopulateKeysForFields(Field, IdealInitKeys);
}
unsigned NumIdealInits = IdealInitKeys.size();
unsigned IdealIndex = 0;
CXXCtorInitializer *PrevInit = nullptr;
for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) {
CXXCtorInitializer *Init = Inits[InitIndex];
const void *InitKey = GetKeyForMember(SemaRef.Context, Init);
// Scan forward to try to find this initializer in the idealized
// initializers list.
for (; IdealIndex != NumIdealInits; ++IdealIndex)
if (InitKey == IdealInitKeys[IdealIndex])
break;
// If we didn't find this initializer, it must be because we
// scanned past it on a previous iteration. That can only
// happen if we're out of order; emit a warning.
if (IdealIndex == NumIdealInits && PrevInit) {
Sema::SemaDiagnosticBuilder D =
SemaRef.Diag(PrevInit->getSourceLocation(),
diag::warn_initializer_out_of_order);
if (PrevInit->isAnyMemberInitializer())
D << 0 << PrevInit->getAnyMember()->getDeclName();
else
D << 1 << PrevInit->getTypeSourceInfo()->getType();
if (Init->isAnyMemberInitializer())
D << 0 << Init->getAnyMember()->getDeclName();
else
D << 1 << Init->getTypeSourceInfo()->getType();
// Move back to the initializer's location in the ideal list.
for (IdealIndex = 0; IdealIndex != NumIdealInits; ++IdealIndex)
if (InitKey == IdealInitKeys[IdealIndex])
break;
assert(IdealIndex < NumIdealInits &&
"initializer not found in initializer list");
}
PrevInit = Init;
}
}
namespace {
bool CheckRedundantInit(Sema &S,
CXXCtorInitializer *Init,
CXXCtorInitializer *&PrevInit) {
if (!PrevInit) {
PrevInit = Init;
return false;
}
if (FieldDecl *Field = Init->getAnyMember())
S.Diag(Init->getSourceLocation(),
diag::err_multiple_mem_initialization)
<< Field->getDeclName()
<< Init->getSourceRange();
else {
const Type *BaseClass = Init->getBaseClass();
assert(BaseClass && "neither field nor base");
S.Diag(Init->getSourceLocation(),
diag::err_multiple_base_initialization)
<< QualType(BaseClass, 0)
<< Init->getSourceRange();
}
S.Diag(PrevInit->getSourceLocation(), diag::note_previous_initializer)
<< 0 << PrevInit->getSourceRange();
return true;
}
typedef std::pair<NamedDecl *, CXXCtorInitializer *> UnionEntry;
typedef llvm::DenseMap<RecordDecl*, UnionEntry> RedundantUnionMap;
bool CheckRedundantUnionInit(Sema &S,
CXXCtorInitializer *Init,
RedundantUnionMap &Unions) {
FieldDecl *Field = Init->getAnyMember();
RecordDecl *Parent = Field->getParent();
NamedDecl *Child = Field;
while (Parent->isAnonymousStructOrUnion() || Parent->isUnion()) {
if (Parent->isUnion()) {
UnionEntry &En = Unions[Parent];
if (En.first && En.first != Child) {
S.Diag(Init->getSourceLocation(),
diag::err_multiple_mem_union_initialization)
<< Field->getDeclName()
<< Init->getSourceRange();
S.Diag(En.second->getSourceLocation(), diag::note_previous_initializer)
<< 0 << En.second->getSourceRange();
return true;
}
if (!En.first) {
En.first = Child;
En.second = Init;
}
if (!Parent->isAnonymousStructOrUnion())
return false;
}
Child = Parent;
Parent = cast<RecordDecl>(Parent->getDeclContext());
}
return false;
}
}
/// ActOnMemInitializers - Handle the member initializers for a constructor.
void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
SourceLocation ColonLoc,
ArrayRef<CXXCtorInitializer*> MemInits,
bool AnyErrors) {
if (!ConstructorDecl)
return;
AdjustDeclIfTemplate(ConstructorDecl);
CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(ConstructorDecl);
if (!Constructor) {
Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
return;
}
// Mapping for the duplicate initializers check.
// For member initializers, this is keyed with a FieldDecl*.
// For base initializers, this is keyed with a Type*.
llvm::DenseMap<const void *, CXXCtorInitializer *> Members;
// Mapping for the inconsistent anonymous-union initializers check.
RedundantUnionMap MemberUnions;
bool HadError = false;
for (unsigned i = 0; i < MemInits.size(); i++) {
CXXCtorInitializer *Init = MemInits[i];
// Set the source order index.
Init->setSourceOrder(i);
if (Init->isAnyMemberInitializer()) {
const void *Key = GetKeyForMember(Context, Init);
if (CheckRedundantInit(*this, Init, Members[Key]) ||
CheckRedundantUnionInit(*this, Init, MemberUnions))
HadError = true;
} else if (Init->isBaseInitializer()) {
const void *Key = GetKeyForMember(Context, Init);
if (CheckRedundantInit(*this, Init, Members[Key]))
HadError = true;
} else {
assert(Init->isDelegatingInitializer());
// This must be the only initializer
if (MemInits.size() != 1) {
Diag(Init->getSourceLocation(),
diag::err_delegating_initializer_alone)
<< Init->getSourceRange() << MemInits[i ? 0 : 1]->getSourceRange();
// We will treat this as being the only initializer.
}
SetDelegatingInitializer(Constructor, MemInits[i]);
// Return immediately as the initializer is set.
return;
}
}
if (HadError)
return;
DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits);
SetCtorInitializers(Constructor, AnyErrors, MemInits);
DiagnoseUninitializedFields(*this, Constructor);
}
void
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
CXXRecordDecl *ClassDecl) {
// Ignore dependent contexts. Also ignore unions, since their members never
// have destructors implicitly called.
if (ClassDecl->isDependentContext() || ClassDecl->isUnion())
return;
// FIXME: all the access-control diagnostics are positioned on the
// field/base declaration. That's probably good; that said, the
// user might reasonably want to know why the destructor is being
// emitted, and we currently don't say.
// Non-static data members.
for (auto *Field : ClassDecl->fields()) {
if (Field->isInvalidDecl())
continue;
// Don't destroy incomplete or zero-length arrays.
if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
continue;
QualType FieldType = Context.getBaseElementType(Field->getType());
const RecordType* RT = FieldType->getAs<RecordType>();
if (!RT)
continue;
CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
if (FieldClassDecl->isInvalidDecl())
continue;
if (FieldClassDecl->hasIrrelevantDestructor())
continue;
// The destructor for an implicit anonymous union member is never invoked.
if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
continue;
CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
assert(Dtor && "No dtor found for FieldClassDecl!");
CheckDestructorAccess(Field->getLocation(), Dtor,
PDiag(diag::err_access_dtor_field)
<< Field->getDeclName()
<< FieldType);
MarkFunctionReferenced(Location, Dtor);
DiagnoseUseOfDecl(Dtor, Location);
}
// We only potentially invoke the destructors of potentially constructed
// subobjects.
bool VisitVirtualBases = !ClassDecl->isAbstract();
llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases;
// Bases.
for (const auto &Base : ClassDecl->bases()) {
// Bases are always records in a well-formed non-dependent class.
const RecordType *RT = Base.getType()->getAs<RecordType>();
// Remember direct virtual bases.
if (Base.isVirtual()) {
if (!VisitVirtualBases)
continue;
DirectVirtualBases.insert(RT);
}
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
// If our base class is invalid, we probably can't get its dtor anyway.
if (BaseClassDecl->isInvalidDecl())
continue;
if (BaseClassDecl->hasIrrelevantDestructor())
continue;
CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
assert(Dtor && "No dtor found for BaseClassDecl!");
// FIXME: caret should be on the start of the class name
CheckDestructorAccess(Base.getBeginLoc(), Dtor,
PDiag(diag::err_access_dtor_base)
<< Base.getType() << Base.getSourceRange(),
Context.getTypeDeclType(ClassDecl));
MarkFunctionReferenced(Location, Dtor);
DiagnoseUseOfDecl(Dtor, Location);
}
if (!VisitVirtualBases)
return;
// Virtual bases.
for (const auto &VBase : ClassDecl->vbases()) {
// Bases are always records in a well-formed non-dependent class.
const RecordType *RT = VBase.getType()->castAs<RecordType>();
// Ignore direct virtual bases.
if (DirectVirtualBases.count(RT))
continue;
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
// If our base class is invalid, we probably can't get its dtor anyway.
if (BaseClassDecl->isInvalidDecl())
continue;
if (BaseClassDecl->hasIrrelevantDestructor())
continue;
CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
assert(Dtor && "No dtor found for BaseClassDecl!");
if (CheckDestructorAccess(
ClassDecl->getLocation(), Dtor,
PDiag(diag::err_access_dtor_vbase)
<< Context.getTypeDeclType(ClassDecl) << VBase.getType(),
Context.getTypeDeclType(ClassDecl)) ==
AR_accessible) {
CheckDerivedToBaseConversion(
Context.getTypeDeclType(ClassDecl), VBase.getType(),
diag::err_access_dtor_vbase, 0, ClassDecl->getLocation(),
SourceRange(), DeclarationName(), nullptr);
}
MarkFunctionReferenced(Location, Dtor);
DiagnoseUseOfDecl(Dtor, Location);
}
}
void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) {
if (!CDtorDecl)
return;
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(CDtorDecl)) {
SetCtorInitializers(Constructor, /*AnyErrors=*/false);
DiagnoseUninitializedFields(*this, Constructor);
}
}
bool Sema::isAbstractType(SourceLocation Loc, QualType T) {
if (!getLangOpts().CPlusPlus)
return false;
const auto *RD = Context.getBaseElementType(T)->getAsCXXRecordDecl();
if (!RD)
return false;
// FIXME: Per [temp.inst]p1, we are supposed to trigger instantiation of a
// class template specialization here, but doing so breaks a lot of code.
// We can't answer whether something is abstract until it has a
// definition. If it's currently being defined, we'll walk back
// over all the declarations when we have a full definition.
const CXXRecordDecl *Def = RD->getDefinition();
if (!Def || Def->isBeingDefined())
return false;
return RD->isAbstract();
}
bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser) {
if (!isAbstractType(Loc, T))
return false;
T = Context.getBaseElementType(T);
Diagnoser.diagnose(*this, Loc, T);
DiagnoseAbstractType(T->getAsCXXRecordDecl());
return true;
}
void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) {
// Check if we've already emitted the list of pure virtual functions
// for this class.
if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD))
return;
// If the diagnostic is suppressed, don't emit the notes. We're only
// going to emit them once, so try to attach them to a diagnostic we're
// actually going to show.
if (Diags.isLastDiagnosticIgnored())
return;
CXXFinalOverriderMap FinalOverriders;
RD->getFinalOverriders(FinalOverriders);
// Keep a set of seen pure methods so we won't diagnose the same method
// more than once.
llvm::SmallPtrSet<const CXXMethodDecl *, 8> SeenPureMethods;
for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(),
MEnd = FinalOverriders.end();
M != MEnd;
++M) {
for (OverridingMethods::iterator SO = M->second.begin(),
SOEnd = M->second.end();
SO != SOEnd; ++SO) {
// C++ [class.abstract]p4:
// A class is abstract if it contains or inherits at least one
// pure virtual function for which the final overrider is pure
// virtual.
//
if (SO->second.size() != 1)
continue;
if (!SO->second.front().Method->isPure())
continue;
if (!SeenPureMethods.insert(SO->second.front().Method).second)
continue;
Diag(SO->second.front().Method->getLocation(),
diag::note_pure_virtual_function)
<< SO->second.front().Method->getDeclName() << RD->getDeclName();
}
}
if (!PureVirtualClassDiagSet)
PureVirtualClassDiagSet.reset(new RecordDeclSetTy);
PureVirtualClassDiagSet->insert(RD);
}
namespace {
struct AbstractUsageInfo {
Sema &S;
CXXRecordDecl *Record;
CanQualType AbstractType;
bool Invalid;
AbstractUsageInfo(Sema &S, CXXRecordDecl *Record)
: S(S), Record(Record),
AbstractType(S.Context.getCanonicalType(
S.Context.getTypeDeclType(Record))),
Invalid(false) {}
void DiagnoseAbstractType() {
if (Invalid) return;
S.DiagnoseAbstractType(Record);
Invalid = true;
}
void CheckType(const NamedDecl *D, TypeLoc TL, Sema::AbstractDiagSelID Sel);
};
struct CheckAbstractUsage {
AbstractUsageInfo &Info;
const NamedDecl *Ctx;
CheckAbstractUsage(AbstractUsageInfo &Info, const NamedDecl *Ctx)
: Info(Info), Ctx(Ctx) {}
void Visit(TypeLoc TL, Sema::AbstractDiagSelID Sel) {
switch (TL.getTypeLocClass()) {
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
case TypeLoc::CLASS: Check(TL.castAs<CLASS##TypeLoc>(), Sel); break;
#include "clang/AST/TypeLocNodes.def"
}
}
void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) {
Visit(TL.getReturnLoc(), Sema::AbstractReturnType);
for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) {
if (!TL.getParam(I))
continue;
TypeSourceInfo *TSI = TL.getParam(I)->getTypeSourceInfo();
if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType);
}
}
void Check(ArrayTypeLoc TL, Sema::AbstractDiagSelID Sel) {
Visit(TL.getElementLoc(), Sema::AbstractArrayType);
}
void Check(TemplateSpecializationTypeLoc TL, Sema::AbstractDiagSelID Sel) {
// Visit the type parameters from a permissive context.
for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
TemplateArgumentLoc TAL = TL.getArgLoc(I);
if (TAL.getArgument().getKind() == TemplateArgument::Type)
if (TypeSourceInfo *TSI = TAL.getTypeSourceInfo())
Visit(TSI->getTypeLoc(), Sema::AbstractNone);
// TODO: other template argument types?
}
}
// Visit pointee types from a permissive context.
#define CheckPolymorphic(Type) \
void Check(Type TL, Sema::AbstractDiagSelID Sel) { \
Visit(TL.getNextTypeLoc(), Sema::AbstractNone); \
}
CheckPolymorphic(PointerTypeLoc)
CheckPolymorphic(ReferenceTypeLoc)
CheckPolymorphic(MemberPointerTypeLoc)
CheckPolymorphic(BlockPointerTypeLoc)
CheckPolymorphic(AtomicTypeLoc)
/// Handle all the types we haven't given a more specific
/// implementation for above.
void Check(TypeLoc TL, Sema::AbstractDiagSelID Sel) {
// Every other kind of type that we haven't called out already
// that has an inner type is either (1) sugar or (2) contains that
// inner type in some way as a subobject.
if (TypeLoc Next = TL.getNextTypeLoc())
return Visit(Next, Sel);
// If there's no inner type and we're in a permissive context,
// don't diagnose.
if (Sel == Sema::AbstractNone) return;
// Check whether the type matches the abstract type.
QualType T = TL.getType();
if (T->isArrayType()) {
Sel = Sema::AbstractArrayType;
T = Info.S.Context.getBaseElementType(T);
}
CanQualType CT = T->getCanonicalTypeUnqualified().getUnqualifiedType();
if (CT != Info.AbstractType) return;
// It matched; do some magic.
if (Sel == Sema::AbstractArrayType) {
Info.S.Diag(Ctx->getLocation(), diag::err_array_of_abstract_type)
<< T << TL.getSourceRange();
} else {
Info.S.Diag(Ctx->getLocation(), diag::err_abstract_type_in_decl)
<< Sel << T << TL.getSourceRange();
}
Info.DiagnoseAbstractType();
}
};
void AbstractUsageInfo::CheckType(const NamedDecl *D, TypeLoc TL,
Sema::AbstractDiagSelID Sel) {
CheckAbstractUsage(*this, D).Visit(TL, Sel);
}
}
/// Check for invalid uses of an abstract type in a method declaration.
static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
CXXMethodDecl *MD) {
// No need to do the check on definitions, which require that
// the return/param types be complete.
if (MD->doesThisDeclarationHaveABody())
return;
// For safety's sake, just ignore it if we don't have type source
// information. This should never happen for non-implicit methods,
// but...
if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
Info.CheckType(MD, TSI->getTypeLoc(), Sema::AbstractNone);
}
/// Check for invalid uses of an abstract type within a class definition.
static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
CXXRecordDecl *RD) {
for (auto *D : RD->decls()) {
if (D->isImplicit()) continue;
// Methods and method templates.
if (isa<CXXMethodDecl>(D)) {
CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(D));
} else if (isa<FunctionTemplateDecl>(D)) {
FunctionDecl *FD = cast<FunctionTemplateDecl>(D)->getTemplatedDecl();
CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(FD));
// Fields and static variables.
} else if (isa<FieldDecl>(D)) {
FieldDecl *FD = cast<FieldDecl>(D);
if (TypeSourceInfo *TSI = FD->getTypeSourceInfo())
Info.CheckType(FD, TSI->getTypeLoc(), Sema::AbstractFieldType);
} else if (isa<VarDecl>(D)) {
VarDecl *VD = cast<VarDecl>(D);
if (TypeSourceInfo *TSI = VD->getTypeSourceInfo())
Info.CheckType(VD, TSI->getTypeLoc(), Sema::AbstractVariableType);
// Nested classes and class templates.
} else if (isa<CXXRecordDecl>(D)) {
CheckAbstractClassUsage(Info, cast<CXXRecordDecl>(D));
} else if (isa<ClassTemplateDecl>(D)) {
CheckAbstractClassUsage(Info,
cast<ClassTemplateDecl>(D)->getTemplatedDecl());
}
}
}
static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
if (!ClassAttr)
return;
assert(ClassAttr->getKind() == attr::DLLExport);
TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind();
if (TSK == TSK_ExplicitInstantiationDeclaration)
// Don't go any further if this is just an explicit instantiation
// declaration.
return;
if (S.Context.getTargetInfo().getTriple().isWindowsGNUEnvironment())
S.MarkVTableUsed(Class->getLocation(), Class, true);
for (Decl *Member : Class->decls()) {
// Defined static variables that are members of an exported base
// class must be marked export too.
auto *VD = dyn_cast<VarDecl>(Member);
if (VD && Member->getAttr<DLLExportAttr>() &&
VD->getStorageClass() == SC_Static &&
TSK == TSK_ImplicitInstantiation)
S.MarkVariableReferenced(VD->getLocation(), VD);
auto *MD = dyn_cast<CXXMethodDecl>(Member);
if (!MD)
continue;
if (Member->getAttr<DLLExportAttr>()) {
if (MD->isUserProvided()) {
// Instantiate non-default class member functions ...
// .. except for certain kinds of template specializations.
if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited())
continue;
S.MarkFunctionReferenced(Class->getLocation(), MD);
// The function will be passed to the consumer when its definition is
// encountered.
} else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() ||
MD->isCopyAssignmentOperator() ||
MD->isMoveAssignmentOperator()) {
// Synthesize and instantiate non-trivial implicit methods, explicitly
// defaulted methods, and the copy and move assignment operators. The
// latter are exported even if they are trivial, because the address of
// an operator can be taken and should compare equal across libraries.
DiagnosticErrorTrap Trap(S.Diags);
S.MarkFunctionReferenced(Class->getLocation(), MD);
if (Trap.hasErrorOccurred()) {
S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
<< Class << !S.getLangOpts().CPlusPlus11;
break;
}
// There is no later point when we will see the definition of this
// function, so pass it to the consumer now.
S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
}
}
}
}
static void checkForMultipleExportedDefaultConstructors(Sema &S,
CXXRecordDecl *Class) {
// Only the MS ABI has default constructor closures, so we don't need to do
// this semantic checking anywhere else.
if (!S.Context.getTargetInfo().getCXXABI().isMicrosoft())
return;
CXXConstructorDecl *LastExportedDefaultCtor = nullptr;
for (Decl *Member : Class->decls()) {
// Look for exported default constructors.
auto *CD = dyn_cast<CXXConstructorDecl>(Member);
if (!CD || !CD->isDefaultConstructor())
continue;
auto *Attr = CD->getAttr<DLLExportAttr>();
if (!Attr)
continue;
// If the class is non-dependent, mark the default arguments as ODR-used so
// that we can properly codegen the constructor closure.
if (!Class->isDependentContext()) {
for (ParmVarDecl *PD : CD->parameters()) {
(void)S.CheckCXXDefaultArgExpr(Attr->getLocation(), CD, PD);
S.DiscardCleanupsInEvaluationContext();
}
}
if (LastExportedDefaultCtor) {
S.Diag(LastExportedDefaultCtor->getLocation(),
diag::err_attribute_dll_ambiguous_default_ctor)
<< Class;
S.Diag(CD->getLocation(), diag::note_entity_declared_at)
<< CD->getDeclName();
return;
}
LastExportedDefaultCtor = CD;
}
}
void Sema::checkClassLevelCodeSegAttribute(CXXRecordDecl *Class) {
// Mark any compiler-generated routines with the implicit code_seg attribute.
for (auto *Method : Class->methods()) {
if (Method->isUserProvided())
continue;
if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true))
Method->addAttr(A);
}
}
/// Check class-level dllimport/dllexport attribute.
void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
Attr *ClassAttr = getDLLAttr(Class);
// MSVC inherits DLL attributes to partial class template specializations.
if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) {
if (auto *Spec = dyn_cast<ClassTemplatePartialSpecializationDecl>(Class)) {
if (Attr *TemplateAttr =
getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) {
auto *A = cast<InheritableAttr>(TemplateAttr->clone(getASTContext()));
A->setInherited(true);
ClassAttr = A;
}
}
}
if (!ClassAttr)
return;
if (!Class->isExternallyVisible()) {
Diag(Class->getLocation(), diag::err_attribute_dll_not_extern)
<< Class << ClassAttr;
return;
}
if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
!ClassAttr->isInherited()) {
// Diagnose dll attributes on members of class with dll attribute.
for (Decl *Member : Class->decls()) {
if (!isa<VarDecl>(Member) && !isa<CXXMethodDecl>(Member))
continue;
InheritableAttr *MemberAttr = getDLLAttr(Member);
if (!MemberAttr || MemberAttr->isInherited() || Member->isInvalidDecl())
continue;
Diag(MemberAttr->getLocation(),
diag::err_attribute_dll_member_of_dll_class)
<< MemberAttr << ClassAttr;
Diag(ClassAttr->getLocation(), diag::note_previous_attribute);
Member->setInvalidDecl();
}
}
if (Class->getDescribedClassTemplate())
// Don't inherit dll attribute until the template is instantiated.
return;
// The class is either imported or exported.
const bool ClassExported = ClassAttr->getKind() == attr::DLLExport;
// Check if this was a dllimport attribute propagated from a derived class to
// a base class template specialization. We don't apply these attributes to
// static data members.
const bool PropagatedImport =
!ClassExported &&
cast<DLLImportAttr>(ClassAttr)->wasPropagatedToBaseTemplate();
TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind();
// Ignore explicit dllexport on explicit class template instantiation declarations.
if (ClassExported && !ClassAttr->isInherited() &&
TSK == TSK_ExplicitInstantiationDeclaration) {
Class->dropAttr<DLLExportAttr>();
return;
}
// Force declaration of implicit members so they can inherit the attribute.
ForceDeclarationOfImplicitMembers(Class);
// FIXME: MSVC's docs say all bases must be exportable, but this doesn't
// seem to be true in practice?
for (Decl *Member : Class->decls()) {
VarDecl *VD = dyn_cast<VarDecl>(Member);
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member);
// Only methods and static fields inherit the attributes.
if (!VD && !MD)
continue;
if (MD) {
// Don't process deleted methods.
if (MD->isDeleted())
continue;
if (MD->isInlined()) {
// MinGW does not import or export inline methods.
if (!Context.getTargetInfo().getCXXABI().isMicrosoft() &&
!Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())
continue;
// MSVC versions before 2015 don't export the move assignment operators
// and move constructor, so don't attempt to import/export them if
// we have a definition.
auto *Ctor = dyn_cast<CXXConstructorDecl>(MD);
if ((MD->isMoveAssignmentOperator() ||
(Ctor && Ctor->isMoveConstructor())) &&
!getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015))
continue;
// MSVC2015 doesn't export trivial defaulted x-tor but copy assign
// operator is exported anyway.
if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
(Ctor || isa<CXXDestructorDecl>(MD)) && MD->isTrivial())
continue;
}
}
// Don't apply dllimport attributes to static data members of class template
// instantiations when the attribute is propagated from a derived class.
if (VD && PropagatedImport)
continue;
if (!cast<NamedDecl>(Member)->isExternallyVisible())
continue;
if (!getDLLAttr(Member)) {
InheritableAttr *NewAttr = nullptr;
// Do not export/import inline function when -fno-dllexport-inlines is
// passed. But add attribute for later local static var check.
if (!getLangOpts().DllExportInlines && MD && MD->isInlined() &&
TSK != TSK_ExplicitInstantiationDeclaration &&
TSK != TSK_ExplicitInstantiationDefinition) {
if (ClassExported) {
NewAttr = ::new (getASTContext())
DLLExportStaticLocalAttr(ClassAttr->getRange(),
getASTContext(),
ClassAttr->getSpellingListIndex());
} else {
NewAttr = ::new (getASTContext())
DLLImportStaticLocalAttr(ClassAttr->getRange(),
getASTContext(),
ClassAttr->getSpellingListIndex());
}
} else {
NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
}
NewAttr->setInherited(true);
Member->addAttr(NewAttr);
if (MD) {
// Propagate DLLAttr to friend re-declarations of MD that have already
// been constructed.
for (FunctionDecl *FD = MD->getMostRecentDecl(); FD;
FD = FD->getPreviousDecl()) {
if (FD->getFriendObjectKind() == Decl::FOK_None)
continue;
assert(!getDLLAttr(FD) &&
"friend re-decl should not already have a DLLAttr");
NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
NewAttr->setInherited(true);
FD->addAttr(NewAttr);
}
}
}
}
if (ClassExported)
DelayedDllExportClasses.push_back(Class);
}
/// Perform propagation of DLL attributes from a derived class to a
/// templated base class for MS compatibility.
void Sema::propagateDLLAttrToBaseClassTemplate(
CXXRecordDecl *Class, Attr *ClassAttr,
ClassTemplateSpecializationDecl *BaseTemplateSpec, SourceLocation BaseLoc) {
if (getDLLAttr(
BaseTemplateSpec->getSpecializedTemplate()->getTemplatedDecl())) {
// If the base class template has a DLL attribute, don't try to change it.
return;
}
auto TSK = BaseTemplateSpec->getSpecializationKind();
if (!getDLLAttr(BaseTemplateSpec) &&
(TSK == TSK_Undeclared || TSK == TSK_ExplicitInstantiationDeclaration ||
TSK == TSK_ImplicitInstantiation)) {
// The template hasn't been instantiated yet (or it has, but only as an
// explicit instantiation declaration or implicit instantiation, which means
// we haven't codegenned any members yet), so propagate the attribute.
auto *NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
NewAttr->setInherited(true);
BaseTemplateSpec->addAttr(NewAttr);
// If this was an import, mark that we propagated it from a derived class to
// a base class template specialization.
if (auto *ImportAttr = dyn_cast<DLLImportAttr>(NewAttr))
ImportAttr->setPropagatedToBaseTemplate();
// If the template is already instantiated, checkDLLAttributeRedeclaration()
// needs to be run again to work see the new attribute. Otherwise this will
// get run whenever the template is instantiated.
if (TSK != TSK_Undeclared)
checkClassLevelDLLAttribute(BaseTemplateSpec);
return;
}
if (getDLLAttr(BaseTemplateSpec)) {
// The template has already been specialized or instantiated with an
// attribute, explicitly or through propagation. We should not try to change
// it.
return;
}
// The template was previously instantiated or explicitly specialized without
// a dll attribute, It's too late for us to add an attribute, so warn that
// this is unsupported.
Diag(BaseLoc, diag::warn_attribute_dll_instantiated_base_class)
<< BaseTemplateSpec->isExplicitSpecialization();
Diag(ClassAttr->getLocation(), diag::note_attribute);
if (BaseTemplateSpec->isExplicitSpecialization()) {
Diag(BaseTemplateSpec->getLocation(),
diag::note_template_class_explicit_specialization_was_here)
<< BaseTemplateSpec;
} else {
Diag(BaseTemplateSpec->getPointOfInstantiation(),
diag::note_template_class_instantiation_was_here)
<< BaseTemplateSpec;
}
}
static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD,
SourceLocation DefaultLoc) {
switch (S.getSpecialMember(MD)) {
case Sema::CXXDefaultConstructor:
S.DefineImplicitDefaultConstructor(DefaultLoc,
cast<CXXConstructorDecl>(MD));
break;
case Sema::CXXCopyConstructor:
S.DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD));
break;
case Sema::CXXCopyAssignment:
S.DefineImplicitCopyAssignment(DefaultLoc, MD);
break;
case Sema::CXXDestructor:
S.DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(MD));
break;
case Sema::CXXMoveConstructor:
S.DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD));
break;
case Sema::CXXMoveAssignment:
S.DefineImplicitMoveAssignment(DefaultLoc, MD);
break;
case Sema::CXXInvalid:
llvm_unreachable("Invalid special member.");
}
}
/// Determine whether a type is permitted to be passed or returned in
/// registers, per C++ [class.temporary]p3.
static bool canPassInRegisters(Sema &S, CXXRecordDecl *D,
TargetInfo::CallingConvKind CCK) {
if (D->isDependentType() || D->isInvalidDecl())
return false;
-
- if (D->hasAttr<TrivialABIAttr>())
- return true;
// Clang <= 4 used the pre-C++11 rule, which ignores move operations.
// The PS4 platform ABI follows the behavior of Clang 3.2.
if (CCK == TargetInfo::CCK_ClangABI4OrPS4)
return !D->hasNonTrivialDestructorForCall() &&
!D->hasNonTrivialCopyConstructorForCall();
if (CCK == TargetInfo::CCK_MicrosoftWin64) {
bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;
bool DtorIsTrivialForCall = false;
// If a class has at least one non-deleted, trivial copy constructor, it
// is passed according to the C ABI. Otherwise, it is passed indirectly.
//
// Note: This permits classes with non-trivial copy or move ctors to be
// passed in registers, so long as they *also* have a trivial copy ctor,
// which is non-conforming.
if (D->needsImplicitCopyConstructor()) {
if (!D->defaultedCopyConstructorIsDeleted()) {
if (D->hasTrivialCopyConstructor())
CopyCtorIsTrivial = true;
if (D->hasTrivialCopyConstructorForCall())
CopyCtorIsTrivialForCall = true;
}
} else {
for (const CXXConstructorDecl *CD : D->ctors()) {
if (CD->isCopyConstructor() && !CD->isDeleted()) {
if (CD->isTrivial())
CopyCtorIsTrivial = true;
if (CD->isTrivialForCall())
CopyCtorIsTrivialForCall = true;
}
}
}
if (D->needsImplicitDestructor()) {
if (!D->defaultedDestructorIsDeleted() &&
D->hasTrivialDestructorForCall())
DtorIsTrivialForCall = true;
} else if (const auto *DD = D->getDestructor()) {
if (!DD->isDeleted() && DD->isTrivialForCall())
DtorIsTrivialForCall = true;
}
// If the copy ctor and dtor are both trivial-for-calls, pass direct.
if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall)
return true;
// If a class has a destructor, we'd really like to pass it indirectly
// because it allows us to elide copies. Unfortunately, MSVC makes that
// impossible for small types, which it will pass in a single register or
// stack slot. Most objects with dtors are large-ish, so handle that early.
// We can't call out all large objects as being indirect because there are
// multiple x64 calling conventions and the C++ ABI code shouldn't dictate
// how we pass large POD types.
// Note: This permits small classes with nontrivial destructors to be
// passed in registers, which is non-conforming.
if (CopyCtorIsTrivial &&
S.getASTContext().getTypeSize(D->getTypeForDecl()) <= 64)
return true;
return false;
}
// Per C++ [class.temporary]p3, the relevant condition is:
// each copy constructor, move constructor, and destructor of X is
// either trivial or deleted, and X has at least one non-deleted copy
// or move constructor
bool HasNonDeletedCopyOrMove = false;
if (D->needsImplicitCopyConstructor() &&
!D->defaultedCopyConstructorIsDeleted()) {
if (!D->hasTrivialCopyConstructorForCall())
return false;
HasNonDeletedCopyOrMove = true;
}
if (S.getLangOpts().CPlusPlus11 && D->needsImplicitMoveConstructor() &&
!D->defaultedMoveConstructorIsDeleted()) {
if (!D->hasTrivialMoveConstructorForCall())
return false;
HasNonDeletedCopyOrMove = true;
}
if (D->needsImplicitDestructor() && !D->defaultedDestructorIsDeleted() &&
!D->hasTrivialDestructorForCall())
return false;
for (const CXXMethodDecl *MD : D->methods()) {
if (MD->isDeleted())
continue;
auto *CD = dyn_cast<CXXConstructorDecl>(MD);
if (CD && CD->isCopyOrMoveConstructor())
HasNonDeletedCopyOrMove = true;
else if (!isa<CXXDestructorDecl>(MD))
continue;
if (!MD->isTrivialForCall())
return false;
}
return HasNonDeletedCopyOrMove;
}
/// Perform semantic checks on a class definition that has been
/// completing, introducing implicitly-declared members, checking for
/// abstract types, etc.
void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
if (!Record)
return;
if (Record->isAbstract() && !Record->isInvalidDecl()) {
AbstractUsageInfo Info(*this, Record);
CheckAbstractClassUsage(Info, Record);
}
// If this is not an aggregate type and has no user-declared constructor,
// complain about any non-static data members of reference or const scalar
// type, since they will never get initializers.
if (!Record->isInvalidDecl() && !Record->isDependentType() &&
!Record->isAggregate() && !Record->hasUserDeclaredConstructor() &&
!Record->isLambda()) {
bool Complained = false;
for (const auto *F : Record->fields()) {
if (F->hasInClassInitializer() || F->isUnnamedBitfield())
continue;
if (F->getType()->isReferenceType() ||
(F->getType().isConstQualified() && F->getType()->isScalarType())) {
if (!Complained) {
Diag(Record->getLocation(), diag::warn_no_constructor_for_refconst)
<< Record->getTagKind() << Record;
Complained = true;
}
Diag(F->getLocation(), diag::note_refconst_member_not_initialized)
<< F->getType()->isReferenceType()
<< F->getDeclName();
}
}
}
if (Record->getIdentifier()) {
// C++ [class.mem]p13:
// If T is the name of a class, then each of the following shall have a
// name different from T:
// - every member of every anonymous union that is a member of class T.
//
// C++ [class.mem]p14:
// In addition, if class T has a user-declared constructor (12.1), every
// non-static data member of class T shall have a name different from T.
DeclContext::lookup_result R = Record->lookup(Record->getDeclName());
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
if (((isa<FieldDecl>(D) || isa<UnresolvedUsingValueDecl>(D)) &&
Record->hasUserDeclaredConstructor()) ||
isa<IndirectFieldDecl>(D)) {
Diag((*I)->getLocation(), diag::err_member_name_of_class)
<< D->getDeclName();
break;
}
}
}
// Warn if the class has virtual methods but non-virtual public destructor.
if (Record->isPolymorphic() && !Record->isDependentType()) {
CXXDestructorDecl *dtor = Record->getDestructor();
if ((!dtor || (!dtor->isVirtual() && dtor->getAccess() == AS_public)) &&
!Record->hasAttr<FinalAttr>())
Diag(dtor ? dtor->getLocation() : Record->getLocation(),
diag::warn_non_virtual_dtor) << Context.getRecordType(Record);
}
if (Record->isAbstract()) {
if (FinalAttr *FA = Record->getAttr<FinalAttr>()) {
Diag(Record->getLocation(), diag::warn_abstract_final_class)
<< FA->isSpelledAsSealed();
DiagnoseAbstractType(Record);
}
}
// See if trivial_abi has to be dropped.
if (Record->hasAttr<TrivialABIAttr>())
checkIllFormedTrivialABIStruct(*Record);
// Set HasTrivialSpecialMemberForCall if the record has attribute
// "trivial_abi".
bool HasTrivialABI = Record->hasAttr<TrivialABIAttr>();
if (HasTrivialABI)
Record->setHasTrivialSpecialMemberForCall();
bool HasMethodWithOverrideControl = false,
HasOverridingMethodWithoutOverrideControl = false;
if (!Record->isDependentType()) {
for (auto *M : Record->methods()) {
// See if a method overloads virtual methods in a base
// class without overriding any.
if (!M->isStatic())
DiagnoseHiddenVirtualMethods(M);
if (M->hasAttr<OverrideAttr>())
HasMethodWithOverrideControl = true;
else if (M->size_overridden_methods() > 0)
HasOverridingMethodWithoutOverrideControl = true;
// Check whether the explicitly-defaulted special members are valid.
if (!M->isInvalidDecl() && M->isExplicitlyDefaulted())
CheckExplicitlyDefaultedSpecialMember(M);
// For an explicitly defaulted or deleted special member, we defer
// determining triviality until the class is complete. That time is now!
CXXSpecialMember CSM = getSpecialMember(M);
if (!M->isImplicit() && !M->isUserProvided()) {
if (CSM != CXXInvalid) {
M->setTrivial(SpecialMemberIsTrivial(M, CSM));
// Inform the class that we've finished declaring this member.
Record->finishedDefaultedOrDeletedMember(M);
M->setTrivialForCall(
HasTrivialABI ||
SpecialMemberIsTrivial(M, CSM, TAH_ConsiderTrivialABI));
Record->setTrivialForCallFlags(M);
}
}
// Set triviality for the purpose of calls if this is a user-provided
// copy/move constructor or destructor.
if ((CSM == CXXCopyConstructor || CSM == CXXMoveConstructor ||
CSM == CXXDestructor) && M->isUserProvided()) {
M->setTrivialForCall(HasTrivialABI);
Record->setTrivialForCallFlags(M);
}
if (!M->isInvalidDecl() && M->isExplicitlyDefaulted() &&
M->hasAttr<DLLExportAttr>()) {
if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
M->isTrivial() &&
(CSM == CXXDefaultConstructor || CSM == CXXCopyConstructor ||
CSM == CXXDestructor))
M->dropAttr<DLLExportAttr>();
if (M->hasAttr<DLLExportAttr>()) {
DefineImplicitSpecialMember(*this, M, M->getLocation());
ActOnFinishInlineFunctionDef(M);
}
}
}
}
if (HasMethodWithOverrideControl &&
HasOverridingMethodWithoutOverrideControl) {
// At least one method has the 'override' control declared.
// Diagnose all other overridden methods which do not have 'override' specified on them.
for (auto *M : Record->methods())
DiagnoseAbsenceOfOverrideControl(M);
}
// ms_struct is a request to use the same ABI rules as MSVC. Check
// whether this class uses any C++ features that are implemented
// completely differently in MSVC, and if so, emit a diagnostic.
// That diagnostic defaults to an error, but we allow projects to
// map it down to a warning (or ignore it). It's a fairly common
// practice among users of the ms_struct pragma to mass-annotate
// headers, sweeping up a bunch of types that the project doesn't
// really rely on MSVC-compatible layout for. We must therefore
// support "ms_struct except for C++ stuff" as a secondary ABI.
if (Record->isMsStruct(Context) &&
(Record->isPolymorphic() || Record->getNumBases())) {
Diag(Record->getLocation(), diag::warn_cxx_ms_struct);
}
checkClassLevelDLLAttribute(Record);
checkClassLevelCodeSegAttribute(Record);
bool ClangABICompat4 =
Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver4;
TargetInfo::CallingConvKind CCK =
Context.getTargetInfo().getCallingConvKind(ClangABICompat4);
bool CanPass = canPassInRegisters(*this, Record, CCK);
// Do not change ArgPassingRestrictions if it has already been set to
// APK_CanNeverPassInRegs.
if (Record->getArgPassingRestrictions() != RecordDecl::APK_CanNeverPassInRegs)
Record->setArgPassingRestrictions(CanPass
? RecordDecl::APK_CanPassInRegs
: RecordDecl::APK_CannotPassInRegs);
// If canPassInRegisters returns true despite the record having a non-trivial
// destructor, the record is destructed in the callee. This happens only when
// the record or one of its subobjects has a field annotated with trivial_abi
// or a field qualified with ObjC __strong/__weak.
if (Context.getTargetInfo().getCXXABI().areArgsDestroyedLeftToRightInCallee())
Record->setParamDestroyedInCallee(true);
else if (Record->hasNonTrivialDestructor())
Record->setParamDestroyedInCallee(CanPass);
if (getLangOpts().ForceEmitVTables) {
// If we want to emit all the vtables, we need to mark it as used. This
// is especially required for cases like vtable assumption loads.
MarkVTableUsed(Record->getInnerLocStart(), Record);
}
}
/// Look up the special member function that would be called by a special
/// member function for a subobject of class type.
///
/// \param Class The class type of the subobject.
/// \param CSM The kind of special member function.
/// \param FieldQuals If the subobject is a field, its cv-qualifiers.
/// \param ConstRHS True if this is a copy operation with a const object
/// on its RHS, that is, if the argument to the outer special member
/// function is 'const' and this is not a field marked 'mutable'.
static Sema::SpecialMemberOverloadResult lookupCallFromSpecialMember(
Sema &S, CXXRecordDecl *Class, Sema::CXXSpecialMember CSM,
unsigned FieldQuals, bool ConstRHS) {
unsigned LHSQuals = 0;
if (CSM == Sema::CXXCopyAssignment || CSM == Sema::CXXMoveAssignment)
LHSQuals = FieldQuals;
unsigned RHSQuals = FieldQuals;
if (CSM == Sema::CXXDefaultConstructor || CSM == Sema::CXXDestructor)
RHSQuals = 0;
else if (ConstRHS)
RHSQuals |= Qualifiers::Const;
return S.LookupSpecialMember(Class, CSM,
RHSQuals & Qualifiers::Const,
RHSQuals & Qualifiers::Volatile,
false,
LHSQuals & Qualifiers::Const,
LHSQuals & Qualifiers::Volatile);
}
class Sema::InheritedConstructorInfo {
Sema &S;
SourceLocation UseLoc;
/// A mapping from the base classes through which the constructor was
/// inherited to the using shadow declaration in that base class (or a null
/// pointer if the constructor was declared in that base class).
llvm::DenseMap<CXXRecordDecl *, ConstructorUsingShadowDecl *>
InheritedFromBases;
public:
InheritedConstructorInfo(Sema &S, SourceLocation UseLoc,
ConstructorUsingShadowDecl *Shadow)
: S(S), UseLoc(UseLoc) {
bool DiagnosedMultipleConstructedBases = false;
CXXRecordDecl *ConstructedBase = nullptr;
UsingDecl *ConstructedBaseUsing = nullptr;
// Find the set of such base class subobjects and check that there's a
// unique constructed subobject.
for (auto *D : Shadow->redecls()) {
auto *DShadow = cast<ConstructorUsingShadowDecl>(D);
auto *DNominatedBase = DShadow->getNominatedBaseClass();
auto *DConstructedBase = DShadow->getConstructedBaseClass();
InheritedFromBases.insert(
std::make_pair(DNominatedBase->getCanonicalDecl(),
DShadow->getNominatedBaseClassShadowDecl()));
if (DShadow->constructsVirtualBase())
InheritedFromBases.insert(
std::make_pair(DConstructedBase->getCanonicalDecl(),
DShadow->getConstructedBaseClassShadowDecl()));
else
assert(DNominatedBase == DConstructedBase);
// [class.inhctor.init]p2:
// If the constructor was inherited from multiple base class subobjects
// of type B, the program is ill-formed.
if (!ConstructedBase) {
ConstructedBase = DConstructedBase;
ConstructedBaseUsing = D->getUsingDecl();
} else if (ConstructedBase != DConstructedBase &&
!Shadow->isInvalidDecl()) {
if (!DiagnosedMultipleConstructedBases) {
S.Diag(UseLoc, diag::err_ambiguous_inherited_constructor)
<< Shadow->getTargetDecl();
S.Diag(ConstructedBaseUsing->getLocation(),
diag::note_ambiguous_inherited_constructor_using)
<< ConstructedBase;
DiagnosedMultipleConstructedBases = true;
}
S.Diag(D->getUsingDecl()->getLocation(),
diag::note_ambiguous_inherited_constructor_using)
<< DConstructedBase;
}
}
if (DiagnosedMultipleConstructedBases)
Shadow->setInvalidDecl();
}
/// Find the constructor to use for inherited construction of a base class,
/// and whether that base class constructor inherits the constructor from a
/// virtual base class (in which case it won't actually invoke it).
std::pair<CXXConstructorDecl *, bool>
findConstructorForBase(CXXRecordDecl *Base, CXXConstructorDecl *Ctor) const {
auto It = InheritedFromBases.find(Base->getCanonicalDecl());
if (It == InheritedFromBases.end())
return std::make_pair(nullptr, false);
// This is an intermediary class.
if (It->second)
return std::make_pair(
S.findInheritingConstructor(UseLoc, Ctor, It->second),
It->second->constructsVirtualBase());
// This is the base class from which the constructor was inherited.
return std::make_pair(Ctor, false);
}
};
/// Is the special member function which would be selected to perform the
/// specified operation on the specified class type a constexpr constructor?
static bool
specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
Sema::CXXSpecialMember CSM, unsigned Quals,
bool ConstRHS,
CXXConstructorDecl *InheritedCtor = nullptr,
Sema::InheritedConstructorInfo *Inherited = nullptr) {
// If we're inheriting a constructor, see if we need to call it for this base
// class.
if (InheritedCtor) {
assert(CSM == Sema::CXXDefaultConstructor);
auto BaseCtor =
Inherited->findConstructorForBase(ClassDecl, InheritedCtor).first;
if (BaseCtor)
return BaseCtor->isConstexpr();
}
if (CSM == Sema::CXXDefaultConstructor)
return ClassDecl->hasConstexprDefaultConstructor();
Sema::SpecialMemberOverloadResult SMOR =
lookupCallFromSpecialMember(S, ClassDecl, CSM, Quals, ConstRHS);
if (!SMOR.getMethod())
// A constructor we wouldn't select can't be "involved in initializing"
// anything.
return true;
return SMOR.getMethod()->isConstexpr();
}
/// Determine whether the specified special member function would be constexpr
/// if it were implicitly defined.
static bool defaultedSpecialMemberIsConstexpr(
Sema &S, CXXRecordDecl *ClassDecl, Sema::CXXSpecialMember CSM,
bool ConstArg, CXXConstructorDecl *InheritedCtor = nullptr,
Sema::InheritedConstructorInfo *Inherited = nullptr) {
if (!S.getLangOpts().CPlusPlus11)
return false;
// C++11 [dcl.constexpr]p4:
// In the definition of a constexpr constructor [...]
bool Ctor = true;
switch (CSM) {
case Sema::CXXDefaultConstructor:
if (Inherited)
break;
// Since default constructor lookup is essentially trivial (and cannot
// involve, for instance, template instantiation), we compute whether a
// defaulted default constructor is constexpr directly within CXXRecordDecl.
//
// This is important for performance; we need to know whether the default
// constructor is constexpr to determine whether the type is a literal type.
return ClassDecl->defaultedDefaultConstructorIsConstexpr();
case Sema::CXXCopyConstructor:
case Sema::CXXMoveConstructor:
// For copy or move constructors, we need to perform overload resolution.
break;
case Sema::CXXCopyAssignment:
case Sema::CXXMoveAssignment:
if (!S.getLangOpts().CPlusPlus14)
return false;
// In C++1y, we need to perform overload resolution.
Ctor = false;
break;
case Sema::CXXDestructor:
case Sema::CXXInvalid:
return false;
}
// -- if the class is a non-empty union, or for each non-empty anonymous
// union member of a non-union class, exactly one non-static data member
// shall be initialized; [DR1359]
//
// If we squint, this is guaranteed, since exactly one non-static data member
// will be initialized (if the constructor isn't deleted), we just don't know
// which one.
if (Ctor && ClassDecl->isUnion())
return CSM == Sema::CXXDefaultConstructor
? ClassDecl->hasInClassInitializer() ||
!ClassDecl->hasVariantMembers()
: true;
// -- the class shall not have any virtual base classes;
if (Ctor && ClassDecl->getNumVBases())
return false;
// C++1y [class.copy]p26:
// -- [the class] is a literal type, and
if (!Ctor && !ClassDecl->isLiteral())
return false;
// -- every constructor involved in initializing [...] base class
// sub-objects shall be a constexpr constructor;
// -- the assignment operator selected to copy/move each direct base
// class is a constexpr function, and
for (const auto &B : ClassDecl->bases()) {
const RecordType *BaseType = B.getType()->getAs<RecordType>();
if (!BaseType) continue;
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg,
InheritedCtor, Inherited))
return false;
}
// -- every constructor involved in initializing non-static data members
// [...] shall be a constexpr constructor;
// -- every non-static data member and base class sub-object shall be
// initialized
// -- for each non-static data member of X that is of class type (or array
// thereof), the assignment operator selected to copy/move that member is
// a constexpr function
for (const auto *F : ClassDecl->fields()) {
if (F->isInvalidDecl())
continue;
if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer())
continue;
QualType BaseType = S.Context.getBaseElementType(F->getType());
if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM,
BaseType.getCVRQualifiers(),
ConstArg && !F->isMutable()))
return false;
} else if (CSM == Sema::CXXDefaultConstructor) {
return false;
}
}
// All OK, it's constexpr!
return true;
}
static Sema::ImplicitExceptionSpecification
ComputeDefaultedSpecialMemberExceptionSpec(
Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM,
Sema::InheritedConstructorInfo *ICI);
static Sema::ImplicitExceptionSpecification
computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, CXXMethodDecl *MD) {
auto CSM = S.getSpecialMember(MD);
if (CSM != Sema::CXXInvalid)
return ComputeDefaultedSpecialMemberExceptionSpec(S, Loc, MD, CSM, nullptr);
auto *CD = cast<CXXConstructorDecl>(MD);
assert(CD->getInheritedConstructor() &&
"only special members have implicit exception specs");
Sema::InheritedConstructorInfo ICI(
S, Loc, CD->getInheritedConstructor().getShadowDecl());
return ComputeDefaultedSpecialMemberExceptionSpec(
S, Loc, CD, Sema::CXXDefaultConstructor, &ICI);
}
static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S,
CXXMethodDecl *MD) {
FunctionProtoType::ExtProtoInfo EPI;
// Build an exception specification pointing back at this member.
EPI.ExceptionSpec.Type = EST_Unevaluated;
EPI.ExceptionSpec.SourceDecl = MD;
// Set the calling convention to the default for C++ instance methods.
EPI.ExtInfo = EPI.ExtInfo.withCallingConv(
S.Context.getDefaultCallingConvention(/*IsVariadic=*/false,
/*IsCXXMethod=*/true));
return EPI;
}
void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) {
const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
if (FPT->getExceptionSpecType() != EST_Unevaluated)
return;
// Evaluate the exception specification.
auto IES = computeImplicitExceptionSpec(*this, Loc, MD);
auto ESI = IES.getExceptionSpec();
// Update the type of the special member to use it.
UpdateExceptionSpec(MD, ESI);
// A user-provided destructor can be defined outside the class. When that
// happens, be sure to update the exception specification on both
// declarations.
const FunctionProtoType *CanonicalFPT =
MD->getCanonicalDecl()->getType()->castAs<FunctionProtoType>();
if (CanonicalFPT->getExceptionSpecType() == EST_Unevaluated)
UpdateExceptionSpec(MD->getCanonicalDecl(), ESI);
}
void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
CXXRecordDecl *RD = MD->getParent();
CXXSpecialMember CSM = getSpecialMember(MD);
assert(MD->isExplicitlyDefaulted() && CSM != CXXInvalid &&
"not an explicitly-defaulted special member");
// Whether this was the first-declared instance of the constructor.
// This affects whether we implicitly add an exception spec and constexpr.
bool First = MD == MD->getCanonicalDecl();
bool HadError = false;
// C++11 [dcl.fct.def.default]p1:
// A function that is explicitly defaulted shall
// -- be a special member function (checked elsewhere),
// -- have the same type (except for ref-qualifiers, and except that a
// copy operation can take a non-const reference) as an implicit
// declaration, and
// -- not have default arguments.
// C++2a changes the second bullet to instead delete the function if it's
// defaulted on its first declaration, unless it's "an assignment operator,
// and its return type differs or its parameter type is not a reference".
bool DeleteOnTypeMismatch = getLangOpts().CPlusPlus2a && First;
bool ShouldDeleteForTypeMismatch = false;
unsigned ExpectedParams = 1;
if (CSM == CXXDefaultConstructor || CSM == CXXDestructor)
ExpectedParams = 0;
if (MD->getNumParams() != ExpectedParams) {
// This checks for default arguments: a copy or move constructor with a
// default argument is classified as a default constructor, and assignment
// operations and destructors can't have default arguments.
Diag(MD->getLocation(), diag::err_defaulted_special_member_params)
<< CSM << MD->getSourceRange();
HadError = true;
} else if (MD->isVariadic()) {
if (DeleteOnTypeMismatch)
ShouldDeleteForTypeMismatch = true;
else {
Diag(MD->getLocation(), diag::err_defaulted_special_member_variadic)
<< CSM << MD->getSourceRange();
HadError = true;
}
}
const FunctionProtoType *Type = MD->getType()->getAs<FunctionProtoType>();
bool CanHaveConstParam = false;
if (CSM == CXXCopyConstructor)
CanHaveConstParam = RD->implicitCopyConstructorHasConstParam();
else if (CSM == CXXCopyAssignment)
CanHaveConstParam = RD->implicitCopyAssignmentHasConstParam();
QualType ReturnType = Context.VoidTy;
if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) {
// Check for return type matching.
ReturnType = Type->getReturnType();
QualType DeclType = Context.getTypeDeclType(RD);
DeclType = Context.getAddrSpaceQualType(DeclType, MD->getTypeQualifiers().getAddressSpace());
QualType ExpectedReturnType = Context.getLValueReferenceType(DeclType);
if (!Context.hasSameType(ReturnType, ExpectedReturnType)) {
Diag(MD->getLocation(), diag::err_defaulted_special_member_return_type)
<< (CSM == CXXMoveAssignment) << ExpectedReturnType;
HadError = true;
}
// A defaulted special member cannot have cv-qualifiers.
if (Type->getTypeQuals().hasConst() || Type->getTypeQuals().hasVolatile()) {
if (DeleteOnTypeMismatch)
ShouldDeleteForTypeMismatch = true;
else {
Diag(MD->getLocation(), diag::err_defaulted_special_member_quals)
<< (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus14;
HadError = true;
}
}
}
// Check for parameter type matching.
QualType ArgType = ExpectedParams ? Type->getParamType(0) : QualType();
bool HasConstParam = false;
if (ExpectedParams && ArgType->isReferenceType()) {
// Argument must be reference to possibly-const T.
QualType ReferentType = ArgType->getPointeeType();
HasConstParam = ReferentType.isConstQualified();
if (ReferentType.isVolatileQualified()) {
if (DeleteOnTypeMismatch)
ShouldDeleteForTypeMismatch = true;
else {
Diag(MD->getLocation(),
diag::err_defaulted_special_member_volatile_param) << CSM;
HadError = true;
}
}
if (HasConstParam && !CanHaveConstParam) {
if (DeleteOnTypeMismatch)
ShouldDeleteForTypeMismatch = true;
else if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment) {
Diag(MD->getLocation(),
diag::err_defaulted_special_member_copy_const_param)
<< (CSM == CXXCopyAssignment);
// FIXME: Explain why this special member can't be const.
HadError = true;
} else {
Diag(MD->getLocation(),
diag::err_defaulted_special_member_move_const_param)
<< (CSM == CXXMoveAssignment);
HadError = true;
}
}
} else if (ExpectedParams) {
// A copy assignment operator can take its argument by value, but a
// defaulted one cannot.
assert(CSM == CXXCopyAssignment && "unexpected non-ref argument");
Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref);
HadError = true;
}
// C++11 [dcl.fct.def.default]p2:
// An explicitly-defaulted function may be declared constexpr only if it
// would have been implicitly declared as constexpr,
// Do not apply this rule to members of class templates, since core issue 1358
// makes such functions always instantiate to constexpr functions. For
// functions which cannot be constexpr (for non-constructors in C++11 and for
// destructors in C++1y), this is checked elsewhere.
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, RD, CSM,
HasConstParam);
if ((getLangOpts().CPlusPlus14 ? !isa<CXXDestructorDecl>(MD)
: isa<CXXConstructorDecl>(MD)) &&
MD->isConstexpr() && !Constexpr &&
MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr) << CSM;
// FIXME: Explain why the special member can't be constexpr.
HadError = true;
}
// and may have an explicit exception-specification only if it is compatible
// with the exception-specification on the implicit declaration.
if (Type->hasExceptionSpec()) {
// Delay the check if this is the first declaration of the special member,
// since we may not have parsed some necessary in-class initializers yet.
if (First) {
// If the exception specification needs to be instantiated, do so now,
// before we clobber it with an EST_Unevaluated specification below.
if (Type->getExceptionSpecType() == EST_Uninstantiated) {
InstantiateExceptionSpec(MD->getBeginLoc(), MD);
Type = MD->getType()->getAs<FunctionProtoType>();
}
DelayedDefaultedMemberExceptionSpecs.push_back(std::make_pair(MD, Type));
} else
CheckExplicitlyDefaultedMemberExceptionSpec(MD, Type);
}
// If a function is explicitly defaulted on its first declaration,
if (First) {
// -- it is implicitly considered to be constexpr if the implicit
// definition would be,
MD->setConstexpr(Constexpr);
// -- it is implicitly considered to have the same exception-specification
// as if it had been implicitly declared,
FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo();
EPI.ExceptionSpec.Type = EST_Unevaluated;
EPI.ExceptionSpec.SourceDecl = MD;
MD->setType(Context.getFunctionType(ReturnType,
llvm::makeArrayRef(&ArgType,
ExpectedParams),
EPI));
}
if (ShouldDeleteForTypeMismatch || ShouldDeleteSpecialMember(MD, CSM)) {
if (First) {
SetDeclDeleted(MD, MD->getLocation());
if (!inTemplateInstantiation() && !HadError) {
Diag(MD->getLocation(), diag::warn_defaulted_method_deleted) << CSM;
if (ShouldDeleteForTypeMismatch) {
Diag(MD->getLocation(), diag::note_deleted_type_mismatch) << CSM;
} else {
ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true);
}
}
if (ShouldDeleteForTypeMismatch && !HadError) {
Diag(MD->getLocation(),
diag::warn_cxx17_compat_defaulted_method_type_mismatch) << CSM;
}
} else {
// C++11 [dcl.fct.def.default]p4:
// [For a] user-provided explicitly-defaulted function [...] if such a
// function is implicitly defined as deleted, the program is ill-formed.
Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM;
assert(!ShouldDeleteForTypeMismatch && "deleted non-first decl");
ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true);
HadError = true;
}
}
if (HadError)
MD->setInvalidDecl();
}
/// Check whether the exception specification provided for an
/// explicitly-defaulted special member matches the exception specification
/// that would have been generated for an implicit special member, per
/// C++11 [dcl.fct.def.default]p2.
void Sema::CheckExplicitlyDefaultedMemberExceptionSpec(
CXXMethodDecl *MD, const FunctionProtoType *SpecifiedType) {
// If the exception specification was explicitly specified but hadn't been
// parsed when the method was defaulted, grab it now.
if (SpecifiedType->getExceptionSpecType() == EST_Unparsed)
SpecifiedType =
MD->getTypeSourceInfo()->getType()->castAs<FunctionProtoType>();
// Compute the implicit exception specification.
CallingConv CC = Context.getDefaultCallingConvention(/*IsVariadic=*/false,
/*IsCXXMethod=*/true);
FunctionProtoType::ExtProtoInfo EPI(CC);
auto IES = computeImplicitExceptionSpec(*this, MD->getLocation(), MD);
EPI.ExceptionSpec = IES.getExceptionSpec();
const FunctionProtoType *ImplicitType = cast<FunctionProtoType>(
Context.getFunctionType(Context.VoidTy, None, EPI));
// Ensure that it matches.
CheckEquivalentExceptionSpec(
PDiag(diag::err_incorrect_defaulted_exception_spec)
<< getSpecialMember(MD), PDiag(),
ImplicitType, SourceLocation(),
SpecifiedType, MD->getLocation());
}
void Sema::CheckDelayedMemberExceptionSpecs() {
decltype(DelayedOverridingExceptionSpecChecks) Overriding;
decltype(DelayedEquivalentExceptionSpecChecks) Equivalent;
decltype(DelayedDefaultedMemberExceptionSpecs) Defaulted;
std::swap(Overriding, DelayedOverridingExceptionSpecChecks);
std::swap(Equivalent, DelayedEquivalentExceptionSpecChecks);
std::swap(Defaulted, DelayedDefaultedMemberExceptionSpecs);
// Perform any deferred checking of exception specifications for virtual
// destructors.
for (auto &Check : Overriding)
CheckOverridingFunctionExceptionSpec(Check.first, Check.second);
// Perform any deferred checking of exception specifications for befriended
// special members.
for (auto &Check : Equivalent)
CheckEquivalentExceptionSpec(Check.second, Check.first);
// Check that any explicitly-defaulted methods have exception specifications
// compatible with their implicit exception specifications.
for (auto &Spec : Defaulted)
CheckExplicitlyDefaultedMemberExceptionSpec(Spec.first, Spec.second);
}
namespace {
/// CRTP base class for visiting operations performed by a special member
/// function (or inherited constructor).
template<typename Derived>
struct SpecialMemberVisitor {
Sema &S;
CXXMethodDecl *MD;
Sema::CXXSpecialMember CSM;
Sema::InheritedConstructorInfo *ICI;
// Properties of the special member, computed for convenience.
bool IsConstructor = false, IsAssignment = false, ConstArg = false;
SpecialMemberVisitor(Sema &S, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM,
Sema::InheritedConstructorInfo *ICI)
: S(S), MD(MD), CSM(CSM), ICI(ICI) {
switch (CSM) {
case Sema::CXXDefaultConstructor:
case Sema::CXXCopyConstructor:
case Sema::CXXMoveConstructor:
IsConstructor = true;
break;
case Sema::CXXCopyAssignment:
case Sema::CXXMoveAssignment:
IsAssignment = true;
break;
case Sema::CXXDestructor:
break;
case Sema::CXXInvalid:
llvm_unreachable("invalid special member kind");
}
if (MD->getNumParams()) {
if (const ReferenceType *RT =
MD->getParamDecl(0)->getType()->getAs<ReferenceType>())
ConstArg = RT->getPointeeType().isConstQualified();
}
}
Derived &getDerived() { return static_cast<Derived&>(*this); }
/// Is this a "move" special member?
bool isMove() const {
return CSM == Sema::CXXMoveConstructor || CSM == Sema::CXXMoveAssignment;
}
/// Look up the corresponding special member in the given class.
Sema::SpecialMemberOverloadResult lookupIn(CXXRecordDecl *Class,
unsigned Quals, bool IsMutable) {
return lookupCallFromSpecialMember(S, Class, CSM, Quals,
ConstArg && !IsMutable);
}
/// Look up the constructor for the specified base class to see if it's
/// overridden due to this being an inherited constructor.
Sema::SpecialMemberOverloadResult lookupInheritedCtor(CXXRecordDecl *Class) {
if (!ICI)
return {};
assert(CSM == Sema::CXXDefaultConstructor);
auto *BaseCtor =
cast<CXXConstructorDecl>(MD)->getInheritedConstructor().getConstructor();
if (auto *MD = ICI->findConstructorForBase(Class, BaseCtor).first)
return MD;
return {};
}
/// A base or member subobject.
typedef llvm::PointerUnion<CXXBaseSpecifier*, FieldDecl*> Subobject;
/// Get the location to use for a subobject in diagnostics.
static SourceLocation getSubobjectLoc(Subobject Subobj) {
// FIXME: For an indirect virtual base, the direct base leading to
// the indirect virtual base would be a more useful choice.
if (auto *B = Subobj.dyn_cast<CXXBaseSpecifier*>())
return B->getBaseTypeLoc();
else
return Subobj.get<FieldDecl*>()->getLocation();
}
enum BasesToVisit {
/// Visit all non-virtual (direct) bases.
VisitNonVirtualBases,
/// Visit all direct bases, virtual or not.
VisitDirectBases,
/// Visit all non-virtual bases, and all virtual bases if the class
/// is not abstract.
VisitPotentiallyConstructedBases,
/// Visit all direct or virtual bases.
VisitAllBases
};
// Visit the bases and members of the class.
bool visit(BasesToVisit Bases) {
CXXRecordDecl *RD = MD->getParent();
if (Bases == VisitPotentiallyConstructedBases)
Bases = RD->isAbstract() ? VisitNonVirtualBases : VisitAllBases;
for (auto &B : RD->bases())
if ((Bases == VisitDirectBases || !B.isVirtual()) &&
getDerived().visitBase(&B))
return true;
if (Bases == VisitAllBases)
for (auto &B : RD->vbases())
if (getDerived().visitBase(&B))
return true;
for (auto *F : RD->fields())
if (!F->isInvalidDecl() && !F->isUnnamedBitfield() &&
getDerived().visitField(F))
return true;
return false;
}
};
}
namespace {
struct SpecialMemberDeletionInfo
: SpecialMemberVisitor<SpecialMemberDeletionInfo> {
bool Diagnose;
SourceLocation Loc;
bool AllFieldsAreConst;
SpecialMemberDeletionInfo(Sema &S, CXXMethodDecl *MD,
Sema::CXXSpecialMember CSM,
Sema::InheritedConstructorInfo *ICI, bool Diagnose)
: SpecialMemberVisitor(S, MD, CSM, ICI), Diagnose(Diagnose),
Loc(MD->getLocation()), AllFieldsAreConst(true) {}
bool inUnion() const { return MD->getParent()->isUnion(); }
Sema::CXXSpecialMember getEffectiveCSM() {
return ICI ? Sema::CXXInvalid : CSM;
}
bool visitBase(CXXBaseSpecifier *Base) { return shouldDeleteForBase(Base); }
bool visitField(FieldDecl *Field) { return shouldDeleteForField(Field); }
bool shouldDeleteForBase(CXXBaseSpecifier *Base);
bool shouldDeleteForField(FieldDecl *FD);
bool shouldDeleteForAllConstMembers();
bool shouldDeleteForClassSubobject(CXXRecordDecl *Class, Subobject Subobj,
unsigned Quals);
bool shouldDeleteForSubobjectCall(Subobject Subobj,
Sema::SpecialMemberOverloadResult SMOR,
bool IsDtorCallInCtor);
bool isAccessible(Subobject Subobj, CXXMethodDecl *D);
};
}
/// Is the given special member inaccessible when used on the given
/// sub-object.
bool SpecialMemberDeletionInfo::isAccessible(Subobject Subobj,
CXXMethodDecl *target) {
/// If we're operating on a base class, the object type is the
/// type of this special member.
QualType objectTy;
AccessSpecifier access = target->getAccess();
if (CXXBaseSpecifier *base = Subobj.dyn_cast<CXXBaseSpecifier*>()) {
objectTy = S.Context.getTypeDeclType(MD->getParent());
access = CXXRecordDecl::MergeAccess(base->getAccessSpecifier(), access);
// If we're operating on a field, the object type is the type of the field.
} else {
objectTy = S.Context.getTypeDeclType(target->getParent());
}
return S.isSpecialMemberAccessibleForDeletion(target, access, objectTy);
}
/// Check whether we should delete a special member due to the implicit
/// definition containing a call to a special member of a subobject.
bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
Subobject Subobj, Sema::SpecialMemberOverloadResult SMOR,
bool IsDtorCallInCtor) {
CXXMethodDecl *Decl = SMOR.getMethod();
FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
int DiagKind = -1;
if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
DiagKind = !Decl ? 0 : 1;
else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
DiagKind = 2;
else if (!isAccessible(Subobj, Decl))
DiagKind = 3;
else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() &&
!Decl->isTrivial()) {
// A member of a union must have a trivial corresponding special member.
// As a weird special case, a destructor call from a union's constructor
// must be accessible and non-deleted, but need not be trivial. Such a
// destructor is never actually called, but is semantically checked as
// if it were.
DiagKind = 4;
}
if (DiagKind == -1)
return false;
if (Diagnose) {
if (Field) {
S.Diag(Field->getLocation(),
diag::note_deleted_special_member_class_subobject)
<< getEffectiveCSM() << MD->getParent() << /*IsField*/true
<< Field << DiagKind << IsDtorCallInCtor;
} else {
CXXBaseSpecifier *Base = Subobj.get<CXXBaseSpecifier*>();
S.Diag(Base->getBeginLoc(),
diag::note_deleted_special_member_class_subobject)
<< getEffectiveCSM() << MD->getParent() << /*IsField*/ false
<< Base->getType() << DiagKind << IsDtorCallInCtor;
}
if (DiagKind == 1)
S.NoteDeletedFunction(Decl);
// FIXME: Explain inaccessibility if DiagKind == 3.
}
return true;
}
/// Check whether we should delete a special member function due to having a
/// direct or virtual base class or non-static data member of class type M.
bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
CXXRecordDecl *Class, Subobject Subobj, unsigned Quals) {
FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
bool IsMutable = Field && Field->isMutable();
// C++11 [class.ctor]p5:
// -- any direct or virtual base class, or non-static data member with no
// brace-or-equal-initializer, has class type M (or array thereof) and
// either M has no default constructor or overload resolution as applied
// to M's default constructor results in an ambiguity or in a function
// that is deleted or inaccessible
// C++11 [class.copy]p11, C++11 [class.copy]p23:
// -- a direct or virtual base class B that cannot be copied/moved because
// overload resolution, as applied to B's corresponding special member,
// results in an ambiguity or a function that is deleted or inaccessible
// from the defaulted special member
// C++11 [class.dtor]p5:
// -- any direct or virtual base class [...] has a type with a destructor
// that is deleted or inaccessible
if (!(CSM == Sema::CXXDefaultConstructor &&
Field && Field->hasInClassInitializer()) &&
shouldDeleteForSubobjectCall(Subobj, lookupIn(Class, Quals, IsMutable),
false))
return true;
// C++11 [class.ctor]p5, C++11 [class.copy]p11:
// -- any direct or virtual base class or non-static data member has a
// type with a destructor that is deleted or inaccessible
if (IsConstructor) {
Sema::SpecialMemberOverloadResult SMOR =
S.LookupSpecialMember(Class, Sema::CXXDestructor,
false, false, false, false, false);
if (shouldDeleteForSubobjectCall(Subobj, SMOR, true))
return true;
}
return false;
}
/// Check whether we should delete a special member function due to the class
/// having a particular direct or virtual base class.
bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) {
CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl();
// If program is correct, BaseClass cannot be null, but if it is, the error
// must be reported elsewhere.
if (!BaseClass)
return false;
// If we have an inheriting constructor, check whether we're calling an
// inherited constructor instead of a default constructor.
Sema::SpecialMemberOverloadResult SMOR = lookupInheritedCtor(BaseClass);
if (auto *BaseCtor = SMOR.getMethod()) {
// Note that we do not check access along this path; other than that,
// this is the same as shouldDeleteForSubobjectCall(Base, BaseCtor, false);
// FIXME: Check that the base has a usable destructor! Sink this into
// shouldDeleteForClassSubobject.
if (BaseCtor->isDeleted() && Diagnose) {
S.Diag(Base->getBeginLoc(),
diag::note_deleted_special_member_class_subobject)
<< getEffectiveCSM() << MD->getParent() << /*IsField*/ false
<< Base->getType() << /*Deleted*/ 1 << /*IsDtorCallInCtor*/ false;
S.NoteDeletedFunction(BaseCtor);
}
return BaseCtor->isDeleted();
}
return shouldDeleteForClassSubobject(BaseClass, Base, 0);
}
/// Check whether we should delete a special member function due to the class
/// having a particular non-static data member.
bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
QualType FieldType = S.Context.getBaseElementType(FD->getType());
CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl();
if (CSM == Sema::CXXDefaultConstructor) {
// For a default constructor, all references must be initialized in-class
// and, if a union, it must have a non-const member.
if (FieldType->isReferenceType() && !FD->hasInClassInitializer()) {
if (Diagnose)
S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field)
<< !!ICI << MD->getParent() << FD << FieldType << /*Reference*/0;
return true;
}
// C++11 [class.ctor]p5: any non-variant non-static data member of
// const-qualified type (or array thereof) with no
// brace-or-equal-initializer does not have a user-provided default
// constructor.
if (!inUnion() && FieldType.isConstQualified() &&
!FD->hasInClassInitializer() &&
(!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor())) {
if (Diagnose)
S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field)
<< !!ICI << MD->getParent() << FD << FD->getType() << /*Const*/1;
return true;
}
if (inUnion() && !FieldType.isConstQualified())
AllFieldsAreConst = false;
} else if (CSM == Sema::CXXCopyConstructor) {
// For a copy constructor, data members must not be of rvalue reference
// type.
if (FieldType->isRValueReferenceType()) {
if (Diagnose)
S.Diag(FD->getLocation(), diag::note_deleted_copy_ctor_rvalue_reference)
<< MD->getParent() << FD << FieldType;
return true;
}
} else if (IsAssignment) {
// For an assignment operator, data members must not be of reference type.
if (FieldType->isReferenceType()) {
if (Diagnose)
S.Diag(FD->getLocation(), diag::note_deleted_assign_field)
<< isMove() << MD->getParent() << FD << FieldType << /*Reference*/0;
return true;
}
if (!FieldRecord && FieldType.isConstQualified()) {
// C++11 [class.copy]p23:
// -- a non-static data member of const non-class type (or array thereof)
if (Diagnose)
S.Diag(FD->getLocation(), diag::note_deleted_assign_field)
<< isMove() << MD->getParent() << FD << FD->getType() << /*Const*/1;
return true;
}
}
if (FieldRecord) {
// Some additional restrictions exist on the variant members.
if (!inUnion() && FieldRecord->isUnion() &&
FieldRecord->isAnonymousStructOrUnion()) {
bool AllVariantFieldsAreConst = true;
// FIXME: Handle anonymous unions declared within anonymous unions.
for (auto *UI : FieldRecord->fields()) {
QualType UnionFieldType = S.Context.getBaseElementType(UI->getType());
if (!UnionFieldType.isConstQualified())
AllVariantFieldsAreConst = false;
CXXRecordDecl *UnionFieldRecord = UnionFieldType->getAsCXXRecordDecl();
if (UnionFieldRecord &&
shouldDeleteForClassSubobject(UnionFieldRecord, UI,
UnionFieldType.getCVRQualifiers()))
return true;
}
// At least one member in each anonymous union must be non-const
if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst &&
!FieldRecord->field_empty()) {
if (Diagnose)
S.Diag(FieldRecord->getLocation(),
diag::note_deleted_default_ctor_all_const)
<< !!ICI << MD->getParent() << /*anonymous union*/1;
return true;
}
// Don't check the implicit member of the anonymous union type.
// This is technically non-conformant, but sanity demands it.
return false;
}
if (shouldDeleteForClassSubobject(FieldRecord, FD,
FieldType.getCVRQualifiers()))
return true;
}
return false;
}
/// C++11 [class.ctor] p5:
/// A defaulted default constructor for a class X is defined as deleted if
/// X is a union and all of its variant members are of const-qualified type.
bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() {
// This is a silly definition, because it gives an empty union a deleted
// default constructor. Don't do that.
if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst) {
bool AnyFields = false;
for (auto *F : MD->getParent()->fields())
if ((AnyFields = !F->isUnnamedBitfield()))
break;
if (!AnyFields)
return false;
if (Diagnose)
S.Diag(MD->getParent()->getLocation(),
diag::note_deleted_default_ctor_all_const)
<< !!ICI << MD->getParent() << /*not anonymous union*/0;
return true;
}
return false;
}
/// Determine whether a defaulted special member function should be defined as
/// deleted, as specified in C++11 [class.ctor]p5, C++11 [class.copy]p11,
/// C++11 [class.copy]p23, and C++11 [class.dtor]p5.
bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
InheritedConstructorInfo *ICI,
bool Diagnose) {
if (MD->isInvalidDecl())
return false;
CXXRecordDecl *RD = MD->getParent();
assert(!RD->isDependentType() && "do deletion after instantiation");
if (!LangOpts.CPlusPlus11 || RD->isInvalidDecl())
return false;
// C++11 [expr.lambda.prim]p19:
// The closure type associated with a lambda-expression has a
// deleted (8.4.3) default constructor and a deleted copy
// assignment operator.
// C++2a adds back these operators if the lambda has no capture-default.
if (RD->isLambda() && !RD->lambdaIsDefaultConstructibleAndAssignable() &&
(CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment)) {
if (Diagnose)
Diag(RD->getLocation(), diag::note_lambda_decl);
return true;
}
// For an anonymous struct or union, the copy and assignment special members
// will never be used, so skip the check. For an anonymous union declared at
// namespace scope, the constructor and destructor are used.
if (CSM != CXXDefaultConstructor && CSM != CXXDestructor &&
RD->isAnonymousStructOrUnion())
return false;
// C++11 [class.copy]p7, p18:
// If the class definition declares a move constructor or move assignment
// operator, an implicitly declared copy constructor or copy assignment
// operator is defined as deleted.
if (MD->isImplicit() &&
(CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) {
CXXMethodDecl *UserDeclaredMove = nullptr;
// In Microsoft mode up to MSVC 2013, a user-declared move only causes the
// deletion of the corresponding copy operation, not both copy operations.
// MSVC 2015 has adopted the standards conforming behavior.
bool DeletesOnlyMatchingCopy =
getLangOpts().MSVCCompat &&
!getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015);
if (RD->hasUserDeclaredMoveConstructor() &&
(!DeletesOnlyMatchingCopy || CSM == CXXCopyConstructor)) {
if (!Diagnose) return true;
// Find any user-declared move constructor.
for (auto *I : RD->ctors()) {
if (I->isMoveConstructor()) {
UserDeclaredMove = I;
break;
}
}
assert(UserDeclaredMove);
} else if (RD->hasUserDeclaredMoveAssignment() &&
(!DeletesOnlyMatchingCopy || CSM == CXXCopyAssignment)) {
if (!Diagnose) return true;
// Find any user-declared move assignment operator.
for (auto *I : RD->methods()) {
if (I->isMoveAssignmentOperator()) {
UserDeclaredMove = I;
break;
}
}
assert(UserDeclaredMove);
}
if (UserDeclaredMove) {
Diag(UserDeclaredMove->getLocation(),
diag::note_deleted_copy_user_declared_move)
<< (CSM == CXXCopyAssignment) << RD
<< UserDeclaredMove->isMoveAssignmentOperator();
return true;
}
}
// Do access control from the special member function
ContextRAII MethodContext(*this, MD);
// C++11 [class.dtor]p5:
// -- for a virtual destructor, lookup of the non-array deallocation function
// results in an ambiguity or in a function that is deleted or inaccessible
if (CSM == CXXDestructor && MD->isVirtual()) {
FunctionDecl *OperatorDelete = nullptr;
DeclarationName Name =
Context.DeclarationNames.getCXXOperatorName(OO_Delete);
if (FindDeallocationFunction(MD->getLocation(), MD->getParent(), Name,
OperatorDelete, /*Diagnose*/false)) {
if (Diagnose)
Diag(RD->getLocation(), diag::note_deleted_dtor_no_operator_delete);
return true;
}
}
SpecialMemberDeletionInfo SMI(*this, MD, CSM, ICI, Diagnose);
// Per DR1611, do not consider virtual bases of constructors of abstract
// classes, since we are not going to construct them.
// Per DR1658, do not consider virtual bases of destructors of abstract
// classes either.
// Per DR2180, for assignment operators we only assign (and thus only
// consider) direct bases.
if (SMI.visit(SMI.IsAssignment ? SMI.VisitDirectBases
: SMI.VisitPotentiallyConstructedBases))
return true;
if (SMI.shouldDeleteForAllConstMembers())
return true;
if (getLangOpts().CUDA) {
// We should delete the special member in CUDA mode if target inference
// failed.
// For inherited constructors (non-null ICI), CSM may be passed so that MD
// is treated as certain special member, which may not reflect what special
// member MD really is. However inferCUDATargetForImplicitSpecialMember
// expects CSM to match MD, therefore recalculate CSM.
assert(ICI || CSM == getSpecialMember(MD));
auto RealCSM = CSM;
if (ICI)
RealCSM = getSpecialMember(MD);
return inferCUDATargetForImplicitSpecialMember(RD, RealCSM, MD,
SMI.ConstArg, Diagnose);
}
return false;
}
/// Perform lookup for a special member of the specified kind, and determine
/// whether it is trivial. If the triviality can be determined without the
/// lookup, skip it. This is intended for use when determining whether a
/// special member of a containing object is trivial, and thus does not ever
/// perform overload resolution for default constructors.
///
/// If \p Selected is not \c NULL, \c *Selected will be filled in with the
/// member that was most likely to be intended to be trivial, if any.
///
/// If \p ForCall is true, look at CXXRecord::HasTrivialSpecialMembersForCall to
/// determine whether the special member is trivial.
static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
Sema::CXXSpecialMember CSM, unsigned Quals,
bool ConstRHS,
Sema::TrivialABIHandling TAH,
CXXMethodDecl **Selected) {
if (Selected)
*Selected = nullptr;
switch (CSM) {
case Sema::CXXInvalid:
llvm_unreachable("not a special member");
case Sema::CXXDefaultConstructor:
// C++11 [class.ctor]p5:
// A default constructor is trivial if:
// - all the [direct subobjects] have trivial default constructors
//
// Note, no overload resolution is performed in this case.
if (RD->hasTrivialDefaultConstructor())
return true;
if (Selected) {
// If there's a default constructor which could have been trivial, dig it
// out. Otherwise, if there's any user-provided default constructor, point
// to that as an example of why there's not a trivial one.
CXXConstructorDecl *DefCtor = nullptr;
if (RD->needsImplicitDefaultConstructor())
S.DeclareImplicitDefaultConstructor(RD);
for (auto *CI : RD->ctors()) {
if (!CI->isDefaultConstructor())
continue;
DefCtor = CI;
if (!DefCtor->isUserProvided())
break;
}
*Selected = DefCtor;
}
return false;
case Sema::CXXDestructor:
// C++11 [class.dtor]p5:
// A destructor is trivial if:
// - all the direct [subobjects] have trivial destructors
if (RD->hasTrivialDestructor() ||
(TAH == Sema::TAH_ConsiderTrivialABI &&
RD->hasTrivialDestructorForCall()))
return true;
if (Selected) {
if (RD->needsImplicitDestructor())
S.DeclareImplicitDestructor(RD);
*Selected = RD->getDestructor();
}
return false;
case Sema::CXXCopyConstructor:
// C++11 [class.copy]p12:
// A copy constructor is trivial if:
// - the constructor selected to copy each direct [subobject] is trivial
if (RD->hasTrivialCopyConstructor() ||
(TAH == Sema::TAH_ConsiderTrivialABI &&
RD->hasTrivialCopyConstructorForCall())) {
if (Quals == Qualifiers::Const)
// We must either select the trivial copy constructor or reach an
// ambiguity; no need to actually perform overload resolution.
return true;
} else if (!Selected) {
return false;
}
// In C++98, we are not supposed to perform overload resolution here, but we
// treat that as a language defect, as suggested on cxx-abi-dev, to treat
// cases like B as having a non-trivial copy constructor:
// struct A { template<typename T> A(T&); };
// struct B { mutable A a; };
goto NeedOverloadResolution;
case Sema::CXXCopyAssignment:
// C++11 [class.copy]p25:
// A copy assignment operator is trivial if:
// - the assignment operator selected to copy each direct [subobject] is
// trivial
if (RD->hasTrivialCopyAssignment()) {
if (Quals == Qualifiers::Const)
return true;
} else if (!Selected) {
return false;
}
// In C++98, we are not supposed to perform overload resolution here, but we
// treat that as a language defect.
goto NeedOverloadResolution;
case Sema::CXXMoveConstructor:
case Sema::CXXMoveAssignment:
NeedOverloadResolution:
Sema::SpecialMemberOverloadResult SMOR =
lookupCallFromSpecialMember(S, RD, CSM, Quals, ConstRHS);
// The standard doesn't describe how to behave if the lookup is ambiguous.
// We treat it as not making the member non-trivial, just like the standard
// mandates for the default constructor. This should rarely matter, because
// the member will also be deleted.
if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
return true;
if (!SMOR.getMethod()) {
assert(SMOR.getKind() ==
Sema::SpecialMemberOverloadResult::NoMemberOrDeleted);
return false;
}
// We deliberately don't check if we found a deleted special member. We're
// not supposed to!
if (Selected)
*Selected = SMOR.getMethod();
if (TAH == Sema::TAH_ConsiderTrivialABI &&
(CSM == Sema::CXXCopyConstructor || CSM == Sema::CXXMoveConstructor))
return SMOR.getMethod()->isTrivialForCall();
return SMOR.getMethod()->isTrivial();
}
llvm_unreachable("unknown special method kind");
}
static CXXConstructorDecl *findUserDeclaredCtor(CXXRecordDecl *RD) {
for (auto *CI : RD->ctors())
if (!CI->isImplicit())
return CI;
// Look for constructor templates.
typedef CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl> tmpl_iter;
for (tmpl_iter TI(RD->decls_begin()), TE(RD->decls_end()); TI != TE; ++TI) {
if (CXXConstructorDecl *CD =
dyn_cast<CXXConstructorDecl>(TI->getTemplatedDecl()))
return CD;
}
return nullptr;
}
/// The kind of subobject we are checking for triviality. The values of this
/// enumeration are used in diagnostics.
enum TrivialSubobjectKind {
/// The subobject is a base class.
TSK_BaseClass,
/// The subobject is a non-static data member.
TSK_Field,
/// The object is actually the complete object.
TSK_CompleteObject
};
/// Check whether the special member selected for a given type would be trivial.
static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
QualType SubType, bool ConstRHS,
Sema::CXXSpecialMember CSM,
TrivialSubobjectKind Kind,
Sema::TrivialABIHandling TAH, bool Diagnose) {
CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl();
if (!SubRD)
return true;
CXXMethodDecl *Selected;
if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(),
ConstRHS, TAH, Diagnose ? &Selected : nullptr))
return true;
if (Diagnose) {
if (ConstRHS)
SubType.addConst();
if (!Selected && CSM == Sema::CXXDefaultConstructor) {
S.Diag(SubobjLoc, diag::note_nontrivial_no_def_ctor)
<< Kind << SubType.getUnqualifiedType();
if (CXXConstructorDecl *CD = findUserDeclaredCtor(SubRD))
S.Diag(CD->getLocation(), diag::note_user_declared_ctor);
} else if (!Selected)
S.Diag(SubobjLoc, diag::note_nontrivial_no_copy)
<< Kind << SubType.getUnqualifiedType() << CSM << SubType;
else if (Selected->isUserProvided()) {
if (Kind == TSK_CompleteObject)
S.Diag(Selected->getLocation(), diag::note_nontrivial_user_provided)
<< Kind << SubType.getUnqualifiedType() << CSM;
else {
S.Diag(SubobjLoc, diag::note_nontrivial_user_provided)
<< Kind << SubType.getUnqualifiedType() << CSM;
S.Diag(Selected->getLocation(), diag::note_declared_at);
}
} else {
if (Kind != TSK_CompleteObject)
S.Diag(SubobjLoc, diag::note_nontrivial_subobject)
<< Kind << SubType.getUnqualifiedType() << CSM;
// Explain why the defaulted or deleted special member isn't trivial.
S.SpecialMemberIsTrivial(Selected, CSM, Sema::TAH_IgnoreTrivialABI,
Diagnose);
}
}
return false;
}
/// Check whether the members of a class type allow a special member to be
/// trivial.
static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
Sema::CXXSpecialMember CSM,
bool ConstArg,
Sema::TrivialABIHandling TAH,
bool Diagnose) {
for (const auto *FI : RD->fields()) {
if (FI->isInvalidDecl() || FI->isUnnamedBitfield())
continue;
QualType FieldType = S.Context.getBaseElementType(FI->getType());
// Pretend anonymous struct or union members are members of this class.
if (FI->isAnonymousStructOrUnion()) {
if (!checkTrivialClassMembers(S, FieldType->getAsCXXRecordDecl(),
CSM, ConstArg, TAH, Diagnose))
return false;
continue;
}
// C++11 [class.ctor]p5:
// A default constructor is trivial if [...]
// -- no non-static data member of its class has a
// brace-or-equal-initializer
if (CSM == Sema::CXXDefaultConstructor && FI->hasInClassInitializer()) {
if (Diagnose)
S.Diag(FI->getLocation(), diag::note_nontrivial_in_class_init) << FI;
return false;
}
// Objective C ARC 4.3.5:
// [...] nontrivally ownership-qualified types are [...] not trivially
// default constructible, copy constructible, move constructible, copy
// assignable, move assignable, or destructible [...]
if (FieldType.hasNonTrivialObjCLifetime()) {
if (Diagnose)
S.Diag(FI->getLocation(), diag::note_nontrivial_objc_ownership)
<< RD << FieldType.getObjCLifetime();
return false;
}
bool ConstRHS = ConstArg && !FI->isMutable();
if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, ConstRHS,
CSM, TSK_Field, TAH, Diagnose))
return false;
}
return true;
}
/// Diagnose why the specified class does not have a trivial special member of
/// the given kind.
void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) {
QualType Ty = Context.getRecordType(RD);
bool ConstArg = (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment);
checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, ConstArg, CSM,
TSK_CompleteObject, TAH_IgnoreTrivialABI,
/*Diagnose*/true);
}
/// Determine whether a defaulted or deleted special member function is trivial,
/// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12,
/// C++11 [class.copy]p25, and C++11 [class.dtor]p5.
bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
TrivialABIHandling TAH, bool Diagnose) {
assert(!MD->isUserProvided() && CSM != CXXInvalid && "not special enough");
CXXRecordDecl *RD = MD->getParent();
bool ConstArg = false;
// C++11 [class.copy]p12, p25: [DR1593]
// A [special member] is trivial if [...] its parameter-type-list is
// equivalent to the parameter-type-list of an implicit declaration [...]
switch (CSM) {
case CXXDefaultConstructor:
case CXXDestructor:
// Trivial default constructors and destructors cannot have parameters.
break;
case CXXCopyConstructor:
case CXXCopyAssignment: {
// Trivial copy operations always have const, non-volatile parameter types.
ConstArg = true;
const ParmVarDecl *Param0 = MD->getParamDecl(0);
const ReferenceType *RT = Param0->getType()->getAs<ReferenceType>();
if (!RT || RT->getPointeeType().getCVRQualifiers() != Qualifiers::Const) {
if (Diagnose)
Diag(Param0->getLocation(), diag::note_nontrivial_param_type)
<< Param0->getSourceRange() << Param0->getType()
<< Context.getLValueReferenceType(
Context.getRecordType(RD).withConst());
return false;
}
break;
}
case CXXMoveConstructor:
case CXXMoveAssignment: {
// Trivial move operations always have non-cv-qualified parameters.
const ParmVarDecl *Param0 = MD->getParamDecl(0);
const RValueReferenceType *RT =
Param0->getType()->getAs<RValueReferenceType>();
if (!RT || RT->getPointeeType().getCVRQualifiers()) {
if (Diagnose)
Diag(Param0->getLocation(), diag::note_nontrivial_param_type)
<< Param0->getSourceRange() << Param0->getType()
<< Context.getRValueReferenceType(Context.getRecordType(RD));
return false;
}
break;
}
case CXXInvalid:
llvm_unreachable("not a special member");
}
if (MD->getMinRequiredArguments() < MD->getNumParams()) {
if (Diagnose)
Diag(MD->getParamDecl(MD->getMinRequiredArguments())->getLocation(),
diag::note_nontrivial_default_arg)
<< MD->getParamDecl(MD->getMinRequiredArguments())->getSourceRange();
return false;
}
if (MD->isVariadic()) {
if (Diagnose)
Diag(MD->getLocation(), diag::note_nontrivial_variadic);
return false;
}
// C++11 [class.ctor]p5, C++11 [class.dtor]p5:
// A copy/move [constructor or assignment operator] is trivial if
// -- the [member] selected to copy/move each direct base class subobject
// is trivial
//
// C++11 [class.copy]p12, C++11 [class.copy]p25:
// A [default constructor or destructor] is trivial if
// -- all the direct base classes have trivial [default constructors or
// destructors]
for (const auto &BI : RD->bases())
if (!checkTrivialSubobjectCall(*this, BI.getBeginLoc(), BI.getType(),
ConstArg, CSM, TSK_BaseClass, TAH, Diagnose))
return false;
// C++11 [class.ctor]p5, C++11 [class.dtor]p5:
// A copy/move [constructor or assignment operator] for a class X is
// trivial if
// -- for each non-static data member of X that is of class type (or array
// thereof), the constructor selected to copy/move that member is
// trivial
//
// C++11 [class.copy]p12, C++11 [class.copy]p25:
// A [default constructor or destructor] is trivial if
// -- for all of the non-static data members of its class that are of class
// type (or array thereof), each such class has a trivial [default
// constructor or destructor]
if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, TAH, Diagnose))
return false;
// C++11 [class.dtor]p5:
// A destructor is trivial if [...]
// -- the destructor is not virtual
if (CSM == CXXDestructor && MD->isVirtual()) {
if (Diagnose)
Diag(MD->getLocation(), diag::note_nontrivial_virtual_dtor) << RD;
return false;
}
// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25:
// A [special member] for class X is trivial if [...]
// -- class X has no virtual functions and no virtual base classes
if (CSM != CXXDestructor && MD->getParent()->isDynamicClass()) {
if (!Diagnose)
return false;
if (RD->getNumVBases()) {
// Check for virtual bases. We already know that the corresponding
// member in all bases is trivial, so vbases must all be direct.
CXXBaseSpecifier &BS = *RD->vbases_begin();
assert(BS.isVirtual());
Diag(BS.getBeginLoc(), diag::note_nontrivial_has_virtual) << RD << 1;
return false;
}
// Must have a virtual method.
for (const auto *MI : RD->methods()) {
if (MI->isVirtual()) {
SourceLocation MLoc = MI->getBeginLoc();
Diag(MLoc, diag::note_nontrivial_has_virtual) << RD << 0;
return false;
}
}
llvm_unreachable("dynamic class with no vbases and no virtual functions");
}
// Looks like it's trivial!
return true;
}
namespace {
struct FindHiddenVirtualMethod {
Sema *S;
CXXMethodDecl *Method;
llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods;
SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
private:
/// Check whether any most overridden method from MD in Methods
static bool CheckMostOverridenMethods(
const CXXMethodDecl *MD,
const llvm::SmallPtrSetImpl<const CXXMethodDecl *> &Methods) {
if (MD->size_overridden_methods() == 0)
return Methods.count(MD->getCanonicalDecl());
for (const CXXMethodDecl *O : MD->overridden_methods())
if (CheckMostOverridenMethods(O, Methods))
return true;
return false;
}
public:
/// Member lookup function that determines whether a given C++
/// method overloads virtual methods in a base class without overriding any,
/// to be used with CXXRecordDecl::lookupInBases().
bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
RecordDecl *BaseRecord =
Specifier->getType()->getAs<RecordType>()->getDecl();
DeclarationName Name = Method->getDeclName();
assert(Name.getNameKind() == DeclarationName::Identifier);
bool foundSameNameMethod = false;
SmallVector<CXXMethodDecl *, 8> overloadedMethods;
for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
Path.Decls = Path.Decls.slice(1)) {
NamedDecl *D = Path.Decls.front();
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
MD = MD->getCanonicalDecl();
foundSameNameMethod = true;
// Interested only in hidden virtual methods.
if (!MD->isVirtual())
continue;
// If the method we are checking overrides a method from its base
// don't warn about the other overloaded methods. Clang deviates from
// GCC by only diagnosing overloads of inherited virtual functions that
// do not override any other virtual functions in the base. GCC's
// -Woverloaded-virtual diagnoses any derived function hiding a virtual
// function from a base class. These cases may be better served by a
// warning (not specific to virtual functions) on call sites when the
// call would select a different function from the base class, were it
// visible.
// See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example.
if (!S->IsOverload(Method, MD, false))
return true;
// Collect the overload only if its hidden.
if (!CheckMostOverridenMethods(MD, OverridenAndUsingBaseMethods))
overloadedMethods.push_back(MD);
}
}
if (foundSameNameMethod)
OverloadedMethods.append(overloadedMethods.begin(),
overloadedMethods.end());
return foundSameNameMethod;
}
};
} // end anonymous namespace
/// Add the most overriden methods from MD to Methods
static void AddMostOverridenMethods(const CXXMethodDecl *MD,
llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) {
if (MD->size_overridden_methods() == 0)
Methods.insert(MD->getCanonicalDecl());
else
for (const CXXMethodDecl *O : MD->overridden_methods())
AddMostOverridenMethods(O, Methods);
}
/// Check if a method overloads virtual methods in a base class without
/// overriding any.
void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD,
SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) {
if (!MD->getDeclName().isIdentifier())
return;
CXXBasePaths Paths(/*FindAmbiguities=*/true, // true to look in all bases.
/*bool RecordPaths=*/false,
/*bool DetectVirtual=*/false);
FindHiddenVirtualMethod FHVM;
FHVM.Method = MD;
FHVM.S = this;
// Keep the base methods that were overridden or introduced in the subclass
// by 'using' in a set. A base method not in this set is hidden.
CXXRecordDecl *DC = MD->getParent();
DeclContext::lookup_result R = DC->lookup(MD->getDeclName());
for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {
NamedDecl *ND = *I;
if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*I))
ND = shad->getTargetDecl();
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
AddMostOverridenMethods(MD, FHVM.OverridenAndUsingBaseMethods);
}
if (DC->lookupInBases(FHVM, Paths))
OverloadedMethods = FHVM.OverloadedMethods;
}
void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD,
SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) {
for (unsigned i = 0, e = OverloadedMethods.size(); i != e; ++i) {
CXXMethodDecl *overloadedMD = OverloadedMethods[i];
PartialDiagnostic PD = PDiag(
diag::note_hidden_overloaded_virtual_declared_here) << overloadedMD;
HandleFunctionTypeMismatch(PD, MD->getType(), overloadedMD->getType());
Diag(overloadedMD->getLocation(), PD);
}
}
/// Diagnose methods which overload virtual methods in a base class
/// without overriding any.
void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) {
if (MD->isInvalidDecl())
return;
if (Diags.isIgnored(diag::warn_overloaded_virtual, MD->getLocation()))
return;
SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
FindHiddenVirtualMethods(MD, OverloadedMethods);
if (!OverloadedMethods.empty()) {
Diag(MD->getLocation(), diag::warn_overloaded_virtual)
<< MD << (OverloadedMethods.size() > 1);
NoteHiddenVirtualMethods(MD, OverloadedMethods);
}
}
void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
auto PrintDiagAndRemoveAttr = [&]() {
// No diagnostics if this is a template instantiation.
if (!isTemplateInstantiation(RD.getTemplateSpecializationKind()))
Diag(RD.getAttr<TrivialABIAttr>()->getLocation(),
diag::ext_cannot_use_trivial_abi) << &RD;
RD.dropAttr<TrivialABIAttr>();
};
// Ill-formed if the struct has virtual functions.
if (RD.isPolymorphic()) {
PrintDiagAndRemoveAttr();
return;
}
for (const auto &B : RD.bases()) {
// Ill-formed if the base class is non-trivial for the purpose of calls or a
// virtual base.
if ((!B.getType()->isDependentType() &&
!B.getType()->getAsCXXRecordDecl()->canPassInRegisters()) ||
B.isVirtual()) {
PrintDiagAndRemoveAttr();
return;
}
}
for (const auto *FD : RD.fields()) {
// Ill-formed if the field is an ObjectiveC pointer or of a type that is
// non-trivial for the purpose of calls.
QualType FT = FD->getType();
if (FT.getObjCLifetime() == Qualifiers::OCL_Weak) {
PrintDiagAndRemoveAttr();
return;
}
if (const auto *RT = FT->getBaseElementTypeUnsafe()->getAs<RecordType>())
if (!RT->isDependentType() &&
!cast<CXXRecordDecl>(RT->getDecl())->canPassInRegisters()) {
PrintDiagAndRemoveAttr();
return;
}
}
}
void Sema::ActOnFinishCXXMemberSpecification(
Scope *S, SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac,
SourceLocation RBrac, const ParsedAttributesView &AttrList) {
if (!TagDecl)
return;
AdjustDeclIfTemplate(TagDecl);
for (const ParsedAttr &AL : AttrList) {
if (AL.getKind() != ParsedAttr::AT_Visibility)
continue;
AL.setInvalid();
Diag(AL.getLoc(), diag::warn_attribute_after_definition_ignored)
<< AL.getName();
}
ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef(
// strict aliasing violation!
reinterpret_cast<Decl**>(FieldCollector->getCurFields()),
FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList);
CheckCompletedCXXClass(cast<CXXRecordDecl>(TagDecl));
}
/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
/// special functions, such as the default constructor, copy
/// constructor, or destructor, to the given C++ class (C++
/// [special]p1). This routine can only be executed just before the
/// definition of the class is complete.
void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
if (ClassDecl->needsImplicitDefaultConstructor()) {
++ASTContext::NumImplicitDefaultConstructors;
if (ClassDecl->hasInheritedConstructor())
DeclareImplicitDefaultConstructor(ClassDecl);
}
if (ClassDecl->needsImplicitCopyConstructor()) {
++ASTContext::NumImplicitCopyConstructors;
// If the properties or semantics of the copy constructor couldn't be
// determined while the class was being declared, force a declaration
// of it now.
if (ClassDecl->needsOverloadResolutionForCopyConstructor() ||
ClassDecl->hasInheritedConstructor())
DeclareImplicitCopyConstructor(ClassDecl);
// For the MS ABI we need to know whether the copy ctor is deleted. A
// prerequisite for deleting the implicit copy ctor is that the class has a
// move ctor or move assignment that is either user-declared or whose
// semantics are inherited from a subobject. FIXME: We should provide a more
// direct way for CodeGen to ask whether the constructor was deleted.
else if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
(ClassDecl->hasUserDeclaredMoveConstructor() ||
ClassDecl->needsOverloadResolutionForMoveConstructor() ||
ClassDecl->hasUserDeclaredMoveAssignment() ||
ClassDecl->needsOverloadResolutionForMoveAssignment()))
DeclareImplicitCopyConstructor(ClassDecl);
}
if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) {
++ASTContext::NumImplicitMoveConstructors;
if (ClassDecl->needsOverloadResolutionForMoveConstructor() ||
ClassDecl->hasInheritedConstructor())
DeclareImplicitMoveConstructor(ClassDecl);
}
if (ClassDecl->needsImplicitCopyAssignment()) {
++ASTContext::NumImplicitCopyAssignmentOperators;
// If we have a dynamic class, then the copy assignment operator may be
// virtual, so we have to declare it immediately. This ensures that, e.g.,
// it shows up in the right place in the vtable and that we diagnose
// problems with the implicit exception specification.
if (ClassDecl->isDynamicClass() ||
ClassDecl->needsOverloadResolutionForCopyAssignment() ||
ClassDecl->hasInheritedAssignment())
DeclareImplicitCopyAssignment(ClassDecl);
}
if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveAssignment()) {
++ASTContext::NumImplicitMoveAssignmentOperators;
// Likewise for the move assignment operator.
if (ClassDecl->isDynamicClass() ||
ClassDecl->needsOverloadResolutionForMoveAssignment() ||
ClassDecl->hasInheritedAssignment())
DeclareImplicitMoveAssignment(ClassDecl);
}
if (ClassDecl->needsImplicitDestructor()) {
++ASTContext::NumImplicitDestructors;
// If we have a dynamic class, then the destructor may be virtual, so we
// have to declare the destructor immediately. This ensures that, e.g., it
// shows up in the right place in the vtable and that we diagnose problems
// with the implicit exception specification.
if (ClassDecl->isDynamicClass() ||
ClassDecl->needsOverloadResolutionForDestructor())
DeclareImplicitDestructor(ClassDecl);
}
}
unsigned Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) {
if (!D)
return 0;
// The order of template parameters is not important here. All names
// get added to the same scope.
SmallVector<TemplateParameterList *, 4> ParameterLists;
if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
D = TD->getTemplatedDecl();
if (auto *PSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
ParameterLists.push_back(PSD->getTemplateParameters());
if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
for (unsigned i = 0; i < DD->getNumTemplateParameterLists(); ++i)
ParameterLists.push_back(DD->getTemplateParameterList(i));
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate())
ParameterLists.push_back(FTD->getTemplateParameters());
}
}
if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
for (unsigned i = 0; i < TD->getNumTemplateParameterLists(); ++i)
ParameterLists.push_back(TD->getTemplateParameterList(i));
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) {
if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
ParameterLists.push_back(CTD->getTemplateParameters());
}
}
unsigned Count = 0;
for (TemplateParameterList *Params : ParameterLists) {
if (Params->size() > 0)
// Ignore explicit specializations; they don't contribute to the template
// depth.
++Count;
for (NamedDecl *Param : *Params) {
if (Param->getDeclName()) {
S->AddDecl(Param);
IdResolver.AddDecl(Param);
}
}
}
return Count;
}
void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) {
if (!RecordD) return;
AdjustDeclIfTemplate(RecordD);
CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordD);
PushDeclContext(S, Record);
}
void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *RecordD) {
if (!RecordD) return;
PopDeclContext();
}
/// This is used to implement the constant expression evaluation part of the
/// attribute enable_if extension. There is nothing in standard C++ which would
/// require reentering parameters.
void Sema::ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param) {
if (!Param)
return;
S->AddDecl(Param);
if (Param->getDeclName())
IdResolver.AddDecl(Param);
}
/// ActOnStartDelayedCXXMethodDeclaration - We have completed
/// parsing a top-level (non-nested) C++ class, and we are now
/// parsing those parts of the given Method declaration that could
/// not be parsed earlier (C++ [class.mem]p2), such as default
/// arguments. This action should enter the scope of the given
/// Method declaration as if we had just parsed the qualified method
/// name. However, it should not bring the parameters into scope;
/// that will be performed by ActOnDelayedCXXMethodParameter.
void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) {
}
/// ActOnDelayedCXXMethodParameter - We've already started a delayed
/// C++ method declaration. We're (re-)introducing the given
/// function parameter into scope for use in parsing later parts of
/// the method declaration. For example, we could see an
/// ActOnParamDefaultArgument event for this parameter.
void Sema::ActOnDelayedCXXMethodParameter(Scope *S, Decl *ParamD) {
if (!ParamD)
return;
ParmVarDecl *Param = cast<ParmVarDecl>(ParamD);
// If this parameter has an unparsed default argument, clear it out
// to make way for the parsed default argument.
if (Param->hasUnparsedDefaultArg())
Param->setDefaultArg(nullptr);
S->AddDecl(Param);
if (Param->getDeclName())
IdResolver.AddDecl(Param);
}
/// ActOnFinishDelayedCXXMethodDeclaration - We have finished
/// processing the delayed method declaration for Method. The method
/// declaration is now considered finished. There may be a separate
/// ActOnStartOfFunctionDef action later (not necessarily
/// immediately!) for this method, if it was also defined inside the
/// class body.
void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) {
if (!MethodD)
return;
AdjustDeclIfTemplate(MethodD);
FunctionDecl *Method = cast<FunctionDecl>(MethodD);
// Now that we have our default arguments, check the constructor
// again. It could produce additional diagnostics or affect whether
// the class has implicitly-declared destructors, among other
// things.
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Method))
CheckConstructor(Constructor);
// Check the default arguments, which we may have added.
if (!Method->isInvalidDecl())
CheckCXXDefaultArguments(Method);
}
/// CheckConstructorDeclarator - Called by ActOnDeclarator to check
/// the well-formedness of the constructor declarator @p D with type @p
/// R. If there are any errors in the declarator, this routine will
/// emit diagnostics and set the invalid bit to true. In any case, the type
/// will be updated to reflect a well-formed type for the constructor and
/// returned.
QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
StorageClass &SC) {
bool isVirtual = D.getDeclSpec().isVirtualSpecified();
// C++ [class.ctor]p3:
// A constructor shall not be virtual (10.3) or static (9.4). A
// constructor can be invoked for a const, volatile or const
// volatile object. A constructor shall not be declared const,
// volatile, or const volatile (9.3.2).
if (isVirtual) {
if (!D.isInvalidType())
Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
<< "virtual" << SourceRange(D.getDeclSpec().getVirtualSpecLoc())
<< SourceRange(D.getIdentifierLoc());
D.setInvalidType();
}
if (SC == SC_Static) {
if (!D.isInvalidType())
Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
<< "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
<< SourceRange(D.getIdentifierLoc());
D.setInvalidType();
SC = SC_None;
}
if (unsigned TypeQuals = D.getDeclSpec().getTypeQualifiers()) {
diagnoseIgnoredQualifiers(
diag::err_constructor_return_type, TypeQuals, SourceLocation(),
D.getDeclSpec().getConstSpecLoc(), D.getDeclSpec().getVolatileSpecLoc(),
D.getDeclSpec().getRestrictSpecLoc(),
D.getDeclSpec().getAtomicSpecLoc());
D.setInvalidType();
}
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
if (FTI.hasMethodTypeQualifiers()) {
FTI.MethodQualifiers->forEachQualifier(
[&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) {
Diag(SL, diag::err_invalid_qualified_constructor)
<< QualName << SourceRange(SL);
});
D.setInvalidType();
}
// C++0x [class.ctor]p4:
// A constructor shall not be declared with a ref-qualifier.
if (FTI.hasRefQualifier()) {
Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor)
<< FTI.RefQualifierIsLValueRef
<< FixItHint::CreateRemoval(FTI.getRefQualifierLoc());
D.setInvalidType();
}
// Rebuild the function type "R" without any type qualifiers (in
// case any of the errors above fired) and with "void" as the
// return type, since constructors don't have return types.
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
if (Proto->getReturnType() == Context.VoidTy && !D.isInvalidType())
return R;
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
EPI.TypeQuals = Qualifiers();
EPI.RefQualifier = RQ_None;
return Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI);
}
/// CheckConstructor - Checks a fully-formed constructor for
/// well-formedness, issuing any diagnostics required. Returns true if
/// the constructor declarator is invalid.
void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
CXXRecordDecl *ClassDecl
= dyn_cast<CXXRecordDecl>(Constructor->getDeclContext());
if (!ClassDecl)
return Constructor->setInvalidDecl();
// C++ [class.copy]p3:
// A declaration of a constructor for a class X is ill-formed if
// its first parameter is of type (optionally cv-qualified) X and
// either there are no other parameters or else all other
// parameters have default arguments.
if (!Constructor->isInvalidDecl() &&
((Constructor->getNumParams() == 1) ||
(Constructor->getNumParams() > 1 &&
Constructor->getParamDecl(1)->hasDefaultArg())) &&
Constructor->getTemplateSpecializationKind()
!= TSK_ImplicitInstantiation) {
QualType ParamType = Constructor->getParamDecl(0)->getType();
QualType ClassTy = Context.getTagDeclType(ClassDecl);
if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation();
const char *ConstRef
= Constructor->getParamDecl(0)->getIdentifier() ? "const &"
: " const &";
Diag(ParamLoc, diag::err_constructor_byvalue_arg)
<< FixItHint::CreateInsertion(ParamLoc, ConstRef);
// FIXME: Rather that making the constructor invalid, we should endeavor
// to fix the type.
Constructor->setInvalidDecl();
}
}
}
/// CheckDestructor - Checks a fully-formed destructor definition for
/// well-formedness, issuing any diagnostics required. Returns true
/// on error.
bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
CXXRecordDecl *RD = Destructor->getParent();
if (!Destructor->getOperatorDelete() && Destructor->isVirtual()) {
SourceLocation Loc;
if (!Destructor->isImplicit())
Loc = Destructor->getLocation();
else
Loc = RD->getLocation();
// If we have a virtual destructor, look up the deallocation function
if (FunctionDecl *OperatorDelete =
FindDeallocationFunctionForDestructor(Loc, RD)) {
Expr *ThisArg = nullptr;
// If the notional 'delete this' expression requires a non-trivial
// conversion from 'this' to the type of a destroying operator delete's
// first parameter, perform that conversion now.
if (OperatorDelete->isDestroyingOperatorDelete()) {
QualType ParamType = OperatorDelete->getParamDecl(0)->getType();
if (!declaresSameEntity(ParamType->getAsCXXRecordDecl(), RD)) {
// C++ [class.dtor]p13:
// ... as if for the expression 'delete this' appearing in a
// non-virtual destructor of the destructor's class.
ContextRAII SwitchContext(*this, Destructor);
ExprResult This =
ActOnCXXThis(OperatorDelete->getParamDecl(0)->getLocation());
assert(!This.isInvalid() && "couldn't form 'this' expr in dtor?");
This = PerformImplicitConversion(This.get(), ParamType, AA_Passing);
if (This.isInvalid()) {
// FIXME: Register this as a context note so that it comes out
// in the right order.
Diag(Loc, diag::note_implicit_delete_this_in_destructor_here);
return true;
}
ThisArg = This.get();
}
}
DiagnoseUseOfDecl(OperatorDelete, Loc);
MarkFunctionReferenced(Loc, OperatorDelete);
Destructor->setOperatorDelete(OperatorDelete, ThisArg);
}
}
return false;
}
/// CheckDestructorDeclarator - Called by ActOnDeclarator to check
/// the well-formednes of the destructor declarator @p D with type @p
/// R. If there are any errors in the declarator, this routine will
/// emit diagnostics and set the declarator to invalid. Even if this happens,
/// will be updated to reflect a well-formed type for the destructor and
/// returned.
QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
StorageClass& SC) {
// C++ [class.dtor]p1:
// [...] A typedef-name that names a class is a class-name
// (7.1.3); however, a typedef-name that names a class shall not
// be used as the identifier in the declarator for a destructor
// declaration.
QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName);
if (const TypedefType *TT = DeclaratorType->getAs<TypedefType>())
Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
<< DeclaratorType << isa<TypeAliasDecl>(TT->getDecl());
else if (const TemplateSpecializationType *TST =
DeclaratorType->getAs<TemplateSpecializationType>())
if (TST->isTypeAlias())
Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
<< DeclaratorType << 1;
// C++ [class.dtor]p2:
// A destructor is used to destroy objects of its class type. A
// destructor takes no parameters, and no return type can be
// specified for it (not even void). The address of a destructor
// shall not be taken. A destructor shall not be static. A
// destructor can be invoked for a const, volatile or const
// volatile object. A destructor shall not be declared const,
// volatile or const volatile (9.3.2).
if (SC == SC_Static) {
if (!D.isInvalidType())
Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be)
<< "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
<< SourceRange(D.getIdentifierLoc())
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
SC = SC_None;
}
if (!D.isInvalidType()) {
// Destructors don't have return types, but the parser will
// happily parse something like:
//
// class X {
// float ~X();
// };
//
// The return type will be eliminated later.
if (D.getDeclSpec().hasTypeSpecifier())
Diag(D.getIdentifierLoc(), diag::err_destructor_return_type)
<< SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
<< SourceRange(D.getIdentifierLoc());
else if (unsigned TypeQuals = D.getDeclSpec().getTypeQualifiers()) {
diagnoseIgnoredQualifiers(diag::err_destructor_return_type, TypeQuals,
SourceLocation(),
D.getDeclSpec().getConstSpecLoc(),
D.getDeclSpec().getVolatileSpecLoc(),
D.getDeclSpec().getRestrictSpecLoc(),
D.getDeclSpec().getAtomicSpecLoc());
D.setInvalidType();
}
}
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
if (FTI.hasMethodTypeQualifiers() && !D.isInvalidType()) {
FTI.MethodQualifiers->forEachQualifier(
[&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) {
Diag(SL, diag::err_invalid_qualified_destructor)
<< QualName << SourceRange(SL);
});
D.setInvalidType();
}
// C++0x [class.dtor]p2:
// A destructor shall not be declared with a ref-qualifier.
if (FTI.hasRefQualifier()) {
Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_destructor)
<< FTI.RefQualifierIsLValueRef
<< FixItHint::CreateRemoval(FTI.getRefQualifierLoc());
D.setInvalidType();
}
// Make sure we don't have any parameters.
if (FTIHasNonVoidParameters(FTI)) {
Diag(D.getIdentifierLoc(), diag::err_destructor_with_params);
// Delete the parameters.
FTI.freeParams();
D.setInvalidType();
}
// Make sure the destructor isn't variadic.
if (FTI.isVariadic) {
Diag(D.getIdentifierLoc(), diag::err_destructor_variadic);
D.setInvalidType();
}
// Rebuild the function type "R" without any type qualifiers or
// parameters (in case any of the errors above fired) and with
// "void" as the return type, since destructors don't have return
// types.
if (!D.isInvalidType())
return R;
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
EPI.Variadic = false;
EPI.TypeQuals = Qualifiers();
EPI.RefQualifier = RQ_None;
return Context.getFunctionType(Context.VoidTy, None, EPI);
}
static void extendLeft(SourceRange &R, SourceRange Before) {
if (Before.isInvalid())
return;
R.setBegin(Before.getBegin());
if (R.getEnd().isInvalid())
R.setEnd(Before.getEnd());
}
static void extendRight(SourceRange &R, SourceRange After) {
if (After.isInvalid())
return;
if (R.getBegin().isInvalid())
R.setBegin(After.getBegin());
R.setEnd(After.getEnd());
}
/// CheckConversionDeclarator - Called by ActOnDeclarator to check the
/// well-formednes of the conversion function declarator @p D with
/// type @p R. If there are any errors in the declarator, this routine
/// will emit diagnostics and return true. Otherwise, it will return
/// false. Either way, the type @p R will be updated to reflect a
/// well-formed type for the conversion operator.
void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
StorageClass& SC) {
// C++ [class.conv.fct]p1:
// Neither parameter types nor return type can be specified. The
// type of a conversion function (8.3.5) is "function taking no
// parameter returning conversion-type-id."
if (SC == SC_Static) {
if (!D.isInvalidType())
Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member)
<< SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
<< D.getName().getSourceRange();
D.setInvalidType();
SC = SC_None;
}
TypeSourceInfo *ConvTSI = nullptr;
QualType ConvType =
GetTypeFromParser(D.getName().ConversionFunctionId, &ConvTSI);
const DeclSpec &DS = D.getDeclSpec();
if (DS.hasTypeSpecifier() && !D.isInvalidType()) {
// Conversion functions don't have return types, but the parser will
// happily parse something like:
//
// class X {
// float operator bool();
// };
//
// The return type will be changed later anyway.
Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type)
<< SourceRange(DS.getTypeSpecTypeLoc())
<< SourceRange(D.getIdentifierLoc());
D.setInvalidType();
} else if (DS.getTypeQualifiers() && !D.isInvalidType()) {
// It's also plausible that the user writes type qualifiers in the wrong
// place, such as:
// struct S { const operator int(); };
// FIXME: we could provide a fixit to move the qualifiers onto the
// conversion type.
Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl)
<< SourceRange(D.getIdentifierLoc()) << 0;
D.setInvalidType();
}
const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
// Make sure we don't have any parameters.
if (Proto->getNumParams() > 0) {
Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params);
// Delete the parameters.
D.getFunctionTypeInfo().freeParams();
D.setInvalidType();
} else if (Proto->isVariadic()) {
Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic);
D.setInvalidType();
}
// Diagnose "&operator bool()" and other such nonsense. This
// is actually a gcc extension which we don't support.
if (Proto->getReturnType() != ConvType) {
bool NeedsTypedef = false;
SourceRange Before, After;
// Walk the chunks and extract information on them for our diagnostic.
bool PastFunctionChunk = false;
for (auto &Chunk : D.type_objects()) {
switch (Chunk.Kind) {
case DeclaratorChunk::Function:
if (!PastFunctionChunk) {
if (Chunk.Fun.HasTrailingReturnType) {
TypeSourceInfo *TRT = nullptr;
GetTypeFromParser(Chunk.Fun.getTrailingReturnType(), &TRT);
if (TRT) extendRight(After, TRT->getTypeLoc().getSourceRange());
}
PastFunctionChunk = true;
break;
}
LLVM_FALLTHROUGH;
case DeclaratorChunk::Array:
NeedsTypedef = true;
extendRight(After, Chunk.getSourceRange());
break;
case DeclaratorChunk::Pointer:
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Pipe:
extendLeft(Before, Chunk.getSourceRange());
break;
case DeclaratorChunk::Paren:
extendLeft(Before, Chunk.Loc);
extendRight(After, Chunk.EndLoc);
break;
}
}
SourceLocation Loc = Before.isValid() ? Before.getBegin() :
After.isValid() ? After.getBegin() :
D.getIdentifierLoc();
auto &&DB = Diag(Loc, diag::err_conv_function_with_complex_decl);
DB << Before << After;
if (!NeedsTypedef) {
DB << /*don't need a typedef*/0;
// If we can provide a correct fix-it hint, do so.
if (After.isInvalid() && ConvTSI) {
SourceLocation InsertLoc =
getLocForEndOfToken(ConvTSI->getTypeLoc().getEndLoc());
DB << FixItHint::CreateInsertion(InsertLoc, " ")
<< FixItHint::CreateInsertionFromRange(
InsertLoc, CharSourceRange::getTokenRange(Before))
<< FixItHint::CreateRemoval(Before);
}
} else if (!Proto->getReturnType()->isDependentType()) {
DB << /*typedef*/1 << Proto->getReturnType();
} else if (getLangOpts().CPlusPlus11) {
DB << /*alias template*/2 << Proto->getReturnType();
} else {
DB << /*might not be fixable*/3;
}
// Recover by incorporating the other type chunks into the result type.
// Note, this does *not* change the name of the function. This is compatible
// with the GCC extension:
// struct S { &operator int(); } s;
// int &r = s.operator int(); // ok in GCC
// S::operator int&() {} // error in GCC, function name is 'operator int'.
ConvType = Proto->getReturnType();
}
// C++ [class.conv.fct]p4:
// The conversion-type-id shall not represent a function type nor
// an array type.
if (ConvType->isArrayType()) {
Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array);
ConvType = Context.getPointerType(ConvType);
D.setInvalidType();
} else if (ConvType->isFunctionType()) {
Diag(D.getIdentifierLoc(), diag::err_conv_function_to_function);
ConvType = Context.getPointerType(ConvType);
D.setInvalidType();
}
// Rebuild the function type "R" without any parameters (in case any
// of the errors above fired) and with the conversion type as the
// return type.
if (D.isInvalidType())
R = Context.getFunctionType(ConvType, None, Proto->getExtProtoInfo());
// C++0x explicit conversion operators.
if (DS.isExplicitSpecified())
Diag(DS.getExplicitSpecLoc(),
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_explicit_conversion_functions
: diag::ext_explicit_conversion_functions)
<< SourceRange(DS.getExplicitSpecLoc());
}
/// ActOnConversionDeclarator - Called by ActOnDeclarator to complete
/// the declaration of the given C++ conversion function. This routine
/// is responsible for recording the conversion function in the C++
/// class, if possible.
Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
assert(Conversion && "Expected to receive a conversion function declaration");
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Conversion->getDeclContext());
// Make sure we aren't redeclaring the conversion function.
QualType ConvType = Context.getCanonicalType(Conversion->getConversionType());
// C++ [class.conv.fct]p1:
// [...] A conversion function is never used to convert a
// (possibly cv-qualified) object to the (possibly cv-qualified)
// same object type (or a reference to it), to a (possibly
// cv-qualified) base class of that type (or a reference to it),
// or to (possibly cv-qualified) void.
// FIXME: Suppress this warning if the conversion function ends up being a
// virtual function that overrides a virtual function in a base class.
QualType ClassType
= Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
if (const ReferenceType *ConvTypeRef = ConvType->getAs<ReferenceType>())
ConvType = ConvTypeRef->getPointeeType();
if (Conversion->getTemplateSpecializationKind() != TSK_Undeclared &&
Conversion->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
/* Suppress diagnostics for instantiations. */;
else if (ConvType->isRecordType()) {
ConvType = Context.getCanonicalType(ConvType).getUnqualifiedType();
if (ConvType == ClassType)
Diag(Conversion->getLocation(), diag::warn_conv_to_self_not_used)
<< ClassType;
else if (IsDerivedFrom(Conversion->getLocation(), ClassType, ConvType))
Diag(Conversion->getLocation(), diag::warn_conv_to_base_not_used)
<< ClassType << ConvType;
} else if (ConvType->isVoidType()) {
Diag(Conversion->getLocation(), diag::warn_conv_to_void_not_used)
<< ClassType << ConvType;
}
if (FunctionTemplateDecl *ConversionTemplate
= Conversion->getDescribedFunctionTemplate())
return ConversionTemplate;
return Conversion;
}
namespace {
/// Utility class to accumulate and print a diagnostic listing the invalid
/// specifier(s) on a declaration.
struct BadSpecifierDiagnoser {
BadSpecifierDiagnoser(Sema &S, SourceLocation Loc, unsigned DiagID)
: S(S), Diagnostic(S.Diag(Loc, DiagID)) {}
~BadSpecifierDiagnoser() {
Diagnostic << Specifiers;
}
template<typename T> void check(SourceLocation SpecLoc, T Spec) {
return check(SpecLoc, DeclSpec::getSpecifierName(Spec));
}
void check(SourceLocation SpecLoc, DeclSpec::TST Spec) {
return check(SpecLoc,
DeclSpec::getSpecifierName(Spec, S.getPrintingPolicy()));
}
void check(SourceLocation SpecLoc, const char *Spec) {
if (SpecLoc.isInvalid()) return;
Diagnostic << SourceRange(SpecLoc, SpecLoc);
if (!Specifiers.empty()) Specifiers += " ";
Specifiers += Spec;
}
Sema &S;
Sema::SemaDiagnosticBuilder Diagnostic;
std::string Specifiers;
};
}
/// Check the validity of a declarator that we parsed for a deduction-guide.
/// These aren't actually declarators in the grammar, so we need to check that
/// the user didn't specify any pieces that are not part of the deduction-guide
/// grammar.
void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
StorageClass &SC) {
TemplateName GuidedTemplate = D.getName().TemplateName.get().get();
TemplateDecl *GuidedTemplateDecl = GuidedTemplate.getAsTemplateDecl();
assert(GuidedTemplateDecl && "missing template decl for deduction guide");
// C++ [temp.deduct.guide]p3:
// A deduction-gide shall be declared in the same scope as the
// corresponding class template.
if (!CurContext->getRedeclContext()->Equals(
GuidedTemplateDecl->getDeclContext()->getRedeclContext())) {
Diag(D.getIdentifierLoc(), diag::err_deduction_guide_wrong_scope)
<< GuidedTemplateDecl;
Diag(GuidedTemplateDecl->getLocation(), diag::note_template_decl_here);
}
auto &DS = D.getMutableDeclSpec();
// We leave 'friend' and 'virtual' to be rejected in the normal way.
if (DS.hasTypeSpecifier() || DS.getTypeQualifiers() ||
DS.getStorageClassSpecLoc().isValid() || DS.isInlineSpecified() ||
DS.isNoreturnSpecified() || DS.isConstexprSpecified()) {
BadSpecifierDiagnoser Diagnoser(
*this, D.getIdentifierLoc(),
diag::err_deduction_guide_invalid_specifier);
Diagnoser.check(DS.getStorageClassSpecLoc(), DS.getStorageClassSpec());
DS.ClearStorageClassSpecs();
SC = SC_None;
// 'explicit' is permitted.
Diagnoser.check(DS.getInlineSpecLoc(), "inline");
Diagnoser.check(DS.getNoreturnSpecLoc(), "_Noreturn");
Diagnoser.check(DS.getConstexprSpecLoc(), "constexpr");
DS.ClearConstexprSpec();
Diagnoser.check(DS.getConstSpecLoc(), "const");
Diagnoser.check(DS.getRestrictSpecLoc(), "__restrict");
Diagnoser.check(DS.getVolatileSpecLoc(), "volatile");
Diagnoser.check(DS.getAtomicSpecLoc(), "_Atomic");
Diagnoser.check(DS.getUnalignedSpecLoc(), "__unaligned");
DS.ClearTypeQualifiers();
Diagnoser.check(DS.getTypeSpecComplexLoc(), DS.getTypeSpecComplex());
Diagnoser.check(DS.getTypeSpecSignLoc(), DS.getTypeSpecSign());
Diagnoser.check(DS.getTypeSpecWidthLoc(), DS.getTypeSpecWidth());
Diagnoser.check(DS.getTypeSpecTypeLoc(), DS.getTypeSpecType());
DS.ClearTypeSpecType();
}
if (D.isInvalidType())
return;
// Check the declarator is simple enough.
bool FoundFunction = false;
for (const DeclaratorChunk &Chunk : llvm::reverse(D.type_objects())) {
if (Chunk.Kind == DeclaratorChunk::Paren)
continue;
if (Chunk.Kind != DeclaratorChunk::Function || FoundFunction) {
Diag(D.getDeclSpec().getBeginLoc(),
diag::err_deduction_guide_with_complex_decl)
<< D.getSourceRange();
break;
}
if (!Chunk.Fun.hasTrailingReturnType()) {
Diag(D.getName().getBeginLoc(),
diag::err_deduction_guide_no_trailing_return_type);
break;
}
// Check that the return type is written as a specialization of
// the template specified as the deduction-guide's name.
ParsedType TrailingReturnType = Chunk.Fun.getTrailingReturnType();
TypeSourceInfo *TSI = nullptr;
QualType RetTy = GetTypeFromParser(TrailingReturnType, &TSI);
assert(TSI && "deduction guide has valid type but invalid return type?");
bool AcceptableReturnType = false;
bool MightInstantiateToSpecialization = false;
if (auto RetTST =
TSI->getTypeLoc().getAs<TemplateSpecializationTypeLoc>()) {
TemplateName SpecifiedName = RetTST.getTypePtr()->getTemplateName();
bool TemplateMatches =
Context.hasSameTemplateName(SpecifiedName, GuidedTemplate);
if (SpecifiedName.getKind() == TemplateName::Template && TemplateMatches)
AcceptableReturnType = true;
else {
// This could still instantiate to the right type, unless we know it
// names the wrong class template.
auto *TD = SpecifiedName.getAsTemplateDecl();
MightInstantiateToSpecialization = !(TD && isa<ClassTemplateDecl>(TD) &&
!TemplateMatches);
}
} else if (!RetTy.hasQualifiers() && RetTy->isDependentType()) {
MightInstantiateToSpecialization = true;
}
if (!AcceptableReturnType) {
Diag(TSI->getTypeLoc().getBeginLoc(),
diag::err_deduction_guide_bad_trailing_return_type)
<< GuidedTemplate << TSI->getType()
<< MightInstantiateToSpecialization
<< TSI->getTypeLoc().getSourceRange();
}
// Keep going to check that we don't have any inner declarator pieces (we
// could still have a function returning a pointer to a function).
FoundFunction = true;
}
if (D.isFunctionDefinition())
Diag(D.getIdentifierLoc(), diag::err_deduction_guide_defines_function);
}
//===----------------------------------------------------------------------===//
// Namespace Handling
//===----------------------------------------------------------------------===//
/// Diagnose a mismatch in 'inline' qualifiers when a namespace is
/// reopened.
static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc,
SourceLocation Loc,
IdentifierInfo *II, bool *IsInline,
NamespaceDecl *PrevNS) {
assert(*IsInline != PrevNS->isInline());
// HACK: Work around a bug in libstdc++4.6's <atomic>, where
// std::__atomic[0,1,2] are defined as non-inline namespaces, then reopened as
// inline namespaces, with the intention of bringing names into namespace std.
//
// We support this just well enough to get that case working; this is not
// sufficient to support reopening namespaces as inline in general.
if (*IsInline && II && II->getName().startswith("__atomic") &&
S.getSourceManager().isInSystemHeader(Loc)) {
// Mark all prior declarations of the namespace as inline.
for (NamespaceDecl *NS = PrevNS->getMostRecentDecl(); NS;
NS = NS->getPreviousDecl())
NS->setInline(*IsInline);
// Patch up the lookup table for the containing namespace. This isn't really
// correct, but it's good enough for this particular case.
for (auto *I : PrevNS->decls())
if (auto *ND = dyn_cast<NamedDecl>(I))
PrevNS->getParent()->makeDeclVisibleInContext(ND);
return;
}
if (PrevNS->isInline())
// The user probably just forgot the 'inline', so suggest that it
// be added back.
S.Diag(Loc, diag::warn_inline_namespace_reopened_noninline)
<< FixItHint::CreateInsertion(KeywordLoc, "inline ");
else
S.Diag(Loc, diag::err_inline_namespace_mismatch);
S.Diag(PrevNS->getLocation(), diag::note_previous_definition);
*IsInline = PrevNS->isInline();
}
/// ActOnStartNamespaceDef - This is called at the start of a namespace
/// definition.
Decl *Sema::ActOnStartNamespaceDef(
Scope *NamespcScope, SourceLocation InlineLoc, SourceLocation NamespaceLoc,
SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace,
const ParsedAttributesView &AttrList, UsingDirectiveDecl *&UD) {
SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc;
// For anonymous namespace, take the location of the left brace.
SourceLocation Loc = II ? IdentLoc : LBrace;
bool IsInline = InlineLoc.isValid();
bool IsInvalid = false;
bool IsStd = false;
bool AddToKnown = false;
Scope *DeclRegionScope = NamespcScope->getParent();
NamespaceDecl *PrevNS = nullptr;
if (II) {
// C++ [namespace.def]p2:
// The identifier in an original-namespace-definition shall not
// have been previously defined in the declarative region in
// which the original-namespace-definition appears. The
// identifier in an original-namespace-definition is the name of
// the namespace. Subsequently in that declarative region, it is
// treated as an original-namespace-name.
//
// Since namespace names are unique in their scope, and we don't
// look through using directives, just look for any ordinary names
// as if by qualified name lookup.
LookupResult R(*this, II, IdentLoc, LookupOrdinaryName,
ForExternalRedeclaration);
LookupQualifiedName(R, CurContext->getRedeclContext());
NamedDecl *PrevDecl =
R.isSingleResult() ? R.getRepresentativeDecl() : nullptr;
PrevNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl);
if (PrevNS) {
// This is an extended namespace definition.
if (IsInline != PrevNS->isInline())
DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, Loc, II,
&IsInline, PrevNS);
} else if (PrevDecl) {
// This is an invalid name redefinition.
Diag(Loc, diag::err_redefinition_different_kind)
<< II;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
IsInvalid = true;
// Continue on to push Namespc as current DeclContext and return it.
} else if (II->isStr("std") &&
CurContext->getRedeclContext()->isTranslationUnit()) {
// This is the first "real" definition of the namespace "std", so update
// our cache of the "std" namespace to point at this definition.
PrevNS = getStdNamespace();
IsStd = true;
AddToKnown = !IsInline;
} else {
// We've seen this namespace for the first time.
AddToKnown = !IsInline;
}
} else {
// Anonymous namespaces.
// Determine whether the parent already has an anonymous namespace.
DeclContext *Parent = CurContext->getRedeclContext();
if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
PrevNS = TU->getAnonymousNamespace();
} else {
NamespaceDecl *ND = cast<NamespaceDecl>(Parent);
PrevNS = ND->getAnonymousNamespace();
}
if (PrevNS && IsInline != PrevNS->isInline())
DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, NamespaceLoc, II,
&IsInline, PrevNS);
}
NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, IsInline,
StartLoc, Loc, II, PrevNS);
if (IsInvalid)
Namespc->setInvalidDecl();
ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
AddPragmaAttributes(DeclRegionScope, Namespc);
// FIXME: Should we be merging attributes?
if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>())
PushNamespaceVisibilityAttr(Attr, Loc);
if (IsStd)
StdNamespace = Namespc;
if (AddToKnown)
KnownNamespaces[Namespc] = false;
if (II) {
PushOnScopeChains(Namespc, DeclRegionScope);
} else {
// Link the anonymous namespace into its parent.
DeclContext *Parent = CurContext->getRedeclContext();
if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
TU->setAnonymousNamespace(Namespc);
} else {
cast<NamespaceDecl>(Parent)->setAnonymousNamespace(Namespc);
}
CurContext->addDecl(Namespc);
// C++ [namespace.unnamed]p1. An unnamed-namespace-definition
// behaves as if it were replaced by
// namespace unique { /* empty body */ }
// using namespace unique;
// namespace unique { namespace-body }
// where all occurrences of 'unique' in a translation unit are
// replaced by the same identifier and this identifier differs
// from all other identifiers in the entire program.
// We just create the namespace with an empty name and then add an
// implicit using declaration, just like the standard suggests.
//
// CodeGen enforces the "universally unique" aspect by giving all
// declarations semantically contained within an anonymous
// namespace internal linkage.
if (!PrevNS) {
UD = UsingDirectiveDecl::Create(Context, Parent,
/* 'using' */ LBrace,
/* 'namespace' */ SourceLocation(),
/* qualifier */ NestedNameSpecifierLoc(),
/* identifier */ SourceLocation(),
Namespc,
/* Ancestor */ Parent);
UD->setImplicit();
Parent->addDecl(UD);
}
}
ActOnDocumentableDecl(Namespc);
// Although we could have an invalid decl (i.e. the namespace name is a
// redefinition), push it as current DeclContext and try to continue parsing.
// FIXME: We should be able to push Namespc here, so that the each DeclContext
// for the namespace has the declarations that showed up in that particular
// namespace definition.
PushDeclContext(NamespcScope, Namespc);
return Namespc;
}
/// getNamespaceDecl - Returns the namespace a decl represents. If the decl
/// is a namespace alias, returns the namespace it points to.
static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) {
if (NamespaceAliasDecl *AD = dyn_cast_or_null<NamespaceAliasDecl>(D))
return AD->getNamespace();
return dyn_cast_or_null<NamespaceDecl>(D);
}
/// ActOnFinishNamespaceDef - This callback is called after a namespace is
/// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef.
void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) {
NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl);
assert(Namespc && "Invalid parameter, expected NamespaceDecl");
Namespc->setRBraceLoc(RBrace);
PopDeclContext();
if (Namespc->hasAttr<VisibilityAttr>())
PopPragmaVisibility(true, RBrace);
}
CXXRecordDecl *Sema::getStdBadAlloc() const {
return cast_or_null<CXXRecordDecl>(
StdBadAlloc.get(Context.getExternalSource()));
}
EnumDecl *Sema::getStdAlignValT() const {
return cast_or_null<EnumDecl>(StdAlignValT.get(Context.getExternalSource()));
}
NamespaceDecl *Sema::getStdNamespace() const {
return cast_or_null<NamespaceDecl>(
StdNamespace.get(Context.getExternalSource()));
}
NamespaceDecl *Sema::lookupStdExperimentalNamespace() {
if (!StdExperimentalNamespaceCache) {
if (auto Std = getStdNamespace()) {
LookupResult Result(*this, &PP.getIdentifierTable().get("experimental"),
SourceLocation(), LookupNamespaceName);
if (!LookupQualifiedName(Result, Std) ||
!(StdExperimentalNamespaceCache =
Result.getAsSingle<NamespaceDecl>()))
Result.suppressDiagnostics();
}
}
return StdExperimentalNamespaceCache;
}
namespace {
enum UnsupportedSTLSelect {
USS_InvalidMember,
USS_MissingMember,
USS_NonTrivial,
USS_Other
};
struct InvalidSTLDiagnoser {
Sema &S;
SourceLocation Loc;
QualType TyForDiags;
QualType operator()(UnsupportedSTLSelect Sel = USS_Other, StringRef Name = "",
const VarDecl *VD = nullptr) {
{
auto D = S.Diag(Loc, diag::err_std_compare_type_not_supported)
<< TyForDiags << ((int)Sel);
if (Sel == USS_InvalidMember || Sel == USS_MissingMember) {
assert(!Name.empty());
D << Name;
}
}
if (Sel == USS_InvalidMember) {
S.Diag(VD->getLocation(), diag::note_var_declared_here)
<< VD << VD->getSourceRange();
}
return QualType();
}
};
} // namespace
QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind,
SourceLocation Loc) {
assert(getLangOpts().CPlusPlus &&
"Looking for comparison category type outside of C++.");
// Check if we've already successfully checked the comparison category type
// before. If so, skip checking it again.
ComparisonCategoryInfo *Info = Context.CompCategories.lookupInfo(Kind);
if (Info && FullyCheckedComparisonCategories[static_cast<unsigned>(Kind)])
return Info->getType();
// If lookup failed
if (!Info) {
std::string NameForDiags = "std::";
NameForDiags += ComparisonCategories::getCategoryString(Kind);
Diag(Loc, diag::err_implied_comparison_category_type_not_found)
<< NameForDiags;
return QualType();
}
assert(Info->Kind == Kind);
assert(Info->Record);
// Update the Record decl in case we encountered a forward declaration on our
// first pass. FIXME: This is a bit of a hack.
if (Info->Record->hasDefinition())
Info->Record = Info->Record->getDefinition();
// Use an elaborated type for diagnostics which has a name containing the
// prepended 'std' namespace but not any inline namespace names.
QualType TyForDiags = [&]() {
auto *NNS =
NestedNameSpecifier::Create(Context, nullptr, getStdNamespace());
return Context.getElaboratedType(ETK_None, NNS, Info->getType());
}();
if (RequireCompleteType(Loc, TyForDiags, diag::err_incomplete_type))
return QualType();
InvalidSTLDiagnoser UnsupportedSTLError{*this, Loc, TyForDiags};
if (!Info->Record->isTriviallyCopyable())
return UnsupportedSTLError(USS_NonTrivial);
for (const CXXBaseSpecifier &BaseSpec : Info->Record->bases()) {
CXXRecordDecl *Base = BaseSpec.getType()->getAsCXXRecordDecl();
// Tolerate empty base classes.
if (Base->isEmpty())
continue;
// Reject STL implementations which have at least one non-empty base.
return UnsupportedSTLError();
}
// Check that the STL has implemented the types using a single integer field.
// This expectation allows better codegen for builtin operators. We require:
// (1) The class has exactly one field.
// (2) The field is an integral or enumeration type.
auto FIt = Info->Record->field_begin(), FEnd = Info->Record->field_end();
if (std::distance(FIt, FEnd) != 1 ||
!FIt->getType()->isIntegralOrEnumerationType()) {
return UnsupportedSTLError();
}
// Build each of the require values and store them in Info.
for (ComparisonCategoryResult CCR :
ComparisonCategories::getPossibleResultsForType(Kind)) {
StringRef MemName = ComparisonCategories::getResultString(CCR);
ComparisonCategoryInfo::ValueInfo *ValInfo = Info->lookupValueInfo(CCR);
if (!ValInfo)
return UnsupportedSTLError(USS_MissingMember, MemName);
VarDecl *VD = ValInfo->VD;
assert(VD && "should not be null!");
// Attempt to diagnose reasons why the STL definition of this type
// might be foobar, including it failing to be a constant expression.
// TODO Handle more ways the lookup or result can be invalid.
if (!VD->isStaticDataMember() || !VD->isConstexpr() || !VD->hasInit() ||
!VD->checkInitIsICE())
return UnsupportedSTLError(USS_InvalidMember, MemName, VD);
// Attempt to evaluate the var decl as a constant expression and extract
// the value of its first field as a ICE. If this fails, the STL
// implementation is not supported.
if (!ValInfo->hasValidIntValue())
return UnsupportedSTLError();
MarkVariableReferenced(Loc, VD);
}
// We've successfully built the required types and expressions. Update
// the cache and return the newly cached value.
FullyCheckedComparisonCategories[static_cast<unsigned>(Kind)] = true;
return Info->getType();
}
/// Retrieve the special "std" namespace, which may require us to
/// implicitly define the namespace.
NamespaceDecl *Sema::getOrCreateStdNamespace() {
if (!StdNamespace) {
// The "std" namespace has not yet been defined, so build one implicitly.
StdNamespace = NamespaceDecl::Create(Context,
Context.getTranslationUnitDecl(),
/*Inline=*/false,
SourceLocation(), SourceLocation(),
&PP.getIdentifierTable().get("std"),
/*PrevDecl=*/nullptr);
getStdNamespace()->setImplicit(true);
}
return getStdNamespace();
}
bool Sema::isStdInitializerList(QualType Ty, QualType *Element) {
assert(getLangOpts().CPlusPlus &&
"Looking for std::initializer_list outside of C++.");
// We're looking for implicit instantiations of
// template <typename E> class std::initializer_list.
if (!StdNamespace) // If we haven't seen namespace std yet, this can't be it.
return false;
ClassTemplateDecl *Template = nullptr;
const TemplateArgument *Arguments = nullptr;
if (const RecordType *RT = Ty->getAs<RecordType>()) {
ClassTemplateSpecializationDecl *Specialization =
dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
if (!Specialization)
return false;
Template = Specialization->getSpecializedTemplate();
Arguments = Specialization->getTemplateArgs().data();
} else if (const TemplateSpecializationType *TST =
Ty->getAs<TemplateSpecializationType>()) {
Template = dyn_cast_or_null<ClassTemplateDecl>(
TST->getTemplateName().getAsTemplateDecl());
Arguments = TST->getArgs();
}
if (!Template)
return false;
if (!StdInitializerList) {
// Haven't recognized std::initializer_list yet, maybe this is it.
CXXRecordDecl *TemplateClass = Template->getTemplatedDecl();
if (TemplateClass->getIdentifier() !=
&PP.getIdentifierTable().get("initializer_list") ||
!getStdNamespace()->InEnclosingNamespaceSetOf(
TemplateClass->getDeclContext()))
return false;
// This is a template called std::initializer_list, but is it the right
// template?
TemplateParameterList *Params = Template->getTemplateParameters();
if (Params->getMinRequiredArguments() != 1)
return false;
if (!isa<TemplateTypeParmDecl>(Params->getParam(0)))
return false;
// It's the right template.
StdInitializerList = Template;
}
if (Template->getCanonicalDecl() != StdInitializerList->getCanonicalDecl())
return false;
// This is an instance of std::initializer_list. Find the argument type.
if (Element)
*Element = Arguments[0].getAsType();
return true;
}
static ClassTemplateDecl *LookupStdInitializerList(Sema &S, SourceLocation Loc){
NamespaceDecl *Std = S.getStdNamespace();
if (!Std) {
S.Diag(Loc, diag::err_implied_std_initializer_list_not_found);
return nullptr;
}
LookupResult Result(S, &S.PP.getIdentifierTable().get("initializer_list"),
Loc, Sema::LookupOrdinaryName);
if (!S.LookupQualifiedName(Result, Std)) {
S.Diag(Loc, diag::err_implied_std_initializer_list_not_found);
return nullptr;
}
ClassTemplateDecl *Template = Result.getAsSingle<ClassTemplateDecl>();
if (!Template) {
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_initializer_list);
return nullptr;
}
// We found some template called std::initializer_list. Now verify that it's
// correct.
TemplateParameterList *Params = Template->getTemplateParameters();
if (Params->getMinRequiredArguments() != 1 ||
!isa<TemplateTypeParmDecl>(Params->getParam(0))) {
S.Diag(Template->getLocation(), diag::err_malformed_std_initializer_list);
return nullptr;
}
return Template;
}
QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) {
if (!StdInitializerList) {
StdInitializerList = LookupStdInitializerList(*this, Loc);
if (!StdInitializerList)
return QualType();
}
TemplateArgumentListInfo Args(Loc, Loc);
Args.addArgument(TemplateArgumentLoc(TemplateArgument(Element),
Context.getTrivialTypeSourceInfo(Element,
Loc)));
return Context.getCanonicalType(
CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args));
}
bool Sema::isInitListConstructor(const FunctionDecl *Ctor) {
// C++ [dcl.init.list]p2:
// A constructor is an initializer-list constructor if its first parameter
// is of type std::initializer_list<E> or reference to possibly cv-qualified
// std::initializer_list<E> for some type E, and either there are no other
// parameters or else all other parameters have default arguments.
if (Ctor->getNumParams() < 1 ||
(Ctor->getNumParams() > 1 && !Ctor->getParamDecl(1)->hasDefaultArg()))
return false;
QualType ArgType = Ctor->getParamDecl(0)->getType();
if (const ReferenceType *RT = ArgType->getAs<ReferenceType>())
ArgType = RT->getPointeeType().getUnqualifiedType();
return isStdInitializerList(ArgType, nullptr);
}
/// Determine whether a using statement is in a context where it will be
/// apply in all contexts.
static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) {
switch (CurContext->getDeclKind()) {
case Decl::TranslationUnit:
return true;
case Decl::LinkageSpec:
return IsUsingDirectiveInToplevelContext(CurContext->getParent());
default:
return false;
}
}
namespace {
// Callback to only accept typo corrections that are namespaces.
class NamespaceValidatorCCC : public CorrectionCandidateCallback {
public:
bool ValidateCandidate(const TypoCorrection &candidate) override {
if (NamedDecl *ND = candidate.getCorrectionDecl())
return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
return false;
}
};
}
static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *Ident) {
R.clear();
if (TypoCorrection Corrected =
S.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), Sc, &SS,
llvm::make_unique<NamespaceValidatorCCC>(),
Sema::CTK_ErrorRecovery)) {
if (DeclContext *DC = S.computeDeclContext(SS, false)) {
std::string CorrectedStr(Corrected.getAsString(S.getLangOpts()));
bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
Ident->getName().equals(CorrectedStr);
S.diagnoseTypo(Corrected,
S.PDiag(diag::err_using_directive_member_suggest)
<< Ident << DC << DroppedSpecifier << SS.getRange(),
S.PDiag(diag::note_namespace_defined_here));
} else {
S.diagnoseTypo(Corrected,
S.PDiag(diag::err_using_directive_suggest) << Ident,
S.PDiag(diag::note_namespace_defined_here));
}
R.addDecl(Corrected.getFoundDecl());
return true;
}
return false;
}
Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc,
SourceLocation NamespcLoc, CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *NamespcName,
const ParsedAttributesView &AttrList) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
assert(NamespcName && "Invalid NamespcName.");
assert(IdentLoc.isValid() && "Invalid NamespceName location.");
// This can only happen along a recovery path.
while (S->isTemplateParamScope())
S = S->getParent();
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
UsingDirectiveDecl *UDir = nullptr;
NestedNameSpecifier *Qualifier = nullptr;
if (SS.isSet())
Qualifier = SS.getScopeRep();
// Lookup namespace name.
LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
LookupParsedName(R, S, &SS);
if (R.isAmbiguous())
return nullptr;
if (R.empty()) {
R.clear();
// Allow "using namespace std;" or "using namespace ::std;" even if
// "std" hasn't been defined yet, for GCC compatibility.
if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) &&
NamespcName->isStr("std")) {
Diag(IdentLoc, diag::ext_using_undefined_std);
R.addDecl(getOrCreateStdNamespace());
R.resolveKind();
}
// Otherwise, attempt typo correction.
else TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName);
}
if (!R.empty()) {
NamedDecl *Named = R.getRepresentativeDecl();
NamespaceDecl *NS = R.getAsSingle<NamespaceDecl>();
assert(NS && "expected namespace decl");
// The use of a nested name specifier may trigger deprecation warnings.
DiagnoseUseOfDecl(Named, IdentLoc);
// C++ [namespace.udir]p1:
// A using-directive specifies that the names in the nominated
// namespace can be used in the scope in which the
// using-directive appears after the using-directive. During
// unqualified name lookup (3.4.1), the names appear as if they
// were declared in the nearest enclosing namespace which
// contains both the using-directive and the nominated
// namespace. [Note: in this context, "contains" means "contains
// directly or indirectly". ]
// Find enclosing context containing both using-directive and
// nominated namespace.
DeclContext *CommonAncestor = NS;
while (CommonAncestor && !CommonAncestor->Encloses(CurContext))
CommonAncestor = CommonAncestor->getParent();
UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc,
SS.getWithLocInContext(Context),
IdentLoc, Named, CommonAncestor);
if (IsUsingDirectiveInToplevelContext(CurContext) &&
!SourceMgr.isInMainFile(SourceMgr.getExpansionLoc(IdentLoc))) {
Diag(IdentLoc, diag::warn_using_directive_in_header);
}
PushUsingDirective(S, UDir);
} else {
Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
}
if (UDir)
ProcessDeclAttributeList(S, UDir, AttrList);
return UDir;
}
void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
// If the scope has an associated entity and the using directive is at
// namespace or translation unit scope, add the UsingDirectiveDecl into
// its lookup structure so qualified name lookup can find it.
DeclContext *Ctx = S->getEntity();
if (Ctx && !Ctx->isFunctionOrMethod())
Ctx->addDecl(UDir);
else
// Otherwise, it is at block scope. The using-directives will affect lookup
// only to the end of the scope.
S->PushUsingDirective(UDir);
}
Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS,
SourceLocation UsingLoc,
SourceLocation TypenameLoc, CXXScopeSpec &SS,
UnqualifiedId &Name,
SourceLocation EllipsisLoc,
const ParsedAttributesView &AttrList) {
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
if (SS.isEmpty()) {
Diag(Name.getBeginLoc(), diag::err_using_requires_qualname);
return nullptr;
}
switch (Name.getKind()) {
case UnqualifiedIdKind::IK_ImplicitSelfParam:
case UnqualifiedIdKind::IK_Identifier:
case UnqualifiedIdKind::IK_OperatorFunctionId:
case UnqualifiedIdKind::IK_LiteralOperatorId:
case UnqualifiedIdKind::IK_ConversionFunctionId:
break;
case UnqualifiedIdKind::IK_ConstructorName:
case UnqualifiedIdKind::IK_ConstructorTemplateId:
// C++11 inheriting constructors.
Diag(Name.getBeginLoc(),
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_using_decl_constructor
: diag::err_using_decl_constructor)
<< SS.getRange();
if (getLangOpts().CPlusPlus11) break;
return nullptr;
case UnqualifiedIdKind::IK_DestructorName:
Diag(Name.getBeginLoc(), diag::err_using_decl_destructor) << SS.getRange();
return nullptr;
case UnqualifiedIdKind::IK_TemplateId:
Diag(Name.getBeginLoc(), diag::err_using_decl_template_id)
<< SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
return nullptr;
case UnqualifiedIdKind::IK_DeductionGuideName:
llvm_unreachable("cannot parse qualified deduction guide name");
}
DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
DeclarationName TargetName = TargetNameInfo.getName();
if (!TargetName)
return nullptr;
// Warn about access declarations.
if (UsingLoc.isInvalid()) {
Diag(Name.getBeginLoc(), getLangOpts().CPlusPlus11
? diag::err_access_decl
: diag::warn_access_decl_deprecated)
<< FixItHint::CreateInsertion(SS.getRange().getBegin(), "using ");
}
if (EllipsisLoc.isInvalid()) {
if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) ||
DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration))
return nullptr;
} else {
if (!SS.getScopeRep()->containsUnexpandedParameterPack() &&
!TargetNameInfo.containsUnexpandedParameterPack()) {
Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
<< SourceRange(SS.getBeginLoc(), TargetNameInfo.getEndLoc());
EllipsisLoc = SourceLocation();
}
}
NamedDecl *UD =
BuildUsingDeclaration(S, AS, UsingLoc, TypenameLoc.isValid(), TypenameLoc,
SS, TargetNameInfo, EllipsisLoc, AttrList,
/*IsInstantiation*/false);
if (UD)
PushOnScopeChains(UD, S, /*AddToContext*/ false);
return UD;
}
/// Determine whether a using declaration considers the given
/// declarations as "equivalent", e.g., if they are redeclarations of
/// the same entity or are both typedefs of the same type.
static bool
IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2) {
if (D1->getCanonicalDecl() == D2->getCanonicalDecl())
return true;
if (TypedefNameDecl *TD1 = dyn_cast<TypedefNameDecl>(D1))
if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2))
return Context.hasSameType(TD1->getUnderlyingType(),
TD2->getUnderlyingType());
return false;
}
/// Determines whether to create a using shadow decl for a particular
/// decl, given the set of decls existing prior to this using lookup.
bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
const LookupResult &Previous,
UsingShadowDecl *&PrevShadow) {
// Diagnose finding a decl which is not from a base class of the
// current class. We do this now because there are cases where this
// function will silently decide not to build a shadow decl, which
// will pre-empt further diagnostics.
//
// We don't need to do this in C++11 because we do the check once on
// the qualifier.
//
// FIXME: diagnose the following if we care enough:
// struct A { int foo; };
// struct B : A { using A::foo; };
// template <class T> struct C : A {};
// template <class T> struct D : C<T> { using B::foo; } // <---
// This is invalid (during instantiation) in C++03 because B::foo
// resolves to the using decl in B, which is not a base class of D<T>.
// We can't diagnose it immediately because C<T> is an unknown
// specialization. The UsingShadowDecl in D<T> then points directly
// to A::foo, which will look well-formed when we instantiate.
// The right solution is to not collapse the shadow-decl chain.
if (!getLangOpts().CPlusPlus11 && CurContext->isRecord()) {
DeclContext *OrigDC = Orig->getDeclContext();
// Handle enums and anonymous structs.
if (isa<EnumDecl>(OrigDC)) OrigDC = OrigDC->getParent();
CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC);
while (OrigRec->isAnonymousStructOrUnion())
OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext());
if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) {
if (OrigDC == CurContext) {
Diag(Using->getLocation(),
diag::err_using_decl_nested_name_specifier_is_current_class)
<< Using->getQualifierLoc().getSourceRange();
Diag(Orig->getLocation(), diag::note_using_decl_target);
Using->setInvalidDecl();
return true;
}
Diag(Using->getQualifierLoc().getBeginLoc(),
diag::err_using_decl_nested_name_specifier_is_not_base_class)
<< Using->getQualifier()
<< cast<CXXRecordDecl>(CurContext)
<< Using->getQualifierLoc().getSourceRange();
Diag(Orig->getLocation(), diag::note_using_decl_target);
Using->setInvalidDecl();
return true;
}
}
if (Previous.empty()) return false;
NamedDecl *Target = Orig;
if (isa<UsingShadowDecl>(Target))
Target = cast<UsingShadowDecl>(Target)->getTargetDecl();
// If the target happens to be one of the previous declarations, we
// don't have a conflict.
//
// FIXME: but we might be increasing its access, in which case we
// should redeclare it.
NamedDecl *NonTag = nullptr, *Tag = nullptr;
bool FoundEquivalentDecl = false;
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
// We can have UsingDecls in our Previous results because we use the same
// LookupResult for checking whether the UsingDecl itself is a valid
// redeclaration.
if (isa<UsingDecl>(D) || isa<UsingPackDecl>(D))
continue;
if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
// C++ [class.mem]p19:
// If T is the name of a class, then [every named member other than
// a non-static data member] shall have a name different from T
if (RD->isInjectedClassName() && !isa<FieldDecl>(Target) &&
!isa<IndirectFieldDecl>(Target) &&
!isa<UnresolvedUsingValueDecl>(Target) &&
DiagnoseClassNameShadow(
CurContext,
DeclarationNameInfo(Using->getDeclName(), Using->getLocation())))
return true;
}
if (IsEquivalentForUsingDecl(Context, D, Target)) {
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I))
PrevShadow = Shadow;
FoundEquivalentDecl = true;
} else if (isEquivalentInternalLinkageDeclaration(D, Target)) {
// We don't conflict with an existing using shadow decl of an equivalent
// declaration, but we're not a redeclaration of it.
FoundEquivalentDecl = true;
}
if (isVisible(D))
(isa<TagDecl>(D) ? Tag : NonTag) = D;
}
if (FoundEquivalentDecl)
return false;
if (FunctionDecl *FD = Target->getAsFunction()) {
NamedDecl *OldDecl = nullptr;
switch (CheckOverload(nullptr, FD, Previous, OldDecl,
/*IsForUsingDecl*/ true)) {
case Ovl_Overload:
return false;
case Ovl_NonFunction:
Diag(Using->getLocation(), diag::err_using_decl_conflict);
break;
// We found a decl with the exact signature.
case Ovl_Match:
// If we're in a record, we want to hide the target, so we
// return true (without a diagnostic) to tell the caller not to
// build a shadow decl.
if (CurContext->isRecord())
return true;
// If we're not in a record, this is an error.
Diag(Using->getLocation(), diag::err_using_decl_conflict);
break;
}
Diag(Target->getLocation(), diag::note_using_decl_target);
Diag(OldDecl->getLocation(), diag::note_using_decl_conflict);
Using->setInvalidDecl();
return true;
}
// Target is not a function.
if (isa<TagDecl>(Target)) {
// No conflict between a tag and a non-tag.
if (!Tag) return false;
Diag(Using->getLocation(), diag::err_using_decl_conflict);
Diag(Target->getLocation(), diag::note_using_decl_target);
Diag(Tag->getLocation(), diag::note_using_decl_conflict);
Using->setInvalidDecl();
return true;
}
// No conflict between a tag and a non-tag.
if (!NonTag) return false;
Diag(Using->getLocation(), diag::err_using_decl_conflict);
Diag(Target->getLocation(), diag::note_using_decl_target);
Diag(NonTag->getLocation(), diag::note_using_decl_conflict);
Using->setInvalidDecl();
return true;
}
/// Determine whether a direct base class is a virtual base class.
static bool isVirtualDirectBase(CXXRecordDecl *Derived, CXXRecordDecl *Base) {
if (!Derived->getNumVBases())
return false;
for (auto &B : Derived->bases())
if (B.getType()->getAsCXXRecordDecl() == Base)
return B.isVirtual();
llvm_unreachable("not a direct base class");
}
/// Builds a shadow declaration corresponding to a 'using' declaration.
UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
UsingDecl *UD,
NamedDecl *Orig,
UsingShadowDecl *PrevDecl) {
// If we resolved to another shadow declaration, just coalesce them.
NamedDecl *Target = Orig;
if (isa<UsingShadowDecl>(Target)) {
Target = cast<UsingShadowDecl>(Target)->getTargetDecl();
assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration");
}
NamedDecl *NonTemplateTarget = Target;
if (auto *TargetTD = dyn_cast<TemplateDecl>(Target))
NonTemplateTarget = TargetTD->getTemplatedDecl();
UsingShadowDecl *Shadow;
if (isa<CXXConstructorDecl>(NonTemplateTarget)) {
bool IsVirtualBase =
isVirtualDirectBase(cast<CXXRecordDecl>(CurContext),
UD->getQualifier()->getAsRecordDecl());
Shadow = ConstructorUsingShadowDecl::Create(
Context, CurContext, UD->getLocation(), UD, Orig, IsVirtualBase);
} else {
Shadow = UsingShadowDecl::Create(Context, CurContext, UD->getLocation(), UD,
Target);
}
UD->addShadowDecl(Shadow);
Shadow->setAccess(UD->getAccess());
if (Orig->isInvalidDecl() || UD->isInvalidDecl())
Shadow->setInvalidDecl();
Shadow->setPreviousDecl(PrevDecl);
if (S)
PushOnScopeChains(Shadow, S);
else
CurContext->addDecl(Shadow);
return Shadow;
}
/// Hides a using shadow declaration. This is required by the current
/// using-decl implementation when a resolvable using declaration in a
/// class is followed by a declaration which would hide or override
/// one or more of the using decl's targets; for example:
///
/// struct Base { void foo(int); };
/// struct Derived : Base {
/// using Base::foo;
/// void foo(int);
/// };
///
/// The governing language is C++03 [namespace.udecl]p12:
///
/// When a using-declaration brings names from a base class into a
/// derived class scope, member functions in the derived class
/// override and/or hide member functions with the same name and
/// parameter types in a base class (rather than conflicting).
///
/// There are two ways to implement this:
/// (1) optimistically create shadow decls when they're not hidden
/// by existing declarations, or
/// (2) don't create any shadow decls (or at least don't make them
/// visible) until we've fully parsed/instantiated the class.
/// The problem with (1) is that we might have to retroactively remove
/// a shadow decl, which requires several O(n) operations because the
/// decl structures are (very reasonably) not designed for removal.
/// (2) avoids this but is very fiddly and phase-dependent.
void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) {
if (Shadow->getDeclName().getNameKind() ==
DeclarationName::CXXConversionFunctionName)
cast<CXXRecordDecl>(Shadow->getDeclContext())->removeConversion(Shadow);
// Remove it from the DeclContext...
Shadow->getDeclContext()->removeDecl(Shadow);
// ...and the scope, if applicable...
if (S) {
S->RemoveDecl(Shadow);
IdResolver.RemoveDecl(Shadow);
}
// ...and the using decl.
Shadow->getUsingDecl()->removeShadowDecl(Shadow);
// TODO: complain somehow if Shadow was used. It shouldn't
// be possible for this to happen, because...?
}
/// Find the base specifier for a base class with the given type.
static CXXBaseSpecifier *findDirectBaseWithType(CXXRecordDecl *Derived,
QualType DesiredBase,
bool &AnyDependentBases) {
// Check whether the named type is a direct base class.
CanQualType CanonicalDesiredBase = DesiredBase->getCanonicalTypeUnqualified();
for (auto &Base : Derived->bases()) {
CanQualType BaseType = Base.getType()->getCanonicalTypeUnqualified();
if (CanonicalDesiredBase == BaseType)
return &Base;
if (BaseType->isDependentType())
AnyDependentBases = true;
}
return nullptr;
}
namespace {
class UsingValidatorCCC : public CorrectionCandidateCallback {
public:
UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation,
NestedNameSpecifier *NNS, CXXRecordDecl *RequireMemberOf)
: HasTypenameKeyword(HasTypenameKeyword),
IsInstantiation(IsInstantiation), OldNNS(NNS),
RequireMemberOf(RequireMemberOf) {}
bool ValidateCandidate(const TypoCorrection &Candidate) override {
NamedDecl *ND = Candidate.getCorrectionDecl();
// Keywords are not valid here.
if (!ND || isa<NamespaceDecl>(ND))
return false;
// Completely unqualified names are invalid for a 'using' declaration.
if (Candidate.WillReplaceSpecifier() && !Candidate.getCorrectionSpecifier())
return false;
// FIXME: Don't correct to a name that CheckUsingDeclRedeclaration would
// reject.
if (RequireMemberOf) {
auto *FoundRecord = dyn_cast<CXXRecordDecl>(ND);
if (FoundRecord && FoundRecord->isInjectedClassName()) {
// No-one ever wants a using-declaration to name an injected-class-name
// of a base class, unless they're declaring an inheriting constructor.
ASTContext &Ctx = ND->getASTContext();
if (!Ctx.getLangOpts().CPlusPlus11)
return false;
QualType FoundType = Ctx.getRecordType(FoundRecord);
// Check that the injected-class-name is named as a member of its own
// type; we don't want to suggest 'using Derived::Base;', since that
// means something else.
NestedNameSpecifier *Specifier =
Candidate.WillReplaceSpecifier()
? Candidate.getCorrectionSpecifier()
: OldNNS;
if (!Specifier->getAsType() ||
!Ctx.hasSameType(QualType(Specifier->getAsType(), 0), FoundType))
return false;
// Check that this inheriting constructor declaration actually names a
// direct base class of the current class.
bool AnyDependentBases = false;
if (!findDirectBaseWithType(RequireMemberOf,
Ctx.getRecordType(FoundRecord),
AnyDependentBases) &&
!AnyDependentBases)
return false;
} else {
auto *RD = dyn_cast<CXXRecordDecl>(ND->getDeclContext());
if (!RD || RequireMemberOf->isProvablyNotDerivedFrom(RD))
return false;
// FIXME: Check that the base class member is accessible?
}
} else {
auto *FoundRecord = dyn_cast<CXXRecordDecl>(ND);
if (FoundRecord && FoundRecord->isInjectedClassName())
return false;
}
if (isa<TypeDecl>(ND))
return HasTypenameKeyword || !IsInstantiation;
return !HasTypenameKeyword;
}
private:
bool HasTypenameKeyword;
bool IsInstantiation;
NestedNameSpecifier *OldNNS;
CXXRecordDecl *RequireMemberOf;
};
} // end anonymous namespace
/// Builds a using declaration.
///
/// \param IsInstantiation - Whether this call arises from an
/// instantiation of an unresolved using declaration. We treat
/// the lookup differently for these declarations.
NamedDecl *Sema::BuildUsingDeclaration(
Scope *S, AccessSpecifier AS, SourceLocation UsingLoc,
bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS,
DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc,
const ParsedAttributesView &AttrList, bool IsInstantiation) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
SourceLocation IdentLoc = NameInfo.getLoc();
assert(IdentLoc.isValid() && "Invalid TargetName location.");
// FIXME: We ignore attributes for now.
// For an inheriting constructor declaration, the name of the using
// declaration is the name of a constructor in this class, not in the
// base class.
DeclarationNameInfo UsingName = NameInfo;
if (UsingName.getName().getNameKind() == DeclarationName::CXXConstructorName)
if (auto *RD = dyn_cast<CXXRecordDecl>(CurContext))
UsingName.setName(Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(Context.getRecordType(RD))));
// Do the redeclaration lookup in the current scope.
LookupResult Previous(*this, UsingName, LookupUsingDeclName,
ForVisibleRedeclaration);
Previous.setHideTags(false);
if (S) {
LookupName(Previous, S);
// It is really dumb that we have to do this.
LookupResult::Filter F = Previous.makeFilter();
while (F.hasNext()) {
NamedDecl *D = F.next();
if (!isDeclInScope(D, CurContext, S))
F.erase();
// If we found a local extern declaration that's not ordinarily visible,
// and this declaration is being added to a non-block scope, ignore it.
// We're only checking for scope conflicts here, not also for violations
// of the linkage rules.
else if (!CurContext->isFunctionOrMethod() && D->isLocalExternDecl() &&
!(D->getIdentifierNamespace() & Decl::IDNS_Ordinary))
F.erase();
}
F.done();
} else {
assert(IsInstantiation && "no scope in non-instantiation");
if (CurContext->isRecord())
LookupQualifiedName(Previous, CurContext);
else {
// No redeclaration check is needed here; in non-member contexts we
// diagnosed all possible conflicts with other using-declarations when
// building the template:
//
// For a dependent non-type using declaration, the only valid case is
// if we instantiate to a single enumerator. We check for conflicts
// between shadow declarations we introduce, and we check in the template
// definition for conflicts between a non-type using declaration and any
// other declaration, which together covers all cases.
//
// A dependent typename using declaration will never successfully
// instantiate, since it will always name a class member, so we reject
// that in the template definition.
}
}
// Check for invalid redeclarations.
if (CheckUsingDeclRedeclaration(UsingLoc, HasTypenameKeyword,
SS, IdentLoc, Previous))
return nullptr;
// Check for bad qualifiers.
if (CheckUsingDeclQualifier(UsingLoc, HasTypenameKeyword, SS, NameInfo,
IdentLoc))
return nullptr;
DeclContext *LookupContext = computeDeclContext(SS);
NamedDecl *D;
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
if (!LookupContext || EllipsisLoc.isValid()) {
if (HasTypenameKeyword) {
// FIXME: not all declaration name kinds are legal here
D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
UsingLoc, TypenameLoc,
QualifierLoc,
IdentLoc, NameInfo.getName(),
EllipsisLoc);
} else {
D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc,
QualifierLoc, NameInfo, EllipsisLoc);
}
D->setAccess(AS);
CurContext->addDecl(D);
return D;
}
auto Build = [&](bool Invalid) {
UsingDecl *UD =
UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc,
UsingName, HasTypenameKeyword);
UD->setAccess(AS);
CurContext->addDecl(UD);
UD->setInvalidDecl(Invalid);
return UD;
};
auto BuildInvalid = [&]{ return Build(true); };
auto BuildValid = [&]{ return Build(false); };
if (RequireCompleteDeclContext(SS, LookupContext))
return BuildInvalid();
// Look up the target name.
LookupResult R(*this, NameInfo, LookupOrdinaryName);
// Unlike most lookups, we don't always want to hide tag
// declarations: tag names are visible through the using declaration
// even if hidden by ordinary names, *except* in a dependent context
// where it's important for the sanity of two-phase lookup.
if (!IsInstantiation)
R.setHideTags(false);
// For the purposes of this lookup, we have a base object type
// equal to that of the current context.
if (CurContext->isRecord()) {
R.setBaseObjectType(
Context.getTypeDeclType(cast<CXXRecordDecl>(CurContext)));
}
LookupQualifiedName(R, LookupContext);
// Try to correct typos if possible. If constructor name lookup finds no
// results, that means the named class has no explicit constructors, and we
// suppressed declaring implicit ones (probably because it's dependent or
// invalid).
if (R.empty() &&
NameInfo.getName().getNameKind() != DeclarationName::CXXConstructorName) {
// HACK: Work around a bug in libstdc++'s detection of ::gets. Sometimes
// it will believe that glibc provides a ::gets in cases where it does not,
// and will try to pull it into namespace std with a using-declaration.
// Just ignore the using-declaration in that case.
auto *II = NameInfo.getName().getAsIdentifierInfo();
if (getLangOpts().CPlusPlus14 && II && II->isStr("gets") &&
CurContext->isStdNamespace() &&
isa<TranslationUnitDecl>(LookupContext) &&
getSourceManager().isInSystemHeader(UsingLoc))
return nullptr;
if (TypoCorrection Corrected = CorrectTypo(
R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
llvm::make_unique<UsingValidatorCCC>(
HasTypenameKeyword, IsInstantiation, SS.getScopeRep(),
dyn_cast<CXXRecordDecl>(CurContext)),
CTK_ErrorRecovery)) {
// We reject candidates where DroppedSpecifier == true, hence the
// literal '0' below.
diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest)
<< NameInfo.getName() << LookupContext << 0
<< SS.getRange());
// If we picked a correction with no attached Decl we can't do anything
// useful with it, bail out.
NamedDecl *ND = Corrected.getCorrectionDecl();
if (!ND)
return BuildInvalid();
// If we corrected to an inheriting constructor, handle it as one.
auto *RD = dyn_cast<CXXRecordDecl>(ND);
if (RD && RD->isInjectedClassName()) {
// The parent of the injected class name is the class itself.
RD = cast<CXXRecordDecl>(RD->getParent());
// Fix up the information we'll use to build the using declaration.
if (Corrected.WillReplaceSpecifier()) {
NestedNameSpecifierLocBuilder Builder;
Builder.MakeTrivial(Context, Corrected.getCorrectionSpecifier(),
QualifierLoc.getSourceRange());
QualifierLoc = Builder.getWithLocInContext(Context);
}
// In this case, the name we introduce is the name of a derived class
// constructor.
auto *CurClass = cast<CXXRecordDecl>(CurContext);
UsingName.setName(Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(Context.getRecordType(CurClass))));
UsingName.setNamedTypeInfo(nullptr);
for (auto *Ctor : LookupConstructors(RD))
R.addDecl(Ctor);
R.resolveKind();
} else {
// FIXME: Pick up all the declarations if we found an overloaded
// function.
UsingName.setName(ND->getDeclName());
R.addDecl(ND);
}
} else {
Diag(IdentLoc, diag::err_no_member)
<< NameInfo.getName() << LookupContext << SS.getRange();
return BuildInvalid();
}
}
if (R.isAmbiguous())
return BuildInvalid();
if (HasTypenameKeyword) {
// If we asked for a typename and got a non-type decl, error out.
if (!R.getAsSingle<TypeDecl>()) {
Diag(IdentLoc, diag::err_using_typename_non_type);
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
Diag((*I)->getUnderlyingDecl()->getLocation(),
diag::note_using_decl_target);
return BuildInvalid();
}
} else {
// If we asked for a non-typename and we got a type, error out,
// but only if this is an instantiation of an unresolved using
// decl. Otherwise just silently find the type name.
if (IsInstantiation && R.getAsSingle<TypeDecl>()) {
Diag(IdentLoc, diag::err_using_dependent_value_is_type);
Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target);
return BuildInvalid();
}
}
// C++14 [namespace.udecl]p6:
// A using-declaration shall not name a namespace.
if (R.getAsSingle<NamespaceDecl>()) {
Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
<< SS.getRange();
return BuildInvalid();
}
// C++14 [namespace.udecl]p7:
// A using-declaration shall not name a scoped enumerator.
if (auto *ED = R.getAsSingle<EnumConstantDecl>()) {
if (cast<EnumDecl>(ED->getDeclContext())->isScoped()) {
Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_scoped_enum)
<< SS.getRange();
return BuildInvalid();
}
}
UsingDecl *UD = BuildValid();
// Some additional rules apply to inheriting constructors.
if (UsingName.getName().getNameKind() ==
DeclarationName::CXXConstructorName) {
// Suppress access diagnostics; the access check is instead performed at the
// point of use for an inheriting constructor.
R.suppressDiagnostics();
if (CheckInheritingConstructorUsingDecl(UD))
return UD;
}
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
UsingShadowDecl *PrevDecl = nullptr;
if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl))
BuildUsingShadowDecl(S, UD, *I, PrevDecl);
}
return UD;
}
NamedDecl *Sema::BuildUsingPackDecl(NamedDecl *InstantiatedFrom,
ArrayRef<NamedDecl *> Expansions) {
assert(isa<UnresolvedUsingValueDecl>(InstantiatedFrom) ||
isa<UnresolvedUsingTypenameDecl>(InstantiatedFrom) ||
isa<UsingPackDecl>(InstantiatedFrom));
auto *UPD =
UsingPackDecl::Create(Context, CurContext, InstantiatedFrom, Expansions);
UPD->setAccess(InstantiatedFrom->getAccess());
CurContext->addDecl(UPD);
return UPD;
}
/// Additional checks for a using declaration referring to a constructor name.
bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
assert(!UD->hasTypename() && "expecting a constructor name");
const Type *SourceType = UD->getQualifier()->getAsType();
assert(SourceType &&
"Using decl naming constructor doesn't have type in scope spec.");
CXXRecordDecl *TargetClass = cast<CXXRecordDecl>(CurContext);
// Check whether the named type is a direct base class.
bool AnyDependentBases = false;
auto *Base = findDirectBaseWithType(TargetClass, QualType(SourceType, 0),
AnyDependentBases);
if (!Base && !AnyDependentBases) {
Diag(UD->getUsingLoc(),
diag::err_using_decl_constructor_not_in_direct_base)
<< UD->getNameInfo().getSourceRange()
<< QualType(SourceType, 0) << TargetClass;
UD->setInvalidDecl();
return true;
}
if (Base)
Base->setInheritConstructors();
return false;
}
/// Checks that the given using declaration is not an invalid
/// redeclaration. Note that this is checking only for the using decl
/// itself, not for any ill-formedness among the UsingShadowDecls.
bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
bool HasTypenameKeyword,
const CXXScopeSpec &SS,
SourceLocation NameLoc,
const LookupResult &Prev) {
NestedNameSpecifier *Qual = SS.getScopeRep();
// C++03 [namespace.udecl]p8:
// C++0x [namespace.udecl]p10:
// A using-declaration is a declaration and can therefore be used
// repeatedly where (and only where) multiple declarations are
// allowed.
//
// That's in non-member contexts.
if (!CurContext->getRedeclContext()->isRecord()) {
// A dependent qualifier outside a class can only ever resolve to an
// enumeration type. Therefore it conflicts with any other non-type
// declaration in the same scope.
// FIXME: How should we check for dependent type-type conflicts at block
// scope?
if (Qual->isDependent() && !HasTypenameKeyword) {
for (auto *D : Prev) {
if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D) && !isa<UsingPackDecl>(D)) {
bool OldCouldBeEnumerator =
isa<UnresolvedUsingValueDecl>(D) || isa<EnumConstantDecl>(D);
Diag(NameLoc,
OldCouldBeEnumerator ? diag::err_redefinition
: diag::err_redefinition_different_kind)
<< Prev.getLookupName();
Diag(D->getLocation(), diag::note_previous_definition);
return true;
}
}
}
return false;
}
for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) {
NamedDecl *D = *I;
bool DTypename;
NestedNameSpecifier *DQual;
if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
DTypename = UD->hasTypename();
DQual = UD->getQualifier();
} else if (UnresolvedUsingValueDecl *UD
= dyn_cast<UnresolvedUsingValueDecl>(D)) {
DTypename = false;
DQual = UD->getQualifier();
} else if (UnresolvedUsingTypenameDecl *UD
= dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
DTypename = true;
DQual = UD->getQualifier();
} else continue;
// using decls differ if one says 'typename' and the other doesn't.
// FIXME: non-dependent using decls?
if (HasTypenameKeyword != DTypename) continue;
// using decls differ if they name different scopes (but note that
// template instantiation can cause this check to trigger when it
// didn't before instantiation).
if (Context.getCanonicalNestedNameSpecifier(Qual) !=
Context.getCanonicalNestedNameSpecifier(DQual))
continue;
Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange();
Diag(D->getLocation(), diag::note_using_decl) << 1;
return true;
}
return false;
}
/// Checks that the given nested-name qualifier used in a using decl
/// in the current context is appropriately related to the current
/// scope. If an error is found, diagnoses it and returns true.
bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
bool HasTypename,
const CXXScopeSpec &SS,
const DeclarationNameInfo &NameInfo,
SourceLocation NameLoc) {
DeclContext *NamedContext = computeDeclContext(SS);
if (!CurContext->isRecord()) {
// C++03 [namespace.udecl]p3:
// C++0x [namespace.udecl]p8:
// A using-declaration for a class member shall be a member-declaration.
// If we weren't able to compute a valid scope, it might validly be a
// dependent class scope or a dependent enumeration unscoped scope. If
// we have a 'typename' keyword, the scope must resolve to a class type.
if ((HasTypename && !NamedContext) ||
(NamedContext && NamedContext->getRedeclContext()->isRecord())) {
auto *RD = NamedContext
? cast<CXXRecordDecl>(NamedContext->getRedeclContext())
: nullptr;
if (RD && RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), RD))
RD = nullptr;
Diag(NameLoc, diag::err_using_decl_can_not_refer_to_class_member)
<< SS.getRange();
// If we have a complete, non-dependent source type, try to suggest a
// way to get the same effect.
if (!RD)
return true;
// Find what this using-declaration was referring to.
LookupResult R(*this, NameInfo, LookupOrdinaryName);
R.setHideTags(false);
R.suppressDiagnostics();
LookupQualifiedName(R, RD);
if (R.getAsSingle<TypeDecl>()) {
if (getLangOpts().CPlusPlus11) {
// Convert 'using X::Y;' to 'using Y = X::Y;'.
Diag(SS.getBeginLoc(), diag::note_using_decl_class_member_workaround)
<< 0 // alias declaration
<< FixItHint::CreateInsertion(SS.getBeginLoc(),
NameInfo.getName().getAsString() +
" = ");
} else {
// Convert 'using X::Y;' to 'typedef X::Y Y;'.
SourceLocation InsertLoc = getLocForEndOfToken(NameInfo.getEndLoc());
Diag(InsertLoc, diag::note_using_decl_class_member_workaround)
<< 1 // typedef declaration
<< FixItHint::CreateReplacement(UsingLoc, "typedef")
<< FixItHint::CreateInsertion(
InsertLoc, " " + NameInfo.getName().getAsString());
}
} else if (R.getAsSingle<VarDecl>()) {
// Don't provide a fixit outside C++11 mode; we don't want to suggest
// repeating the type of the static data member here.
FixItHint FixIt;
if (getLangOpts().CPlusPlus11) {
// Convert 'using X::Y;' to 'auto &Y = X::Y;'.
FixIt = FixItHint::CreateReplacement(
UsingLoc, "auto &" + NameInfo.getName().getAsString() + " = ");
}
Diag(UsingLoc, diag::note_using_decl_class_member_workaround)
<< 2 // reference declaration
<< FixIt;
} else if (R.getAsSingle<EnumConstantDecl>()) {
// Don't provide a fixit outside C++11 mode; we don't want to suggest
// repeating the type of the enumeration here, and we can't do so if
// the type is anonymous.
FixItHint FixIt;
if (getLangOpts().CPlusPlus11) {
// Convert 'using X::Y;' to 'auto &Y = X::Y;'.
FixIt = FixItHint::CreateReplacement(
UsingLoc,
"constexpr auto " + NameInfo.getName().getAsString() + " = ");
}
Diag(UsingLoc, diag::note_using_decl_class_member_workaround)
<< (getLangOpts().CPlusPlus11 ? 4 : 3) // const[expr] variable
<< FixIt;
}
return true;
}
// Otherwise, this might be valid.
return false;
}
// The current scope is a record.
// If the named context is dependent, we can't decide much.
if (!NamedContext) {
// FIXME: in C++0x, we can diagnose if we can prove that the
// nested-name-specifier does not refer to a base class, which is
// still possible in some cases.
// Otherwise we have to conservatively report that things might be
// okay.
return false;
}
if (!NamedContext->isRecord()) {
// Ideally this would point at the last name in the specifier,
// but we don't have that level of source info.
Diag(SS.getRange().getBegin(),
diag::err_using_decl_nested_name_specifier_is_not_class)
<< SS.getScopeRep() << SS.getRange();
return true;
}
if (!NamedContext->isDependentContext() &&
RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), NamedContext))
return true;
if (getLangOpts().CPlusPlus11) {
// C++11 [namespace.udecl]p3:
// In a using-declaration used as a member-declaration, the
// nested-name-specifier shall name a base class of the class
// being defined.
if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(
cast<CXXRecordDecl>(NamedContext))) {
if (CurContext == NamedContext) {
Diag(NameLoc,
diag::err_using_decl_nested_name_specifier_is_current_class)
<< SS.getRange();
return true;
}
if (!cast<CXXRecordDecl>(NamedContext)->isInvalidDecl()) {
Diag(SS.getRange().getBegin(),
diag::err_using_decl_nested_name_specifier_is_not_base_class)
<< SS.getScopeRep()
<< cast<CXXRecordDecl>(CurContext)
<< SS.getRange();
}
return true;
}
return false;
}
// C++03 [namespace.udecl]p4:
// A using-declaration used as a member-declaration shall refer
// to a member of a base class of the class being defined [etc.].
// Salient point: SS doesn't have to name a base class as long as
// lookup only finds members from base classes. Therefore we can
// diagnose here only if we can prove that that can't happen,
// i.e. if the class hierarchies provably don't intersect.
// TODO: it would be nice if "definitely valid" results were cached
// in the UsingDecl and UsingShadowDecl so that these checks didn't
// need to be repeated.
llvm::SmallPtrSet<const CXXRecordDecl *, 4> Bases;
auto Collect = [&Bases](const CXXRecordDecl *Base) {
Bases.insert(Base);
return true;
};
// Collect all bases. Return false if we find a dependent base.
if (!cast<CXXRecordDecl>(CurContext)->forallBases(Collect))
return false;
// Returns true if the base is dependent or is one of the accumulated base
// classes.
auto IsNotBase = [&Bases](const CXXRecordDecl *Base) {
return !Bases.count(Base);
};
// Return false if the class has a dependent base or if it or one
// of its bases is present in the base set of the current context.
if (Bases.count(cast<CXXRecordDecl>(NamedContext)) ||
!cast<CXXRecordDecl>(NamedContext)->forallBases(IsNotBase))
return false;
Diag(SS.getRange().getBegin(),
diag::err_using_decl_nested_name_specifier_is_not_base_class)
<< SS.getScopeRep()
<< cast<CXXRecordDecl>(CurContext)
<< SS.getRange();
return true;
}
Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS,
MultiTemplateParamsArg TemplateParamLists,
SourceLocation UsingLoc, UnqualifiedId &Name,
const ParsedAttributesView &AttrList,
TypeResult Type, Decl *DeclFromDeclSpec) {
// Skip up to the relevant declaration scope.
while (S->isTemplateParamScope())
S = S->getParent();
assert((S->getFlags() & Scope::DeclScope) &&
"got alias-declaration outside of declaration scope");
if (Type.isInvalid())
return nullptr;
bool Invalid = false;
DeclarationNameInfo NameInfo = GetNameFromUnqualifiedId(Name);
TypeSourceInfo *TInfo = nullptr;
GetTypeFromParser(Type.get(), &TInfo);
if (DiagnoseClassNameShadow(CurContext, NameInfo))
return nullptr;
if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo,
UPPC_DeclarationType)) {
Invalid = true;
TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy,
TInfo->getTypeLoc().getBeginLoc());
}
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
TemplateParamLists.size()
? forRedeclarationInCurContext()
: ForVisibleRedeclaration);
LookupName(Previous, S);
// Warn about shadowing the name of a template parameter.
if (Previous.isSingleResult() &&
Previous.getFoundDecl()->isTemplateParameter()) {
DiagnoseTemplateParameterShadow(Name.StartLocation,Previous.getFoundDecl());
Previous.clear();
}
assert(Name.Kind == UnqualifiedIdKind::IK_Identifier &&
"name in alias declaration must be an identifier");
TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc,
Name.StartLocation,
Name.Identifier, TInfo);
NewTD->setAccess(AS);
if (Invalid)
NewTD->setInvalidDecl();
ProcessDeclAttributeList(S, NewTD, AttrList);
AddPragmaAttributes(S, NewTD);
CheckTypedefForVariablyModifiedType(S, NewTD);
Invalid |= NewTD->isInvalidDecl();
bool Redeclaration = false;
NamedDecl *NewND;
if (TemplateParamLists.size()) {
TypeAliasTemplateDecl *OldDecl = nullptr;
TemplateParameterList *OldTemplateParams = nullptr;
if (TemplateParamLists.size() != 1) {
Diag(UsingLoc, diag::err_alias_template_extra_headers)
<< SourceRange(TemplateParamLists[1]->getTemplateLoc(),
TemplateParamLists[TemplateParamLists.size()-1]->getRAngleLoc());
}
TemplateParameterList *TemplateParams = TemplateParamLists[0];
// Check that we can declare a template here.
if (CheckTemplateDeclScope(S, TemplateParams))
return nullptr;
// Only consider previous declarations in the same scope.
FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage*/false,
/*ExplicitInstantiationOrSpecialization*/false);
if (!Previous.empty()) {
Redeclaration = true;
OldDecl = Previous.getAsSingle<TypeAliasTemplateDecl>();
if (!OldDecl && !Invalid) {
Diag(UsingLoc, diag::err_redefinition_different_kind)
<< Name.Identifier;
NamedDecl *OldD = Previous.getRepresentativeDecl();
if (OldD->getLocation().isValid())
Diag(OldD->getLocation(), diag::note_previous_definition);
Invalid = true;
}
if (!Invalid && OldDecl && !OldDecl->isInvalidDecl()) {
if (TemplateParameterListsAreEqual(TemplateParams,
OldDecl->getTemplateParameters(),
/*Complain=*/true,
TPL_TemplateMatch))
OldTemplateParams =
OldDecl->getMostRecentDecl()->getTemplateParameters();
else
Invalid = true;
TypeAliasDecl *OldTD = OldDecl->getTemplatedDecl();
if (!Invalid &&
!Context.hasSameType(OldTD->getUnderlyingType(),
NewTD->getUnderlyingType())) {
// FIXME: The C++0x standard does not clearly say this is ill-formed,
// but we can't reasonably accept it.
Diag(NewTD->getLocation(), diag::err_redefinition_different_typedef)
<< 2 << NewTD->getUnderlyingType() << OldTD->getUnderlyingType();
if (OldTD->getLocation().isValid())
Diag(OldTD->getLocation(), diag::note_previous_definition);
Invalid = true;
}
}
}
// Merge any previous default template arguments into our parameters,
// and check the parameter list.
if (CheckTemplateParameterList(TemplateParams, OldTemplateParams,
TPC_TypeAliasTemplate))
return nullptr;
TypeAliasTemplateDecl *NewDecl =
TypeAliasTemplateDecl::Create(Context, CurContext, UsingLoc,
Name.Identifier, TemplateParams,
NewTD);
NewTD->setDescribedAliasTemplate(NewDecl);
NewDecl->setAccess(AS);
if (Invalid)
NewDecl->setInvalidDecl();
else if (OldDecl) {
NewDecl->setPreviousDecl(OldDecl);
CheckRedeclarationModuleOwnership(NewDecl, OldDecl);
}
NewND = NewDecl;
} else {
if (auto *TD = dyn_cast_or_null<TagDecl>(DeclFromDeclSpec)) {
setTagNameForLinkagePurposes(TD, NewTD);
handleTagNumbering(TD, S);
}
ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration);
NewND = NewTD;
}
PushOnScopeChains(NewND, S);
ActOnDocumentableDecl(NewND);
return NewND;
}
Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
SourceLocation AliasLoc,
IdentifierInfo *Alias, CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *Ident) {
// Lookup the namespace name.
LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName);
LookupParsedName(R, S, &SS);
if (R.isAmbiguous())
return nullptr;
if (R.empty()) {
if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) {
Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
return nullptr;
}
}
assert(!R.isAmbiguous() && !R.empty());
NamedDecl *ND = R.getRepresentativeDecl();
// Check if we have a previous declaration with the same name.
LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName,
ForVisibleRedeclaration);
LookupName(PrevR, S);
// Check we're not shadowing a template parameter.
if (PrevR.isSingleResult() && PrevR.getFoundDecl()->isTemplateParameter()) {
DiagnoseTemplateParameterShadow(AliasLoc, PrevR.getFoundDecl());
PrevR.clear();
}
// Filter out any other lookup result from an enclosing scope.
FilterLookupForScope(PrevR, CurContext, S, /*ConsiderLinkage*/false,
/*AllowInlineNamespace*/false);
// Find the previous declaration and check that we can redeclare it.
NamespaceAliasDecl *Prev = nullptr;
if (PrevR.isSingleResult()) {
NamedDecl *PrevDecl = PrevR.getRepresentativeDecl();
if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
// We already have an alias with the same name that points to the same
// namespace; check that it matches.
if (AD->getNamespace()->Equals(getNamespaceDecl(ND))) {
Prev = AD;
} else if (isVisible(PrevDecl)) {
Diag(AliasLoc, diag::err_redefinition_different_namespace_alias)
<< Alias;
Diag(AD->getLocation(), diag::note_previous_namespace_alias)
<< AD->getNamespace();
return nullptr;
}
} else if (isVisible(PrevDecl)) {
unsigned DiagID = isa<NamespaceDecl>(PrevDecl->getUnderlyingDecl())
? diag::err_redefinition
: diag::err_redefinition_different_kind;
Diag(AliasLoc, DiagID) << Alias;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
return nullptr;
}
}
// The use of a nested name specifier may trigger deprecation warnings.
DiagnoseUseOfDecl(ND, IdentLoc);
NamespaceAliasDecl *AliasDecl =
NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
Alias, SS.getWithLocInContext(Context),
IdentLoc, ND);
if (Prev)
AliasDecl->setPreviousDecl(Prev);
PushOnScopeChains(AliasDecl, S);
return AliasDecl;
}
namespace {
struct SpecialMemberExceptionSpecInfo
: SpecialMemberVisitor<SpecialMemberExceptionSpecInfo> {
SourceLocation Loc;
Sema::ImplicitExceptionSpecification ExceptSpec;
SpecialMemberExceptionSpecInfo(Sema &S, CXXMethodDecl *MD,
Sema::CXXSpecialMember CSM,
Sema::InheritedConstructorInfo *ICI,
SourceLocation Loc)
: SpecialMemberVisitor(S, MD, CSM, ICI), Loc(Loc), ExceptSpec(S) {}
bool visitBase(CXXBaseSpecifier *Base);
bool visitField(FieldDecl *FD);
void visitClassSubobject(CXXRecordDecl *Class, Subobject Subobj,
unsigned Quals);
void visitSubobjectCall(Subobject Subobj,
Sema::SpecialMemberOverloadResult SMOR);
};
}
bool SpecialMemberExceptionSpecInfo::visitBase(CXXBaseSpecifier *Base) {
auto *RT = Base->getType()->getAs<RecordType>();
if (!RT)
return false;
auto *BaseClass = cast<CXXRecordDecl>(RT->getDecl());
Sema::SpecialMemberOverloadResult SMOR = lookupInheritedCtor(BaseClass);
if (auto *BaseCtor = SMOR.getMethod()) {
visitSubobjectCall(Base, BaseCtor);
return false;
}
visitClassSubobject(BaseClass, Base, 0);
return false;
}
bool SpecialMemberExceptionSpecInfo::visitField(FieldDecl *FD) {
if (CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer()) {
Expr *E = FD->getInClassInitializer();
if (!E)
// FIXME: It's a little wasteful to build and throw away a
// CXXDefaultInitExpr here.
// FIXME: We should have a single context note pointing at Loc, and
// this location should be MD->getLocation() instead, since that's
// the location where we actually use the default init expression.
E = S.BuildCXXDefaultInitExpr(Loc, FD).get();
if (E)
ExceptSpec.CalledExpr(E);
} else if (auto *RT = S.Context.getBaseElementType(FD->getType())
->getAs<RecordType>()) {
visitClassSubobject(cast<CXXRecordDecl>(RT->getDecl()), FD,
FD->getType().getCVRQualifiers());
}
return false;
}
void SpecialMemberExceptionSpecInfo::visitClassSubobject(CXXRecordDecl *Class,
Subobject Subobj,
unsigned Quals) {
FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
bool IsMutable = Field && Field->isMutable();
visitSubobjectCall(Subobj, lookupIn(Class, Quals, IsMutable));
}
void SpecialMemberExceptionSpecInfo::visitSubobjectCall(
Subobject Subobj, Sema::SpecialMemberOverloadResult SMOR) {
// Note, if lookup fails, it doesn't matter what exception specification we
// choose because the special member will be deleted.
if (CXXMethodDecl *MD = SMOR.getMethod())
ExceptSpec.CalledDecl(getSubobjectLoc(Subobj), MD);
}
namespace {
/// RAII object to register a special member as being currently declared.
struct ComputingExceptionSpec {
Sema &S;
ComputingExceptionSpec(Sema &S, CXXMethodDecl *MD, SourceLocation Loc)
: S(S) {
Sema::CodeSynthesisContext Ctx;
Ctx.Kind = Sema::CodeSynthesisContext::ExceptionSpecEvaluation;
Ctx.PointOfInstantiation = Loc;
Ctx.Entity = MD;
S.pushCodeSynthesisContext(Ctx);
}
~ComputingExceptionSpec() {
S.popCodeSynthesisContext();
}
};
}
static Sema::ImplicitExceptionSpecification
ComputeDefaultedSpecialMemberExceptionSpec(
Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM,
Sema::InheritedConstructorInfo *ICI) {
ComputingExceptionSpec CES(S, MD, Loc);
CXXRecordDecl *ClassDecl = MD->getParent();
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have an
// exception-specification. [...]
SpecialMemberExceptionSpecInfo Info(S, MD, CSM, ICI, MD->getLocation());
if (ClassDecl->isInvalidDecl())
return Info.ExceptSpec;
// FIXME: If this diagnostic fires, we're probably missing a check for
// attempting to resolve an exception specification before it's known
// at a higher level.
if (S.RequireCompleteType(MD->getLocation(),
S.Context.getRecordType(ClassDecl),
diag::err_exception_spec_incomplete_type))
return Info.ExceptSpec;
// C++1z [except.spec]p7:
// [Look for exceptions thrown by] a constructor selected [...] to
// initialize a potentially constructed subobject,
// C++1z [except.spec]p8:
// The exception specification for an implicitly-declared destructor, or a
// destructor without a noexcept-specifier, is potentially-throwing if and
// only if any of the destructors for any of its potentially constructed
// subojects is potentially throwing.
// FIXME: We respect the first rule but ignore the "potentially constructed"
// in the second rule to resolve a core issue (no number yet) that would have
// us reject:
// struct A { virtual void f() = 0; virtual ~A() noexcept(false) = 0; };
// struct B : A {};
// struct C : B { void f(); };
// ... due to giving B::~B() a non-throwing exception specification.
Info.visit(Info.IsConstructor ? Info.VisitPotentiallyConstructedBases
: Info.VisitAllBases);
return Info.ExceptSpec;
}
namespace {
/// RAII object to register a special member as being currently declared.
struct DeclaringSpecialMember {
Sema &S;
Sema::SpecialMemberDecl D;
Sema::ContextRAII SavedContext;
bool WasAlreadyBeingDeclared;
DeclaringSpecialMember(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM)
: S(S), D(RD, CSM), SavedContext(S, RD) {
WasAlreadyBeingDeclared = !S.SpecialMembersBeingDeclared.insert(D).second;
if (WasAlreadyBeingDeclared)
// This almost never happens, but if it does, ensure that our cache
// doesn't contain a stale result.
S.SpecialMemberCache.clear();
else {
// Register a note to be produced if we encounter an error while
// declaring the special member.
Sema::CodeSynthesisContext Ctx;
Ctx.Kind = Sema::CodeSynthesisContext::DeclaringSpecialMember;
// FIXME: We don't have a location to use here. Using the class's
// location maintains the fiction that we declare all special members
// with the class, but (1) it's not clear that lying about that helps our
// users understand what's going on, and (2) there may be outer contexts
// on the stack (some of which are relevant) and printing them exposes
// our lies.
Ctx.PointOfInstantiation = RD->getLocation();
Ctx.Entity = RD;
Ctx.SpecialMember = CSM;
S.pushCodeSynthesisContext(Ctx);
}
}
~DeclaringSpecialMember() {
if (!WasAlreadyBeingDeclared) {
S.SpecialMembersBeingDeclared.erase(D);
S.popCodeSynthesisContext();
}
}
/// Are we already trying to declare this special member?
bool isAlreadyBeingDeclared() const {
return WasAlreadyBeingDeclared;
}
};
}
void Sema::CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD) {
// Look up any existing declarations, but don't trigger declaration of all
// implicit special members with this name.
DeclarationName Name = FD->getDeclName();
LookupResult R(*this, Name, SourceLocation(), LookupOrdinaryName,
ForExternalRedeclaration);
for (auto *D : FD->getParent()->lookup(Name))
if (auto *Acceptable = R.getAcceptableDecl(D))
R.addDecl(Acceptable);
R.resolveKind();
R.suppressDiagnostics();
CheckFunctionDeclaration(S, FD, R, /*IsMemberSpecialization*/false);
}
void Sema::setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem,
QualType ResultTy,
ArrayRef<QualType> Args) {
// Build an exception specification pointing back at this constructor.
FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, SpecialMem);
if (getLangOpts().OpenCLCPlusPlus) {
// OpenCL: Implicitly defaulted special member are of the generic address
// space.
EPI.TypeQuals.addAddressSpace(LangAS::opencl_generic);
}
auto QT = Context.getFunctionType(ResultTy, Args, EPI);
SpecialMem->setType(QT);
}
CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
CXXRecordDecl *ClassDecl) {
// C++ [class.ctor]p5:
// A default constructor for a class X is a constructor of class X
// that can be called without an argument. If there is no
// user-declared constructor for class X, a default constructor is
// implicitly declared. An implicitly-declared default constructor
// is an inline public member of its class.
assert(ClassDecl->needsImplicitDefaultConstructor() &&
"Should not build implicit default constructor!");
DeclaringSpecialMember DSM(*this, ClassDecl, CXXDefaultConstructor);
if (DSM.isAlreadyBeingDeclared())
return nullptr;
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
CXXDefaultConstructor,
false);
// Create the actual constructor declaration.
CanQualType ClassType
= Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationName Name
= Context.DeclarationNames.getCXXConstructorName(ClassType);
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create(
Context, ClassDecl, ClassLoc, NameInfo, /*Type*/QualType(),
/*TInfo=*/nullptr, /*isExplicit=*/false, /*isInline=*/true,
/*isImplicitlyDeclared=*/true, Constexpr);
DefaultCon->setAccess(AS_public);
DefaultCon->setDefaulted();
if (getLangOpts().CUDA) {
inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDefaultConstructor,
DefaultCon,
/* ConstRHS */ false,
/* Diagnose */ false);
}
setupImplicitSpecialMemberType(DefaultCon, Context.VoidTy, None);
// We don't need to use SpecialMemberIsTrivial here; triviality for default
// constructors is easy to compute.
DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor());
// Note that we have declared this constructor.
++ASTContext::NumImplicitDefaultConstructorsDeclared;
Scope *S = getScopeForContext(ClassDecl);
CheckImplicitSpecialMemberDeclaration(S, DefaultCon);
if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor))
SetDeclDeleted(DefaultCon, ClassLoc);
if (S)
PushOnScopeChains(DefaultCon, S, false);
ClassDecl->addDecl(DefaultCon);
return DefaultCon;
}
void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor) {
assert((Constructor->isDefaulted() && Constructor->isDefaultConstructor() &&
!Constructor->doesThisDeclarationHaveABody() &&
!Constructor->isDeleted()) &&
"DefineImplicitDefaultConstructor - call it for implicit default ctor");
if (Constructor->willHaveBody() || Constructor->isInvalidDecl())
return;
CXXRecordDecl *ClassDecl = Constructor->getParent();
assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
SynthesizedFunctionScope Scope(*this, Constructor);
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
Constructor->getType()->castAs<FunctionProtoType>());
MarkVTableUsed(CurrentLocation, ClassDecl);
// Add a context note for diagnostics produced after this point.
Scope.addContextNote(CurrentLocation);
if (SetCtorInitializers(Constructor, /*AnyErrors=*/false)) {
Constructor->setInvalidDecl();
return;
}
SourceLocation Loc = Constructor->getEndLoc().isValid()
? Constructor->getEndLoc()
: Constructor->getLocation();
Constructor->setBody(new (Context) CompoundStmt(Loc));
Constructor->markUsed(Context);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Constructor);
}
DiagnoseUninitializedFields(*this, Constructor);
}
void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) {
// Perform any delayed checks on exception specifications.
CheckDelayedMemberExceptionSpecs();
}
/// Find or create the fake constructor we synthesize to model constructing an
/// object of a derived class via a constructor of a base class.
CXXConstructorDecl *
Sema::findInheritingConstructor(SourceLocation Loc,
CXXConstructorDecl *BaseCtor,
ConstructorUsingShadowDecl *Shadow) {
CXXRecordDecl *Derived = Shadow->getParent();
SourceLocation UsingLoc = Shadow->getLocation();
// FIXME: Add a new kind of DeclarationName for an inherited constructor.
// For now we use the name of the base class constructor as a member of the
// derived class to indicate a (fake) inherited constructor name.
DeclarationName Name = BaseCtor->getDeclName();
// Check to see if we already have a fake constructor for this inherited
// constructor call.
for (NamedDecl *Ctor : Derived->lookup(Name))
if (declaresSameEntity(cast<CXXConstructorDecl>(Ctor)
->getInheritedConstructor()
.getConstructor(),
BaseCtor))
return cast<CXXConstructorDecl>(Ctor);
DeclarationNameInfo NameInfo(Name, UsingLoc);
TypeSourceInfo *TInfo =
Context.getTrivialTypeSourceInfo(BaseCtor->getType(), UsingLoc);
FunctionProtoTypeLoc ProtoLoc =
TInfo->getTypeLoc().IgnoreParens().castAs<FunctionProtoTypeLoc>();
// Check the inherited constructor is valid and find the list of base classes
// from which it was inherited.
InheritedConstructorInfo ICI(*this, Loc, Shadow);
bool Constexpr =
BaseCtor->isConstexpr() &&
defaultedSpecialMemberIsConstexpr(*this, Derived, CXXDefaultConstructor,
false, BaseCtor, &ICI);
CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create(
Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo,
BaseCtor->isExplicit(), /*Inline=*/true,
/*ImplicitlyDeclared=*/true, Constexpr,
InheritedConstructor(Shadow, BaseCtor));
if (Shadow->isInvalidDecl())
DerivedCtor->setInvalidDecl();
// Build an unevaluated exception specification for this fake constructor.
const FunctionProtoType *FPT = TInfo->getType()->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.ExceptionSpec.Type = EST_Unevaluated;
EPI.ExceptionSpec.SourceDecl = DerivedCtor;
DerivedCtor->setType(Context.getFunctionType(FPT->getReturnType(),
FPT->getParamTypes(), EPI));
// Build the parameter declarations.
SmallVector<ParmVarDecl *, 16> ParamDecls;
for (unsigned I = 0, N = FPT->getNumParams(); I != N; ++I) {
TypeSourceInfo *TInfo =
Context.getTrivialTypeSourceInfo(FPT->getParamType(I), UsingLoc);
ParmVarDecl *PD = ParmVarDecl::Create(
Context, DerivedCtor, UsingLoc, UsingLoc, /*IdentifierInfo=*/nullptr,
FPT->getParamType(I), TInfo, SC_None, /*DefaultArg=*/nullptr);
PD->setScopeInfo(0, I);
PD->setImplicit();
// Ensure attributes are propagated onto parameters (this matters for
// format, pass_object_size, ...).
mergeDeclAttributes(PD, BaseCtor->getParamDecl(I));
ParamDecls.push_back(PD);
ProtoLoc.setParam(I, PD);
}
// Set up the new constructor.
assert(!BaseCtor->isDeleted() && "should not use deleted constructor");
DerivedCtor->setAccess(BaseCtor->getAccess());
DerivedCtor->setParams(ParamDecls);
Derived->addDecl(DerivedCtor);
if (ShouldDeleteSpecialMember(DerivedCtor, CXXDefaultConstructor, &ICI))
SetDeclDeleted(DerivedCtor, UsingLoc);
return DerivedCtor;
}
void Sema::NoteDeletedInheritingConstructor(CXXConstructorDecl *Ctor) {
InheritedConstructorInfo ICI(*this, Ctor->getLocation(),
Ctor->getInheritedConstructor().getShadowDecl());
ShouldDeleteSpecialMember(Ctor, CXXDefaultConstructor, &ICI,
/*Diagnose*/true);
}
void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor) {
CXXRecordDecl *ClassDecl = Constructor->getParent();
assert(Constructor->getInheritedConstructor() &&
!Constructor->doesThisDeclarationHaveABody() &&
!Constructor->isDeleted());
if (Constructor->willHaveBody() || Constructor->isInvalidDecl())
return;
// Initializations are performed "as if by a defaulted default constructor",
// so enter the appropriate scope.
SynthesizedFunctionScope Scope(*this, Constructor);
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
Constructor->getType()->castAs<FunctionProtoType>());
MarkVTableUsed(CurrentLocation, ClassDecl);
// Add a context note for diagnostics produced after this point.
Scope.addContextNote(CurrentLocation);
ConstructorUsingShadowDecl *Shadow =
Constructor->getInheritedConstructor().getShadowDecl();
CXXConstructorDecl *InheritedCtor =
Constructor->getInheritedConstructor().getConstructor();
// [class.inhctor.init]p1:
// initialization proceeds as if a defaulted default constructor is used to
// initialize the D object and each base class subobject from which the
// constructor was inherited
InheritedConstructorInfo ICI(*this, CurrentLocation, Shadow);
CXXRecordDecl *RD = Shadow->getParent();
SourceLocation InitLoc = Shadow->getLocation();
// Build explicit initializers for all base classes from which the
// constructor was inherited.
SmallVector<CXXCtorInitializer*, 8> Inits;
for (bool VBase : {false, true}) {
for (CXXBaseSpecifier &B : VBase ? RD->vbases() : RD->bases()) {
if (B.isVirtual() != VBase)
continue;
auto *BaseRD = B.getType()->getAsCXXRecordDecl();
if (!BaseRD)
continue;
auto BaseCtor = ICI.findConstructorForBase(BaseRD, InheritedCtor);
if (!BaseCtor.first)
continue;
MarkFunctionReferenced(CurrentLocation, BaseCtor.first);
ExprResult Init = new (Context) CXXInheritedCtorInitExpr(
InitLoc, B.getType(), BaseCtor.first, VBase, BaseCtor.second);
auto *TInfo = Context.getTrivialTypeSourceInfo(B.getType(), InitLoc);
Inits.push_back(new (Context) CXXCtorInitializer(
Context, TInfo, VBase, InitLoc, Init.get(), InitLoc,
SourceLocation()));
}
}
// We now proceed as if for a defaulted default constructor, with the relevant
// initializers replaced.
if (SetCtorInitializers(Constructor, /*AnyErrors*/false, Inits)) {
Constructor->setInvalidDecl();
return;
}
Constructor->setBody(new (Context) CompoundStmt(InitLoc));
Constructor->markUsed(Context);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Constructor);
}
DiagnoseUninitializedFields(*this, Constructor);
}
CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
// C++ [class.dtor]p2:
// If a class has no user-declared destructor, a destructor is
// declared implicitly. An implicitly-declared destructor is an
// inline public member of its class.
assert(ClassDecl->needsImplicitDestructor());
DeclaringSpecialMember DSM(*this, ClassDecl, CXXDestructor);
if (DSM.isAlreadyBeingDeclared())
return nullptr;
// Create the actual destructor declaration.
CanQualType ClassType
= Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationName Name
= Context.DeclarationNames.getCXXDestructorName(ClassType);
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXDestructorDecl *Destructor
= CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
QualType(), nullptr, /*isInline=*/true,
/*isImplicitlyDeclared=*/true);
Destructor->setAccess(AS_public);
Destructor->setDefaulted();
if (getLangOpts().CUDA) {
inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDestructor,
Destructor,
/* ConstRHS */ false,
/* Diagnose */ false);
}
setupImplicitSpecialMemberType(Destructor, Context.VoidTy, None);
// We don't need to use SpecialMemberIsTrivial here; triviality for
// destructors is easy to compute.
Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
Destructor->setTrivialForCall(ClassDecl->hasAttr<TrivialABIAttr>() ||
ClassDecl->hasTrivialDestructorForCall());
// Note that we have declared this destructor.
++ASTContext::NumImplicitDestructorsDeclared;
Scope *S = getScopeForContext(ClassDecl);
CheckImplicitSpecialMemberDeclaration(S, Destructor);
// We can't check whether an implicit destructor is deleted before we complete
// the definition of the class, because its validity depends on the alignment
// of the class. We'll check this from ActOnFields once the class is complete.
if (ClassDecl->isCompleteDefinition() &&
ShouldDeleteSpecialMember(Destructor, CXXDestructor))
SetDeclDeleted(Destructor, ClassLoc);
// Introduce this destructor into its scope.
if (S)
PushOnScopeChains(Destructor, S, false);
ClassDecl->addDecl(Destructor);
return Destructor;
}
void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
CXXDestructorDecl *Destructor) {
assert((Destructor->isDefaulted() &&
!Destructor->doesThisDeclarationHaveABody() &&
!Destructor->isDeleted()) &&
"DefineImplicitDestructor - call it for implicit default dtor");
if (Destructor->willHaveBody() || Destructor->isInvalidDecl())
return;
CXXRecordDecl *ClassDecl = Destructor->getParent();
assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
SynthesizedFunctionScope Scope(*this, Destructor);
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
Destructor->getType()->castAs<FunctionProtoType>());
MarkVTableUsed(CurrentLocation, ClassDecl);
// Add a context note for diagnostics produced after this point.
Scope.addContextNote(CurrentLocation);
MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
Destructor->getParent());
if (CheckDestructor(Destructor)) {
Destructor->setInvalidDecl();
return;
}
SourceLocation Loc = Destructor->getEndLoc().isValid()
? Destructor->getEndLoc()
: Destructor->getLocation();
Destructor->setBody(new (Context) CompoundStmt(Loc));
Destructor->markUsed(Context);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Destructor);
}
}
/// Perform any semantic analysis which needs to be delayed until all
/// pending class member declarations have been parsed.
void Sema::ActOnFinishCXXMemberDecls() {
// If the context is an invalid C++ class, just suppress these checks.
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) {
if (Record->isInvalidDecl()) {
DelayedOverridingExceptionSpecChecks.clear();
DelayedEquivalentExceptionSpecChecks.clear();
DelayedDefaultedMemberExceptionSpecs.clear();
return;
}
checkForMultipleExportedDefaultConstructors(*this, Record);
}
}
void Sema::ActOnFinishCXXNonNestedClass(Decl *D) {
referenceDLLExportedClassMethods();
}
void Sema::referenceDLLExportedClassMethods() {
if (!DelayedDllExportClasses.empty()) {
// Calling ReferenceDllExportedMembers might cause the current function to
// be called again, so use a local copy of DelayedDllExportClasses.
SmallVector<CXXRecordDecl *, 4> WorkList;
std::swap(DelayedDllExportClasses, WorkList);
for (CXXRecordDecl *Class : WorkList)
ReferenceDllExportedMembers(*this, Class);
}
}
void Sema::AdjustDestructorExceptionSpec(CXXDestructorDecl *Destructor) {
assert(getLangOpts().CPlusPlus11 &&
"adjusting dtor exception specs was introduced in c++11");
if (Destructor->isDependentContext())
return;
// C++11 [class.dtor]p3:
// A declaration of a destructor that does not have an exception-
// specification is implicitly considered to have the same exception-
// specification as an implicit declaration.
const FunctionProtoType *DtorType = Destructor->getType()->
getAs<FunctionProtoType>();
if (DtorType->hasExceptionSpec())
return;
// Replace the destructor's type, building off the existing one. Fortunately,
// the only thing of interest in the destructor type is its extended info.
// The return and arguments are fixed.
FunctionProtoType::ExtProtoInfo EPI = DtorType->getExtProtoInfo();
EPI.ExceptionSpec.Type = EST_Unevaluated;
EPI.ExceptionSpec.SourceDecl = Destructor;
Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI));
// FIXME: If the destructor has a body that could throw, and the newly created
// spec doesn't allow exceptions, we should emit a warning, because this
// change in behavior can break conforming C++03 programs at runtime.
// However, we don't have a body or an exception specification yet, so it
// needs to be done somewhere else.
}
namespace {
/// An abstract base class for all helper classes used in building the
// copy/move operators. These classes serve as factory functions and help us
// avoid using the same Expr* in the AST twice.
class ExprBuilder {
ExprBuilder(const ExprBuilder&) = delete;
ExprBuilder &operator=(const ExprBuilder&) = delete;
protected:
static Expr *assertNotNull(Expr *E) {
assert(E && "Expression construction must not fail.");
return E;
}
public:
ExprBuilder() {}
virtual ~ExprBuilder() {}
virtual Expr *build(Sema &S, SourceLocation Loc) const = 0;
};
class RefBuilder: public ExprBuilder {
VarDecl *Var;
QualType VarType;
public:
Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.BuildDeclRefExpr(Var, VarType, VK_LValue, Loc).get());
}
RefBuilder(VarDecl *Var, QualType VarType)
: Var(Var), VarType(VarType) {}
};
class ThisBuilder: public ExprBuilder {
public:
Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.ActOnCXXThis(Loc).getAs<Expr>());
}
};
class CastBuilder: public ExprBuilder {
const ExprBuilder &Builder;
QualType Type;
ExprValueKind Kind;
const CXXCastPath &Path;
public:
Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.ImpCastExprToType(Builder.build(S, Loc), Type,
CK_UncheckedDerivedToBase, Kind,
&Path).get());
}
CastBuilder(const ExprBuilder &Builder, QualType Type, ExprValueKind Kind,
const CXXCastPath &Path)
: Builder(Builder), Type(Type), Kind(Kind), Path(Path) {}
};
class DerefBuilder: public ExprBuilder {
const ExprBuilder &Builder;
public:
Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(
S.CreateBuiltinUnaryOp(Loc, UO_Deref, Builder.build(S, Loc)).get());
}
DerefBuilder(const ExprBuilder &Builder) : Builder(Builder) {}
};
class MemberBuilder: public ExprBuilder {
const ExprBuilder &Builder;
QualType Type;
CXXScopeSpec SS;
bool IsArrow;
LookupResult &MemberLookup;
public:
Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.BuildMemberReferenceExpr(
Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(),
nullptr, MemberLookup, nullptr, nullptr).get());
}
MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow,
LookupResult &MemberLookup)
: Builder(Builder), Type(Type), IsArrow(IsArrow),
MemberLookup(MemberLookup) {}
};
class MoveCastBuilder: public ExprBuilder {
const ExprBuilder &Builder;
public:
Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(CastForMoving(S, Builder.build(S, Loc)));
}
MoveCastBuilder(const ExprBuilder &Builder) : Builder(Builder) {}
};
class LvalueConvBuilder: public ExprBuilder {
const ExprBuilder &Builder;
public:
Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(
S.DefaultLvalueConversion(Builder.build(S, Loc)).get());
}
LvalueConvBuilder(const ExprBuilder &Builder) : Builder(Builder) {}
};
class SubscriptBuilder: public ExprBuilder {
const ExprBuilder &Base;
const ExprBuilder &Index;
public:
Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.CreateBuiltinArraySubscriptExpr(
Base.build(S, Loc), Loc, Index.build(S, Loc), Loc).get());
}
SubscriptBuilder(const ExprBuilder &Base, const ExprBuilder &Index)
: Base(Base), Index(Index) {}
};
} // end anonymous namespace
/// When generating a defaulted copy or move assignment operator, if a field
/// should be copied with __builtin_memcpy rather than via explicit assignments,
/// do so. This optimization only applies for arrays of scalars, and for arrays
/// of class type where the selected copy/move-assignment operator is trivial.
static StmtResult
buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
const ExprBuilder &ToB, const ExprBuilder &FromB) {
// Compute the size of the memory buffer to be copied.
QualType SizeType = S.Context.getSizeType();
llvm::APInt Size(S.Context.getTypeSize(SizeType),
S.Context.getTypeSizeInChars(T).getQuantity());
// Take the address of the field references for "from" and "to". We
// directly construct UnaryOperators here because semantic analysis
// does not permit us to take the address of an xvalue.
Expr *From = FromB.build(S, Loc);
From = new (S.Context) UnaryOperator(From, UO_AddrOf,
S.Context.getPointerType(From->getType()),
VK_RValue, OK_Ordinary, Loc, false);
Expr *To = ToB.build(S, Loc);
To = new (S.Context) UnaryOperator(To, UO_AddrOf,
S.Context.getPointerType(To->getType()),
VK_RValue, OK_Ordinary, Loc, false);
const Type *E = T->getBaseElementTypeUnsafe();
bool NeedsCollectableMemCpy =
E->isRecordType() && E->getAs<RecordType>()->getDecl()->hasObjectMember();
// Create a reference to the __builtin_objc_memmove_collectable function
StringRef MemCpyName = NeedsCollectableMemCpy ?
"__builtin_objc_memmove_collectable" :
"__builtin_memcpy";
LookupResult R(S, &S.Context.Idents.get(MemCpyName), Loc,
Sema::LookupOrdinaryName);
S.LookupName(R, S.TUScope, true);
FunctionDecl *MemCpy = R.getAsSingle<FunctionDecl>();
if (!MemCpy)
// Something went horribly wrong earlier, and we will have complained
// about it.
return StmtError();
ExprResult MemCpyRef = S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy,
VK_RValue, Loc, nullptr);
assert(MemCpyRef.isUsable() && "Builtin reference cannot fail");
Expr *CallArgs[] = {
To, From, IntegerLiteral::Create(S.Context, Size, SizeType, Loc)
};
ExprResult Call = S.ActOnCallExpr(/*Scope=*/nullptr, MemCpyRef.get(),
Loc, CallArgs, Loc);
assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
return Call.getAs<Stmt>();
}
/// Builds a statement that copies/moves the given entity from \p From to
/// \c To.
///
/// This routine is used to copy/move the members of a class with an
/// implicitly-declared copy/move assignment operator. When the entities being
/// copied are arrays, this routine builds for loops to copy them.
///
/// \param S The Sema object used for type-checking.
///
/// \param Loc The location where the implicit copy/move is being generated.
///
/// \param T The type of the expressions being copied/moved. Both expressions
/// must have this type.
///
/// \param To The expression we are copying/moving to.
///
/// \param From The expression we are copying/moving from.
///
/// \param CopyingBaseSubobject Whether we're copying/moving a base subobject.
/// Otherwise, it's a non-static member subobject.
///
/// \param Copying Whether we're copying or moving.
///
/// \param Depth Internal parameter recording the depth of the recursion.
///
/// \returns A statement or a loop that copies the expressions, or StmtResult(0)
/// if a memcpy should be used instead.
static StmtResult
buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
const ExprBuilder &To, const ExprBuilder &From,
bool CopyingBaseSubobject, bool Copying,
unsigned Depth = 0) {
// C++11 [class.copy]p28:
// Each subobject is assigned in the manner appropriate to its type:
//
// - if the subobject is of class type, as if by a call to operator= with
// the subobject as the object expression and the corresponding
// subobject of x as a single function argument (as if by explicit
// qualification; that is, ignoring any possible virtual overriding
// functions in more derived classes);
//
// C++03 [class.copy]p13:
// - if the subobject is of class type, the copy assignment operator for
// the class is used (as if by explicit qualification; that is,
// ignoring any possible virtual overriding functions in more derived
// classes);
if (const RecordType *RecordTy = T->getAs<RecordType>()) {
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
// Look for operator=.
DeclarationName Name
= S.Context.DeclarationNames.getCXXOperatorName(OO_Equal);
LookupResult OpLookup(S, Name, Loc, Sema::LookupOrdinaryName);
S.LookupQualifiedName(OpLookup, ClassDecl, false);
// Prior to C++11, filter out any result that isn't a copy/move-assignment
// operator.
if (!S.getLangOpts().CPlusPlus11) {
LookupResult::Filter F = OpLookup.makeFilter();
while (F.hasNext()) {
NamedDecl *D = F.next();
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
if (Method->isCopyAssignmentOperator() ||
(!Copying && Method->isMoveAssignmentOperator()))
continue;
F.erase();
}
F.done();
}
// Suppress the protected check (C++ [class.protected]) for each of the
// assignment operators we found. This strange dance is required when
// we're assigning via a base classes's copy-assignment operator. To
// ensure that we're getting the right base class subobject (without
// ambiguities), we need to cast "this" to that subobject type; to
// ensure that we don't go through the virtual call mechanism, we need
// to qualify the operator= name with the base class (see below). However,
// this means that if the base class has a protected copy assignment
// operator, the protected member access check will fail. So, we
// rewrite "protected" access to "public" access in this case, since we
// know by construction that we're calling from a derived class.
if (CopyingBaseSubobject) {
for (LookupResult::iterator L = OpLookup.begin(), LEnd = OpLookup.end();
L != LEnd; ++L) {
if (L.getAccess() == AS_protected)
L.setAccess(AS_public);
}
}
// Create the nested-name-specifier that will be used to qualify the
// reference to operator=; this is required to suppress the virtual
// call mechanism.
CXXScopeSpec SS;
const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr());
SS.MakeTrivial(S.Context,
NestedNameSpecifier::Create(S.Context, nullptr, false,
CanonicalT),
Loc);
// Create the reference to operator=.
ExprResult OpEqualRef
= S.BuildMemberReferenceExpr(To.build(S, Loc), T, Loc, /*isArrow=*/false,
SS, /*TemplateKWLoc=*/SourceLocation(),
/*FirstQualifierInScope=*/nullptr,
OpLookup,
/*TemplateArgs=*/nullptr, /*S*/nullptr,
/*SuppressQualifierCheck=*/true);
if (OpEqualRef.isInvalid())
return StmtError();
// Build the call to the assignment operator.
Expr *FromInst = From.build(S, Loc);
ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/nullptr,
OpEqualRef.getAs<Expr>(),
Loc, FromInst, Loc);
if (Call.isInvalid())
return StmtError();
// If we built a call to a trivial 'operator=' while copying an array,
// bail out. We'll replace the whole shebang with a memcpy.
CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(Call.get());
if (CE && CE->getMethodDecl()->isTrivial() && Depth)
return StmtResult((Stmt*)nullptr);
// Convert to an expression-statement, and clean up any produced
// temporaries.
return S.ActOnExprStmt(Call);
}
// - if the subobject is of scalar type, the built-in assignment
// operator is used.
const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T);
if (!ArrayTy) {
ExprResult Assignment = S.CreateBuiltinBinOp(
Loc, BO_Assign, To.build(S, Loc), From.build(S, Loc));
if (Assignment.isInvalid())
return StmtError();
return S.ActOnExprStmt(Assignment);
}
// - if the subobject is an array, each element is assigned, in the
// manner appropriate to the element type;
// Construct a loop over the array bounds, e.g.,
//
// for (__SIZE_TYPE__ i0 = 0; i0 != array-size; ++i0)
//
// that will copy each of the array elements.
QualType SizeType = S.Context.getSizeType();
// Create the iteration variable.
IdentifierInfo *IterationVarName = nullptr;
{
SmallString<8> Str;
llvm::raw_svector_ostream OS(Str);
OS << "__i" << Depth;
IterationVarName = &S.Context.Idents.get(OS.str());
}
VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, Loc,
IterationVarName, SizeType,
S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
SC_None);
// Initialize the iteration variable to zero.
llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0);
IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc));
// Creates a reference to the iteration variable.
RefBuilder IterationVarRef(IterationVar, SizeType);
LvalueConvBuilder IterationVarRefRVal(IterationVarRef);
// Create the DeclStmt that holds the iteration variable.
Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc);
// Subscript the "from" and "to" expressions with the iteration variable.
SubscriptBuilder FromIndexCopy(From, IterationVarRefRVal);
MoveCastBuilder FromIndexMove(FromIndexCopy);
const ExprBuilder *FromIndex;
if (Copying)
FromIndex = &FromIndexCopy;
else
FromIndex = &FromIndexMove;
SubscriptBuilder ToIndex(To, IterationVarRefRVal);
// Build the copy/move for an individual element of the array.
StmtResult Copy =
buildSingleCopyAssignRecursively(S, Loc, ArrayTy->getElementType(),
ToIndex, *FromIndex, CopyingBaseSubobject,
Copying, Depth + 1);
// Bail out if copying fails or if we determined that we should use memcpy.
if (Copy.isInvalid() || !Copy.get())
return Copy;
// Create the comparison against the array bound.
llvm::APInt Upper
= ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType));
Expr *Comparison
= new (S.Context) BinaryOperator(IterationVarRefRVal.build(S, Loc),
IntegerLiteral::Create(S.Context, Upper, SizeType, Loc),
BO_NE, S.Context.BoolTy,
VK_RValue, OK_Ordinary, Loc, FPOptions());
// Create the pre-increment of the iteration variable. We can determine
// whether the increment will overflow based on the value of the array
// bound.
Expr *Increment = new (S.Context)
UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc, SizeType,
VK_LValue, OK_Ordinary, Loc, Upper.isMaxValue());
// Construct the loop that copies all elements of this array.
return S.ActOnForStmt(
Loc, Loc, InitStmt,
S.ActOnCondition(nullptr, Loc, Comparison, Sema::ConditionKind::Boolean),
S.MakeFullDiscardedValueExpr(Increment), Loc, Copy.get());
}
static StmtResult
buildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
const ExprBuilder &To, const ExprBuilder &From,
bool CopyingBaseSubobject, bool Copying) {
// Maybe we should use a memcpy?
if (T->isArrayType() && !T.isConstQualified() && !T.isVolatileQualified() &&
T.isTriviallyCopyableType(S.Context))
return buildMemcpyForAssignmentOp(S, Loc, T, To, From);
StmtResult Result(buildSingleCopyAssignRecursively(S, Loc, T, To, From,
CopyingBaseSubobject,
Copying, 0));
// If we ended up picking a trivial assignment operator for an array of a
// non-trivially-copyable class type, just emit a memcpy.
if (!Result.isInvalid() && !Result.get())
return buildMemcpyForAssignmentOp(S, Loc, T, To, From);
return Result;
}
CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
// Note: The following rules are largely analoguous to the copy
// constructor rules. Note that virtual bases are not taken into account
// for determining the argument type of the operator. Note also that
// operators taking an object instead of a reference are allowed.
assert(ClassDecl->needsImplicitCopyAssignment());
DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyAssignment);
if (DSM.isAlreadyBeingDeclared())
return nullptr;
QualType ArgType = Context.getTypeDeclType(ClassDecl);
QualType RetType = Context.getLValueReferenceType(ArgType);
bool Const = ClassDecl->implicitCopyAssignmentHasConstParam();
if (Const)
ArgType = ArgType.withConst();
if (Context.getLangOpts().OpenCLCPlusPlus)
ArgType = Context.getAddrSpaceQualType(ArgType, LangAS::opencl_generic);
ArgType = Context.getLValueReferenceType(ArgType);
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
CXXCopyAssignment,
Const);
// An implicitly-declared copy assignment operator is an inline public
// member of its class.
DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXMethodDecl *CopyAssignment =
CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
/*TInfo=*/nullptr, /*StorageClass=*/SC_None,
/*isInline=*/true, Constexpr, SourceLocation());
CopyAssignment->setAccess(AS_public);
CopyAssignment->setDefaulted();
CopyAssignment->setImplicit();
if (getLangOpts().CUDA) {
inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyAssignment,
CopyAssignment,
/* ConstRHS */ Const,
/* Diagnose */ false);
}
setupImplicitSpecialMemberType(CopyAssignment, RetType, ArgType);
// Add the parameter to the operator.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
ClassLoc, ClassLoc,
/*Id=*/nullptr, ArgType,
/*TInfo=*/nullptr, SC_None,
nullptr);
CopyAssignment->setParams(FromParam);
CopyAssignment->setTrivial(
ClassDecl->needsOverloadResolutionForCopyAssignment()
? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment)
: ClassDecl->hasTrivialCopyAssignment());
// Note that we have added this copy-assignment operator.
++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
Scope *S = getScopeForContext(ClassDecl);
CheckImplicitSpecialMemberDeclaration(S, CopyAssignment);
if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment))
SetDeclDeleted(CopyAssignment, ClassLoc);
if (S)
PushOnScopeChains(CopyAssignment, S, false);
ClassDecl->addDecl(CopyAssignment);
return CopyAssignment;
}
/// Diagnose an implicit copy operation for a class which is odr-used, but
/// which is deprecated because the class has a user-declared copy constructor,
/// copy assignment operator, or destructor.
static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp) {
assert(CopyOp->isImplicit());
CXXRecordDecl *RD = CopyOp->getParent();
CXXMethodDecl *UserDeclaredOperation = nullptr;
// In Microsoft mode, assignment operations don't affect constructors and
// vice versa.
if (RD->hasUserDeclaredDestructor()) {
UserDeclaredOperation = RD->getDestructor();
} else if (!isa<CXXConstructorDecl>(CopyOp) &&
RD->hasUserDeclaredCopyConstructor() &&
!S.getLangOpts().MSVCCompat) {
// Find any user-declared copy constructor.
for (auto *I : RD->ctors()) {
if (I->isCopyConstructor()) {
UserDeclaredOperation = I;
break;
}
}
assert(UserDeclaredOperation);
} else if (isa<CXXConstructorDecl>(CopyOp) &&
RD->hasUserDeclaredCopyAssignment() &&
!S.getLangOpts().MSVCCompat) {
// Find any user-declared move assignment operator.
for (auto *I : RD->methods()) {
if (I->isCopyAssignmentOperator()) {
UserDeclaredOperation = I;
break;
}
}
assert(UserDeclaredOperation);
}
if (UserDeclaredOperation) {
S.Diag(UserDeclaredOperation->getLocation(),
diag::warn_deprecated_copy_operation)
<< RD << /*copy assignment*/!isa<CXXConstructorDecl>(CopyOp)
<< /*destructor*/isa<CXXDestructorDecl>(UserDeclaredOperation);
}
}
void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CXXMethodDecl *CopyAssignOperator) {
assert((CopyAssignOperator->isDefaulted() &&
CopyAssignOperator->isOverloadedOperator() &&
CopyAssignOperator->getOverloadedOperator() == OO_Equal &&
!CopyAssignOperator->doesThisDeclarationHaveABody() &&
!CopyAssignOperator->isDeleted()) &&
"DefineImplicitCopyAssignment called for wrong function");
if (CopyAssignOperator->willHaveBody() || CopyAssignOperator->isInvalidDecl())
return;
CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent();
if (ClassDecl->isInvalidDecl()) {
CopyAssignOperator->setInvalidDecl();
return;
}
SynthesizedFunctionScope Scope(*this, CopyAssignOperator);
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
CopyAssignOperator->getType()->castAs<FunctionProtoType>());
// Add a context note for diagnostics produced after this point.
Scope.addContextNote(CurrentLocation);
// C++11 [class.copy]p18:
// The [definition of an implicitly declared copy assignment operator] is
// deprecated if the class has a user-declared copy constructor or a
// user-declared destructor.
if (getLangOpts().CPlusPlus11 && CopyAssignOperator->isImplicit())
diagnoseDeprecatedCopyOperation(*this, CopyAssignOperator);
// C++0x [class.copy]p30:
// The implicitly-defined or explicitly-defaulted copy assignment operator
// for a non-union class X performs memberwise copy assignment of its
// subobjects. The direct base classes of X are assigned first, in the
// order of their declaration in the base-specifier-list, and then the
// immediate non-static data members of X are assigned, in the order in
// which they were declared in the class definition.
// The statements that form the synthesized function body.
SmallVector<Stmt*, 8> Statements;
// The parameter for the "other" object, which we are copying from.
ParmVarDecl *Other = CopyAssignOperator->getParamDecl(0);
Qualifiers OtherQuals = Other->getType().getQualifiers();
QualType OtherRefType = Other->getType();
if (const LValueReferenceType *OtherRef
= OtherRefType->getAs<LValueReferenceType>()) {
OtherRefType = OtherRef->getPointeeType();
OtherQuals = OtherRefType.getQualifiers();
}
// Our location for everything implicitly-generated.
SourceLocation Loc = CopyAssignOperator->getEndLoc().isValid()
? CopyAssignOperator->getEndLoc()
: CopyAssignOperator->getLocation();
// Builds a DeclRefExpr for the "other" object.
RefBuilder OtherRef(Other, OtherRefType);
// Builds the "this" pointer.
ThisBuilder This;
// Assign base classes.
bool Invalid = false;
for (auto &Base : ClassDecl->bases()) {
// Form the assignment:
// static_cast<Base*>(this)->Base::operator=(static_cast<Base&>(other));
QualType BaseType = Base.getType().getUnqualifiedType();
if (!BaseType->isRecordType()) {
Invalid = true;
continue;
}
CXXCastPath BasePath;
BasePath.push_back(&Base);
// Construct the "from" expression, which is an implicit cast to the
// appropriately-qualified base type.
CastBuilder From(OtherRef, Context.getQualifiedType(BaseType, OtherQuals),
VK_LValue, BasePath);
// Dereference "this".
DerefBuilder DerefThis(This);
CastBuilder To(DerefThis,
Context.getQualifiedType(
BaseType, CopyAssignOperator->getTypeQualifiers()),
VK_LValue, BasePath);
// Build the copy.
StmtResult Copy = buildSingleCopyAssign(*this, Loc, BaseType,
To, From,
/*CopyingBaseSubobject=*/true,
/*Copying=*/true);
if (Copy.isInvalid()) {
CopyAssignOperator->setInvalidDecl();
return;
}
// Success! Record the copy.
Statements.push_back(Copy.getAs<Expr>());
}
// Assign non-static members.
for (auto *Field : ClassDecl->fields()) {
// FIXME: We should form some kind of AST representation for the implied
// memcpy in a union copy operation.
if (Field->isUnnamedBitfield() || Field->getParent()->isUnion())
continue;
if (Field->isInvalidDecl()) {
Invalid = true;
continue;
}
// Check for members of reference type; we can't copy those.
if (Field->getType()->isReferenceType()) {
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
<< Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
Diag(Field->getLocation(), diag::note_declared_at);
Invalid = true;
continue;
}
// Check for members of const-qualified, non-class type.
QualType BaseType = Context.getBaseElementType(Field->getType());
if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) {
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
<< Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
Diag(Field->getLocation(), diag::note_declared_at);
Invalid = true;
continue;
}
// Suppress assigning zero-width bitfields.
if (Field->isZeroLengthBitField(Context))
continue;
QualType FieldType = Field->getType().getNonReferenceType();
if (FieldType->isIncompleteArrayType()) {
assert(ClassDecl->hasFlexibleArrayMember() &&
"Incomplete array type is not valid");
continue;
}
// Build references to the field in the object we're copying from and to.
CXXScopeSpec SS; // Intentionally empty
LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
LookupMemberName);
MemberLookup.addDecl(Field);
MemberLookup.resolveKind();
MemberBuilder From(OtherRef, OtherRefType, /*IsArrow=*/false, MemberLookup);
MemberBuilder To(This, getCurrentThisType(), /*IsArrow=*/true, MemberLookup);
// Build the copy of this field.
StmtResult Copy = buildSingleCopyAssign(*this, Loc, FieldType,
To, From,
/*CopyingBaseSubobject=*/false,
/*Copying=*/true);
if (Copy.isInvalid()) {
CopyAssignOperator->setInvalidDecl();
return;
}
// Success! Record the copy.
Statements.push_back(Copy.getAs<Stmt>());
}
if (!Invalid) {
// Add a "return *this;"
ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));
StmtResult Return = BuildReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
Invalid = true;
else
Statements.push_back(Return.getAs<Stmt>());
}
if (Invalid) {
CopyAssignOperator->setInvalidDecl();
return;
}
StmtResult Body;
{
CompoundScopeRAII CompoundScope(*this);
Body = ActOnCompoundStmt(Loc, Loc, Statements,
/*isStmtExpr=*/false);
assert(!Body.isInvalid() && "Compound statement creation cannot fail");
}
CopyAssignOperator->setBody(Body.getAs<Stmt>());
CopyAssignOperator->markUsed(Context);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(CopyAssignOperator);
}
}
CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
assert(ClassDecl->needsImplicitMoveAssignment());
DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment);
if (DSM.isAlreadyBeingDeclared())
return nullptr;
// Note: The following rules are largely analoguous to the move
// constructor rules.
QualType ArgType = Context.getTypeDeclType(ClassDecl);
QualType RetType = Context.getLValueReferenceType(ArgType);
ArgType = Context.getRValueReferenceType(ArgType);
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
CXXMoveAssignment,
false);
// An implicitly-declared move assignment operator is an inline public
// member of its class.
DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationNameInfo NameInfo(Name, ClassLoc);
CXXMethodDecl *MoveAssignment =
CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
/*TInfo=*/nullptr, /*StorageClass=*/SC_None,
/*isInline=*/true, Constexpr, SourceLocation());
MoveAssignment->setAccess(AS_public);
MoveAssignment->setDefaulted();
MoveAssignment->setImplicit();
if (getLangOpts().CUDA) {
inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveAssignment,
MoveAssignment,
/* ConstRHS */ false,
/* Diagnose */ false);
}
// Build an exception specification pointing back at this member.
FunctionProtoType::ExtProtoInfo EPI =
getImplicitMethodEPI(*this, MoveAssignment);
MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
// Add the parameter to the operator.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,
ClassLoc, ClassLoc,
/*Id=*/nullptr, ArgType,
/*TInfo=*/nullptr, SC_None,
nullptr);
MoveAssignment->setParams(FromParam);
MoveAssignment->setTrivial(
ClassDecl->needsOverloadResolutionForMoveAssignment()
? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment)
: ClassDecl->hasTrivialMoveAssignment());
// Note that we have added this copy-assignment operator.
++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared;
Scope *S = getScopeForContext(ClassDecl);
CheckImplicitSpecialMemberDeclaration(S, MoveAssignment);
if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) {
ClassDecl->setImplicitMoveAssignmentIsDeleted();
SetDeclDeleted(MoveAssignment, ClassLoc);
}
if (S)
PushOnScopeChains(MoveAssignment, S, false);
ClassDecl->addDecl(MoveAssignment);
return MoveAssignment;
}
/// Check if we're implicitly defining a move assignment operator for a class
/// with virtual bases. Such a move assignment might move-assign the virtual
/// base multiple times.
static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class,
SourceLocation CurrentLocation) {
assert(!Class->isDependentContext() && "should not define dependent move");
// Only a virtual base could get implicitly move-assigned multiple times.
// Only a non-trivial move assignment can observe this. We only want to
// diagnose if we implicitly define an assignment operator that assigns
// two base classes, both of which move-assign the same virtual base.
if (Class->getNumVBases() == 0 || Class->hasTrivialMoveAssignment() ||
Class->getNumBases() < 2)
return;
llvm::SmallVector<CXXBaseSpecifier *, 16> Worklist;
typedef llvm::DenseMap<CXXRecordDecl*, CXXBaseSpecifier*> VBaseMap;
VBaseMap VBases;
for (auto &BI : Class->bases()) {
Worklist.push_back(&BI);
while (!Worklist.empty()) {
CXXBaseSpecifier *BaseSpec = Worklist.pop_back_val();
CXXRecordDecl *Base = BaseSpec->getType()->getAsCXXRecordDecl();
// If the base has no non-trivial move assignment operators,
// we don't care about moves from it.
if (!Base->hasNonTrivialMoveAssignment())
continue;
// If there's nothing virtual here, skip it.
if (!BaseSpec->isVirtual() && !Base->getNumVBases())
continue;
// If we're not actually going to call a move assignment for this base,
// or the selected move assignment is trivial, skip it.
Sema::SpecialMemberOverloadResult SMOR =
S.LookupSpecialMember(Base, Sema::CXXMoveAssignment,
/*ConstArg*/false, /*VolatileArg*/false,
/*RValueThis*/true, /*ConstThis*/false,
/*VolatileThis*/false);
if (!SMOR.getMethod() || SMOR.getMethod()->isTrivial() ||
!SMOR.getMethod()->isMoveAssignmentOperator())
continue;
if (BaseSpec->isVirtual()) {
// We're going to move-assign this virtual base, and its move
// assignment operator is not trivial. If this can happen for
// multiple distinct direct bases of Class, diagnose it. (If it
// only happens in one base, we'll diagnose it when synthesizing
// that base class's move assignment operator.)
CXXBaseSpecifier *&Existing =
VBases.insert(std::make_pair(Base->getCanonicalDecl(), &BI))
.first->second;
if (Existing && Existing != &BI) {
S.Diag(CurrentLocation, diag::warn_vbase_moved_multiple_times)
<< Class << Base;
S.Diag(Existing->getBeginLoc(), diag::note_vbase_moved_here)
<< (Base->getCanonicalDecl() ==
Existing->getType()->getAsCXXRecordDecl()->getCanonicalDecl())
<< Base << Existing->getType() << Existing->getSourceRange();
S.Diag(BI.getBeginLoc(), diag::note_vbase_moved_here)
<< (Base->getCanonicalDecl() ==
BI.getType()->getAsCXXRecordDecl()->getCanonicalDecl())
<< Base << BI.getType() << BaseSpec->getSourceRange();
// Only diagnose each vbase once.
Existing = nullptr;
}
} else {
// Only walk over bases that have defaulted move assignment operators.
// We assume that any user-provided move assignment operator handles
// the multiple-moves-of-vbase case itself somehow.
if (!SMOR.getMethod()->isDefaulted())
continue;
// We're going to move the base classes of Base. Add them to the list.
for (auto &BI : Base->bases())
Worklist.push_back(&BI);
}
}
}
}
void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
CXXMethodDecl *MoveAssignOperator) {
assert((MoveAssignOperator->isDefaulted() &&
MoveAssignOperator->isOverloadedOperator() &&
MoveAssignOperator->getOverloadedOperator() == OO_Equal &&
!MoveAssignOperator->doesThisDeclarationHaveABody() &&
!MoveAssignOperator->isDeleted()) &&
"DefineImplicitMoveAssignment called for wrong function");
if (MoveAssignOperator->willHaveBody() || MoveAssignOperator->isInvalidDecl())
return;
CXXRecordDecl *ClassDecl = MoveAssignOperator->getParent();
if (ClassDecl->isInvalidDecl()) {
MoveAssignOperator->setInvalidDecl();
return;
}
// C++0x [class.copy]p28:
// The implicitly-defined or move assignment operator for a non-union class
// X performs memberwise move assignment of its subobjects. The direct base
// classes of X are assigned first, in the order of their declaration in the
// base-specifier-list, and then the immediate non-static data members of X
// are assigned, in the order in which they were declared in the class
// definition.
// Issue a warning if our implicit move assignment operator will move
// from a virtual base more than once.
checkMoveAssignmentForRepeatedMove(*this, ClassDecl, CurrentLocation);
SynthesizedFunctionScope Scope(*this, MoveAssignOperator);
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
MoveAssignOperator->getType()->castAs<FunctionProtoType>());
// Add a context note for diagnostics produced after this point.
Scope.addContextNote(CurrentLocation);
// The statements that form the synthesized function body.
SmallVector<Stmt*, 8> Statements;
// The parameter for the "other" object, which we are move from.
ParmVarDecl *Other = MoveAssignOperator->getParamDecl(0);
QualType OtherRefType = Other->getType()->
getAs<RValueReferenceType>()->getPointeeType();
// Our location for everything implicitly-generated.
SourceLocation Loc = MoveAssignOperator->getEndLoc().isValid()
? MoveAssignOperator->getEndLoc()
: MoveAssignOperator->getLocation();
// Builds a reference to the "other" object.
RefBuilder OtherRef(Other, OtherRefType);
// Cast to rvalue.
MoveCastBuilder MoveOther(OtherRef);
// Builds the "this" pointer.
ThisBuilder This;
// Assign base classes.
bool Invalid = false;
for (auto &Base : ClassDecl->bases()) {
// C++11 [class.copy]p28:
// It is unspecified whether subobjects representing virtual base classes
// are assigned more than once by the implicitly-defined copy assignment
// operator.
// FIXME: Do not assign to a vbase that will be assigned by some other base
// class. For a move-assignment, this can result in the vbase being moved
// multiple times.
// Form the assignment:
// static_cast<Base*>(this)->Base::operator=(static_cast<Base&&>(other));
QualType BaseType = Base.getType().getUnqualifiedType();
if (!BaseType->isRecordType()) {
Invalid = true;
continue;
}
CXXCastPath BasePath;
BasePath.push_back(&Base);
// Construct the "from" expression, which is an implicit cast to the
// appropriately-qualified base type.
CastBuilder From(OtherRef, BaseType, VK_XValue, BasePath);
// Dereference "this".
DerefBuilder DerefThis(This);
// Implicitly cast "this" to the appropriately-qualified base type.
CastBuilder To(DerefThis,
Context.getQualifiedType(
BaseType, MoveAssignOperator->getTypeQualifiers()),
VK_LValue, BasePath);
// Build the move.
StmtResult Move = buildSingleCopyAssign(*this, Loc, BaseType,
To, From,
/*CopyingBaseSubobject=*/true,
/*Copying=*/false);
if (Move.isInvalid()) {
MoveAssignOperator->setInvalidDecl();
return;
}
// Success! Record the move.
Statements.push_back(Move.getAs<Expr>());
}
// Assign non-static members.
for (auto *Field : ClassDecl->fields()) {
// FIXME: We should form some kind of AST representation for the implied
// memcpy in a union copy operation.
if (Field->isUnnamedBitfield() || Field->getParent()->isUnion())
continue;
if (Field->isInvalidDecl()) {
Invalid = true;
continue;
}
// Check for members of reference type; we can't move those.
if (Field->getType()->isReferenceType()) {
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
<< Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
Diag(Field->getLocation(), diag::note_declared_at);
Invalid = true;
continue;
}
// Check for members of const-qualified, non-class type.
QualType BaseType = Context.getBaseElementType(Field->getType());
if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) {
Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
<< Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
Diag(Field->getLocation(), diag::note_declared_at);
Invalid = true;
continue;
}
// Suppress assigning zero-width bitfields.
if (Field->isZeroLengthBitField(Context))
continue;
QualType FieldType = Field->getType().getNonReferenceType();
if (FieldType->isIncompleteArrayType()) {
assert(ClassDecl->hasFlexibleArrayMember() &&
"Incomplete array type is not valid");
continue;
}
// Build references to the field in the object we're copying from and to.
LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
LookupMemberName);
MemberLookup.addDecl(Field);
MemberLookup.resolveKind();
MemberBuilder From(MoveOther, OtherRefType,
/*IsArrow=*/false, MemberLookup);
MemberBuilder To(This, getCurrentThisType(),
/*IsArrow=*/true, MemberLookup);
assert(!From.build(*this, Loc)->isLValue() && // could be xvalue or prvalue
"Member reference with rvalue base must be rvalue except for reference "
"members, which aren't allowed for move assignment.");
// Build the move of this field.
StmtResult Move = buildSingleCopyAssign(*this, Loc, FieldType,
To, From,
/*CopyingBaseSubobject=*/false,
/*Copying=*/false);
if (Move.isInvalid()) {
MoveAssignOperator->setInvalidDecl();
return;
}
// Success! Record the copy.
Statements.push_back(Move.getAs<Stmt>());
}
if (!Invalid) {
// Add a "return *this;"
ExprResult ThisObj =
CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));
StmtResult Return = BuildReturnStmt(Loc, ThisObj.get());
if (Return.isInvalid())
Invalid = true;
else
Statements.push_back(Return.getAs<Stmt>());
}
if (Invalid) {
MoveAssignOperator->setInvalidDecl();
return;
}
StmtResult Body;
{
CompoundScopeRAII CompoundScope(*this);
Body = ActOnCompoundStmt(Loc, Loc, Statements,
/*isStmtExpr=*/false);
assert(!Body.isInvalid() && "Compound statement creation cannot fail");
}
MoveAssignOperator->setBody(Body.getAs<Stmt>());
MoveAssignOperator->markUsed(Context);
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(MoveAssignOperator);
}
}
CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
CXXRecordDecl *ClassDecl) {
// C++ [class.copy]p4:
// If the class definition does not explicitly declare a copy
// constructor, one is declared implicitly.
assert(ClassDecl->needsImplicitCopyConstructor());
DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyConstructor);
if (DSM.isAlreadyBeingDeclared())
return nullptr;
QualType ClassType = Context.getTypeDeclType(ClassDecl);
QualType ArgType = ClassType;
bool Const = ClassDecl->implicitCopyConstructorHasConstParam();
if (Const)
ArgType = ArgType.withConst();
if (Context.getLangOpts().OpenCLCPlusPlus)
ArgType = Context.getAddrSpaceQualType(ArgType, LangAS::opencl_generic);
ArgType = Context.getLValueReferenceType(ArgType);
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
CXXCopyConstructor,
Const);
DeclarationName Name
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(ClassType));
SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationNameInfo NameInfo(Name, ClassLoc);
// An implicitly-declared copy constructor is an inline public
// member of its class.
CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create(
Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr,
/*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
Constexpr);
CopyConstructor->setAccess(AS_public);
CopyConstructor->setDefaulted();
if (getLangOpts().CUDA) {
inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyConstructor,
CopyConstructor,
/* ConstRHS */ Const,
/* Diagnose */ false);
}
setupImplicitSpecialMemberType(CopyConstructor, Context.VoidTy, ArgType);
// Add the parameter to the constructor.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
ClassLoc, ClassLoc,
/*IdentifierInfo=*/nullptr,
ArgType, /*TInfo=*/nullptr,
SC_None, nullptr);
CopyConstructor->setParams(FromParam);
CopyConstructor->setTrivial(
ClassDecl->needsOverloadResolutionForCopyConstructor()
? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
: ClassDecl->hasTrivialCopyConstructor());
CopyConstructor->setTrivialForCall(
ClassDecl->hasAttr<TrivialABIAttr>() ||
(ClassDecl->needsOverloadResolutionForCopyConstructor()
? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor,
TAH_ConsiderTrivialABI)
: ClassDecl->hasTrivialCopyConstructorForCall()));
// Note that we have declared this constructor.
++ASTContext::NumImplicitCopyConstructorsDeclared;
Scope *S = getScopeForContext(ClassDecl);
CheckImplicitSpecialMemberDeclaration(S, CopyConstructor);
if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) {
ClassDecl->setImplicitCopyConstructorIsDeleted();
SetDeclDeleted(CopyConstructor, ClassLoc);
}
if (S)
PushOnScopeChains(CopyConstructor, S, false);
ClassDecl->addDecl(CopyConstructor);
return CopyConstructor;
}
void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *CopyConstructor) {
assert((CopyConstructor->isDefaulted() &&
CopyConstructor->isCopyConstructor() &&
!CopyConstructor->doesThisDeclarationHaveABody() &&
!CopyConstructor->isDeleted()) &&
"DefineImplicitCopyConstructor - call it for implicit copy ctor");
if (CopyConstructor->willHaveBody() || CopyConstructor->isInvalidDecl())
return;
CXXRecordDecl *ClassDecl = CopyConstructor->getParent();
assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
SynthesizedFunctionScope Scope(*this, CopyConstructor);
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
CopyConstructor->getType()->castAs<FunctionProtoType>());
MarkVTableUsed(CurrentLocation, ClassDecl);
// Add a context note for diagnostics produced after this point.
Scope.addContextNote(CurrentLocation);
// C++11 [class.copy]p7:
// The [definition of an implicitly declared copy constructor] is
// deprecated if the class has a user-declared copy assignment operator
// or a user-declared destructor.
if (getLangOpts().CPlusPlus11 && CopyConstructor->isImplicit())
diagnoseDeprecatedCopyOperation(*this, CopyConstructor);
if (SetCtorInitializers(CopyConstructor, /*AnyErrors=*/false)) {
CopyConstructor->setInvalidDecl();
} else {
SourceLocation Loc = CopyConstructor->getEndLoc().isValid()
? CopyConstructor->getEndLoc()
: CopyConstructor->getLocation();
Sema::CompoundScopeRAII CompoundScope(*this);
CopyConstructor->setBody(
ActOnCompoundStmt(Loc, Loc, None, /*isStmtExpr=*/false).getAs<Stmt>());
CopyConstructor->markUsed(Context);
}
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(CopyConstructor);
}
}
CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
CXXRecordDecl *ClassDecl) {
assert(ClassDecl->needsImplicitMoveConstructor());
DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor);
if (DSM.isAlreadyBeingDeclared())
return nullptr;
QualType ClassType = Context.getTypeDeclType(ClassDecl);
QualType ArgType = ClassType;
if (Context.getLangOpts().OpenCLCPlusPlus)
ArgType = Context.getAddrSpaceQualType(ClassType, LangAS::opencl_generic);
ArgType = Context.getRValueReferenceType(ArgType);
bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
CXXMoveConstructor,
false);
DeclarationName Name
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(ClassType));
SourceLocation ClassLoc = ClassDecl->getLocation();
DeclarationNameInfo NameInfo(Name, ClassLoc);
// C++11 [class.copy]p11:
// An implicitly-declared copy/move constructor is an inline public
// member of its class.
CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create(
Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr,
/*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
Constexpr);
MoveConstructor->setAccess(AS_public);
MoveConstructor->setDefaulted();
if (getLangOpts().CUDA) {
inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveConstructor,
MoveConstructor,
/* ConstRHS */ false,
/* Diagnose */ false);
}
setupImplicitSpecialMemberType(MoveConstructor, Context.VoidTy, ArgType);
// Add the parameter to the constructor.
ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor,
ClassLoc, ClassLoc,
/*IdentifierInfo=*/nullptr,
ArgType, /*TInfo=*/nullptr,
SC_None, nullptr);
MoveConstructor->setParams(FromParam);
MoveConstructor->setTrivial(
ClassDecl->needsOverloadResolutionForMoveConstructor()
? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
: ClassDecl->hasTrivialMoveConstructor());
MoveConstructor->setTrivialForCall(
ClassDecl->hasAttr<TrivialABIAttr>() ||
(ClassDecl->needsOverloadResolutionForMoveConstructor()
? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor,
TAH_ConsiderTrivialABI)
: ClassDecl->hasTrivialMoveConstructorForCall()));
// Note that we have declared this constructor.
++ASTContext::NumImplicitMoveConstructorsDeclared;
Scope *S = getScopeForContext(ClassDecl);
CheckImplicitSpecialMemberDeclaration(S, MoveConstructor);
if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) {
ClassDecl->setImplicitMoveConstructorIsDeleted();
SetDeclDeleted(MoveConstructor, ClassLoc);
}
if (S)
PushOnScopeChains(MoveConstructor, S, false);
ClassDecl->addDecl(MoveConstructor);
return MoveConstructor;
}
void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *MoveConstructor) {
assert((MoveConstructor->isDefaulted() &&
MoveConstructor->isMoveConstructor() &&
!MoveConstructor->doesThisDeclarationHaveABody() &&
!MoveConstructor->isDeleted()) &&
"DefineImplicitMoveConstructor - call it for implicit move ctor");
if (MoveConstructor->willHaveBody() || MoveConstructor->isInvalidDecl())
return;
CXXRecordDecl *ClassDecl = MoveConstructor->getParent();
assert(ClassDecl && "DefineImplicitMoveConstructor - invalid constructor");
SynthesizedFunctionScope Scope(*this, MoveConstructor);
// The exception specification is needed because we are defining the
// function.
ResolveExceptionSpec(CurrentLocation,
MoveConstructor->getType()->castAs<FunctionProtoType>());
MarkVTableUsed(CurrentLocation, ClassDecl);
// Add a context note for diagnostics produced after this point.
Scope.addContextNote(CurrentLocation);
if (SetCtorInitializers(MoveConstructor, /*AnyErrors=*/false)) {
MoveConstructor->setInvalidDecl();
} else {
SourceLocation Loc = MoveConstructor->getEndLoc().isValid()
? MoveConstructor->getEndLoc()
: MoveConstructor->getLocation();
Sema::CompoundScopeRAII CompoundScope(*this);
MoveConstructor->setBody(ActOnCompoundStmt(
Loc, Loc, None, /*isStmtExpr=*/ false).getAs<Stmt>());
MoveConstructor->markUsed(Context);
}
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(MoveConstructor);
}
}
bool Sema::isImplicitlyDeleted(FunctionDecl *FD) {
return FD->isDeleted() && FD->isDefaulted() && isa<CXXMethodDecl>(FD);
}
void Sema::DefineImplicitLambdaToFunctionPointerConversion(
SourceLocation CurrentLocation,
CXXConversionDecl *Conv) {
SynthesizedFunctionScope Scope(*this, Conv);
assert(!Conv->getReturnType()->isUndeducedType());
CXXRecordDecl *Lambda = Conv->getParent();
FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker();
if (auto *TemplateArgs = Conv->getTemplateSpecializationArgs()) {
CallOp = InstantiateFunctionDeclaration(
CallOp->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation);
if (!CallOp)
return;
Invoker = InstantiateFunctionDeclaration(
Invoker->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation);
if (!Invoker)
return;
}
if (CallOp->isInvalidDecl())
return;
// Mark the call operator referenced (and add to pending instantiations
// if necessary).
// For both the conversion and static-invoker template specializations
// we construct their body's in this function, so no need to add them
// to the PendingInstantiations.
MarkFunctionReferenced(CurrentLocation, CallOp);
// Fill in the __invoke function with a dummy implementation. IR generation
// will fill in the actual details. Update its type in case it contained
// an 'auto'.
Invoker->markUsed(Context);
Invoker->setReferenced();
Invoker->setType(Conv->getReturnType()->getPointeeType());
Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
// Construct the body of the conversion function { return __invoke; }.
Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(),
VK_LValue, Conv->getLocation()).get();
assert(FunctionRef && "Can't refer to __invoke function?");
Stmt *Return = BuildReturnStmt(Conv->getLocation(), FunctionRef).get();
Conv->setBody(CompoundStmt::Create(Context, Return, Conv->getLocation(),
Conv->getLocation()));
Conv->markUsed(Context);
Conv->setReferenced();
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Conv);
L->CompletedImplicitDefinition(Invoker);
}
}
void Sema::DefineImplicitLambdaToBlockPointerConversion(
SourceLocation CurrentLocation,
CXXConversionDecl *Conv)
{
assert(!Conv->getParent()->isGenericLambda());
SynthesizedFunctionScope Scope(*this, Conv);
// Copy-initialize the lambda object as needed to capture it.
Expr *This = ActOnCXXThis(CurrentLocation).get();
Expr *DerefThis =CreateBuiltinUnaryOp(CurrentLocation, UO_Deref, This).get();
ExprResult BuildBlock = BuildBlockForLambdaConversion(CurrentLocation,
Conv->getLocation(),
Conv, DerefThis);
// If we're not under ARC, make sure we still get the _Block_copy/autorelease
// behavior. Note that only the general conversion function does this
// (since it's unusable otherwise); in the case where we inline the
// block literal, it has block literal lifetime semantics.
if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount)
BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(),
CK_CopyAndAutoreleaseBlockObject,
BuildBlock.get(), nullptr, VK_RValue);
if (BuildBlock.isInvalid()) {
Diag(CurrentLocation, diag::note_lambda_to_block_conv);
Conv->setInvalidDecl();
return;
}
// Create the return statement that returns the block from the conversion
// function.
StmtResult Return = BuildReturnStmt(Conv->getLocation(), BuildBlock.get());
if (Return.isInvalid()) {
Diag(CurrentLocation, diag::note_lambda_to_block_conv);
Conv->setInvalidDecl();
return;
}
// Set the body of the conversion function.
Stmt *ReturnS = Return.get();
Conv->setBody(CompoundStmt::Create(Context, ReturnS, Conv->getLocation(),
Conv->getLocation()));
Conv->markUsed(Context);
// We're done; notify the mutation listener, if any.
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Conv);
}
}
/// Determine whether the given list arguments contains exactly one
/// "real" (non-default) argument.
static bool hasOneRealArgument(MultiExprArg Args) {
switch (Args.size()) {
case 0:
return false;
default:
if (!Args[1]->isDefaultArgument())
return false;
LLVM_FALLTHROUGH;
case 1:
return !Args[0]->isDefaultArgument();
}
return false;
}
ExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
NamedDecl *FoundDecl,
CXXConstructorDecl *Constructor,
MultiExprArg ExprArgs,
bool HadMultipleCandidates,
bool IsListInitialization,
bool IsStdInitListInitialization,
bool RequiresZeroInit,
unsigned ConstructKind,
SourceRange ParenRange) {
bool Elidable = false;
// C++0x [class.copy]p34:
// When certain criteria are met, an implementation is allowed to
// omit the copy/move construction of a class object, even if the
// copy/move constructor and/or destructor for the object have
// side effects. [...]
// - when a temporary class object that has not been bound to a
// reference (12.2) would be copied/moved to a class object
// with the same cv-unqualified type, the copy/move operation
// can be omitted by constructing the temporary object
// directly into the target of the omitted copy/move
if (ConstructKind == CXXConstructExpr::CK_Complete && Constructor &&
Constructor->isCopyOrMoveConstructor() && hasOneRealArgument(ExprArgs)) {
Expr *SubExpr = ExprArgs[0];
Elidable = SubExpr->isTemporaryObject(
Context, cast<CXXRecordDecl>(FoundDecl->getDeclContext()));
}
return BuildCXXConstructExpr(ConstructLoc, DeclInitType,
FoundDecl, Constructor,
Elidable, ExprArgs, HadMultipleCandidates,
IsListInitialization,
IsStdInitListInitialization, RequiresZeroInit,
ConstructKind, ParenRange);
}
ExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
NamedDecl *FoundDecl,
CXXConstructorDecl *Constructor,
bool Elidable,
MultiExprArg ExprArgs,
bool HadMultipleCandidates,
bool IsListInitialization,
bool IsStdInitListInitialization,
bool RequiresZeroInit,
unsigned ConstructKind,
SourceRange ParenRange) {
if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl)) {
Constructor = findInheritingConstructor(ConstructLoc, Constructor, Shadow);
if (DiagnoseUseOfDecl(Constructor, ConstructLoc))
return ExprError();
}
return BuildCXXConstructExpr(
ConstructLoc, DeclInitType, Constructor, Elidable, ExprArgs,
HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization,
RequiresZeroInit, ConstructKind, ParenRange);
}
/// BuildCXXConstructExpr - Creates a complete call to a constructor,
/// including handling of its default argument expressions.
ExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor,
bool Elidable,
MultiExprArg ExprArgs,
bool HadMultipleCandidates,
bool IsListInitialization,
bool IsStdInitListInitialization,
bool RequiresZeroInit,
unsigned ConstructKind,
SourceRange ParenRange) {
assert(declaresSameEntity(
Constructor->getParent(),
DeclInitType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) &&
"given constructor for wrong type");
MarkFunctionReferenced(ConstructLoc, Constructor);
if (getLangOpts().CUDA && !CheckCUDACall(ConstructLoc, Constructor))
return ExprError();
return CXXConstructExpr::Create(
Context, DeclInitType, ConstructLoc, Constructor, Elidable,
ExprArgs, HadMultipleCandidates, IsListInitialization,
IsStdInitListInitialization, RequiresZeroInit,
static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind),
ParenRange);
}
ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
assert(Field->hasInClassInitializer());
// If we already have the in-class initializer nothing needs to be done.
if (Field->getInClassInitializer())
return CXXDefaultInitExpr::Create(Context, Loc, Field);
// If we might have already tried and failed to instantiate, don't try again.
if (Field->isInvalidDecl())
return ExprError();
// Maybe we haven't instantiated the in-class initializer. Go check the
// pattern FieldDecl to see if it has one.
CXXRecordDecl *ParentRD = cast<CXXRecordDecl>(Field->getParent());
if (isTemplateInstantiation(ParentRD->getTemplateSpecializationKind())) {
CXXRecordDecl *ClassPattern = ParentRD->getTemplateInstantiationPattern();
DeclContext::lookup_result Lookup =
ClassPattern->lookup(Field->getDeclName());
// Lookup can return at most two results: the pattern for the field, or the
// injected class name of the parent record. No other member can have the
// same name as the field.
// In modules mode, lookup can return multiple results (coming from
// different modules).
assert((getLangOpts().Modules || (!Lookup.empty() && Lookup.size() <= 2)) &&
"more than two lookup results for field name");
FieldDecl *Pattern = dyn_cast<FieldDecl>(Lookup[0]);
if (!Pattern) {
assert(isa<CXXRecordDecl>(Lookup[0]) &&
"cannot have other non-field member with same name");
for (auto L : Lookup)
if (isa<FieldDecl>(L)) {
Pattern = cast<FieldDecl>(L);
break;
}
assert(Pattern && "We must have set the Pattern!");
}
if (!Pattern->hasInClassInitializer() ||
InstantiateInClassInitializer(Loc, Field, Pattern,
getTemplateInstantiationArgs(Field))) {
// Don't diagnose this again.
Field->setInvalidDecl();
return ExprError();
}
return CXXDefaultInitExpr::Create(Context, Loc, Field);
}
// DR1351:
// If the brace-or-equal-initializer of a non-static data member
// invokes a defaulted default constructor of its class or of an
// enclosing class in a potentially evaluated subexpression, the
// program is ill-formed.
//
// This resolution is unworkable: the exception specification of the
// default constructor can be needed in an unevaluated context, in
// particular, in the operand of a noexcept-expression, and we can be
// unable to compute an exception specification for an enclosed class.
//
// Any attempt to resolve the exception specification of a defaulted default
// constructor before the initializer is lexically complete will ultimately
// come here at which point we can diagnose it.
RecordDecl *OutermostClass = ParentRD->getOuterLexicalRecordContext();
Diag(Loc, diag::err_in_class_initializer_not_yet_parsed)
<< OutermostClass << Field;
Diag(Field->getEndLoc(), diag::note_in_class_initializer_not_yet_parsed);
// Recover by marking the field invalid, unless we're in a SFINAE context.
if (!isSFINAEContext())
Field->setInvalidDecl();
return ExprError();
}
void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
if (VD->isInvalidDecl()) return;
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl());
if (ClassDecl->isInvalidDecl()) return;
if (ClassDecl->hasIrrelevantDestructor()) return;
if (ClassDecl->isDependentContext()) return;
if (VD->isNoDestroy(getASTContext()))
return;
CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
MarkFunctionReferenced(VD->getLocation(), Destructor);
CheckDestructorAccess(VD->getLocation(), Destructor,
PDiag(diag::err_access_dtor_var)
<< VD->getDeclName()
<< VD->getType());
DiagnoseUseOfDecl(Destructor, VD->getLocation());
if (Destructor->isTrivial()) return;
if (!VD->hasGlobalStorage()) return;
// Emit warning for non-trivial dtor in global scope (a real global,
// class-static, function-static).
Diag(VD->getLocation(), diag::warn_exit_time_destructor);
// TODO: this should be re-enabled for static locals by !CXAAtExit
if (!VD->isStaticLocal())
Diag(VD->getLocation(), diag::warn_global_destructor);
}
/// Given a constructor and the set of arguments provided for the
/// constructor, convert the arguments and add any required default arguments
/// to form a proper call to this constructor.
///
/// \returns true if an error occurred, false otherwise.
bool
Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
MultiExprArg ArgsPtr,
SourceLocation Loc,
SmallVectorImpl<Expr*> &ConvertedArgs,
bool AllowExplicit,
bool IsListInitialization) {
// FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall.
unsigned NumArgs = ArgsPtr.size();
Expr **Args = ArgsPtr.data();
const FunctionProtoType *Proto
= Constructor->getType()->getAs<FunctionProtoType>();
assert(Proto && "Constructor without a prototype?");
unsigned NumParams = Proto->getNumParams();
// If too few arguments are available, we'll fill in the rest with defaults.
if (NumArgs < NumParams)
ConvertedArgs.reserve(NumParams);
else
ConvertedArgs.reserve(NumArgs);
VariadicCallType CallType =
Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
SmallVector<Expr *, 8> AllArgs;
bool Invalid = GatherArgumentsForCall(Loc, Constructor,
Proto, 0,
llvm::makeArrayRef(Args, NumArgs),
AllArgs,
CallType, AllowExplicit,
IsListInitialization);
ConvertedArgs.append(AllArgs.begin(), AllArgs.end());
DiagnoseSentinelCalls(Constructor, Loc, AllArgs);
CheckConstructorCall(Constructor,
llvm::makeArrayRef(AllArgs.data(), AllArgs.size()),
Proto, Loc);
return Invalid;
}
static inline bool
CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef,
const FunctionDecl *FnDecl) {
const DeclContext *DC = FnDecl->getDeclContext()->getRedeclContext();
if (isa<NamespaceDecl>(DC)) {
return SemaRef.Diag(FnDecl->getLocation(),
diag::err_operator_new_delete_declared_in_namespace)
<< FnDecl->getDeclName();
}
if (isa<TranslationUnitDecl>(DC) &&
FnDecl->getStorageClass() == SC_Static) {
return SemaRef.Diag(FnDecl->getLocation(),
diag::err_operator_new_delete_declared_static)
<< FnDecl->getDeclName();
}
return false;
}
static QualType
RemoveAddressSpaceFromPtr(Sema &SemaRef, const PointerType *PtrTy) {
QualType QTy = PtrTy->getPointeeType();
QTy = SemaRef.Context.removeAddrSpaceQualType(QTy);
return SemaRef.Context.getPointerType(QTy);
}
static inline bool
CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
CanQualType ExpectedResultType,
CanQualType ExpectedFirstParamType,
unsigned DependentParamTypeDiag,
unsigned InvalidParamTypeDiag) {
QualType ResultType =
FnDecl->getType()->getAs<FunctionType>()->getReturnType();
// Check that the result type is not dependent.
if (ResultType->isDependentType())
return SemaRef.Diag(FnDecl->getLocation(),
diag::err_operator_new_delete_dependent_result_type)
<< FnDecl->getDeclName() << ExpectedResultType;
// OpenCL C++: the operator is valid on any address space.
if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
if (auto *PtrTy = ResultType->getAs<PointerType>()) {
ResultType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy);
}
}
// Check that the result type is what we expect.
if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType)
return SemaRef.Diag(FnDecl->getLocation(),
diag::err_operator_new_delete_invalid_result_type)
<< FnDecl->getDeclName() << ExpectedResultType;
// A function template must have at least 2 parameters.
if (FnDecl->getDescribedFunctionTemplate() && FnDecl->getNumParams() < 2)
return SemaRef.Diag(FnDecl->getLocation(),
diag::err_operator_new_delete_template_too_few_parameters)
<< FnDecl->getDeclName();
// The function decl must have at least 1 parameter.
if (FnDecl->getNumParams() == 0)
return SemaRef.Diag(FnDecl->getLocation(),
diag::err_operator_new_delete_too_few_parameters)
<< FnDecl->getDeclName();
// Check the first parameter type is not dependent.
QualType FirstParamType = FnDecl->getParamDecl(0)->getType();
if (FirstParamType->isDependentType())
return SemaRef.Diag(FnDecl->getLocation(), DependentParamTypeDiag)
<< FnDecl->getDeclName() << ExpectedFirstParamType;
// Check that the first parameter type is what we expect.
if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
// OpenCL C++: the operator is valid on any address space.
if (auto *PtrTy =
FnDecl->getParamDecl(0)->getType()->getAs<PointerType>()) {
FirstParamType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy);
}
}
if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() !=
ExpectedFirstParamType)
return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag)
<< FnDecl->getDeclName() << ExpectedFirstParamType;
return false;
}
static bool
CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
// C++ [basic.stc.dynamic.allocation]p1:
// A program is ill-formed if an allocation function is declared in a
// namespace scope other than global scope or declared static in global
// scope.
if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
return true;
CanQualType SizeTy =
SemaRef.Context.getCanonicalType(SemaRef.Context.getSizeType());
// C++ [basic.stc.dynamic.allocation]p1:
// The return type shall be void*. The first parameter shall have type
// std::size_t.
if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidPtrTy,
SizeTy,
diag::err_operator_new_dependent_param_type,
diag::err_operator_new_param_type))
return true;
// C++ [basic.stc.dynamic.allocation]p1:
// The first parameter shall not have an associated default argument.
if (FnDecl->getParamDecl(0)->hasDefaultArg())
return SemaRef.Diag(FnDecl->getLocation(),
diag::err_operator_new_default_arg)
<< FnDecl->getDeclName() << FnDecl->getParamDecl(0)->getDefaultArgRange();
return false;
}
static bool
CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
// C++ [basic.stc.dynamic.deallocation]p1:
// A program is ill-formed if deallocation functions are declared in a
// namespace scope other than global scope or declared static in global
// scope.
if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
return true;
auto *MD = dyn_cast<CXXMethodDecl>(FnDecl);
// C++ P0722:
// Within a class C, the first parameter of a destroying operator delete
// shall be of type C *. The first parameter of any other deallocation
// function shall be of type void *.
CanQualType ExpectedFirstParamType =
MD && MD->isDestroyingOperatorDelete()
? SemaRef.Context.getCanonicalType(SemaRef.Context.getPointerType(
SemaRef.Context.getRecordType(MD->getParent())))
: SemaRef.Context.VoidPtrTy;
// C++ [basic.stc.dynamic.deallocation]p2:
// Each deallocation function shall return void
if (CheckOperatorNewDeleteTypes(
SemaRef, FnDecl, SemaRef.Context.VoidTy, ExpectedFirstParamType,
diag::err_operator_delete_dependent_param_type,
diag::err_operator_delete_param_type))
return true;
// C++ P0722:
// A destroying operator delete shall be a usual deallocation function.
if (MD && !MD->getParent()->isDependentContext() &&
MD->isDestroyingOperatorDelete() &&
!SemaRef.isUsualDeallocationFunction(MD)) {
SemaRef.Diag(MD->getLocation(),
diag::err_destroying_operator_delete_not_usual);
return true;
}
return false;
}
/// CheckOverloadedOperatorDeclaration - Check whether the declaration
/// of this overloaded operator is well-formed. If so, returns false;
/// otherwise, emits appropriate diagnostics and returns true.
bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
assert(FnDecl && FnDecl->isOverloadedOperator() &&
"Expected an overloaded operator declaration");
OverloadedOperatorKind Op = FnDecl->getOverloadedOperator();
// C++ [over.oper]p5:
// The allocation and deallocation functions, operator new,
// operator new[], operator delete and operator delete[], are
// described completely in 3.7.3. The attributes and restrictions
// found in the rest of this subclause do not apply to them unless
// explicitly stated in 3.7.3.
if (Op == OO_Delete || Op == OO_Array_Delete)
return CheckOperatorDeleteDeclaration(*this, FnDecl);
if (Op == OO_New || Op == OO_Array_New)
return CheckOperatorNewDeclaration(*this, FnDecl);
// C++ [over.oper]p6:
// An operator function shall either be a non-static member
// function or be a non-member function and have at least one
// parameter whose type is a class, a reference to a class, an
// enumeration, or a reference to an enumeration.
if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(FnDecl)) {
if (MethodDecl->isStatic())
return Diag(FnDecl->getLocation(),
diag::err_operator_overload_static) << FnDecl->getDeclName();
} else {
bool ClassOrEnumParam = false;
for (auto Param : FnDecl->parameters()) {
QualType ParamType = Param->getType().getNonReferenceType();
if (ParamType->isDependentType() || ParamType->isRecordType() ||
ParamType->isEnumeralType()) {
ClassOrEnumParam = true;
break;
}
}
if (!ClassOrEnumParam)
return Diag(FnDecl->getLocation(),
diag::err_operator_overload_needs_class_or_enum)
<< FnDecl->getDeclName();
}
// C++ [over.oper]p8:
// An operator function cannot have default arguments (8.3.6),
// except where explicitly stated below.
//
// Only the function-call operator allows default arguments
// (C++ [over.call]p1).
if (Op != OO_Call) {
for (auto Param : FnDecl->parameters()) {
if (Param->hasDefaultArg())
return Diag(Param->getLocation(),
diag::err_operator_overload_default_arg)
<< FnDecl->getDeclName() << Param->getDefaultArgRange();
}
}
static const bool OperatorUses[NUM_OVERLOADED_OPERATORS][3] = {
{ false, false, false }
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
, { Unary, Binary, MemberOnly }
#include "clang/Basic/OperatorKinds.def"
};
bool CanBeUnaryOperator = OperatorUses[Op][0];
bool CanBeBinaryOperator = OperatorUses[Op][1];
bool MustBeMemberOperator = OperatorUses[Op][2];
// C++ [over.oper]p8:
// [...] Operator functions cannot have more or fewer parameters
// than the number required for the corresponding operator, as
// described in the rest of this subclause.
unsigned NumParams = FnDecl->getNumParams()
+ (isa<CXXMethodDecl>(FnDecl)? 1 : 0);
if (Op != OO_Call &&
((NumParams == 1 && !CanBeUnaryOperator) ||
(NumParams == 2 && !CanBeBinaryOperator) ||
(NumParams < 1) || (NumParams > 2))) {
// We have the wrong number of parameters.
unsigned ErrorKind;
if (CanBeUnaryOperator && CanBeBinaryOperator) {
ErrorKind = 2; // 2 -> unary or binary.
} else if (CanBeUnaryOperator) {
ErrorKind = 0; // 0 -> unary
} else {
assert(CanBeBinaryOperator &&
"All non-call overloaded operators are unary or binary!");
ErrorKind = 1; // 1 -> binary
}
return Diag(FnDecl->getLocation(), diag::err_operator_overload_must_be)
<< FnDecl->getDeclName() << NumParams << ErrorKind;
}
// Overloaded operators other than operator() cannot be variadic.
if (Op != OO_Call &&
FnDecl->getType()->getAs<FunctionProtoType>()->isVariadic()) {
return Diag(FnDecl->getLocation(), diag::err_operator_overload_variadic)
<< FnDecl->getDeclName();
}
// Some operators must be non-static member functions.
if (MustBeMemberOperator && !isa<CXXMethodDecl>(FnDecl)) {
return Diag(FnDecl->getLocation(),
diag::err_operator_overload_must_be_member)
<< FnDecl->getDeclName();
}
// C++ [over.inc]p1:
// The user-defined function called operator++ implements the
// prefix and postfix ++ operator. If this function is a member
// function with no parameters, or a non-member function with one
// parameter of class or enumeration type, it defines the prefix
// increment operator ++ for objects of that type. If the function
// is a member function with one parameter (which shall be of type
// int) or a non-member function with two parameters (the second
// of which shall be of type int), it defines the postfix
// increment operator ++ for objects of that type.
if ((Op == OO_PlusPlus || Op == OO_MinusMinus) && NumParams == 2) {
ParmVarDecl *LastParam = FnDecl->getParamDecl(FnDecl->getNumParams() - 1);
QualType ParamType = LastParam->getType();
if (!ParamType->isSpecificBuiltinType(BuiltinType::Int) &&
!ParamType->isDependentType())
return Diag(LastParam->getLocation(),
diag::err_operator_overload_post_incdec_must_be_int)
<< LastParam->getType() << (Op == OO_MinusMinus);
}
return false;
}
static bool
checkLiteralOperatorTemplateParameterList(Sema &SemaRef,
FunctionTemplateDecl *TpDecl) {
TemplateParameterList *TemplateParams = TpDecl->getTemplateParameters();
// Must have one or two template parameters.
if (TemplateParams->size() == 1) {
NonTypeTemplateParmDecl *PmDecl =
dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(0));
// The template parameter must be a char parameter pack.
if (PmDecl && PmDecl->isTemplateParameterPack() &&
SemaRef.Context.hasSameType(PmDecl->getType(), SemaRef.Context.CharTy))
return false;
} else if (TemplateParams->size() == 2) {
TemplateTypeParmDecl *PmType =
dyn_cast<TemplateTypeParmDecl>(TemplateParams->getParam(0));
NonTypeTemplateParmDecl *PmArgs =
dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(1));
// The second template parameter must be a parameter pack with the
// first template parameter as its type.
if (PmType && PmArgs && !PmType->isTemplateParameterPack() &&
PmArgs->isTemplateParameterPack()) {
const TemplateTypeParmType *TArgs =
PmArgs->getType()->getAs<TemplateTypeParmType>();
if (TArgs && TArgs->getDepth() == PmType->getDepth() &&
TArgs->getIndex() == PmType->getIndex()) {
if (!SemaRef.inTemplateInstantiation())
SemaRef.Diag(TpDecl->getLocation(),
diag::ext_string_literal_operator_template);
return false;
}
}
}
SemaRef.Diag(TpDecl->getTemplateParameters()->getSourceRange().getBegin(),
diag::err_literal_operator_template)
<< TpDecl->getTemplateParameters()->getSourceRange();
return true;
}
/// CheckLiteralOperatorDeclaration - Check whether the declaration
/// of this literal operator function is well-formed. If so, returns
/// false; otherwise, emits appropriate diagnostics and returns true.
bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
if (isa<CXXMethodDecl>(FnDecl)) {
Diag(FnDecl->getLocation(), diag::err_literal_operator_outside_namespace)
<< FnDecl->getDeclName();
return true;
}
if (FnDecl->isExternC()) {
Diag(FnDecl->getLocation(), diag::err_literal_operator_extern_c);
if (const LinkageSpecDecl *LSD =
FnDecl->getDeclContext()->getExternCContext())
Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here);
return true;
}
// This might be the definition of a literal operator template.
FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate();
// This might be a specialization of a literal operator template.
if (!TpDecl)
TpDecl = FnDecl->getPrimaryTemplate();
// template <char...> type operator "" name() and
// template <class T, T...> type operator "" name() are the only valid
// template signatures, and the only valid signatures with no parameters.
if (TpDecl) {
if (FnDecl->param_size() != 0) {
Diag(FnDecl->getLocation(),
diag::err_literal_operator_template_with_params);
return true;
}
if (checkLiteralOperatorTemplateParameterList(*this, TpDecl))
return true;
} else if (FnDecl->param_size() == 1) {
const ParmVarDecl *Param = FnDecl->getParamDecl(0);
QualType ParamType = Param->getType().getUnqualifiedType();
// Only unsigned long long int, long double, any character type, and const
// char * are allowed as the only parameters.
if (ParamType->isSpecificBuiltinType(BuiltinType::ULongLong) ||
ParamType->isSpecificBuiltinType(BuiltinType::LongDouble) ||
Context.hasSameType(ParamType, Context.CharTy) ||
Context.hasSameType(ParamType, Context.WideCharTy) ||
Context.hasSameType(ParamType, Context.Char8Ty) ||
Context.hasSameType(ParamType, Context.Char16Ty) ||
Context.hasSameType(ParamType, Context.Char32Ty)) {
} else if (const PointerType *Ptr = ParamType->getAs<PointerType>()) {
QualType InnerType = Ptr->getPointeeType();
// Pointer parameter must be a const char *.
if (!(Context.hasSameType(InnerType.getUnqualifiedType(),
Context.CharTy) &&
InnerType.isConstQualified() && !InnerType.isVolatileQualified())) {
Diag(Param->getSourceRange().getBegin(),
diag::err_literal_operator_param)
<< ParamType << "'const char *'" << Param->getSourceRange();
return true;
}
} else if (ParamType->isRealFloatingType()) {
Diag(Param->getSourceRange().getBegin(), diag::err_literal_operator_param)
<< ParamType << Context.LongDoubleTy << Param->getSourceRange();
return true;
} else if (ParamType->isIntegerType()) {
Diag(Param->getSourceRange().getBegin(), diag::err_literal_operator_param)
<< ParamType << Context.UnsignedLongLongTy << Param->getSourceRange();
return true;
} else {
Diag(Param->getSourceRange().getBegin(),
diag::err_literal_operator_invalid_param)
<< ParamType << Param->getSourceRange();
return true;
}
} else if (FnDecl->param_size() == 2) {
FunctionDecl::param_iterator Param = FnDecl->param_begin();
// First, verify that the first parameter is correct.
QualType FirstParamType = (*Param)->getType().getUnqualifiedType();
// Two parameter function must have a pointer to const as a
// first parameter; let's strip those qualifiers.
const PointerType *PT = FirstParamType->getAs<PointerType>();
if (!PT) {
Diag((*Param)->getSourceRange().getBegin(),
diag::err_literal_operator_param)
<< FirstParamType << "'const char *'" << (*Param)->getSourceRange();
return true;
}
QualType PointeeType = PT->getPointeeType();
// First parameter must be const
if (!PointeeType.isConstQualified() || PointeeType.isVolatileQualified()) {
Diag((*Param)->getSourceRange().getBegin(),
diag::err_literal_operator_param)
<< FirstParamType << "'const char *'" << (*Param)->getSourceRange();
return true;
}
QualType InnerType = PointeeType.getUnqualifiedType();
// Only const char *, const wchar_t*, const char8_t*, const char16_t*, and
// const char32_t* are allowed as the first parameter to a two-parameter
// function
if (!(Context.hasSameType(InnerType, Context.CharTy) ||
Context.hasSameType(InnerType, Context.WideCharTy) ||
Context.hasSameType(InnerType, Context.Char8Ty) ||
Context.hasSameType(InnerType, Context.Char16Ty) ||
Context.hasSameType(InnerType, Context.Char32Ty))) {
Diag((*Param)->getSourceRange().getBegin(),
diag::err_literal_operator_param)
<< FirstParamType << "'const char *'" << (*Param)->getSourceRange();
return true;
}
// Move on to the second and final parameter.
++Param;
// The second parameter must be a std::size_t.
QualType SecondParamType = (*Param)->getType().getUnqualifiedType();
if (!Context.hasSameType(SecondParamType, Context.getSizeType())) {
Diag((*Param)->getSourceRange().getBegin(),
diag::err_literal_operator_param)
<< SecondParamType << Context.getSizeType()
<< (*Param)->getSourceRange();
return true;
}
} else {
Diag(FnDecl->getLocation(), diag::err_literal_operator_bad_param_count);
return true;
}
// Parameters are good.
// A parameter-declaration-clause containing a default argument is not
// equivalent to any of the permitted forms.
for (auto Param : FnDecl->parameters()) {
if (Param->hasDefaultArg()) {
Diag(Param->getDefaultArgRange().getBegin(),
diag::err_literal_operator_default_argument)
<< Param->getDefaultArgRange();
break;
}
}
StringRef LiteralName
= FnDecl->getDeclName().getCXXLiteralIdentifier()->getName();
if (LiteralName[0] != '_' &&
!getSourceManager().isInSystemHeader(FnDecl->getLocation())) {
// C++11 [usrlit.suffix]p1:
// Literal suffix identifiers that do not start with an underscore
// are reserved for future standardization.
Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved)
<< StringLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
}
return false;
}
/// ActOnStartLinkageSpecification - Parsed the beginning of a C++
/// linkage specification, including the language and (if present)
/// the '{'. ExternLoc is the location of the 'extern', Lang is the
/// language string literal. LBraceLoc, if valid, provides the location of
/// the '{' brace. Otherwise, this linkage specification does not
/// have any braces.
Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc,
Expr *LangStr,
SourceLocation LBraceLoc) {
StringLiteral *Lit = cast<StringLiteral>(LangStr);
if (!Lit->isAscii()) {
Diag(LangStr->getExprLoc(), diag::err_language_linkage_spec_not_ascii)
<< LangStr->getSourceRange();
return nullptr;
}
StringRef Lang = Lit->getString();
LinkageSpecDecl::LanguageIDs Language;
if (Lang == "C")
Language = LinkageSpecDecl::lang_c;
else if (Lang == "C++")
Language = LinkageSpecDecl::lang_cxx;
else {
Diag(LangStr->getExprLoc(), diag::err_language_linkage_spec_unknown)
<< LangStr->getSourceRange();
return nullptr;
}
// FIXME: Add all the various semantics of linkage specifications
LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext, ExternLoc,
LangStr->getExprLoc(), Language,
LBraceLoc.isValid());
CurContext->addDecl(D);
PushDeclContext(S, D);
return D;
}
/// ActOnFinishLinkageSpecification - Complete the definition of
/// the C++ linkage specification LinkageSpec. If RBraceLoc is
/// valid, it's the position of the closing '}' brace in a linkage
/// specification that uses braces.
Decl *Sema::ActOnFinishLinkageSpecification(Scope *S,
Decl *LinkageSpec,
SourceLocation RBraceLoc) {
if (RBraceLoc.isValid()) {
LinkageSpecDecl* LSDecl = cast<LinkageSpecDecl>(LinkageSpec);
LSDecl->setRBraceLoc(RBraceLoc);
}
PopDeclContext();
return LinkageSpec;
}
Decl *Sema::ActOnEmptyDeclaration(Scope *S,
const ParsedAttributesView &AttrList,
SourceLocation SemiLoc) {
Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc);
// Attribute declarations appertain to empty declaration so we handle
// them here.
ProcessDeclAttributeList(S, ED, AttrList);
CurContext->addDecl(ED);
return ED;
}
/// Perform semantic analysis for the variable declaration that
/// occurs within a C++ catch clause, returning the newly-created
/// variable.
VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
TypeSourceInfo *TInfo,
SourceLocation StartLoc,
SourceLocation Loc,
IdentifierInfo *Name) {
bool Invalid = false;
QualType ExDeclType = TInfo->getType();
// Arrays and functions decay.
if (ExDeclType->isArrayType())
ExDeclType = Context.getArrayDecayedType(ExDeclType);
else if (ExDeclType->isFunctionType())
ExDeclType = Context.getPointerType(ExDeclType);
// C++ 15.3p1: The exception-declaration shall not denote an incomplete type.
// The exception-declaration shall not denote a pointer or reference to an
// incomplete type, other than [cv] void*.
// N2844 forbids rvalue references.
if (!ExDeclType->isDependentType() && ExDeclType->isRValueReferenceType()) {
Diag(Loc, diag::err_catch_rvalue_ref);
Invalid = true;
}
if (ExDeclType->isVariablyModifiedType()) {
Diag(Loc, diag::err_catch_variably_modified) << ExDeclType;
Invalid = true;
}
QualType BaseType = ExDeclType;
int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference
unsigned DK = diag::err_catch_incomplete;
if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
BaseType = Ptr->getPointeeType();
Mode = 1;
DK = diag::err_catch_incomplete_ptr;
} else if (const ReferenceType *Ref = BaseType->getAs<ReferenceType>()) {
// For the purpose of error recovery, we treat rvalue refs like lvalue refs.
BaseType = Ref->getPointeeType();
Mode = 2;
DK = diag::err_catch_incomplete_ref;
}
if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) &&
!BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK))
Invalid = true;
if (!Invalid && !ExDeclType->isDependentType() &&
RequireNonAbstractType(Loc, ExDeclType,
diag::err_abstract_type_in_decl,
AbstractVariableType))
Invalid = true;
// Only the non-fragile NeXT runtime currently supports C++ catches
// of ObjC types, and no runtime supports catching ObjC types by value.
if (!Invalid && getLangOpts().ObjC) {
QualType T = ExDeclType;
if (const ReferenceType *RT = T->getAs<ReferenceType>())
T = RT->getPointeeType();
if (T->isObjCObjectType()) {
Diag(Loc, diag::err_objc_object_catch);
Invalid = true;
} else if (T->isObjCObjectPointerType()) {
// FIXME: should this be a test for macosx-fragile specifically?
if (getLangOpts().ObjCRuntime.isFragile())
Diag(Loc, diag::warn_objc_pointer_cxx_catch_fragile);
}
}
VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name,
ExDeclType, TInfo, SC_None);
ExDecl->setExceptionVariable(true);
// In ARC, infer 'retaining' for variables of retainable type.
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(ExDecl))
Invalid = true;
if (!Invalid && !ExDeclType->isDependentType()) {
if (const RecordType *recordType = ExDeclType->getAs<RecordType>()) {
// Insulate this from anything else we might currently be parsing.
EnterExpressionEvaluationContext scope(
*this, ExpressionEvaluationContext::PotentiallyEvaluated);
// C++ [except.handle]p16:
// The object declared in an exception-declaration or, if the
// exception-declaration does not specify a name, a temporary (12.2) is
// copy-initialized (8.5) from the exception object. [...]
// The object is destroyed when the handler exits, after the destruction
// of any automatic objects initialized within the handler.
//
// We just pretend to initialize the object with itself, then make sure
// it can be destroyed later.
QualType initType = Context.getExceptionObjectType(ExDeclType);
InitializedEntity entity =
InitializedEntity::InitializeVariable(ExDecl);
InitializationKind initKind =
InitializationKind::CreateCopy(Loc, SourceLocation());
Expr *opaqueValue =
new (Context) OpaqueValueExpr(Loc, initType, VK_LValue, OK_Ordinary);
InitializationSequence sequence(*this, entity, initKind, opaqueValue);
ExprResult result = sequence.Perform(*this, entity, initKind, opaqueValue);
if (result.isInvalid())
Invalid = true;
else {
// If the constructor used was non-trivial, set this as the
// "initializer".
CXXConstructExpr *construct = result.getAs<CXXConstructExpr>();
if (!construct->getConstructor()->isTrivial()) {
Expr *init = MaybeCreateExprWithCleanups(construct);
ExDecl->setInit(init);
}
// And make sure it's destructable.
FinalizeVarWithDestructor(ExDecl, recordType);
}
}
}
if (Invalid)
ExDecl->setInvalidDecl();
return ExDecl;
}
/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch
/// handler.
Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
bool Invalid = D.isInvalidType();
// Check for unexpanded parameter packs.
if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
UPPC_ExceptionType)) {
TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy,
D.getIdentifierLoc());
Invalid = true;
}
IdentifierInfo *II = D.getIdentifier();
if (NamedDecl *PrevDecl = LookupSingleName(S, II, D.getIdentifierLoc(),
LookupOrdinaryName,
ForVisibleRedeclaration)) {
// The scope should be freshly made just for us. There is just no way
// it contains any previous declaration, except for function parameters in
// a function-try-block's catch statement.
assert(!S->isDeclScope(PrevDecl));
if (isDeclInScope(PrevDecl, CurContext, S)) {
Diag(D.getIdentifierLoc(), diag::err_redefinition)
<< D.getIdentifier();
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
Invalid = true;
} else if (PrevDecl->isTemplateParameter())
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
}
if (D.getCXXScopeSpec().isSet() && !Invalid) {
Diag(D.getIdentifierLoc(), diag::err_qualified_catch_declarator)
<< D.getCXXScopeSpec().getRange();
Invalid = true;
}
VarDecl *ExDecl = BuildExceptionDeclaration(
S, TInfo, D.getBeginLoc(), D.getIdentifierLoc(), D.getIdentifier());
if (Invalid)
ExDecl->setInvalidDecl();
// Add the exception declaration into this scope.
if (II)
PushOnScopeChains(ExDecl, S);
else
CurContext->addDecl(ExDecl);
ProcessDeclAttributes(S, ExDecl, D);
return ExDecl;
}
Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc,
Expr *AssertExpr,
Expr *AssertMessageExpr,
SourceLocation RParenLoc) {
StringLiteral *AssertMessage =
AssertMessageExpr ? cast<StringLiteral>(AssertMessageExpr) : nullptr;
if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression))
return nullptr;
return BuildStaticAssertDeclaration(StaticAssertLoc, AssertExpr,
AssertMessage, RParenLoc, false);
}
Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
Expr *AssertExpr,
StringLiteral *AssertMessage,
SourceLocation RParenLoc,
bool Failed) {
assert(AssertExpr != nullptr && "Expected non-null condition");
if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent() &&
!Failed) {
// In a static_assert-declaration, the constant-expression shall be a
// constant expression that can be contextually converted to bool.
ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr);
if (Converted.isInvalid())
Failed = true;
else
Converted = ConstantExpr::Create(Context, Converted.get());
llvm::APSInt Cond;
if (!Failed && VerifyIntegerConstantExpression(Converted.get(), &Cond,
diag::err_static_assert_expression_is_not_constant,
/*AllowFold=*/false).isInvalid())
Failed = true;
if (!Failed && !Cond) {
SmallString<256> MsgBuffer;
llvm::raw_svector_ostream Msg(MsgBuffer);
if (AssertMessage)
AssertMessage->printPretty(Msg, nullptr, getPrintingPolicy());
Expr *InnerCond = nullptr;
std::string InnerCondDescription;
std::tie(InnerCond, InnerCondDescription) =
findFailedBooleanCondition(Converted.get());
if (InnerCond && !isa<CXXBoolLiteralExpr>(InnerCond)
&& !isa<IntegerLiteral>(InnerCond)) {
Diag(StaticAssertLoc, diag::err_static_assert_requirement_failed)
<< InnerCondDescription << !AssertMessage
<< Msg.str() << InnerCond->getSourceRange();
} else {
Diag(StaticAssertLoc, diag::err_static_assert_failed)
<< !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
}
Failed = true;
}
}
ExprResult FullAssertExpr = ActOnFinishFullExpr(AssertExpr, StaticAssertLoc,
/*DiscardedValue*/false,
/*IsConstexpr*/true);
if (FullAssertExpr.isInvalid())
Failed = true;
else
AssertExpr = FullAssertExpr.get();
Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc,
AssertExpr, AssertMessage, RParenLoc,
Failed);
CurContext->addDecl(Decl);
return Decl;
}
/// Perform semantic analysis of the given friend type declaration.
///
/// \returns A friend declaration that.
FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
SourceLocation FriendLoc,
TypeSourceInfo *TSInfo) {
assert(TSInfo && "NULL TypeSourceInfo for friend type declaration");
QualType T = TSInfo->getType();
SourceRange TypeRange = TSInfo->getTypeLoc().getLocalSourceRange();
// C++03 [class.friend]p2:
// An elaborated-type-specifier shall be used in a friend declaration
// for a class.*
//
// * The class-key of the elaborated-type-specifier is required.
if (!CodeSynthesisContexts.empty()) {
// Do not complain about the form of friend template types during any kind
// of code synthesis. For template instantiation, we will have complained
// when the template was defined.
} else {
if (!T->isElaboratedTypeSpecifier()) {
// If we evaluated the type to a record type, suggest putting
// a tag in front.
if (const RecordType *RT = T->getAs<RecordType>()) {
RecordDecl *RD = RT->getDecl();
SmallString<16> InsertionText(" ");
InsertionText += RD->getKindName();
Diag(TypeRange.getBegin(),
getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_unelaborated_friend_type :
diag::ext_unelaborated_friend_type)
<< (unsigned) RD->getTagKind()
<< T
<< FixItHint::CreateInsertion(getLocForEndOfToken(FriendLoc),
InsertionText);
} else {
Diag(FriendLoc,
getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_nonclass_type_friend :
diag::ext_nonclass_type_friend)
<< T
<< TypeRange;
}
} else if (T->getAs<EnumType>()) {
Diag(FriendLoc,
getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_enum_friend :
diag::ext_enum_friend)
<< T
<< TypeRange;
}
// C++11 [class.friend]p3:
// A friend declaration that does not declare a function shall have one
// of the following forms:
// friend elaborated-type-specifier ;
// friend simple-type-specifier ;
// friend typename-specifier ;
if (getLangOpts().CPlusPlus11 && LocStart != FriendLoc)
Diag(FriendLoc, diag::err_friend_not_first_in_declaration) << T;
}
// If the type specifier in a friend declaration designates a (possibly
// cv-qualified) class type, that class is declared as a friend; otherwise,
// the friend declaration is ignored.
return FriendDecl::Create(Context, CurContext,
TSInfo->getTypeLoc().getBeginLoc(), TSInfo,
FriendLoc);
}
/// Handle a friend tag declaration where the scope specifier was
/// templated.
Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
unsigned TagSpec, SourceLocation TagLoc,
CXXScopeSpec &SS, IdentifierInfo *Name,
SourceLocation NameLoc,
const ParsedAttributesView &Attr,
MultiTemplateParamsArg TempParamLists) {
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
bool IsMemberSpecialization = false;
bool Invalid = false;
if (TemplateParameterList *TemplateParams =
MatchTemplateParametersToScopeSpecifier(
TagLoc, NameLoc, SS, nullptr, TempParamLists, /*friend*/ true,
IsMemberSpecialization, Invalid)) {
if (TemplateParams->size() > 0) {
// This is a declaration of a class template.
if (Invalid)
return nullptr;
return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc, SS, Name,
NameLoc, Attr, TemplateParams, AS_public,
/*ModulePrivateLoc=*/SourceLocation(),
FriendLoc, TempParamLists.size() - 1,
TempParamLists.data()).get();
} else {
// The "template<>" header is extraneous.
Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams)
<< TypeWithKeyword::getTagTypeKindName(Kind) << Name;
IsMemberSpecialization = true;
}
}
if (Invalid) return nullptr;
bool isAllExplicitSpecializations = true;
for (unsigned I = TempParamLists.size(); I-- > 0; ) {
if (TempParamLists[I]->size()) {
isAllExplicitSpecializations = false;
break;
}
}
// FIXME: don't ignore attributes.
// If it's explicit specializations all the way down, just forget
// about the template header and build an appropriate non-templated
// friend. TODO: for source fidelity, remember the headers.
if (isAllExplicitSpecializations) {
if (SS.isEmpty()) {
bool Owned = false;
bool IsDependent = false;
return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc,
Attr, AS_public,
/*ModulePrivateLoc=*/SourceLocation(),
MultiTemplateParamsArg(), Owned, IsDependent,
/*ScopedEnumKWLoc=*/SourceLocation(),
/*ScopedEnumUsesClassTag=*/false,
/*UnderlyingType=*/TypeResult(),
/*IsTypeSpecifier=*/false,
/*IsTemplateParamOrArg=*/false);
}
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
ElaboratedTypeKeyword Keyword
= TypeWithKeyword::getKeywordForTagTypeKind(Kind);
QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc,
*Name, NameLoc);
if (T.isNull())
return nullptr;
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
if (isa<DependentNameType>(T)) {
DependentNameTypeLoc TL =
TSI->getTypeLoc().castAs<DependentNameTypeLoc>();
TL.setElaboratedKeywordLoc(TagLoc);
TL.setQualifierLoc(QualifierLoc);
TL.setNameLoc(NameLoc);
} else {
ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs<ElaboratedTypeLoc>();
TL.setElaboratedKeywordLoc(TagLoc);
TL.setQualifierLoc(QualifierLoc);
TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(NameLoc);
}
FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc,
TSI, FriendLoc, TempParamLists);
Friend->setAccess(AS_public);
CurContext->addDecl(Friend);
return Friend;
}
assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?");
// Handle the case of a templated-scope friend class. e.g.
// template <class T> class A<T>::B;
// FIXME: we don't support these right now.
Diag(NameLoc, diag::warn_template_qualified_friend_unsupported)
<< SS.getScopeRep() << SS.getRange() << cast<CXXRecordDecl>(CurContext);
ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name);
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
DependentNameTypeLoc TL = TSI->getTypeLoc().castAs<DependentNameTypeLoc>();
TL.setElaboratedKeywordLoc(TagLoc);
TL.setQualifierLoc(SS.getWithLocInContext(Context));
TL.setNameLoc(NameLoc);
FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc,
TSI, FriendLoc, TempParamLists);
Friend->setAccess(AS_public);
Friend->setUnsupportedFriend(true);
CurContext->addDecl(Friend);
return Friend;
}
/// Handle a friend type declaration. This works in tandem with
/// ActOnTag.
///
/// Notes on friend class templates:
///
/// We generally treat friend class declarations as if they were
/// declaring a class. So, for example, the elaborated type specifier
/// in a friend declaration is required to obey the restrictions of a
/// class-head (i.e. no typedefs in the scope chain), template
/// parameters are required to match up with simple template-ids, &c.
/// However, unlike when declaring a template specialization, it's
/// okay to refer to a template specialization without an empty
/// template parameter declaration, e.g.
/// friend class A<T>::B<unsigned>;
/// We permit this as a special case; if there are any template
/// parameters present at all, require proper matching, i.e.
/// template <> template \<class T> friend class A<int>::B;
Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
MultiTemplateParamsArg TempParams) {
SourceLocation Loc = DS.getBeginLoc();
assert(DS.isFriendSpecified());
assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
// C++ [class.friend]p3:
// A friend declaration that does not declare a function shall have one of
// the following forms:
// friend elaborated-type-specifier ;
// friend simple-type-specifier ;
// friend typename-specifier ;
//
// Any declaration with a type qualifier does not have that form. (It's
// legal to specify a qualified type as a friend, you just can't write the
// keywords.)
if (DS.getTypeQualifiers()) {
if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
Diag(DS.getConstSpecLoc(), diag::err_friend_decl_spec) << "const";
if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
Diag(DS.getVolatileSpecLoc(), diag::err_friend_decl_spec) << "volatile";
if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
Diag(DS.getRestrictSpecLoc(), diag::err_friend_decl_spec) << "restrict";
if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
Diag(DS.getAtomicSpecLoc(), diag::err_friend_decl_spec) << "_Atomic";
if (DS.getTypeQualifiers() & DeclSpec::TQ_unaligned)
Diag(DS.getUnalignedSpecLoc(), diag::err_friend_decl_spec) << "__unaligned";
}
// Try to convert the decl specifier to a type. This works for
// friend templates because ActOnTag never produces a ClassTemplateDecl
// for a TUK_Friend.
Declarator TheDeclarator(DS, DeclaratorContext::MemberContext);
TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S);
QualType T = TSI->getType();
if (TheDeclarator.isInvalidType())
return nullptr;
if (DiagnoseUnexpandedParameterPack(Loc, TSI, UPPC_FriendDeclaration))
return nullptr;
// This is definitely an error in C++98. It's probably meant to
// be forbidden in C++0x, too, but the specification is just
// poorly written.
//
// The problem is with declarations like the following:
// template <T> friend A<T>::foo;
// where deciding whether a class C is a friend or not now hinges
// on whether there exists an instantiation of A that causes
// 'foo' to equal C. There are restrictions on class-heads
// (which we declare (by fiat) elaborated friend declarations to
// be) that makes this tractable.
//
// FIXME: handle "template <> friend class A<T>;", which
// is possibly well-formed? Who even knows?
if (TempParams.size() && !T->isElaboratedTypeSpecifier()) {
Diag(Loc, diag::err_tagless_friend_type_template)
<< DS.getSourceRange();
return nullptr;
}
// C++98 [class.friend]p1: A friend of a class is a function
// or class that is not a member of the class . . .
// This is fixed in DR77, which just barely didn't make the C++03
// deadline. It's also a very silly restriction that seriously
// affects inner classes and which nobody else seems to implement;
// thus we never diagnose it, not even in -pedantic.
//
// But note that we could warn about it: it's always useless to
// friend one of your own members (it's not, however, worthless to
// friend a member of an arbitrary specialization of your template).
Decl *D;
if (!TempParams.empty())
D = FriendTemplateDecl::Create(Context, CurContext, Loc,
TempParams,
TSI,
DS.getFriendSpecLoc());
else
D = CheckFriendTypeDecl(Loc, DS.getFriendSpecLoc(), TSI);
if (!D)
return nullptr;
D->setAccess(AS_public);
CurContext->addDecl(D);
return D;
}
NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
MultiTemplateParamsArg TemplateParams) {
const DeclSpec &DS = D.getDeclSpec();
assert(DS.isFriendSpecified());
assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
SourceLocation Loc = D.getIdentifierLoc();
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
// C++ [class.friend]p1
// A friend of a class is a function or class....
// Note that this sees through typedefs, which is intended.
// It *doesn't* see through dependent types, which is correct
// according to [temp.arg.type]p3:
// If a declaration acquires a function type through a
// type dependent on a template-parameter and this causes
// a declaration that does not use the syntactic form of a
// function declarator to have a function type, the program
// is ill-formed.
if (!TInfo->getType()->isFunctionType()) {
Diag(Loc, diag::err_unexpected_friend);
// It might be worthwhile to try to recover by creating an
// appropriate declaration.
return nullptr;
}
// C++ [namespace.memdef]p3
// - If a friend declaration in a non-local class first declares a
// class or function, the friend class or function is a member
// of the innermost enclosing namespace.
// - The name of the friend is not found by simple name lookup
// until a matching declaration is provided in that namespace
// scope (either before or after the class declaration granting
// friendship).
// - If a friend function is called, its name may be found by the
// name lookup that considers functions from namespaces and
// classes associated with the types of the function arguments.
// - When looking for a prior declaration of a class or a function
// declared as a friend, scopes outside the innermost enclosing
// namespace scope are not considered.
CXXScopeSpec &SS = D.getCXXScopeSpec();
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
assert(NameInfo.getName());
// Check for unexpanded parameter packs.
if (DiagnoseUnexpandedParameterPack(Loc, TInfo, UPPC_FriendDeclaration) ||
DiagnoseUnexpandedParameterPack(NameInfo, UPPC_FriendDeclaration) ||
DiagnoseUnexpandedParameterPack(SS, UPPC_FriendDeclaration))
return nullptr;
// The context we found the declaration in, or in which we should
// create the declaration.
DeclContext *DC;
Scope *DCScope = S;
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
ForExternalRedeclaration);
// There are five cases here.
// - There's no scope specifier and we're in a local class. Only look
// for functions declared in the immediately-enclosing block scope.
// We recover from invalid scope qualifiers as if they just weren't there.
FunctionDecl *FunctionContainingLocalClass = nullptr;
if ((SS.isInvalid() || !SS.isSet()) &&
(FunctionContainingLocalClass =
cast<CXXRecordDecl>(CurContext)->isLocalClass())) {
// C++11 [class.friend]p11:
// If a friend declaration appears in a local class and the name
// specified is an unqualified name, a prior declaration is
// looked up without considering scopes that are outside the
// innermost enclosing non-class scope. For a friend function
// declaration, if there is no prior declaration, the program is
// ill-formed.
// Find the innermost enclosing non-class scope. This is the block
// scope containing the local class definition (or for a nested class,
// the outer local class).
DCScope = S->getFnParent();
// Look up the function name in the scope.
Previous.clear(LookupLocalFriendName);
LookupName(Previous, S, /*AllowBuiltinCreation*/false);
if (!Previous.empty()) {
// All possible previous declarations must have the same context:
// either they were declared at block scope or they are members of
// one of the enclosing local classes.
DC = Previous.getRepresentativeDecl()->getDeclContext();
} else {
// This is ill-formed, but provide the context that we would have
// declared the function in, if we were permitted to, for error recovery.
DC = FunctionContainingLocalClass;
}
adjustContextForLocalExternDecl(DC);
// C++ [class.friend]p6:
// A function can be defined in a friend declaration of a class if and
// only if the class is a non-local class (9.8), the function name is
// unqualified, and the function has namespace scope.
if (D.isFunctionDefinition()) {
Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class);
}
// - There's no scope specifier, in which case we just go to the
// appropriate scope and look for a function or function template
// there as appropriate.
} else if (SS.isInvalid() || !SS.isSet()) {
// C++11 [namespace.memdef]p3:
// If the name in a friend declaration is neither qualified nor
// a template-id and the declaration is a function or an
// elaborated-type-specifier, the lookup to determine whether
// the entity has been previously declared shall not consider
// any scopes outside the innermost enclosing namespace.
bool isTemplateId =
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId;
// Find the appropriate context according to the above.
DC = CurContext;
// Skip class contexts. If someone can cite chapter and verse
// for this behavior, that would be nice --- it's what GCC and
// EDG do, and it seems like a reasonable intent, but the spec
// really only says that checks for unqualified existing
// declarations should stop at the nearest enclosing namespace,
// not that they should only consider the nearest enclosing
// namespace.
while (DC->isRecord())
DC = DC->getParent();
DeclContext *LookupDC = DC;
while (LookupDC->isTransparentContext())
LookupDC = LookupDC->getParent();
while (true) {
LookupQualifiedName(Previous, LookupDC);
if (!Previous.empty()) {
DC = LookupDC;
break;
}
if (isTemplateId) {
if (isa<TranslationUnitDecl>(LookupDC)) break;
} else {
if (LookupDC->isFileContext()) break;
}
LookupDC = LookupDC->getParent();
}
DCScope = getScopeForDeclContext(S, DC);
// - There's a non-dependent scope specifier, in which case we
// compute it and do a previous lookup there for a function
// or function template.
} else if (!SS.getScopeRep()->isDependent()) {
DC = computeDeclContext(SS);
if (!DC) return nullptr;
if (RequireCompleteDeclContext(SS, DC)) return nullptr;
LookupQualifiedName(Previous, DC);
// C++ [class.friend]p1: A friend of a class is a function or
// class that is not a member of the class . . .
if (DC->Equals(CurContext))
Diag(DS.getFriendSpecLoc(),
getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_friend_is_member :
diag::err_friend_is_member);
if (D.isFunctionDefinition()) {
// C++ [class.friend]p6:
// A function can be defined in a friend declaration of a class if and
// only if the class is a non-local class (9.8), the function name is
// unqualified, and the function has namespace scope.
//
// FIXME: We should only do this if the scope specifier names the
// innermost enclosing namespace; otherwise the fixit changes the
// meaning of the code.
SemaDiagnosticBuilder DB
= Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def);
DB << SS.getScopeRep();
if (DC->isFileContext())
DB << FixItHint::CreateRemoval(SS.getRange());
SS.clear();
}
// - There's a scope specifier that does not match any template
// parameter lists, in which case we use some arbitrary context,
// create a method or method template, and wait for instantiation.
// - There's a scope specifier that does match some template
// parameter lists, which we don't handle right now.
} else {
if (D.isFunctionDefinition()) {
// C++ [class.friend]p6:
// A function can be defined in a friend declaration of a class if and
// only if the class is a non-local class (9.8), the function name is
// unqualified, and the function has namespace scope.
Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def)
<< SS.getScopeRep();
}
DC = CurContext;
assert(isa<CXXRecordDecl>(DC) && "friend declaration not in class?");
}
if (!DC->isRecord()) {
int DiagArg = -1;
switch (D.getName().getKind()) {
case UnqualifiedIdKind::IK_ConstructorTemplateId:
case UnqualifiedIdKind::IK_ConstructorName:
DiagArg = 0;
break;
case UnqualifiedIdKind::IK_DestructorName:
DiagArg = 1;
break;
case UnqualifiedIdKind::IK_ConversionFunctionId:
DiagArg = 2;
break;
case UnqualifiedIdKind::IK_DeductionGuideName:
DiagArg = 3;
break;
case UnqualifiedIdKind::IK_Identifier:
case UnqualifiedIdKind::IK_ImplicitSelfParam:
case UnqualifiedIdKind::IK_LiteralOperatorId:
case UnqualifiedIdKind::IK_OperatorFunctionId:
case UnqualifiedIdKind::IK_TemplateId:
break;
}
// This implies that it has to be an operator or function.
if (DiagArg >= 0) {
Diag(Loc, diag::err_introducing_special_friend) << DiagArg;
return nullptr;
}
}
// FIXME: This is an egregious hack to cope with cases where the scope stack
// does not contain the declaration context, i.e., in an out-of-line
// definition of a class.
Scope FakeDCScope(S, Scope::DeclScope, Diags);
if (!DCScope) {
FakeDCScope.setEntity(DC);
DCScope = &FakeDCScope;
}
bool AddToScope = true;
NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous,
TemplateParams, AddToScope);
if (!ND) return nullptr;
assert(ND->getLexicalDeclContext() == CurContext);
// If we performed typo correction, we might have added a scope specifier
// and changed the decl context.
DC = ND->getDeclContext();
// Add the function declaration to the appropriate lookup tables,
// adjusting the redeclarations list as necessary. We don't
// want to do this yet if the friending class is dependent.
//
// Also update the scope-based lookup if the target context's
// lookup context is in lexical scope.
if (!CurContext->isDependentContext()) {
DC = DC->getRedeclContext();
DC->makeDeclVisibleInContext(ND);
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false);
}
FriendDecl *FrD = FriendDecl::Create(Context, CurContext,
D.getIdentifierLoc(), ND,
DS.getFriendSpecLoc());
FrD->setAccess(AS_public);
CurContext->addDecl(FrD);
if (ND->isInvalidDecl()) {
FrD->setInvalidDecl();
} else {
if (DC->isRecord()) CheckFriendAccess(ND);
FunctionDecl *FD;
if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
FD = FTD->getTemplatedDecl();
else
FD = cast<FunctionDecl>(ND);
// C++11 [dcl.fct.default]p4: If a friend declaration specifies a
// default argument expression, that declaration shall be a definition
// and shall be the only declaration of the function or function
// template in the translation unit.
if (functionDeclHasDefaultArgument(FD)) {
// We can't look at FD->getPreviousDecl() because it may not have been set
// if we're in a dependent context. If the function is known to be a
// redeclaration, we will have narrowed Previous down to the right decl.
if (D.isRedeclaration()) {
Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_redeclared);
Diag(Previous.getRepresentativeDecl()->getLocation(),
diag::note_previous_declaration);
} else if (!D.isFunctionDefinition())
Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_must_be_def);
}
// Mark templated-scope function declarations as unsupported.
if (FD->getNumTemplateParameterLists() && SS.isValid()) {
Diag(FD->getLocation(), diag::warn_template_qualified_friend_unsupported)
<< SS.getScopeRep() << SS.getRange()
<< cast<CXXRecordDecl>(CurContext);
FrD->setUnsupportedFriend(true);
}
}
return ND;
}
void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
AdjustDeclIfTemplate(Dcl);
FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(Dcl);
if (!Fn) {
Diag(DelLoc, diag::err_deleted_non_function);
return;
}
// Deleted function does not have a body.
Fn->setWillHaveBody(false);
if (const FunctionDecl *Prev = Fn->getPreviousDecl()) {
// Don't consider the implicit declaration we generate for explicit
// specializations. FIXME: Do not generate these implicit declarations.
if ((Prev->getTemplateSpecializationKind() != TSK_ExplicitSpecialization ||
Prev->getPreviousDecl()) &&
!Prev->isDefined()) {
Diag(DelLoc, diag::err_deleted_decl_not_first);
Diag(Prev->getLocation().isInvalid() ? DelLoc : Prev->getLocation(),
Prev->isImplicit() ? diag::note_previous_implicit_declaration
: diag::note_previous_declaration);
}
// If the declaration wasn't the first, we delete the function anyway for
// recovery.
Fn = Fn->getCanonicalDecl();
}
// dllimport/dllexport cannot be deleted.
if (const InheritableAttr *DLLAttr = getDLLAttr(Fn)) {
Diag(Fn->getLocation(), diag::err_attribute_dll_deleted) << DLLAttr;
Fn->setInvalidDecl();
}
if (Fn->isDeleted())
return;
// See if we're deleting a function which is already known to override a
// non-deleted virtual function.
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) {
bool IssuedDiagnostic = false;
for (const CXXMethodDecl *O : MD->overridden_methods()) {
if (!(*MD->begin_overridden_methods())->isDeleted()) {
if (!IssuedDiagnostic) {
Diag(DelLoc, diag::err_deleted_override) << MD->getDeclName();
IssuedDiagnostic = true;
}
Diag(O->getLocation(), diag::note_overridden_virtual_function);
}
}
// If this function was implicitly deleted because it was defaulted,
// explain why it was deleted.
if (IssuedDiagnostic && MD->isDefaulted())
ShouldDeleteSpecialMember(MD, getSpecialMember(MD), nullptr,
/*Diagnose*/true);
}
// C++11 [basic.start.main]p3:
// A program that defines main as deleted [...] is ill-formed.
if (Fn->isMain())
Diag(DelLoc, diag::err_deleted_main);
// C++11 [dcl.fct.def.delete]p4:
// A deleted function is implicitly inline.
Fn->setImplicitlyInline();
Fn->setDeletedAsWritten();
}
void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Dcl);
if (MD) {
if (MD->getParent()->isDependentType()) {
MD->setDefaulted();
MD->setExplicitlyDefaulted();
return;
}
CXXSpecialMember Member = getSpecialMember(MD);
if (Member == CXXInvalid) {
if (!MD->isInvalidDecl())
Diag(DefaultLoc, diag::err_default_special_members);
return;
}
MD->setDefaulted();
MD->setExplicitlyDefaulted();
// Unset that we will have a body for this function. We might not,
// if it turns out to be trivial, and we don't need this marking now
// that we've marked it as defaulted.
MD->setWillHaveBody(false);
// If this definition appears within the record, do the checking when
// the record is complete.
const FunctionDecl *Primary = MD;
if (const FunctionDecl *Pattern = MD->getTemplateInstantiationPattern())
// Ask the template instantiation pattern that actually had the
// '= default' on it.
Primary = Pattern;
// If the method was defaulted on its first declaration, we will have
// already performed the checking in CheckCompletedCXXClass. Such a
// declaration doesn't trigger an implicit definition.
if (Primary->getCanonicalDecl()->isDefaulted())
return;
CheckExplicitlyDefaultedSpecialMember(MD);
if (!MD->isInvalidDecl())
DefineImplicitSpecialMember(*this, MD, DefaultLoc);
} else {
Diag(DefaultLoc, diag::err_default_special_members);
}
}
static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
for (Stmt *SubStmt : S->children()) {
if (!SubStmt)
continue;
if (isa<ReturnStmt>(SubStmt))
Self.Diag(SubStmt->getBeginLoc(),
diag::err_return_in_constructor_handler);
if (!isa<Expr>(SubStmt))
SearchForReturnInStmt(Self, SubStmt);
}
}
void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) {
for (unsigned I = 0, E = TryBlock->getNumHandlers(); I != E; ++I) {
CXXCatchStmt *Handler = TryBlock->getHandler(I);
SearchForReturnInStmt(*this, Handler);
}
}
bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
const CXXMethodDecl *Old) {
const auto *NewFT = New->getType()->getAs<FunctionProtoType>();
const auto *OldFT = Old->getType()->getAs<FunctionProtoType>();
if (OldFT->hasExtParameterInfos()) {
for (unsigned I = 0, E = OldFT->getNumParams(); I != E; ++I)
// A parameter of the overriding method should be annotated with noescape
// if the corresponding parameter of the overridden method is annotated.
if (OldFT->getExtParameterInfo(I).isNoEscape() &&
!NewFT->getExtParameterInfo(I).isNoEscape()) {
Diag(New->getParamDecl(I)->getLocation(),
diag::warn_overriding_method_missing_noescape);
Diag(Old->getParamDecl(I)->getLocation(),
diag::note_overridden_marked_noescape);
}
}
// Virtual overrides must have the same code_seg.
const auto *OldCSA = Old->getAttr<CodeSegAttr>();
const auto *NewCSA = New->getAttr<CodeSegAttr>();
if ((NewCSA || OldCSA) &&
(!OldCSA || !NewCSA || NewCSA->getName() != OldCSA->getName())) {
Diag(New->getLocation(), diag::err_mismatched_code_seg_override);
Diag(Old->getLocation(), diag::note_previous_declaration);
return true;
}
CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv();
// If the calling conventions match, everything is fine
if (NewCC == OldCC)
return false;
// If the calling conventions mismatch because the new function is static,
// suppress the calling convention mismatch error; the error about static
// function override (err_static_overrides_virtual from
// Sema::CheckFunctionDeclaration) is more clear.
if (New->getStorageClass() == SC_Static)
return false;
Diag(New->getLocation(),
diag::err_conflicting_overriding_cc_attributes)
<< New->getDeclName() << New->getType() << Old->getType();
Diag(Old->getLocation(), diag::note_overridden_virtual_function);
return true;
}
bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
const CXXMethodDecl *Old) {
QualType NewTy = New->getType()->getAs<FunctionType>()->getReturnType();
QualType OldTy = Old->getType()->getAs<FunctionType>()->getReturnType();
if (Context.hasSameType(NewTy, OldTy) ||
NewTy->isDependentType() || OldTy->isDependentType())
return false;
// Check if the return types are covariant
QualType NewClassTy, OldClassTy;
/// Both types must be pointers or references to classes.
if (const PointerType *NewPT = NewTy->getAs<PointerType>()) {
if (const PointerType *OldPT = OldTy->getAs<PointerType>()) {
NewClassTy = NewPT->getPointeeType();
OldClassTy = OldPT->getPointeeType();
}
} else if (const ReferenceType *NewRT = NewTy->getAs<ReferenceType>()) {
if (const ReferenceType *OldRT = OldTy->getAs<ReferenceType>()) {
if (NewRT->getTypeClass() == OldRT->getTypeClass()) {
NewClassTy = NewRT->getPointeeType();
OldClassTy = OldRT->getPointeeType();
}
}
}
// The return types aren't either both pointers or references to a class type.
if (NewClassTy.isNull()) {
Diag(New->getLocation(),
diag::err_different_return_type_for_overriding_virtual_function)
<< New->getDeclName() << NewTy << OldTy
<< New->getReturnTypeSourceRange();
Diag(Old->getLocation(), diag::note_overridden_virtual_function)
<< Old->getReturnTypeSourceRange();
return true;
}
if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) {
// C++14 [class.virtual]p8:
// If the class type in the covariant return type of D::f differs from
// that of B::f, the class type in the return type of D::f shall be
// complete at the point of declaration of D::f or shall be the class
// type D.
if (const RecordType *RT = NewClassTy->getAs<RecordType>()) {
if (!RT->isBeingDefined() &&
RequireCompleteType(New->getLocation(), NewClassTy,
diag::err_covariant_return_incomplete,
New->getDeclName()))
return true;
}
// Check if the new class derives from the old class.
if (!IsDerivedFrom(New->getLocation(), NewClassTy, OldClassTy)) {
Diag(New->getLocation(), diag::err_covariant_return_not_derived)
<< New->getDeclName() << NewTy << OldTy
<< New->getReturnTypeSourceRange();
Diag(Old->getLocation(), diag::note_overridden_virtual_function)
<< Old->getReturnTypeSourceRange();
return true;
}
// Check if we the conversion from derived to base is valid.
if (CheckDerivedToBaseConversion(
NewClassTy, OldClassTy,
diag::err_covariant_return_inaccessible_base,
diag::err_covariant_return_ambiguous_derived_to_base_conv,
New->getLocation(), New->getReturnTypeSourceRange(),
New->getDeclName(), nullptr)) {
// FIXME: this note won't trigger for delayed access control
// diagnostics, and it's impossible to get an undelayed error
// here from access control during the original parse because
// the ParsingDeclSpec/ParsingDeclarator are still in scope.
Diag(Old->getLocation(), diag::note_overridden_virtual_function)
<< Old->getReturnTypeSourceRange();
return true;
}
}
// The qualifiers of the return types must be the same.
if (NewTy.getLocalCVRQualifiers() != OldTy.getLocalCVRQualifiers()) {
Diag(New->getLocation(),
diag::err_covariant_return_type_different_qualifications)
<< New->getDeclName() << NewTy << OldTy
<< New->getReturnTypeSourceRange();
Diag(Old->getLocation(), diag::note_overridden_virtual_function)
<< Old->getReturnTypeSourceRange();
return true;
}
// The new class type must have the same or less qualifiers as the old type.
if (NewClassTy.isMoreQualifiedThan(OldClassTy)) {
Diag(New->getLocation(),
diag::err_covariant_return_type_class_type_more_qualified)
<< New->getDeclName() << NewTy << OldTy
<< New->getReturnTypeSourceRange();
Diag(Old->getLocation(), diag::note_overridden_virtual_function)
<< Old->getReturnTypeSourceRange();
return true;
}
return false;
}
/// Mark the given method pure.
///
/// \param Method the method to be marked pure.
///
/// \param InitRange the source range that covers the "0" initializer.
bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) {
SourceLocation EndLoc = InitRange.getEnd();
if (EndLoc.isValid())
Method->setRangeEnd(EndLoc);
if (Method->isVirtual() || Method->getParent()->isDependentContext()) {
Method->setPure();
return false;
}
if (!Method->isInvalidDecl())
Diag(Method->getLocation(), diag::err_non_virtual_pure)
<< Method->getDeclName() << InitRange;
return true;
}
void Sema::ActOnPureSpecifier(Decl *D, SourceLocation ZeroLoc) {
if (D->getFriendObjectKind())
Diag(D->getLocation(), diag::err_pure_friend);
else if (auto *M = dyn_cast<CXXMethodDecl>(D))
CheckPureMethod(M, ZeroLoc);
else
Diag(D->getLocation(), diag::err_illegal_initializer);
}
/// Determine whether the given declaration is a global variable or
/// static data member.
static bool isNonlocalVariable(const Decl *D) {
if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
return Var->hasGlobalStorage();
return false;
}
/// Invoked when we are about to parse an initializer for the declaration
/// 'Dcl'.
///
/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
/// static data member of class X, names should be looked up in the scope of
/// class X. If the declaration had a scope specifier, a scope will have
/// been created and passed in for this purpose. Otherwise, S will be null.
void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
// If there is no declaration, there was an error parsing it.
if (!D || D->isInvalidDecl())
return;
// We will always have a nested name specifier here, but this declaration
// might not be out of line if the specifier names the current namespace:
// extern int n;
// int ::n = 0;
if (S && D->isOutOfLine())
EnterDeclaratorContext(S, D->getDeclContext());
// If we are parsing the initializer for a static data member, push a
// new expression evaluation context that is associated with this static
// data member.
if (isNonlocalVariable(D))
PushExpressionEvaluationContext(
ExpressionEvaluationContext::PotentiallyEvaluated, D);
}
/// Invoked after we are finished parsing an initializer for the declaration D.
void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) {
// If there is no declaration, there was an error parsing it.
if (!D || D->isInvalidDecl())
return;
if (isNonlocalVariable(D))
PopExpressionEvaluationContext();
if (S && D->isOutOfLine())
ExitDeclaratorContext(S);
}
/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
/// C++ if/switch/while/for statement.
/// e.g: "if (int x = f()) {...}"
DeclResult Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
// C++ 6.4p2:
// The declarator shall not specify a function or an array.
// The type-specifier-seq shall not contain typedef and shall not declare a
// new class or enumeration.
assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
"Parser allowed 'typedef' as storage class of condition decl.");
Decl *Dcl = ActOnDeclarator(S, D);
if (!Dcl)
return true;
if (isa<FunctionDecl>(Dcl)) { // The declarator shall not specify a function.
Diag(Dcl->getLocation(), diag::err_invalid_use_of_function_type)
<< D.getSourceRange();
return true;
}
return Dcl;
}
void Sema::LoadExternalVTableUses() {
if (!ExternalSource)
return;
SmallVector<ExternalVTableUse, 4> VTables;
ExternalSource->ReadUsedVTables(VTables);
SmallVector<VTableUse, 4> NewUses;
for (unsigned I = 0, N = VTables.size(); I != N; ++I) {
llvm::DenseMap<CXXRecordDecl *, bool>::iterator Pos
= VTablesUsed.find(VTables[I].Record);
// Even if a definition wasn't required before, it may be required now.
if (Pos != VTablesUsed.end()) {
if (!Pos->second && VTables[I].DefinitionRequired)
Pos->second = true;
continue;
}
VTablesUsed[VTables[I].Record] = VTables[I].DefinitionRequired;
NewUses.push_back(VTableUse(VTables[I].Record, VTables[I].Location));
}
VTableUses.insert(VTableUses.begin(), NewUses.begin(), NewUses.end());
}
void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
bool DefinitionRequired) {
// Ignore any vtable uses in unevaluated operands or for classes that do
// not have a vtable.
if (!Class->isDynamicClass() || Class->isDependentContext() ||
CurContext->isDependentContext() || isUnevaluatedContext())
return;
// Do not mark as used if compiling for the device outside of the target
// region.
if (LangOpts.OpenMP && LangOpts.OpenMPIsDevice &&
!isInOpenMPDeclareTargetContext() &&
!isInOpenMPTargetExecutionDirective()) {
if (!DefinitionRequired)
MarkVirtualMembersReferenced(Loc, Class);
return;
}
// Try to insert this class into the map.
LoadExternalVTableUses();
Class = Class->getCanonicalDecl();
std::pair<llvm::DenseMap<CXXRecordDecl *, bool>::iterator, bool>
Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired));
if (!Pos.second) {
// If we already had an entry, check to see if we are promoting this vtable
// to require a definition. If so, we need to reappend to the VTableUses
// list, since we may have already processed the first entry.
if (DefinitionRequired && !Pos.first->second) {
Pos.first->second = true;
} else {
// Otherwise, we can early exit.
return;
}
} else {
// The Microsoft ABI requires that we perform the destructor body
// checks (i.e. operator delete() lookup) when the vtable is marked used, as
// the deleting destructor is emitted with the vtable, not with the
// destructor definition as in the Itanium ABI.
if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
CXXDestructorDecl *DD = Class->getDestructor();
if (DD && DD->isVirtual() && !DD->isDeleted()) {
if (Class->hasUserDeclaredDestructor() && !DD->isDefined()) {
// If this is an out-of-line declaration, marking it referenced will
// not do anything. Manually call CheckDestructor to look up operator
// delete().
ContextRAII SavedContext(*this, DD);
CheckDestructor(DD);
} else {
MarkFunctionReferenced(Loc, Class->getDestructor());
}
}
}
}
// Local classes need to have their virtual members marked
// immediately. For all other classes, we mark their virtual members
// at the end of the translation unit.
if (Class->isLocalClass())
MarkVirtualMembersReferenced(Loc, Class);
else
VTableUses.push_back(std::make_pair(Class, Loc));
}
bool Sema::DefineUsedVTables() {
LoadExternalVTableUses();
if (VTableUses.empty())
return false;
// Note: The VTableUses vector could grow as a result of marking
// the members of a class as "used", so we check the size each
// time through the loop and prefer indices (which are stable) to
// iterators (which are not).
bool DefinedAnything = false;
for (unsigned I = 0; I != VTableUses.size(); ++I) {
CXXRecordDecl *Class = VTableUses[I].first->getDefinition();
if (!Class)
continue;
TemplateSpecializationKind ClassTSK =
Class->getTemplateSpecializationKind();
SourceLocation Loc = VTableUses[I].second;
bool DefineVTable = true;
// If this class has a key function, but that key function is
// defined in another translation unit, we don't need to emit the
// vtable even though we're using it.
const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(Class);
if (KeyFunction && !KeyFunction->hasBody()) {
// The key function is in another translation unit.
DefineVTable = false;
TemplateSpecializationKind TSK =
KeyFunction->getTemplateSpecializationKind();
assert(TSK != TSK_ExplicitInstantiationDefinition &&
TSK != TSK_ImplicitInstantiation &&
"Instantiations don't have key functions");
(void)TSK;
} else if (!KeyFunction) {
// If we have a class with no key function that is the subject
// of an explicit instantiation declaration, suppress the
// vtable; it will live with the explicit instantiation
// definition.
bool IsExplicitInstantiationDeclaration =
ClassTSK == TSK_ExplicitInstantiationDeclaration;
for (auto R : Class->redecls()) {
TemplateSpecializationKind TSK
= cast<CXXRecordDecl>(R)->getTemplateSpecializationKind();
if (TSK == TSK_ExplicitInstantiationDeclaration)
IsExplicitInstantiationDeclaration = true;
else if (TSK == TSK_ExplicitInstantiationDefinition) {
IsExplicitInstantiationDeclaration = false;
break;
}
}
if (IsExplicitInstantiationDeclaration)
DefineVTable = false;
}
// The exception specifications for all virtual members may be needed even
// if we are not providing an authoritative form of the vtable in this TU.
// We may choose to emit it available_externally anyway.
if (!DefineVTable) {
MarkVirtualMemberExceptionSpecsNeeded(Loc, Class);
continue;
}
// Mark all of the virtual members of this class as referenced, so
// that we can build a vtable. Then, tell the AST consumer that a
// vtable for this class is required.
DefinedAnything = true;
MarkVirtualMembersReferenced(Loc, Class);
CXXRecordDecl *Canonical = Class->getCanonicalDecl();
if (VTablesUsed[Canonical])
Consumer.HandleVTable(Class);
// Warn if we're emitting a weak vtable. The vtable will be weak if there is
// no key function or the key function is inlined. Don't warn in C++ ABIs
// that lack key functions, since the user won't be able to make one.
if (Context.getTargetInfo().getCXXABI().hasKeyFunctions() &&
Class->isExternallyVisible() && ClassTSK != TSK_ImplicitInstantiation) {
const FunctionDecl *KeyFunctionDef = nullptr;
if (!KeyFunction || (KeyFunction->hasBody(KeyFunctionDef) &&
KeyFunctionDef->isInlined())) {
Diag(Class->getLocation(),
ClassTSK == TSK_ExplicitInstantiationDefinition
? diag::warn_weak_template_vtable
: diag::warn_weak_vtable)
<< Class;
}
}
}
VTableUses.clear();
return DefinedAnything;
}
void Sema::MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
const CXXRecordDecl *RD) {
for (const auto *I : RD->methods())
if (I->isVirtual() && !I->isPure())
ResolveExceptionSpec(Loc, I->getType()->castAs<FunctionProtoType>());
}
void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
const CXXRecordDecl *RD) {
// Mark all functions which will appear in RD's vtable as used.
CXXFinalOverriderMap FinalOverriders;
RD->getFinalOverriders(FinalOverriders);
for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(),
E = FinalOverriders.end();
I != E; ++I) {
for (OverridingMethods::const_iterator OI = I->second.begin(),
OE = I->second.end();
OI != OE; ++OI) {
assert(OI->second.size() > 0 && "no final overrider");
CXXMethodDecl *Overrider = OI->second.front().Method;
// C++ [basic.def.odr]p2:
// [...] A virtual member function is used if it is not pure. [...]
if (!Overrider->isPure())
MarkFunctionReferenced(Loc, Overrider);
}
}
// Only classes that have virtual bases need a VTT.
if (RD->getNumVBases() == 0)
return;
for (const auto &I : RD->bases()) {
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
if (Base->getNumVBases() == 0)
continue;
MarkVirtualMembersReferenced(Loc, Base);
}
}
/// SetIvarInitializers - This routine builds initialization ASTs for the
/// Objective-C implementation whose ivars need be initialized.
void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
if (!getLangOpts().CPlusPlus)
return;
if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) {
SmallVector<ObjCIvarDecl*, 8> ivars;
CollectIvarsToConstructOrDestruct(OID, ivars);
if (ivars.empty())
return;
SmallVector<CXXCtorInitializer*, 32> AllToInit;
for (unsigned i = 0; i < ivars.size(); i++) {
FieldDecl *Field = ivars[i];
if (Field->isInvalidDecl())
continue;
CXXCtorInitializer *Member;
InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field);
InitializationKind InitKind =
InitializationKind::CreateDefault(ObjCImplementation->getLocation());
InitializationSequence InitSeq(*this, InitEntity, InitKind, None);
ExprResult MemberInit =
InitSeq.Perform(*this, InitEntity, InitKind, None);
MemberInit = MaybeCreateExprWithCleanups(MemberInit);
// Note, MemberInit could actually come back empty if no initialization
// is required (e.g., because it would call a trivial default constructor)
if (!MemberInit.get() || MemberInit.isInvalid())
continue;
Member =
new (Context) CXXCtorInitializer(Context, Field, SourceLocation(),
SourceLocation(),
MemberInit.getAs<Expr>(),
SourceLocation());
AllToInit.push_back(Member);
// Be sure that the destructor is accessible and is marked as referenced.
if (const RecordType *RecordTy =
Context.getBaseElementType(Field->getType())
->getAs<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) {
MarkFunctionReferenced(Field->getLocation(), Destructor);
CheckDestructorAccess(Field->getLocation(), Destructor,
PDiag(diag::err_access_dtor_ivar)
<< Context.getBaseElementType(Field->getType()));
}
}
}
ObjCImplementation->setIvarInitializers(Context,
AllToInit.data(), AllToInit.size());
}
}
static
void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Valid,
llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Invalid,
llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Current,
Sema &S) {
if (Ctor->isInvalidDecl())
return;
CXXConstructorDecl *Target = Ctor->getTargetConstructor();
// Target may not be determinable yet, for instance if this is a dependent
// call in an uninstantiated template.
if (Target) {
const FunctionDecl *FNTarget = nullptr;
(void)Target->hasBody(FNTarget);
Target = const_cast<CXXConstructorDecl*>(
cast_or_null<CXXConstructorDecl>(FNTarget));
}
CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(),
// Avoid dereferencing a null pointer here.
*TCanonical = Target? Target->getCanonicalDecl() : nullptr;
if (!Current.insert(Canonical).second)
return;
// We know that beyond here, we aren't chaining into a cycle.
if (!Target || !Target->isDelegatingConstructor() ||
Target->isInvalidDecl() || Valid.count(TCanonical)) {
Valid.insert(Current.begin(), Current.end());
Current.clear();
// We've hit a cycle.
} else if (TCanonical == Canonical || Invalid.count(TCanonical) ||
Current.count(TCanonical)) {
// If we haven't diagnosed this cycle yet, do so now.
if (!Invalid.count(TCanonical)) {
S.Diag((*Ctor->init_begin())->getSourceLocation(),
diag::warn_delegating_ctor_cycle)
<< Ctor;
// Don't add a note for a function delegating directly to itself.
if (TCanonical != Canonical)
S.Diag(Target->getLocation(), diag::note_it_delegates_to);
CXXConstructorDecl *C = Target;
while (C->getCanonicalDecl() != Canonical) {
const FunctionDecl *FNTarget = nullptr;
(void)C->getTargetConstructor()->hasBody(FNTarget);
assert(FNTarget && "Ctor cycle through bodiless function");
C = const_cast<CXXConstructorDecl*>(
cast<CXXConstructorDecl>(FNTarget));
S.Diag(C->getLocation(), diag::note_which_delegates_to);
}
}
Invalid.insert(Current.begin(), Current.end());
Current.clear();
} else {
DelegatingCycleHelper(Target, Valid, Invalid, Current, S);
}
}
void Sema::CheckDelegatingCtorCycles() {
llvm::SmallPtrSet<CXXConstructorDecl*, 4> Valid, Invalid, Current;
for (DelegatingCtorDeclsType::iterator
I = DelegatingCtorDecls.begin(ExternalSource),
E = DelegatingCtorDecls.end();
I != E; ++I)
DelegatingCycleHelper(*I, Valid, Invalid, Current, *this);
for (auto CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI)
(*CI)->setInvalidDecl();
}
namespace {
/// AST visitor that finds references to the 'this' expression.
class FindCXXThisExpr : public RecursiveASTVisitor<FindCXXThisExpr> {
Sema &S;
public:
explicit FindCXXThisExpr(Sema &S) : S(S) { }
bool VisitCXXThisExpr(CXXThisExpr *E) {
S.Diag(E->getLocation(), diag::err_this_static_member_func)
<< E->isImplicit();
return false;
}
};
}
bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) {
TypeSourceInfo *TSInfo = Method->getTypeSourceInfo();
if (!TSInfo)
return false;
TypeLoc TL = TSInfo->getTypeLoc();
FunctionProtoTypeLoc ProtoTL = TL.getAs<FunctionProtoTypeLoc>();
if (!ProtoTL)
return false;
// C++11 [expr.prim.general]p3:
// [The expression this] shall not appear before the optional
// cv-qualifier-seq and it shall not appear within the declaration of a
// static member function (although its type and value category are defined
// within a static member function as they are within a non-static member
// function). [ Note: this is because declaration matching does not occur
// until the complete declarator is known. - end note ]
const FunctionProtoType *Proto = ProtoTL.getTypePtr();
FindCXXThisExpr Finder(*this);
// If the return type came after the cv-qualifier-seq, check it now.
if (Proto->hasTrailingReturn() &&
!Finder.TraverseTypeLoc(ProtoTL.getReturnLoc()))
return true;
// Check the exception specification.
if (checkThisInStaticMemberFunctionExceptionSpec(Method))
return true;
return checkThisInStaticMemberFunctionAttributes(Method);
}
bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) {
TypeSourceInfo *TSInfo = Method->getTypeSourceInfo();
if (!TSInfo)
return false;
TypeLoc TL = TSInfo->getTypeLoc();
FunctionProtoTypeLoc ProtoTL = TL.getAs<FunctionProtoTypeLoc>();
if (!ProtoTL)
return false;
const FunctionProtoType *Proto = ProtoTL.getTypePtr();
FindCXXThisExpr Finder(*this);
switch (Proto->getExceptionSpecType()) {
case EST_Unparsed:
case EST_Uninstantiated:
case EST_Unevaluated:
case EST_BasicNoexcept:
case EST_DynamicNone:
case EST_MSAny:
case EST_None:
break;
case EST_DependentNoexcept:
case EST_NoexceptFalse:
case EST_NoexceptTrue:
if (!Finder.TraverseStmt(Proto->getNoexceptExpr()))
return true;
LLVM_FALLTHROUGH;
case EST_Dynamic:
for (const auto &E : Proto->exceptions()) {
if (!Finder.TraverseType(E))
return true;
}
break;
}
return false;
}
bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
FindCXXThisExpr Finder(*this);
// Check attributes.
for (const auto *A : Method->attrs()) {
// FIXME: This should be emitted by tblgen.
Expr *Arg = nullptr;
ArrayRef<Expr *> Args;
if (const auto *G = dyn_cast<GuardedByAttr>(A))
Arg = G->getArg();
else if (const auto *G = dyn_cast<PtGuardedByAttr>(A))
Arg = G->getArg();
else if (const auto *AA = dyn_cast<AcquiredAfterAttr>(A))
Args = llvm::makeArrayRef(AA->args_begin(), AA->args_size());
else if (const auto *AB = dyn_cast<AcquiredBeforeAttr>(A))
Args = llvm::makeArrayRef(AB->args_begin(), AB->args_size());
else if (const auto *ETLF = dyn_cast<ExclusiveTrylockFunctionAttr>(A)) {
Arg = ETLF->getSuccessValue();
Args = llvm::makeArrayRef(ETLF->args_begin(), ETLF->args_size());
} else if (const auto *STLF = dyn_cast<SharedTrylockFunctionAttr>(A)) {
Arg = STLF->getSuccessValue();
Args = llvm::makeArrayRef(STLF->args_begin(), STLF->args_size());
} else if (const auto *LR = dyn_cast<LockReturnedAttr>(A))
Arg = LR->getArg();
else if (const auto *LE = dyn_cast<LocksExcludedAttr>(A))
Args = llvm::makeArrayRef(LE->args_begin(), LE->args_size());
else if (const auto *RC = dyn_cast<RequiresCapabilityAttr>(A))
Args = llvm::makeArrayRef(RC->args_begin(), RC->args_size());
else if (const auto *AC = dyn_cast<AcquireCapabilityAttr>(A))
Args = llvm::makeArrayRef(AC->args_begin(), AC->args_size());
else if (const auto *AC = dyn_cast<TryAcquireCapabilityAttr>(A))
Args = llvm::makeArrayRef(AC->args_begin(), AC->args_size());
else if (const auto *RC = dyn_cast<ReleaseCapabilityAttr>(A))
Args = llvm::makeArrayRef(RC->args_begin(), RC->args_size());
if (Arg && !Finder.TraverseStmt(Arg))
return true;
for (unsigned I = 0, N = Args.size(); I != N; ++I) {
if (!Finder.TraverseStmt(Args[I]))
return true;
}
}
return false;
}
void Sema::checkExceptionSpecification(
bool IsTopLevel, ExceptionSpecificationType EST,
ArrayRef<ParsedType> DynamicExceptions,
ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr,
SmallVectorImpl<QualType> &Exceptions,
FunctionProtoType::ExceptionSpecInfo &ESI) {
Exceptions.clear();
ESI.Type = EST;
if (EST == EST_Dynamic) {
Exceptions.reserve(DynamicExceptions.size());
for (unsigned ei = 0, ee = DynamicExceptions.size(); ei != ee; ++ei) {
// FIXME: Preserve type source info.
QualType ET = GetTypeFromParser(DynamicExceptions[ei]);
if (IsTopLevel) {
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
collectUnexpandedParameterPacks(ET, Unexpanded);
if (!Unexpanded.empty()) {
DiagnoseUnexpandedParameterPacks(
DynamicExceptionRanges[ei].getBegin(), UPPC_ExceptionType,
Unexpanded);
continue;
}
}
// Check that the type is valid for an exception spec, and
// drop it if not.
if (!CheckSpecifiedExceptionType(ET, DynamicExceptionRanges[ei]))
Exceptions.push_back(ET);
}
ESI.Exceptions = Exceptions;
return;
}
if (isComputedNoexcept(EST)) {
assert((NoexceptExpr->isTypeDependent() ||
NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
Context.BoolTy) &&
"Parser should have made sure that the expression is boolean");
if (IsTopLevel && DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
ESI.Type = EST_BasicNoexcept;
return;
}
ESI.NoexceptExpr = NoexceptExpr;
return;
}
}
void Sema::actOnDelayedExceptionSpecification(Decl *MethodD,
ExceptionSpecificationType EST,
SourceRange SpecificationRange,
ArrayRef<ParsedType> DynamicExceptions,
ArrayRef<SourceRange> DynamicExceptionRanges,
Expr *NoexceptExpr) {
if (!MethodD)
return;
// Dig out the method we're referring to.
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(MethodD))
MethodD = FunTmpl->getTemplatedDecl();
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(MethodD);
if (!Method)
return;
// Check the exception specification.
llvm::SmallVector<QualType, 4> Exceptions;
FunctionProtoType::ExceptionSpecInfo ESI;
checkExceptionSpecification(/*IsTopLevel*/true, EST, DynamicExceptions,
DynamicExceptionRanges, NoexceptExpr, Exceptions,
ESI);
// Update the exception specification on the function type.
Context.adjustExceptionSpec(Method, ESI, /*AsWritten*/true);
if (Method->isStatic())
checkThisInStaticMemberFunctionExceptionSpec(Method);
if (Method->isVirtual()) {
// Check overrides, which we previously had to delay.
for (const CXXMethodDecl *O : Method->overridden_methods())
CheckOverridingFunctionExceptionSpec(Method, O);
}
}
/// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class.
///
MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
SourceLocation DeclStart, Declarator &D,
Expr *BitWidth,
InClassInitStyle InitStyle,
AccessSpecifier AS,
const ParsedAttr &MSPropertyAttr) {
IdentifierInfo *II = D.getIdentifier();
if (!II) {
Diag(DeclStart, diag::err_anonymous_property);
return nullptr;
}
SourceLocation Loc = D.getIdentifierLoc();
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType T = TInfo->getType();
if (getLangOpts().CPlusPlus) {
CheckExtraCXXDefaultArguments(D);
if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
UPPC_DataMemberType)) {
D.setInvalidType();
T = Context.IntTy;
TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
}
}
DiagnoseFunctionSpecifiers(D.getDeclSpec());
if (D.getDeclSpec().isInlineSpecified())
Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function)
<< getLangOpts().CPlusPlus17;
if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec())
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
diag::err_invalid_thread)
<< DeclSpec::getSpecifierName(TSCS);
// Check to see if this name was declared as a member previously
NamedDecl *PrevDecl = nullptr;
LookupResult Previous(*this, II, Loc, LookupMemberName,
ForVisibleRedeclaration);
LookupName(Previous, S);
switch (Previous.getResultKind()) {
case LookupResult::Found:
case LookupResult::FoundUnresolvedValue:
PrevDecl = Previous.getAsSingle<NamedDecl>();
break;
case LookupResult::FoundOverloaded:
PrevDecl = Previous.getRepresentativeDecl();
break;
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
case LookupResult::Ambiguous:
break;
}
if (PrevDecl && PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
// Just pretend that we didn't see the previous declaration.
PrevDecl = nullptr;
}
if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
PrevDecl = nullptr;
SourceLocation TSSL = D.getBeginLoc();
MSPropertyDecl *NewPD =
MSPropertyDecl::Create(Context, Record, Loc, II, T, TInfo, TSSL,
MSPropertyAttr.getPropertyDataGetter(),
MSPropertyAttr.getPropertyDataSetter());
ProcessDeclAttributes(TUScope, NewPD, D);
NewPD->setAccess(AS);
if (NewPD->isInvalidDecl())
Record->setInvalidDecl();
if (D.getDeclSpec().isModulePrivateSpecified())
NewPD->setModulePrivate();
if (NewPD->isInvalidDecl() && PrevDecl) {
// Don't introduce NewFD into scope; there's already something
// with the same name in the same scope.
} else if (II) {
PushOnScopeChains(NewPD, S);
} else
Record->addDecl(NewPD);
return NewPD;
}
Index: vendor/clang/dist-release_80/lib/Sema/SemaExpr.cpp
===================================================================
--- vendor/clang/dist-release_80/lib/Sema/SemaExpr.cpp (revision 343795)
+++ vendor/clang/dist-release_80/lib/Sema/SemaExpr.cpp (revision 343796)
@@ -1,16864 +1,16851 @@
//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements semantic analysis for expressions.
//
//===----------------------------------------------------------------------===//
#include "TreeTransform.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/FixedPoint.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/AnalysisBasedWarnings.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Designator.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaFixItUtils.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "llvm/Support/ConvertUTF.h"
using namespace clang;
using namespace sema;
/// Determine whether the use of this declaration is valid, without
/// emitting diagnostics.
bool Sema::CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid) {
// See if this is an auto-typed variable whose initializer we are parsing.
if (ParsingInitForAutoVars.count(D))
return false;
// See if this is a deleted function.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isDeleted())
return false;
// If the function has a deduced return type, and we can't deduce it,
// then we can't use it either.
if (getLangOpts().CPlusPlus14 && FD->getReturnType()->isUndeducedType() &&
DeduceReturnType(FD, SourceLocation(), /*Diagnose*/ false))
return false;
// See if this is an aligned allocation/deallocation function that is
// unavailable.
if (TreatUnavailableAsInvalid &&
isUnavailableAlignedAllocationFunction(*FD))
return false;
}
// See if this function is unavailable.
if (TreatUnavailableAsInvalid && D->getAvailability() == AR_Unavailable &&
cast<Decl>(CurContext)->getAvailability() != AR_Unavailable)
return false;
return true;
}
static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) {
// Warn if this is used but marked unused.
if (const auto *A = D->getAttr<UnusedAttr>()) {
// [[maybe_unused]] should not diagnose uses, but __attribute__((unused))
// should diagnose them.
if (A->getSemanticSpelling() != UnusedAttr::CXX11_maybe_unused &&
A->getSemanticSpelling() != UnusedAttr::C2x_maybe_unused) {
const Decl *DC = cast_or_null<Decl>(S.getCurObjCLexicalContext());
if (DC && !DC->hasAttr<UnusedAttr>())
S.Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName();
}
}
}
/// Emit a note explaining that this function is deleted.
void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
assert(Decl->isDeleted());
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Decl);
if (Method && Method->isDeleted() && Method->isDefaulted()) {
// If the method was explicitly defaulted, point at that declaration.
if (!Method->isImplicit())
Diag(Decl->getLocation(), diag::note_implicitly_deleted);
// Try to diagnose why this special member function was implicitly
// deleted. This might fail, if that reason no longer applies.
CXXSpecialMember CSM = getSpecialMember(Method);
if (CSM != CXXInvalid)
ShouldDeleteSpecialMember(Method, CSM, nullptr, /*Diagnose=*/true);
return;
}
auto *Ctor = dyn_cast<CXXConstructorDecl>(Decl);
if (Ctor && Ctor->isInheritingConstructor())
return NoteDeletedInheritingConstructor(Ctor);
Diag(Decl->getLocation(), diag::note_availability_specified_here)
<< Decl << 1;
}
/// Determine whether a FunctionDecl was ever declared with an
/// explicit storage class.
static bool hasAnyExplicitStorageClass(const FunctionDecl *D) {
for (auto I : D->redecls()) {
if (I->getStorageClass() != SC_None)
return true;
}
return false;
}
/// Check whether we're in an extern inline function and referring to a
/// variable or function with internal linkage (C11 6.7.4p3).
///
/// This is only a warning because we used to silently accept this code, but
/// in many cases it will not behave correctly. This is not enabled in C++ mode
/// because the restriction language is a bit weaker (C++11 [basic.def.odr]p6)
/// and so while there may still be user mistakes, most of the time we can't
/// prove that there are errors.
static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S,
const NamedDecl *D,
SourceLocation Loc) {
// This is disabled under C++; there are too many ways for this to fire in
// contexts where the warning is a false positive, or where it is technically
// correct but benign.
if (S.getLangOpts().CPlusPlus)
return;
// Check if this is an inlined function or method.
FunctionDecl *Current = S.getCurFunctionDecl();
if (!Current)
return;
if (!Current->isInlined())
return;
if (!Current->isExternallyVisible())
return;
// Check if the decl has internal linkage.
if (D->getFormalLinkage() != InternalLinkage)
return;
// Downgrade from ExtWarn to Extension if
// (1) the supposedly external inline function is in the main file,
// and probably won't be included anywhere else.
// (2) the thing we're referencing is a pure function.
// (3) the thing we're referencing is another inline function.
// This last can give us false negatives, but it's better than warning on
// wrappers for simple C library functions.
const FunctionDecl *UsedFn = dyn_cast<FunctionDecl>(D);
bool DowngradeWarning = S.getSourceManager().isInMainFile(Loc);
if (!DowngradeWarning && UsedFn)
DowngradeWarning = UsedFn->isInlined() || UsedFn->hasAttr<ConstAttr>();
S.Diag(Loc, DowngradeWarning ? diag::ext_internal_in_extern_inline_quiet
: diag::ext_internal_in_extern_inline)
<< /*IsVar=*/!UsedFn << D;
S.MaybeSuggestAddingStaticToDecl(Current);
S.Diag(D->getCanonicalDecl()->getLocation(), diag::note_entity_declared_at)
<< D;
}
void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) {
const FunctionDecl *First = Cur->getFirstDecl();
// Suggest "static" on the function, if possible.
if (!hasAnyExplicitStorageClass(First)) {
SourceLocation DeclBegin = First->getSourceRange().getBegin();
Diag(DeclBegin, diag::note_convert_inline_to_static)
<< Cur << FixItHint::CreateInsertion(DeclBegin, "static ");
}
}
/// Determine whether the use of this declaration is valid, and
/// emit any corresponding diagnostics.
///
/// This routine diagnoses various problems with referencing
/// declarations that can occur when using a declaration. For example,
/// it might warn if a deprecated or unavailable declaration is being
/// used, or produce an error (and return true) if a C++0x deleted
/// function is being used.
///
/// \returns true if there was an error (this declaration cannot be
/// referenced), false otherwise.
///
bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
const ObjCInterfaceDecl *UnknownObjCClass,
bool ObjCPropertyAccess,
bool AvoidPartialAvailabilityChecks,
ObjCInterfaceDecl *ClassReceiver) {
SourceLocation Loc = Locs.front();
if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) {
// If there were any diagnostics suppressed by template argument deduction,
// emit them now.
auto Pos = SuppressedDiagnostics.find(D->getCanonicalDecl());
if (Pos != SuppressedDiagnostics.end()) {
for (const PartialDiagnosticAt &Suppressed : Pos->second)
Diag(Suppressed.first, Suppressed.second);
// Clear out the list of suppressed diagnostics, so that we don't emit
// them again for this specialization. However, we don't obsolete this
// entry from the table, because we want to avoid ever emitting these
// diagnostics again.
Pos->second.clear();
}
// C++ [basic.start.main]p3:
// The function 'main' shall not be used within a program.
if (cast<FunctionDecl>(D)->isMain())
Diag(Loc, diag::ext_main_used);
diagnoseUnavailableAlignedAllocation(*cast<FunctionDecl>(D), Loc);
}
// See if this is an auto-typed variable whose initializer we are parsing.
if (ParsingInitForAutoVars.count(D)) {
if (isa<BindingDecl>(D)) {
Diag(Loc, diag::err_binding_cannot_appear_in_own_initializer)
<< D->getDeclName();
} else {
Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
<< D->getDeclName() << cast<VarDecl>(D)->getType();
}
return true;
}
// See if this is a deleted function.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isDeleted()) {
auto *Ctor = dyn_cast<CXXConstructorDecl>(FD);
if (Ctor && Ctor->isInheritingConstructor())
Diag(Loc, diag::err_deleted_inherited_ctor_use)
<< Ctor->getParent()
<< Ctor->getInheritedConstructor().getConstructor()->getParent();
else
Diag(Loc, diag::err_deleted_function_use);
NoteDeletedFunction(FD);
return true;
}
// If the function has a deduced return type, and we can't deduce it,
// then we can't use it either.
if (getLangOpts().CPlusPlus14 && FD->getReturnType()->isUndeducedType() &&
DeduceReturnType(FD, Loc))
return true;
if (getLangOpts().CUDA && !CheckCUDACall(Loc, FD))
return true;
}
if (auto *MD = dyn_cast<CXXMethodDecl>(D)) {
// Lambdas are only default-constructible or assignable in C++2a onwards.
if (MD->getParent()->isLambda() &&
((isa<CXXConstructorDecl>(MD) &&
cast<CXXConstructorDecl>(MD)->isDefaultConstructor()) ||
MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator())) {
Diag(Loc, diag::warn_cxx17_compat_lambda_def_ctor_assign)
<< !isa<CXXConstructorDecl>(MD);
}
}
auto getReferencedObjCProp = [](const NamedDecl *D) ->
const ObjCPropertyDecl * {
if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
return MD->findPropertyDecl();
return nullptr;
};
if (const ObjCPropertyDecl *ObjCPDecl = getReferencedObjCProp(D)) {
if (diagnoseArgIndependentDiagnoseIfAttrs(ObjCPDecl, Loc))
return true;
} else if (diagnoseArgIndependentDiagnoseIfAttrs(D, Loc)) {
return true;
}
// [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
// Only the variables omp_in and omp_out are allowed in the combiner.
// Only the variables omp_priv and omp_orig are allowed in the
// initializer-clause.
auto *DRD = dyn_cast<OMPDeclareReductionDecl>(CurContext);
if (LangOpts.OpenMP && DRD && !CurContext->containsDecl(D) &&
isa<VarDecl>(D)) {
Diag(Loc, diag::err_omp_wrong_var_in_declare_reduction)
<< getCurFunction()->HasOMPDeclareReductionCombiner;
Diag(D->getLocation(), diag::note_entity_declared_at) << D;
return true;
}
DiagnoseAvailabilityOfDecl(D, Locs, UnknownObjCClass, ObjCPropertyAccess,
AvoidPartialAvailabilityChecks, ClassReceiver);
DiagnoseUnusedOfDecl(*this, D, Loc);
diagnoseUseOfInternalDeclInInlineFunction(*this, D, Loc);
return false;
}
/// Retrieve the message suffix that should be added to a
/// diagnostic complaining about the given function being deleted or
/// unavailable.
std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) {
std::string Message;
if (FD->getAvailability(&Message))
return ": " + Message;
return std::string();
}
/// DiagnoseSentinelCalls - This routine checks whether a call or
/// message-send is to a declaration with the sentinel attribute, and
/// if so, it checks that the requirements of the sentinel are
/// satisfied.
void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
ArrayRef<Expr *> Args) {
const SentinelAttr *attr = D->getAttr<SentinelAttr>();
if (!attr)
return;
// The number of formal parameters of the declaration.
unsigned numFormalParams;
// The kind of declaration. This is also an index into a %select in
// the diagnostic.
enum CalleeType { CT_Function, CT_Method, CT_Block } calleeType;
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
numFormalParams = MD->param_size();
calleeType = CT_Method;
} else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
numFormalParams = FD->param_size();
calleeType = CT_Function;
} else if (isa<VarDecl>(D)) {
QualType type = cast<ValueDecl>(D)->getType();
const FunctionType *fn = nullptr;
if (const PointerType *ptr = type->getAs<PointerType>()) {
fn = ptr->getPointeeType()->getAs<FunctionType>();
if (!fn) return;
calleeType = CT_Function;
} else if (const BlockPointerType *ptr = type->getAs<BlockPointerType>()) {
fn = ptr->getPointeeType()->castAs<FunctionType>();
calleeType = CT_Block;
} else {
return;
}
if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fn)) {
numFormalParams = proto->getNumParams();
} else {
numFormalParams = 0;
}
} else {
return;
}
// "nullPos" is the number of formal parameters at the end which
// effectively count as part of the variadic arguments. This is
// useful if you would prefer to not have *any* formal parameters,
// but the language forces you to have at least one.
unsigned nullPos = attr->getNullPos();
assert((nullPos == 0 || nullPos == 1) && "invalid null position on sentinel");
numFormalParams = (nullPos > numFormalParams ? 0 : numFormalParams - nullPos);
// The number of arguments which should follow the sentinel.
unsigned numArgsAfterSentinel = attr->getSentinel();
// If there aren't enough arguments for all the formal parameters,
// the sentinel, and the args after the sentinel, complain.
if (Args.size() < numFormalParams + numArgsAfterSentinel + 1) {
Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName();
Diag(D->getLocation(), diag::note_sentinel_here) << int(calleeType);
return;
}
// Otherwise, find the sentinel expression.
Expr *sentinelExpr = Args[Args.size() - numArgsAfterSentinel - 1];
if (!sentinelExpr) return;
if (sentinelExpr->isValueDependent()) return;
if (Context.isSentinelNullExpr(sentinelExpr)) return;
// Pick a reasonable string to insert. Optimistically use 'nil', 'nullptr',
// or 'NULL' if those are actually defined in the context. Only use
// 'nil' for ObjC methods, where it's much more likely that the
// variadic arguments form a list of object pointers.
SourceLocation MissingNilLoc = getLocForEndOfToken(sentinelExpr->getEndLoc());
std::string NullValue;
if (calleeType == CT_Method && PP.isMacroDefined("nil"))
NullValue = "nil";
else if (getLangOpts().CPlusPlus11)
NullValue = "nullptr";
else if (PP.isMacroDefined("NULL"))
NullValue = "NULL";
else
NullValue = "(void*) 0";
if (MissingNilLoc.isInvalid())
Diag(Loc, diag::warn_missing_sentinel) << int(calleeType);
else
Diag(MissingNilLoc, diag::warn_missing_sentinel)
<< int(calleeType)
<< FixItHint::CreateInsertion(MissingNilLoc, ", " + NullValue);
Diag(D->getLocation(), diag::note_sentinel_here) << int(calleeType);
}
SourceRange Sema::getExprRange(Expr *E) const {
return E ? E->getSourceRange() : SourceRange();
}
//===----------------------------------------------------------------------===//
// Standard Promotions and Conversions
//===----------------------------------------------------------------------===//
/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
// Handle any placeholder expressions which made it here.
if (E->getType()->isPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(E);
if (result.isInvalid()) return ExprError();
E = result.get();
}
QualType Ty = E->getType();
assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");
if (Ty->isFunctionType()) {
if (auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl()))
if (!checkAddressOfFunctionIsAvailable(FD, Diagnose, E->getExprLoc()))
return ExprError();
E = ImpCastExprToType(E, Context.getPointerType(Ty),
CK_FunctionToPointerDecay).get();
} else if (Ty->isArrayType()) {
// In C90 mode, arrays only promote to pointers if the array expression is
// an lvalue. The relevant legalese is C90 6.2.2.1p3: "an lvalue that has
// type 'array of type' is converted to an expression that has type 'pointer
// to type'...". In C99 this was changed to: C99 6.3.2.1p3: "an expression
// that has type 'array of type' ...". The relevant change is "an lvalue"
// (C90) to "an expression" (C99).
//
// C++ 4.2p1:
// An lvalue or rvalue of type "array of N T" or "array of unknown bound of
// T" can be converted to an rvalue of type "pointer to T".
//
if (getLangOpts().C99 || getLangOpts().CPlusPlus || E->isLValue())
E = ImpCastExprToType(E, Context.getArrayDecayedType(Ty),
CK_ArrayToPointerDecay).get();
}
return E;
}
static void CheckForNullPointerDereference(Sema &S, Expr *E) {
// Check to see if we are dereferencing a null pointer. If so,
// and if not volatile-qualified, this is undefined behavior that the
// optimizer will delete, so warn about it. People sometimes try to use this
// to get a deterministic trap and are surprised by clang's behavior. This
// only handles the pattern "*null", which is a very syntactic check.
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts()))
if (UO->getOpcode() == UO_Deref &&
UO->getSubExpr()->IgnoreParenCasts()->
isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) &&
!UO->getType().isVolatileQualified()) {
S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
S.PDiag(diag::warn_indirection_through_null)
<< UO->getSubExpr()->getSourceRange());
S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO,
S.PDiag(diag::note_indirection_through_null));
}
}
static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE,
SourceLocation AssignLoc,
const Expr* RHS) {
const ObjCIvarDecl *IV = OIRE->getDecl();
if (!IV)
return;
DeclarationName MemberName = IV->getDeclName();
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
if (!Member || !Member->isStr("isa"))
return;
const Expr *Base = OIRE->getBase();
QualType BaseType = Base->getType();
if (OIRE->isArrow())
BaseType = BaseType->getPointeeType();
if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>())
if (ObjCInterfaceDecl *IDecl = OTy->getInterface()) {
ObjCInterfaceDecl *ClassDeclared = nullptr;
ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared);
if (!ClassDeclared->getSuperClass()
&& (*ClassDeclared->ivar_begin()) == IV) {
if (RHS) {
NamedDecl *ObjectSetClass =
S.LookupSingleName(S.TUScope,
&S.Context.Idents.get("object_setClass"),
SourceLocation(), S.LookupOrdinaryName);
if (ObjectSetClass) {
SourceLocation RHSLocEnd = S.getLocForEndOfToken(RHS->getEndLoc());
S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_assign)
<< FixItHint::CreateInsertion(OIRE->getBeginLoc(),
"object_setClass(")
<< FixItHint::CreateReplacement(
SourceRange(OIRE->getOpLoc(), AssignLoc), ",")
<< FixItHint::CreateInsertion(RHSLocEnd, ")");
}
else
S.Diag(OIRE->getLocation(), diag::warn_objc_isa_assign);
} else {
NamedDecl *ObjectGetClass =
S.LookupSingleName(S.TUScope,
&S.Context.Idents.get("object_getClass"),
SourceLocation(), S.LookupOrdinaryName);
if (ObjectGetClass)
S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_use)
<< FixItHint::CreateInsertion(OIRE->getBeginLoc(),
"object_getClass(")
<< FixItHint::CreateReplacement(
SourceRange(OIRE->getOpLoc(), OIRE->getEndLoc()), ")");
else
S.Diag(OIRE->getLocation(), diag::warn_objc_isa_use);
}
S.Diag(IV->getLocation(), diag::note_ivar_decl);
}
}
}
ExprResult Sema::DefaultLvalueConversion(Expr *E) {
// Handle any placeholder expressions which made it here.
if (E->getType()->isPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(E);
if (result.isInvalid()) return ExprError();
E = result.get();
}
// C++ [conv.lval]p1:
// A glvalue of a non-function, non-array type T can be
// converted to a prvalue.
if (!E->isGLValue()) return E;
QualType T = E->getType();
assert(!T.isNull() && "r-value conversion on typeless expression?");
// We don't want to throw lvalue-to-rvalue casts on top of
// expressions of certain types in C++.
if (getLangOpts().CPlusPlus &&
(E->getType() == Context.OverloadTy ||
T->isDependentType() ||
T->isRecordType()))
return E;
// The C standard is actually really unclear on this point, and
// DR106 tells us what the result should be but not why. It's
// generally best to say that void types just doesn't undergo
// lvalue-to-rvalue at all. Note that expressions of unqualified
// 'void' type are never l-values, but qualified void can be.
if (T->isVoidType())
return E;
// OpenCL usually rejects direct accesses to values of 'half' type.
if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") &&
T->isHalfType()) {
Diag(E->getExprLoc(), diag::err_opencl_half_load_store)
<< 0 << T;
return ExprError();
}
CheckForNullPointerDereference(*this, E);
if (const ObjCIsaExpr *OISA = dyn_cast<ObjCIsaExpr>(E->IgnoreParenCasts())) {
NamedDecl *ObjectGetClass = LookupSingleName(TUScope,
&Context.Idents.get("object_getClass"),
SourceLocation(), LookupOrdinaryName);
if (ObjectGetClass)
Diag(E->getExprLoc(), diag::warn_objc_isa_use)
<< FixItHint::CreateInsertion(OISA->getBeginLoc(), "object_getClass(")
<< FixItHint::CreateReplacement(
SourceRange(OISA->getOpLoc(), OISA->getIsaMemberLoc()), ")");
else
Diag(E->getExprLoc(), diag::warn_objc_isa_use);
}
else if (const ObjCIvarRefExpr *OIRE =
dyn_cast<ObjCIvarRefExpr>(E->IgnoreParenCasts()))
DiagnoseDirectIsaAccess(*this, OIRE, SourceLocation(), /* Expr*/nullptr);
// C++ [conv.lval]p1:
// [...] If T is a non-class type, the type of the prvalue is the
// cv-unqualified version of T. Otherwise, the type of the
// rvalue is T.
//
// C99 6.3.2.1p2:
// If the lvalue has qualified type, the value has the unqualified
// version of the type of the lvalue; otherwise, the value has the
// type of the lvalue.
if (T.hasQualifiers())
T = T.getUnqualifiedType();
// Under the MS ABI, lock down the inheritance model now.
if (T->isMemberPointerType() &&
Context.getTargetInfo().getCXXABI().isMicrosoft())
(void)isCompleteType(E->getExprLoc(), T);
UpdateMarkingForLValueToRValue(E);
// Loading a __weak object implicitly retains the value, so we need a cleanup to
// balance that.
if (E->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
Cleanup.setExprNeedsCleanups(true);
ExprResult Res = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E,
nullptr, VK_RValue);
// C11 6.3.2.1p2:
// ... if the lvalue has atomic type, the value has the non-atomic version
// of the type of the lvalue ...
if (const AtomicType *Atomic = T->getAs<AtomicType>()) {
T = Atomic->getValueType().getUnqualifiedType();
Res = ImplicitCastExpr::Create(Context, T, CK_AtomicToNonAtomic, Res.get(),
nullptr, VK_RValue);
}
return Res;
}
ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose) {
ExprResult Res = DefaultFunctionArrayConversion(E, Diagnose);
if (Res.isInvalid())
return ExprError();
Res = DefaultLvalueConversion(Res.get());
if (Res.isInvalid())
return ExprError();
return Res;
}
/// CallExprUnaryConversions - a special case of an unary conversion
/// performed on a function designator of a call expression.
ExprResult Sema::CallExprUnaryConversions(Expr *E) {
QualType Ty = E->getType();
ExprResult Res = E;
// Only do implicit cast for a function type, but not for a pointer
// to function type.
if (Ty->isFunctionType()) {
Res = ImpCastExprToType(E, Context.getPointerType(Ty),
CK_FunctionToPointerDecay).get();
if (Res.isInvalid())
return ExprError();
}
Res = DefaultLvalueConversion(Res.get());
if (Res.isInvalid())
return ExprError();
return Res.get();
}
/// UsualUnaryConversions - Performs various conversions that are common to most
/// operators (C99 6.3). The conversions of array and function types are
/// sometimes suppressed. For example, the array->pointer conversion doesn't
/// apply if the array is an argument to the sizeof or address (&) operators.
/// In these instances, this routine should *not* be called.
ExprResult Sema::UsualUnaryConversions(Expr *E) {
// First, convert to an r-value.
ExprResult Res = DefaultFunctionArrayLvalueConversion(E);
if (Res.isInvalid())
return ExprError();
E = Res.get();
QualType Ty = E->getType();
assert(!Ty.isNull() && "UsualUnaryConversions - missing type");
// Half FP have to be promoted to float unless it is natively supported
if (Ty->isHalfType() && !getLangOpts().NativeHalfType)
return ImpCastExprToType(Res.get(), Context.FloatTy, CK_FloatingCast);
// Try to perform integral promotions if the object has a theoretically
// promotable type.
if (Ty->isIntegralOrUnscopedEnumerationType()) {
// C99 6.3.1.1p2:
//
// The following may be used in an expression wherever an int or
// unsigned int may be used:
// - an object or expression with an integer type whose integer
// conversion rank is less than or equal to the rank of int
// and unsigned int.
// - A bit-field of type _Bool, int, signed int, or unsigned int.
//
// If an int can represent all values of the original type, the
// value is converted to an int; otherwise, it is converted to an
// unsigned int. These are called the integer promotions. All
// other types are unchanged by the integer promotions.
QualType PTy = Context.isPromotableBitField(E);
if (!PTy.isNull()) {
E = ImpCastExprToType(E, PTy, CK_IntegralCast).get();
return E;
}
if (Ty->isPromotableIntegerType()) {
QualType PT = Context.getPromotedIntegerType(Ty);
E = ImpCastExprToType(E, PT, CK_IntegralCast).get();
return E;
}
}
return E;
}
/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
/// do not have a prototype. Arguments that have type float or __fp16
/// are promoted to double. All other argument types are converted by
/// UsualUnaryConversions().
ExprResult Sema::DefaultArgumentPromotion(Expr *E) {
QualType Ty = E->getType();
assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type");
ExprResult Res = UsualUnaryConversions(E);
if (Res.isInvalid())
return ExprError();
E = Res.get();
- QualType ScalarTy = Ty;
- unsigned NumElts = 0;
- if (const ExtVectorType *VecTy = Ty->getAs<ExtVectorType>()) {
- NumElts = VecTy->getNumElements();
- ScalarTy = VecTy->getElementType();
- }
-
// If this is a 'float' or '__fp16' (CVR qualified or typedef)
// promote to double.
// Note that default argument promotion applies only to float (and
// half/fp16); it does not apply to _Float16.
- const BuiltinType *BTy = ScalarTy->getAs<BuiltinType>();
+ const BuiltinType *BTy = Ty->getAs<BuiltinType>();
if (BTy && (BTy->getKind() == BuiltinType::Half ||
BTy->getKind() == BuiltinType::Float)) {
if (getLangOpts().OpenCL &&
!getOpenCLOptions().isEnabled("cl_khr_fp64")) {
- if (BTy->getKind() == BuiltinType::Half) {
- QualType Ty = Context.FloatTy;
- if (NumElts != 0)
- Ty = Context.getExtVectorType(Ty, NumElts);
- E = ImpCastExprToType(E, Ty, CK_FloatingCast).get();
- }
+ if (BTy->getKind() == BuiltinType::Half) {
+ E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get();
+ }
} else {
- QualType Ty = Context.DoubleTy;
- if (NumElts != 0)
- Ty = Context.getExtVectorType(Ty, NumElts);
- E = ImpCastExprToType(E, Ty, CK_FloatingCast).get();
+ E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).get();
}
}
// C++ performs lvalue-to-rvalue conversion as a default argument
// promotion, even on class types, but note:
// C++11 [conv.lval]p2:
// When an lvalue-to-rvalue conversion occurs in an unevaluated
// operand or a subexpression thereof the value contained in the
// referenced object is not accessed. Otherwise, if the glvalue
// has a class type, the conversion copy-initializes a temporary
// of type T from the glvalue and the result of the conversion
// is a prvalue for the temporary.
// FIXME: add some way to gate this entire thing for correctness in
// potentially potentially evaluated contexts.
if (getLangOpts().CPlusPlus && E->isGLValue() && !isUnevaluatedContext()) {
ExprResult Temp = PerformCopyInitialization(
InitializedEntity::InitializeTemporary(E->getType()),
E->getExprLoc(), E);
if (Temp.isInvalid())
return ExprError();
E = Temp.get();
}
return E;
}
/// Determine the degree of POD-ness for an expression.
/// Incomplete types are considered POD, since this check can be performed
/// when we're in an unevaluated context.
Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) {
if (Ty->isIncompleteType()) {
// C++11 [expr.call]p7:
// After these conversions, if the argument does not have arithmetic,
// enumeration, pointer, pointer to member, or class type, the program
// is ill-formed.
//
// Since we've already performed array-to-pointer and function-to-pointer
// decay, the only such type in C++ is cv void. This also handles
// initializer lists as variadic arguments.
if (Ty->isVoidType())
return VAK_Invalid;
if (Ty->isObjCObjectType())
return VAK_Invalid;
return VAK_Valid;
}
if (Ty.isDestructedType() == QualType::DK_nontrivial_c_struct)
return VAK_Invalid;
if (Ty.isCXX98PODType(Context))
return VAK_Valid;
// C++11 [expr.call]p7:
// Passing a potentially-evaluated argument of class type (Clause 9)
// having a non-trivial copy constructor, a non-trivial move constructor,
// or a non-trivial destructor, with no corresponding parameter,
// is conditionally-supported with implementation-defined semantics.
if (getLangOpts().CPlusPlus11 && !Ty->isDependentType())
if (CXXRecordDecl *Record = Ty->getAsCXXRecordDecl())
if (!Record->hasNonTrivialCopyConstructor() &&
!Record->hasNonTrivialMoveConstructor() &&
!Record->hasNonTrivialDestructor())
return VAK_ValidInCXX11;
if (getLangOpts().ObjCAutoRefCount && Ty->isObjCLifetimeType())
return VAK_Valid;
if (Ty->isObjCObjectType())
return VAK_Invalid;
if (getLangOpts().MSVCCompat)
return VAK_MSVCUndefined;
// FIXME: In C++11, these cases are conditionally-supported, meaning we're
// permitted to reject them. We should consider doing so.
return VAK_Undefined;
}
void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) {
// Don't allow one to pass an Objective-C interface to a vararg.
const QualType &Ty = E->getType();
VarArgKind VAK = isValidVarArgType(Ty);
// Complain about passing non-POD types through varargs.
switch (VAK) {
case VAK_ValidInCXX11:
DiagRuntimeBehavior(
E->getBeginLoc(), nullptr,
PDiag(diag::warn_cxx98_compat_pass_non_pod_arg_to_vararg) << Ty << CT);
LLVM_FALLTHROUGH;
case VAK_Valid:
if (Ty->isRecordType()) {
// This is unlikely to be what the user intended. If the class has a
// 'c_str' member function, the user probably meant to call that.
DiagRuntimeBehavior(E->getBeginLoc(), nullptr,
PDiag(diag::warn_pass_class_arg_to_vararg)
<< Ty << CT << hasCStrMethod(E) << ".c_str()");
}
break;
case VAK_Undefined:
case VAK_MSVCUndefined:
DiagRuntimeBehavior(E->getBeginLoc(), nullptr,
PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg)
<< getLangOpts().CPlusPlus11 << Ty << CT);
break;
case VAK_Invalid:
if (Ty.isDestructedType() == QualType::DK_nontrivial_c_struct)
Diag(E->getBeginLoc(),
diag::err_cannot_pass_non_trivial_c_struct_to_vararg)
<< Ty << CT;
else if (Ty->isObjCObjectType())
DiagRuntimeBehavior(E->getBeginLoc(), nullptr,
PDiag(diag::err_cannot_pass_objc_interface_to_vararg)
<< Ty << CT);
else
Diag(E->getBeginLoc(), diag::err_cannot_pass_to_vararg)
<< isa<InitListExpr>(E) << Ty << CT;
break;
}
}
/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
/// will create a trap if the resulting type is not a POD type.
ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
FunctionDecl *FDecl) {
if (const BuiltinType *PlaceholderTy = E->getType()->getAsPlaceholderType()) {
// Strip the unbridged-cast placeholder expression off, if applicable.
if (PlaceholderTy->getKind() == BuiltinType::ARCUnbridgedCast &&
(CT == VariadicMethod ||
(FDecl && FDecl->hasAttr<CFAuditedTransferAttr>()))) {
E = stripARCUnbridgedCast(E);
// Otherwise, do normal placeholder checking.
} else {
ExprResult ExprRes = CheckPlaceholderExpr(E);
if (ExprRes.isInvalid())
return ExprError();
E = ExprRes.get();
}
}
ExprResult ExprRes = DefaultArgumentPromotion(E);
if (ExprRes.isInvalid())
return ExprError();
E = ExprRes.get();
// Diagnostics regarding non-POD argument types are
// emitted along with format string checking in Sema::CheckFunctionCall().
if (isValidVarArgType(E->getType()) == VAK_Undefined) {
// Turn this into a trap.
CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
UnqualifiedId Name;
Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"),
E->getBeginLoc());
ExprResult TrapFn = ActOnIdExpression(TUScope, SS, TemplateKWLoc,
Name, true, false);
if (TrapFn.isInvalid())
return ExprError();
ExprResult Call = ActOnCallExpr(TUScope, TrapFn.get(), E->getBeginLoc(),
None, E->getEndLoc());
if (Call.isInvalid())
return ExprError();
ExprResult Comma =
ActOnBinOp(TUScope, E->getBeginLoc(), tok::comma, Call.get(), E);
if (Comma.isInvalid())
return ExprError();
return Comma.get();
}
if (!getLangOpts().CPlusPlus &&
RequireCompleteType(E->getExprLoc(), E->getType(),
diag::err_call_incomplete_argument))
return ExprError();
return E;
}
/// Converts an integer to complex float type. Helper function of
/// UsualArithmeticConversions()
///
/// \return false if the integer expression is an integer type and is
/// successfully converted to the complex type.
static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &IntExpr,
ExprResult &ComplexExpr,
QualType IntTy,
QualType ComplexTy,
bool SkipCast) {
if (IntTy->isComplexType() || IntTy->isRealFloatingType()) return true;
if (SkipCast) return false;
if (IntTy->isIntegerType()) {
QualType fpTy = cast<ComplexType>(ComplexTy)->getElementType();
IntExpr = S.ImpCastExprToType(IntExpr.get(), fpTy, CK_IntegralToFloating);
IntExpr = S.ImpCastExprToType(IntExpr.get(), ComplexTy,
CK_FloatingRealToComplex);
} else {
assert(IntTy->isComplexIntegerType());
IntExpr = S.ImpCastExprToType(IntExpr.get(), ComplexTy,
CK_IntegralComplexToFloatingComplex);
}
return false;
}
/// Handle arithmetic conversion with complex types. Helper function of
/// UsualArithmeticConversions()
static QualType handleComplexFloatConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
QualType RHSType,
bool IsCompAssign) {
// if we have an integer operand, the result is the complex type.
if (!handleIntegerToComplexFloatConversion(S, RHS, LHS, RHSType, LHSType,
/*skipCast*/false))
return LHSType;
if (!handleIntegerToComplexFloatConversion(S, LHS, RHS, LHSType, RHSType,
/*skipCast*/IsCompAssign))
return RHSType;
// This handles complex/complex, complex/float, or float/complex.
// When both operands are complex, the shorter operand is converted to the
// type of the longer, and that is the type of the result. This corresponds
// to what is done when combining two real floating-point operands.
// The fun begins when size promotion occur across type domains.
// From H&S 6.3.4: When one operand is complex and the other is a real
// floating-point type, the less precise type is converted, within it's
// real or complex domain, to the precision of the other type. For example,
// when combining a "long double" with a "double _Complex", the
// "double _Complex" is promoted to "long double _Complex".
// Compute the rank of the two types, regardless of whether they are complex.
int Order = S.Context.getFloatingTypeOrder(LHSType, RHSType);
auto *LHSComplexType = dyn_cast<ComplexType>(LHSType);
auto *RHSComplexType = dyn_cast<ComplexType>(RHSType);
QualType LHSElementType =
LHSComplexType ? LHSComplexType->getElementType() : LHSType;
QualType RHSElementType =
RHSComplexType ? RHSComplexType->getElementType() : RHSType;
QualType ResultType = S.Context.getComplexType(LHSElementType);
if (Order < 0) {
// Promote the precision of the LHS if not an assignment.
ResultType = S.Context.getComplexType(RHSElementType);
if (!IsCompAssign) {
if (LHSComplexType)
LHS =
S.ImpCastExprToType(LHS.get(), ResultType, CK_FloatingComplexCast);
else
LHS = S.ImpCastExprToType(LHS.get(), RHSElementType, CK_FloatingCast);
}
} else if (Order > 0) {
// Promote the precision of the RHS.
if (RHSComplexType)
RHS = S.ImpCastExprToType(RHS.get(), ResultType, CK_FloatingComplexCast);
else
RHS = S.ImpCastExprToType(RHS.get(), LHSElementType, CK_FloatingCast);
}
return ResultType;
}
/// Handle arithmetic conversion from integer to float. Helper function
/// of UsualArithmeticConversions()
static QualType handleIntToFloatConversion(Sema &S, ExprResult &FloatExpr,
ExprResult &IntExpr,
QualType FloatTy, QualType IntTy,
bool ConvertFloat, bool ConvertInt) {
if (IntTy->isIntegerType()) {
if (ConvertInt)
// Convert intExpr to the lhs floating point type.
IntExpr = S.ImpCastExprToType(IntExpr.get(), FloatTy,
CK_IntegralToFloating);
return FloatTy;
}
// Convert both sides to the appropriate complex float.
assert(IntTy->isComplexIntegerType());
QualType result = S.Context.getComplexType(FloatTy);
// _Complex int -> _Complex float
if (ConvertInt)
IntExpr = S.ImpCastExprToType(IntExpr.get(), result,
CK_IntegralComplexToFloatingComplex);
// float -> _Complex float
if (ConvertFloat)
FloatExpr = S.ImpCastExprToType(FloatExpr.get(), result,
CK_FloatingRealToComplex);
return result;
}
/// Handle arithmethic conversion with floating point types. Helper
/// function of UsualArithmeticConversions()
static QualType handleFloatConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
QualType RHSType, bool IsCompAssign) {
bool LHSFloat = LHSType->isRealFloatingType();
bool RHSFloat = RHSType->isRealFloatingType();
// If we have two real floating types, convert the smaller operand
// to the bigger result.
if (LHSFloat && RHSFloat) {
int order = S.Context.getFloatingTypeOrder(LHSType, RHSType);
if (order > 0) {
RHS = S.ImpCastExprToType(RHS.get(), LHSType, CK_FloatingCast);
return LHSType;
}
assert(order < 0 && "illegal float comparison");
if (!IsCompAssign)
LHS = S.ImpCastExprToType(LHS.get(), RHSType, CK_FloatingCast);
return RHSType;
}
if (LHSFloat) {
// Half FP has to be promoted to float unless it is natively supported
if (LHSType->isHalfType() && !S.getLangOpts().NativeHalfType)
LHSType = S.Context.FloatTy;
return handleIntToFloatConversion(S, LHS, RHS, LHSType, RHSType,
/*convertFloat=*/!IsCompAssign,
/*convertInt=*/ true);
}
assert(RHSFloat);
return handleIntToFloatConversion(S, RHS, LHS, RHSType, LHSType,
/*convertInt=*/ true,
/*convertFloat=*/!IsCompAssign);
}
/// Diagnose attempts to convert between __float128 and long double if
/// there is no support for such conversion. Helper function of
/// UsualArithmeticConversions().
static bool unsupportedTypeConversion(const Sema &S, QualType LHSType,
QualType RHSType) {
/* No issue converting if at least one of the types is not a floating point
type or the two types have the same rank.
*/
if (!LHSType->isFloatingType() || !RHSType->isFloatingType() ||
S.Context.getFloatingTypeOrder(LHSType, RHSType) == 0)
return false;
assert(LHSType->isFloatingType() && RHSType->isFloatingType() &&
"The remaining types must be floating point types.");
auto *LHSComplex = LHSType->getAs<ComplexType>();
auto *RHSComplex = RHSType->getAs<ComplexType>();
QualType LHSElemType = LHSComplex ?
LHSComplex->getElementType() : LHSType;
QualType RHSElemType = RHSComplex ?
RHSComplex->getElementType() : RHSType;
// No issue if the two types have the same representation
if (&S.Context.getFloatTypeSemantics(LHSElemType) ==
&S.Context.getFloatTypeSemantics(RHSElemType))
return false;
bool Float128AndLongDouble = (LHSElemType == S.Context.Float128Ty &&
RHSElemType == S.Context.LongDoubleTy);
Float128AndLongDouble |= (LHSElemType == S.Context.LongDoubleTy &&
RHSElemType == S.Context.Float128Ty);
// We've handled the situation where __float128 and long double have the same
// representation. We allow all conversions for all possible long double types
// except PPC's double double.
return Float128AndLongDouble &&
(&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) ==
&llvm::APFloat::PPCDoubleDouble());
}
typedef ExprResult PerformCastFn(Sema &S, Expr *operand, QualType toType);
namespace {
/// These helper callbacks are placed in an anonymous namespace to
/// permit their use as function template parameters.
ExprResult doIntegralCast(Sema &S, Expr *op, QualType toType) {
return S.ImpCastExprToType(op, toType, CK_IntegralCast);
}
ExprResult doComplexIntegralCast(Sema &S, Expr *op, QualType toType) {
return S.ImpCastExprToType(op, S.Context.getComplexType(toType),
CK_IntegralComplexCast);
}
}
/// Handle integer arithmetic conversions. Helper function of
/// UsualArithmeticConversions()
template <PerformCastFn doLHSCast, PerformCastFn doRHSCast>
static QualType handleIntegerConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
QualType RHSType, bool IsCompAssign) {
// The rules for this case are in C99 6.3.1.8
int order = S.Context.getIntegerTypeOrder(LHSType, RHSType);
bool LHSSigned = LHSType->hasSignedIntegerRepresentation();
bool RHSSigned = RHSType->hasSignedIntegerRepresentation();
if (LHSSigned == RHSSigned) {
// Same signedness; use the higher-ranked type
if (order >= 0) {
RHS = (*doRHSCast)(S, RHS.get(), LHSType);
return LHSType;
} else if (!IsCompAssign)
LHS = (*doLHSCast)(S, LHS.get(), RHSType);
return RHSType;
} else if (order != (LHSSigned ? 1 : -1)) {
// The unsigned type has greater than or equal rank to the
// signed type, so use the unsigned type
if (RHSSigned) {
RHS = (*doRHSCast)(S, RHS.get(), LHSType);
return LHSType;
} else if (!IsCompAssign)
LHS = (*doLHSCast)(S, LHS.get(), RHSType);
return RHSType;
} else if (S.Context.getIntWidth(LHSType) != S.Context.getIntWidth(RHSType)) {
// The two types are different widths; if we are here, that
// means the signed type is larger than the unsigned type, so
// use the signed type.
if (LHSSigned) {
RHS = (*doRHSCast)(S, RHS.get(), LHSType);
return LHSType;
} else if (!IsCompAssign)
LHS = (*doLHSCast)(S, LHS.get(), RHSType);
return RHSType;
} else {
// The signed type is higher-ranked than the unsigned type,
// but isn't actually any bigger (like unsigned int and long
// on most 32-bit systems). Use the unsigned type corresponding
// to the signed type.
QualType result =
S.Context.getCorrespondingUnsignedType(LHSSigned ? LHSType : RHSType);
RHS = (*doRHSCast)(S, RHS.get(), result);
if (!IsCompAssign)
LHS = (*doLHSCast)(S, LHS.get(), result);
return result;
}
}
/// Handle conversions with GCC complex int extension. Helper function
/// of UsualArithmeticConversions()
static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS,
ExprResult &RHS, QualType LHSType,
QualType RHSType,
bool IsCompAssign) {
const ComplexType *LHSComplexInt = LHSType->getAsComplexIntegerType();
const ComplexType *RHSComplexInt = RHSType->getAsComplexIntegerType();
if (LHSComplexInt && RHSComplexInt) {
QualType LHSEltType = LHSComplexInt->getElementType();
QualType RHSEltType = RHSComplexInt->getElementType();
QualType ScalarType =
handleIntegerConversion<doComplexIntegralCast, doComplexIntegralCast>
(S, LHS, RHS, LHSEltType, RHSEltType, IsCompAssign);
return S.Context.getComplexType(ScalarType);
}
if (LHSComplexInt) {
QualType LHSEltType = LHSComplexInt->getElementType();
QualType ScalarType =
handleIntegerConversion<doComplexIntegralCast, doIntegralCast>
(S, LHS, RHS, LHSEltType, RHSType, IsCompAssign);
QualType ComplexType = S.Context.getComplexType(ScalarType);
RHS = S.ImpCastExprToType(RHS.get(), ComplexType,
CK_IntegralRealToComplex);
return ComplexType;
}
assert(RHSComplexInt);
QualType RHSEltType = RHSComplexInt->getElementType();
QualType ScalarType =
handleIntegerConversion<doIntegralCast, doComplexIntegralCast>
(S, LHS, RHS, LHSType, RHSEltType, IsCompAssign);
QualType ComplexType = S.Context.getComplexType(ScalarType);
if (!IsCompAssign)
LHS = S.ImpCastExprToType(LHS.get(), ComplexType,
CK_IntegralRealToComplex);
return ComplexType;
}
/// UsualArithmeticConversions - Performs various conversions that are common to
/// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
/// routine returns the first non-arithmetic type found. The client is
/// responsible for emitting appropriate error diagnostics.
QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
bool IsCompAssign) {
if (!IsCompAssign) {
LHS = UsualUnaryConversions(LHS.get());
if (LHS.isInvalid())
return QualType();
}
RHS = UsualUnaryConversions(RHS.get());
if (RHS.isInvalid())
return QualType();
// For conversion purposes, we ignore any qualifiers.
// For example, "const float" and "float" are equivalent.
QualType LHSType =
Context.getCanonicalType(LHS.get()->getType()).getUnqualifiedType();
QualType RHSType =
Context.getCanonicalType(RHS.get()->getType()).getUnqualifiedType();
// For conversion purposes, we ignore any atomic qualifier on the LHS.
if (const AtomicType *AtomicLHS = LHSType->getAs<AtomicType>())
LHSType = AtomicLHS->getValueType();
// If both types are identical, no conversion is needed.
if (LHSType == RHSType)
return LHSType;
// If either side is a non-arithmetic type (e.g. a pointer), we are done.
// The caller can deal with this (e.g. pointer + int).
if (!LHSType->isArithmeticType() || !RHSType->isArithmeticType())
return QualType();
// Apply unary and bitfield promotions to the LHS's type.
QualType LHSUnpromotedType = LHSType;
if (LHSType->isPromotableIntegerType())
LHSType = Context.getPromotedIntegerType(LHSType);
QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(LHS.get());
if (!LHSBitfieldPromoteTy.isNull())
LHSType = LHSBitfieldPromoteTy;
if (LHSType != LHSUnpromotedType && !IsCompAssign)
LHS = ImpCastExprToType(LHS.get(), LHSType, CK_IntegralCast);
// If both types are identical, no conversion is needed.
if (LHSType == RHSType)
return LHSType;
// At this point, we have two different arithmetic types.
// Diagnose attempts to convert between __float128 and long double where
// such conversions currently can't be handled.
if (unsupportedTypeConversion(*this, LHSType, RHSType))
return QualType();
// Handle complex types first (C99 6.3.1.8p1).
if (LHSType->isComplexType() || RHSType->isComplexType())
return handleComplexFloatConversion(*this, LHS, RHS, LHSType, RHSType,
IsCompAssign);
// Now handle "real" floating types (i.e. float, double, long double).
if (LHSType->isRealFloatingType() || RHSType->isRealFloatingType())
return handleFloatConversion(*this, LHS, RHS, LHSType, RHSType,
IsCompAssign);
// Handle GCC complex int extension.
if (LHSType->isComplexIntegerType() || RHSType->isComplexIntegerType())
return handleComplexIntConversion(*this, LHS, RHS, LHSType, RHSType,
IsCompAssign);
// Finally, we have two differing integer types.
return handleIntegerConversion<doIntegralCast, doIntegralCast>
(*this, LHS, RHS, LHSType, RHSType, IsCompAssign);
}
//===----------------------------------------------------------------------===//
// Semantic Analysis for various Expression Types
//===----------------------------------------------------------------------===//
ExprResult
Sema::ActOnGenericSelectionExpr(SourceLocation KeyLoc,
SourceLocation DefaultLoc,
SourceLocation RParenLoc,
Expr *ControllingExpr,
ArrayRef<ParsedType> ArgTypes,
ArrayRef<Expr *> ArgExprs) {
unsigned NumAssocs = ArgTypes.size();
assert(NumAssocs == ArgExprs.size());
TypeSourceInfo **Types = new TypeSourceInfo*[NumAssocs];
for (unsigned i = 0; i < NumAssocs; ++i) {
if (ArgTypes[i])
(void) GetTypeFromParser(ArgTypes[i], &Types[i]);
else
Types[i] = nullptr;
}
ExprResult ER = CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc,
ControllingExpr,
llvm::makeArrayRef(Types, NumAssocs),
ArgExprs);
delete [] Types;
return ER;
}
ExprResult
Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc,
SourceLocation DefaultLoc,
SourceLocation RParenLoc,
Expr *ControllingExpr,
ArrayRef<TypeSourceInfo *> Types,
ArrayRef<Expr *> Exprs) {
unsigned NumAssocs = Types.size();
assert(NumAssocs == Exprs.size());
// Decay and strip qualifiers for the controlling expression type, and handle
// placeholder type replacement. See committee discussion from WG14 DR423.
{
EnterExpressionEvaluationContext Unevaluated(
*this, Sema::ExpressionEvaluationContext::Unevaluated);
ExprResult R = DefaultFunctionArrayLvalueConversion(ControllingExpr);
if (R.isInvalid())
return ExprError();
ControllingExpr = R.get();
}
// The controlling expression is an unevaluated operand, so side effects are
// likely unintended.
if (!inTemplateInstantiation() &&
ControllingExpr->HasSideEffects(Context, false))
Diag(ControllingExpr->getExprLoc(),
diag::warn_side_effects_unevaluated_context);
bool TypeErrorFound = false,
IsResultDependent = ControllingExpr->isTypeDependent(),
ContainsUnexpandedParameterPack
= ControllingExpr->containsUnexpandedParameterPack();
for (unsigned i = 0; i < NumAssocs; ++i) {
if (Exprs[i]->containsUnexpandedParameterPack())
ContainsUnexpandedParameterPack = true;
if (Types[i]) {
if (Types[i]->getType()->containsUnexpandedParameterPack())
ContainsUnexpandedParameterPack = true;
if (Types[i]->getType()->isDependentType()) {
IsResultDependent = true;
} else {
// C11 6.5.1.1p2 "The type name in a generic association shall specify a
// complete object type other than a variably modified type."
unsigned D = 0;
if (Types[i]->getType()->isIncompleteType())
D = diag::err_assoc_type_incomplete;
else if (!Types[i]->getType()->isObjectType())
D = diag::err_assoc_type_nonobject;
else if (Types[i]->getType()->isVariablyModifiedType())
D = diag::err_assoc_type_variably_modified;
if (D != 0) {
Diag(Types[i]->getTypeLoc().getBeginLoc(), D)
<< Types[i]->getTypeLoc().getSourceRange()
<< Types[i]->getType();
TypeErrorFound = true;
}
// C11 6.5.1.1p2 "No two generic associations in the same generic
// selection shall specify compatible types."
for (unsigned j = i+1; j < NumAssocs; ++j)
if (Types[j] && !Types[j]->getType()->isDependentType() &&
Context.typesAreCompatible(Types[i]->getType(),
Types[j]->getType())) {
Diag(Types[j]->getTypeLoc().getBeginLoc(),
diag::err_assoc_compatible_types)
<< Types[j]->getTypeLoc().getSourceRange()
<< Types[j]->getType()
<< Types[i]->getType();
Diag(Types[i]->getTypeLoc().getBeginLoc(),
diag::note_compat_assoc)
<< Types[i]->getTypeLoc().getSourceRange()
<< Types[i]->getType();
TypeErrorFound = true;
}
}
}
}
if (TypeErrorFound)
return ExprError();
// If we determined that the generic selection is result-dependent, don't
// try to compute the result expression.
if (IsResultDependent)
return new (Context) GenericSelectionExpr(
Context, KeyLoc, ControllingExpr, Types, Exprs, DefaultLoc, RParenLoc,
ContainsUnexpandedParameterPack);
SmallVector<unsigned, 1> CompatIndices;
unsigned DefaultIndex = -1U;
for (unsigned i = 0; i < NumAssocs; ++i) {
if (!Types[i])
DefaultIndex = i;
else if (Context.typesAreCompatible(ControllingExpr->getType(),
Types[i]->getType()))
CompatIndices.push_back(i);
}
// C11 6.5.1.1p2 "The controlling expression of a generic selection shall have
// type compatible with at most one of the types named in its generic
// association list."
if (CompatIndices.size() > 1) {
// We strip parens here because the controlling expression is typically
// parenthesized in macro definitions.
ControllingExpr = ControllingExpr->IgnoreParens();
Diag(ControllingExpr->getBeginLoc(), diag::err_generic_sel_multi_match)
<< ControllingExpr->getSourceRange() << ControllingExpr->getType()
<< (unsigned)CompatIndices.size();
for (unsigned I : CompatIndices) {
Diag(Types[I]->getTypeLoc().getBeginLoc(),
diag::note_compat_assoc)
<< Types[I]->getTypeLoc().getSourceRange()
<< Types[I]->getType();
}
return ExprError();
}
// C11 6.5.1.1p2 "If a generic selection has no default generic association,
// its controlling expression shall have type compatible with exactly one of
// the types named in its generic association list."
if (DefaultIndex == -1U && CompatIndices.size() == 0) {
// We strip parens here because the controlling expression is typically
// parenthesized in macro definitions.
ControllingExpr = ControllingExpr->IgnoreParens();
Diag(ControllingExpr->getBeginLoc(), diag::err_generic_sel_no_match)
<< ControllingExpr->getSourceRange() << ControllingExpr->getType();
return ExprError();
}
// C11 6.5.1.1p3 "If a generic selection has a generic association with a
// type name that is compatible with the type of the controlling expression,
// then the result expression of the generic selection is the expression
// in that generic association. Otherwise, the result expression of the
// generic selection is the expression in the default generic association."
unsigned ResultIndex =
CompatIndices.size() ? CompatIndices[0] : DefaultIndex;
return new (Context) GenericSelectionExpr(
Context, KeyLoc, ControllingExpr, Types, Exprs, DefaultLoc, RParenLoc,
ContainsUnexpandedParameterPack, ResultIndex);
}
/// getUDSuffixLoc - Create a SourceLocation for a ud-suffix, given the
/// location of the token and the offset of the ud-suffix within it.
static SourceLocation getUDSuffixLoc(Sema &S, SourceLocation TokLoc,
unsigned Offset) {
return Lexer::AdvanceToTokenCharacter(TokLoc, Offset, S.getSourceManager(),
S.getLangOpts());
}
/// BuildCookedLiteralOperatorCall - A user-defined literal was found. Look up
/// the corresponding cooked (non-raw) literal operator, and build a call to it.
static ExprResult BuildCookedLiteralOperatorCall(Sema &S, Scope *Scope,
IdentifierInfo *UDSuffix,
SourceLocation UDSuffixLoc,
ArrayRef<Expr*> Args,
SourceLocation LitEndLoc) {
assert(Args.size() <= 2 && "too many arguments for literal operator");
QualType ArgTy[2];
for (unsigned ArgIdx = 0; ArgIdx != Args.size(); ++ArgIdx) {
ArgTy[ArgIdx] = Args[ArgIdx]->getType();
if (ArgTy[ArgIdx]->isArrayType())
ArgTy[ArgIdx] = S.Context.getArrayDecayedType(ArgTy[ArgIdx]);
}
DeclarationName OpName =
S.Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
LookupResult R(S, OpName, UDSuffixLoc, Sema::LookupOrdinaryName);
if (S.LookupLiteralOperator(Scope, R, llvm::makeArrayRef(ArgTy, Args.size()),
/*AllowRaw*/ false, /*AllowTemplate*/ false,
/*AllowStringTemplate*/ false,
/*DiagnoseMissing*/ true) == Sema::LOLR_Error)
return ExprError();
return S.BuildLiteralOperatorCall(R, OpNameInfo, Args, LitEndLoc);
}
/// ActOnStringLiteral - The specified tokens were lexed as pasted string
/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string
/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
/// multiple tokens. However, the common case is that StringToks points to one
/// string.
///
ExprResult
Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
assert(!StringToks.empty() && "Must have at least one string!");
StringLiteralParser Literal(StringToks, PP);
if (Literal.hadError)
return ExprError();
SmallVector<SourceLocation, 4> StringTokLocs;
for (const Token &Tok : StringToks)
StringTokLocs.push_back(Tok.getLocation());
QualType CharTy = Context.CharTy;
StringLiteral::StringKind Kind = StringLiteral::Ascii;
if (Literal.isWide()) {
CharTy = Context.getWideCharType();
Kind = StringLiteral::Wide;
} else if (Literal.isUTF8()) {
if (getLangOpts().Char8)
CharTy = Context.Char8Ty;
Kind = StringLiteral::UTF8;
} else if (Literal.isUTF16()) {
CharTy = Context.Char16Ty;
Kind = StringLiteral::UTF16;
} else if (Literal.isUTF32()) {
CharTy = Context.Char32Ty;
Kind = StringLiteral::UTF32;
} else if (Literal.isPascal()) {
CharTy = Context.UnsignedCharTy;
}
// Warn on initializing an array of char from a u8 string literal; this
// becomes ill-formed in C++2a.
if (getLangOpts().CPlusPlus && !getLangOpts().CPlusPlus2a &&
!getLangOpts().Char8 && Kind == StringLiteral::UTF8) {
Diag(StringTokLocs.front(), diag::warn_cxx2a_compat_utf8_string);
// Create removals for all 'u8' prefixes in the string literal(s). This
// ensures C++2a compatibility (but may change the program behavior when
// built by non-Clang compilers for which the execution character set is
// not always UTF-8).
auto RemovalDiag = PDiag(diag::note_cxx2a_compat_utf8_string_remove_u8);
SourceLocation RemovalDiagLoc;
for (const Token &Tok : StringToks) {
if (Tok.getKind() == tok::utf8_string_literal) {
if (RemovalDiagLoc.isInvalid())
RemovalDiagLoc = Tok.getLocation();
RemovalDiag << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
Tok.getLocation(),
Lexer::AdvanceToTokenCharacter(Tok.getLocation(), 2,
getSourceManager(), getLangOpts())));
}
}
Diag(RemovalDiagLoc, RemovalDiag);
}
QualType CharTyConst = CharTy;
// A C++ string literal has a const-qualified element type (C++ 2.13.4p1).
if (getLangOpts().CPlusPlus || getLangOpts().ConstStrings)
CharTyConst.addConst();
CharTyConst = Context.adjustStringLiteralBaseType(CharTyConst);
// Get an array type for the string, according to C99 6.4.5. This includes
// the nul terminator character as well as the string length for pascal
// strings.
QualType StrTy = Context.getConstantArrayType(
CharTyConst, llvm::APInt(32, Literal.GetNumStringChars() + 1),
ArrayType::Normal, 0);
// Pass &StringTokLocs[0], StringTokLocs.size() to factory!
StringLiteral *Lit = StringLiteral::Create(Context, Literal.GetString(),
Kind, Literal.Pascal, StrTy,
&StringTokLocs[0],
StringTokLocs.size());
if (Literal.getUDSuffix().empty())
return Lit;
// We're building a user-defined literal.
IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
SourceLocation UDSuffixLoc =
getUDSuffixLoc(*this, StringTokLocs[Literal.getUDSuffixToken()],
Literal.getUDSuffixOffset());
// Make sure we're allowed user-defined literals here.
if (!UDLScope)
return ExprError(Diag(UDSuffixLoc, diag::err_invalid_string_udl));
// C++11 [lex.ext]p5: The literal L is treated as a call of the form
// operator "" X (str, len)
QualType SizeType = Context.getSizeType();
DeclarationName OpName =
Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
QualType ArgTy[] = {
Context.getArrayDecayedType(StrTy), SizeType
};
LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
switch (LookupLiteralOperator(UDLScope, R, ArgTy,
/*AllowRaw*/ false, /*AllowTemplate*/ false,
/*AllowStringTemplate*/ true,
/*DiagnoseMissing*/ true)) {
case LOLR_Cooked: {
llvm::APInt Len(Context.getIntWidth(SizeType), Literal.GetNumStringChars());
IntegerLiteral *LenArg = IntegerLiteral::Create(Context, Len, SizeType,
StringTokLocs[0]);
Expr *Args[] = { Lit, LenArg };
return BuildLiteralOperatorCall(R, OpNameInfo, Args, StringTokLocs.back());
}
case LOLR_StringTemplate: {
TemplateArgumentListInfo ExplicitArgs;
unsigned CharBits = Context.getIntWidth(CharTy);
bool CharIsUnsigned = CharTy->isUnsignedIntegerType();
llvm::APSInt Value(CharBits, CharIsUnsigned);
TemplateArgument TypeArg(CharTy);
TemplateArgumentLocInfo TypeArgInfo(Context.getTrivialTypeSourceInfo(CharTy));
ExplicitArgs.addArgument(TemplateArgumentLoc(TypeArg, TypeArgInfo));
for (unsigned I = 0, N = Lit->getLength(); I != N; ++I) {
Value = Lit->getCodeUnit(I);
TemplateArgument Arg(Context, Value, CharTy);
TemplateArgumentLocInfo ArgInfo;
ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo));
}
return BuildLiteralOperatorCall(R, OpNameInfo, None, StringTokLocs.back(),
&ExplicitArgs);
}
case LOLR_Raw:
case LOLR_Template:
case LOLR_ErrorNoDiagnostic:
llvm_unreachable("unexpected literal operator lookup result");
case LOLR_Error:
return ExprError();
}
llvm_unreachable("unexpected literal operator lookup result");
}
ExprResult
Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
SourceLocation Loc,
const CXXScopeSpec *SS) {
DeclarationNameInfo NameInfo(D->getDeclName(), Loc);
return BuildDeclRefExpr(D, Ty, VK, NameInfo, SS);
}
/// BuildDeclRefExpr - Build an expression that references a
/// declaration that does not require a closure capture.
ExprResult
Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
const DeclarationNameInfo &NameInfo,
const CXXScopeSpec *SS, NamedDecl *FoundD,
const TemplateArgumentListInfo *TemplateArgs) {
bool RefersToCapturedVariable =
isa<VarDecl>(D) &&
NeedToCaptureVariable(cast<VarDecl>(D), NameInfo.getLoc());
DeclRefExpr *E;
if (isa<VarTemplateSpecializationDecl>(D)) {
VarTemplateSpecializationDecl *VarSpec =
cast<VarTemplateSpecializationDecl>(D);
E = DeclRefExpr::Create(Context, SS ? SS->getWithLocInContext(Context)
: NestedNameSpecifierLoc(),
VarSpec->getTemplateKeywordLoc(), D,
RefersToCapturedVariable, NameInfo.getLoc(), Ty, VK,
FoundD, TemplateArgs);
} else {
assert(!TemplateArgs && "No template arguments for non-variable"
" template specialization references");
E = DeclRefExpr::Create(Context, SS ? SS->getWithLocInContext(Context)
: NestedNameSpecifierLoc(),
SourceLocation(), D, RefersToCapturedVariable,
NameInfo, Ty, VK, FoundD);
}
MarkDeclRefReferenced(E);
if (getLangOpts().ObjCWeak && isa<VarDecl>(D) &&
Ty.getObjCLifetime() == Qualifiers::OCL_Weak && !isUnevaluatedContext() &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getBeginLoc()))
getCurFunction()->recordUseOfWeak(E);
FieldDecl *FD = dyn_cast<FieldDecl>(D);
if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(D))
FD = IFD->getAnonField();
if (FD) {
UnusedPrivateFields.remove(FD);
// Just in case we're building an illegal pointer-to-member.
if (FD->isBitField())
E->setObjectKind(OK_BitField);
}
// C++ [expr.prim]/8: The expression [...] is a bit-field if the identifier
// designates a bit-field.
if (auto *BD = dyn_cast<BindingDecl>(D))
if (auto *BE = BD->getBinding())
E->setObjectKind(BE->getObjectKind());
return E;
}
/// Decomposes the given name into a DeclarationNameInfo, its location, and
/// possibly a list of template arguments.
///
/// If this produces template arguments, it is permitted to call
/// DecomposeTemplateName.
///
/// This actually loses a lot of source location information for
/// non-standard name kinds; we should consider preserving that in
/// some way.
void
Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id,
TemplateArgumentListInfo &Buffer,
DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *&TemplateArgs) {
if (Id.getKind() == UnqualifiedIdKind::IK_TemplateId) {
Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc);
Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc);
ASTTemplateArgsPtr TemplateArgsPtr(Id.TemplateId->getTemplateArgs(),
Id.TemplateId->NumArgs);
translateTemplateArguments(TemplateArgsPtr, Buffer);
TemplateName TName = Id.TemplateId->Template.get();
SourceLocation TNameLoc = Id.TemplateId->TemplateNameLoc;
NameInfo = Context.getNameForTemplate(TName, TNameLoc);
TemplateArgs = &Buffer;
} else {
NameInfo = GetNameFromUnqualifiedId(Id);
TemplateArgs = nullptr;
}
}
static void emitEmptyLookupTypoDiagnostic(
const TypoCorrection &TC, Sema &SemaRef, const CXXScopeSpec &SS,
DeclarationName Typo, SourceLocation TypoLoc, ArrayRef<Expr *> Args,
unsigned DiagnosticID, unsigned DiagnosticSuggestID) {
DeclContext *Ctx =
SS.isEmpty() ? nullptr : SemaRef.computeDeclContext(SS, false);
if (!TC) {
// Emit a special diagnostic for failed member lookups.
// FIXME: computing the declaration context might fail here (?)
if (Ctx)
SemaRef.Diag(TypoLoc, diag::err_no_member) << Typo << Ctx
<< SS.getRange();
else
SemaRef.Diag(TypoLoc, DiagnosticID) << Typo;
return;
}
std::string CorrectedStr = TC.getAsString(SemaRef.getLangOpts());
bool DroppedSpecifier =
TC.WillReplaceSpecifier() && Typo.getAsString() == CorrectedStr;
unsigned NoteID = TC.getCorrectionDeclAs<ImplicitParamDecl>()
? diag::note_implicit_param_decl
: diag::note_previous_decl;
if (!Ctx)
SemaRef.diagnoseTypo(TC, SemaRef.PDiag(DiagnosticSuggestID) << Typo,
SemaRef.PDiag(NoteID));
else
SemaRef.diagnoseTypo(TC, SemaRef.PDiag(diag::err_no_member_suggest)
<< Typo << Ctx << DroppedSpecifier
<< SS.getRange(),
SemaRef.PDiag(NoteID));
}
/// Diagnose an empty lookup.
///
/// \return false if new lookup candidates were found
bool
Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
std::unique_ptr<CorrectionCandidateCallback> CCC,
TemplateArgumentListInfo *ExplicitTemplateArgs,
ArrayRef<Expr *> Args, TypoExpr **Out) {
DeclarationName Name = R.getLookupName();
unsigned diagnostic = diag::err_undeclared_var_use;
unsigned diagnostic_suggest = diag::err_undeclared_var_use_suggest;
if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
Name.getNameKind() == DeclarationName::CXXLiteralOperatorName ||
Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
diagnostic = diag::err_undeclared_use;
diagnostic_suggest = diag::err_undeclared_use_suggest;
}
// If the original lookup was an unqualified lookup, fake an
// unqualified lookup. This is useful when (for example) the
// original lookup would not have found something because it was a
// dependent name.
DeclContext *DC = SS.isEmpty() ? CurContext : nullptr;
while (DC) {
if (isa<CXXRecordDecl>(DC)) {
LookupQualifiedName(R, DC);
if (!R.empty()) {
// Don't give errors about ambiguities in this lookup.
R.suppressDiagnostics();
// During a default argument instantiation the CurContext points
// to a CXXMethodDecl; but we can't apply a this-> fixit inside a
// function parameter list, hence add an explicit check.
bool isDefaultArgument =
!CodeSynthesisContexts.empty() &&
CodeSynthesisContexts.back().Kind ==
CodeSynthesisContext::DefaultFunctionArgumentInstantiation;
CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);
bool isInstance = CurMethod &&
CurMethod->isInstance() &&
DC == CurMethod->getParent() && !isDefaultArgument;
// Give a code modification hint to insert 'this->'.
// TODO: fixit for inserting 'Base<T>::' in the other cases.
// Actually quite difficult!
if (getLangOpts().MSVCCompat)
diagnostic = diag::ext_found_via_dependent_bases_lookup;
if (isInstance) {
Diag(R.getNameLoc(), diagnostic) << Name
<< FixItHint::CreateInsertion(R.getNameLoc(), "this->");
CheckCXXThisCapture(R.getNameLoc());
} else {
Diag(R.getNameLoc(), diagnostic) << Name;
}
// Do we really want to note all of these?
for (NamedDecl *D : R)
Diag(D->getLocation(), diag::note_dependent_var_use);
// Return true if we are inside a default argument instantiation
// and the found name refers to an instance member function, otherwise
// the function calling DiagnoseEmptyLookup will try to create an
// implicit member call and this is wrong for default argument.
if (isDefaultArgument && ((*R.begin())->isCXXInstanceMember())) {
Diag(R.getNameLoc(), diag::err_member_call_without_object);
return true;
}
// Tell the callee to try to recover.
return false;
}
R.clear();
}
// In Microsoft mode, if we are performing lookup from within a friend
// function definition declared at class scope then we must set
// DC to the lexical parent to be able to search into the parent
// class.
if (getLangOpts().MSVCCompat && isa<FunctionDecl>(DC) &&
cast<FunctionDecl>(DC)->getFriendObjectKind() &&
DC->getLexicalParent()->isRecord())
DC = DC->getLexicalParent();
else
DC = DC->getParent();
}
// We didn't find anything, so try to correct for a typo.
TypoCorrection Corrected;
if (S && Out) {
SourceLocation TypoLoc = R.getNameLoc();
assert(!ExplicitTemplateArgs &&
"Diagnosing an empty lookup with explicit template args!");
*Out = CorrectTypoDelayed(
R.getLookupNameInfo(), R.getLookupKind(), S, &SS, std::move(CCC),
[=](const TypoCorrection &TC) {
emitEmptyLookupTypoDiagnostic(TC, *this, SS, Name, TypoLoc, Args,
diagnostic, diagnostic_suggest);
},
nullptr, CTK_ErrorRecovery);
if (*Out)
return true;
} else if (S && (Corrected =
CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S,
&SS, std::move(CCC), CTK_ErrorRecovery))) {
std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
bool DroppedSpecifier =
Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr;
R.setLookupName(Corrected.getCorrection());
bool AcceptableWithRecovery = false;
bool AcceptableWithoutRecovery = false;
NamedDecl *ND = Corrected.getFoundDecl();
if (ND) {
if (Corrected.isOverloaded()) {
OverloadCandidateSet OCS(R.getNameLoc(),
OverloadCandidateSet::CSK_Normal);
OverloadCandidateSet::iterator Best;
for (NamedDecl *CD : Corrected) {
if (FunctionTemplateDecl *FTD =
dyn_cast<FunctionTemplateDecl>(CD))
AddTemplateOverloadCandidate(
FTD, DeclAccessPair::make(FTD, AS_none), ExplicitTemplateArgs,
Args, OCS);
else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(CD))
if (!ExplicitTemplateArgs || ExplicitTemplateArgs->size() == 0)
AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none),
Args, OCS);
}
switch (OCS.BestViableFunction(*this, R.getNameLoc(), Best)) {
case OR_Success:
ND = Best->FoundDecl;
Corrected.setCorrectionDecl(ND);
break;
default:
// FIXME: Arbitrarily pick the first declaration for the note.
Corrected.setCorrectionDecl(ND);
break;
}
}
R.addDecl(ND);
if (getLangOpts().CPlusPlus && ND->isCXXClassMember()) {
CXXRecordDecl *Record = nullptr;
if (Corrected.getCorrectionSpecifier()) {
const Type *Ty = Corrected.getCorrectionSpecifier()->getAsType();
Record = Ty->getAsCXXRecordDecl();
}
if (!Record)
Record = cast<CXXRecordDecl>(
ND->getDeclContext()->getRedeclContext());
R.setNamingClass(Record);
}
auto *UnderlyingND = ND->getUnderlyingDecl();
AcceptableWithRecovery = isa<ValueDecl>(UnderlyingND) ||
isa<FunctionTemplateDecl>(UnderlyingND);
// FIXME: If we ended up with a typo for a type name or
// Objective-C class name, we're in trouble because the parser
// is in the wrong place to recover. Suggest the typo
// correction, but don't make it a fix-it since we're not going
// to recover well anyway.
AcceptableWithoutRecovery =
isa<TypeDecl>(UnderlyingND) || isa<ObjCInterfaceDecl>(UnderlyingND);
} else {
// FIXME: We found a keyword. Suggest it, but don't provide a fix-it
// because we aren't able to recover.
AcceptableWithoutRecovery = true;
}
if (AcceptableWithRecovery || AcceptableWithoutRecovery) {
unsigned NoteID = Corrected.getCorrectionDeclAs<ImplicitParamDecl>()
? diag::note_implicit_param_decl
: diag::note_previous_decl;
if (SS.isEmpty())
diagnoseTypo(Corrected, PDiag(diagnostic_suggest) << Name,
PDiag(NoteID), AcceptableWithRecovery);
else
diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest)
<< Name << computeDeclContext(SS, false)
<< DroppedSpecifier << SS.getRange(),
PDiag(NoteID), AcceptableWithRecovery);
// Tell the callee whether to try to recover.
return !AcceptableWithRecovery;
}
}
R.clear();
// Emit a special diagnostic for failed member lookups.
// FIXME: computing the declaration context might fail here (?)
if (!SS.isEmpty()) {
Diag(R.getNameLoc(), diag::err_no_member)
<< Name << computeDeclContext(SS, false)
<< SS.getRange();
return true;
}
// Give up, we can't recover.
Diag(R.getNameLoc(), diagnostic) << Name;
return true;
}
/// In Microsoft mode, if we are inside a template class whose parent class has
/// dependent base classes, and we can't resolve an unqualified identifier, then
/// assume the identifier is a member of a dependent base class. We can only
/// recover successfully in static methods, instance methods, and other contexts
/// where 'this' is available. This doesn't precisely match MSVC's
/// instantiation model, but it's close enough.
static Expr *
recoverFromMSUnqualifiedLookup(Sema &S, ASTContext &Context,
DeclarationNameInfo &NameInfo,
SourceLocation TemplateKWLoc,
const TemplateArgumentListInfo *TemplateArgs) {
// Only try to recover from lookup into dependent bases in static methods or
// contexts where 'this' is available.
QualType ThisType = S.getCurrentThisType();
const CXXRecordDecl *RD = nullptr;
if (!ThisType.isNull())
RD = ThisType->getPointeeType()->getAsCXXRecordDecl();
else if (auto *MD = dyn_cast<CXXMethodDecl>(S.CurContext))
RD = MD->getParent();
if (!RD || !RD->hasAnyDependentBases())
return nullptr;
// Diagnose this as unqualified lookup into a dependent base class. If 'this'
// is available, suggest inserting 'this->' as a fixit.
SourceLocation Loc = NameInfo.getLoc();
auto DB = S.Diag(Loc, diag::ext_undeclared_unqual_id_with_dependent_base);
DB << NameInfo.getName() << RD;
if (!ThisType.isNull()) {
DB << FixItHint::CreateInsertion(Loc, "this->");
return CXXDependentScopeMemberExpr::Create(
Context, /*This=*/nullptr, ThisType, /*IsArrow=*/true,
/*Op=*/SourceLocation(), NestedNameSpecifierLoc(), TemplateKWLoc,
/*FirstQualifierInScope=*/nullptr, NameInfo, TemplateArgs);
}
// Synthesize a fake NNS that points to the derived class. This will
// perform name lookup during template instantiation.
CXXScopeSpec SS;
auto *NNS =
NestedNameSpecifier::Create(Context, nullptr, true, RD->getTypeForDecl());
SS.MakeTrivial(Context, NNS, SourceRange(Loc, Loc));
return DependentScopeDeclRefExpr::Create(
Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo,
TemplateArgs);
}
ExprResult
Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
SourceLocation TemplateKWLoc, UnqualifiedId &Id,
bool HasTrailingLParen, bool IsAddressOfOperand,
std::unique_ptr<CorrectionCandidateCallback> CCC,
bool IsInlineAsmIdentifier, Token *KeywordReplacement) {
assert(!(IsAddressOfOperand && HasTrailingLParen) &&
"cannot be direct & operand and have a trailing lparen");
if (SS.isInvalid())
return ExprError();
TemplateArgumentListInfo TemplateArgsBuffer;
// Decompose the UnqualifiedId into the following data.
DeclarationNameInfo NameInfo;
const TemplateArgumentListInfo *TemplateArgs;
DecomposeUnqualifiedId(Id, TemplateArgsBuffer, NameInfo, TemplateArgs);
DeclarationName Name = NameInfo.getName();
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,
// (note: handled after lookup)
// -- a template-id that is dependent,
// (note: handled in BuildTemplateIdExpr)
// -- a conversion-function-id that specifies a dependent type,
// -- a nested-name-specifier that contains a class-name that
// names a dependent type.
// Determine whether this is a member of an unknown specialization;
// we need to handle these differently.
bool DependentID = false;
if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
Name.getCXXNameType()->isDependentType()) {
DependentID = true;
} else if (SS.isSet()) {
if (DeclContext *DC = computeDeclContext(SS, false)) {
if (RequireCompleteDeclContext(SS, DC))
return ExprError();
} else {
DependentID = true;
}
}
if (DependentID)
return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
IsAddressOfOperand, TemplateArgs);
// Perform the required lookup.
LookupResult R(*this, NameInfo,
(Id.getKind() == UnqualifiedIdKind::IK_ImplicitSelfParam)
? LookupObjCImplicitSelfParam
: LookupOrdinaryName);
if (TemplateKWLoc.isValid() || TemplateArgs) {
// Lookup the template name again to correctly establish the context in
// which it was found. This is really unfortunate as we already did the
// lookup to determine that it was a template name in the first place. If
// this becomes a performance hit, we can work harder to preserve those
// results until we get here but it's likely not worth it.
bool MemberOfUnknownSpecialization;
if (LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false,
MemberOfUnknownSpecialization, TemplateKWLoc))
return ExprError();
if (MemberOfUnknownSpecialization ||
(R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation))
return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
IsAddressOfOperand, TemplateArgs);
} else {
bool IvarLookupFollowUp = II && !SS.isSet() && getCurMethodDecl();
LookupParsedName(R, S, &SS, !IvarLookupFollowUp);
// If the result might be in a dependent base class, this is a dependent
// id-expression.
if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)
return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo,
IsAddressOfOperand, TemplateArgs);
// If this reference is in an Objective-C method, then we need to do
// some special Objective-C lookup, too.
if (IvarLookupFollowUp) {
ExprResult E(LookupInObjCMethod(R, S, II, true));
if (E.isInvalid())
return ExprError();
if (Expr *Ex = E.getAs<Expr>())
return Ex;
}
}
if (R.isAmbiguous())
return ExprError();
// This could be an implicitly declared function reference (legal in C90,
// extension in C99, forbidden in C++).
if (R.empty() && HasTrailingLParen && II && !getLangOpts().CPlusPlus) {
NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S);
if (D) R.addDecl(D);
}
// Determine whether this name might be a candidate for
// argument-dependent lookup.
bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen);
if (R.empty() && !ADL) {
if (SS.isEmpty() && getLangOpts().MSVCCompat) {
if (Expr *E = recoverFromMSUnqualifiedLookup(*this, Context, NameInfo,
TemplateKWLoc, TemplateArgs))
return E;
}
// Don't diagnose an empty lookup for inline assembly.
if (IsInlineAsmIdentifier)
return ExprError();
// If this name wasn't predeclared and if this is not a function
// call, diagnose the problem.
TypoExpr *TE = nullptr;
auto DefaultValidator = llvm::make_unique<CorrectionCandidateCallback>(
II, SS.isValid() ? SS.getScopeRep() : nullptr);
DefaultValidator->IsAddressOfOperand = IsAddressOfOperand;
assert((!CCC || CCC->IsAddressOfOperand == IsAddressOfOperand) &&
"Typo correction callback misconfigured");
if (CCC) {
// Make sure the callback knows what the typo being diagnosed is.
CCC->setTypoName(II);
if (SS.isValid())
CCC->setTypoNNS(SS.getScopeRep());
}
// FIXME: DiagnoseEmptyLookup produces bad diagnostics if we're looking for
// a template name, but we happen to have always already looked up the name
// before we get here if it must be a template name.
if (DiagnoseEmptyLookup(S, SS, R,
CCC ? std::move(CCC) : std::move(DefaultValidator),
nullptr, None, &TE)) {
if (TE && KeywordReplacement) {
auto &State = getTypoExprState(TE);
auto BestTC = State.Consumer->getNextCorrection();
if (BestTC.isKeyword()) {
auto *II = BestTC.getCorrectionAsIdentifierInfo();
if (State.DiagHandler)
State.DiagHandler(BestTC);
KeywordReplacement->startToken();
KeywordReplacement->setKind(II->getTokenID());
KeywordReplacement->setIdentifierInfo(II);
KeywordReplacement->setLocation(BestTC.getCorrectionRange().getBegin());
// Clean up the state associated with the TypoExpr, since it has
// now been diagnosed (without a call to CorrectDelayedTyposInExpr).
clearDelayedTypo(TE);
// Signal that a correction to a keyword was performed by returning a
// valid-but-null ExprResult.
return (Expr*)nullptr;
}
State.Consumer->resetCorrectionStream();
}
return TE ? TE : ExprError();
}
assert(!R.empty() &&
"DiagnoseEmptyLookup returned false but added no results");
// If we found an Objective-C instance variable, let
// LookupInObjCMethod build the appropriate expression to
// reference the ivar.
if (ObjCIvarDecl *Ivar = R.getAsSingle<ObjCIvarDecl>()) {
R.clear();
ExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier()));
// In a hopelessly buggy code, Objective-C instance variable
// lookup fails and no expression will be built to reference it.
if (!E.isInvalid() && !E.get())
return ExprError();
return E;
}
}
// This is guaranteed from this point on.
assert(!R.empty() || ADL);
// Check whether this might be a C++ implicit instance member access.
// C++ [class.mfct.non-static]p3:
// When an id-expression that is not part of a class member access
// syntax and not used to form a pointer to member is used in the
// body of a non-static member function of class X, if name lookup
// resolves the name in the id-expression to a non-static non-type
// member of some class C, the id-expression is transformed into a
// class member access expression using (*this) as the
// postfix-expression to the left of the . operator.
//
// But we don't actually need to do this for '&' operands if R
// resolved to a function or overloaded function set, because the
// expression is ill-formed if it actually works out to be a
// non-static member function:
//
// C++ [expr.ref]p4:
// Otherwise, if E1.E2 refers to a non-static member function. . .
// [t]he expression can be used only as the left-hand operand of a
// member function call.
//
// There are other safeguards against such uses, but it's important
// to get this right here so that we don't end up making a
// spuriously dependent expression if we're inside a dependent
// instance method.
if (!R.empty() && (*R.begin())->isCXXClassMember()) {
bool MightBeImplicitMember;
if (!IsAddressOfOperand)
MightBeImplicitMember = true;
else if (!SS.isEmpty())
MightBeImplicitMember = false;
else if (R.isOverloadedResult())
MightBeImplicitMember = false;
else if (R.isUnresolvableResult())
MightBeImplicitMember = true;
else
MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) ||
isa<IndirectFieldDecl>(R.getFoundDecl()) ||
isa<MSPropertyDecl>(R.getFoundDecl());
if (MightBeImplicitMember)
return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc,
R, TemplateArgs, S);
}
if (TemplateArgs || TemplateKWLoc.isValid()) {
// In C++1y, if this is a variable template id, then check it
// in BuildTemplateIdExpr().
// The single lookup result must be a variable template declaration.
if (Id.getKind() == UnqualifiedIdKind::IK_TemplateId && Id.TemplateId &&
Id.TemplateId->Kind == TNK_Var_template) {
assert(R.getAsSingle<VarTemplateDecl>() &&
"There should only be one declaration found.");
}
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, ADL, TemplateArgs);
}
return BuildDeclarationNameExpr(SS, R, ADL);
}
/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified
/// declaration name, generally during template instantiation.
/// There's a large number of things which don't need to be done along
/// this path.
ExprResult Sema::BuildQualifiedDeclarationNameExpr(
CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo,
bool IsAddressOfOperand, const Scope *S, TypeSourceInfo **RecoveryTSI) {
DeclContext *DC = computeDeclContext(SS, false);
if (!DC)
return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
NameInfo, /*TemplateArgs=*/nullptr);
if (RequireCompleteDeclContext(SS, DC))
return ExprError();
LookupResult R(*this, NameInfo, LookupOrdinaryName);
LookupQualifiedName(R, DC);
if (R.isAmbiguous())
return ExprError();
if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)
return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(),
NameInfo, /*TemplateArgs=*/nullptr);
if (R.empty()) {
Diag(NameInfo.getLoc(), diag::err_no_member)
<< NameInfo.getName() << DC << SS.getRange();
return ExprError();
}
if (const TypeDecl *TD = R.getAsSingle<TypeDecl>()) {
// Diagnose a missing typename if this resolved unambiguously to a type in
// a dependent context. If we can recover with a type, downgrade this to
// a warning in Microsoft compatibility mode.
unsigned DiagID = diag::err_typename_missing;
if (RecoveryTSI && getLangOpts().MSVCCompat)
DiagID = diag::ext_typename_missing;
SourceLocation Loc = SS.getBeginLoc();
auto D = Diag(Loc, DiagID);
D << SS.getScopeRep() << NameInfo.getName().getAsString()
<< SourceRange(Loc, NameInfo.getEndLoc());
// Don't recover if the caller isn't expecting us to or if we're in a SFINAE
// context.
if (!RecoveryTSI)
return ExprError();
// Only issue the fixit if we're prepared to recover.
D << FixItHint::CreateInsertion(Loc, "typename ");
// Recover by pretending this was an elaborated type.
QualType Ty = Context.getTypeDeclType(TD);
TypeLocBuilder TLB;
TLB.pushTypeSpec(Ty).setNameLoc(NameInfo.getLoc());
QualType ET = getElaboratedType(ETK_None, SS, Ty);
ElaboratedTypeLoc QTL = TLB.push<ElaboratedTypeLoc>(ET);
QTL.setElaboratedKeywordLoc(SourceLocation());
QTL.setQualifierLoc(SS.getWithLocInContext(Context));
*RecoveryTSI = TLB.getTypeSourceInfo(Context, ET);
return ExprEmpty();
}
// Defend against this resolving to an implicit member access. We usually
// won't get here if this might be a legitimate a class member (we end up in
// BuildMemberReferenceExpr instead), but this can be valid if we're forming
// a pointer-to-member or in an unevaluated context in C++11.
if (!R.empty() && (*R.begin())->isCXXClassMember() && !IsAddressOfOperand)
return BuildPossibleImplicitMemberExpr(SS,
/*TemplateKWLoc=*/SourceLocation(),
R, /*TemplateArgs=*/nullptr, S);
return BuildDeclarationNameExpr(SS, R, /* ADL */ false);
}
/// LookupInObjCMethod - The parser has read a name in, and Sema has
/// detected that we're currently inside an ObjC method. Perform some
/// additional lookup.
///
/// Ideally, most of this would be done by lookup, but there's
/// actually quite a lot of extra work involved.
///
/// Returns a null sentinel to indicate trivial success.
ExprResult
Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
IdentifierInfo *II, bool AllowBuiltinCreation) {
SourceLocation Loc = Lookup.getNameLoc();
ObjCMethodDecl *CurMethod = getCurMethodDecl();
// Check for error condition which is already reported.
if (!CurMethod)
return ExprError();
// There are two cases to handle here. 1) scoped lookup could have failed,
// in which case we should look for an ivar. 2) scoped lookup could have
// found a decl, but that decl is outside the current instance method (i.e.
// a global variable). In these two cases, we do a lookup for an ivar with
// this name, if the lookup sucedes, we replace it our current decl.
// If we're in a class method, we don't normally want to look for
// ivars. But if we don't find anything else, and there's an
// ivar, that's an error.
bool IsClassMethod = CurMethod->isClassMethod();
bool LookForIvars;
if (Lookup.empty())
LookForIvars = true;
else if (IsClassMethod)
LookForIvars = false;
else
LookForIvars = (Lookup.isSingleResult() &&
Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod());
ObjCInterfaceDecl *IFace = nullptr;
if (LookForIvars) {
IFace = CurMethod->getClassInterface();
ObjCInterfaceDecl *ClassDeclared;
ObjCIvarDecl *IV = nullptr;
if (IFace && (IV = IFace->lookupInstanceVariable(II, ClassDeclared))) {
// Diagnose using an ivar in a class method.
if (IsClassMethod)
return ExprError(Diag(Loc, diag::err_ivar_use_in_class_method)
<< IV->getDeclName());
// If we're referencing an invalid decl, just return this as a silent
// error node. The error diagnostic was already emitted on the decl.
if (IV->isInvalidDecl())
return ExprError();
// Check if referencing a field with __attribute__((deprecated)).
if (DiagnoseUseOfDecl(IV, Loc))
return ExprError();
// Diagnose the use of an ivar outside of the declaring class.
if (IV->getAccessControl() == ObjCIvarDecl::Private &&
!declaresSameEntity(ClassDeclared, IFace) &&
!getLangOpts().DebuggerSupport)
Diag(Loc, diag::err_private_ivar_access) << IV->getDeclName();
// FIXME: This should use a new expr for a direct reference, don't
// turn this into Self->ivar, just return a BareIVarExpr or something.
IdentifierInfo &II = Context.Idents.get("self");
UnqualifiedId SelfName;
SelfName.setIdentifier(&II, SourceLocation());
SelfName.setKind(UnqualifiedIdKind::IK_ImplicitSelfParam);
CXXScopeSpec SelfScopeSpec;
SourceLocation TemplateKWLoc;
ExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, TemplateKWLoc,
SelfName, false, false);
if (SelfExpr.isInvalid())
return ExprError();
SelfExpr = DefaultLvalueConversion(SelfExpr.get());
if (SelfExpr.isInvalid())
return ExprError();
MarkAnyDeclReferenced(Loc, IV, true);
ObjCMethodFamily MF = CurMethod->getMethodFamily();
if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&
!IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV))
Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName();
ObjCIvarRefExpr *Result = new (Context)
ObjCIvarRefExpr(IV, IV->getUsageType(SelfExpr.get()->getType()), Loc,
IV->getLocation(), SelfExpr.get(), true, true);
if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
if (!isUnevaluatedContext() &&
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, Loc))
getCurFunction()->recordUseOfWeak(Result);
}
if (getLangOpts().ObjCAutoRefCount) {
if (CurContext->isClosure())
Diag(Loc, diag::warn_implicitly_retains_self)
<< FixItHint::CreateInsertion(Loc, "self->");
}
return Result;
}
} else if (CurMethod->isInstanceMethod()) {
// We should warn if a local variable hides an ivar.
if (ObjCInterfaceDecl *IFace = CurMethod->getClassInterface()) {
ObjCInterfaceDecl *ClassDeclared;
if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) {
if (IV->getAccessControl() != ObjCIvarDecl::Private ||
declaresSameEntity(IFace, ClassDeclared))
Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName();
}
}
} else if (Lookup.isSingleResult() &&
Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()) {
// If accessing a stand-alone ivar in a class method, this is an error.
if (const ObjCIvarDecl *IV = dyn_cast<ObjCIvarDecl>(Lookup.getFoundDecl()))
return ExprError(Diag(Loc, diag::err_ivar_use_in_class_method)
<< IV->getDeclName());
}
if (Lookup.empty() && II && AllowBuiltinCreation) {
// FIXME. Consolidate this with similar code in LookupName.
if (unsigned BuiltinID = II->getBuiltinID()) {
if (!(getLangOpts().CPlusPlus &&
Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))) {
NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
S, Lookup.isForRedeclaration(),
Lookup.getNameLoc());
if (D) Lookup.addDecl(D);
}
}
}
// Sentinel value saying that we didn't do anything special.
return ExprResult((Expr *)nullptr);
}
/// Cast a base object to a member's actual type.
///
/// Logically this happens in three phases:
///
/// * First we cast from the base type to the naming class.
/// The naming class is the class into which we were looking
/// when we found the member; it's the qualifier type if a
/// qualifier was provided, and otherwise it's the base type.
///
/// * Next we cast from the naming class to the declaring class.
/// If the member we found was brought into a class's scope by
/// a using declaration, this is that class; otherwise it's
/// the class declaring the member.
///
/// * Finally we cast from the declaring class to the "true"
/// declaring class of the member. This conversion does not
/// obey access control.
ExprResult
Sema::PerformObjectMemberConversion(Expr *From,
NestedNameSpecifier *Qualifier,
NamedDecl *FoundDecl,
NamedDecl *Member) {
CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext());
if (!RD)
return From;
QualType DestRecordType;
QualType DestType;
QualType FromRecordType;
QualType FromType = From->getType();
bool PointerConversions = false;
if (isa<FieldDecl>(Member)) {
DestRecordType = Context.getCanonicalType(Context.getTypeDeclType(RD));
if (FromType->getAs<PointerType>()) {
DestType = Context.getPointerType(DestRecordType);
FromRecordType = FromType->getPointeeType();
PointerConversions = true;
} else {
DestType = DestRecordType;
FromRecordType = FromType;
}
} else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member)) {
if (Method->isStatic())
return From;
DestType = Method->getThisType();
DestRecordType = DestType->getPointeeType();
if (FromType->getAs<PointerType>()) {
FromRecordType = FromType->getPointeeType();
PointerConversions = true;
} else {
FromRecordType = FromType;
DestType = DestRecordType;
}
} else {
// No conversion necessary.
return From;
}
if (DestType->isDependentType() || FromType->isDependentType())
return From;
// If the unqualified types are the same, no conversion is necessary.
if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))
return From;
SourceRange FromRange = From->getSourceRange();
SourceLocation FromLoc = FromRange.getBegin();
ExprValueKind VK = From->getValueKind();
// C++ [class.member.lookup]p8:
// [...] Ambiguities can often be resolved by qualifying a name with its
// class name.
//
// If the member was a qualified name and the qualified referred to a
// specific base subobject type, we'll cast to that intermediate type
// first and then to the object in which the member is declared. That allows
// one to resolve ambiguities in, e.g., a diamond-shaped hierarchy such as:
//
// class Base { public: int x; };
// class Derived1 : public Base { };
// class Derived2 : public Base { };
// class VeryDerived : public Derived1, public Derived2 { void f(); };
//
// void VeryDerived::f() {
// x = 17; // error: ambiguous base subobjects
// Derived1::x = 17; // okay, pick the Base subobject of Derived1
// }
if (Qualifier && Qualifier->getAsType()) {
QualType QType = QualType(Qualifier->getAsType(), 0);
assert(QType->isRecordType() && "lookup done with non-record type");
QualType QRecordType = QualType(QType->getAs<RecordType>(), 0);
// In C++98, the qualifier type doesn't actually have to be a base
// type of the object type, in which case we just ignore it.
// Otherwise build the appropriate casts.
if (IsDerivedFrom(FromLoc, FromRecordType, QRecordType)) {
CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, QRecordType,
FromLoc, FromRange, &BasePath))
return ExprError();
if (PointerConversions)
QType = Context.getPointerType(QType);
From = ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase,
VK, &BasePath).get();
FromType = QType;
FromRecordType = QRecordType;
// If the qualifier type was the same as the destination type,
// we're done.
if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))
return From;
}
}
bool IgnoreAccess = false;
// If we actually found the member through a using declaration, cast
// down to the using declaration's type.
//
// Pointer equality is fine here because only one declaration of a
// class ever has member declarations.
if (FoundDecl->getDeclContext() != Member->getDeclContext()) {
assert(isa<UsingShadowDecl>(FoundDecl));
QualType URecordType = Context.getTypeDeclType(
cast<CXXRecordDecl>(FoundDecl->getDeclContext()));
// We only need to do this if the naming-class to declaring-class
// conversion is non-trivial.
if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) {
assert(IsDerivedFrom(FromLoc, FromRecordType, URecordType));
CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, URecordType,
FromLoc, FromRange, &BasePath))
return ExprError();
QualType UType = URecordType;
if (PointerConversions)
UType = Context.getPointerType(UType);
From = ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase,
VK, &BasePath).get();
FromType = UType;
FromRecordType = URecordType;
}
// We don't do access control for the conversion from the
// declaring class to the true declaring class.
IgnoreAccess = true;
}
CXXCastPath BasePath;
if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType,
FromLoc, FromRange, &BasePath,
IgnoreAccess))
return ExprError();
return ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase,
VK, &BasePath);
}
bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
const LookupResult &R,
bool HasTrailingLParen) {
// Only when used directly as the postfix-expression of a call.
if (!HasTrailingLParen)
return false;
// Never if a scope specifier was provided.
if (SS.isSet())
return false;
// Only in C++ or ObjC++.
if (!getLangOpts().CPlusPlus)
return false;
// Turn off ADL when we find certain kinds of declarations during
// normal lookup:
for (NamedDecl *D : R) {
// C++0x [basic.lookup.argdep]p3:
// -- a declaration of a class member
// Since using decls preserve this property, we check this on the
// original decl.
if (D->isCXXClassMember())
return false;
// C++0x [basic.lookup.argdep]p3:
// -- a block-scope function declaration that is not a
// using-declaration
// NOTE: we also trigger this for function templates (in fact, we
// don't check the decl type at all, since all other decl types
// turn off ADL anyway).
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
else if (D->getLexicalDeclContext()->isFunctionOrMethod())
return false;
// C++0x [basic.lookup.argdep]p3:
// -- a declaration that is neither a function or a function
// template
// And also for builtin functions.
if (isa<FunctionDecl>(D)) {
FunctionDecl *FDecl = cast<FunctionDecl>(D);
// But also builtin functions.
if (FDecl->getBuiltinID() && FDecl->isImplicit())
return false;
} else if (!isa<FunctionTemplateDecl>(D))
return false;
}
return true;
}
/// Diagnoses obvious problems with the use of the given declaration
/// as an expression. This is only actually called for lookups that
/// were not overloaded, and it doesn't promise that the declaration
/// will in fact be used.
static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) {
if (D->isInvalidDecl())
return true;
if (isa<TypedefNameDecl>(D)) {
S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName();
return true;
}
if (isa<ObjCInterfaceDecl>(D)) {
S.Diag(Loc, diag::err_unexpected_interface) << D->getDeclName();
return true;
}
if (isa<NamespaceDecl>(D)) {
S.Diag(Loc, diag::err_unexpected_namespace) << D->getDeclName();
return true;
}
return false;
}
// Certain multiversion types should be treated as overloaded even when there is
// only one result.
static bool ShouldLookupResultBeMultiVersionOverload(const LookupResult &R) {
assert(R.isSingleResult() && "Expected only a single result");
const auto *FD = dyn_cast<FunctionDecl>(R.getFoundDecl());
return FD &&
(FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion());
}
ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
LookupResult &R, bool NeedsADL,
bool AcceptInvalidDecl) {
// If this is a single, fully-resolved result and we don't need ADL,
// just build an ordinary singleton decl ref.
if (!NeedsADL && R.isSingleResult() &&
!R.getAsSingle<FunctionTemplateDecl>() &&
!ShouldLookupResultBeMultiVersionOverload(R))
return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(),
R.getRepresentativeDecl(), nullptr,
AcceptInvalidDecl);
// We only need to check the declaration if there's exactly one
// result, because in the overloaded case the results can only be
// functions and function templates.
if (R.isSingleResult() && !ShouldLookupResultBeMultiVersionOverload(R) &&
CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl()))
return ExprError();
// Otherwise, just build an unresolved lookup expression. Suppress
// any lookup-related diagnostics; we'll hash these out later, when
// we've picked a target.
R.suppressDiagnostics();
UnresolvedLookupExpr *ULE
= UnresolvedLookupExpr::Create(Context, R.getNamingClass(),
SS.getWithLocInContext(Context),
R.getLookupNameInfo(),
NeedsADL, R.isOverloadedResult(),
R.begin(), R.end());
return ULE;
}
static void
diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
ValueDecl *var, DeclContext *DC);
/// Complete semantic analysis for a reference to the given declaration.
ExprResult Sema::BuildDeclarationNameExpr(
const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs,
bool AcceptInvalidDecl) {
assert(D && "Cannot refer to a NULL declaration");
assert(!isa<FunctionTemplateDecl>(D) &&
"Cannot refer unambiguously to a function template");
SourceLocation Loc = NameInfo.getLoc();
if (CheckDeclInExpr(*this, Loc, D))
return ExprError();
if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
// Specifically diagnose references to class templates that are missing
// a template argument list.
diagnoseMissingTemplateArguments(TemplateName(Template), Loc);
return ExprError();
}
// Make sure that we're referring to a value.
ValueDecl *VD = dyn_cast<ValueDecl>(D);
if (!VD) {
Diag(Loc, diag::err_ref_non_value)
<< D << SS.getRange();
Diag(D->getLocation(), diag::note_declared_at);
return ExprError();
}
// Check whether this declaration can be used. Note that we suppress
// this check when we're going to perform argument-dependent lookup
// on this function name, because this might not be the function
// that overload resolution actually selects.
if (DiagnoseUseOfDecl(VD, Loc))
return ExprError();
// Only create DeclRefExpr's for valid Decl's.
if (VD->isInvalidDecl() && !AcceptInvalidDecl)
return ExprError();
// Handle members of anonymous structs and unions. If we got here,
// and the reference is to a class member indirect field, then this
// must be the subject of a pointer-to-member expression.
if (IndirectFieldDecl *indirectField = dyn_cast<IndirectFieldDecl>(VD))
if (!indirectField->isCXXClassMember())
return BuildAnonymousStructUnionMemberReference(SS, NameInfo.getLoc(),
indirectField);
{
QualType type = VD->getType();
if (type.isNull())
return ExprError();
if (auto *FPT = type->getAs<FunctionProtoType>()) {
// C++ [except.spec]p17:
// An exception-specification is considered to be needed when:
// - in an expression, the function is the unique lookup result or
// the selected member of a set of overloaded functions.
ResolveExceptionSpec(Loc, FPT);
type = VD->getType();
}
ExprValueKind valueKind = VK_RValue;
switch (D->getKind()) {
// Ignore all the non-ValueDecl kinds.
#define ABSTRACT_DECL(kind)
#define VALUE(type, base)
#define DECL(type, base) \
case Decl::type:
#include "clang/AST/DeclNodes.inc"
llvm_unreachable("invalid value decl kind");
// These shouldn't make it here.
case Decl::ObjCAtDefsField:
case Decl::ObjCIvar:
llvm_unreachable("forming non-member reference to ivar?");
// Enum constants are always r-values and never references.
// Unresolved using declarations are dependent.
case Decl::EnumConstant:
case Decl::UnresolvedUsingValue:
case Decl::OMPDeclareReduction:
valueKind = VK_RValue;
break;
// Fields and indirect fields that got here must be for
// pointer-to-member expressions; we just call them l-values for
// internal consistency, because this subexpression doesn't really
// exist in the high-level semantics.
case Decl::Field:
case Decl::IndirectField:
assert(getLangOpts().CPlusPlus &&
"building reference to field in C?");
// These can't have reference type in well-formed programs, but
// for internal consistency we do this anyway.
type = type.getNonReferenceType();
valueKind = VK_LValue;
break;
// Non-type template parameters are either l-values or r-values
// depending on the type.
case Decl::NonTypeTemplateParm: {
if (const ReferenceType *reftype = type->getAs<ReferenceType>()) {
type = reftype->getPointeeType();
valueKind = VK_LValue; // even if the parameter is an r-value reference
break;
}
// For non-references, we need to strip qualifiers just in case
// the template parameter was declared as 'const int' or whatever.
valueKind = VK_RValue;
type = type.getUnqualifiedType();
break;
}
case Decl::Var:
case Decl::VarTemplateSpecialization:
case Decl::VarTemplatePartialSpecialization:
case Decl::Decomposition:
case Decl::OMPCapturedExpr:
// In C, "extern void blah;" is valid and is an r-value.
if (!getLangOpts().CPlusPlus &&
!type.hasQualifiers() &&
type->isVoidType()) {
valueKind = VK_RValue;
break;
}
LLVM_FALLTHROUGH;
case Decl::ImplicitParam:
case Decl::ParmVar: {
// These are always l-values.
valueKind = VK_LValue;
type = type.getNonReferenceType();
// FIXME: Does the addition of const really only apply in
// potentially-evaluated contexts? Since the variable isn't actually
// captured in an unevaluated context, it seems that the answer is no.
if (!isUnevaluatedContext()) {
QualType CapturedType = getCapturedDeclRefType(cast<VarDecl>(VD), Loc);
if (!CapturedType.isNull())
type = CapturedType;
}
break;
}
case Decl::Binding: {
// These are always lvalues.
valueKind = VK_LValue;
type = type.getNonReferenceType();
// FIXME: Support lambda-capture of BindingDecls, once CWG actually
// decides how that's supposed to work.
auto *BD = cast<BindingDecl>(VD);
if (BD->getDeclContext()->isFunctionOrMethod() &&
BD->getDeclContext() != CurContext)
diagnoseUncapturableValueReference(*this, Loc, BD, CurContext);
break;
}
case Decl::Function: {
if (unsigned BID = cast<FunctionDecl>(VD)->getBuiltinID()) {
if (!Context.BuiltinInfo.isPredefinedLibFunction(BID)) {
type = Context.BuiltinFnTy;
valueKind = VK_RValue;
break;
}
}
const FunctionType *fty = type->castAs<FunctionType>();
// If we're referring to a function with an __unknown_anytype
// result type, make the entire expression __unknown_anytype.
if (fty->getReturnType() == Context.UnknownAnyTy) {
type = Context.UnknownAnyTy;
valueKind = VK_RValue;
break;
}
// Functions are l-values in C++.
if (getLangOpts().CPlusPlus) {
valueKind = VK_LValue;
break;
}
// C99 DR 316 says that, if a function type comes from a
// function definition (without a prototype), that type is only
// used for checking compatibility. Therefore, when referencing
// the function, we pretend that we don't have the full function
// type.
if (!cast<FunctionDecl>(VD)->hasPrototype() &&
isa<FunctionProtoType>(fty))
type = Context.getFunctionNoProtoType(fty->getReturnType(),
fty->getExtInfo());
// Functions are r-values in C.
valueKind = VK_RValue;
break;
}
case Decl::CXXDeductionGuide:
llvm_unreachable("building reference to deduction guide");
case Decl::MSProperty:
valueKind = VK_LValue;
break;
case Decl::CXXMethod:
// If we're referring to a method with an __unknown_anytype
// result type, make the entire expression __unknown_anytype.
// This should only be possible with a type written directly.
if (const FunctionProtoType *proto
= dyn_cast<FunctionProtoType>(VD->getType()))
if (proto->getReturnType() == Context.UnknownAnyTy) {
type = Context.UnknownAnyTy;
valueKind = VK_RValue;
break;
}
// C++ methods are l-values if static, r-values if non-static.
if (cast<CXXMethodDecl>(VD)->isStatic()) {
valueKind = VK_LValue;
break;
}
LLVM_FALLTHROUGH;
case Decl::CXXConversion:
case Decl::CXXDestructor:
case Decl::CXXConstructor:
valueKind = VK_RValue;
break;
}
return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD,
TemplateArgs);
}
}
static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,
SmallString<32> &Target) {
Target.resize(CharByteWidth * (Source.size() + 1));
char *ResultPtr = &Target[0];
const llvm::UTF8 *ErrorPtr;
bool success =
llvm::ConvertUTF8toWide(CharByteWidth, Source, ResultPtr, ErrorPtr);
(void)success;
assert(success);
Target.resize(ResultPtr - &Target[0]);
}
ExprResult Sema::BuildPredefinedExpr(SourceLocation Loc,
PredefinedExpr::IdentKind IK) {
// Pick the current block, lambda, captured statement or function.
Decl *currentDecl = nullptr;
if (const BlockScopeInfo *BSI = getCurBlock())
currentDecl = BSI->TheDecl;
else if (const LambdaScopeInfo *LSI = getCurLambda())
currentDecl = LSI->CallOperator;
else if (const CapturedRegionScopeInfo *CSI = getCurCapturedRegion())
currentDecl = CSI->TheCapturedDecl;
else
currentDecl = getCurFunctionOrMethodDecl();
if (!currentDecl) {
Diag(Loc, diag::ext_predef_outside_function);
currentDecl = Context.getTranslationUnitDecl();
}
QualType ResTy;
StringLiteral *SL = nullptr;
if (cast<DeclContext>(currentDecl)->isDependentContext())
ResTy = Context.DependentTy;
else {
// Pre-defined identifiers are of type char[x], where x is the length of
// the string.
auto Str = PredefinedExpr::ComputeName(IK, currentDecl);
unsigned Length = Str.length();
llvm::APInt LengthI(32, Length + 1);
if (IK == PredefinedExpr::LFunction || IK == PredefinedExpr::LFuncSig) {
ResTy =
Context.adjustStringLiteralBaseType(Context.WideCharTy.withConst());
SmallString<32> RawChars;
ConvertUTF8ToWideString(Context.getTypeSizeInChars(ResTy).getQuantity(),
Str, RawChars);
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal,
/*IndexTypeQuals*/ 0);
SL = StringLiteral::Create(Context, RawChars, StringLiteral::Wide,
/*Pascal*/ false, ResTy, Loc);
} else {
ResTy = Context.adjustStringLiteralBaseType(Context.CharTy.withConst());
ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal,
/*IndexTypeQuals*/ 0);
SL = StringLiteral::Create(Context, Str, StringLiteral::Ascii,
/*Pascal*/ false, ResTy, Loc);
}
}
return PredefinedExpr::Create(Context, Loc, ResTy, IK, SL);
}
ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
PredefinedExpr::IdentKind IK;
switch (Kind) {
default: llvm_unreachable("Unknown simple primary expr!");
case tok::kw___func__: IK = PredefinedExpr::Func; break; // [C99 6.4.2.2]
case tok::kw___FUNCTION__: IK = PredefinedExpr::Function; break;
case tok::kw___FUNCDNAME__: IK = PredefinedExpr::FuncDName; break; // [MS]
case tok::kw___FUNCSIG__: IK = PredefinedExpr::FuncSig; break; // [MS]
case tok::kw_L__FUNCTION__: IK = PredefinedExpr::LFunction; break; // [MS]
case tok::kw_L__FUNCSIG__: IK = PredefinedExpr::LFuncSig; break; // [MS]
case tok::kw___PRETTY_FUNCTION__: IK = PredefinedExpr::PrettyFunction; break;
}
return BuildPredefinedExpr(Loc, IK);
}
ExprResult Sema::ActOnCharacterConstant(const Token &Tok, Scope *UDLScope) {
SmallString<16> CharBuffer;
bool Invalid = false;
StringRef ThisTok = PP.getSpelling(Tok, CharBuffer, &Invalid);
if (Invalid)
return ExprError();
CharLiteralParser Literal(ThisTok.begin(), ThisTok.end(), Tok.getLocation(),
PP, Tok.getKind());
if (Literal.hadError())
return ExprError();
QualType Ty;
if (Literal.isWide())
Ty = Context.WideCharTy; // L'x' -> wchar_t in C and C++.
else if (Literal.isUTF8() && getLangOpts().Char8)
Ty = Context.Char8Ty; // u8'x' -> char8_t when it exists.
else if (Literal.isUTF16())
Ty = Context.Char16Ty; // u'x' -> char16_t in C11 and C++11.
else if (Literal.isUTF32())
Ty = Context.Char32Ty; // U'x' -> char32_t in C11 and C++11.
else if (!getLangOpts().CPlusPlus || Literal.isMultiChar())
Ty = Context.IntTy; // 'x' -> int in C, 'wxyz' -> int in C++.
else
Ty = Context.CharTy; // 'x' -> char in C++
CharacterLiteral::CharacterKind Kind = CharacterLiteral::Ascii;
if (Literal.isWide())
Kind = CharacterLiteral::Wide;
else if (Literal.isUTF16())
Kind = CharacterLiteral::UTF16;
else if (Literal.isUTF32())
Kind = CharacterLiteral::UTF32;
else if (Literal.isUTF8())
Kind = CharacterLiteral::UTF8;
Expr *Lit = new (Context) CharacterLiteral(Literal.getValue(), Kind, Ty,
Tok.getLocation());
if (Literal.getUDSuffix().empty())
return Lit;
// We're building a user-defined literal.
IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
SourceLocation UDSuffixLoc =
getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset());
// Make sure we're allowed user-defined literals here.
if (!UDLScope)
return ExprError(Diag(UDSuffixLoc, diag::err_invalid_character_udl));
// C++11 [lex.ext]p6: The literal L is treated as a call of the form
// operator "" X (ch)
return BuildCookedLiteralOperatorCall(*this, UDLScope, UDSuffix, UDSuffixLoc,
Lit, Tok.getLocation());
}
ExprResult Sema::ActOnIntegerConstant(SourceLocation Loc, uint64_t Val) {
unsigned IntSize = Context.getTargetInfo().getIntWidth();
return IntegerLiteral::Create(Context, llvm::APInt(IntSize, Val),
Context.IntTy, Loc);
}
static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal,
QualType Ty, SourceLocation Loc) {
const llvm::fltSemantics &Format = S.Context.getFloatTypeSemantics(Ty);
using llvm::APFloat;
APFloat Val(Format);
APFloat::opStatus result = Literal.GetFloatValue(Val);
// Overflow is always an error, but underflow is only an error if
// we underflowed to zero (APFloat reports denormals as underflow).
if ((result & APFloat::opOverflow) ||
((result & APFloat::opUnderflow) && Val.isZero())) {
unsigned diagnostic;
SmallString<20> buffer;
if (result & APFloat::opOverflow) {
diagnostic = diag::warn_float_overflow;
APFloat::getLargest(Format).toString(buffer);
} else {
diagnostic = diag::warn_float_underflow;
APFloat::getSmallest(Format).toString(buffer);
}
S.Diag(Loc, diagnostic)
<< Ty
<< StringRef(buffer.data(), buffer.size());
}
bool isExact = (result == APFloat::opOK);
return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc);
}
bool Sema::CheckLoopHintExpr(Expr *E, SourceLocation Loc) {
assert(E && "Invalid expression");
if (E->isValueDependent())
return false;
QualType QT = E->getType();
if (!QT->isIntegerType() || QT->isBooleanType() || QT->isCharType()) {
Diag(E->getExprLoc(), diag::err_pragma_loop_invalid_argument_type) << QT;
return true;
}
llvm::APSInt ValueAPS;
ExprResult R = VerifyIntegerConstantExpression(E, &ValueAPS);
if (R.isInvalid())
return true;
bool ValueIsPositive = ValueAPS.isStrictlyPositive();
if (!ValueIsPositive || ValueAPS.getActiveBits() > 31) {
Diag(E->getExprLoc(), diag::err_pragma_loop_invalid_argument_value)
<< ValueAPS.toString(10) << ValueIsPositive;
return true;
}
return false;
}
ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
// Fast path for a single digit (which is quite common). A single digit
// cannot have a trigraph, escaped newline, radix prefix, or suffix.
if (Tok.getLength() == 1) {
const char Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok);
return ActOnIntegerConstant(Tok.getLocation(), Val-'0');
}
SmallString<128> SpellingBuffer;
// NumericLiteralParser wants to overread by one character. Add padding to
// the buffer in case the token is copied to the buffer. If getSpelling()
// returns a StringRef to the memory buffer, it should have a null char at
// the EOF, so it is also safe.
SpellingBuffer.resize(Tok.getLength() + 1);
// Get the spelling of the token, which eliminates trigraphs, etc.
bool Invalid = false;
StringRef TokSpelling = PP.getSpelling(Tok, SpellingBuffer, &Invalid);
if (Invalid)
return ExprError();
NumericLiteralParser Literal(TokSpelling, Tok.getLocation(), PP);
if (Literal.hadError)
return ExprError();
if (Literal.hasUDSuffix()) {
// We're building a user-defined literal.
IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix());
SourceLocation UDSuffixLoc =
getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset());
// Make sure we're allowed user-defined literals here.
if (!UDLScope)
return ExprError(Diag(UDSuffixLoc, diag::err_invalid_numeric_udl));
QualType CookedTy;
if (Literal.isFloatingLiteral()) {
// C++11 [lex.ext]p4: If S contains a literal operator with parameter type
// long double, the literal is treated as a call of the form
// operator "" X (f L)
CookedTy = Context.LongDoubleTy;
} else {
// C++11 [lex.ext]p3: If S contains a literal operator with parameter type
// unsigned long long, the literal is treated as a call of the form
// operator "" X (n ULL)
CookedTy = Context.UnsignedLongLongTy;
}
DeclarationName OpName =
Context.DeclarationNames.getCXXLiteralOperatorName(UDSuffix);
DeclarationNameInfo OpNameInfo(OpName, UDSuffixLoc);
OpNameInfo.setCXXLiteralOperatorNameLoc(UDSuffixLoc);
SourceLocation TokLoc = Tok.getLocation();
// Perform literal operator lookup to determine if we're building a raw
// literal or a cooked one.
LookupResult R(*this, OpName, UDSuffixLoc, LookupOrdinaryName);
switch (LookupLiteralOperator(UDLScope, R, CookedTy,
/*AllowRaw*/ true, /*AllowTemplate*/ true,
/*AllowStringTemplate*/ false,
/*DiagnoseMissing*/ !Literal.isImaginary)) {
case LOLR_ErrorNoDiagnostic:
// Lookup failure for imaginary constants isn't fatal, there's still the
// GNU extension producing _Complex types.
break;
case LOLR_Error:
return ExprError();
case LOLR_Cooked: {
Expr *Lit;
if (Literal.isFloatingLiteral()) {
Lit = BuildFloatingLiteral(*this, Literal, CookedTy, Tok.getLocation());
} else {
llvm::APInt ResultVal(Context.getTargetInfo().getLongLongWidth(), 0);
if (Literal.GetIntegerValue(ResultVal))
Diag(Tok.getLocation(), diag::err_integer_literal_too_large)
<< /* Unsigned */ 1;
Lit = IntegerLiteral::Create(Context, ResultVal, CookedTy,
Tok.getLocation());
}
return BuildLiteralOperatorCall(R, OpNameInfo, Lit, TokLoc);
}
case LOLR_Raw: {
// C++11 [lit.ext]p3, p4: If S contains a raw literal operator, the
// literal is treated as a call of the form
// operator "" X ("n")
unsigned Length = Literal.getUDSuffixOffset();
QualType StrTy = Context.getConstantArrayType(
Context.adjustStringLiteralBaseType(Context.CharTy.withConst()),
llvm::APInt(32, Length + 1), ArrayType::Normal, 0);
Expr *Lit = StringLiteral::Create(
Context, StringRef(TokSpelling.data(), Length), StringLiteral::Ascii,
/*Pascal*/false, StrTy, &TokLoc, 1);
return BuildLiteralOperatorCall(R, OpNameInfo, Lit, TokLoc);
}
case LOLR_Template: {
// C++11 [lit.ext]p3, p4: Otherwise (S contains a literal operator
// template), L is treated as a call fo the form
// operator "" X <'c1', 'c2', ... 'ck'>()
// where n is the source character sequence c1 c2 ... ck.
TemplateArgumentListInfo ExplicitArgs;
unsigned CharBits = Context.getIntWidth(Context.CharTy);
bool CharIsUnsigned = Context.CharTy->isUnsignedIntegerType();
llvm::APSInt Value(CharBits, CharIsUnsigned);
for (unsigned I = 0, N = Literal.getUDSuffixOffset(); I != N; ++I) {
Value = TokSpelling[I];
TemplateArgument Arg(Context, Value, Context.CharTy);
TemplateArgumentLocInfo ArgInfo;
ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo));
}
return BuildLiteralOperatorCall(R, OpNameInfo, None, TokLoc,
&ExplicitArgs);
}
case LOLR_StringTemplate:
llvm_unreachable("unexpected literal operator lookup result");
}
}
Expr *Res;
if (Literal.isFixedPointLiteral()) {
QualType Ty;
if (Literal.isAccum) {
if (Literal.isHalf) {
Ty = Context.ShortAccumTy;
} else if (Literal.isLong) {
Ty = Context.LongAccumTy;
} else {
Ty = Context.AccumTy;
}
} else if (Literal.isFract) {
if (Literal.isHalf) {
Ty = Context.ShortFractTy;
} else if (Literal.isLong) {
Ty = Context.LongFractTy;
} else {
Ty = Context.FractTy;
}
}
if (Literal.isUnsigned) Ty = Context.getCorrespondingUnsignedType(Ty);
bool isSigned = !Literal.isUnsigned;
unsigned scale = Context.getFixedPointScale(Ty);
unsigned bit_width = Context.getTypeInfo(Ty).Width;
llvm::APInt Val(bit_width, 0, isSigned);
bool Overflowed = Literal.GetFixedPointValue(Val, scale);
bool ValIsZero = Val.isNullValue() && !Overflowed;
auto MaxVal = Context.getFixedPointMax(Ty).getValue();
if (Literal.isFract && Val == MaxVal + 1 && !ValIsZero)
// Clause 6.4.4 - The value of a constant shall be in the range of
// representable values for its type, with exception for constants of a
// fract type with a value of exactly 1; such a constant shall denote
// the maximal value for the type.
--Val;
else if (Val.ugt(MaxVal) || Overflowed)
Diag(Tok.getLocation(), diag::err_too_large_for_fixed_point);
Res = FixedPointLiteral::CreateFromRawInt(Context, Val, Ty,
Tok.getLocation(), scale);
} else if (Literal.isFloatingLiteral()) {
QualType Ty;
if (Literal.isHalf){
if (getOpenCLOptions().isEnabled("cl_khr_fp16"))
Ty = Context.HalfTy;
else {
Diag(Tok.getLocation(), diag::err_half_const_requires_fp16);
return ExprError();
}
} else if (Literal.isFloat)
Ty = Context.FloatTy;
else if (Literal.isLong)
Ty = Context.LongDoubleTy;
else if (Literal.isFloat16)
Ty = Context.Float16Ty;
else if (Literal.isFloat128)
Ty = Context.Float128Ty;
else
Ty = Context.DoubleTy;
Res = BuildFloatingLiteral(*this, Literal, Ty, Tok.getLocation());
if (Ty == Context.DoubleTy) {
if (getLangOpts().SinglePrecisionConstants) {
const BuiltinType *BTy = Ty->getAs<BuiltinType>();
if (BTy->getKind() != BuiltinType::Float) {
Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
}
} else if (getLangOpts().OpenCL &&
!getOpenCLOptions().isEnabled("cl_khr_fp64")) {
// Impose single-precision float type when cl_khr_fp64 is not enabled.
Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64);
Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
}
}
} else if (!Literal.isIntegerLiteral()) {
return ExprError();
} else {
QualType Ty;
// 'long long' is a C99 or C++11 feature.
if (!getLangOpts().C99 && Literal.isLongLong) {
if (getLangOpts().CPlusPlus)
Diag(Tok.getLocation(),
getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
else
Diag(Tok.getLocation(), diag::ext_c99_longlong);
}
// Get the value in the widest-possible width.
unsigned MaxWidth = Context.getTargetInfo().getIntMaxTWidth();
llvm::APInt ResultVal(MaxWidth, 0);
if (Literal.GetIntegerValue(ResultVal)) {
// If this value didn't fit into uintmax_t, error and force to ull.
Diag(Tok.getLocation(), diag::err_integer_literal_too_large)
<< /* Unsigned */ 1;
Ty = Context.UnsignedLongLongTy;
assert(Context.getTypeSize(Ty) == ResultVal.getBitWidth() &&
"long long is not intmax_t?");
} else {
// If this value fits into a ULL, try to figure out what else it fits into
// according to the rules of C99 6.4.4.1p5.
// Octal, Hexadecimal, and integers with a U suffix are allowed to
// be an unsigned int.
bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10;
// Check from smallest to largest, picking the smallest type we can.
unsigned Width = 0;
// Microsoft specific integer suffixes are explicitly sized.
if (Literal.MicrosoftInteger) {
if (Literal.MicrosoftInteger == 8 && !Literal.isUnsigned) {
Width = 8;
Ty = Context.CharTy;
} else {
Width = Literal.MicrosoftInteger;
Ty = Context.getIntTypeForBitwidth(Width,
/*Signed=*/!Literal.isUnsigned);
}
}
if (Ty.isNull() && !Literal.isLong && !Literal.isLongLong) {
// Are int/unsigned possibilities?
unsigned IntSize = Context.getTargetInfo().getIntWidth();
// Does it fit in a unsigned int?
if (ResultVal.isIntN(IntSize)) {
// Does it fit in a signed int?
if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0)
Ty = Context.IntTy;
else if (AllowUnsigned)
Ty = Context.UnsignedIntTy;
Width = IntSize;
}
}
// Are long/unsigned long possibilities?
if (Ty.isNull() && !Literal.isLongLong) {
unsigned LongSize = Context.getTargetInfo().getLongWidth();
// Does it fit in a unsigned long?
if (ResultVal.isIntN(LongSize)) {
// Does it fit in a signed long?
if (!Literal.isUnsigned && ResultVal[LongSize-1] == 0)
Ty = Context.LongTy;
else if (AllowUnsigned)
Ty = Context.UnsignedLongTy;
// Check according to the rules of C90 6.1.3.2p5. C++03 [lex.icon]p2
// is compatible.
else if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11) {
const unsigned LongLongSize =
Context.getTargetInfo().getLongLongWidth();
Diag(Tok.getLocation(),
getLangOpts().CPlusPlus
? Literal.isLong
? diag::warn_old_implicitly_unsigned_long_cxx
: /*C++98 UB*/ diag::
ext_old_implicitly_unsigned_long_cxx
: diag::warn_old_implicitly_unsigned_long)
<< (LongLongSize > LongSize ? /*will have type 'long long'*/ 0
: /*will be ill-formed*/ 1);
Ty = Context.UnsignedLongTy;
}
Width = LongSize;
}
}
// Check long long if needed.
if (Ty.isNull()) {
unsigned LongLongSize = Context.getTargetInfo().getLongLongWidth();
// Does it fit in a unsigned long long?
if (ResultVal.isIntN(LongLongSize)) {
// Does it fit in a signed long long?
// To be compatible with MSVC, hex integer literals ending with the
// LL or i64 suffix are always signed in Microsoft mode.
if (!Literal.isUnsigned && (ResultVal[LongLongSize-1] == 0 ||
(getLangOpts().MSVCCompat && Literal.isLongLong)))
Ty = Context.LongLongTy;
else if (AllowUnsigned)
Ty = Context.UnsignedLongLongTy;
Width = LongLongSize;
}
}
// If we still couldn't decide a type, we probably have something that
// does not fit in a signed long long, but has no U suffix.
if (Ty.isNull()) {
Diag(Tok.getLocation(), diag::ext_integer_literal_too_large_for_signed);
Ty = Context.UnsignedLongLongTy;
Width = Context.getTargetInfo().getLongLongWidth();
}
if (ResultVal.getBitWidth() != Width)
ResultVal = ResultVal.trunc(Width);
}
Res = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation());
}
// If this is an imaginary literal, create the ImaginaryLiteral wrapper.
if (Literal.isImaginary) {
Res = new (Context) ImaginaryLiteral(Res,
Context.getComplexType(Res->getType()));
Diag(Tok.getLocation(), diag::ext_imaginary_constant);
}
return Res;
}
ExprResult Sema::ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E) {
assert(E && "ActOnParenExpr() missing expr");
return new (Context) ParenExpr(L, R, E);
}
static bool CheckVecStepTraitOperandType(Sema &S, QualType T,
SourceLocation Loc,
SourceRange ArgRange) {
// [OpenCL 1.1 6.11.12] "The vec_step built-in function takes a built-in
// scalar or vector data type argument..."
// Every built-in scalar type (OpenCL 1.1 6.1.1) is either an arithmetic
// type (C99 6.2.5p18) or void.
if (!(T->isArithmeticType() || T->isVoidType() || T->isVectorType())) {
S.Diag(Loc, diag::err_vecstep_non_scalar_vector_type)
<< T << ArgRange;
return true;
}
assert((T->isVoidType() || !T->isIncompleteType()) &&
"Scalar types should always be complete");
return false;
}
static bool CheckExtensionTraitOperandType(Sema &S, QualType T,
SourceLocation Loc,
SourceRange ArgRange,
UnaryExprOrTypeTrait TraitKind) {
// Invalid types must be hard errors for SFINAE in C++.
if (S.LangOpts.CPlusPlus)
return true;
// C99 6.5.3.4p1:
if (T->isFunctionType() &&
(TraitKind == UETT_SizeOf || TraitKind == UETT_AlignOf ||
TraitKind == UETT_PreferredAlignOf)) {
// sizeof(function)/alignof(function) is allowed as an extension.
S.Diag(Loc, diag::ext_sizeof_alignof_function_type)
<< TraitKind << ArgRange;
return false;
}
// Allow sizeof(void)/alignof(void) as an extension, unless in OpenCL where
// this is an error (OpenCL v1.1 s6.3.k)
if (T->isVoidType()) {
unsigned DiagID = S.LangOpts.OpenCL ? diag::err_opencl_sizeof_alignof_type
: diag::ext_sizeof_alignof_void_type;
S.Diag(Loc, DiagID) << TraitKind << ArgRange;
return false;
}
return true;
}
static bool CheckObjCTraitOperandConstraints(Sema &S, QualType T,
SourceLocation Loc,
SourceRange ArgRange,
UnaryExprOrTypeTrait TraitKind) {
// Reject sizeof(interface) and sizeof(interface<proto>) if the
// runtime doesn't allow it.
if (!S.LangOpts.ObjCRuntime.allowsSizeofAlignof() && T->isObjCObjectType()) {
S.Diag(Loc, diag::err_sizeof_nonfragile_interface)
<< T << (TraitKind == UETT_SizeOf)
<< ArgRange;
return true;
}
return false;
}
/// Check whether E is a pointer from a decayed array type (the decayed
/// pointer type is equal to T) and emit a warning if it is.
static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T,
Expr *E) {
// Don't warn if the operation changed the type.
if (T != E->getType())
return;
// Now look for array decays.
ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E);
if (!ICE || ICE->getCastKind() != CK_ArrayToPointerDecay)
return;
S.Diag(Loc, diag::warn_sizeof_array_decay) << ICE->getSourceRange()
<< ICE->getType()
<< ICE->getSubExpr()->getType();
}
/// Check the constraints on expression operands to unary type expression
/// and type traits.
///
/// Completes any types necessary and validates the constraints on the operand
/// expression. The logic mostly mirrors the type-based overload, but may modify
/// the expression as it completes the type for that expression through template
/// instantiation, etc.
bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E,
UnaryExprOrTypeTrait ExprKind) {
QualType ExprTy = E->getType();
assert(!ExprTy->isReferenceType());
if (ExprKind == UETT_VecStep)
return CheckVecStepTraitOperandType(*this, ExprTy, E->getExprLoc(),
E->getSourceRange());
// Whitelist some types as extensions
if (!CheckExtensionTraitOperandType(*this, ExprTy, E->getExprLoc(),
E->getSourceRange(), ExprKind))
return false;
// 'alignof' applied to an expression only requires the base element type of
// the expression to be complete. 'sizeof' requires the expression's type to
// be complete (and will attempt to complete it if it's an array of unknown
// bound).
if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf) {
if (RequireCompleteType(E->getExprLoc(),
Context.getBaseElementType(E->getType()),
diag::err_sizeof_alignof_incomplete_type, ExprKind,
E->getSourceRange()))
return true;
} else {
if (RequireCompleteExprType(E, diag::err_sizeof_alignof_incomplete_type,
ExprKind, E->getSourceRange()))
return true;
}
// Completing the expression's type may have changed it.
ExprTy = E->getType();
assert(!ExprTy->isReferenceType());
if (ExprTy->isFunctionType()) {
Diag(E->getExprLoc(), diag::err_sizeof_alignof_function_type)
<< ExprKind << E->getSourceRange();
return true;
}
// The operand for sizeof and alignof is in an unevaluated expression context,
// so side effects could result in unintended consequences.
if ((ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf ||
ExprKind == UETT_PreferredAlignOf) &&
!inTemplateInstantiation() && E->HasSideEffects(Context, false))
Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
if (CheckObjCTraitOperandConstraints(*this, ExprTy, E->getExprLoc(),
E->getSourceRange(), ExprKind))
return true;
if (ExprKind == UETT_SizeOf) {
if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(DeclRef->getFoundDecl())) {
QualType OType = PVD->getOriginalType();
QualType Type = PVD->getType();
if (Type->isPointerType() && OType->isArrayType()) {
Diag(E->getExprLoc(), diag::warn_sizeof_array_param)
<< Type << OType;
Diag(PVD->getLocation(), diag::note_declared_at);
}
}
}
// Warn on "sizeof(array op x)" and "sizeof(x op array)", where the array
// decays into a pointer and returns an unintended result. This is most
// likely a typo for "sizeof(array) op x".
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E->IgnoreParens())) {
warnOnSizeofOnArrayDecay(*this, BO->getOperatorLoc(), BO->getType(),
BO->getLHS());
warnOnSizeofOnArrayDecay(*this, BO->getOperatorLoc(), BO->getType(),
BO->getRHS());
}
}
return false;
}
/// Check the constraints on operands to unary expression and type
/// traits.
///
/// This will complete any types necessary, and validate the various constraints
/// on those operands.
///
/// The UsualUnaryConversions() function is *not* called by this routine.
/// C99 6.3.2.1p[2-4] all state:
/// Except when it is the operand of the sizeof operator ...
///
/// C++ [expr.sizeof]p4
/// The lvalue-to-rvalue, array-to-pointer, and function-to-pointer
/// standard conversions are not applied to the operand of sizeof.
///
/// This policy is followed for all of the unary trait expressions.
bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
SourceLocation OpLoc,
SourceRange ExprRange,
UnaryExprOrTypeTrait ExprKind) {
if (ExprType->isDependentType())
return false;
// C++ [expr.sizeof]p2:
// When applied to a reference or a reference type, the result
// is the size of the referenced type.
// C++11 [expr.alignof]p3:
// When alignof is applied to a reference type, the result
// shall be the alignment of the referenced type.
if (const ReferenceType *Ref = ExprType->getAs<ReferenceType>())
ExprType = Ref->getPointeeType();
// C11 6.5.3.4/3, C++11 [expr.alignof]p3:
// When alignof or _Alignof is applied to an array type, the result
// is the alignment of the element type.
if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf ||
ExprKind == UETT_OpenMPRequiredSimdAlign)
ExprType = Context.getBaseElementType(ExprType);
if (ExprKind == UETT_VecStep)
return CheckVecStepTraitOperandType(*this, ExprType, OpLoc, ExprRange);
// Whitelist some types as extensions
if (!CheckExtensionTraitOperandType(*this, ExprType, OpLoc, ExprRange,
ExprKind))
return false;
if (RequireCompleteType(OpLoc, ExprType,
diag::err_sizeof_alignof_incomplete_type,
ExprKind, ExprRange))
return true;
if (ExprType->isFunctionType()) {
Diag(OpLoc, diag::err_sizeof_alignof_function_type)
<< ExprKind << ExprRange;
return true;
}
if (CheckObjCTraitOperandConstraints(*this, ExprType, OpLoc, ExprRange,
ExprKind))
return true;
return false;
}
static bool CheckAlignOfExpr(Sema &S, Expr *E, UnaryExprOrTypeTrait ExprKind) {
E = E->IgnoreParens();
// Cannot know anything else if the expression is dependent.
if (E->isTypeDependent())
return false;
if (E->getObjectKind() == OK_BitField) {
S.Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield)
<< 1 << E->getSourceRange();
return true;
}
ValueDecl *D = nullptr;
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
D = DRE->getDecl();
} else if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
D = ME->getMemberDecl();
}
// If it's a field, require the containing struct to have a
// complete definition so that we can compute the layout.
//
// This can happen in C++11 onwards, either by naming the member
// in a way that is not transformed into a member access expression
// (in an unevaluated operand, for instance), or by naming the member
// in a trailing-return-type.
//
// For the record, since __alignof__ on expressions is a GCC
// extension, GCC seems to permit this but always gives the
// nonsensical answer 0.
//
// We don't really need the layout here --- we could instead just
// directly check for all the appropriate alignment-lowing
// attributes --- but that would require duplicating a lot of
// logic that just isn't worth duplicating for such a marginal
// use-case.
if (FieldDecl *FD = dyn_cast_or_null<FieldDecl>(D)) {
// Fast path this check, since we at least know the record has a
// definition if we can find a member of it.
if (!FD->getParent()->isCompleteDefinition()) {
S.Diag(E->getExprLoc(), diag::err_alignof_member_of_incomplete_type)
<< E->getSourceRange();
return true;
}
// Otherwise, if it's a field, and the field doesn't have
// reference type, then it must have a complete type (or be a
// flexible array member, which we explicitly want to
// white-list anyway), which makes the following checks trivial.
if (!FD->getType()->isReferenceType())
return false;
}
return S.CheckUnaryExprOrTypeTraitOperand(E, ExprKind);
}
bool Sema::CheckVecStepExpr(Expr *E) {
E = E->IgnoreParens();
// Cannot know anything else if the expression is dependent.
if (E->isTypeDependent())
return false;
return CheckUnaryExprOrTypeTraitOperand(E, UETT_VecStep);
}
static void captureVariablyModifiedType(ASTContext &Context, QualType T,
CapturingScopeInfo *CSI) {
assert(T->isVariablyModifiedType());
assert(CSI != nullptr);
// We're going to walk down into the type and look for VLA expressions.
do {
const Type *Ty = T.getTypePtr();
switch (Ty->getTypeClass()) {
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define NON_CANONICAL_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base)
#include "clang/AST/TypeNodes.def"
T = QualType();
break;
// These types are never variably-modified.
case Type::Builtin:
case Type::Complex:
case Type::Vector:
case Type::ExtVector:
case Type::Record:
case Type::Enum:
case Type::Elaborated:
case Type::TemplateSpecialization:
case Type::ObjCObject:
case Type::ObjCInterface:
case Type::ObjCObjectPointer:
case Type::ObjCTypeParam:
case Type::Pipe:
llvm_unreachable("type class is never variably-modified!");
case Type::Adjusted:
T = cast<AdjustedType>(Ty)->getOriginalType();
break;
case Type::Decayed:
T = cast<DecayedType>(Ty)->getPointeeType();
break;
case Type::Pointer:
T = cast<PointerType>(Ty)->getPointeeType();
break;
case Type::BlockPointer:
T = cast<BlockPointerType>(Ty)->getPointeeType();
break;
case Type::LValueReference:
case Type::RValueReference:
T = cast<ReferenceType>(Ty)->getPointeeType();
break;
case Type::MemberPointer:
T = cast<MemberPointerType>(Ty)->getPointeeType();
break;
case Type::ConstantArray:
case Type::IncompleteArray:
// Losing element qualification here is fine.
T = cast<ArrayType>(Ty)->getElementType();
break;
case Type::VariableArray: {
// Losing element qualification here is fine.
const VariableArrayType *VAT = cast<VariableArrayType>(Ty);
// Unknown size indication requires no size computation.
// Otherwise, evaluate and record it.
if (auto Size = VAT->getSizeExpr()) {
if (!CSI->isVLATypeCaptured(VAT)) {
RecordDecl *CapRecord = nullptr;
if (auto LSI = dyn_cast<LambdaScopeInfo>(CSI)) {
CapRecord = LSI->Lambda;
} else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
CapRecord = CRSI->TheRecordDecl;
}
if (CapRecord) {
auto ExprLoc = Size->getExprLoc();
auto SizeType = Context.getSizeType();
// Build the non-static data member.
auto Field =
FieldDecl::Create(Context, CapRecord, ExprLoc, ExprLoc,
/*Id*/ nullptr, SizeType, /*TInfo*/ nullptr,
/*BW*/ nullptr, /*Mutable*/ false,
/*InitStyle*/ ICIS_NoInit);
Field->setImplicit(true);
Field->setAccess(AS_private);
Field->setCapturedVLAType(VAT);
CapRecord->addDecl(Field);
CSI->addVLATypeCapture(ExprLoc, SizeType);
}
}
}
T = VAT->getElementType();
break;
}
case Type::FunctionProto:
case Type::FunctionNoProto:
T = cast<FunctionType>(Ty)->getReturnType();
break;
case Type::Paren:
case Type::TypeOf:
case Type::UnaryTransform:
case Type::Attributed:
case Type::SubstTemplateTypeParm:
case Type::PackExpansion:
// Keep walking after single level desugaring.
T = T.getSingleStepDesugaredType(Context);
break;
case Type::Typedef:
T = cast<TypedefType>(Ty)->desugar();
break;
case Type::Decltype:
T = cast<DecltypeType>(Ty)->desugar();
break;
case Type::Auto:
case Type::DeducedTemplateSpecialization:
T = cast<DeducedType>(Ty)->getDeducedType();
break;
case Type::TypeOfExpr:
T = cast<TypeOfExprType>(Ty)->getUnderlyingExpr()->getType();
break;
case Type::Atomic:
T = cast<AtomicType>(Ty)->getValueType();
break;
}
} while (!T.isNull() && T->isVariablyModifiedType());
}
/// Build a sizeof or alignof expression given a type operand.
ExprResult
Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind,
SourceRange R) {
if (!TInfo)
return ExprError();
QualType T = TInfo->getType();
if (!T->isDependentType() &&
CheckUnaryExprOrTypeTraitOperand(T, OpLoc, R, ExprKind))
return ExprError();
if (T->isVariablyModifiedType() && FunctionScopes.size() > 1) {
if (auto *TT = T->getAs<TypedefType>()) {
for (auto I = FunctionScopes.rbegin(),
E = std::prev(FunctionScopes.rend());
I != E; ++I) {
auto *CSI = dyn_cast<CapturingScopeInfo>(*I);
if (CSI == nullptr)
break;
DeclContext *DC = nullptr;
if (auto *LSI = dyn_cast<LambdaScopeInfo>(CSI))
DC = LSI->CallOperator;
else if (auto *CRSI = dyn_cast<CapturedRegionScopeInfo>(CSI))
DC = CRSI->TheCapturedDecl;
else if (auto *BSI = dyn_cast<BlockScopeInfo>(CSI))
DC = BSI->TheDecl;
if (DC) {
if (DC->containsDecl(TT->getDecl()))
break;
captureVariablyModifiedType(Context, T, CSI);
}
}
}
}
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
return new (Context) UnaryExprOrTypeTraitExpr(
ExprKind, TInfo, Context.getSizeType(), OpLoc, R.getEnd());
}
/// Build a sizeof or alignof expression given an expression
/// operand.
ExprResult
Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind) {
ExprResult PE = CheckPlaceholderExpr(E);
if (PE.isInvalid())
return ExprError();
E = PE.get();
// Verify that the operand is valid.
bool isInvalid = false;
if (E->isTypeDependent()) {
// Delay type-checking for type-dependent expressions.
} else if (ExprKind == UETT_AlignOf || ExprKind == UETT_PreferredAlignOf) {
isInvalid = CheckAlignOfExpr(*this, E, ExprKind);
} else if (ExprKind == UETT_VecStep) {
isInvalid = CheckVecStepExpr(E);
} else if (ExprKind == UETT_OpenMPRequiredSimdAlign) {
Diag(E->getExprLoc(), diag::err_openmp_default_simd_align_expr);
isInvalid = true;
} else if (E->refersToBitField()) { // C99 6.5.3.4p1.
Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 0;
isInvalid = true;
} else {
isInvalid = CheckUnaryExprOrTypeTraitOperand(E, UETT_SizeOf);
}
if (isInvalid)
return ExprError();
if (ExprKind == UETT_SizeOf && E->getType()->isVariableArrayType()) {
PE = TransformToPotentiallyEvaluated(E);
if (PE.isInvalid()) return ExprError();
E = PE.get();
}
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
return new (Context) UnaryExprOrTypeTraitExpr(
ExprKind, E, Context.getSizeType(), OpLoc, E->getSourceRange().getEnd());
}
/// ActOnUnaryExprOrTypeTraitExpr - Handle @c sizeof(type) and @c sizeof @c
/// expr and the same for @c alignof and @c __alignof
/// Note that the ArgRange is invalid if isType is false.
ExprResult
Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
UnaryExprOrTypeTrait ExprKind, bool IsType,
void *TyOrEx, SourceRange ArgRange) {
// If error parsing type, ignore.
if (!TyOrEx) return ExprError();
if (IsType) {
TypeSourceInfo *TInfo;
(void) GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrEx), &TInfo);
return CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, ArgRange);
}
Expr *ArgEx = (Expr *)TyOrEx;
ExprResult Result = CreateUnaryExprOrTypeTraitExpr(ArgEx, OpLoc, ExprKind);
return Result;
}
static QualType CheckRealImagOperand(Sema &S, ExprResult &V, SourceLocation Loc,
bool IsReal) {
if (V.get()->isTypeDependent())
return S.Context.DependentTy;
// _Real and _Imag are only l-values for normal l-values.
if (V.get()->getObjectKind() != OK_Ordinary) {
V = S.DefaultLvalueConversion(V.get());
if (V.isInvalid())
return QualType();
}
// These operators return the element type of a complex type.
if (const ComplexType *CT = V.get()->getType()->getAs<ComplexType>())
return CT->getElementType();
// Otherwise they pass through real integer and floating point types here.
if (V.get()->getType()->isArithmeticType())
return V.get()->getType();
// Test for placeholders.
ExprResult PR = S.CheckPlaceholderExpr(V.get());
if (PR.isInvalid()) return QualType();
if (PR.get() != V.get()) {
V = PR;
return CheckRealImagOperand(S, V, Loc, IsReal);
}
// Reject anything else.
S.Diag(Loc, diag::err_realimag_invalid_type) << V.get()->getType()
<< (IsReal ? "__real" : "__imag");
return QualType();
}
ExprResult
Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
tok::TokenKind Kind, Expr *Input) {
UnaryOperatorKind Opc;
switch (Kind) {
default: llvm_unreachable("Unknown unary op!");
case tok::plusplus: Opc = UO_PostInc; break;
case tok::minusminus: Opc = UO_PostDec; break;
}
// Since this might is a postfix expression, get rid of ParenListExprs.
ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Input);
if (Result.isInvalid()) return ExprError();
Input = Result.get();
return BuildUnaryOp(S, OpLoc, Opc, Input);
}
/// Diagnose if arithmetic on the given ObjC pointer is illegal.
///
/// \return true on error
static bool checkArithmeticOnObjCPointer(Sema &S,
SourceLocation opLoc,
Expr *op) {
assert(op->getType()->isObjCObjectPointerType());
if (S.LangOpts.ObjCRuntime.allowsPointerArithmetic() &&
!S.LangOpts.ObjCSubscriptingLegacyRuntime)
return false;
S.Diag(opLoc, diag::err_arithmetic_nonfragile_interface)
<< op->getType()->castAs<ObjCObjectPointerType>()->getPointeeType()
<< op->getSourceRange();
return true;
}
static bool isMSPropertySubscriptExpr(Sema &S, Expr *Base) {
auto *BaseNoParens = Base->IgnoreParens();
if (auto *MSProp = dyn_cast<MSPropertyRefExpr>(BaseNoParens))
return MSProp->getPropertyDecl()->getType()->isArrayType();
return isa<MSPropertySubscriptExpr>(BaseNoParens);
}
ExprResult
Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
Expr *idx, SourceLocation rbLoc) {
if (base && !base->getType().isNull() &&
base->getType()->isSpecificPlaceholderType(BuiltinType::OMPArraySection))
return ActOnOMPArraySectionExpr(base, lbLoc, idx, SourceLocation(),
/*Length=*/nullptr, rbLoc);
// Since this might be a postfix expression, get rid of ParenListExprs.
if (isa<ParenListExpr>(base)) {
ExprResult result = MaybeConvertParenListExprToParenExpr(S, base);
if (result.isInvalid()) return ExprError();
base = result.get();
}
// Handle any non-overload placeholder types in the base and index
// expressions. We can't handle overloads here because the other
// operand might be an overloadable type, in which case the overload
// resolution for the operator overload should get the first crack
// at the overload.
bool IsMSPropertySubscript = false;
if (base->getType()->isNonOverloadPlaceholderType()) {
IsMSPropertySubscript = isMSPropertySubscriptExpr(*this, base);
if (!IsMSPropertySubscript) {
ExprResult result = CheckPlaceholderExpr(base);
if (result.isInvalid())
return ExprError();
base = result.get();
}
}
if (idx->getType()->isNonOverloadPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(idx);
if (result.isInvalid()) return ExprError();
idx = result.get();
}
// Build an unanalyzed expression if either operand is type-dependent.
if (getLangOpts().CPlusPlus &&
(base->isTypeDependent() || idx->isTypeDependent())) {
return new (Context) ArraySubscriptExpr(base, idx, Context.DependentTy,
VK_LValue, OK_Ordinary, rbLoc);
}
// MSDN, property (C++)
// https://msdn.microsoft.com/en-us/library/yhfk0thd(v=vs.120).aspx
// This attribute can also be used in the declaration of an empty array in a
// class or structure definition. For example:
// __declspec(property(get=GetX, put=PutX)) int x[];
// The above statement indicates that x[] can be used with one or more array
// indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b),
// and p->x[a][b] = i will be turned into p->PutX(a, b, i);
if (IsMSPropertySubscript) {
// Build MS property subscript expression if base is MS property reference
// or MS property subscript.
return new (Context) MSPropertySubscriptExpr(
base, idx, Context.PseudoObjectTy, VK_LValue, OK_Ordinary, rbLoc);
}
// Use C++ overloaded-operator rules if either operand has record
// type. The spec says to do this if either type is *overloadable*,
// but enum types can't declare subscript operators or conversion
// operators, so there's nothing interesting for overload resolution
// to do if there aren't any record types involved.
//
// ObjC pointers have their own subscripting logic that is not tied
// to overload resolution and so should not take this path.
if (getLangOpts().CPlusPlus &&
(base->getType()->isRecordType() ||
(!base->getType()->isObjCObjectPointerType() &&
idx->getType()->isRecordType()))) {
return CreateOverloadedArraySubscriptExpr(lbLoc, rbLoc, base, idx);
}
ExprResult Res = CreateBuiltinArraySubscriptExpr(base, lbLoc, idx, rbLoc);
if (!Res.isInvalid() && isa<ArraySubscriptExpr>(Res.get()))
CheckSubscriptAccessOfNoDeref(cast<ArraySubscriptExpr>(Res.get()));
return Res;
}
void Sema::CheckAddressOfNoDeref(const Expr *E) {
ExpressionEvaluationContextRecord &LastRecord = ExprEvalContexts.back();
const Expr *StrippedExpr = E->IgnoreParenImpCasts();
// For expressions like `&(*s).b`, the base is recorded and what should be
// checked.
const MemberExpr *Member = nullptr;
while ((Member = dyn_cast<MemberExpr>(StrippedExpr)) && !Member->isArrow())
StrippedExpr = Member->getBase()->IgnoreParenImpCasts();
LastRecord.PossibleDerefs.erase(StrippedExpr);
}
void Sema::CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E) {
QualType ResultTy = E->getType();
ExpressionEvaluationContextRecord &LastRecord = ExprEvalContexts.back();
// Bail if the element is an array since it is not memory access.
if (isa<ArrayType>(ResultTy))
return;
if (ResultTy->hasAttr(attr::NoDeref)) {
LastRecord.PossibleDerefs.insert(E);
return;
}
// Check if the base type is a pointer to a member access of a struct
// marked with noderef.
const Expr *Base = E->getBase();
QualType BaseTy = Base->getType();
if (!(isa<ArrayType>(BaseTy) || isa<PointerType>(BaseTy)))
// Not a pointer access
return;
const MemberExpr *Member = nullptr;
while ((Member = dyn_cast<MemberExpr>(Base->IgnoreParenCasts())) &&
Member->isArrow())
Base = Member->getBase();
if (const auto *Ptr = dyn_cast<PointerType>(Base->getType())) {
if (Ptr->getPointeeType()->hasAttr(attr::NoDeref))
LastRecord.PossibleDerefs.insert(E);
}
}
ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
Expr *LowerBound,
SourceLocation ColonLoc, Expr *Length,
SourceLocation RBLoc) {
if (Base->getType()->isPlaceholderType() &&
!Base->getType()->isSpecificPlaceholderType(
BuiltinType::OMPArraySection)) {
ExprResult Result = CheckPlaceholderExpr(Base);
if (Result.isInvalid())
return ExprError();
Base = Result.get();
}
if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
ExprResult Result = CheckPlaceholderExpr(LowerBound);
if (Result.isInvalid())
return ExprError();
Result = DefaultLvalueConversion(Result.get());
if (Result.isInvalid())
return ExprError();
LowerBound = Result.get();
}
if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
ExprResult Result = CheckPlaceholderExpr(Length);
if (Result.isInvalid())
return ExprError();
Result = DefaultLvalueConversion(Result.get());
if (Result.isInvalid())
return ExprError();
Length = Result.get();
}
// Build an unanalyzed expression if either operand is type-dependent.
if (Base->isTypeDependent() ||
(LowerBound &&
(LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
(Length && (Length->isTypeDependent() || Length->isValueDependent()))) {
return new (Context)
OMPArraySectionExpr(Base, LowerBound, Length, Context.DependentTy,
VK_LValue, OK_Ordinary, ColonLoc, RBLoc);
}
// Perform default conversions.
QualType OriginalTy = OMPArraySectionExpr::getBaseOriginalType(Base);
QualType ResultTy;
if (OriginalTy->isAnyPointerType()) {
ResultTy = OriginalTy->getPointeeType();
} else if (OriginalTy->isArrayType()) {
ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
} else {
return ExprError(
Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
<< Base->getSourceRange());
}
// C99 6.5.2.1p1
if (LowerBound) {
auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
LowerBound);
if (Res.isInvalid())
return ExprError(Diag(LowerBound->getExprLoc(),
diag::err_omp_typecheck_section_not_integer)
<< 0 << LowerBound->getSourceRange());
LowerBound = Res.get();
if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
<< 0 << LowerBound->getSourceRange();
}
if (Length) {
auto Res =
PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
if (Res.isInvalid())
return ExprError(Diag(Length->getExprLoc(),
diag::err_omp_typecheck_section_not_integer)
<< 1 << Length->getSourceRange());
Length = Res.get();
if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
<< 1 << Length->getSourceRange();
}
// C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
// C++ [expr.sub]p1: The type "T" shall be a completely-defined object
// type. Note that functions are not objects, and that (in C99 parlance)
// incomplete types are not object types.
if (ResultTy->isFunctionType()) {
Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
<< ResultTy << Base->getSourceRange();
return ExprError();
}
if (RequireCompleteType(Base->getExprLoc(), ResultTy,
diag::err_omp_section_incomplete_type, Base))
return ExprError();
if (LowerBound && !OriginalTy->isAnyPointerType()) {
Expr::EvalResult Result;
if (LowerBound->EvaluateAsInt(Result, Context)) {
// OpenMP 4.5, [2.4 Array Sections]
// The array section must be a subset of the original array.
llvm::APSInt LowerBoundValue = Result.Val.getInt();
if (LowerBoundValue.isNegative()) {
Diag(LowerBound->getExprLoc(), diag::err_omp_section_not_subset_of_array)
<< LowerBound->getSourceRange();
return ExprError();
}
}
}
if (Length) {
Expr::EvalResult Result;
if (Length->EvaluateAsInt(Result, Context)) {
// OpenMP 4.5, [2.4 Array Sections]
// The length must evaluate to non-negative integers.
llvm::APSInt LengthValue = Result.Val.getInt();
if (LengthValue.isNegative()) {
Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
<< LengthValue.toString(/*Radix=*/10, /*Signed=*/true)
<< Length->getSourceRange();
return ExprError();
}
}
} else if (ColonLoc.isValid() &&
(OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
!OriginalTy->isVariableArrayType()))) {
// OpenMP 4.5, [2.4 Array Sections]
// When the size of the array dimension is not known, the length must be
// specified explicitly.
Diag(ColonLoc, diag::err_omp_section_length_undefined)
<< (!OriginalTy.isNull() && OriginalTy->isArrayType());
return ExprError();
}
if (!Base->getType()->isSpecificPlaceholderType(
BuiltinType::OMPArraySection)) {
ExprResult Result = DefaultFunctionArrayLvalueConversion(Base);
if (Result.isInvalid())
return ExprError();
Base = Result.get();
}
return new (Context)
OMPArraySectionExpr(Base, LowerBound, Length, Context.OMPArraySectionTy,
VK_LValue, OK_Ordinary, ColonLoc, RBLoc);
}
ExprResult
Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Expr *Idx, SourceLocation RLoc) {
Expr *LHSExp = Base;
Expr *RHSExp = Idx;
ExprValueKind VK = VK_LValue;
ExprObjectKind OK = OK_Ordinary;
// Per C++ core issue 1213, the result is an xvalue if either operand is
// a non-lvalue array, and an lvalue otherwise.
if (getLangOpts().CPlusPlus11) {
for (auto *Op : {LHSExp, RHSExp}) {
Op = Op->IgnoreImplicit();
if (Op->getType()->isArrayType() && !Op->isLValue())
VK = VK_XValue;
}
}
// Perform default conversions.
if (!LHSExp->getType()->getAs<VectorType>()) {
ExprResult Result = DefaultFunctionArrayLvalueConversion(LHSExp);
if (Result.isInvalid())
return ExprError();
LHSExp = Result.get();
}
ExprResult Result = DefaultFunctionArrayLvalueConversion(RHSExp);
if (Result.isInvalid())
return ExprError();
RHSExp = Result.get();
QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
// C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
// to the expression *((e1)+(e2)). This means the array "Base" may actually be
// in the subscript position. As a result, we need to derive the array base
// and index from the expression types.
Expr *BaseExpr, *IndexExpr;
QualType ResultType;
if (LHSTy->isDependentType() || RHSTy->isDependentType()) {
BaseExpr = LHSExp;
IndexExpr = RHSExp;
ResultType = Context.DependentTy;
} else if (const PointerType *PTy = LHSTy->getAs<PointerType>()) {
BaseExpr = LHSExp;
IndexExpr = RHSExp;
ResultType = PTy->getPointeeType();
} else if (const ObjCObjectPointerType *PTy =
LHSTy->getAs<ObjCObjectPointerType>()) {
BaseExpr = LHSExp;
IndexExpr = RHSExp;
// Use custom logic if this should be the pseudo-object subscript
// expression.
if (!LangOpts.isSubscriptPointerArithmetic())
return BuildObjCSubscriptExpression(RLoc, BaseExpr, IndexExpr, nullptr,
nullptr);
ResultType = PTy->getPointeeType();
} else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) {
// Handle the uncommon case of "123[Ptr]".
BaseExpr = RHSExp;
IndexExpr = LHSExp;
ResultType = PTy->getPointeeType();
} else if (const ObjCObjectPointerType *PTy =
RHSTy->getAs<ObjCObjectPointerType>()) {
// Handle the uncommon case of "123[Ptr]".
BaseExpr = RHSExp;
IndexExpr = LHSExp;
ResultType = PTy->getPointeeType();
if (!LangOpts.isSubscriptPointerArithmetic()) {
Diag(LLoc, diag::err_subscript_nonfragile_interface)
<< ResultType << BaseExpr->getSourceRange();
return ExprError();
}
} else if (const VectorType *VTy = LHSTy->getAs<VectorType>()) {
BaseExpr = LHSExp; // vectors: V[123]
IndexExpr = RHSExp;
// We apply C++ DR1213 to vector subscripting too.
if (getLangOpts().CPlusPlus11 && LHSExp->getValueKind() == VK_RValue) {
ExprResult Materialized = TemporaryMaterializationConversion(LHSExp);
if (Materialized.isInvalid())
return ExprError();
LHSExp = Materialized.get();
}
VK = LHSExp->getValueKind();
if (VK != VK_RValue)
OK = OK_VectorComponent;
ResultType = VTy->getElementType();
QualType BaseType = BaseExpr->getType();
Qualifiers BaseQuals = BaseType.getQualifiers();
Qualifiers MemberQuals = ResultType.getQualifiers();
Qualifiers Combined = BaseQuals + MemberQuals;
if (Combined != MemberQuals)
ResultType = Context.getQualifiedType(ResultType, Combined);
} else if (LHSTy->isArrayType()) {
// If we see an array that wasn't promoted by
// DefaultFunctionArrayLvalueConversion, it must be an array that
// wasn't promoted because of the C90 rule that doesn't
// allow promoting non-lvalue arrays. Warn, then
// force the promotion here.
Diag(LHSExp->getBeginLoc(), diag::ext_subscript_non_lvalue)
<< LHSExp->getSourceRange();
LHSExp = ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy),
CK_ArrayToPointerDecay).get();
LHSTy = LHSExp->getType();
BaseExpr = LHSExp;
IndexExpr = RHSExp;
ResultType = LHSTy->getAs<PointerType>()->getPointeeType();
} else if (RHSTy->isArrayType()) {
// Same as previous, except for 123[f().a] case
Diag(RHSExp->getBeginLoc(), diag::ext_subscript_non_lvalue)
<< RHSExp->getSourceRange();
RHSExp = ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy),
CK_ArrayToPointerDecay).get();
RHSTy = RHSExp->getType();
BaseExpr = RHSExp;
IndexExpr = LHSExp;
ResultType = RHSTy->getAs<PointerType>()->getPointeeType();
} else {
return ExprError(Diag(LLoc, diag::err_typecheck_subscript_value)
<< LHSExp->getSourceRange() << RHSExp->getSourceRange());
}
// C99 6.5.2.1p1
if (!IndexExpr->getType()->isIntegerType() && !IndexExpr->isTypeDependent())
return ExprError(Diag(LLoc, diag::err_typecheck_subscript_not_integer)
<< IndexExpr->getSourceRange());
if ((IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
&& !IndexExpr->isTypeDependent())
Diag(LLoc, diag::warn_subscript_is_char) << IndexExpr->getSourceRange();
// C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
// C++ [expr.sub]p1: The type "T" shall be a completely-defined object
// type. Note that Functions are not objects, and that (in C99 parlance)
// incomplete types are not object types.
if (ResultType->isFunctionType()) {
Diag(BaseExpr->getBeginLoc(), diag::err_subscript_function_type)
<< ResultType << BaseExpr->getSourceRange();
return ExprError();
}
if (ResultType->isVoidType() && !getLangOpts().CPlusPlus) {
// GNU extension: subscripting on pointer to void
Diag(LLoc, diag::ext_gnu_subscript_void_type)
<< BaseExpr->getSourceRange();
// C forbids expressions of unqualified void type from being l-values.
// See IsCForbiddenLValueType.
if (!ResultType.hasQualifiers()) VK = VK_RValue;
} else if (!ResultType->isDependentType() &&
RequireCompleteType(LLoc, ResultType,
diag::err_subscript_incomplete_type, BaseExpr))
return ExprError();
assert(VK == VK_RValue || LangOpts.CPlusPlus ||
!ResultType.isCForbiddenLValueType());
return new (Context)
ArraySubscriptExpr(LHSExp, RHSExp, ResultType, VK, OK, RLoc);
}
bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
ParmVarDecl *Param) {
if (Param->hasUnparsedDefaultArg()) {
Diag(CallLoc,
diag::err_use_of_default_argument_to_function_declared_later) <<
FD << cast<CXXRecordDecl>(FD->getDeclContext())->getDeclName();
Diag(UnparsedDefaultArgLocs[Param],
diag::note_default_argument_declared_here);
return true;
}
if (Param->hasUninstantiatedDefaultArg()) {
Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
EnterExpressionEvaluationContext EvalContext(
*this, ExpressionEvaluationContext::PotentiallyEvaluated, Param);
// Instantiate the expression.
//
// FIXME: Pass in a correct Pattern argument, otherwise
// getTemplateInstantiationArgs uses the lexical context of FD, e.g.
//
// template<typename T>
// struct A {
// static int FooImpl();
//
// template<typename Tp>
// // bug: default argument A<T>::FooImpl() is evaluated with 2-level
// // template argument list [[T], [Tp]], should be [[Tp]].
// friend A<Tp> Foo(int a);
// };
//
// template<typename T>
// A<T> Foo(int a = A<T>::FooImpl());
MultiLevelTemplateArgumentList MutiLevelArgList
= getTemplateInstantiationArgs(FD, nullptr, /*RelativeToPrimary=*/true);
InstantiatingTemplate Inst(*this, CallLoc, Param,
MutiLevelArgList.getInnermost());
if (Inst.isInvalid())
return true;
if (Inst.isAlreadyInstantiating()) {
Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD;
Param->setInvalidDecl();
return true;
}
ExprResult Result;
{
// C++ [dcl.fct.default]p5:
// The names in the [default argument] expression are bound, and
// the semantic constraints are checked, at the point where the
// default argument expression appears.
ContextRAII SavedContext(*this, FD);
LocalInstantiationScope Local(*this);
Result = SubstInitializer(UninstExpr, MutiLevelArgList,
/*DirectInit*/false);
}
if (Result.isInvalid())
return true;
// Check the expression as an initializer for the parameter.
InitializedEntity Entity
= InitializedEntity::InitializeParameter(Context, Param);
InitializationKind Kind = InitializationKind::CreateCopy(
Param->getLocation(),
/*FIXME:EqualLoc*/ UninstExpr->getBeginLoc());
Expr *ResultE = Result.getAs<Expr>();
InitializationSequence InitSeq(*this, Entity, Kind, ResultE);
Result = InitSeq.Perform(*this, Entity, Kind, ResultE);
if (Result.isInvalid())
return true;
Result =
ActOnFinishFullExpr(Result.getAs<Expr>(), Param->getOuterLocStart(),
/*DiscardedValue*/ false);
if (Result.isInvalid())
return true;
// Remember the instantiated default argument.
Param->setDefaultArg(Result.getAs<Expr>());
if (ASTMutationListener *L = getASTMutationListener()) {
L->DefaultArgumentInstantiated(Param);
}
}
// If the default argument expression is not set yet, we are building it now.
if (!Param->hasInit()) {
Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD;
Param->setInvalidDecl();
return true;
}
// If the default expression creates temporaries, we need to
// push them to the current stack of expression temporaries so they'll
// be properly destroyed.
// FIXME: We should really be rebuilding the default argument with new
// bound temporaries; see the comment in PR5810.
// We don't need to do that with block decls, though, because
// blocks in default argument expression can never capture anything.
if (auto Init = dyn_cast<ExprWithCleanups>(Param->getInit())) {
// Set the "needs cleanups" bit regardless of whether there are
// any explicit objects.
Cleanup.setExprNeedsCleanups(Init->cleanupsHaveSideEffects());
// Append all the objects to the cleanup list. Right now, this
// should always be a no-op, because blocks in default argument
// expressions should never be able to capture anything.
assert(!Init->getNumObjects() &&
"default argument expression has capturing blocks?");
}
// We already type-checked the argument, so we know it works.
// Just mark all of the declarations in this potentially-evaluated expression
// as being "referenced".
MarkDeclarationsReferencedInExpr(Param->getDefaultArg(),
/*SkipLocalVariables=*/true);
return false;
}
ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
FunctionDecl *FD, ParmVarDecl *Param) {
if (CheckCXXDefaultArgExpr(CallLoc, FD, Param))
return ExprError();
return CXXDefaultArgExpr::Create(Context, CallLoc, Param);
}
Sema::VariadicCallType
Sema::getVariadicCallType(FunctionDecl *FDecl, const FunctionProtoType *Proto,
Expr *Fn) {
if (Proto && Proto->isVariadic()) {
if (dyn_cast_or_null<CXXConstructorDecl>(FDecl))
return VariadicConstructor;
else if (Fn && Fn->getType()->isBlockPointerType())
return VariadicBlock;
else if (FDecl) {
if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl))
if (Method->isInstance())
return VariadicMethod;
} else if (Fn && Fn->getType() == Context.BoundMemberTy)
return VariadicMethod;
return VariadicFunction;
}
return VariadicDoesNotApply;
}
namespace {
class FunctionCallCCC : public FunctionCallFilterCCC {
public:
FunctionCallCCC(Sema &SemaRef, const IdentifierInfo *FuncName,
unsigned NumArgs, MemberExpr *ME)
: FunctionCallFilterCCC(SemaRef, NumArgs, false, ME),
FunctionName(FuncName) {}
bool ValidateCandidate(const TypoCorrection &candidate) override {
if (!candidate.getCorrectionSpecifier() ||
candidate.getCorrectionAsIdentifierInfo() != FunctionName) {
return false;
}
return FunctionCallFilterCCC::ValidateCandidate(candidate);
}
private:
const IdentifierInfo *const FunctionName;
};
}
static TypoCorrection TryTypoCorrectionForCall(Sema &S, Expr *Fn,
FunctionDecl *FDecl,
ArrayRef<Expr *> Args) {
MemberExpr *ME = dyn_cast<MemberExpr>(Fn);
DeclarationName FuncName = FDecl->getDeclName();
SourceLocation NameLoc = ME ? ME->getMemberLoc() : Fn->getBeginLoc();
if (TypoCorrection Corrected = S.CorrectTypo(
DeclarationNameInfo(FuncName, NameLoc), Sema::LookupOrdinaryName,
S.getScopeForContext(S.CurContext), nullptr,
llvm::make_unique<FunctionCallCCC>(S, FuncName.getAsIdentifierInfo(),
Args.size(), ME),
Sema::CTK_ErrorRecovery)) {
if (NamedDecl *ND = Corrected.getFoundDecl()) {
if (Corrected.isOverloaded()) {
OverloadCandidateSet OCS(NameLoc, OverloadCandidateSet::CSK_Normal);
OverloadCandidateSet::iterator Best;
for (NamedDecl *CD : Corrected) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(CD))
S.AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none), Args,
OCS);
}
switch (OCS.BestViableFunction(S, NameLoc, Best)) {
case OR_Success:
ND = Best->FoundDecl;
Corrected.setCorrectionDecl(ND);
break;
default:
break;
}
}
ND = ND->getUnderlyingDecl();
if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND))
return Corrected;
}
}
return TypoCorrection();
}
/// ConvertArgumentsForCall - Converts the arguments specified in
/// Args/NumArgs to the parameter types of the function FDecl with
/// function prototype Proto. Call is the call expression itself, and
/// Fn is the function expression. For a C++ member function, this
/// routine does not attempt to convert the object argument. Returns
/// true if the call is ill-formed.
bool
Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
FunctionDecl *FDecl,
const FunctionProtoType *Proto,
ArrayRef<Expr *> Args,
SourceLocation RParenLoc,
bool IsExecConfig) {
// Bail out early if calling a builtin with custom typechecking.
if (FDecl)
if (unsigned ID = FDecl->getBuiltinID())
if (Context.BuiltinInfo.hasCustomTypechecking(ID))
return false;
// C99 6.5.2.2p7 - the arguments are implicitly converted, as if by
// assignment, to the types of the corresponding parameter, ...
unsigned NumParams = Proto->getNumParams();
bool Invalid = false;
unsigned MinArgs = FDecl ? FDecl->getMinRequiredArguments() : NumParams;
unsigned FnKind = Fn->getType()->isBlockPointerType()
? 1 /* block */
: (IsExecConfig ? 3 /* kernel function (exec config) */
: 0 /* function */);
// If too few arguments are available (and we don't have default
// arguments for the remaining parameters), don't make the call.
if (Args.size() < NumParams) {
if (Args.size() < MinArgs) {
TypoCorrection TC;
if (FDecl && (TC = TryTypoCorrectionForCall(*this, Fn, FDecl, Args))) {
unsigned diag_id =
MinArgs == NumParams && !Proto->isVariadic()
? diag::err_typecheck_call_too_few_args_suggest
: diag::err_typecheck_call_too_few_args_at_least_suggest;
diagnoseTypo(TC, PDiag(diag_id) << FnKind << MinArgs
<< static_cast<unsigned>(Args.size())
<< TC.getCorrectionRange());
} else if (MinArgs == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName())
Diag(RParenLoc,
MinArgs == NumParams && !Proto->isVariadic()
? diag::err_typecheck_call_too_few_args_one
: diag::err_typecheck_call_too_few_args_at_least_one)
<< FnKind << FDecl->getParamDecl(0) << Fn->getSourceRange();
else
Diag(RParenLoc, MinArgs == NumParams && !Proto->isVariadic()
? diag::err_typecheck_call_too_few_args
: diag::err_typecheck_call_too_few_args_at_least)
<< FnKind << MinArgs << static_cast<unsigned>(Args.size())
<< Fn->getSourceRange();
// Emit the location of the prototype.
if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
Diag(FDecl->getBeginLoc(), diag::note_callee_decl) << FDecl;
return true;
}
// We reserve space for the default arguments when we create
// the call expression, before calling ConvertArgumentsForCall.
assert((Call->getNumArgs() == NumParams) &&
"We should have reserved space for the default arguments before!");
}
// If too many are passed and not variadic, error on the extras and drop
// them.
if (Args.size() > NumParams) {
if (!Proto->isVariadic()) {
TypoCorrection TC;
if (FDecl && (TC = TryTypoCorrectionForCall(*this, Fn, FDecl, Args))) {
unsigned diag_id =
MinArgs == NumParams && !Proto->isVariadic()
? diag::err_typecheck_call_too_many_args_suggest
: diag::err_typecheck_call_too_many_args_at_most_suggest;
diagnoseTypo(TC, PDiag(diag_id) << FnKind << NumParams
<< static_cast<unsigned>(Args.size())
<< TC.getCorrectionRange());
} else if (NumParams == 1 && FDecl &&
FDecl->getParamDecl(0)->getDeclName())
Diag(Args[NumParams]->getBeginLoc(),
MinArgs == NumParams
? diag::err_typecheck_call_too_many_args_one
: diag::err_typecheck_call_too_many_args_at_most_one)
<< FnKind << FDecl->getParamDecl(0)
<< static_cast<unsigned>(Args.size()) << Fn->getSourceRange()
<< SourceRange(Args[NumParams]->getBeginLoc(),
Args.back()->getEndLoc());
else
Diag(Args[NumParams]->getBeginLoc(),
MinArgs == NumParams
? diag::err_typecheck_call_too_many_args
: diag::err_typecheck_call_too_many_args_at_most)
<< FnKind << NumParams << static_cast<unsigned>(Args.size())
<< Fn->getSourceRange()
<< SourceRange(Args[NumParams]->getBeginLoc(),
Args.back()->getEndLoc());
// Emit the location of the prototype.
if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
Diag(FDecl->getBeginLoc(), diag::note_callee_decl) << FDecl;
// This deletes the extra arguments.
Call->shrinkNumArgs(NumParams);
return true;
}
}
SmallVector<Expr *, 8> AllArgs;
VariadicCallType CallType = getVariadicCallType(FDecl, Proto, Fn);
Invalid = GatherArgumentsForCall(Call->getBeginLoc(), FDecl, Proto, 0, Args,
AllArgs, CallType);
if (Invalid)
return true;
unsigned TotalNumArgs = AllArgs.size();
for (unsigned i = 0; i < TotalNumArgs; ++i)
Call->setArg(i, AllArgs[i]);
return false;
}
bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
const FunctionProtoType *Proto,
unsigned FirstParam, ArrayRef<Expr *> Args,
SmallVectorImpl<Expr *> &AllArgs,
VariadicCallType CallType, bool AllowExplicit,
bool IsListInitialization) {
unsigned NumParams = Proto->getNumParams();
bool Invalid = false;
size_t ArgIx = 0;
// Continue to check argument types (even if we have too few/many args).
for (unsigned i = FirstParam; i < NumParams; i++) {
QualType ProtoArgType = Proto->getParamType(i);
Expr *Arg;
ParmVarDecl *Param = FDecl ? FDecl->getParamDecl(i) : nullptr;
if (ArgIx < Args.size()) {
Arg = Args[ArgIx++];
if (RequireCompleteType(Arg->getBeginLoc(), ProtoArgType,
diag::err_call_incomplete_argument, Arg))
return true;
// Strip the unbridged-cast placeholder expression off, if applicable.
bool CFAudited = false;
if (Arg->getType() == Context.ARCUnbridgedCastTy &&
FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() &&
(!Param || !Param->hasAttr<CFConsumedAttr>()))
Arg = stripARCUnbridgedCast(Arg);
else if (getLangOpts().ObjCAutoRefCount &&
FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() &&
(!Param || !Param->hasAttr<CFConsumedAttr>()))
CFAudited = true;
if (Proto->getExtParameterInfo(i).isNoEscape())
if (auto *BE = dyn_cast<BlockExpr>(Arg->IgnoreParenNoopCasts(Context)))
BE->getBlockDecl()->setDoesNotEscape();
InitializedEntity Entity =
Param ? InitializedEntity::InitializeParameter(Context, Param,
ProtoArgType)
: InitializedEntity::InitializeParameter(
Context, ProtoArgType, Proto->isParamConsumed(i));
// Remember that parameter belongs to a CF audited API.
if (CFAudited)
Entity.setParameterCFAudited();
ExprResult ArgE = PerformCopyInitialization(
Entity, SourceLocation(), Arg, IsListInitialization, AllowExplicit);
if (ArgE.isInvalid())
return true;
Arg = ArgE.getAs<Expr>();
} else {
assert(Param && "can't use default arguments without a known callee");
ExprResult ArgExpr =
BuildCXXDefaultArgExpr(CallLoc, FDecl, Param);
if (ArgExpr.isInvalid())
return true;
Arg = ArgExpr.getAs<Expr>();
}
// Check for array bounds violations for each argument to the call. This
// check only triggers warnings when the argument isn't a more complex Expr
// with its own checking, such as a BinaryOperator.
CheckArrayAccess(Arg);
// Check for violations of C99 static array rules (C99 6.7.5.3p7).
CheckStaticArrayArgument(CallLoc, Param, Arg);
AllArgs.push_back(Arg);
}
// If this is a variadic call, handle args passed through "...".
if (CallType != VariadicDoesNotApply) {
// Assume that extern "C" functions with variadic arguments that
// return __unknown_anytype aren't *really* variadic.
if (Proto->getReturnType() == Context.UnknownAnyTy && FDecl &&
FDecl->isExternC()) {
for (Expr *A : Args.slice(ArgIx)) {
QualType paramType; // ignored
ExprResult arg = checkUnknownAnyArg(CallLoc, A, paramType);
Invalid |= arg.isInvalid();
AllArgs.push_back(arg.get());
}
// Otherwise do argument promotion, (C99 6.5.2.2p7).
} else {
for (Expr *A : Args.slice(ArgIx)) {
ExprResult Arg = DefaultVariadicArgumentPromotion(A, CallType, FDecl);
Invalid |= Arg.isInvalid();
AllArgs.push_back(Arg.get());
}
}
// Check for array bounds violations.
for (Expr *A : Args.slice(ArgIx))
CheckArrayAccess(A);
}
return Invalid;
}
static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) {
TypeLoc TL = PVD->getTypeSourceInfo()->getTypeLoc();
if (DecayedTypeLoc DTL = TL.getAs<DecayedTypeLoc>())
TL = DTL.getOriginalLoc();
if (ArrayTypeLoc ATL = TL.getAs<ArrayTypeLoc>())
S.Diag(PVD->getLocation(), diag::note_callee_static_array)
<< ATL.getLocalSourceRange();
}
/// CheckStaticArrayArgument - If the given argument corresponds to a static
/// array parameter, check that it is non-null, and that if it is formed by
/// array-to-pointer decay, the underlying array is sufficiently large.
///
/// C99 6.7.5.3p7: If the keyword static also appears within the [ and ] of the
/// array type derivation, then for each call to the function, the value of the
/// corresponding actual argument shall provide access to the first element of
/// an array with at least as many elements as specified by the size expression.
void
Sema::CheckStaticArrayArgument(SourceLocation CallLoc,
ParmVarDecl *Param,
const Expr *ArgExpr) {
// Static array parameters are not supported in C++.
if (!Param || getLangOpts().CPlusPlus)
return;
QualType OrigTy = Param->getOriginalType();
const ArrayType *AT = Context.getAsArrayType(OrigTy);
if (!AT || AT->getSizeModifier() != ArrayType::Static)
return;
if (ArgExpr->isNullPointerConstant(Context,
Expr::NPC_NeverValueDependent)) {
Diag(CallLoc, diag::warn_null_arg) << ArgExpr->getSourceRange();
DiagnoseCalleeStaticArrayParam(*this, Param);
return;
}
const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT);
if (!CAT)
return;
const ConstantArrayType *ArgCAT =
Context.getAsConstantArrayType(ArgExpr->IgnoreParenImpCasts()->getType());
if (!ArgCAT)
return;
if (ArgCAT->getSize().ult(CAT->getSize())) {
Diag(CallLoc, diag::warn_static_array_too_small)
<< ArgExpr->getSourceRange()
<< (unsigned) ArgCAT->getSize().getZExtValue()
<< (unsigned) CAT->getSize().getZExtValue();
DiagnoseCalleeStaticArrayParam(*this, Param);
}
}
/// Given a function expression of unknown-any type, try to rebuild it
/// to have a function type.
static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn);
/// Is the given type a placeholder that we need to lower out
/// immediately during argument processing?
static bool isPlaceholderToRemoveAsArg(QualType type) {
// Placeholders are never sugared.
const BuiltinType *placeholder = dyn_cast<BuiltinType>(type);
if (!placeholder) return false;
switch (placeholder->getKind()) {
// Ignore all the non-placeholder types.
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLExtensionTypes.def"
#define PLACEHOLDER_TYPE(ID, SINGLETON_ID)
#define BUILTIN_TYPE(ID, SINGLETON_ID) case BuiltinType::ID:
#include "clang/AST/BuiltinTypes.def"
return false;
// We cannot lower out overload sets; they might validly be resolved
// by the call machinery.
case BuiltinType::Overload:
return false;
// Unbridged casts in ARC can be handled in some call positions and
// should be left in place.
case BuiltinType::ARCUnbridgedCast:
return false;
// Pseudo-objects should be converted as soon as possible.
case BuiltinType::PseudoObject:
return true;
// The debugger mode could theoretically but currently does not try
// to resolve unknown-typed arguments based on known parameter types.
case BuiltinType::UnknownAny:
return true;
// These are always invalid as call arguments and should be reported.
case BuiltinType::BoundMember:
case BuiltinType::BuiltinFn:
case BuiltinType::OMPArraySection:
return true;
}
llvm_unreachable("bad builtin type kind");
}
/// Check an argument list for placeholders that we won't try to
/// handle later.
static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args) {
// Apply this processing to all the arguments at once instead of
// dying at the first failure.
bool hasInvalid = false;
for (size_t i = 0, e = args.size(); i != e; i++) {
if (isPlaceholderToRemoveAsArg(args[i]->getType())) {
ExprResult result = S.CheckPlaceholderExpr(args[i]);
if (result.isInvalid()) hasInvalid = true;
else args[i] = result.get();
} else if (hasInvalid) {
(void)S.CorrectDelayedTyposInExpr(args[i]);
}
}
return hasInvalid;
}
/// If a builtin function has a pointer argument with no explicit address
/// space, then it should be able to accept a pointer to any address
/// space as input. In order to do this, we need to replace the
/// standard builtin declaration with one that uses the same address space
/// as the call.
///
/// \returns nullptr If this builtin is not a candidate for a rewrite i.e.
/// it does not contain any pointer arguments without
/// an address space qualifer. Otherwise the rewritten
/// FunctionDecl is returned.
/// TODO: Handle pointer return types.
static FunctionDecl *rewriteBuiltinFunctionDecl(Sema *Sema, ASTContext &Context,
const FunctionDecl *FDecl,
MultiExprArg ArgExprs) {
QualType DeclType = FDecl->getType();
const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(DeclType);
if (!Context.BuiltinInfo.hasPtrArgsOrResult(FDecl->getBuiltinID()) ||
!FT || FT->isVariadic() || ArgExprs.size() != FT->getNumParams())
return nullptr;
bool NeedsNewDecl = false;
unsigned i = 0;
SmallVector<QualType, 8> OverloadParams;
for (QualType ParamType : FT->param_types()) {
// Convert array arguments to pointer to simplify type lookup.
ExprResult ArgRes =
Sema->DefaultFunctionArrayLvalueConversion(ArgExprs[i++]);
if (ArgRes.isInvalid())
return nullptr;
Expr *Arg = ArgRes.get();
QualType ArgType = Arg->getType();
if (!ParamType->isPointerType() ||
ParamType.getQualifiers().hasAddressSpace() ||
!ArgType->isPointerType() ||
!ArgType->getPointeeType().getQualifiers().hasAddressSpace()) {
OverloadParams.push_back(ParamType);
continue;
}
QualType PointeeType = ParamType->getPointeeType();
if (PointeeType.getQualifiers().hasAddressSpace())
continue;
NeedsNewDecl = true;
LangAS AS = ArgType->getPointeeType().getAddressSpace();
PointeeType = Context.getAddrSpaceQualType(PointeeType, AS);
OverloadParams.push_back(Context.getPointerType(PointeeType));
}
if (!NeedsNewDecl)
return nullptr;
FunctionProtoType::ExtProtoInfo EPI;
QualType OverloadTy = Context.getFunctionType(FT->getReturnType(),
OverloadParams, EPI);
DeclContext *Parent = Context.getTranslationUnitDecl();
FunctionDecl *OverloadDecl = FunctionDecl::Create(Context, Parent,
FDecl->getLocation(),
FDecl->getLocation(),
FDecl->getIdentifier(),
OverloadTy,
/*TInfo=*/nullptr,
SC_Extern, false,
/*hasPrototype=*/true);
SmallVector<ParmVarDecl*, 16> Params;
FT = cast<FunctionProtoType>(OverloadTy);
for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
QualType ParamType = FT->getParamType(i);
ParmVarDecl *Parm =
ParmVarDecl::Create(Context, OverloadDecl, SourceLocation(),
SourceLocation(), nullptr, ParamType,
/*TInfo=*/nullptr, SC_None, nullptr);
Parm->setScopeInfo(0, i);
Params.push_back(Parm);
}
OverloadDecl->setParams(Params);
return OverloadDecl;
}
static void checkDirectCallValidity(Sema &S, const Expr *Fn,
FunctionDecl *Callee,
MultiExprArg ArgExprs) {
// `Callee` (when called with ArgExprs) may be ill-formed. enable_if (and
// similar attributes) really don't like it when functions are called with an
// invalid number of args.
if (S.TooManyArguments(Callee->getNumParams(), ArgExprs.size(),
/*PartialOverloading=*/false) &&
!Callee->isVariadic())
return;
if (Callee->getMinRequiredArguments() > ArgExprs.size())
return;
if (const EnableIfAttr *Attr = S.CheckEnableIf(Callee, ArgExprs, true)) {
S.Diag(Fn->getBeginLoc(),
isa<CXXMethodDecl>(Callee)
? diag::err_ovl_no_viable_member_function_in_call
: diag::err_ovl_no_viable_function_in_call)
<< Callee << Callee->getSourceRange();
S.Diag(Callee->getLocation(),
diag::note_ovl_candidate_disabled_by_function_cond_attr)
<< Attr->getCond()->getSourceRange() << Attr->getMessage();
return;
}
}
static bool enclosingClassIsRelatedToClassInWhichMembersWereFound(
const UnresolvedMemberExpr *const UME, Sema &S) {
const auto GetFunctionLevelDCIfCXXClass =
[](Sema &S) -> const CXXRecordDecl * {
const DeclContext *const DC = S.getFunctionLevelDeclContext();
if (!DC || !DC->getParent())
return nullptr;
// If the call to some member function was made from within a member
// function body 'M' return return 'M's parent.
if (const auto *MD = dyn_cast<CXXMethodDecl>(DC))
return MD->getParent()->getCanonicalDecl();
// else the call was made from within a default member initializer of a
// class, so return the class.
if (const auto *RD = dyn_cast<CXXRecordDecl>(DC))
return RD->getCanonicalDecl();
return nullptr;
};
// If our DeclContext is neither a member function nor a class (in the
// case of a lambda in a default member initializer), we can't have an
// enclosing 'this'.
const CXXRecordDecl *const CurParentClass = GetFunctionLevelDCIfCXXClass(S);
if (!CurParentClass)
return false;
// The naming class for implicit member functions call is the class in which
// name lookup starts.
const CXXRecordDecl *const NamingClass =
UME->getNamingClass()->getCanonicalDecl();
assert(NamingClass && "Must have naming class even for implicit access");
// If the unresolved member functions were found in a 'naming class' that is
// related (either the same or derived from) to the class that contains the
// member function that itself contained the implicit member access.
return CurParentClass == NamingClass ||
CurParentClass->isDerivedFrom(NamingClass);
}
static void
tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs(
Sema &S, const UnresolvedMemberExpr *const UME, SourceLocation CallLoc) {
if (!UME)
return;
LambdaScopeInfo *const CurLSI = S.getCurLambda();
// Only try and implicitly capture 'this' within a C++ Lambda if it hasn't
// already been captured, or if this is an implicit member function call (if
// it isn't, an attempt to capture 'this' should already have been made).
if (!CurLSI || CurLSI->ImpCaptureStyle == CurLSI->ImpCap_None ||
!UME->isImplicitAccess() || CurLSI->isCXXThisCaptured())
return;
// Check if the naming class in which the unresolved members were found is
// related (same as or is a base of) to the enclosing class.
if (!enclosingClassIsRelatedToClassInWhichMembersWereFound(UME, S))
return;
DeclContext *EnclosingFunctionCtx = S.CurContext->getParent()->getParent();
// If the enclosing function is not dependent, then this lambda is
// capture ready, so if we can capture this, do so.
if (!EnclosingFunctionCtx->isDependentContext()) {
// If the current lambda and all enclosing lambdas can capture 'this' -
// then go ahead and capture 'this' (since our unresolved overload set
// contains at least one non-static member function).
if (!S.CheckCXXThisCapture(CallLoc, /*Explcit*/ false, /*Diagnose*/ false))
S.CheckCXXThisCapture(CallLoc);
} else if (S.CurContext->isDependentContext()) {
// ... since this is an implicit member reference, that might potentially
// involve a 'this' capture, mark 'this' for potential capture in
// enclosing lambdas.
if (CurLSI->ImpCaptureStyle != CurLSI->ImpCap_None)
CurLSI->addPotentialThisCapture(CallLoc);
}
}
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations.
ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
MultiExprArg ArgExprs, SourceLocation RParenLoc,
Expr *ExecConfig, bool IsExecConfig) {
// Since this might be a postfix expression, get rid of ParenListExprs.
ExprResult Result = MaybeConvertParenListExprToParenExpr(Scope, Fn);
if (Result.isInvalid()) return ExprError();
Fn = Result.get();
if (checkArgsForPlaceholders(*this, ArgExprs))
return ExprError();
if (getLangOpts().CPlusPlus) {
// If this is a pseudo-destructor expression, build the call immediately.
if (isa<CXXPseudoDestructorExpr>(Fn)) {
if (!ArgExprs.empty()) {
// Pseudo-destructor calls should not have any arguments.
Diag(Fn->getBeginLoc(), diag::err_pseudo_dtor_call_with_args)
<< FixItHint::CreateRemoval(
SourceRange(ArgExprs.front()->getBeginLoc(),
ArgExprs.back()->getEndLoc()));
}
return CallExpr::Create(Context, Fn, /*Args=*/{}, Context.VoidTy,
VK_RValue, RParenLoc);
}
if (Fn->getType() == Context.PseudoObjectTy) {
ExprResult result = CheckPlaceholderExpr(Fn);
if (result.isInvalid()) return ExprError();
Fn = result.get();
}
// Determine whether this is a dependent call inside a C++ template,
// in which case we won't do any semantic analysis now.
if (Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(ArgExprs)) {
if (ExecConfig) {
return CUDAKernelCallExpr::Create(
Context, Fn, cast<CallExpr>(ExecConfig), ArgExprs,
Context.DependentTy, VK_RValue, RParenLoc);
} else {
tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs(
*this, dyn_cast<UnresolvedMemberExpr>(Fn->IgnoreParens()),
Fn->getBeginLoc());
return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy,
VK_RValue, RParenLoc);
}
}
// Determine whether this is a call to an object (C++ [over.call.object]).
if (Fn->getType()->isRecordType())
return BuildCallToObjectOfClassType(Scope, Fn, LParenLoc, ArgExprs,
RParenLoc);
if (Fn->getType() == Context.UnknownAnyTy) {
ExprResult result = rebuildUnknownAnyFunction(*this, Fn);
if (result.isInvalid()) return ExprError();
Fn = result.get();
}
if (Fn->getType() == Context.BoundMemberTy) {
return BuildCallToMemberFunction(Scope, Fn, LParenLoc, ArgExprs,
RParenLoc);
}
}
// Check for overloaded calls. This can happen even in C due to extensions.
if (Fn->getType() == Context.OverloadTy) {
OverloadExpr::FindResult find = OverloadExpr::find(Fn);
// We aren't supposed to apply this logic if there's an '&' involved.
if (!find.HasFormOfMemberPointer) {
if (Expr::hasAnyTypeDependentArguments(ArgExprs))
return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy,
VK_RValue, RParenLoc);
OverloadExpr *ovl = find.Expression;
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(ovl))
return BuildOverloadedCallExpr(
Scope, Fn, ULE, LParenLoc, ArgExprs, RParenLoc, ExecConfig,
/*AllowTypoCorrection=*/true, find.IsAddressOfOperand);
return BuildCallToMemberFunction(Scope, Fn, LParenLoc, ArgExprs,
RParenLoc);
}
}
// If we're directly calling a function, get the appropriate declaration.
if (Fn->getType() == Context.UnknownAnyTy) {
ExprResult result = rebuildUnknownAnyFunction(*this, Fn);
if (result.isInvalid()) return ExprError();
Fn = result.get();
}
Expr *NakedFn = Fn->IgnoreParens();
bool CallingNDeclIndirectly = false;
NamedDecl *NDecl = nullptr;
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn)) {
if (UnOp->getOpcode() == UO_AddrOf) {
CallingNDeclIndirectly = true;
NakedFn = UnOp->getSubExpr()->IgnoreParens();
}
}
if (isa<DeclRefExpr>(NakedFn)) {
NDecl = cast<DeclRefExpr>(NakedFn)->getDecl();
FunctionDecl *FDecl = dyn_cast<FunctionDecl>(NDecl);
if (FDecl && FDecl->getBuiltinID()) {
// Rewrite the function decl for this builtin by replacing parameters
// with no explicit address space with the address space of the arguments
// in ArgExprs.
if ((FDecl =
rewriteBuiltinFunctionDecl(this, Context, FDecl, ArgExprs))) {
NDecl = FDecl;
Fn = DeclRefExpr::Create(
Context, FDecl->getQualifierLoc(), SourceLocation(), FDecl, false,
SourceLocation(), FDecl->getType(), Fn->getValueKind(), FDecl);
}
}
} else if (isa<MemberExpr>(NakedFn))
NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl();
if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(NDecl)) {
if (CallingNDeclIndirectly && !checkAddressOfFunctionIsAvailable(
FD, /*Complain=*/true, Fn->getBeginLoc()))
return ExprError();
if (getLangOpts().OpenCL && checkOpenCLDisabledDecl(*FD, *Fn))
return ExprError();
checkDirectCallValidity(*this, Fn, FD, ArgExprs);
}
return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc,
ExecConfig, IsExecConfig);
}
/// ActOnAsTypeExpr - create a new asType (bitcast) from the arguments.
///
/// __builtin_astype( value, dst type )
///
ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
SourceLocation BuiltinLoc,
SourceLocation RParenLoc) {
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
QualType DstTy = GetTypeFromParser(ParsedDestTy);
QualType SrcTy = E->getType();
if (Context.getTypeSize(DstTy) != Context.getTypeSize(SrcTy))
return ExprError(Diag(BuiltinLoc,
diag::err_invalid_astype_of_different_size)
<< DstTy
<< SrcTy
<< E->getSourceRange());
return new (Context) AsTypeExpr(E, DstTy, VK, OK, BuiltinLoc, RParenLoc);
}
/// ActOnConvertVectorExpr - create a new convert-vector expression from the
/// provided arguments.
///
/// __builtin_convertvector( value, dst type )
///
ExprResult Sema::ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy,
SourceLocation BuiltinLoc,
SourceLocation RParenLoc) {
TypeSourceInfo *TInfo;
GetTypeFromParser(ParsedDestTy, &TInfo);
return SemaConvertVectorExpr(E, TInfo, BuiltinLoc, RParenLoc);
}
/// BuildResolvedCallExpr - Build a call to a resolved expression,
/// i.e. an expression not of \p OverloadTy. The expression should
/// unary-convert to an expression of function-pointer or
/// block-pointer type.
///
/// \param NDecl the declaration being called, if available
ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
SourceLocation LParenLoc,
ArrayRef<Expr *> Args,
SourceLocation RParenLoc, Expr *Config,
bool IsExecConfig, ADLCallKind UsesADL) {
FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl);
unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0);
// Functions with 'interrupt' attribute cannot be called directly.
if (FDecl && FDecl->hasAttr<AnyX86InterruptAttr>()) {
Diag(Fn->getExprLoc(), diag::err_anyx86_interrupt_called);
return ExprError();
}
// Interrupt handlers don't save off the VFP regs automatically on ARM,
// so there's some risk when calling out to non-interrupt handler functions
// that the callee might not preserve them. This is easy to diagnose here,
// but can be very challenging to debug.
if (auto *Caller = getCurFunctionDecl())
if (Caller->hasAttr<ARMInterruptAttr>()) {
bool VFP = Context.getTargetInfo().hasFeature("vfp");
if (VFP && (!FDecl || !FDecl->hasAttr<ARMInterruptAttr>()))
Diag(Fn->getExprLoc(), diag::warn_arm_interrupt_calling_convention);
}
// Promote the function operand.
// We special-case function promotion here because we only allow promoting
// builtin functions to function pointers in the callee of a call.
ExprResult Result;
QualType ResultTy;
if (BuiltinID &&
Fn->getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn)) {
// Extract the return type from the (builtin) function pointer type.
// FIXME Several builtins still have setType in
// Sema::CheckBuiltinFunctionCall. One should review their definitions in
// Builtins.def to ensure they are correct before removing setType calls.
QualType FnPtrTy = Context.getPointerType(FDecl->getType());
Result = ImpCastExprToType(Fn, FnPtrTy, CK_BuiltinFnToFnPtr).get();
ResultTy = FDecl->getCallResultType();
} else {
Result = CallExprUnaryConversions(Fn);
ResultTy = Context.BoolTy;
}
if (Result.isInvalid())
return ExprError();
Fn = Result.get();
// Check for a valid function type, but only if it is not a builtin which
// requires custom type checking. These will be handled by
// CheckBuiltinFunctionCall below just after creation of the call expression.
const FunctionType *FuncT = nullptr;
if (!BuiltinID || !Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) {
retry:
if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) {
// C99 6.5.2.2p1 - "The expression that denotes the called function shall
// have type pointer to function".
FuncT = PT->getPointeeType()->getAs<FunctionType>();
if (!FuncT)
return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
<< Fn->getType() << Fn->getSourceRange());
} else if (const BlockPointerType *BPT =
Fn->getType()->getAs<BlockPointerType>()) {
FuncT = BPT->getPointeeType()->castAs<FunctionType>();
} else {
// Handle calls to expressions of unknown-any type.
if (Fn->getType() == Context.UnknownAnyTy) {
ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn);
if (rewrite.isInvalid()) return ExprError();
Fn = rewrite.get();
goto retry;
}
return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function)
<< Fn->getType() << Fn->getSourceRange());
}
}
// Get the number of parameters in the function prototype, if any.
// We will allocate space for max(Args.size(), NumParams) arguments
// in the call expression.
const auto *Proto = dyn_cast_or_null<FunctionProtoType>(FuncT);
unsigned NumParams = Proto ? Proto->getNumParams() : 0;
CallExpr *TheCall;
if (Config) {
assert(UsesADL == ADLCallKind::NotADL &&
"CUDAKernelCallExpr should not use ADL");
TheCall =
CUDAKernelCallExpr::Create(Context, Fn, cast<CallExpr>(Config), Args,
ResultTy, VK_RValue, RParenLoc, NumParams);
} else {
TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue,
RParenLoc, NumParams, UsesADL);
}
if (!getLangOpts().CPlusPlus) {
// C cannot always handle TypoExpr nodes in builtin calls and direct
// function calls as their argument checking don't necessarily handle
// dependent types properly, so make sure any TypoExprs have been
// dealt with.
ExprResult Result = CorrectDelayedTyposInExpr(TheCall);
if (!Result.isUsable()) return ExprError();
TheCall = dyn_cast<CallExpr>(Result.get());
if (!TheCall) return Result;
// TheCall at this point has max(Args.size(), NumParams) arguments,
// with extra arguments nulled. We don't want to introduce nulled
// arguments in Args and so we only take the first Args.size() arguments.
Args = llvm::makeArrayRef(TheCall->getArgs(), Args.size());
}
// Bail out early if calling a builtin with custom type checking.
if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID))
return CheckBuiltinFunctionCall(FDecl, BuiltinID, TheCall);
if (getLangOpts().CUDA) {
if (Config) {
// CUDA: Kernel calls must be to global functions
if (FDecl && !FDecl->hasAttr<CUDAGlobalAttr>())
return ExprError(Diag(LParenLoc,diag::err_kern_call_not_global_function)
<< FDecl << Fn->getSourceRange());
// CUDA: Kernel function must have 'void' return type
if (!FuncT->getReturnType()->isVoidType())
return ExprError(Diag(LParenLoc, diag::err_kern_type_not_void_return)
<< Fn->getType() << Fn->getSourceRange());
} else {
// CUDA: Calls to global functions must be configured
if (FDecl && FDecl->hasAttr<CUDAGlobalAttr>())
return ExprError(Diag(LParenLoc, diag::err_global_call_not_config)
<< FDecl << Fn->getSourceRange());
}
}
// Check for a valid return type
if (CheckCallReturnType(FuncT->getReturnType(), Fn->getBeginLoc(), TheCall,
FDecl))
return ExprError();
// We know the result type of the call, set it.
TheCall->setType(FuncT->getCallResultType(Context));
TheCall->setValueKind(Expr::getValueKindForType(FuncT->getReturnType()));
if (Proto) {
if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, RParenLoc,
IsExecConfig))
return ExprError();
} else {
assert(isa<FunctionNoProtoType>(FuncT) && "Unknown FunctionType!");
if (FDecl) {
// Check if we have too few/too many template arguments, based
// on our knowledge of the function definition.
const FunctionDecl *Def = nullptr;
if (FDecl->hasBody(Def) && Args.size() != Def->param_size()) {
Proto = Def->getType()->getAs<FunctionProtoType>();
if (!Proto || !(Proto->isVariadic() && Args.size() >= Def->param_size()))
Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments)
<< (Args.size() > Def->param_size()) << FDecl << Fn->getSourceRange();
}
// If the function we're calling isn't a function prototype, but we have
// a function prototype from a prior declaratiom, use that prototype.
if (!FDecl->hasPrototype())
Proto = FDecl->getType()->getAs<FunctionProtoType>();
}
// Promote the arguments (C99 6.5.2.2p6).
for (unsigned i = 0, e = Args.size(); i != e; i++) {
Expr *Arg = Args[i];
if (Proto && i < Proto->getNumParams()) {
InitializedEntity Entity = InitializedEntity::InitializeParameter(
Context, Proto->getParamType(i), Proto->isParamConsumed(i));
ExprResult ArgE =
PerformCopyInitialization(Entity, SourceLocation(), Arg);
if (ArgE.isInvalid())
return true;
Arg = ArgE.getAs<Expr>();
} else {
ExprResult ArgE = DefaultArgumentPromotion(Arg);
if (ArgE.isInvalid())
return true;
Arg = ArgE.getAs<Expr>();
}
if (RequireCompleteType(Arg->getBeginLoc(), Arg->getType(),
diag::err_call_incomplete_argument, Arg))
return ExprError();
TheCall->setArg(i, Arg);
}
}
if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl))
if (!Method->isStatic())
return ExprError(Diag(LParenLoc, diag::err_member_call_without_object)
<< Fn->getSourceRange());
// Check for sentinels
if (NDecl)
DiagnoseSentinelCalls(NDecl, LParenLoc, Args);
// Do special checking on direct calls to functions.
if (FDecl) {
if (CheckFunctionCall(FDecl, TheCall, Proto))
return ExprError();
if (BuiltinID)
return CheckBuiltinFunctionCall(FDecl, BuiltinID, TheCall);
} else if (NDecl) {
if (CheckPointerCall(NDecl, TheCall, Proto))
return ExprError();
} else {
if (CheckOtherCall(TheCall, Proto))
return ExprError();
}
return MaybeBindToTemporary(TheCall);
}
ExprResult
Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
SourceLocation RParenLoc, Expr *InitExpr) {
assert(Ty && "ActOnCompoundLiteral(): missing type");
assert(InitExpr && "ActOnCompoundLiteral(): missing expression");
TypeSourceInfo *TInfo;
QualType literalType = GetTypeFromParser(Ty, &TInfo);
if (!TInfo)
TInfo = Context.getTrivialTypeSourceInfo(literalType);
return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, InitExpr);
}
ExprResult
Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
SourceLocation RParenLoc, Expr *LiteralExpr) {
QualType literalType = TInfo->getType();
if (literalType->isArrayType()) {
if (RequireCompleteType(LParenLoc, Context.getBaseElementType(literalType),
diag::err_illegal_decl_array_incomplete_type,
SourceRange(LParenLoc,
LiteralExpr->getSourceRange().getEnd())))
return ExprError();
if (literalType->isVariableArrayType())
return ExprError(Diag(LParenLoc, diag::err_variable_object_no_init)
<< SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd()));
} else if (!literalType->isDependentType() &&
RequireCompleteType(LParenLoc, literalType,
diag::err_typecheck_decl_incomplete_type,
SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd())))
return ExprError();
InitializedEntity Entity
= InitializedEntity::InitializeCompoundLiteralInit(TInfo);
InitializationKind Kind
= InitializationKind::CreateCStyleCast(LParenLoc,
SourceRange(LParenLoc, RParenLoc),
/*InitList=*/true);
InitializationSequence InitSeq(*this, Entity, Kind, LiteralExpr);
ExprResult Result = InitSeq.Perform(*this, Entity, Kind, LiteralExpr,
&literalType);
if (Result.isInvalid())
return ExprError();
LiteralExpr = Result.get();
bool isFileScope = !CurContext->isFunctionOrMethod();
// In C, compound literals are l-values for some reason.
// For GCC compatibility, in C++, file-scope array compound literals with
// constant initializers are also l-values, and compound literals are
// otherwise prvalues.
//
// (GCC also treats C++ list-initialized file-scope array prvalues with
// constant initializers as l-values, but that's non-conforming, so we don't
// follow it there.)
//
// FIXME: It would be better to handle the lvalue cases as materializing and
// lifetime-extending a temporary object, but our materialized temporaries
// representation only supports lifetime extension from a variable, not "out
// of thin air".
// FIXME: For C++, we might want to instead lifetime-extend only if a pointer
// is bound to the result of applying array-to-pointer decay to the compound
// literal.
// FIXME: GCC supports compound literals of reference type, which should
// obviously have a value kind derived from the kind of reference involved.
ExprValueKind VK =
(getLangOpts().CPlusPlus && !(isFileScope && literalType->isArrayType()))
? VK_RValue
: VK_LValue;
if (isFileScope)
if (auto ILE = dyn_cast<InitListExpr>(LiteralExpr))
for (unsigned i = 0, j = ILE->getNumInits(); i != j; i++) {
Expr *Init = ILE->getInit(i);
ILE->setInit(i, ConstantExpr::Create(Context, Init));
}
Expr *E = new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
VK, LiteralExpr, isFileScope);
if (isFileScope) {
if (!LiteralExpr->isTypeDependent() &&
!LiteralExpr->isValueDependent() &&
!literalType->isDependentType()) // C99 6.5.2.5p3
if (CheckForConstantInitializer(LiteralExpr, literalType))
return ExprError();
} else if (literalType.getAddressSpace() != LangAS::opencl_private &&
literalType.getAddressSpace() != LangAS::Default) {
// Embedded-C extensions to C99 6.5.2.5:
// "If the compound literal occurs inside the body of a function, the
// type name shall not be qualified by an address-space qualifier."
Diag(LParenLoc, diag::err_compound_literal_with_address_space)
<< SourceRange(LParenLoc, LiteralExpr->getSourceRange().getEnd());
return ExprError();
}
return MaybeBindToTemporary(E);
}
ExprResult
Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
SourceLocation RBraceLoc) {
// Immediately handle non-overload placeholders. Overloads can be
// resolved contextually, but everything else here can't.
for (unsigned I = 0, E = InitArgList.size(); I != E; ++I) {
if (InitArgList[I]->getType()->isNonOverloadPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(InitArgList[I]);
// Ignore failures; dropping the entire initializer list because
// of one failure would be terrible for indexing/etc.
if (result.isInvalid()) continue;
InitArgList[I] = result.get();
}
}
// Semantic analysis for initializers is done by ActOnDeclarator() and
// CheckInitializer() - it requires knowledge of the object being initialized.
InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitArgList,
RBraceLoc);
E->setType(Context.VoidTy); // FIXME: just a place holder for now.
return E;
}
/// Do an explicit extend of the given block pointer if we're in ARC.
void Sema::maybeExtendBlockObject(ExprResult &E) {
assert(E.get()->getType()->isBlockPointerType());
assert(E.get()->isRValue());
// Only do this in an r-value context.
if (!getLangOpts().ObjCAutoRefCount) return;
E = ImplicitCastExpr::Create(Context, E.get()->getType(),
CK_ARCExtendBlockObject, E.get(),
/*base path*/ nullptr, VK_RValue);
Cleanup.setExprNeedsCleanups(true);
}
/// Prepare a conversion of the given expression to an ObjC object
/// pointer type.
CastKind Sema::PrepareCastToObjCObjectPointer(ExprResult &E) {
QualType type = E.get()->getType();
if (type->isObjCObjectPointerType()) {
return CK_BitCast;
} else if (type->isBlockPointerType()) {
maybeExtendBlockObject(E);
return CK_BlockPointerToObjCPointerCast;
} else {
assert(type->isPointerType());
return CK_CPointerToObjCPointerCast;
}
}
/// Prepares for a scalar cast, performing all the necessary stages
/// except the final cast and returning the kind required.
CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) {
// Both Src and Dest are scalar types, i.e. arithmetic or pointer.
// Also, callers should have filtered out the invalid cases with
// pointers. Everything else should be possible.
QualType SrcTy = Src.get()->getType();
if (Context.hasSameUnqualifiedType(SrcTy, DestTy))
return CK_NoOp;
switch (Type::ScalarTypeKind SrcKind = SrcTy->getScalarTypeKind()) {
case Type::STK_MemberPointer:
llvm_unreachable("member pointer type in C");
case Type::STK_CPointer:
case Type::STK_BlockPointer:
case Type::STK_ObjCObjectPointer:
switch (DestTy->getScalarTypeKind()) {
case Type::STK_CPointer: {
LangAS SrcAS = SrcTy->getPointeeType().getAddressSpace();
LangAS DestAS = DestTy->getPointeeType().getAddressSpace();
if (SrcAS != DestAS)
return CK_AddressSpaceConversion;
if (Context.hasCvrSimilarType(SrcTy, DestTy))
return CK_NoOp;
return CK_BitCast;
}
case Type::STK_BlockPointer:
return (SrcKind == Type::STK_BlockPointer
? CK_BitCast : CK_AnyPointerToBlockPointerCast);
case Type::STK_ObjCObjectPointer:
if (SrcKind == Type::STK_ObjCObjectPointer)
return CK_BitCast;
if (SrcKind == Type::STK_CPointer)
return CK_CPointerToObjCPointerCast;
maybeExtendBlockObject(Src);
return CK_BlockPointerToObjCPointerCast;
case Type::STK_Bool:
return CK_PointerToBoolean;
case Type::STK_Integral:
return CK_PointerToIntegral;
case Type::STK_Floating:
case Type::STK_FloatingComplex:
case Type::STK_IntegralComplex:
case Type::STK_MemberPointer:
case Type::STK_FixedPoint:
llvm_unreachable("illegal cast from pointer");
}
llvm_unreachable("Should have returned before this");
case Type::STK_FixedPoint:
switch (DestTy->getScalarTypeKind()) {
case Type::STK_FixedPoint:
return CK_FixedPointCast;
case Type::STK_Bool:
return CK_FixedPointToBoolean;
case Type::STK_Integral:
case Type::STK_Floating:
case Type::STK_IntegralComplex:
case Type::STK_FloatingComplex:
Diag(Src.get()->getExprLoc(),
diag::err_unimplemented_conversion_with_fixed_point_type)
<< DestTy;
return CK_IntegralCast;
case Type::STK_CPointer:
case Type::STK_ObjCObjectPointer:
case Type::STK_BlockPointer:
case Type::STK_MemberPointer:
llvm_unreachable("illegal cast to pointer type");
}
llvm_unreachable("Should have returned before this");
case Type::STK_Bool: // casting from bool is like casting from an integer
case Type::STK_Integral:
switch (DestTy->getScalarTypeKind()) {
case Type::STK_CPointer:
case Type::STK_ObjCObjectPointer:
case Type::STK_BlockPointer:
if (Src.get()->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull))
return CK_NullToPointer;
return CK_IntegralToPointer;
case Type::STK_Bool:
return CK_IntegralToBoolean;
case Type::STK_Integral:
return CK_IntegralCast;
case Type::STK_Floating:
return CK_IntegralToFloating;
case Type::STK_IntegralComplex:
Src = ImpCastExprToType(Src.get(),
DestTy->castAs<ComplexType>()->getElementType(),
CK_IntegralCast);
return CK_IntegralRealToComplex;
case Type::STK_FloatingComplex:
Src = ImpCastExprToType(Src.get(),
DestTy->castAs<ComplexType>()->getElementType(),
CK_IntegralToFloating);
return CK_FloatingRealToComplex;
case Type::STK_MemberPointer:
llvm_unreachable("member pointer type in C");
case Type::STK_FixedPoint:
Diag(Src.get()->getExprLoc(),
diag::err_unimplemented_conversion_with_fixed_point_type)
<< SrcTy;
return CK_IntegralCast;
}
llvm_unreachable("Should have returned before this");
case Type::STK_Floating:
switch (DestTy->getScalarTypeKind()) {
case Type::STK_Floating:
return CK_FloatingCast;
case Type::STK_Bool:
return CK_FloatingToBoolean;
case Type::STK_Integral:
return CK_FloatingToIntegral;
case Type::STK_FloatingComplex:
Src = ImpCastExprToType(Src.get(),
DestTy->castAs<ComplexType>()->getElementType(),
CK_FloatingCast);
return CK_FloatingRealToComplex;
case Type::STK_IntegralComplex:
Src = ImpCastExprToType(Src.get(),
DestTy->castAs<ComplexType>()->getElementType(),
CK_FloatingToIntegral);
return CK_IntegralRealToComplex;
case Type::STK_CPointer:
case Type::STK_ObjCObjectPointer:
case Type::STK_BlockPointer:
llvm_unreachable("valid float->pointer cast?");
case Type::STK_MemberPointer:
llvm_unreachable("member pointer type in C");
case Type::STK_FixedPoint:
Diag(Src.get()->getExprLoc(),
diag::err_unimplemented_conversion_with_fixed_point_type)
<< SrcTy;
return CK_IntegralCast;
}
llvm_unreachable("Should have returned before this");
case Type::STK_FloatingComplex:
switch (DestTy->getScalarTypeKind()) {
case Type::STK_FloatingComplex:
return CK_FloatingComplexCast;
case Type::STK_IntegralComplex:
return CK_FloatingComplexToIntegralComplex;
case Type::STK_Floating: {
QualType ET = SrcTy->castAs<ComplexType>()->getElementType();
if (Context.hasSameType(ET, DestTy))
return CK_FloatingComplexToReal;
Src = ImpCastExprToType(Src.get(), ET, CK_FloatingComplexToReal);
return CK_FloatingCast;
}
case Type::STK_Bool:
return CK_FloatingComplexToBoolean;
case Type::STK_Integral:
Src = ImpCastExprToType(Src.get(),
SrcTy->castAs<ComplexType>()->getElementType(),
CK_FloatingComplexToReal);
return CK_FloatingToIntegral;
case Type::STK_CPointer:
case Type::STK_ObjCObjectPointer:
case Type::STK_BlockPointer:
llvm_unreachable("valid complex float->pointer cast?");
case Type::STK_MemberPointer:
llvm_unreachable("member pointer type in C");
case Type::STK_FixedPoint:
Diag(Src.get()->getExprLoc(),
diag::err_unimplemented_conversion_with_fixed_point_type)
<< SrcTy;
return CK_IntegralCast;
}
llvm_unreachable("Should have returned before this");
case Type::STK_IntegralComplex:
switch (DestTy->getScalarTypeKind()) {
case Type::STK_FloatingComplex:
return CK_IntegralComplexToFloatingComplex;
case Type::STK_IntegralComplex:
return CK_IntegralComplexCast;
case Type::STK_Integral: {
QualType ET = SrcTy->castAs<ComplexType>()->getElementType();
if (Context.hasSameType(ET, DestTy))
return CK_IntegralComplexToReal;
Src = ImpCastExprToType(Src.get(), ET, CK_IntegralComplexToReal);
return CK_IntegralCast;
}
case Type::STK_Bool:
return CK_IntegralComplexToBoolean;
case Type::STK_Floating:
Src = ImpCastExprToType(Src.get(),
SrcTy->castAs<ComplexType>()->getElementType(),
CK_IntegralComplexToReal);
return CK_IntegralToFloating;
case Type::STK_CPointer:
case Type::STK_ObjCObjectPointer:
case Type::STK_BlockPointer:
llvm_unreachable("valid complex int->pointer cast?");
case Type::STK_MemberPointer:
llvm_unreachable("member pointer type in C");
case Type::STK_FixedPoint:
Diag(Src.get()->getExprLoc(),
diag::err_unimplemented_conversion_with_fixed_point_type)
<< SrcTy;
return CK_IntegralCast;
}
llvm_unreachable("Should have returned before this");
}
llvm_unreachable("Unhandled scalar cast");
}
static bool breakDownVectorType(QualType type, uint64_t &len,
QualType &eltType) {
// Vectors are simple.
if (const VectorType *vecType = type->getAs<VectorType>()) {
len = vecType->getNumElements();
eltType = vecType->getElementType();
assert(eltType->isScalarType());
return true;
}
// We allow lax conversion to and from non-vector types, but only if
// they're real types (i.e. non-complex, non-pointer scalar types).
if (!type->isRealType()) return false;
len = 1;
eltType = type;
return true;
}
/// Are the two types lax-compatible vector types? That is, given
/// that one of them is a vector, do they have equal storage sizes,
/// where the storage size is the number of elements times the element
/// size?
///
/// This will also return false if either of the types is neither a
/// vector nor a real type.
bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) {
assert(destTy->isVectorType() || srcTy->isVectorType());
// Disallow lax conversions between scalars and ExtVectors (these
// conversions are allowed for other vector types because common headers
// depend on them). Most scalar OP ExtVector cases are handled by the
// splat path anyway, which does what we want (convert, not bitcast).
// What this rules out for ExtVectors is crazy things like char4*float.
if (srcTy->isScalarType() && destTy->isExtVectorType()) return false;
if (destTy->isScalarType() && srcTy->isExtVectorType()) return false;
uint64_t srcLen, destLen;
QualType srcEltTy, destEltTy;
if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false;
if (!breakDownVectorType(destTy, destLen, destEltTy)) return false;
// ASTContext::getTypeSize will return the size rounded up to a
// power of 2, so instead of using that, we need to use the raw
// element size multiplied by the element count.
uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
uint64_t destEltSize = Context.getTypeSize(destEltTy);
return (srcLen * srcEltSize == destLen * destEltSize);
}
/// Is this a legal conversion between two types, one of which is
/// known to be a vector type?
bool Sema::isLaxVectorConversion(QualType srcTy, QualType destTy) {
assert(destTy->isVectorType() || srcTy->isVectorType());
if (!Context.getLangOpts().LaxVectorConversions)
return false;
return areLaxCompatibleVectorTypes(srcTy, destTy);
}
bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
CastKind &Kind) {
assert(VectorTy->isVectorType() && "Not a vector type!");
if (Ty->isVectorType() || Ty->isIntegralType(Context)) {
if (!areLaxCompatibleVectorTypes(Ty, VectorTy))
return Diag(R.getBegin(),
Ty->isVectorType() ?
diag::err_invalid_conversion_between_vectors :
diag::err_invalid_conversion_between_vector_and_integer)
<< VectorTy << Ty << R;
} else
return Diag(R.getBegin(),
diag::err_invalid_conversion_between_vector_and_scalar)
<< VectorTy << Ty << R;
Kind = CK_BitCast;
return false;
}
ExprResult Sema::prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr) {
QualType DestElemTy = VectorTy->castAs<VectorType>()->getElementType();
if (DestElemTy == SplattedExpr->getType())
return SplattedExpr;
assert(DestElemTy->isFloatingType() ||
DestElemTy->isIntegralOrEnumerationType());
CastKind CK;
if (VectorTy->isExtVectorType() && SplattedExpr->getType()->isBooleanType()) {
// OpenCL requires that we convert `true` boolean expressions to -1, but
// only when splatting vectors.
if (DestElemTy->isFloatingType()) {
// To avoid having to have a CK_BooleanToSignedFloating cast kind, we cast
// in two steps: boolean to signed integral, then to floating.
ExprResult CastExprRes = ImpCastExprToType(SplattedExpr, Context.IntTy,
CK_BooleanToSignedIntegral);
SplattedExpr = CastExprRes.get();
CK = CK_IntegralToFloating;
} else {
CK = CK_BooleanToSignedIntegral;
}
} else {
ExprResult CastExprRes = SplattedExpr;
CK = PrepareScalarCast(CastExprRes, DestElemTy);
if (CastExprRes.isInvalid())
return ExprError();
SplattedExpr = CastExprRes.get();
}
return ImpCastExprToType(SplattedExpr, DestElemTy, CK);
}
ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy,
Expr *CastExpr, CastKind &Kind) {
assert(DestTy->isExtVectorType() && "Not an extended vector type!");
QualType SrcTy = CastExpr->getType();
// If SrcTy is a VectorType, the total size must match to explicitly cast to
// an ExtVectorType.
// In OpenCL, casts between vectors of different types are not allowed.
// (See OpenCL 6.2).
if (SrcTy->isVectorType()) {
if (!areLaxCompatibleVectorTypes(SrcTy, DestTy) ||
(getLangOpts().OpenCL &&
!Context.hasSameUnqualifiedType(DestTy, SrcTy))) {
Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
<< DestTy << SrcTy << R;
return ExprError();
}
Kind = CK_BitCast;
return CastExpr;
}
// All non-pointer scalars can be cast to ExtVector type. The appropriate
// conversion will take place first from scalar to elt type, and then
// splat from elt type to vector.
if (SrcTy->isPointerType())
return Diag(R.getBegin(),
diag::err_invalid_conversion_between_vector_and_scalar)
<< DestTy << SrcTy << R;
Kind = CK_VectorSplat;
return prepareVectorSplat(DestTy, CastExpr);
}
ExprResult
Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
Declarator &D, ParsedType &Ty,
SourceLocation RParenLoc, Expr *CastExpr) {
assert(!D.isInvalidType() && (CastExpr != nullptr) &&
"ActOnCastExpr(): missing type or expr");
TypeSourceInfo *castTInfo = GetTypeForDeclaratorCast(D, CastExpr->getType());
if (D.isInvalidType())
return ExprError();
if (getLangOpts().CPlusPlus) {
// Check that there are no default arguments (C++ only).
CheckExtraCXXDefaultArguments(D);
} else {
// Make sure any TypoExprs have been dealt with.
ExprResult Res = CorrectDelayedTyposInExpr(CastExpr);
if (!Res.isUsable())
return ExprError();
CastExpr = Res.get();
}
checkUnusedDeclAttributes(D);
QualType castType = castTInfo->getType();
Ty = CreateParsedType(castType, castTInfo);
bool isVectorLiteral = false;
// Check for an altivec or OpenCL literal,
// i.e. all the elements are integer constants.
ParenExpr *PE = dyn_cast<ParenExpr>(CastExpr);
ParenListExpr *PLE = dyn_cast<ParenListExpr>(CastExpr);
if ((getLangOpts().AltiVec || getLangOpts().ZVector || getLangOpts().OpenCL)
&& castType->isVectorType() && (PE || PLE)) {
if (PLE && PLE->getNumExprs() == 0) {
Diag(PLE->getExprLoc(), diag::err_altivec_empty_initializer);
return ExprError();
}
if (PE || PLE->getNumExprs() == 1) {
Expr *E = (PE ? PE->getSubExpr() : PLE->getExpr(0));
if (!E->getType()->isVectorType())
isVectorLiteral = true;
}
else
isVectorLiteral = true;
}
// If this is a vector initializer, '(' type ')' '(' init, ..., init ')'
// then handle it as such.
if (isVectorLiteral)
return BuildVectorLiteral(LParenLoc, RParenLoc, CastExpr, castTInfo);
// If the Expr being casted is a ParenListExpr, handle it specially.
// This is not an AltiVec-style cast, so turn the ParenListExpr into a
// sequence of BinOp comma operators.
if (isa<ParenListExpr>(CastExpr)) {
ExprResult Result = MaybeConvertParenListExprToParenExpr(S, CastExpr);
if (Result.isInvalid()) return ExprError();
CastExpr = Result.get();
}
if (getLangOpts().CPlusPlus && !castType->isVoidType() &&
!getSourceManager().isInSystemMacro(LParenLoc))
Diag(LParenLoc, diag::warn_old_style_cast) << CastExpr->getSourceRange();
CheckTollFreeBridgeCast(castType, CastExpr);
CheckObjCBridgeRelatedCast(castType, CastExpr);
DiscardMisalignedMemberAddress(castType.getTypePtr(), CastExpr);
return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, CastExpr);
}
ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc,
SourceLocation RParenLoc, Expr *E,
TypeSourceInfo *TInfo) {
assert((isa<ParenListExpr>(E) || isa<ParenExpr>(E)) &&
"Expected paren or paren list expression");
Expr **exprs;
unsigned numExprs;
Expr *subExpr;
SourceLocation LiteralLParenLoc, LiteralRParenLoc;
if (ParenListExpr *PE = dyn_cast<ParenListExpr>(E)) {
LiteralLParenLoc = PE->getLParenLoc();
LiteralRParenLoc = PE->getRParenLoc();
exprs = PE->getExprs();
numExprs = PE->getNumExprs();
} else { // isa<ParenExpr> by assertion at function entrance
LiteralLParenLoc = cast<ParenExpr>(E)->getLParen();
LiteralRParenLoc = cast<ParenExpr>(E)->getRParen();
subExpr = cast<ParenExpr>(E)->getSubExpr();
exprs = &subExpr;
numExprs = 1;
}
QualType Ty = TInfo->getType();
assert(Ty->isVectorType() && "Expected vector type");
SmallVector<Expr *, 8> initExprs;
const VectorType *VTy = Ty->getAs<VectorType>();
unsigned numElems = Ty->getAs<VectorType>()->getNumElements();
// '(...)' form of vector initialization in AltiVec: the number of
// initializers must be one or must match the size of the vector.
// If a single value is specified in the initializer then it will be
// replicated to all the components of the vector
if (VTy->getVectorKind() == VectorType::AltiVecVector) {
// The number of initializers must be one or must match the size of the
// vector. If a single value is specified in the initializer then it will
// be replicated to all the components of the vector
if (numExprs == 1) {
QualType ElemTy = Ty->getAs<VectorType>()->getElementType();
ExprResult Literal = DefaultLvalueConversion(exprs[0]);
if (Literal.isInvalid())
return ExprError();
Literal = ImpCastExprToType(Literal.get(), ElemTy,
PrepareScalarCast(Literal, ElemTy));
return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.get());
}
else if (numExprs < numElems) {
Diag(E->getExprLoc(),
diag::err_incorrect_number_of_vector_initializers);
return ExprError();
}
else
initExprs.append(exprs, exprs + numExprs);
}
else {
// For OpenCL, when the number of initializers is a single value,
// it will be replicated to all components of the vector.
if (getLangOpts().OpenCL &&
VTy->getVectorKind() == VectorType::GenericVector &&
numExprs == 1) {
QualType ElemTy = Ty->getAs<VectorType>()->getElementType();
ExprResult Literal = DefaultLvalueConversion(exprs[0]);
if (Literal.isInvalid())
return ExprError();
Literal = ImpCastExprToType(Literal.get(), ElemTy,
PrepareScalarCast(Literal, ElemTy));
return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.get());
}
initExprs.append(exprs, exprs + numExprs);
}
// FIXME: This means that pretty-printing the final AST will produce curly
// braces instead of the original commas.
InitListExpr *initE = new (Context) InitListExpr(Context, LiteralLParenLoc,
initExprs, LiteralRParenLoc);
initE->setType(Ty);
return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, initE);
}
/// This is not an AltiVec-style cast or or C++ direct-initialization, so turn
/// the ParenListExpr into a sequence of comma binary operators.
ExprResult
Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) {
ParenListExpr *E = dyn_cast<ParenListExpr>(OrigExpr);
if (!E)
return OrigExpr;
ExprResult Result(E->getExpr(0));
for (unsigned i = 1, e = E->getNumExprs(); i != e && !Result.isInvalid(); ++i)
Result = ActOnBinOp(S, E->getExprLoc(), tok::comma, Result.get(),
E->getExpr(i));
if (Result.isInvalid()) return ExprError();
return ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), Result.get());
}
ExprResult Sema::ActOnParenListExpr(SourceLocation L,
SourceLocation R,
MultiExprArg Val) {
return ParenListExpr::Create(Context, L, Val, R);
}
/// Emit a specialized diagnostic when one expression is a null pointer
/// constant and the other is not a pointer. Returns true if a diagnostic is
/// emitted.
bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr,
SourceLocation QuestionLoc) {
Expr *NullExpr = LHSExpr;
Expr *NonPointerExpr = RHSExpr;
Expr::NullPointerConstantKind NullKind =
NullExpr->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNotNull);
if (NullKind == Expr::NPCK_NotNull) {
NullExpr = RHSExpr;
NonPointerExpr = LHSExpr;
NullKind =
NullExpr->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNotNull);
}
if (NullKind == Expr::NPCK_NotNull)
return false;
if (NullKind == Expr::NPCK_ZeroExpression)
return false;
if (NullKind == Expr::NPCK_ZeroLiteral) {
// In this case, check to make sure that we got here from a "NULL"
// string in the source code.
NullExpr = NullExpr->IgnoreParenImpCasts();
SourceLocation loc = NullExpr->getExprLoc();
if (!findMacroSpelling(loc, "NULL"))
return false;
}
int DiagType = (NullKind == Expr::NPCK_CXX11_nullptr);
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands_null)
<< NonPointerExpr->getType() << DiagType
<< NonPointerExpr->getSourceRange();
return true;
}
/// Return false if the condition expression is valid, true otherwise.
static bool checkCondition(Sema &S, Expr *Cond, SourceLocation QuestionLoc) {
QualType CondTy = Cond->getType();
// OpenCL v1.1 s6.3.i says the condition cannot be a floating point type.
if (S.getLangOpts().OpenCL && CondTy->isFloatingType()) {
S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_nonfloat)
<< CondTy << Cond->getSourceRange();
return true;
}
// C99 6.5.15p2
if (CondTy->isScalarType()) return false;
S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_scalar)
<< CondTy << Cond->getSourceRange();
return true;
}
/// Handle when one or both operands are void type.
static QualType checkConditionalVoidType(Sema &S, ExprResult &LHS,
ExprResult &RHS) {
Expr *LHSExpr = LHS.get();
Expr *RHSExpr = RHS.get();
if (!LHSExpr->getType()->isVoidType())
S.Diag(RHSExpr->getBeginLoc(), diag::ext_typecheck_cond_one_void)
<< RHSExpr->getSourceRange();
if (!RHSExpr->getType()->isVoidType())
S.Diag(LHSExpr->getBeginLoc(), diag::ext_typecheck_cond_one_void)
<< LHSExpr->getSourceRange();
LHS = S.ImpCastExprToType(LHS.get(), S.Context.VoidTy, CK_ToVoid);
RHS = S.ImpCastExprToType(RHS.get(), S.Context.VoidTy, CK_ToVoid);
return S.Context.VoidTy;
}
/// Return false if the NullExpr can be promoted to PointerTy,
/// true otherwise.
static bool checkConditionalNullPointer(Sema &S, ExprResult &NullExpr,
QualType PointerTy) {
if ((!PointerTy->isAnyPointerType() && !PointerTy->isBlockPointerType()) ||
!NullExpr.get()->isNullPointerConstant(S.Context,
Expr::NPC_ValueDependentIsNull))
return true;
NullExpr = S.ImpCastExprToType(NullExpr.get(), PointerTy, CK_NullToPointer);
return false;
}
/// Checks compatibility between two pointers and return the resulting
/// type.
static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
ExprResult &RHS,
SourceLocation Loc) {
QualType LHSTy = LHS.get()->getType();
QualType RHSTy = RHS.get()->getType();
if (S.Context.hasSameType(LHSTy, RHSTy)) {
// Two identical pointers types are always compatible.
return LHSTy;
}
QualType lhptee, rhptee;
// Get the pointee types.
bool IsBlockPointer = false;
if (const BlockPointerType *LHSBTy = LHSTy->getAs<BlockPointerType>()) {
lhptee = LHSBTy->getPointeeType();
rhptee = RHSTy->castAs<BlockPointerType>()->getPointeeType();
IsBlockPointer = true;
} else {
lhptee = LHSTy->castAs<PointerType>()->getPointeeType();
rhptee = RHSTy->castAs<PointerType>()->getPointeeType();
}
// C99 6.5.15p6: If both operands are pointers to compatible types or to
// differently qualified versions of compatible types, the result type is
// a pointer to an appropriately qualified version of the composite
// type.
// Only CVR-qualifiers exist in the standard, and the differently-qualified
// clause doesn't make sense for our extensions. E.g. address space 2 should
// be incompatible with address space 3: they may live on different devices or
// anything.
Qualifiers lhQual = lhptee.getQualifiers();
Qualifiers rhQual = rhptee.getQualifiers();
LangAS ResultAddrSpace = LangAS::Default;
LangAS LAddrSpace = lhQual.getAddressSpace();
LangAS RAddrSpace = rhQual.getAddressSpace();
// OpenCL v1.1 s6.5 - Conversion between pointers to distinct address
// spaces is disallowed.
if (lhQual.isAddressSpaceSupersetOf(rhQual))
ResultAddrSpace = LAddrSpace;
else if (rhQual.isAddressSpaceSupersetOf(lhQual))
ResultAddrSpace = RAddrSpace;
else {
S.Diag(Loc, diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
<< LHSTy << RHSTy << 2 << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
return QualType();
}
unsigned MergedCVRQual = lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers();
auto LHSCastKind = CK_BitCast, RHSCastKind = CK_BitCast;
lhQual.removeCVRQualifiers();
rhQual.removeCVRQualifiers();
// OpenCL v2.0 specification doesn't extend compatibility of type qualifiers
// (C99 6.7.3) for address spaces. We assume that the check should behave in
// the same manner as it's defined for CVR qualifiers, so for OpenCL two
// qual types are compatible iff
// * corresponded types are compatible
// * CVR qualifiers are equal
// * address spaces are equal
// Thus for conditional operator we merge CVR and address space unqualified
// pointees and if there is a composite type we return a pointer to it with
// merged qualifiers.
LHSCastKind =
LAddrSpace == ResultAddrSpace ? CK_BitCast : CK_AddressSpaceConversion;
RHSCastKind =
RAddrSpace == ResultAddrSpace ? CK_BitCast : CK_AddressSpaceConversion;
lhQual.removeAddressSpace();
rhQual.removeAddressSpace();
lhptee = S.Context.getQualifiedType(lhptee.getUnqualifiedType(), lhQual);
rhptee = S.Context.getQualifiedType(rhptee.getUnqualifiedType(), rhQual);
QualType CompositeTy = S.Context.mergeTypes(lhptee, rhptee);
if (CompositeTy.isNull()) {
// In this situation, we assume void* type. No especially good
// reason, but this is what gcc does, and we do have to pick
// to get a consistent AST.
QualType incompatTy;
incompatTy = S.Context.getPointerType(
S.Context.getAddrSpaceQualType(S.Context.VoidTy, ResultAddrSpace));
LHS = S.ImpCastExprToType(LHS.get(), incompatTy, LHSCastKind);
RHS = S.ImpCastExprToType(RHS.get(), incompatTy, RHSCastKind);
// FIXME: For OpenCL the warning emission and cast to void* leaves a room
// for casts between types with incompatible address space qualifiers.
// For the following code the compiler produces casts between global and
// local address spaces of the corresponded innermost pointees:
// local int *global *a;
// global int *global *b;
// a = (0 ? a : b); // see C99 6.5.16.1.p1.
S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers)
<< LHSTy << RHSTy << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
return incompatTy;
}
// The pointer types are compatible.
// In case of OpenCL ResultTy should have the address space qualifier
// which is a superset of address spaces of both the 2nd and the 3rd
// operands of the conditional operator.
QualType ResultTy = [&, ResultAddrSpace]() {
if (S.getLangOpts().OpenCL) {
Qualifiers CompositeQuals = CompositeTy.getQualifiers();
CompositeQuals.setAddressSpace(ResultAddrSpace);
return S.Context
.getQualifiedType(CompositeTy.getUnqualifiedType(), CompositeQuals)
.withCVRQualifiers(MergedCVRQual);
}
return CompositeTy.withCVRQualifiers(MergedCVRQual);
}();
if (IsBlockPointer)
ResultTy = S.Context.getBlockPointerType(ResultTy);
else
ResultTy = S.Context.getPointerType(ResultTy);
LHS = S.ImpCastExprToType(LHS.get(), ResultTy, LHSCastKind);
RHS = S.ImpCastExprToType(RHS.get(), ResultTy, RHSCastKind);
return ResultTy;
}
/// Return the resulting type when the operands are both block pointers.
static QualType checkConditionalBlockPointerCompatibility(Sema &S,
ExprResult &LHS,
ExprResult &RHS,
SourceLocation Loc) {
QualType LHSTy = LHS.get()->getType();
QualType RHSTy = RHS.get()->getType();
if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) {
if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) {
QualType destType = S.Context.getPointerType(S.Context.VoidTy);
LHS = S.ImpCastExprToType(LHS.get(), destType, CK_BitCast);
RHS = S.ImpCastExprToType(RHS.get(), destType, CK_BitCast);
return destType;
}
S.Diag(Loc, diag::err_typecheck_cond_incompatible_operands)
<< LHSTy << RHSTy << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
return QualType();
}
// We have 2 block pointer types.
return checkConditionalPointerCompatibility(S, LHS, RHS, Loc);
}
/// Return the resulting type when the operands are both pointers.
static QualType
checkConditionalObjectPointersCompatibility(Sema &S, ExprResult &LHS,
ExprResult &RHS,
SourceLocation Loc) {
// get the pointer types
QualType LHSTy = LHS.get()->getType();
QualType RHSTy = RHS.get()->getType();
// get the "pointed to" types
QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType();
QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType();
// ignore qualifiers on void (C99 6.5.15p3, clause 6)
if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) {
// Figure out necessary qualifiers (C99 6.5.15p6)
QualType destPointee
= S.Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = S.Context.getPointerType(destPointee);
// Add qualifiers if necessary.
LHS = S.ImpCastExprToType(LHS.get(), destType, CK_NoOp);
// Promote to void*.
RHS = S.ImpCastExprToType(RHS.get(), destType, CK_BitCast);
return destType;
}
if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {
QualType destPointee
= S.Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = S.Context.getPointerType(destPointee);
// Add qualifiers if necessary.
RHS = S.ImpCastExprToType(RHS.get(), destType, CK_NoOp);
// Promote to void*.
LHS = S.ImpCastExprToType(LHS.get(), destType, CK_BitCast);
return destType;
}
return checkConditionalPointerCompatibility(S, LHS, RHS, Loc);
}
/// Return false if the first expression is not an integer and the second
/// expression is not a pointer, true otherwise.
static bool checkPointerIntegerMismatch(Sema &S, ExprResult &Int,
Expr* PointerExpr, SourceLocation Loc,
bool IsIntFirstExpr) {
if (!PointerExpr->getType()->isPointerType() ||
!Int.get()->getType()->isIntegerType())
return false;
Expr *Expr1 = IsIntFirstExpr ? Int.get() : PointerExpr;
Expr *Expr2 = IsIntFirstExpr ? PointerExpr : Int.get();
S.Diag(Loc, diag::ext_typecheck_cond_pointer_integer_mismatch)
<< Expr1->getType() << Expr2->getType()
<< Expr1->getSourceRange() << Expr2->getSourceRange();
Int = S.ImpCastExprToType(Int.get(), PointerExpr->getType(),
CK_IntegralToPointer);
return true;
}
/// Simple conversion between integer and floating point types.
///
/// Used when handling the OpenCL conditional operator where the
/// condition is a vector while the other operands are scalar.
///
/// OpenCL v1.1 s6.3.i and s6.11.6 together require that the scalar
/// types are either integer or floating type. Between the two
/// operands, the type with the higher rank is defined as the "result
/// type". The other operand needs to be promoted to the same type. No
/// other type promotion is allowed. We cannot use
/// UsualArithmeticConversions() for this purpose, since it always
/// promotes promotable types.
static QualType OpenCLArithmeticConversions(Sema &S, ExprResult &LHS,
ExprResult &RHS,
SourceLocation QuestionLoc) {
LHS = S.DefaultFunctionArrayLvalueConversion(LHS.get());
if (LHS.isInvalid())
return QualType();
RHS = S.DefaultFunctionArrayLvalueConversion(RHS.get());
if (RHS.isInvalid())
return QualType();
// For conversion purposes, we ignore any qualifiers.
// For example, "const float" and "float" are equivalent.
QualType LHSType =
S.Context.getCanonicalType(LHS.get()->getType()).getUnqualifiedType();
QualType RHSType =
S.Context.getCanonicalType(RHS.get()->getType()).getUnqualifiedType();
if (!LHSType->isIntegerType() && !LHSType->isRealFloatingType()) {
S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_int_float)
<< LHSType << LHS.get()->getSourceRange();
return QualType();
}
if (!RHSType->isIntegerType() && !RHSType->isRealFloatingType()) {
S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_int_float)
<< RHSType << RHS.get()->getSourceRange();
return QualType();
}
// If both types are identical, no conversion is needed.
if (LHSType == RHSType)
return LHSType;
// Now handle "real" floating types (i.e. float, double, long double).
if (LHSType->isRealFloatingType() || RHSType->isRealFloatingType())
return handleFloatConversion(S, LHS, RHS, LHSType, RHSType,
/*IsCompAssign = */ false);
// Finally, we have two differing integer types.
return handleIntegerConversion<doIntegralCast, doIntegralCast>
(S, LHS, RHS, LHSType, RHSType, /*IsCompAssign = */ false);
}
/// Convert scalar operands to a vector that matches the
/// condition in length.
///
/// Used when handling the OpenCL conditional operator where the
/// condition is a vector while the other operands are scalar.
///
/// We first compute the "result type" for the scalar operands
/// according to OpenCL v1.1 s6.3.i. Both operands are then converted
/// into a vector of that type where the length matches the condition
/// vector type. s6.11.6 requires that the element types of the result
/// and the condition must have the same number of bits.
static QualType
OpenCLConvertScalarsToVectors(Sema &S, ExprResult &LHS, ExprResult &RHS,
QualType CondTy, SourceLocation QuestionLoc) {
QualType ResTy = OpenCLArithmeticConversions(S, LHS, RHS, QuestionLoc);
if (ResTy.isNull()) return QualType();
const VectorType *CV = CondTy->getAs<VectorType>();
assert(CV);
// Determine the vector result type
unsigned NumElements = CV->getNumElements();
QualType VectorTy = S.Context.getExtVectorType(ResTy, NumElements);
// Ensure that all types have the same number of bits
if (S.Context.getTypeSize(CV->getElementType())
!= S.Context.getTypeSize(ResTy)) {
// Since VectorTy is created internally, it does not pretty print
// with an OpenCL name. Instead, we just print a description.
std::string EleTyName = ResTy.getUnqualifiedType().getAsString();
SmallString<64> Str;
llvm::raw_svector_ostream OS(Str);
OS << "(vector of " << NumElements << " '" << EleTyName << "' values)";
S.Diag(QuestionLoc, diag::err_conditional_vector_element_size)
<< CondTy << OS.str();
return QualType();
}
// Convert operands to the vector result type
LHS = S.ImpCastExprToType(LHS.get(), VectorTy, CK_VectorSplat);
RHS = S.ImpCastExprToType(RHS.get(), VectorTy, CK_VectorSplat);
return VectorTy;
}
/// Return false if this is a valid OpenCL condition vector
static bool checkOpenCLConditionVector(Sema &S, Expr *Cond,
SourceLocation QuestionLoc) {
// OpenCL v1.1 s6.11.6 says the elements of the vector must be of
// integral type.
const VectorType *CondTy = Cond->getType()->getAs<VectorType>();
assert(CondTy);
QualType EleTy = CondTy->getElementType();
if (EleTy->isIntegerType()) return false;
S.Diag(QuestionLoc, diag::err_typecheck_cond_expect_nonfloat)
<< Cond->getType() << Cond->getSourceRange();
return true;
}
/// Return false if the vector condition type and the vector
/// result type are compatible.
///
/// OpenCL v1.1 s6.11.6 requires that both vector types have the same
/// number of elements, and their element types have the same number
/// of bits.
static bool checkVectorResult(Sema &S, QualType CondTy, QualType VecResTy,
SourceLocation QuestionLoc) {
const VectorType *CV = CondTy->getAs<VectorType>();
const VectorType *RV = VecResTy->getAs<VectorType>();
assert(CV && RV);
if (CV->getNumElements() != RV->getNumElements()) {
S.Diag(QuestionLoc, diag::err_conditional_vector_size)
<< CondTy << VecResTy;
return true;
}
QualType CVE = CV->getElementType();
QualType RVE = RV->getElementType();
if (S.Context.getTypeSize(CVE) != S.Context.getTypeSize(RVE)) {
S.Diag(QuestionLoc, diag::err_conditional_vector_element_size)
<< CondTy << VecResTy;
return true;
}
return false;
}
/// Return the resulting type for the conditional operator in
/// OpenCL (aka "ternary selection operator", OpenCL v1.1
/// s6.3.i) when the condition is a vector type.
static QualType
OpenCLCheckVectorConditional(Sema &S, ExprResult &Cond,
ExprResult &LHS, ExprResult &RHS,
SourceLocation QuestionLoc) {
Cond = S.DefaultFunctionArrayLvalueConversion(Cond.get());
if (Cond.isInvalid())
return QualType();
QualType CondTy = Cond.get()->getType();
if (checkOpenCLConditionVector(S, Cond.get(), QuestionLoc))
return QualType();
// If either operand is a vector then find the vector type of the
// result as specified in OpenCL v1.1 s6.3.i.
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType()) {
QualType VecResTy = S.CheckVectorOperands(LHS, RHS, QuestionLoc,
/*isCompAssign*/false,
/*AllowBothBool*/true,
/*AllowBoolConversions*/false);
if (VecResTy.isNull()) return QualType();
// The result type must match the condition type as specified in
// OpenCL v1.1 s6.11.6.
if (checkVectorResult(S, CondTy, VecResTy, QuestionLoc))
return QualType();
return VecResTy;
}
// Both operands are scalar.
return OpenCLConvertScalarsToVectors(S, LHS, RHS, CondTy, QuestionLoc);
}
/// Return true if the Expr is block type
static bool checkBlockType(Sema &S, const Expr *E) {
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
QualType Ty = CE->getCallee()->getType();
if (Ty->isBlockPointerType()) {
S.Diag(E->getExprLoc(), diag::err_opencl_ternary_with_block);
return true;
}
}
return false;
}
/// Note that LHS is not null here, even if this is the gnu "x ?: y" extension.
/// In that case, LHS = cond.
/// C99 6.5.15
QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
ExprResult &RHS, ExprValueKind &VK,
ExprObjectKind &OK,
SourceLocation QuestionLoc) {
ExprResult LHSResult = CheckPlaceholderExpr(LHS.get());
if (!LHSResult.isUsable()) return QualType();
LHS = LHSResult;
ExprResult RHSResult = CheckPlaceholderExpr(RHS.get());
if (!RHSResult.isUsable()) return QualType();
RHS = RHSResult;
// C++ is sufficiently different to merit its own checker.
if (getLangOpts().CPlusPlus)
return CXXCheckConditionalOperands(Cond, LHS, RHS, VK, OK, QuestionLoc);
VK = VK_RValue;
OK = OK_Ordinary;
// The OpenCL operator with a vector condition is sufficiently
// different to merit its own checker.
if (getLangOpts().OpenCL && Cond.get()->getType()->isVectorType())
return OpenCLCheckVectorConditional(*this, Cond, LHS, RHS, QuestionLoc);
// First, check the condition.
Cond = UsualUnaryConversions(Cond.get());
if (Cond.isInvalid())
return QualType();
if (checkCondition(*this, Cond.get(), QuestionLoc))
return QualType();
// Now check the two expressions.
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType())
return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false,
/*AllowBothBool*/true,
/*AllowBoolConversions*/false);
QualType ResTy = UsualArithmeticConversions(LHS, RHS);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
QualType LHSTy = LHS.get()->getType();
QualType RHSTy = RHS.get()->getType();
// Diagnose attempts to convert between __float128 and long double where
// such conversions currently can't be handled.
if (unsupportedTypeConversion(*this, LHSTy, RHSTy)) {
Diag(QuestionLoc,
diag::err_typecheck_cond_incompatible_operands) << LHSTy << RHSTy
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
// OpenCL v2.0 s6.12.5 - Blocks cannot be used as expressions of the ternary
// selection operator (?:).
if (getLangOpts().OpenCL &&
(checkBlockType(*this, LHS.get()) | checkBlockType(*this, RHS.get()))) {
return QualType();
}
// If both operands have arithmetic type, do the usual arithmetic conversions
// to find a common type: C99 6.5.15p3,5.
if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) {
LHS = ImpCastExprToType(LHS.get(), ResTy, PrepareScalarCast(LHS, ResTy));
RHS = ImpCastExprToType(RHS.get(), ResTy, PrepareScalarCast(RHS, ResTy));
return ResTy;
}
// If both operands are the same structure or union type, the result is that
// type.
if (const RecordType *LHSRT = LHSTy->getAs<RecordType>()) { // C99 6.5.15p3
if (const RecordType *RHSRT = RHSTy->getAs<RecordType>())
if (LHSRT->getDecl() == RHSRT->getDecl())
// "If both the operands have structure or union type, the result has
// that type." This implies that CV qualifiers are dropped.
return LHSTy.getUnqualifiedType();
// FIXME: Type of conditional expression must be complete in C mode.
}
// C99 6.5.15p5: "If both operands have void type, the result has void type."
// The following || allows only one side to be void (a GCC-ism).
if (LHSTy->isVoidType() || RHSTy->isVoidType()) {
return checkConditionalVoidType(*this, LHS, RHS);
}
// C99 6.5.15p6 - "if one operand is a null pointer constant, the result has
// the type of the other operand."
if (!checkConditionalNullPointer(*this, RHS, LHSTy)) return LHSTy;
if (!checkConditionalNullPointer(*this, LHS, RHSTy)) return RHSTy;
// All objective-c pointer type analysis is done here.
QualType compositeType = FindCompositeObjCPointerType(LHS, RHS,
QuestionLoc);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
if (!compositeType.isNull())
return compositeType;
// Handle block pointer types.
if (LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType())
return checkConditionalBlockPointerCompatibility(*this, LHS, RHS,
QuestionLoc);
// Check constraints for C object pointers types (C99 6.5.15p3,6).
if (LHSTy->isPointerType() && RHSTy->isPointerType())
return checkConditionalObjectPointersCompatibility(*this, LHS, RHS,
QuestionLoc);
// GCC compatibility: soften pointer/integer mismatch. Note that
// null pointers have been filtered out by this point.
if (checkPointerIntegerMismatch(*this, LHS, RHS.get(), QuestionLoc,
/*isIntFirstExpr=*/true))
return RHSTy;
if (checkPointerIntegerMismatch(*this, RHS, LHS.get(), QuestionLoc,
/*isIntFirstExpr=*/false))
return LHSTy;
// Emit a better diagnostic if one of the expressions is a null pointer
// constant and the other is not a pointer type. In this case, the user most
// likely forgot to take the address of the other expression.
if (DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc))
return QualType();
// Otherwise, the operands are not compatible.
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
<< LHSTy << RHSTy << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
return QualType();
}
/// FindCompositeObjCPointerType - Helper method to find composite type of
/// two objective-c pointer types of the two input expressions.
QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
SourceLocation QuestionLoc) {
QualType LHSTy = LHS.get()->getType();
QualType RHSTy = RHS.get()->getType();
// Handle things like Class and struct objc_class*. Here we case the result
// to the pseudo-builtin, because that will be implicitly cast back to the
// redefinition type if an attempt is made to access its fields.
if (LHSTy->isObjCClassType() &&
(Context.hasSameType(RHSTy, Context.getObjCClassRedefinitionType()))) {
RHS = ImpCastExprToType(RHS.get(), LHSTy, CK_CPointerToObjCPointerCast);
return LHSTy;
}
if (RHSTy->isObjCClassType() &&
(Context.hasSameType(LHSTy, Context.getObjCClassRedefinitionType()))) {
LHS = ImpCastExprToType(LHS.get(), RHSTy, CK_CPointerToObjCPointerCast);
return RHSTy;
}
// And the same for struct objc_object* / id
if (LHSTy->isObjCIdType() &&
(Context.hasSameType(RHSTy, Context.getObjCIdRedefinitionType()))) {
RHS = ImpCastExprToType(RHS.get(), LHSTy, CK_CPointerToObjCPointerCast);
return LHSTy;
}
if (RHSTy->isObjCIdType() &&
(Context.hasSameType(LHSTy, Context.getObjCIdRedefinitionType()))) {
LHS = ImpCastExprToType(LHS.get(), RHSTy, CK_CPointerToObjCPointerCast);
return RHSTy;
}
// And the same for struct objc_selector* / SEL
if (Context.isObjCSelType(LHSTy) &&
(Context.hasSameType(RHSTy, Context.getObjCSelRedefinitionType()))) {
RHS = ImpCastExprToType(RHS.get(), LHSTy, CK_BitCast);
return LHSTy;
}
if (Context.isObjCSelType(RHSTy) &&
(Context.hasSameType(LHSTy, Context.getObjCSelRedefinitionType()))) {
LHS = ImpCastExprToType(LHS.get(), RHSTy, CK_BitCast);
return RHSTy;
}
// Check constraints for Objective-C object pointers types.
if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) {
if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) {
// Two identical object pointer types are always compatible.
return LHSTy;
}
const ObjCObjectPointerType *LHSOPT = LHSTy->castAs<ObjCObjectPointerType>();
const ObjCObjectPointerType *RHSOPT = RHSTy->castAs<ObjCObjectPointerType>();
QualType compositeType = LHSTy;
// If both operands are interfaces and either operand can be
// assigned to the other, use that type as the composite
// type. This allows
// xxx ? (A*) a : (B*) b
// where B is a subclass of A.
//
// Additionally, as for assignment, if either type is 'id'
// allow silent coercion. Finally, if the types are
// incompatible then make sure to use 'id' as the composite
// type so the result is acceptable for sending messages to.
// FIXME: Consider unifying with 'areComparableObjCPointerTypes'.
// It could return the composite type.
if (!(compositeType =
Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull()) {
// Nothing more to do.
} else if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) {
compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy;
} else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) {
compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy;
} else if ((LHSTy->isObjCQualifiedIdType() ||
RHSTy->isObjCQualifiedIdType()) &&
Context.ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true)) {
// Need to handle "id<xx>" explicitly.
// GCC allows qualified id and any Objective-C type to devolve to
// id. Currently localizing to here until clear this should be
// part of ObjCQualifiedIdTypesAreCompatible.
compositeType = Context.getObjCIdType();
} else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) {
compositeType = Context.getObjCIdType();
} else {
Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands)
<< LHSTy << RHSTy
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
QualType incompatTy = Context.getObjCIdType();
LHS = ImpCastExprToType(LHS.get(), incompatTy, CK_BitCast);
RHS = ImpCastExprToType(RHS.get(), incompatTy, CK_BitCast);
return incompatTy;
}
// The object pointer types are compatible.
LHS = ImpCastExprToType(LHS.get(), compositeType, CK_BitCast);
RHS = ImpCastExprToType(RHS.get(), compositeType, CK_BitCast);
return compositeType;
}
// Check Objective-C object pointer types and 'void *'
if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) {
if (getLangOpts().ObjCAutoRefCount) {
// ARC forbids the implicit conversion of object pointers to 'void *',
// so these types are not compatible.
Diag(QuestionLoc, diag::err_cond_voidptr_arc) << LHSTy << RHSTy
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
LHS = RHS = true;
return QualType();
}
QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType();
QualType rhptee = RHSTy->getAs<ObjCObjectPointerType>()->getPointeeType();
QualType destPointee
= Context.getQualifiedType(lhptee, rhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
// Add qualifiers if necessary.
LHS = ImpCastExprToType(LHS.get(), destType, CK_NoOp);
// Promote to void*.
RHS = ImpCastExprToType(RHS.get(), destType, CK_BitCast);
return destType;
}
if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) {
if (getLangOpts().ObjCAutoRefCount) {
// ARC forbids the implicit conversion of object pointers to 'void *',
// so these types are not compatible.
Diag(QuestionLoc, diag::err_cond_voidptr_arc) << LHSTy << RHSTy
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
LHS = RHS = true;
return QualType();
}
QualType lhptee = LHSTy->getAs<ObjCObjectPointerType>()->getPointeeType();
QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType();
QualType destPointee
= Context.getQualifiedType(rhptee, lhptee.getQualifiers());
QualType destType = Context.getPointerType(destPointee);
// Add qualifiers if necessary.
RHS = ImpCastExprToType(RHS.get(), destType, CK_NoOp);
// Promote to void*.
LHS = ImpCastExprToType(LHS.get(), destType, CK_BitCast);
return destType;
}
return QualType();
}
/// SuggestParentheses - Emit a note with a fixit hint that wraps
/// ParenRange in parentheses.
static void SuggestParentheses(Sema &Self, SourceLocation Loc,
const PartialDiagnostic &Note,
SourceRange ParenRange) {
SourceLocation EndLoc = Self.getLocForEndOfToken(ParenRange.getEnd());
if (ParenRange.getBegin().isFileID() && ParenRange.getEnd().isFileID() &&
EndLoc.isValid()) {
Self.Diag(Loc, Note)
<< FixItHint::CreateInsertion(ParenRange.getBegin(), "(")
<< FixItHint::CreateInsertion(EndLoc, ")");
} else {
// We can't display the parentheses, so just show the bare note.
Self.Diag(Loc, Note) << ParenRange;
}
}
static bool IsArithmeticOp(BinaryOperatorKind Opc) {
return BinaryOperator::isAdditiveOp(Opc) ||
BinaryOperator::isMultiplicativeOp(Opc) ||
BinaryOperator::isShiftOp(Opc);
}
/// IsArithmeticBinaryExpr - Returns true if E is an arithmetic binary
/// expression, either using a built-in or overloaded operator,
/// and sets *OpCode to the opcode and *RHSExprs to the right-hand side
/// expression.
static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode,
Expr **RHSExprs) {
// Don't strip parenthesis: we should not warn if E is in parenthesis.
E = E->IgnoreImpCasts();
E = E->IgnoreConversionOperator();
E = E->IgnoreImpCasts();
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E)) {
E = MTE->GetTemporaryExpr();
E = E->IgnoreImpCasts();
}
// Built-in binary operator.
if (BinaryOperator *OP = dyn_cast<BinaryOperator>(E)) {
if (IsArithmeticOp(OP->getOpcode())) {
*Opcode = OP->getOpcode();
*RHSExprs = OP->getRHS();
return true;
}
}
// Overloaded operator.
if (CXXOperatorCallExpr *Call = dyn_cast<CXXOperatorCallExpr>(E)) {
if (Call->getNumArgs() != 2)
return false;
// Make sure this is really a binary operator that is safe to pass into
// BinaryOperator::getOverloadedOpcode(), e.g. it's not a subscript op.
OverloadedOperatorKind OO = Call->getOperator();
if (OO < OO_Plus || OO > OO_Arrow ||
OO == OO_PlusPlus || OO == OO_MinusMinus)
return false;
BinaryOperatorKind OpKind = BinaryOperator::getOverloadedOpcode(OO);
if (IsArithmeticOp(OpKind)) {
*Opcode = OpKind;
*RHSExprs = Call->getArg(1);
return true;
}
}
return false;
}
/// ExprLooksBoolean - Returns true if E looks boolean, i.e. it has boolean type
/// or is a logical expression such as (x==y) which has int type, but is
/// commonly interpreted as boolean.
static bool ExprLooksBoolean(Expr *E) {
E = E->IgnoreParenImpCasts();
if (E->getType()->isBooleanType())
return true;
if (BinaryOperator *OP = dyn_cast<BinaryOperator>(E))
return OP->isComparisonOp() || OP->isLogicalOp();
if (UnaryOperator *OP = dyn_cast<UnaryOperator>(E))
return OP->getOpcode() == UO_LNot;
if (E->getType()->isPointerType())
return true;
// FIXME: What about overloaded operator calls returning "unspecified boolean
// type"s (commonly pointer-to-members)?
return false;
}
/// DiagnoseConditionalPrecedence - Emit a warning when a conditional operator
/// and binary operator are mixed in a way that suggests the programmer assumed
/// the conditional operator has higher precedence, for example:
/// "int x = a + someBinaryCondition ? 1 : 2".
static void DiagnoseConditionalPrecedence(Sema &Self,
SourceLocation OpLoc,
Expr *Condition,
Expr *LHSExpr,
Expr *RHSExpr) {
BinaryOperatorKind CondOpcode;
Expr *CondRHS;
if (!IsArithmeticBinaryExpr(Condition, &CondOpcode, &CondRHS))
return;
if (!ExprLooksBoolean(CondRHS))
return;
// The condition is an arithmetic binary expression, with a right-
// hand side that looks boolean, so warn.
Self.Diag(OpLoc, diag::warn_precedence_conditional)
<< Condition->getSourceRange()
<< BinaryOperator::getOpcodeStr(CondOpcode);
SuggestParentheses(
Self, OpLoc,
Self.PDiag(diag::note_precedence_silence)
<< BinaryOperator::getOpcodeStr(CondOpcode),
SourceRange(Condition->getBeginLoc(), Condition->getEndLoc()));
SuggestParentheses(Self, OpLoc,
Self.PDiag(diag::note_precedence_conditional_first),
SourceRange(CondRHS->getBeginLoc(), RHSExpr->getEndLoc()));
}
/// Compute the nullability of a conditional expression.
static QualType computeConditionalNullability(QualType ResTy, bool IsBin,
QualType LHSTy, QualType RHSTy,
ASTContext &Ctx) {
if (!ResTy->isAnyPointerType())
return ResTy;
auto GetNullability = [&Ctx](QualType Ty) {
Optional<NullabilityKind> Kind = Ty->getNullability(Ctx);
if (Kind)
return *Kind;
return NullabilityKind::Unspecified;
};
auto LHSKind = GetNullability(LHSTy), RHSKind = GetNullability(RHSTy);
NullabilityKind MergedKind;
// Compute nullability of a binary conditional expression.
if (IsBin) {
if (LHSKind == NullabilityKind::NonNull)
MergedKind = NullabilityKind::NonNull;
else
MergedKind = RHSKind;
// Compute nullability of a normal conditional expression.
} else {
if (LHSKind == NullabilityKind::Nullable ||
RHSKind == NullabilityKind::Nullable)
MergedKind = NullabilityKind::Nullable;
else if (LHSKind == NullabilityKind::NonNull)
MergedKind = RHSKind;
else if (RHSKind == NullabilityKind::NonNull)
MergedKind = LHSKind;
else
MergedKind = NullabilityKind::Unspecified;
}
// Return if ResTy already has the correct nullability.
if (GetNullability(ResTy) == MergedKind)
return ResTy;
// Strip all nullability from ResTy.
while (ResTy->getNullability(Ctx))
ResTy = ResTy.getSingleStepDesugaredType(Ctx);
// Create a new AttributedType with the new nullability kind.
auto NewAttr = AttributedType::getNullabilityAttrKind(MergedKind);
return Ctx.getAttributedType(NewAttr, ResTy, ResTy);
}
/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
/// in the case of a the GNU conditional expr extension.
ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
SourceLocation ColonLoc,
Expr *CondExpr, Expr *LHSExpr,
Expr *RHSExpr) {
if (!getLangOpts().CPlusPlus) {
// C cannot handle TypoExpr nodes in the condition because it
// doesn't handle dependent types properly, so make sure any TypoExprs have
// been dealt with before checking the operands.
ExprResult CondResult = CorrectDelayedTyposInExpr(CondExpr);
ExprResult LHSResult = CorrectDelayedTyposInExpr(LHSExpr);
ExprResult RHSResult = CorrectDelayedTyposInExpr(RHSExpr);
if (!CondResult.isUsable())
return ExprError();
if (LHSExpr) {
if (!LHSResult.isUsable())
return ExprError();
}
if (!RHSResult.isUsable())
return ExprError();
CondExpr = CondResult.get();
LHSExpr = LHSResult.get();
RHSExpr = RHSResult.get();
}
// If this is the gnu "x ?: y" extension, analyze the types as though the LHS
// was the condition.
OpaqueValueExpr *opaqueValue = nullptr;
Expr *commonExpr = nullptr;
if (!LHSExpr) {
commonExpr = CondExpr;
// Lower out placeholder types first. This is important so that we don't
// try to capture a placeholder. This happens in few cases in C++; such
// as Objective-C++'s dictionary subscripting syntax.
if (commonExpr->hasPlaceholderType()) {
ExprResult result = CheckPlaceholderExpr(commonExpr);
if (!result.isUsable()) return ExprError();
commonExpr = result.get();
}
// We usually want to apply unary conversions *before* saving, except
// in the special case of a C++ l-value conditional.
if (!(getLangOpts().CPlusPlus
&& !commonExpr->isTypeDependent()
&& commonExpr->getValueKind() == RHSExpr->getValueKind()
&& commonExpr->isGLValue()
&& commonExpr->isOrdinaryOrBitFieldObject()
&& RHSExpr->isOrdinaryOrBitFieldObject()
&& Context.hasSameType(commonExpr->getType(), RHSExpr->getType()))) {
ExprResult commonRes = UsualUnaryConversions(commonExpr);
if (commonRes.isInvalid())
return ExprError();
commonExpr = commonRes.get();
}
// If the common expression is a class or array prvalue, materialize it
// so that we can safely refer to it multiple times.
if (commonExpr->isRValue() && (commonExpr->getType()->isRecordType() ||
commonExpr->getType()->isArrayType())) {
ExprResult MatExpr = TemporaryMaterializationConversion(commonExpr);
if (MatExpr.isInvalid())
return ExprError();
commonExpr = MatExpr.get();
}
opaqueValue = new (Context) OpaqueValueExpr(commonExpr->getExprLoc(),
commonExpr->getType(),
commonExpr->getValueKind(),
commonExpr->getObjectKind(),
commonExpr);
LHSExpr = CondExpr = opaqueValue;
}
QualType LHSTy = LHSExpr->getType(), RHSTy = RHSExpr->getType();
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
ExprResult Cond = CondExpr, LHS = LHSExpr, RHS = RHSExpr;
QualType result = CheckConditionalOperands(Cond, LHS, RHS,
VK, OK, QuestionLoc);
if (result.isNull() || Cond.isInvalid() || LHS.isInvalid() ||
RHS.isInvalid())
return ExprError();
DiagnoseConditionalPrecedence(*this, QuestionLoc, Cond.get(), LHS.get(),
RHS.get());
CheckBoolLikeConversion(Cond.get(), QuestionLoc);
result = computeConditionalNullability(result, commonExpr, LHSTy, RHSTy,
Context);
if (!commonExpr)
return new (Context)
ConditionalOperator(Cond.get(), QuestionLoc, LHS.get(), ColonLoc,
RHS.get(), result, VK, OK);
return new (Context) BinaryConditionalOperator(
commonExpr, opaqueValue, Cond.get(), LHS.get(), RHS.get(), QuestionLoc,
ColonLoc, result, VK, OK);
}
// checkPointerTypesForAssignment - This is a very tricky routine (despite
// being closely modeled after the C99 spec:-). The odd characteristic of this
// routine is it effectively iqnores the qualifiers on the top level pointee.
// This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3].
// FIXME: add a couple examples in this comment.
static Sema::AssignConvertType
checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) {
assert(LHSType.isCanonical() && "LHS not canonicalized!");
assert(RHSType.isCanonical() && "RHS not canonicalized!");
// get the "pointed to" type (ignoring qualifiers at the top level)
const Type *lhptee, *rhptee;
Qualifiers lhq, rhq;
std::tie(lhptee, lhq) =
cast<PointerType>(LHSType)->getPointeeType().split().asPair();
std::tie(rhptee, rhq) =
cast<PointerType>(RHSType)->getPointeeType().split().asPair();
Sema::AssignConvertType ConvTy = Sema::Compatible;
// C99 6.5.16.1p1: This following citation is common to constraints
// 3 & 4 (below). ...and the type *pointed to* by the left has all the
// qualifiers of the type *pointed to* by the right;
// As a special case, 'non-__weak A *' -> 'non-__weak const *' is okay.
if (lhq.getObjCLifetime() != rhq.getObjCLifetime() &&
lhq.compatiblyIncludesObjCLifetime(rhq)) {
// Ignore lifetime for further calculation.
lhq.removeObjCLifetime();
rhq.removeObjCLifetime();
}
if (!lhq.compatiblyIncludes(rhq)) {
// Treat address-space mismatches as fatal. TODO: address subspaces
if (!lhq.isAddressSpaceSupersetOf(rhq))
ConvTy = Sema::IncompatiblePointerDiscardsQualifiers;
// It's okay to add or remove GC or lifetime qualifiers when converting to
// and from void*.
else if (lhq.withoutObjCGCAttr().withoutObjCLifetime()
.compatiblyIncludes(
rhq.withoutObjCGCAttr().withoutObjCLifetime())
&& (lhptee->isVoidType() || rhptee->isVoidType()))
; // keep old
// Treat lifetime mismatches as fatal.
else if (lhq.getObjCLifetime() != rhq.getObjCLifetime())
ConvTy = Sema::IncompatiblePointerDiscardsQualifiers;
// For GCC/MS compatibility, other qualifier mismatches are treated
// as still compatible in C.
else ConvTy = Sema::CompatiblePointerDiscardsQualifiers;
}
// C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or
// incomplete type and the other is a pointer to a qualified or unqualified
// version of void...
if (lhptee->isVoidType()) {
if (rhptee->isIncompleteOrObjectType())
return ConvTy;
// As an extension, we allow cast to/from void* to function pointer.
assert(rhptee->isFunctionType());
return Sema::FunctionVoidPointer;
}
if (rhptee->isVoidType()) {
if (lhptee->isIncompleteOrObjectType())
return ConvTy;
// As an extension, we allow cast to/from void* to function pointer.
assert(lhptee->isFunctionType());
return Sema::FunctionVoidPointer;
}
// C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or
// unqualified versions of compatible types, ...
QualType ltrans = QualType(lhptee, 0), rtrans = QualType(rhptee, 0);
if (!S.Context.typesAreCompatible(ltrans, rtrans)) {
// Check if the pointee types are compatible ignoring the sign.
// We explicitly check for char so that we catch "char" vs
// "unsigned char" on systems where "char" is unsigned.
if (lhptee->isCharType())
ltrans = S.Context.UnsignedCharTy;
else if (lhptee->hasSignedIntegerRepresentation())
ltrans = S.Context.getCorrespondingUnsignedType(ltrans);
if (rhptee->isCharType())
rtrans = S.Context.UnsignedCharTy;
else if (rhptee->hasSignedIntegerRepresentation())
rtrans = S.Context.getCorrespondingUnsignedType(rtrans);
if (ltrans == rtrans) {
// Types are compatible ignoring the sign. Qualifier incompatibility
// takes priority over sign incompatibility because the sign
// warning can be disabled.
if (ConvTy != Sema::Compatible)
return ConvTy;
return Sema::IncompatiblePointerSign;
}
// If we are a multi-level pointer, it's possible that our issue is simply
// one of qualification - e.g. char ** -> const char ** is not allowed. If
// the eventual target type is the same and the pointers have the same
// level of indirection, this must be the issue.
if (isa<PointerType>(lhptee) && isa<PointerType>(rhptee)) {
do {
lhptee = cast<PointerType>(lhptee)->getPointeeType().getTypePtr();
rhptee = cast<PointerType>(rhptee)->getPointeeType().getTypePtr();
} while (isa<PointerType>(lhptee) && isa<PointerType>(rhptee));
if (lhptee == rhptee)
return Sema::IncompatibleNestedPointerQualifiers;
}
// General pointer incompatibility takes priority over qualifiers.
return Sema::IncompatiblePointer;
}
if (!S.getLangOpts().CPlusPlus &&
S.IsFunctionConversion(ltrans, rtrans, ltrans))
return Sema::IncompatiblePointer;
return ConvTy;
}
/// checkBlockPointerTypesForAssignment - This routine determines whether two
/// block pointer types are compatible or whether a block and normal pointer
/// are compatible. It is more restrict than comparing two function pointer
// types.
static Sema::AssignConvertType
checkBlockPointerTypesForAssignment(Sema &S, QualType LHSType,
QualType RHSType) {
assert(LHSType.isCanonical() && "LHS not canonicalized!");
assert(RHSType.isCanonical() && "RHS not canonicalized!");
QualType lhptee, rhptee;
// get the "pointed to" type (ignoring qualifiers at the top level)
lhptee = cast<BlockPointerType>(LHSType)->getPointeeType();
rhptee = cast<BlockPointerType>(RHSType)->getPointeeType();
// In C++, the types have to match exactly.
if (S.getLangOpts().CPlusPlus)
return Sema::IncompatibleBlockPointer;
Sema::AssignConvertType ConvTy = Sema::Compatible;
// For blocks we enforce that qualifiers are identical.
Qualifiers LQuals = lhptee.getLocalQualifiers();
Qualifiers RQuals = rhptee.getLocalQualifiers();
if (S.getLangOpts().OpenCL) {
LQuals.removeAddressSpace();
RQuals.removeAddressSpace();
}
if (LQuals != RQuals)
ConvTy = Sema::CompatiblePointerDiscardsQualifiers;
// FIXME: OpenCL doesn't define the exact compile time semantics for a block
// assignment.
// The current behavior is similar to C++ lambdas. A block might be
// assigned to a variable iff its return type and parameters are compatible
// (C99 6.2.7) with the corresponding return type and parameters of the LHS of
// an assignment. Presumably it should behave in way that a function pointer
// assignment does in C, so for each parameter and return type:
// * CVR and address space of LHS should be a superset of CVR and address
// space of RHS.
// * unqualified types should be compatible.
if (S.getLangOpts().OpenCL) {
if (!S.Context.typesAreBlockPointerCompatible(
S.Context.getQualifiedType(LHSType.getUnqualifiedType(), LQuals),
S.Context.getQualifiedType(RHSType.getUnqualifiedType(), RQuals)))
return Sema::IncompatibleBlockPointer;
} else if (!S.Context.typesAreBlockPointerCompatible(LHSType, RHSType))
return Sema::IncompatibleBlockPointer;
return ConvTy;
}
/// checkObjCPointerTypesForAssignment - Compares two objective-c pointer types
/// for assignment compatibility.
static Sema::AssignConvertType
checkObjCPointerTypesForAssignment(Sema &S, QualType LHSType,
QualType RHSType) {
assert(LHSType.isCanonical() && "LHS was not canonicalized!");
assert(RHSType.isCanonical() && "RHS was not canonicalized!");
if (LHSType->isObjCBuiltinType()) {
// Class is not compatible with ObjC object pointers.
if (LHSType->isObjCClassType() && !RHSType->isObjCBuiltinType() &&
!RHSType->isObjCQualifiedClassType())
return Sema::IncompatiblePointer;
return Sema::Compatible;
}
if (RHSType->isObjCBuiltinType()) {
if (RHSType->isObjCClassType() && !LHSType->isObjCBuiltinType() &&
!LHSType->isObjCQualifiedClassType())
return Sema::IncompatiblePointer;
return Sema::Compatible;
}
QualType lhptee = LHSType->getAs<ObjCObjectPointerType>()->getPointeeType();
QualType rhptee = RHSType->getAs<ObjCObjectPointerType>()->getPointeeType();
if (!lhptee.isAtLeastAsQualifiedAs(rhptee) &&
// make an exception for id<P>
!LHSType->isObjCQualifiedIdType())
return Sema::CompatiblePointerDiscardsQualifiers;
if (S.Context.typesAreCompatible(LHSType, RHSType))
return Sema::Compatible;
if (LHSType->isObjCQualifiedIdType() || RHSType->isObjCQualifiedIdType())
return Sema::IncompatibleObjCQualifiedId;
return Sema::IncompatiblePointer;
}
Sema::AssignConvertType
Sema::CheckAssignmentConstraints(SourceLocation Loc,
QualType LHSType, QualType RHSType) {
// Fake up an opaque expression. We don't actually care about what
// cast operations are required, so if CheckAssignmentConstraints
// adds casts to this they'll be wasted, but fortunately that doesn't
// usually happen on valid code.
OpaqueValueExpr RHSExpr(Loc, RHSType, VK_RValue);
ExprResult RHSPtr = &RHSExpr;
CastKind K;
return CheckAssignmentConstraints(LHSType, RHSPtr, K, /*ConvertRHS=*/false);
}
/// This helper function returns true if QT is a vector type that has element
/// type ElementType.
static bool isVector(QualType QT, QualType ElementType) {
if (const VectorType *VT = QT->getAs<VectorType>())
return VT->getElementType() == ElementType;
return false;
}
/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently
/// has code to accommodate several GCC extensions when type checking
/// pointers. Here are some objectionable examples that GCC considers warnings:
///
/// int a, *pint;
/// short *pshort;
/// struct foo *pfoo;
///
/// pint = pshort; // warning: assignment from incompatible pointer type
/// a = pint; // warning: assignment makes integer from pointer without a cast
/// pint = a; // warning: assignment makes pointer from integer without a cast
/// pint = pfoo; // warning: assignment from incompatible pointer type
///
/// As a result, the code for dealing with pointers is more complex than the
/// C99 spec dictates.
///
/// Sets 'Kind' for any result kind except Incompatible.
Sema::AssignConvertType
Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
CastKind &Kind, bool ConvertRHS) {
QualType RHSType = RHS.get()->getType();
QualType OrigLHSType = LHSType;
// Get canonical types. We're not formatting these types, just comparing
// them.
LHSType = Context.getCanonicalType(LHSType).getUnqualifiedType();
RHSType = Context.getCanonicalType(RHSType).getUnqualifiedType();
// Common case: no conversion required.
if (LHSType == RHSType) {
Kind = CK_NoOp;
return Compatible;
}
// If we have an atomic type, try a non-atomic assignment, then just add an
// atomic qualification step.
if (const AtomicType *AtomicTy = dyn_cast<AtomicType>(LHSType)) {
Sema::AssignConvertType result =
CheckAssignmentConstraints(AtomicTy->getValueType(), RHS, Kind);
if (result != Compatible)
return result;
if (Kind != CK_NoOp && ConvertRHS)
RHS = ImpCastExprToType(RHS.get(), AtomicTy->getValueType(), Kind);
Kind = CK_NonAtomicToAtomic;
return Compatible;
}
// If the left-hand side is a reference type, then we are in a
// (rare!) case where we've allowed the use of references in C,
// e.g., as a parameter type in a built-in function. In this case,
// just make sure that the type referenced is compatible with the
// right-hand side type. The caller is responsible for adjusting
// LHSType so that the resulting expression does not have reference
// type.
if (const ReferenceType *LHSTypeRef = LHSType->getAs<ReferenceType>()) {
if (Context.typesAreCompatible(LHSTypeRef->getPointeeType(), RHSType)) {
Kind = CK_LValueBitCast;
return Compatible;
}
return Incompatible;
}
// Allow scalar to ExtVector assignments, and assignments of an ExtVector type
// to the same ExtVector type.
if (LHSType->isExtVectorType()) {
if (RHSType->isExtVectorType())
return Incompatible;
if (RHSType->isArithmeticType()) {
// CK_VectorSplat does T -> vector T, so first cast to the element type.
if (ConvertRHS)
RHS = prepareVectorSplat(LHSType, RHS.get());
Kind = CK_VectorSplat;
return Compatible;
}
}
// Conversions to or from vector type.
if (LHSType->isVectorType() || RHSType->isVectorType()) {
if (LHSType->isVectorType() && RHSType->isVectorType()) {
// Allow assignments of an AltiVec vector type to an equivalent GCC
// vector type and vice versa
if (Context.areCompatibleVectorTypes(LHSType, RHSType)) {
Kind = CK_BitCast;
return Compatible;
}
// If we are allowing lax vector conversions, and LHS and RHS are both
// vectors, the total size only needs to be the same. This is a bitcast;
// no bits are changed but the result type is different.
if (isLaxVectorConversion(RHSType, LHSType)) {
Kind = CK_BitCast;
return IncompatibleVectors;
}
}
// When the RHS comes from another lax conversion (e.g. binops between
// scalars and vectors) the result is canonicalized as a vector. When the
// LHS is also a vector, the lax is allowed by the condition above. Handle
// the case where LHS is a scalar.
if (LHSType->isScalarType()) {
const VectorType *VecType = RHSType->getAs<VectorType>();
if (VecType && VecType->getNumElements() == 1 &&
isLaxVectorConversion(RHSType, LHSType)) {
ExprResult *VecExpr = &RHS;
*VecExpr = ImpCastExprToType(VecExpr->get(), LHSType, CK_BitCast);
Kind = CK_BitCast;
return Compatible;
}
}
return Incompatible;
}
// Diagnose attempts to convert between __float128 and long double where
// such conversions currently can't be handled.
if (unsupportedTypeConversion(*this, LHSType, RHSType))
return Incompatible;
// Disallow assigning a _Complex to a real type in C++ mode since it simply
// discards the imaginary part.
if (getLangOpts().CPlusPlus && RHSType->getAs<ComplexType>() &&
!LHSType->getAs<ComplexType>())
return Incompatible;
// Arithmetic conversions.
if (LHSType->isArithmeticType() && RHSType->isArithmeticType() &&
!(getLangOpts().CPlusPlus && LHSType->isEnumeralType())) {
if (ConvertRHS)
Kind = PrepareScalarCast(RHS, LHSType);
return Compatible;
}
// Conversions to normal pointers.
if (const PointerType *LHSPointer = dyn_cast<PointerType>(LHSType)) {
// U* -> T*
if (isa<PointerType>(RHSType)) {
LangAS AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace();
LangAS AddrSpaceR = RHSType->getPointeeType().getAddressSpace();
if (AddrSpaceL != AddrSpaceR)
Kind = CK_AddressSpaceConversion;
else if (Context.hasCvrSimilarType(RHSType, LHSType))
Kind = CK_NoOp;
else
Kind = CK_BitCast;
return checkPointerTypesForAssignment(*this, LHSType, RHSType);
}
// int -> T*
if (RHSType->isIntegerType()) {
Kind = CK_IntegralToPointer; // FIXME: null?
return IntToPointer;
}
// C pointers are not compatible with ObjC object pointers,
// with two exceptions:
if (isa<ObjCObjectPointerType>(RHSType)) {
// - conversions to void*
if (LHSPointer->getPointeeType()->isVoidType()) {
Kind = CK_BitCast;
return Compatible;
}
// - conversions from 'Class' to the redefinition type
if (RHSType->isObjCClassType() &&
Context.hasSameType(LHSType,
Context.getObjCClassRedefinitionType())) {
Kind = CK_BitCast;
return Compatible;
}
Kind = CK_BitCast;
return IncompatiblePointer;
}
// U^ -> void*
if (RHSType->getAs<BlockPointerType>()) {
if (LHSPointer->getPointeeType()->isVoidType()) {
LangAS AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace();
LangAS AddrSpaceR = RHSType->getAs<BlockPointerType>()
->getPointeeType()
.getAddressSpace();
Kind =
AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast;
return Compatible;
}
}
return Incompatible;
}
// Conversions to block pointers.
if (isa<BlockPointerType>(LHSType)) {
// U^ -> T^
if (RHSType->isBlockPointerType()) {
LangAS AddrSpaceL = LHSType->getAs<BlockPointerType>()
->getPointeeType()
.getAddressSpace();
LangAS AddrSpaceR = RHSType->getAs<BlockPointerType>()
->getPointeeType()
.getAddressSpace();
Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast;
return checkBlockPointerTypesForAssignment(*this, LHSType, RHSType);
}
// int or null -> T^
if (RHSType->isIntegerType()) {
Kind = CK_IntegralToPointer; // FIXME: null
return IntToBlockPointer;
}
// id -> T^
if (getLangOpts().ObjC && RHSType->isObjCIdType()) {
Kind = CK_AnyPointerToBlockPointerCast;
return Compatible;
}
// void* -> T^
if (const PointerType *RHSPT = RHSType->getAs<PointerType>())
if (RHSPT->getPointeeType()->isVoidType()) {
Kind = CK_AnyPointerToBlockPointerCast;
return Compatible;
}
return Incompatible;
}
// Conversions to Objective-C pointers.
if (isa<ObjCObjectPointerType>(LHSType)) {
// A* -> B*
if (RHSType->isObjCObjectPointerType()) {
Kind = CK_BitCast;
Sema::AssignConvertType result =
checkObjCPointerTypesForAssignment(*this, LHSType, RHSType);
if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() &&
result == Compatible &&
!CheckObjCARCUnavailableWeakConversion(OrigLHSType, RHSType))
result = IncompatibleObjCWeakRef;
return result;
}
// int or null -> A*
if (RHSType->isIntegerType()) {
Kind = CK_IntegralToPointer; // FIXME: null
return IntToPointer;
}
// In general, C pointers are not compatible with ObjC object pointers,
// with two exceptions:
if (isa<PointerType>(RHSType)) {
Kind = CK_CPointerToObjCPointerCast;
// - conversions from 'void*'
if (RHSType->isVoidPointerType()) {
return Compatible;
}
// - conversions to 'Class' from its redefinition type
if (LHSType->isObjCClassType() &&
Context.hasSameType(RHSType,
Context.getObjCClassRedefinitionType())) {
return Compatible;
}
return IncompatiblePointer;
}
// Only under strict condition T^ is compatible with an Objective-C pointer.
if (RHSType->isBlockPointerType() &&
LHSType->isBlockCompatibleObjCPointerType(Context)) {
if (ConvertRHS)
maybeExtendBlockObject(RHS);
Kind = CK_BlockPointerToObjCPointerCast;
return Compatible;
}
return Incompatible;
}
// Conversions from pointers that are not covered by the above.
if (isa<PointerType>(RHSType)) {
// T* -> _Bool
if (LHSType == Context.BoolTy) {
Kind = CK_PointerToBoolean;
return Compatible;
}
// T* -> int
if (LHSType->isIntegerType()) {
Kind = CK_PointerToIntegral;
return PointerToInt;
}
return Incompatible;
}
// Conversions from Objective-C pointers that are not covered by the above.
if (isa<ObjCObjectPointerType>(RHSType)) {
// T* -> _Bool
if (LHSType == Context.BoolTy) {
Kind = CK_PointerToBoolean;
return Compatible;
}
// T* -> int
if (LHSType->isIntegerType()) {
Kind = CK_PointerToIntegral;
return PointerToInt;
}
return Incompatible;
}
// struct A -> struct B
if (isa<TagType>(LHSType) && isa<TagType>(RHSType)) {
if (Context.typesAreCompatible(LHSType, RHSType)) {
Kind = CK_NoOp;
return Compatible;
}
}
if (LHSType->isSamplerT() && RHSType->isIntegerType()) {
Kind = CK_IntToOCLSampler;
return Compatible;
}
return Incompatible;
}
/// Constructs a transparent union from an expression that is
/// used to initialize the transparent union.
static void ConstructTransparentUnion(Sema &S, ASTContext &C,
ExprResult &EResult, QualType UnionType,
FieldDecl *Field) {
// Build an initializer list that designates the appropriate member
// of the transparent union.
Expr *E = EResult.get();
InitListExpr *Initializer = new (C) InitListExpr(C, SourceLocation(),
E, SourceLocation());
Initializer->setType(UnionType);
Initializer->setInitializedFieldInUnion(Field);
// Build a compound literal constructing a value of the transparent
// union type from this initializer list.
TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType);
EResult = new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType,
VK_RValue, Initializer, false);
}
Sema::AssignConvertType
Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType,
ExprResult &RHS) {
QualType RHSType = RHS.get()->getType();
// If the ArgType is a Union type, we want to handle a potential
// transparent_union GCC extension.
const RecordType *UT = ArgType->getAsUnionType();
if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
return Incompatible;
// The field to initialize within the transparent union.
RecordDecl *UD = UT->getDecl();
FieldDecl *InitField = nullptr;
// It's compatible if the expression matches any of the fields.
for (auto *it : UD->fields()) {
if (it->getType()->isPointerType()) {
// If the transparent union contains a pointer type, we allow:
// 1) void pointer
// 2) null pointer constant
if (RHSType->isPointerType())
if (RHSType->castAs<PointerType>()->getPointeeType()->isVoidType()) {
RHS = ImpCastExprToType(RHS.get(), it->getType(), CK_BitCast);
InitField = it;
break;
}
if (RHS.get()->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
RHS = ImpCastExprToType(RHS.get(), it->getType(),
CK_NullToPointer);
InitField = it;
break;
}
}
CastKind Kind;
if (CheckAssignmentConstraints(it->getType(), RHS, Kind)
== Compatible) {
RHS = ImpCastExprToType(RHS.get(), it->getType(), Kind);
InitField = it;
break;
}
}
if (!InitField)
return Incompatible;
ConstructTransparentUnion(*this, Context, RHS, ArgType, InitField);
return Compatible;
}
Sema::AssignConvertType
Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &CallerRHS,
bool Diagnose,
bool DiagnoseCFAudited,
bool ConvertRHS) {
// We need to be able to tell the caller whether we diagnosed a problem, if
// they ask us to issue diagnostics.
assert((ConvertRHS || !Diagnose) && "can't indicate whether we diagnosed");
// If ConvertRHS is false, we want to leave the caller's RHS untouched. Sadly,
// we can't avoid *all* modifications at the moment, so we need some somewhere
// to put the updated value.
ExprResult LocalRHS = CallerRHS;
ExprResult &RHS = ConvertRHS ? CallerRHS : LocalRHS;
if (const auto *LHSPtrType = LHSType->getAs<PointerType>()) {
if (const auto *RHSPtrType = RHS.get()->getType()->getAs<PointerType>()) {
if (RHSPtrType->getPointeeType()->hasAttr(attr::NoDeref) &&
!LHSPtrType->getPointeeType()->hasAttr(attr::NoDeref)) {
Diag(RHS.get()->getExprLoc(),
diag::warn_noderef_to_dereferenceable_pointer)
<< RHS.get()->getSourceRange();
}
}
}
if (getLangOpts().CPlusPlus) {
if (!LHSType->isRecordType() && !LHSType->isAtomicType()) {
// C++ 5.17p3: If the left operand is not of class type, the
// expression is implicitly converted (C++ 4) to the
// cv-unqualified type of the left operand.
QualType RHSType = RHS.get()->getType();
if (Diagnose) {
RHS = PerformImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(),
AA_Assigning);
} else {
ImplicitConversionSequence ICS =
TryImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(),
/*SuppressUserConversions=*/false,
/*AllowExplicit=*/false,
/*InOverloadResolution=*/false,
/*CStyle=*/false,
/*AllowObjCWritebackConversion=*/false);
if (ICS.isFailure())
return Incompatible;
RHS = PerformImplicitConversion(RHS.get(), LHSType.getUnqualifiedType(),
ICS, AA_Assigning);
}
if (RHS.isInvalid())
return Incompatible;
Sema::AssignConvertType result = Compatible;
if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() &&
!CheckObjCARCUnavailableWeakConversion(LHSType, RHSType))
result = IncompatibleObjCWeakRef;
return result;
}
// FIXME: Currently, we fall through and treat C++ classes like C
// structures.
// FIXME: We also fall through for atomics; not sure what should
// happen there, though.
} else if (RHS.get()->getType() == Context.OverloadTy) {
// As a set of extensions to C, we support overloading on functions. These
// functions need to be resolved here.
DeclAccessPair DAP;
if (FunctionDecl *FD = ResolveAddressOfOverloadedFunction(
RHS.get(), LHSType, /*Complain=*/false, DAP))
RHS = FixOverloadedFunctionReference(RHS.get(), DAP, FD);
else
return Incompatible;
}
// C99 6.5.16.1p1: the left operand is a pointer and the right is
// a null pointer constant.
if ((LHSType->isPointerType() || LHSType->isObjCObjectPointerType() ||
LHSType->isBlockPointerType()) &&
RHS.get()->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
if (Diagnose || ConvertRHS) {
CastKind Kind;
CXXCastPath Path;
CheckPointerConversion(RHS.get(), LHSType, Kind, Path,
/*IgnoreBaseAccess=*/false, Diagnose);
if (ConvertRHS)
RHS = ImpCastExprToType(RHS.get(), LHSType, Kind, VK_RValue, &Path);
}
return Compatible;
}
// OpenCL queue_t type assignment.
if (LHSType->isQueueT() && RHS.get()->isNullPointerConstant(
Context, Expr::NPC_ValueDependentIsNull)) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
return Compatible;
}
// This check seems unnatural, however it is necessary to ensure the proper
// conversion of functions/arrays. If the conversion were done for all
// DeclExpr's (created by ActOnIdExpression), it would mess up the unary
// expressions that suppress this implicit conversion (&, sizeof).
//
// Suppress this for references: C++ 8.5.3p5.
if (!LHSType->isReferenceType()) {
// FIXME: We potentially allocate here even if ConvertRHS is false.
RHS = DefaultFunctionArrayLvalueConversion(RHS.get(), Diagnose);
if (RHS.isInvalid())
return Incompatible;
}
CastKind Kind;
Sema::AssignConvertType result =
CheckAssignmentConstraints(LHSType, RHS, Kind, ConvertRHS);
// C99 6.5.16.1p2: The value of the right operand is converted to the
// type of the assignment expression.
// CheckAssignmentConstraints allows the left-hand side to be a reference,
// so that we can use references in built-in functions even in C.
// The getNonReferenceType() call makes sure that the resulting expression
// does not have reference type.
if (result != Incompatible && RHS.get()->getType() != LHSType) {
QualType Ty = LHSType.getNonLValueExprType(Context);
Expr *E = RHS.get();
// Check for various Objective-C errors. If we are not reporting
// diagnostics and just checking for errors, e.g., during overload
// resolution, return Incompatible to indicate the failure.
if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() &&
CheckObjCConversion(SourceRange(), Ty, E, CCK_ImplicitConversion,
Diagnose, DiagnoseCFAudited) != ACR_okay) {
if (!Diagnose)
return Incompatible;
}
if (getLangOpts().ObjC &&
(CheckObjCBridgeRelatedConversions(E->getBeginLoc(), LHSType,
E->getType(), E, Diagnose) ||
ConversionToObjCStringLiteralCheck(LHSType, E, Diagnose))) {
if (!Diagnose)
return Incompatible;
// Replace the expression with a corrected version and continue so we
// can find further errors.
RHS = E;
return Compatible;
}
if (ConvertRHS)
RHS = ImpCastExprToType(E, Ty, Kind);
}
return result;
}
namespace {
/// The original operand to an operator, prior to the application of the usual
/// arithmetic conversions and converting the arguments of a builtin operator
/// candidate.
struct OriginalOperand {
explicit OriginalOperand(Expr *Op) : Orig(Op), Conversion(nullptr) {
if (auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Op))
Op = MTE->GetTemporaryExpr();
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Op))
Op = BTE->getSubExpr();
if (auto *ICE = dyn_cast<ImplicitCastExpr>(Op)) {
Orig = ICE->getSubExprAsWritten();
Conversion = ICE->getConversionFunction();
}
}
QualType getType() const { return Orig->getType(); }
Expr *Orig;
NamedDecl *Conversion;
};
}
QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS,
ExprResult &RHS) {
OriginalOperand OrigLHS(LHS.get()), OrigRHS(RHS.get());
Diag(Loc, diag::err_typecheck_invalid_operands)
<< OrigLHS.getType() << OrigRHS.getType()
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
// If a user-defined conversion was applied to either of the operands prior
// to applying the built-in operator rules, tell the user about it.
if (OrigLHS.Conversion) {
Diag(OrigLHS.Conversion->getLocation(),
diag::note_typecheck_invalid_operands_converted)
<< 0 << LHS.get()->getType();
}
if (OrigRHS.Conversion) {
Diag(OrigRHS.Conversion->getLocation(),
diag::note_typecheck_invalid_operands_converted)
<< 1 << RHS.get()->getType();
}
return QualType();
}
// Diagnose cases where a scalar was implicitly converted to a vector and
// diagnose the underlying types. Otherwise, diagnose the error
// as invalid vector logical operands for non-C++ cases.
QualType Sema::InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS,
ExprResult &RHS) {
QualType LHSType = LHS.get()->IgnoreImpCasts()->getType();
QualType RHSType = RHS.get()->IgnoreImpCasts()->getType();
bool LHSNatVec = LHSType->isVectorType();
bool RHSNatVec = RHSType->isVectorType();
if (!(LHSNatVec && RHSNatVec)) {
Expr *Vector = LHSNatVec ? LHS.get() : RHS.get();
Expr *NonVector = !LHSNatVec ? LHS.get() : RHS.get();
Diag(Loc, diag::err_typecheck_logical_vector_expr_gnu_cpp_restrict)
<< 0 << Vector->getType() << NonVector->IgnoreImpCasts()->getType()
<< Vector->getSourceRange();
return QualType();
}
Diag(Loc, diag::err_typecheck_logical_vector_expr_gnu_cpp_restrict)
<< 1 << LHSType << RHSType << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
return QualType();
}
/// Try to convert a value of non-vector type to a vector type by converting
/// the type to the element type of the vector and then performing a splat.
/// If the language is OpenCL, we only use conversions that promote scalar
/// rank; for C, Obj-C, and C++ we allow any real scalar conversion except
/// for float->int.
///
/// OpenCL V2.0 6.2.6.p2:
/// An error shall occur if any scalar operand type has greater rank
/// than the type of the vector element.
///
/// \param scalar - if non-null, actually perform the conversions
/// \return true if the operation fails (but without diagnosing the failure)
static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar,
QualType scalarTy,
QualType vectorEltTy,
QualType vectorTy,
unsigned &DiagID) {
// The conversion to apply to the scalar before splatting it,
// if necessary.
CastKind scalarCast = CK_NoOp;
if (vectorEltTy->isIntegralType(S.Context)) {
if (S.getLangOpts().OpenCL && (scalarTy->isRealFloatingType() ||
(scalarTy->isIntegerType() &&
S.Context.getIntegerTypeOrder(vectorEltTy, scalarTy) < 0))) {
DiagID = diag::err_opencl_scalar_type_rank_greater_than_vector_type;
return true;
}
if (!scalarTy->isIntegralType(S.Context))
return true;
scalarCast = CK_IntegralCast;
} else if (vectorEltTy->isRealFloatingType()) {
if (scalarTy->isRealFloatingType()) {
if (S.getLangOpts().OpenCL &&
S.Context.getFloatingTypeOrder(vectorEltTy, scalarTy) < 0) {
DiagID = diag::err_opencl_scalar_type_rank_greater_than_vector_type;
return true;
}
scalarCast = CK_FloatingCast;
}
else if (scalarTy->isIntegralType(S.Context))
scalarCast = CK_IntegralToFloating;
else
return true;
} else {
return true;
}
// Adjust scalar if desired.
if (scalar) {
if (scalarCast != CK_NoOp)
*scalar = S.ImpCastExprToType(scalar->get(), vectorEltTy, scalarCast);
*scalar = S.ImpCastExprToType(scalar->get(), vectorTy, CK_VectorSplat);
}
return false;
}
/// Convert vector E to a vector with the same number of elements but different
/// element type.
static ExprResult convertVector(Expr *E, QualType ElementType, Sema &S) {
const auto *VecTy = E->getType()->getAs<VectorType>();
assert(VecTy && "Expression E must be a vector");
QualType NewVecTy = S.Context.getVectorType(ElementType,
VecTy->getNumElements(),
VecTy->getVectorKind());
// Look through the implicit cast. Return the subexpression if its type is
// NewVecTy.
if (auto *ICE = dyn_cast<ImplicitCastExpr>(E))
if (ICE->getSubExpr()->getType() == NewVecTy)
return ICE->getSubExpr();
auto Cast = ElementType->isIntegerType() ? CK_IntegralCast : CK_FloatingCast;
return S.ImpCastExprToType(E, NewVecTy, Cast);
}
/// Test if a (constant) integer Int can be casted to another integer type
/// IntTy without losing precision.
static bool canConvertIntToOtherIntTy(Sema &S, ExprResult *Int,
QualType OtherIntTy) {
QualType IntTy = Int->get()->getType().getUnqualifiedType();
// Reject cases where the value of the Int is unknown as that would
// possibly cause truncation, but accept cases where the scalar can be
// demoted without loss of precision.
Expr::EvalResult EVResult;
bool CstInt = Int->get()->EvaluateAsInt(EVResult, S.Context);
int Order = S.Context.getIntegerTypeOrder(OtherIntTy, IntTy);
bool IntSigned = IntTy->hasSignedIntegerRepresentation();
bool OtherIntSigned = OtherIntTy->hasSignedIntegerRepresentation();
if (CstInt) {
// If the scalar is constant and is of a higher order and has more active
// bits that the vector element type, reject it.
llvm::APSInt Result = EVResult.Val.getInt();
unsigned NumBits = IntSigned
? (Result.isNegative() ? Result.getMinSignedBits()
: Result.getActiveBits())
: Result.getActiveBits();
if (Order < 0 && S.Context.getIntWidth(OtherIntTy) < NumBits)
return true;
// If the signedness of the scalar type and the vector element type
// differs and the number of bits is greater than that of the vector
// element reject it.
return (IntSigned != OtherIntSigned &&
NumBits > S.Context.getIntWidth(OtherIntTy));
}
// Reject cases where the value of the scalar is not constant and it's
// order is greater than that of the vector element type.
return (Order < 0);
}
/// Test if a (constant) integer Int can be casted to floating point type
/// FloatTy without losing precision.
static bool canConvertIntTyToFloatTy(Sema &S, ExprResult *Int,
QualType FloatTy) {
QualType IntTy = Int->get()->getType().getUnqualifiedType();
// Determine if the integer constant can be expressed as a floating point
// number of the appropriate type.
Expr::EvalResult EVResult;
bool CstInt = Int->get()->EvaluateAsInt(EVResult, S.Context);
uint64_t Bits = 0;
if (CstInt) {
// Reject constants that would be truncated if they were converted to
// the floating point type. Test by simple to/from conversion.
// FIXME: Ideally the conversion to an APFloat and from an APFloat
// could be avoided if there was a convertFromAPInt method
// which could signal back if implicit truncation occurred.
llvm::APSInt Result = EVResult.Val.getInt();
llvm::APFloat Float(S.Context.getFloatTypeSemantics(FloatTy));
Float.convertFromAPInt(Result, IntTy->hasSignedIntegerRepresentation(),
llvm::APFloat::rmTowardZero);
llvm::APSInt ConvertBack(S.Context.getIntWidth(IntTy),
!IntTy->hasSignedIntegerRepresentation());
bool Ignored = false;
Float.convertToInteger(ConvertBack, llvm::APFloat::rmNearestTiesToEven,
&Ignored);
if (Result != ConvertBack)
return true;
} else {
// Reject types that cannot be fully encoded into the mantissa of
// the float.
Bits = S.Context.getTypeSize(IntTy);
unsigned FloatPrec = llvm::APFloat::semanticsPrecision(
S.Context.getFloatTypeSemantics(FloatTy));
if (Bits > FloatPrec)
return true;
}
return false;
}
/// Attempt to convert and splat Scalar into a vector whose types matches
/// Vector following GCC conversion rules. The rule is that implicit
/// conversion can occur when Scalar can be casted to match Vector's element
/// type without causing truncation of Scalar.
static bool tryGCCVectorConvertAndSplat(Sema &S, ExprResult *Scalar,
ExprResult *Vector) {
QualType ScalarTy = Scalar->get()->getType().getUnqualifiedType();
QualType VectorTy = Vector->get()->getType().getUnqualifiedType();
const VectorType *VT = VectorTy->getAs<VectorType>();
assert(!isa<ExtVectorType>(VT) &&
"ExtVectorTypes should not be handled here!");
QualType VectorEltTy = VT->getElementType();
// Reject cases where the vector element type or the scalar element type are
// not integral or floating point types.
if (!VectorEltTy->isArithmeticType() || !ScalarTy->isArithmeticType())
return true;
// The conversion to apply to the scalar before splatting it,
// if necessary.
CastKind ScalarCast = CK_NoOp;
// Accept cases where the vector elements are integers and the scalar is
// an integer.
// FIXME: Notionally if the scalar was a floating point value with a precise
// integral representation, we could cast it to an appropriate integer
// type and then perform the rest of the checks here. GCC will perform
// this conversion in some cases as determined by the input language.
// We should accept it on a language independent basis.
if (VectorEltTy->isIntegralType(S.Context) &&
ScalarTy->isIntegralType(S.Context) &&
S.Context.getIntegerTypeOrder(VectorEltTy, ScalarTy)) {
if (canConvertIntToOtherIntTy(S, Scalar, VectorEltTy))
return true;
ScalarCast = CK_IntegralCast;
} else if (VectorEltTy->isRealFloatingType()) {
if (ScalarTy->isRealFloatingType()) {
// Reject cases where the scalar type is not a constant and has a higher
// Order than the vector element type.
llvm::APFloat Result(0.0);
bool CstScalar = Scalar->get()->EvaluateAsFloat(Result, S.Context);
int Order = S.Context.getFloatingTypeOrder(VectorEltTy, ScalarTy);
if (!CstScalar && Order < 0)
return true;
// If the scalar cannot be safely casted to the vector element type,
// reject it.
if (CstScalar) {
bool Truncated = false;
Result.convert(S.Context.getFloatTypeSemantics(VectorEltTy),
llvm::APFloat::rmNearestTiesToEven, &Truncated);
if (Truncated)
return true;
}
ScalarCast = CK_FloatingCast;
} else if (ScalarTy->isIntegralType(S.Context)) {
if (canConvertIntTyToFloatTy(S, Scalar, VectorEltTy))
return true;
ScalarCast = CK_IntegralToFloating;
} else
return true;
}
// Adjust scalar if desired.
if (Scalar) {
if (ScalarCast != CK_NoOp)
*Scalar = S.ImpCastExprToType(Scalar->get(), VectorEltTy, ScalarCast);
*Scalar = S.ImpCastExprToType(Scalar->get(), VectorTy, CK_VectorSplat);
}
return false;
}
QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, bool IsCompAssign,
bool AllowBothBool,
bool AllowBoolConversions) {
if (!IsCompAssign) {
LHS = DefaultFunctionArrayLvalueConversion(LHS.get());
if (LHS.isInvalid())
return QualType();
}
RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
if (RHS.isInvalid())
return QualType();
// For conversion purposes, we ignore any qualifiers.
// For example, "const float" and "float" are equivalent.
QualType LHSType = LHS.get()->getType().getUnqualifiedType();
QualType RHSType = RHS.get()->getType().getUnqualifiedType();
const VectorType *LHSVecType = LHSType->getAs<VectorType>();
const VectorType *RHSVecType = RHSType->getAs<VectorType>();
assert(LHSVecType || RHSVecType);
// AltiVec-style "vector bool op vector bool" combinations are allowed
// for some operators but not others.
if (!AllowBothBool &&
LHSVecType && LHSVecType->getVectorKind() == VectorType::AltiVecBool &&
RHSVecType && RHSVecType->getVectorKind() == VectorType::AltiVecBool)
return InvalidOperands(Loc, LHS, RHS);
// If the vector types are identical, return.
if (Context.hasSameType(LHSType, RHSType))
return LHSType;
// If we have compatible AltiVec and GCC vector types, use the AltiVec type.
if (LHSVecType && RHSVecType &&
Context.areCompatibleVectorTypes(LHSType, RHSType)) {
if (isa<ExtVectorType>(LHSVecType)) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
return LHSType;
}
if (!IsCompAssign)
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_BitCast);
return RHSType;
}
// AllowBoolConversions says that bool and non-bool AltiVec vectors
// can be mixed, with the result being the non-bool type. The non-bool
// operand must have integer element type.
if (AllowBoolConversions && LHSVecType && RHSVecType &&
LHSVecType->getNumElements() == RHSVecType->getNumElements() &&
(Context.getTypeSize(LHSVecType->getElementType()) ==
Context.getTypeSize(RHSVecType->getElementType()))) {
if (LHSVecType->getVectorKind() == VectorType::AltiVecVector &&
LHSVecType->getElementType()->isIntegerType() &&
RHSVecType->getVectorKind() == VectorType::AltiVecBool) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
return LHSType;
}
if (!IsCompAssign &&
LHSVecType->getVectorKind() == VectorType::AltiVecBool &&
RHSVecType->getVectorKind() == VectorType::AltiVecVector &&
RHSVecType->getElementType()->isIntegerType()) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_BitCast);
return RHSType;
}
}
// If there's a vector type and a scalar, try to convert the scalar to
// the vector element type and splat.
unsigned DiagID = diag::err_typecheck_vector_not_convertable;
if (!RHSVecType) {
if (isa<ExtVectorType>(LHSVecType)) {
if (!tryVectorConvertAndSplat(*this, &RHS, RHSType,
LHSVecType->getElementType(), LHSType,
DiagID))
return LHSType;
} else {
if (!tryGCCVectorConvertAndSplat(*this, &RHS, &LHS))
return LHSType;
}
}
if (!LHSVecType) {
if (isa<ExtVectorType>(RHSVecType)) {
if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? nullptr : &LHS),
LHSType, RHSVecType->getElementType(),
RHSType, DiagID))
return RHSType;
} else {
if (LHS.get()->getValueKind() == VK_LValue ||
!tryGCCVectorConvertAndSplat(*this, &LHS, &RHS))
return RHSType;
}
}
// FIXME: The code below also handles conversion between vectors and
// non-scalars, we should break this down into fine grained specific checks
// and emit proper diagnostics.
QualType VecType = LHSVecType ? LHSType : RHSType;
const VectorType *VT = LHSVecType ? LHSVecType : RHSVecType;
QualType OtherType = LHSVecType ? RHSType : LHSType;
ExprResult *OtherExpr = LHSVecType ? &RHS : &LHS;
if (isLaxVectorConversion(OtherType, VecType)) {
// If we're allowing lax vector conversions, only the total (data) size
// needs to be the same. For non compound assignment, if one of the types is
// scalar, the result is always the vector type.
if (!IsCompAssign) {
*OtherExpr = ImpCastExprToType(OtherExpr->get(), VecType, CK_BitCast);
return VecType;
// In a compound assignment, lhs += rhs, 'lhs' is a lvalue src, forbidding
// any implicit cast. Here, the 'rhs' should be implicit casted to 'lhs'
// type. Note that this is already done by non-compound assignments in
// CheckAssignmentConstraints. If it's a scalar type, only bitcast for
// <1 x T> -> T. The result is also a vector type.
} else if (OtherType->isExtVectorType() || OtherType->isVectorType() ||
(OtherType->isScalarType() && VT->getNumElements() == 1)) {
ExprResult *RHSExpr = &RHS;
*RHSExpr = ImpCastExprToType(RHSExpr->get(), LHSType, CK_BitCast);
return VecType;
}
}
// Okay, the expression is invalid.
// If there's a non-vector, non-real operand, diagnose that.
if ((!RHSVecType && !RHSType->isRealType()) ||
(!LHSVecType && !LHSType->isRealType())) {
Diag(Loc, diag::err_typecheck_vector_not_convertable_non_scalar)
<< LHSType << RHSType
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
// OpenCL V1.1 6.2.6.p1:
// If the operands are of more than one vector type, then an error shall
// occur. Implicit conversions between vector types are not permitted, per
// section 6.2.1.
if (getLangOpts().OpenCL &&
RHSVecType && isa<ExtVectorType>(RHSVecType) &&
LHSVecType && isa<ExtVectorType>(LHSVecType)) {
Diag(Loc, diag::err_opencl_implicit_vector_conversion) << LHSType
<< RHSType;
return QualType();
}
// If there is a vector type that is not a ExtVector and a scalar, we reach
// this point if scalar could not be converted to the vector's element type
// without truncation.
if ((RHSVecType && !isa<ExtVectorType>(RHSVecType)) ||
(LHSVecType && !isa<ExtVectorType>(LHSVecType))) {
QualType Scalar = LHSVecType ? RHSType : LHSType;
QualType Vector = LHSVecType ? LHSType : RHSType;
unsigned ScalarOrVector = LHSVecType && RHSVecType ? 1 : 0;
Diag(Loc,
diag::err_typecheck_vector_not_convertable_implict_truncation)
<< ScalarOrVector << Scalar << Vector;
return QualType();
}
// Otherwise, use the generic diagnostic.
Diag(Loc, DiagID)
<< LHSType << RHSType
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
// checkArithmeticNull - Detect when a NULL constant is used improperly in an
// expression. These are mainly cases where the null pointer is used as an
// integer instead of a pointer.
static void checkArithmeticNull(Sema &S, ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, bool IsCompare) {
// The canonical way to check for a GNU null is with isNullPointerConstant,
// but we use a bit of a hack here for speed; this is a relatively
// hot path, and isNullPointerConstant is slow.
bool LHSNull = isa<GNUNullExpr>(LHS.get()->IgnoreParenImpCasts());
bool RHSNull = isa<GNUNullExpr>(RHS.get()->IgnoreParenImpCasts());
QualType NonNullType = LHSNull ? RHS.get()->getType() : LHS.get()->getType();
// Avoid analyzing cases where the result will either be invalid (and
// diagnosed as such) or entirely valid and not something to warn about.
if ((!LHSNull && !RHSNull) || NonNullType->isBlockPointerType() ||
NonNullType->isMemberPointerType() || NonNullType->isFunctionType())
return;
// Comparison operations would not make sense with a null pointer no matter
// what the other expression is.
if (!IsCompare) {
S.Diag(Loc, diag::warn_null_in_arithmetic_operation)
<< (LHSNull ? LHS.get()->getSourceRange() : SourceRange())
<< (RHSNull ? RHS.get()->getSourceRange() : SourceRange());
return;
}
// The rest of the operations only make sense with a null pointer
// if the other expression is a pointer.
if (LHSNull == RHSNull || NonNullType->isAnyPointerType() ||
NonNullType->canDecayToPointerType())
return;
S.Diag(Loc, diag::warn_null_in_comparison_operation)
<< LHSNull /* LHS is NULL */ << NonNullType
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
static void DiagnoseDivisionSizeofPointer(Sema &S, Expr *LHS, Expr *RHS,
SourceLocation Loc) {
const auto *LUE = dyn_cast<UnaryExprOrTypeTraitExpr>(LHS);
const auto *RUE = dyn_cast<UnaryExprOrTypeTraitExpr>(RHS);
if (!LUE || !RUE)
return;
if (LUE->getKind() != UETT_SizeOf || LUE->isArgumentType() ||
RUE->getKind() != UETT_SizeOf)
return;
QualType LHSTy = LUE->getArgumentExpr()->IgnoreParens()->getType();
QualType RHSTy;
if (RUE->isArgumentType())
RHSTy = RUE->getArgumentType();
else
RHSTy = RUE->getArgumentExpr()->IgnoreParens()->getType();
if (!LHSTy->isPointerType() || RHSTy->isPointerType())
return;
if (LHSTy->getPointeeType() != RHSTy)
return;
S.Diag(Loc, diag::warn_division_sizeof_ptr) << LHS << LHS->getSourceRange();
}
static void DiagnoseBadDivideOrRemainderValues(Sema& S, ExprResult &LHS,
ExprResult &RHS,
SourceLocation Loc, bool IsDiv) {
// Check for division/remainder by zero.
Expr::EvalResult RHSValue;
if (!RHS.get()->isValueDependent() &&
RHS.get()->EvaluateAsInt(RHSValue, S.Context) &&
RHSValue.Val.getInt() == 0)
S.DiagRuntimeBehavior(Loc, RHS.get(),
S.PDiag(diag::warn_remainder_division_by_zero)
<< IsDiv << RHS.get()->getSourceRange());
}
QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
bool IsCompAssign, bool IsDiv) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType())
return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign,
/*AllowBothBool*/getLangOpts().AltiVec,
/*AllowBoolConversions*/false);
QualType compType = UsualArithmeticConversions(LHS, RHS, IsCompAssign);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
if (compType.isNull() || !compType->isArithmeticType())
return InvalidOperands(Loc, LHS, RHS);
if (IsDiv) {
DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, IsDiv);
DiagnoseDivisionSizeofPointer(*this, LHS.get(), RHS.get(), Loc);
}
return compType;
}
QualType Sema::CheckRemainderOperands(
ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType()) {
if (LHS.get()->getType()->hasIntegerRepresentation() &&
RHS.get()->getType()->hasIntegerRepresentation())
return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign,
/*AllowBothBool*/getLangOpts().AltiVec,
/*AllowBoolConversions*/false);
return InvalidOperands(Loc, LHS, RHS);
}
QualType compType = UsualArithmeticConversions(LHS, RHS, IsCompAssign);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
if (compType.isNull() || !compType->isIntegerType())
return InvalidOperands(Loc, LHS, RHS);
DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, false /* IsDiv */);
return compType;
}
/// Diagnose invalid arithmetic on two void pointers.
static void diagnoseArithmeticOnTwoVoidPointers(Sema &S, SourceLocation Loc,
Expr *LHSExpr, Expr *RHSExpr) {
S.Diag(Loc, S.getLangOpts().CPlusPlus
? diag::err_typecheck_pointer_arith_void_type
: diag::ext_gnu_void_ptr)
<< 1 /* two pointers */ << LHSExpr->getSourceRange()
<< RHSExpr->getSourceRange();
}
/// Diagnose invalid arithmetic on a void pointer.
static void diagnoseArithmeticOnVoidPointer(Sema &S, SourceLocation Loc,
Expr *Pointer) {
S.Diag(Loc, S.getLangOpts().CPlusPlus
? diag::err_typecheck_pointer_arith_void_type
: diag::ext_gnu_void_ptr)
<< 0 /* one pointer */ << Pointer->getSourceRange();
}
/// Diagnose invalid arithmetic on a null pointer.
///
/// If \p IsGNUIdiom is true, the operation is using the 'p = (i8*)nullptr + n'
/// idiom, which we recognize as a GNU extension.
///
static void diagnoseArithmeticOnNullPointer(Sema &S, SourceLocation Loc,
Expr *Pointer, bool IsGNUIdiom) {
if (IsGNUIdiom)
S.Diag(Loc, diag::warn_gnu_null_ptr_arith)
<< Pointer->getSourceRange();
else
S.Diag(Loc, diag::warn_pointer_arith_null_ptr)
<< S.getLangOpts().CPlusPlus << Pointer->getSourceRange();
}
/// Diagnose invalid arithmetic on two function pointers.
static void diagnoseArithmeticOnTwoFunctionPointers(Sema &S, SourceLocation Loc,
Expr *LHS, Expr *RHS) {
assert(LHS->getType()->isAnyPointerType());
assert(RHS->getType()->isAnyPointerType());
S.Diag(Loc, S.getLangOpts().CPlusPlus
? diag::err_typecheck_pointer_arith_function_type
: diag::ext_gnu_ptr_func_arith)
<< 1 /* two pointers */ << LHS->getType()->getPointeeType()
// We only show the second type if it differs from the first.
<< (unsigned)!S.Context.hasSameUnqualifiedType(LHS->getType(),
RHS->getType())
<< RHS->getType()->getPointeeType()
<< LHS->getSourceRange() << RHS->getSourceRange();
}
/// Diagnose invalid arithmetic on a function pointer.
static void diagnoseArithmeticOnFunctionPointer(Sema &S, SourceLocation Loc,
Expr *Pointer) {
assert(Pointer->getType()->isAnyPointerType());
S.Diag(Loc, S.getLangOpts().CPlusPlus
? diag::err_typecheck_pointer_arith_function_type
: diag::ext_gnu_ptr_func_arith)
<< 0 /* one pointer */ << Pointer->getType()->getPointeeType()
<< 0 /* one pointer, so only one type */
<< Pointer->getSourceRange();
}
/// Emit error if Operand is incomplete pointer type
///
/// \returns True if pointer has incomplete type
static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc,
Expr *Operand) {
QualType ResType = Operand->getType();
if (const AtomicType *ResAtomicType = ResType->getAs<AtomicType>())
ResType = ResAtomicType->getValueType();
assert(ResType->isAnyPointerType() && !ResType->isDependentType());
QualType PointeeTy = ResType->getPointeeType();
return S.RequireCompleteType(Loc, PointeeTy,
diag::err_typecheck_arithmetic_incomplete_type,
PointeeTy, Operand->getSourceRange());
}
/// Check the validity of an arithmetic pointer operand.
///
/// If the operand has pointer type, this code will check for pointer types
/// which are invalid in arithmetic operations. These will be diagnosed
/// appropriately, including whether or not the use is supported as an
/// extension.
///
/// \returns True when the operand is valid to use (even if as an extension).
static bool checkArithmeticOpPointerOperand(Sema &S, SourceLocation Loc,
Expr *Operand) {
QualType ResType = Operand->getType();
if (const AtomicType *ResAtomicType = ResType->getAs<AtomicType>())
ResType = ResAtomicType->getValueType();
if (!ResType->isAnyPointerType()) return true;
QualType PointeeTy = ResType->getPointeeType();
if (PointeeTy->isVoidType()) {
diagnoseArithmeticOnVoidPointer(S, Loc, Operand);
return !S.getLangOpts().CPlusPlus;
}
if (PointeeTy->isFunctionType()) {
diagnoseArithmeticOnFunctionPointer(S, Loc, Operand);
return !S.getLangOpts().CPlusPlus;
}
if (checkArithmeticIncompletePointerType(S, Loc, Operand)) return false;
return true;
}
/// Check the validity of a binary arithmetic operation w.r.t. pointer
/// operands.
///
/// This routine will diagnose any invalid arithmetic on pointer operands much
/// like \see checkArithmeticOpPointerOperand. However, it has special logic
/// for emitting a single diagnostic even for operations where both LHS and RHS
/// are (potentially problematic) pointers.
///
/// \returns True when the operand is valid to use (even if as an extension).
static bool checkArithmeticBinOpPointerOperands(Sema &S, SourceLocation Loc,
Expr *LHSExpr, Expr *RHSExpr) {
bool isLHSPointer = LHSExpr->getType()->isAnyPointerType();
bool isRHSPointer = RHSExpr->getType()->isAnyPointerType();
if (!isLHSPointer && !isRHSPointer) return true;
QualType LHSPointeeTy, RHSPointeeTy;
if (isLHSPointer) LHSPointeeTy = LHSExpr->getType()->getPointeeType();
if (isRHSPointer) RHSPointeeTy = RHSExpr->getType()->getPointeeType();
// if both are pointers check if operation is valid wrt address spaces
if (S.getLangOpts().OpenCL && isLHSPointer && isRHSPointer) {
const PointerType *lhsPtr = LHSExpr->getType()->getAs<PointerType>();
const PointerType *rhsPtr = RHSExpr->getType()->getAs<PointerType>();
if (!lhsPtr->isAddressSpaceOverlapping(*rhsPtr)) {
S.Diag(Loc,
diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
<< LHSExpr->getType() << RHSExpr->getType() << 1 /*arithmetic op*/
<< LHSExpr->getSourceRange() << RHSExpr->getSourceRange();
return false;
}
}
// Check for arithmetic on pointers to incomplete types.
bool isLHSVoidPtr = isLHSPointer && LHSPointeeTy->isVoidType();
bool isRHSVoidPtr = isRHSPointer && RHSPointeeTy->isVoidType();
if (isLHSVoidPtr || isRHSVoidPtr) {
if (!isRHSVoidPtr) diagnoseArithmeticOnVoidPointer(S, Loc, LHSExpr);
else if (!isLHSVoidPtr) diagnoseArithmeticOnVoidPointer(S, Loc, RHSExpr);
else diagnoseArithmeticOnTwoVoidPointers(S, Loc, LHSExpr, RHSExpr);
return !S.getLangOpts().CPlusPlus;
}
bool isLHSFuncPtr = isLHSPointer && LHSPointeeTy->isFunctionType();
bool isRHSFuncPtr = isRHSPointer && RHSPointeeTy->isFunctionType();
if (isLHSFuncPtr || isRHSFuncPtr) {
if (!isRHSFuncPtr) diagnoseArithmeticOnFunctionPointer(S, Loc, LHSExpr);
else if (!isLHSFuncPtr) diagnoseArithmeticOnFunctionPointer(S, Loc,
RHSExpr);
else diagnoseArithmeticOnTwoFunctionPointers(S, Loc, LHSExpr, RHSExpr);
return !S.getLangOpts().CPlusPlus;
}
if (isLHSPointer && checkArithmeticIncompletePointerType(S, Loc, LHSExpr))
return false;
if (isRHSPointer && checkArithmeticIncompletePointerType(S, Loc, RHSExpr))
return false;
return true;
}
/// diagnoseStringPlusInt - Emit a warning when adding an integer to a string
/// literal.
static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc,
Expr *LHSExpr, Expr *RHSExpr) {
StringLiteral* StrExpr = dyn_cast<StringLiteral>(LHSExpr->IgnoreImpCasts());
Expr* IndexExpr = RHSExpr;
if (!StrExpr) {
StrExpr = dyn_cast<StringLiteral>(RHSExpr->IgnoreImpCasts());
IndexExpr = LHSExpr;
}
bool IsStringPlusInt = StrExpr &&
IndexExpr->getType()->isIntegralOrUnscopedEnumerationType();
if (!IsStringPlusInt || IndexExpr->isValueDependent())
return;
SourceRange DiagRange(LHSExpr->getBeginLoc(), RHSExpr->getEndLoc());
Self.Diag(OpLoc, diag::warn_string_plus_int)
<< DiagRange << IndexExpr->IgnoreImpCasts()->getType();
// Only print a fixit for "str" + int, not for int + "str".
if (IndexExpr == RHSExpr) {
SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getEndLoc());
Self.Diag(OpLoc, diag::note_string_plus_scalar_silence)
<< FixItHint::CreateInsertion(LHSExpr->getBeginLoc(), "&")
<< FixItHint::CreateReplacement(SourceRange(OpLoc), "[")
<< FixItHint::CreateInsertion(EndLoc, "]");
} else
Self.Diag(OpLoc, diag::note_string_plus_scalar_silence);
}
/// Emit a warning when adding a char literal to a string.
static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc,
Expr *LHSExpr, Expr *RHSExpr) {
const Expr *StringRefExpr = LHSExpr;
const CharacterLiteral *CharExpr =
dyn_cast<CharacterLiteral>(RHSExpr->IgnoreImpCasts());
if (!CharExpr) {
CharExpr = dyn_cast<CharacterLiteral>(LHSExpr->IgnoreImpCasts());
StringRefExpr = RHSExpr;
}
if (!CharExpr || !StringRefExpr)
return;
const QualType StringType = StringRefExpr->getType();
// Return if not a PointerType.
if (!StringType->isAnyPointerType())
return;
// Return if not a CharacterType.
if (!StringType->getPointeeType()->isAnyCharacterType())
return;
ASTContext &Ctx = Self.getASTContext();
SourceRange DiagRange(LHSExpr->getBeginLoc(), RHSExpr->getEndLoc());
const QualType CharType = CharExpr->getType();
if (!CharType->isAnyCharacterType() &&
CharType->isIntegerType() &&
llvm::isUIntN(Ctx.getCharWidth(), CharExpr->getValue())) {
Self.Diag(OpLoc, diag::warn_string_plus_char)
<< DiagRange << Ctx.CharTy;
} else {
Self.Diag(OpLoc, diag::warn_string_plus_char)
<< DiagRange << CharExpr->getType();
}
// Only print a fixit for str + char, not for char + str.
if (isa<CharacterLiteral>(RHSExpr->IgnoreImpCasts())) {
SourceLocation EndLoc = Self.getLocForEndOfToken(RHSExpr->getEndLoc());
Self.Diag(OpLoc, diag::note_string_plus_scalar_silence)
<< FixItHint::CreateInsertion(LHSExpr->getBeginLoc(), "&")
<< FixItHint::CreateReplacement(SourceRange(OpLoc), "[")
<< FixItHint::CreateInsertion(EndLoc, "]");
} else {
Self.Diag(OpLoc, diag::note_string_plus_scalar_silence);
}
}
/// Emit error when two pointers are incompatible.
static void diagnosePointerIncompatibility(Sema &S, SourceLocation Loc,
Expr *LHSExpr, Expr *RHSExpr) {
assert(LHSExpr->getType()->isAnyPointerType());
assert(RHSExpr->getType()->isAnyPointerType());
S.Diag(Loc, diag::err_typecheck_sub_ptr_compatible)
<< LHSExpr->getType() << RHSExpr->getType() << LHSExpr->getSourceRange()
<< RHSExpr->getSourceRange();
}
// C99 6.5.6
QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, BinaryOperatorKind Opc,
QualType* CompLHSTy) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType()) {
QualType compType = CheckVectorOperands(
LHS, RHS, Loc, CompLHSTy,
/*AllowBothBool*/getLangOpts().AltiVec,
/*AllowBoolConversions*/getLangOpts().ZVector);
if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
QualType compType = UsualArithmeticConversions(LHS, RHS, CompLHSTy);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
// Diagnose "string literal" '+' int and string '+' "char literal".
if (Opc == BO_Add) {
diagnoseStringPlusInt(*this, Loc, LHS.get(), RHS.get());
diagnoseStringPlusChar(*this, Loc, LHS.get(), RHS.get());
}
// handle the common case first (both operands are arithmetic).
if (!compType.isNull() && compType->isArithmeticType()) {
if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
// Type-checking. Ultimately the pointer's going to be in PExp;
// note that we bias towards the LHS being the pointer.
Expr *PExp = LHS.get(), *IExp = RHS.get();
bool isObjCPointer;
if (PExp->getType()->isPointerType()) {
isObjCPointer = false;
} else if (PExp->getType()->isObjCObjectPointerType()) {
isObjCPointer = true;
} else {
std::swap(PExp, IExp);
if (PExp->getType()->isPointerType()) {
isObjCPointer = false;
} else if (PExp->getType()->isObjCObjectPointerType()) {
isObjCPointer = true;
} else {
return InvalidOperands(Loc, LHS, RHS);
}
}
assert(PExp->getType()->isAnyPointerType());
if (!IExp->getType()->isIntegerType())
return InvalidOperands(Loc, LHS, RHS);
// Adding to a null pointer results in undefined behavior.
if (PExp->IgnoreParenCasts()->isNullPointerConstant(
Context, Expr::NPC_ValueDependentIsNotNull)) {
// In C++ adding zero to a null pointer is defined.
Expr::EvalResult KnownVal;
if (!getLangOpts().CPlusPlus ||
(!IExp->isValueDependent() &&
(!IExp->EvaluateAsInt(KnownVal, Context) ||
KnownVal.Val.getInt() != 0))) {
// Check the conditions to see if this is the 'p = nullptr + n' idiom.
bool IsGNUIdiom = BinaryOperator::isNullPointerArithmeticExtension(
Context, BO_Add, PExp, IExp);
diagnoseArithmeticOnNullPointer(*this, Loc, PExp, IsGNUIdiom);
}
}
if (!checkArithmeticOpPointerOperand(*this, Loc, PExp))
return QualType();
if (isObjCPointer && checkArithmeticOnObjCPointer(*this, Loc, PExp))
return QualType();
// Check array bounds for pointer arithemtic
CheckArrayAccess(PExp, IExp);
if (CompLHSTy) {
QualType LHSTy = Context.isPromotableBitField(LHS.get());
if (LHSTy.isNull()) {
LHSTy = LHS.get()->getType();
if (LHSTy->isPromotableIntegerType())
LHSTy = Context.getPromotedIntegerType(LHSTy);
}
*CompLHSTy = LHSTy;
}
return PExp->getType();
}
// C99 6.5.6
QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
QualType* CompLHSTy) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType()) {
QualType compType = CheckVectorOperands(
LHS, RHS, Loc, CompLHSTy,
/*AllowBothBool*/getLangOpts().AltiVec,
/*AllowBoolConversions*/getLangOpts().ZVector);
if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
QualType compType = UsualArithmeticConversions(LHS, RHS, CompLHSTy);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
// Enforce type constraints: C99 6.5.6p3.
// Handle the common case first (both operands are arithmetic).
if (!compType.isNull() && compType->isArithmeticType()) {
if (CompLHSTy) *CompLHSTy = compType;
return compType;
}
// Either ptr - int or ptr - ptr.
if (LHS.get()->getType()->isAnyPointerType()) {
QualType lpointee = LHS.get()->getType()->getPointeeType();
// Diagnose bad cases where we step over interface counts.
if (LHS.get()->getType()->isObjCObjectPointerType() &&
checkArithmeticOnObjCPointer(*this, Loc, LHS.get()))
return QualType();
// The result type of a pointer-int computation is the pointer type.
if (RHS.get()->getType()->isIntegerType()) {
// Subtracting from a null pointer should produce a warning.
// The last argument to the diagnose call says this doesn't match the
// GNU int-to-pointer idiom.
if (LHS.get()->IgnoreParenCasts()->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNotNull)) {
// In C++ adding zero to a null pointer is defined.
Expr::EvalResult KnownVal;
if (!getLangOpts().CPlusPlus ||
(!RHS.get()->isValueDependent() &&
(!RHS.get()->EvaluateAsInt(KnownVal, Context) ||
KnownVal.Val.getInt() != 0))) {
diagnoseArithmeticOnNullPointer(*this, Loc, LHS.get(), false);
}
}
if (!checkArithmeticOpPointerOperand(*this, Loc, LHS.get()))
return QualType();
// Check array bounds for pointer arithemtic
CheckArrayAccess(LHS.get(), RHS.get(), /*ArraySubscriptExpr*/nullptr,
/*AllowOnePastEnd*/true, /*IndexNegated*/true);
if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
return LHS.get()->getType();
}
// Handle pointer-pointer subtractions.
if (const PointerType *RHSPTy
= RHS.get()->getType()->getAs<PointerType>()) {
QualType rpointee = RHSPTy->getPointeeType();
if (getLangOpts().CPlusPlus) {
// Pointee types must be the same: C++ [expr.add]
if (!Context.hasSameUnqualifiedType(lpointee, rpointee)) {
diagnosePointerIncompatibility(*this, Loc, LHS.get(), RHS.get());
}
} else {
// Pointee types must be compatible C99 6.5.6p3
if (!Context.typesAreCompatible(
Context.getCanonicalType(lpointee).getUnqualifiedType(),
Context.getCanonicalType(rpointee).getUnqualifiedType())) {
diagnosePointerIncompatibility(*this, Loc, LHS.get(), RHS.get());
return QualType();
}
}
if (!checkArithmeticBinOpPointerOperands(*this, Loc,
LHS.get(), RHS.get()))
return QualType();
// FIXME: Add warnings for nullptr - ptr.
// The pointee type may have zero size. As an extension, a structure or
// union may have zero size or an array may have zero length. In this
// case subtraction does not make sense.
if (!rpointee->isVoidType() && !rpointee->isFunctionType()) {
CharUnits ElementSize = Context.getTypeSizeInChars(rpointee);
if (ElementSize.isZero()) {
Diag(Loc,diag::warn_sub_ptr_zero_size_types)
<< rpointee.getUnqualifiedType()
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
}
if (CompLHSTy) *CompLHSTy = LHS.get()->getType();
return Context.getPointerDiffType();
}
}
return InvalidOperands(Loc, LHS, RHS);
}
static bool isScopedEnumerationType(QualType T) {
if (const EnumType *ET = T->getAs<EnumType>())
return ET->getDecl()->isScoped();
return false;
}
static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, BinaryOperatorKind Opc,
QualType LHSType) {
// OpenCL 6.3j: shift values are effectively % word size of LHS (more defined),
// so skip remaining warnings as we don't want to modify values within Sema.
if (S.getLangOpts().OpenCL)
return;
// Check right/shifter operand
Expr::EvalResult RHSResult;
if (RHS.get()->isValueDependent() ||
!RHS.get()->EvaluateAsInt(RHSResult, S.Context))
return;
llvm::APSInt Right = RHSResult.Val.getInt();
if (Right.isNegative()) {
S.DiagRuntimeBehavior(Loc, RHS.get(),
S.PDiag(diag::warn_shift_negative)
<< RHS.get()->getSourceRange());
return;
}
llvm::APInt LeftBits(Right.getBitWidth(),
S.Context.getTypeSize(LHS.get()->getType()));
if (Right.uge(LeftBits)) {
S.DiagRuntimeBehavior(Loc, RHS.get(),
S.PDiag(diag::warn_shift_gt_typewidth)
<< RHS.get()->getSourceRange());
return;
}
if (Opc != BO_Shl)
return;
// When left shifting an ICE which is signed, we can check for overflow which
// according to C++ has undefined behavior ([expr.shift] 5.8/2). Unsigned
// integers have defined behavior modulo one more than the maximum value
// representable in the result type, so never warn for those.
Expr::EvalResult LHSResult;
if (LHS.get()->isValueDependent() ||
LHSType->hasUnsignedIntegerRepresentation() ||
!LHS.get()->EvaluateAsInt(LHSResult, S.Context))
return;
llvm::APSInt Left = LHSResult.Val.getInt();
// If LHS does not have a signed type and non-negative value
// then, the behavior is undefined. Warn about it.
if (Left.isNegative() && !S.getLangOpts().isSignedOverflowDefined()) {
S.DiagRuntimeBehavior(Loc, LHS.get(),
S.PDiag(diag::warn_shift_lhs_negative)
<< LHS.get()->getSourceRange());
return;
}
llvm::APInt ResultBits =
static_cast<llvm::APInt&>(Right) + Left.getMinSignedBits();
if (LeftBits.uge(ResultBits))
return;
llvm::APSInt Result = Left.extend(ResultBits.getLimitedValue());
Result = Result.shl(Right);
// Print the bit representation of the signed integer as an unsigned
// hexadecimal number.
SmallString<40> HexResult;
Result.toString(HexResult, 16, /*Signed =*/false, /*Literal =*/true);
// If we are only missing a sign bit, this is less likely to result in actual
// bugs -- if the result is cast back to an unsigned type, it will have the
// expected value. Thus we place this behind a different warning that can be
// turned off separately if needed.
if (LeftBits == ResultBits - 1) {
S.Diag(Loc, diag::warn_shift_result_sets_sign_bit)
<< HexResult << LHSType
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return;
}
S.Diag(Loc, diag::warn_shift_result_gt_typewidth)
<< HexResult.str() << Result.getMinSignedBits() << LHSType
<< Left.getBitWidth() << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
}
/// Return the resulting type when a vector is shifted
/// by a scalar or vector shift amount.
static QualType checkVectorShift(Sema &S, ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, bool IsCompAssign) {
// OpenCL v1.1 s6.3.j says RHS can be a vector only if LHS is a vector.
if ((S.LangOpts.OpenCL || S.LangOpts.ZVector) &&
!LHS.get()->getType()->isVectorType()) {
S.Diag(Loc, diag::err_shift_rhs_only_vector)
<< RHS.get()->getType() << LHS.get()->getType()
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
if (!IsCompAssign) {
LHS = S.UsualUnaryConversions(LHS.get());
if (LHS.isInvalid()) return QualType();
}
RHS = S.UsualUnaryConversions(RHS.get());
if (RHS.isInvalid()) return QualType();
QualType LHSType = LHS.get()->getType();
// Note that LHS might be a scalar because the routine calls not only in
// OpenCL case.
const VectorType *LHSVecTy = LHSType->getAs<VectorType>();
QualType LHSEleType = LHSVecTy ? LHSVecTy->getElementType() : LHSType;
// Note that RHS might not be a vector.
QualType RHSType = RHS.get()->getType();
const VectorType *RHSVecTy = RHSType->getAs<VectorType>();
QualType RHSEleType = RHSVecTy ? RHSVecTy->getElementType() : RHSType;
// The operands need to be integers.
if (!LHSEleType->isIntegerType()) {
S.Diag(Loc, diag::err_typecheck_expect_int)
<< LHS.get()->getType() << LHS.get()->getSourceRange();
return QualType();
}
if (!RHSEleType->isIntegerType()) {
S.Diag(Loc, diag::err_typecheck_expect_int)
<< RHS.get()->getType() << RHS.get()->getSourceRange();
return QualType();
}
if (!LHSVecTy) {
assert(RHSVecTy);
if (IsCompAssign)
return RHSType;
if (LHSEleType != RHSEleType) {
LHS = S.ImpCastExprToType(LHS.get(),RHSEleType, CK_IntegralCast);
LHSEleType = RHSEleType;
}
QualType VecTy =
S.Context.getExtVectorType(LHSEleType, RHSVecTy->getNumElements());
LHS = S.ImpCastExprToType(LHS.get(), VecTy, CK_VectorSplat);
LHSType = VecTy;
} else if (RHSVecTy) {
// OpenCL v1.1 s6.3.j says that for vector types, the operators
// are applied component-wise. So if RHS is a vector, then ensure
// that the number of elements is the same as LHS...
if (RHSVecTy->getNumElements() != LHSVecTy->getNumElements()) {
S.Diag(Loc, diag::err_typecheck_vector_lengths_not_equal)
<< LHS.get()->getType() << RHS.get()->getType()
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
return QualType();
}
if (!S.LangOpts.OpenCL && !S.LangOpts.ZVector) {
const BuiltinType *LHSBT = LHSEleType->getAs<clang::BuiltinType>();
const BuiltinType *RHSBT = RHSEleType->getAs<clang::BuiltinType>();
if (LHSBT != RHSBT &&
S.Context.getTypeSize(LHSBT) != S.Context.getTypeSize(RHSBT)) {
S.Diag(Loc, diag::warn_typecheck_vector_element_sizes_not_equal)
<< LHS.get()->getType() << RHS.get()->getType()
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
}
} else {
// ...else expand RHS to match the number of elements in LHS.
QualType VecTy =
S.Context.getExtVectorType(RHSEleType, LHSVecTy->getNumElements());
RHS = S.ImpCastExprToType(RHS.get(), VecTy, CK_VectorSplat);
}
return LHSType;
}
// C99 6.5.7
QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc, BinaryOperatorKind Opc,
bool IsCompAssign) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
// Vector shifts promote their scalar inputs to vector type.
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType()) {
if (LangOpts.ZVector) {
// The shift operators for the z vector extensions work basically
// like general shifts, except that neither the LHS nor the RHS is
// allowed to be a "vector bool".
if (auto LHSVecType = LHS.get()->getType()->getAs<VectorType>())
if (LHSVecType->getVectorKind() == VectorType::AltiVecBool)
return InvalidOperands(Loc, LHS, RHS);
if (auto RHSVecType = RHS.get()->getType()->getAs<VectorType>())
if (RHSVecType->getVectorKind() == VectorType::AltiVecBool)
return InvalidOperands(Loc, LHS, RHS);
}
return checkVectorShift(*this, LHS, RHS, Loc, IsCompAssign);
}
// Shifts don't perform usual arithmetic conversions, they just do integer
// promotions on each operand. C99 6.5.7p3
// For the LHS, do usual unary conversions, but then reset them away
// if this is a compound assignment.
ExprResult OldLHS = LHS;
LHS = UsualUnaryConversions(LHS.get());
if (LHS.isInvalid())
return QualType();
QualType LHSType = LHS.get()->getType();
if (IsCompAssign) LHS = OldLHS;
// The RHS is simpler.
RHS = UsualUnaryConversions(RHS.get());
if (RHS.isInvalid())
return QualType();
QualType RHSType = RHS.get()->getType();
// C99 6.5.7p2: Each of the operands shall have integer type.
if (!LHSType->hasIntegerRepresentation() ||
!RHSType->hasIntegerRepresentation())
return InvalidOperands(Loc, LHS, RHS);
// C++0x: Don't allow scoped enums. FIXME: Use something better than
// hasIntegerRepresentation() above instead of this.
if (isScopedEnumerationType(LHSType) ||
isScopedEnumerationType(RHSType)) {
return InvalidOperands(Loc, LHS, RHS);
}
// Sanity-check shift operands
DiagnoseBadShiftValues(*this, LHS, RHS, Loc, Opc, LHSType);
// "The type of the result is that of the promoted left operand."
return LHSType;
}
/// If two different enums are compared, raise a warning.
static void checkEnumComparison(Sema &S, SourceLocation Loc, Expr *LHS,
Expr *RHS) {
QualType LHSStrippedType = LHS->IgnoreParenImpCasts()->getType();
QualType RHSStrippedType = RHS->IgnoreParenImpCasts()->getType();
const EnumType *LHSEnumType = LHSStrippedType->getAs<EnumType>();
if (!LHSEnumType)
return;
const EnumType *RHSEnumType = RHSStrippedType->getAs<EnumType>();
if (!RHSEnumType)
return;
// Ignore anonymous enums.
if (!LHSEnumType->getDecl()->getIdentifier() &&
!LHSEnumType->getDecl()->getTypedefNameForAnonDecl())
return;
if (!RHSEnumType->getDecl()->getIdentifier() &&
!RHSEnumType->getDecl()->getTypedefNameForAnonDecl())
return;
if (S.Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType))
return;
S.Diag(Loc, diag::warn_comparison_of_mixed_enum_types)
<< LHSStrippedType << RHSStrippedType
<< LHS->getSourceRange() << RHS->getSourceRange();
}
/// Diagnose bad pointer comparisons.
static void diagnoseDistinctPointerComparison(Sema &S, SourceLocation Loc,
ExprResult &LHS, ExprResult &RHS,
bool IsError) {
S.Diag(Loc, IsError ? diag::err_typecheck_comparison_of_distinct_pointers
: diag::ext_typecheck_comparison_of_distinct_pointers)
<< LHS.get()->getType() << RHS.get()->getType()
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
/// Returns false if the pointers are converted to a composite type,
/// true otherwise.
static bool convertPointersToCompositeType(Sema &S, SourceLocation Loc,
ExprResult &LHS, ExprResult &RHS) {
// C++ [expr.rel]p2:
// [...] Pointer conversions (4.10) and qualification
// conversions (4.4) are performed on pointer operands (or on
// a pointer operand and a null pointer constant) to bring
// them to their composite pointer type. [...]
//
// C++ [expr.eq]p1 uses the same notion for (in)equality
// comparisons of pointers.
QualType LHSType = LHS.get()->getType();
QualType RHSType = RHS.get()->getType();
assert(LHSType->isPointerType() || RHSType->isPointerType() ||
LHSType->isMemberPointerType() || RHSType->isMemberPointerType());
QualType T = S.FindCompositePointerType(Loc, LHS, RHS);
if (T.isNull()) {
if ((LHSType->isPointerType() || LHSType->isMemberPointerType()) &&
(RHSType->isPointerType() || RHSType->isMemberPointerType()))
diagnoseDistinctPointerComparison(S, Loc, LHS, RHS, /*isError*/true);
else
S.InvalidOperands(Loc, LHS, RHS);
return true;
}
LHS = S.ImpCastExprToType(LHS.get(), T, CK_BitCast);
RHS = S.ImpCastExprToType(RHS.get(), T, CK_BitCast);
return false;
}
static void diagnoseFunctionPointerToVoidComparison(Sema &S, SourceLocation Loc,
ExprResult &LHS,
ExprResult &RHS,
bool IsError) {
S.Diag(Loc, IsError ? diag::err_typecheck_comparison_of_fptr_to_void
: diag::ext_typecheck_comparison_of_fptr_to_void)
<< LHS.get()->getType() << RHS.get()->getType()
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
static bool isObjCObjectLiteral(ExprResult &E) {
switch (E.get()->IgnoreParenImpCasts()->getStmtClass()) {
case Stmt::ObjCArrayLiteralClass:
case Stmt::ObjCDictionaryLiteralClass:
case Stmt::ObjCStringLiteralClass:
case Stmt::ObjCBoxedExprClass:
return true;
default:
// Note that ObjCBoolLiteral is NOT an object literal!
return false;
}
}
static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) {
const ObjCObjectPointerType *Type =
LHS->getType()->getAs<ObjCObjectPointerType>();
// If this is not actually an Objective-C object, bail out.
if (!Type)
return false;
// Get the LHS object's interface type.
QualType InterfaceType = Type->getPointeeType();
// If the RHS isn't an Objective-C object, bail out.
if (!RHS->getType()->isObjCObjectPointerType())
return false;
// Try to find the -isEqual: method.
Selector IsEqualSel = S.NSAPIObj->getIsEqualSelector();
ObjCMethodDecl *Method = S.LookupMethodInObjectType(IsEqualSel,
InterfaceType,
/*instance=*/true);
if (!Method) {
if (Type->isObjCIdType()) {
// For 'id', just check the global pool.
Method = S.LookupInstanceMethodInGlobalPool(IsEqualSel, SourceRange(),
/*receiverId=*/true);
} else {
// Check protocols.
Method = S.LookupMethodInQualifiedType(IsEqualSel, Type,
/*instance=*/true);
}
}
if (!Method)
return false;
QualType T = Method->parameters()[0]->getType();
if (!T->isObjCObjectPointerType())
return false;
QualType R = Method->getReturnType();
if (!R->isScalarType())
return false;
return true;
}
Sema::ObjCLiteralKind Sema::CheckLiteralKind(Expr *FromE) {
FromE = FromE->IgnoreParenImpCasts();
switch (FromE->getStmtClass()) {
default:
break;
case Stmt::ObjCStringLiteralClass:
// "string literal"
return LK_String;
case Stmt::ObjCArrayLiteralClass:
// "array literal"
return LK_Array;
case Stmt::ObjCDictionaryLiteralClass:
// "dictionary literal"
return LK_Dictionary;
case Stmt::BlockExprClass:
return LK_Block;
case Stmt::ObjCBoxedExprClass: {
Expr *Inner = cast<ObjCBoxedExpr>(FromE)->getSubExpr()->IgnoreParens();
switch (Inner->getStmtClass()) {
case Stmt::IntegerLiteralClass:
case Stmt::FloatingLiteralClass:
case Stmt::CharacterLiteralClass:
case Stmt::ObjCBoolLiteralExprClass:
case Stmt::CXXBoolLiteralExprClass:
// "numeric literal"
return LK_Numeric;
case Stmt::ImplicitCastExprClass: {
CastKind CK = cast<CastExpr>(Inner)->getCastKind();
// Boolean literals can be represented by implicit casts.
if (CK == CK_IntegralToBoolean || CK == CK_IntegralCast)
return LK_Numeric;
break;
}
default:
break;
}
return LK_Boxed;
}
}
return LK_None;
}
static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc,
ExprResult &LHS, ExprResult &RHS,
BinaryOperator::Opcode Opc){
Expr *Literal;
Expr *Other;
if (isObjCObjectLiteral(LHS)) {
Literal = LHS.get();
Other = RHS.get();
} else {
Literal = RHS.get();
Other = LHS.get();
}
// Don't warn on comparisons against nil.
Other = Other->IgnoreParenCasts();
if (Other->isNullPointerConstant(S.getASTContext(),
Expr::NPC_ValueDependentIsNotNull))
return;
// This should be kept in sync with warn_objc_literal_comparison.
// LK_String should always be after the other literals, since it has its own
// warning flag.
Sema::ObjCLiteralKind LiteralKind = S.CheckLiteralKind(Literal);
assert(LiteralKind != Sema::LK_Block);
if (LiteralKind == Sema::LK_None) {
llvm_unreachable("Unknown Objective-C object literal kind");
}
if (LiteralKind == Sema::LK_String)
S.Diag(Loc, diag::warn_objc_string_literal_comparison)
<< Literal->getSourceRange();
else
S.Diag(Loc, diag::warn_objc_literal_comparison)
<< LiteralKind << Literal->getSourceRange();
if (BinaryOperator::isEqualityOp(Opc) &&
hasIsEqualMethod(S, LHS.get(), RHS.get())) {
SourceLocation Start = LHS.get()->getBeginLoc();
SourceLocation End = S.getLocForEndOfToken(RHS.get()->getEndLoc());
CharSourceRange OpRange =
CharSourceRange::getCharRange(Loc, S.getLocForEndOfToken(Loc));
S.Diag(Loc, diag::note_objc_literal_comparison_isequal)
<< FixItHint::CreateInsertion(Start, Opc == BO_EQ ? "[" : "![")
<< FixItHint::CreateReplacement(OpRange, " isEqual:")
<< FixItHint::CreateInsertion(End, "]");
}
}
/// Warns on !x < y, !x & y where !(x < y), !(x & y) was probably intended.
static void diagnoseLogicalNotOnLHSofCheck(Sema &S, ExprResult &LHS,
ExprResult &RHS, SourceLocation Loc,
BinaryOperatorKind Opc) {
// Check that left hand side is !something.
UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS.get()->IgnoreImpCasts());
if (!UO || UO->getOpcode() != UO_LNot) return;
// Only check if the right hand side is non-bool arithmetic type.
if (RHS.get()->isKnownToHaveBooleanValue()) return;
// Make sure that the something in !something is not bool.
Expr *SubExpr = UO->getSubExpr()->IgnoreImpCasts();
if (SubExpr->isKnownToHaveBooleanValue()) return;
// Emit warning.
bool IsBitwiseOp = Opc == BO_And || Opc == BO_Or || Opc == BO_Xor;
S.Diag(UO->getOperatorLoc(), diag::warn_logical_not_on_lhs_of_check)
<< Loc << IsBitwiseOp;
// First note suggest !(x < y)
SourceLocation FirstOpen = SubExpr->getBeginLoc();
SourceLocation FirstClose = RHS.get()->getEndLoc();
FirstClose = S.getLocForEndOfToken(FirstClose);
if (FirstClose.isInvalid())
FirstOpen = SourceLocation();
S.Diag(UO->getOperatorLoc(), diag::note_logical_not_fix)
<< IsBitwiseOp
<< FixItHint::CreateInsertion(FirstOpen, "(")
<< FixItHint::CreateInsertion(FirstClose, ")");
// Second note suggests (!x) < y
SourceLocation SecondOpen = LHS.get()->getBeginLoc();
SourceLocation SecondClose = LHS.get()->getEndLoc();
SecondClose = S.getLocForEndOfToken(SecondClose);
if (SecondClose.isInvalid())
SecondOpen = SourceLocation();
S.Diag(UO->getOperatorLoc(), diag::note_logical_not_silence_with_parens)
<< FixItHint::CreateInsertion(SecondOpen, "(")
<< FixItHint::CreateInsertion(SecondClose, ")");
}
// Get the decl for a simple expression: a reference to a variable,
// an implicit C++ field reference, or an implicit ObjC ivar reference.
static ValueDecl *getCompareDecl(Expr *E) {
if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E))
return DR->getDecl();
if (ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E)) {
if (Ivar->isFreeIvar())
return Ivar->getDecl();
}
if (MemberExpr *Mem = dyn_cast<MemberExpr>(E)) {
if (Mem->isImplicitAccess())
return Mem->getMemberDecl();
}
return nullptr;
}
/// Diagnose some forms of syntactically-obvious tautological comparison.
static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc,
Expr *LHS, Expr *RHS,
BinaryOperatorKind Opc) {
Expr *LHSStripped = LHS->IgnoreParenImpCasts();
Expr *RHSStripped = RHS->IgnoreParenImpCasts();
QualType LHSType = LHS->getType();
QualType RHSType = RHS->getType();
if (LHSType->hasFloatingRepresentation() ||
(LHSType->isBlockPointerType() && !BinaryOperator::isEqualityOp(Opc)) ||
LHS->getBeginLoc().isMacroID() || RHS->getBeginLoc().isMacroID() ||
S.inTemplateInstantiation())
return;
// Comparisons between two array types are ill-formed for operator<=>, so
// we shouldn't emit any additional warnings about it.
if (Opc == BO_Cmp && LHSType->isArrayType() && RHSType->isArrayType())
return;
// For non-floating point types, check for self-comparisons of the form
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
// often indicate logic errors in the program.
//
// NOTE: Don't warn about comparison expressions resulting from macro
// expansion. Also don't warn about comparisons which are only self
// comparisons within a template instantiation. The warnings should catch
// obvious cases in the definition of the template anyways. The idea is to
// warn when the typed comparison operator will always evaluate to the same
// result.
ValueDecl *DL = getCompareDecl(LHSStripped);
ValueDecl *DR = getCompareDecl(RHSStripped);
if (DL && DR && declaresSameEntity(DL, DR)) {
StringRef Result;
switch (Opc) {
case BO_EQ: case BO_LE: case BO_GE:
Result = "true";
break;
case BO_NE: case BO_LT: case BO_GT:
Result = "false";
break;
case BO_Cmp:
Result = "'std::strong_ordering::equal'";
break;
default:
break;
}
S.DiagRuntimeBehavior(Loc, nullptr,
S.PDiag(diag::warn_comparison_always)
<< 0 /*self-comparison*/ << !Result.empty()
<< Result);
} else if (DL && DR &&
DL->getType()->isArrayType() && DR->getType()->isArrayType() &&
!DL->isWeak() && !DR->isWeak()) {
// What is it always going to evaluate to?
StringRef Result;
switch(Opc) {
case BO_EQ: // e.g. array1 == array2
Result = "false";
break;
case BO_NE: // e.g. array1 != array2
Result = "true";
break;
default: // e.g. array1 <= array2
// The best we can say is 'a constant'
break;
}
S.DiagRuntimeBehavior(Loc, nullptr,
S.PDiag(diag::warn_comparison_always)
<< 1 /*array comparison*/
<< !Result.empty() << Result);
}
if (isa<CastExpr>(LHSStripped))
LHSStripped = LHSStripped->IgnoreParenCasts();
if (isa<CastExpr>(RHSStripped))
RHSStripped = RHSStripped->IgnoreParenCasts();
// Warn about comparisons against a string constant (unless the other
// operand is null); the user probably wants strcmp.
Expr *LiteralString = nullptr;
Expr *LiteralStringStripped = nullptr;
if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) &&
!RHSStripped->isNullPointerConstant(S.Context,
Expr::NPC_ValueDependentIsNull)) {
LiteralString = LHS;
LiteralStringStripped = LHSStripped;
} else if ((isa<StringLiteral>(RHSStripped) ||
isa<ObjCEncodeExpr>(RHSStripped)) &&
!LHSStripped->isNullPointerConstant(S.Context,
Expr::NPC_ValueDependentIsNull)) {
LiteralString = RHS;
LiteralStringStripped = RHSStripped;
}
if (LiteralString) {
S.DiagRuntimeBehavior(Loc, nullptr,
S.PDiag(diag::warn_stringcompare)
<< isa<ObjCEncodeExpr>(LiteralStringStripped)
<< LiteralString->getSourceRange());
}
}
static ImplicitConversionKind castKindToImplicitConversionKind(CastKind CK) {
switch (CK) {
default: {
#ifndef NDEBUG
llvm::errs() << "unhandled cast kind: " << CastExpr::getCastKindName(CK)
<< "\n";
#endif
llvm_unreachable("unhandled cast kind");
}
case CK_UserDefinedConversion:
return ICK_Identity;
case CK_LValueToRValue:
return ICK_Lvalue_To_Rvalue;
case CK_ArrayToPointerDecay:
return ICK_Array_To_Pointer;
case CK_FunctionToPointerDecay:
return ICK_Function_To_Pointer;
case CK_IntegralCast:
return ICK_Integral_Conversion;
case CK_FloatingCast:
return ICK_Floating_Conversion;
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
return ICK_Floating_Integral;
case CK_IntegralComplexCast:
case CK_FloatingComplexCast:
case CK_FloatingComplexToIntegralComplex:
case CK_IntegralComplexToFloatingComplex:
return ICK_Complex_Conversion;
case CK_FloatingComplexToReal:
case CK_FloatingRealToComplex:
case CK_IntegralComplexToReal:
case CK_IntegralRealToComplex:
return ICK_Complex_Real;
}
}
static bool checkThreeWayNarrowingConversion(Sema &S, QualType ToType, Expr *E,
QualType FromType,
SourceLocation Loc) {
// Check for a narrowing implicit conversion.
StandardConversionSequence SCS;
SCS.setAsIdentityConversion();
SCS.setToType(0, FromType);
SCS.setToType(1, ToType);
if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
SCS.Second = castKindToImplicitConversionKind(ICE->getCastKind());
APValue PreNarrowingValue;
QualType PreNarrowingType;
switch (SCS.getNarrowingKind(S.Context, E, PreNarrowingValue,
PreNarrowingType,
/*IgnoreFloatToIntegralConversion*/ true)) {
case NK_Dependent_Narrowing:
// Implicit conversion to a narrower type, but the expression is
// value-dependent so we can't tell whether it's actually narrowing.
case NK_Not_Narrowing:
return false;
case NK_Constant_Narrowing:
// Implicit conversion to a narrower type, and the value is not a constant
// expression.
S.Diag(E->getBeginLoc(), diag::err_spaceship_argument_narrowing)
<< /*Constant*/ 1
<< PreNarrowingValue.getAsString(S.Context, PreNarrowingType) << ToType;
return true;
case NK_Variable_Narrowing:
// Implicit conversion to a narrower type, and the value is not a constant
// expression.
case NK_Type_Narrowing:
S.Diag(E->getBeginLoc(), diag::err_spaceship_argument_narrowing)
<< /*Constant*/ 0 << FromType << ToType;
// TODO: It's not a constant expression, but what if the user intended it
// to be? Can we produce notes to help them figure out why it isn't?
return true;
}
llvm_unreachable("unhandled case in switch");
}
static QualType checkArithmeticOrEnumeralThreeWayCompare(Sema &S,
ExprResult &LHS,
ExprResult &RHS,
SourceLocation Loc) {
using CCT = ComparisonCategoryType;
QualType LHSType = LHS.get()->getType();
QualType RHSType = RHS.get()->getType();
// Dig out the original argument type and expression before implicit casts
// were applied. These are the types/expressions we need to check the
// [expr.spaceship] requirements against.
ExprResult LHSStripped = LHS.get()->IgnoreParenImpCasts();
ExprResult RHSStripped = RHS.get()->IgnoreParenImpCasts();
QualType LHSStrippedType = LHSStripped.get()->getType();
QualType RHSStrippedType = RHSStripped.get()->getType();
// C++2a [expr.spaceship]p3: If one of the operands is of type bool and the
// other is not, the program is ill-formed.
if (LHSStrippedType->isBooleanType() != RHSStrippedType->isBooleanType()) {
S.InvalidOperands(Loc, LHSStripped, RHSStripped);
return QualType();
}
int NumEnumArgs = (int)LHSStrippedType->isEnumeralType() +
RHSStrippedType->isEnumeralType();
if (NumEnumArgs == 1) {
bool LHSIsEnum = LHSStrippedType->isEnumeralType();
QualType OtherTy = LHSIsEnum ? RHSStrippedType : LHSStrippedType;
if (OtherTy->hasFloatingRepresentation()) {
S.InvalidOperands(Loc, LHSStripped, RHSStripped);
return QualType();
}
}
if (NumEnumArgs == 2) {
// C++2a [expr.spaceship]p5: If both operands have the same enumeration
// type E, the operator yields the result of converting the operands
// to the underlying type of E and applying <=> to the converted operands.
if (!S.Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType)) {
S.InvalidOperands(Loc, LHS, RHS);
return QualType();
}
QualType IntType =
LHSStrippedType->getAs<EnumType>()->getDecl()->getIntegerType();
assert(IntType->isArithmeticType());
// We can't use `CK_IntegralCast` when the underlying type is 'bool', so we
// promote the boolean type, and all other promotable integer types, to
// avoid this.
if (IntType->isPromotableIntegerType())
IntType = S.Context.getPromotedIntegerType(IntType);
LHS = S.ImpCastExprToType(LHS.get(), IntType, CK_IntegralCast);
RHS = S.ImpCastExprToType(RHS.get(), IntType, CK_IntegralCast);
LHSType = RHSType = IntType;
}
// C++2a [expr.spaceship]p4: If both operands have arithmetic types, the
// usual arithmetic conversions are applied to the operands.
QualType Type = S.UsualArithmeticConversions(LHS, RHS);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
if (Type.isNull())
return S.InvalidOperands(Loc, LHS, RHS);
assert(Type->isArithmeticType() || Type->isEnumeralType());
bool HasNarrowing = checkThreeWayNarrowingConversion(
S, Type, LHS.get(), LHSType, LHS.get()->getBeginLoc());
HasNarrowing |= checkThreeWayNarrowingConversion(S, Type, RHS.get(), RHSType,
RHS.get()->getBeginLoc());
if (HasNarrowing)
return QualType();
assert(!Type.isNull() && "composite type for <=> has not been set");
auto TypeKind = [&]() {
if (const ComplexType *CT = Type->getAs<ComplexType>()) {
if (CT->getElementType()->hasFloatingRepresentation())
return CCT::WeakEquality;
return CCT::StrongEquality;
}
if (Type->isIntegralOrEnumerationType())
return CCT::StrongOrdering;
if (Type->hasFloatingRepresentation())
return CCT::PartialOrdering;
llvm_unreachable("other types are unimplemented");
}();
return S.CheckComparisonCategoryType(TypeKind, Loc);
}
static QualType checkArithmeticOrEnumeralCompare(Sema &S, ExprResult &LHS,
ExprResult &RHS,
SourceLocation Loc,
BinaryOperatorKind Opc) {
if (Opc == BO_Cmp)
return checkArithmeticOrEnumeralThreeWayCompare(S, LHS, RHS, Loc);
// C99 6.5.8p3 / C99 6.5.9p4
QualType Type = S.UsualArithmeticConversions(LHS, RHS);
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
if (Type.isNull())
return S.InvalidOperands(Loc, LHS, RHS);
assert(Type->isArithmeticType() || Type->isEnumeralType());
checkEnumComparison(S, Loc, LHS.get(), RHS.get());
if (Type->isAnyComplexType() && BinaryOperator::isRelationalOp(Opc))
return S.InvalidOperands(Loc, LHS, RHS);
// Check for comparisons of floating point operands using != and ==.
if (Type->hasFloatingRepresentation() && BinaryOperator::isEqualityOp(Opc))
S.CheckFloatComparison(Loc, LHS.get(), RHS.get());
// The result of comparisons is 'bool' in C++, 'int' in C.
return S.Context.getLogicalOperationType();
}
// C99 6.5.8, C++ [expr.rel]
QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
BinaryOperatorKind Opc) {
bool IsRelational = BinaryOperator::isRelationalOp(Opc);
bool IsThreeWay = Opc == BO_Cmp;
auto IsAnyPointerType = [](ExprResult E) {
QualType Ty = E.get()->getType();
return Ty->isPointerType() || Ty->isMemberPointerType();
};
// C++2a [expr.spaceship]p6: If at least one of the operands is of pointer
// type, array-to-pointer, ..., conversions are performed on both operands to
// bring them to their composite type.
// Otherwise, all comparisons expect an rvalue, so convert to rvalue before
// any type-related checks.
if (!IsThreeWay || IsAnyPointerType(LHS) || IsAnyPointerType(RHS)) {
LHS = DefaultFunctionArrayLvalueConversion(LHS.get());
if (LHS.isInvalid())
return QualType();
RHS = DefaultFunctionArrayLvalueConversion(RHS.get());
if (RHS.isInvalid())
return QualType();
} else {
LHS = DefaultLvalueConversion(LHS.get());
if (LHS.isInvalid())
return QualType();
RHS = DefaultLvalueConversion(RHS.get());
if (RHS.isInvalid())
return QualType();
}
checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/true);
// Handle vector comparisons separately.
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType())
return CheckVectorCompareOperands(LHS, RHS, Loc, Opc);
diagnoseLogicalNotOnLHSofCheck(*this, LHS, RHS, Loc, Opc);
diagnoseTautologicalComparison(*this, Loc, LHS.get(), RHS.get(), Opc);
QualType LHSType = LHS.get()->getType();
QualType RHSType = RHS.get()->getType();
if ((LHSType->isArithmeticType() || LHSType->isEnumeralType()) &&
(RHSType->isArithmeticType() || RHSType->isEnumeralType()))
return checkArithmeticOrEnumeralCompare(*this, LHS, RHS, Loc, Opc);
const Expr::NullPointerConstantKind LHSNullKind =
LHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull);
const Expr::NullPointerConstantKind RHSNullKind =
RHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull);
bool LHSIsNull = LHSNullKind != Expr::NPCK_NotNull;
bool RHSIsNull = RHSNullKind != Expr::NPCK_NotNull;
auto computeResultTy = [&]() {
if (Opc != BO_Cmp)
return Context.getLogicalOperationType();
assert(getLangOpts().CPlusPlus);
assert(Context.hasSameType(LHS.get()->getType(), RHS.get()->getType()));
QualType CompositeTy = LHS.get()->getType();
assert(!CompositeTy->isReferenceType());
auto buildResultTy = [&](ComparisonCategoryType Kind) {
return CheckComparisonCategoryType(Kind, Loc);
};
// C++2a [expr.spaceship]p7: If the composite pointer type is a function
// pointer type, a pointer-to-member type, or std::nullptr_t, the
// result is of type std::strong_equality
if (CompositeTy->isFunctionPointerType() ||
CompositeTy->isMemberPointerType() || CompositeTy->isNullPtrType())
// FIXME: consider making the function pointer case produce
// strong_ordering not strong_equality, per P0946R0-Jax18 discussion
// and direction polls
return buildResultTy(ComparisonCategoryType::StrongEquality);
// C++2a [expr.spaceship]p8: If the composite pointer type is an object
// pointer type, p <=> q is of type std::strong_ordering.
if (CompositeTy->isPointerType()) {
// P0946R0: Comparisons between a null pointer constant and an object
// pointer result in std::strong_equality
if (LHSIsNull != RHSIsNull)
return buildResultTy(ComparisonCategoryType::StrongEquality);
return buildResultTy(ComparisonCategoryType::StrongOrdering);
}
// C++2a [expr.spaceship]p9: Otherwise, the program is ill-formed.
// TODO: Extend support for operator<=> to ObjC types.
return InvalidOperands(Loc, LHS, RHS);
};
if (!IsRelational && LHSIsNull != RHSIsNull) {
bool IsEquality = Opc == BO_EQ;
if (RHSIsNull)
DiagnoseAlwaysNonNullPointer(LHS.get(), RHSNullKind, IsEquality,
RHS.get()->getSourceRange());
else
DiagnoseAlwaysNonNullPointer(RHS.get(), LHSNullKind, IsEquality,
LHS.get()->getSourceRange());
}
if ((LHSType->isIntegerType() && !LHSIsNull) ||
(RHSType->isIntegerType() && !RHSIsNull)) {
// Skip normal pointer conversion checks in this case; we have better
// diagnostics for this below.
} else if (getLangOpts().CPlusPlus) {
// Equality comparison of a function pointer to a void pointer is invalid,
// but we allow it as an extension.
// FIXME: If we really want to allow this, should it be part of composite
// pointer type computation so it works in conditionals too?
if (!IsRelational &&
((LHSType->isFunctionPointerType() && RHSType->isVoidPointerType()) ||
(RHSType->isFunctionPointerType() && LHSType->isVoidPointerType()))) {
// This is a gcc extension compatibility comparison.
// In a SFINAE context, we treat this as a hard error to maintain
// conformance with the C++ standard.
diagnoseFunctionPointerToVoidComparison(
*this, Loc, LHS, RHS, /*isError*/ (bool)isSFINAEContext());
if (isSFINAEContext())
return QualType();
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
return computeResultTy();
}
// C++ [expr.eq]p2:
// If at least one operand is a pointer [...] bring them to their
// composite pointer type.
// C++ [expr.spaceship]p6
// If at least one of the operands is of pointer type, [...] bring them
// to their composite pointer type.
// C++ [expr.rel]p2:
// If both operands are pointers, [...] bring them to their composite
// pointer type.
if ((int)LHSType->isPointerType() + (int)RHSType->isPointerType() >=
(IsRelational ? 2 : 1) &&
(!LangOpts.ObjCAutoRefCount || !(LHSType->isObjCObjectPointerType() ||
RHSType->isObjCObjectPointerType()))) {
if (convertPointersToCompositeType(*this, Loc, LHS, RHS))
return QualType();
return computeResultTy();
}
} else if (LHSType->isPointerType() &&
RHSType->isPointerType()) { // C99 6.5.8p2
// All of the following pointer-related warnings are GCC extensions, except
// when handling null pointer constants.
QualType LCanPointeeTy =
LHSType->castAs<PointerType>()->getPointeeType().getCanonicalType();
QualType RCanPointeeTy =
RHSType->castAs<PointerType>()->getPointeeType().getCanonicalType();
// C99 6.5.9p2 and C99 6.5.8p2
if (Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(),
RCanPointeeTy.getUnqualifiedType())) {
// Valid unless a relational comparison of function pointers
if (IsRelational && LCanPointeeTy->isFunctionType()) {
Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers)
<< LHSType << RHSType << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
}
} else if (!IsRelational &&
(LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) {
// Valid unless comparison between non-null pointer and function pointer
if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType())
&& !LHSIsNull && !RHSIsNull)
diagnoseFunctionPointerToVoidComparison(*this, Loc, LHS, RHS,
/*isError*/false);
} else {
// Invalid
diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS, /*isError*/false);
}
if (LCanPointeeTy != RCanPointeeTy) {
// Treat NULL constant as a special case in OpenCL.
if (getLangOpts().OpenCL && !LHSIsNull && !RHSIsNull) {
const PointerType *LHSPtr = LHSType->getAs<PointerType>();
if (!LHSPtr->isAddressSpaceOverlapping(*RHSType->getAs<PointerType>())) {
Diag(Loc,
diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
<< LHSType << RHSType << 0 /* comparison */
<< LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
}
}
LangAS AddrSpaceL = LCanPointeeTy.getAddressSpace();
LangAS AddrSpaceR = RCanPointeeTy.getAddressSpace();
CastKind Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion
: CK_BitCast;
if (LHSIsNull && !RHSIsNull)
LHS = ImpCastExprToType(LHS.get(), RHSType, Kind);
else
RHS = ImpCastExprToType(RHS.get(), LHSType, Kind);
}
return computeResultTy();
}
if (getLangOpts().CPlusPlus) {
// C++ [expr.eq]p4:
// Two operands of type std::nullptr_t or one operand of type
// std::nullptr_t and the other a null pointer constant compare equal.
if (!IsRelational && LHSIsNull && RHSIsNull) {
if (LHSType->isNullPtrType()) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
return computeResultTy();
}
if (RHSType->isNullPtrType()) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
return computeResultTy();
}
}
// Comparison of Objective-C pointers and block pointers against nullptr_t.
// These aren't covered by the composite pointer type rules.
if (!IsRelational && RHSType->isNullPtrType() &&
(LHSType->isObjCObjectPointerType() || LHSType->isBlockPointerType())) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
return computeResultTy();
}
if (!IsRelational && LHSType->isNullPtrType() &&
(RHSType->isObjCObjectPointerType() || RHSType->isBlockPointerType())) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
return computeResultTy();
}
if (IsRelational &&
((LHSType->isNullPtrType() && RHSType->isPointerType()) ||
(RHSType->isNullPtrType() && LHSType->isPointerType()))) {
// HACK: Relational comparison of nullptr_t against a pointer type is
// invalid per DR583, but we allow it within std::less<> and friends,
// since otherwise common uses of it break.
// FIXME: Consider removing this hack once LWG fixes std::less<> and
// friends to have std::nullptr_t overload candidates.
DeclContext *DC = CurContext;
if (isa<FunctionDecl>(DC))
DC = DC->getParent();
if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
if (CTSD->isInStdNamespace() &&
llvm::StringSwitch<bool>(CTSD->getName())
.Cases("less", "less_equal", "greater", "greater_equal", true)
.Default(false)) {
if (RHSType->isNullPtrType())
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
else
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
return computeResultTy();
}
}
}
// C++ [expr.eq]p2:
// If at least one operand is a pointer to member, [...] bring them to
// their composite pointer type.
if (!IsRelational &&
(LHSType->isMemberPointerType() || RHSType->isMemberPointerType())) {
if (convertPointersToCompositeType(*this, Loc, LHS, RHS))
return QualType();
else
return computeResultTy();
}
}
// Handle block pointer types.
if (!IsRelational && LHSType->isBlockPointerType() &&
RHSType->isBlockPointerType()) {
QualType lpointee = LHSType->castAs<BlockPointerType>()->getPointeeType();
QualType rpointee = RHSType->castAs<BlockPointerType>()->getPointeeType();
if (!LHSIsNull && !RHSIsNull &&
!Context.typesAreCompatible(lpointee, rpointee)) {
Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
<< LHSType << RHSType << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
}
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
return computeResultTy();
}
// Allow block pointers to be compared with null pointer constants.
if (!IsRelational
&& ((LHSType->isBlockPointerType() && RHSType->isPointerType())
|| (LHSType->isPointerType() && RHSType->isBlockPointerType()))) {
if (!LHSIsNull && !RHSIsNull) {
if (!((RHSType->isPointerType() && RHSType->castAs<PointerType>()
->getPointeeType()->isVoidType())
|| (LHSType->isPointerType() && LHSType->castAs<PointerType>()
->getPointeeType()->isVoidType())))
Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)
<< LHSType << RHSType << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
}
if (LHSIsNull && !RHSIsNull)
LHS = ImpCastExprToType(LHS.get(), RHSType,
RHSType->isPointerType() ? CK_BitCast
: CK_AnyPointerToBlockPointerCast);
else
RHS = ImpCastExprToType(RHS.get(), LHSType,
LHSType->isPointerType() ? CK_BitCast
: CK_AnyPointerToBlockPointerCast);
return computeResultTy();
}
if (LHSType->isObjCObjectPointerType() ||
RHSType->isObjCObjectPointerType()) {
const PointerType *LPT = LHSType->getAs<PointerType>();
const PointerType *RPT = RHSType->getAs<PointerType>();
if (LPT || RPT) {
bool LPtrToVoid = LPT ? LPT->getPointeeType()->isVoidType() : false;
bool RPtrToVoid = RPT ? RPT->getPointeeType()->isVoidType() : false;
if (!LPtrToVoid && !RPtrToVoid &&
!Context.typesAreCompatible(LHSType, RHSType)) {
diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS,
/*isError*/false);
}
if (LHSIsNull && !RHSIsNull) {
Expr *E = LHS.get();
if (getLangOpts().ObjCAutoRefCount)
CheckObjCConversion(SourceRange(), RHSType, E,
CCK_ImplicitConversion);
LHS = ImpCastExprToType(E, RHSType,
RPT ? CK_BitCast :CK_CPointerToObjCPointerCast);
}
else {
Expr *E = RHS.get();
if (getLangOpts().ObjCAutoRefCount)
CheckObjCConversion(SourceRange(), LHSType, E, CCK_ImplicitConversion,
/*Diagnose=*/true,
/*DiagnoseCFAudited=*/false, Opc);
RHS = ImpCastExprToType(E, LHSType,
LPT ? CK_BitCast :CK_CPointerToObjCPointerCast);
}
return computeResultTy();
}
if (LHSType->isObjCObjectPointerType() &&
RHSType->isObjCObjectPointerType()) {
if (!Context.areComparableObjCPointerTypes(LHSType, RHSType))
diagnoseDistinctPointerComparison(*this, Loc, LHS, RHS,
/*isError*/false);
if (isObjCObjectLiteral(LHS) || isObjCObjectLiteral(RHS))
diagnoseObjCLiteralComparison(*this, Loc, LHS, RHS, Opc);
if (LHSIsNull && !RHSIsNull)
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_BitCast);
else
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_BitCast);
return computeResultTy();
}
if (!IsRelational && LHSType->isBlockPointerType() &&
RHSType->isBlockCompatibleObjCPointerType(Context)) {
LHS = ImpCastExprToType(LHS.get(), RHSType,
CK_BlockPointerToObjCPointerCast);
return computeResultTy();
} else if (!IsRelational &&
LHSType->isBlockCompatibleObjCPointerType(Context) &&
RHSType->isBlockPointerType()) {
RHS = ImpCastExprToType(RHS.get(), LHSType,
CK_BlockPointerToObjCPointerCast);
return computeResultTy();
}
}
if ((LHSType->isAnyPointerType() && RHSType->isIntegerType()) ||
(LHSType->isIntegerType() && RHSType->isAnyPointerType())) {
unsigned DiagID = 0;
bool isError = false;
if (LangOpts.DebuggerSupport) {
// Under a debugger, allow the comparison of pointers to integers,
// since users tend to want to compare addresses.
} else if ((LHSIsNull && LHSType->isIntegerType()) ||
(RHSIsNull && RHSType->isIntegerType())) {
if (IsRelational) {
isError = getLangOpts().CPlusPlus;
DiagID =
isError ? diag::err_typecheck_ordered_comparison_of_pointer_and_zero
: diag::ext_typecheck_ordered_comparison_of_pointer_and_zero;
}
} else if (getLangOpts().CPlusPlus) {
DiagID = diag::err_typecheck_comparison_of_pointer_integer;
isError = true;
} else if (IsRelational)
DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer;
else
DiagID = diag::ext_typecheck_comparison_of_pointer_integer;
if (DiagID) {
Diag(Loc, DiagID)
<< LHSType << RHSType << LHS.get()->getSourceRange()
<< RHS.get()->getSourceRange();
if (isError)
return QualType();
}
if (LHSType->isIntegerType())
LHS = ImpCastExprToType(LHS.get(), RHSType,
LHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
else
RHS = ImpCastExprToType(RHS.get(), LHSType,
RHSIsNull ? CK_NullToPointer : CK_IntegralToPointer);
return computeResultTy();
}
// Handle block pointers.
if (!IsRelational && RHSIsNull
&& LHSType->isBlockPointerType() && RHSType->isIntegerType()) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
return computeResultTy();
}
if (!IsRelational && LHSIsNull
&& LHSType->isIntegerType() && RHSType->isBlockPointerType()) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
return computeResultTy();
}
if (getLangOpts().OpenCLVersion >= 200) {
if (LHSType->isClkEventT() && RHSType->isClkEventT()) {
return computeResultTy();
}
if (LHSType->isQueueT() && RHSType->isQueueT()) {
return computeResultTy();
}
if (LHSIsNull && RHSType->isQueueT()) {
LHS = ImpCastExprToType(LHS.get(), RHSType, CK_NullToPointer);
return computeResultTy();
}
if (LHSType->isQueueT() && RHSIsNull) {
RHS = ImpCastExprToType(RHS.get(), LHSType, CK_NullToPointer);
return computeResultTy();
}
}
return InvalidOperands(Loc, LHS, RHS);
}
// Return a signed ext_vector_type that is of identical size and number of
// elements. For floating point vectors, return an integer type of identical
// size and number of elements. In the non ext_vector_type case, search from
// the largest type to the smallest type to avoid cases where long long == long,
// where long gets picked over long long.
QualType Sema::GetSignedVectorType(QualType V) {
const VectorType *VTy = V->getAs<VectorType>();
unsigned TypeSize = Context.getTypeSize(VTy->getElementType());
if (isa<ExtVectorType>(VTy)) {
if (TypeSize == Context.getTypeSize(Context.CharTy))
return Context.getExtVectorType(Context.CharTy, VTy->getNumElements());
else if (TypeSize == Context.getTypeSize(Context.ShortTy))
return Context.getExtVectorType(Context.ShortTy, VTy->getNumElements());
else if (TypeSize == Context.getTypeSize(Context.IntTy))
return Context.getExtVectorType(Context.IntTy, VTy->getNumElements());
else if (TypeSize == Context.getTypeSize(Context.LongTy))
return Context.getExtVectorType(Context.LongTy, VTy->getNumElements());
assert(TypeSize == Context.getTypeSize(Context.LongLongTy) &&
"Unhandled vector element size in vector compare");
return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements());
}
if (TypeSize == Context.getTypeSize(Context.LongLongTy))
return Context.getVectorType(Context.LongLongTy, VTy->getNumElements(),
VectorType::GenericVector);
else if (TypeSize == Context.getTypeSize(Context.LongTy))
return Context.getVectorType(Context.LongTy, VTy->getNumElements(),
VectorType::GenericVector);
else if (TypeSize == Context.getTypeSize(Context.IntTy))
return Context.getVectorType(Context.IntTy, VTy->getNumElements(),
VectorType::GenericVector);
else if (TypeSize == Context.getTypeSize(Context.ShortTy))
return Context.getVectorType(Context.ShortTy, VTy->getNumElements(),
VectorType::GenericVector);
assert(TypeSize == Context.getTypeSize(Context.CharTy) &&
"Unhandled vector element size in vector compare");
return Context.getVectorType(Context.CharTy, VTy->getNumElements(),
VectorType::GenericVector);
}
/// CheckVectorCompareOperands - vector comparisons are a clang extension that
/// operates on extended vector types. Instead of producing an IntTy result,
/// like a scalar comparison, a vector comparison produces a vector of integer
/// types.
QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
BinaryOperatorKind Opc) {
// Check to make sure we're operating on vectors of the same type and width,
// Allowing one side to be a scalar of element type.
QualType vType = CheckVectorOperands(LHS, RHS, Loc, /*isCompAssign*/false,
/*AllowBothBool*/true,
/*AllowBoolConversions*/getLangOpts().ZVector);
if (vType.isNull())
return vType;
QualType LHSType = LHS.get()->getType();
// If AltiVec, the comparison results in a numeric type, i.e.
// bool for C++, int for C
if (getLangOpts().AltiVec &&
vType->getAs<VectorType>()->getVectorKind() == VectorType::AltiVecVector)
return Context.getLogicalOperationType();
// For non-floating point types, check for self-comparisons of the form
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
// often indicate logic errors in the program.
diagnoseTautologicalComparison(*this, Loc, LHS.get(), RHS.get(), Opc);
// Check for comparisons of floating point operands using != and ==.
if (BinaryOperator::isEqualityOp(Opc) &&
LHSType->hasFloatingRepresentation()) {
assert(RHS.get()->getType()->hasFloatingRepresentation());
CheckFloatComparison(Loc, LHS.get(), RHS.get());
}
// Return a signed type for the vector.
return GetSignedVectorType(vType);
}
QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc) {
// Ensure that either both operands are of the same vector type, or
// one operand is of a vector type and the other is of its element type.
QualType vType = CheckVectorOperands(LHS, RHS, Loc, false,
/*AllowBothBool*/true,
/*AllowBoolConversions*/false);
if (vType.isNull())
return InvalidOperands(Loc, LHS, RHS);
if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion < 120 &&
vType->hasFloatingRepresentation())
return InvalidOperands(Loc, LHS, RHS);
// FIXME: The check for C++ here is for GCC compatibility. GCC rejects the
// usage of the logical operators && and || with vectors in C. This
// check could be notionally dropped.
if (!getLangOpts().CPlusPlus &&
!(isa<ExtVectorType>(vType->getAs<VectorType>())))
return InvalidLogicalVectorOperands(Loc, LHS, RHS);
return GetSignedVectorType(LHS.get()->getType());
}
inline QualType Sema::CheckBitwiseOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
BinaryOperatorKind Opc) {
checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false);
bool IsCompAssign =
Opc == BO_AndAssign || Opc == BO_OrAssign || Opc == BO_XorAssign;
if (LHS.get()->getType()->isVectorType() ||
RHS.get()->getType()->isVectorType()) {
if (LHS.get()->getType()->hasIntegerRepresentation() &&
RHS.get()->getType()->hasIntegerRepresentation())
return CheckVectorOperands(LHS, RHS, Loc, IsCompAssign,
/*AllowBothBool*/true,
/*AllowBoolConversions*/getLangOpts().ZVector);
return InvalidOperands(Loc, LHS, RHS);
}
if (Opc == BO_And)
diagnoseLogicalNotOnLHSofCheck(*this, LHS, RHS, Loc, Opc);
ExprResult LHSResult = LHS, RHSResult = RHS;
QualType compType = UsualArithmeticConversions(LHSResult, RHSResult,
IsCompAssign);
if (LHSResult.isInvalid() || RHSResult.isInvalid())
return QualType();
LHS = LHSResult.get();
RHS = RHSResult.get();
if (!compType.isNull() && compType->isIntegralOrUnscopedEnumerationType())
return compType;
return InvalidOperands(Loc, LHS, RHS);
}
// C99 6.5.[13,14]
inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc,
BinaryOperatorKind Opc) {
// Check vector operands differently.
if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType())
return CheckVectorLogicalOperands(LHS, RHS, Loc);
// Diagnose cases where the user write a logical and/or but probably meant a
// bitwise one. We do this when the LHS is a non-bool integer and the RHS
// is a constant.
if (LHS.get()->getType()->isIntegerType() &&
!LHS.get()->getType()->isBooleanType() &&
RHS.get()->getType()->isIntegerType() && !RHS.get()->isValueDependent() &&
// Don't warn in macros or template instantiations.
!Loc.isMacroID() && !inTemplateInstantiation()) {
// If the RHS can be constant folded, and if it constant folds to something
// that isn't 0 or 1 (which indicate a potential logical operation that
// happened to fold to true/false) then warn.
// Parens on the RHS are ignored.
Expr::EvalResult EVResult;
if (RHS.get()->EvaluateAsInt(EVResult, Context)) {
llvm::APSInt Result = EVResult.Val.getInt();
if ((getLangOpts().Bool && !RHS.get()->getType()->isBooleanType() &&
!RHS.get()->getExprLoc().isMacroID()) ||
(Result != 0 && Result != 1)) {
Diag(Loc, diag::warn_logical_instead_of_bitwise)
<< RHS.get()->getSourceRange()
<< (Opc == BO_LAnd ? "&&" : "||");
// Suggest replacing the logical operator with the bitwise version
Diag(Loc, diag::note_logical_instead_of_bitwise_change_operator)
<< (Opc == BO_LAnd ? "&" : "|")
<< FixItHint::CreateReplacement(SourceRange(
Loc, getLocForEndOfToken(Loc)),
Opc == BO_LAnd ? "&" : "|");
if (Opc == BO_LAnd)
// Suggest replacing "Foo() && kNonZero" with "Foo()"
Diag(Loc, diag::note_logical_instead_of_bitwise_remove_constant)
<< FixItHint::CreateRemoval(
SourceRange(getLocForEndOfToken(LHS.get()->getEndLoc()),
RHS.get()->getEndLoc()));
}
}
}
if (!Context.getLangOpts().CPlusPlus) {
// OpenCL v1.1 s6.3.g: The logical operators and (&&), or (||) do
// not operate on the built-in scalar and vector float types.
if (Context.getLangOpts().OpenCL &&
Context.getLangOpts().OpenCLVersion < 120) {
if (LHS.get()->getType()->isFloatingType() ||
RHS.get()->getType()->isFloatingType())
return InvalidOperands(Loc, LHS, RHS);
}
LHS = UsualUnaryConversions(LHS.get());
if (LHS.isInvalid())
return QualType();
RHS = UsualUnaryConversions(RHS.get());
if (RHS.isInvalid())
return QualType();
if (!LHS.get()->getType()->isScalarType() ||
!RHS.get()->getType()->isScalarType())
return InvalidOperands(Loc, LHS, RHS);
return Context.IntTy;
}
// The following is safe because we only use this method for
// non-overloadable operands.
// C++ [expr.log.and]p1
// C++ [expr.log.or]p1
// The operands are both contextually converted to type bool.
ExprResult LHSRes = PerformContextuallyConvertToBool(LHS.get());
if (LHSRes.isInvalid())
return InvalidOperands(Loc, LHS, RHS);
LHS = LHSRes;
ExprResult RHSRes = PerformContextuallyConvertToBool(RHS.get());
if (RHSRes.isInvalid())
return InvalidOperands(Loc, LHS, RHS);
RHS = RHSRes;
// C++ [expr.log.and]p2
// C++ [expr.log.or]p2
// The result is a bool.
return Context.BoolTy;
}
static bool IsReadonlyMessage(Expr *E, Sema &S) {
const MemberExpr *ME = dyn_cast<MemberExpr>(E);
if (!ME) return false;
if (!isa<FieldDecl>(ME->getMemberDecl())) return false;
ObjCMessageExpr *Base = dyn_cast<ObjCMessageExpr>(
ME->getBase()->IgnoreImplicit()->IgnoreParenImpCasts());
if (!Base) return false;
return Base->getMethodDecl() != nullptr;
}
/// Is the given expression (which must be 'const') a reference to a
/// variable which was originally non-const, but which has become
/// 'const' due to being captured within a block?
enum NonConstCaptureKind { NCCK_None, NCCK_Block, NCCK_Lambda };
static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E) {
assert(E->isLValue() && E->getType().isConstQualified());
E = E->IgnoreParens();
// Must be a reference to a declaration from an enclosing scope.
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
if (!DRE) return NCCK_None;
if (!DRE->refersToEnclosingVariableOrCapture()) return NCCK_None;
// The declaration must be a variable which is not declared 'const'.
VarDecl *var = dyn_cast<VarDecl>(DRE->getDecl());
if (!var) return NCCK_None;
if (var->getType().isConstQualified()) return NCCK_None;
assert(var->hasLocalStorage() && "capture added 'const' to non-local?");
// Decide whether the first capture was for a block or a lambda.
DeclContext *DC = S.CurContext, *Prev = nullptr;
// Decide whether the first capture was for a block or a lambda.
while (DC) {
// For init-capture, it is possible that the variable belongs to the
// template pattern of the current context.
if (auto *FD = dyn_cast<FunctionDecl>(DC))
if (var->isInitCapture() &&
FD->getTemplateInstantiationPattern() == var->getDeclContext())
break;
if (DC == var->getDeclContext())
break;
Prev = DC;
DC = DC->getParent();
}
// Unless we have an init-capture, we've gone one step too far.
if (!var->isInitCapture())
DC = Prev;
return (isa<BlockDecl>(DC) ? NCCK_Block : NCCK_Lambda);
}
static bool IsTypeModifiable(QualType Ty, bool IsDereference) {
Ty = Ty.getNonReferenceType();
if (IsDereference && Ty->isPointerType())
Ty = Ty->getPointeeType();
return !Ty.isConstQualified();
}
// Update err_typecheck_assign_const and note_typecheck_assign_const
// when this enum is changed.
enum {
ConstFunction,
ConstVariable,
ConstMember,
ConstMethod,
NestedConstMember,
ConstUnknown, // Keep as last element
};
/// Emit the "read-only variable not assignable" error and print notes to give
/// more information about why the variable is not assignable, such as pointing
/// to the declaration of a const variable, showing that a method is const, or
/// that the function is returning a const reference.
static void DiagnoseConstAssignment(Sema &S, const Expr *E,
SourceLocation Loc) {
SourceRange ExprRange = E->getSourceRange();
// Only emit one error on the first const found. All other consts will emit
// a note to the error.
bool DiagnosticEmitted = false;
// Track if the current expression is the result of a dereference, and if the
// next checked expression is the result of a dereference.
bool IsDereference = false;
bool NextIsDereference = false;
// Loop to process MemberExpr chains.
while (true) {
IsDereference = NextIsDereference;
E = E->IgnoreImplicit()->IgnoreParenImpCasts();
if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
NextIsDereference = ME->isArrow();
const ValueDecl *VD = ME->getMemberDecl();
if (const FieldDecl *Field = dyn_cast<FieldDecl>(VD)) {
// Mutable fields can be modified even if the class is const.
if (Field->isMutable()) {
assert(DiagnosticEmitted && "Expected diagnostic not emitted.");
break;
}
if (!IsTypeModifiable(Field->getType(), IsDereference)) {
if (!DiagnosticEmitted) {
S.Diag(Loc, diag::err_typecheck_assign_const)
<< ExprRange << ConstMember << false /*static*/ << Field
<< Field->getType();
DiagnosticEmitted = true;
}
S.Diag(VD->getLocation(), diag::note_typecheck_assign_const)
<< ConstMember << false /*static*/ << Field << Field->getType()
<< Field->getSourceRange();
}
E = ME->getBase();
continue;
} else if (const VarDecl *VDecl = dyn_cast<VarDecl>(VD)) {
if (VDecl->getType().isConstQualified()) {
if (!DiagnosticEmitted) {
S.Diag(Loc, diag::err_typecheck_assign_const)
<< ExprRange << ConstMember << true /*static*/ << VDecl
<< VDecl->getType();
DiagnosticEmitted = true;
}
S.Diag(VD->getLocation(), diag::note_typecheck_assign_const)
<< ConstMember << true /*static*/ << VDecl << VDecl->getType()
<< VDecl->getSourceRange();
}
// Static fields do not inherit constness from parents.
break;
}
break; // End MemberExpr
} else if (const ArraySubscriptExpr *ASE =
dyn_cast<ArraySubscriptExpr>(E)) {
E = ASE->getBase()->IgnoreParenImpCasts();
continue;
} else if (const ExtVectorElementExpr *EVE =
dyn_cast<ExtVectorElementExpr>(E)) {
E = EVE->getBase()->IgnoreParenImpCasts();
continue;
}
break;
}
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
// Function calls
const FunctionDecl *FD = CE->getDirectCallee();
if (FD && !IsTypeModifiable(FD->getReturnType(), IsDereference)) {
if (!DiagnosticEmitted) {
S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange
<< ConstFunction << FD;
DiagnosticEmitted = true;
}
S.Diag(FD->getReturnTypeSourceRange().getBegin(),
diag::note_typecheck_assign_const)
<< ConstFunction << FD << FD->getReturnType()
<< FD->getReturnTypeSourceRange();
}
} else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
// Point to variable declaration.
if (const ValueDecl *VD = DRE->getDecl()) {
if (!IsTypeModifiable(VD->getType(), IsDereference)) {
if (!DiagnosticEmitted) {
S.Diag(Loc, diag::err_typecheck_assign_const)
<< ExprRange << ConstVariable << VD << VD->getType();
DiagnosticEmitted = true;
}
S.Diag(VD->getLocation(), diag::note_typecheck_assign_const)
<< ConstVariable << VD << VD->getType() << VD->getSourceRange();
}
}
} else if (isa<CXXThisExpr>(E)) {
if (const DeclContext *DC = S.getFunctionLevelDeclContext()) {
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) {
if (MD->isConst()) {
if (!DiagnosticEmitted) {
S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange
<< ConstMethod << MD;
DiagnosticEmitted = true;
}
S.Diag(MD->getLocation(), diag::note_typecheck_assign_const)
<< ConstMethod << MD << MD->getSourceRange();
}
}
}
}
if (DiagnosticEmitted)
return;
// Can't determine a more specific message, so display the generic error.
S.Diag(Loc, diag::err_typecheck_assign_const) << ExprRange << ConstUnknown;
}
enum OriginalExprKind {
OEK_Variable,
OEK_Member,
OEK_LValue
};
static void DiagnoseRecursiveConstFields(Sema &S, const ValueDecl *VD,
const RecordType *Ty,
SourceLocation Loc, SourceRange Range,
OriginalExprKind OEK,
bool &DiagnosticEmitted) {
std::vector<const RecordType *> RecordTypeList;
RecordTypeList.push_back(Ty);
unsigned NextToCheckIndex = 0;
// We walk the record hierarchy breadth-first to ensure that we print
// diagnostics in field nesting order.
while (RecordTypeList.size() > NextToCheckIndex) {
bool IsNested = NextToCheckIndex > 0;
for (const FieldDecl *Field :
RecordTypeList[NextToCheckIndex]->getDecl()->fields()) {
// First, check every field for constness.
QualType FieldTy = Field->getType();
if (FieldTy.isConstQualified()) {
if (!DiagnosticEmitted) {
S.Diag(Loc, diag::err_typecheck_assign_const)
<< Range << NestedConstMember << OEK << VD
<< IsNested << Field;
DiagnosticEmitted = true;
}
S.Diag(Field->getLocation(), diag::note_typecheck_assign_const)
<< NestedConstMember << IsNested << Field
<< FieldTy << Field->getSourceRange();
}
// Then we append it to the list to check next in order.
FieldTy = FieldTy.getCanonicalType();
if (const auto *FieldRecTy = FieldTy->getAs<RecordType>()) {
if (llvm::find(RecordTypeList, FieldRecTy) == RecordTypeList.end())
RecordTypeList.push_back(FieldRecTy);
}
}
++NextToCheckIndex;
}
}
/// Emit an error for the case where a record we are trying to assign to has a
/// const-qualified field somewhere in its hierarchy.
static void DiagnoseRecursiveConstFields(Sema &S, const Expr *E,
SourceLocation Loc) {
QualType Ty = E->getType();
assert(Ty->isRecordType() && "lvalue was not record?");
SourceRange Range = E->getSourceRange();
const RecordType *RTy = Ty.getCanonicalType()->getAs<RecordType>();
bool DiagEmitted = false;
if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
DiagnoseRecursiveConstFields(S, ME->getMemberDecl(), RTy, Loc,
Range, OEK_Member, DiagEmitted);
else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
DiagnoseRecursiveConstFields(S, DRE->getDecl(), RTy, Loc,
Range, OEK_Variable, DiagEmitted);
else
DiagnoseRecursiveConstFields(S, nullptr, RTy, Loc,
Range, OEK_LValue, DiagEmitted);
if (!DiagEmitted)
DiagnoseConstAssignment(S, E, Loc);
}
/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not,
/// emit an error and return true. If so, return false.
static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
assert(!E->hasPlaceholderType(BuiltinType::PseudoObject));
S.CheckShadowingDeclModification(E, Loc);
SourceLocation OrigLoc = Loc;
Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context,
&Loc);
if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S))
IsLV = Expr::MLV_InvalidMessageExpression;
if (IsLV == Expr::MLV_Valid)
return false;
unsigned DiagID = 0;
bool NeedType = false;
switch (IsLV) { // C99 6.5.16p2
case Expr::MLV_ConstQualified:
// Use a specialized diagnostic when we're assigning to an object
// from an enclosing function or block.
if (NonConstCaptureKind NCCK = isReferenceToNonConstCapture(S, E)) {
if (NCCK == NCCK_Block)
DiagID = diag::err_block_decl_ref_not_modifiable_lvalue;
else
DiagID = diag::err_lambda_decl_ref_not_modifiable_lvalue;
break;
}
// In ARC, use some specialized diagnostics for occasions where we
// infer 'const'. These are always pseudo-strong variables.
if (S.getLangOpts().ObjCAutoRefCount) {
DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts());
if (declRef && isa<VarDecl>(declRef->getDecl())) {
VarDecl *var = cast<VarDecl>(declRef->getDecl());
// Use the normal diagnostic if it's pseudo-__strong but the
// user actually wrote 'const'.
if (var->isARCPseudoStrong() &&
(!var->getTypeSourceInfo() ||
!var->getTypeSourceInfo()->getType().isConstQualified())) {
// There are three pseudo-strong cases:
// - self
ObjCMethodDecl *method = S.getCurMethodDecl();
if (method && var == method->getSelfDecl()) {
DiagID = method->isClassMethod()
? diag::err_typecheck_arc_assign_self_class_method
: diag::err_typecheck_arc_assign_self;
// - Objective-C externally_retained attribute.
} else if (var->hasAttr<ObjCExternallyRetainedAttr>() ||
isa<ParmVarDecl>(var)) {
DiagID = diag::err_typecheck_arc_assign_externally_retained;
// - fast enumeration variables
} else {
DiagID = diag::err_typecheck_arr_assign_enumeration;
}
SourceRange Assign;
if (Loc != OrigLoc)
Assign = SourceRange(OrigLoc, OrigLoc);
S.Diag(Loc, DiagID) << E->getSourceRange() << Assign;
// We need to preserve the AST regardless, so migration tool
// can do its job.
return false;
}
}
}
// If none of the special cases above are triggered, then this is a
// simple const assignment.
if (DiagID == 0) {
DiagnoseConstAssignment(S, E, Loc);
return true;
}
break;
case Expr::MLV_ConstAddrSpace:
DiagnoseConstAssignment(S, E, Loc);
return true;
case Expr::MLV_ConstQualifiedField:
DiagnoseRecursiveConstFields(S, E, Loc);
return true;
case Expr::MLV_ArrayType:
case Expr::MLV_ArrayTemporary:
DiagID = diag::err_typecheck_array_not_modifiable_lvalue;
NeedType = true;
break;
case Expr::MLV_NotObjectType:
DiagID = diag::err_typecheck_non_object_not_modifiable_lvalue;
NeedType = true;
break;
case Expr::MLV_LValueCast:
DiagID = diag::err_typecheck_lvalue_casts_not_supported;
break;
case Expr::MLV_Valid:
llvm_unreachable("did not take early return for MLV_Valid");
case Expr::MLV_InvalidExpression:
case Expr::MLV_MemberFunction:
case Expr::MLV_ClassTemporary:
DiagID = diag::err_typecheck_expression_not_modifiable_lvalue;
break;
case Expr::MLV_IncompleteType:
case Expr::MLV_IncompleteVoidType:
return S.RequireCompleteType(Loc, E->getType(),
diag::err_typecheck_incomplete_type_not_modifiable_lvalue, E);
case Expr::MLV_DuplicateVectorComponents:
DiagID = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
break;
case Expr::MLV_NoSetterProperty:
llvm_unreachable("readonly properties should be processed differently");
case Expr::MLV_InvalidMessageExpression:
DiagID = diag::err_readonly_message_assignment;
break;
case Expr::MLV_SubObjCPropertySetting:
DiagID = diag::err_no_subobject_property_setting;
break;
}
SourceRange Assign;
if (Loc != OrigLoc)
Assign = SourceRange(OrigLoc, OrigLoc);
if (NeedType)
S.Diag(Loc, DiagID) << E->getType() << E->getSourceRange() << Assign;
else
S.Diag(Loc, DiagID) << E->getSourceRange() << Assign;
return true;
}
static void CheckIdentityFieldAssignment(Expr *LHSExpr, Expr *RHSExpr,
SourceLocation Loc,
Sema &Sema) {
if (Sema.inTemplateInstantiation())
return;
if (Sema.isUnevaluatedContext())
return;
if (Loc.isInvalid() || Loc.isMacroID())
return;
if (LHSExpr->getExprLoc().isMacroID() || RHSExpr->getExprLoc().isMacroID())
return;
// C / C++ fields
MemberExpr *ML = dyn_cast<MemberExpr>(LHSExpr);
MemberExpr *MR = dyn_cast<MemberExpr>(RHSExpr);
if (ML && MR) {
if (!(isa<CXXThisExpr>(ML->getBase()) && isa<CXXThisExpr>(MR->getBase())))
return;
const ValueDecl *LHSDecl =
cast<ValueDecl>(ML->getMemberDecl()->getCanonicalDecl());
const ValueDecl *RHSDecl =
cast<ValueDecl>(MR->getMemberDecl()->getCanonicalDecl());
if (LHSDecl != RHSDecl)
return;
if (LHSDecl->getType().isVolatileQualified())
return;
if (const ReferenceType *RefTy = LHSDecl->getType()->getAs<ReferenceType>())
if (RefTy->getPointeeType().isVolatileQualified())
return;
Sema.Diag(Loc, diag::warn_identity_field_assign) << 0;
}
// Objective-C instance variables
ObjCIvarRefExpr *OL = dyn_cast<ObjCIvarRefExpr>(LHSExpr);
ObjCIvarRefExpr *OR = dyn_cast<ObjCIvarRefExpr>(RHSExpr);
if (OL && OR && OL->getDecl() == OR->getDecl()) {
DeclRefExpr *RL = dyn_cast<DeclRefExpr>(OL->getBase()->IgnoreImpCasts());
DeclRefExpr *RR = dyn_cast<DeclRefExpr>(OR->getBase()->IgnoreImpCasts());
if (RL && RR && RL->getDecl() == RR->getDecl())
Sema.Diag(Loc, diag::warn_identity_field_assign) << 1;
}
}
// C99 6.5.16.1
QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
SourceLocation Loc,
QualType CompoundType) {
assert(!LHSExpr->hasPlaceholderType(BuiltinType::PseudoObject));
// Verify that LHS is a modifiable lvalue, and emit error if not.
if (CheckForModifiableLvalue(LHSExpr, Loc, *this))
return QualType();
QualType LHSType = LHSExpr->getType();
QualType RHSType = CompoundType.isNull() ? RHS.get()->getType() :
CompoundType;
// OpenCL v1.2 s6.1.1.1 p2:
// The half data type can only be used to declare a pointer to a buffer that
// contains half values
if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") &&
LHSType->isHalfType()) {
Diag(Loc, diag::err_opencl_half_load_store) << 1
<< LHSType.getUnqualifiedType();
return QualType();
}
AssignConvertType ConvTy;
if (CompoundType.isNull()) {
Expr *RHSCheck = RHS.get();
CheckIdentityFieldAssignment(LHSExpr, RHSCheck, Loc, *this);
QualType LHSTy(LHSType);
ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
if (RHS.isInvalid())
return QualType();
// Special case of NSObject attributes on c-style pointer types.
if (ConvTy == IncompatiblePointer &&
((Context.isObjCNSObjectType(LHSType) &&
RHSType->isObjCObjectPointerType()) ||
(Context.isObjCNSObjectType(RHSType) &&
LHSType->isObjCObjectPointerType())))
ConvTy = Compatible;
if (ConvTy == Compatible &&
LHSType->isObjCObjectType())
Diag(Loc, diag::err_objc_object_assignment)
<< LHSType;
// If the RHS is a unary plus or minus, check to see if they = and + are
// right next to each other. If so, the user may have typo'd "x =+ 4"
// instead of "x += 4".
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RHSCheck))
RHSCheck = ICE->getSubExpr();
if (UnaryOperator *UO = dyn_cast<UnaryOperator>(RHSCheck)) {
if ((UO->getOpcode() == UO_Plus || UO->getOpcode() == UO_Minus) &&
Loc.isFileID() && UO->getOperatorLoc().isFileID() &&
// Only if the two operators are exactly adjacent.
Loc.getLocWithOffset(1) == UO->getOperatorLoc() &&
// And there is a space or other character before the subexpr of the
// unary +/-. We don't want to warn on "x=-1".
Loc.getLocWithOffset(2) != UO->getSubExpr()->getBeginLoc() &&
UO->getSubExpr()->getBeginLoc().isFileID()) {
Diag(Loc, diag::warn_not_compound_assign)
<< (UO->getOpcode() == UO_Plus ? "+" : "-")
<< SourceRange(UO->getOperatorLoc(), UO->getOperatorLoc());
}
}
if (ConvTy == Compatible) {
if (LHSType.getObjCLifetime() == Qualifiers::OCL_Strong) {
// Warn about retain cycles where a block captures the LHS, but
// not if the LHS is a simple variable into which the block is
// being stored...unless that variable can be captured by reference!
const Expr *InnerLHS = LHSExpr->IgnoreParenCasts();
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InnerLHS);
if (!DRE || DRE->getDecl()->hasAttr<BlocksAttr>())
checkRetainCycles(LHSExpr, RHS.get());
}
if (LHSType.getObjCLifetime() == Qualifiers::OCL_Strong ||
LHSType.isNonWeakInMRRWithObjCWeak(Context)) {
// It is safe to assign a weak reference into a strong variable.
// Although this code can still have problems:
// id x = self.weakProp;
// id y = self.weakProp;
// we do not warn to warn spuriously when 'x' and 'y' are on separate
// paths through the function. This should be revisited if
// -Wrepeated-use-of-weak is made flow-sensitive.
// For ObjCWeak only, we do not warn if the assign is to a non-weak
// variable, which will be valid for the current autorelease scope.
if (!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak,
RHS.get()->getBeginLoc()))
getCurFunction()->markSafeWeakUse(RHS.get());
} else if (getLangOpts().ObjCAutoRefCount || getLangOpts().ObjCWeak) {
checkUnsafeExprAssigns(Loc, LHSExpr, RHS.get());
}
}
} else {
// Compound assignment "x += y"
ConvTy = CheckAssignmentConstraints(Loc, LHSType, RHSType);
}
if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType,
RHS.get(), AA_Assigning))
return QualType();
CheckForNullPointerDereference(*this, LHSExpr);
// C99 6.5.16p3: The type of an assignment expression is the type of the
// left operand unless the left operand has qualified type, in which case
// it is the unqualified version of the type of the left operand.
// C99 6.5.16.1p2: In simple assignment, the value of the right operand
// is converted to the type of the assignment expression (above).
// C++ 5.17p1: the type of the assignment expression is that of its left
// operand.
return (getLangOpts().CPlusPlus
? LHSType : LHSType.getUnqualifiedType());
}
// Only ignore explicit casts to void.
static bool IgnoreCommaOperand(const Expr *E) {
E = E->IgnoreParens();
if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
if (CE->getCastKind() == CK_ToVoid) {
return true;
}
// static_cast<void> on a dependent type will not show up as CK_ToVoid.
if (CE->getCastKind() == CK_Dependent && E->getType()->isVoidType() &&
CE->getSubExpr()->getType()->isDependentType()) {
return true;
}
}
return false;
}
// Look for instances where it is likely the comma operator is confused with
// another operator. There is a whitelist of acceptable expressions for the
// left hand side of the comma operator, otherwise emit a warning.
void Sema::DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc) {
// No warnings in macros
if (Loc.isMacroID())
return;
// Don't warn in template instantiations.
if (inTemplateInstantiation())
return;
// Scope isn't fine-grained enough to whitelist the specific cases, so
// instead, skip more than needed, then call back into here with the
// CommaVisitor in SemaStmt.cpp.
// The whitelisted locations are the initialization and increment portions
// of a for loop. The additional checks are on the condition of
// if statements, do/while loops, and for loops.
// Differences in scope flags for C89 mode requires the extra logic.
const unsigned ForIncrementFlags =
getLangOpts().C99 || getLangOpts().CPlusPlus
? Scope::ControlScope | Scope::ContinueScope | Scope::BreakScope
: Scope::ContinueScope | Scope::BreakScope;
const unsigned ForInitFlags = Scope::ControlScope | Scope::DeclScope;
const unsigned ScopeFlags = getCurScope()->getFlags();
if ((ScopeFlags & ForIncrementFlags) == ForIncrementFlags ||
(ScopeFlags & ForInitFlags) == ForInitFlags)
return;
// If there are multiple comma operators used together, get the RHS of the
// of the comma operator as the LHS.
while (const BinaryOperator *BO = dyn_cast<BinaryOperator>(LHS)) {
if (BO->getOpcode() != BO_Comma)
break;
LHS = BO->getRHS();
}
// Only allow some expressions on LHS to not warn.
if (IgnoreCommaOperand(LHS))
return;
Diag(Loc, diag::warn_comma_operator);
Diag(LHS->getBeginLoc(), diag::note_cast_to_void)
<< LHS->getSourceRange()
<< FixItHint::CreateInsertion(LHS->getBeginLoc(),
LangOpts.CPlusPlus ? "static_cast<void>("
: "(void)(")
<< FixItHint::CreateInsertion(PP.getLocForEndOfToken(LHS->getEndLoc()),
")");
}
// C99 6.5.17
static QualType CheckCommaOperands(Sema &S, ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc) {
LHS = S.CheckPlaceholderExpr(LHS.get());
RHS = S.CheckPlaceholderExpr(RHS.get());
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
// C's comma performs lvalue conversion (C99 6.3.2.1) on both its
// operands, but not unary promotions.
// C++'s comma does not do any conversions at all (C++ [expr.comma]p1).
// So we treat the LHS as a ignored value, and in C++ we allow the
// containing site to determine what should be done with the RHS.
LHS = S.IgnoredValueConversions(LHS.get());
if (LHS.isInvalid())
return QualType();
S.DiagnoseUnusedExprResult(LHS.get());
if (!S.getLangOpts().CPlusPlus) {
RHS = S.DefaultFunctionArrayLvalueConversion(RHS.get());
if (RHS.isInvalid())
return QualType();
if (!RHS.get()->getType()->isVoidType())
S.RequireCompleteType(Loc, RHS.get()->getType(),
diag::err_incomplete_type);
}
if (!S.getDiagnostics().isIgnored(diag::warn_comma_operator, Loc))
S.DiagnoseCommaOperator(LHS.get(), Loc);
return RHS.get()->getType();
}
/// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine
/// doesn't need to call UsualUnaryConversions or UsualArithmeticConversions.
static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
ExprValueKind &VK,
ExprObjectKind &OK,
SourceLocation OpLoc,
bool IsInc, bool IsPrefix) {
if (Op->isTypeDependent())
return S.Context.DependentTy;
QualType ResType = Op->getType();
// Atomic types can be used for increment / decrement where the non-atomic
// versions can, so ignore the _Atomic() specifier for the purpose of
// checking.
if (const AtomicType *ResAtomicType = ResType->getAs<AtomicType>())
ResType = ResAtomicType->getValueType();
assert(!ResType.isNull() && "no type for increment/decrement expression");
if (S.getLangOpts().CPlusPlus && ResType->isBooleanType()) {
// Decrement of bool is not allowed.
if (!IsInc) {
S.Diag(OpLoc, diag::err_decrement_bool) << Op->getSourceRange();
return QualType();
}
// Increment of bool sets it to true, but is deprecated.
S.Diag(OpLoc, S.getLangOpts().CPlusPlus17 ? diag::ext_increment_bool
: diag::warn_increment_bool)
<< Op->getSourceRange();
} else if (S.getLangOpts().CPlusPlus && ResType->isEnumeralType()) {
// Error on enum increments and decrements in C++ mode
S.Diag(OpLoc, diag::err_increment_decrement_enum) << IsInc << ResType;
return QualType();
} else if (ResType->isRealType()) {
// OK!
} else if (ResType->isPointerType()) {
// C99 6.5.2.4p2, 6.5.6p2
if (!checkArithmeticOpPointerOperand(S, OpLoc, Op))
return QualType();
} else if (ResType->isObjCObjectPointerType()) {
// On modern runtimes, ObjC pointer arithmetic is forbidden.
// Otherwise, we just need a complete type.
if (checkArithmeticIncompletePointerType(S, OpLoc, Op) ||
checkArithmeticOnObjCPointer(S, OpLoc, Op))
return QualType();
} else if (ResType->isAnyComplexType()) {
// C99 does not support ++/-- on complex types, we allow as an extension.
S.Diag(OpLoc, diag::ext_integer_increment_complex)
<< ResType << Op->getSourceRange();
} else if (ResType->isPlaceholderType()) {
ExprResult PR = S.CheckPlaceholderExpr(Op);
if (PR.isInvalid()) return QualType();
return CheckIncrementDecrementOperand(S, PR.get(), VK, OK, OpLoc,
IsInc, IsPrefix);
} else if (S.getLangOpts().AltiVec && ResType->isVectorType()) {
// OK! ( C/C++ Language Extensions for CBEA(Version 2.6) 10.3 )
} else if (S.getLangOpts().ZVector && ResType->isVectorType() &&
(ResType->getAs<VectorType>()->getVectorKind() !=
VectorType::AltiVecBool)) {
// The z vector extensions allow ++ and -- for non-bool vectors.
} else if(S.getLangOpts().OpenCL && ResType->isVectorType() &&
ResType->getAs<VectorType>()->getElementType()->isIntegerType()) {
// OpenCL V1.2 6.3 says dec/inc ops operate on integer vector types.
} else {
S.Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement)
<< ResType << int(IsInc) << Op->getSourceRange();
return QualType();
}
// At this point, we know we have a real, complex or pointer type.
// Now make sure the operand is a modifiable lvalue.
if (CheckForModifiableLvalue(Op, OpLoc, S))
return QualType();
// In C++, a prefix increment is the same type as the operand. Otherwise
// (in C or with postfix), the increment is the unqualified type of the
// operand.
if (IsPrefix && S.getLangOpts().CPlusPlus) {
VK = VK_LValue;
OK = Op->getObjectKind();
return ResType;
} else {
VK = VK_RValue;
return ResType.getUnqualifiedType();
}
}
/// getPrimaryDecl - Helper function for CheckAddressOfOperand().
/// This routine allows us to typecheck complex/recursive expressions
/// where the declaration is needed for type checking. We only need to
/// handle cases when the expression references a function designator
/// or is an lvalue. Here are some examples:
/// - &(x) => x
/// - &*****f => f for f a function designator.
/// - &s.xx => s
/// - &s.zz[1].yy -> s, if zz is an array
/// - *(x + 1) -> x, if x is an array
/// - &"123"[2] -> 0
/// - & __real__ x -> x
static ValueDecl *getPrimaryDecl(Expr *E) {
switch (E->getStmtClass()) {
case Stmt::DeclRefExprClass:
return cast<DeclRefExpr>(E)->getDecl();
case Stmt::MemberExprClass:
// If this is an arrow operator, the address is an offset from
// the base's value, so the object the base refers to is
// irrelevant.
if (cast<MemberExpr>(E)->isArrow())
return nullptr;
// Otherwise, the expression refers to a part of the base
return getPrimaryDecl(cast<MemberExpr>(E)->getBase());
case Stmt::ArraySubscriptExprClass: {
// FIXME: This code shouldn't be necessary! We should catch the implicit
// promotion of register arrays earlier.
Expr* Base = cast<ArraySubscriptExpr>(E)->getBase();
if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(Base)) {
if (ICE->getSubExpr()->getType()->isArrayType())
return getPrimaryDecl(ICE->getSubExpr());
}
return nullptr;
}
case Stmt::UnaryOperatorClass: {
UnaryOperator *UO = cast<UnaryOperator>(E);
switch(UO->getOpcode()) {
case UO_Real:
case UO_Imag:
case UO_Extension:
return getPrimaryDecl(UO->getSubExpr());
default:
return nullptr;
}
}
case Stmt::ParenExprClass:
return getPrimaryDecl(cast<ParenExpr>(E)->getSubExpr());
case Stmt::ImplicitCastExprClass:
// If the result of an implicit cast is an l-value, we care about
// the sub-expression; otherwise, the result here doesn't matter.
return getPrimaryDecl(cast<ImplicitCastExpr>(E)->getSubExpr());
default:
return nullptr;
}
}
namespace {
enum {
AO_Bit_Field = 0,
AO_Vector_Element = 1,
AO_Property_Expansion = 2,
AO_Register_Variable = 3,
AO_No_Error = 4
};
}
/// Diagnose invalid operand for address of operations.
///
/// \param Type The type of operand which cannot have its address taken.
static void diagnoseAddressOfInvalidType(Sema &S, SourceLocation Loc,
Expr *E, unsigned Type) {
S.Diag(Loc, diag::err_typecheck_address_of) << Type << E->getSourceRange();
}
/// CheckAddressOfOperand - The operand of & must be either a function
/// designator or an lvalue designating an object. If it is an lvalue, the
/// object cannot be declared with storage class register or be a bit field.
/// Note: The usual conversions are *not* applied to the operand of the &
/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
/// In C++, the operand might be an overloaded function name, in which case
/// we allow the '&' but retain the overloaded-function type.
QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){
if (PTy->getKind() == BuiltinType::Overload) {
Expr *E = OrigOp.get()->IgnoreParens();
if (!isa<OverloadExpr>(E)) {
assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf);
Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof_addrof_function)
<< OrigOp.get()->getSourceRange();
return QualType();
}
OverloadExpr *Ovl = cast<OverloadExpr>(E);
if (isa<UnresolvedMemberExpr>(Ovl))
if (!ResolveSingleFunctionTemplateSpecialization(Ovl)) {
Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
<< OrigOp.get()->getSourceRange();
return QualType();
}
return Context.OverloadTy;
}
if (PTy->getKind() == BuiltinType::UnknownAny)
return Context.UnknownAnyTy;
if (PTy->getKind() == BuiltinType::BoundMember) {
Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
<< OrigOp.get()->getSourceRange();
return QualType();
}
OrigOp = CheckPlaceholderExpr(OrigOp.get());
if (OrigOp.isInvalid()) return QualType();
}
if (OrigOp.get()->isTypeDependent())
return Context.DependentTy;
assert(!OrigOp.get()->getType()->isPlaceholderType());
// Make sure to ignore parentheses in subsequent checks
Expr *op = OrigOp.get()->IgnoreParens();
// In OpenCL captures for blocks called as lambda functions
// are located in the private address space. Blocks used in
// enqueue_kernel can be located in a different address space
// depending on a vendor implementation. Thus preventing
// taking an address of the capture to avoid invalid AS casts.
if (LangOpts.OpenCL) {
auto* VarRef = dyn_cast<DeclRefExpr>(op);
if (VarRef && VarRef->refersToEnclosingVariableOrCapture()) {
Diag(op->getExprLoc(), diag::err_opencl_taking_address_capture);
return QualType();
}
}
if (getLangOpts().C99) {
// Implement C99-only parts of addressof rules.
if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) {
if (uOp->getOpcode() == UO_Deref)
// Per C99 6.5.3.2, the address of a deref always returns a valid result
// (assuming the deref expression is valid).
return uOp->getSubExpr()->getType();
}
// Technically, there should be a check for array subscript
// expressions here, but the result of one is always an lvalue anyway.
}
ValueDecl *dcl = getPrimaryDecl(op);
if (auto *FD = dyn_cast_or_null<FunctionDecl>(dcl))
if (!checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
op->getBeginLoc()))
return QualType();
Expr::LValueClassification lval = op->ClassifyLValue(Context);
unsigned AddressOfError = AO_No_Error;
if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) {
bool sfinae = (bool)isSFINAEContext();
Diag(OpLoc, isSFINAEContext() ? diag::err_typecheck_addrof_temporary
: diag::ext_typecheck_addrof_temporary)
<< op->getType() << op->getSourceRange();
if (sfinae)
return QualType();
// Materialize the temporary as an lvalue so that we can take its address.
OrigOp = op =
CreateMaterializeTemporaryExpr(op->getType(), OrigOp.get(), true);
} else if (isa<ObjCSelectorExpr>(op)) {
return Context.getPointerType(op->getType());
} else if (lval == Expr::LV_MemberFunction) {
// If it's an instance method, make a member pointer.
// The expression must have exactly the form &A::foo.
// If the underlying expression isn't a decl ref, give up.
if (!isa<DeclRefExpr>(op)) {
Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
<< OrigOp.get()->getSourceRange();
return QualType();
}
DeclRefExpr *DRE = cast<DeclRefExpr>(op);
CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl());
// The id-expression was parenthesized.
if (OrigOp.get() != DRE) {
Diag(OpLoc, diag::err_parens_pointer_member_function)
<< OrigOp.get()->getSourceRange();
// The method was named without a qualifier.
} else if (!DRE->getQualifier()) {
if (MD->getParent()->getName().empty())
Diag(OpLoc, diag::err_unqualified_pointer_member_function)
<< op->getSourceRange();
else {
SmallString<32> Str;
StringRef Qual = (MD->getParent()->getName() + "::").toStringRef(Str);
Diag(OpLoc, diag::err_unqualified_pointer_member_function)
<< op->getSourceRange()
<< FixItHint::CreateInsertion(op->getSourceRange().getBegin(), Qual);
}
}
// Taking the address of a dtor is illegal per C++ [class.dtor]p2.
if (isa<CXXDestructorDecl>(MD))
Diag(OpLoc, diag::err_typecheck_addrof_dtor) << op->getSourceRange();
QualType MPTy = Context.getMemberPointerType(
op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr());
// Under the MS ABI, lock down the inheritance model now.
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
(void)isCompleteType(OpLoc, MPTy);
return MPTy;
} else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
// C99 6.5.3.2p1
// The operand must be either an l-value or a function designator
if (!op->getType()->isFunctionType()) {
// Use a special diagnostic for loads from property references.
if (isa<PseudoObjectExpr>(op)) {
AddressOfError = AO_Property_Expansion;
} else {
Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
<< op->getType() << op->getSourceRange();
return QualType();
}
}
} else if (op->getObjectKind() == OK_BitField) { // C99 6.5.3.2p1
// The operand cannot be a bit-field
AddressOfError = AO_Bit_Field;
} else if (op->getObjectKind() == OK_VectorComponent) {
// The operand cannot be an element of a vector
AddressOfError = AO_Vector_Element;
} else if (dcl) { // C99 6.5.3.2p1
// We have an lvalue with a decl. Make sure the decl is not declared
// with the register storage-class specifier.
if (const VarDecl *vd = dyn_cast<VarDecl>(dcl)) {
// in C++ it is not error to take address of a register
// variable (c++03 7.1.1P3)
if (vd->getStorageClass() == SC_Register &&
!getLangOpts().CPlusPlus) {
AddressOfError = AO_Register_Variable;
}
} else if (isa<MSPropertyDecl>(dcl)) {
AddressOfError = AO_Property_Expansion;
} else if (isa<FunctionTemplateDecl>(dcl)) {
return Context.OverloadTy;
} else if (isa<FieldDecl>(dcl) || isa<IndirectFieldDecl>(dcl)) {
// Okay: we can take the address of a field.
// Could be a pointer to member, though, if there is an explicit
// scope qualifier for the class.
if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier()) {
DeclContext *Ctx = dcl->getDeclContext();
if (Ctx && Ctx->isRecord()) {
if (dcl->getType()->isReferenceType()) {
Diag(OpLoc,
diag::err_cannot_form_pointer_to_member_of_reference_type)
<< dcl->getDeclName() << dcl->getType();
return QualType();
}
while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion())
Ctx = Ctx->getParent();
QualType MPTy = Context.getMemberPointerType(
op->getType(),
Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
// Under the MS ABI, lock down the inheritance model now.
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
(void)isCompleteType(OpLoc, MPTy);
return MPTy;
}
}
} else if (!isa<FunctionDecl>(dcl) && !isa<NonTypeTemplateParmDecl>(dcl) &&
!isa<BindingDecl>(dcl))
llvm_unreachable("Unknown/unexpected decl type");
}
if (AddressOfError != AO_No_Error) {
diagnoseAddressOfInvalidType(*this, OpLoc, op, AddressOfError);
return QualType();
}
if (lval == Expr::LV_IncompleteVoidType) {
// Taking the address of a void variable is technically illegal, but we
// allow it in cases which are otherwise valid.
// Example: "extern void x; void* y = &x;".
Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange();
}
// If the operand has type "type", the result has type "pointer to type".
if (op->getType()->isObjCObjectType())
return Context.getObjCObjectPointerType(op->getType());
CheckAddressOfPackedMember(op);
return Context.getPointerType(op->getType());
}
static void RecordModifiableNonNullParam(Sema &S, const Expr *Exp) {
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp);
if (!DRE)
return;
const Decl *D = DRE->getDecl();
if (!D)
return;
const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D);
if (!Param)
return;
if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(Param->getDeclContext()))
if (!FD->hasAttr<NonNullAttr>() && !Param->hasAttr<NonNullAttr>())
return;
if (FunctionScopeInfo *FD = S.getCurFunction())
if (!FD->ModifiedNonNullParams.count(Param))
FD->ModifiedNonNullParams.insert(Param);
}
/// CheckIndirectionOperand - Type check unary indirection (prefix '*').
static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
SourceLocation OpLoc) {
if (Op->isTypeDependent())
return S.Context.DependentTy;
ExprResult ConvResult = S.UsualUnaryConversions(Op);
if (ConvResult.isInvalid())
return QualType();
Op = ConvResult.get();
QualType OpTy = Op->getType();
QualType Result;
if (isa<CXXReinterpretCastExpr>(Op)) {
QualType OpOrigType = Op->IgnoreParenCasts()->getType();
S.CheckCompatibleReinterpretCast(OpOrigType, OpTy, /*IsDereference*/true,
Op->getSourceRange());
}
if (const PointerType *PT = OpTy->getAs<PointerType>())
{
Result = PT->getPointeeType();
}
else if (const ObjCObjectPointerType *OPT =
OpTy->getAs<ObjCObjectPointerType>())
Result = OPT->getPointeeType();
else {
ExprResult PR = S.CheckPlaceholderExpr(Op);
if (PR.isInvalid()) return QualType();
if (PR.get() != Op)
return CheckIndirectionOperand(S, PR.get(), VK, OpLoc);
}
if (Result.isNull()) {
S.Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer)
<< OpTy << Op->getSourceRange();
return QualType();
}
// Note that per both C89 and C99, indirection is always legal, even if Result
// is an incomplete type or void. It would be possible to warn about
// dereferencing a void pointer, but it's completely well-defined, and such a
// warning is unlikely to catch any mistakes. In C++, indirection is not valid
// for pointers to 'void' but is fine for any other pointer type:
//
// C++ [expr.unary.op]p1:
// [...] the expression to which [the unary * operator] is applied shall
// be a pointer to an object type, or a pointer to a function type
if (S.getLangOpts().CPlusPlus && Result->isVoidType())
S.Diag(OpLoc, diag::ext_typecheck_indirection_through_void_pointer)
<< OpTy << Op->getSourceRange();
// Dereferences are usually l-values...
VK = VK_LValue;
// ...except that certain expressions are never l-values in C.
if (!S.getLangOpts().CPlusPlus && Result.isCForbiddenLValueType())
VK = VK_RValue;
return Result;
}
BinaryOperatorKind Sema::ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind) {
BinaryOperatorKind Opc;
switch (Kind) {
default: llvm_unreachable("Unknown binop!");
case tok::periodstar: Opc = BO_PtrMemD; break;
case tok::arrowstar: Opc = BO_PtrMemI; break;
case tok::star: Opc = BO_Mul; break;
case tok::slash: Opc = BO_Div; break;
case tok::percent: Opc = BO_Rem; break;
case tok::plus: Opc = BO_Add; break;
case tok::minus: Opc = BO_Sub; break;
case tok::lessless: Opc = BO_Shl; break;
case tok::greatergreater: Opc = BO_Shr; break;
case tok::lessequal: Opc = BO_LE; break;
case tok::less: Opc = BO_LT; break;
case tok::greaterequal: Opc = BO_GE; break;
case tok::greater: Opc = BO_GT; break;
case tok::exclaimequal: Opc = BO_NE; break;
case tok::equalequal: Opc = BO_EQ; break;
case tok::spaceship: Opc = BO_Cmp; break;
case tok::amp: Opc = BO_And; break;
case tok::caret: Opc = BO_Xor; break;
case tok::pipe: Opc = BO_Or; break;
case tok::ampamp: Opc = BO_LAnd; break;
case tok::pipepipe: Opc = BO_LOr; break;
case tok::equal: Opc = BO_Assign; break;
case tok::starequal: Opc = BO_MulAssign; break;
case tok::slashequal: Opc = BO_DivAssign; break;
case tok::percentequal: Opc = BO_RemAssign; break;
case tok::plusequal: Opc = BO_AddAssign; break;
case tok::minusequal: Opc = BO_SubAssign; break;
case tok::lesslessequal: Opc = BO_ShlAssign; break;
case tok::greatergreaterequal: Opc = BO_ShrAssign; break;
case tok::ampequal: Opc = BO_AndAssign; break;
case tok::caretequal: Opc = BO_XorAssign; break;
case tok::pipeequal: Opc = BO_OrAssign; break;
case tok::comma: Opc = BO_Comma; break;
}
return Opc;
}
static inline UnaryOperatorKind ConvertTokenKindToUnaryOpcode(
tok::TokenKind Kind) {
UnaryOperatorKind Opc;
switch (Kind) {
default: llvm_unreachable("Unknown unary op!");
case tok::plusplus: Opc = UO_PreInc; break;
case tok::minusminus: Opc = UO_PreDec; break;
case tok::amp: Opc = UO_AddrOf; break;
case tok::star: Opc = UO_Deref; break;
case tok::plus: Opc = UO_Plus; break;
case tok::minus: Opc = UO_Minus; break;
case tok::tilde: Opc = UO_Not; break;
case tok::exclaim: Opc = UO_LNot; break;
case tok::kw___real: Opc = UO_Real; break;
case tok::kw___imag: Opc = UO_Imag; break;
case tok::kw___extension__: Opc = UO_Extension; break;
}
return Opc;
}
/// DiagnoseSelfAssignment - Emits a warning if a value is assigned to itself.
/// This warning suppressed in the event of macro expansions.
static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr,
SourceLocation OpLoc, bool IsBuiltin) {
if (S.inTemplateInstantiation())
return;
if (S.isUnevaluatedContext())
return;
if (OpLoc.isInvalid() || OpLoc.isMacroID())
return;
LHSExpr = LHSExpr->IgnoreParenImpCasts();
RHSExpr = RHSExpr->IgnoreParenImpCasts();
const DeclRefExpr *LHSDeclRef = dyn_cast<DeclRefExpr>(LHSExpr);
const DeclRefExpr *RHSDeclRef = dyn_cast<DeclRefExpr>(RHSExpr);
if (!LHSDeclRef || !RHSDeclRef ||
LHSDeclRef->getLocation().isMacroID() ||
RHSDeclRef->getLocation().isMacroID())
return;
const ValueDecl *LHSDecl =
cast<ValueDecl>(LHSDeclRef->getDecl()->getCanonicalDecl());
const ValueDecl *RHSDecl =
cast<ValueDecl>(RHSDeclRef->getDecl()->getCanonicalDecl());
if (LHSDecl != RHSDecl)
return;
if (LHSDecl->getType().isVolatileQualified())
return;
if (const ReferenceType *RefTy = LHSDecl->getType()->getAs<ReferenceType>())
if (RefTy->getPointeeType().isVolatileQualified())
return;
S.Diag(OpLoc, IsBuiltin ? diag::warn_self_assignment_builtin
: diag::warn_self_assignment_overloaded)
<< LHSDeclRef->getType() << LHSExpr->getSourceRange()
<< RHSExpr->getSourceRange();
}
/// Check if a bitwise-& is performed on an Objective-C pointer. This
/// is usually indicative of introspection within the Objective-C pointer.
static void checkObjCPointerIntrospection(Sema &S, ExprResult &L, ExprResult &R,
SourceLocation OpLoc) {
if (!S.getLangOpts().ObjC)
return;
const Expr *ObjCPointerExpr = nullptr, *OtherExpr = nullptr;
const Expr *LHS = L.get();
const Expr *RHS = R.get();
if (LHS->IgnoreParenCasts()->getType()->isObjCObjectPointerType()) {
ObjCPointerExpr = LHS;
OtherExpr = RHS;
}
else if (RHS->IgnoreParenCasts()->getType()->isObjCObjectPointerType()) {
ObjCPointerExpr = RHS;
OtherExpr = LHS;
}
// This warning is deliberately made very specific to reduce false
// positives with logic that uses '&' for hashing. This logic mainly
// looks for code trying to introspect into tagged pointers, which
// code should generally never do.
if (ObjCPointerExpr && isa<IntegerLiteral>(OtherExpr->IgnoreParenCasts())) {
unsigned Diag = diag::warn_objc_pointer_masking;
// Determine if we are introspecting the result of performSelectorXXX.
const Expr *Ex = ObjCPointerExpr->IgnoreParenCasts();
// Special case messages to -performSelector and friends, which
// can return non-pointer values boxed in a pointer value.
// Some clients may wish to silence warnings in this subcase.
if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(Ex)) {
Selector S = ME->getSelector();
StringRef SelArg0 = S.getNameForSlot(0);
if (SelArg0.startswith("performSelector"))
Diag = diag::warn_objc_pointer_masking_performSelector;
}
S.Diag(OpLoc, Diag)
<< ObjCPointerExpr->getSourceRange();
}
}
static NamedDecl *getDeclFromExpr(Expr *E) {
if (!E)
return nullptr;
if (auto *DRE = dyn_cast<DeclRefExpr>(E))
return DRE->getDecl();
if (auto *ME = dyn_cast<MemberExpr>(E))
return ME->getMemberDecl();
if (auto *IRE = dyn_cast<ObjCIvarRefExpr>(E))
return IRE->getDecl();
return nullptr;
}
// This helper function promotes a binary operator's operands (which are of a
// half vector type) to a vector of floats and then truncates the result to
// a vector of either half or short.
static ExprResult convertHalfVecBinOp(Sema &S, ExprResult LHS, ExprResult RHS,
BinaryOperatorKind Opc, QualType ResultTy,
ExprValueKind VK, ExprObjectKind OK,
bool IsCompAssign, SourceLocation OpLoc,
FPOptions FPFeatures) {
auto &Context = S.getASTContext();
assert((isVector(ResultTy, Context.HalfTy) ||
isVector(ResultTy, Context.ShortTy)) &&
"Result must be a vector of half or short");
assert(isVector(LHS.get()->getType(), Context.HalfTy) &&
isVector(RHS.get()->getType(), Context.HalfTy) &&
"both operands expected to be a half vector");
RHS = convertVector(RHS.get(), Context.FloatTy, S);
QualType BinOpResTy = RHS.get()->getType();
// If Opc is a comparison, ResultType is a vector of shorts. In that case,
// change BinOpResTy to a vector of ints.
if (isVector(ResultTy, Context.ShortTy))
BinOpResTy = S.GetSignedVectorType(BinOpResTy);
if (IsCompAssign)
return new (Context) CompoundAssignOperator(
LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, BinOpResTy, BinOpResTy,
OpLoc, FPFeatures);
LHS = convertVector(LHS.get(), Context.FloatTy, S);
auto *BO = new (Context) BinaryOperator(LHS.get(), RHS.get(), Opc, BinOpResTy,
VK, OK, OpLoc, FPFeatures);
return convertVector(BO, ResultTy->getAs<VectorType>()->getElementType(), S);
}
static std::pair<ExprResult, ExprResult>
CorrectDelayedTyposInBinOp(Sema &S, BinaryOperatorKind Opc, Expr *LHSExpr,
Expr *RHSExpr) {
ExprResult LHS = LHSExpr, RHS = RHSExpr;
if (!S.getLangOpts().CPlusPlus) {
// C cannot handle TypoExpr nodes on either side of a binop because it
// doesn't handle dependent types properly, so make sure any TypoExprs have
// been dealt with before checking the operands.
LHS = S.CorrectDelayedTyposInExpr(LHS);
RHS = S.CorrectDelayedTyposInExpr(RHS, [Opc, LHS](Expr *E) {
if (Opc != BO_Assign)
return ExprResult(E);
// Avoid correcting the RHS to the same Expr as the LHS.
Decl *D = getDeclFromExpr(E);
return (D && D == getDeclFromExpr(LHS.get())) ? ExprError() : E;
});
}
return std::make_pair(LHS, RHS);
}
/// Returns true if conversion between vectors of halfs and vectors of floats
/// is needed.
static bool needsConversionOfHalfVec(bool OpRequiresConversion, ASTContext &Ctx,
QualType SrcType) {
return OpRequiresConversion && !Ctx.getLangOpts().NativeHalfType &&
!Ctx.getTargetInfo().useFP16ConversionIntrinsics() &&
isVector(SrcType, Ctx.HalfTy);
}
/// CreateBuiltinBinOp - Creates a new built-in binary operation with
/// operator @p Opc at location @c TokLoc. This routine only supports
/// built-in operations; ActOnBinOp handles overloaded operators.
ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
BinaryOperatorKind Opc,
Expr *LHSExpr, Expr *RHSExpr) {
if (getLangOpts().CPlusPlus11 && isa<InitListExpr>(RHSExpr)) {
// The syntax only allows initializer lists on the RHS of assignment,
// so we don't need to worry about accepting invalid code for
// non-assignment operators.
// C++11 5.17p9:
// The meaning of x = {v} [...] is that of x = T(v) [...]. The meaning
// of x = {} is x = T().
InitializationKind Kind = InitializationKind::CreateDirectList(
RHSExpr->getBeginLoc(), RHSExpr->getBeginLoc(), RHSExpr->getEndLoc());
InitializedEntity Entity =
InitializedEntity::InitializeTemporary(LHSExpr->getType());
InitializationSequence InitSeq(*this, Entity, Kind, RHSExpr);
ExprResult Init = InitSeq.Perform(*this, Entity, Kind, RHSExpr);
if (Init.isInvalid())
return Init;
RHSExpr = Init.get();
}
ExprResult LHS = LHSExpr, RHS = RHSExpr;
QualType ResultTy; // Result type of the binary operator.
// The following two variables are used for compound assignment operators
QualType CompLHSTy; // Type of LHS after promotions for computation
QualType CompResultTy; // Type of computation result
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
bool ConvertHalfVec = false;
std::tie(LHS, RHS) = CorrectDelayedTyposInBinOp(*this, Opc, LHSExpr, RHSExpr);
if (!LHS.isUsable() || !RHS.isUsable())
return ExprError();
if (getLangOpts().OpenCL) {
QualType LHSTy = LHSExpr->getType();
QualType RHSTy = RHSExpr->getType();
// OpenCLC v2.0 s6.13.11.1 allows atomic variables to be initialized by
// the ATOMIC_VAR_INIT macro.
if (LHSTy->isAtomicType() || RHSTy->isAtomicType()) {
SourceRange SR(LHSExpr->getBeginLoc(), RHSExpr->getEndLoc());
if (BO_Assign == Opc)
Diag(OpLoc, diag::err_opencl_atomic_init) << 0 << SR;
else
ResultTy = InvalidOperands(OpLoc, LHS, RHS);
return ExprError();
}
// OpenCL special types - image, sampler, pipe, and blocks are to be used
// only with a builtin functions and therefore should be disallowed here.
if (LHSTy->isImageType() || RHSTy->isImageType() ||
LHSTy->isSamplerT() || RHSTy->isSamplerT() ||
LHSTy->isPipeType() || RHSTy->isPipeType() ||
LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType()) {
ResultTy = InvalidOperands(OpLoc, LHS, RHS);
return ExprError();
}
}
switch (Opc) {
case BO_Assign:
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType());
if (getLangOpts().CPlusPlus &&
LHS.get()->getObjectKind() != OK_ObjCProperty) {
VK = LHS.get()->getValueKind();
OK = LHS.get()->getObjectKind();
}
if (!ResultTy.isNull()) {
DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc, true);
DiagnoseSelfMove(LHS.get(), RHS.get(), OpLoc);
}
RecordModifiableNonNullParam(*this, LHS.get());
break;
case BO_PtrMemD:
case BO_PtrMemI:
ResultTy = CheckPointerToMemberOperands(LHS, RHS, VK, OpLoc,
Opc == BO_PtrMemI);
break;
case BO_Mul:
case BO_Div:
ConvertHalfVec = true;
ResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, false,
Opc == BO_Div);
break;
case BO_Rem:
ResultTy = CheckRemainderOperands(LHS, RHS, OpLoc);
break;
case BO_Add:
ConvertHalfVec = true;
ResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, Opc);
break;
case BO_Sub:
ConvertHalfVec = true;
ResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc);
break;
case BO_Shl:
case BO_Shr:
ResultTy = CheckShiftOperands(LHS, RHS, OpLoc, Opc);
break;
case BO_LE:
case BO_LT:
case BO_GE:
case BO_GT:
ConvertHalfVec = true;
ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc);
break;
case BO_EQ:
case BO_NE:
ConvertHalfVec = true;
ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc);
break;
case BO_Cmp:
ConvertHalfVec = true;
ResultTy = CheckCompareOperands(LHS, RHS, OpLoc, Opc);
assert(ResultTy.isNull() || ResultTy->getAsCXXRecordDecl());
break;
case BO_And:
checkObjCPointerIntrospection(*this, LHS, RHS, OpLoc);
LLVM_FALLTHROUGH;
case BO_Xor:
case BO_Or:
ResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, Opc);
break;
case BO_LAnd:
case BO_LOr:
ConvertHalfVec = true;
ResultTy = CheckLogicalOperands(LHS, RHS, OpLoc, Opc);
break;
case BO_MulAssign:
case BO_DivAssign:
ConvertHalfVec = true;
CompResultTy = CheckMultiplyDivideOperands(LHS, RHS, OpLoc, true,
Opc == BO_DivAssign);
CompLHSTy = CompResultTy;
if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
break;
case BO_RemAssign:
CompResultTy = CheckRemainderOperands(LHS, RHS, OpLoc, true);
CompLHSTy = CompResultTy;
if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
break;
case BO_AddAssign:
ConvertHalfVec = true;
CompResultTy = CheckAdditionOperands(LHS, RHS, OpLoc, Opc, &CompLHSTy);
if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
break;
case BO_SubAssign:
ConvertHalfVec = true;
CompResultTy = CheckSubtractionOperands(LHS, RHS, OpLoc, &CompLHSTy);
if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
break;
case BO_ShlAssign:
case BO_ShrAssign:
CompResultTy = CheckShiftOperands(LHS, RHS, OpLoc, Opc, true);
CompLHSTy = CompResultTy;
if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
break;
case BO_AndAssign:
case BO_OrAssign: // fallthrough
DiagnoseSelfAssignment(*this, LHS.get(), RHS.get(), OpLoc, true);
LLVM_FALLTHROUGH;
case BO_XorAssign:
CompResultTy = CheckBitwiseOperands(LHS, RHS, OpLoc, Opc);
CompLHSTy = CompResultTy;
if (!CompResultTy.isNull() && !LHS.isInvalid() && !RHS.isInvalid())
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, CompResultTy);
break;
case BO_Comma:
ResultTy = CheckCommaOperands(*this, LHS, RHS, OpLoc);
if (getLangOpts().CPlusPlus && !RHS.isInvalid()) {
VK = RHS.get()->getValueKind();
OK = RHS.get()->getObjectKind();
}
break;
}
if (ResultTy.isNull() || LHS.isInvalid() || RHS.isInvalid())
return ExprError();
// Some of the binary operations require promoting operands of half vector to
// float vectors and truncating the result back to half vector. For now, we do
// this only when HalfArgsAndReturn is set (that is, when the target is arm or
// arm64).
assert(isVector(RHS.get()->getType(), Context.HalfTy) ==
isVector(LHS.get()->getType(), Context.HalfTy) &&
"both sides are half vectors or neither sides are");
ConvertHalfVec = needsConversionOfHalfVec(ConvertHalfVec, Context,
LHS.get()->getType());
// Check for array bounds violations for both sides of the BinaryOperator
CheckArrayAccess(LHS.get());
CheckArrayAccess(RHS.get());
if (const ObjCIsaExpr *OISA = dyn_cast<ObjCIsaExpr>(LHS.get()->IgnoreParenCasts())) {
NamedDecl *ObjectSetClass = LookupSingleName(TUScope,
&Context.Idents.get("object_setClass"),
SourceLocation(), LookupOrdinaryName);
if (ObjectSetClass && isa<ObjCIsaExpr>(LHS.get())) {
SourceLocation RHSLocEnd = getLocForEndOfToken(RHS.get()->getEndLoc());
Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign)
<< FixItHint::CreateInsertion(LHS.get()->getBeginLoc(),
"object_setClass(")
<< FixItHint::CreateReplacement(SourceRange(OISA->getOpLoc(), OpLoc),
",")
<< FixItHint::CreateInsertion(RHSLocEnd, ")");
}
else
Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign);
}
else if (const ObjCIvarRefExpr *OIRE =
dyn_cast<ObjCIvarRefExpr>(LHS.get()->IgnoreParenCasts()))
DiagnoseDirectIsaAccess(*this, OIRE, OpLoc, RHS.get());
// Opc is not a compound assignment if CompResultTy is null.
if (CompResultTy.isNull()) {
if (ConvertHalfVec)
return convertHalfVecBinOp(*this, LHS, RHS, Opc, ResultTy, VK, OK, false,
OpLoc, FPFeatures);
return new (Context) BinaryOperator(LHS.get(), RHS.get(), Opc, ResultTy, VK,
OK, OpLoc, FPFeatures);
}
// Handle compound assignments.
if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() !=
OK_ObjCProperty) {
VK = VK_LValue;
OK = LHS.get()->getObjectKind();
}
if (ConvertHalfVec)
return convertHalfVecBinOp(*this, LHS, RHS, Opc, ResultTy, VK, OK, true,
OpLoc, FPFeatures);
return new (Context) CompoundAssignOperator(
LHS.get(), RHS.get(), Opc, ResultTy, VK, OK, CompLHSTy, CompResultTy,
OpLoc, FPFeatures);
}
/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison
/// operators are mixed in a way that suggests that the programmer forgot that
/// comparison operators have higher precedence. The most typical example of
/// such code is "flags & 0x0020 != 0", which is equivalent to "flags & 1".
static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc,
SourceLocation OpLoc, Expr *LHSExpr,
Expr *RHSExpr) {
BinaryOperator *LHSBO = dyn_cast<BinaryOperator>(LHSExpr);
BinaryOperator *RHSBO = dyn_cast<BinaryOperator>(RHSExpr);
// Check that one of the sides is a comparison operator and the other isn't.
bool isLeftComp = LHSBO && LHSBO->isComparisonOp();
bool isRightComp = RHSBO && RHSBO->isComparisonOp();
if (isLeftComp == isRightComp)
return;
// Bitwise operations are sometimes used as eager logical ops.
// Don't diagnose this.
bool isLeftBitwise = LHSBO && LHSBO->isBitwiseOp();
bool isRightBitwise = RHSBO && RHSBO->isBitwiseOp();
if (isLeftBitwise || isRightBitwise)
return;
SourceRange DiagRange = isLeftComp
? SourceRange(LHSExpr->getBeginLoc(), OpLoc)
: SourceRange(OpLoc, RHSExpr->getEndLoc());
StringRef OpStr = isLeftComp ? LHSBO->getOpcodeStr() : RHSBO->getOpcodeStr();
SourceRange ParensRange =
isLeftComp
? SourceRange(LHSBO->getRHS()->getBeginLoc(), RHSExpr->getEndLoc())
: SourceRange(LHSExpr->getBeginLoc(), RHSBO->getLHS()->getEndLoc());
Self.Diag(OpLoc, diag::warn_precedence_bitwise_rel)
<< DiagRange << BinaryOperator::getOpcodeStr(Opc) << OpStr;
SuggestParentheses(Self, OpLoc,
Self.PDiag(diag::note_precedence_silence) << OpStr,
(isLeftComp ? LHSExpr : RHSExpr)->getSourceRange());
SuggestParentheses(Self, OpLoc,
Self.PDiag(diag::note_precedence_bitwise_first)
<< BinaryOperator::getOpcodeStr(Opc),
ParensRange);
}
/// It accepts a '&&' expr that is inside a '||' one.
/// Emit a diagnostic together with a fixit hint that wraps the '&&' expression
/// in parentheses.
static void
EmitDiagnosticForLogicalAndInLogicalOr(Sema &Self, SourceLocation OpLoc,
BinaryOperator *Bop) {
assert(Bop->getOpcode() == BO_LAnd);
Self.Diag(Bop->getOperatorLoc(), diag::warn_logical_and_in_logical_or)
<< Bop->getSourceRange() << OpLoc;
SuggestParentheses(Self, Bop->getOperatorLoc(),
Self.PDiag(diag::note_precedence_silence)
<< Bop->getOpcodeStr(),
Bop->getSourceRange());
}
/// Returns true if the given expression can be evaluated as a constant
/// 'true'.
static bool EvaluatesAsTrue(Sema &S, Expr *E) {
bool Res;
return !E->isValueDependent() &&
E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && Res;
}
/// Returns true if the given expression can be evaluated as a constant
/// 'false'.
static bool EvaluatesAsFalse(Sema &S, Expr *E) {
bool Res;
return !E->isValueDependent() &&
E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && !Res;
}
/// Look for '&&' in the left hand of a '||' expr.
static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc,
Expr *LHSExpr, Expr *RHSExpr) {
if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(LHSExpr)) {
if (Bop->getOpcode() == BO_LAnd) {
// If it's "a && b || 0" don't warn since the precedence doesn't matter.
if (EvaluatesAsFalse(S, RHSExpr))
return;
// If it's "1 && a || b" don't warn since the precedence doesn't matter.
if (!EvaluatesAsTrue(S, Bop->getLHS()))
return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop);
} else if (Bop->getOpcode() == BO_LOr) {
if (BinaryOperator *RBop = dyn_cast<BinaryOperator>(Bop->getRHS())) {
// If it's "a || b && 1 || c" we didn't warn earlier for
// "a || b && 1", but warn now.
if (RBop->getOpcode() == BO_LAnd && EvaluatesAsTrue(S, RBop->getRHS()))
return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, RBop);
}
}
}
}
/// Look for '&&' in the right hand of a '||' expr.
static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc,
Expr *LHSExpr, Expr *RHSExpr) {
if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(RHSExpr)) {
if (Bop->getOpcode() == BO_LAnd) {
// If it's "0 || a && b" don't warn since the precedence doesn't matter.
if (EvaluatesAsFalse(S, LHSExpr))
return;
// If it's "a || b && 1" don't warn since the precedence doesn't matter.
if (!EvaluatesAsTrue(S, Bop->getRHS()))
return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop);
}
}
}
/// Look for bitwise op in the left or right hand of a bitwise op with
/// lower precedence and emit a diagnostic together with a fixit hint that wraps
/// the '&' expression in parentheses.
static void DiagnoseBitwiseOpInBitwiseOp(Sema &S, BinaryOperatorKind Opc,
SourceLocation OpLoc, Expr *SubExpr) {
if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(SubExpr)) {
if (Bop->isBitwiseOp() && Bop->getOpcode() < Opc) {
S.Diag(Bop->getOperatorLoc(), diag::warn_bitwise_op_in_bitwise_op)
<< Bop->getOpcodeStr() << BinaryOperator::getOpcodeStr(Opc)
<< Bop->getSourceRange() << OpLoc;
SuggestParentheses(S, Bop->getOperatorLoc(),
S.PDiag(diag::note_precedence_silence)
<< Bop->getOpcodeStr(),
Bop->getSourceRange());
}
}
}
static void DiagnoseAdditionInShift(Sema &S, SourceLocation OpLoc,
Expr *SubExpr, StringRef Shift) {
if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(SubExpr)) {
if (Bop->getOpcode() == BO_Add || Bop->getOpcode() == BO_Sub) {
StringRef Op = Bop->getOpcodeStr();
S.Diag(Bop->getOperatorLoc(), diag::warn_addition_in_bitshift)
<< Bop->getSourceRange() << OpLoc << Shift << Op;
SuggestParentheses(S, Bop->getOperatorLoc(),
S.PDiag(diag::note_precedence_silence) << Op,
Bop->getSourceRange());
}
}
}
static void DiagnoseShiftCompare(Sema &S, SourceLocation OpLoc,
Expr *LHSExpr, Expr *RHSExpr) {
CXXOperatorCallExpr *OCE = dyn_cast<CXXOperatorCallExpr>(LHSExpr);
if (!OCE)
return;
FunctionDecl *FD = OCE->getDirectCallee();
if (!FD || !FD->isOverloadedOperator())
return;
OverloadedOperatorKind Kind = FD->getOverloadedOperator();
if (Kind != OO_LessLess && Kind != OO_GreaterGreater)
return;
S.Diag(OpLoc, diag::warn_overloaded_shift_in_comparison)
<< LHSExpr->getSourceRange() << RHSExpr->getSourceRange()
<< (Kind == OO_LessLess);
SuggestParentheses(S, OCE->getOperatorLoc(),
S.PDiag(diag::note_precedence_silence)
<< (Kind == OO_LessLess ? "<<" : ">>"),
OCE->getSourceRange());
SuggestParentheses(
S, OpLoc, S.PDiag(diag::note_evaluate_comparison_first),
SourceRange(OCE->getArg(1)->getBeginLoc(), RHSExpr->getEndLoc()));
}
/// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky
/// precedence.
static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc,
SourceLocation OpLoc, Expr *LHSExpr,
Expr *RHSExpr){
// Diagnose "arg1 'bitwise' arg2 'eq' arg3".
if (BinaryOperator::isBitwiseOp(Opc))
DiagnoseBitwisePrecedence(Self, Opc, OpLoc, LHSExpr, RHSExpr);
// Diagnose "arg1 & arg2 | arg3"
if ((Opc == BO_Or || Opc == BO_Xor) &&
!OpLoc.isMacroID()/* Don't warn in macros. */) {
DiagnoseBitwiseOpInBitwiseOp(Self, Opc, OpLoc, LHSExpr);
DiagnoseBitwiseOpInBitwiseOp(Self, Opc, OpLoc, RHSExpr);
}
// Warn about arg1 || arg2 && arg3, as GCC 4.3+ does.
// We don't warn for 'assert(a || b && "bad")' since this is safe.
if (Opc == BO_LOr && !OpLoc.isMacroID()/* Don't warn in macros. */) {
DiagnoseLogicalAndInLogicalOrLHS(Self, OpLoc, LHSExpr, RHSExpr);
DiagnoseLogicalAndInLogicalOrRHS(Self, OpLoc, LHSExpr, RHSExpr);
}
if ((Opc == BO_Shl && LHSExpr->getType()->isIntegralType(Self.getASTContext()))
|| Opc == BO_Shr) {
StringRef Shift = BinaryOperator::getOpcodeStr(Opc);
DiagnoseAdditionInShift(Self, OpLoc, LHSExpr, Shift);
DiagnoseAdditionInShift(Self, OpLoc, RHSExpr, Shift);
}
// Warn on overloaded shift operators and comparisons, such as:
// cout << 5 == 4;
if (BinaryOperator::isComparisonOp(Opc))
DiagnoseShiftCompare(Self, OpLoc, LHSExpr, RHSExpr);
}
// Binary Operators. 'Tok' is the token for the operator.
ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
tok::TokenKind Kind,
Expr *LHSExpr, Expr *RHSExpr) {
BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Kind);
assert(LHSExpr && "ActOnBinOp(): missing left expression");
assert(RHSExpr && "ActOnBinOp(): missing right expression");
// Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0"
DiagnoseBinOpPrecedence(*this, Opc, TokLoc, LHSExpr, RHSExpr);
return BuildBinOp(S, TokLoc, Opc, LHSExpr, RHSExpr);
}
/// Build an overloaded binary operator expression in the given scope.
static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
BinaryOperatorKind Opc,
Expr *LHS, Expr *RHS) {
switch (Opc) {
case BO_Assign:
case BO_DivAssign:
case BO_RemAssign:
case BO_SubAssign:
case BO_AndAssign:
case BO_OrAssign:
case BO_XorAssign:
DiagnoseSelfAssignment(S, LHS, RHS, OpLoc, false);
CheckIdentityFieldAssignment(LHS, RHS, OpLoc, S);
break;
default:
break;
}
// Find all of the overloaded operators visible from this
// point. We perform both an operator-name lookup from the local
// scope and an argument-dependent lookup based on the types of
// the arguments.
UnresolvedSet<16> Functions;
OverloadedOperatorKind OverOp
= BinaryOperator::getOverloadedOperator(Opc);
if (Sc && OverOp != OO_None && OverOp != OO_Equal)
S.LookupOverloadedOperatorName(OverOp, Sc, LHS->getType(),
RHS->getType(), Functions);
// Build the (potentially-overloaded, potentially-dependent)
// binary operation.
return S.CreateOverloadedBinOp(OpLoc, Opc, Functions, LHS, RHS);
}
ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
BinaryOperatorKind Opc,
Expr *LHSExpr, Expr *RHSExpr) {
ExprResult LHS, RHS;
std::tie(LHS, RHS) = CorrectDelayedTyposInBinOp(*this, Opc, LHSExpr, RHSExpr);
if (!LHS.isUsable() || !RHS.isUsable())
return ExprError();
LHSExpr = LHS.get();
RHSExpr = RHS.get();
// We want to end up calling one of checkPseudoObjectAssignment
// (if the LHS is a pseudo-object), BuildOverloadedBinOp (if
// both expressions are overloadable or either is type-dependent),
// or CreateBuiltinBinOp (in any other case). We also want to get
// any placeholder types out of the way.
// Handle pseudo-objects in the LHS.
if (const BuiltinType *pty = LHSExpr->getType()->getAsPlaceholderType()) {
// Assignments with a pseudo-object l-value need special analysis.
if (pty->getKind() == BuiltinType::PseudoObject &&
BinaryOperator::isAssignmentOp(Opc))
return checkPseudoObjectAssignment(S, OpLoc, Opc, LHSExpr, RHSExpr);
// Don't resolve overloads if the other type is overloadable.
if (getLangOpts().CPlusPlus && pty->getKind() == BuiltinType::Overload) {
// We can't actually test that if we still have a placeholder,
// though. Fortunately, none of the exceptions we see in that
// code below are valid when the LHS is an overload set. Note
// that an overload set can be dependently-typed, but it never
// instantiates to having an overloadable type.
ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr);
if (resolvedRHS.isInvalid()) return ExprError();
RHSExpr = resolvedRHS.get();
if (RHSExpr->isTypeDependent() ||
RHSExpr->getType()->isOverloadableType())
return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
}
// If we're instantiating "a.x < b" or "A::x < b" and 'x' names a function
// template, diagnose the missing 'template' keyword instead of diagnosing
// an invalid use of a bound member function.
//
// Note that "A::x < b" might be valid if 'b' has an overloadable type due
// to C++1z [over.over]/1.4, but we already checked for that case above.
if (Opc == BO_LT && inTemplateInstantiation() &&
(pty->getKind() == BuiltinType::BoundMember ||
pty->getKind() == BuiltinType::Overload)) {
auto *OE = dyn_cast<OverloadExpr>(LHSExpr);
if (OE && !OE->hasTemplateKeyword() && !OE->hasExplicitTemplateArgs() &&
std::any_of(OE->decls_begin(), OE->decls_end(), [](NamedDecl *ND) {
return isa<FunctionTemplateDecl>(ND);
})) {
Diag(OE->getQualifier() ? OE->getQualifierLoc().getBeginLoc()
: OE->getNameLoc(),
diag::err_template_kw_missing)
<< OE->getName().getAsString() << "";
return ExprError();
}
}
ExprResult LHS = CheckPlaceholderExpr(LHSExpr);
if (LHS.isInvalid()) return ExprError();
LHSExpr = LHS.get();
}
// Handle pseudo-objects in the RHS.
if (const BuiltinType *pty = RHSExpr->getType()->getAsPlaceholderType()) {
// An overload in the RHS can potentially be resolved by the type
// being assigned to.
if (Opc == BO_Assign && pty->getKind() == BuiltinType::Overload) {
if (getLangOpts().CPlusPlus &&
(LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent() ||
LHSExpr->getType()->isOverloadableType()))
return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr);
}
// Don't resolve overloads if the other type is overloadable.
if (getLangOpts().CPlusPlus && pty->getKind() == BuiltinType::Overload &&
LHSExpr->getType()->isOverloadableType())
return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr);
if (!resolvedRHS.isUsable()) return ExprError();
RHSExpr = resolvedRHS.get();
}
if (getLangOpts().CPlusPlus) {
// If either expression is type-dependent, always build an
// overloaded op.
if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent())
return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
// Otherwise, build an overloaded op if either expression has an
// overloadable type.
if (LHSExpr->getType()->isOverloadableType() ||
RHSExpr->getType()->isOverloadableType())
return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
}
// Build a built-in binary operation.
return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr);
}
static bool isOverflowingIntegerType(ASTContext &Ctx, QualType T) {
if (T.isNull() || T->isDependentType())
return false;
if (!T->isPromotableIntegerType())
return true;
return Ctx.getIntWidth(T) >= Ctx.getIntWidth(Ctx.IntTy);
}
ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
UnaryOperatorKind Opc,
Expr *InputExpr) {
ExprResult Input = InputExpr;
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
QualType resultType;
bool CanOverflow = false;
bool ConvertHalfVec = false;
if (getLangOpts().OpenCL) {
QualType Ty = InputExpr->getType();
// The only legal unary operation for atomics is '&'.
if ((Opc != UO_AddrOf && Ty->isAtomicType()) ||
// OpenCL special types - image, sampler, pipe, and blocks are to be used
// only with a builtin functions and therefore should be disallowed here.
(Ty->isImageType() || Ty->isSamplerT() || Ty->isPipeType()
|| Ty->isBlockPointerType())) {
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< InputExpr->getType()
<< Input.get()->getSourceRange());
}
}
switch (Opc) {
case UO_PreInc:
case UO_PreDec:
case UO_PostInc:
case UO_PostDec:
resultType = CheckIncrementDecrementOperand(*this, Input.get(), VK, OK,
OpLoc,
Opc == UO_PreInc ||
Opc == UO_PostInc,
Opc == UO_PreInc ||
Opc == UO_PreDec);
CanOverflow = isOverflowingIntegerType(Context, resultType);
break;
case UO_AddrOf:
resultType = CheckAddressOfOperand(Input, OpLoc);
CheckAddressOfNoDeref(InputExpr);
RecordModifiableNonNullParam(*this, InputExpr);
break;
case UO_Deref: {
Input = DefaultFunctionArrayLvalueConversion(Input.get());
if (Input.isInvalid()) return ExprError();
resultType = CheckIndirectionOperand(*this, Input.get(), VK, OpLoc);
break;
}
case UO_Plus:
case UO_Minus:
CanOverflow = Opc == UO_Minus &&
isOverflowingIntegerType(Context, Input.get()->getType());
Input = UsualUnaryConversions(Input.get());
if (Input.isInvalid()) return ExprError();
// Unary plus and minus require promoting an operand of half vector to a
// float vector and truncating the result back to a half vector. For now, we
// do this only when HalfArgsAndReturns is set (that is, when the target is
// arm or arm64).
ConvertHalfVec =
needsConversionOfHalfVec(true, Context, Input.get()->getType());
// If the operand is a half vector, promote it to a float vector.
if (ConvertHalfVec)
Input = convertVector(Input.get(), Context.FloatTy, *this);
resultType = Input.get()->getType();
if (resultType->isDependentType())
break;
if (resultType->isArithmeticType()) // C99 6.5.3.3p1
break;
else if (resultType->isVectorType() &&
// The z vector extensions don't allow + or - with bool vectors.
(!Context.getLangOpts().ZVector ||
resultType->getAs<VectorType>()->getVectorKind() !=
VectorType::AltiVecBool))
break;
else if (getLangOpts().CPlusPlus && // C++ [expr.unary.op]p6
Opc == UO_Plus &&
resultType->isPointerType())
break;
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< resultType << Input.get()->getSourceRange());
case UO_Not: // bitwise complement
Input = UsualUnaryConversions(Input.get());
if (Input.isInvalid())
return ExprError();
resultType = Input.get()->getType();
if (resultType->isDependentType())
break;
// C99 6.5.3.3p1. We allow complex int and float as a GCC extension.
if (resultType->isComplexType() || resultType->isComplexIntegerType())
// C99 does not support '~' for complex conjugation.
Diag(OpLoc, diag::ext_integer_complement_complex)
<< resultType << Input.get()->getSourceRange();
else if (resultType->hasIntegerRepresentation())
break;
else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) {
// OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate
// on vector float types.
QualType T = resultType->getAs<ExtVectorType>()->getElementType();
if (!T->isIntegerType())
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< resultType << Input.get()->getSourceRange());
} else {
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< resultType << Input.get()->getSourceRange());
}
break;
case UO_LNot: // logical negation
// Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5).
Input = DefaultFunctionArrayLvalueConversion(Input.get());
if (Input.isInvalid()) return ExprError();
resultType = Input.get()->getType();
// Though we still have to promote half FP to float...
if (resultType->isHalfType() && !Context.getLangOpts().NativeHalfType) {
Input = ImpCastExprToType(Input.get(), Context.FloatTy, CK_FloatingCast).get();
resultType = Context.FloatTy;
}
if (resultType->isDependentType())
break;
if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) {
// C99 6.5.3.3p1: ok, fallthrough;
if (Context.getLangOpts().CPlusPlus) {
// C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9:
// operand contextually converted to bool.
Input = ImpCastExprToType(Input.get(), Context.BoolTy,
ScalarTypeToBooleanCastKind(resultType));
} else if (Context.getLangOpts().OpenCL &&
Context.getLangOpts().OpenCLVersion < 120) {
// OpenCL v1.1 6.3.h: The logical operator not (!) does not
// operate on scalar float types.
if (!resultType->isIntegerType() && !resultType->isPointerType())
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< resultType << Input.get()->getSourceRange());
}
} else if (resultType->isExtVectorType()) {
if (Context.getLangOpts().OpenCL &&
Context.getLangOpts().OpenCLVersion < 120) {
// OpenCL v1.1 6.3.h: The logical operator not (!) does not
// operate on vector float types.
QualType T = resultType->getAs<ExtVectorType>()->getElementType();
if (!T->isIntegerType())
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< resultType << Input.get()->getSourceRange());
}
// Vector logical not returns the signed variant of the operand type.
resultType = GetSignedVectorType(resultType);
break;
} else {
// FIXME: GCC's vector extension permits the usage of '!' with a vector
// type in C++. We should allow that here too.
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
<< resultType << Input.get()->getSourceRange());
}
// LNot always has type int. C99 6.5.3.3p5.
// In C++, it's bool. C++ 5.3.1p8
resultType = Context.getLogicalOperationType();
break;
case UO_Real:
case UO_Imag:
resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real);
// _Real maps ordinary l-values into ordinary l-values. _Imag maps ordinary
// complex l-values to ordinary l-values and all other values to r-values.
if (Input.isInvalid()) return ExprError();
if (Opc == UO_Real || Input.get()->getType()->isAnyComplexType()) {
if (Input.get()->getValueKind() != VK_RValue &&
Input.get()->getObjectKind() == OK_Ordinary)
VK = Input.get()->getValueKind();
} else if (!getLangOpts().CPlusPlus) {
// In C, a volatile scalar is read by __imag. In C++, it is not.
Input = DefaultLvalueConversion(Input.get());
}
break;
case UO_Extension:
resultType = Input.get()->getType();
VK = Input.get()->getValueKind();
OK = Input.get()->getObjectKind();
break;
case UO_Coawait:
// It's unnecessary to represent the pass-through operator co_await in the
// AST; just return the input expression instead.
assert(!Input.get()->getType()->isDependentType() &&
"the co_await expression must be non-dependant before "
"building operator co_await");
return Input;
}
if (resultType.isNull() || Input.isInvalid())
return ExprError();
// Check for array bounds violations in the operand of the UnaryOperator,
// except for the '*' and '&' operators that have to be handled specially
// by CheckArrayAccess (as there are special cases like &array[arraysize]
// that are explicitly defined as valid by the standard).
if (Opc != UO_AddrOf && Opc != UO_Deref)
CheckArrayAccess(Input.get());
auto *UO = new (Context)
UnaryOperator(Input.get(), Opc, resultType, VK, OK, OpLoc, CanOverflow);
if (Opc == UO_Deref && UO->getType()->hasAttr(attr::NoDeref) &&
!isa<ArrayType>(UO->getType().getDesugaredType(Context)))
ExprEvalContexts.back().PossibleDerefs.insert(UO);
// Convert the result back to a half vector.
if (ConvertHalfVec)
return convertVector(UO, Context.HalfTy, *this);
return UO;
}
/// Determine whether the given expression is a qualified member
/// access expression, of a form that could be turned into a pointer to member
/// with the address-of operator.
bool Sema::isQualifiedMemberAccess(Expr *E) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
if (!DRE->getQualifier())
return false;
ValueDecl *VD = DRE->getDecl();
if (!VD->isCXXClassMember())
return false;
if (isa<FieldDecl>(VD) || isa<IndirectFieldDecl>(VD))
return true;
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(VD))
return Method->isInstance();
return false;
}
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
if (!ULE->getQualifier())
return false;
for (NamedDecl *D : ULE->decls()) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
if (Method->isInstance())
return true;
} else {
// Overload set does not contain methods.
break;
}
}
return false;
}
return false;
}
ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
UnaryOperatorKind Opc, Expr *Input) {
// First things first: handle placeholders so that the
// overloaded-operator check considers the right type.
if (const BuiltinType *pty = Input->getType()->getAsPlaceholderType()) {
// Increment and decrement of pseudo-object references.
if (pty->getKind() == BuiltinType::PseudoObject &&
UnaryOperator::isIncrementDecrementOp(Opc))
return checkPseudoObjectIncDec(S, OpLoc, Opc, Input);
// extension is always a builtin operator.
if (Opc == UO_Extension)
return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
// & gets special logic for several kinds of placeholder.
// The builtin code knows what to do.
if (Opc == UO_AddrOf &&
(pty->getKind() == BuiltinType::Overload ||
pty->getKind() == BuiltinType::UnknownAny ||
pty->getKind() == BuiltinType::BoundMember))
return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
// Anything else needs to be handled now.
ExprResult Result = CheckPlaceholderExpr(Input);
if (Result.isInvalid()) return ExprError();
Input = Result.get();
}
if (getLangOpts().CPlusPlus && Input->getType()->isOverloadableType() &&
UnaryOperator::getOverloadedOperator(Opc) != OO_None &&
!(Opc == UO_AddrOf && isQualifiedMemberAccess(Input))) {
// Find all of the overloaded operators visible from this
// point. We perform both an operator-name lookup from the local
// scope and an argument-dependent lookup based on the types of
// the arguments.
UnresolvedSet<16> Functions;
OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc);
if (S && OverOp != OO_None)
LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
Functions);
return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, Input);
}
return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
}
// Unary Operators. 'Tok' is the token for the operator.
ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
tok::TokenKind Op, Expr *Input) {
return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), Input);
}
/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
LabelDecl *TheDecl) {
TheDecl->markUsed(Context);
// Create the AST node. The address of a label always has type 'void*'.
return new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl,
Context.getPointerType(Context.VoidTy));
}
/// Given the last statement in a statement-expression, check whether
/// the result is a producing expression (like a call to an
/// ns_returns_retained function) and, if so, rebuild it to hoist the
/// release out of the full-expression. Otherwise, return null.
/// Cannot fail.
static Expr *maybeRebuildARCConsumingStmt(Stmt *Statement) {
// Should always be wrapped with one of these.
ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(Statement);
if (!cleanups) return nullptr;
ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(cleanups->getSubExpr());
if (!cast || cast->getCastKind() != CK_ARCConsumeObject)
return nullptr;
// Splice out the cast. This shouldn't modify any interesting
// features of the statement.
Expr *producer = cast->getSubExpr();
assert(producer->getType() == cast->getType());
assert(producer->getValueKind() == cast->getValueKind());
cleanups->setSubExpr(producer);
return cleanups;
}
void Sema::ActOnStartStmtExpr() {
PushExpressionEvaluationContext(ExprEvalContexts.back().Context);
}
void Sema::ActOnStmtExprError() {
// Note that function is also called by TreeTransform when leaving a
// StmtExpr scope without rebuilding anything.
DiscardCleanupsInEvaluationContext();
PopExpressionEvaluationContext();
}
ExprResult
Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
SourceLocation RPLoc) { // "({..})"
assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!");
CompoundStmt *Compound = cast<CompoundStmt>(SubStmt);
if (hasAnyUnrecoverableErrorsInThisFunction())
DiscardCleanupsInEvaluationContext();
assert(!Cleanup.exprNeedsCleanups() &&
"cleanups within StmtExpr not correctly bound!");
PopExpressionEvaluationContext();
// FIXME: there are a variety of strange constraints to enforce here, for
// example, it is not possible to goto into a stmt expression apparently.
// More semantic analysis is needed.
// If there are sub-stmts in the compound stmt, take the type of the last one
// as the type of the stmtexpr.
QualType Ty = Context.VoidTy;
bool StmtExprMayBindToTemp = false;
if (!Compound->body_empty()) {
Stmt *LastStmt = Compound->body_back();
LabelStmt *LastLabelStmt = nullptr;
// If LastStmt is a label, skip down through into the body.
while (LabelStmt *Label = dyn_cast<LabelStmt>(LastStmt)) {
LastLabelStmt = Label;
LastStmt = Label->getSubStmt();
}
if (Expr *LastE = dyn_cast<Expr>(LastStmt)) {
// Do function/array conversion on the last expression, but not
// lvalue-to-rvalue. However, initialize an unqualified type.
ExprResult LastExpr = DefaultFunctionArrayConversion(LastE);
if (LastExpr.isInvalid())
return ExprError();
Ty = LastExpr.get()->getType().getUnqualifiedType();
if (!Ty->isDependentType() && !LastExpr.get()->isTypeDependent()) {
// In ARC, if the final expression ends in a consume, splice
// the consume out and bind it later. In the alternate case
// (when dealing with a retainable type), the result
// initialization will create a produce. In both cases the
// result will be +1, and we'll need to balance that out with
// a bind.
if (Expr *rebuiltLastStmt
= maybeRebuildARCConsumingStmt(LastExpr.get())) {
LastExpr = rebuiltLastStmt;
} else {
LastExpr = PerformCopyInitialization(
InitializedEntity::InitializeStmtExprResult(LPLoc, Ty),
SourceLocation(), LastExpr);
}
if (LastExpr.isInvalid())
return ExprError();
if (LastExpr.get() != nullptr) {
if (!LastLabelStmt)
Compound->setLastStmt(LastExpr.get());
else
LastLabelStmt->setSubStmt(LastExpr.get());
StmtExprMayBindToTemp = true;
}
}
}
}
// FIXME: Check that expression type is complete/non-abstract; statement
// expressions are not lvalues.
Expr *ResStmtExpr = new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc);
if (StmtExprMayBindToTemp)
return MaybeBindToTemporary(ResStmtExpr);
return ResStmtExpr;
}
ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
TypeSourceInfo *TInfo,
ArrayRef<OffsetOfComponent> Components,
SourceLocation RParenLoc) {
QualType ArgTy = TInfo->getType();
bool Dependent = ArgTy->isDependentType();
SourceRange TypeRange = TInfo->getTypeLoc().getLocalSourceRange();
// We must have at least one component that refers to the type, and the first
// one is known to be a field designator. Verify that the ArgTy represents
// a struct/union/class.
if (!Dependent && !ArgTy->isRecordType())
return ExprError(Diag(BuiltinLoc, diag::err_offsetof_record_type)
<< ArgTy << TypeRange);
// Type must be complete per C99 7.17p3 because a declaring a variable
// with an incomplete type would be ill-formed.
if (!Dependent
&& RequireCompleteType(BuiltinLoc, ArgTy,
diag::err_offsetof_incomplete_type, TypeRange))
return ExprError();
bool DidWarnAboutNonPOD = false;
QualType CurrentType = ArgTy;
SmallVector<OffsetOfNode, 4> Comps;
SmallVector<Expr*, 4> Exprs;
for (const OffsetOfComponent &OC : Components) {
if (OC.isBrackets) {
// Offset of an array sub-field. TODO: Should we allow vector elements?
if (!CurrentType->isDependentType()) {
const ArrayType *AT = Context.getAsArrayType(CurrentType);
if(!AT)
return ExprError(Diag(OC.LocEnd, diag::err_offsetof_array_type)
<< CurrentType);
CurrentType = AT->getElementType();
} else
CurrentType = Context.DependentTy;
ExprResult IdxRval = DefaultLvalueConversion(static_cast<Expr*>(OC.U.E));
if (IdxRval.isInvalid())
return ExprError();
Expr *Idx = IdxRval.get();
// The expression must be an integral expression.
// FIXME: An integral constant expression?
if (!Idx->isTypeDependent() && !Idx->isValueDependent() &&
!Idx->getType()->isIntegerType())
return ExprError(
Diag(Idx->getBeginLoc(), diag::err_typecheck_subscript_not_integer)
<< Idx->getSourceRange());
// Record this array index.
Comps.push_back(OffsetOfNode(OC.LocStart, Exprs.size(), OC.LocEnd));
Exprs.push_back(Idx);
continue;
}
// Offset of a field.
if (CurrentType->isDependentType()) {
// We have the offset of a field, but we can't look into the dependent
// type. Just record the identifier of the field.
Comps.push_back(OffsetOfNode(OC.LocStart, OC.U.IdentInfo, OC.LocEnd));
CurrentType = Context.DependentTy;
continue;
}
// We need to have a complete type to look into.
if (RequireCompleteType(OC.LocStart, CurrentType,
diag::err_offsetof_incomplete_type))
return ExprError();
// Look for the designated field.
const RecordType *RC = CurrentType->getAs<RecordType>();
if (!RC)
return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type)
<< CurrentType);
RecordDecl *RD = RC->getDecl();
// C++ [lib.support.types]p5:
// The macro offsetof accepts a restricted set of type arguments in this
// International Standard. type shall be a POD structure or a POD union
// (clause 9).
// C++11 [support.types]p4:
// If type is not a standard-layout class (Clause 9), the results are
// undefined.
if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
bool IsSafe = LangOpts.CPlusPlus11? CRD->isStandardLayout() : CRD->isPOD();
unsigned DiagID =
LangOpts.CPlusPlus11? diag::ext_offsetof_non_standardlayout_type
: diag::ext_offsetof_non_pod_type;
if (!IsSafe && !DidWarnAboutNonPOD &&
DiagRuntimeBehavior(BuiltinLoc, nullptr,
PDiag(DiagID)
<< SourceRange(Components[0].LocStart, OC.LocEnd)
<< CurrentType))
DidWarnAboutNonPOD = true;
}
// Look for the field.
LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);
LookupQualifiedName(R, RD);
FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>();
IndirectFieldDecl *IndirectMemberDecl = nullptr;
if (!MemberDecl) {
if ((IndirectMemberDecl = R.getAsSingle<IndirectFieldDecl>()))
MemberDecl = IndirectMemberDecl->getAnonField();
}
if (!MemberDecl)
return ExprError(Diag(BuiltinLoc, diag::err_no_member)
<< OC.U.IdentInfo << RD << SourceRange(OC.LocStart,
OC.LocEnd));
// C99 7.17p3:
// (If the specified member is a bit-field, the behavior is undefined.)
//
// We diagnose this as an error.
if (MemberDecl->isBitField()) {
Diag(OC.LocEnd, diag::err_offsetof_bitfield)
<< MemberDecl->getDeclName()
<< SourceRange(BuiltinLoc, RParenLoc);
Diag(MemberDecl->getLocation(), diag::note_bitfield_decl);
return ExprError();
}
RecordDecl *Parent = MemberDecl->getParent();
if (IndirectMemberDecl)
Parent = cast<RecordDecl>(IndirectMemberDecl->getDeclContext());
// If the member was found in a base class, introduce OffsetOfNodes for
// the base class indirections.
CXXBasePaths Paths;
if (IsDerivedFrom(OC.LocStart, CurrentType, Context.getTypeDeclType(Parent),
Paths)) {
if (Paths.getDetectedVirtual()) {
Diag(OC.LocEnd, diag::err_offsetof_field_of_virtual_base)
<< MemberDecl->getDeclName()
<< SourceRange(BuiltinLoc, RParenLoc);
return ExprError();
}
CXXBasePath &Path = Paths.front();
for (const CXXBasePathElement &B : Path)
Comps.push_back(OffsetOfNode(B.Base));
}
if (IndirectMemberDecl) {
for (auto *FI : IndirectMemberDecl->chain()) {
assert(isa<FieldDecl>(FI));
Comps.push_back(OffsetOfNode(OC.LocStart,
cast<FieldDecl>(FI), OC.LocEnd));
}
} else
Comps.push_back(OffsetOfNode(OC.LocStart, MemberDecl, OC.LocEnd));
CurrentType = MemberDecl->getType().getNonReferenceType();
}
return OffsetOfExpr::Create(Context, Context.getSizeType(), BuiltinLoc, TInfo,
Comps, Exprs, RParenLoc);
}
ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
SourceLocation BuiltinLoc,
SourceLocation TypeLoc,
ParsedType ParsedArgTy,
ArrayRef<OffsetOfComponent> Components,
SourceLocation RParenLoc) {
TypeSourceInfo *ArgTInfo;
QualType ArgTy = GetTypeFromParser(ParsedArgTy, &ArgTInfo);
if (ArgTy.isNull())
return ExprError();
if (!ArgTInfo)
ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc);
return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, Components, RParenLoc);
}
ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc,
Expr *CondExpr,
Expr *LHSExpr, Expr *RHSExpr,
SourceLocation RPLoc) {
assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)");
ExprValueKind VK = VK_RValue;
ExprObjectKind OK = OK_Ordinary;
QualType resType;
bool ValueDependent = false;
bool CondIsTrue = false;
if (CondExpr->isTypeDependent() || CondExpr->isValueDependent()) {
resType = Context.DependentTy;
ValueDependent = true;
} else {
// The conditional expression is required to be a constant expression.
llvm::APSInt condEval(32);
ExprResult CondICE
= VerifyIntegerConstantExpression(CondExpr, &condEval,
diag::err_typecheck_choose_expr_requires_constant, false);
if (CondICE.isInvalid())
return ExprError();
CondExpr = CondICE.get();
CondIsTrue = condEval.getZExtValue();
// If the condition is > zero, then the AST type is the same as the LHSExpr.
Expr *ActiveExpr = CondIsTrue ? LHSExpr : RHSExpr;
resType = ActiveExpr->getType();
ValueDependent = ActiveExpr->isValueDependent();
VK = ActiveExpr->getValueKind();
OK = ActiveExpr->getObjectKind();
}
return new (Context)
ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, resType, VK, OK, RPLoc,
CondIsTrue, resType->isDependentType(), ValueDependent);
}
//===----------------------------------------------------------------------===//
// Clang Extensions.
//===----------------------------------------------------------------------===//
/// ActOnBlockStart - This callback is invoked when a block literal is started.
void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {
BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc);
if (LangOpts.CPlusPlus) {
Decl *ManglingContextDecl;
if (MangleNumberingContext *MCtx =
getCurrentMangleNumberContext(Block->getDeclContext(),
ManglingContextDecl)) {
unsigned ManglingNumber = MCtx->getManglingNumber(Block);
Block->setBlockMangling(ManglingNumber, ManglingContextDecl);
}
}
PushBlockScope(CurScope, Block);
CurContext->addDecl(Block);
if (CurScope)
PushDeclContext(CurScope, Block);
else
CurContext = Block;
getCurBlock()->HasImplicitReturnType = true;
// Enter a new evaluation context to insulate the block from any
// cleanups from the enclosing full-expression.
PushExpressionEvaluationContext(
ExpressionEvaluationContext::PotentiallyEvaluated);
}
void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
Scope *CurScope) {
assert(ParamInfo.getIdentifier() == nullptr &&
"block-id should have no identifier!");
assert(ParamInfo.getContext() == DeclaratorContext::BlockLiteralContext);
BlockScopeInfo *CurBlock = getCurBlock();
TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo, CurScope);
QualType T = Sig->getType();
// FIXME: We should allow unexpanded parameter packs here, but that would,
// in turn, make the block expression contain unexpanded parameter packs.
if (DiagnoseUnexpandedParameterPack(CaretLoc, Sig, UPPC_Block)) {
// Drop the parameters.
FunctionProtoType::ExtProtoInfo EPI;
EPI.HasTrailingReturn = false;
EPI.TypeQuals.addConst();
T = Context.getFunctionType(Context.DependentTy, None, EPI);
Sig = Context.getTrivialTypeSourceInfo(T);
}
// GetTypeForDeclarator always produces a function type for a block
// literal signature. Furthermore, it is always a FunctionProtoType
// unless the function was written with a typedef.
assert(T->isFunctionType() &&
"GetTypeForDeclarator made a non-function block signature");
// Look for an explicit signature in that function type.
FunctionProtoTypeLoc ExplicitSignature;
if ((ExplicitSignature =
Sig->getTypeLoc().getAsAdjusted<FunctionProtoTypeLoc>())) {
// Check whether that explicit signature was synthesized by
// GetTypeForDeclarator. If so, don't save that as part of the
// written signature.
if (ExplicitSignature.getLocalRangeBegin() ==
ExplicitSignature.getLocalRangeEnd()) {
// This would be much cheaper if we stored TypeLocs instead of
// TypeSourceInfos.
TypeLoc Result = ExplicitSignature.getReturnLoc();
unsigned Size = Result.getFullDataSize();
Sig = Context.CreateTypeSourceInfo(Result.getType(), Size);
Sig->getTypeLoc().initializeFullCopy(Result, Size);
ExplicitSignature = FunctionProtoTypeLoc();
}
}
CurBlock->TheDecl->setSignatureAsWritten(Sig);
CurBlock->FunctionType = T;
const FunctionType *Fn = T->getAs<FunctionType>();
QualType RetTy = Fn->getReturnType();
bool isVariadic =
(isa<FunctionProtoType>(Fn) && cast<FunctionProtoType>(Fn)->isVariadic());
CurBlock->TheDecl->setIsVariadic(isVariadic);
// Context.DependentTy is used as a placeholder for a missing block
// return type. TODO: what should we do with declarators like:
// ^ * { ... }
// If the answer is "apply template argument deduction"....
if (RetTy != Context.DependentTy) {
CurBlock->ReturnType = RetTy;
CurBlock->TheDecl->setBlockMissingReturnType(false);
CurBlock->HasImplicitReturnType = false;
}
// Push block parameters from the declarator if we had them.
SmallVector<ParmVarDecl*, 8> Params;
if (ExplicitSignature) {
for (unsigned I = 0, E = ExplicitSignature.getNumParams(); I != E; ++I) {
ParmVarDecl *Param = ExplicitSignature.getParam(I);
if (Param->getIdentifier() == nullptr &&
!Param->isImplicit() &&
!Param->isInvalidDecl() &&
!getLangOpts().CPlusPlus)
Diag(Param->getLocation(), diag::err_parameter_name_omitted);
Params.push_back(Param);
}
// Fake up parameter variables if we have a typedef, like
// ^ fntype { ... }
} else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) {
for (const auto &I : Fn->param_types()) {
ParmVarDecl *Param = BuildParmVarDeclForTypedef(
CurBlock->TheDecl, ParamInfo.getBeginLoc(), I);
Params.push_back(Param);
}
}
// Set the parameters on the block decl.
if (!Params.empty()) {
CurBlock->TheDecl->setParams(Params);
CheckParmsForFunctionDef(CurBlock->TheDecl->parameters(),
/*CheckParameterNames=*/false);
}
// Finally we can process decl attributes.
ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
// Put the parameter variables in scope.
for (auto AI : CurBlock->TheDecl->parameters()) {
AI->setOwningFunction(CurBlock->TheDecl);
// If this has an identifier, add it to the scope stack.
if (AI->getIdentifier()) {
CheckShadow(CurBlock->TheScope, AI);
PushOnScopeChains(AI, CurBlock->TheScope);
}
}
}
/// ActOnBlockError - If there is an error parsing a block, this callback
/// is invoked to pop the information about the block from the action impl.
void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {
// Leave the expression-evaluation context.
DiscardCleanupsInEvaluationContext();
PopExpressionEvaluationContext();
// Pop off CurBlock, handle nested blocks.
PopDeclContext();
PopFunctionScopeInfo();
}
/// ActOnBlockStmtExpr - This is called when the body of a block statement
/// literal was successfully completed. ^(int x){...}
ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
Stmt *Body, Scope *CurScope) {
// If blocks are disabled, emit an error.
if (!LangOpts.Blocks)
Diag(CaretLoc, diag::err_blocks_disable) << LangOpts.OpenCL;
// Leave the expression-evaluation context.
if (hasAnyUnrecoverableErrorsInThisFunction())
DiscardCleanupsInEvaluationContext();
assert(!Cleanup.exprNeedsCleanups() &&
"cleanups within block not correctly bound!");
PopExpressionEvaluationContext();
BlockScopeInfo *BSI = cast<BlockScopeInfo>(FunctionScopes.back());
BlockDecl *BD = BSI->TheDecl;
if (BSI->HasImplicitReturnType)
deduceClosureReturnType(*BSI);
PopDeclContext();
QualType RetTy = Context.VoidTy;
if (!BSI->ReturnType.isNull())
RetTy = BSI->ReturnType;
bool NoReturn = BD->hasAttr<NoReturnAttr>();
QualType BlockTy;
// Set the captured variables on the block.
// FIXME: Share capture structure between BlockDecl and CapturingScopeInfo!
SmallVector<BlockDecl::Capture, 4> Captures;
for (Capture &Cap : BSI->Captures) {
if (Cap.isThisCapture())
continue;
BlockDecl::Capture NewCap(Cap.getVariable(), Cap.isBlockCapture(),
Cap.isNested(), Cap.getInitExpr());
Captures.push_back(NewCap);
}
BD->setCaptures(Context, Captures, BSI->CXXThisCaptureIndex != 0);
// If the user wrote a function type in some form, try to use that.
if (!BSI->FunctionType.isNull()) {
const FunctionType *FTy = BSI->FunctionType->getAs<FunctionType>();
FunctionType::ExtInfo Ext = FTy->getExtInfo();
if (NoReturn && !Ext.getNoReturn()) Ext = Ext.withNoReturn(true);
// Turn protoless block types into nullary block types.
if (isa<FunctionNoProtoType>(FTy)) {
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExtInfo = Ext;
BlockTy = Context.getFunctionType(RetTy, None, EPI);
// Otherwise, if we don't need to change anything about the function type,
// preserve its sugar structure.
} else if (FTy->getReturnType() == RetTy &&
(!NoReturn || FTy->getNoReturnAttr())) {
BlockTy = BSI->FunctionType;
// Otherwise, make the minimal modifications to the function type.
} else {
const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy);
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals = Qualifiers();
EPI.ExtInfo = Ext;
BlockTy = Context.getFunctionType(RetTy, FPT->getParamTypes(), EPI);
}
// If we don't have a function type, just build one from nothing.
} else {
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExtInfo = FunctionType::ExtInfo().withNoReturn(NoReturn);
BlockTy = Context.getFunctionType(RetTy, None, EPI);
}
DiagnoseUnusedParameters(BD->parameters());
BlockTy = Context.getBlockPointerType(BlockTy);
// If needed, diagnose invalid gotos and switches in the block.
if (getCurFunction()->NeedsScopeChecking() &&
!PP.isCodeCompletionEnabled())
DiagnoseInvalidJumps(cast<CompoundStmt>(Body));
BD->setBody(cast<CompoundStmt>(Body));
if (Body && getCurFunction()->HasPotentialAvailabilityViolations)
DiagnoseUnguardedAvailabilityViolations(BD);
// Try to apply the named return value optimization. We have to check again
// if we can do this, though, because blocks keep return statements around
// to deduce an implicit return type.
if (getLangOpts().CPlusPlus && RetTy->isRecordType() &&
!BD->isDependentContext())
computeNRVO(Body, BSI);
BlockExpr *Result = new (Context) BlockExpr(BD, BlockTy);
AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
PopFunctionScopeInfo(&WP, Result->getBlockDecl(), Result);
// If the block isn't obviously global, i.e. it captures anything at
// all, then we need to do a few things in the surrounding context:
if (Result->getBlockDecl()->hasCaptures()) {
// First, this expression has a new cleanup object.
ExprCleanupObjects.push_back(Result->getBlockDecl());
Cleanup.setExprNeedsCleanups(true);
// It also gets a branch-protected scope if any of the captured
// variables needs destruction.
for (const auto &CI : Result->getBlockDecl()->captures()) {
const VarDecl *var = CI.getVariable();
if (var->getType().isDestructedType() != QualType::DK_none) {
setFunctionHasBranchProtectedScope();
break;
}
}
}
if (getCurFunction())
getCurFunction()->addBlock(BD);
return Result;
}
ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc, Expr *E, ParsedType Ty,
SourceLocation RPLoc) {
TypeSourceInfo *TInfo;
GetTypeFromParser(Ty, &TInfo);
return BuildVAArgExpr(BuiltinLoc, E, TInfo, RPLoc);
}
ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc,
Expr *E, TypeSourceInfo *TInfo,
SourceLocation RPLoc) {
Expr *OrigExpr = E;
bool IsMS = false;
// CUDA device code does not support varargs.
if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) {
if (const FunctionDecl *F = dyn_cast<FunctionDecl>(CurContext)) {
CUDAFunctionTarget T = IdentifyCUDATarget(F);
if (T == CFT_Global || T == CFT_Device || T == CFT_HostDevice)
return ExprError(Diag(E->getBeginLoc(), diag::err_va_arg_in_device));
}
}
// It might be a __builtin_ms_va_list. (But don't ever mark a va_arg()
// as Microsoft ABI on an actual Microsoft platform, where
// __builtin_ms_va_list and __builtin_va_list are the same.)
if (!E->isTypeDependent() && Context.getTargetInfo().hasBuiltinMSVaList() &&
Context.getTargetInfo().getBuiltinVaListKind() != TargetInfo::CharPtrBuiltinVaList) {
QualType MSVaListType = Context.getBuiltinMSVaListType();
if (Context.hasSameType(MSVaListType, E->getType())) {
if (CheckForModifiableLvalue(E, BuiltinLoc, *this))
return ExprError();
IsMS = true;
}
}
// Get the va_list type
QualType VaListType = Context.getBuiltinVaListType();
if (!IsMS) {
if (VaListType->isArrayType()) {
// Deal with implicit array decay; for example, on x86-64,
// va_list is an array, but it's supposed to decay to
// a pointer for va_arg.
VaListType = Context.getArrayDecayedType(VaListType);
// Make sure the input expression also decays appropriately.
ExprResult Result = UsualUnaryConversions(E);
if (Result.isInvalid())
return ExprError();
E = Result.get();
} else if (VaListType->isRecordType() && getLangOpts().CPlusPlus) {
// If va_list is a record type and we are compiling in C++ mode,
// check the argument using reference binding.
InitializedEntity Entity = InitializedEntity::InitializeParameter(
Context, Context.getLValueReferenceType(VaListType), false);
ExprResult Init = PerformCopyInitialization(Entity, SourceLocation(), E);
if (Init.isInvalid())
return ExprError();
E = Init.getAs<Expr>();
} else {
// Otherwise, the va_list argument must be an l-value because
// it is modified by va_arg.
if (!E->isTypeDependent() &&
CheckForModifiableLvalue(E, BuiltinLoc, *this))
return ExprError();
}
}
if (!IsMS && !E->isTypeDependent() &&
!Context.hasSameType(VaListType, E->getType()))
return ExprError(
Diag(E->getBeginLoc(),
diag::err_first_argument_to_va_arg_not_of_type_va_list)
<< OrigExpr->getType() << E->getSourceRange());
if (!TInfo->getType()->isDependentType()) {
if (RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), TInfo->getType(),
diag::err_second_parameter_to_va_arg_incomplete,
TInfo->getTypeLoc()))
return ExprError();
if (RequireNonAbstractType(TInfo->getTypeLoc().getBeginLoc(),
TInfo->getType(),
diag::err_second_parameter_to_va_arg_abstract,
TInfo->getTypeLoc()))
return ExprError();
if (!TInfo->getType().isPODType(Context)) {
Diag(TInfo->getTypeLoc().getBeginLoc(),
TInfo->getType()->isObjCLifetimeType()
? diag::warn_second_parameter_to_va_arg_ownership_qualified
: diag::warn_second_parameter_to_va_arg_not_pod)
<< TInfo->getType()
<< TInfo->getTypeLoc().getSourceRange();
}
// Check for va_arg where arguments of the given type will be promoted
// (i.e. this va_arg is guaranteed to have undefined behavior).
QualType PromoteType;
if (TInfo->getType()->isPromotableIntegerType()) {
PromoteType = Context.getPromotedIntegerType(TInfo->getType());
if (Context.typesAreCompatible(PromoteType, TInfo->getType()))
PromoteType = QualType();
}
if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float))
PromoteType = Context.DoubleTy;
if (!PromoteType.isNull())
DiagRuntimeBehavior(TInfo->getTypeLoc().getBeginLoc(), E,
PDiag(diag::warn_second_parameter_to_va_arg_never_compatible)
<< TInfo->getType()
<< PromoteType
<< TInfo->getTypeLoc().getSourceRange());
}
QualType T = TInfo->getType().getNonLValueExprType(Context);
return new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T, IsMS);
}
ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) {
// The type of __null will be int or long, depending on the size of
// pointers on the target.
QualType Ty;
unsigned pw = Context.getTargetInfo().getPointerWidth(0);
if (pw == Context.getTargetInfo().getIntWidth())
Ty = Context.IntTy;
else if (pw == Context.getTargetInfo().getLongWidth())
Ty = Context.LongTy;
else if (pw == Context.getTargetInfo().getLongLongWidth())
Ty = Context.LongLongTy;
else {
llvm_unreachable("I don't know size of pointer!");
}
return new (Context) GNUNullExpr(Ty, TokenLoc);
}
bool Sema::ConversionToObjCStringLiteralCheck(QualType DstType, Expr *&Exp,
bool Diagnose) {
if (!getLangOpts().ObjC)
return false;
const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>();
if (!PT)
return false;
if (!PT->isObjCIdType()) {
// Check if the destination is the 'NSString' interface.
const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
if (!ID || !ID->getIdentifier()->isStr("NSString"))
return false;
}
// Ignore any parens, implicit casts (should only be
// array-to-pointer decays), and not-so-opaque values. The last is
// important for making this trigger for property assignments.
Expr *SrcExpr = Exp->IgnoreParenImpCasts();
if (OpaqueValueExpr *OV = dyn_cast<OpaqueValueExpr>(SrcExpr))
if (OV->getSourceExpr())
SrcExpr = OV->getSourceExpr()->IgnoreParenImpCasts();
StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr);
if (!SL || !SL->isAscii())
return false;
if (Diagnose) {
Diag(SL->getBeginLoc(), diag::err_missing_atsign_prefix)
<< FixItHint::CreateInsertion(SL->getBeginLoc(), "@");
Exp = BuildObjCStringLiteral(SL->getBeginLoc(), SL).get();
}
return true;
}
static bool maybeDiagnoseAssignmentToFunction(Sema &S, QualType DstType,
const Expr *SrcExpr) {
if (!DstType->isFunctionPointerType() ||
!SrcExpr->getType()->isFunctionType())
return false;
auto *DRE = dyn_cast<DeclRefExpr>(SrcExpr->IgnoreParenImpCasts());
if (!DRE)
return false;
auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl());
if (!FD)
return false;
return !S.checkAddressOfFunctionIsAvailable(FD,
/*Complain=*/true,
SrcExpr->getBeginLoc());
}
bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
SourceLocation Loc,
QualType DstType, QualType SrcType,
Expr *SrcExpr, AssignmentAction Action,
bool *Complained) {
if (Complained)
*Complained = false;
// Decode the result (notice that AST's are still created for extensions).
bool CheckInferredResultType = false;
bool isInvalid = false;
unsigned DiagKind = 0;
FixItHint Hint;
ConversionFixItGenerator ConvHints;
bool MayHaveConvFixit = false;
bool MayHaveFunctionDiff = false;
const ObjCInterfaceDecl *IFace = nullptr;
const ObjCProtocolDecl *PDecl = nullptr;
switch (ConvTy) {
case Compatible:
DiagnoseAssignmentEnum(DstType, SrcType, SrcExpr);
return false;
case PointerToInt:
DiagKind = diag::ext_typecheck_convert_pointer_int;
ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
MayHaveConvFixit = true;
break;
case IntToPointer:
DiagKind = diag::ext_typecheck_convert_int_pointer;
ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
MayHaveConvFixit = true;
break;
case IncompatiblePointer:
if (Action == AA_Passing_CFAudited)
DiagKind = diag::err_arc_typecheck_convert_incompatible_pointer;
else if (SrcType->isFunctionPointerType() &&
DstType->isFunctionPointerType())
DiagKind = diag::ext_typecheck_convert_incompatible_function_pointer;
else
DiagKind = diag::ext_typecheck_convert_incompatible_pointer;
CheckInferredResultType = DstType->isObjCObjectPointerType() &&
SrcType->isObjCObjectPointerType();
if (Hint.isNull() && !CheckInferredResultType) {
ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
}
else if (CheckInferredResultType) {
SrcType = SrcType.getUnqualifiedType();
DstType = DstType.getUnqualifiedType();
}
MayHaveConvFixit = true;
break;
case IncompatiblePointerSign:
DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign;
break;
case FunctionVoidPointer:
DiagKind = diag::ext_typecheck_convert_pointer_void_func;
break;
case IncompatiblePointerDiscardsQualifiers: {
// Perform array-to-pointer decay if necessary.
if (SrcType->isArrayType()) SrcType = Context.getArrayDecayedType(SrcType);
Qualifiers lhq = SrcType->getPointeeType().getQualifiers();
Qualifiers rhq = DstType->getPointeeType().getQualifiers();
if (lhq.getAddressSpace() != rhq.getAddressSpace()) {
DiagKind = diag::err_typecheck_incompatible_address_space;
break;
} else if (lhq.getObjCLifetime() != rhq.getObjCLifetime()) {
DiagKind = diag::err_typecheck_incompatible_ownership;
break;
}
llvm_unreachable("unknown error case for discarding qualifiers!");
// fallthrough
}
case CompatiblePointerDiscardsQualifiers:
// If the qualifiers lost were because we were applying the
// (deprecated) C++ conversion from a string literal to a char*
// (or wchar_t*), then there was no error (C++ 4.2p2). FIXME:
// Ideally, this check would be performed in
// checkPointerTypesForAssignment. However, that would require a
// bit of refactoring (so that the second argument is an
// expression, rather than a type), which should be done as part
// of a larger effort to fix checkPointerTypesForAssignment for
// C++ semantics.
if (getLangOpts().CPlusPlus &&
IsStringLiteralToNonConstPointerConversion(SrcExpr, DstType))
return false;
DiagKind = diag::ext_typecheck_convert_discards_qualifiers;
break;
case IncompatibleNestedPointerQualifiers:
DiagKind = diag::ext_nested_pointer_qualifier_mismatch;
break;
case IntToBlockPointer:
DiagKind = diag::err_int_to_block_pointer;
break;
case IncompatibleBlockPointer:
DiagKind = diag::err_typecheck_convert_incompatible_block_pointer;
break;
case IncompatibleObjCQualifiedId: {
if (SrcType->isObjCQualifiedIdType()) {
const ObjCObjectPointerType *srcOPT =
SrcType->getAs<ObjCObjectPointerType>();
for (auto *srcProto : srcOPT->quals()) {
PDecl = srcProto;
break;
}
if (const ObjCInterfaceType *IFaceT =
DstType->getAs<ObjCObjectPointerType>()->getInterfaceType())
IFace = IFaceT->getDecl();
}
else if (DstType->isObjCQualifiedIdType()) {
const ObjCObjectPointerType *dstOPT =
DstType->getAs<ObjCObjectPointerType>();
for (auto *dstProto : dstOPT->quals()) {
PDecl = dstProto;
break;
}
if (const ObjCInterfaceType *IFaceT =
SrcType->getAs<ObjCObjectPointerType>()->getInterfaceType())
IFace = IFaceT->getDecl();
}
DiagKind = diag::warn_incompatible_qualified_id;
break;
}
case IncompatibleVectors:
DiagKind = diag::warn_incompatible_vectors;
break;
case IncompatibleObjCWeakRef:
DiagKind = diag::err_arc_weak_unavailable_assign;
break;
case Incompatible:
if (maybeDiagnoseAssignmentToFunction(*this, DstType, SrcExpr)) {
if (Complained)
*Complained = true;
return true;
}
DiagKind = diag::err_typecheck_convert_incompatible;
ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
MayHaveConvFixit = true;
isInvalid = true;
MayHaveFunctionDiff = true;
break;
}
QualType FirstType, SecondType;
switch (Action) {
case AA_Assigning:
case AA_Initializing:
// The destination type comes first.
FirstType = DstType;
SecondType = SrcType;
break;
case AA_Returning:
case AA_Passing:
case AA_Passing_CFAudited:
case AA_Converting:
case AA_Sending:
case AA_Casting:
// The source type comes first.
FirstType = SrcType;
SecondType = DstType;
break;
}
PartialDiagnostic FDiag = PDiag(DiagKind);
if (Action == AA_Passing_CFAudited)
FDiag << FirstType << SecondType << AA_Passing << SrcExpr->getSourceRange();
else
FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange();
// If we can fix the conversion, suggest the FixIts.
assert(ConvHints.isNull() || Hint.isNull());
if (!ConvHints.isNull()) {
for (FixItHint &H : ConvHints.Hints)
FDiag << H;
} else {
FDiag << Hint;
}
if (MayHaveConvFixit) { FDiag << (unsigned) (ConvHints.Kind); }
if (MayHaveFunctionDiff)
HandleFunctionTypeMismatch(FDiag, SecondType, FirstType);
Diag(Loc, FDiag);
if (DiagKind == diag::warn_incompatible_qualified_id &&
PDecl && IFace && !IFace->hasDefinition())
Diag(IFace->getLocation(), diag::note_incomplete_class_and_qualified_id)
<< IFace << PDecl;
if (SecondType == Context.OverloadTy)
NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression,
FirstType, /*TakingAddress=*/true);
if (CheckInferredResultType)
EmitRelatedResultTypeNote(SrcExpr);
if (Action == AA_Returning && ConvTy == IncompatiblePointer)
EmitRelatedResultTypeNoteForReturn(DstType);
if (Complained)
*Complained = true;
return isInvalid;
}
ExprResult Sema::VerifyIntegerConstantExpression(Expr *E,
llvm::APSInt *Result) {
class SimpleICEDiagnoser : public VerifyICEDiagnoser {
public:
void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
S.Diag(Loc, diag::err_expr_not_ice) << S.LangOpts.CPlusPlus << SR;
}
} Diagnoser;
return VerifyIntegerConstantExpression(E, Result, Diagnoser);
}
ExprResult Sema::VerifyIntegerConstantExpression(Expr *E,
llvm::APSInt *Result,
unsigned DiagID,
bool AllowFold) {
class IDDiagnoser : public VerifyICEDiagnoser {
unsigned DiagID;
public:
IDDiagnoser(unsigned DiagID)
: VerifyICEDiagnoser(DiagID == 0), DiagID(DiagID) { }
void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
S.Diag(Loc, DiagID) << SR;
}
} Diagnoser(DiagID);
return VerifyIntegerConstantExpression(E, Result, Diagnoser, AllowFold);
}
void Sema::VerifyICEDiagnoser::diagnoseFold(Sema &S, SourceLocation Loc,
SourceRange SR) {
S.Diag(Loc, diag::ext_expr_not_ice) << SR << S.LangOpts.CPlusPlus;
}
ExprResult
Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
VerifyICEDiagnoser &Diagnoser,
bool AllowFold) {
SourceLocation DiagLoc = E->getBeginLoc();
if (getLangOpts().CPlusPlus11) {
// C++11 [expr.const]p5:
// If an expression of literal class type is used in a context where an
// integral constant expression is required, then that class type shall
// have a single non-explicit conversion function to an integral or
// unscoped enumeration type
ExprResult Converted;
class CXX11ConvertDiagnoser : public ICEConvertDiagnoser {
public:
CXX11ConvertDiagnoser(bool Silent)
: ICEConvertDiagnoser(/*AllowScopedEnumerations*/false,
Silent, true) {}
SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
QualType T) override {
return S.Diag(Loc, diag::err_ice_not_integral) << T;
}
SemaDiagnosticBuilder diagnoseIncomplete(
Sema &S, SourceLocation Loc, QualType T) override {
return S.Diag(Loc, diag::err_ice_incomplete_type) << T;
}
SemaDiagnosticBuilder diagnoseExplicitConv(
Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
return S.Diag(Loc, diag::err_ice_explicit_conversion) << T << ConvTy;
}
SemaDiagnosticBuilder noteExplicitConv(
Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
<< ConvTy->isEnumeralType() << ConvTy;
}
SemaDiagnosticBuilder diagnoseAmbiguous(
Sema &S, SourceLocation Loc, QualType T) override {
return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T;
}
SemaDiagnosticBuilder noteAmbiguous(
Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here)
<< ConvTy->isEnumeralType() << ConvTy;
}
SemaDiagnosticBuilder diagnoseConversion(
Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override {
llvm_unreachable("conversion functions are permitted");
}
} ConvertDiagnoser(Diagnoser.Suppress);
Converted = PerformContextualImplicitConversion(DiagLoc, E,
ConvertDiagnoser);
if (Converted.isInvalid())
return Converted;
E = Converted.get();
if (!E->getType()->isIntegralOrUnscopedEnumerationType())
return ExprError();
} else if (!E->getType()->isIntegralOrUnscopedEnumerationType()) {
// An ICE must be of integral or unscoped enumeration type.
if (!Diagnoser.Suppress)
Diagnoser.diagnoseNotICE(*this, DiagLoc, E->getSourceRange());
return ExprError();
}
if (!isa<ConstantExpr>(E))
E = ConstantExpr::Create(Context, E);
// Circumvent ICE checking in C++11 to avoid evaluating the expression twice
// in the non-ICE case.
if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) {
if (Result)
*Result = E->EvaluateKnownConstIntCheckOverflow(Context);
return E;
}
Expr::EvalResult EvalResult;
SmallVector<PartialDiagnosticAt, 8> Notes;
EvalResult.Diag = &Notes;
// Try to evaluate the expression, and produce diagnostics explaining why it's
// not a constant expression as a side-effect.
bool Folded = E->EvaluateAsRValue(EvalResult, Context) &&
EvalResult.Val.isInt() && !EvalResult.HasSideEffects;
// In C++11, we can rely on diagnostics being produced for any expression
// which is not a constant expression. If no diagnostics were produced, then
// this is a constant expression.
if (Folded && getLangOpts().CPlusPlus11 && Notes.empty()) {
if (Result)
*Result = EvalResult.Val.getInt();
return E;
}
// If our only note is the usual "invalid subexpression" note, just point
// the caret at its location rather than producing an essentially
// redundant note.
if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
diag::note_invalid_subexpr_in_const_expr) {
DiagLoc = Notes[0].first;
Notes.clear();
}
if (!Folded || !AllowFold) {
if (!Diagnoser.Suppress) {
Diagnoser.diagnoseNotICE(*this, DiagLoc, E->getSourceRange());
for (const PartialDiagnosticAt &Note : Notes)
Diag(Note.first, Note.second);
}
return ExprError();
}
Diagnoser.diagnoseFold(*this, DiagLoc, E->getSourceRange());
for (const PartialDiagnosticAt &Note : Notes)
Diag(Note.first, Note.second);
if (Result)
*Result = EvalResult.Val.getInt();
return E;
}
namespace {
// Handle the case where we conclude a expression which we speculatively
// considered to be unevaluated is actually evaluated.
class TransformToPE : public TreeTransform<TransformToPE> {
typedef TreeTransform<TransformToPE> BaseTransform;
public:
TransformToPE(Sema &SemaRef) : BaseTransform(SemaRef) { }
// Make sure we redo semantic analysis
bool AlwaysRebuild() { return true; }
// Make sure we handle LabelStmts correctly.
// FIXME: This does the right thing, but maybe we need a more general
// fix to TreeTransform?
StmtResult TransformLabelStmt(LabelStmt *S) {
S->getDecl()->setStmt(nullptr);
return BaseTransform::TransformLabelStmt(S);
}
// We need to special-case DeclRefExprs referring to FieldDecls which
// are not part of a member pointer formation; normal TreeTransforming
// doesn't catch this case because of the way we represent them in the AST.
// FIXME: This is a bit ugly; is it really the best way to handle this
// case?
//
// Error on DeclRefExprs referring to FieldDecls.
ExprResult TransformDeclRefExpr(DeclRefExpr *E) {
if (isa<FieldDecl>(E->getDecl()) &&
!SemaRef.isUnevaluatedContext())
return SemaRef.Diag(E->getLocation(),
diag::err_invalid_non_static_member_use)
<< E->getDecl() << E->getSourceRange();
return BaseTransform::TransformDeclRefExpr(E);
}
// Exception: filter out member pointer formation
ExprResult TransformUnaryOperator(UnaryOperator *E) {
if (E->getOpcode() == UO_AddrOf && E->getType()->isMemberPointerType())
return E;
return BaseTransform::TransformUnaryOperator(E);
}
ExprResult TransformLambdaExpr(LambdaExpr *E) {
// Lambdas never need to be transformed.
return E;
}
};
}
ExprResult Sema::TransformToPotentiallyEvaluated(Expr *E) {
assert(isUnevaluatedContext() &&
"Should only transform unevaluated expressions");
ExprEvalContexts.back().Context =
ExprEvalContexts[ExprEvalContexts.size()-2].Context;
if (isUnevaluatedContext())
return E;
return TransformToPE(*this).TransformExpr(E);
}
void
Sema::PushExpressionEvaluationContext(
ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl,
ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup,
LambdaContextDecl, ExprContext);
Cleanup.reset();
if (!MaybeODRUseExprs.empty())
std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
}
void
Sema::PushExpressionEvaluationContext(
ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t,
ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl;
PushExpressionEvaluationContext(NewContext, ClosureContextDecl, ExprContext);
}
namespace {
const DeclRefExpr *CheckPossibleDeref(Sema &S, const Expr *PossibleDeref) {
PossibleDeref = PossibleDeref->IgnoreParenImpCasts();
if (const auto *E = dyn_cast<UnaryOperator>(PossibleDeref)) {
if (E->getOpcode() == UO_Deref)
return CheckPossibleDeref(S, E->getSubExpr());
} else if (const auto *E = dyn_cast<ArraySubscriptExpr>(PossibleDeref)) {
return CheckPossibleDeref(S, E->getBase());
} else if (const auto *E = dyn_cast<MemberExpr>(PossibleDeref)) {
return CheckPossibleDeref(S, E->getBase());
} else if (const auto E = dyn_cast<DeclRefExpr>(PossibleDeref)) {
QualType Inner;
QualType Ty = E->getType();
if (const auto *Ptr = Ty->getAs<PointerType>())
Inner = Ptr->getPointeeType();
else if (const auto *Arr = S.Context.getAsArrayType(Ty))
Inner = Arr->getElementType();
else
return nullptr;
if (Inner->hasAttr(attr::NoDeref))
return E;
}
return nullptr;
}
} // namespace
void Sema::WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec) {
for (const Expr *E : Rec.PossibleDerefs) {
const DeclRefExpr *DeclRef = CheckPossibleDeref(*this, E);
if (DeclRef) {
const ValueDecl *Decl = DeclRef->getDecl();
Diag(E->getExprLoc(), diag::warn_dereference_of_noderef_type)
<< Decl->getName() << E->getSourceRange();
Diag(Decl->getLocation(), diag::note_previous_decl) << Decl->getName();
} else {
Diag(E->getExprLoc(), diag::warn_dereference_of_noderef_type_no_decl)
<< E->getSourceRange();
}
}
Rec.PossibleDerefs.clear();
}
void Sema::PopExpressionEvaluationContext() {
ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
unsigned NumTypos = Rec.NumTypos;
if (!Rec.Lambdas.empty()) {
using ExpressionKind = ExpressionEvaluationContextRecord::ExpressionKind;
if (Rec.ExprContext == ExpressionKind::EK_TemplateArgument || Rec.isUnevaluated() ||
(Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17)) {
unsigned D;
if (Rec.isUnevaluated()) {
// C++11 [expr.prim.lambda]p2:
// A lambda-expression shall not appear in an unevaluated operand
// (Clause 5).
D = diag::err_lambda_unevaluated_operand;
} else if (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17) {
// C++1y [expr.const]p2:
// A conditional-expression e is a core constant expression unless the
// evaluation of e, following the rules of the abstract machine, would
// evaluate [...] a lambda-expression.
D = diag::err_lambda_in_constant_expression;
} else if (Rec.ExprContext == ExpressionKind::EK_TemplateArgument) {
// C++17 [expr.prim.lamda]p2:
// A lambda-expression shall not appear [...] in a template-argument.
D = diag::err_lambda_in_invalid_context;
} else
llvm_unreachable("Couldn't infer lambda error message.");
for (const auto *L : Rec.Lambdas)
Diag(L->getBeginLoc(), D);
} else {
// Mark the capture expressions odr-used. This was deferred
// during lambda expression creation.
for (auto *Lambda : Rec.Lambdas) {
for (auto *C : Lambda->capture_inits())
MarkDeclarationsReferencedInExpr(C);
}
}
}
WarnOnPendingNoDerefs(Rec);
// When are coming out of an unevaluated context, clear out any
// temporaries that we may have created as part of the evaluation of
// the expression in that context: they aren't relevant because they
// will never be constructed.
if (Rec.isUnevaluated() || Rec.isConstantEvaluated()) {
ExprCleanupObjects.erase(ExprCleanupObjects.begin() + Rec.NumCleanupObjects,
ExprCleanupObjects.end());
Cleanup = Rec.ParentCleanup;
CleanupVarDeclMarking();
std::swap(MaybeODRUseExprs, Rec.SavedMaybeODRUseExprs);
// Otherwise, merge the contexts together.
} else {
Cleanup.mergeFrom(Rec.ParentCleanup);
MaybeODRUseExprs.insert(Rec.SavedMaybeODRUseExprs.begin(),
Rec.SavedMaybeODRUseExprs.end());
}
// Pop the current expression evaluation context off the stack.
ExprEvalContexts.pop_back();
// The global expression evaluation context record is never popped.
ExprEvalContexts.back().NumTypos += NumTypos;
}
void Sema::DiscardCleanupsInEvaluationContext() {
ExprCleanupObjects.erase(
ExprCleanupObjects.begin() + ExprEvalContexts.back().NumCleanupObjects,
ExprCleanupObjects.end());
Cleanup.reset();
MaybeODRUseExprs.clear();
}
ExprResult Sema::HandleExprEvaluationContextForTypeof(Expr *E) {
ExprResult Result = CheckPlaceholderExpr(E);
if (Result.isInvalid())
return ExprError();
E = Result.get();
if (!E->getType()->isVariablyModifiedType())
return E;
return TransformToPotentiallyEvaluated(E);
}
/// Are we within a context in which some evaluation could be performed (be it
/// constant evaluation or runtime evaluation)? Sadly, this notion is not quite
/// captured by C++'s idea of an "unevaluated context".
static bool isEvaluatableContext(Sema &SemaRef) {
switch (SemaRef.ExprEvalContexts.back().Context) {
case Sema::ExpressionEvaluationContext::Unevaluated:
case Sema::ExpressionEvaluationContext::UnevaluatedAbstract:
// Expressions in this context are never evaluated.
return false;
case Sema::ExpressionEvaluationContext::UnevaluatedList:
case Sema::ExpressionEvaluationContext::ConstantEvaluated:
case Sema::ExpressionEvaluationContext::PotentiallyEvaluated:
case Sema::ExpressionEvaluationContext::DiscardedStatement:
// Expressions in this context could be evaluated.
return true;
case Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:
// Referenced declarations will only be used if the construct in the
// containing expression is used, at which point we'll be given another
// turn to mark them.
return false;
}
llvm_unreachable("Invalid context");
}
/// Are we within a context in which references to resolved functions or to
/// variables result in odr-use?
static bool isOdrUseContext(Sema &SemaRef, bool SkipDependentUses = true) {
// An expression in a template is not really an expression until it's been
// instantiated, so it doesn't trigger odr-use.
if (SkipDependentUses && SemaRef.CurContext->isDependentContext())
return false;
switch (SemaRef.ExprEvalContexts.back().Context) {
case Sema::ExpressionEvaluationContext::Unevaluated:
case Sema::ExpressionEvaluationContext::UnevaluatedList:
case Sema::ExpressionEvaluationContext::UnevaluatedAbstract:
case Sema::ExpressionEvaluationContext::DiscardedStatement:
return false;
case Sema::ExpressionEvaluationContext::ConstantEvaluated:
case Sema::ExpressionEvaluationContext::PotentiallyEvaluated:
return true;
case Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:
return false;
}
llvm_unreachable("Invalid context");
}
static bool isImplicitlyDefinableConstexprFunction(FunctionDecl *Func) {
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Func);
return Func->isConstexpr() &&
(Func->isImplicitlyInstantiable() || (MD && !MD->isUserProvided()));
}
/// Mark a function referenced, and check whether it is odr-used
/// (C++ [basic.def.odr]p2, C99 6.9p3)
void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
bool MightBeOdrUse) {
assert(Func && "No function?");
Func->setReferenced();
// C++11 [basic.def.odr]p3:
// A function whose name appears as a potentially-evaluated expression is
// odr-used if it is the unique lookup result or the selected member of a
// set of overloaded functions [...].
//
// We (incorrectly) mark overload resolution as an unevaluated context, so we
// can just check that here.
bool OdrUse = MightBeOdrUse && isOdrUseContext(*this);
// Determine whether we require a function definition to exist, per
// C++11 [temp.inst]p3:
// Unless a function template specialization has been explicitly
// instantiated or explicitly specialized, the function template
// specialization is implicitly instantiated when the specialization is
// referenced in a context that requires a function definition to exist.
//
// That is either when this is an odr-use, or when a usage of a constexpr
// function occurs within an evaluatable context.
bool NeedDefinition =
OdrUse || (isEvaluatableContext(*this) &&
isImplicitlyDefinableConstexprFunction(Func));
// C++14 [temp.expl.spec]p6:
// If a template [...] is explicitly specialized then that specialization
// shall be declared before the first use of that specialization that would
// cause an implicit instantiation to take place, in every translation unit
// in which such a use occurs
if (NeedDefinition &&
(Func->getTemplateSpecializationKind() != TSK_Undeclared ||
Func->getMemberSpecializationInfo()))
checkSpecializationVisibility(Loc, Func);
// C++14 [except.spec]p17:
// An exception-specification is considered to be needed when:
// - the function is odr-used or, if it appears in an unevaluated operand,
// would be odr-used if the expression were potentially-evaluated;
//
// Note, we do this even if MightBeOdrUse is false. That indicates that the
// function is a pure virtual function we're calling, and in that case the
// function was selected by overload resolution and we need to resolve its
// exception specification for a different reason.
const FunctionProtoType *FPT = Func->getType()->getAs<FunctionProtoType>();
if (FPT && isUnresolvedExceptionSpec(FPT->getExceptionSpecType()))
ResolveExceptionSpec(Loc, FPT);
// If we don't need to mark the function as used, and we don't need to
// try to provide a definition, there's nothing more to do.
if ((Func->isUsed(/*CheckUsedAttr=*/false) || !OdrUse) &&
(!NeedDefinition || Func->getBody()))
return;
// Note that this declaration has been used.
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Func)) {
Constructor = cast<CXXConstructorDecl>(Constructor->getFirstDecl());
if (Constructor->isDefaulted() && !Constructor->isDeleted()) {
if (Constructor->isDefaultConstructor()) {
if (Constructor->isTrivial() && !Constructor->hasAttr<DLLExportAttr>())
return;
DefineImplicitDefaultConstructor(Loc, Constructor);
} else if (Constructor->isCopyConstructor()) {
DefineImplicitCopyConstructor(Loc, Constructor);
} else if (Constructor->isMoveConstructor()) {
DefineImplicitMoveConstructor(Loc, Constructor);
}
} else if (Constructor->getInheritedConstructor()) {
DefineInheritingConstructor(Loc, Constructor);
}
} else if (CXXDestructorDecl *Destructor =
dyn_cast<CXXDestructorDecl>(Func)) {
Destructor = cast<CXXDestructorDecl>(Destructor->getFirstDecl());
if (Destructor->isDefaulted() && !Destructor->isDeleted()) {
if (Destructor->isTrivial() && !Destructor->hasAttr<DLLExportAttr>())
return;
DefineImplicitDestructor(Loc, Destructor);
}
if (Destructor->isVirtual() && getLangOpts().AppleKext)
MarkVTableUsed(Loc, Destructor->getParent());
} else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(Func)) {
if (MethodDecl->isOverloadedOperator() &&
MethodDecl->getOverloadedOperator() == OO_Equal) {
MethodDecl = cast<CXXMethodDecl>(MethodDecl->getFirstDecl());
if (MethodDecl->isDefaulted() && !MethodDecl->isDeleted()) {
if (MethodDecl->isCopyAssignmentOperator())
DefineImplicitCopyAssignment(Loc, MethodDecl);
else if (MethodDecl->isMoveAssignmentOperator())
DefineImplicitMoveAssignment(Loc, MethodDecl);
}
} else if (isa<CXXConversionDecl>(MethodDecl) &&
MethodDecl->getParent()->isLambda()) {
CXXConversionDecl *Conversion =
cast<CXXConversionDecl>(MethodDecl->getFirstDecl());
if (Conversion->isLambdaToBlockPointerConversion())
DefineImplicitLambdaToBlockPointerConversion(Loc, Conversion);
else
DefineImplicitLambdaToFunctionPointerConversion(Loc, Conversion);
} else if (MethodDecl->isVirtual() && getLangOpts().AppleKext)
MarkVTableUsed(Loc, MethodDecl->getParent());
}
// Recursive functions should be marked when used from another function.
// FIXME: Is this really right?
if (CurContext == Func) return;
// Implicit instantiation of function templates and member functions of
// class templates.
if (Func->isImplicitlyInstantiable()) {
TemplateSpecializationKind TSK = Func->getTemplateSpecializationKind();
SourceLocation PointOfInstantiation = Func->getPointOfInstantiation();
bool FirstInstantiation = PointOfInstantiation.isInvalid();
if (FirstInstantiation) {
PointOfInstantiation = Loc;
Func->setTemplateSpecializationKind(TSK, PointOfInstantiation);
} else if (TSK != TSK_ImplicitInstantiation) {
// Use the point of use as the point of instantiation, instead of the
// point of explicit instantiation (which we track as the actual point of
// instantiation). This gives better backtraces in diagnostics.
PointOfInstantiation = Loc;
}
if (FirstInstantiation || TSK != TSK_ImplicitInstantiation ||
Func->isConstexpr()) {
if (isa<CXXRecordDecl>(Func->getDeclContext()) &&
cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass() &&
CodeSynthesisContexts.size())
PendingLocalImplicitInstantiations.push_back(
std::make_pair(Func, PointOfInstantiation));
else if (Func->isConstexpr())
// Do not defer instantiations of constexpr functions, to avoid the
// expression evaluator needing to call back into Sema if it sees a
// call to such a function.
InstantiateFunctionDefinition(PointOfInstantiation, Func);
else {
Func->setInstantiationIsPending(true);
PendingInstantiations.push_back(std::make_pair(Func,
PointOfInstantiation));
// Notify the consumer that a function was implicitly instantiated.
Consumer.HandleCXXImplicitFunctionInstantiation(Func);
}
}
} else {
// Walk redefinitions, as some of them may be instantiable.
for (auto i : Func->redecls()) {
if (!i->isUsed(false) && i->isImplicitlyInstantiable())
MarkFunctionReferenced(Loc, i, OdrUse);
}
}
if (!OdrUse) return;
// Keep track of used but undefined functions.
if (!Func->isDefined()) {
if (mightHaveNonExternalLinkage(Func))
UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
else if (Func->getMostRecentDecl()->isInlined() &&
!LangOpts.GNUInline &&
!Func->getMostRecentDecl()->hasAttr<GNUInlineAttr>())
UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
else if (isExternalWithNoLinkageType(Func))
UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
}
Func->markUsed(Context);
}
static void
diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
ValueDecl *var, DeclContext *DC) {
DeclContext *VarDC = var->getDeclContext();
// If the parameter still belongs to the translation unit, then
// we're actually just using one parameter in the declaration of
// the next.
if (isa<ParmVarDecl>(var) &&
isa<TranslationUnitDecl>(VarDC))
return;
// For C code, don't diagnose about capture if we're not actually in code
// right now; it's impossible to write a non-constant expression outside of
// function context, so we'll get other (more useful) diagnostics later.
//
// For C++, things get a bit more nasty... it would be nice to suppress this
// diagnostic for certain cases like using a local variable in an array bound
// for a member of a local class, but the correct predicate is not obvious.
if (!S.getLangOpts().CPlusPlus && !S.CurContext->isFunctionOrMethod())
return;
unsigned ValueKind = isa<BindingDecl>(var) ? 1 : 0;
unsigned ContextKind = 3; // unknown
if (isa<CXXMethodDecl>(VarDC) &&
cast<CXXRecordDecl>(VarDC->getParent())->isLambda()) {
ContextKind = 2;
} else if (isa<FunctionDecl>(VarDC)) {
ContextKind = 0;
} else if (isa<BlockDecl>(VarDC)) {
ContextKind = 1;
}
S.Diag(loc, diag::err_reference_to_local_in_enclosing_context)
<< var << ValueKind << ContextKind << VarDC;
S.Diag(var->getLocation(), diag::note_entity_declared_at)
<< var;
// FIXME: Add additional diagnostic info about class etc. which prevents
// capture.
}
static bool isVariableAlreadyCapturedInScopeInfo(CapturingScopeInfo *CSI, VarDecl *Var,
bool &SubCapturesAreNested,
QualType &CaptureType,
QualType &DeclRefType) {
// Check whether we've already captured it.
if (CSI->CaptureMap.count(Var)) {
// If we found a capture, any subcaptures are nested.
SubCapturesAreNested = true;
// Retrieve the capture type for this variable.
CaptureType = CSI->getCapture(Var).getCaptureType();
// Compute the type of an expression that refers to this variable.
DeclRefType = CaptureType.getNonReferenceType();
// Similarly to mutable captures in lambda, all the OpenMP captures by copy
// are mutable in the sense that user can change their value - they are
// private instances of the captured declarations.
const Capture &Cap = CSI->getCapture(Var);
if (Cap.isCopyCapture() &&
!(isa<LambdaScopeInfo>(CSI) && cast<LambdaScopeInfo>(CSI)->Mutable) &&
!(isa<CapturedRegionScopeInfo>(CSI) &&
cast<CapturedRegionScopeInfo>(CSI)->CapRegionKind == CR_OpenMP))
DeclRefType.addConst();
return true;
}
return false;
}
// Only block literals, captured statements, and lambda expressions can
// capture; other scopes don't work.
static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl *Var,
SourceLocation Loc,
const bool Diagnose, Sema &S) {
if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC) || isLambdaCallOperator(DC))
return getLambdaAwareParentOfDeclContext(DC);
else if (Var->hasLocalStorage()) {
if (Diagnose)
diagnoseUncapturableValueReference(S, Loc, Var, DC);
}
return nullptr;
}
// Certain capturing entities (lambdas, blocks etc.) are not allowed to capture
// certain types of variables (unnamed, variably modified types etc.)
// so check for eligibility.
static bool isVariableCapturable(CapturingScopeInfo *CSI, VarDecl *Var,
SourceLocation Loc,
const bool Diagnose, Sema &S) {
bool IsBlock = isa<BlockScopeInfo>(CSI);
bool IsLambda = isa<LambdaScopeInfo>(CSI);
// Lambdas are not allowed to capture unnamed variables
// (e.g. anonymous unions).
// FIXME: The C++11 rule don't actually state this explicitly, but I'm
// assuming that's the intent.
if (IsLambda && !Var->getDeclName()) {
if (Diagnose) {
S.Diag(Loc, diag::err_lambda_capture_anonymous_var);
S.Diag(Var->getLocation(), diag::note_declared_at);
}
return false;
}
// Prohibit variably-modified types in blocks; they're difficult to deal with.
if (Var->getType()->isVariablyModifiedType() && IsBlock) {
if (Diagnose) {
S.Diag(Loc, diag::err_ref_vm_type);
S.Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
}
return false;
}
// Prohibit structs with flexible array members too.
// We cannot capture what is in the tail end of the struct.
if (const RecordType *VTTy = Var->getType()->getAs<RecordType>()) {
if (VTTy->getDecl()->hasFlexibleArrayMember()) {
if (Diagnose) {
if (IsBlock)
S.Diag(Loc, diag::err_ref_flexarray_type);
else
S.Diag(Loc, diag::err_lambda_capture_flexarray_type)
<< Var->getDeclName();
S.Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
}
return false;
}
}
const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>();
// Lambdas and captured statements are not allowed to capture __block
// variables; they don't support the expected semantics.
if (HasBlocksAttr && (IsLambda || isa<CapturedRegionScopeInfo>(CSI))) {
if (Diagnose) {
S.Diag(Loc, diag::err_capture_block_variable)
<< Var->getDeclName() << !IsLambda;
S.Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
}
return false;
}
// OpenCL v2.0 s6.12.5: Blocks cannot reference/capture other blocks
if (S.getLangOpts().OpenCL && IsBlock &&
Var->getType()->isBlockPointerType()) {
if (Diagnose)
S.Diag(Loc, diag::err_opencl_block_ref_block);
return false;
}
return true;
}
// Returns true if the capture by block was successful.
static bool captureInBlock(BlockScopeInfo *BSI, VarDecl *Var,
SourceLocation Loc,
const bool BuildAndDiagnose,
QualType &CaptureType,
QualType &DeclRefType,
const bool Nested,
Sema &S) {
Expr *CopyExpr = nullptr;
bool ByRef = false;
// Blocks are not allowed to capture arrays, excepting OpenCL.
// OpenCL v2.0 s1.12.5 (revision 40): arrays are captured by reference
// (decayed to pointers).
if (!S.getLangOpts().OpenCL && CaptureType->isArrayType()) {
if (BuildAndDiagnose) {
S.Diag(Loc, diag::err_ref_array_type);
S.Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
}
return false;
}
// Forbid the block-capture of autoreleasing variables.
if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
if (BuildAndDiagnose) {
S.Diag(Loc, diag::err_arc_autoreleasing_capture)
<< /*block*/ 0;
S.Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
}
return false;
}
// Warn about implicitly autoreleasing indirect parameters captured by blocks.
if (const auto *PT = CaptureType->getAs<PointerType>()) {
// This function finds out whether there is an AttributedType of kind
// attr::ObjCOwnership in Ty. The existence of AttributedType of kind
// attr::ObjCOwnership implies __autoreleasing was explicitly specified
// rather than being added implicitly by the compiler.
auto IsObjCOwnershipAttributedType = [](QualType Ty) {
while (const auto *AttrTy = Ty->getAs<AttributedType>()) {
if (AttrTy->getAttrKind() == attr::ObjCOwnership)
return true;
// Peel off AttributedTypes that are not of kind ObjCOwnership.
Ty = AttrTy->getModifiedType();
}
return false;
};
QualType PointeeTy = PT->getPointeeType();
if (PointeeTy->getAs<ObjCObjectPointerType>() &&
PointeeTy.getObjCLifetime() == Qualifiers::OCL_Autoreleasing &&
!IsObjCOwnershipAttributedType(PointeeTy)) {
if (BuildAndDiagnose) {
SourceLocation VarLoc = Var->getLocation();
S.Diag(Loc, diag::warn_block_capture_autoreleasing);
S.Diag(VarLoc, diag::note_declare_parameter_strong);
}
}
}
const bool HasBlocksAttr = Var->hasAttr<BlocksAttr>();
if (HasBlocksAttr || CaptureType->isReferenceType() ||
(S.getLangOpts().OpenMP && S.isOpenMPCapturedDecl(Var))) {
// Block capture by reference does not change the capture or
// declaration reference types.
ByRef = true;
} else {
// Block capture by copy introduces 'const'.
CaptureType = CaptureType.getNonReferenceType().withConst();
DeclRefType = CaptureType;
if (S.getLangOpts().CPlusPlus && BuildAndDiagnose) {
if (const RecordType *Record = DeclRefType->getAs<RecordType>()) {
// The capture logic needs the destructor, so make sure we mark it.
// Usually this is unnecessary because most local variables have
// their destructors marked at declaration time, but parameters are
// an exception because it's technically only the call site that
// actually requires the destructor.
if (isa<ParmVarDecl>(Var))
S.FinalizeVarWithDestructor(Var, Record);
// Enter a new evaluation context to insulate the copy
// full-expression.
EnterExpressionEvaluationContext scope(
S, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
// According to the blocks spec, the capture of a variable from
// the stack requires a const copy constructor. This is not true
// of the copy/move done to move a __block variable to the heap.
Expr *DeclRef = new (S.Context) DeclRefExpr(
S.Context, Var, Nested, DeclRefType.withConst(), VK_LValue, Loc);
ExprResult Result
= S.PerformCopyInitialization(
InitializedEntity::InitializeBlock(Var->getLocation(),
CaptureType, false),
Loc, DeclRef);
// Build a full-expression copy expression if initialization
// succeeded and used a non-trivial constructor. Recover from
// errors by pretending that the copy isn't necessary.
if (!Result.isInvalid() &&
!cast<CXXConstructExpr>(Result.get())->getConstructor()
->isTrivial()) {
Result = S.MaybeCreateExprWithCleanups(Result);
CopyExpr = Result.get();
}
}
}
}
// Actually capture the variable.
if (BuildAndDiagnose)
BSI->addCapture(Var, HasBlocksAttr, ByRef, Nested, Loc,
SourceLocation(), CaptureType, CopyExpr);
return true;
}
/// Capture the given variable in the captured region.
static bool captureInCapturedRegion(CapturedRegionScopeInfo *RSI,
VarDecl *Var,
SourceLocation Loc,
const bool BuildAndDiagnose,
QualType &CaptureType,
QualType &DeclRefType,
const bool RefersToCapturedVariable,
Sema &S) {
// By default, capture variables by reference.
bool ByRef = true;
// Using an LValue reference type is consistent with Lambdas (see below).
if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP) {
if (S.isOpenMPCapturedDecl(Var)) {
bool HasConst = DeclRefType.isConstQualified();
DeclRefType = DeclRefType.getUnqualifiedType();
// Don't lose diagnostics about assignments to const.
if (HasConst)
DeclRefType.addConst();
}
ByRef = S.isOpenMPCapturedByRef(Var, RSI->OpenMPLevel);
}
if (ByRef)
CaptureType = S.Context.getLValueReferenceType(DeclRefType);
else
CaptureType = DeclRefType;
Expr *CopyExpr = nullptr;
if (BuildAndDiagnose) {
// The current implementation assumes that all variables are captured
// by references. Since there is no capture by copy, no expression
// evaluation will be needed.
RecordDecl *RD = RSI->TheRecordDecl;
FieldDecl *Field
= FieldDecl::Create(S.Context, RD, Loc, Loc, nullptr, CaptureType,
S.Context.getTrivialTypeSourceInfo(CaptureType, Loc),
nullptr, false, ICIS_NoInit);
Field->setImplicit(true);
Field->setAccess(AS_private);
RD->addDecl(Field);
if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP)
S.setOpenMPCaptureKind(Field, Var, RSI->OpenMPLevel);
CopyExpr = new (S.Context) DeclRefExpr(
S.Context, Var, RefersToCapturedVariable, DeclRefType, VK_LValue, Loc);
Var->setReferenced(true);
Var->markUsed(S.Context);
}
// Actually capture the variable.
if (BuildAndDiagnose)
RSI->addCapture(Var, /*isBlock*/false, ByRef, RefersToCapturedVariable, Loc,
SourceLocation(), CaptureType, CopyExpr);
return true;
}
/// Create a field within the lambda class for the variable
/// being captured.
static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI,
QualType FieldType, QualType DeclRefType,
SourceLocation Loc,
bool RefersToCapturedVariable) {
CXXRecordDecl *Lambda = LSI->Lambda;
// Build the non-static data member.
FieldDecl *Field
= FieldDecl::Create(S.Context, Lambda, Loc, Loc, nullptr, FieldType,
S.Context.getTrivialTypeSourceInfo(FieldType, Loc),
nullptr, false, ICIS_NoInit);
// If the variable being captured has an invalid type, mark the lambda class
// as invalid as well.
if (!FieldType->isDependentType()) {
if (S.RequireCompleteType(Loc, FieldType, diag::err_field_incomplete)) {
Lambda->setInvalidDecl();
Field->setInvalidDecl();
} else {
NamedDecl *Def;
FieldType->isIncompleteType(&Def);
if (Def && Def->isInvalidDecl()) {
Lambda->setInvalidDecl();
Field->setInvalidDecl();
}
}
}
Field->setImplicit(true);
Field->setAccess(AS_private);
Lambda->addDecl(Field);
}
/// Capture the given variable in the lambda.
static bool captureInLambda(LambdaScopeInfo *LSI,
VarDecl *Var,
SourceLocation Loc,
const bool BuildAndDiagnose,
QualType &CaptureType,
QualType &DeclRefType,
const bool RefersToCapturedVariable,
const Sema::TryCaptureKind Kind,
SourceLocation EllipsisLoc,
const bool IsTopScope,
Sema &S) {
// Determine whether we are capturing by reference or by value.
bool ByRef = false;
if (IsTopScope && Kind != Sema::TryCapture_Implicit) {
ByRef = (Kind == Sema::TryCapture_ExplicitByRef);
} else {
ByRef = (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByref);
}
// Compute the type of the field that will capture this variable.
if (ByRef) {
// C++11 [expr.prim.lambda]p15:
// An entity is captured by reference if it is implicitly or
// explicitly captured but not captured by copy. It is
// unspecified whether additional unnamed non-static data
// members are declared in the closure type for entities
// captured by reference.
//
// FIXME: It is not clear whether we want to build an lvalue reference
// to the DeclRefType or to CaptureType.getNonReferenceType(). GCC appears
// to do the former, while EDG does the latter. Core issue 1249 will
// clarify, but for now we follow GCC because it's a more permissive and
// easily defensible position.
CaptureType = S.Context.getLValueReferenceType(DeclRefType);
} else {
// C++11 [expr.prim.lambda]p14:
// For each entity captured by copy, an unnamed non-static
// data member is declared in the closure type. The
// declaration order of these members is unspecified. The type
// of such a data member is the type of the corresponding
// captured entity if the entity is not a reference to an
// object, or the referenced type otherwise. [Note: If the
// captured entity is a reference to a function, the
// corresponding data member is also a reference to a
// function. - end note ]
if (const ReferenceType *RefType = CaptureType->getAs<ReferenceType>()){
if (!RefType->getPointeeType()->isFunctionType())
CaptureType = RefType->getPointeeType();
}
// Forbid the lambda copy-capture of autoreleasing variables.
if (CaptureType.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) {
if (BuildAndDiagnose) {
S.Diag(Loc, diag::err_arc_autoreleasing_capture) << /*lambda*/ 1;
S.Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
}
return false;
}
// Make sure that by-copy captures are of a complete and non-abstract type.
if (BuildAndDiagnose) {
if (!CaptureType->isDependentType() &&
S.RequireCompleteType(Loc, CaptureType,
diag::err_capture_of_incomplete_type,
Var->getDeclName()))
return false;
if (S.RequireNonAbstractType(Loc, CaptureType,
diag::err_capture_of_abstract_type))
return false;
}
}
// Capture this variable in the lambda.
if (BuildAndDiagnose)
addAsFieldToClosureType(S, LSI, CaptureType, DeclRefType, Loc,
RefersToCapturedVariable);
// Compute the type of a reference to this captured variable.
if (ByRef)
DeclRefType = CaptureType.getNonReferenceType();
else {
// C++ [expr.prim.lambda]p5:
// The closure type for a lambda-expression has a public inline
// function call operator [...]. This function call operator is
// declared const (9.3.1) if and only if the lambda-expression's
// parameter-declaration-clause is not followed by mutable.
DeclRefType = CaptureType.getNonReferenceType();
if (!LSI->Mutable && !CaptureType->isReferenceType())
DeclRefType.addConst();
}
// Add the capture.
if (BuildAndDiagnose)
LSI->addCapture(Var, /*IsBlock=*/false, ByRef, RefersToCapturedVariable,
Loc, EllipsisLoc, CaptureType, /*CopyExpr=*/nullptr);
return true;
}
bool Sema::tryCaptureVariable(
VarDecl *Var, SourceLocation ExprLoc, TryCaptureKind Kind,
SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType,
QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt) {
// An init-capture is notionally from the context surrounding its
// declaration, but its parent DC is the lambda class.
DeclContext *VarDC = Var->getDeclContext();
if (Var->isInitCapture())
VarDC = VarDC->getParent();
DeclContext *DC = CurContext;
const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt
? *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1;
// We need to sync up the Declaration Context with the
// FunctionScopeIndexToStopAt
if (FunctionScopeIndexToStopAt) {
unsigned FSIndex = FunctionScopes.size() - 1;
while (FSIndex != MaxFunctionScopesIndex) {
DC = getLambdaAwareParentOfDeclContext(DC);
--FSIndex;
}
}
// If the variable is declared in the current context, there is no need to
// capture it.
if (VarDC == DC) return true;
// Capture global variables if it is required to use private copy of this
// variable.
bool IsGlobal = !Var->hasLocalStorage();
if (IsGlobal && !(LangOpts.OpenMP && isOpenMPCapturedDecl(Var)))
return true;
Var = Var->getCanonicalDecl();
// Walk up the stack to determine whether we can capture the variable,
// performing the "simple" checks that don't depend on type. We stop when
// we've either hit the declared scope of the variable or find an existing
// capture of that variable. We start from the innermost capturing-entity
// (the DC) and ensure that all intervening capturing-entities
// (blocks/lambdas etc.) between the innermost capturer and the variable`s
// declcontext can either capture the variable or have already captured
// the variable.
CaptureType = Var->getType();
DeclRefType = CaptureType.getNonReferenceType();
bool Nested = false;
bool Explicit = (Kind != TryCapture_Implicit);
unsigned FunctionScopesIndex = MaxFunctionScopesIndex;
do {
// Only block literals, captured statements, and lambda expressions can
// capture; other scopes don't work.
DeclContext *ParentDC = getParentOfCapturingContextOrNull(DC, Var,
ExprLoc,
BuildAndDiagnose,
*this);
// We need to check for the parent *first* because, if we *have*
// private-captured a global variable, we need to recursively capture it in
// intermediate blocks, lambdas, etc.
if (!ParentDC) {
if (IsGlobal) {
FunctionScopesIndex = MaxFunctionScopesIndex - 1;
break;
}
return true;
}
FunctionScopeInfo *FSI = FunctionScopes[FunctionScopesIndex];
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FSI);
// Check whether we've already captured it.
if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType,
DeclRefType)) {
CSI->getCapture(Var).markUsed(BuildAndDiagnose);
break;
}
// If we are instantiating a generic lambda call operator body,
// we do not want to capture new variables. What was captured
// during either a lambdas transformation or initial parsing
// should be used.
if (isGenericLambdaCallOperatorSpecialization(DC)) {
if (BuildAndDiagnose) {
LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
if (LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None) {
Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName();
Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
Diag(LSI->Lambda->getBeginLoc(), diag::note_lambda_decl);
} else
diagnoseUncapturableValueReference(*this, ExprLoc, Var, DC);
}
return true;
}
// Certain capturing entities (lambdas, blocks etc.) are not allowed to capture
// certain types of variables (unnamed, variably modified types etc.)
// so check for eligibility.
if (!isVariableCapturable(CSI, Var, ExprLoc, BuildAndDiagnose, *this))
return true;
// Try to capture variable-length arrays types.
if (Var->getType()->isVariablyModifiedType()) {
// We're going to walk down into the type and look for VLA
// expressions.
QualType QTy = Var->getType();
if (ParmVarDecl *PVD = dyn_cast_or_null<ParmVarDecl>(Var))
QTy = PVD->getOriginalType();
captureVariablyModifiedType(Context, QTy, CSI);
}
if (getLangOpts().OpenMP) {
if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
// OpenMP private variables should not be captured in outer scope, so
// just break here. Similarly, global variables that are captured in a
// target region should not be captured outside the scope of the region.
if (RSI->CapRegionKind == CR_OpenMP) {
bool IsOpenMPPrivateDecl = isOpenMPPrivateDecl(Var, RSI->OpenMPLevel);
auto IsTargetCap = !IsOpenMPPrivateDecl &&
isOpenMPTargetCapturedDecl(Var, RSI->OpenMPLevel);
// When we detect target captures we are looking from inside the
// target region, therefore we need to propagate the capture from the
// enclosing region. Therefore, the capture is not initially nested.
if (IsTargetCap)
adjustOpenMPTargetScopeIndex(FunctionScopesIndex, RSI->OpenMPLevel);
if (IsTargetCap || IsOpenMPPrivateDecl) {
Nested = !IsTargetCap;
DeclRefType = DeclRefType.getUnqualifiedType();
CaptureType = Context.getLValueReferenceType(DeclRefType);
break;
}
}
}
}
if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None && !Explicit) {
// No capture-default, and this is not an explicit capture
// so cannot capture this variable.
if (BuildAndDiagnose) {
Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName();
Diag(Var->getLocation(), diag::note_previous_decl)
<< Var->getDeclName();
if (cast<LambdaScopeInfo>(CSI)->Lambda)
Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getBeginLoc(),
diag::note_lambda_decl);
// FIXME: If we error out because an outer lambda can not implicitly
// capture a variable that an inner lambda explicitly captures, we
// should have the inner lambda do the explicit capture - because
// it makes for cleaner diagnostics later. This would purely be done
// so that the diagnostic does not misleadingly claim that a variable
// can not be captured by a lambda implicitly even though it is captured
// explicitly. Suggestion:
// - create const bool VariableCaptureWasInitiallyExplicit = Explicit
// at the function head
// - cache the StartingDeclContext - this must be a lambda
// - captureInLambda in the innermost lambda the variable.
}
return true;
}
FunctionScopesIndex--;
DC = ParentDC;
Explicit = false;
} while (!VarDC->Equals(DC));
// Walk back down the scope stack, (e.g. from outer lambda to inner lambda)
// computing the type of the capture at each step, checking type-specific
// requirements, and adding captures if requested.
// If the variable had already been captured previously, we start capturing
// at the lambda nested within that one.
for (unsigned I = ++FunctionScopesIndex, N = MaxFunctionScopesIndex + 1; I != N;
++I) {
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[I]);
if (BlockScopeInfo *BSI = dyn_cast<BlockScopeInfo>(CSI)) {
if (!captureInBlock(BSI, Var, ExprLoc,
BuildAndDiagnose, CaptureType,
DeclRefType, Nested, *this))
return true;
Nested = true;
} else if (CapturedRegionScopeInfo *RSI = dyn_cast<CapturedRegionScopeInfo>(CSI)) {
if (!captureInCapturedRegion(RSI, Var, ExprLoc,
BuildAndDiagnose, CaptureType,
DeclRefType, Nested, *this))
return true;
Nested = true;
} else {
LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
if (!captureInLambda(LSI, Var, ExprLoc,
BuildAndDiagnose, CaptureType,
DeclRefType, Nested, Kind, EllipsisLoc,
/*IsTopScope*/I == N - 1, *this))
return true;
Nested = true;
}
}
return false;
}
bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc,
TryCaptureKind Kind, SourceLocation EllipsisLoc) {
QualType CaptureType;
QualType DeclRefType;
return tryCaptureVariable(Var, Loc, Kind, EllipsisLoc,
/*BuildAndDiagnose=*/true, CaptureType,
DeclRefType, nullptr);
}
bool Sema::NeedToCaptureVariable(VarDecl *Var, SourceLocation Loc) {
QualType CaptureType;
QualType DeclRefType;
return !tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(),
/*BuildAndDiagnose=*/false, CaptureType,
DeclRefType, nullptr);
}
QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {
QualType CaptureType;
QualType DeclRefType;
// Determine whether we can capture this variable.
if (tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(),
/*BuildAndDiagnose=*/false, CaptureType,
DeclRefType, nullptr))
return QualType();
return DeclRefType;
}
// If either the type of the variable or the initializer is dependent,
// return false. Otherwise, determine whether the variable is a constant
// expression. Use this if you need to know if a variable that might or
// might not be dependent is truly a constant expression.
static inline bool IsVariableNonDependentAndAConstantExpression(VarDecl *Var,
ASTContext &Context) {
if (Var->getType()->isDependentType())
return false;
const VarDecl *DefVD = nullptr;
Var->getAnyInitializer(DefVD);
if (!DefVD)
return false;
EvaluatedStmt *Eval = DefVD->ensureEvaluatedStmt();
Expr *Init = cast<Expr>(Eval->Value);
if (Init->isValueDependent())
return false;
return IsVariableAConstantExpression(Var, Context);
}
void Sema::UpdateMarkingForLValueToRValue(Expr *E) {
// Per C++11 [basic.def.odr], a variable is odr-used "unless it is
// an object that satisfies the requirements for appearing in a
// constant expression (5.19) and the lvalue-to-rvalue conversion (4.1)
// is immediately applied." This function handles the lvalue-to-rvalue
// conversion part.
MaybeODRUseExprs.erase(E->IgnoreParens());
// If we are in a lambda, check if this DeclRefExpr or MemberExpr refers
// to a variable that is a constant expression, and if so, identify it as
// a reference to a variable that does not involve an odr-use of that
// variable.
if (LambdaScopeInfo *LSI = getCurLambda()) {
Expr *SansParensExpr = E->IgnoreParens();
VarDecl *Var = nullptr;
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SansParensExpr))
Var = dyn_cast<VarDecl>(DRE->getFoundDecl());
else if (MemberExpr *ME = dyn_cast<MemberExpr>(SansParensExpr))
Var = dyn_cast<VarDecl>(ME->getMemberDecl());
if (Var && IsVariableNonDependentAndAConstantExpression(Var, Context))
LSI->markVariableExprAsNonODRUsed(SansParensExpr);
}
}
ExprResult Sema::ActOnConstantExpression(ExprResult Res) {
Res = CorrectDelayedTyposInExpr(Res);
if (!Res.isUsable())
return Res;
// If a constant-expression is a reference to a variable where we delay
// deciding whether it is an odr-use, just assume we will apply the
// lvalue-to-rvalue conversion. In the one case where this doesn't happen
// (a non-type template argument), we have special handling anyway.
UpdateMarkingForLValueToRValue(Res.get());
return Res;
}
void Sema::CleanupVarDeclMarking() {
for (Expr *E : MaybeODRUseExprs) {
VarDecl *Var;
SourceLocation Loc;
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
Var = cast<VarDecl>(DRE->getDecl());
Loc = DRE->getLocation();
} else if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
Var = cast<VarDecl>(ME->getMemberDecl());
Loc = ME->getMemberLoc();
} else {
llvm_unreachable("Unexpected expression");
}
MarkVarDeclODRUsed(Var, Loc, *this,
/*MaxFunctionScopeIndex Pointer*/ nullptr);
}
MaybeODRUseExprs.clear();
}
static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
VarDecl *Var, Expr *E) {
assert((!E || isa<DeclRefExpr>(E) || isa<MemberExpr>(E)) &&
"Invalid Expr argument to DoMarkVarDeclReferenced");
Var->setReferenced();
TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind();
bool OdrUseContext = isOdrUseContext(SemaRef);
bool UsableInConstantExpr =
Var->isUsableInConstantExpressions(SemaRef.Context);
bool NeedDefinition =
OdrUseContext || (isEvaluatableContext(SemaRef) && UsableInConstantExpr);
VarTemplateSpecializationDecl *VarSpec =
dyn_cast<VarTemplateSpecializationDecl>(Var);
assert(!isa<VarTemplatePartialSpecializationDecl>(Var) &&
"Can't instantiate a partial template specialization.");
// If this might be a member specialization of a static data member, check
// the specialization is visible. We already did the checks for variable
// template specializations when we created them.
if (NeedDefinition && TSK != TSK_Undeclared &&
!isa<VarTemplateSpecializationDecl>(Var))
SemaRef.checkSpecializationVisibility(Loc, Var);
// Perform implicit instantiation of static data members, static data member
// templates of class templates, and variable template specializations. Delay
// instantiations of variable templates, except for those that could be used
// in a constant expression.
if (NeedDefinition && isTemplateInstantiation(TSK)) {
// Per C++17 [temp.explicit]p10, we may instantiate despite an explicit
// instantiation declaration if a variable is usable in a constant
// expression (among other cases).
bool TryInstantiating =
TSK == TSK_ImplicitInstantiation ||
(TSK == TSK_ExplicitInstantiationDeclaration && UsableInConstantExpr);
if (TryInstantiating) {
SourceLocation PointOfInstantiation = Var->getPointOfInstantiation();
bool FirstInstantiation = PointOfInstantiation.isInvalid();
if (FirstInstantiation) {
PointOfInstantiation = Loc;
Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
}
bool InstantiationDependent = false;
bool IsNonDependent =
VarSpec ? !TemplateSpecializationType::anyDependentTemplateArguments(
VarSpec->getTemplateArgsInfo(), InstantiationDependent)
: true;
// Do not instantiate specializations that are still type-dependent.
if (IsNonDependent) {
if (UsableInConstantExpr) {
// Do not defer instantiations of variables that could be used in a
// constant expression.
SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var);
} else if (FirstInstantiation ||
isa<VarTemplateSpecializationDecl>(Var)) {
// FIXME: For a specialization of a variable template, we don't
// distinguish between "declaration and type implicitly instantiated"
// and "implicit instantiation of definition requested", so we have
// no direct way to avoid enqueueing the pending instantiation
// multiple times.
SemaRef.PendingInstantiations
.push_back(std::make_pair(Var, PointOfInstantiation));
}
}
}
}
// Per C++11 [basic.def.odr], a variable is odr-used "unless it satisfies
// the requirements for appearing in a constant expression (5.19) and, if
// it is an object, the lvalue-to-rvalue conversion (4.1)
// is immediately applied." We check the first part here, and
// Sema::UpdateMarkingForLValueToRValue deals with the second part.
// Note that we use the C++11 definition everywhere because nothing in
// C++03 depends on whether we get the C++03 version correct. The second
// part does not apply to references, since they are not objects.
if (OdrUseContext && E &&
IsVariableAConstantExpression(Var, SemaRef.Context)) {
// A reference initialized by a constant expression can never be
// odr-used, so simply ignore it.
if (!Var->getType()->isReferenceType() ||
(SemaRef.LangOpts.OpenMP && SemaRef.isOpenMPCapturedDecl(Var)))
SemaRef.MaybeODRUseExprs.insert(E);
} else if (OdrUseContext) {
MarkVarDeclODRUsed(Var, Loc, SemaRef,
/*MaxFunctionScopeIndex ptr*/ nullptr);
} else if (isOdrUseContext(SemaRef, /*SkipDependentUses*/false)) {
// If this is a dependent context, we don't need to mark variables as
// odr-used, but we may still need to track them for lambda capture.
// FIXME: Do we also need to do this inside dependent typeid expressions
// (which are modeled as unevaluated at this point)?
const bool RefersToEnclosingScope =
(SemaRef.CurContext != Var->getDeclContext() &&
Var->getDeclContext()->isFunctionOrMethod() && Var->hasLocalStorage());
if (RefersToEnclosingScope) {
LambdaScopeInfo *const LSI =
SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true);
if (LSI && (!LSI->CallOperator ||
!LSI->CallOperator->Encloses(Var->getDeclContext()))) {
// If a variable could potentially be odr-used, defer marking it so
// until we finish analyzing the full expression for any
// lvalue-to-rvalue
// or discarded value conversions that would obviate odr-use.
// Add it to the list of potential captures that will be analyzed
// later (ActOnFinishFullExpr) for eventual capture and odr-use marking
// unless the variable is a reference that was initialized by a constant
// expression (this will never need to be captured or odr-used).
assert(E && "Capture variable should be used in an expression.");
if (!Var->getType()->isReferenceType() ||
!IsVariableNonDependentAndAConstantExpression(Var, SemaRef.Context))
LSI->addPotentialCapture(E->IgnoreParens());
}
}
}
}
/// Mark a variable referenced, and check whether it is odr-used
/// (C++ [basic.def.odr]p2, C99 6.9p3). Note that this should not be
/// used directly for normal expressions referring to VarDecl.
void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) {
DoMarkVarDeclReferenced(*this, Loc, Var, nullptr);
}
static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
Decl *D, Expr *E, bool MightBeOdrUse) {
if (SemaRef.isInOpenMPDeclareTargetContext())
SemaRef.checkDeclIsAllowedInOpenMPTarget(E, D);
if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
DoMarkVarDeclReferenced(SemaRef, Loc, Var, E);
return;
}
SemaRef.MarkAnyDeclReferenced(Loc, D, MightBeOdrUse);
// If this is a call to a method via a cast, also mark the method in the
// derived class used in case codegen can devirtualize the call.
const MemberExpr *ME = dyn_cast<MemberExpr>(E);
if (!ME)
return;
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ME->getMemberDecl());
if (!MD)
return;
// Only attempt to devirtualize if this is truly a virtual call.
bool IsVirtualCall = MD->isVirtual() &&
ME->performsVirtualDispatch(SemaRef.getLangOpts());
if (!IsVirtualCall)
return;
// If it's possible to devirtualize the call, mark the called function
// referenced.
CXXMethodDecl *DM = MD->getDevirtualizedMethod(
ME->getBase(), SemaRef.getLangOpts().AppleKext);
if (DM)
SemaRef.MarkAnyDeclReferenced(Loc, DM, MightBeOdrUse);
}
/// Perform reference-marking and odr-use handling for a DeclRefExpr.
void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) {
// TODO: update this with DR# once a defect report is filed.
// C++11 defect. The address of a pure member should not be an ODR use, even
// if it's a qualified reference.
bool OdrUse = true;
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getDecl()))
if (Method->isVirtual() &&
!Method->getDevirtualizedMethod(Base, getLangOpts().AppleKext))
OdrUse = false;
MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse);
}
/// Perform reference-marking and odr-use handling for a MemberExpr.
void Sema::MarkMemberReferenced(MemberExpr *E) {
// C++11 [basic.def.odr]p2:
// A non-overloaded function whose name appears as a potentially-evaluated
// expression or a member of a set of candidate functions, if selected by
// overload resolution when referred to from a potentially-evaluated
// expression, is odr-used, unless it is a pure virtual function and its
// name is not explicitly qualified.
bool MightBeOdrUse = true;
if (E->performsVirtualDispatch(getLangOpts())) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getMemberDecl()))
if (Method->isPure())
MightBeOdrUse = false;
}
SourceLocation Loc =
E->getMemberLoc().isValid() ? E->getMemberLoc() : E->getBeginLoc();
MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, MightBeOdrUse);
}
/// Perform marking for a reference to an arbitrary declaration. It
/// marks the declaration referenced, and performs odr-use checking for
/// functions and variables. This method should not be used when building a
/// normal expression which refers to a variable.
void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D,
bool MightBeOdrUse) {
if (MightBeOdrUse) {
if (auto *VD = dyn_cast<VarDecl>(D)) {
MarkVariableReferenced(Loc, VD);
return;
}
}
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
MarkFunctionReferenced(Loc, FD, MightBeOdrUse);
return;
}
D->setReferenced();
}
namespace {
// Mark all of the declarations used by a type as referenced.
// FIXME: Not fully implemented yet! We need to have a better understanding
// of when we're entering a context we should not recurse into.
// FIXME: This is and EvaluatedExprMarker are more-or-less equivalent to
// TreeTransforms rebuilding the type in a new context. Rather than
// duplicating the TreeTransform logic, we should consider reusing it here.
// Currently that causes problems when rebuilding LambdaExprs.
class MarkReferencedDecls : public RecursiveASTVisitor<MarkReferencedDecls> {
Sema &S;
SourceLocation Loc;
public:
typedef RecursiveASTVisitor<MarkReferencedDecls> Inherited;
MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) { }
bool TraverseTemplateArgument(const TemplateArgument &Arg);
};
}
bool MarkReferencedDecls::TraverseTemplateArgument(
const TemplateArgument &Arg) {
{
// A non-type template argument is a constant-evaluated context.
EnterExpressionEvaluationContext Evaluated(
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
if (Arg.getKind() == TemplateArgument::Declaration) {
if (Decl *D = Arg.getAsDecl())
S.MarkAnyDeclReferenced(Loc, D, true);
} else if (Arg.getKind() == TemplateArgument::Expression) {
S.MarkDeclarationsReferencedInExpr(Arg.getAsExpr(), false);
}
}
return Inherited::TraverseTemplateArgument(Arg);
}
void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) {
MarkReferencedDecls Marker(*this, Loc);
Marker.TraverseType(T);
}
namespace {
/// Helper class that marks all of the declarations referenced by
/// potentially-evaluated subexpressions as "referenced".
class EvaluatedExprMarker : public EvaluatedExprVisitor<EvaluatedExprMarker> {
Sema &S;
bool SkipLocalVariables;
public:
typedef EvaluatedExprVisitor<EvaluatedExprMarker> Inherited;
EvaluatedExprMarker(Sema &S, bool SkipLocalVariables)
: Inherited(S.Context), S(S), SkipLocalVariables(SkipLocalVariables) { }
void VisitDeclRefExpr(DeclRefExpr *E) {
// If we were asked not to visit local variables, don't.
if (SkipLocalVariables) {
if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()))
if (VD->hasLocalStorage())
return;
}
S.MarkDeclRefReferenced(E);
}
void VisitMemberExpr(MemberExpr *E) {
S.MarkMemberReferenced(E);
Inherited::VisitMemberExpr(E);
}
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
S.MarkFunctionReferenced(
E->getBeginLoc(),
const_cast<CXXDestructorDecl *>(E->getTemporary()->getDestructor()));
Visit(E->getSubExpr());
}
void VisitCXXNewExpr(CXXNewExpr *E) {
if (E->getOperatorNew())
S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorNew());
if (E->getOperatorDelete())
S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorDelete());
Inherited::VisitCXXNewExpr(E);
}
void VisitCXXDeleteExpr(CXXDeleteExpr *E) {
if (E->getOperatorDelete())
S.MarkFunctionReferenced(E->getBeginLoc(), E->getOperatorDelete());
QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType());
if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
S.MarkFunctionReferenced(E->getBeginLoc(), S.LookupDestructor(Record));
}
Inherited::VisitCXXDeleteExpr(E);
}
void VisitCXXConstructExpr(CXXConstructExpr *E) {
S.MarkFunctionReferenced(E->getBeginLoc(), E->getConstructor());
Inherited::VisitCXXConstructExpr(E);
}
void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
Visit(E->getExpr());
}
void VisitImplicitCastExpr(ImplicitCastExpr *E) {
Inherited::VisitImplicitCastExpr(E);
if (E->getCastKind() == CK_LValueToRValue)
S.UpdateMarkingForLValueToRValue(E->getSubExpr());
}
};
}
/// Mark any declarations that appear within this expression or any
/// potentially-evaluated subexpressions as "referenced".
///
/// \param SkipLocalVariables If true, don't mark local variables as
/// 'referenced'.
void Sema::MarkDeclarationsReferencedInExpr(Expr *E,
bool SkipLocalVariables) {
EvaluatedExprMarker(*this, SkipLocalVariables).Visit(E);
}
/// Emit a diagnostic that describes an effect on the run-time behavior
/// of the program being compiled.
///
/// This routine emits the given diagnostic when the code currently being
/// type-checked is "potentially evaluated", meaning that there is a
/// possibility that the code will actually be executable. Code in sizeof()
/// expressions, code used only during overload resolution, etc., are not
/// potentially evaluated. This routine will suppress such diagnostics or,
/// in the absolutely nutty case of potentially potentially evaluated
/// expressions (C++ typeid), queue the diagnostic to potentially emit it
/// later.
///
/// This routine should be used for all diagnostics that describe the run-time
/// behavior of a program, such as passing a non-POD value through an ellipsis.
/// Failure to do so will likely result in spurious diagnostics or failures
/// during overload resolution or within sizeof/alignof/typeof/typeid.
bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement,
const PartialDiagnostic &PD) {
switch (ExprEvalContexts.back().Context) {
case ExpressionEvaluationContext::Unevaluated:
case ExpressionEvaluationContext::UnevaluatedList:
case ExpressionEvaluationContext::UnevaluatedAbstract:
case ExpressionEvaluationContext::DiscardedStatement:
// The argument will never be evaluated, so don't complain.
break;
case ExpressionEvaluationContext::ConstantEvaluated:
// Relevant diagnostics should be produced by constant evaluation.
break;
case ExpressionEvaluationContext::PotentiallyEvaluated:
case ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:
if (Statement && getCurFunctionOrMethodDecl()) {
FunctionScopes.back()->PossiblyUnreachableDiags.
push_back(sema::PossiblyUnreachableDiag(PD, Loc, Statement));
return true;
}
// The initializer of a constexpr variable or of the first declaration of a
// static data member is not syntactically a constant evaluated constant,
// but nonetheless is always required to be a constant expression, so we
// can skip diagnosing.
// FIXME: Using the mangling context here is a hack.
if (auto *VD = dyn_cast_or_null<VarDecl>(
ExprEvalContexts.back().ManglingContextDecl)) {
if (VD->isConstexpr() ||
(VD->isStaticDataMember() && VD->isFirstDecl() && !VD->isInline()))
break;
// FIXME: For any other kind of variable, we should build a CFG for its
// initializer and check whether the context in question is reachable.
}
Diag(Loc, PD);
return true;
}
return false;
}
bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
CallExpr *CE, FunctionDecl *FD) {
if (ReturnType->isVoidType() || !ReturnType->isIncompleteType())
return false;
// If we're inside a decltype's expression, don't check for a valid return
// type or construct temporaries until we know whether this is the last call.
if (ExprEvalContexts.back().ExprContext ==
ExpressionEvaluationContextRecord::EK_Decltype) {
ExprEvalContexts.back().DelayedDecltypeCalls.push_back(CE);
return false;
}
class CallReturnIncompleteDiagnoser : public TypeDiagnoser {
FunctionDecl *FD;
CallExpr *CE;
public:
CallReturnIncompleteDiagnoser(FunctionDecl *FD, CallExpr *CE)
: FD(FD), CE(CE) { }
void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
if (!FD) {
S.Diag(Loc, diag::err_call_incomplete_return)
<< T << CE->getSourceRange();
return;
}
S.Diag(Loc, diag::err_call_function_incomplete_return)
<< CE->getSourceRange() << FD->getDeclName() << T;
S.Diag(FD->getLocation(), diag::note_entity_declared_at)
<< FD->getDeclName();
}
} Diagnoser(FD, CE);
if (RequireCompleteType(Loc, ReturnType, Diagnoser))
return true;
return false;
}
// Diagnose the s/=/==/ and s/\|=/!=/ typos. Note that adding parentheses
// will prevent this condition from triggering, which is what we want.
void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
SourceLocation Loc;
unsigned diagnostic = diag::warn_condition_is_assignment;
bool IsOrAssign = false;
if (BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) {
if (Op->getOpcode() != BO_Assign && Op->getOpcode() != BO_OrAssign)
return;
IsOrAssign = Op->getOpcode() == BO_OrAssign;
// Greylist some idioms by putting them into a warning subcategory.
if (ObjCMessageExpr *ME
= dyn_cast<ObjCMessageExpr>(Op->getRHS()->IgnoreParenCasts())) {
Selector Sel = ME->getSelector();
// self = [<foo> init...]
if (isSelfExpr(Op->getLHS()) && ME->getMethodFamily() == OMF_init)
diagnostic = diag::warn_condition_is_idiomatic_assignment;
// <foo> = [<bar> nextObject]
else if (Sel.isUnarySelector() && Sel.getNameForSlot(0) == "nextObject")
diagnostic = diag::warn_condition_is_idiomatic_assignment;
}
Loc = Op->getOperatorLoc();
} else if (CXXOperatorCallExpr *Op = dyn_cast<CXXOperatorCallExpr>(E)) {
if (Op->getOperator() != OO_Equal && Op->getOperator() != OO_PipeEqual)
return;
IsOrAssign = Op->getOperator() == OO_PipeEqual;
Loc = Op->getOperatorLoc();
} else if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))
return DiagnoseAssignmentAsCondition(POE->getSyntacticForm());
else {
// Not an assignment.
return;
}
Diag(Loc, diagnostic) << E->getSourceRange();
SourceLocation Open = E->getBeginLoc();
SourceLocation Close = getLocForEndOfToken(E->getSourceRange().getEnd());
Diag(Loc, diag::note_condition_assign_silence)
<< FixItHint::CreateInsertion(Open, "(")
<< FixItHint::CreateInsertion(Close, ")");
if (IsOrAssign)
Diag(Loc, diag::note_condition_or_assign_to_comparison)
<< FixItHint::CreateReplacement(Loc, "!=");
else
Diag(Loc, diag::note_condition_assign_to_comparison)
<< FixItHint::CreateReplacement(Loc, "==");
}
/// Redundant parentheses over an equality comparison can indicate
/// that the user intended an assignment used as condition.
void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) {
// Don't warn if the parens came from a macro.
SourceLocation parenLoc = ParenE->getBeginLoc();
if (parenLoc.isInvalid() || parenLoc.isMacroID())
return;
// Don't warn for dependent expressions.
if (ParenE->isTypeDependent())
return;
Expr *E = ParenE->IgnoreParens();
if (BinaryOperator *opE = dyn_cast<BinaryOperator>(E))
if (opE->getOpcode() == BO_EQ &&
opE->getLHS()->IgnoreParenImpCasts()->isModifiableLvalue(Context)
== Expr::MLV_Valid) {
SourceLocation Loc = opE->getOperatorLoc();
Diag(Loc, diag::warn_equality_with_extra_parens) << E->getSourceRange();
SourceRange ParenERange = ParenE->getSourceRange();
Diag(Loc, diag::note_equality_comparison_silence)
<< FixItHint::CreateRemoval(ParenERange.getBegin())
<< FixItHint::CreateRemoval(ParenERange.getEnd());
Diag(Loc, diag::note_equality_comparison_to_assign)
<< FixItHint::CreateReplacement(Loc, "=");
}
}
ExprResult Sema::CheckBooleanCondition(SourceLocation Loc, Expr *E,
bool IsConstexpr) {
DiagnoseAssignmentAsCondition(E);
if (ParenExpr *parenE = dyn_cast<ParenExpr>(E))
DiagnoseEqualityWithExtraParens(parenE);
ExprResult result = CheckPlaceholderExpr(E);
if (result.isInvalid()) return ExprError();
E = result.get();
if (!E->isTypeDependent()) {
if (getLangOpts().CPlusPlus)
return CheckCXXBooleanCondition(E, IsConstexpr); // C++ 6.4p4
ExprResult ERes = DefaultFunctionArrayLvalueConversion(E);
if (ERes.isInvalid())
return ExprError();
E = ERes.get();
QualType T = E->getType();
if (!T->isScalarType()) { // C99 6.8.4.1p1
Diag(Loc, diag::err_typecheck_statement_requires_scalar)
<< T << E->getSourceRange();
return ExprError();
}
CheckBoolLikeConversion(E, Loc);
}
return E;
}
Sema::ConditionResult Sema::ActOnCondition(Scope *S, SourceLocation Loc,
Expr *SubExpr, ConditionKind CK) {
// Empty conditions are valid in for-statements.
if (!SubExpr)
return ConditionResult();
ExprResult Cond;
switch (CK) {
case ConditionKind::Boolean:
Cond = CheckBooleanCondition(Loc, SubExpr);
break;
case ConditionKind::ConstexprIf:
Cond = CheckBooleanCondition(Loc, SubExpr, true);
break;
case ConditionKind::Switch:
Cond = CheckSwitchCondition(Loc, SubExpr);
break;
}
if (Cond.isInvalid())
return ConditionError();
// FIXME: FullExprArg doesn't have an invalid bit, so check nullness instead.
FullExprArg FullExpr = MakeFullExpr(Cond.get(), Loc);
if (!FullExpr.get())
return ConditionError();
return ConditionResult(*this, nullptr, FullExpr,
CK == ConditionKind::ConstexprIf);
}
namespace {
/// A visitor for rebuilding a call to an __unknown_any expression
/// to have an appropriate type.
struct RebuildUnknownAnyFunction
: StmtVisitor<RebuildUnknownAnyFunction, ExprResult> {
Sema &S;
RebuildUnknownAnyFunction(Sema &S) : S(S) {}
ExprResult VisitStmt(Stmt *S) {
llvm_unreachable("unexpected statement!");
}
ExprResult VisitExpr(Expr *E) {
S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_call)
<< E->getSourceRange();
return ExprError();
}
/// Rebuild an expression which simply semantically wraps another
/// expression which it shares the type and value kind of.
template <class T> ExprResult rebuildSugarExpr(T *E) {
ExprResult SubResult = Visit(E->getSubExpr());
if (SubResult.isInvalid()) return ExprError();
Expr *SubExpr = SubResult.get();
E->setSubExpr(SubExpr);
E->setType(SubExpr->getType());
E->setValueKind(SubExpr->getValueKind());
assert(E->getObjectKind() == OK_Ordinary);
return E;
}
ExprResult VisitParenExpr(ParenExpr *E) {
return rebuildSugarExpr(E);
}
ExprResult VisitUnaryExtension(UnaryOperator *E) {
return rebuildSugarExpr(E);
}
ExprResult VisitUnaryAddrOf(UnaryOperator *E) {
ExprResult SubResult = Visit(E->getSubExpr());
if (SubResult.isInvalid()) return ExprError();
Expr *SubExpr = SubResult.get();
E->setSubExpr(SubExpr);
E->setType(S.Context.getPointerType(SubExpr->getType()));
assert(E->getValueKind() == VK_RValue);
assert(E->getObjectKind() == OK_Ordinary);
return E;
}
ExprResult resolveDecl(Expr *E, ValueDecl *VD) {
if (!isa<FunctionDecl>(VD)) return VisitExpr(E);
E->setType(VD->getType());
assert(E->getValueKind() == VK_RValue);
if (S.getLangOpts().CPlusPlus &&
!(isa<CXXMethodDecl>(VD) &&
cast<CXXMethodDecl>(VD)->isInstance()))
E->setValueKind(VK_LValue);
return E;
}
ExprResult VisitMemberExpr(MemberExpr *E) {
return resolveDecl(E, E->getMemberDecl());
}
ExprResult VisitDeclRefExpr(DeclRefExpr *E) {
return resolveDecl(E, E->getDecl());
}
};
}
/// Given a function expression of unknown-any type, try to rebuild it
/// to have a function type.
static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *FunctionExpr) {
ExprResult Result = RebuildUnknownAnyFunction(S).Visit(FunctionExpr);
if (Result.isInvalid()) return ExprError();
return S.DefaultFunctionArrayConversion(Result.get());
}
namespace {
/// A visitor for rebuilding an expression of type __unknown_anytype
/// into one which resolves the type directly on the referring
/// expression. Strict preservation of the original source
/// structure is not a goal.
struct RebuildUnknownAnyExpr
: StmtVisitor<RebuildUnknownAnyExpr, ExprResult> {
Sema &S;
/// The current destination type.
QualType DestType;
RebuildUnknownAnyExpr(Sema &S, QualType CastType)
: S(S), DestType(CastType) {}
ExprResult VisitStmt(Stmt *S) {
llvm_unreachable("unexpected statement!");
}
ExprResult VisitExpr(Expr *E) {
S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_expr)
<< E->getSourceRange();
return ExprError();
}
ExprResult VisitCallExpr(CallExpr *E);
ExprResult VisitObjCMessageExpr(ObjCMessageExpr *E);
/// Rebuild an expression which simply semantically wraps another
/// expression which it shares the type and value kind of.
template <class T> ExprResult rebuildSugarExpr(T *E) {
ExprResult SubResult = Visit(E->getSubExpr());
if (SubResult.isInvalid()) return ExprError();
Expr *SubExpr = SubResult.get();
E->setSubExpr(SubExpr);
E->setType(SubExpr->getType());
E->setValueKind(SubExpr->getValueKind());
assert(E->getObjectKind() == OK_Ordinary);
return E;
}
ExprResult VisitParenExpr(ParenExpr *E) {
return rebuildSugarExpr(E);
}
ExprResult VisitUnaryExtension(UnaryOperator *E) {
return rebuildSugarExpr(E);
}
ExprResult VisitUnaryAddrOf(UnaryOperator *E) {
const PointerType *Ptr = DestType->getAs<PointerType>();
if (!Ptr) {
S.Diag(E->getOperatorLoc(), diag::err_unknown_any_addrof)
<< E->getSourceRange();
return ExprError();
}
if (isa<CallExpr>(E->getSubExpr())) {
S.Diag(E->getOperatorLoc(), diag::err_unknown_any_addrof_call)
<< E->getSourceRange();
return ExprError();
}
assert(E->getValueKind() == VK_RValue);
assert(E->getObjectKind() == OK_Ordinary);
E->setType(DestType);
// Build the sub-expression as if it were an object of the pointee type.
DestType = Ptr->getPointeeType();
ExprResult SubResult = Visit(E->getSubExpr());
if (SubResult.isInvalid()) return ExprError();
E->setSubExpr(SubResult.get());
return E;
}
ExprResult VisitImplicitCastExpr(ImplicitCastExpr *E);
ExprResult resolveDecl(Expr *E, ValueDecl *VD);
ExprResult VisitMemberExpr(MemberExpr *E) {
return resolveDecl(E, E->getMemberDecl());
}
ExprResult VisitDeclRefExpr(DeclRefExpr *E) {
return resolveDecl(E, E->getDecl());
}
};
}
/// Rebuilds a call expression which yielded __unknown_anytype.
ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) {
Expr *CalleeExpr = E->getCallee();
enum FnKind {
FK_MemberFunction,
FK_FunctionPointer,
FK_BlockPointer
};
FnKind Kind;
QualType CalleeType = CalleeExpr->getType();
if (CalleeType == S.Context.BoundMemberTy) {
assert(isa<CXXMemberCallExpr>(E) || isa<CXXOperatorCallExpr>(E));
Kind = FK_MemberFunction;
CalleeType = Expr::findBoundMemberType(CalleeExpr);
} else if (const PointerType *Ptr = CalleeType->getAs<PointerType>()) {
CalleeType = Ptr->getPointeeType();
Kind = FK_FunctionPointer;
} else {
CalleeType = CalleeType->castAs<BlockPointerType>()->getPointeeType();
Kind = FK_BlockPointer;
}
const FunctionType *FnType = CalleeType->castAs<FunctionType>();
// Verify that this is a legal result type of a function.
if (DestType->isArrayType() || DestType->isFunctionType()) {
unsigned diagID = diag::err_func_returning_array_function;
if (Kind == FK_BlockPointer)
diagID = diag::err_block_returning_array_function;
S.Diag(E->getExprLoc(), diagID)
<< DestType->isFunctionType() << DestType;
return ExprError();
}
// Otherwise, go ahead and set DestType as the call's result.
E->setType(DestType.getNonLValueExprType(S.Context));
E->setValueKind(Expr::getValueKindForType(DestType));
assert(E->getObjectKind() == OK_Ordinary);
// Rebuild the function type, replacing the result type with DestType.
const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType);
if (Proto) {
// __unknown_anytype(...) is a special case used by the debugger when
// it has no idea what a function's signature is.
//
// We want to build this call essentially under the K&R
// unprototyped rules, but making a FunctionNoProtoType in C++
// would foul up all sorts of assumptions. However, we cannot
// simply pass all arguments as variadic arguments, nor can we
// portably just call the function under a non-variadic type; see
// the comment on IR-gen's TargetInfo::isNoProtoCallVariadic.
// However, it turns out that in practice it is generally safe to
// call a function declared as "A foo(B,C,D);" under the prototype
// "A foo(B,C,D,...);". The only known exception is with the
// Windows ABI, where any variadic function is implicitly cdecl
// regardless of its normal CC. Therefore we change the parameter
// types to match the types of the arguments.
//
// This is a hack, but it is far superior to moving the
// corresponding target-specific code from IR-gen to Sema/AST.
ArrayRef<QualType> ParamTypes = Proto->getParamTypes();
SmallVector<QualType, 8> ArgTypes;
if (ParamTypes.empty() && Proto->isVariadic()) { // the special case
ArgTypes.reserve(E->getNumArgs());
for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
Expr *Arg = E->getArg(i);
QualType ArgType = Arg->getType();
if (E->isLValue()) {
ArgType = S.Context.getLValueReferenceType(ArgType);
} else if (E->isXValue()) {
ArgType = S.Context.getRValueReferenceType(ArgType);
}
ArgTypes.push_back(ArgType);
}
ParamTypes = ArgTypes;
}
DestType = S.Context.getFunctionType(DestType, ParamTypes,
Proto->getExtProtoInfo());
} else {
DestType = S.Context.getFunctionNoProtoType(DestType,
FnType->getExtInfo());
}
// Rebuild the appropriate pointer-to-function type.
switch (Kind) {
case FK_MemberFunction:
// Nothing to do.
break;
case FK_FunctionPointer:
DestType = S.Context.getPointerType(DestType);
break;
case FK_BlockPointer:
DestType = S.Context.getBlockPointerType(DestType);
break;
}
// Finally, we can recurse.
ExprResult CalleeResult = Visit(CalleeExpr);
if (!CalleeResult.isUsable()) return ExprError();
E->setCallee(CalleeResult.get());
// Bind a temporary if necessary.
return S.MaybeBindToTemporary(E);
}
ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *E) {
// Verify that this is a legal result type of a call.
if (DestType->isArrayType() || DestType->isFunctionType()) {
S.Diag(E->getExprLoc(), diag::err_func_returning_array_function)
<< DestType->isFunctionType() << DestType;
return ExprError();
}
// Rewrite the method result type if available.
if (ObjCMethodDecl *Method = E->getMethodDecl()) {
assert(Method->getReturnType() == S.Context.UnknownAnyTy);
Method->setReturnType(DestType);
}
// Change the type of the message.
E->setType(DestType.getNonReferenceType());
E->setValueKind(Expr::getValueKindForType(DestType));
return S.MaybeBindToTemporary(E);
}
ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *E) {
// The only case we should ever see here is a function-to-pointer decay.
if (E->getCastKind() == CK_FunctionToPointerDecay) {
assert(E->getValueKind() == VK_RValue);
assert(E->getObjectKind() == OK_Ordinary);
E->setType(DestType);
// Rebuild the sub-expression as the pointee (function) type.
DestType = DestType->castAs<PointerType>()->getPointeeType();
ExprResult Result = Visit(E->getSubExpr());
if (!Result.isUsable()) return ExprError();
E->setSubExpr(Result.get());
return E;
} else if (E->getCastKind() == CK_LValueToRValue) {
assert(E->getValueKind() == VK_RValue);
assert(E->getObjectKind() == OK_Ordinary);
assert(isa<BlockPointerType>(E->getType()));
E->setType(DestType);
// The sub-expression has to be a lvalue reference, so rebuild it as such.
DestType = S.Context.getLValueReferenceType(DestType);
ExprResult Result = Visit(E->getSubExpr());
if (!Result.isUsable()) return ExprError();
E->setSubExpr(Result.get());
return E;
} else {
llvm_unreachable("Unhandled cast type!");
}
}
ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) {
ExprValueKind ValueKind = VK_LValue;
QualType Type = DestType;
// We know how to make this work for certain kinds of decls:
// - functions
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(VD)) {
if (const PointerType *Ptr = Type->getAs<PointerType>()) {
DestType = Ptr->getPointeeType();
ExprResult Result = resolveDecl(E, VD);
if (Result.isInvalid()) return ExprError();
return S.ImpCastExprToType(Result.get(), Type,
CK_FunctionToPointerDecay, VK_RValue);
}
if (!Type->isFunctionType()) {
S.Diag(E->getExprLoc(), diag::err_unknown_any_function)
<< VD << E->getSourceRange();
return ExprError();
}
if (const FunctionProtoType *FT = Type->getAs<FunctionProtoType>()) {
// We must match the FunctionDecl's type to the hack introduced in
// RebuildUnknownAnyExpr::VisitCallExpr to vararg functions of unknown
// type. See the lengthy commentary in that routine.
QualType FDT = FD->getType();
const FunctionType *FnType = FDT->castAs<FunctionType>();
const FunctionProtoType *Proto = dyn_cast_or_null<FunctionProtoType>(FnType);
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
if (DRE && Proto && Proto->getParamTypes().empty() && Proto->isVariadic()) {
SourceLocation Loc = FD->getLocation();
FunctionDecl *NewFD = FunctionDecl::Create(S.Context,
FD->getDeclContext(),
Loc, Loc, FD->getNameInfo().getName(),
DestType, FD->getTypeSourceInfo(),
SC_None, false/*isInlineSpecified*/,
FD->hasPrototype(),
false/*isConstexprSpecified*/);
if (FD->getQualifier())
NewFD->setQualifierInfo(FD->getQualifierLoc());
SmallVector<ParmVarDecl*, 16> Params;
for (const auto &AI : FT->param_types()) {
ParmVarDecl *Param =
S.BuildParmVarDeclForTypedef(FD, Loc, AI);
Param->setScopeInfo(0, Params.size());
Params.push_back(Param);
}
NewFD->setParams(Params);
DRE->setDecl(NewFD);
VD = DRE->getDecl();
}
}
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
if (MD->isInstance()) {
ValueKind = VK_RValue;
Type = S.Context.BoundMemberTy;
}
// Function references aren't l-values in C.
if (!S.getLangOpts().CPlusPlus)
ValueKind = VK_RValue;
// - variables
} else if (isa<VarDecl>(VD)) {
if (const ReferenceType *RefTy = Type->getAs<ReferenceType>()) {
Type = RefTy->getPointeeType();
} else if (Type->isFunctionType()) {
S.Diag(E->getExprLoc(), diag::err_unknown_any_var_function_type)
<< VD << E->getSourceRange();
return ExprError();
}
// - nothing else
} else {
S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_decl)
<< VD << E->getSourceRange();
return ExprError();
}
// Modifying the declaration like this is friendly to IR-gen but
// also really dangerous.
VD->setType(DestType);
E->setType(Type);
E->setValueKind(ValueKind);
return E;
}
/// Check a cast of an unknown-any type. We intentionally only
/// trigger this for C-style casts.
ExprResult Sema::checkUnknownAnyCast(SourceRange TypeRange, QualType CastType,
Expr *CastExpr, CastKind &CastKind,
ExprValueKind &VK, CXXCastPath &Path) {
// The type we're casting to must be either void or complete.
if (!CastType->isVoidType() &&
RequireCompleteType(TypeRange.getBegin(), CastType,
diag::err_typecheck_cast_to_incomplete))
return ExprError();
// Rewrite the casted expression from scratch.
ExprResult result = RebuildUnknownAnyExpr(*this, CastType).Visit(CastExpr);
if (!result.isUsable()) return ExprError();
CastExpr = result.get();
VK = CastExpr->getValueKind();
CastKind = CK_NoOp;
return CastExpr;
}
ExprResult Sema::forceUnknownAnyToType(Expr *E, QualType ToType) {
return RebuildUnknownAnyExpr(*this, ToType).Visit(E);
}
ExprResult Sema::checkUnknownAnyArg(SourceLocation callLoc,
Expr *arg, QualType &paramType) {
// If the syntactic form of the argument is not an explicit cast of
// any sort, just do default argument promotion.
ExplicitCastExpr *castArg = dyn_cast<ExplicitCastExpr>(arg->IgnoreParens());
if (!castArg) {
ExprResult result = DefaultArgumentPromotion(arg);
if (result.isInvalid()) return ExprError();
paramType = result.get()->getType();
return result;
}
// Otherwise, use the type that was written in the explicit cast.
assert(!arg->hasPlaceholderType());
paramType = castArg->getTypeAsWritten();
// Copy-initialize a parameter of that type.
InitializedEntity entity =
InitializedEntity::InitializeParameter(Context, paramType,
/*consumed*/ false);
return PerformCopyInitialization(entity, callLoc, arg);
}
static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) {
Expr *orig = E;
unsigned diagID = diag::err_uncasted_use_of_unknown_any;
while (true) {
E = E->IgnoreParenImpCasts();
if (CallExpr *call = dyn_cast<CallExpr>(E)) {
E = call->getCallee();
diagID = diag::err_uncasted_call_of_unknown_any;
} else {
break;
}
}
SourceLocation loc;
NamedDecl *d;
if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(E)) {
loc = ref->getLocation();
d = ref->getDecl();
} else if (MemberExpr *mem = dyn_cast<MemberExpr>(E)) {
loc = mem->getMemberLoc();
d = mem->getMemberDecl();
} else if (ObjCMessageExpr *msg = dyn_cast<ObjCMessageExpr>(E)) {
diagID = diag::err_uncasted_call_of_unknown_any;
loc = msg->getSelectorStartLoc();
d = msg->getMethodDecl();
if (!d) {
S.Diag(loc, diag::err_uncasted_send_to_unknown_any_method)
<< static_cast<unsigned>(msg->isClassMessage()) << msg->getSelector()
<< orig->getSourceRange();
return ExprError();
}
} else {
S.Diag(E->getExprLoc(), diag::err_unsupported_unknown_any_expr)
<< E->getSourceRange();
return ExprError();
}
S.Diag(loc, diagID) << d << orig->getSourceRange();
// Never recoverable.
return ExprError();
}
/// Check for operands with placeholder types and complain if found.
/// Returns ExprError() if there was an error and no recovery was possible.
ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
if (!getLangOpts().CPlusPlus) {
// C cannot handle TypoExpr nodes on either side of a binop because it
// doesn't handle dependent types properly, so make sure any TypoExprs have
// been dealt with before checking the operands.
ExprResult Result = CorrectDelayedTyposInExpr(E);
if (!Result.isUsable()) return ExprError();
E = Result.get();
}
const BuiltinType *placeholderType = E->getType()->getAsPlaceholderType();
if (!placeholderType) return E;
switch (placeholderType->getKind()) {
// Overloaded expressions.
case BuiltinType::Overload: {
// Try to resolve a single function template specialization.
// This is obligatory.
ExprResult Result = E;
if (ResolveAndFixSingleFunctionTemplateSpecialization(Result, false))
return Result;
// No guarantees that ResolveAndFixSingleFunctionTemplateSpecialization
// leaves Result unchanged on failure.
Result = E;
if (resolveAndFixAddressOfOnlyViableOverloadCandidate(Result))
return Result;
// If that failed, try to recover with a call.
tryToRecoverWithCall(Result, PDiag(diag::err_ovl_unresolvable),
/*complain*/ true);
return Result;
}
// Bound member functions.
case BuiltinType::BoundMember: {
ExprResult result = E;
const Expr *BME = E->IgnoreParens();
PartialDiagnostic PD = PDiag(diag::err_bound_member_function);
// Try to give a nicer diagnostic if it is a bound member that we recognize.
if (isa<CXXPseudoDestructorExpr>(BME)) {
PD = PDiag(diag::err_dtor_expr_without_call) << /*pseudo-destructor*/ 1;
} else if (const auto *ME = dyn_cast<MemberExpr>(BME)) {
if (ME->getMemberNameInfo().getName().getNameKind() ==
DeclarationName::CXXDestructorName)
PD = PDiag(diag::err_dtor_expr_without_call) << /*destructor*/ 0;
}
tryToRecoverWithCall(result, PD,
/*complain*/ true);
return result;
}
// ARC unbridged casts.
case BuiltinType::ARCUnbridgedCast: {
Expr *realCast = stripARCUnbridgedCast(E);
diagnoseARCUnbridgedCast(realCast);
return realCast;
}
// Expressions of unknown type.
case BuiltinType::UnknownAny:
return diagnoseUnknownAnyExpr(*this, E);
// Pseudo-objects.
case BuiltinType::PseudoObject:
return checkPseudoObjectRValue(E);
case BuiltinType::BuiltinFn: {
// Accept __noop without parens by implicitly converting it to a call expr.
auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts());
if (DRE) {
auto *FD = cast<FunctionDecl>(DRE->getDecl());
if (FD->getBuiltinID() == Builtin::BI__noop) {
E = ImpCastExprToType(E, Context.getPointerType(FD->getType()),
CK_BuiltinFnToFnPtr)
.get();
return CallExpr::Create(Context, E, /*Args=*/{}, Context.IntTy,
VK_RValue, SourceLocation());
}
}
Diag(E->getBeginLoc(), diag::err_builtin_fn_use);
return ExprError();
}
// Expressions of unknown type.
case BuiltinType::OMPArraySection:
Diag(E->getBeginLoc(), diag::err_omp_array_section_use);
return ExprError();
// Everything else should be impossible.
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLImageTypes.def"
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
case BuiltinType::Id:
#include "clang/Basic/OpenCLExtensionTypes.def"
#define BUILTIN_TYPE(Id, SingletonId) case BuiltinType::Id:
#define PLACEHOLDER_TYPE(Id, SingletonId)
#include "clang/AST/BuiltinTypes.def"
break;
}
llvm_unreachable("invalid placeholder type!");
}
bool Sema::CheckCaseExpression(Expr *E) {
if (E->isTypeDependent())
return true;
if (E->isValueDependent() || E->isIntegerConstantExpr(Context))
return E->getType()->isIntegralOrEnumerationType();
return false;
}
/// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.
ExprResult
Sema::ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
assert((Kind == tok::kw___objc_yes || Kind == tok::kw___objc_no) &&
"Unknown Objective-C Boolean value!");
QualType BoolT = Context.ObjCBuiltinBoolTy;
if (!Context.getBOOLDecl()) {
LookupResult Result(*this, &Context.Idents.get("BOOL"), OpLoc,
Sema::LookupOrdinaryName);
if (LookupName(Result, getCurScope()) && Result.isSingleResult()) {
NamedDecl *ND = Result.getFoundDecl();
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(ND))
Context.setBOOLDecl(TD);
}
}
if (Context.getBOOLDecl())
BoolT = Context.getBOOLType();
return new (Context)
ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes, BoolT, OpLoc);
}
ExprResult Sema::ActOnObjCAvailabilityCheckExpr(
llvm::ArrayRef<AvailabilitySpec> AvailSpecs, SourceLocation AtLoc,
SourceLocation RParen) {
StringRef Platform = getASTContext().getTargetInfo().getPlatformName();
auto Spec = std::find_if(AvailSpecs.begin(), AvailSpecs.end(),
[&](const AvailabilitySpec &Spec) {
return Spec.getPlatform() == Platform;
});
VersionTuple Version;
if (Spec != AvailSpecs.end())
Version = Spec->getVersion();
// The use of `@available` in the enclosing function should be analyzed to
// warn when it's used inappropriately (i.e. not if(@available)).
if (getCurFunctionOrMethodDecl())
getEnclosingFunction()->HasPotentialAvailabilityViolations = true;
else if (getCurBlock() || getCurLambda())
getCurFunction()->HasPotentialAvailabilityViolations = true;
return new (Context)
ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy);
}
Index: vendor/clang/dist-release_80/lib/Sema/SemaTemplate.cpp
===================================================================
--- vendor/clang/dist-release_80/lib/Sema/SemaTemplate.cpp (revision 343795)
+++ vendor/clang/dist-release_80/lib/Sema/SemaTemplate.cpp (revision 343796)
@@ -1,10167 +1,10167 @@
//===------- SemaTemplate.cpp - Semantic Analysis for C++ Templates -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//===----------------------------------------------------------------------===//
//
// This file implements semantic analysis for C++ templates.
//===----------------------------------------------------------------------===//
#include "TreeTransform.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TypeVisitor.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include <iterator>
using namespace clang;
using namespace sema;
// Exported for use by Parser.
SourceRange
clang::getTemplateParamsRange(TemplateParameterList const * const *Ps,
unsigned N) {
if (!N) return SourceRange();
return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc());
}
namespace clang {
/// [temp.constr.decl]p2: A template's associated constraints are
/// defined as a single constraint-expression derived from the introduced
/// constraint-expressions [ ... ].
///
/// \param Params The template parameter list and optional requires-clause.
///
/// \param FD The underlying templated function declaration for a function
/// template.
static Expr *formAssociatedConstraints(TemplateParameterList *Params,
FunctionDecl *FD);
}
static Expr *clang::formAssociatedConstraints(TemplateParameterList *Params,
FunctionDecl *FD) {
// FIXME: Concepts: collect additional introduced constraint-expressions
assert(!FD && "Cannot collect constraints from function declaration yet.");
return Params->getRequiresClause();
}
/// Determine whether the declaration found is acceptable as the name
/// of a template and, if so, return that template declaration. Otherwise,
/// returns NULL.
static NamedDecl *isAcceptableTemplateName(ASTContext &Context,
NamedDecl *Orig,
bool AllowFunctionTemplates) {
NamedDecl *D = Orig->getUnderlyingDecl();
if (isa<TemplateDecl>(D)) {
if (!AllowFunctionTemplates && isa<FunctionTemplateDecl>(D))
return nullptr;
return Orig;
}
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
// C++ [temp.local]p1:
// Like normal (non-template) classes, class templates have an
// injected-class-name (Clause 9). The injected-class-name
// can be used with or without a template-argument-list. When
// it is used without a template-argument-list, it is
// equivalent to the injected-class-name followed by the
// template-parameters of the class template enclosed in
// <>. When it is used with a template-argument-list, it
// refers to the specified class template specialization,
// which could be the current specialization or another
// specialization.
if (Record->isInjectedClassName()) {
Record = cast<CXXRecordDecl>(Record->getDeclContext());
if (Record->getDescribedClassTemplate())
return Record->getDescribedClassTemplate();
if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Record))
return Spec->getSpecializedTemplate();
}
return nullptr;
}
// 'using Dependent::foo;' can resolve to a template name.
// 'using typename Dependent::foo;' cannot (not even if 'foo' is an
// injected-class-name).
if (isa<UnresolvedUsingValueDecl>(D))
return D;
return nullptr;
}
void Sema::FilterAcceptableTemplateNames(LookupResult &R,
bool AllowFunctionTemplates) {
// The set of class templates we've already seen.
llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates;
LookupResult::Filter filter = R.makeFilter();
while (filter.hasNext()) {
NamedDecl *Orig = filter.next();
NamedDecl *Repl = isAcceptableTemplateName(Context, Orig,
AllowFunctionTemplates);
if (!Repl)
filter.erase();
else if (Repl != Orig) {
// C++ [temp.local]p3:
// A lookup that finds an injected-class-name (10.2) can result in an
// ambiguity in certain cases (for example, if it is found in more than
// one base class). If all of the injected-class-names that are found
// refer to specializations of the same class template, and if the name
// is used as a template-name, the reference refers to the class
// template itself and not a specialization thereof, and is not
// ambiguous.
if (ClassTemplateDecl *ClassTmpl = dyn_cast<ClassTemplateDecl>(Repl))
if (!ClassTemplates.insert(ClassTmpl).second) {
filter.erase();
continue;
}
// FIXME: we promote access to public here as a workaround to
// the fact that LookupResult doesn't let us remember that we
// found this template through a particular injected class name,
// which means we end up doing nasty things to the invariants.
// Pretending that access is public is *much* safer.
filter.replace(Repl, AS_public);
}
}
filter.done();
}
bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R,
bool AllowFunctionTemplates) {
for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I)
if (isAcceptableTemplateName(Context, *I, AllowFunctionTemplates))
return true;
return false;
}
TemplateNameKind Sema::isTemplateName(Scope *S,
CXXScopeSpec &SS,
bool hasTemplateKeyword,
const UnqualifiedId &Name,
ParsedType ObjectTypePtr,
bool EnteringContext,
TemplateTy &TemplateResult,
bool &MemberOfUnknownSpecialization) {
assert(getLangOpts().CPlusPlus && "No template names in C!");
DeclarationName TName;
MemberOfUnknownSpecialization = false;
switch (Name.getKind()) {
case UnqualifiedIdKind::IK_Identifier:
TName = DeclarationName(Name.Identifier);
break;
case UnqualifiedIdKind::IK_OperatorFunctionId:
TName = Context.DeclarationNames.getCXXOperatorName(
Name.OperatorFunctionId.Operator);
break;
case UnqualifiedIdKind::IK_LiteralOperatorId:
TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier);
break;
default:
return TNK_Non_template;
}
QualType ObjectType = ObjectTypePtr.get();
LookupResult R(*this, TName, Name.getBeginLoc(), LookupOrdinaryName);
if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
MemberOfUnknownSpecialization))
return TNK_Non_template;
if (R.empty()) return TNK_Non_template;
if (R.isAmbiguous()) {
// Suppress diagnostics; we'll redo this lookup later.
R.suppressDiagnostics();
// FIXME: we might have ambiguous templates, in which case we
// should at least parse them properly!
return TNK_Non_template;
}
TemplateName Template;
TemplateNameKind TemplateKind;
unsigned ResultCount = R.end() - R.begin();
if (ResultCount > 1) {
// We assume that we'll preserve the qualifier from a function
// template name in other ways.
Template = Context.getOverloadedTemplateName(R.begin(), R.end());
TemplateKind = TNK_Function_template;
// We'll do this lookup again later.
R.suppressDiagnostics();
} else if (isa<UnresolvedUsingValueDecl>((*R.begin())->getUnderlyingDecl())) {
// We don't yet know whether this is a template-name or not.
MemberOfUnknownSpecialization = true;
return TNK_Non_template;
} else {
TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl());
if (SS.isSet() && !SS.isInvalid()) {
NestedNameSpecifier *Qualifier = SS.getScopeRep();
Template = Context.getQualifiedTemplateName(Qualifier,
hasTemplateKeyword, TD);
} else {
Template = TemplateName(TD);
}
if (isa<FunctionTemplateDecl>(TD)) {
TemplateKind = TNK_Function_template;
// We'll do this lookup again later.
R.suppressDiagnostics();
} else {
assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) ||
isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD) ||
isa<BuiltinTemplateDecl>(TD));
TemplateKind =
isa<VarTemplateDecl>(TD) ? TNK_Var_template : TNK_Type_template;
}
}
TemplateResult = TemplateTy::make(Template);
return TemplateKind;
}
bool Sema::isDeductionGuideName(Scope *S, const IdentifierInfo &Name,
SourceLocation NameLoc,
ParsedTemplateTy *Template) {
CXXScopeSpec SS;
bool MemberOfUnknownSpecialization = false;
// We could use redeclaration lookup here, but we don't need to: the
// syntactic form of a deduction guide is enough to identify it even
// if we can't look up the template name at all.
LookupResult R(*this, DeclarationName(&Name), NameLoc, LookupOrdinaryName);
if (LookupTemplateName(R, S, SS, /*ObjectType*/ QualType(),
/*EnteringContext*/ false,
MemberOfUnknownSpecialization))
return false;
if (R.empty()) return false;
if (R.isAmbiguous()) {
// FIXME: Diagnose an ambiguity if we find at least one template.
R.suppressDiagnostics();
return false;
}
// We only treat template-names that name type templates as valid deduction
// guide names.
TemplateDecl *TD = R.getAsSingle<TemplateDecl>();
if (!TD || !getAsTypeTemplateDecl(TD))
return false;
if (Template)
*Template = TemplateTy::make(TemplateName(TD));
return true;
}
bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II,
SourceLocation IILoc,
Scope *S,
const CXXScopeSpec *SS,
TemplateTy &SuggestedTemplate,
TemplateNameKind &SuggestedKind) {
// We can't recover unless there's a dependent scope specifier preceding the
// template name.
// FIXME: Typo correction?
if (!SS || !SS->isSet() || !isDependentScopeSpecifier(*SS) ||
computeDeclContext(*SS))
return false;
// The code is missing a 'template' keyword prior to the dependent template
// name.
NestedNameSpecifier *Qualifier = (NestedNameSpecifier*)SS->getScopeRep();
Diag(IILoc, diag::err_template_kw_missing)
<< Qualifier << II.getName()
<< FixItHint::CreateInsertion(IILoc, "template ");
SuggestedTemplate
= TemplateTy::make(Context.getDependentTemplateName(Qualifier, &II));
SuggestedKind = TNK_Dependent_template_name;
return true;
}
bool Sema::LookupTemplateName(LookupResult &Found,
Scope *S, CXXScopeSpec &SS,
QualType ObjectType,
bool EnteringContext,
bool &MemberOfUnknownSpecialization,
SourceLocation TemplateKWLoc) {
// Determine where to perform name lookup
MemberOfUnknownSpecialization = false;
DeclContext *LookupCtx = nullptr;
bool IsDependent = false;
if (!ObjectType.isNull()) {
// This nested-name-specifier occurs in a member access expression, e.g.,
// x->B::f, and we are looking into the type of the object.
assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
LookupCtx = computeDeclContext(ObjectType);
IsDependent = !LookupCtx;
assert((IsDependent || !ObjectType->isIncompleteType() ||
ObjectType->castAs<TagType>()->isBeingDefined()) &&
"Caller should have completed object type");
// Template names cannot appear inside an Objective-C class or object type.
if (ObjectType->isObjCObjectOrInterfaceType()) {
Found.clear();
return false;
}
} else if (SS.isSet()) {
// This nested-name-specifier occurs after another nested-name-specifier,
// so long into the context associated with the prior nested-name-specifier.
LookupCtx = computeDeclContext(SS, EnteringContext);
IsDependent = !LookupCtx;
// The declaration context must be complete.
if (LookupCtx && RequireCompleteDeclContext(SS, LookupCtx))
return true;
}
bool ObjectTypeSearchedInScope = false;
bool AllowFunctionTemplatesInLookup = true;
if (LookupCtx) {
// Perform "qualified" name lookup into the declaration context we
// computed, which is either the type of the base of a member access
// expression or the declaration context associated with a prior
// nested-name-specifier.
LookupQualifiedName(Found, LookupCtx);
// FIXME: The C++ standard does not clearly specify what happens in the
// case where the object type is dependent, and implementations vary. In
// Clang, we treat a name after a . or -> as a template-name if lookup
// finds a non-dependent member or member of the current instantiation that
// is a type template, or finds no such members and lookup in the context
// of the postfix-expression finds a type template. In the latter case, the
// name is nonetheless dependent, and we may resolve it to a member of an
// unknown specialization when we come to instantiate the template.
IsDependent |= Found.wasNotFoundInCurrentInstantiation();
}
if (!SS.isSet() && (ObjectType.isNull() || Found.empty())) {
// C++ [basic.lookup.classref]p1:
// In a class member access expression (5.2.5), if the . or -> token is
// immediately followed by an identifier followed by a <, the
// identifier must be looked up to determine whether the < is the
// beginning of a template argument list (14.2) or a less-than operator.
// The identifier is first looked up in the class of the object
// expression. If the identifier is not found, it is then looked up in
// the context of the entire postfix-expression and shall name a class
// template.
if (S)
LookupName(Found, S);
if (!ObjectType.isNull()) {
// FIXME: We should filter out all non-type templates here, particularly
// variable templates and concepts. But the exclusion of alias templates
// and template template parameters is a wording defect.
AllowFunctionTemplatesInLookup = false;
ObjectTypeSearchedInScope = true;
}
IsDependent |= Found.wasNotFoundInCurrentInstantiation();
}
if (Found.empty() && !IsDependent) {
// If we did not find any names, attempt to correct any typos.
DeclarationName Name = Found.getLookupName();
Found.clear();
// Simple filter callback that, for keywords, only accepts the C++ *_cast
auto FilterCCC = llvm::make_unique<CorrectionCandidateCallback>();
FilterCCC->WantTypeSpecifiers = false;
FilterCCC->WantExpressionKeywords = false;
FilterCCC->WantRemainingKeywords = false;
FilterCCC->WantCXXNamedCasts = true;
if (TypoCorrection Corrected = CorrectTypo(
Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS,
std::move(FilterCCC), CTK_ErrorRecovery, LookupCtx)) {
Found.setLookupName(Corrected.getCorrection());
if (auto *ND = Corrected.getFoundDecl())
Found.addDecl(ND);
FilterAcceptableTemplateNames(Found);
if (!Found.empty()) {
if (LookupCtx) {
std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
Name.getAsString() == CorrectedStr;
diagnoseTypo(Corrected, PDiag(diag::err_no_member_template_suggest)
<< Name << LookupCtx << DroppedSpecifier
<< SS.getRange());
} else {
diagnoseTypo(Corrected, PDiag(diag::err_no_template_suggest) << Name);
}
}
} else {
Found.setLookupName(Name);
}
}
NamedDecl *ExampleLookupResult =
Found.empty() ? nullptr : Found.getRepresentativeDecl();
FilterAcceptableTemplateNames(Found, AllowFunctionTemplatesInLookup);
if (Found.empty()) {
if (IsDependent) {
MemberOfUnknownSpecialization = true;
return false;
}
// If a 'template' keyword was used, a lookup that finds only non-template
// names is an error.
if (ExampleLookupResult && TemplateKWLoc.isValid()) {
Diag(Found.getNameLoc(), diag::err_template_kw_refers_to_non_template)
<< Found.getLookupName() << SS.getRange();
Diag(ExampleLookupResult->getUnderlyingDecl()->getLocation(),
diag::note_template_kw_refers_to_non_template)
<< Found.getLookupName();
return true;
}
return false;
}
if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope &&
!getLangOpts().CPlusPlus11) {
// C++03 [basic.lookup.classref]p1:
// [...] If the lookup in the class of the object expression finds a
// template, the name is also looked up in the context of the entire
// postfix-expression and [...]
//
// Note: C++11 does not perform this second lookup.
LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(),
LookupOrdinaryName);
LookupName(FoundOuter, S);
FilterAcceptableTemplateNames(FoundOuter, /*AllowFunctionTemplates=*/false);
if (FoundOuter.empty()) {
// - if the name is not found, the name found in the class of the
// object expression is used, otherwise
} else if (!FoundOuter.getAsSingle<ClassTemplateDecl>() ||
FoundOuter.isAmbiguous()) {
// - if the name is found in the context of the entire
// postfix-expression and does not name a class template, the name
// found in the class of the object expression is used, otherwise
FoundOuter.clear();
} else if (!Found.isSuppressingDiagnostics()) {
// - if the name found is a class template, it must refer to the same
// entity as the one found in the class of the object expression,
// otherwise the program is ill-formed.
if (!Found.isSingleResult() ||
Found.getFoundDecl()->getCanonicalDecl()
!= FoundOuter.getFoundDecl()->getCanonicalDecl()) {
Diag(Found.getNameLoc(),
diag::ext_nested_name_member_ref_lookup_ambiguous)
<< Found.getLookupName()
<< ObjectType;
Diag(Found.getRepresentativeDecl()->getLocation(),
diag::note_ambig_member_ref_object_type)
<< ObjectType;
Diag(FoundOuter.getFoundDecl()->getLocation(),
diag::note_ambig_member_ref_scope);
// Recover by taking the template that we found in the object
// expression's type.
}
}
}
return false;
}
void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,
SourceLocation Less,
SourceLocation Greater) {
if (TemplateName.isInvalid())
return;
DeclarationNameInfo NameInfo;
CXXScopeSpec SS;
LookupNameKind LookupKind;
DeclContext *LookupCtx = nullptr;
NamedDecl *Found = nullptr;
bool MissingTemplateKeyword = false;
// Figure out what name we looked up.
if (auto *DRE = dyn_cast<DeclRefExpr>(TemplateName.get())) {
NameInfo = DRE->getNameInfo();
SS.Adopt(DRE->getQualifierLoc());
LookupKind = LookupOrdinaryName;
Found = DRE->getFoundDecl();
} else if (auto *ME = dyn_cast<MemberExpr>(TemplateName.get())) {
NameInfo = ME->getMemberNameInfo();
SS.Adopt(ME->getQualifierLoc());
LookupKind = LookupMemberName;
LookupCtx = ME->getBase()->getType()->getAsCXXRecordDecl();
Found = ME->getMemberDecl();
} else if (auto *DSDRE =
dyn_cast<DependentScopeDeclRefExpr>(TemplateName.get())) {
NameInfo = DSDRE->getNameInfo();
SS.Adopt(DSDRE->getQualifierLoc());
MissingTemplateKeyword = true;
} else if (auto *DSME =
dyn_cast<CXXDependentScopeMemberExpr>(TemplateName.get())) {
NameInfo = DSME->getMemberNameInfo();
SS.Adopt(DSME->getQualifierLoc());
MissingTemplateKeyword = true;
} else {
llvm_unreachable("unexpected kind of potential template name");
}
// If this is a dependent-scope lookup, diagnose that the 'template' keyword
// was missing.
if (MissingTemplateKeyword) {
Diag(NameInfo.getBeginLoc(), diag::err_template_kw_missing)
<< "" << NameInfo.getName().getAsString() << SourceRange(Less, Greater);
return;
}
// Try to correct the name by looking for templates and C++ named casts.
struct TemplateCandidateFilter : CorrectionCandidateCallback {
TemplateCandidateFilter() {
WantTypeSpecifiers = false;
WantExpressionKeywords = false;
WantRemainingKeywords = false;
WantCXXNamedCasts = true;
};
bool ValidateCandidate(const TypoCorrection &Candidate) override {
if (auto *ND = Candidate.getCorrectionDecl())
return isAcceptableTemplateName(ND->getASTContext(), ND, true);
return Candidate.isKeyword();
}
};
DeclarationName Name = NameInfo.getName();
if (TypoCorrection Corrected =
CorrectTypo(NameInfo, LookupKind, S, &SS,
llvm::make_unique<TemplateCandidateFilter>(),
CTK_ErrorRecovery, LookupCtx)) {
auto *ND = Corrected.getFoundDecl();
if (ND)
ND = isAcceptableTemplateName(Context, ND,
/*AllowFunctionTemplates*/ true);
if (ND || Corrected.isKeyword()) {
if (LookupCtx) {
std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
Name.getAsString() == CorrectedStr;
diagnoseTypo(Corrected,
PDiag(diag::err_non_template_in_member_template_id_suggest)
<< Name << LookupCtx << DroppedSpecifier
<< SS.getRange(), false);
} else {
diagnoseTypo(Corrected,
PDiag(diag::err_non_template_in_template_id_suggest)
<< Name, false);
}
if (Found)
Diag(Found->getLocation(),
diag::note_non_template_in_template_id_found);
return;
}
}
Diag(NameInfo.getLoc(), diag::err_non_template_in_template_id)
<< Name << SourceRange(Less, Greater);
if (Found)
Diag(Found->getLocation(), diag::note_non_template_in_template_id_found);
}
/// ActOnDependentIdExpression - Handle a dependent id-expression that
/// was just parsed. This is only possible with an explicit scope
/// specifier naming a dependent type.
ExprResult
Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
bool isAddressOfOperand,
const TemplateArgumentListInfo *TemplateArgs) {
DeclContext *DC = getFunctionLevelDeclContext();
// C++11 [expr.prim.general]p12:
// An id-expression that denotes a non-static data member or non-static
// member function of a class can only be used:
// (...)
// - if that id-expression denotes a non-static data member and it
// appears in an unevaluated operand.
//
// If this might be the case, form a DependentScopeDeclRefExpr instead of a
// CXXDependentScopeMemberExpr. The former can instantiate to either
// DeclRefExpr or MemberExpr depending on lookup results, while the latter is
// always a MemberExpr.
bool MightBeCxx11UnevalField =
getLangOpts().CPlusPlus11 && isUnevaluatedContext();
// Check if the nested name specifier is an enum type.
bool IsEnum = false;
if (NestedNameSpecifier *NNS = SS.getScopeRep())
IsEnum = dyn_cast_or_null<EnumType>(NNS->getAsType());
if (!MightBeCxx11UnevalField && !isAddressOfOperand && !IsEnum &&
isa<CXXMethodDecl>(DC) && cast<CXXMethodDecl>(DC)->isInstance()) {
QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType();
// Since the 'this' expression is synthesized, we don't need to
// perform the double-lookup check.
NamedDecl *FirstQualifierInScope = nullptr;
return CXXDependentScopeMemberExpr::Create(
Context, /*This*/ nullptr, ThisType, /*IsArrow*/ true,
/*Op*/ SourceLocation(), SS.getWithLocInContext(Context), TemplateKWLoc,
FirstQualifierInScope, NameInfo, TemplateArgs);
}
return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs);
}
ExprResult
Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
return DependentScopeDeclRefExpr::Create(
Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo,
TemplateArgs);
}
/// Determine whether we would be unable to instantiate this template (because
/// it either has no definition, or is in the process of being instantiated).
bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
NamedDecl *Instantiation,
bool InstantiatedFromMember,
const NamedDecl *Pattern,
const NamedDecl *PatternDef,
TemplateSpecializationKind TSK,
bool Complain /*= true*/) {
assert(isa<TagDecl>(Instantiation) || isa<FunctionDecl>(Instantiation) ||
isa<VarDecl>(Instantiation));
bool IsEntityBeingDefined = false;
if (const TagDecl *TD = dyn_cast_or_null<TagDecl>(PatternDef))
IsEntityBeingDefined = TD->isBeingDefined();
if (PatternDef && !IsEntityBeingDefined) {
NamedDecl *SuggestedDef = nullptr;
if (!hasVisibleDefinition(const_cast<NamedDecl*>(PatternDef), &SuggestedDef,
/*OnlyNeedComplete*/false)) {
// If we're allowed to diagnose this and recover, do so.
bool Recover = Complain && !isSFINAEContext();
if (Complain)
diagnoseMissingImport(PointOfInstantiation, SuggestedDef,
Sema::MissingImportKind::Definition, Recover);
return !Recover;
}
return false;
}
if (!Complain || (PatternDef && PatternDef->isInvalidDecl()))
return true;
llvm::Optional<unsigned> Note;
QualType InstantiationTy;
if (TagDecl *TD = dyn_cast<TagDecl>(Instantiation))
InstantiationTy = Context.getTypeDeclType(TD);
if (PatternDef) {
Diag(PointOfInstantiation,
diag::err_template_instantiate_within_definition)
<< /*implicit|explicit*/(TSK != TSK_ImplicitInstantiation)
<< InstantiationTy;
// Not much point in noting the template declaration here, since
// we're lexically inside it.
Instantiation->setInvalidDecl();
} else if (InstantiatedFromMember) {
if (isa<FunctionDecl>(Instantiation)) {
Diag(PointOfInstantiation,
diag::err_explicit_instantiation_undefined_member)
<< /*member function*/ 1 << Instantiation->getDeclName()
<< Instantiation->getDeclContext();
Note = diag::note_explicit_instantiation_here;
} else {
assert(isa<TagDecl>(Instantiation) && "Must be a TagDecl!");
Diag(PointOfInstantiation,
diag::err_implicit_instantiate_member_undefined)
<< InstantiationTy;
Note = diag::note_member_declared_at;
}
} else {
if (isa<FunctionDecl>(Instantiation)) {
Diag(PointOfInstantiation,
diag::err_explicit_instantiation_undefined_func_template)
<< Pattern;
Note = diag::note_explicit_instantiation_here;
} else if (isa<TagDecl>(Instantiation)) {
Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
<< (TSK != TSK_ImplicitInstantiation)
<< InstantiationTy;
Note = diag::note_template_decl_here;
} else {
assert(isa<VarDecl>(Instantiation) && "Must be a VarDecl!");
if (isa<VarTemplateSpecializationDecl>(Instantiation)) {
Diag(PointOfInstantiation,
diag::err_explicit_instantiation_undefined_var_template)
<< Instantiation;
Instantiation->setInvalidDecl();
} else
Diag(PointOfInstantiation,
diag::err_explicit_instantiation_undefined_member)
<< /*static data member*/ 2 << Instantiation->getDeclName()
<< Instantiation->getDeclContext();
Note = diag::note_explicit_instantiation_here;
}
}
if (Note) // Diagnostics were emitted.
Diag(Pattern->getLocation(), Note.getValue());
// In general, Instantiation isn't marked invalid to get more than one
// error for multiple undefined instantiations. But the code that does
// explicit declaration -> explicit definition conversion can't handle
// invalid declarations, so mark as invalid in that case.
if (TSK == TSK_ExplicitInstantiationDeclaration)
Instantiation->setInvalidDecl();
return true;
}
/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
/// that the template parameter 'PrevDecl' is being shadowed by a new
/// declaration at location Loc. Returns true to indicate that this is
/// an error, and false otherwise.
void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) {
assert(PrevDecl->isTemplateParameter() && "Not a template parameter");
// Microsoft Visual C++ permits template parameters to be shadowed.
if (getLangOpts().MicrosoftExt)
return;
// C++ [temp.local]p4:
// A template-parameter shall not be redeclared within its
// scope (including nested scopes).
Diag(Loc, diag::err_template_param_shadow)
<< cast<NamedDecl>(PrevDecl)->getDeclName();
Diag(PrevDecl->getLocation(), diag::note_template_param_here);
}
/// AdjustDeclIfTemplate - If the given decl happens to be a template, reset
/// the parameter D to reference the templated declaration and return a pointer
/// to the template declaration. Otherwise, do nothing to D and return null.
TemplateDecl *Sema::AdjustDeclIfTemplate(Decl *&D) {
if (TemplateDecl *Temp = dyn_cast_or_null<TemplateDecl>(D)) {
D = Temp->getTemplatedDecl();
return Temp;
}
return nullptr;
}
ParsedTemplateArgument ParsedTemplateArgument::getTemplatePackExpansion(
SourceLocation EllipsisLoc) const {
assert(Kind == Template &&
"Only template template arguments can be pack expansions here");
assert(getAsTemplate().get().containsUnexpandedParameterPack() &&
"Template template argument pack expansion without packs");
ParsedTemplateArgument Result(*this);
Result.EllipsisLoc = EllipsisLoc;
return Result;
}
static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
const ParsedTemplateArgument &Arg) {
switch (Arg.getKind()) {
case ParsedTemplateArgument::Type: {
TypeSourceInfo *DI;
QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI);
if (!DI)
DI = SemaRef.Context.getTrivialTypeSourceInfo(T, Arg.getLocation());
return TemplateArgumentLoc(TemplateArgument(T), DI);
}
case ParsedTemplateArgument::NonType: {
Expr *E = static_cast<Expr *>(Arg.getAsExpr());
return TemplateArgumentLoc(TemplateArgument(E), E);
}
case ParsedTemplateArgument::Template: {
TemplateName Template = Arg.getAsTemplate().get();
TemplateArgument TArg;
if (Arg.getEllipsisLoc().isValid())
TArg = TemplateArgument(Template, Optional<unsigned int>());
else
TArg = Template;
return TemplateArgumentLoc(TArg,
Arg.getScopeSpec().getWithLocInContext(
SemaRef.Context),
Arg.getLocation(),
Arg.getEllipsisLoc());
}
}
llvm_unreachable("Unhandled parsed template argument");
}
/// Translates template arguments as provided by the parser
/// into template arguments used by semantic analysis.
void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn,
TemplateArgumentListInfo &TemplateArgs) {
for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I)
TemplateArgs.addArgument(translateTemplateArgument(*this,
TemplateArgsIn[I]));
}
static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S,
SourceLocation Loc,
IdentifierInfo *Name) {
NamedDecl *PrevDecl = SemaRef.LookupSingleName(
S, Name, Loc, Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration);
if (PrevDecl && PrevDecl->isTemplateParameter())
SemaRef.DiagnoseTemplateParameterShadow(Loc, PrevDecl);
}
/// Convert a parsed type into a parsed template argument. This is mostly
/// trivial, except that we may have parsed a C++17 deduced class template
/// specialization type, in which case we should form a template template
/// argument instead of a type template argument.
ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) {
TypeSourceInfo *TInfo;
QualType T = GetTypeFromParser(ParsedType.get(), &TInfo);
if (T.isNull())
return ParsedTemplateArgument();
assert(TInfo && "template argument with no location");
// If we might have formed a deduced template specialization type, convert
// it to a template template argument.
if (getLangOpts().CPlusPlus17) {
TypeLoc TL = TInfo->getTypeLoc();
SourceLocation EllipsisLoc;
if (auto PET = TL.getAs<PackExpansionTypeLoc>()) {
EllipsisLoc = PET.getEllipsisLoc();
TL = PET.getPatternLoc();
}
CXXScopeSpec SS;
if (auto ET = TL.getAs<ElaboratedTypeLoc>()) {
SS.Adopt(ET.getQualifierLoc());
TL = ET.getNamedTypeLoc();
}
if (auto DTST = TL.getAs<DeducedTemplateSpecializationTypeLoc>()) {
TemplateName Name = DTST.getTypePtr()->getTemplateName();
if (SS.isSet())
Name = Context.getQualifiedTemplateName(SS.getScopeRep(),
/*HasTemplateKeyword*/ false,
Name.getAsTemplateDecl());
ParsedTemplateArgument Result(SS, TemplateTy::make(Name),
DTST.getTemplateNameLoc());
if (EllipsisLoc.isValid())
Result = Result.getTemplatePackExpansion(EllipsisLoc);
return Result;
}
}
// This is a normal type template argument. Note, if the type template
// argument is an injected-class-name for a template, it has a dual nature
// and can be used as either a type or a template. We handle that in
// convertTypeTemplateArgumentToTemplate.
return ParsedTemplateArgument(ParsedTemplateArgument::Type,
ParsedType.get().getAsOpaquePtr(),
TInfo->getTypeLoc().getBeginLoc());
}
/// ActOnTypeParameter - Called when a C++ template type parameter
/// (e.g., "typename T") has been parsed. Typename specifies whether
/// the keyword "typename" was used to declare the type parameter
/// (otherwise, "class" was used), and KeyLoc is the location of the
/// "class" or "typename" keyword. ParamName is the name of the
/// parameter (NULL indicates an unnamed template parameter) and
/// ParamNameLoc is the location of the parameter name (if any).
/// If the type parameter has a default argument, it will be added
/// later via ActOnTypeParameterDefault.
NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
SourceLocation EllipsisLoc,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
SourceLocation ParamNameLoc,
unsigned Depth, unsigned Position,
SourceLocation EqualLoc,
ParsedType DefaultArg) {
assert(S->isTemplateParamScope() &&
"Template type parameter not in template parameter scope!");
SourceLocation Loc = ParamNameLoc;
if (!ParamName)
Loc = KeyLoc;
bool IsParameterPack = EllipsisLoc.isValid();
TemplateTypeParmDecl *Param
= TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(),
KeyLoc, Loc, Depth, Position, ParamName,
Typename, IsParameterPack);
Param->setAccess(AS_public);
if (ParamName) {
maybeDiagnoseTemplateParameterShadow(*this, S, ParamNameLoc, ParamName);
// Add the template parameter into the current scope.
S->AddDecl(Param);
IdResolver.AddDecl(Param);
}
// C++0x [temp.param]p9:
// A default template-argument may be specified for any kind of
// template-parameter that is not a template parameter pack.
if (DefaultArg && IsParameterPack) {
Diag(EqualLoc, diag::err_template_param_pack_default_arg);
DefaultArg = nullptr;
}
// Handle the default argument, if provided.
if (DefaultArg) {
TypeSourceInfo *DefaultTInfo;
GetTypeFromParser(DefaultArg, &DefaultTInfo);
assert(DefaultTInfo && "expected source information for type");
// Check for unexpanded parameter packs.
if (DiagnoseUnexpandedParameterPack(Loc, DefaultTInfo,
UPPC_DefaultArgument))
return Param;
// Check the template argument itself.
if (CheckTemplateArgument(Param, DefaultTInfo)) {
Param->setInvalidDecl();
return Param;
}
Param->setDefaultArgument(DefaultTInfo);
}
return Param;
}
/// Check that the type of a non-type template parameter is
/// well-formed.
///
/// \returns the (possibly-promoted) parameter type if valid;
/// otherwise, produces a diagnostic and returns a NULL type.
QualType Sema::CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
SourceLocation Loc) {
if (TSI->getType()->isUndeducedType()) {
// C++17 [temp.dep.expr]p3:
// An id-expression is type-dependent if it contains
// - an identifier associated by name lookup with a non-type
// template-parameter declared with a type that contains a
// placeholder type (7.1.7.4),
TSI = SubstAutoTypeSourceInfo(TSI, Context.DependentTy);
}
return CheckNonTypeTemplateParameterType(TSI->getType(), Loc);
}
QualType Sema::CheckNonTypeTemplateParameterType(QualType T,
SourceLocation Loc) {
// We don't allow variably-modified types as the type of non-type template
// parameters.
if (T->isVariablyModifiedType()) {
Diag(Loc, diag::err_variably_modified_nontype_template_param)
<< T;
return QualType();
}
// C++ [temp.param]p4:
//
// A non-type template-parameter shall have one of the following
// (optionally cv-qualified) types:
//
// -- integral or enumeration type,
if (T->isIntegralOrEnumerationType() ||
// -- pointer to object or pointer to function,
T->isPointerType() ||
// -- reference to object or reference to function,
T->isReferenceType() ||
// -- pointer to member,
T->isMemberPointerType() ||
// -- std::nullptr_t.
T->isNullPtrType() ||
// If T is a dependent type, we can't do the check now, so we
// assume that it is well-formed.
T->isDependentType() ||
// Allow use of auto in template parameter declarations.
T->isUndeducedType()) {
// C++ [temp.param]p5: The top-level cv-qualifiers on the template-parameter
// are ignored when determining its type.
return T.getUnqualifiedType();
}
// C++ [temp.param]p8:
//
// A non-type template-parameter of type "array of T" or
// "function returning T" is adjusted to be of type "pointer to
// T" or "pointer to function returning T", respectively.
else if (T->isArrayType() || T->isFunctionType())
return Context.getDecayedType(T);
Diag(Loc, diag::err_template_nontype_parm_bad_type)
<< T;
return QualType();
}
NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
unsigned Depth,
unsigned Position,
SourceLocation EqualLoc,
Expr *Default) {
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
// Check that we have valid decl-specifiers specified.
auto CheckValidDeclSpecifiers = [this, &D] {
// C++ [temp.param]
// p1
// template-parameter:
// ...
// parameter-declaration
// p2
// ... A storage class shall not be specified in a template-parameter
// declaration.
// [dcl.typedef]p1:
// The typedef specifier [...] shall not be used in the decl-specifier-seq
// of a parameter-declaration
const DeclSpec &DS = D.getDeclSpec();
auto EmitDiag = [this](SourceLocation Loc) {
Diag(Loc, diag::err_invalid_decl_specifier_in_nontype_parm)
<< FixItHint::CreateRemoval(Loc);
};
if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified)
EmitDiag(DS.getStorageClassSpecLoc());
if (DS.getThreadStorageClassSpec() != TSCS_unspecified)
EmitDiag(DS.getThreadStorageClassSpecLoc());
// [dcl.inline]p1:
// The inline specifier can be applied only to the declaration or
// definition of a variable or function.
if (DS.isInlineSpecified())
EmitDiag(DS.getInlineSpecLoc());
// [dcl.constexpr]p1:
// The constexpr specifier shall be applied only to the definition of a
// variable or variable template or the declaration of a function or
// function template.
if (DS.isConstexprSpecified())
EmitDiag(DS.getConstexprSpecLoc());
// [dcl.fct.spec]p1:
// Function-specifiers can be used only in function declarations.
if (DS.isVirtualSpecified())
EmitDiag(DS.getVirtualSpecLoc());
if (DS.isExplicitSpecified())
EmitDiag(DS.getExplicitSpecLoc());
if (DS.isNoreturnSpecified())
EmitDiag(DS.getNoreturnSpecLoc());
};
CheckValidDeclSpecifiers();
if (TInfo->getType()->isUndeducedType()) {
Diag(D.getIdentifierLoc(),
diag::warn_cxx14_compat_template_nontype_parm_auto_type)
<< QualType(TInfo->getType()->getContainedAutoType(), 0);
}
assert(S->isTemplateParamScope() &&
"Non-type template parameter not in template parameter scope!");
bool Invalid = false;
QualType T = CheckNonTypeTemplateParameterType(TInfo, D.getIdentifierLoc());
if (T.isNull()) {
T = Context.IntTy; // Recover with an 'int' type.
Invalid = true;
}
IdentifierInfo *ParamName = D.getIdentifier();
bool IsParameterPack = D.hasEllipsis();
NonTypeTemplateParmDecl *Param = NonTypeTemplateParmDecl::Create(
Context, Context.getTranslationUnitDecl(), D.getBeginLoc(),
D.getIdentifierLoc(), Depth, Position, ParamName, T, IsParameterPack,
TInfo);
Param->setAccess(AS_public);
if (Invalid)
Param->setInvalidDecl();
if (ParamName) {
maybeDiagnoseTemplateParameterShadow(*this, S, D.getIdentifierLoc(),
ParamName);
// Add the template parameter into the current scope.
S->AddDecl(Param);
IdResolver.AddDecl(Param);
}
// C++0x [temp.param]p9:
// A default template-argument may be specified for any kind of
// template-parameter that is not a template parameter pack.
if (Default && IsParameterPack) {
Diag(EqualLoc, diag::err_template_param_pack_default_arg);
Default = nullptr;
}
// Check the well-formedness of the default template argument, if provided.
if (Default) {
// Check for unexpanded parameter packs.
if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument))
return Param;
TemplateArgument Converted;
ExprResult DefaultRes =
CheckTemplateArgument(Param, Param->getType(), Default, Converted);
if (DefaultRes.isInvalid()) {
Param->setInvalidDecl();
return Param;
}
Default = DefaultRes.get();
Param->setDefaultArgument(Default);
}
return Param;
}
/// ActOnTemplateTemplateParameter - Called when a C++ template template
/// parameter (e.g. T in template <template \<typename> class T> class array)
/// has been parsed. S is the current scope.
NamedDecl *Sema::ActOnTemplateTemplateParameter(Scope* S,
SourceLocation TmpLoc,
TemplateParameterList *Params,
SourceLocation EllipsisLoc,
IdentifierInfo *Name,
SourceLocation NameLoc,
unsigned Depth,
unsigned Position,
SourceLocation EqualLoc,
ParsedTemplateArgument Default) {
assert(S->isTemplateParamScope() &&
"Template template parameter not in template parameter scope!");
// Construct the parameter object.
bool IsParameterPack = EllipsisLoc.isValid();
TemplateTemplateParmDecl *Param =
TemplateTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
NameLoc.isInvalid()? TmpLoc : NameLoc,
Depth, Position, IsParameterPack,
Name, Params);
Param->setAccess(AS_public);
// If the template template parameter has a name, then link the identifier
// into the scope and lookup mechanisms.
if (Name) {
maybeDiagnoseTemplateParameterShadow(*this, S, NameLoc, Name);
S->AddDecl(Param);
IdResolver.AddDecl(Param);
}
if (Params->size() == 0) {
Diag(Param->getLocation(), diag::err_template_template_parm_no_parms)
<< SourceRange(Params->getLAngleLoc(), Params->getRAngleLoc());
Param->setInvalidDecl();
}
// C++0x [temp.param]p9:
// A default template-argument may be specified for any kind of
// template-parameter that is not a template parameter pack.
if (IsParameterPack && !Default.isInvalid()) {
Diag(EqualLoc, diag::err_template_param_pack_default_arg);
Default = ParsedTemplateArgument();
}
if (!Default.isInvalid()) {
// Check only that we have a template template argument. We don't want to
// try to check well-formedness now, because our template template parameter
// might have dependent types in its template parameters, which we wouldn't
// be able to match now.
//
// If none of the template template parameter's template arguments mention
// other template parameters, we could actually perform more checking here.
// However, it isn't worth doing.
TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
if (DefaultArg.getArgument().getAsTemplate().isNull()) {
Diag(DefaultArg.getLocation(), diag::err_template_arg_not_valid_template)
<< DefaultArg.getSourceRange();
return Param;
}
// Check for unexpanded parameter packs.
if (DiagnoseUnexpandedParameterPack(DefaultArg.getLocation(),
DefaultArg.getArgument().getAsTemplate(),
UPPC_DefaultArgument))
return Param;
Param->setDefaultArgument(Context, DefaultArg);
}
return Param;
}
/// ActOnTemplateParameterList - Builds a TemplateParameterList, optionally
/// constrained by RequiresClause, that contains the template parameters in
/// Params.
TemplateParameterList *
Sema::ActOnTemplateParameterList(unsigned Depth,
SourceLocation ExportLoc,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ArrayRef<NamedDecl *> Params,
SourceLocation RAngleLoc,
Expr *RequiresClause) {
if (ExportLoc.isValid())
Diag(ExportLoc, diag::warn_template_export_unsupported);
return TemplateParameterList::Create(
Context, TemplateLoc, LAngleLoc,
llvm::makeArrayRef(Params.data(), Params.size()),
RAngleLoc, RequiresClause);
}
static void SetNestedNameSpecifier(Sema &S, TagDecl *T,
const CXXScopeSpec &SS) {
if (SS.isSet())
T->setQualifierInfo(SS.getWithLocInContext(S.Context));
}
DeclResult Sema::CheckClassTemplate(
Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists,
TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody) {
assert(TemplateParams && TemplateParams->size() > 0 &&
"No template parameters");
assert(TUK != TUK_Reference && "Can only declare or define class templates");
bool Invalid = false;
// Check that we can declare a template here.
if (CheckTemplateDeclScope(S, TemplateParams))
return true;
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
assert(Kind != TTK_Enum && "can't build template of enumerated type");
// There is no such thing as an unnamed class template.
if (!Name) {
Diag(KWLoc, diag::err_template_unnamed_class);
return true;
}
// Find any previous declaration with this name. For a friend with no
// scope explicitly specified, we only look for tag declarations (per
// C++11 [basic.lookup.elab]p2).
DeclContext *SemanticContext;
LookupResult Previous(*this, Name, NameLoc,
(SS.isEmpty() && TUK == TUK_Friend)
? LookupTagName : LookupOrdinaryName,
forRedeclarationInCurContext());
if (SS.isNotEmpty() && !SS.isInvalid()) {
SemanticContext = computeDeclContext(SS, true);
if (!SemanticContext) {
// FIXME: Horrible, horrible hack! We can't currently represent this
// in the AST, and historically we have just ignored such friend
// class templates, so don't complain here.
Diag(NameLoc, TUK == TUK_Friend
? diag::warn_template_qualified_friend_ignored
: diag::err_template_qualified_declarator_no_match)
<< SS.getScopeRep() << SS.getRange();
return TUK != TUK_Friend;
}
if (RequireCompleteDeclContext(SS, SemanticContext))
return true;
// If we're adding a template to a dependent context, we may need to
// rebuilding some of the types used within the template parameter list,
// now that we know what the current instantiation is.
if (SemanticContext->isDependentContext()) {
ContextRAII SavedContext(*this, SemanticContext);
if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams))
Invalid = true;
} else if (TUK != TUK_Friend && TUK != TUK_Reference)
diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc, false);
LookupQualifiedName(Previous, SemanticContext);
} else {
SemanticContext = CurContext;
// C++14 [class.mem]p14:
// If T is the name of a class, then each of the following shall have a
// name different from T:
// -- every member template of class T
if (TUK != TUK_Friend &&
DiagnoseClassNameShadow(SemanticContext,
DeclarationNameInfo(Name, NameLoc)))
return true;
LookupName(Previous, S);
}
if (Previous.isAmbiguous())
return true;
NamedDecl *PrevDecl = nullptr;
if (Previous.begin() != Previous.end())
PrevDecl = (*Previous.begin())->getUnderlyingDecl();
if (PrevDecl && PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
// Just pretend that we didn't see the previous declaration.
PrevDecl = nullptr;
}
// If there is a previous declaration with the same name, check
// whether this is a valid redeclaration.
ClassTemplateDecl *PrevClassTemplate =
dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
// We may have found the injected-class-name of a class template,
// class template partial specialization, or class template specialization.
// In these cases, grab the template that is being defined or specialized.
if (!PrevClassTemplate && PrevDecl && isa<CXXRecordDecl>(PrevDecl) &&
cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) {
PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext());
PrevClassTemplate
= cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate();
if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) {
PrevClassTemplate
= cast<ClassTemplateSpecializationDecl>(PrevDecl)
->getSpecializedTemplate();
}
}
if (TUK == TUK_Friend) {
// C++ [namespace.memdef]p3:
// [...] When looking for a prior declaration of a class or a function
// declared as a friend, and when the name of the friend class or
// function is neither a qualified name nor a template-id, scopes outside
// the innermost enclosing namespace scope are not considered.
if (!SS.isSet()) {
DeclContext *OutermostContext = CurContext;
while (!OutermostContext->isFileContext())
OutermostContext = OutermostContext->getLookupParent();
if (PrevDecl &&
(OutermostContext->Equals(PrevDecl->getDeclContext()) ||
OutermostContext->Encloses(PrevDecl->getDeclContext()))) {
SemanticContext = PrevDecl->getDeclContext();
} else {
// Declarations in outer scopes don't matter. However, the outermost
// context we computed is the semantic context for our new
// declaration.
PrevDecl = PrevClassTemplate = nullptr;
SemanticContext = OutermostContext;
// Check that the chosen semantic context doesn't already contain a
// declaration of this name as a non-tag type.
Previous.clear(LookupOrdinaryName);
DeclContext *LookupContext = SemanticContext;
while (LookupContext->isTransparentContext())
LookupContext = LookupContext->getLookupParent();
LookupQualifiedName(Previous, LookupContext);
if (Previous.isAmbiguous())
return true;
if (Previous.begin() != Previous.end())
PrevDecl = (*Previous.begin())->getUnderlyingDecl();
}
}
} else if (PrevDecl &&
!isDeclInScope(Previous.getRepresentativeDecl(), SemanticContext,
S, SS.isValid()))
PrevDecl = PrevClassTemplate = nullptr;
if (auto *Shadow = dyn_cast_or_null<UsingShadowDecl>(
PrevDecl ? Previous.getRepresentativeDecl() : nullptr)) {
if (SS.isEmpty() &&
!(PrevClassTemplate &&
PrevClassTemplate->getDeclContext()->getRedeclContext()->Equals(
SemanticContext->getRedeclContext()))) {
Diag(KWLoc, diag::err_using_decl_conflict_reverse);
Diag(Shadow->getTargetDecl()->getLocation(),
diag::note_using_decl_target);
Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) << 0;
// Recover by ignoring the old declaration.
PrevDecl = PrevClassTemplate = nullptr;
}
}
// TODO Memory management; associated constraints are not always stored.
Expr *const CurAC = formAssociatedConstraints(TemplateParams, nullptr);
if (PrevClassTemplate) {
// Ensure that the template parameter lists are compatible. Skip this check
// for a friend in a dependent context: the template parameter list itself
// could be dependent.
if (!(TUK == TUK_Friend && CurContext->isDependentContext()) &&
!TemplateParameterListsAreEqual(TemplateParams,
PrevClassTemplate->getTemplateParameters(),
/*Complain=*/true,
TPL_TemplateMatch))
return true;
// Check for matching associated constraints on redeclarations.
const Expr *const PrevAC = PrevClassTemplate->getAssociatedConstraints();
const bool RedeclACMismatch = [&] {
if (!(CurAC || PrevAC))
return false; // Nothing to check; no mismatch.
if (CurAC && PrevAC) {
llvm::FoldingSetNodeID CurACInfo, PrevACInfo;
CurAC->Profile(CurACInfo, Context, /*Canonical=*/true);
PrevAC->Profile(PrevACInfo, Context, /*Canonical=*/true);
if (CurACInfo == PrevACInfo)
return false; // All good; no mismatch.
}
return true;
}();
if (RedeclACMismatch) {
Diag(CurAC ? CurAC->getBeginLoc() : NameLoc,
diag::err_template_different_associated_constraints);
Diag(PrevAC ? PrevAC->getBeginLoc() : PrevClassTemplate->getLocation(),
diag::note_template_prev_declaration)
<< /*declaration*/ 0;
return true;
}
// C++ [temp.class]p4:
// In a redeclaration, partial specialization, explicit
// specialization or explicit instantiation of a class template,
// the class-key shall agree in kind with the original class
// template declaration (7.1.5.3).
RecordDecl *PrevRecordDecl = PrevClassTemplate->getTemplatedDecl();
if (!isAcceptableTagRedeclaration(PrevRecordDecl, Kind,
TUK == TUK_Definition, KWLoc, Name)) {
Diag(KWLoc, diag::err_use_with_wrong_tag)
<< Name
<< FixItHint::CreateReplacement(KWLoc, PrevRecordDecl->getKindName());
Diag(PrevRecordDecl->getLocation(), diag::note_previous_use);
Kind = PrevRecordDecl->getTagKind();
}
// Check for redefinition of this class template.
if (TUK == TUK_Definition) {
if (TagDecl *Def = PrevRecordDecl->getDefinition()) {
// If we have a prior definition that is not visible, treat this as
// simply making that previous definition visible.
NamedDecl *Hidden = nullptr;
if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
SkipBody->ShouldSkip = true;
SkipBody->Previous = Def;
auto *Tmpl = cast<CXXRecordDecl>(Hidden)->getDescribedClassTemplate();
assert(Tmpl && "original definition of a class template is not a "
"class template?");
makeMergedDefinitionVisible(Hidden);
makeMergedDefinitionVisible(Tmpl);
} else {
Diag(NameLoc, diag::err_redefinition) << Name;
Diag(Def->getLocation(), diag::note_previous_definition);
// FIXME: Would it make sense to try to "forget" the previous
// definition, as part of error recovery?
return true;
}
}
}
} else if (PrevDecl) {
// C++ [temp]p5:
// A class template shall not have the same name as any other
// template, class, function, object, enumeration, enumerator,
// namespace, or type in the same scope (3.3), except as specified
// in (14.5.4).
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
return true;
}
// Check the template parameter list of this declaration, possibly
// merging in the template parameter list from the previous class
// template declaration. Skip this check for a friend in a dependent
// context, because the template parameter list might be dependent.
if (!(TUK == TUK_Friend && CurContext->isDependentContext()) &&
CheckTemplateParameterList(
TemplateParams,
PrevClassTemplate
? PrevClassTemplate->getMostRecentDecl()->getTemplateParameters()
: nullptr,
(SS.isSet() && SemanticContext && SemanticContext->isRecord() &&
SemanticContext->isDependentContext())
? TPC_ClassTemplateMember
: TUK == TUK_Friend ? TPC_FriendClassTemplate : TPC_ClassTemplate,
SkipBody))
Invalid = true;
if (SS.isSet()) {
// If the name of the template was qualified, we must be defining the
// template out-of-line.
if (!SS.isInvalid() && !Invalid && !PrevClassTemplate) {
Diag(NameLoc, TUK == TUK_Friend ? diag::err_friend_decl_does_not_match
: diag::err_member_decl_does_not_match)
<< Name << SemanticContext << /*IsDefinition*/true << SS.getRange();
Invalid = true;
}
}
// If this is a templated friend in a dependent context we should not put it
// on the redecl chain. In some cases, the templated friend can be the most
// recent declaration tricking the template instantiator to make substitutions
// there.
// FIXME: Figure out how to combine with shouldLinkDependentDeclWithPrevious
bool ShouldAddRedecl
= !(TUK == TUK_Friend && CurContext->isDependentContext());
CXXRecordDecl *NewClass =
CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name,
PrevClassTemplate && ShouldAddRedecl ?
PrevClassTemplate->getTemplatedDecl() : nullptr,
/*DelayTypeCreation=*/true);
SetNestedNameSpecifier(*this, NewClass, SS);
if (NumOuterTemplateParamLists > 0)
NewClass->setTemplateParameterListsInfo(
Context, llvm::makeArrayRef(OuterTemplateParamLists,
NumOuterTemplateParamLists));
// Add alignment attributes if necessary; these attributes are checked when
// the ASTContext lays out the structure.
if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) {
AddAlignmentAttributesForRecord(NewClass);
AddMsStructLayoutForRecord(NewClass);
}
// Attach the associated constraints when the declaration will not be part of
// a decl chain.
Expr *const ACtoAttach =
PrevClassTemplate && ShouldAddRedecl ? nullptr : CurAC;
ClassTemplateDecl *NewTemplate
= ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
DeclarationName(Name), TemplateParams,
NewClass, ACtoAttach);
if (ShouldAddRedecl)
NewTemplate->setPreviousDecl(PrevClassTemplate);
NewClass->setDescribedClassTemplate(NewTemplate);
if (ModulePrivateLoc.isValid())
NewTemplate->setModulePrivate();
// Build the type for the class template declaration now.
QualType T = NewTemplate->getInjectedClassNameSpecialization();
T = Context.getInjectedClassNameType(NewClass, T);
assert(T->isDependentType() && "Class template type is not dependent?");
(void)T;
// If we are providing an explicit specialization of a member that is a
// class template, make a note of that.
if (PrevClassTemplate &&
PrevClassTemplate->getInstantiatedFromMemberTemplate())
PrevClassTemplate->setMemberSpecialization();
// Set the access specifier.
if (!Invalid && TUK != TUK_Friend && NewTemplate->getDeclContext()->isRecord())
SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS);
// Set the lexical context of these templates
NewClass->setLexicalDeclContext(CurContext);
NewTemplate->setLexicalDeclContext(CurContext);
if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip))
NewClass->startDefinition();
ProcessDeclAttributeList(S, NewClass, Attr);
if (PrevClassTemplate)
mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl());
AddPushedVisibilityAttribute(NewClass);
if (TUK != TUK_Friend) {
// Per C++ [basic.scope.temp]p2, skip the template parameter scopes.
Scope *Outer = S;
while ((Outer->getFlags() & Scope::TemplateParamScope) != 0)
Outer = Outer->getParent();
PushOnScopeChains(NewTemplate, Outer);
} else {
if (PrevClassTemplate && PrevClassTemplate->getAccess() != AS_none) {
NewTemplate->setAccess(PrevClassTemplate->getAccess());
NewClass->setAccess(PrevClassTemplate->getAccess());
}
NewTemplate->setObjectOfFriendDecl();
// Friend templates are visible in fairly strange ways.
if (!CurContext->isDependentContext()) {
DeclContext *DC = SemanticContext->getRedeclContext();
DC->makeDeclVisibleInContext(NewTemplate);
if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
PushOnScopeChains(NewTemplate, EnclosingScope,
/* AddToContext = */ false);
}
FriendDecl *Friend = FriendDecl::Create(
Context, CurContext, NewClass->getLocation(), NewTemplate, FriendLoc);
Friend->setAccess(AS_public);
CurContext->addDecl(Friend);
}
if (PrevClassTemplate)
CheckRedeclarationModuleOwnership(NewTemplate, PrevClassTemplate);
if (Invalid) {
NewTemplate->setInvalidDecl();
NewClass->setInvalidDecl();
}
ActOnDocumentableDecl(NewTemplate);
if (SkipBody && SkipBody->ShouldSkip)
return SkipBody->Previous;
return NewTemplate;
}
namespace {
/// Tree transform to "extract" a transformed type from a class template's
/// constructor to a deduction guide.
class ExtractTypeForDeductionGuide
: public TreeTransform<ExtractTypeForDeductionGuide> {
public:
typedef TreeTransform<ExtractTypeForDeductionGuide> Base;
ExtractTypeForDeductionGuide(Sema &SemaRef) : Base(SemaRef) {}
TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); }
QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) {
return TransformType(
TLB,
TL.getTypedefNameDecl()->getTypeSourceInfo()->getTypeLoc());
}
};
/// Transform to convert portions of a constructor declaration into the
/// corresponding deduction guide, per C++1z [over.match.class.deduct]p1.
struct ConvertConstructorToDeductionGuideTransform {
ConvertConstructorToDeductionGuideTransform(Sema &S,
ClassTemplateDecl *Template)
: SemaRef(S), Template(Template) {}
Sema &SemaRef;
ClassTemplateDecl *Template;
DeclContext *DC = Template->getDeclContext();
CXXRecordDecl *Primary = Template->getTemplatedDecl();
DeclarationName DeductionGuideName =
SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(Template);
QualType DeducedType = SemaRef.Context.getTypeDeclType(Primary);
// Index adjustment to apply to convert depth-1 template parameters into
// depth-0 template parameters.
unsigned Depth1IndexAdjustment = Template->getTemplateParameters()->size();
/// Transform a constructor declaration into a deduction guide.
NamedDecl *transformConstructor(FunctionTemplateDecl *FTD,
CXXConstructorDecl *CD) {
SmallVector<TemplateArgument, 16> SubstArgs;
LocalInstantiationScope Scope(SemaRef);
// C++ [over.match.class.deduct]p1:
// -- For each constructor of the class template designated by the
// template-name, a function template with the following properties:
// -- The template parameters are the template parameters of the class
// template followed by the template parameters (including default
// template arguments) of the constructor, if any.
TemplateParameterList *TemplateParams = Template->getTemplateParameters();
if (FTD) {
TemplateParameterList *InnerParams = FTD->getTemplateParameters();
SmallVector<NamedDecl *, 16> AllParams;
AllParams.reserve(TemplateParams->size() + InnerParams->size());
AllParams.insert(AllParams.begin(),
TemplateParams->begin(), TemplateParams->end());
SubstArgs.reserve(InnerParams->size());
// Later template parameters could refer to earlier ones, so build up
// a list of substituted template arguments as we go.
for (NamedDecl *Param : *InnerParams) {
MultiLevelTemplateArgumentList Args;
Args.addOuterTemplateArguments(SubstArgs);
Args.addOuterRetainedLevel();
NamedDecl *NewParam = transformTemplateParameter(Param, Args);
if (!NewParam)
return nullptr;
AllParams.push_back(NewParam);
SubstArgs.push_back(SemaRef.Context.getCanonicalTemplateArgument(
SemaRef.Context.getInjectedTemplateArg(NewParam)));
}
TemplateParams = TemplateParameterList::Create(
SemaRef.Context, InnerParams->getTemplateLoc(),
InnerParams->getLAngleLoc(), AllParams, InnerParams->getRAngleLoc(),
/*FIXME: RequiresClause*/ nullptr);
}
// If we built a new template-parameter-list, track that we need to
// substitute references to the old parameters into references to the
// new ones.
MultiLevelTemplateArgumentList Args;
if (FTD) {
Args.addOuterTemplateArguments(SubstArgs);
Args.addOuterRetainedLevel();
}
FunctionProtoTypeLoc FPTL = CD->getTypeSourceInfo()->getTypeLoc()
.getAsAdjusted<FunctionProtoTypeLoc>();
assert(FPTL && "no prototype for constructor declaration");
// Transform the type of the function, adjusting the return type and
// replacing references to the old parameters with references to the
// new ones.
TypeLocBuilder TLB;
SmallVector<ParmVarDecl*, 8> Params;
QualType NewType = transformFunctionProtoType(TLB, FPTL, Params, Args);
if (NewType.isNull())
return nullptr;
TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType);
return buildDeductionGuide(TemplateParams, CD->isExplicit(), NewTInfo,
CD->getBeginLoc(), CD->getLocation(),
CD->getEndLoc());
}
/// Build a deduction guide with the specified parameter types.
NamedDecl *buildSimpleDeductionGuide(MutableArrayRef<QualType> ParamTypes) {
SourceLocation Loc = Template->getLocation();
// Build the requested type.
FunctionProtoType::ExtProtoInfo EPI;
EPI.HasTrailingReturn = true;
QualType Result = SemaRef.BuildFunctionType(DeducedType, ParamTypes, Loc,
DeductionGuideName, EPI);
TypeSourceInfo *TSI = SemaRef.Context.getTrivialTypeSourceInfo(Result, Loc);
FunctionProtoTypeLoc FPTL =
TSI->getTypeLoc().castAs<FunctionProtoTypeLoc>();
// Build the parameters, needed during deduction / substitution.
SmallVector<ParmVarDecl*, 4> Params;
for (auto T : ParamTypes) {
ParmVarDecl *NewParam = ParmVarDecl::Create(
SemaRef.Context, DC, Loc, Loc, nullptr, T,
SemaRef.Context.getTrivialTypeSourceInfo(T, Loc), SC_None, nullptr);
NewParam->setScopeInfo(0, Params.size());
FPTL.setParam(Params.size(), NewParam);
Params.push_back(NewParam);
}
return buildDeductionGuide(Template->getTemplateParameters(), false, TSI,
Loc, Loc, Loc);
}
private:
/// Transform a constructor template parameter into a deduction guide template
/// parameter, rebuilding any internal references to earlier parameters and
/// renumbering as we go.
NamedDecl *transformTemplateParameter(NamedDecl *TemplateParam,
MultiLevelTemplateArgumentList &Args) {
if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) {
// TemplateTypeParmDecl's index cannot be changed after creation, so
// substitute it directly.
auto *NewTTP = TemplateTypeParmDecl::Create(
SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(),
/*Depth*/ 0, Depth1IndexAdjustment + TTP->getIndex(),
TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
TTP->isParameterPack());
if (TTP->hasDefaultArgument()) {
TypeSourceInfo *InstantiatedDefaultArg =
SemaRef.SubstType(TTP->getDefaultArgumentInfo(), Args,
TTP->getDefaultArgumentLoc(), TTP->getDeclName());
if (InstantiatedDefaultArg)
NewTTP->setDefaultArgument(InstantiatedDefaultArg);
}
SemaRef.CurrentInstantiationScope->InstantiatedLocal(TemplateParam,
NewTTP);
return NewTTP;
}
if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam))
return transformTemplateParameterImpl(TTP, Args);
return transformTemplateParameterImpl(
cast<NonTypeTemplateParmDecl>(TemplateParam), Args);
}
template<typename TemplateParmDecl>
TemplateParmDecl *
transformTemplateParameterImpl(TemplateParmDecl *OldParam,
MultiLevelTemplateArgumentList &Args) {
// Ask the template instantiator to do the heavy lifting for us, then adjust
// the index of the parameter once it's done.
auto *NewParam =
cast_or_null<TemplateParmDecl>(SemaRef.SubstDecl(OldParam, DC, Args));
assert(NewParam->getDepth() == 0 && "unexpected template param depth");
NewParam->setPosition(NewParam->getPosition() + Depth1IndexAdjustment);
return NewParam;
}
QualType transformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
SmallVectorImpl<ParmVarDecl*> &Params,
MultiLevelTemplateArgumentList &Args) {
SmallVector<QualType, 4> ParamTypes;
const FunctionProtoType *T = TL.getTypePtr();
// -- The types of the function parameters are those of the constructor.
for (auto *OldParam : TL.getParams()) {
ParmVarDecl *NewParam = transformFunctionTypeParam(OldParam, Args);
if (!NewParam)
return QualType();
ParamTypes.push_back(NewParam->getType());
Params.push_back(NewParam);
}
// -- The return type is the class template specialization designated by
// the template-name and template arguments corresponding to the
// template parameters obtained from the class template.
//
// We use the injected-class-name type of the primary template instead.
// This has the convenient property that it is different from any type that
// the user can write in a deduction-guide (because they cannot enter the
// context of the template), so implicit deduction guides can never collide
// with explicit ones.
QualType ReturnType = DeducedType;
TLB.pushTypeSpec(ReturnType).setNameLoc(Primary->getLocation());
// Resolving a wording defect, we also inherit the variadicness of the
// constructor.
FunctionProtoType::ExtProtoInfo EPI;
EPI.Variadic = T->isVariadic();
EPI.HasTrailingReturn = true;
QualType Result = SemaRef.BuildFunctionType(
ReturnType, ParamTypes, TL.getBeginLoc(), DeductionGuideName, EPI);
if (Result.isNull())
return QualType();
FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result);
NewTL.setLocalRangeBegin(TL.getLocalRangeBegin());
NewTL.setLParenLoc(TL.getLParenLoc());
NewTL.setRParenLoc(TL.getRParenLoc());
NewTL.setExceptionSpecRange(SourceRange());
NewTL.setLocalRangeEnd(TL.getLocalRangeEnd());
for (unsigned I = 0, E = NewTL.getNumParams(); I != E; ++I)
NewTL.setParam(I, Params[I]);
return Result;
}
ParmVarDecl *
transformFunctionTypeParam(ParmVarDecl *OldParam,
MultiLevelTemplateArgumentList &Args) {
TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo();
TypeSourceInfo *NewDI;
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;
// Extract the type. This (for instance) replaces references to typedef
// members of the current instantiations with the definitions of those
// typedefs, avoiding triggering instantiation of the deduced type during
// deduction.
NewDI = ExtractTypeForDeductionGuide(SemaRef).transform(NewDI);
// Resolving a wording defect, we also inherit default arguments from the
// constructor.
ExprResult NewDefArg;
if (OldParam->hasDefaultArg()) {
NewDefArg = SemaRef.SubstExpr(OldParam->getDefaultArg(), Args);
if (NewDefArg.isInvalid())
return nullptr;
}
ParmVarDecl *NewParam = ParmVarDecl::Create(SemaRef.Context, DC,
OldParam->getInnerLocStart(),
OldParam->getLocation(),
OldParam->getIdentifier(),
NewDI->getType(),
NewDI,
OldParam->getStorageClass(),
NewDefArg.get());
NewParam->setScopeInfo(OldParam->getFunctionScopeDepth(),
OldParam->getFunctionScopeIndex());
SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
return NewParam;
}
NamedDecl *buildDeductionGuide(TemplateParameterList *TemplateParams,
bool Explicit, TypeSourceInfo *TInfo,
SourceLocation LocStart, SourceLocation Loc,
SourceLocation LocEnd) {
DeclarationNameInfo Name(DeductionGuideName, Loc);
ArrayRef<ParmVarDecl *> Params =
TInfo->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams();
// Build the implicit deduction guide template.
auto *Guide =
CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, Explicit,
Name, TInfo->getType(), TInfo, LocEnd);
Guide->setImplicit();
Guide->setParams(Params);
for (auto *Param : Params)
Param->setDeclContext(Guide);
auto *GuideTemplate = FunctionTemplateDecl::Create(
SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
GuideTemplate->setImplicit();
Guide->setDescribedFunctionTemplate(GuideTemplate);
if (isa<CXXRecordDecl>(DC)) {
Guide->setAccess(AS_public);
GuideTemplate->setAccess(AS_public);
}
DC->addDecl(GuideTemplate);
return GuideTemplate;
}
};
}
void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
SourceLocation Loc) {
DeclContext *DC = Template->getDeclContext();
if (DC->isDependentContext())
return;
ConvertConstructorToDeductionGuideTransform Transform(
*this, cast<ClassTemplateDecl>(Template));
if (!isCompleteType(Loc, Transform.DeducedType))
return;
// Check whether we've already declared deduction guides for this template.
// FIXME: Consider storing a flag on the template to indicate this.
auto Existing = DC->lookup(Transform.DeductionGuideName);
for (auto *D : Existing)
if (D->isImplicit())
return;
// In case we were expanding a pack when we attempted to declare deduction
// guides, turn off pack expansion for everything we're about to do.
ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1);
// Create a template instantiation record to track the "instantiation" of
// constructors into deduction guides.
// FIXME: Add a kind for this to give more meaningful diagnostics. But can
// this substitution process actually fail?
InstantiatingTemplate BuildingDeductionGuides(*this, Loc, Template);
if (BuildingDeductionGuides.isInvalid())
return;
// Convert declared constructors into deduction guide templates.
// FIXME: Skip constructors for which deduction must necessarily fail (those
// for which some class template parameter without a default argument never
// appears in a deduced context).
bool AddedAny = false;
for (NamedDecl *D : LookupConstructors(Transform.Primary)) {
D = D->getUnderlyingDecl();
if (D->isInvalidDecl() || D->isImplicit())
continue;
D = cast<NamedDecl>(D->getCanonicalDecl());
auto *FTD = dyn_cast<FunctionTemplateDecl>(D);
auto *CD =
dyn_cast_or_null<CXXConstructorDecl>(FTD ? FTD->getTemplatedDecl() : D);
// Class-scope explicit specializations (MS extension) do not result in
// deduction guides.
if (!CD || (!FTD && CD->isFunctionTemplateSpecialization()))
continue;
Transform.transformConstructor(FTD, CD);
AddedAny = true;
}
// C++17 [over.match.class.deduct]
// -- If C is not defined or does not declare any constructors, an
// additional function template derived as above from a hypothetical
// constructor C().
if (!AddedAny)
Transform.buildSimpleDeductionGuide(None);
// -- An additional function template derived as above from a hypothetical
// constructor C(C), called the copy deduction candidate.
cast<CXXDeductionGuideDecl>(
cast<FunctionTemplateDecl>(
Transform.buildSimpleDeductionGuide(Transform.DeducedType))
->getTemplatedDecl())
->setIsCopyDeductionCandidate();
}
/// Diagnose the presence of a default template argument on a
/// template parameter, which is ill-formed in certain contexts.
///
/// \returns true if the default template argument should be dropped.
static bool DiagnoseDefaultTemplateArgument(Sema &S,
Sema::TemplateParamListContext TPC,
SourceLocation ParamLoc,
SourceRange DefArgRange) {
switch (TPC) {
case Sema::TPC_ClassTemplate:
case Sema::TPC_VarTemplate:
case Sema::TPC_TypeAliasTemplate:
return false;
case Sema::TPC_FunctionTemplate:
case Sema::TPC_FriendFunctionTemplateDefinition:
// C++ [temp.param]p9:
// A default template-argument shall not be specified in a
// function template declaration or a function template
// definition [...]
// If a friend function template declaration specifies a default
// template-argument, that declaration shall be a definition and shall be
// the only declaration of the function template in the translation unit.
// (C++98/03 doesn't have this wording; see DR226).
S.Diag(ParamLoc, S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_template_parameter_default_in_function_template
: diag::ext_template_parameter_default_in_function_template)
<< DefArgRange;
return false;
case Sema::TPC_ClassTemplateMember:
// C++0x [temp.param]p9:
// A default template-argument shall not be specified in the
// template-parameter-lists of the definition of a member of a
// class template that appears outside of the member's class.
S.Diag(ParamLoc, diag::err_template_parameter_default_template_member)
<< DefArgRange;
return true;
case Sema::TPC_FriendClassTemplate:
case Sema::TPC_FriendFunctionTemplate:
// C++ [temp.param]p9:
// A default template-argument shall not be specified in a
// friend template declaration.
S.Diag(ParamLoc, diag::err_template_parameter_default_friend_template)
<< DefArgRange;
return true;
// FIXME: C++0x [temp.param]p9 allows default template-arguments
// for friend function templates if there is only a single
// declaration (and it is a definition). Strange!
}
llvm_unreachable("Invalid TemplateParamListContext!");
}
/// Check for unexpanded parameter packs within the template parameters
/// of a template template parameter, recursively.
static bool DiagnoseUnexpandedParameterPacks(Sema &S,
TemplateTemplateParmDecl *TTP) {
// A template template parameter which is a parameter pack is also a pack
// expansion.
if (TTP->isParameterPack())
return false;
TemplateParameterList *Params = TTP->getTemplateParameters();
for (unsigned I = 0, N = Params->size(); I != N; ++I) {
NamedDecl *P = Params->getParam(I);
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
if (!NTTP->isParameterPack() &&
S.DiagnoseUnexpandedParameterPack(NTTP->getLocation(),
NTTP->getTypeSourceInfo(),
Sema::UPPC_NonTypeTemplateParameterType))
return true;
continue;
}
if (TemplateTemplateParmDecl *InnerTTP
= dyn_cast<TemplateTemplateParmDecl>(P))
if (DiagnoseUnexpandedParameterPacks(S, InnerTTP))
return true;
}
return false;
}
/// Checks the validity of a template parameter list, possibly
/// considering the template parameter list from a previous
/// declaration.
///
/// If an "old" template parameter list is provided, it must be
/// equivalent (per TemplateParameterListsAreEqual) to the "new"
/// template parameter list.
///
/// \param NewParams Template parameter list for a new template
/// declaration. This template parameter list will be updated with any
/// default arguments that are carried through from the previous
/// template parameter list.
///
/// \param OldParams If provided, template parameter list from a
/// previous declaration of the same template. Default template
/// arguments will be merged from the old template parameter list to
/// the new template parameter list.
///
/// \param TPC Describes the context in which we are checking the given
/// template parameter list.
///
/// \param SkipBody If we might have already made a prior merged definition
/// of this template visible, the corresponding body-skipping information.
/// Default argument redefinition is not an error when skipping such a body,
/// because (under the ODR) we can assume the default arguments are the same
/// as the prior merged definition.
///
/// \returns true if an error occurred, false otherwise.
bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
TemplateParameterList *OldParams,
TemplateParamListContext TPC,
SkipBodyInfo *SkipBody) {
bool Invalid = false;
// C++ [temp.param]p10:
// The set of default template-arguments available for use with a
// template declaration or definition is obtained by merging the
// default arguments from the definition (if in scope) and all
// declarations in scope in the same way default function
// arguments are (8.3.6).
bool SawDefaultArgument = false;
SourceLocation PreviousDefaultArgLoc;
// Dummy initialization to avoid warnings.
TemplateParameterList::iterator OldParam = NewParams->end();
if (OldParams)
OldParam = OldParams->begin();
bool RemoveDefaultArguments = false;
for (TemplateParameterList::iterator NewParam = NewParams->begin(),
NewParamEnd = NewParams->end();
NewParam != NewParamEnd; ++NewParam) {
// Variables used to diagnose redundant default arguments
bool RedundantDefaultArg = false;
SourceLocation OldDefaultLoc;
SourceLocation NewDefaultLoc;
// Variable used to diagnose missing default arguments
bool MissingDefaultArg = false;
// Variable used to diagnose non-final parameter packs
bool SawParameterPack = false;
if (TemplateTypeParmDecl *NewTypeParm
= dyn_cast<TemplateTypeParmDecl>(*NewParam)) {
// Check the presence of a default argument here.
if (NewTypeParm->hasDefaultArgument() &&
DiagnoseDefaultTemplateArgument(*this, TPC,
NewTypeParm->getLocation(),
NewTypeParm->getDefaultArgumentInfo()->getTypeLoc()
.getSourceRange()))
NewTypeParm->removeDefaultArgument();
// Merge default arguments for template type parameters.
TemplateTypeParmDecl *OldTypeParm
= OldParams? cast<TemplateTypeParmDecl>(*OldParam) : nullptr;
if (NewTypeParm->isParameterPack()) {
assert(!NewTypeParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
SawParameterPack = true;
} else if (OldTypeParm && hasVisibleDefaultArgument(OldTypeParm) &&
NewTypeParm->hasDefaultArgument() &&
(!SkipBody || !SkipBody->ShouldSkip)) {
OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc();
SawDefaultArgument = true;
RedundantDefaultArg = true;
PreviousDefaultArgLoc = NewDefaultLoc;
} else if (OldTypeParm && OldTypeParm->hasDefaultArgument()) {
// Merge the default argument from the old declaration to the
// new declaration.
NewTypeParm->setInheritedDefaultArgument(Context, OldTypeParm);
PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc();
} else if (NewTypeParm->hasDefaultArgument()) {
SawDefaultArgument = true;
PreviousDefaultArgLoc = NewTypeParm->getDefaultArgumentLoc();
} else if (SawDefaultArgument)
MissingDefaultArg = true;
} else if (NonTypeTemplateParmDecl *NewNonTypeParm
= dyn_cast<NonTypeTemplateParmDecl>(*NewParam)) {
// Check for unexpanded parameter packs.
if (!NewNonTypeParm->isParameterPack() &&
DiagnoseUnexpandedParameterPack(NewNonTypeParm->getLocation(),
NewNonTypeParm->getTypeSourceInfo(),
UPPC_NonTypeTemplateParameterType)) {
Invalid = true;
continue;
}
// Check the presence of a default argument here.
if (NewNonTypeParm->hasDefaultArgument() &&
DiagnoseDefaultTemplateArgument(*this, TPC,
NewNonTypeParm->getLocation(),
NewNonTypeParm->getDefaultArgument()->getSourceRange())) {
NewNonTypeParm->removeDefaultArgument();
}
// Merge default arguments for non-type template parameters
NonTypeTemplateParmDecl *OldNonTypeParm
= OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : nullptr;
if (NewNonTypeParm->isParameterPack()) {
assert(!NewNonTypeParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
if (!NewNonTypeParm->isPackExpansion())
SawParameterPack = true;
} else if (OldNonTypeParm && hasVisibleDefaultArgument(OldNonTypeParm) &&
NewNonTypeParm->hasDefaultArgument() &&
(!SkipBody || !SkipBody->ShouldSkip)) {
OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc();
NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc();
SawDefaultArgument = true;
RedundantDefaultArg = true;
PreviousDefaultArgLoc = NewDefaultLoc;
} else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument()) {
// Merge the default argument from the old declaration to the
// new declaration.
NewNonTypeParm->setInheritedDefaultArgument(Context, OldNonTypeParm);
PreviousDefaultArgLoc = OldNonTypeParm->getDefaultArgumentLoc();
} else if (NewNonTypeParm->hasDefaultArgument()) {
SawDefaultArgument = true;
PreviousDefaultArgLoc = NewNonTypeParm->getDefaultArgumentLoc();
} else if (SawDefaultArgument)
MissingDefaultArg = true;
} else {
TemplateTemplateParmDecl *NewTemplateParm
= cast<TemplateTemplateParmDecl>(*NewParam);
// Check for unexpanded parameter packs, recursively.
if (::DiagnoseUnexpandedParameterPacks(*this, NewTemplateParm)) {
Invalid = true;
continue;
}
// Check the presence of a default argument here.
if (NewTemplateParm->hasDefaultArgument() &&
DiagnoseDefaultTemplateArgument(*this, TPC,
NewTemplateParm->getLocation(),
NewTemplateParm->getDefaultArgument().getSourceRange()))
NewTemplateParm->removeDefaultArgument();
// Merge default arguments for template template parameters
TemplateTemplateParmDecl *OldTemplateParm
= OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : nullptr;
if (NewTemplateParm->isParameterPack()) {
assert(!NewTemplateParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
if (!NewTemplateParm->isPackExpansion())
SawParameterPack = true;
} else if (OldTemplateParm &&
hasVisibleDefaultArgument(OldTemplateParm) &&
NewTemplateParm->hasDefaultArgument() &&
(!SkipBody || !SkipBody->ShouldSkip)) {
OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation();
NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation();
SawDefaultArgument = true;
RedundantDefaultArg = true;
PreviousDefaultArgLoc = NewDefaultLoc;
} else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument()) {
// Merge the default argument from the old declaration to the
// new declaration.
NewTemplateParm->setInheritedDefaultArgument(Context, OldTemplateParm);
PreviousDefaultArgLoc
= OldTemplateParm->getDefaultArgument().getLocation();
} else if (NewTemplateParm->hasDefaultArgument()) {
SawDefaultArgument = true;
PreviousDefaultArgLoc
= NewTemplateParm->getDefaultArgument().getLocation();
} else if (SawDefaultArgument)
MissingDefaultArg = true;
}
// C++11 [temp.param]p11:
// If a template parameter of a primary class template or alias template
// is a template parameter pack, it shall be the last template parameter.
if (SawParameterPack && (NewParam + 1) != NewParamEnd &&
(TPC == TPC_ClassTemplate || TPC == TPC_VarTemplate ||
TPC == TPC_TypeAliasTemplate)) {
Diag((*NewParam)->getLocation(),
diag::err_template_param_pack_must_be_last_template_parameter);
Invalid = true;
}
if (RedundantDefaultArg) {
// C++ [temp.param]p12:
// A template-parameter shall not be given default arguments
// by two different declarations in the same scope.
Diag(NewDefaultLoc, diag::err_template_param_default_arg_redefinition);
Diag(OldDefaultLoc, diag::note_template_param_prev_default_arg);
Invalid = true;
} else if (MissingDefaultArg && TPC != TPC_FunctionTemplate) {
// C++ [temp.param]p11:
// If a template-parameter of a class template has a default
// template-argument, each subsequent template-parameter shall either
// have a default template-argument supplied or be a template parameter
// pack.
Diag((*NewParam)->getLocation(),
diag::err_template_param_default_arg_missing);
Diag(PreviousDefaultArgLoc, diag::note_template_param_prev_default_arg);
Invalid = true;
RemoveDefaultArguments = true;
}
// If we have an old template parameter list that we're merging
// in, move on to the next parameter.
if (OldParams)
++OldParam;
}
// We were missing some default arguments at the end of the list, so remove
// all of the default arguments.
if (RemoveDefaultArguments) {
for (TemplateParameterList::iterator NewParam = NewParams->begin(),
NewParamEnd = NewParams->end();
NewParam != NewParamEnd; ++NewParam) {
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*NewParam))
TTP->removeDefaultArgument();
else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(*NewParam))
NTTP->removeDefaultArgument();
else
cast<TemplateTemplateParmDecl>(*NewParam)->removeDefaultArgument();
}
}
return Invalid;
}
namespace {
/// A class which looks for a use of a certain level of template
/// parameter.
struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> {
typedef RecursiveASTVisitor<DependencyChecker> super;
unsigned Depth;
// Whether we're looking for a use of a template parameter that makes the
// overall construct type-dependent / a dependent type. This is strictly
// best-effort for now; we may fail to match at all for a dependent type
// in some cases if this is set.
bool IgnoreNonTypeDependent;
bool Match;
SourceLocation MatchLoc;
DependencyChecker(unsigned Depth, bool IgnoreNonTypeDependent)
: Depth(Depth), IgnoreNonTypeDependent(IgnoreNonTypeDependent),
Match(false) {}
DependencyChecker(TemplateParameterList *Params, bool IgnoreNonTypeDependent)
: IgnoreNonTypeDependent(IgnoreNonTypeDependent), Match(false) {
NamedDecl *ND = Params->getParam(0);
if (TemplateTypeParmDecl *PD = dyn_cast<TemplateTypeParmDecl>(ND)) {
Depth = PD->getDepth();
} else if (NonTypeTemplateParmDecl *PD =
dyn_cast<NonTypeTemplateParmDecl>(ND)) {
Depth = PD->getDepth();
} else {
Depth = cast<TemplateTemplateParmDecl>(ND)->getDepth();
}
}
bool Matches(unsigned ParmDepth, SourceLocation Loc = SourceLocation()) {
if (ParmDepth >= Depth) {
Match = true;
MatchLoc = Loc;
return true;
}
return false;
}
bool TraverseStmt(Stmt *S, DataRecursionQueue *Q = nullptr) {
// Prune out non-type-dependent expressions if requested. This can
// sometimes result in us failing to find a template parameter reference
// (if a value-dependent expression creates a dependent type), but this
// mode is best-effort only.
if (auto *E = dyn_cast_or_null<Expr>(S))
if (IgnoreNonTypeDependent && !E->isTypeDependent())
return true;
return super::TraverseStmt(S, Q);
}
bool TraverseTypeLoc(TypeLoc TL) {
if (IgnoreNonTypeDependent && !TL.isNull() &&
!TL.getType()->isDependentType())
return true;
return super::TraverseTypeLoc(TL);
}
bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
return !Matches(TL.getTypePtr()->getDepth(), TL.getNameLoc());
}
bool VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
// For a best-effort search, keep looking until we find a location.
return IgnoreNonTypeDependent || !Matches(T->getDepth());
}
bool TraverseTemplateName(TemplateName N) {
if (TemplateTemplateParmDecl *PD =
dyn_cast_or_null<TemplateTemplateParmDecl>(N.getAsTemplateDecl()))
if (Matches(PD->getDepth()))
return false;
return super::TraverseTemplateName(N);
}
bool VisitDeclRefExpr(DeclRefExpr *E) {
if (NonTypeTemplateParmDecl *PD =
dyn_cast<NonTypeTemplateParmDecl>(E->getDecl()))
if (Matches(PD->getDepth(), E->getExprLoc()))
return false;
return super::VisitDeclRefExpr(E);
}
bool VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
return TraverseType(T->getReplacementType());
}
bool
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
return TraverseTemplateArgument(T->getArgumentPack());
}
bool TraverseInjectedClassNameType(const InjectedClassNameType *T) {
return TraverseType(T->getInjectedSpecializationType());
}
};
} // end anonymous namespace
/// Determines whether a given type depends on the given parameter
/// list.
static bool
DependsOnTemplateParameters(QualType T, TemplateParameterList *Params) {
DependencyChecker Checker(Params, /*IgnoreNonTypeDependent*/false);
Checker.TraverseType(T);
return Checker.Match;
}
// Find the source range corresponding to the named type in the given
// nested-name-specifier, if any.
static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
QualType T,
const CXXScopeSpec &SS) {
NestedNameSpecifierLoc NNSLoc(SS.getScopeRep(), SS.location_data());
while (NestedNameSpecifier *NNS = NNSLoc.getNestedNameSpecifier()) {
if (const Type *CurType = NNS->getAsType()) {
if (Context.hasSameUnqualifiedType(T, QualType(CurType, 0)))
return NNSLoc.getTypeLoc().getSourceRange();
} else
break;
NNSLoc = NNSLoc.getPrefix();
}
return SourceRange();
}
/// Match the given template parameter lists to the given scope
/// specifier, returning the template parameter list that applies to the
/// name.
///
/// \param DeclStartLoc the start of the declaration that has a scope
/// specifier or a template parameter list.
///
/// \param DeclLoc The location of the declaration itself.
///
/// \param SS the scope specifier that will be matched to the given template
/// parameter lists. This scope specifier precedes a qualified name that is
/// being declared.
///
/// \param TemplateId The template-id following the scope specifier, if there
/// is one. Used to check for a missing 'template<>'.
///
/// \param ParamLists the template parameter lists, from the outermost to the
/// innermost template parameter lists.
///
/// \param IsFriend Whether to apply the slightly different rules for
/// matching template parameters to scope specifiers in friend
/// declarations.
///
/// \param IsMemberSpecialization will be set true if the scope specifier
/// denotes a fully-specialized type, and therefore this is a declaration of
/// a member specialization.
///
/// \returns the template parameter list, if any, that corresponds to the
/// name that is preceded by the scope specifier @p SS. This template
/// parameter list may have template parameters (if we're declaring a
/// template) or may have no template parameters (if we're declaring a
/// template specialization), or may be NULL (if what we're declaring isn't
/// itself a template).
TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS,
TemplateIdAnnotation *TemplateId,
ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend,
bool &IsMemberSpecialization, bool &Invalid) {
IsMemberSpecialization = false;
Invalid = false;
// The sequence of nested types to which we will match up the template
// parameter lists. We first build this list by starting with the type named
// by the nested-name-specifier and walking out until we run out of types.
SmallVector<QualType, 4> NestedTypes;
QualType T;
if (SS.getScopeRep()) {
if (CXXRecordDecl *Record
= dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, true)))
T = Context.getTypeDeclType(Record);
else
T = QualType(SS.getScopeRep()->getAsType(), 0);
}
// If we found an explicit specialization that prevents us from needing
// 'template<>' headers, this will be set to the location of that
// explicit specialization.
SourceLocation ExplicitSpecLoc;
while (!T.isNull()) {
NestedTypes.push_back(T);
// Retrieve the parent of a record type.
if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) {
// If this type is an explicit specialization, we're done.
if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
if (!isa<ClassTemplatePartialSpecializationDecl>(Spec) &&
Spec->getSpecializationKind() == TSK_ExplicitSpecialization) {
ExplicitSpecLoc = Spec->getLocation();
break;
}
} else if (Record->getTemplateSpecializationKind()
== TSK_ExplicitSpecialization) {
ExplicitSpecLoc = Record->getLocation();
break;
}
if (TypeDecl *Parent = dyn_cast<TypeDecl>(Record->getParent()))
T = Context.getTypeDeclType(Parent);
else
T = QualType();
continue;
}
if (const TemplateSpecializationType *TST
= T->getAs<TemplateSpecializationType>()) {
if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {
if (TypeDecl *Parent = dyn_cast<TypeDecl>(Template->getDeclContext()))
T = Context.getTypeDeclType(Parent);
else
T = QualType();
continue;
}
}
// Look one step prior in a dependent template specialization type.
if (const DependentTemplateSpecializationType *DependentTST
= T->getAs<DependentTemplateSpecializationType>()) {
if (NestedNameSpecifier *NNS = DependentTST->getQualifier())
T = QualType(NNS->getAsType(), 0);
else
T = QualType();
continue;
}
// Look one step prior in a dependent name type.
if (const DependentNameType *DependentName = T->getAs<DependentNameType>()){
if (NestedNameSpecifier *NNS = DependentName->getQualifier())
T = QualType(NNS->getAsType(), 0);
else
T = QualType();
continue;
}
// Retrieve the parent of an enumeration type.
if (const EnumType *EnumT = T->getAs<EnumType>()) {
// FIXME: Forward-declared enums require a TSK_ExplicitSpecialization
// check here.
EnumDecl *Enum = EnumT->getDecl();
// Get to the parent type.
if (TypeDecl *Parent = dyn_cast<TypeDecl>(Enum->getParent()))
T = Context.getTypeDeclType(Parent);
else
T = QualType();
continue;
}
T = QualType();
}
// Reverse the nested types list, since we want to traverse from the outermost
// to the innermost while checking template-parameter-lists.
std::reverse(NestedTypes.begin(), NestedTypes.end());
// C++0x [temp.expl.spec]p17:
// A member or a member template may be nested within many
// enclosing class templates. In an explicit specialization for
// such a member, the member declaration shall be preceded by a
// template<> for each enclosing class template that is
// explicitly specialized.
bool SawNonEmptyTemplateParameterList = false;
auto CheckExplicitSpecialization = [&](SourceRange Range, bool Recovery) {
if (SawNonEmptyTemplateParameterList) {
Diag(DeclLoc, diag::err_specialize_member_of_template)
<< !Recovery << Range;
Invalid = true;
IsMemberSpecialization = false;
return true;
}
return false;
};
auto DiagnoseMissingExplicitSpecialization = [&] (SourceRange Range) {
// Check that we can have an explicit specialization here.
if (CheckExplicitSpecialization(Range, true))
return true;
// We don't have a template header, but we should.
SourceLocation ExpectedTemplateLoc;
if (!ParamLists.empty())
ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc();
else
ExpectedTemplateLoc = DeclStartLoc;
Diag(DeclLoc, diag::err_template_spec_needs_header)
<< Range
<< FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> ");
return false;
};
unsigned ParamIdx = 0;
for (unsigned TypeIdx = 0, NumTypes = NestedTypes.size(); TypeIdx != NumTypes;
++TypeIdx) {
T = NestedTypes[TypeIdx];
// Whether we expect a 'template<>' header.
bool NeedEmptyTemplateHeader = false;
// Whether we expect a template header with parameters.
bool NeedNonemptyTemplateHeader = false;
// For a dependent type, the set of template parameters that we
// expect to see.
TemplateParameterList *ExpectedTemplateParams = nullptr;
// C++0x [temp.expl.spec]p15:
// A member or a member template may be nested within many enclosing
// class templates. In an explicit specialization for such a member, the
// member declaration shall be preceded by a template<> for each
// enclosing class template that is explicitly specialized.
if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) {
if (ClassTemplatePartialSpecializationDecl *Partial
= dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
ExpectedTemplateParams = Partial->getTemplateParameters();
NeedNonemptyTemplateHeader = true;
} else if (Record->isDependentType()) {
if (Record->getDescribedClassTemplate()) {
ExpectedTemplateParams = Record->getDescribedClassTemplate()
->getTemplateParameters();
NeedNonemptyTemplateHeader = true;
}
} else if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
// C++0x [temp.expl.spec]p4:
// Members of an explicitly specialized class template are defined
// in the same manner as members of normal classes, and not using
// the template<> syntax.
if (Spec->getSpecializationKind() != TSK_ExplicitSpecialization)
NeedEmptyTemplateHeader = true;
else
continue;
} else if (Record->getTemplateSpecializationKind()) {
if (Record->getTemplateSpecializationKind()
!= TSK_ExplicitSpecialization &&
TypeIdx == NumTypes - 1)
IsMemberSpecialization = true;
continue;
}
} else if (const TemplateSpecializationType *TST
= T->getAs<TemplateSpecializationType>()) {
if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {
ExpectedTemplateParams = Template->getTemplateParameters();
NeedNonemptyTemplateHeader = true;
}
} else if (T->getAs<DependentTemplateSpecializationType>()) {
// FIXME: We actually could/should check the template arguments here
// against the corresponding template parameter list.
NeedNonemptyTemplateHeader = false;
}
// C++ [temp.expl.spec]p16:
// In an explicit specialization declaration for a member of a class
// template or a member template that ap- pears in namespace scope, the
// member template and some of its enclosing class templates may remain
// unspecialized, except that the declaration shall not explicitly
// specialize a class member template if its en- closing class templates
// are not explicitly specialized as well.
if (ParamIdx < ParamLists.size()) {
if (ParamLists[ParamIdx]->size() == 0) {
if (CheckExplicitSpecialization(ParamLists[ParamIdx]->getSourceRange(),
false))
return nullptr;
} else
SawNonEmptyTemplateParameterList = true;
}
if (NeedEmptyTemplateHeader) {
// If we're on the last of the types, and we need a 'template<>' header
// here, then it's a member specialization.
if (TypeIdx == NumTypes - 1)
IsMemberSpecialization = true;
if (ParamIdx < ParamLists.size()) {
if (ParamLists[ParamIdx]->size() > 0) {
// The header has template parameters when it shouldn't. Complain.
Diag(ParamLists[ParamIdx]->getTemplateLoc(),
diag::err_template_param_list_matches_nontemplate)
<< T
<< SourceRange(ParamLists[ParamIdx]->getLAngleLoc(),
ParamLists[ParamIdx]->getRAngleLoc())
<< getRangeOfTypeInNestedNameSpecifier(Context, T, SS);
Invalid = true;
return nullptr;
}
// Consume this template header.
++ParamIdx;
continue;
}
if (!IsFriend)
if (DiagnoseMissingExplicitSpecialization(
getRangeOfTypeInNestedNameSpecifier(Context, T, SS)))
return nullptr;
continue;
}
if (NeedNonemptyTemplateHeader) {
// In friend declarations we can have template-ids which don't
// depend on the corresponding template parameter lists. But
// assume that empty parameter lists are supposed to match this
// template-id.
if (IsFriend && T->isDependentType()) {
if (ParamIdx < ParamLists.size() &&
DependsOnTemplateParameters(T, ParamLists[ParamIdx]))
ExpectedTemplateParams = nullptr;
else
continue;
}
if (ParamIdx < ParamLists.size()) {
// Check the template parameter list, if we can.
if (ExpectedTemplateParams &&
!TemplateParameterListsAreEqual(ParamLists[ParamIdx],
ExpectedTemplateParams,
true, TPL_TemplateMatch))
Invalid = true;
if (!Invalid &&
CheckTemplateParameterList(ParamLists[ParamIdx], nullptr,
TPC_ClassTemplateMember))
Invalid = true;
++ParamIdx;
continue;
}
Diag(DeclLoc, diag::err_template_spec_needs_template_parameters)
<< T
<< getRangeOfTypeInNestedNameSpecifier(Context, T, SS);
Invalid = true;
continue;
}
}
// If there were at least as many template-ids as there were template
// parameter lists, then there are no template parameter lists remaining for
// the declaration itself.
if (ParamIdx >= ParamLists.size()) {
if (TemplateId && !IsFriend) {
// We don't have a template header for the declaration itself, but we
// should.
DiagnoseMissingExplicitSpecialization(SourceRange(TemplateId->LAngleLoc,
TemplateId->RAngleLoc));
// Fabricate an empty template parameter list for the invented header.
return TemplateParameterList::Create(Context, SourceLocation(),
SourceLocation(), None,
SourceLocation(), nullptr);
}
return nullptr;
}
// If there were too many template parameter lists, complain about that now.
if (ParamIdx < ParamLists.size() - 1) {
bool HasAnyExplicitSpecHeader = false;
bool AllExplicitSpecHeaders = true;
for (unsigned I = ParamIdx, E = ParamLists.size() - 1; I != E; ++I) {
if (ParamLists[I]->size() == 0)
HasAnyExplicitSpecHeader = true;
else
AllExplicitSpecHeaders = false;
}
Diag(ParamLists[ParamIdx]->getTemplateLoc(),
AllExplicitSpecHeaders ? diag::warn_template_spec_extra_headers
: diag::err_template_spec_extra_headers)
<< SourceRange(ParamLists[ParamIdx]->getTemplateLoc(),
ParamLists[ParamLists.size() - 2]->getRAngleLoc());
// If there was a specialization somewhere, such that 'template<>' is
// not required, and there were any 'template<>' headers, note where the
// specialization occurred.
if (ExplicitSpecLoc.isValid() && HasAnyExplicitSpecHeader)
Diag(ExplicitSpecLoc,
diag::note_explicit_template_spec_does_not_need_header)
<< NestedTypes.back();
// We have a template parameter list with no corresponding scope, which
// means that the resulting template declaration can't be instantiated
// properly (we'll end up with dependent nodes when we shouldn't).
if (!AllExplicitSpecHeaders)
Invalid = true;
}
// C++ [temp.expl.spec]p16:
// In an explicit specialization declaration for a member of a class
// template or a member template that ap- pears in namespace scope, the
// member template and some of its enclosing class templates may remain
// unspecialized, except that the declaration shall not explicitly
// specialize a class member template if its en- closing class templates
// are not explicitly specialized as well.
if (ParamLists.back()->size() == 0 &&
CheckExplicitSpecialization(ParamLists[ParamIdx]->getSourceRange(),
false))
return nullptr;
// Return the last template parameter list, which corresponds to the
// entity being declared.
return ParamLists.back();
}
void Sema::NoteAllFoundTemplates(TemplateName Name) {
if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
Diag(Template->getLocation(), diag::note_template_declared_here)
<< (isa<FunctionTemplateDecl>(Template)
? 0
: isa<ClassTemplateDecl>(Template)
? 1
: isa<VarTemplateDecl>(Template)
? 2
: isa<TypeAliasTemplateDecl>(Template) ? 3 : 4)
<< Template->getDeclName();
return;
}
if (OverloadedTemplateStorage *OST = Name.getAsOverloadedTemplate()) {
for (OverloadedTemplateStorage::iterator I = OST->begin(),
IEnd = OST->end();
I != IEnd; ++I)
Diag((*I)->getLocation(), diag::note_template_declared_here)
<< 0 << (*I)->getDeclName();
return;
}
}
static QualType
checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
const SmallVectorImpl<TemplateArgument> &Converted,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs) {
ASTContext &Context = SemaRef.getASTContext();
switch (BTD->getBuiltinTemplateKind()) {
case BTK__make_integer_seq: {
// Specializations of __make_integer_seq<S, T, N> are treated like
// S<T, 0, ..., N-1>.
// C++14 [inteseq.intseq]p1:
// T shall be an integer type.
if (!Converted[1].getAsType()->isIntegralType(Context)) {
SemaRef.Diag(TemplateArgs[1].getLocation(),
diag::err_integer_sequence_integral_element_type);
return QualType();
}
// C++14 [inteseq.make]p1:
// If N is negative the program is ill-formed.
TemplateArgument NumArgsArg = Converted[2];
llvm::APSInt NumArgs = NumArgsArg.getAsIntegral();
if (NumArgs < 0) {
SemaRef.Diag(TemplateArgs[2].getLocation(),
diag::err_integer_sequence_negative_length);
return QualType();
}
QualType ArgTy = NumArgsArg.getIntegralType();
TemplateArgumentListInfo SyntheticTemplateArgs;
// The type argument gets reused as the first template argument in the
// synthetic template argument list.
SyntheticTemplateArgs.addArgument(TemplateArgs[1]);
// Expand N into 0 ... N-1.
for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned());
I < NumArgs; ++I) {
TemplateArgument TA(Context, I, ArgTy);
SyntheticTemplateArgs.addArgument(SemaRef.getTrivialTemplateArgumentLoc(
TA, ArgTy, TemplateArgs[2].getLocation()));
}
// The first template argument will be reused as the template decl that
// our synthetic template arguments will be applied to.
return SemaRef.CheckTemplateIdType(Converted[0].getAsTemplate(),
TemplateLoc, SyntheticTemplateArgs);
}
case BTK__type_pack_element:
// Specializations of
// __type_pack_element<Index, T_1, ..., T_N>
// are treated like T_Index.
assert(Converted.size() == 2 &&
"__type_pack_element should be given an index and a parameter pack");
// If the Index is out of bounds, the program is ill-formed.
TemplateArgument IndexArg = Converted[0], Ts = Converted[1];
llvm::APSInt Index = IndexArg.getAsIntegral();
assert(Index >= 0 && "the index used with __type_pack_element should be of "
"type std::size_t, and hence be non-negative");
if (Index >= Ts.pack_size()) {
SemaRef.Diag(TemplateArgs[0].getLocation(),
diag::err_type_pack_element_out_of_bounds);
return QualType();
}
// We simply return the type at index `Index`.
auto Nth = std::next(Ts.pack_begin(), Index.getExtValue());
return Nth->getAsType();
}
llvm_unreachable("unexpected BuiltinTemplateDecl!");
}
/// Determine whether this alias template is "enable_if_t".
static bool isEnableIfAliasTemplate(TypeAliasTemplateDecl *AliasTemplate) {
return AliasTemplate->getName().equals("enable_if_t");
}
/// Collect all of the separable terms in the given condition, which
/// might be a conjunction.
///
/// FIXME: The right answer is to convert the logical expression into
/// disjunctive normal form, so we can find the first failed term
/// within each possible clause.
static void collectConjunctionTerms(Expr *Clause,
SmallVectorImpl<Expr *> &Terms) {
if (auto BinOp = dyn_cast<BinaryOperator>(Clause->IgnoreParenImpCasts())) {
if (BinOp->getOpcode() == BO_LAnd) {
collectConjunctionTerms(BinOp->getLHS(), Terms);
collectConjunctionTerms(BinOp->getRHS(), Terms);
}
return;
}
Terms.push_back(Clause);
}
// The ranges-v3 library uses an odd pattern of a top-level "||" with
// a left-hand side that is value-dependent but never true. Identify
// the idiom and ignore that term.
static Expr *lookThroughRangesV3Condition(Preprocessor &PP, Expr *Cond) {
// Top-level '||'.
auto *BinOp = dyn_cast<BinaryOperator>(Cond->IgnoreParenImpCasts());
if (!BinOp) return Cond;
if (BinOp->getOpcode() != BO_LOr) return Cond;
// With an inner '==' that has a literal on the right-hand side.
Expr *LHS = BinOp->getLHS();
auto *InnerBinOp = dyn_cast<BinaryOperator>(LHS->IgnoreParenImpCasts());
if (!InnerBinOp) return Cond;
if (InnerBinOp->getOpcode() != BO_EQ ||
!isa<IntegerLiteral>(InnerBinOp->getRHS()))
return Cond;
// If the inner binary operation came from a macro expansion named
// CONCEPT_REQUIRES or CONCEPT_REQUIRES_, return the right-hand side
// of the '||', which is the real, user-provided condition.
SourceLocation Loc = InnerBinOp->getExprLoc();
if (!Loc.isMacroID()) return Cond;
StringRef MacroName = PP.getImmediateMacroName(Loc);
if (MacroName == "CONCEPT_REQUIRES" || MacroName == "CONCEPT_REQUIRES_")
return BinOp->getRHS();
return Cond;
}
namespace {
// A PrinterHelper that prints more helpful diagnostics for some sub-expressions
// within failing boolean expression, such as substituting template parameters
// for actual types.
class FailedBooleanConditionPrinterHelper : public PrinterHelper {
public:
explicit FailedBooleanConditionPrinterHelper(const PrintingPolicy &P)
: Policy(P) {}
bool handledStmt(Stmt *E, raw_ostream &OS) override {
const auto *DR = dyn_cast<DeclRefExpr>(E);
if (DR && DR->getQualifier()) {
// If this is a qualified name, expand the template arguments in nested
// qualifiers.
DR->getQualifier()->print(OS, Policy, true);
// Then print the decl itself.
const ValueDecl *VD = DR->getDecl();
OS << VD->getName();
if (const auto *IV = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
// This is a template variable, print the expanded template arguments.
printTemplateArgumentList(OS, IV->getTemplateArgs().asArray(), Policy);
}
return true;
}
return false;
}
private:
const PrintingPolicy Policy;
};
} // end anonymous namespace
std::pair<Expr *, std::string>
Sema::findFailedBooleanCondition(Expr *Cond) {
Cond = lookThroughRangesV3Condition(PP, Cond);
// Separate out all of the terms in a conjunction.
SmallVector<Expr *, 4> Terms;
collectConjunctionTerms(Cond, Terms);
// Determine which term failed.
Expr *FailedCond = nullptr;
for (Expr *Term : Terms) {
Expr *TermAsWritten = Term->IgnoreParenImpCasts();
// Literals are uninteresting.
if (isa<CXXBoolLiteralExpr>(TermAsWritten) ||
isa<IntegerLiteral>(TermAsWritten))
continue;
// The initialization of the parameter from the argument is
// a constant-evaluated context.
EnterExpressionEvaluationContext ConstantEvaluated(
*this, Sema::ExpressionEvaluationContext::ConstantEvaluated);
bool Succeeded;
if (Term->EvaluateAsBooleanCondition(Succeeded, Context) &&
!Succeeded) {
FailedCond = TermAsWritten;
break;
}
}
if (!FailedCond)
FailedCond = Cond->IgnoreParenImpCasts();
std::string Description;
{
llvm::raw_string_ostream Out(Description);
PrintingPolicy Policy = getPrintingPolicy();
Policy.PrintCanonicalTypes = true;
FailedBooleanConditionPrinterHelper Helper(Policy);
FailedCond->printPretty(Out, &Helper, Policy, 0, "\n", nullptr);
}
return { FailedCond, Description };
}
QualType Sema::CheckTemplateIdType(TemplateName Name,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs) {
DependentTemplateName *DTN
= Name.getUnderlying().getAsDependentTemplateName();
if (DTN && DTN->isIdentifier())
// When building a template-id where the template-name is dependent,
// assume the template is a type template. Either our assumption is
// correct, or the code is ill-formed and will be diagnosed when the
// dependent name is substituted.
return Context.getDependentTemplateSpecializationType(ETK_None,
DTN->getQualifier(),
DTN->getIdentifier(),
TemplateArgs);
TemplateDecl *Template = Name.getAsTemplateDecl();
if (!Template || isa<FunctionTemplateDecl>(Template) ||
isa<VarTemplateDecl>(Template)) {
// We might have a substituted template template parameter pack. If so,
// build a template specialization type for it.
if (Name.getAsSubstTemplateTemplateParmPack())
return Context.getTemplateSpecializationType(Name, TemplateArgs);
Diag(TemplateLoc, diag::err_template_id_not_a_type)
<< Name;
NoteAllFoundTemplates(Name);
return QualType();
}
// Check that the template argument list is well-formed for this
// template.
SmallVector<TemplateArgument, 4> Converted;
if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs,
false, Converted))
return QualType();
QualType CanonType;
bool InstantiationDependent = false;
if (TypeAliasTemplateDecl *AliasTemplate =
dyn_cast<TypeAliasTemplateDecl>(Template)) {
// Find the canonical type for this type alias template specialization.
TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl();
if (Pattern->isInvalidDecl())
return QualType();
TemplateArgumentList StackTemplateArgs(TemplateArgumentList::OnStack,
Converted);
// Only substitute for the innermost template argument list.
MultiLevelTemplateArgumentList TemplateArgLists;
TemplateArgLists.addOuterTemplateArguments(&StackTemplateArgs);
unsigned Depth = AliasTemplate->getTemplateParameters()->getDepth();
for (unsigned I = 0; I < Depth; ++I)
TemplateArgLists.addOuterTemplateArguments(None);
LocalInstantiationScope Scope(*this);
InstantiatingTemplate Inst(*this, TemplateLoc, Template);
if (Inst.isInvalid())
return QualType();
CanonType = SubstType(Pattern->getUnderlyingType(),
TemplateArgLists, AliasTemplate->getLocation(),
AliasTemplate->getDeclName());
if (CanonType.isNull()) {
// If this was enable_if and we failed to find the nested type
// within enable_if in a SFINAE context, dig out the specific
// enable_if condition that failed and present that instead.
if (isEnableIfAliasTemplate(AliasTemplate)) {
if (auto DeductionInfo = isSFINAEContext()) {
if (*DeductionInfo &&
(*DeductionInfo)->hasSFINAEDiagnostic() &&
(*DeductionInfo)->peekSFINAEDiagnostic().second.getDiagID() ==
diag::err_typename_nested_not_found_enable_if &&
TemplateArgs[0].getArgument().getKind()
== TemplateArgument::Expression) {
Expr *FailedCond;
std::string FailedDescription;
std::tie(FailedCond, FailedDescription) =
findFailedBooleanCondition(TemplateArgs[0].getSourceExpression());
// Remove the old SFINAE diagnostic.
PartialDiagnosticAt OldDiag =
{SourceLocation(), PartialDiagnostic::NullDiagnostic()};
(*DeductionInfo)->takeSFINAEDiagnostic(OldDiag);
// Add a new SFINAE diagnostic specifying which condition
// failed.
(*DeductionInfo)->addSFINAEDiagnostic(
OldDiag.first,
PDiag(diag::err_typename_nested_not_found_requirement)
<< FailedDescription
<< FailedCond->getSourceRange());
}
}
}
return QualType();
}
} else if (Name.isDependent() ||
TemplateSpecializationType::anyDependentTemplateArguments(
TemplateArgs, InstantiationDependent)) {
// This class template specialization is a dependent
// type. Therefore, its canonical type is another class template
// specialization type that contains all of the converted
// arguments in canonical form. This ensures that, e.g., A<T> and
// A<T, T> have identical types when A is declared as:
//
// template<typename T, typename U = T> struct A;
CanonType = Context.getCanonicalTemplateSpecializationType(Name, Converted);
// This might work out to be a current instantiation, in which
// case the canonical type needs to be the InjectedClassNameType.
//
// TODO: in theory this could be a simple hashtable lookup; most
// changes to CurContext don't change the set of current
// instantiations.
if (isa<ClassTemplateDecl>(Template)) {
for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getLookupParent()) {
// If we get out to a namespace, we're done.
if (Ctx->isFileContext()) break;
// If this isn't a record, keep looking.
CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx);
if (!Record) continue;
// Look for one of the two cases with InjectedClassNameTypes
// and check whether it's the same template.
if (!isa<ClassTemplatePartialSpecializationDecl>(Record) &&
!Record->getDescribedClassTemplate())
continue;
// Fetch the injected class name type and check whether its
// injected type is equal to the type we just built.
QualType ICNT = Context.getTypeDeclType(Record);
QualType Injected = cast<InjectedClassNameType>(ICNT)
->getInjectedSpecializationType();
if (CanonType != Injected->getCanonicalTypeInternal())
continue;
// If so, the canonical type of this TST is the injected
// class name type of the record we just found.
assert(ICNT.isCanonical());
CanonType = ICNT;
break;
}
}
} else if (ClassTemplateDecl *ClassTemplate
= dyn_cast<ClassTemplateDecl>(Template)) {
// Find the class template specialization declaration that
// corresponds to these arguments.
void *InsertPos = nullptr;
ClassTemplateSpecializationDecl *Decl
= ClassTemplate->findSpecialization(Converted, InsertPos);
if (!Decl) {
// This is the first time we have referenced this class template
// specialization. Create the canonical declaration and add it to
// the set of specializations.
Decl = ClassTemplateSpecializationDecl::Create(
Context, ClassTemplate->getTemplatedDecl()->getTagKind(),
ClassTemplate->getDeclContext(),
ClassTemplate->getTemplatedDecl()->getBeginLoc(),
ClassTemplate->getLocation(), ClassTemplate, Converted, nullptr);
ClassTemplate->AddSpecialization(Decl, InsertPos);
if (ClassTemplate->isOutOfLine())
Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext());
}
if (Decl->getSpecializationKind() == TSK_Undeclared) {
MultiLevelTemplateArgumentList TemplateArgLists;
TemplateArgLists.addOuterTemplateArguments(Converted);
InstantiateAttrsForDecl(TemplateArgLists, ClassTemplate->getTemplatedDecl(),
Decl);
}
// Diagnose uses of this specialization.
(void)DiagnoseUseOfDecl(Decl, TemplateLoc);
CanonType = Context.getTypeDeclType(Decl);
assert(isa<RecordType>(CanonType) &&
"type of non-dependent specialization is not a RecordType");
} else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) {
CanonType = checkBuiltinTemplateIdType(*this, BTD, Converted, TemplateLoc,
TemplateArgs);
}
// Build the fully-sugared type for this class template
// specialization, which refers back to the class template
// specialization we created or found.
return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType);
}
TypeResult
Sema::ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
TemplateTy TemplateD, IdentifierInfo *TemplateII,
SourceLocation TemplateIILoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
SourceLocation RAngleLoc,
bool IsCtorOrDtorName, bool IsClassName) {
if (SS.isInvalid())
return true;
if (!IsCtorOrDtorName && !IsClassName && SS.isSet()) {
DeclContext *LookupCtx = computeDeclContext(SS, /*EnteringContext*/false);
// C++ [temp.res]p3:
// A qualified-id that refers to a type and in which the
// nested-name-specifier depends on a template-parameter (14.6.2)
// shall be prefixed by the keyword typename to indicate that the
// qualified-id denotes a type, forming an
// elaborated-type-specifier (7.1.5.3).
if (!LookupCtx && isDependentScopeSpecifier(SS)) {
Diag(SS.getBeginLoc(), diag::err_typename_missing_template)
<< SS.getScopeRep() << TemplateII->getName();
// Recover as if 'typename' were specified.
// FIXME: This is not quite correct recovery as we don't transform SS
// into the corresponding dependent form (and we don't diagnose missing
// 'template' keywords within SS as a result).
return ActOnTypenameType(nullptr, SourceLocation(), SS, TemplateKWLoc,
TemplateD, TemplateII, TemplateIILoc, LAngleLoc,
TemplateArgsIn, RAngleLoc);
}
// Per C++ [class.qual]p2, if the template-id was an injected-class-name,
// it's not actually allowed to be used as a type in most cases. Because
// we annotate it before we know whether it's valid, we have to check for
// this case here.
auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx);
if (LookupRD && LookupRD->getIdentifier() == TemplateII) {
Diag(TemplateIILoc,
TemplateKWLoc.isInvalid()
? diag::err_out_of_line_qualified_id_type_names_constructor
: diag::ext_out_of_line_qualified_id_type_names_constructor)
<< TemplateII << 0 /*injected-class-name used as template name*/
<< 1 /*if any keyword was present, it was 'template'*/;
}
}
TemplateName Template = TemplateD.get();
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
QualType T
= Context.getDependentTemplateSpecializationType(ETK_None,
DTN->getQualifier(),
DTN->getIdentifier(),
TemplateArgs);
// Build type-source information.
TypeLocBuilder TLB;
DependentTemplateSpecializationTypeLoc SpecTL
= TLB.push<DependentTemplateSpecializationTypeLoc>(T);
SpecTL.setElaboratedKeywordLoc(SourceLocation());
SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
SpecTL.setTemplateNameLoc(TemplateIILoc);
SpecTL.setLAngleLoc(LAngleLoc);
SpecTL.setRAngleLoc(RAngleLoc);
for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I)
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
}
QualType Result = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs);
if (Result.isNull())
return true;
// Build type-source information.
TypeLocBuilder TLB;
TemplateSpecializationTypeLoc SpecTL
= TLB.push<TemplateSpecializationTypeLoc>(Result);
SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
SpecTL.setTemplateNameLoc(TemplateIILoc);
SpecTL.setLAngleLoc(LAngleLoc);
SpecTL.setRAngleLoc(RAngleLoc);
for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i)
SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
// NOTE: avoid constructing an ElaboratedTypeLoc if this is a
// constructor or destructor name (in such a case, the scope specifier
// will be attached to the enclosing Decl or Expr node).
if (SS.isNotEmpty() && !IsCtorOrDtorName) {
// Create an elaborated-type-specifier containing the nested-name-specifier.
Result = Context.getElaboratedType(ETK_None, SS.getScopeRep(), Result);
ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result);
ElabTL.setElaboratedKeywordLoc(SourceLocation());
ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
}
return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
}
TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
TypeSpecifierType TagSpec,
SourceLocation TagLoc,
CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
TemplateTy TemplateD,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
SourceLocation RAngleLoc) {
TemplateName Template = TemplateD.get();
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
// Determine the tag kind
TagTypeKind TagKind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
ElaboratedTypeKeyword Keyword
= TypeWithKeyword::getKeywordForTagTypeKind(TagKind);
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
QualType T = Context.getDependentTemplateSpecializationType(Keyword,
DTN->getQualifier(),
DTN->getIdentifier(),
TemplateArgs);
// Build type-source information.
TypeLocBuilder TLB;
DependentTemplateSpecializationTypeLoc SpecTL
= TLB.push<DependentTemplateSpecializationTypeLoc>(T);
SpecTL.setElaboratedKeywordLoc(TagLoc);
SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
SpecTL.setTemplateNameLoc(TemplateLoc);
SpecTL.setLAngleLoc(LAngleLoc);
SpecTL.setRAngleLoc(RAngleLoc);
for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I)
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
}
if (TypeAliasTemplateDecl *TAT =
dyn_cast_or_null<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) {
// C++0x [dcl.type.elab]p2:
// If the identifier resolves to a typedef-name or the simple-template-id
// resolves to an alias template specialization, the
// elaborated-type-specifier is ill-formed.
Diag(TemplateLoc, diag::err_tag_reference_non_tag)
<< TAT << NTK_TypeAliasTemplate << TagKind;
Diag(TAT->getLocation(), diag::note_declared_at);
}
QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
if (Result.isNull())
return TypeResult(true);
// Check the tag kind
if (const RecordType *RT = Result->getAs<RecordType>()) {
RecordDecl *D = RT->getDecl();
IdentifierInfo *Id = D->getIdentifier();
assert(Id && "templated class must have an identifier");
if (!isAcceptableTagRedeclaration(D, TagKind, TUK == TUK_Definition,
TagLoc, Id)) {
Diag(TagLoc, diag::err_use_with_wrong_tag)
<< Result
<< FixItHint::CreateReplacement(SourceRange(TagLoc), D->getKindName());
Diag(D->getLocation(), diag::note_previous_use);
}
}
// Provide source-location information for the template specialization.
TypeLocBuilder TLB;
TemplateSpecializationTypeLoc SpecTL
= TLB.push<TemplateSpecializationTypeLoc>(Result);
SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
SpecTL.setTemplateNameLoc(TemplateLoc);
SpecTL.setLAngleLoc(LAngleLoc);
SpecTL.setRAngleLoc(RAngleLoc);
for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i)
SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
// Construct an elaborated type containing the nested-name-specifier (if any)
// and tag keyword.
Result = Context.getElaboratedType(Keyword, SS.getScopeRep(), Result);
ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result);
ElabTL.setElaboratedKeywordLoc(TagLoc);
ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
}
static bool CheckTemplateSpecializationScope(Sema &S, NamedDecl *Specialized,
NamedDecl *PrevDecl,
SourceLocation Loc,
bool IsPartialSpecialization);
static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D);
static bool isTemplateArgumentTemplateParameter(
const TemplateArgument &Arg, unsigned Depth, unsigned Index) {
switch (Arg.getKind()) {
case TemplateArgument::Null:
case TemplateArgument::NullPtr:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
case TemplateArgument::Pack:
case TemplateArgument::TemplateExpansion:
return false;
case TemplateArgument::Type: {
QualType Type = Arg.getAsType();
const TemplateTypeParmType *TPT =
Arg.getAsType()->getAs<TemplateTypeParmType>();
return TPT && !Type.hasQualifiers() &&
TPT->getDepth() == Depth && TPT->getIndex() == Index;
}
case TemplateArgument::Expression: {
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg.getAsExpr());
if (!DRE || !DRE->getDecl())
return false;
const NonTypeTemplateParmDecl *NTTP =
dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
return NTTP && NTTP->getDepth() == Depth && NTTP->getIndex() == Index;
}
case TemplateArgument::Template:
const TemplateTemplateParmDecl *TTP =
dyn_cast_or_null<TemplateTemplateParmDecl>(
Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl());
return TTP && TTP->getDepth() == Depth && TTP->getIndex() == Index;
}
llvm_unreachable("unexpected kind of template argument");
}
static bool isSameAsPrimaryTemplate(TemplateParameterList *Params,
ArrayRef<TemplateArgument> Args) {
if (Params->size() != Args.size())
return false;
unsigned Depth = Params->getDepth();
for (unsigned I = 0, N = Args.size(); I != N; ++I) {
TemplateArgument Arg = Args[I];
// If the parameter is a pack expansion, the argument must be a pack
// whose only element is a pack expansion.
if (Params->getParam(I)->isParameterPack()) {
if (Arg.getKind() != TemplateArgument::Pack || Arg.pack_size() != 1 ||
!Arg.pack_begin()->isPackExpansion())
return false;
Arg = Arg.pack_begin()->getPackExpansionPattern();
}
if (!isTemplateArgumentTemplateParameter(Arg, Depth, I))
return false;
}
return true;
}
/// Convert the parser's template argument list representation into our form.
static TemplateArgumentListInfo
makeTemplateArgumentListInfo(Sema &S, TemplateIdAnnotation &TemplateId) {
TemplateArgumentListInfo TemplateArgs(TemplateId.LAngleLoc,
TemplateId.RAngleLoc);
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId.getTemplateArgs(),
TemplateId.NumArgs);
S.translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
return TemplateArgs;
}
template<typename PartialSpecDecl>
static void checkMoreSpecializedThanPrimary(Sema &S, PartialSpecDecl *Partial) {
if (Partial->getDeclContext()->isDependentContext())
return;
// FIXME: Get the TDK from deduction in order to provide better diagnostics
// for non-substitution-failure issues?
TemplateDeductionInfo Info(Partial->getLocation());
if (S.isMoreSpecializedThanPrimary(Partial, Info))
return;
auto *Template = Partial->getSpecializedTemplate();
S.Diag(Partial->getLocation(),
diag::ext_partial_spec_not_more_specialized_than_primary)
<< isa<VarTemplateDecl>(Template);
if (Info.hasSFINAEDiagnostic()) {
PartialDiagnosticAt Diag = {SourceLocation(),
PartialDiagnostic::NullDiagnostic()};
Info.takeSFINAEDiagnostic(Diag);
SmallString<128> SFINAEArgString;
Diag.second.EmitToString(S.getDiagnostics(), SFINAEArgString);
S.Diag(Diag.first,
diag::note_partial_spec_not_more_specialized_than_primary)
<< SFINAEArgString;
}
S.Diag(Template->getLocation(), diag::note_template_decl_here);
}
static void
noteNonDeducibleParameters(Sema &S, TemplateParameterList *TemplateParams,
const llvm::SmallBitVector &DeducibleParams) {
for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) {
if (!DeducibleParams[I]) {
NamedDecl *Param = TemplateParams->getParam(I);
if (Param->getDeclName())
S.Diag(Param->getLocation(), diag::note_non_deducible_parameter)
<< Param->getDeclName();
else
S.Diag(Param->getLocation(), diag::note_non_deducible_parameter)
<< "(anonymous)";
}
}
}
template<typename PartialSpecDecl>
static void checkTemplatePartialSpecialization(Sema &S,
PartialSpecDecl *Partial) {
// C++1z [temp.class.spec]p8: (DR1495)
// - The specialization shall be more specialized than the primary
// template (14.5.5.2).
checkMoreSpecializedThanPrimary(S, Partial);
// C++ [temp.class.spec]p8: (DR1315)
// - Each template-parameter shall appear at least once in the
// template-id outside a non-deduced context.
// C++1z [temp.class.spec.match]p3 (P0127R2)
// If the template arguments of a partial specialization cannot be
// deduced because of the structure of its template-parameter-list
// and the template-id, the program is ill-formed.
auto *TemplateParams = Partial->getTemplateParameters();
llvm::SmallBitVector DeducibleParams(TemplateParams->size());
S.MarkUsedTemplateParameters(Partial->getTemplateArgs(), true,
TemplateParams->getDepth(), DeducibleParams);
if (!DeducibleParams.all()) {
unsigned NumNonDeducible = DeducibleParams.size() - DeducibleParams.count();
S.Diag(Partial->getLocation(), diag::ext_partial_specs_not_deducible)
<< isa<VarTemplatePartialSpecializationDecl>(Partial)
<< (NumNonDeducible > 1)
<< SourceRange(Partial->getLocation(),
Partial->getTemplateArgsAsWritten()->RAngleLoc);
noteNonDeducibleParameters(S, TemplateParams, DeducibleParams);
}
}
void Sema::CheckTemplatePartialSpecialization(
ClassTemplatePartialSpecializationDecl *Partial) {
checkTemplatePartialSpecialization(*this, Partial);
}
void Sema::CheckTemplatePartialSpecialization(
VarTemplatePartialSpecializationDecl *Partial) {
checkTemplatePartialSpecialization(*this, Partial);
}
void Sema::CheckDeductionGuideTemplate(FunctionTemplateDecl *TD) {
// C++1z [temp.param]p11:
// A template parameter of a deduction guide template that does not have a
// default-argument shall be deducible from the parameter-type-list of the
// deduction guide template.
auto *TemplateParams = TD->getTemplateParameters();
llvm::SmallBitVector DeducibleParams(TemplateParams->size());
MarkDeducedTemplateParameters(TD, DeducibleParams);
for (unsigned I = 0; I != TemplateParams->size(); ++I) {
// A parameter pack is deducible (to an empty pack).
auto *Param = TemplateParams->getParam(I);
if (Param->isParameterPack() || hasVisibleDefaultArgument(Param))
DeducibleParams[I] = true;
}
if (!DeducibleParams.all()) {
unsigned NumNonDeducible = DeducibleParams.size() - DeducibleParams.count();
Diag(TD->getLocation(), diag::err_deduction_guide_template_not_deducible)
<< (NumNonDeducible > 1);
noteNonDeducibleParameters(*this, TemplateParams, DeducibleParams);
}
}
DeclResult Sema::ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI, SourceLocation TemplateKWLoc,
TemplateParameterList *TemplateParams, StorageClass SC,
bool IsPartialSpecialization) {
// D must be variable template id.
assert(D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId &&
"Variable template specialization is declared with a template it.");
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
TemplateArgumentListInfo TemplateArgs =
makeTemplateArgumentListInfo(*this, *TemplateId);
SourceLocation TemplateNameLoc = D.getIdentifierLoc();
SourceLocation LAngleLoc = TemplateId->LAngleLoc;
SourceLocation RAngleLoc = TemplateId->RAngleLoc;
TemplateName Name = TemplateId->Template.get();
// The template-id must name a variable template.
VarTemplateDecl *VarTemplate =
dyn_cast_or_null<VarTemplateDecl>(Name.getAsTemplateDecl());
if (!VarTemplate) {
NamedDecl *FnTemplate;
if (auto *OTS = Name.getAsOverloadedTemplate())
FnTemplate = *OTS->begin();
else
FnTemplate = dyn_cast_or_null<FunctionTemplateDecl>(Name.getAsTemplateDecl());
if (FnTemplate)
return Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template_but_method)
<< FnTemplate->getDeclName();
return Diag(D.getIdentifierLoc(), diag::err_var_spec_no_template)
<< IsPartialSpecialization;
}
// Check for unexpanded parameter packs in any of the template arguments.
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
if (DiagnoseUnexpandedParameterPack(TemplateArgs[I],
UPPC_PartialSpecialization))
return true;
// Check that the template argument list is well-formed for this
// template.
SmallVector<TemplateArgument, 4> Converted;
if (CheckTemplateArgumentList(VarTemplate, TemplateNameLoc, TemplateArgs,
false, Converted))
return true;
// Find the variable template (partial) specialization declaration that
// corresponds to these arguments.
if (IsPartialSpecialization) {
if (CheckTemplatePartialSpecializationArgs(TemplateNameLoc, VarTemplate,
TemplateArgs.size(), Converted))
return true;
// FIXME: Move these checks to CheckTemplatePartialSpecializationArgs so we
// also do them during instantiation.
bool InstantiationDependent;
if (!Name.isDependent() &&
!TemplateSpecializationType::anyDependentTemplateArguments(
TemplateArgs.arguments(),
InstantiationDependent)) {
Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
<< VarTemplate->getDeclName();
IsPartialSpecialization = false;
}
if (isSameAsPrimaryTemplate(VarTemplate->getTemplateParameters(),
Converted)) {
// C++ [temp.class.spec]p9b3:
//
// -- The argument list of the specialization shall not be identical
// to the implicit argument list of the primary template.
Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
<< /*variable template*/ 1
<< /*is definition*/(SC != SC_Extern && !CurContext->isRecord())
<< FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
// FIXME: Recover from this by treating the declaration as a redeclaration
// of the primary template.
return true;
}
}
void *InsertPos = nullptr;
VarTemplateSpecializationDecl *PrevDecl = nullptr;
if (IsPartialSpecialization)
// FIXME: Template parameter list matters too
PrevDecl = VarTemplate->findPartialSpecialization(Converted, InsertPos);
else
PrevDecl = VarTemplate->findSpecialization(Converted, InsertPos);
VarTemplateSpecializationDecl *Specialization = nullptr;
// Check whether we can declare a variable template specialization in
// the current scope.
if (CheckTemplateSpecializationScope(*this, VarTemplate, PrevDecl,
TemplateNameLoc,
IsPartialSpecialization))
return true;
if (PrevDecl && PrevDecl->getSpecializationKind() == TSK_Undeclared) {
// Since the only prior variable template specialization with these
// arguments was referenced but not declared, reuse that
// declaration node as our own, updating its source location and
// the list of outer template parameters to reflect our new declaration.
Specialization = PrevDecl;
Specialization->setLocation(TemplateNameLoc);
PrevDecl = nullptr;
} else if (IsPartialSpecialization) {
// Create a new class template partial specialization declaration node.
VarTemplatePartialSpecializationDecl *PrevPartial =
cast_or_null<VarTemplatePartialSpecializationDecl>(PrevDecl);
VarTemplatePartialSpecializationDecl *Partial =
VarTemplatePartialSpecializationDecl::Create(
Context, VarTemplate->getDeclContext(), TemplateKWLoc,
TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC,
Converted, TemplateArgs);
if (!PrevPartial)
VarTemplate->AddPartialSpecialization(Partial, InsertPos);
Specialization = Partial;
// If we are providing an explicit specialization of a member variable
// template specialization, make a note of that.
if (PrevPartial && PrevPartial->getInstantiatedFromMember())
PrevPartial->setMemberSpecialization();
CheckTemplatePartialSpecialization(Partial);
} else {
// Create a new class template specialization declaration node for
// this explicit specialization or friend declaration.
Specialization = VarTemplateSpecializationDecl::Create(
Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc,
VarTemplate, DI->getType(), DI, SC, Converted);
Specialization->setTemplateArgsInfo(TemplateArgs);
if (!PrevDecl)
VarTemplate->AddSpecialization(Specialization, InsertPos);
}
// C++ [temp.expl.spec]p6:
// If a template, a member template or the member of a class template is
// explicitly specialized then that specialization shall be declared
// before the first use of that specialization that would cause an implicit
// instantiation to take place, in every translation unit in which such a
// use occurs; no diagnostic is required.
if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) {
bool Okay = false;
for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
// Is there any previous explicit specialization declaration?
if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
Okay = true;
break;
}
}
if (!Okay) {
SourceRange Range(TemplateNameLoc, RAngleLoc);
Diag(TemplateNameLoc, diag::err_specialization_after_instantiation)
<< Name << Range;
Diag(PrevDecl->getPointOfInstantiation(),
diag::note_instantiation_required_here)
<< (PrevDecl->getTemplateSpecializationKind() !=
TSK_ImplicitInstantiation);
return true;
}
}
Specialization->setTemplateKeywordLoc(TemplateKWLoc);
Specialization->setLexicalDeclContext(CurContext);
// Add the specialization into its lexical context, so that it can
// be seen when iterating through the list of declarations in that
// context. However, specializations are not found by name lookup.
CurContext->addDecl(Specialization);
// Note that this is an explicit specialization.
Specialization->setSpecializationKind(TSK_ExplicitSpecialization);
if (PrevDecl) {
// Check that this isn't a redefinition of this specialization,
// merging with previous declarations.
LookupResult PrevSpec(*this, GetNameForDeclarator(D), LookupOrdinaryName,
forRedeclarationInCurContext());
PrevSpec.addDecl(PrevDecl);
D.setRedeclaration(CheckVariableDeclaration(Specialization, PrevSpec));
} else if (Specialization->isStaticDataMember() &&
Specialization->isOutOfLine()) {
Specialization->setAccess(VarTemplate->getAccess());
}
// Link instantiations of static data members back to the template from
// which they were instantiated.
if (Specialization->isStaticDataMember())
Specialization->setInstantiationOfStaticDataMember(
VarTemplate->getTemplatedDecl(),
Specialization->getSpecializationKind());
return Specialization;
}
namespace {
/// A partial specialization whose template arguments have matched
/// a given template-id.
struct PartialSpecMatchResult {
VarTemplatePartialSpecializationDecl *Partial;
TemplateArgumentList *Args;
};
} // end anonymous namespace
DeclResult
Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
SourceLocation TemplateNameLoc,
const TemplateArgumentListInfo &TemplateArgs) {
assert(Template && "A variable template id without template?");
// Check that the template argument list is well-formed for this template.
SmallVector<TemplateArgument, 4> Converted;
if (CheckTemplateArgumentList(
Template, TemplateNameLoc,
const_cast<TemplateArgumentListInfo &>(TemplateArgs), false,
Converted))
return true;
// Find the variable template specialization declaration that
// corresponds to these arguments.
void *InsertPos = nullptr;
if (VarTemplateSpecializationDecl *Spec = Template->findSpecialization(
Converted, InsertPos)) {
checkSpecializationVisibility(TemplateNameLoc, Spec);
// If we already have a variable template specialization, return it.
return Spec;
}
// This is the first time we have referenced this variable template
// specialization. Create the canonical declaration and add it to
// the set of specializations, based on the closest partial specialization
// that it represents. That is,
VarDecl *InstantiationPattern = Template->getTemplatedDecl();
TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack,
Converted);
TemplateArgumentList *InstantiationArgs = &TemplateArgList;
bool AmbiguousPartialSpec = false;
typedef PartialSpecMatchResult MatchResult;
SmallVector<MatchResult, 4> Matched;
SourceLocation PointOfInstantiation = TemplateNameLoc;
TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation,
/*ForTakingAddress=*/false);
// 1. Attempt to find the closest partial specialization that this
// specializes, if any.
// If any of the template arguments is dependent, then this is probably
// a placeholder for an incomplete declarative context; which must be
// complete by instantiation time. Thus, do not search through the partial
// specializations yet.
// TODO: Unify with InstantiateClassTemplateSpecialization()?
// Perhaps better after unification of DeduceTemplateArguments() and
// getMoreSpecializedPartialSpecialization().
bool InstantiationDependent = false;
if (!TemplateSpecializationType::anyDependentTemplateArguments(
TemplateArgs, InstantiationDependent)) {
SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
Template->getPartialSpecializations(PartialSpecs);
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
VarTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (TemplateDeductionResult Result =
DeduceTemplateArguments(Partial, TemplateArgList, Info)) {
// Store the failed-deduction information for use in diagnostics, later.
// TODO: Actually use the failed-deduction info?
FailedCandidates.addCandidate().set(
DeclAccessPair::make(Template, AS_public), Partial,
MakeDeductionFailureInfo(Context, Result, Info));
(void)Result;
} else {
Matched.push_back(PartialSpecMatchResult());
Matched.back().Partial = Partial;
Matched.back().Args = Info.take();
}
}
if (Matched.size() >= 1) {
SmallVector<MatchResult, 4>::iterator Best = Matched.begin();
if (Matched.size() == 1) {
// -- If exactly one matching specialization is found, the
// instantiation is generated from that specialization.
// We don't need to do anything for this.
} else {
// -- If more than one matching specialization is found, the
// partial order rules (14.5.4.2) are used to determine
// whether one of the specializations is more specialized
// than the others. If none of the specializations is more
// specialized than all of the other matching
// specializations, then the use of the variable template is
// ambiguous and the program is ill-formed.
for (SmallVector<MatchResult, 4>::iterator P = Best + 1,
PEnd = Matched.end();
P != PEnd; ++P) {
if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial,
PointOfInstantiation) ==
P->Partial)
Best = P;
}
// Determine if the best partial specialization is more specialized than
// the others.
for (SmallVector<MatchResult, 4>::iterator P = Matched.begin(),
PEnd = Matched.end();
P != PEnd; ++P) {
if (P != Best && getMoreSpecializedPartialSpecialization(
P->Partial, Best->Partial,
PointOfInstantiation) != Best->Partial) {
AmbiguousPartialSpec = true;
break;
}
}
}
// Instantiate using the best variable template partial specialization.
InstantiationPattern = Best->Partial;
InstantiationArgs = Best->Args;
} else {
// -- If no match is found, the instantiation is generated
// from the primary template.
// InstantiationPattern = Template->getTemplatedDecl();
}
}
// 2. Create the canonical declaration.
// Note that we do not instantiate a definition until we see an odr-use
// in DoMarkVarDeclReferenced().
// FIXME: LateAttrs et al.?
VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation(
Template, InstantiationPattern, *InstantiationArgs, TemplateArgs,
Converted, TemplateNameLoc, InsertPos /*, LateAttrs, StartingScope*/);
if (!Decl)
return true;
if (AmbiguousPartialSpec) {
// Partial ordering did not produce a clear winner. Complain.
Decl->setInvalidDecl();
Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous)
<< Decl;
// Print the matching partial specializations.
for (MatchResult P : Matched)
Diag(P.Partial->getLocation(), diag::note_partial_spec_match)
<< getTemplateArgumentBindingsText(P.Partial->getTemplateParameters(),
*P.Args);
return true;
}
if (VarTemplatePartialSpecializationDecl *D =
dyn_cast<VarTemplatePartialSpecializationDecl>(InstantiationPattern))
Decl->setInstantiationOf(D, InstantiationArgs);
checkSpecializationVisibility(TemplateNameLoc, Decl);
assert(Decl && "No variable template specialization?");
return Decl;
}
ExprResult
Sema::CheckVarTemplateId(const CXXScopeSpec &SS,
const DeclarationNameInfo &NameInfo,
VarTemplateDecl *Template, SourceLocation TemplateLoc,
const TemplateArgumentListInfo *TemplateArgs) {
DeclResult Decl = CheckVarTemplateId(Template, TemplateLoc, NameInfo.getLoc(),
*TemplateArgs);
if (Decl.isInvalid())
return ExprError();
VarDecl *Var = cast<VarDecl>(Decl.get());
if (!Var->getTemplateSpecializationKind())
Var->setTemplateSpecializationKind(TSK_ImplicitInstantiation,
NameInfo.getLoc());
// Build an ordinary singleton decl ref.
return BuildDeclarationNameExpr(SS, NameInfo, Var,
/*FoundD=*/nullptr, TemplateArgs);
}
void Sema::diagnoseMissingTemplateArguments(TemplateName Name,
SourceLocation Loc) {
Diag(Loc, diag::err_template_missing_args)
<< (int)getTemplateNameKindForDiagnostics(Name) << Name;
if (TemplateDecl *TD = Name.getAsTemplateDecl()) {
Diag(TD->getLocation(), diag::note_template_decl_here)
<< TD->getTemplateParameters()->getSourceRange();
}
}
ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
bool RequiresADL,
const TemplateArgumentListInfo *TemplateArgs) {
// FIXME: Can we do any checking at this point? I guess we could check the
// template arguments that we have against the template name, if the template
// name refers to a single template. That's not a terribly common case,
// though.
// foo<int> could identify a single function unambiguously
// This approach does NOT work, since f<int>(1);
// gets resolved prior to resorting to overload resolution
// i.e., template<class T> void f(double);
// vs template<class T, class U> void f(U);
// These should be filtered out by our callers.
assert(!R.empty() && "empty lookup results when building templateid");
assert(!R.isAmbiguous() && "ambiguous lookup when building templateid");
// Non-function templates require a template argument list.
if (auto *TD = R.getAsSingle<TemplateDecl>()) {
if (!TemplateArgs && !isa<FunctionTemplateDecl>(TD)) {
diagnoseMissingTemplateArguments(TemplateName(TD), R.getNameLoc());
return ExprError();
}
}
auto AnyDependentArguments = [&]() -> bool {
bool InstantiationDependent;
return TemplateArgs &&
TemplateSpecializationType::anyDependentTemplateArguments(
*TemplateArgs, InstantiationDependent);
};
// In C++1y, check variable template ids.
if (R.getAsSingle<VarTemplateDecl>() && !AnyDependentArguments()) {
return CheckVarTemplateId(SS, R.getLookupNameInfo(),
R.getAsSingle<VarTemplateDecl>(),
TemplateKWLoc, TemplateArgs);
}
// We don't want lookup warnings at this point.
R.suppressDiagnostics();
UnresolvedLookupExpr *ULE
= UnresolvedLookupExpr::Create(Context, R.getNamingClass(),
SS.getWithLocInContext(Context),
TemplateKWLoc,
R.getLookupNameInfo(),
RequiresADL, TemplateArgs,
R.begin(), R.end());
return ULE;
}
// We actually only call this from template instantiation.
ExprResult
Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
assert(TemplateArgs || TemplateKWLoc.isValid());
DeclContext *DC;
if (!(DC = computeDeclContext(SS, false)) ||
DC->isDependentContext() ||
RequireCompleteDeclContext(SS, DC))
return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs);
bool MemberOfUnknownSpecialization;
LookupResult R(*this, NameInfo, LookupOrdinaryName);
if (LookupTemplateName(R, (Scope *)nullptr, SS, QualType(),
/*Entering*/false, MemberOfUnknownSpecialization,
TemplateKWLoc))
return ExprError();
if (R.isAmbiguous())
return ExprError();
if (R.empty()) {
Diag(NameInfo.getLoc(), diag::err_no_member)
<< NameInfo.getName() << DC << SS.getRange();
return ExprError();
}
if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) {
Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_class_template)
<< SS.getScopeRep()
<< NameInfo.getName().getAsString() << SS.getRange();
Diag(Temp->getLocation(), diag::note_referenced_class_template);
return ExprError();
}
return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/ false, TemplateArgs);
}
/// Form a dependent template name.
///
/// This action forms a dependent template name given the template
/// name and its (presumably dependent) scope specifier. For
/// example, given "MetaFun::template apply", the scope specifier \p
/// SS will be "MetaFun::", \p TemplateKWLoc contains the location
/// of the "template" keyword, and "apply" is the \p Name.
TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
const UnqualifiedId &Name,
ParsedType ObjectType,
bool EnteringContext,
TemplateTy &Result,
bool AllowInjectedClassName) {
if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent())
Diag(TemplateKWLoc,
getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_template_outside_of_template :
diag::ext_template_outside_of_template)
<< FixItHint::CreateRemoval(TemplateKWLoc);
DeclContext *LookupCtx = nullptr;
if (SS.isSet())
LookupCtx = computeDeclContext(SS, EnteringContext);
if (!LookupCtx && ObjectType)
LookupCtx = computeDeclContext(ObjectType.get());
if (LookupCtx) {
// C++0x [temp.names]p5:
// If a name prefixed by the keyword template is not the name of
// a template, the program is ill-formed. [Note: the keyword
// template may not be applied to non-template members of class
// templates. -end note ] [ Note: as is the case with the
// typename prefix, the template prefix is allowed in cases
// where it is not strictly necessary; i.e., when the
// nested-name-specifier or the expression on the left of the ->
// or . is not dependent on a template-parameter, or the use
// does not appear in the scope of a template. -end note]
//
// Note: C++03 was more strict here, because it banned the use of
// the "template" keyword prior to a template-name that was not a
// dependent name. C++ DR468 relaxed this requirement (the
// "template" keyword is now permitted). We follow the C++0x
// rules, even in C++03 mode with a warning, retroactively applying the DR.
bool MemberOfUnknownSpecialization;
TemplateNameKind TNK = isTemplateName(S, SS, TemplateKWLoc.isValid(), Name,
ObjectType, EnteringContext, Result,
MemberOfUnknownSpecialization);
if (TNK == TNK_Non_template && MemberOfUnknownSpecialization) {
// This is a dependent template. Handle it below.
} else if (TNK == TNK_Non_template) {
// Do the lookup again to determine if this is a "nothing found" case or
// a "not a template" case. FIXME: Refactor isTemplateName so we don't
// need to do this.
DeclarationNameInfo DNI = GetNameFromUnqualifiedId(Name);
LookupResult R(*this, DNI.getName(), Name.getBeginLoc(),
LookupOrdinaryName);
bool MOUS;
if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext,
MOUS, TemplateKWLoc))
Diag(Name.getBeginLoc(), diag::err_no_member)
<< DNI.getName() << LookupCtx << SS.getRange();
return TNK_Non_template;
} else {
// We found something; return it.
auto *LookupRD = dyn_cast<CXXRecordDecl>(LookupCtx);
if (!AllowInjectedClassName && SS.isSet() && LookupRD &&
Name.getKind() == UnqualifiedIdKind::IK_Identifier &&
Name.Identifier && LookupRD->getIdentifier() == Name.Identifier) {
// C++14 [class.qual]p2:
// In a lookup in which function names are not ignored and the
// nested-name-specifier nominates a class C, if the name specified
// [...] is the injected-class-name of C, [...] the name is instead
// considered to name the constructor
//
// We don't get here if naming the constructor would be valid, so we
// just reject immediately and recover by treating the
// injected-class-name as naming the template.
Diag(Name.getBeginLoc(),
diag::ext_out_of_line_qualified_id_type_names_constructor)
<< Name.Identifier
<< 0 /*injected-class-name used as template name*/
<< 1 /*'template' keyword was used*/;
}
return TNK;
}
}
NestedNameSpecifier *Qualifier = SS.getScopeRep();
switch (Name.getKind()) {
case UnqualifiedIdKind::IK_Identifier:
Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
Name.Identifier));
return TNK_Dependent_template_name;
case UnqualifiedIdKind::IK_OperatorFunctionId:
Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
Name.OperatorFunctionId.Operator));
return TNK_Function_template;
case UnqualifiedIdKind::IK_LiteralOperatorId:
llvm_unreachable("literal operator id cannot have a dependent scope");
default:
break;
}
Diag(Name.getBeginLoc(), diag::err_template_kw_refers_to_non_template)
<< GetNameFromUnqualifiedId(Name).getName() << Name.getSourceRange()
<< TemplateKWLoc;
return TNK_Non_template;
}
bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
TemplateArgumentLoc &AL,
SmallVectorImpl<TemplateArgument> &Converted) {
const TemplateArgument &Arg = AL.getArgument();
QualType ArgType;
TypeSourceInfo *TSI = nullptr;
// Check template type parameter.
switch(Arg.getKind()) {
case TemplateArgument::Type:
// C++ [temp.arg.type]p1:
// A template-argument for a template-parameter which is a
// type shall be a type-id.
ArgType = Arg.getAsType();
TSI = AL.getTypeSourceInfo();
break;
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion: {
// We have a template type parameter but the template argument
// is a template without any arguments.
SourceRange SR = AL.getSourceRange();
TemplateName Name = Arg.getAsTemplateOrTemplatePattern();
diagnoseMissingTemplateArguments(Name, SR.getEnd());
return true;
}
case TemplateArgument::Expression: {
// We have a template type parameter but the template argument is an
// expression; see if maybe it is missing the "typename" keyword.
CXXScopeSpec SS;
DeclarationNameInfo NameInfo;
if (DeclRefExpr *ArgExpr = dyn_cast<DeclRefExpr>(Arg.getAsExpr())) {
SS.Adopt(ArgExpr->getQualifierLoc());
NameInfo = ArgExpr->getNameInfo();
} else if (DependentScopeDeclRefExpr *ArgExpr =
dyn_cast<DependentScopeDeclRefExpr>(Arg.getAsExpr())) {
SS.Adopt(ArgExpr->getQualifierLoc());
NameInfo = ArgExpr->getNameInfo();
} else if (CXXDependentScopeMemberExpr *ArgExpr =
dyn_cast<CXXDependentScopeMemberExpr>(Arg.getAsExpr())) {
if (ArgExpr->isImplicitAccess()) {
SS.Adopt(ArgExpr->getQualifierLoc());
NameInfo = ArgExpr->getMemberNameInfo();
}
}
if (auto *II = NameInfo.getName().getAsIdentifierInfo()) {
LookupResult Result(*this, NameInfo, LookupOrdinaryName);
LookupParsedName(Result, CurScope, &SS);
if (Result.getAsSingle<TypeDecl>() ||
Result.getResultKind() ==
LookupResult::NotFoundInCurrentInstantiation) {
// Suggest that the user add 'typename' before the NNS.
SourceLocation Loc = AL.getSourceRange().getBegin();
Diag(Loc, getLangOpts().MSVCCompat
? diag::ext_ms_template_type_arg_missing_typename
: diag::err_template_arg_must_be_type_suggest)
<< FixItHint::CreateInsertion(Loc, "typename ");
Diag(Param->getLocation(), diag::note_template_param_here);
// Recover by synthesizing a type using the location information that we
// already have.
ArgType =
Context.getDependentNameType(ETK_Typename, SS.getScopeRep(), II);
TypeLocBuilder TLB;
DependentNameTypeLoc TL = TLB.push<DependentNameTypeLoc>(ArgType);
TL.setElaboratedKeywordLoc(SourceLocation(/*synthesized*/));
TL.setQualifierLoc(SS.getWithLocInContext(Context));
TL.setNameLoc(NameInfo.getLoc());
TSI = TLB.getTypeSourceInfo(Context, ArgType);
// Overwrite our input TemplateArgumentLoc so that we can recover
// properly.
AL = TemplateArgumentLoc(TemplateArgument(ArgType),
TemplateArgumentLocInfo(TSI));
break;
}
}
// fallthrough
LLVM_FALLTHROUGH;
}
default: {
// We have a template type parameter but the template argument
// is not a type.
SourceRange SR = AL.getSourceRange();
Diag(SR.getBegin(), diag::err_template_arg_must_be_type) << SR;
Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
}
if (CheckTemplateArgument(Param, TSI))
return true;
// Add the converted template type argument.
ArgType = Context.getCanonicalType(ArgType);
// Objective-C ARC:
// If an explicitly-specified template argument type is a lifetime type
// with no lifetime qualifier, the __strong lifetime qualifier is inferred.
if (getLangOpts().ObjCAutoRefCount &&
ArgType->isObjCLifetimeType() &&
!ArgType.getObjCLifetime()) {
Qualifiers Qs;
Qs.setObjCLifetime(Qualifiers::OCL_Strong);
ArgType = Context.getQualifiedType(ArgType, Qs);
}
Converted.push_back(TemplateArgument(ArgType));
return false;
}
/// Substitute template arguments into the default template argument for
/// the given template type parameter.
///
/// \param SemaRef the semantic analysis object for which we are performing
/// the substitution.
///
/// \param Template the template that we are synthesizing template arguments
/// for.
///
/// \param TemplateLoc the location of the template name that started the
/// template-id we are checking.
///
/// \param RAngleLoc the location of the right angle bracket ('>') that
/// terminates the template-id.
///
/// \param Param the template template parameter whose default we are
/// substituting into.
///
/// \param Converted the list of template arguments provided for template
/// parameters that precede \p Param in the template parameter list.
/// \returns the substituted template argument, or NULL if an error occurred.
static TypeSourceInfo *
SubstDefaultTemplateArgument(Sema &SemaRef,
TemplateDecl *Template,
SourceLocation TemplateLoc,
SourceLocation RAngleLoc,
TemplateTypeParmDecl *Param,
SmallVectorImpl<TemplateArgument> &Converted) {
TypeSourceInfo *ArgType = Param->getDefaultArgumentInfo();
// If the argument type is dependent, instantiate it now based
// on the previously-computed template arguments.
if (ArgType->getType()->isInstantiationDependentType()) {
Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
Param, Template, Converted,
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
return nullptr;
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
// Only substitute for the innermost template argument list.
MultiLevelTemplateArgumentList TemplateArgLists;
TemplateArgLists.addOuterTemplateArguments(&TemplateArgs);
for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
TemplateArgLists.addOuterTemplateArguments(None);
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
ArgType =
SemaRef.SubstType(ArgType, TemplateArgLists,
Param->getDefaultArgumentLoc(), Param->getDeclName());
}
return ArgType;
}
/// Substitute template arguments into the default template argument for
/// the given non-type template parameter.
///
/// \param SemaRef the semantic analysis object for which we are performing
/// the substitution.
///
/// \param Template the template that we are synthesizing template arguments
/// for.
///
/// \param TemplateLoc the location of the template name that started the
/// template-id we are checking.
///
/// \param RAngleLoc the location of the right angle bracket ('>') that
/// terminates the template-id.
///
/// \param Param the non-type template parameter whose default we are
/// substituting into.
///
/// \param Converted the list of template arguments provided for template
/// parameters that precede \p Param in the template parameter list.
///
/// \returns the substituted template argument, or NULL if an error occurred.
static ExprResult
SubstDefaultTemplateArgument(Sema &SemaRef,
TemplateDecl *Template,
SourceLocation TemplateLoc,
SourceLocation RAngleLoc,
NonTypeTemplateParmDecl *Param,
SmallVectorImpl<TemplateArgument> &Converted) {
Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
Param, Template, Converted,
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
return ExprError();
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
// Only substitute for the innermost template argument list.
MultiLevelTemplateArgumentList TemplateArgLists;
TemplateArgLists.addOuterTemplateArguments(&TemplateArgs);
for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
TemplateArgLists.addOuterTemplateArguments(None);
EnterExpressionEvaluationContext ConstantEvaluated(
SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists);
}
/// Substitute template arguments into the default template argument for
/// the given template template parameter.
///
/// \param SemaRef the semantic analysis object for which we are performing
/// the substitution.
///
/// \param Template the template that we are synthesizing template arguments
/// for.
///
/// \param TemplateLoc the location of the template name that started the
/// template-id we are checking.
///
/// \param RAngleLoc the location of the right angle bracket ('>') that
/// terminates the template-id.
///
/// \param Param the template template parameter whose default we are
/// substituting into.
///
/// \param Converted the list of template arguments provided for template
/// parameters that precede \p Param in the template parameter list.
///
/// \param QualifierLoc Will be set to the nested-name-specifier (with
/// source-location information) that precedes the template name.
///
/// \returns the substituted template argument, or NULL if an error occurred.
static TemplateName
SubstDefaultTemplateArgument(Sema &SemaRef,
TemplateDecl *Template,
SourceLocation TemplateLoc,
SourceLocation RAngleLoc,
TemplateTemplateParmDecl *Param,
SmallVectorImpl<TemplateArgument> &Converted,
NestedNameSpecifierLoc &QualifierLoc) {
Sema::InstantiatingTemplate Inst(
SemaRef, TemplateLoc, TemplateParameter(Param), Template, Converted,
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
return TemplateName();
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
// Only substitute for the innermost template argument list.
MultiLevelTemplateArgumentList TemplateArgLists;
TemplateArgLists.addOuterTemplateArguments(&TemplateArgs);
for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
TemplateArgLists.addOuterTemplateArguments(None);
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
// Substitute into the nested-name-specifier first,
QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc();
if (QualifierLoc) {
QualifierLoc =
SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, TemplateArgLists);
if (!QualifierLoc)
return TemplateName();
}
return SemaRef.SubstTemplateName(
QualifierLoc,
Param->getDefaultArgument().getArgument().getAsTemplate(),
Param->getDefaultArgument().getTemplateNameLoc(),
TemplateArgLists);
}
/// If the given template parameter has a default template
/// argument, substitute into that default template argument and
/// return the corresponding template argument.
TemplateArgumentLoc
Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
SourceLocation TemplateLoc,
SourceLocation RAngleLoc,
Decl *Param,
SmallVectorImpl<TemplateArgument>
&Converted,
bool &HasDefaultArg) {
HasDefaultArg = false;
if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) {
if (!hasVisibleDefaultArgument(TypeParm))
return TemplateArgumentLoc();
HasDefaultArg = true;
TypeSourceInfo *DI = SubstDefaultTemplateArgument(*this, Template,
TemplateLoc,
RAngleLoc,
TypeParm,
Converted);
if (DI)
return TemplateArgumentLoc(TemplateArgument(DI->getType()), DI);
return TemplateArgumentLoc();
}
if (NonTypeTemplateParmDecl *NonTypeParm
= dyn_cast<NonTypeTemplateParmDecl>(Param)) {
if (!hasVisibleDefaultArgument(NonTypeParm))
return TemplateArgumentLoc();
HasDefaultArg = true;
ExprResult Arg = SubstDefaultTemplateArgument(*this, Template,
TemplateLoc,
RAngleLoc,
NonTypeParm,
Converted);
if (Arg.isInvalid())
return TemplateArgumentLoc();
Expr *ArgE = Arg.getAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(ArgE), ArgE);
}
TemplateTemplateParmDecl *TempTempParm
= cast<TemplateTemplateParmDecl>(Param);
if (!hasVisibleDefaultArgument(TempTempParm))
return TemplateArgumentLoc();
HasDefaultArg = true;
NestedNameSpecifierLoc QualifierLoc;
TemplateName TName = SubstDefaultTemplateArgument(*this, Template,
TemplateLoc,
RAngleLoc,
TempTempParm,
Converted,
QualifierLoc);
if (TName.isNull())
return TemplateArgumentLoc();
return TemplateArgumentLoc(TemplateArgument(TName),
TempTempParm->getDefaultArgument().getTemplateQualifierLoc(),
TempTempParm->getDefaultArgument().getTemplateNameLoc());
}
/// Convert a template-argument that we parsed as a type into a template, if
/// possible. C++ permits injected-class-names to perform dual service as
/// template template arguments and as template type arguments.
static TemplateArgumentLoc convertTypeTemplateArgumentToTemplate(TypeLoc TLoc) {
// Extract and step over any surrounding nested-name-specifier.
NestedNameSpecifierLoc QualLoc;
if (auto ETLoc = TLoc.getAs<ElaboratedTypeLoc>()) {
if (ETLoc.getTypePtr()->getKeyword() != ETK_None)
return TemplateArgumentLoc();
QualLoc = ETLoc.getQualifierLoc();
TLoc = ETLoc.getNamedTypeLoc();
}
// If this type was written as an injected-class-name, it can be used as a
// template template argument.
if (auto InjLoc = TLoc.getAs<InjectedClassNameTypeLoc>())
return TemplateArgumentLoc(InjLoc.getTypePtr()->getTemplateName(),
QualLoc, InjLoc.getNameLoc());
// If this type was written as an injected-class-name, it may have been
// converted to a RecordType during instantiation. If the RecordType is
// *not* wrapped in a TemplateSpecializationType and denotes a class
// template specialization, it must have come from an injected-class-name.
if (auto RecLoc = TLoc.getAs<RecordTypeLoc>())
if (auto *CTSD =
dyn_cast<ClassTemplateSpecializationDecl>(RecLoc.getDecl()))
return TemplateArgumentLoc(TemplateName(CTSD->getSpecializedTemplate()),
QualLoc, RecLoc.getNameLoc());
return TemplateArgumentLoc();
}
/// Check that the given template argument corresponds to the given
/// template parameter.
///
/// \param Param The template parameter against which the argument will be
/// checked.
///
/// \param Arg The template argument, which may be updated due to conversions.
///
/// \param Template The template in which the template argument resides.
///
/// \param TemplateLoc The location of the template name for the template
/// whose argument list we're matching.
///
/// \param RAngleLoc The location of the right angle bracket ('>') that closes
/// the template argument list.
///
/// \param ArgumentPackIndex The index into the argument pack where this
/// argument will be placed. Only valid if the parameter is a parameter pack.
///
/// \param Converted The checked, converted argument will be added to the
/// end of this small vector.
///
/// \param CTAK Describes how we arrived at this particular template argument:
/// explicitly written, deduced, etc.
///
/// \returns true on error, false otherwise.
bool Sema::CheckTemplateArgument(NamedDecl *Param,
TemplateArgumentLoc &Arg,
NamedDecl *Template,
SourceLocation TemplateLoc,
SourceLocation RAngleLoc,
unsigned ArgumentPackIndex,
SmallVectorImpl<TemplateArgument> &Converted,
CheckTemplateArgumentKind CTAK) {
// Check template type parameters.
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
return CheckTemplateTypeArgument(TTP, Arg, Converted);
// Check non-type template parameters.
if (NonTypeTemplateParmDecl *NTTP =dyn_cast<NonTypeTemplateParmDecl>(Param)) {
// Do substitution on the type of the non-type template parameter
// with the template arguments we've seen thus far. But if the
// template has a dependent context then we cannot substitute yet.
QualType NTTPType = NTTP->getType();
if (NTTP->isParameterPack() && NTTP->isExpandedParameterPack())
NTTPType = NTTP->getExpansionType(ArgumentPackIndex);
// FIXME: Do we need to substitute into parameters here if they're
// instantiation-dependent but not dependent?
if (NTTPType->isDependentType() &&
!isa<TemplateTemplateParmDecl>(Template) &&
!Template->getDeclContext()->isDependentContext()) {
// Do substitution on the type of the non-type template parameter.
InstantiatingTemplate Inst(*this, TemplateLoc, Template,
NTTP, Converted,
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
return true;
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack,
Converted);
NTTPType = SubstType(NTTPType,
MultiLevelTemplateArgumentList(TemplateArgs),
NTTP->getLocation(),
NTTP->getDeclName());
// If that worked, check the non-type template parameter type
// for validity.
if (!NTTPType.isNull())
NTTPType = CheckNonTypeTemplateParameterType(NTTPType,
NTTP->getLocation());
if (NTTPType.isNull())
return true;
}
switch (Arg.getArgument().getKind()) {
case TemplateArgument::Null:
llvm_unreachable("Should never see a NULL template argument here");
case TemplateArgument::Expression: {
TemplateArgument Result;
unsigned CurSFINAEErrors = NumSFINAEErrors;
ExprResult Res =
CheckTemplateArgument(NTTP, NTTPType, Arg.getArgument().getAsExpr(),
Result, CTAK);
if (Res.isInvalid())
return true;
// If the current template argument causes an error, give up now.
if (CurSFINAEErrors < NumSFINAEErrors)
return true;
// If the resulting expression is new, then use it in place of the
// old expression in the template argument.
if (Res.get() != Arg.getArgument().getAsExpr()) {
TemplateArgument TA(Res.get());
Arg = TemplateArgumentLoc(TA, Res.get());
}
Converted.push_back(Result);
break;
}
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
case TemplateArgument::NullPtr:
// We've already checked this template argument, so just copy
// it to the list of converted arguments.
Converted.push_back(Arg.getArgument());
break;
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
// We were given a template template argument. It may not be ill-formed;
// see below.
if (DependentTemplateName *DTN
= Arg.getArgument().getAsTemplateOrTemplatePattern()
.getAsDependentTemplateName()) {
// We have a template argument such as \c T::template X, which we
// parsed as a template template argument. However, since we now
// know that we need a non-type template argument, convert this
// template name into an expression.
DeclarationNameInfo NameInfo(DTN->getIdentifier(),
Arg.getTemplateNameLoc());
CXXScopeSpec SS;
SS.Adopt(Arg.getTemplateQualifierLoc());
// FIXME: the template-template arg was a DependentTemplateName,
// so it was provided with a template keyword. However, its source
// location is not stored in the template argument structure.
SourceLocation TemplateKWLoc;
ExprResult E = DependentScopeDeclRefExpr::Create(
Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo,
nullptr);
// If we parsed the template argument as a pack expansion, create a
// pack expansion expression.
if (Arg.getArgument().getKind() == TemplateArgument::TemplateExpansion){
E = ActOnPackExpansion(E.get(), Arg.getTemplateEllipsisLoc());
if (E.isInvalid())
return true;
}
TemplateArgument Result;
E = CheckTemplateArgument(NTTP, NTTPType, E.get(), Result);
if (E.isInvalid())
return true;
Converted.push_back(Result);
break;
}
// We have a template argument that actually does refer to a class
// template, alias template, or template template parameter, and
// therefore cannot be a non-type template argument.
Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr)
<< Arg.getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
return true;
case TemplateArgument::Type: {
// We have a non-type template parameter but the template
// argument is a type.
// C++ [temp.arg]p2:
// In a template-argument, an ambiguity between a type-id and
// an expression is resolved to a type-id, regardless of the
// form of the corresponding template-parameter.
//
// We warn specifically about this case, since it can be rather
// confusing for users.
QualType T = Arg.getArgument().getAsType();
SourceRange SR = Arg.getSourceRange();
if (T->isFunctionType())
Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) << SR << T;
else
Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR;
Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
case TemplateArgument::Pack:
llvm_unreachable("Caller must expand template argument packs");
}
return false;
}
// Check template template parameters.
TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(Param);
TemplateParameterList *Params = TempParm->getTemplateParameters();
if (TempParm->isExpandedParameterPack())
Params = TempParm->getExpansionTemplateParameters(ArgumentPackIndex);
// Substitute into the template parameter list of the template
// template parameter, since previously-supplied template arguments
// may appear within the template template parameter.
//
// FIXME: Skip this if the parameters aren't instantiation-dependent.
{
// Set up a template instantiation context.
LocalInstantiationScope Scope(*this);
InstantiatingTemplate Inst(*this, TemplateLoc, Template,
TempParm, Converted,
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
return true;
TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted);
Params = SubstTemplateParams(Params, CurContext,
MultiLevelTemplateArgumentList(TemplateArgs));
if (!Params)
return true;
}
// C++1z [temp.local]p1: (DR1004)
// When [the injected-class-name] is used [...] as a template-argument for
// a template template-parameter [...] it refers to the class template
// itself.
if (Arg.getArgument().getKind() == TemplateArgument::Type) {
TemplateArgumentLoc ConvertedArg = convertTypeTemplateArgumentToTemplate(
Arg.getTypeSourceInfo()->getTypeLoc());
if (!ConvertedArg.getArgument().isNull())
Arg = ConvertedArg;
}
switch (Arg.getArgument().getKind()) {
case TemplateArgument::Null:
llvm_unreachable("Should never see a NULL template argument here");
case TemplateArgument::Template:
case TemplateArgument::TemplateExpansion:
if (CheckTemplateTemplateArgument(Params, Arg))
return true;
Converted.push_back(Arg.getArgument());
break;
case TemplateArgument::Expression:
case TemplateArgument::Type:
// We have a template template parameter but the template
// argument does not refer to a template.
Diag(Arg.getLocation(), diag::err_template_arg_must_be_template)
<< getLangOpts().CPlusPlus11;
return true;
case TemplateArgument::Declaration:
llvm_unreachable("Declaration argument with template template parameter");
case TemplateArgument::Integral:
llvm_unreachable("Integral argument with template template parameter");
case TemplateArgument::NullPtr:
llvm_unreachable("Null pointer argument with template template parameter");
case TemplateArgument::Pack:
llvm_unreachable("Caller must expand template argument packs");
}
return false;
}
/// Check whether the template parameter is a pack expansion, and if so,
/// determine the number of parameters produced by that expansion. For instance:
///
/// \code
/// template<typename ...Ts> struct A {
/// template<Ts ...NTs, template<Ts> class ...TTs, typename ...Us> struct B;
/// };
/// \endcode
///
/// In \c A<int,int>::B, \c NTs and \c TTs have expanded pack size 2, and \c Us
/// is not a pack expansion, so returns an empty Optional.
static Optional<unsigned> getExpandedPackSize(NamedDecl *Param) {
if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(Param)) {
if (NTTP->isExpandedParameterPack())
return NTTP->getNumExpansionTypes();
}
if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(Param)) {
if (TTP->isExpandedParameterPack())
return TTP->getNumExpansionTemplateParameters();
}
return None;
}
/// Diagnose a missing template argument.
template<typename TemplateParmDecl>
static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc,
TemplateDecl *TD,
const TemplateParmDecl *D,
TemplateArgumentListInfo &Args) {
// Dig out the most recent declaration of the template parameter; there may be
// declarations of the template that are more recent than TD.
D = cast<TemplateParmDecl>(cast<TemplateDecl>(TD->getMostRecentDecl())
->getTemplateParameters()
->getParam(D->getIndex()));
// If there's a default argument that's not visible, diagnose that we're
// missing a module import.
llvm::SmallVector<Module*, 8> Modules;
if (D->hasDefaultArgument() && !S.hasVisibleDefaultArgument(D, &Modules)) {
S.diagnoseMissingImport(Loc, cast<NamedDecl>(TD),
D->getDefaultArgumentLoc(), Modules,
Sema::MissingImportKind::DefaultArgument,
/*Recover*/true);
return true;
}
// FIXME: If there's a more recent default argument that *is* visible,
// diagnose that it was declared too late.
TemplateParameterList *Params = TD->getTemplateParameters();
S.Diag(Loc, diag::err_template_arg_list_different_arity)
<< /*not enough args*/0
<< (int)S.getTemplateNameKindForDiagnostics(TemplateName(TD))
<< TD;
S.Diag(TD->getLocation(), diag::note_template_decl_here)
<< Params->getSourceRange();
return true;
}
/// Check that the given template argument list is well-formed
/// for specializing the given template.
bool Sema::CheckTemplateArgumentList(
TemplateDecl *Template, SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs,
SmallVectorImpl<TemplateArgument> &Converted,
bool UpdateArgsWithConversions) {
// Make a copy of the template arguments for processing. Only make the
// changes at the end when successful in matching the arguments to the
// template.
TemplateArgumentListInfo NewArgs = TemplateArgs;
// Make sure we get the template parameter list from the most
// recentdeclaration, since that is the only one that has is guaranteed to
// have all the default template argument information.
TemplateParameterList *Params =
cast<TemplateDecl>(Template->getMostRecentDecl())
->getTemplateParameters();
SourceLocation RAngleLoc = NewArgs.getRAngleLoc();
// C++ [temp.arg]p1:
// [...] The type and form of each template-argument specified in
// a template-id shall match the type and form specified for the
// corresponding parameter declared by the template in its
// template-parameter-list.
bool isTemplateTemplateParameter = isa<TemplateTemplateParmDecl>(Template);
SmallVector<TemplateArgument, 2> ArgumentPack;
unsigned ArgIdx = 0, NumArgs = NewArgs.size();
LocalInstantiationScope InstScope(*this, true);
for (TemplateParameterList::iterator Param = Params->begin(),
ParamEnd = Params->end();
Param != ParamEnd; /* increment in loop */) {
// If we have an expanded parameter pack, make sure we don't have too
// many arguments.
if (Optional<unsigned> Expansions = getExpandedPackSize(*Param)) {
if (*Expansions == ArgumentPack.size()) {
// We're done with this parameter pack. Pack up its arguments and add
// them to the list.
Converted.push_back(
TemplateArgument::CreatePackCopy(Context, ArgumentPack));
ArgumentPack.clear();
// This argument is assigned to the next parameter.
++Param;
continue;
} else if (ArgIdx == NumArgs && !PartialTemplateArgs) {
// Not enough arguments for this parameter pack.
Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
<< /*not enough args*/0
<< (int)getTemplateNameKindForDiagnostics(TemplateName(Template))
<< Template;
Diag(Template->getLocation(), diag::note_template_decl_here)
<< Params->getSourceRange();
return true;
}
}
if (ArgIdx < NumArgs) {
// Check the template argument we were given.
if (CheckTemplateArgument(*Param, NewArgs[ArgIdx], Template,
TemplateLoc, RAngleLoc,
ArgumentPack.size(), Converted))
return true;
bool PackExpansionIntoNonPack =
NewArgs[ArgIdx].getArgument().isPackExpansion() &&
(!(*Param)->isTemplateParameterPack() || getExpandedPackSize(*Param));
if (PackExpansionIntoNonPack && isa<TypeAliasTemplateDecl>(Template)) {
// Core issue 1430: we have a pack expansion as an argument to an
// alias template, and it's not part of a parameter pack. This
// can't be canonicalized, so reject it now.
Diag(NewArgs[ArgIdx].getLocation(),
diag::err_alias_template_expansion_into_fixed_list)
<< NewArgs[ArgIdx].getSourceRange();
Diag((*Param)->getLocation(), diag::note_template_param_here);
return true;
}
// We're now done with this argument.
++ArgIdx;
if ((*Param)->isTemplateParameterPack()) {
// The template parameter was a template parameter pack, so take the
// deduced argument and place it on the argument pack. Note that we
// stay on the same template parameter so that we can deduce more
// arguments.
ArgumentPack.push_back(Converted.pop_back_val());
} else {
// Move to the next template parameter.
++Param;
}
// If we just saw a pack expansion into a non-pack, then directly convert
// the remaining arguments, because we don't know what parameters they'll
// match up with.
if (PackExpansionIntoNonPack) {
if (!ArgumentPack.empty()) {
// If we were part way through filling in an expanded parameter pack,
// fall back to just producing individual arguments.
Converted.insert(Converted.end(),
ArgumentPack.begin(), ArgumentPack.end());
ArgumentPack.clear();
}
while (ArgIdx < NumArgs) {
Converted.push_back(NewArgs[ArgIdx].getArgument());
++ArgIdx;
}
return false;
}
continue;
}
// If we're checking a partial template argument list, we're done.
if (PartialTemplateArgs) {
if ((*Param)->isTemplateParameterPack() && !ArgumentPack.empty())
Converted.push_back(
TemplateArgument::CreatePackCopy(Context, ArgumentPack));
return false;
}
// If we have a template parameter pack with no more corresponding
// arguments, just break out now and we'll fill in the argument pack below.
if ((*Param)->isTemplateParameterPack()) {
assert(!getExpandedPackSize(*Param) &&
"Should have dealt with this already");
// A non-expanded parameter pack before the end of the parameter list
// only occurs for an ill-formed template parameter list, unless we've
// got a partial argument list for a function template, so just bail out.
if (Param + 1 != ParamEnd)
return true;
Converted.push_back(
TemplateArgument::CreatePackCopy(Context, ArgumentPack));
ArgumentPack.clear();
++Param;
continue;
}
// Check whether we have a default argument.
TemplateArgumentLoc Arg;
// Retrieve the default template argument from the template
// parameter. For each kind of template parameter, we substitute the
// template arguments provided thus far and any "outer" template arguments
// (when the template parameter was part of a nested template) into
// the default argument.
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
if (!hasVisibleDefaultArgument(TTP))
return diagnoseMissingArgument(*this, TemplateLoc, Template, TTP,
NewArgs);
TypeSourceInfo *ArgType = SubstDefaultTemplateArgument(*this,
Template,
TemplateLoc,
RAngleLoc,
TTP,
Converted);
if (!ArgType)
return true;
Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()),
ArgType);
} else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
if (!hasVisibleDefaultArgument(NTTP))
return diagnoseMissingArgument(*this, TemplateLoc, Template, NTTP,
NewArgs);
ExprResult E = SubstDefaultTemplateArgument(*this, Template,
TemplateLoc,
RAngleLoc,
NTTP,
Converted);
if (E.isInvalid())
return true;
Expr *Ex = E.getAs<Expr>();
Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex);
} else {
TemplateTemplateParmDecl *TempParm
= cast<TemplateTemplateParmDecl>(*Param);
if (!hasVisibleDefaultArgument(TempParm))
return diagnoseMissingArgument(*this, TemplateLoc, Template, TempParm,
NewArgs);
NestedNameSpecifierLoc QualifierLoc;
TemplateName Name = SubstDefaultTemplateArgument(*this, Template,
TemplateLoc,
RAngleLoc,
TempParm,
Converted,
QualifierLoc);
if (Name.isNull())
return true;
Arg = TemplateArgumentLoc(TemplateArgument(Name), QualifierLoc,
TempParm->getDefaultArgument().getTemplateNameLoc());
}
// Introduce an instantiation record that describes where we are using
// the default template argument. We're not actually instantiating a
// template here, we just create this object to put a note into the
// context stack.
InstantiatingTemplate Inst(*this, RAngleLoc, Template, *Param, Converted,
SourceRange(TemplateLoc, RAngleLoc));
if (Inst.isInvalid())
return true;
// Check the default template argument.
if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc,
RAngleLoc, 0, Converted))
return true;
// Core issue 150 (assumed resolution): if this is a template template
// parameter, keep track of the default template arguments from the
// template definition.
if (isTemplateTemplateParameter)
NewArgs.addArgument(Arg);
// Move to the next template parameter and argument.
++Param;
++ArgIdx;
}
// If we're performing a partial argument substitution, allow any trailing
// pack expansions; they might be empty. This can happen even if
// PartialTemplateArgs is false (the list of arguments is complete but
// still dependent).
if (ArgIdx < NumArgs && CurrentInstantiationScope &&
CurrentInstantiationScope->getPartiallySubstitutedPack()) {
while (ArgIdx < NumArgs && NewArgs[ArgIdx].getArgument().isPackExpansion())
Converted.push_back(NewArgs[ArgIdx++].getArgument());
}
// If we have any leftover arguments, then there were too many arguments.
// Complain and fail.
if (ArgIdx < NumArgs) {
Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
<< /*too many args*/1
<< (int)getTemplateNameKindForDiagnostics(TemplateName(Template))
<< Template
<< SourceRange(NewArgs[ArgIdx].getLocation(), NewArgs.getRAngleLoc());
Diag(Template->getLocation(), diag::note_template_decl_here)
<< Params->getSourceRange();
return true;
}
// No problems found with the new argument list, propagate changes back
// to caller.
if (UpdateArgsWithConversions)
TemplateArgs = std::move(NewArgs);
return false;
}
namespace {
class UnnamedLocalNoLinkageFinder
: public TypeVisitor<UnnamedLocalNoLinkageFinder, bool>
{
Sema &S;
SourceRange SR;
typedef TypeVisitor<UnnamedLocalNoLinkageFinder, bool> inherited;
public:
UnnamedLocalNoLinkageFinder(Sema &S, SourceRange SR) : S(S), SR(SR) { }
bool Visit(QualType T) {
return T.isNull() ? false : inherited::Visit(T.getTypePtr());
}
#define TYPE(Class, Parent) \
bool Visit##Class##Type(const Class##Type *);
#define ABSTRACT_TYPE(Class, Parent) \
bool Visit##Class##Type(const Class##Type *) { return false; }
#define NON_CANONICAL_TYPE(Class, Parent) \
bool Visit##Class##Type(const Class##Type *) { return false; }
#include "clang/AST/TypeNodes.def"
bool VisitTagDecl(const TagDecl *Tag);
bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS);
};
} // end anonymous namespace
bool UnnamedLocalNoLinkageFinder::VisitBuiltinType(const BuiltinType*) {
return false;
}
bool UnnamedLocalNoLinkageFinder::VisitComplexType(const ComplexType* T) {
return Visit(T->getElementType());
}
bool UnnamedLocalNoLinkageFinder::VisitPointerType(const PointerType* T) {
return Visit(T->getPointeeType());
}
bool UnnamedLocalNoLinkageFinder::VisitBlockPointerType(
const BlockPointerType* T) {
return Visit(T->getPointeeType());
}
bool UnnamedLocalNoLinkageFinder::VisitLValueReferenceType(
const LValueReferenceType* T) {
return Visit(T->getPointeeType());
}
bool UnnamedLocalNoLinkageFinder::VisitRValueReferenceType(
const RValueReferenceType* T) {
return Visit(T->getPointeeType());
}
bool UnnamedLocalNoLinkageFinder::VisitMemberPointerType(
const MemberPointerType* T) {
return Visit(T->getPointeeType()) || Visit(QualType(T->getClass(), 0));
}
bool UnnamedLocalNoLinkageFinder::VisitConstantArrayType(
const ConstantArrayType* T) {
return Visit(T->getElementType());
}
bool UnnamedLocalNoLinkageFinder::VisitIncompleteArrayType(
const IncompleteArrayType* T) {
return Visit(T->getElementType());
}
bool UnnamedLocalNoLinkageFinder::VisitVariableArrayType(
const VariableArrayType* T) {
return Visit(T->getElementType());
}
bool UnnamedLocalNoLinkageFinder::VisitDependentSizedArrayType(
const DependentSizedArrayType* T) {
return Visit(T->getElementType());
}
bool UnnamedLocalNoLinkageFinder::VisitDependentSizedExtVectorType(
const DependentSizedExtVectorType* T) {
return Visit(T->getElementType());
}
bool UnnamedLocalNoLinkageFinder::VisitDependentAddressSpaceType(
const DependentAddressSpaceType *T) {
return Visit(T->getPointeeType());
}
bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) {
return Visit(T->getElementType());
}
bool UnnamedLocalNoLinkageFinder::VisitDependentVectorType(
const DependentVectorType *T) {
return Visit(T->getElementType());
}
bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) {
return Visit(T->getElementType());
}
bool UnnamedLocalNoLinkageFinder::VisitFunctionProtoType(
const FunctionProtoType* T) {
for (const auto &A : T->param_types()) {
if (Visit(A))
return true;
}
return Visit(T->getReturnType());
}
bool UnnamedLocalNoLinkageFinder::VisitFunctionNoProtoType(
const FunctionNoProtoType* T) {
return Visit(T->getReturnType());
}
bool UnnamedLocalNoLinkageFinder::VisitUnresolvedUsingType(
const UnresolvedUsingType*) {
return false;
}
bool UnnamedLocalNoLinkageFinder::VisitTypeOfExprType(const TypeOfExprType*) {
return false;
}
bool UnnamedLocalNoLinkageFinder::VisitTypeOfType(const TypeOfType* T) {
return Visit(T->getUnderlyingType());
}
bool UnnamedLocalNoLinkageFinder::VisitDecltypeType(const DecltypeType*) {
return false;
}
bool UnnamedLocalNoLinkageFinder::VisitUnaryTransformType(
const UnaryTransformType*) {
return false;
}
bool UnnamedLocalNoLinkageFinder::VisitAutoType(const AutoType *T) {
return Visit(T->getDeducedType());
}
bool UnnamedLocalNoLinkageFinder::VisitDeducedTemplateSpecializationType(
const DeducedTemplateSpecializationType *T) {
return Visit(T->getDeducedType());
}
bool UnnamedLocalNoLinkageFinder::VisitRecordType(const RecordType* T) {
return VisitTagDecl(T->getDecl());
}
bool UnnamedLocalNoLinkageFinder::VisitEnumType(const EnumType* T) {
return VisitTagDecl(T->getDecl());
}
bool UnnamedLocalNoLinkageFinder::VisitTemplateTypeParmType(
const TemplateTypeParmType*) {
return false;
}
bool UnnamedLocalNoLinkageFinder::VisitSubstTemplateTypeParmPackType(
const SubstTemplateTypeParmPackType *) {
return false;
}
bool UnnamedLocalNoLinkageFinder::VisitTemplateSpecializationType(
const TemplateSpecializationType*) {
return false;
}
bool UnnamedLocalNoLinkageFinder::VisitInjectedClassNameType(
const InjectedClassNameType* T) {
return VisitTagDecl(T->getDecl());
}
bool UnnamedLocalNoLinkageFinder::VisitDependentNameType(
const DependentNameType* T) {
return VisitNestedNameSpecifier(T->getQualifier());
}
bool UnnamedLocalNoLinkageFinder::VisitDependentTemplateSpecializationType(
const DependentTemplateSpecializationType* T) {
return VisitNestedNameSpecifier(T->getQualifier());
}
bool UnnamedLocalNoLinkageFinder::VisitPackExpansionType(
const PackExpansionType* T) {
return Visit(T->getPattern());
}
bool UnnamedLocalNoLinkageFinder::VisitObjCObjectType(const ObjCObjectType *) {
return false;
}
bool UnnamedLocalNoLinkageFinder::VisitObjCInterfaceType(
const ObjCInterfaceType *) {
return false;
}
bool UnnamedLocalNoLinkageFinder::VisitObjCObjectPointerType(
const ObjCObjectPointerType *) {
return false;
}
bool UnnamedLocalNoLinkageFinder::VisitAtomicType(const AtomicType* T) {
return Visit(T->getValueType());
}
bool UnnamedLocalNoLinkageFinder::VisitPipeType(const PipeType* T) {
return false;
}
bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
if (Tag->getDeclContext()->isFunctionOrMethod()) {
S.Diag(SR.getBegin(),
S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_template_arg_local_type :
diag::ext_template_arg_local_type)
<< S.Context.getTypeDeclType(Tag) << SR;
return true;
}
if (!Tag->hasNameForLinkage()) {
S.Diag(SR.getBegin(),
S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_template_arg_unnamed_type :
diag::ext_template_arg_unnamed_type) << SR;
S.Diag(Tag->getLocation(), diag::note_template_unnamed_type_here);
return true;
}
return false;
}
bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier(
NestedNameSpecifier *NNS) {
if (NNS->getPrefix() && VisitNestedNameSpecifier(NNS->getPrefix()))
return true;
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
case NestedNameSpecifier::Super:
return false;
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
return Visit(QualType(NNS->getAsType(), 0));
}
llvm_unreachable("Invalid NestedNameSpecifier::Kind!");
}
/// Check a template argument against its corresponding
/// template type parameter.
///
/// This routine implements the semantics of C++ [temp.arg.type]. It
/// returns true if an error occurred, and false otherwise.
bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
TypeSourceInfo *ArgInfo) {
assert(ArgInfo && "invalid TypeSourceInfo");
QualType Arg = ArgInfo->getType();
SourceRange SR = ArgInfo->getTypeLoc().getSourceRange();
if (Arg->isVariablyModifiedType()) {
return Diag(SR.getBegin(), diag::err_variably_modified_template_arg) << Arg;
} else if (Context.hasSameUnqualifiedType(Arg, Context.OverloadTy)) {
return Diag(SR.getBegin(), diag::err_template_arg_overload_type) << SR;
}
// C++03 [temp.arg.type]p2:
// A local type, a type with no linkage, an unnamed type or a type
// compounded from any of these types shall not be used as a
// template-argument for a template type-parameter.
//
// C++11 allows these, and even in C++03 we allow them as an extension with
// a warning.
if (LangOpts.CPlusPlus11 || Arg->hasUnnamedOrLocalType()) {
UnnamedLocalNoLinkageFinder Finder(*this, SR);
(void)Finder.Visit(Context.getCanonicalType(Arg));
}
return false;
}
enum NullPointerValueKind {
NPV_NotNullPointer,
NPV_NullPointer,
NPV_Error
};
/// Determine whether the given template argument is a null pointer
/// value of the appropriate type.
static NullPointerValueKind
isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
QualType ParamType, Expr *Arg,
Decl *Entity = nullptr) {
if (Arg->isValueDependent() || Arg->isTypeDependent())
return NPV_NotNullPointer;
// dllimport'd entities aren't constant but are available inside of template
// arguments.
if (Entity && Entity->hasAttr<DLLImportAttr>())
return NPV_NotNullPointer;
if (!S.isCompleteType(Arg->getExprLoc(), ParamType))
llvm_unreachable(
"Incomplete parameter type in isNullPointerValueTemplateArgument!");
if (!S.getLangOpts().CPlusPlus11)
return NPV_NotNullPointer;
// Determine whether we have a constant expression.
ExprResult ArgRV = S.DefaultFunctionArrayConversion(Arg);
if (ArgRV.isInvalid())
return NPV_Error;
Arg = ArgRV.get();
Expr::EvalResult EvalResult;
SmallVector<PartialDiagnosticAt, 8> Notes;
EvalResult.Diag = &Notes;
if (!Arg->EvaluateAsRValue(EvalResult, S.Context) ||
EvalResult.HasSideEffects) {
SourceLocation DiagLoc = Arg->getExprLoc();
// If our only note is the usual "invalid subexpression" note, just point
// the caret at its location rather than producing an essentially
// redundant note.
if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
diag::note_invalid_subexpr_in_const_expr) {
DiagLoc = Notes[0].first;
Notes.clear();
}
S.Diag(DiagLoc, diag::err_template_arg_not_address_constant)
<< Arg->getType() << Arg->getSourceRange();
for (unsigned I = 0, N = Notes.size(); I != N; ++I)
S.Diag(Notes[I].first, Notes[I].second);
S.Diag(Param->getLocation(), diag::note_template_param_here);
return NPV_Error;
}
// C++11 [temp.arg.nontype]p1:
// - an address constant expression of type std::nullptr_t
if (Arg->getType()->isNullPtrType())
return NPV_NullPointer;
// - a constant expression that evaluates to a null pointer value (4.10); or
// - a constant expression that evaluates to a null member pointer value
// (4.11); or
if ((EvalResult.Val.isLValue() && !EvalResult.Val.getLValueBase()) ||
(EvalResult.Val.isMemberPointer() &&
!EvalResult.Val.getMemberPointerDecl())) {
// If our expression has an appropriate type, we've succeeded.
bool ObjCLifetimeConversion;
if (S.Context.hasSameUnqualifiedType(Arg->getType(), ParamType) ||
S.IsQualificationConversion(Arg->getType(), ParamType, false,
ObjCLifetimeConversion))
return NPV_NullPointer;
// The types didn't match, but we know we got a null pointer; complain,
// then recover as if the types were correct.
S.Diag(Arg->getExprLoc(), diag::err_template_arg_wrongtype_null_constant)
<< Arg->getType() << ParamType << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return NPV_NullPointer;
}
// If we don't have a null pointer value, but we do have a NULL pointer
// constant, suggest a cast to the appropriate type.
if (Arg->isNullPointerConstant(S.Context, Expr::NPC_NeverValueDependent)) {
std::string Code = "static_cast<" + ParamType.getAsString() + ">(";
S.Diag(Arg->getExprLoc(), diag::err_template_arg_untyped_null_constant)
<< ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), Code)
<< FixItHint::CreateInsertion(S.getLocForEndOfToken(Arg->getEndLoc()),
")");
S.Diag(Param->getLocation(), diag::note_template_param_here);
return NPV_NullPointer;
}
// FIXME: If we ever want to support general, address-constant expressions
// as non-type template arguments, we should return the ExprResult here to
// be interpreted by the caller.
return NPV_NotNullPointer;
}
/// Checks whether the given template argument is compatible with its
/// template parameter.
static bool CheckTemplateArgumentIsCompatibleWithParameter(
Sema &S, NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *ArgIn,
Expr *Arg, QualType ArgType) {
bool ObjCLifetimeConversion;
if (ParamType->isPointerType() &&
!ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType() &&
S.IsQualificationConversion(ArgType, ParamType, false,
ObjCLifetimeConversion)) {
// For pointer-to-object types, qualification conversions are
// permitted.
} else {
if (const ReferenceType *ParamRef = ParamType->getAs<ReferenceType>()) {
if (!ParamRef->getPointeeType()->isFunctionType()) {
// C++ [temp.arg.nontype]p5b3:
// For a non-type template-parameter of type reference to
// object, no conversions apply. The type referred to by the
// reference may be more cv-qualified than the (otherwise
// identical) type of the template- argument. The
// template-parameter is bound directly to the
// template-argument, which shall be an lvalue.
// FIXME: Other qualifiers?
unsigned ParamQuals = ParamRef->getPointeeType().getCVRQualifiers();
unsigned ArgQuals = ArgType.getCVRQualifiers();
if ((ParamQuals | ArgQuals) != ParamQuals) {
S.Diag(Arg->getBeginLoc(),
diag::err_template_arg_ref_bind_ignores_quals)
<< ParamType << Arg->getType() << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
}
}
// At this point, the template argument refers to an object or
// function with external linkage. We now need to check whether the
// argument and parameter types are compatible.
if (!S.Context.hasSameUnqualifiedType(ArgType,
ParamType.getNonReferenceType())) {
// We can't perform this conversion or binding.
if (ParamType->isReferenceType())
S.Diag(Arg->getBeginLoc(), diag::err_template_arg_no_ref_bind)
<< ParamType << ArgIn->getType() << Arg->getSourceRange();
else
S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_convertible)
<< ArgIn->getType() << ParamType << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
}
return false;
}
/// Checks whether the given template argument is the address
/// of an object or function according to C++ [temp.arg.nontype]p1.
static bool
CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
NonTypeTemplateParmDecl *Param,
QualType ParamType,
Expr *ArgIn,
TemplateArgument &Converted) {
bool Invalid = false;
Expr *Arg = ArgIn;
QualType ArgType = Arg->getType();
bool AddressTaken = false;
SourceLocation AddrOpLoc;
if (S.getLangOpts().MicrosoftExt) {
// Microsoft Visual C++ strips all casts, allows an arbitrary number of
// dereference and address-of operators.
Arg = Arg->IgnoreParenCasts();
bool ExtWarnMSTemplateArg = false;
UnaryOperatorKind FirstOpKind;
SourceLocation FirstOpLoc;
while (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
UnaryOperatorKind UnOpKind = UnOp->getOpcode();
if (UnOpKind == UO_Deref)
ExtWarnMSTemplateArg = true;
if (UnOpKind == UO_AddrOf || UnOpKind == UO_Deref) {
Arg = UnOp->getSubExpr()->IgnoreParenCasts();
if (!AddrOpLoc.isValid()) {
FirstOpKind = UnOpKind;
FirstOpLoc = UnOp->getOperatorLoc();
}
} else
break;
}
if (FirstOpLoc.isValid()) {
if (ExtWarnMSTemplateArg)
S.Diag(ArgIn->getBeginLoc(), diag::ext_ms_deref_template_argument)
<< ArgIn->getSourceRange();
if (FirstOpKind == UO_AddrOf)
AddressTaken = true;
else if (Arg->getType()->isPointerType()) {
// We cannot let pointers get dereferenced here, that is obviously not a
// constant expression.
assert(FirstOpKind == UO_Deref);
S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref)
<< Arg->getSourceRange();
}
}
} else {
// See through any implicit casts we added to fix the type.
Arg = Arg->IgnoreImpCasts();
// C++ [temp.arg.nontype]p1:
//
// A template-argument for a non-type, non-template
// template-parameter shall be one of: [...]
//
// -- the address of an object or function with external
// linkage, including function templates and function
// template-ids but excluding non-static class members,
// expressed as & id-expression where the & is optional if
// the name refers to a function or array, or if the
// corresponding template-parameter is a reference; or
// In C++98/03 mode, give an extension warning on any extra parentheses.
// See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
bool ExtraParens = false;
while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
if (!Invalid && !ExtraParens) {
S.Diag(Arg->getBeginLoc(),
S.getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_template_arg_extra_parens
: diag::ext_template_arg_extra_parens)
<< Arg->getSourceRange();
ExtraParens = true;
}
Arg = Parens->getSubExpr();
}
while (SubstNonTypeTemplateParmExpr *subst =
dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
Arg = subst->getReplacement()->IgnoreImpCasts();
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
if (UnOp->getOpcode() == UO_AddrOf) {
Arg = UnOp->getSubExpr();
AddressTaken = true;
AddrOpLoc = UnOp->getOperatorLoc();
}
}
while (SubstNonTypeTemplateParmExpr *subst =
dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
Arg = subst->getReplacement()->IgnoreImpCasts();
}
DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg);
ValueDecl *Entity = DRE ? DRE->getDecl() : nullptr;
// If our parameter has pointer type, check for a null template value.
if (ParamType->isPointerType() || ParamType->isNullPtrType()) {
switch (isNullPointerValueTemplateArgument(S, Param, ParamType, ArgIn,
Entity)) {
case NPV_NullPointer:
S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
Converted = TemplateArgument(S.Context.getCanonicalType(ParamType),
/*isNullPtr=*/true);
return false;
case NPV_Error:
return true;
case NPV_NotNullPointer:
break;
}
}
// Stop checking the precise nature of the argument if it is value dependent,
// it should be checked when instantiated.
if (Arg->isValueDependent()) {
Converted = TemplateArgument(ArgIn);
return false;
}
if (isa<CXXUuidofExpr>(Arg)) {
if (CheckTemplateArgumentIsCompatibleWithParameter(S, Param, ParamType,
ArgIn, Arg, ArgType))
return true;
Converted = TemplateArgument(ArgIn);
return false;
}
if (!DRE) {
S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref)
<< Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
// Cannot refer to non-static data members
if (isa<FieldDecl>(Entity) || isa<IndirectFieldDecl>(Entity)) {
S.Diag(Arg->getBeginLoc(), diag::err_template_arg_field)
<< Entity << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
// Cannot refer to non-static member functions
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Entity)) {
if (!Method->isStatic()) {
S.Diag(Arg->getBeginLoc(), diag::err_template_arg_method)
<< Method << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
}
FunctionDecl *Func = dyn_cast<FunctionDecl>(Entity);
VarDecl *Var = dyn_cast<VarDecl>(Entity);
// A non-type template argument must refer to an object or function.
if (!Func && !Var) {
// We found something, but we don't know specifically what it is.
S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_object_or_func)
<< Arg->getSourceRange();
S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here);
return true;
}
// Address / reference template args must have external linkage in C++98.
if (Entity->getFormalLinkage() == InternalLinkage) {
S.Diag(Arg->getBeginLoc(),
S.getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_template_arg_object_internal
: diag::ext_template_arg_object_internal)
<< !Func << Entity << Arg->getSourceRange();
S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
<< !Func;
} else if (!Entity->hasLinkage()) {
S.Diag(Arg->getBeginLoc(), diag::err_template_arg_object_no_linkage)
<< !Func << Entity << Arg->getSourceRange();
S.Diag(Entity->getLocation(), diag::note_template_arg_internal_object)
<< !Func;
return true;
}
if (Func) {
// If the template parameter has pointer type, the function decays.
if (ParamType->isPointerType() && !AddressTaken)
ArgType = S.Context.getPointerType(Func->getType());
else if (AddressTaken && ParamType->isReferenceType()) {
// If we originally had an address-of operator, but the
// parameter has reference type, complain and (if things look
// like they will work) drop the address-of operator.
if (!S.Context.hasSameUnqualifiedType(Func->getType(),
ParamType.getNonReferenceType())) {
S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
<< ParamType;
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
<< ParamType
<< FixItHint::CreateRemoval(AddrOpLoc);
S.Diag(Param->getLocation(), diag::note_template_param_here);
ArgType = Func->getType();
}
} else {
// A value of reference type is not an object.
if (Var->getType()->isReferenceType()) {
S.Diag(Arg->getBeginLoc(), diag::err_template_arg_reference_var)
<< Var->getType() << Arg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
// A template argument must have static storage duration.
if (Var->getTLSKind()) {
S.Diag(Arg->getBeginLoc(), diag::err_template_arg_thread_local)
<< Arg->getSourceRange();
S.Diag(Var->getLocation(), diag::note_template_arg_refers_here);
return true;
}
// If the template parameter has pointer type, we must have taken
// the address of this object.
if (ParamType->isReferenceType()) {
if (AddressTaken) {
// If we originally had an address-of operator, but the
// parameter has reference type, complain and (if things look
// like they will work) drop the address-of operator.
if (!S.Context.hasSameUnqualifiedType(Var->getType(),
ParamType.getNonReferenceType())) {
S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
<< ParamType;
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer)
<< ParamType
<< FixItHint::CreateRemoval(AddrOpLoc);
S.Diag(Param->getLocation(), diag::note_template_param_here);
ArgType = Var->getType();
}
} else if (!AddressTaken && ParamType->isPointerType()) {
if (Var->getType()->isArrayType()) {
// Array-to-pointer decay.
ArgType = S.Context.getArrayDecayedType(Var->getType());
} else {
// If the template parameter has pointer type but the address of
// this object was not taken, complain and (possibly) recover by
// taking the address of the entity.
ArgType = S.Context.getPointerType(Var->getType());
if (!S.Context.hasSameUnqualifiedType(ArgType, ParamType)) {
S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of)
<< ParamType;
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_address_of)
<< ParamType << FixItHint::CreateInsertion(Arg->getBeginLoc(), "&");
S.Diag(Param->getLocation(), diag::note_template_param_here);
}
}
}
if (CheckTemplateArgumentIsCompatibleWithParameter(S, Param, ParamType, ArgIn,
Arg, ArgType))
return true;
// Create the template argument.
Converted =
TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()), ParamType);
S.MarkAnyDeclReferenced(Arg->getBeginLoc(), Entity, false);
return false;
}
/// Checks whether the given template argument is a pointer to
/// member constant according to C++ [temp.arg.nontype]p1.
static bool CheckTemplateArgumentPointerToMember(Sema &S,
NonTypeTemplateParmDecl *Param,
QualType ParamType,
Expr *&ResultArg,
TemplateArgument &Converted) {
bool Invalid = false;
Expr *Arg = ResultArg;
bool ObjCLifetimeConversion;
// C++ [temp.arg.nontype]p1:
//
// A template-argument for a non-type, non-template
// template-parameter shall be one of: [...]
//
// -- a pointer to member expressed as described in 5.3.1.
DeclRefExpr *DRE = nullptr;
// In C++98/03 mode, give an extension warning on any extra parentheses.
// See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773
bool ExtraParens = false;
while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) {
if (!Invalid && !ExtraParens) {
S.Diag(Arg->getBeginLoc(),
S.getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_template_arg_extra_parens
: diag::ext_template_arg_extra_parens)
<< Arg->getSourceRange();
ExtraParens = true;
}
Arg = Parens->getSubExpr();
}
while (SubstNonTypeTemplateParmExpr *subst =
dyn_cast<SubstNonTypeTemplateParmExpr>(Arg))
Arg = subst->getReplacement()->IgnoreImpCasts();
// A pointer-to-member constant written &Class::member.
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
if (UnOp->getOpcode() == UO_AddrOf) {
DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
if (DRE && !DRE->getQualifier())
DRE = nullptr;
}
}
// A constant of pointer-to-member type.
else if ((DRE = dyn_cast<DeclRefExpr>(Arg))) {
ValueDecl *VD = DRE->getDecl();
if (VD->getType()->isMemberPointerType()) {
if (isa<NonTypeTemplateParmDecl>(VD)) {
if (Arg->isTypeDependent() || Arg->isValueDependent()) {
Converted = TemplateArgument(Arg);
} else {
VD = cast<ValueDecl>(VD->getCanonicalDecl());
Converted = TemplateArgument(VD, ParamType);
}
return Invalid;
}
}
DRE = nullptr;
}
ValueDecl *Entity = DRE ? DRE->getDecl() : nullptr;
// Check for a null pointer value.
switch (isNullPointerValueTemplateArgument(S, Param, ParamType, ResultArg,
Entity)) {
case NPV_Error:
return true;
case NPV_NullPointer:
S.Diag(ResultArg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
Converted = TemplateArgument(S.Context.getCanonicalType(ParamType),
/*isNullPtr*/true);
return false;
case NPV_NotNullPointer:
break;
}
if (S.IsQualificationConversion(ResultArg->getType(),
ParamType.getNonReferenceType(), false,
ObjCLifetimeConversion)) {
ResultArg = S.ImpCastExprToType(ResultArg, ParamType, CK_NoOp,
ResultArg->getValueKind())
.get();
} else if (!S.Context.hasSameUnqualifiedType(
ResultArg->getType(), ParamType.getNonReferenceType())) {
// We can't perform this conversion.
S.Diag(ResultArg->getBeginLoc(), diag::err_template_arg_not_convertible)
<< ResultArg->getType() << ParamType << ResultArg->getSourceRange();
S.Diag(Param->getLocation(), diag::note_template_param_here);
return true;
}
if (!DRE)
return S.Diag(Arg->getBeginLoc(),
diag::err_template_arg_not_pointer_to_member_form)
<< Arg->getSourceRange();
if (isa<FieldDecl>(DRE->getDecl()) ||
isa<IndirectFieldDecl>(DRE->getDecl()) ||
isa<CXXMethodDecl>(DRE->getDecl())) {
assert((isa<FieldDecl>(DRE->getDecl()) ||
isa<IndirectFieldDecl>(DRE->getDecl()) ||
!cast<CXXMethodDecl>(DRE->getDecl())->isStatic()) &&
"Only non-static member pointers can make it here");
// Okay: this is the address of a non-static member, and therefore
// a member pointer constant.
if (Arg->isTypeDependent() || Arg->isValueDependent()) {
Converted = TemplateArgument(Arg);
} else {
ValueDecl *D = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
Converted = TemplateArgument(D, ParamType);
}
return Invalid;
}
// We found something else, but we don't know specifically what it is.
S.Diag(Arg->getBeginLoc(), diag::err_template_arg_not_pointer_to_member_form)
<< Arg->getSourceRange();
S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here);
return true;
}
/// Check a template argument against its corresponding
/// non-type template parameter.
///
/// This routine implements the semantics of C++ [temp.arg.nontype].
/// If an error occurred, it returns ExprError(); otherwise, it
/// returns the converted template argument. \p ParamType is the
/// type of the non-type template parameter after it has been instantiated.
ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
QualType ParamType, Expr *Arg,
TemplateArgument &Converted,
CheckTemplateArgumentKind CTAK) {
SourceLocation StartLoc = Arg->getBeginLoc();
// If the parameter type somehow involves auto, deduce the type now.
if (getLangOpts().CPlusPlus17 && ParamType->isUndeducedType()) {
// During template argument deduction, we allow 'decltype(auto)' to
// match an arbitrary dependent argument.
// FIXME: The language rules don't say what happens in this case.
// FIXME: We get an opaque dependent type out of decltype(auto) if the
// expression is merely instantiation-dependent; is this enough?
if (CTAK == CTAK_Deduced && Arg->isTypeDependent()) {
auto *AT = dyn_cast<AutoType>(ParamType);
if (AT && AT->isDecltypeAuto()) {
Converted = TemplateArgument(Arg);
return Arg;
}
}
// When checking a deduced template argument, deduce from its type even if
// the type is dependent, in order to check the types of non-type template
// arguments line up properly in partial ordering.
Optional<unsigned> Depth;
if (CTAK != CTAK_Specified)
Depth = Param->getDepth() + 1;
if (DeduceAutoType(
Context.getTrivialTypeSourceInfo(ParamType, Param->getLocation()),
Arg, ParamType, Depth) == DAR_Failed) {
Diag(Arg->getExprLoc(),
diag::err_non_type_template_parm_type_deduction_failure)
<< Param->getDeclName() << Param->getType() << Arg->getType()
<< Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
return ExprError();
}
// CheckNonTypeTemplateParameterType will produce a diagnostic if there's
// an error. The error message normally references the parameter
// declaration, but here we'll pass the argument location because that's
// where the parameter type is deduced.
ParamType = CheckNonTypeTemplateParameterType(ParamType, Arg->getExprLoc());
if (ParamType.isNull()) {
Diag(Param->getLocation(), diag::note_template_param_here);
return ExprError();
}
}
// We should have already dropped all cv-qualifiers by now.
assert(!ParamType.hasQualifiers() &&
"non-type template parameter type cannot be qualified");
if (CTAK == CTAK_Deduced &&
!Context.hasSameType(ParamType.getNonLValueExprType(Context),
Arg->getType())) {
// FIXME: If either type is dependent, we skip the check. This isn't
// correct, since during deduction we're supposed to have replaced each
// template parameter with some unique (non-dependent) placeholder.
// FIXME: If the argument type contains 'auto', we carry on and fail the
// type check in order to force specific types to be more specialized than
// 'auto'. It's not clear how partial ordering with 'auto' is supposed to
// work.
if ((ParamType->isDependentType() || Arg->isTypeDependent()) &&
!Arg->getType()->getContainedAutoType()) {
Converted = TemplateArgument(Arg);
return Arg;
}
// FIXME: This attempts to implement C++ [temp.deduct.type]p17. Per DR1770,
// we should actually be checking the type of the template argument in P,
// not the type of the template argument deduced from A, against the
// template parameter type.
Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
<< Arg->getType()
<< ParamType.getUnqualifiedType();
Diag(Param->getLocation(), diag::note_template_param_here);
return ExprError();
}
// If either the parameter has a dependent type or the argument is
// type-dependent, there's nothing we can check now.
if (ParamType->isDependentType() || Arg->isTypeDependent()) {
// FIXME: Produce a cloned, canonical expression?
Converted = TemplateArgument(Arg);
return Arg;
}
// The initialization of the parameter from the argument is
// a constant-evaluated context.
EnterExpressionEvaluationContext ConstantEvaluated(
*this, Sema::ExpressionEvaluationContext::ConstantEvaluated);
if (getLangOpts().CPlusPlus17) {
// C++17 [temp.arg.nontype]p1:
// A template-argument for a non-type template parameter shall be
// a converted constant expression of the type of the template-parameter.
APValue Value;
ExprResult ArgResult = CheckConvertedConstantExpression(
Arg, ParamType, Value, CCEK_TemplateArg);
if (ArgResult.isInvalid())
return ExprError();
// For a value-dependent argument, CheckConvertedConstantExpression is
// permitted (and expected) to be unable to determine a value.
if (ArgResult.get()->isValueDependent()) {
Converted = TemplateArgument(ArgResult.get());
return ArgResult;
}
QualType CanonParamType = Context.getCanonicalType(ParamType);
// Convert the APValue to a TemplateArgument.
switch (Value.getKind()) {
case APValue::Uninitialized:
assert(ParamType->isNullPtrType());
Converted = TemplateArgument(CanonParamType, /*isNullPtr*/true);
break;
case APValue::Int:
assert(ParamType->isIntegralOrEnumerationType());
Converted = TemplateArgument(Context, Value.getInt(), CanonParamType);
break;
case APValue::MemberPointer: {
assert(ParamType->isMemberPointerType());
// FIXME: We need TemplateArgument representation and mangling for these.
if (!Value.getMemberPointerPath().empty()) {
Diag(Arg->getBeginLoc(),
diag::err_template_arg_member_ptr_base_derived_not_supported)
<< Value.getMemberPointerDecl() << ParamType
<< Arg->getSourceRange();
return ExprError();
}
auto *VD = const_cast<ValueDecl*>(Value.getMemberPointerDecl());
Converted = VD ? TemplateArgument(VD, CanonParamType)
: TemplateArgument(CanonParamType, /*isNullPtr*/true);
break;
}
case APValue::LValue: {
// For a non-type template-parameter of pointer or reference type,
// the value of the constant expression shall not refer to
assert(ParamType->isPointerType() || ParamType->isReferenceType() ||
ParamType->isNullPtrType());
// -- a temporary object
// -- a string literal
// -- the result of a typeid expression, or
// -- a predefined __func__ variable
if (auto *E = Value.getLValueBase().dyn_cast<const Expr*>()) {
if (isa<CXXUuidofExpr>(E)) {
- Converted = TemplateArgument(ArgResult.get());
+ Converted = TemplateArgument(ArgResult.get()->IgnoreImpCasts());
break;
}
Diag(Arg->getBeginLoc(), diag::err_template_arg_not_decl_ref)
<< Arg->getSourceRange();
return ExprError();
}
auto *VD = const_cast<ValueDecl *>(
Value.getLValueBase().dyn_cast<const ValueDecl *>());
// -- a subobject
if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 &&
VD && VD->getType()->isArrayType() &&
Value.getLValuePath()[0].ArrayIndex == 0 &&
!Value.isLValueOnePastTheEnd() && ParamType->isPointerType()) {
// Per defect report (no number yet):
// ... other than a pointer to the first element of a complete array
// object.
} else if (!Value.hasLValuePath() || Value.getLValuePath().size() ||
Value.isLValueOnePastTheEnd()) {
Diag(StartLoc, diag::err_non_type_template_arg_subobject)
<< Value.getAsString(Context, ParamType);
return ExprError();
}
assert((VD || !ParamType->isReferenceType()) &&
"null reference should not be a constant expression");
assert((!VD || !ParamType->isNullPtrType()) &&
"non-null value of type nullptr_t?");
Converted = VD ? TemplateArgument(VD, CanonParamType)
: TemplateArgument(CanonParamType, /*isNullPtr*/true);
break;
}
case APValue::AddrLabelDiff:
return Diag(StartLoc, diag::err_non_type_template_arg_addr_label_diff);
case APValue::Float:
case APValue::ComplexInt:
case APValue::ComplexFloat:
case APValue::Vector:
case APValue::Array:
case APValue::Struct:
case APValue::Union:
llvm_unreachable("invalid kind for template argument");
}
return ArgResult.get();
}
// C++ [temp.arg.nontype]p5:
// The following conversions are performed on each expression used
// as a non-type template-argument. If a non-type
// template-argument cannot be converted to the type of the
// corresponding template-parameter then the program is
// ill-formed.
if (ParamType->isIntegralOrEnumerationType()) {
// C++11:
// -- for a non-type template-parameter of integral or
// enumeration type, conversions permitted in a converted
// constant expression are applied.
//
// C++98:
// -- for a non-type template-parameter of integral or
// enumeration type, integral promotions (4.5) and integral
// conversions (4.7) are applied.
if (getLangOpts().CPlusPlus11) {
// C++ [temp.arg.nontype]p1:
// A template-argument for a non-type, non-template template-parameter
// shall be one of:
//
// -- for a non-type template-parameter of integral or enumeration
// type, a converted constant expression of the type of the
// template-parameter; or
llvm::APSInt Value;
ExprResult ArgResult =
CheckConvertedConstantExpression(Arg, ParamType, Value,
CCEK_TemplateArg);
if (ArgResult.isInvalid())
return ExprError();
// We can't check arbitrary value-dependent arguments.
if (ArgResult.get()->isValueDependent()) {
Converted = TemplateArgument(ArgResult.get());
return ArgResult;
}
// Widen the argument value to sizeof(parameter type). This is almost
// always a no-op, except when the parameter type is bool. In
// that case, this may extend the argument from 1 bit to 8 bits.
QualType IntegerType = ParamType;
if (const EnumType *Enum = IntegerType->getAs<EnumType>())
IntegerType = Enum->getDecl()->getIntegerType();
Value = Value.extOrTrunc(Context.getTypeSize(IntegerType));
Converted = TemplateArgument(Context, Value,
Context.getCanonicalType(ParamType));
return ArgResult;
}
ExprResult ArgResult = DefaultLvalueConversion(Arg);
if (ArgResult.isInvalid())
return ExprError();
Arg = ArgResult.get();
QualType ArgType = Arg->getType();
// C++ [temp.arg.nontype]p1:
// A template-argument for a non-type, non-template
// template-parameter shall be one of:
//
// -- an integral constant-expression of integral or enumeration
// type; or
// -- the name of a non-type template-parameter; or
llvm::APSInt Value;
if (!ArgType->isIntegralOrEnumerationType()) {
Diag(Arg->getBeginLoc(), diag::err_template_arg_not_integral_or_enumeral)
<< ArgType << Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
return ExprError();
} else if (!Arg->isValueDependent()) {
class TmplArgICEDiagnoser : public VerifyICEDiagnoser {
QualType T;
public:
TmplArgICEDiagnoser(QualType T) : T(T) { }
void diagnoseNotICE(Sema &S, SourceLocation Loc,
SourceRange SR) override {
S.Diag(Loc, diag::err_template_arg_not_ice) << T << SR;
}
} Diagnoser(ArgType);
Arg = VerifyIntegerConstantExpression(Arg, &Value, Diagnoser,
false).get();
if (!Arg)
return ExprError();
}
// From here on out, all we care about is the unqualified form
// of the argument type.
ArgType = ArgType.getUnqualifiedType();
// Try to convert the argument to the parameter's type.
if (Context.hasSameType(ParamType, ArgType)) {
// Okay: no conversion necessary
} else if (ParamType->isBooleanType()) {
// This is an integral-to-boolean conversion.
Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean).get();
} else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||
!ParamType->isEnumeralType()) {
// This is an integral promotion or conversion.
Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralCast).get();
} else {
// We can't perform this conversion.
Diag(Arg->getBeginLoc(), diag::err_template_arg_not_convertible)
<< Arg->getType() << ParamType << Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
return ExprError();
}
// Add the value of this argument to the list of converted
// arguments. We use the bitwidth and signedness of the template
// parameter.
if (Arg->isValueDependent()) {
// The argument is value-dependent. Create a new
// TemplateArgument with the converted expression.
Converted = TemplateArgument(Arg);
return Arg;
}
QualType IntegerType = Context.getCanonicalType(ParamType);
if (const EnumType *Enum = IntegerType->getAs<EnumType>())
IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType());
if (ParamType->isBooleanType()) {
// Value must be zero or one.
Value = Value != 0;
unsigned AllowedBits = Context.getTypeSize(IntegerType);
if (Value.getBitWidth() != AllowedBits)
Value = Value.extOrTrunc(AllowedBits);
Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType());
} else {
llvm::APSInt OldValue = Value;
// Coerce the template argument's value to the value it will have
// based on the template parameter's type.
unsigned AllowedBits = Context.getTypeSize(IntegerType);
if (Value.getBitWidth() != AllowedBits)
Value = Value.extOrTrunc(AllowedBits);
Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType());
// Complain if an unsigned parameter received a negative value.
if (IntegerType->isUnsignedIntegerOrEnumerationType()
&& (OldValue.isSigned() && OldValue.isNegative())) {
Diag(Arg->getBeginLoc(), diag::warn_template_arg_negative)
<< OldValue.toString(10) << Value.toString(10) << Param->getType()
<< Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
}
// Complain if we overflowed the template parameter's type.
unsigned RequiredBits;
if (IntegerType->isUnsignedIntegerOrEnumerationType())
RequiredBits = OldValue.getActiveBits();
else if (OldValue.isUnsigned())
RequiredBits = OldValue.getActiveBits() + 1;
else
RequiredBits = OldValue.getMinSignedBits();
if (RequiredBits > AllowedBits) {
Diag(Arg->getBeginLoc(), diag::warn_template_arg_too_large)
<< OldValue.toString(10) << Value.toString(10) << Param->getType()
<< Arg->getSourceRange();
Diag(Param->getLocation(), diag::note_template_param_here);
}
}
Converted = TemplateArgument(Context, Value,
ParamType->isEnumeralType()
? Context.getCanonicalType(ParamType)
: IntegerType);
return Arg;
}
QualType ArgType = Arg->getType();
DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction
// Handle pointer-to-function, reference-to-function, and
// pointer-to-member-function all in (roughly) the same way.
if (// -- For a non-type template-parameter of type pointer to
// function, only the function-to-pointer conversion (4.3) is
// applied. If the template-argument represents a set of
// overloaded functions (or a pointer to such), the matching
// function is selected from the set (13.4).
(ParamType->isPointerType() &&
ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType()) ||
// -- For a non-type template-parameter of type reference to
// function, no conversions apply. If the template-argument
// represents a set of overloaded functions, the matching
// function is selected from the set (13.4).
(ParamType->isReferenceType() &&
ParamType->getAs<ReferenceType>()->getPointeeType()->isFunctionType()) ||
// -- For a non-type template-parameter of type pointer to
// member function, no conversions apply. If the
// template-argument represents a set of overloaded member
// functions, the matching member function is selected from
// the set (13.4).
(ParamType->isMemberPointerType() &&
ParamType->getAs<MemberPointerType>()->getPointeeType()
->isFunctionType())) {
if (Arg->getType() == Context.OverloadTy) {
if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType,
true,
FoundResult)) {
if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc()))
return ExprError();
Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
ArgType = Arg->getType();
} else
return ExprError();
}
if (!ParamType->isMemberPointerType()) {
if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
ParamType,
Arg, Converted))
return ExprError();
return Arg;
}
if (CheckTemplateArgumentPointerToMember(*this, Param, ParamType, Arg,
Converted))
return ExprError();
return Arg;
}
if (ParamType->isPointerType()) {
// -- for a non-type template-parameter of type pointer to
// object, qualification conversions (4.4) and the
// array-to-pointer conversion (4.2) are applied.
// C++0x also allows a value of std::nullptr_t.
assert(ParamType->getPointeeType()->isIncompleteOrObjectType() &&
"Only object pointers allowed here");
if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
ParamType,
Arg, Converted))
return ExprError();
return Arg;
}
if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) {
// -- For a non-type template-parameter of type reference to
// object, no conversions apply. The type referred to by the
// reference may be more cv-qualified than the (otherwise
// identical) type of the template-argument. The
// template-parameter is bound directly to the
// template-argument, which must be an lvalue.
assert(ParamRefType->getPointeeType()->isIncompleteOrObjectType() &&
"Only object references allowed here");
if (Arg->getType() == Context.OverloadTy) {
if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg,
ParamRefType->getPointeeType(),
true,
FoundResult)) {
if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc()))
return ExprError();
Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
ArgType = Arg->getType();
} else
return ExprError();
}
if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
ParamType,
Arg, Converted))
return ExprError();
return Arg;
}
// Deal with parameters of type std::nullptr_t.
if (ParamType->isNullPtrType()) {
if (Arg->isTypeDependent() || Arg->isValueDependent()) {
Converted = TemplateArgument(Arg);
return Arg;
}
switch (isNullPointerValueTemplateArgument(*this, Param, ParamType, Arg)) {
case NPV_NotNullPointer:
Diag(Arg->getExprLoc(), diag::err_template_arg_not_convertible)
<< Arg->getType() << ParamType;
Diag(Param->getLocation(), diag::note_template_param_here);
return ExprError();
case NPV_Error:
return ExprError();
case NPV_NullPointer:
Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
Converted = TemplateArgument(Context.getCanonicalType(ParamType),
/*isNullPtr*/true);
return Arg;
}
}
// -- For a non-type template-parameter of type pointer to data
// member, qualification conversions (4.4) are applied.
assert(ParamType->isMemberPointerType() && "Only pointers to members remain");
if (CheckTemplateArgumentPointerToMember(*this, Param, ParamType, Arg,
Converted))
return ExprError();
return Arg;
}
static void DiagnoseTemplateParameterListArityMismatch(
Sema &S, TemplateParameterList *New, TemplateParameterList *Old,
Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc);
/// Check a template argument against its corresponding
/// template template parameter.
///
/// This routine implements the semantics of C++ [temp.arg.template].
/// It returns true if an error occurred, and false otherwise.
bool Sema::CheckTemplateTemplateArgument(TemplateParameterList *Params,
TemplateArgumentLoc &Arg) {
TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern();
TemplateDecl *Template = Name.getAsTemplateDecl();
if (!Template) {
// Any dependent template name is fine.
assert(Name.isDependent() && "Non-dependent template isn't a declaration?");
return false;
}
if (Template->isInvalidDecl())
return true;
// C++0x [temp.arg.template]p1:
// A template-argument for a template template-parameter shall be
// the name of a class template or an alias template, expressed as an
// id-expression. When the template-argument names a class template, only
// primary class templates are considered when matching the
// template template argument with the corresponding parameter;
// partial specializations are not considered even if their
// parameter lists match that of the template template parameter.
//
// Note that we also allow template template parameters here, which
// will happen when we are dealing with, e.g., class template
// partial specializations.
if (!isa<ClassTemplateDecl>(Template) &&
!isa<TemplateTemplateParmDecl>(Template) &&
!isa<TypeAliasTemplateDecl>(Template) &&
!isa<BuiltinTemplateDecl>(Template)) {
assert(isa<FunctionTemplateDecl>(Template) &&
"Only function templates are possible here");
Diag(Arg.getLocation(), diag::err_template_arg_not_valid_template);
Diag(Template->getLocation(), diag::note_template_arg_refers_here_func)
<< Template;
}
// C++1z [temp.arg.template]p3: (DR 150)
// A template-argument matches a template template-parameter P when P
// is at least as specialized as the template-argument A.
if (getLangOpts().RelaxedTemplateTemplateArgs) {
// Quick check for the common case:
// If P contains a parameter pack, then A [...] matches P if each of A's
// template parameters matches the corresponding template parameter in
// the template-parameter-list of P.
if (TemplateParameterListsAreEqual(
Template->getTemplateParameters(), Params, false,
TPL_TemplateTemplateArgumentMatch, Arg.getLocation()))
return false;
if (isTemplateTemplateParameterAtLeastAsSpecializedAs(Params, Template,
Arg.getLocation()))
return false;
// FIXME: Produce better diagnostics for deduction failures.
}
return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
Params,
true,
TPL_TemplateTemplateArgumentMatch,
Arg.getLocation());
}
/// Given a non-type template argument that refers to a
/// declaration and the type of its corresponding non-type template
/// parameter, produce an expression that properly refers to that
/// declaration.
ExprResult
Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
QualType ParamType,
SourceLocation Loc) {
// C++ [temp.param]p8:
//
// A non-type template-parameter of type "array of T" or
// "function returning T" is adjusted to be of type "pointer to
// T" or "pointer to function returning T", respectively.
if (ParamType->isArrayType())
ParamType = Context.getArrayDecayedType(ParamType);
else if (ParamType->isFunctionType())
ParamType = Context.getPointerType(ParamType);
// For a NULL non-type template argument, return nullptr casted to the
// parameter's type.
if (Arg.getKind() == TemplateArgument::NullPtr) {
return ImpCastExprToType(
new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc),
ParamType,
ParamType->getAs<MemberPointerType>()
? CK_NullToMemberPointer
: CK_NullToPointer);
}
assert(Arg.getKind() == TemplateArgument::Declaration &&
"Only declaration template arguments permitted here");
ValueDecl *VD = Arg.getAsDecl();
if (VD->getDeclContext()->isRecord() &&
(isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD) ||
isa<IndirectFieldDecl>(VD))) {
// If the value is a class member, we might have a pointer-to-member.
// Determine whether the non-type template template parameter is of
// pointer-to-member type. If so, we need to build an appropriate
// expression for a pointer-to-member, since a "normal" DeclRefExpr
// would refer to the member itself.
if (ParamType->isMemberPointerType()) {
QualType ClassType
= Context.getTypeDeclType(cast<RecordDecl>(VD->getDeclContext()));
NestedNameSpecifier *Qualifier
= NestedNameSpecifier::Create(Context, nullptr, false,
ClassType.getTypePtr());
CXXScopeSpec SS;
SS.MakeTrivial(Context, Qualifier, Loc);
// The actual value-ness of this is unimportant, but for
// internal consistency's sake, references to instance methods
// are r-values.
ExprValueKind VK = VK_LValue;
if (isa<CXXMethodDecl>(VD) && cast<CXXMethodDecl>(VD)->isInstance())
VK = VK_RValue;
ExprResult RefExpr = BuildDeclRefExpr(VD,
VD->getType().getNonReferenceType(),
VK,
Loc,
&SS);
if (RefExpr.isInvalid())
return ExprError();
RefExpr = CreateBuiltinUnaryOp(Loc, UO_AddrOf, RefExpr.get());
// We might need to perform a trailing qualification conversion, since
// the element type on the parameter could be more qualified than the
// element type in the expression we constructed.
bool ObjCLifetimeConversion;
if (IsQualificationConversion(((Expr*) RefExpr.get())->getType(),
ParamType.getUnqualifiedType(), false,
ObjCLifetimeConversion))
RefExpr = ImpCastExprToType(RefExpr.get(), ParamType.getUnqualifiedType(), CK_NoOp);
assert(!RefExpr.isInvalid() &&
Context.hasSameType(((Expr*) RefExpr.get())->getType(),
ParamType.getUnqualifiedType()));
return RefExpr;
}
}
QualType T = VD->getType().getNonReferenceType();
if (ParamType->isPointerType()) {
// When the non-type template parameter is a pointer, take the
// address of the declaration.
ExprResult RefExpr = BuildDeclRefExpr(VD, T, VK_LValue, Loc);
if (RefExpr.isInvalid())
return ExprError();
if (!Context.hasSameUnqualifiedType(ParamType->getPointeeType(), T) &&
(T->isFunctionType() || T->isArrayType())) {
// Decay functions and arrays unless we're forming a pointer to array.
RefExpr = DefaultFunctionArrayConversion(RefExpr.get());
if (RefExpr.isInvalid())
return ExprError();
return RefExpr;
}
// Take the address of everything else
return CreateBuiltinUnaryOp(Loc, UO_AddrOf, RefExpr.get());
}
ExprValueKind VK = VK_RValue;
// If the non-type template parameter has reference type, qualify the
// resulting declaration reference with the extra qualifiers on the
// type that the reference refers to.
if (const ReferenceType *TargetRef = ParamType->getAs<ReferenceType>()) {
VK = VK_LValue;
T = Context.getQualifiedType(T,
TargetRef->getPointeeType().getQualifiers());
} else if (isa<FunctionDecl>(VD)) {
// References to functions are always lvalues.
VK = VK_LValue;
}
return BuildDeclRefExpr(VD, T, VK, Loc);
}
/// Construct a new expression that refers to the given
/// integral template argument with the given source-location
/// information.
///
/// This routine takes care of the mapping from an integral template
/// argument (which may have any integral type) to the appropriate
/// literal value.
ExprResult
Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
SourceLocation Loc) {
assert(Arg.getKind() == TemplateArgument::Integral &&
"Operation is only valid for integral template arguments");
QualType OrigT = Arg.getIntegralType();
// If this is an enum type that we're instantiating, we need to use an integer
// type the same size as the enumerator. We don't want to build an
// IntegerLiteral with enum type. The integer type of an enum type can be of
// any integral type with C++11 enum classes, make sure we create the right
// type of literal for it.
QualType T = OrigT;
if (const EnumType *ET = OrigT->getAs<EnumType>())
T = ET->getDecl()->getIntegerType();
Expr *E;
if (T->isAnyCharacterType()) {
CharacterLiteral::CharacterKind Kind;
if (T->isWideCharType())
Kind = CharacterLiteral::Wide;
else if (T->isChar8Type() && getLangOpts().Char8)
Kind = CharacterLiteral::UTF8;
else if (T->isChar16Type())
Kind = CharacterLiteral::UTF16;
else if (T->isChar32Type())
Kind = CharacterLiteral::UTF32;
else
Kind = CharacterLiteral::Ascii;
E = new (Context) CharacterLiteral(Arg.getAsIntegral().getZExtValue(),
Kind, T, Loc);
} else if (T->isBooleanType()) {
E = new (Context) CXXBoolLiteralExpr(Arg.getAsIntegral().getBoolValue(),
T, Loc);
} else if (T->isNullPtrType()) {
E = new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc);
} else {
E = IntegerLiteral::Create(Context, Arg.getAsIntegral(), T, Loc);
}
if (OrigT->isEnumeralType()) {
// FIXME: This is a hack. We need a better way to handle substituted
// non-type template parameters.
E = CStyleCastExpr::Create(Context, OrigT, VK_RValue, CK_IntegralCast, E,
nullptr,
Context.getTrivialTypeSourceInfo(OrigT, Loc),
Loc, Loc);
}
return E;
}
/// Match two template parameters within template parameter lists.
static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
bool Complain,
Sema::TemplateParameterListEqualKind Kind,
SourceLocation TemplateArgLoc) {
// Check the actual kind (type, non-type, template).
if (Old->getKind() != New->getKind()) {
if (Complain) {
unsigned NextDiag = diag::err_template_param_different_kind;
if (TemplateArgLoc.isValid()) {
S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
NextDiag = diag::note_template_param_different_kind;
}
S.Diag(New->getLocation(), NextDiag)
<< (Kind != Sema::TPL_TemplateMatch);
S.Diag(Old->getLocation(), diag::note_template_prev_declaration)
<< (Kind != Sema::TPL_TemplateMatch);
}
return false;
}
// Check that both are parameter packs or neither are parameter packs.
// However, if we are matching a template template argument to a
// template template parameter, the template template parameter can have
// a parameter pack where the template template argument does not.
if (Old->isTemplateParameterPack() != New->isTemplateParameterPack() &&
!(Kind == Sema::TPL_TemplateTemplateArgumentMatch &&
Old->isTemplateParameterPack())) {
if (Complain) {
unsigned NextDiag = diag::err_template_parameter_pack_non_pack;
if (TemplateArgLoc.isValid()) {
S.Diag(TemplateArgLoc,
diag::err_template_arg_template_params_mismatch);
NextDiag = diag::note_template_parameter_pack_non_pack;
}
unsigned ParamKind = isa<TemplateTypeParmDecl>(New)? 0
: isa<NonTypeTemplateParmDecl>(New)? 1
: 2;
S.Diag(New->getLocation(), NextDiag)
<< ParamKind << New->isParameterPack();
S.Diag(Old->getLocation(), diag::note_template_parameter_pack_here)
<< ParamKind << Old->isParameterPack();
}
return false;
}
// For non-type template parameters, check the type of the parameter.
if (NonTypeTemplateParmDecl *OldNTTP
= dyn_cast<NonTypeTemplateParmDecl>(Old)) {
NonTypeTemplateParmDecl *NewNTTP = cast<NonTypeTemplateParmDecl>(New);
// If we are matching a template template argument to a template
// template parameter and one of the non-type template parameter types
// is dependent, then we must wait until template instantiation time
// to actually compare the arguments.
if (Kind == Sema::TPL_TemplateTemplateArgumentMatch &&
(OldNTTP->getType()->isDependentType() ||
NewNTTP->getType()->isDependentType()))
return true;
if (!S.Context.hasSameType(OldNTTP->getType(), NewNTTP->getType())) {
if (Complain) {
unsigned NextDiag = diag::err_template_nontype_parm_different_type;
if (TemplateArgLoc.isValid()) {
S.Diag(TemplateArgLoc,
diag::err_template_arg_template_params_mismatch);
NextDiag = diag::note_template_nontype_parm_different_type;
}
S.Diag(NewNTTP->getLocation(), NextDiag)
<< NewNTTP->getType()
<< (Kind != Sema::TPL_TemplateMatch);
S.Diag(OldNTTP->getLocation(),
diag::note_template_nontype_parm_prev_declaration)
<< OldNTTP->getType();
}
return false;
}
return true;
}
// For template template parameters, check the template parameter types.
// The template parameter lists of template template
// parameters must agree.
if (TemplateTemplateParmDecl *OldTTP
= dyn_cast<TemplateTemplateParmDecl>(Old)) {
TemplateTemplateParmDecl *NewTTP = cast<TemplateTemplateParmDecl>(New);
return S.TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(),
OldTTP->getTemplateParameters(),
Complain,
(Kind == Sema::TPL_TemplateMatch
? Sema::TPL_TemplateTemplateParmMatch
: Kind),
TemplateArgLoc);
}
return true;
}
/// Diagnose a known arity mismatch when comparing template argument
/// lists.
static
void DiagnoseTemplateParameterListArityMismatch(Sema &S,
TemplateParameterList *New,
TemplateParameterList *Old,
Sema::TemplateParameterListEqualKind Kind,
SourceLocation TemplateArgLoc) {
unsigned NextDiag = diag::err_template_param_list_different_arity;
if (TemplateArgLoc.isValid()) {
S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
NextDiag = diag::note_template_param_list_different_arity;
}
S.Diag(New->getTemplateLoc(), NextDiag)
<< (New->size() > Old->size())
<< (Kind != Sema::TPL_TemplateMatch)
<< SourceRange(New->getTemplateLoc(), New->getRAngleLoc());
S.Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration)
<< (Kind != Sema::TPL_TemplateMatch)
<< SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
}
/// Determine whether the given template parameter lists are
/// equivalent.
///
/// \param New The new template parameter list, typically written in the
/// source code as part of a new template declaration.
///
/// \param Old The old template parameter list, typically found via
/// name lookup of the template declared with this template parameter
/// list.
///
/// \param Complain If true, this routine will produce a diagnostic if
/// the template parameter lists are not equivalent.
///
/// \param Kind describes how we are to match the template parameter lists.
///
/// \param TemplateArgLoc If this source location is valid, then we
/// are actually checking the template parameter list of a template
/// argument (New) against the template parameter list of its
/// corresponding template template parameter (Old). We produce
/// slightly different diagnostics in this scenario.
///
/// \returns True if the template parameter lists are equal, false
/// otherwise.
bool
Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
TemplateParameterList *Old,
bool Complain,
TemplateParameterListEqualKind Kind,
SourceLocation TemplateArgLoc) {
if (Old->size() != New->size() && Kind != TPL_TemplateTemplateArgumentMatch) {
if (Complain)
DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
TemplateArgLoc);
return false;
}
// C++0x [temp.arg.template]p3:
// A template-argument matches a template template-parameter (call it P)
// when each of the template parameters in the template-parameter-list of
// the template-argument's corresponding class template or alias template
// (call it A) matches the corresponding template parameter in the
// template-parameter-list of P. [...]
TemplateParameterList::iterator NewParm = New->begin();
TemplateParameterList::iterator NewParmEnd = New->end();
for (TemplateParameterList::iterator OldParm = Old->begin(),
OldParmEnd = Old->end();
OldParm != OldParmEnd; ++OldParm) {
if (Kind != TPL_TemplateTemplateArgumentMatch ||
!(*OldParm)->isTemplateParameterPack()) {
if (NewParm == NewParmEnd) {
if (Complain)
DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
TemplateArgLoc);
return false;
}
if (!MatchTemplateParameterKind(*this, *NewParm, *OldParm, Complain,
Kind, TemplateArgLoc))
return false;
++NewParm;
continue;
}
// C++0x [temp.arg.template]p3:
// [...] When P's template- parameter-list contains a template parameter
// pack (14.5.3), the template parameter pack will match zero or more
// template parameters or template parameter packs in the
// template-parameter-list of A with the same type and form as the
// template parameter pack in P (ignoring whether those template
// parameters are template parameter packs).
for (; NewParm != NewParmEnd; ++NewParm) {
if (!MatchTemplateParameterKind(*this, *NewParm, *OldParm, Complain,
Kind, TemplateArgLoc))
return false;
}
}
// Make sure we exhausted all of the arguments.
if (NewParm != NewParmEnd) {
if (Complain)
DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind,
TemplateArgLoc);
return false;
}
return true;
}
/// Check whether a template can be declared within this scope.
///
/// If the template declaration is valid in this scope, returns
/// false. Otherwise, issues a diagnostic and returns true.
bool
Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
if (!S)
return false;
// Find the nearest enclosing declaration scope.
while ((S->getFlags() & Scope::DeclScope) == 0 ||
(S->getFlags() & Scope::TemplateParamScope) != 0)
S = S->getParent();
// C++ [temp]p4:
// A template [...] shall not have C linkage.
DeclContext *Ctx = S->getEntity();
if (Ctx && Ctx->isExternCContext()) {
Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage)
<< TemplateParams->getSourceRange();
if (const LinkageSpecDecl *LSD = Ctx->getExternCContext())
Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here);
return true;
}
Ctx = Ctx->getRedeclContext();
// C++ [temp]p2:
// A template-declaration can appear only as a namespace scope or
// class scope declaration.
if (Ctx) {
if (Ctx->isFileContext())
return false;
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Ctx)) {
// C++ [temp.mem]p2:
// A local class shall not have member templates.
if (RD->isLocalClass())
return Diag(TemplateParams->getTemplateLoc(),
diag::err_template_inside_local_class)
<< TemplateParams->getSourceRange();
else
return false;
}
}
return Diag(TemplateParams->getTemplateLoc(),
diag::err_template_outside_namespace_or_class_scope)
<< TemplateParams->getSourceRange();
}
/// Determine what kind of template specialization the given declaration
/// is.
static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D) {
if (!D)
return TSK_Undeclared;
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D))
return Record->getTemplateSpecializationKind();
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
return Function->getTemplateSpecializationKind();
if (VarDecl *Var = dyn_cast<VarDecl>(D))
return Var->getTemplateSpecializationKind();
return TSK_Undeclared;
}
/// Check whether a specialization is well-formed in the current
/// context.
///
/// This routine determines whether a template specialization can be declared
/// in the current context (C++ [temp.expl.spec]p2).
///
/// \param S the semantic analysis object for which this check is being
/// performed.
///
/// \param Specialized the entity being specialized or instantiated, which
/// may be a kind of template (class template, function template, etc.) or
/// a member of a class template (member function, static data member,
/// member class).
///
/// \param PrevDecl the previous declaration of this entity, if any.
///
/// \param Loc the location of the explicit specialization or instantiation of
/// this entity.
///
/// \param IsPartialSpecialization whether this is a partial specialization of
/// a class template.
///
/// \returns true if there was an error that we cannot recover from, false
/// otherwise.
static bool CheckTemplateSpecializationScope(Sema &S,
NamedDecl *Specialized,
NamedDecl *PrevDecl,
SourceLocation Loc,
bool IsPartialSpecialization) {
// Keep these "kind" numbers in sync with the %select statements in the
// various diagnostics emitted by this routine.
int EntityKind = 0;
if (isa<ClassTemplateDecl>(Specialized))
EntityKind = IsPartialSpecialization? 1 : 0;
else if (isa<VarTemplateDecl>(Specialized))
EntityKind = IsPartialSpecialization ? 3 : 2;
else if (isa<FunctionTemplateDecl>(Specialized))
EntityKind = 4;
else if (isa<CXXMethodDecl>(Specialized))
EntityKind = 5;
else if (isa<VarDecl>(Specialized))
EntityKind = 6;
else if (isa<RecordDecl>(Specialized))
EntityKind = 7;
else if (isa<EnumDecl>(Specialized) && S.getLangOpts().CPlusPlus11)
EntityKind = 8;
else {
S.Diag(Loc, diag::err_template_spec_unknown_kind)
<< S.getLangOpts().CPlusPlus11;
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
return true;
}
// C++ [temp.expl.spec]p2:
// An explicit specialization may be declared in any scope in which
// the corresponding primary template may be defined.
if (S.CurContext->getRedeclContext()->isFunctionOrMethod()) {
S.Diag(Loc, diag::err_template_spec_decl_function_scope)
<< Specialized;
return true;
}
// C++ [temp.class.spec]p6:
// A class template partial specialization may be declared in any
// scope in which the primary template may be defined.
DeclContext *SpecializedContext =
Specialized->getDeclContext()->getRedeclContext();
DeclContext *DC = S.CurContext->getRedeclContext();
// Make sure that this redeclaration (or definition) occurs in the same
// scope or an enclosing namespace.
if (!(DC->isFileContext() ? DC->Encloses(SpecializedContext)
: DC->Equals(SpecializedContext))) {
if (isa<TranslationUnitDecl>(SpecializedContext))
S.Diag(Loc, diag::err_template_spec_redecl_global_scope)
<< EntityKind << Specialized;
else {
auto *ND = cast<NamedDecl>(SpecializedContext);
int Diag = diag::err_template_spec_redecl_out_of_scope;
if (S.getLangOpts().MicrosoftExt && !DC->isRecord())
Diag = diag::ext_ms_template_spec_redecl_out_of_scope;
S.Diag(Loc, Diag) << EntityKind << Specialized
<< ND << isa<CXXRecordDecl>(ND);
}
S.Diag(Specialized->getLocation(), diag::note_specialized_entity);
// Don't allow specializing in the wrong class during error recovery.
// Otherwise, things can go horribly wrong.
if (DC->isRecord())
return true;
}
return false;
}
static SourceRange findTemplateParameterInType(unsigned Depth, Expr *E) {
if (!E->isTypeDependent())
return SourceLocation();
DependencyChecker Checker(Depth, /*IgnoreNonTypeDependent*/true);
Checker.TraverseStmt(E);
if (Checker.MatchLoc.isInvalid())
return E->getSourceRange();
return Checker.MatchLoc;
}
static SourceRange findTemplateParameter(unsigned Depth, TypeLoc TL) {
if (!TL.getType()->isDependentType())
return SourceLocation();
DependencyChecker Checker(Depth, /*IgnoreNonTypeDependent*/true);
Checker.TraverseTypeLoc(TL);
if (Checker.MatchLoc.isInvalid())
return TL.getSourceRange();
return Checker.MatchLoc;
}
/// Subroutine of Sema::CheckTemplatePartialSpecializationArgs
/// that checks non-type template partial specialization arguments.
static bool CheckNonTypeTemplatePartialSpecializationArgs(
Sema &S, SourceLocation TemplateNameLoc, NonTypeTemplateParmDecl *Param,
const TemplateArgument *Args, unsigned NumArgs, bool IsDefaultArgument) {
for (unsigned I = 0; I != NumArgs; ++I) {
if (Args[I].getKind() == TemplateArgument::Pack) {
if (CheckNonTypeTemplatePartialSpecializationArgs(
S, TemplateNameLoc, Param, Args[I].pack_begin(),
Args[I].pack_size(), IsDefaultArgument))
return true;
continue;
}
if (Args[I].getKind() != TemplateArgument::Expression)
continue;
Expr *ArgExpr = Args[I].getAsExpr();
// We can have a pack expansion of any of the bullets below.
if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(ArgExpr))
ArgExpr = Expansion->getPattern();
// Strip off any implicit casts we added as part of type checking.
while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgExpr))
ArgExpr = ICE->getSubExpr();
// C++ [temp.class.spec]p8:
// A non-type argument is non-specialized if it is the name of a
// non-type parameter. All other non-type arguments are
// specialized.
//
// Below, we check the two conditions that only apply to
// specialized non-type arguments, so skip any non-specialized
// arguments.
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr))
if (isa<NonTypeTemplateParmDecl>(DRE->getDecl()))
continue;
// C++ [temp.class.spec]p9:
// Within the argument list of a class template partial
// specialization, the following restrictions apply:
// -- A partially specialized non-type argument expression
// shall not involve a template parameter of the partial
// specialization except when the argument expression is a
// simple identifier.
// -- The type of a template parameter corresponding to a
// specialized non-type argument shall not be dependent on a
// parameter of the specialization.
// DR1315 removes the first bullet, leaving an incoherent set of rules.
// We implement a compromise between the original rules and DR1315:
// -- A specialized non-type template argument shall not be
// type-dependent and the corresponding template parameter
// shall have a non-dependent type.
SourceRange ParamUseRange =
findTemplateParameterInType(Param->getDepth(), ArgExpr);
if (ParamUseRange.isValid()) {
if (IsDefaultArgument) {
S.Diag(TemplateNameLoc,
diag::err_dependent_non_type_arg_in_partial_spec);
S.Diag(ParamUseRange.getBegin(),
diag::note_dependent_non_type_default_arg_in_partial_spec)
<< ParamUseRange;
} else {
S.Diag(ParamUseRange.getBegin(),
diag::err_dependent_non_type_arg_in_partial_spec)
<< ParamUseRange;
}
return true;
}
ParamUseRange = findTemplateParameter(
Param->getDepth(), Param->getTypeSourceInfo()->getTypeLoc());
if (ParamUseRange.isValid()) {
S.Diag(IsDefaultArgument ? TemplateNameLoc : ArgExpr->getBeginLoc(),
diag::err_dependent_typed_non_type_arg_in_partial_spec)
<< Param->getType();
S.Diag(Param->getLocation(), diag::note_template_param_here)
<< (IsDefaultArgument ? ParamUseRange : SourceRange())
<< ParamUseRange;
return true;
}
}
return false;
}
/// Check the non-type template arguments of a class template
/// partial specialization according to C++ [temp.class.spec]p9.
///
/// \param TemplateNameLoc the location of the template name.
/// \param PrimaryTemplate the template parameters of the primary class
/// template.
/// \param NumExplicit the number of explicitly-specified template arguments.
/// \param TemplateArgs the template arguments of the class template
/// partial specialization.
///
/// \returns \c true if there was an error, \c false otherwise.
bool Sema::CheckTemplatePartialSpecializationArgs(
SourceLocation TemplateNameLoc, TemplateDecl *PrimaryTemplate,
unsigned NumExplicit, ArrayRef<TemplateArgument> TemplateArgs) {
// We have to be conservative when checking a template in a dependent
// context.
if (PrimaryTemplate->getDeclContext()->isDependentContext())
return false;
TemplateParameterList *TemplateParams =
PrimaryTemplate->getTemplateParameters();
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
NonTypeTemplateParmDecl *Param
= dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I));
if (!Param)
continue;
if (CheckNonTypeTemplatePartialSpecializationArgs(*this, TemplateNameLoc,
Param, &TemplateArgs[I],
1, I >= NumExplicit))
return true;
}
return false;
}
DeclResult Sema::ActOnClassTemplateSpecialization(
Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId,
const ParsedAttributesView &Attr,
MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) {
assert(TUK != TUK_Reference && "References are not specializations");
CXXScopeSpec &SS = TemplateId.SS;
// NOTE: KWLoc is the location of the tag keyword. This will instead
// store the location of the outermost template keyword in the declaration.
SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0
? TemplateParameterLists[0]->getTemplateLoc() : KWLoc;
SourceLocation TemplateNameLoc = TemplateId.TemplateNameLoc;
SourceLocation LAngleLoc = TemplateId.LAngleLoc;
SourceLocation RAngleLoc = TemplateId.RAngleLoc;
// Find the class template we're specializing
TemplateName Name = TemplateId.Template.get();
ClassTemplateDecl *ClassTemplate
= dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl());
if (!ClassTemplate) {
Diag(TemplateNameLoc, diag::err_not_class_template_specialization)
<< (Name.getAsTemplateDecl() &&
isa<TemplateTemplateParmDecl>(Name.getAsTemplateDecl()));
return true;
}
bool isMemberSpecialization = false;
bool isPartialSpecialization = false;
// Check the validity of the template headers that introduce this
// template.
// FIXME: We probably shouldn't complain about these headers for
// friend declarations.
bool Invalid = false;
TemplateParameterList *TemplateParams =
MatchTemplateParametersToScopeSpecifier(
KWLoc, TemplateNameLoc, SS, &TemplateId,
TemplateParameterLists, TUK == TUK_Friend, isMemberSpecialization,
Invalid);
if (Invalid)
return true;
if (TemplateParams && TemplateParams->size() > 0) {
isPartialSpecialization = true;
if (TUK == TUK_Friend) {
Diag(KWLoc, diag::err_partial_specialization_friend)
<< SourceRange(LAngleLoc, RAngleLoc);
return true;
}
// C++ [temp.class.spec]p10:
// The template parameter list of a specialization shall not
// contain default template argument values.
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
Decl *Param = TemplateParams->getParam(I);
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
if (TTP->hasDefaultArgument()) {
Diag(TTP->getDefaultArgumentLoc(),
diag::err_default_arg_in_partial_spec);
TTP->removeDefaultArgument();
}
} else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(Param)) {
if (Expr *DefArg = NTTP->getDefaultArgument()) {
Diag(NTTP->getDefaultArgumentLoc(),
diag::err_default_arg_in_partial_spec)
<< DefArg->getSourceRange();
NTTP->removeDefaultArgument();
}
} else {
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param);
if (TTP->hasDefaultArgument()) {
Diag(TTP->getDefaultArgument().getLocation(),
diag::err_default_arg_in_partial_spec)
<< TTP->getDefaultArgument().getSourceRange();
TTP->removeDefaultArgument();
}
}
}
} else if (TemplateParams) {
if (TUK == TUK_Friend)
Diag(KWLoc, diag::err_template_spec_friend)
<< FixItHint::CreateRemoval(
SourceRange(TemplateParams->getTemplateLoc(),
TemplateParams->getRAngleLoc()))
<< SourceRange(LAngleLoc, RAngleLoc);
} else {
assert(TUK == TUK_Friend && "should have a 'template<>' for this decl");
}
// Check that the specialization uses the same tag kind as the
// original template.
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
assert(Kind != TTK_Enum && "Invalid enum tag in class template spec!");
if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
Kind, TUK == TUK_Definition, KWLoc,
ClassTemplate->getIdentifier())) {
Diag(KWLoc, diag::err_use_with_wrong_tag)
<< ClassTemplate
<< FixItHint::CreateReplacement(KWLoc,
ClassTemplate->getTemplatedDecl()->getKindName());
Diag(ClassTemplate->getTemplatedDecl()->getLocation(),
diag::note_previous_use);
Kind = ClassTemplate->getTemplatedDecl()->getTagKind();
}
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs =
makeTemplateArgumentListInfo(*this, TemplateId);
// Check for unexpanded parameter packs in any of the template arguments.
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
if (DiagnoseUnexpandedParameterPack(TemplateArgs[I],
UPPC_PartialSpecialization))
return true;
// Check that the template argument list is well-formed for this
// template.
SmallVector<TemplateArgument, 4> Converted;
if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc,
TemplateArgs, false, Converted))
return true;
// Find the class template (partial) specialization declaration that
// corresponds to these arguments.
if (isPartialSpecialization) {
if (CheckTemplatePartialSpecializationArgs(TemplateNameLoc, ClassTemplate,
TemplateArgs.size(), Converted))
return true;
// FIXME: Move this to CheckTemplatePartialSpecializationArgs so we
// also do it during instantiation.
bool InstantiationDependent;
if (!Name.isDependent() &&
!TemplateSpecializationType::anyDependentTemplateArguments(
TemplateArgs.arguments(), InstantiationDependent)) {
Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
<< ClassTemplate->getDeclName();
isPartialSpecialization = false;
}
}
void *InsertPos = nullptr;
ClassTemplateSpecializationDecl *PrevDecl = nullptr;
if (isPartialSpecialization)
// FIXME: Template parameter list matters, too
PrevDecl = ClassTemplate->findPartialSpecialization(Converted, InsertPos);
else
PrevDecl = ClassTemplate->findSpecialization(Converted, InsertPos);
ClassTemplateSpecializationDecl *Specialization = nullptr;
// Check whether we can declare a class template specialization in
// the current scope.
if (TUK != TUK_Friend &&
CheckTemplateSpecializationScope(*this, ClassTemplate, PrevDecl,
TemplateNameLoc,
isPartialSpecialization))
return true;
// The canonical type
QualType CanonType;
if (isPartialSpecialization) {
// Build the canonical type that describes the converted template
// arguments of the class template partial specialization.
TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
CanonType = Context.getTemplateSpecializationType(CanonTemplate,
Converted);
if (Context.hasSameType(CanonType,
ClassTemplate->getInjectedClassNameSpecialization())) {
// C++ [temp.class.spec]p9b3:
//
// -- The argument list of the specialization shall not be identical
// to the implicit argument list of the primary template.
//
// This rule has since been removed, because it's redundant given DR1495,
// but we keep it because it produces better diagnostics and recovery.
Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
<< /*class template*/0 << (TUK == TUK_Definition)
<< FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS,
ClassTemplate->getIdentifier(),
TemplateNameLoc,
Attr,
TemplateParams,
AS_none, /*ModulePrivateLoc=*/SourceLocation(),
/*FriendLoc*/SourceLocation(),
TemplateParameterLists.size() - 1,
TemplateParameterLists.data());
}
// Create a new class template partial specialization declaration node.
ClassTemplatePartialSpecializationDecl *PrevPartial
= cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl);
ClassTemplatePartialSpecializationDecl *Partial
= ClassTemplatePartialSpecializationDecl::Create(Context, Kind,
ClassTemplate->getDeclContext(),
KWLoc, TemplateNameLoc,
TemplateParams,
ClassTemplate,
Converted,
TemplateArgs,
CanonType,
PrevPartial);
SetNestedNameSpecifier(*this, Partial, SS);
if (TemplateParameterLists.size() > 1 && SS.isSet()) {
Partial->setTemplateParameterListsInfo(
Context, TemplateParameterLists.drop_back(1));
}
if (!PrevPartial)
ClassTemplate->AddPartialSpecialization(Partial, InsertPos);
Specialization = Partial;
// If we are providing an explicit specialization of a member class
// template specialization, make a note of that.
if (PrevPartial && PrevPartial->getInstantiatedFromMember())
PrevPartial->setMemberSpecialization();
CheckTemplatePartialSpecialization(Partial);
} else {
// Create a new class template specialization declaration node for
// this explicit specialization or friend declaration.
Specialization
= ClassTemplateSpecializationDecl::Create(Context, Kind,
ClassTemplate->getDeclContext(),
KWLoc, TemplateNameLoc,
ClassTemplate,
Converted,
PrevDecl);
SetNestedNameSpecifier(*this, Specialization, SS);
if (TemplateParameterLists.size() > 0) {
Specialization->setTemplateParameterListsInfo(Context,
TemplateParameterLists);
}
if (!PrevDecl)
ClassTemplate->AddSpecialization(Specialization, InsertPos);
if (CurContext->isDependentContext()) {
TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);
CanonType = Context.getTemplateSpecializationType(
CanonTemplate, Converted);
} else {
CanonType = Context.getTypeDeclType(Specialization);
}
}
// C++ [temp.expl.spec]p6:
// If a template, a member template or the member of a class template is
// explicitly specialized then that specialization shall be declared
// before the first use of that specialization that would cause an implicit
// instantiation to take place, in every translation unit in which such a
// use occurs; no diagnostic is required.
if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) {
bool Okay = false;
for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
// Is there any previous explicit specialization declaration?
if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
Okay = true;
break;
}
}
if (!Okay) {
SourceRange Range(TemplateNameLoc, RAngleLoc);
Diag(TemplateNameLoc, diag::err_specialization_after_instantiation)
<< Context.getTypeDeclType(Specialization) << Range;
Diag(PrevDecl->getPointOfInstantiation(),
diag::note_instantiation_required_here)
<< (PrevDecl->getTemplateSpecializationKind()
!= TSK_ImplicitInstantiation);
return true;
}
}
// If this is not a friend, note that this is an explicit specialization.
if (TUK != TUK_Friend)
Specialization->setSpecializationKind(TSK_ExplicitSpecialization);
// Check that this isn't a redefinition of this specialization.
if (TUK == TUK_Definition) {
RecordDecl *Def = Specialization->getDefinition();
NamedDecl *Hidden = nullptr;
if (Def && SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
SkipBody->ShouldSkip = true;
SkipBody->Previous = Def;
makeMergedDefinitionVisible(Hidden);
} else if (Def) {
SourceRange Range(TemplateNameLoc, RAngleLoc);
Diag(TemplateNameLoc, diag::err_redefinition) << Specialization << Range;
Diag(Def->getLocation(), diag::note_previous_definition);
Specialization->setInvalidDecl();
return true;
}
}
ProcessDeclAttributeList(S, Specialization, Attr);
// Add alignment attributes if necessary; these attributes are checked when
// the ASTContext lays out the structure.
if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) {
AddAlignmentAttributesForRecord(Specialization);
AddMsStructLayoutForRecord(Specialization);
}
if (ModulePrivateLoc.isValid())
Diag(Specialization->getLocation(), diag::err_module_private_specialization)
<< (isPartialSpecialization? 1 : 0)
<< FixItHint::CreateRemoval(ModulePrivateLoc);
// Build the fully-sugared type for this class template
// specialization as the user wrote in the specialization
// itself. This means that we'll pretty-print the type retrieved
// from the specialization's declaration the way that the user
// actually wrote the specialization, rather than formatting the
// name based on the "canonical" representation used to store the
// template arguments in the specialization.
TypeSourceInfo *WrittenTy
= Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc,
TemplateArgs, CanonType);
if (TUK != TUK_Friend) {
Specialization->setTypeAsWritten(WrittenTy);
Specialization->setTemplateKeywordLoc(TemplateKWLoc);
}
// C++ [temp.expl.spec]p9:
// A template explicit specialization is in the scope of the
// namespace in which the template was defined.
//
// We actually implement this paragraph where we set the semantic
// context (in the creation of the ClassTemplateSpecializationDecl),
// but we also maintain the lexical context where the actual
// definition occurs.
Specialization->setLexicalDeclContext(CurContext);
// We may be starting the definition of this specialization.
if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip))
Specialization->startDefinition();
if (TUK == TUK_Friend) {
FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
TemplateNameLoc,
WrittenTy,
/*FIXME:*/KWLoc);
Friend->setAccess(AS_public);
CurContext->addDecl(Friend);
} else {
// Add the specialization into its lexical context, so that it can
// be seen when iterating through the list of declarations in that
// context. However, specializations are not found by name lookup.
CurContext->addDecl(Specialization);
}
if (SkipBody && SkipBody->ShouldSkip)
return SkipBody->Previous;
return Specialization;
}
Decl *Sema::ActOnTemplateDeclarator(Scope *S,
MultiTemplateParamsArg TemplateParameterLists,
Declarator &D) {
Decl *NewDecl = HandleDeclarator(S, D, TemplateParameterLists);
ActOnDocumentableDecl(NewDecl);
return NewDecl;
}
/// Strips various properties off an implicit instantiation
/// that has just been explicitly specialized.
static void StripImplicitInstantiation(NamedDecl *D) {
D->dropAttr<DLLImportAttr>();
D->dropAttr<DLLExportAttr>();
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
FD->setInlineSpecified(false);
}
/// Compute the diagnostic location for an explicit instantiation
// declaration or definition.
static SourceLocation DiagLocForExplicitInstantiation(
NamedDecl* D, SourceLocation PointOfInstantiation) {
// Explicit instantiations following a specialization have no effect and
// hence no PointOfInstantiation. In that case, walk decl backwards
// until a valid name loc is found.
SourceLocation PrevDiagLoc = PointOfInstantiation;
for (Decl *Prev = D; Prev && !PrevDiagLoc.isValid();
Prev = Prev->getPreviousDecl()) {
PrevDiagLoc = Prev->getLocation();
}
assert(PrevDiagLoc.isValid() &&
"Explicit instantiation without point of instantiation?");
return PrevDiagLoc;
}
/// Diagnose cases where we have an explicit template specialization
/// before/after an explicit template instantiation, producing diagnostics
/// for those cases where they are required and determining whether the
/// new specialization/instantiation will have any effect.
///
/// \param NewLoc the location of the new explicit specialization or
/// instantiation.
///
/// \param NewTSK the kind of the new explicit specialization or instantiation.
///
/// \param PrevDecl the previous declaration of the entity.
///
/// \param PrevTSK the kind of the old explicit specialization or instantiatin.
///
/// \param PrevPointOfInstantiation if valid, indicates where the previus
/// declaration was instantiated (either implicitly or explicitly).
///
/// \param HasNoEffect will be set to true to indicate that the new
/// specialization or instantiation has no effect and should be ignored.
///
/// \returns true if there was an error that should prevent the introduction of
/// the new declaration into the AST, false otherwise.
bool
Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
TemplateSpecializationKind NewTSK,
NamedDecl *PrevDecl,
TemplateSpecializationKind PrevTSK,
SourceLocation PrevPointOfInstantiation,
bool &HasNoEffect) {
HasNoEffect = false;
switch (NewTSK) {
case TSK_Undeclared:
case TSK_ImplicitInstantiation:
assert(
(PrevTSK == TSK_Undeclared || PrevTSK == TSK_ImplicitInstantiation) &&
"previous declaration must be implicit!");
return false;
case TSK_ExplicitSpecialization:
switch (PrevTSK) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
// Okay, we're just specializing something that is either already
// explicitly specialized or has merely been mentioned without any
// instantiation.
return false;
case TSK_ImplicitInstantiation:
if (PrevPointOfInstantiation.isInvalid()) {
// The declaration itself has not actually been instantiated, so it is
// still okay to specialize it.
StripImplicitInstantiation(PrevDecl);
return false;
}
// Fall through
LLVM_FALLTHROUGH;
case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
assert((PrevTSK == TSK_ImplicitInstantiation ||
PrevPointOfInstantiation.isValid()) &&
"Explicit instantiation without point of instantiation?");
// C++ [temp.expl.spec]p6:
// If a template, a member template or the member of a class template
// is explicitly specialized then that specialization shall be declared
// before the first use of that specialization that would cause an
// implicit instantiation to take place, in every translation unit in
// which such a use occurs; no diagnostic is required.
for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
// Is there any previous explicit specialization declaration?
if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization)
return false;
}
Diag(NewLoc, diag::err_specialization_after_instantiation)
<< PrevDecl;
Diag(PrevPointOfInstantiation, diag::note_instantiation_required_here)
<< (PrevTSK != TSK_ImplicitInstantiation);
return true;
}
llvm_unreachable("The switch over PrevTSK must be exhaustive.");
case TSK_ExplicitInstantiationDeclaration:
switch (PrevTSK) {
case TSK_ExplicitInstantiationDeclaration:
// This explicit instantiation declaration is redundant (that's okay).
HasNoEffect = true;
return false;
case TSK_Undeclared:
case TSK_ImplicitInstantiation:
// We're explicitly instantiating something that may have already been
// implicitly instantiated; that's fine.
return false;
case TSK_ExplicitSpecialization:
// C++0x [temp.explicit]p4:
// For a given set of template parameters, if an explicit instantiation
// of a template appears after a declaration of an explicit
// specialization for that template, the explicit instantiation has no
// effect.
HasNoEffect = true;
return false;
case TSK_ExplicitInstantiationDefinition:
// C++0x [temp.explicit]p10:
// If an entity is the subject of both an explicit instantiation
// declaration and an explicit instantiation definition in the same
// translation unit, the definition shall follow the declaration.
Diag(NewLoc,
diag::err_explicit_instantiation_declaration_after_definition);
// Explicit instantiations following a specialization have no effect and
// hence no PrevPointOfInstantiation. In that case, walk decl backwards
// until a valid name loc is found.
Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation),
diag::note_explicit_instantiation_definition_here);
HasNoEffect = true;
return false;
}
llvm_unreachable("Unexpected TemplateSpecializationKind!");
case TSK_ExplicitInstantiationDefinition:
switch (PrevTSK) {
case TSK_Undeclared:
case TSK_ImplicitInstantiation:
// We're explicitly instantiating something that may have already been
// implicitly instantiated; that's fine.
return false;
case TSK_ExplicitSpecialization:
// C++ DR 259, C++0x [temp.explicit]p4:
// For a given set of template parameters, if an explicit
// instantiation of a template appears after a declaration of
// an explicit specialization for that template, the explicit
// instantiation has no effect.
Diag(NewLoc, diag::warn_explicit_instantiation_after_specialization)
<< PrevDecl;
Diag(PrevDecl->getLocation(),
diag::note_previous_template_specialization);
HasNoEffect = true;
return false;
case TSK_ExplicitInstantiationDeclaration:
// We're explicitly instantiating a definition for something for which we
// were previously asked to suppress instantiations. That's fine.
// C++0x [temp.explicit]p4:
// For a given set of template parameters, if an explicit instantiation
// of a template appears after a declaration of an explicit
// specialization for that template, the explicit instantiation has no
// effect.
for (Decl *Prev = PrevDecl; Prev; Prev = Prev->getPreviousDecl()) {
// Is there any previous explicit specialization declaration?
if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
HasNoEffect = true;
break;
}
}
return false;
case TSK_ExplicitInstantiationDefinition:
// C++0x [temp.spec]p5:
// For a given template and a given set of template-arguments,
// - an explicit instantiation definition shall appear at most once
// in a program,
// MSVCCompat: MSVC silently ignores duplicate explicit instantiations.
Diag(NewLoc, (getLangOpts().MSVCCompat)
? diag::ext_explicit_instantiation_duplicate
: diag::err_explicit_instantiation_duplicate)
<< PrevDecl;
Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation),
diag::note_previous_explicit_instantiation);
HasNoEffect = true;
return false;
}
}
llvm_unreachable("Missing specialization/instantiation case?");
}
/// Perform semantic analysis for the given dependent function
/// template specialization.
///
/// The only possible way to get a dependent function template specialization
/// is with a friend declaration, like so:
///
/// \code
/// template \<class T> void foo(T);
/// template \<class T> class A {
/// friend void foo<>(T);
/// };
/// \endcode
///
/// There really isn't any useful analysis we can do here, so we
/// just store the information.
bool
Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
const TemplateArgumentListInfo &ExplicitTemplateArgs,
LookupResult &Previous) {
// Remove anything from Previous that isn't a function template in
// the correct context.
DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
LookupResult::Filter F = Previous.makeFilter();
enum DiscardReason { NotAFunctionTemplate, NotAMemberOfEnclosing };
SmallVector<std::pair<DiscardReason, Decl *>, 8> DiscardedCandidates;
while (F.hasNext()) {
NamedDecl *D = F.next()->getUnderlyingDecl();
if (!isa<FunctionTemplateDecl>(D)) {
F.erase();
DiscardedCandidates.push_back(std::make_pair(NotAFunctionTemplate, D));
continue;
}
if (!FDLookupContext->InEnclosingNamespaceSetOf(
D->getDeclContext()->getRedeclContext())) {
F.erase();
DiscardedCandidates.push_back(std::make_pair(NotAMemberOfEnclosing, D));
continue;
}
}
F.done();
if (Previous.empty()) {
Diag(FD->getLocation(),
diag::err_dependent_function_template_spec_no_match);
for (auto &P : DiscardedCandidates)
Diag(P.second->getLocation(),
diag::note_dependent_function_template_spec_discard_reason)
<< P.first;
return true;
}
FD->setDependentTemplateSpecialization(Context, Previous.asUnresolvedSet(),
ExplicitTemplateArgs);
return false;
}
/// Perform semantic analysis for the given function template
/// specialization.
///
/// This routine performs all of the semantic analysis required for an
/// explicit function template specialization. On successful completion,
/// the function declaration \p FD will become a function template
/// specialization.
///
/// \param FD the function declaration, which will be updated to become a
/// function template specialization.
///
/// \param ExplicitTemplateArgs the explicitly-provided template arguments,
/// if any. Note that this may be valid info even when 0 arguments are
/// explicitly provided as in, e.g., \c void sort<>(char*, char*);
/// as it anyway contains info on the angle brackets locations.
///
/// \param Previous the set of declarations that may be specialized by
/// this function specialization.
///
/// \param QualifiedFriend whether this is a lookup for a qualified friend
/// declaration with no explicit template argument list that might be
/// befriending a function template specialization.
bool Sema::CheckFunctionTemplateSpecialization(
FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
LookupResult &Previous, bool QualifiedFriend) {
// The set of function template specializations that could match this
// explicit function template specialization.
UnresolvedSet<8> Candidates;
TemplateSpecCandidateSet FailedCandidates(FD->getLocation(),
/*ForTakingAddress=*/false);
llvm::SmallDenseMap<FunctionDecl *, TemplateArgumentListInfo, 8>
ConvertedTemplateArgs;
DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I) {
NamedDecl *Ovl = (*I)->getUnderlyingDecl();
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Ovl)) {
// Only consider templates found within the same semantic lookup scope as
// FD.
if (!FDLookupContext->InEnclosingNamespaceSetOf(
Ovl->getDeclContext()->getRedeclContext()))
continue;
// When matching a constexpr member function template specialization
// against the primary template, we don't yet know whether the
// specialization has an implicit 'const' (because we don't know whether
// it will be a static member function until we know which template it
// specializes), so adjust it now assuming it specializes this template.
QualType FT = FD->getType();
if (FD->isConstexpr()) {
CXXMethodDecl *OldMD =
dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
if (OldMD && OldMD->isConst()) {
const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
EPI.TypeQuals.addConst();
FT = Context.getFunctionType(FPT->getReturnType(),
FPT->getParamTypes(), EPI);
}
}
TemplateArgumentListInfo Args;
if (ExplicitTemplateArgs)
Args = *ExplicitTemplateArgs;
// C++ [temp.expl.spec]p11:
// A trailing template-argument can be left unspecified in the
// template-id naming an explicit function template specialization
// provided it can be deduced from the function argument type.
// Perform template argument deduction to determine whether we may be
// specializing this template.
// FIXME: It is somewhat wasteful to build
TemplateDeductionInfo Info(FailedCandidates.getLocation());
FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult TDK = DeduceTemplateArguments(
cast<FunctionTemplateDecl>(FunTmpl->getFirstDecl()),
ExplicitTemplateArgs ? &Args : nullptr, FT, Specialization,
Info)) {
// Template argument deduction failed; record why it failed, so
// that we can provide nifty diagnostics.
FailedCandidates.addCandidate().set(
I.getPair(), FunTmpl->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, TDK, Info));
(void)TDK;
continue;
}
// Target attributes are part of the cuda function signature, so
// the deduced template's cuda target must match that of the
// specialization. Given that C++ template deduction does not
// take target attributes into account, we reject candidates
// here that have a different target.
if (LangOpts.CUDA &&
IdentifyCUDATarget(Specialization,
/* IgnoreImplicitHDAttributes = */ true) !=
IdentifyCUDATarget(FD, /* IgnoreImplicitHDAttributes = */ true)) {
FailedCandidates.addCandidate().set(
I.getPair(), FunTmpl->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info));
continue;
}
// Record this candidate.
if (ExplicitTemplateArgs)
ConvertedTemplateArgs[Specialization] = std::move(Args);
Candidates.addDecl(Specialization, I.getAccess());
}
}
// For a qualified friend declaration (with no explicit marker to indicate
// that a template specialization was intended), note all (template and
// non-template) candidates.
if (QualifiedFriend && Candidates.empty()) {
Diag(FD->getLocation(), diag::err_qualified_friend_no_match)
<< FD->getDeclName() << FDLookupContext;
// FIXME: We should form a single candidate list and diagnose all
// candidates at once, to get proper sorting and limiting.
for (auto *OldND : Previous) {
if (auto *OldFD = dyn_cast<FunctionDecl>(OldND->getUnderlyingDecl()))
NoteOverloadCandidate(OldND, OldFD, FD->getType(), false);
}
FailedCandidates.NoteCandidates(*this, FD->getLocation());
return true;
}
// Find the most specialized function template.
UnresolvedSetIterator Result = getMostSpecialized(
Candidates.begin(), Candidates.end(), FailedCandidates, FD->getLocation(),
PDiag(diag::err_function_template_spec_no_match) << FD->getDeclName(),
PDiag(diag::err_function_template_spec_ambiguous)
<< FD->getDeclName() << (ExplicitTemplateArgs != nullptr),
PDiag(diag::note_function_template_spec_matched));
if (Result == Candidates.end())
return true;
// Ignore access information; it doesn't figure into redeclaration checking.
FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
FunctionTemplateSpecializationInfo *SpecInfo
= Specialization->getTemplateSpecializationInfo();
assert(SpecInfo && "Function template specialization info missing?");
// Note: do not overwrite location info if previous template
// specialization kind was explicit.
TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind();
if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation) {
Specialization->setLocation(FD->getLocation());
Specialization->setLexicalDeclContext(FD->getLexicalDeclContext());
// C++11 [dcl.constexpr]p1: An explicit specialization of a constexpr
// function can differ from the template declaration with respect to
// the constexpr specifier.
// FIXME: We need an update record for this AST mutation.
// FIXME: What if there are multiple such prior declarations (for instance,
// from different modules)?
Specialization->setConstexpr(FD->isConstexpr());
}
// FIXME: Check if the prior specialization has a point of instantiation.
// If so, we have run afoul of .
// If this is a friend declaration, then we're not really declaring
// an explicit specialization.
bool isFriend = (FD->getFriendObjectKind() != Decl::FOK_None);
// Check the scope of this explicit specialization.
if (!isFriend &&
CheckTemplateSpecializationScope(*this,
Specialization->getPrimaryTemplate(),
Specialization, FD->getLocation(),
false))
return true;
// C++ [temp.expl.spec]p6:
// If a template, a member template or the member of a class template is
// explicitly specialized then that specialization shall be declared
// before the first use of that specialization that would cause an implicit
// instantiation to take place, in every translation unit in which such a
// use occurs; no diagnostic is required.
bool HasNoEffect = false;
if (!isFriend &&
CheckSpecializationInstantiationRedecl(FD->getLocation(),
TSK_ExplicitSpecialization,
Specialization,
SpecInfo->getTemplateSpecializationKind(),
SpecInfo->getPointOfInstantiation(),
HasNoEffect))
return true;
// Mark the prior declaration as an explicit specialization, so that later
// clients know that this is an explicit specialization.
if (!isFriend) {
// Since explicit specializations do not inherit '=delete' from their
// primary function template - check if the 'specialization' that was
// implicitly generated (during template argument deduction for partial
// ordering) from the most specialized of all the function templates that
// 'FD' could have been specializing, has a 'deleted' definition. If so,
// first check that it was implicitly generated during template argument
// deduction by making sure it wasn't referenced, and then reset the deleted
// flag to not-deleted, so that we can inherit that information from 'FD'.
if (Specialization->isDeleted() && !SpecInfo->isExplicitSpecialization() &&
!Specialization->getCanonicalDecl()->isReferenced()) {
// FIXME: This assert will not hold in the presence of modules.
assert(
Specialization->getCanonicalDecl() == Specialization &&
"This must be the only existing declaration of this specialization");
// FIXME: We need an update record for this AST mutation.
Specialization->setDeletedAsWritten(false);
}
// FIXME: We need an update record for this AST mutation.
SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
MarkUnusedFileScopedDecl(Specialization);
}
// Turn the given function declaration into a function template
// specialization, with the template arguments from the previous
// specialization.
// Take copies of (semantic and syntactic) template argument lists.
const TemplateArgumentList* TemplArgs = new (Context)
TemplateArgumentList(Specialization->getTemplateSpecializationArgs());
FD->setFunctionTemplateSpecialization(
Specialization->getPrimaryTemplate(), TemplArgs, /*InsertPos=*/nullptr,
SpecInfo->getTemplateSpecializationKind(),
ExplicitTemplateArgs ? &ConvertedTemplateArgs[Specialization] : nullptr);
// A function template specialization inherits the target attributes
// of its template. (We require the attributes explicitly in the
// code to match, but a template may have implicit attributes by
// virtue e.g. of being constexpr, and it passes these implicit
// attributes on to its specializations.)
if (LangOpts.CUDA)
inheritCUDATargetAttrs(FD, *Specialization->getPrimaryTemplate());
// The "previous declaration" for this function template specialization is
// the prior function template specialization.
Previous.clear();
Previous.addDecl(Specialization);
return false;
}
/// Perform semantic analysis for the given non-template member
/// specialization.
///
/// This routine performs all of the semantic analysis required for an
/// explicit member function specialization. On successful completion,
/// the function declaration \p FD will become a member function
/// specialization.
///
/// \param Member the member declaration, which will be updated to become a
/// specialization.
///
/// \param Previous the set of declarations, one of which may be specialized
/// by this function specialization; the set will be modified to contain the
/// redeclared member.
bool
Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
assert(!isa<TemplateDecl>(Member) && "Only for non-template members");
// Try to find the member we are instantiating.
NamedDecl *FoundInstantiation = nullptr;
NamedDecl *Instantiation = nullptr;
NamedDecl *InstantiatedFrom = nullptr;
MemberSpecializationInfo *MSInfo = nullptr;
if (Previous.empty()) {
// Nowhere to look anyway.
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) {
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
QualType Adjusted = Function->getType();
if (!hasExplicitCallingConv(Adjusted))
Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType());
// This doesn't handle deduced return types, but both function
// declarations should be undeduced at this point.
if (Context.hasSameType(Adjusted, Method->getType())) {
FoundInstantiation = *I;
Instantiation = Method;
InstantiatedFrom = Method->getInstantiatedFromMemberFunction();
MSInfo = Method->getMemberSpecializationInfo();
break;
}
}
}
} else if (isa<VarDecl>(Member)) {
VarDecl *PrevVar;
if (Previous.isSingleResult() &&
(PrevVar = dyn_cast<VarDecl>(Previous.getFoundDecl())))
if (PrevVar->isStaticDataMember()) {
FoundInstantiation = Previous.getRepresentativeDecl();
Instantiation = PrevVar;
InstantiatedFrom = PrevVar->getInstantiatedFromStaticDataMember();
MSInfo = PrevVar->getMemberSpecializationInfo();
}
} else if (isa<RecordDecl>(Member)) {
CXXRecordDecl *PrevRecord;
if (Previous.isSingleResult() &&
(PrevRecord = dyn_cast<CXXRecordDecl>(Previous.getFoundDecl()))) {
FoundInstantiation = Previous.getRepresentativeDecl();
Instantiation = PrevRecord;
InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass();
MSInfo = PrevRecord->getMemberSpecializationInfo();
}
} else if (isa<EnumDecl>(Member)) {
EnumDecl *PrevEnum;
if (Previous.isSingleResult() &&
(PrevEnum = dyn_cast<EnumDecl>(Previous.getFoundDecl()))) {
FoundInstantiation = Previous.getRepresentativeDecl();
Instantiation = PrevEnum;
InstantiatedFrom = PrevEnum->getInstantiatedFromMemberEnum();
MSInfo = PrevEnum->getMemberSpecializationInfo();
}
}
if (!Instantiation) {
// There is no previous declaration that matches. Since member
// specializations are always out-of-line, the caller will complain about
// this mismatch later.
return false;
}
// A member specialization in a friend declaration isn't really declaring
// an explicit specialization, just identifying a specific (possibly implicit)
// specialization. Don't change the template specialization kind.
//
// FIXME: Is this really valid? Other compilers reject.
if (Member->getFriendObjectKind() != Decl::FOK_None) {
// Preserve instantiation information.
if (InstantiatedFrom && isa<CXXMethodDecl>(Member)) {
cast<CXXMethodDecl>(Member)->setInstantiationOfMemberFunction(
cast<CXXMethodDecl>(InstantiatedFrom),
cast<CXXMethodDecl>(Instantiation)->getTemplateSpecializationKind());
} else if (InstantiatedFrom && isa<CXXRecordDecl>(Member)) {
cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass(
cast<CXXRecordDecl>(InstantiatedFrom),
cast<CXXRecordDecl>(Instantiation)->getTemplateSpecializationKind());
}
Previous.clear();
Previous.addDecl(FoundInstantiation);
return false;
}
// Make sure that this is a specialization of a member.
if (!InstantiatedFrom) {
Diag(Member->getLocation(), diag::err_spec_member_not_instantiated)
<< Member;
Diag(Instantiation->getLocation(), diag::note_specialized_decl);
return true;
}
// C++ [temp.expl.spec]p6:
// If a template, a member template or the member of a class template is
// explicitly specialized then that specialization shall be declared
// before the first use of that specialization that would cause an implicit
// instantiation to take place, in every translation unit in which such a
// use occurs; no diagnostic is required.
assert(MSInfo && "Member specialization info missing?");
bool HasNoEffect = false;
if (CheckSpecializationInstantiationRedecl(Member->getLocation(),
TSK_ExplicitSpecialization,
Instantiation,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
HasNoEffect))
return true;
// Check the scope of this explicit specialization.
if (CheckTemplateSpecializationScope(*this,
InstantiatedFrom,
Instantiation, Member->getLocation(),
false))
return true;
// Note that this member specialization is an "instantiation of" the
// corresponding member of the original template.
if (auto *MemberFunction = dyn_cast<FunctionDecl>(Member)) {
FunctionDecl *InstantiationFunction = cast<FunctionDecl>(Instantiation);
if (InstantiationFunction->getTemplateSpecializationKind() ==
TSK_ImplicitInstantiation) {
// Explicit specializations of member functions of class templates do not
// inherit '=delete' from the member function they are specializing.
if (InstantiationFunction->isDeleted()) {
// FIXME: This assert will not hold in the presence of modules.
assert(InstantiationFunction->getCanonicalDecl() ==
InstantiationFunction);
// FIXME: We need an update record for this AST mutation.
InstantiationFunction->setDeletedAsWritten(false);
}
}
MemberFunction->setInstantiationOfMemberFunction(
cast<CXXMethodDecl>(InstantiatedFrom), TSK_ExplicitSpecialization);
} else if (auto *MemberVar = dyn_cast<VarDecl>(Member)) {
MemberVar->setInstantiationOfStaticDataMember(
cast<VarDecl>(InstantiatedFrom), TSK_ExplicitSpecialization);
} else if (auto *MemberClass = dyn_cast<CXXRecordDecl>(Member)) {
MemberClass->setInstantiationOfMemberClass(
cast<CXXRecordDecl>(InstantiatedFrom), TSK_ExplicitSpecialization);
} else if (auto *MemberEnum = dyn_cast<EnumDecl>(Member)) {
MemberEnum->setInstantiationOfMemberEnum(
cast<EnumDecl>(InstantiatedFrom), TSK_ExplicitSpecialization);
} else {
llvm_unreachable("unknown member specialization kind");
}
// Save the caller the trouble of having to figure out which declaration
// this specialization matches.
Previous.clear();
Previous.addDecl(FoundInstantiation);
return false;
}
/// Complete the explicit specialization of a member of a class template by
/// updating the instantiated member to be marked as an explicit specialization.
///
/// \param OrigD The member declaration instantiated from the template.
/// \param Loc The location of the explicit specialization of the member.
template<typename DeclT>
static void completeMemberSpecializationImpl(Sema &S, DeclT *OrigD,
SourceLocation Loc) {
if (OrigD->getTemplateSpecializationKind() != TSK_ImplicitInstantiation)
return;
// FIXME: Inform AST mutation listeners of this AST mutation.
// FIXME: If there are multiple in-class declarations of the member (from
// multiple modules, or a declaration and later definition of a member type),
// should we update all of them?
OrigD->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
OrigD->setLocation(Loc);
}
void Sema::CompleteMemberSpecialization(NamedDecl *Member,
LookupResult &Previous) {
NamedDecl *Instantiation = cast<NamedDecl>(Member->getCanonicalDecl());
if (Instantiation == Member)
return;
if (auto *Function = dyn_cast<CXXMethodDecl>(Instantiation))
completeMemberSpecializationImpl(*this, Function, Member->getLocation());
else if (auto *Var = dyn_cast<VarDecl>(Instantiation))
completeMemberSpecializationImpl(*this, Var, Member->getLocation());
else if (auto *Record = dyn_cast<CXXRecordDecl>(Instantiation))
completeMemberSpecializationImpl(*this, Record, Member->getLocation());
else if (auto *Enum = dyn_cast<EnumDecl>(Instantiation))
completeMemberSpecializationImpl(*this, Enum, Member->getLocation());
else
llvm_unreachable("unknown member specialization kind");
}
/// Check the scope of an explicit instantiation.
///
/// \returns true if a serious error occurs, false otherwise.
static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
SourceLocation InstLoc,
bool WasQualifiedName) {
DeclContext *OrigContext= D->getDeclContext()->getEnclosingNamespaceContext();
DeclContext *CurContext = S.CurContext->getRedeclContext();
if (CurContext->isRecord()) {
S.Diag(InstLoc, diag::err_explicit_instantiation_in_class)
<< D;
return true;
}
// C++11 [temp.explicit]p3:
// An explicit instantiation shall appear in an enclosing namespace of its
// template. If the name declared in the explicit instantiation is an
// unqualified name, the explicit instantiation shall appear in the
// namespace where its template is declared or, if that namespace is inline
// (7.3.1), any namespace from its enclosing namespace set.
//
// This is DR275, which we do not retroactively apply to C++98/03.
if (WasQualifiedName) {
if (CurContext->Encloses(OrigContext))
return false;
} else {
if (CurContext->InEnclosingNamespaceSetOf(OrigContext))
return false;
}
if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext)) {
if (WasQualifiedName)
S.Diag(InstLoc,
S.getLangOpts().CPlusPlus11?
diag::err_explicit_instantiation_out_of_scope :
diag::warn_explicit_instantiation_out_of_scope_0x)
<< D << NS;
else
S.Diag(InstLoc,
S.getLangOpts().CPlusPlus11?
diag::err_explicit_instantiation_unqualified_wrong_namespace :
diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x)
<< D << NS;
} else
S.Diag(InstLoc,
S.getLangOpts().CPlusPlus11?
diag::err_explicit_instantiation_must_be_global :
diag::warn_explicit_instantiation_must_be_global_0x)
<< D;
S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
return false;
}
/// Determine whether the given scope specifier has a template-id in it.
static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) {
if (!SS.isSet())
return false;
// C++11 [temp.explicit]p3:
// If the explicit instantiation is for a member function, a member class
// or a static data member of a class template specialization, the name of
// the class template specialization in the qualified-id for the member
// name shall be a simple-template-id.
//
// C++98 has the same restriction, just worded differently.
for (NestedNameSpecifier *NNS = SS.getScopeRep(); NNS;
NNS = NNS->getPrefix())
if (const Type *T = NNS->getAsType())
if (isa<TemplateSpecializationType>(T))
return true;
return false;
}
/// Make a dllexport or dllimport attr on a class template specialization take
/// effect.
static void dllExportImportClassTemplateSpecialization(
Sema &S, ClassTemplateSpecializationDecl *Def) {
auto *A = cast_or_null<InheritableAttr>(getDLLAttr(Def));
assert(A && "dllExportImportClassTemplateSpecialization called "
"on Def without dllexport or dllimport");
// We reject explicit instantiations in class scope, so there should
// never be any delayed exported classes to worry about.
assert(S.DelayedDllExportClasses.empty() &&
"delayed exports present at explicit instantiation");
S.checkClassLevelDLLAttribute(Def);
// Propagate attribute to base class templates.
for (auto &B : Def->bases()) {
if (auto *BT = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
B.getType()->getAsCXXRecordDecl()))
S.propagateDLLAttrToBaseClassTemplate(Def, A, BT, B.getBeginLoc());
}
S.referenceDLLExportedClassMethods();
}
// Explicit instantiation of a class template specialization
DeclResult Sema::ActOnExplicitInstantiation(
Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc,
unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS,
TemplateTy TemplateD, SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn,
SourceLocation RAngleLoc, const ParsedAttributesView &Attr) {
// Find the class template we're specializing
TemplateName Name = TemplateD.get();
TemplateDecl *TD = Name.getAsTemplateDecl();
// Check that the specialization uses the same tag kind as the
// original template.
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
assert(Kind != TTK_Enum &&
"Invalid enum tag in class template explicit instantiation!");
ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(TD);
if (!ClassTemplate) {
NonTagKind NTK = getNonTagTypeDeclKind(TD, Kind);
Diag(TemplateNameLoc, diag::err_tag_reference_non_tag) << TD << NTK << Kind;
Diag(TD->getLocation(), diag::note_previous_use);
return true;
}
if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
Kind, /*isDefinition*/false, KWLoc,
ClassTemplate->getIdentifier())) {
Diag(KWLoc, diag::err_use_with_wrong_tag)
<< ClassTemplate
<< FixItHint::CreateReplacement(KWLoc,
ClassTemplate->getTemplatedDecl()->getKindName());
Diag(ClassTemplate->getTemplatedDecl()->getLocation(),
diag::note_previous_use);
Kind = ClassTemplate->getTemplatedDecl()->getTagKind();
}
// C++0x [temp.explicit]p2:
// There are two forms of explicit instantiation: an explicit instantiation
// definition and an explicit instantiation declaration. An explicit
// instantiation declaration begins with the extern keyword. [...]
TemplateSpecializationKind TSK = ExternLoc.isInvalid()
? TSK_ExplicitInstantiationDefinition
: TSK_ExplicitInstantiationDeclaration;
if (TSK == TSK_ExplicitInstantiationDeclaration) {
// Check for dllexport class template instantiation declarations.
for (const ParsedAttr &AL : Attr) {
if (AL.getKind() == ParsedAttr::AT_DLLExport) {
Diag(ExternLoc,
diag::warn_attribute_dllexport_explicit_instantiation_decl);
Diag(AL.getLoc(), diag::note_attribute);
break;
}
}
if (auto *A = ClassTemplate->getTemplatedDecl()->getAttr<DLLExportAttr>()) {
Diag(ExternLoc,
diag::warn_attribute_dllexport_explicit_instantiation_decl);
Diag(A->getLocation(), diag::note_attribute);
}
}
// In MSVC mode, dllimported explicit instantiation definitions are treated as
// instantiation declarations for most purposes.
bool DLLImportExplicitInstantiationDef = false;
if (TSK == TSK_ExplicitInstantiationDefinition &&
Context.getTargetInfo().getCXXABI().isMicrosoft()) {
// Check for dllimport class template instantiation definitions.
bool DLLImport =
ClassTemplate->getTemplatedDecl()->getAttr<DLLImportAttr>();
for (const ParsedAttr &AL : Attr) {
if (AL.getKind() == ParsedAttr::AT_DLLImport)
DLLImport = true;
if (AL.getKind() == ParsedAttr::AT_DLLExport) {
// dllexport trumps dllimport here.
DLLImport = false;
break;
}
}
if (DLLImport) {
TSK = TSK_ExplicitInstantiationDeclaration;
DLLImportExplicitInstantiationDef = true;
}
}
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
// Check that the template argument list is well-formed for this
// template.
SmallVector<TemplateArgument, 4> Converted;
if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc,
TemplateArgs, false, Converted))
return true;
// Find the class template specialization declaration that
// corresponds to these arguments.
void *InsertPos = nullptr;
ClassTemplateSpecializationDecl *PrevDecl
= ClassTemplate->findSpecialization(Converted, InsertPos);
TemplateSpecializationKind PrevDecl_TSK
= PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared;
// C++0x [temp.explicit]p2:
// [...] An explicit instantiation shall appear in an enclosing
// namespace of its template. [...]
//
// This is C++ DR 275.
if (CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc,
SS.isSet()))
return true;
ClassTemplateSpecializationDecl *Specialization = nullptr;
bool HasNoEffect = false;
if (PrevDecl) {
if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK,
PrevDecl, PrevDecl_TSK,
PrevDecl->getPointOfInstantiation(),
HasNoEffect))
return PrevDecl;
// Even though HasNoEffect == true means that this explicit instantiation
// has no effect on semantics, we go on to put its syntax in the AST.
if (PrevDecl_TSK == TSK_ImplicitInstantiation ||
PrevDecl_TSK == TSK_Undeclared) {
// Since the only prior class template specialization with these
// arguments was referenced but not declared, reuse that
// declaration node as our own, updating the source location
// for the template name to reflect our new declaration.
// (Other source locations will be updated later.)
Specialization = PrevDecl;
Specialization->setLocation(TemplateNameLoc);
PrevDecl = nullptr;
}
if (PrevDecl_TSK == TSK_ExplicitInstantiationDeclaration &&
DLLImportExplicitInstantiationDef) {
// The new specialization might add a dllimport attribute.
HasNoEffect = false;
}
}
if (!Specialization) {
// Create a new class template specialization declaration node for
// this explicit specialization.
Specialization
= ClassTemplateSpecializationDecl::Create(Context, Kind,
ClassTemplate->getDeclContext(),
KWLoc, TemplateNameLoc,
ClassTemplate,
Converted,
PrevDecl);
SetNestedNameSpecifier(*this, Specialization, SS);
if (!HasNoEffect && !PrevDecl) {
// Insert the new specialization.
ClassTemplate->AddSpecialization(Specialization, InsertPos);
}
}
// Build the fully-sugared type for this explicit instantiation as
// the user wrote in the explicit instantiation itself. This means
// that we'll pretty-print the type retrieved from the
// specialization's declaration the way that the user actually wrote
// the explicit instantiation, rather than formatting the name based
// on the "canonical" representation used to store the template
// arguments in the specialization.
TypeSourceInfo *WrittenTy
= Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc,
TemplateArgs,
Context.getTypeDeclType(Specialization));
Specialization->setTypeAsWritten(WrittenTy);
// Set source locations for keywords.
Specialization->setExternLoc(ExternLoc);
Specialization->setTemplateKeywordLoc(TemplateLoc);
Specialization->setBraceRange(SourceRange());
bool PreviouslyDLLExported = Specialization->hasAttr<DLLExportAttr>();
ProcessDeclAttributeList(S, Specialization, Attr);
// Add the explicit instantiation into its lexical context. However,
// since explicit instantiations are never found by name lookup, we
// just put it into the declaration context directly.
Specialization->setLexicalDeclContext(CurContext);
CurContext->addDecl(Specialization);
// Syntax is now OK, so return if it has no other effect on semantics.
if (HasNoEffect) {
// Set the template specialization kind.
Specialization->setTemplateSpecializationKind(TSK);
return Specialization;
}
// C++ [temp.explicit]p3:
// A definition of a class template or class member template
// shall be in scope at the point of the explicit instantiation of
// the class template or class member template.
//
// This check comes when we actually try to perform the
// instantiation.
ClassTemplateSpecializationDecl *Def
= cast_or_null<ClassTemplateSpecializationDecl>(
Specialization->getDefinition());
if (!Def)
InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK);
else if (TSK == TSK_ExplicitInstantiationDefinition) {
MarkVTableUsed(TemplateNameLoc, Specialization, true);
Specialization->setPointOfInstantiation(Def->getPointOfInstantiation());
}
// Instantiate the members of this class template specialization.
Def = cast_or_null<ClassTemplateSpecializationDecl>(
Specialization->getDefinition());
if (Def) {
TemplateSpecializationKind Old_TSK = Def->getTemplateSpecializationKind();
// Fix a TSK_ExplicitInstantiationDeclaration followed by a
// TSK_ExplicitInstantiationDefinition
if (Old_TSK == TSK_ExplicitInstantiationDeclaration &&
(TSK == TSK_ExplicitInstantiationDefinition ||
DLLImportExplicitInstantiationDef)) {
// FIXME: Need to notify the ASTMutationListener that we did this.
Def->setTemplateSpecializationKind(TSK);
if (!getDLLAttr(Def) && getDLLAttr(Specialization) &&
(Context.getTargetInfo().getCXXABI().isMicrosoft() ||
Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) {
// In the MS ABI, an explicit instantiation definition can add a dll
// attribute to a template with a previous instantiation declaration.
// MinGW doesn't allow this.
auto *A = cast<InheritableAttr>(
getDLLAttr(Specialization)->clone(getASTContext()));
A->setInherited(true);
Def->addAttr(A);
dllExportImportClassTemplateSpecialization(*this, Def);
}
}
// Fix a TSK_ImplicitInstantiation followed by a
// TSK_ExplicitInstantiationDefinition
bool NewlyDLLExported =
!PreviouslyDLLExported && Specialization->hasAttr<DLLExportAttr>();
if (Old_TSK == TSK_ImplicitInstantiation && NewlyDLLExported &&
(Context.getTargetInfo().getCXXABI().isMicrosoft() ||
Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) {
// In the MS ABI, an explicit instantiation definition can add a dll
// attribute to a template with a previous implicit instantiation.
// MinGW doesn't allow this. We limit clang to only adding dllexport, to
// avoid potentially strange codegen behavior. For example, if we extend
// this conditional to dllimport, and we have a source file calling a
// method on an implicitly instantiated template class instance and then
// declaring a dllimport explicit instantiation definition for the same
// template class, the codegen for the method call will not respect the
// dllimport, while it will with cl. The Def will already have the DLL
// attribute, since the Def and Specialization will be the same in the
// case of Old_TSK == TSK_ImplicitInstantiation, and we already added the
// attribute to the Specialization; we just need to make it take effect.
assert(Def == Specialization &&
"Def and Specialization should match for implicit instantiation");
dllExportImportClassTemplateSpecialization(*this, Def);
}
// Set the template specialization kind. Make sure it is set before
// instantiating the members which will trigger ASTConsumer callbacks.
Specialization->setTemplateSpecializationKind(TSK);
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
} else {
// Set the template specialization kind.
Specialization->setTemplateSpecializationKind(TSK);
}
return Specialization;
}
// Explicit instantiation of a member class of a class template.
DeclResult
Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
SourceLocation TemplateLoc, unsigned TagSpec,
SourceLocation KWLoc, CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
const ParsedAttributesView &Attr) {
bool Owned = false;
bool IsDependent = false;
Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference,
KWLoc, SS, Name, NameLoc, Attr, AS_none,
/*ModulePrivateLoc=*/SourceLocation(),
MultiTemplateParamsArg(), Owned, IsDependent,
SourceLocation(), false, TypeResult(),
/*IsTypeSpecifier*/false,
/*IsTemplateParamOrArg*/false);
assert(!IsDependent && "explicit instantiation of dependent name not yet handled");
if (!TagD)
return true;
TagDecl *Tag = cast<TagDecl>(TagD);
assert(!Tag->isEnum() && "shouldn't see enumerations here");
if (Tag->isInvalidDecl())
return true;
CXXRecordDecl *Record = cast<CXXRecordDecl>(Tag);
CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
if (!Pattern) {
Diag(TemplateLoc, diag::err_explicit_instantiation_nontemplate_type)
<< Context.getTypeDeclType(Record);
Diag(Record->getLocation(), diag::note_nontemplate_decl_here);
return true;
}
// C++0x [temp.explicit]p2:
// If the explicit instantiation is for a class or member class, the
// elaborated-type-specifier in the declaration shall include a
// simple-template-id.
//
// C++98 has the same restriction, just worded differently.
if (!ScopeSpecifierHasTemplateId(SS))
Diag(TemplateLoc, diag::ext_explicit_instantiation_without_qualified_id)
<< Record << SS.getRange();
// C++0x [temp.explicit]p2:
// There are two forms of explicit instantiation: an explicit instantiation
// definition and an explicit instantiation declaration. An explicit
// instantiation declaration begins with the extern keyword. [...]
TemplateSpecializationKind TSK
= ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
: TSK_ExplicitInstantiationDeclaration;
// C++0x [temp.explicit]p2:
// [...] An explicit instantiation shall appear in an enclosing
// namespace of its template. [...]
//
// This is C++ DR 275.
CheckExplicitInstantiationScope(*this, Record, NameLoc, true);
// Verify that it is okay to explicitly instantiate here.
CXXRecordDecl *PrevDecl
= cast_or_null<CXXRecordDecl>(Record->getPreviousDecl());
if (!PrevDecl && Record->getDefinition())
PrevDecl = Record;
if (PrevDecl) {
MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo();
bool HasNoEffect = false;
assert(MSInfo && "No member specialization information?");
if (CheckSpecializationInstantiationRedecl(TemplateLoc, TSK,
PrevDecl,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
HasNoEffect))
return true;
if (HasNoEffect)
return TagD;
}
CXXRecordDecl *RecordDef
= cast_or_null<CXXRecordDecl>(Record->getDefinition());
if (!RecordDef) {
// C++ [temp.explicit]p3:
// A definition of a member class of a class template shall be in scope
// at the point of an explicit instantiation of the member class.
CXXRecordDecl *Def
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
if (!Def) {
Diag(TemplateLoc, diag::err_explicit_instantiation_undefined_member)
<< 0 << Record->getDeclName() << Record->getDeclContext();
Diag(Pattern->getLocation(), diag::note_forward_declaration)
<< Pattern;
return true;
} else {
if (InstantiateClass(NameLoc, Record, Def,
getTemplateInstantiationArgs(Record),
TSK))
return true;
RecordDef = cast_or_null<CXXRecordDecl>(Record->getDefinition());
if (!RecordDef)
return true;
}
}
// Instantiate all of the members of the class.
InstantiateClassMembers(NameLoc, RecordDef,
getTemplateInstantiationArgs(Record), TSK);
if (TSK == TSK_ExplicitInstantiationDefinition)
MarkVTableUsed(NameLoc, RecordDef, true);
// FIXME: We don't have any representation for explicit instantiations of
// member classes. Such a representation is not needed for compilation, but it
// should be available for clients that want to see all of the declarations in
// the source code.
return TagD;
}
DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
SourceLocation ExternLoc,
SourceLocation TemplateLoc,
Declarator &D) {
// Explicit instantiations always require a name.
// TODO: check if/when DNInfo should replace Name.
DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
DeclarationName Name = NameInfo.getName();
if (!Name) {
if (!D.isInvalidType())
Diag(D.getDeclSpec().getBeginLoc(),
diag::err_explicit_instantiation_requires_name)
<< D.getDeclSpec().getSourceRange() << D.getSourceRange();
return true;
}
// The scope passed in may not be a decl scope. Zip up the scope tree until
// we find one that is.
while ((S->getFlags() & Scope::DeclScope) == 0 ||
(S->getFlags() & Scope::TemplateParamScope) != 0)
S = S->getParent();
// Determine the type of the declaration.
TypeSourceInfo *T = GetTypeForDeclarator(D, S);
QualType R = T->getType();
if (R.isNull())
return true;
// C++ [dcl.stc]p1:
// A storage-class-specifier shall not be specified in [...] an explicit
// instantiation (14.7.2) directive.
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_of_typedef)
<< Name;
return true;
} else if (D.getDeclSpec().getStorageClassSpec()
!= DeclSpec::SCS_unspecified) {
// Complain about then remove the storage class specifier.
Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_storage_class)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
D.getMutableDeclSpec().ClearStorageClassSpecs();
}
// C++0x [temp.explicit]p1:
// [...] An explicit instantiation of a function template shall not use the
// inline or constexpr specifiers.
// Presumably, this also applies to member functions of class templates as
// well.
if (D.getDeclSpec().isInlineSpecified())
Diag(D.getDeclSpec().getInlineSpecLoc(),
getLangOpts().CPlusPlus11 ?
diag::err_explicit_instantiation_inline :
diag::warn_explicit_instantiation_inline_0x)
<< FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc());
if (D.getDeclSpec().isConstexprSpecified() && R->isFunctionType())
// FIXME: Add a fix-it to remove the 'constexpr' and add a 'const' if one is
// not already specified.
Diag(D.getDeclSpec().getConstexprSpecLoc(),
diag::err_explicit_instantiation_constexpr);
// A deduction guide is not on the list of entities that can be explicitly
// instantiated.
if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
Diag(D.getDeclSpec().getBeginLoc(), diag::err_deduction_guide_specialized)
<< /*explicit instantiation*/ 0;
return true;
}
// C++0x [temp.explicit]p2:
// There are two forms of explicit instantiation: an explicit instantiation
// definition and an explicit instantiation declaration. An explicit
// instantiation declaration begins with the extern keyword. [...]
TemplateSpecializationKind TSK
= ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
: TSK_ExplicitInstantiationDeclaration;
LookupResult Previous(*this, NameInfo, LookupOrdinaryName);
LookupParsedName(Previous, S, &D.getCXXScopeSpec());
if (!R->isFunctionType()) {
// C++ [temp.explicit]p1:
// A [...] static data member of a class template can be explicitly
// instantiated from the member definition associated with its class
// template.
// C++1y [temp.explicit]p1:
// A [...] variable [...] template specialization can be explicitly
// instantiated from its template.
if (Previous.isAmbiguous())
return true;
VarDecl *Prev = Previous.getAsSingle<VarDecl>();
VarTemplateDecl *PrevTemplate = Previous.getAsSingle<VarTemplateDecl>();
if (!PrevTemplate) {
if (!Prev || !Prev->isStaticDataMember()) {
// We expect to see a data data member here.
Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_not_known)
<< Name;
for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
P != PEnd; ++P)
Diag((*P)->getLocation(), diag::note_explicit_instantiation_here);
return true;
}
if (!Prev->getInstantiatedFromStaticDataMember()) {
// FIXME: Check for explicit specialization?
Diag(D.getIdentifierLoc(),
diag::err_explicit_instantiation_data_member_not_instantiated)
<< Prev;
Diag(Prev->getLocation(), diag::note_explicit_instantiation_here);
// FIXME: Can we provide a note showing where this was declared?
return true;
}
} else {
// Explicitly instantiate a variable template.
// C++1y [dcl.spec.auto]p6:
// ... A program that uses auto or decltype(auto) in a context not
// explicitly allowed in this section is ill-formed.
//
// This includes auto-typed variable template instantiations.
if (R->isUndeducedType()) {
Diag(T->getTypeLoc().getBeginLoc(),
diag::err_auto_not_allowed_var_inst);
return true;
}
if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
// C++1y [temp.explicit]p3:
// If the explicit instantiation is for a variable, the unqualified-id
// in the declaration shall be a template-id.
Diag(D.getIdentifierLoc(),
diag::err_explicit_instantiation_without_template_id)
<< PrevTemplate;
Diag(PrevTemplate->getLocation(),
diag::note_explicit_instantiation_here);
return true;
}
// Translate the parser's template argument list into our AST format.
TemplateArgumentListInfo TemplateArgs =
makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc,
D.getIdentifierLoc(), TemplateArgs);
if (Res.isInvalid())
return true;
// Ignore access control bits, we don't need them for redeclaration
// checking.
Prev = cast<VarDecl>(Res.get());
}
// C++0x [temp.explicit]p2:
// If the explicit instantiation is for a member function, a member class
// or a static data member of a class template specialization, the name of
// the class template specialization in the qualified-id for the member
// name shall be a simple-template-id.
//
// C++98 has the same restriction, just worded differently.
//
// This does not apply to variable template specializations, where the
// template-id is in the unqualified-id instead.
if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()) && !PrevTemplate)
Diag(D.getIdentifierLoc(),
diag::ext_explicit_instantiation_without_qualified_id)
<< Prev << D.getCXXScopeSpec().getRange();
// Check the scope of this explicit instantiation.
CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true);
// Verify that it is okay to explicitly instantiate here.
TemplateSpecializationKind PrevTSK = Prev->getTemplateSpecializationKind();
SourceLocation POI = Prev->getPointOfInstantiation();
bool HasNoEffect = false;
if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev,
PrevTSK, POI, HasNoEffect))
return true;
if (!HasNoEffect) {
// Instantiate static data member or variable template.
Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
// Merge attributes.
ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes());
if (TSK == TSK_ExplicitInstantiationDefinition)
InstantiateVariableDefinition(D.getIdentifierLoc(), Prev);
}
// Check the new variable specialization against the parsed input.
if (PrevTemplate && Prev && !Context.hasSameType(Prev->getType(), R)) {
Diag(T->getTypeLoc().getBeginLoc(),
diag::err_invalid_var_template_spec_type)
<< 0 << PrevTemplate << R << Prev->getType();
Diag(PrevTemplate->getLocation(), diag::note_template_declared_here)
<< 2 << PrevTemplate->getDeclName();
return true;
}
// FIXME: Create an ExplicitInstantiation node?
return (Decl*) nullptr;
}
// If the declarator is a template-id, translate the parser's template
// argument list into our AST format.
bool HasExplicitTemplateArgs = false;
TemplateArgumentListInfo TemplateArgs;
if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
HasExplicitTemplateArgs = true;
}
// C++ [temp.explicit]p1:
// A [...] function [...] can be explicitly instantiated from its template.
// A member function [...] of a class template can be explicitly
// instantiated from the member definition associated with its class
// template.
UnresolvedSet<8> TemplateMatches;
FunctionDecl *NonTemplateMatch = nullptr;
TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc());
for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
P != PEnd; ++P) {
NamedDecl *Prev = *P;
if (!HasExplicitTemplateArgs) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
QualType Adjusted = adjustCCAndNoReturn(R, Method->getType(),
/*AdjustExceptionSpec*/true);
if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) {
if (Method->getPrimaryTemplate()) {
TemplateMatches.addDecl(Method, P.getAccess());
} else {
// FIXME: Can this assert ever happen? Needs a test.
assert(!NonTemplateMatch && "Multiple NonTemplateMatches");
NonTemplateMatch = Method;
}
}
}
}
FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Prev);
if (!FunTmpl)
continue;
TemplateDeductionInfo Info(FailedCandidates.getLocation());
FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult TDK
= DeduceTemplateArguments(FunTmpl,
(HasExplicitTemplateArgs ? &TemplateArgs
: nullptr),
R, Specialization, Info)) {
// Keep track of almost-matches.
FailedCandidates.addCandidate()
.set(P.getPair(), FunTmpl->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, TDK, Info));
(void)TDK;
continue;
}
// Target attributes are part of the cuda function signature, so
// the cuda target of the instantiated function must match that of its
// template. Given that C++ template deduction does not take
// target attributes into account, we reject candidates here that
// have a different target.
if (LangOpts.CUDA &&
IdentifyCUDATarget(Specialization,
/* IgnoreImplicitHDAttributes = */ true) !=
IdentifyCUDATarget(D.getDeclSpec().getAttributes())) {
FailedCandidates.addCandidate().set(
P.getPair(), FunTmpl->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info));
continue;
}
TemplateMatches.addDecl(Specialization, P.getAccess());
}
FunctionDecl *Specialization = NonTemplateMatch;
if (!Specialization) {
// Find the most specialized function template specialization.
UnresolvedSetIterator Result = getMostSpecialized(
TemplateMatches.begin(), TemplateMatches.end(), FailedCandidates,
D.getIdentifierLoc(),
PDiag(diag::err_explicit_instantiation_not_known) << Name,
PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
PDiag(diag::note_explicit_instantiation_candidate));
if (Result == TemplateMatches.end())
return true;
// Ignore access control bits, we don't need them for redeclaration checking.
Specialization = cast<FunctionDecl>(*Result);
}
// C++11 [except.spec]p4
// In an explicit instantiation an exception-specification may be specified,
// but is not required.
// If an exception-specification is specified in an explicit instantiation
// directive, it shall be compatible with the exception-specifications of
// other declarations of that function.
if (auto *FPT = R->getAs<FunctionProtoType>())
if (FPT->hasExceptionSpec()) {
unsigned DiagID =
diag::err_mismatched_exception_spec_explicit_instantiation;
if (getLangOpts().MicrosoftExt)
DiagID = diag::ext_mismatched_exception_spec_explicit_instantiation;
bool Result = CheckEquivalentExceptionSpec(
PDiag(DiagID) << Specialization->getType(),
PDiag(diag::note_explicit_instantiation_here),
Specialization->getType()->getAs<FunctionProtoType>(),
Specialization->getLocation(), FPT, D.getBeginLoc());
// In Microsoft mode, mismatching exception specifications just cause a
// warning.
if (!getLangOpts().MicrosoftExt && Result)
return true;
}
if (Specialization->getTemplateSpecializationKind() == TSK_Undeclared) {
Diag(D.getIdentifierLoc(),
diag::err_explicit_instantiation_member_function_not_instantiated)
<< Specialization
<< (Specialization->getTemplateSpecializationKind() ==
TSK_ExplicitSpecialization);
Diag(Specialization->getLocation(), diag::note_explicit_instantiation_here);
return true;
}
FunctionDecl *PrevDecl = Specialization->getPreviousDecl();
if (!PrevDecl && Specialization->isThisDeclarationADefinition())
PrevDecl = Specialization;
if (PrevDecl) {
bool HasNoEffect = false;
if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK,
PrevDecl,
PrevDecl->getTemplateSpecializationKind(),
PrevDecl->getPointOfInstantiation(),
HasNoEffect))
return true;
// FIXME: We may still want to build some representation of this
// explicit specialization.
if (HasNoEffect)
return (Decl*) nullptr;
}
ProcessDeclAttributeList(S, Specialization, D.getDeclSpec().getAttributes());
// In MSVC mode, dllimported explicit instantiation definitions are treated as
// instantiation declarations.
if (TSK == TSK_ExplicitInstantiationDefinition &&
Specialization->hasAttr<DLLImportAttr>() &&
Context.getTargetInfo().getCXXABI().isMicrosoft())
TSK = TSK_ExplicitInstantiationDeclaration;
Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
if (Specialization->isDefined()) {
// Let the ASTConsumer know that this function has been explicitly
// instantiated now, and its linkage might have changed.
Consumer.HandleTopLevelDecl(DeclGroupRef(Specialization));
} else if (TSK == TSK_ExplicitInstantiationDefinition)
InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization);
// C++0x [temp.explicit]p2:
// If the explicit instantiation is for a member function, a member class
// or a static data member of a class template specialization, the name of
// the class template specialization in the qualified-id for the member
// name shall be a simple-template-id.
//
// C++98 has the same restriction, just worded differently.
FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId && !FunTmpl &&
D.getCXXScopeSpec().isSet() &&
!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
Diag(D.getIdentifierLoc(),
diag::ext_explicit_instantiation_without_qualified_id)
<< Specialization << D.getCXXScopeSpec().getRange();
CheckExplicitInstantiationScope(*this,
FunTmpl? (NamedDecl *)FunTmpl
: Specialization->getInstantiatedFromMemberFunction(),
D.getIdentifierLoc(),
D.getCXXScopeSpec().isSet());
// FIXME: Create some kind of ExplicitInstantiationDecl here.
return (Decl*) nullptr;
}
TypeResult
Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
const CXXScopeSpec &SS, IdentifierInfo *Name,
SourceLocation TagLoc, SourceLocation NameLoc) {
// This has to hold, because SS is expected to be defined.
assert(Name && "Expected a name in a dependent tag");
NestedNameSpecifier *NNS = SS.getScopeRep();
if (!NNS)
return true;
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
if (TUK == TUK_Declaration || TUK == TUK_Definition) {
Diag(NameLoc, diag::err_dependent_tag_decl)
<< (TUK == TUK_Definition) << Kind << SS.getRange();
return true;
}
// Create the resulting type.
ElaboratedTypeKeyword Kwd = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
QualType Result = Context.getDependentNameType(Kwd, NNS, Name);
// Create type-source location information for this type.
TypeLocBuilder TLB;
DependentNameTypeLoc TL = TLB.push<DependentNameTypeLoc>(Result);
TL.setElaboratedKeywordLoc(TagLoc);
TL.setQualifierLoc(SS.getWithLocInContext(Context));
TL.setNameLoc(NameLoc);
return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
}
TypeResult
Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
const CXXScopeSpec &SS, const IdentifierInfo &II,
SourceLocation IdLoc) {
if (SS.isInvalid())
return true;
if (TypenameLoc.isValid() && S && !S->getTemplateParamParent())
Diag(TypenameLoc,
getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_typename_outside_of_template :
diag::ext_typename_outside_of_template)
<< FixItHint::CreateRemoval(TypenameLoc);
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
QualType T = CheckTypenameType(TypenameLoc.isValid()? ETK_Typename : ETK_None,
TypenameLoc, QualifierLoc, II, IdLoc);
if (T.isNull())
return true;
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
if (isa<DependentNameType>(T)) {
DependentNameTypeLoc TL = TSI->getTypeLoc().castAs<DependentNameTypeLoc>();
TL.setElaboratedKeywordLoc(TypenameLoc);
TL.setQualifierLoc(QualifierLoc);
TL.setNameLoc(IdLoc);
} else {
ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs<ElaboratedTypeLoc>();
TL.setElaboratedKeywordLoc(TypenameLoc);
TL.setQualifierLoc(QualifierLoc);
TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IdLoc);
}
return CreateParsedType(T, TSI);
}
TypeResult
Sema::ActOnTypenameType(Scope *S,
SourceLocation TypenameLoc,
const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
TemplateTy TemplateIn,
IdentifierInfo *TemplateII,
SourceLocation TemplateIILoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
SourceLocation RAngleLoc) {
if (TypenameLoc.isValid() && S && !S->getTemplateParamParent())
Diag(TypenameLoc,
getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_typename_outside_of_template :
diag::ext_typename_outside_of_template)
<< FixItHint::CreateRemoval(TypenameLoc);
// Strangely, non-type results are not ignored by this lookup, so the
// program is ill-formed if it finds an injected-class-name.
if (TypenameLoc.isValid()) {
auto *LookupRD =
dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, false));
if (LookupRD && LookupRD->getIdentifier() == TemplateII) {
Diag(TemplateIILoc,
diag::ext_out_of_line_qualified_id_type_names_constructor)
<< TemplateII << 0 /*injected-class-name used as template name*/
<< (TemplateKWLoc.isValid() ? 1 : 0 /*'template'/'typename' keyword*/);
}
}
// Translate the parser's template argument list in our AST format.
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
TemplateName Template = TemplateIn.get();
if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
// Construct a dependent template specialization type.
assert(DTN && "dependent template has non-dependent name?");
assert(DTN->getQualifier() == SS.getScopeRep());
QualType T = Context.getDependentTemplateSpecializationType(ETK_Typename,
DTN->getQualifier(),
DTN->getIdentifier(),
TemplateArgs);
// Create source-location information for this type.
TypeLocBuilder Builder;
DependentTemplateSpecializationTypeLoc SpecTL
= Builder.push<DependentTemplateSpecializationTypeLoc>(T);
SpecTL.setElaboratedKeywordLoc(TypenameLoc);
SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
SpecTL.setTemplateNameLoc(TemplateIILoc);
SpecTL.setLAngleLoc(LAngleLoc);
SpecTL.setRAngleLoc(RAngleLoc);
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
}
QualType T = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs);
if (T.isNull())
return true;
// Provide source-location information for the template specialization type.
TypeLocBuilder Builder;
TemplateSpecializationTypeLoc SpecTL
= Builder.push<TemplateSpecializationTypeLoc>(T);
SpecTL.setTemplateKeywordLoc(TemplateKWLoc);
SpecTL.setTemplateNameLoc(TemplateIILoc);
SpecTL.setLAngleLoc(LAngleLoc);
SpecTL.setRAngleLoc(RAngleLoc);
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
T = Context.getElaboratedType(ETK_Typename, SS.getScopeRep(), T);
ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T);
TL.setElaboratedKeywordLoc(TypenameLoc);
TL.setQualifierLoc(SS.getWithLocInContext(Context));
TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T);
return CreateParsedType(T, TSI);
}
/// Determine whether this failed name lookup should be treated as being
/// disabled by a usage of std::enable_if.
static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II,
SourceRange &CondRange, Expr *&Cond) {
// We must be looking for a ::type...
if (!II.isStr("type"))
return false;
// ... within an explicitly-written template specialization...
if (!NNS || !NNS.getNestedNameSpecifier()->getAsType())
return false;
TypeLoc EnableIfTy = NNS.getTypeLoc();
TemplateSpecializationTypeLoc EnableIfTSTLoc =
EnableIfTy.getAs<TemplateSpecializationTypeLoc>();
if (!EnableIfTSTLoc || EnableIfTSTLoc.getNumArgs() == 0)
return false;
const TemplateSpecializationType *EnableIfTST = EnableIfTSTLoc.getTypePtr();
// ... which names a complete class template declaration...
const TemplateDecl *EnableIfDecl =
EnableIfTST->getTemplateName().getAsTemplateDecl();
if (!EnableIfDecl || EnableIfTST->isIncompleteType())
return false;
// ... called "enable_if".
const IdentifierInfo *EnableIfII =
EnableIfDecl->getDeclName().getAsIdentifierInfo();
if (!EnableIfII || !EnableIfII->isStr("enable_if"))
return false;
// Assume the first template argument is the condition.
CondRange = EnableIfTSTLoc.getArgLoc(0).getSourceRange();
// Dig out the condition.
Cond = nullptr;
if (EnableIfTSTLoc.getArgLoc(0).getArgument().getKind()
!= TemplateArgument::Expression)
return true;
Cond = EnableIfTSTLoc.getArgLoc(0).getSourceExpression();
// Ignore Boolean literals; they add no value.
if (isa<CXXBoolLiteralExpr>(Cond->IgnoreParenCasts()))
Cond = nullptr;
return true;
}
/// Build the type that describes a C++ typename specifier,
/// e.g., "typename T::type".
QualType
Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
SourceLocation KeywordLoc,
NestedNameSpecifierLoc QualifierLoc,
const IdentifierInfo &II,
SourceLocation IILoc) {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
DeclContext *Ctx = computeDeclContext(SS);
if (!Ctx) {
// If the nested-name-specifier is dependent and couldn't be
// resolved to a type, build a typename type.
assert(QualifierLoc.getNestedNameSpecifier()->isDependent());
return Context.getDependentNameType(Keyword,
QualifierLoc.getNestedNameSpecifier(),
&II);
}
// If the nested-name-specifier refers to the current instantiation,
// the "typename" keyword itself is superfluous. In C++03, the
// program is actually ill-formed. However, DR 382 (in C++0x CD1)
// allows such extraneous "typename" keywords, and we retroactively
// apply this DR to C++03 code with only a warning. In any case we continue.
if (RequireCompleteDeclContext(SS, Ctx))
return QualType();
DeclarationName Name(&II);
LookupResult Result(*this, Name, IILoc, LookupOrdinaryName);
LookupQualifiedName(Result, Ctx, SS);
unsigned DiagID = 0;
Decl *Referenced = nullptr;
switch (Result.getResultKind()) {
case LookupResult::NotFound: {
// If we're looking up 'type' within a template named 'enable_if', produce
// a more specific diagnostic.
SourceRange CondRange;
Expr *Cond = nullptr;
if (isEnableIf(QualifierLoc, II, CondRange, Cond)) {
// If we have a condition, narrow it down to the specific failed
// condition.
if (Cond) {
Expr *FailedCond;
std::string FailedDescription;
std::tie(FailedCond, FailedDescription) =
findFailedBooleanCondition(Cond);
Diag(FailedCond->getExprLoc(),
diag::err_typename_nested_not_found_requirement)
<< FailedDescription
<< FailedCond->getSourceRange();
return QualType();
}
Diag(CondRange.getBegin(), diag::err_typename_nested_not_found_enable_if)
<< Ctx << CondRange;
return QualType();
}
DiagID = diag::err_typename_nested_not_found;
break;
}
case LookupResult::FoundUnresolvedValue: {
// We found a using declaration that is a value. Most likely, the using
// declaration itself is meant to have the 'typename' keyword.
SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(),
IILoc);
Diag(IILoc, diag::err_typename_refers_to_using_value_decl)
<< Name << Ctx << FullRange;
if (UnresolvedUsingValueDecl *Using
= dyn_cast<UnresolvedUsingValueDecl>(Result.getRepresentativeDecl())){
SourceLocation Loc = Using->getQualifierLoc().getBeginLoc();
Diag(Loc, diag::note_using_value_decl_missing_typename)
<< FixItHint::CreateInsertion(Loc, "typename ");
}
}
// Fall through to create a dependent typename type, from which we can recover
// better.
LLVM_FALLTHROUGH;
case LookupResult::NotFoundInCurrentInstantiation:
// Okay, it's a member of an unknown instantiation.
return Context.getDependentNameType(Keyword,
QualifierLoc.getNestedNameSpecifier(),
&II);
case LookupResult::Found:
if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {
// C++ [class.qual]p2:
// In a lookup in which function names are not ignored and the
// nested-name-specifier nominates a class C, if the name specified
// after the nested-name-specifier, when looked up in C, is the
// injected-class-name of C [...] then the name is instead considered
// to name the constructor of class C.
//
// Unlike in an elaborated-type-specifier, function names are not ignored
// in typename-specifier lookup. However, they are ignored in all the
// contexts where we form a typename type with no keyword (that is, in
// mem-initializer-ids, base-specifiers, and elaborated-type-specifiers).
//
// FIXME: That's not strictly true: mem-initializer-id lookup does not
// ignore functions, but that appears to be an oversight.
auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(Ctx);
auto *FoundRD = dyn_cast<CXXRecordDecl>(Type);
if (Keyword == ETK_Typename && LookupRD && FoundRD &&
FoundRD->isInjectedClassName() &&
declaresSameEntity(LookupRD, cast<Decl>(FoundRD->getParent())))
Diag(IILoc, diag::ext_out_of_line_qualified_id_type_names_constructor)
<< &II << 1 << 0 /*'typename' keyword used*/;
// We found a type. Build an ElaboratedType, since the
// typename-specifier was just sugar.
MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false);
return Context.getElaboratedType(Keyword,
QualifierLoc.getNestedNameSpecifier(),
Context.getTypeDeclType(Type));
}
// C++ [dcl.type.simple]p2:
// A type-specifier of the form
// typename[opt] nested-name-specifier[opt] template-name
// is a placeholder for a deduced class type [...].
if (getLangOpts().CPlusPlus17) {
if (auto *TD = getAsTypeTemplateDecl(Result.getFoundDecl())) {
return Context.getElaboratedType(
Keyword, QualifierLoc.getNestedNameSpecifier(),
Context.getDeducedTemplateSpecializationType(TemplateName(TD),
QualType(), false));
}
}
DiagID = diag::err_typename_nested_not_type;
Referenced = Result.getFoundDecl();
break;
case LookupResult::FoundOverloaded:
DiagID = diag::err_typename_nested_not_type;
Referenced = *Result.begin();
break;
case LookupResult::Ambiguous:
return QualType();
}
// If we get here, it's because name lookup did not find a
// type. Emit an appropriate diagnostic and return an error.
SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(),
IILoc);
Diag(IILoc, DiagID) << FullRange << Name << Ctx;
if (Referenced)
Diag(Referenced->getLocation(), diag::note_typename_refers_here)
<< Name;
return QualType();
}
namespace {
// See Sema::RebuildTypeInCurrentInstantiation
class CurrentInstantiationRebuilder
: public TreeTransform<CurrentInstantiationRebuilder> {
SourceLocation Loc;
DeclarationName Entity;
public:
typedef TreeTransform<CurrentInstantiationRebuilder> inherited;
CurrentInstantiationRebuilder(Sema &SemaRef,
SourceLocation Loc,
DeclarationName Entity)
: TreeTransform<CurrentInstantiationRebuilder>(SemaRef),
Loc(Loc), Entity(Entity) { }
/// Determine whether the given type \p T has already been
/// transformed.
///
/// For the purposes of type reconstruction, a type has already been
/// transformed if it is NULL or if it is not dependent.
bool AlreadyTransformed(QualType T) {
return T.isNull() || !T->isDependentType();
}
/// Returns the location of the entity whose type is being
/// rebuilt.
SourceLocation getBaseLocation() { return Loc; }
/// Returns the name of the entity whose type is being rebuilt.
DeclarationName getBaseEntity() { return Entity; }
/// Sets the "base" location and entity when that
/// information is known based on another transformation.
void setBase(SourceLocation Loc, DeclarationName Entity) {
this->Loc = Loc;
this->Entity = Entity;
}
ExprResult TransformLambdaExpr(LambdaExpr *E) {
// Lambdas never need to be transformed.
return E;
}
};
} // end anonymous namespace
/// Rebuilds a type within the context of the current instantiation.
///
/// The type \p T is part of the type of an out-of-line member definition of
/// a class template (or class template partial specialization) that was parsed
/// and constructed before we entered the scope of the class template (or
/// partial specialization thereof). This routine will rebuild that type now
/// that we have entered the declarator's scope, which may produce different
/// canonical types, e.g.,
///
/// \code
/// template<typename T>
/// struct X {
/// typedef T* pointer;
/// pointer data();
/// };
///
/// template<typename T>
/// typename X<T>::pointer X<T>::data() { ... }
/// \endcode
///
/// Here, the type "typename X<T>::pointer" will be created as a DependentNameType,
/// since we do not know that we can look into X<T> when we parsed the type.
/// This function will rebuild the type, performing the lookup of "pointer"
/// in X<T> and returning an ElaboratedType whose canonical type is the same
/// as the canonical type of T*, allowing the return types of the out-of-line
/// definition and the declaration to match.
TypeSourceInfo *Sema::RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
SourceLocation Loc,
DeclarationName Name) {
if (!T || !T->getType()->isDependentType())
return T;
CurrentInstantiationRebuilder Rebuilder(*this, Loc, Name);
return Rebuilder.TransformType(T);
}
ExprResult Sema::RebuildExprInCurrentInstantiation(Expr *E) {
CurrentInstantiationRebuilder Rebuilder(*this, E->getExprLoc(),
DeclarationName());
return Rebuilder.TransformExpr(E);
}
bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) {
if (SS.isInvalid())
return true;
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
CurrentInstantiationRebuilder Rebuilder(*this, SS.getRange().getBegin(),
DeclarationName());
NestedNameSpecifierLoc Rebuilt
= Rebuilder.TransformNestedNameSpecifierLoc(QualifierLoc);
if (!Rebuilt)
return true;
SS.Adopt(Rebuilt);
return false;
}
/// Rebuild the template parameters now that we know we're in a current
/// instantiation.
bool Sema::RebuildTemplateParamsInCurrentInstantiation(
TemplateParameterList *Params) {
for (unsigned I = 0, N = Params->size(); I != N; ++I) {
Decl *Param = Params->getParam(I);
// There is nothing to rebuild in a type parameter.
if (isa<TemplateTypeParmDecl>(Param))
continue;
// Rebuild the template parameter list of a template template parameter.
if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(Param)) {
if (RebuildTemplateParamsInCurrentInstantiation(
TTP->getTemplateParameters()))
return true;
continue;
}
// Rebuild the type of a non-type template parameter.
NonTypeTemplateParmDecl *NTTP = cast<NonTypeTemplateParmDecl>(Param);
TypeSourceInfo *NewTSI
= RebuildTypeInCurrentInstantiation(NTTP->getTypeSourceInfo(),
NTTP->getLocation(),
NTTP->getDeclName());
if (!NewTSI)
return true;
if (NewTSI->getType()->isUndeducedType()) {
// C++17 [temp.dep.expr]p3:
// An id-expression is type-dependent if it contains
// - an identifier associated by name lookup with a non-type
// template-parameter declared with a type that contains a
// placeholder type (7.1.7.4),
NewTSI = SubstAutoTypeSourceInfo(NewTSI, Context.DependentTy);
}
if (NewTSI != NTTP->getTypeSourceInfo()) {
NTTP->setTypeSourceInfo(NewTSI);
NTTP->setType(NewTSI->getType());
}
}
return false;
}
/// Produces a formatted string that describes the binding of
/// template parameters to template arguments.
std::string
Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
const TemplateArgumentList &Args) {
return getTemplateArgumentBindingsText(Params, Args.data(), Args.size());
}
std::string
Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
const TemplateArgument *Args,
unsigned NumArgs) {
SmallString<128> Str;
llvm::raw_svector_ostream Out(Str);
if (!Params || Params->size() == 0 || NumArgs == 0)
return std::string();
for (unsigned I = 0, N = Params->size(); I != N; ++I) {
if (I >= NumArgs)
break;
if (I == 0)
Out << "[with ";
else
Out << ", ";
if (const IdentifierInfo *Id = Params->getParam(I)->getIdentifier()) {
Out << Id->getName();
} else {
Out << '$' << I;
}
Out << " = ";
Args[I].print(getPrintingPolicy(), Out);
}
Out << ']';
return Out.str();
}
void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD,
CachedTokens &Toks) {
if (!FD)
return;
auto LPT = llvm::make_unique<LateParsedTemplate>();
// Take tokens to avoid allocations
LPT->Toks.swap(Toks);
LPT->D = FnD;
LateParsedTemplateMap.insert(std::make_pair(FD, std::move(LPT)));
FD->setLateTemplateParsed(true);
}
void Sema::UnmarkAsLateParsedTemplate(FunctionDecl *FD) {
if (!FD)
return;
FD->setLateTemplateParsed(false);
}
bool Sema::IsInsideALocalClassWithinATemplateFunction() {
DeclContext *DC = CurContext;
while (DC) {
if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) {
const FunctionDecl *FD = RD->isLocalClass();
return (FD && FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate);
} else if (DC->isTranslationUnit() || DC->isNamespace())
return false;
DC = DC->getParent();
}
return false;
}
namespace {
/// Walk the path from which a declaration was instantiated, and check
/// that every explicit specialization along that path is visible. This enforces
/// C++ [temp.expl.spec]/6:
///
/// If a template, a member template or a member of a class template is
/// explicitly specialized then that specialization shall be declared before
/// the first use of that specialization that would cause an implicit
/// instantiation to take place, in every translation unit in which such a
/// use occurs; no diagnostic is required.
///
/// and also C++ [temp.class.spec]/1:
///
/// A partial specialization shall be declared before the first use of a
/// class template specialization that would make use of the partial
/// specialization as the result of an implicit or explicit instantiation
/// in every translation unit in which such a use occurs; no diagnostic is
/// required.
class ExplicitSpecializationVisibilityChecker {
Sema &S;
SourceLocation Loc;
llvm::SmallVector<Module *, 8> Modules;
public:
ExplicitSpecializationVisibilityChecker(Sema &S, SourceLocation Loc)
: S(S), Loc(Loc) {}
void check(NamedDecl *ND) {
if (auto *FD = dyn_cast<FunctionDecl>(ND))
return checkImpl(FD);
if (auto *RD = dyn_cast<CXXRecordDecl>(ND))
return checkImpl(RD);
if (auto *VD = dyn_cast<VarDecl>(ND))
return checkImpl(VD);
if (auto *ED = dyn_cast<EnumDecl>(ND))
return checkImpl(ED);
}
private:
void diagnose(NamedDecl *D, bool IsPartialSpec) {
auto Kind = IsPartialSpec ? Sema::MissingImportKind::PartialSpecialization
: Sema::MissingImportKind::ExplicitSpecialization;
const bool Recover = true;
// If we got a custom set of modules (because only a subset of the
// declarations are interesting), use them, otherwise let
// diagnoseMissingImport intelligently pick some.
if (Modules.empty())
S.diagnoseMissingImport(Loc, D, Kind, Recover);
else
S.diagnoseMissingImport(Loc, D, D->getLocation(), Modules, Kind, Recover);
}
// Check a specific declaration. There are three problematic cases:
//
// 1) The declaration is an explicit specialization of a template
// specialization.
// 2) The declaration is an explicit specialization of a member of an
// templated class.
// 3) The declaration is an instantiation of a template, and that template
// is an explicit specialization of a member of a templated class.
//
// We don't need to go any deeper than that, as the instantiation of the
// surrounding class / etc is not triggered by whatever triggered this
// instantiation, and thus should be checked elsewhere.
template<typename SpecDecl>
void checkImpl(SpecDecl *Spec) {
bool IsHiddenExplicitSpecialization = false;
if (Spec->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
IsHiddenExplicitSpecialization =
Spec->getMemberSpecializationInfo()
? !S.hasVisibleMemberSpecialization(Spec, &Modules)
: !S.hasVisibleExplicitSpecialization(Spec, &Modules);
} else {
checkInstantiated(Spec);
}
if (IsHiddenExplicitSpecialization)
diagnose(Spec->getMostRecentDecl(), false);
}
void checkInstantiated(FunctionDecl *FD) {
if (auto *TD = FD->getPrimaryTemplate())
checkTemplate(TD);
}
void checkInstantiated(CXXRecordDecl *RD) {
auto *SD = dyn_cast<ClassTemplateSpecializationDecl>(RD);
if (!SD)
return;
auto From = SD->getSpecializedTemplateOrPartial();
if (auto *TD = From.dyn_cast<ClassTemplateDecl *>())
checkTemplate(TD);
else if (auto *TD =
From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
if (!S.hasVisibleDeclaration(TD))
diagnose(TD, true);
checkTemplate(TD);
}
}
void checkInstantiated(VarDecl *RD) {
auto *SD = dyn_cast<VarTemplateSpecializationDecl>(RD);
if (!SD)
return;
auto From = SD->getSpecializedTemplateOrPartial();
if (auto *TD = From.dyn_cast<VarTemplateDecl *>())
checkTemplate(TD);
else if (auto *TD =
From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
if (!S.hasVisibleDeclaration(TD))
diagnose(TD, true);
checkTemplate(TD);
}
}
void checkInstantiated(EnumDecl *FD) {}
template<typename TemplDecl>
void checkTemplate(TemplDecl *TD) {
if (TD->isMemberSpecialization()) {
if (!S.hasVisibleMemberSpecialization(TD, &Modules))
diagnose(TD->getMostRecentDecl(), false);
}
}
};
} // end anonymous namespace
void Sema::checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec) {
if (!getLangOpts().Modules)
return;
ExplicitSpecializationVisibilityChecker(*this, Loc).check(Spec);
}
/// Check whether a template partial specialization that we've discovered
/// is hidden, and produce suitable diagnostics if so.
void Sema::checkPartialSpecializationVisibility(SourceLocation Loc,
NamedDecl *Spec) {
llvm::SmallVector<Module *, 8> Modules;
if (!hasVisibleDeclaration(Spec, &Modules))
diagnoseMissingImport(Loc, Spec, Spec->getLocation(), Modules,
MissingImportKind::PartialSpecialization,
/*Recover*/true);
}
Index: vendor/clang/dist-release_80/lib/Sema/SemaType.cpp
===================================================================
--- vendor/clang/dist-release_80/lib/Sema/SemaType.cpp (revision 343795)
+++ vendor/clang/dist-release_80/lib/Sema/SemaType.cpp (revision 343796)
@@ -1,8219 +1,8224 @@
//===--- SemaType.cpp - Semantic Analysis for Types -----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements type-related semantic analysis.
//
//===----------------------------------------------------------------------===//
#include "TypeLocBuilder.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/ASTStructuralEquivalence.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeLocVisitor.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateInstCallback.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
enum TypeDiagSelector {
TDS_Function,
TDS_Pointer,
TDS_ObjCObjOrBlock
};
/// isOmittedBlockReturnType - Return true if this declarator is missing a
/// return type because this is a omitted return type on a block literal.
static bool isOmittedBlockReturnType(const Declarator &D) {
if (D.getContext() != DeclaratorContext::BlockLiteralContext ||
D.getDeclSpec().hasTypeSpecifier())
return false;
if (D.getNumTypeObjects() == 0)
return true; // ^{ ... }
if (D.getNumTypeObjects() == 1 &&
D.getTypeObject(0).Kind == DeclaratorChunk::Function)
return true; // ^(int X, float Y) { ... }
return false;
}
/// diagnoseBadTypeAttribute - Diagnoses a type attribute which
/// doesn't apply to the given type.
static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr,
QualType type) {
TypeDiagSelector WhichType;
bool useExpansionLoc = true;
switch (attr.getKind()) {
case ParsedAttr::AT_ObjCGC:
WhichType = TDS_Pointer;
break;
case ParsedAttr::AT_ObjCOwnership:
WhichType = TDS_ObjCObjOrBlock;
break;
default:
// Assume everything else was a function attribute.
WhichType = TDS_Function;
useExpansionLoc = false;
break;
}
SourceLocation loc = attr.getLoc();
StringRef name = attr.getName()->getName();
// The GC attributes are usually written with macros; special-case them.
IdentifierInfo *II = attr.isArgIdent(0) ? attr.getArgAsIdent(0)->Ident
: nullptr;
if (useExpansionLoc && loc.isMacroID() && II) {
if (II->isStr("strong")) {
if (S.findMacroSpelling(loc, "__strong")) name = "__strong";
} else if (II->isStr("weak")) {
if (S.findMacroSpelling(loc, "__weak")) name = "__weak";
}
}
S.Diag(loc, diag::warn_type_attribute_wrong_type) << name << WhichType
<< type;
}
// objc_gc applies to Objective-C pointers or, otherwise, to the
// smallest available pointer type (i.e. 'void*' in 'void**').
#define OBJC_POINTER_TYPE_ATTRS_CASELIST \
case ParsedAttr::AT_ObjCGC: \
case ParsedAttr::AT_ObjCOwnership
// Calling convention attributes.
#define CALLING_CONV_ATTRS_CASELIST \
case ParsedAttr::AT_CDecl: \
case ParsedAttr::AT_FastCall: \
case ParsedAttr::AT_StdCall: \
case ParsedAttr::AT_ThisCall: \
case ParsedAttr::AT_RegCall: \
case ParsedAttr::AT_Pascal: \
case ParsedAttr::AT_SwiftCall: \
case ParsedAttr::AT_VectorCall: \
case ParsedAttr::AT_AArch64VectorPcs: \
case ParsedAttr::AT_MSABI: \
case ParsedAttr::AT_SysVABI: \
case ParsedAttr::AT_Pcs: \
case ParsedAttr::AT_IntelOclBicc: \
case ParsedAttr::AT_PreserveMost: \
case ParsedAttr::AT_PreserveAll
// Function type attributes.
#define FUNCTION_TYPE_ATTRS_CASELIST \
case ParsedAttr::AT_NSReturnsRetained: \
case ParsedAttr::AT_NoReturn: \
case ParsedAttr::AT_Regparm: \
case ParsedAttr::AT_AnyX86NoCallerSavedRegisters: \
case ParsedAttr::AT_AnyX86NoCfCheck: \
CALLING_CONV_ATTRS_CASELIST
// Microsoft-specific type qualifiers.
#define MS_TYPE_ATTRS_CASELIST \
case ParsedAttr::AT_Ptr32: \
case ParsedAttr::AT_Ptr64: \
case ParsedAttr::AT_SPtr: \
case ParsedAttr::AT_UPtr
// Nullability qualifiers.
#define NULLABILITY_TYPE_ATTRS_CASELIST \
case ParsedAttr::AT_TypeNonNull: \
case ParsedAttr::AT_TypeNullable: \
case ParsedAttr::AT_TypeNullUnspecified
namespace {
/// An object which stores processing state for the entire
/// GetTypeForDeclarator process.
class TypeProcessingState {
Sema &sema;
/// The declarator being processed.
Declarator &declarator;
/// The index of the declarator chunk we're currently processing.
/// May be the total number of valid chunks, indicating the
/// DeclSpec.
unsigned chunkIndex;
/// Whether there are non-trivial modifications to the decl spec.
bool trivial;
/// Whether we saved the attributes in the decl spec.
bool hasSavedAttrs;
/// The original set of attributes on the DeclSpec.
SmallVector<ParsedAttr *, 2> savedAttrs;
/// A list of attributes to diagnose the uselessness of when the
/// processing is complete.
SmallVector<ParsedAttr *, 2> ignoredTypeAttrs;
/// Attributes corresponding to AttributedTypeLocs that we have not yet
/// populated.
// FIXME: The two-phase mechanism by which we construct Types and fill
// their TypeLocs makes it hard to correctly assign these. We keep the
// attributes in creation order as an attempt to make them line up
// properly.
using TypeAttrPair = std::pair<const AttributedType*, const Attr*>;
SmallVector<TypeAttrPair, 8> AttrsForTypes;
bool AttrsForTypesSorted = true;
/// Flag to indicate we parsed a noderef attribute. This is used for
/// validating that noderef was used on a pointer or array.
bool parsedNoDeref;
public:
TypeProcessingState(Sema &sema, Declarator &declarator)
: sema(sema), declarator(declarator),
chunkIndex(declarator.getNumTypeObjects()), trivial(true),
hasSavedAttrs(false), parsedNoDeref(false) {}
Sema &getSema() const {
return sema;
}
Declarator &getDeclarator() const {
return declarator;
}
bool isProcessingDeclSpec() const {
return chunkIndex == declarator.getNumTypeObjects();
}
unsigned getCurrentChunkIndex() const {
return chunkIndex;
}
void setCurrentChunkIndex(unsigned idx) {
assert(idx <= declarator.getNumTypeObjects());
chunkIndex = idx;
}
ParsedAttributesView &getCurrentAttributes() const {
if (isProcessingDeclSpec())
return getMutableDeclSpec().getAttributes();
return declarator.getTypeObject(chunkIndex).getAttrs();
}
/// Save the current set of attributes on the DeclSpec.
void saveDeclSpecAttrs() {
// Don't try to save them multiple times.
if (hasSavedAttrs) return;
DeclSpec &spec = getMutableDeclSpec();
for (ParsedAttr &AL : spec.getAttributes())
savedAttrs.push_back(&AL);
trivial &= savedAttrs.empty();
hasSavedAttrs = true;
}
/// Record that we had nowhere to put the given type attribute.
/// We will diagnose such attributes later.
void addIgnoredTypeAttr(ParsedAttr &attr) {
ignoredTypeAttrs.push_back(&attr);
}
/// Diagnose all the ignored type attributes, given that the
/// declarator worked out to the given type.
void diagnoseIgnoredTypeAttrs(QualType type) const {
for (auto *Attr : ignoredTypeAttrs)
diagnoseBadTypeAttribute(getSema(), *Attr, type);
}
/// Get an attributed type for the given attribute, and remember the Attr
/// object so that we can attach it to the AttributedTypeLoc.
QualType getAttributedType(Attr *A, QualType ModifiedType,
QualType EquivType) {
QualType T =
sema.Context.getAttributedType(A->getKind(), ModifiedType, EquivType);
AttrsForTypes.push_back({cast<AttributedType>(T.getTypePtr()), A});
AttrsForTypesSorted = false;
return T;
}
/// Extract and remove the Attr* for a given attributed type.
const Attr *takeAttrForAttributedType(const AttributedType *AT) {
if (!AttrsForTypesSorted) {
std::stable_sort(AttrsForTypes.begin(), AttrsForTypes.end(),
[](const TypeAttrPair &A, const TypeAttrPair &B) {
return A.first < B.first;
});
AttrsForTypesSorted = true;
}
// FIXME: This is quadratic if we have lots of reuses of the same
// attributed type.
for (auto It = std::partition_point(
AttrsForTypes.begin(), AttrsForTypes.end(),
[=](const TypeAttrPair &A) { return A.first < AT; });
It != AttrsForTypes.end() && It->first == AT; ++It) {
if (It->second) {
const Attr *Result = It->second;
It->second = nullptr;
return Result;
}
}
llvm_unreachable("no Attr* for AttributedType*");
}
void setParsedNoDeref(bool parsed) { parsedNoDeref = parsed; }
bool didParseNoDeref() const { return parsedNoDeref; }
~TypeProcessingState() {
if (trivial) return;
restoreDeclSpecAttrs();
}
private:
DeclSpec &getMutableDeclSpec() const {
return const_cast<DeclSpec&>(declarator.getDeclSpec());
}
void restoreDeclSpecAttrs() {
assert(hasSavedAttrs);
getMutableDeclSpec().getAttributes().clearListOnly();
for (ParsedAttr *AL : savedAttrs)
getMutableDeclSpec().getAttributes().addAtEnd(AL);
}
};
} // end anonymous namespace
static void moveAttrFromListToList(ParsedAttr &attr,
ParsedAttributesView &fromList,
ParsedAttributesView &toList) {
fromList.remove(&attr);
toList.addAtEnd(&attr);
}
/// The location of a type attribute.
enum TypeAttrLocation {
/// The attribute is in the decl-specifier-seq.
TAL_DeclSpec,
/// The attribute is part of a DeclaratorChunk.
TAL_DeclChunk,
/// The attribute is immediately after the declaration's name.
TAL_DeclName
};
static void processTypeAttrs(TypeProcessingState &state, QualType &type,
TypeAttrLocation TAL, ParsedAttributesView &attrs);
static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
QualType &type);
static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &state,
ParsedAttr &attr, QualType &type);
static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
QualType &type);
static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
ParsedAttr &attr, QualType &type);
static bool handleObjCPointerTypeAttr(TypeProcessingState &state,
ParsedAttr &attr, QualType &type) {
if (attr.getKind() == ParsedAttr::AT_ObjCGC)
return handleObjCGCTypeAttr(state, attr, type);
assert(attr.getKind() == ParsedAttr::AT_ObjCOwnership);
return handleObjCOwnershipTypeAttr(state, attr, type);
}
/// Given the index of a declarator chunk, check whether that chunk
/// directly specifies the return type of a function and, if so, find
/// an appropriate place for it.
///
/// \param i - a notional index which the search will start
/// immediately inside
///
/// \param onlyBlockPointers Whether we should only look into block
/// pointer types (vs. all pointer types).
static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
unsigned i,
bool onlyBlockPointers) {
assert(i <= declarator.getNumTypeObjects());
DeclaratorChunk *result = nullptr;
// First, look inwards past parens for a function declarator.
for (; i != 0; --i) {
DeclaratorChunk &fnChunk = declarator.getTypeObject(i-1);
switch (fnChunk.Kind) {
case DeclaratorChunk::Paren:
continue;
// If we find anything except a function, bail out.
case DeclaratorChunk::Pointer:
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::Array:
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Pipe:
return result;
// If we do find a function declarator, scan inwards from that,
// looking for a (block-)pointer declarator.
case DeclaratorChunk::Function:
for (--i; i != 0; --i) {
DeclaratorChunk &ptrChunk = declarator.getTypeObject(i-1);
switch (ptrChunk.Kind) {
case DeclaratorChunk::Paren:
case DeclaratorChunk::Array:
case DeclaratorChunk::Function:
case DeclaratorChunk::Reference:
case DeclaratorChunk::Pipe:
continue;
case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Pointer:
if (onlyBlockPointers)
continue;
LLVM_FALLTHROUGH;
case DeclaratorChunk::BlockPointer:
result = &ptrChunk;
goto continue_outer;
}
llvm_unreachable("bad declarator chunk kind");
}
// If we run out of declarators doing that, we're done.
return result;
}
llvm_unreachable("bad declarator chunk kind");
// Okay, reconsider from our new point.
continue_outer: ;
}
// Ran out of chunks, bail out.
return result;
}
/// Given that an objc_gc attribute was written somewhere on a
/// declaration *other* than on the declarator itself (for which, use
/// distributeObjCPointerTypeAttrFromDeclarator), and given that it
/// didn't apply in whatever position it was written in, try to move
/// it to a more appropriate position.
static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
ParsedAttr &attr, QualType type) {
Declarator &declarator = state.getDeclarator();
// Move it to the outermost normal or block pointer declarator.
for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
switch (chunk.Kind) {
case DeclaratorChunk::Pointer:
case DeclaratorChunk::BlockPointer: {
// But don't move an ARC ownership attribute to the return type
// of a block.
DeclaratorChunk *destChunk = nullptr;
if (state.isProcessingDeclSpec() &&
attr.getKind() == ParsedAttr::AT_ObjCOwnership)
destChunk = maybeMovePastReturnType(declarator, i - 1,
/*onlyBlockPointers=*/true);
if (!destChunk) destChunk = &chunk;
moveAttrFromListToList(attr, state.getCurrentAttributes(),
destChunk->getAttrs());
return;
}
case DeclaratorChunk::Paren:
case DeclaratorChunk::Array:
continue;
// We may be starting at the return type of a block.
case DeclaratorChunk::Function:
if (state.isProcessingDeclSpec() &&
attr.getKind() == ParsedAttr::AT_ObjCOwnership) {
if (DeclaratorChunk *dest = maybeMovePastReturnType(
declarator, i,
/*onlyBlockPointers=*/true)) {
moveAttrFromListToList(attr, state.getCurrentAttributes(),
dest->getAttrs());
return;
}
}
goto error;
// Don't walk through these.
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Pipe:
goto error;
}
}
error:
diagnoseBadTypeAttribute(state.getSema(), attr, type);
}
/// Distribute an objc_gc type attribute that was written on the
/// declarator.
static void distributeObjCPointerTypeAttrFromDeclarator(
TypeProcessingState &state, ParsedAttr &attr, QualType &declSpecType) {
Declarator &declarator = state.getDeclarator();
// objc_gc goes on the innermost pointer to something that's not a
// pointer.
unsigned innermost = -1U;
bool considerDeclSpec = true;
for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
DeclaratorChunk &chunk = declarator.getTypeObject(i);
switch (chunk.Kind) {
case DeclaratorChunk::Pointer:
case DeclaratorChunk::BlockPointer:
innermost = i;
continue;
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Paren:
case DeclaratorChunk::Array:
case DeclaratorChunk::Pipe:
continue;
case DeclaratorChunk::Function:
considerDeclSpec = false;
goto done;
}
}
done:
// That might actually be the decl spec if we weren't blocked by
// anything in the declarator.
if (considerDeclSpec) {
if (handleObjCPointerTypeAttr(state, attr, declSpecType)) {
// Splice the attribute into the decl spec. Prevents the
// attribute from being applied multiple times and gives
// the source-location-filler something to work with.
state.saveDeclSpecAttrs();
moveAttrFromListToList(attr, declarator.getAttributes(),
declarator.getMutableDeclSpec().getAttributes());
return;
}
}
// Otherwise, if we found an appropriate chunk, splice the attribute
// into it.
if (innermost != -1U) {
moveAttrFromListToList(attr, declarator.getAttributes(),
declarator.getTypeObject(innermost).getAttrs());
return;
}
// Otherwise, diagnose when we're done building the type.
declarator.getAttributes().remove(&attr);
state.addIgnoredTypeAttr(attr);
}
/// A function type attribute was written somewhere in a declaration
/// *other* than on the declarator itself or in the decl spec. Given
/// that it didn't apply in whatever position it was written in, try
/// to move it to a more appropriate position.
static void distributeFunctionTypeAttr(TypeProcessingState &state,
ParsedAttr &attr, QualType type) {
Declarator &declarator = state.getDeclarator();
// Try to push the attribute from the return type of a function to
// the function itself.
for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
switch (chunk.Kind) {
case DeclaratorChunk::Function:
moveAttrFromListToList(attr, state.getCurrentAttributes(),
chunk.getAttrs());
return;
case DeclaratorChunk::Paren:
case DeclaratorChunk::Pointer:
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::Array:
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Pipe:
continue;
}
}
diagnoseBadTypeAttribute(state.getSema(), attr, type);
}
/// Try to distribute a function type attribute to the innermost
/// function chunk or type. Returns true if the attribute was
/// distributed, false if no location was found.
static bool distributeFunctionTypeAttrToInnermost(
TypeProcessingState &state, ParsedAttr &attr,
ParsedAttributesView &attrList, QualType &declSpecType) {
Declarator &declarator = state.getDeclarator();
// Put it on the innermost function chunk, if there is one.
for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
DeclaratorChunk &chunk = declarator.getTypeObject(i);
if (chunk.Kind != DeclaratorChunk::Function) continue;
moveAttrFromListToList(attr, attrList, chunk.getAttrs());
return true;
}
return handleFunctionTypeAttr(state, attr, declSpecType);
}
/// A function type attribute was written in the decl spec. Try to
/// apply it somewhere.
static void distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
ParsedAttr &attr,
QualType &declSpecType) {
state.saveDeclSpecAttrs();
// C++11 attributes before the decl specifiers actually appertain to
// the declarators. Move them straight there. We don't support the
// 'put them wherever you like' semantics we allow for GNU attributes.
if (attr.isCXX11Attribute()) {
moveAttrFromListToList(attr, state.getCurrentAttributes(),
state.getDeclarator().getAttributes());
return;
}
// Try to distribute to the innermost.
if (distributeFunctionTypeAttrToInnermost(
state, attr, state.getCurrentAttributes(), declSpecType))
return;
// If that failed, diagnose the bad attribute when the declarator is
// fully built.
state.addIgnoredTypeAttr(attr);
}
/// A function type attribute was written on the declarator. Try to
/// apply it somewhere.
static void distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state,
ParsedAttr &attr,
QualType &declSpecType) {
Declarator &declarator = state.getDeclarator();
// Try to distribute to the innermost.
if (distributeFunctionTypeAttrToInnermost(
state, attr, declarator.getAttributes(), declSpecType))
return;
// If that failed, diagnose the bad attribute when the declarator is
// fully built.
declarator.getAttributes().remove(&attr);
state.addIgnoredTypeAttr(attr);
}
/// Given that there are attributes written on the declarator
/// itself, try to distribute any type attributes to the appropriate
/// declarator chunk.
///
/// These are attributes like the following:
/// int f ATTR;
/// int (f ATTR)();
/// but not necessarily this:
/// int f() ATTR;
static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
QualType &declSpecType) {
// Collect all the type attributes from the declarator itself.
assert(!state.getDeclarator().getAttributes().empty() &&
"declarator has no attrs!");
// The called functions in this loop actually remove things from the current
// list, so iterating over the existing list isn't possible. Instead, make a
// non-owning copy and iterate over that.
ParsedAttributesView AttrsCopy{state.getDeclarator().getAttributes()};
for (ParsedAttr &attr : AttrsCopy) {
// Do not distribute C++11 attributes. They have strict rules for what
// they appertain to.
if (attr.isCXX11Attribute())
continue;
switch (attr.getKind()) {
OBJC_POINTER_TYPE_ATTRS_CASELIST:
distributeObjCPointerTypeAttrFromDeclarator(state, attr, declSpecType);
break;
FUNCTION_TYPE_ATTRS_CASELIST:
distributeFunctionTypeAttrFromDeclarator(state, attr, declSpecType);
break;
MS_TYPE_ATTRS_CASELIST:
// Microsoft type attributes cannot go after the declarator-id.
continue;
NULLABILITY_TYPE_ATTRS_CASELIST:
// Nullability specifiers cannot go after the declarator-id.
// Objective-C __kindof does not get distributed.
case ParsedAttr::AT_ObjCKindOf:
continue;
default:
break;
}
}
}
/// Add a synthetic '()' to a block-literal declarator if it is
/// required, given the return type.
static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
QualType declSpecType) {
Declarator &declarator = state.getDeclarator();
// First, check whether the declarator would produce a function,
// i.e. whether the innermost semantic chunk is a function.
if (declarator.isFunctionDeclarator()) {
// If so, make that declarator a prototyped declarator.
declarator.getFunctionTypeInfo().hasPrototype = true;
return;
}
// If there are any type objects, the type as written won't name a
// function, regardless of the decl spec type. This is because a
// block signature declarator is always an abstract-declarator, and
// abstract-declarators can't just be parentheses chunks. Therefore
// we need to build a function chunk unless there are no type
// objects and the decl spec type is a function.
if (!declarator.getNumTypeObjects() && declSpecType->isFunctionType())
return;
// Note that there *are* cases with invalid declarators where
// declarators consist solely of parentheses. In general, these
// occur only in failed efforts to make function declarators, so
// faking up the function chunk is still the right thing to do.
// Otherwise, we need to fake up a function declarator.
SourceLocation loc = declarator.getBeginLoc();
// ...and *prepend* it to the declarator.
SourceLocation NoLoc;
declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction(
/*HasProto=*/true,
/*IsAmbiguous=*/false,
/*LParenLoc=*/NoLoc,
/*ArgInfo=*/nullptr,
/*NumArgs=*/0,
/*EllipsisLoc=*/NoLoc,
/*RParenLoc=*/NoLoc,
/*RefQualifierIsLvalueRef=*/true,
/*RefQualifierLoc=*/NoLoc,
/*MutableLoc=*/NoLoc, EST_None,
/*ESpecRange=*/SourceRange(),
/*Exceptions=*/nullptr,
/*ExceptionRanges=*/nullptr,
/*NumExceptions=*/0,
/*NoexceptExpr=*/nullptr,
/*ExceptionSpecTokens=*/nullptr,
/*DeclsInPrototype=*/None, loc, loc, declarator));
// For consistency, make sure the state still has us as processing
// the decl spec.
assert(state.getCurrentChunkIndex() == declarator.getNumTypeObjects() - 1);
state.setCurrentChunkIndex(declarator.getNumTypeObjects());
}
static void diagnoseAndRemoveTypeQualifiers(Sema &S, const DeclSpec &DS,
unsigned &TypeQuals,
QualType TypeSoFar,
unsigned RemoveTQs,
unsigned DiagID) {
// If this occurs outside a template instantiation, warn the user about
// it; they probably didn't mean to specify a redundant qualifier.
typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc;
for (QualLoc Qual : {QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()),
QualLoc(DeclSpec::TQ_restrict, DS.getRestrictSpecLoc()),
QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()),
QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())}) {
if (!(RemoveTQs & Qual.first))
continue;
if (!S.inTemplateInstantiation()) {
if (TypeQuals & Qual.first)
S.Diag(Qual.second, DiagID)
<< DeclSpec::getSpecifierName(Qual.first) << TypeSoFar
<< FixItHint::CreateRemoval(Qual.second);
}
TypeQuals &= ~Qual.first;
}
}
/// Return true if this is omitted block return type. Also check type
/// attributes and type qualifiers when returning true.
static bool checkOmittedBlockReturnType(Sema &S, Declarator &declarator,
QualType Result) {
if (!isOmittedBlockReturnType(declarator))
return false;
// Warn if we see type attributes for omitted return type on a block literal.
SmallVector<ParsedAttr *, 2> ToBeRemoved;
for (ParsedAttr &AL : declarator.getMutableDeclSpec().getAttributes()) {
if (AL.isInvalid() || !AL.isTypeAttr())
continue;
S.Diag(AL.getLoc(),
diag::warn_block_literal_attributes_on_omitted_return_type)
<< AL.getName();
ToBeRemoved.push_back(&AL);
}
// Remove bad attributes from the list.
for (ParsedAttr *AL : ToBeRemoved)
declarator.getMutableDeclSpec().getAttributes().remove(AL);
// Warn if we see type qualifiers for omitted return type on a block literal.
const DeclSpec &DS = declarator.getDeclSpec();
unsigned TypeQuals = DS.getTypeQualifiers();
diagnoseAndRemoveTypeQualifiers(S, DS, TypeQuals, Result, (unsigned)-1,
diag::warn_block_literal_qualifiers_on_omitted_return_type);
declarator.getMutableDeclSpec().ClearTypeQualifiers();
return true;
}
/// Apply Objective-C type arguments to the given type.
static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
ArrayRef<TypeSourceInfo *> typeArgs,
SourceRange typeArgsRange,
bool failOnError = false) {
// We can only apply type arguments to an Objective-C class type.
const auto *objcObjectType = type->getAs<ObjCObjectType>();
if (!objcObjectType || !objcObjectType->getInterface()) {
S.Diag(loc, diag::err_objc_type_args_non_class)
<< type
<< typeArgsRange;
if (failOnError)
return QualType();
return type;
}
// The class type must be parameterized.
ObjCInterfaceDecl *objcClass = objcObjectType->getInterface();
ObjCTypeParamList *typeParams = objcClass->getTypeParamList();
if (!typeParams) {
S.Diag(loc, diag::err_objc_type_args_non_parameterized_class)
<< objcClass->getDeclName()
<< FixItHint::CreateRemoval(typeArgsRange);
if (failOnError)
return QualType();
return type;
}
// The type must not already be specialized.
if (objcObjectType->isSpecialized()) {
S.Diag(loc, diag::err_objc_type_args_specialized_class)
<< type
<< FixItHint::CreateRemoval(typeArgsRange);
if (failOnError)
return QualType();
return type;
}
// Check the type arguments.
SmallVector<QualType, 4> finalTypeArgs;
unsigned numTypeParams = typeParams->size();
bool anyPackExpansions = false;
for (unsigned i = 0, n = typeArgs.size(); i != n; ++i) {
TypeSourceInfo *typeArgInfo = typeArgs[i];
QualType typeArg = typeArgInfo->getType();
// Type arguments cannot have explicit qualifiers or nullability.
// We ignore indirect sources of these, e.g. behind typedefs or
// template arguments.
if (TypeLoc qual = typeArgInfo->getTypeLoc().findExplicitQualifierLoc()) {
bool diagnosed = false;
SourceRange rangeToRemove;
if (auto attr = qual.getAs<AttributedTypeLoc>()) {
rangeToRemove = attr.getLocalSourceRange();
if (attr.getTypePtr()->getImmediateNullability()) {
typeArg = attr.getTypePtr()->getModifiedType();
S.Diag(attr.getBeginLoc(),
diag::err_objc_type_arg_explicit_nullability)
<< typeArg << FixItHint::CreateRemoval(rangeToRemove);
diagnosed = true;
}
}
if (!diagnosed) {
S.Diag(qual.getBeginLoc(), diag::err_objc_type_arg_qualified)
<< typeArg << typeArg.getQualifiers().getAsString()
<< FixItHint::CreateRemoval(rangeToRemove);
}
}
// Remove qualifiers even if they're non-local.
typeArg = typeArg.getUnqualifiedType();
finalTypeArgs.push_back(typeArg);
if (typeArg->getAs<PackExpansionType>())
anyPackExpansions = true;
// Find the corresponding type parameter, if there is one.
ObjCTypeParamDecl *typeParam = nullptr;
if (!anyPackExpansions) {
if (i < numTypeParams) {
typeParam = typeParams->begin()[i];
} else {
// Too many arguments.
S.Diag(loc, diag::err_objc_type_args_wrong_arity)
<< false
<< objcClass->getDeclName()
<< (unsigned)typeArgs.size()
<< numTypeParams;
S.Diag(objcClass->getLocation(), diag::note_previous_decl)
<< objcClass;
if (failOnError)
return QualType();
return type;
}
}
// Objective-C object pointer types must be substitutable for the bounds.
if (const auto *typeArgObjC = typeArg->getAs<ObjCObjectPointerType>()) {
// If we don't have a type parameter to match against, assume
// everything is fine. There was a prior pack expansion that
// means we won't be able to match anything.
if (!typeParam) {
assert(anyPackExpansions && "Too many arguments?");
continue;
}
// Retrieve the bound.
QualType bound = typeParam->getUnderlyingType();
const auto *boundObjC = bound->getAs<ObjCObjectPointerType>();
// Determine whether the type argument is substitutable for the bound.
if (typeArgObjC->isObjCIdType()) {
// When the type argument is 'id', the only acceptable type
// parameter bound is 'id'.
if (boundObjC->isObjCIdType())
continue;
} else if (S.Context.canAssignObjCInterfaces(boundObjC, typeArgObjC)) {
// Otherwise, we follow the assignability rules.
continue;
}
// Diagnose the mismatch.
S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),
diag::err_objc_type_arg_does_not_match_bound)
<< typeArg << bound << typeParam->getDeclName();
S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
<< typeParam->getDeclName();
if (failOnError)
return QualType();
return type;
}
// Block pointer types are permitted for unqualified 'id' bounds.
if (typeArg->isBlockPointerType()) {
// If we don't have a type parameter to match against, assume
// everything is fine. There was a prior pack expansion that
// means we won't be able to match anything.
if (!typeParam) {
assert(anyPackExpansions && "Too many arguments?");
continue;
}
// Retrieve the bound.
QualType bound = typeParam->getUnderlyingType();
if (bound->isBlockCompatibleObjCPointerType(S.Context))
continue;
// Diagnose the mismatch.
S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),
diag::err_objc_type_arg_does_not_match_bound)
<< typeArg << bound << typeParam->getDeclName();
S.Diag(typeParam->getLocation(), diag::note_objc_type_param_here)
<< typeParam->getDeclName();
if (failOnError)
return QualType();
return type;
}
// Dependent types will be checked at instantiation time.
if (typeArg->isDependentType()) {
continue;
}
// Diagnose non-id-compatible type arguments.
S.Diag(typeArgInfo->getTypeLoc().getBeginLoc(),
diag::err_objc_type_arg_not_id_compatible)
<< typeArg << typeArgInfo->getTypeLoc().getSourceRange();
if (failOnError)
return QualType();
return type;
}
// Make sure we didn't have the wrong number of arguments.
if (!anyPackExpansions && finalTypeArgs.size() != numTypeParams) {
S.Diag(loc, diag::err_objc_type_args_wrong_arity)
<< (typeArgs.size() < typeParams->size())
<< objcClass->getDeclName()
<< (unsigned)finalTypeArgs.size()
<< (unsigned)numTypeParams;
S.Diag(objcClass->getLocation(), diag::note_previous_decl)
<< objcClass;
if (failOnError)
return QualType();
return type;
}
// Success. Form the specialized type.
return S.Context.getObjCObjectType(type, finalTypeArgs, { }, false);
}
QualType Sema::BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
SourceLocation ProtocolLAngleLoc,
ArrayRef<ObjCProtocolDecl *> Protocols,
ArrayRef<SourceLocation> ProtocolLocs,
SourceLocation ProtocolRAngleLoc,
bool FailOnError) {
QualType Result = QualType(Decl->getTypeForDecl(), 0);
if (!Protocols.empty()) {
bool HasError;
Result = Context.applyObjCProtocolQualifiers(Result, Protocols,
HasError);
if (HasError) {
Diag(SourceLocation(), diag::err_invalid_protocol_qualifiers)
<< SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc);
if (FailOnError) Result = QualType();
}
if (FailOnError && Result.isNull())
return QualType();
}
return Result;
}
QualType Sema::BuildObjCObjectType(QualType BaseType,
SourceLocation Loc,
SourceLocation TypeArgsLAngleLoc,
ArrayRef<TypeSourceInfo *> TypeArgs,
SourceLocation TypeArgsRAngleLoc,
SourceLocation ProtocolLAngleLoc,
ArrayRef<ObjCProtocolDecl *> Protocols,
ArrayRef<SourceLocation> ProtocolLocs,
SourceLocation ProtocolRAngleLoc,
bool FailOnError) {
QualType Result = BaseType;
if (!TypeArgs.empty()) {
Result = applyObjCTypeArgs(*this, Loc, Result, TypeArgs,
SourceRange(TypeArgsLAngleLoc,
TypeArgsRAngleLoc),
FailOnError);
if (FailOnError && Result.isNull())
return QualType();
}
if (!Protocols.empty()) {
bool HasError;
Result = Context.applyObjCProtocolQualifiers(Result, Protocols,
HasError);
if (HasError) {
Diag(Loc, diag::err_invalid_protocol_qualifiers)
<< SourceRange(ProtocolLAngleLoc, ProtocolRAngleLoc);
if (FailOnError) Result = QualType();
}
if (FailOnError && Result.isNull())
return QualType();
}
return Result;
}
TypeResult Sema::actOnObjCProtocolQualifierType(
SourceLocation lAngleLoc,
ArrayRef<Decl *> protocols,
ArrayRef<SourceLocation> protocolLocs,
SourceLocation rAngleLoc) {
// Form id<protocol-list>.
QualType Result = Context.getObjCObjectType(
Context.ObjCBuiltinIdTy, { },
llvm::makeArrayRef(
(ObjCProtocolDecl * const *)protocols.data(),
protocols.size()),
false);
Result = Context.getObjCObjectPointerType(Result);
TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result);
TypeLoc ResultTL = ResultTInfo->getTypeLoc();
auto ObjCObjectPointerTL = ResultTL.castAs<ObjCObjectPointerTypeLoc>();
ObjCObjectPointerTL.setStarLoc(SourceLocation()); // implicit
auto ObjCObjectTL = ObjCObjectPointerTL.getPointeeLoc()
.castAs<ObjCObjectTypeLoc>();
ObjCObjectTL.setHasBaseTypeAsWritten(false);
ObjCObjectTL.getBaseLoc().initialize(Context, SourceLocation());
// No type arguments.
ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation());
ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation());
// Fill in protocol qualifiers.
ObjCObjectTL.setProtocolLAngleLoc(lAngleLoc);
ObjCObjectTL.setProtocolRAngleLoc(rAngleLoc);
for (unsigned i = 0, n = protocols.size(); i != n; ++i)
ObjCObjectTL.setProtocolLoc(i, protocolLocs[i]);
// We're done. Return the completed type to the parser.
return CreateParsedType(Result, ResultTInfo);
}
TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers(
Scope *S,
SourceLocation Loc,
ParsedType BaseType,
SourceLocation TypeArgsLAngleLoc,
ArrayRef<ParsedType> TypeArgs,
SourceLocation TypeArgsRAngleLoc,
SourceLocation ProtocolLAngleLoc,
ArrayRef<Decl *> Protocols,
ArrayRef<SourceLocation> ProtocolLocs,
SourceLocation ProtocolRAngleLoc) {
TypeSourceInfo *BaseTypeInfo = nullptr;
QualType T = GetTypeFromParser(BaseType, &BaseTypeInfo);
if (T.isNull())
return true;
// Handle missing type-source info.
if (!BaseTypeInfo)
BaseTypeInfo = Context.getTrivialTypeSourceInfo(T, Loc);
// Extract type arguments.
SmallVector<TypeSourceInfo *, 4> ActualTypeArgInfos;
for (unsigned i = 0, n = TypeArgs.size(); i != n; ++i) {
TypeSourceInfo *TypeArgInfo = nullptr;
QualType TypeArg = GetTypeFromParser(TypeArgs[i], &TypeArgInfo);
if (TypeArg.isNull()) {
ActualTypeArgInfos.clear();
break;
}
assert(TypeArgInfo && "No type source info?");
ActualTypeArgInfos.push_back(TypeArgInfo);
}
// Build the object type.
QualType Result = BuildObjCObjectType(
T, BaseTypeInfo->getTypeLoc().getSourceRange().getBegin(),
TypeArgsLAngleLoc, ActualTypeArgInfos, TypeArgsRAngleLoc,
ProtocolLAngleLoc,
llvm::makeArrayRef((ObjCProtocolDecl * const *)Protocols.data(),
Protocols.size()),
ProtocolLocs, ProtocolRAngleLoc,
/*FailOnError=*/false);
if (Result == T)
return BaseType;
// Create source information for this type.
TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result);
TypeLoc ResultTL = ResultTInfo->getTypeLoc();
// For id<Proto1, Proto2> or Class<Proto1, Proto2>, we'll have an
// object pointer type. Fill in source information for it.
if (auto ObjCObjectPointerTL = ResultTL.getAs<ObjCObjectPointerTypeLoc>()) {
// The '*' is implicit.
ObjCObjectPointerTL.setStarLoc(SourceLocation());
ResultTL = ObjCObjectPointerTL.getPointeeLoc();
}
if (auto OTPTL = ResultTL.getAs<ObjCTypeParamTypeLoc>()) {
// Protocol qualifier information.
if (OTPTL.getNumProtocols() > 0) {
assert(OTPTL.getNumProtocols() == Protocols.size());
OTPTL.setProtocolLAngleLoc(ProtocolLAngleLoc);
OTPTL.setProtocolRAngleLoc(ProtocolRAngleLoc);
for (unsigned i = 0, n = Protocols.size(); i != n; ++i)
OTPTL.setProtocolLoc(i, ProtocolLocs[i]);
}
// We're done. Return the completed type to the parser.
return CreateParsedType(Result, ResultTInfo);
}
auto ObjCObjectTL = ResultTL.castAs<ObjCObjectTypeLoc>();
// Type argument information.
if (ObjCObjectTL.getNumTypeArgs() > 0) {
assert(ObjCObjectTL.getNumTypeArgs() == ActualTypeArgInfos.size());
ObjCObjectTL.setTypeArgsLAngleLoc(TypeArgsLAngleLoc);
ObjCObjectTL.setTypeArgsRAngleLoc(TypeArgsRAngleLoc);
for (unsigned i = 0, n = ActualTypeArgInfos.size(); i != n; ++i)
ObjCObjectTL.setTypeArgTInfo(i, ActualTypeArgInfos[i]);
} else {
ObjCObjectTL.setTypeArgsLAngleLoc(SourceLocation());
ObjCObjectTL.setTypeArgsRAngleLoc(SourceLocation());
}
// Protocol qualifier information.
if (ObjCObjectTL.getNumProtocols() > 0) {
assert(ObjCObjectTL.getNumProtocols() == Protocols.size());
ObjCObjectTL.setProtocolLAngleLoc(ProtocolLAngleLoc);
ObjCObjectTL.setProtocolRAngleLoc(ProtocolRAngleLoc);
for (unsigned i = 0, n = Protocols.size(); i != n; ++i)
ObjCObjectTL.setProtocolLoc(i, ProtocolLocs[i]);
} else {
ObjCObjectTL.setProtocolLAngleLoc(SourceLocation());
ObjCObjectTL.setProtocolRAngleLoc(SourceLocation());
}
// Base type.
ObjCObjectTL.setHasBaseTypeAsWritten(true);
if (ObjCObjectTL.getType() == T)
ObjCObjectTL.getBaseLoc().initializeFullCopy(BaseTypeInfo->getTypeLoc());
else
ObjCObjectTL.getBaseLoc().initialize(Context, Loc);
// We're done. Return the completed type to the parser.
return CreateParsedType(Result, ResultTInfo);
}
static OpenCLAccessAttr::Spelling
getImageAccess(const ParsedAttributesView &Attrs) {
for (const ParsedAttr &AL : Attrs)
if (AL.getKind() == ParsedAttr::AT_OpenCLAccess)
return static_cast<OpenCLAccessAttr::Spelling>(AL.getSemanticSpelling());
return OpenCLAccessAttr::Keyword_read_only;
}
/// Convert the specified declspec to the appropriate type
/// object.
/// \param state Specifies the declarator containing the declaration specifier
/// to be converted, along with other associated processing state.
/// \returns The type described by the declaration specifiers. This function
/// never returns null.
static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// FIXME: Should move the logic from DeclSpec::Finish to here for validity
// checking.
Sema &S = state.getSema();
Declarator &declarator = state.getDeclarator();
DeclSpec &DS = declarator.getMutableDeclSpec();
SourceLocation DeclLoc = declarator.getIdentifierLoc();
if (DeclLoc.isInvalid())
DeclLoc = DS.getBeginLoc();
ASTContext &Context = S.Context;
QualType Result;
switch (DS.getTypeSpecType()) {
case DeclSpec::TST_void:
Result = Context.VoidTy;
break;
case DeclSpec::TST_char:
if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
Result = Context.CharTy;
else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed)
Result = Context.SignedCharTy;
else {
assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
"Unknown TSS value");
Result = Context.UnsignedCharTy;
}
break;
case DeclSpec::TST_wchar:
if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
Result = Context.WCharTy;
else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
<< DS.getSpecifierName(DS.getTypeSpecType(),
Context.getPrintingPolicy());
Result = Context.getSignedWCharType();
} else {
assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
"Unknown TSS value");
S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
<< DS.getSpecifierName(DS.getTypeSpecType(),
Context.getPrintingPolicy());
Result = Context.getUnsignedWCharType();
}
break;
case DeclSpec::TST_char8:
assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
"Unknown TSS value");
Result = Context.Char8Ty;
break;
case DeclSpec::TST_char16:
assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
"Unknown TSS value");
Result = Context.Char16Ty;
break;
case DeclSpec::TST_char32:
assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
"Unknown TSS value");
Result = Context.Char32Ty;
break;
case DeclSpec::TST_unspecified:
// If this is a missing declspec in a block literal return context, then it
// is inferred from the return statements inside the block.
// The declspec is always missing in a lambda expr context; it is either
// specified with a trailing return type or inferred.
if (S.getLangOpts().CPlusPlus14 &&
declarator.getContext() == DeclaratorContext::LambdaExprContext) {
// In C++1y, a lambda's implicit return type is 'auto'.
Result = Context.getAutoDeductType();
break;
} else if (declarator.getContext() ==
DeclaratorContext::LambdaExprContext ||
checkOmittedBlockReturnType(S, declarator,
Context.DependentTy)) {
Result = Context.DependentTy;
break;
}
// Unspecified typespec defaults to int in C90. However, the C90 grammar
// [C90 6.5] only allows a decl-spec if there was *some* type-specifier,
// type-qualifier, or storage-class-specifier. If not, emit an extwarn.
// Note that the one exception to this is function definitions, which are
// allowed to be completely missing a declspec. This is handled in the
// parser already though by it pretending to have seen an 'int' in this
// case.
if (S.getLangOpts().ImplicitInt) {
// In C89 mode, we only warn if there is a completely missing declspec
// when one is not allowed.
if (DS.isEmpty()) {
S.Diag(DeclLoc, diag::ext_missing_declspec)
<< DS.getSourceRange()
<< FixItHint::CreateInsertion(DS.getBeginLoc(), "int");
}
} else if (!DS.hasTypeSpecifier()) {
// C99 and C++ require a type specifier. For example, C99 6.7.2p2 says:
// "At least one type specifier shall be given in the declaration
// specifiers in each declaration, and in the specifier-qualifier list in
// each struct declaration and type name."
if (S.getLangOpts().CPlusPlus) {
S.Diag(DeclLoc, diag::err_missing_type_specifier)
<< DS.getSourceRange();
// When this occurs in C++ code, often something is very broken with the
// value being declared, poison it as invalid so we don't get chains of
// errors.
declarator.setInvalidType(true);
} else if (S.getLangOpts().OpenCLVersion >= 200 && DS.isTypeSpecPipe()){
S.Diag(DeclLoc, diag::err_missing_actual_pipe_type)
<< DS.getSourceRange();
declarator.setInvalidType(true);
} else {
S.Diag(DeclLoc, diag::ext_missing_type_specifier)
<< DS.getSourceRange();
}
}
LLVM_FALLTHROUGH;
case DeclSpec::TST_int: {
if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
switch (DS.getTypeSpecWidth()) {
case DeclSpec::TSW_unspecified: Result = Context.IntTy; break;
case DeclSpec::TSW_short: Result = Context.ShortTy; break;
case DeclSpec::TSW_long: Result = Context.LongTy; break;
case DeclSpec::TSW_longlong:
Result = Context.LongLongTy;
// 'long long' is a C99 or C++11 feature.
if (!S.getLangOpts().C99) {
if (S.getLangOpts().CPlusPlus)
S.Diag(DS.getTypeSpecWidthLoc(),
S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
else
S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_c99_longlong);
}
break;
}
} else {
switch (DS.getTypeSpecWidth()) {
case DeclSpec::TSW_unspecified: Result = Context.UnsignedIntTy; break;
case DeclSpec::TSW_short: Result = Context.UnsignedShortTy; break;
case DeclSpec::TSW_long: Result = Context.UnsignedLongTy; break;
case DeclSpec::TSW_longlong:
Result = Context.UnsignedLongLongTy;
// 'long long' is a C99 or C++11 feature.
if (!S.getLangOpts().C99) {
if (S.getLangOpts().CPlusPlus)
S.Diag(DS.getTypeSpecWidthLoc(),
S.getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
else
S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_c99_longlong);
}
break;
}
}
break;
}
case DeclSpec::TST_accum: {
switch (DS.getTypeSpecWidth()) {
case DeclSpec::TSW_short:
Result = Context.ShortAccumTy;
break;
case DeclSpec::TSW_unspecified:
Result = Context.AccumTy;
break;
case DeclSpec::TSW_long:
Result = Context.LongAccumTy;
break;
case DeclSpec::TSW_longlong:
llvm_unreachable("Unable to specify long long as _Accum width");
}
if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
Result = Context.getCorrespondingUnsignedType(Result);
if (DS.isTypeSpecSat())
Result = Context.getCorrespondingSaturatedType(Result);
break;
}
case DeclSpec::TST_fract: {
switch (DS.getTypeSpecWidth()) {
case DeclSpec::TSW_short:
Result = Context.ShortFractTy;
break;
case DeclSpec::TSW_unspecified:
Result = Context.FractTy;
break;
case DeclSpec::TSW_long:
Result = Context.LongFractTy;
break;
case DeclSpec::TSW_longlong:
llvm_unreachable("Unable to specify long long as _Fract width");
}
if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
Result = Context.getCorrespondingUnsignedType(Result);
if (DS.isTypeSpecSat())
Result = Context.getCorrespondingSaturatedType(Result);
break;
}
case DeclSpec::TST_int128:
if (!S.Context.getTargetInfo().hasInt128Type())
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
<< "__int128";
if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
Result = Context.UnsignedInt128Ty;
else
Result = Context.Int128Ty;
break;
- case DeclSpec::TST_float16: Result = Context.Float16Ty; break;
+ case DeclSpec::TST_float16:
+ if (!S.Context.getTargetInfo().hasFloat16Type())
+ S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
+ << "_Float16";
+ Result = Context.Float16Ty;
+ break;
case DeclSpec::TST_half: Result = Context.HalfTy; break;
case DeclSpec::TST_float: Result = Context.FloatTy; break;
case DeclSpec::TST_double:
if (DS.getTypeSpecWidth() == DeclSpec::TSW_long)
Result = Context.LongDoubleTy;
else
Result = Context.DoubleTy;
break;
case DeclSpec::TST_float128:
if (!S.Context.getTargetInfo().hasFloat128Type())
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
<< "__float128";
Result = Context.Float128Ty;
break;
case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool
break;
case DeclSpec::TST_decimal32: // _Decimal32
case DeclSpec::TST_decimal64: // _Decimal64
case DeclSpec::TST_decimal128: // _Decimal128
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported);
Result = Context.IntTy;
declarator.setInvalidType(true);
break;
case DeclSpec::TST_class:
case DeclSpec::TST_enum:
case DeclSpec::TST_union:
case DeclSpec::TST_struct:
case DeclSpec::TST_interface: {
TagDecl *D = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl());
if (!D) {
// This can happen in C++ with ambiguous lookups.
Result = Context.IntTy;
declarator.setInvalidType(true);
break;
}
// If the type is deprecated or unavailable, diagnose it.
S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeNameLoc());
assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!");
// TypeQuals handled by caller.
Result = Context.getTypeDeclType(D);
// In both C and C++, make an ElaboratedType.
ElaboratedTypeKeyword Keyword
= ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType());
Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result,
DS.isTypeSpecOwned() ? D : nullptr);
break;
}
case DeclSpec::TST_typename: {
assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
DS.getTypeSpecSign() == 0 &&
"Can't handle qualifiers on typedef names yet!");
Result = S.GetTypeFromParser(DS.getRepAsType());
if (Result.isNull()) {
declarator.setInvalidType(true);
}
// TypeQuals handled by caller.
break;
}
case DeclSpec::TST_typeofType:
// FIXME: Preserve type source info.
Result = S.GetTypeFromParser(DS.getRepAsType());
assert(!Result.isNull() && "Didn't get a type for typeof?");
if (!Result->isDependentType())
if (const TagType *TT = Result->getAs<TagType>())
S.DiagnoseUseOfDecl(TT->getDecl(), DS.getTypeSpecTypeLoc());
// TypeQuals handled by caller.
Result = Context.getTypeOfType(Result);
break;
case DeclSpec::TST_typeofExpr: {
Expr *E = DS.getRepAsExpr();
assert(E && "Didn't get an expression for typeof?");
// TypeQuals handled by caller.
Result = S.BuildTypeofExprType(E, DS.getTypeSpecTypeLoc());
if (Result.isNull()) {
Result = Context.IntTy;
declarator.setInvalidType(true);
}
break;
}
case DeclSpec::TST_decltype: {
Expr *E = DS.getRepAsExpr();
assert(E && "Didn't get an expression for decltype?");
// TypeQuals handled by caller.
Result = S.BuildDecltypeType(E, DS.getTypeSpecTypeLoc());
if (Result.isNull()) {
Result = Context.IntTy;
declarator.setInvalidType(true);
}
break;
}
case DeclSpec::TST_underlyingType:
Result = S.GetTypeFromParser(DS.getRepAsType());
assert(!Result.isNull() && "Didn't get a type for __underlying_type?");
Result = S.BuildUnaryTransformType(Result,
UnaryTransformType::EnumUnderlyingType,
DS.getTypeSpecTypeLoc());
if (Result.isNull()) {
Result = Context.IntTy;
declarator.setInvalidType(true);
}
break;
case DeclSpec::TST_auto:
Result = Context.getAutoType(QualType(), AutoTypeKeyword::Auto, false);
break;
case DeclSpec::TST_auto_type:
Result = Context.getAutoType(QualType(), AutoTypeKeyword::GNUAutoType, false);
break;
case DeclSpec::TST_decltype_auto:
Result = Context.getAutoType(QualType(), AutoTypeKeyword::DecltypeAuto,
/*IsDependent*/ false);
break;
case DeclSpec::TST_unknown_anytype:
Result = Context.UnknownAnyTy;
break;
case DeclSpec::TST_atomic:
Result = S.GetTypeFromParser(DS.getRepAsType());
assert(!Result.isNull() && "Didn't get a type for _Atomic?");
Result = S.BuildAtomicType(Result, DS.getTypeSpecTypeLoc());
if (Result.isNull()) {
Result = Context.IntTy;
declarator.setInvalidType(true);
}
break;
#define GENERIC_IMAGE_TYPE(ImgType, Id) \
case DeclSpec::TST_##ImgType##_t: \
switch (getImageAccess(DS.getAttributes())) { \
case OpenCLAccessAttr::Keyword_write_only: \
Result = Context.Id##WOTy; \
break; \
case OpenCLAccessAttr::Keyword_read_write: \
Result = Context.Id##RWTy; \
break; \
case OpenCLAccessAttr::Keyword_read_only: \
Result = Context.Id##ROTy; \
break; \
} \
break;
#include "clang/Basic/OpenCLImageTypes.def"
case DeclSpec::TST_error:
Result = Context.IntTy;
declarator.setInvalidType(true);
break;
}
if (S.getLangOpts().OpenCL &&
S.checkOpenCLDisabledTypeDeclSpec(DS, Result))
declarator.setInvalidType(true);
bool IsFixedPointType = DS.getTypeSpecType() == DeclSpec::TST_accum ||
DS.getTypeSpecType() == DeclSpec::TST_fract;
// Only fixed point types can be saturated
if (DS.isTypeSpecSat() && !IsFixedPointType)
S.Diag(DS.getTypeSpecSatLoc(), diag::err_invalid_saturation_spec)
<< DS.getSpecifierName(DS.getTypeSpecType(),
Context.getPrintingPolicy());
// Handle complex types.
if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
if (S.getLangOpts().Freestanding)
S.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex);
Result = Context.getComplexType(Result);
} else if (DS.isTypeAltiVecVector()) {
unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(Result));
assert(typeSize > 0 && "type size for vector must be greater than 0 bits");
VectorType::VectorKind VecKind = VectorType::AltiVecVector;
if (DS.isTypeAltiVecPixel())
VecKind = VectorType::AltiVecPixel;
else if (DS.isTypeAltiVecBool())
VecKind = VectorType::AltiVecBool;
Result = Context.getVectorType(Result, 128/typeSize, VecKind);
}
// FIXME: Imaginary.
if (DS.getTypeSpecComplex() == DeclSpec::TSC_imaginary)
S.Diag(DS.getTypeSpecComplexLoc(), diag::err_imaginary_not_supported);
// Before we process any type attributes, synthesize a block literal
// function declarator if necessary.
if (declarator.getContext() == DeclaratorContext::BlockLiteralContext)
maybeSynthesizeBlockSignature(state, Result);
// Apply any type attributes from the decl spec. This may cause the
// list of type attributes to be temporarily saved while the type
// attributes are pushed around.
// pipe attributes will be handled later ( at GetFullTypeForDeclarator )
if (!DS.isTypeSpecPipe())
processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes());
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
// Warn about CV qualifiers on function types.
// C99 6.7.3p8:
// If the specification of a function type includes any type qualifiers,
// the behavior is undefined.
// C++11 [dcl.fct]p7:
// The effect of a cv-qualifier-seq in a function declarator is not the
// same as adding cv-qualification on top of the function type. In the
// latter case, the cv-qualifiers are ignored.
if (TypeQuals && Result->isFunctionType()) {
diagnoseAndRemoveTypeQualifiers(
S, DS, TypeQuals, Result, DeclSpec::TQ_const | DeclSpec::TQ_volatile,
S.getLangOpts().CPlusPlus
? diag::warn_typecheck_function_qualifiers_ignored
: diag::warn_typecheck_function_qualifiers_unspecified);
// No diagnostic for 'restrict' or '_Atomic' applied to a
// function type; we'll diagnose those later, in BuildQualifiedType.
}
// C++11 [dcl.ref]p1:
// Cv-qualified references are ill-formed except when the
// cv-qualifiers are introduced through the use of a typedef-name
// or decltype-specifier, in which case the cv-qualifiers are ignored.
//
// There don't appear to be any other contexts in which a cv-qualified
// reference type could be formed, so the 'ill-formed' clause here appears
// to never happen.
if (TypeQuals && Result->isReferenceType()) {
diagnoseAndRemoveTypeQualifiers(
S, DS, TypeQuals, Result,
DeclSpec::TQ_const | DeclSpec::TQ_volatile | DeclSpec::TQ_atomic,
diag::warn_typecheck_reference_qualifiers);
}
// C90 6.5.3 constraints: "The same type qualifier shall not appear more
// than once in the same specifier-list or qualifier-list, either directly
// or via one or more typedefs."
if (!S.getLangOpts().C99 && !S.getLangOpts().CPlusPlus
&& TypeQuals & Result.getCVRQualifiers()) {
if (TypeQuals & DeclSpec::TQ_const && Result.isConstQualified()) {
S.Diag(DS.getConstSpecLoc(), diag::ext_duplicate_declspec)
<< "const";
}
if (TypeQuals & DeclSpec::TQ_volatile && Result.isVolatileQualified()) {
S.Diag(DS.getVolatileSpecLoc(), diag::ext_duplicate_declspec)
<< "volatile";
}
// C90 doesn't have restrict nor _Atomic, so it doesn't force us to
// produce a warning in this case.
}
QualType Qualified = S.BuildQualifiedType(Result, DeclLoc, TypeQuals, &DS);
// If adding qualifiers fails, just use the unqualified type.
if (Qualified.isNull())
declarator.setInvalidType(true);
else
Result = Qualified;
}
assert(!Result.isNull() && "This function should not return a null type");
return Result;
}
static std::string getPrintableNameForEntity(DeclarationName Entity) {
if (Entity)
return Entity.getAsString();
return "type name";
}
QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
Qualifiers Qs, const DeclSpec *DS) {
if (T.isNull())
return QualType();
// Ignore any attempt to form a cv-qualified reference.
if (T->isReferenceType()) {
Qs.removeConst();
Qs.removeVolatile();
}
// Enforce C99 6.7.3p2: "Types other than pointer types derived from
// object or incomplete types shall not be restrict-qualified."
if (Qs.hasRestrict()) {
unsigned DiagID = 0;
QualType ProblemTy;
if (T->isAnyPointerType() || T->isReferenceType() ||
T->isMemberPointerType()) {
QualType EltTy;
if (T->isObjCObjectPointerType())
EltTy = T;
else if (const MemberPointerType *PTy = T->getAs<MemberPointerType>())
EltTy = PTy->getPointeeType();
else
EltTy = T->getPointeeType();
// If we have a pointer or reference, the pointee must have an object
// incomplete type.
if (!EltTy->isIncompleteOrObjectType()) {
DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
ProblemTy = EltTy;
}
} else if (!T->isDependentType()) {
DiagID = diag::err_typecheck_invalid_restrict_not_pointer;
ProblemTy = T;
}
if (DiagID) {
Diag(DS ? DS->getRestrictSpecLoc() : Loc, DiagID) << ProblemTy;
Qs.removeRestrict();
}
}
return Context.getQualifiedType(T, Qs);
}
QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
unsigned CVRAU, const DeclSpec *DS) {
if (T.isNull())
return QualType();
// Ignore any attempt to form a cv-qualified reference.
if (T->isReferenceType())
CVRAU &=
~(DeclSpec::TQ_const | DeclSpec::TQ_volatile | DeclSpec::TQ_atomic);
// Convert from DeclSpec::TQ to Qualifiers::TQ by just dropping TQ_atomic and
// TQ_unaligned;
unsigned CVR = CVRAU & ~(DeclSpec::TQ_atomic | DeclSpec::TQ_unaligned);
// C11 6.7.3/5:
// If the same qualifier appears more than once in the same
// specifier-qualifier-list, either directly or via one or more typedefs,
// the behavior is the same as if it appeared only once.
//
// It's not specified what happens when the _Atomic qualifier is applied to
// a type specified with the _Atomic specifier, but we assume that this
// should be treated as if the _Atomic qualifier appeared multiple times.
if (CVRAU & DeclSpec::TQ_atomic && !T->isAtomicType()) {
// C11 6.7.3/5:
// If other qualifiers appear along with the _Atomic qualifier in a
// specifier-qualifier-list, the resulting type is the so-qualified
// atomic type.
//
// Don't need to worry about array types here, since _Atomic can't be
// applied to such types.
SplitQualType Split = T.getSplitUnqualifiedType();
T = BuildAtomicType(QualType(Split.Ty, 0),
DS ? DS->getAtomicSpecLoc() : Loc);
if (T.isNull())
return T;
Split.Quals.addCVRQualifiers(CVR);
return BuildQualifiedType(T, Loc, Split.Quals);
}
Qualifiers Q = Qualifiers::fromCVRMask(CVR);
Q.setUnaligned(CVRAU & DeclSpec::TQ_unaligned);
return BuildQualifiedType(T, Loc, Q, DS);
}
/// Build a paren type including \p T.
QualType Sema::BuildParenType(QualType T) {
return Context.getParenType(T);
}
/// Given that we're building a pointer or reference to the given
static QualType inferARCLifetimeForPointee(Sema &S, QualType type,
SourceLocation loc,
bool isReference) {
// Bail out if retention is unrequired or already specified.
if (!type->isObjCLifetimeType() ||
type.getObjCLifetime() != Qualifiers::OCL_None)
return type;
Qualifiers::ObjCLifetime implicitLifetime = Qualifiers::OCL_None;
// If the object type is const-qualified, we can safely use
// __unsafe_unretained. This is safe (because there are no read
// barriers), and it'll be safe to coerce anything but __weak* to
// the resulting type.
if (type.isConstQualified()) {
implicitLifetime = Qualifiers::OCL_ExplicitNone;
// Otherwise, check whether the static type does not require
// retaining. This currently only triggers for Class (possibly
// protocol-qualifed, and arrays thereof).
} else if (type->isObjCARCImplicitlyUnretainedType()) {
implicitLifetime = Qualifiers::OCL_ExplicitNone;
// If we are in an unevaluated context, like sizeof, skip adding a
// qualification.
} else if (S.isUnevaluatedContext()) {
return type;
// If that failed, give an error and recover using __strong. __strong
// is the option most likely to prevent spurious second-order diagnostics,
// like when binding a reference to a field.
} else {
// These types can show up in private ivars in system headers, so
// we need this to not be an error in those cases. Instead we
// want to delay.
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
S.DelayedDiagnostics.add(
sema::DelayedDiagnostic::makeForbiddenType(loc,
diag::err_arc_indirect_no_ownership, type, isReference));
} else {
S.Diag(loc, diag::err_arc_indirect_no_ownership) << type << isReference;
}
implicitLifetime = Qualifiers::OCL_Strong;
}
assert(implicitLifetime && "didn't infer any lifetime!");
Qualifiers qs;
qs.addObjCLifetime(implicitLifetime);
return S.Context.getQualifiedType(type, qs);
}
static std::string getFunctionQualifiersAsString(const FunctionProtoType *FnTy){
std::string Quals = FnTy->getTypeQuals().getAsString();
switch (FnTy->getRefQualifier()) {
case RQ_None:
break;
case RQ_LValue:
if (!Quals.empty())
Quals += ' ';
Quals += '&';
break;
case RQ_RValue:
if (!Quals.empty())
Quals += ' ';
Quals += "&&";
break;
}
return Quals;
}
namespace {
/// Kinds of declarator that cannot contain a qualified function type.
///
/// C++98 [dcl.fct]p4 / C++11 [dcl.fct]p6:
/// a function type with a cv-qualifier or a ref-qualifier can only appear
/// at the topmost level of a type.
///
/// Parens and member pointers are permitted. We don't diagnose array and
/// function declarators, because they don't allow function types at all.
///
/// The values of this enum are used in diagnostics.
enum QualifiedFunctionKind { QFK_BlockPointer, QFK_Pointer, QFK_Reference };
} // end anonymous namespace
/// Check whether the type T is a qualified function type, and if it is,
/// diagnose that it cannot be contained within the given kind of declarator.
static bool checkQualifiedFunction(Sema &S, QualType T, SourceLocation Loc,
QualifiedFunctionKind QFK) {
// Does T refer to a function type with a cv-qualifier or a ref-qualifier?
const FunctionProtoType *FPT = T->getAs<FunctionProtoType>();
if (!FPT || (FPT->getTypeQuals().empty() && FPT->getRefQualifier() == RQ_None))
return false;
S.Diag(Loc, diag::err_compound_qualified_function_type)
<< QFK << isa<FunctionType>(T.IgnoreParens()) << T
<< getFunctionQualifiersAsString(FPT);
return true;
}
/// Build a pointer type.
///
/// \param T The type to which we'll be building a pointer.
///
/// \param Loc The location of the entity whose type involves this
/// pointer type or, if there is no such entity, the location of the
/// type that will have pointer type.
///
/// \param Entity The name of the entity that involves the pointer
/// type, if known.
///
/// \returns A suitable pointer type, if there are no
/// errors. Otherwise, returns a NULL type.
QualType Sema::BuildPointerType(QualType T,
SourceLocation Loc, DeclarationName Entity) {
if (T->isReferenceType()) {
// C++ 8.3.2p4: There shall be no ... pointers to references ...
Diag(Loc, diag::err_illegal_decl_pointer_to_reference)
<< getPrintableNameForEntity(Entity) << T;
return QualType();
}
if (T->isFunctionType() && getLangOpts().OpenCL) {
Diag(Loc, diag::err_opencl_function_pointer);
return QualType();
}
if (checkQualifiedFunction(*this, T, Loc, QFK_Pointer))
return QualType();
assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
// In ARC, it is forbidden to build pointers to unqualified pointers.
if (getLangOpts().ObjCAutoRefCount)
T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ false);
// Build the pointer type.
return Context.getPointerType(T);
}
/// Build a reference type.
///
/// \param T The type to which we'll be building a reference.
///
/// \param Loc The location of the entity whose type involves this
/// reference type or, if there is no such entity, the location of the
/// type that will have reference type.
///
/// \param Entity The name of the entity that involves the reference
/// type, if known.
///
/// \returns A suitable reference type, if there are no
/// errors. Otherwise, returns a NULL type.
QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
SourceLocation Loc,
DeclarationName Entity) {
assert(Context.getCanonicalType(T) != Context.OverloadTy &&
"Unresolved overloaded function type");
// C++0x [dcl.ref]p6:
// If a typedef (7.1.3), a type template-parameter (14.3.1), or a
// decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a
// type T, an attempt to create the type "lvalue reference to cv TR" creates
// the type "lvalue reference to T", while an attempt to create the type
// "rvalue reference to cv TR" creates the type TR.
bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>();
// C++ [dcl.ref]p4: There shall be no references to references.
//
// According to C++ DR 106, references to references are only
// diagnosed when they are written directly (e.g., "int & &"),
// but not when they happen via a typedef:
//
// typedef int& intref;
// typedef intref& intref2;
//
// Parser::ParseDeclaratorInternal diagnoses the case where
// references are written directly; here, we handle the
// collapsing of references-to-references as described in C++0x.
// DR 106 and 540 introduce reference-collapsing into C++98/03.
// C++ [dcl.ref]p1:
// A declarator that specifies the type "reference to cv void"
// is ill-formed.
if (T->isVoidType()) {
Diag(Loc, diag::err_reference_to_void);
return QualType();
}
if (checkQualifiedFunction(*this, T, Loc, QFK_Reference))
return QualType();
// In ARC, it is forbidden to build references to unqualified pointers.
if (getLangOpts().ObjCAutoRefCount)
T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ true);
// Handle restrict on references.
if (LValueRef)
return Context.getLValueReferenceType(T, SpelledAsLValue);
return Context.getRValueReferenceType(T);
}
/// Build a Read-only Pipe type.
///
/// \param T The type to which we'll be building a Pipe.
///
/// \param Loc We do not use it for now.
///
/// \returns A suitable pipe type, if there are no errors. Otherwise, returns a
/// NULL type.
QualType Sema::BuildReadPipeType(QualType T, SourceLocation Loc) {
return Context.getReadPipeType(T);
}
/// Build a Write-only Pipe type.
///
/// \param T The type to which we'll be building a Pipe.
///
/// \param Loc We do not use it for now.
///
/// \returns A suitable pipe type, if there are no errors. Otherwise, returns a
/// NULL type.
QualType Sema::BuildWritePipeType(QualType T, SourceLocation Loc) {
return Context.getWritePipeType(T);
}
/// Check whether the specified array size makes the array type a VLA. If so,
/// return true, if not, return the size of the array in SizeVal.
static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
// If the size is an ICE, it certainly isn't a VLA. If we're in a GNU mode
// (like gnu99, but not c99) accept any evaluatable value as an extension.
class VLADiagnoser : public Sema::VerifyICEDiagnoser {
public:
VLADiagnoser() : Sema::VerifyICEDiagnoser(true) {}
void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) override {
}
void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR) override {
S.Diag(Loc, diag::ext_vla_folded_to_constant) << SR;
}
} Diagnoser;
return S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser,
S.LangOpts.GNUMode ||
S.LangOpts.OpenCL).isInvalid();
}
/// Build an array type.
///
/// \param T The type of each element in the array.
///
/// \param ASM C99 array size modifier (e.g., '*', 'static').
///
/// \param ArraySize Expression describing the size of the array.
///
/// \param Brackets The range from the opening '[' to the closing ']'.
///
/// \param Entity The name of the entity that involves the array
/// type, if known.
///
/// \returns A suitable array type, if there are no errors. Otherwise,
/// returns a NULL type.
QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Expr *ArraySize, unsigned Quals,
SourceRange Brackets, DeclarationName Entity) {
SourceLocation Loc = Brackets.getBegin();
if (getLangOpts().CPlusPlus) {
// C++ [dcl.array]p1:
// T is called the array element type; this type shall not be a reference
// type, the (possibly cv-qualified) type void, a function type or an
// abstract class type.
//
// C++ [dcl.array]p3:
// When several "array of" specifications are adjacent, [...] only the
// first of the constant expressions that specify the bounds of the arrays
// may be omitted.
//
// Note: function types are handled in the common path with C.
if (T->isReferenceType()) {
Diag(Loc, diag::err_illegal_decl_array_of_references)
<< getPrintableNameForEntity(Entity) << T;
return QualType();
}
if (T->isVoidType() || T->isIncompleteArrayType()) {
Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T;
return QualType();
}
if (RequireNonAbstractType(Brackets.getBegin(), T,
diag::err_array_of_abstract_type))
return QualType();
// Mentioning a member pointer type for an array type causes us to lock in
// an inheritance model, even if it's inside an unused typedef.
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
if (!MPTy->getClass()->isDependentType())
(void)isCompleteType(Loc, T);
} else {
// C99 6.7.5.2p1: If the element type is an incomplete or function type,
// reject it (e.g. void ary[7], struct foo ary[7], void ary[7]())
if (RequireCompleteType(Loc, T,
diag::err_illegal_decl_array_incomplete_type))
return QualType();
}
if (T->isFunctionType()) {
Diag(Loc, diag::err_illegal_decl_array_of_functions)
<< getPrintableNameForEntity(Entity) << T;
return QualType();
}
if (const RecordType *EltTy = T->getAs<RecordType>()) {
// If the element type is a struct or union that contains a variadic
// array, accept it as a GNU extension: C99 6.7.2.1p2.
if (EltTy->getDecl()->hasFlexibleArrayMember())
Diag(Loc, diag::ext_flexible_array_in_array) << T;
} else if (T->isObjCObjectType()) {
Diag(Loc, diag::err_objc_array_of_interfaces) << T;
return QualType();
}
// Do placeholder conversions on the array size expression.
if (ArraySize && ArraySize->hasPlaceholderType()) {
ExprResult Result = CheckPlaceholderExpr(ArraySize);
if (Result.isInvalid()) return QualType();
ArraySize = Result.get();
}
// Do lvalue-to-rvalue conversions on the array size expression.
if (ArraySize && !ArraySize->isRValue()) {
ExprResult Result = DefaultLvalueConversion(ArraySize);
if (Result.isInvalid())
return QualType();
ArraySize = Result.get();
}
// C99 6.7.5.2p1: The size expression shall have integer type.
// C++11 allows contextual conversions to such types.
if (!getLangOpts().CPlusPlus11 &&
ArraySize && !ArraySize->isTypeDependent() &&
!ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
Diag(ArraySize->getBeginLoc(), diag::err_array_size_non_int)
<< ArraySize->getType() << ArraySize->getSourceRange();
return QualType();
}
llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType()));
if (!ArraySize) {
if (ASM == ArrayType::Star)
T = Context.getVariableArrayType(T, nullptr, ASM, Quals, Brackets);
else
T = Context.getIncompleteArrayType(T, ASM, Quals);
} else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) {
T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
} else if ((!T->isDependentType() && !T->isIncompleteType() &&
!T->isConstantSizeType()) ||
isArraySizeVLA(*this, ArraySize, ConstVal)) {
// Even in C++11, don't allow contextual conversions in the array bound
// of a VLA.
if (getLangOpts().CPlusPlus11 &&
!ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
Diag(ArraySize->getBeginLoc(), diag::err_array_size_non_int)
<< ArraySize->getType() << ArraySize->getSourceRange();
return QualType();
}
// C99: an array with an element type that has a non-constant-size is a VLA.
// C99: an array with a non-ICE size is a VLA. We accept any expression
// that we can fold to a non-zero positive value as an extension.
T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
} else {
// C99 6.7.5.2p1: If the expression is a constant expression, it shall
// have a value greater than zero.
if (ConstVal.isSigned() && ConstVal.isNegative()) {
if (Entity)
Diag(ArraySize->getBeginLoc(), diag::err_decl_negative_array_size)
<< getPrintableNameForEntity(Entity) << ArraySize->getSourceRange();
else
Diag(ArraySize->getBeginLoc(), diag::err_typecheck_negative_array_size)
<< ArraySize->getSourceRange();
return QualType();
}
if (ConstVal == 0) {
// GCC accepts zero sized static arrays. We allow them when
// we're not in a SFINAE context.
Diag(ArraySize->getBeginLoc(), isSFINAEContext()
? diag::err_typecheck_zero_array_size
: diag::ext_typecheck_zero_array_size)
<< ArraySize->getSourceRange();
if (ASM == ArrayType::Static) {
Diag(ArraySize->getBeginLoc(),
diag::warn_typecheck_zero_static_array_size)
<< ArraySize->getSourceRange();
ASM = ArrayType::Normal;
}
} else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
!T->isIncompleteType() && !T->isUndeducedType()) {
// Is the array too large?
unsigned ActiveSizeBits
= ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
Diag(ArraySize->getBeginLoc(), diag::err_array_too_large)
<< ConstVal.toString(10) << ArraySize->getSourceRange();
return QualType();
}
}
T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
}
// OpenCL v1.2 s6.9.d: variable length arrays are not supported.
if (getLangOpts().OpenCL && T->isVariableArrayType()) {
Diag(Loc, diag::err_opencl_vla);
return QualType();
}
if (T->isVariableArrayType() && !Context.getTargetInfo().isVLASupported()) {
if (getLangOpts().CUDA) {
// CUDA device code doesn't support VLAs.
CUDADiagIfDeviceCode(Loc, diag::err_cuda_vla) << CurrentCUDATarget();
} else if (!getLangOpts().OpenMP ||
shouldDiagnoseTargetSupportFromOpenMP()) {
// Some targets don't support VLAs.
Diag(Loc, diag::err_vla_unsupported);
return QualType();
}
}
// If this is not C99, extwarn about VLA's and C99 array size modifiers.
if (!getLangOpts().C99) {
if (T->isVariableArrayType()) {
// Prohibit the use of VLAs during template argument deduction.
if (isSFINAEContext()) {
Diag(Loc, diag::err_vla_in_sfinae);
return QualType();
}
// Just extwarn about VLAs.
else
Diag(Loc, diag::ext_vla);
} else if (ASM != ArrayType::Normal || Quals != 0)
Diag(Loc,
getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx
: diag::ext_c99_array_usage) << ASM;
}
if (T->isVariableArrayType()) {
// Warn about VLAs for -Wvla.
Diag(Loc, diag::warn_vla_used);
}
// OpenCL v2.0 s6.12.5 - Arrays of blocks are not supported.
// OpenCL v2.0 s6.16.13.1 - Arrays of pipe type are not supported.
// OpenCL v2.0 s6.9.b - Arrays of image/sampler type are not supported.
if (getLangOpts().OpenCL) {
const QualType ArrType = Context.getBaseElementType(T);
if (ArrType->isBlockPointerType() || ArrType->isPipeType() ||
ArrType->isSamplerT() || ArrType->isImageType()) {
Diag(Loc, diag::err_opencl_invalid_type_array) << ArrType;
return QualType();
}
}
return T;
}
QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
SourceLocation AttrLoc) {
// The base type must be integer (not Boolean or enumeration) or float, and
// can't already be a vector.
if (!CurType->isDependentType() &&
(!CurType->isBuiltinType() || CurType->isBooleanType() ||
(!CurType->isIntegerType() && !CurType->isRealFloatingType()))) {
Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType;
return QualType();
}
if (SizeExpr->isTypeDependent() || SizeExpr->isValueDependent())
return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc,
VectorType::GenericVector);
llvm::APSInt VecSize(32);
if (!SizeExpr->isIntegerConstantExpr(VecSize, Context)) {
Diag(AttrLoc, diag::err_attribute_argument_type)
<< "vector_size" << AANT_ArgumentIntegerConstant
<< SizeExpr->getSourceRange();
return QualType();
}
if (CurType->isDependentType())
return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc,
VectorType::GenericVector);
unsigned VectorSize = static_cast<unsigned>(VecSize.getZExtValue() * 8);
unsigned TypeSize = static_cast<unsigned>(Context.getTypeSize(CurType));
if (VectorSize == 0) {
Diag(AttrLoc, diag::err_attribute_zero_size) << SizeExpr->getSourceRange();
return QualType();
}
// vecSize is specified in bytes - convert to bits.
if (VectorSize % TypeSize) {
Diag(AttrLoc, diag::err_attribute_invalid_size)
<< SizeExpr->getSourceRange();
return QualType();
}
if (VectorType::isVectorSizeTooLarge(VectorSize / TypeSize)) {
Diag(AttrLoc, diag::err_attribute_size_too_large)
<< SizeExpr->getSourceRange();
return QualType();
}
return Context.getVectorType(CurType, VectorSize / TypeSize,
VectorType::GenericVector);
}
/// Build an ext-vector type.
///
/// Run the required checks for the extended vector type.
QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
SourceLocation AttrLoc) {
// Unlike gcc's vector_size attribute, we do not allow vectors to be defined
// in conjunction with complex types (pointers, arrays, functions, etc.).
//
// Additionally, OpenCL prohibits vectors of booleans (they're considered a
// reserved data type under OpenCL v2.0 s6.1.4), we don't support selects
// on bitvectors, and we have no well-defined ABI for bitvectors, so vectors
// of bool aren't allowed.
if ((!T->isDependentType() && !T->isIntegerType() &&
!T->isRealFloatingType()) ||
T->isBooleanType()) {
Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T;
return QualType();
}
if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) {
llvm::APSInt vecSize(32);
if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) {
Diag(AttrLoc, diag::err_attribute_argument_type)
<< "ext_vector_type" << AANT_ArgumentIntegerConstant
<< ArraySize->getSourceRange();
return QualType();
}
// Unlike gcc's vector_size attribute, the size is specified as the
// number of elements, not the number of bytes.
unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
if (vectorSize == 0) {
Diag(AttrLoc, diag::err_attribute_zero_size)
<< ArraySize->getSourceRange();
return QualType();
}
if (VectorType::isVectorSizeTooLarge(vectorSize)) {
Diag(AttrLoc, diag::err_attribute_size_too_large)
<< ArraySize->getSourceRange();
return QualType();
}
return Context.getExtVectorType(T, vectorSize);
}
return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc);
}
bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) {
if (T->isArrayType() || T->isFunctionType()) {
Diag(Loc, diag::err_func_returning_array_function)
<< T->isFunctionType() << T;
return true;
}
// Functions cannot return half FP.
if (T->isHalfType() && !getLangOpts().HalfArgsAndReturns) {
Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 <<
FixItHint::CreateInsertion(Loc, "*");
return true;
}
// Methods cannot return interface types. All ObjC objects are
// passed by reference.
if (T->isObjCObjectType()) {
Diag(Loc, diag::err_object_cannot_be_passed_returned_by_value)
<< 0 << T << FixItHint::CreateInsertion(Loc, "*");
return true;
}
return false;
}
/// Check the extended parameter information. Most of the necessary
/// checking should occur when applying the parameter attribute; the
/// only other checks required are positional restrictions.
static void checkExtParameterInfos(Sema &S, ArrayRef<QualType> paramTypes,
const FunctionProtoType::ExtProtoInfo &EPI,
llvm::function_ref<SourceLocation(unsigned)> getParamLoc) {
assert(EPI.ExtParameterInfos && "shouldn't get here without param infos");
bool hasCheckedSwiftCall = false;
auto checkForSwiftCC = [&](unsigned paramIndex) {
// Only do this once.
if (hasCheckedSwiftCall) return;
hasCheckedSwiftCall = true;
if (EPI.ExtInfo.getCC() == CC_Swift) return;
S.Diag(getParamLoc(paramIndex), diag::err_swift_param_attr_not_swiftcall)
<< getParameterABISpelling(EPI.ExtParameterInfos[paramIndex].getABI());
};
for (size_t paramIndex = 0, numParams = paramTypes.size();
paramIndex != numParams; ++paramIndex) {
switch (EPI.ExtParameterInfos[paramIndex].getABI()) {
// Nothing interesting to check for orindary-ABI parameters.
case ParameterABI::Ordinary:
continue;
// swift_indirect_result parameters must be a prefix of the function
// arguments.
case ParameterABI::SwiftIndirectResult:
checkForSwiftCC(paramIndex);
if (paramIndex != 0 &&
EPI.ExtParameterInfos[paramIndex - 1].getABI()
!= ParameterABI::SwiftIndirectResult) {
S.Diag(getParamLoc(paramIndex),
diag::err_swift_indirect_result_not_first);
}
continue;
case ParameterABI::SwiftContext:
checkForSwiftCC(paramIndex);
continue;
// swift_error parameters must be preceded by a swift_context parameter.
case ParameterABI::SwiftErrorResult:
checkForSwiftCC(paramIndex);
if (paramIndex == 0 ||
EPI.ExtParameterInfos[paramIndex - 1].getABI() !=
ParameterABI::SwiftContext) {
S.Diag(getParamLoc(paramIndex),
diag::err_swift_error_result_not_after_swift_context);
}
continue;
}
llvm_unreachable("bad ABI kind");
}
}
QualType Sema::BuildFunctionType(QualType T,
MutableArrayRef<QualType> ParamTypes,
SourceLocation Loc, DeclarationName Entity,
const FunctionProtoType::ExtProtoInfo &EPI) {
bool Invalid = false;
Invalid |= CheckFunctionReturnType(T, Loc);
for (unsigned Idx = 0, Cnt = ParamTypes.size(); Idx < Cnt; ++Idx) {
// FIXME: Loc is too inprecise here, should use proper locations for args.
QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]);
if (ParamType->isVoidType()) {
Diag(Loc, diag::err_param_with_void_type);
Invalid = true;
} else if (ParamType->isHalfType() && !getLangOpts().HalfArgsAndReturns) {
// Disallow half FP arguments.
Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 0 <<
FixItHint::CreateInsertion(Loc, "*");
Invalid = true;
}
ParamTypes[Idx] = ParamType;
}
if (EPI.ExtParameterInfos) {
checkExtParameterInfos(*this, ParamTypes, EPI,
[=](unsigned i) { return Loc; });
}
if (EPI.ExtInfo.getProducesResult()) {
// This is just a warning, so we can't fail to build if we see it.
checkNSReturnsRetainedReturnType(Loc, T);
}
if (Invalid)
return QualType();
return Context.getFunctionType(T, ParamTypes, EPI);
}
/// Build a member pointer type \c T Class::*.
///
/// \param T the type to which the member pointer refers.
/// \param Class the class type into which the member pointer points.
/// \param Loc the location where this type begins
/// \param Entity the name of the entity that will have this member pointer type
///
/// \returns a member pointer type, if successful, or a NULL type if there was
/// an error.
QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
SourceLocation Loc,
DeclarationName Entity) {
// Verify that we're not building a pointer to pointer to function with
// exception specification.
if (CheckDistantExceptionSpec(T)) {
Diag(Loc, diag::err_distant_exception_spec);
return QualType();
}
// C++ 8.3.3p3: A pointer to member shall not point to ... a member
// with reference type, or "cv void."
if (T->isReferenceType()) {
Diag(Loc, diag::err_illegal_decl_mempointer_to_reference)
<< getPrintableNameForEntity(Entity) << T;
return QualType();
}
if (T->isVoidType()) {
Diag(Loc, diag::err_illegal_decl_mempointer_to_void)
<< getPrintableNameForEntity(Entity);
return QualType();
}
if (!Class->isDependentType() && !Class->isRecordType()) {
Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class;
return QualType();
}
// Adjust the default free function calling convention to the default method
// calling convention.
bool IsCtorOrDtor =
(Entity.getNameKind() == DeclarationName::CXXConstructorName) ||
(Entity.getNameKind() == DeclarationName::CXXDestructorName);
if (T->isFunctionType())
adjustMemberFunctionCC(T, /*IsStatic=*/false, IsCtorOrDtor, Loc);
return Context.getMemberPointerType(T, Class.getTypePtr());
}
/// Build a block pointer type.
///
/// \param T The type to which we'll be building a block pointer.
///
/// \param Loc The source location, used for diagnostics.
///
/// \param Entity The name of the entity that involves the block pointer
/// type, if known.
///
/// \returns A suitable block pointer type, if there are no
/// errors. Otherwise, returns a NULL type.
QualType Sema::BuildBlockPointerType(QualType T,
SourceLocation Loc,
DeclarationName Entity) {
if (!T->isFunctionType()) {
Diag(Loc, diag::err_nonfunction_block_type);
return QualType();
}
if (checkQualifiedFunction(*this, T, Loc, QFK_BlockPointer))
return QualType();
return Context.getBlockPointerType(T);
}
QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) {
QualType QT = Ty.get();
if (QT.isNull()) {
if (TInfo) *TInfo = nullptr;
return QualType();
}
TypeSourceInfo *DI = nullptr;
if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) {
QT = LIT->getType();
DI = LIT->getTypeSourceInfo();
}
if (TInfo) *TInfo = DI;
return QT;
}
static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
Qualifiers::ObjCLifetime ownership,
unsigned chunkIndex);
/// Given that this is the declaration of a parameter under ARC,
/// attempt to infer attributes and such for pointer-to-whatever
/// types.
static void inferARCWriteback(TypeProcessingState &state,
QualType &declSpecType) {
Sema &S = state.getSema();
Declarator &declarator = state.getDeclarator();
// TODO: should we care about decl qualifiers?
// Check whether the declarator has the expected form. We walk
// from the inside out in order to make the block logic work.
unsigned outermostPointerIndex = 0;
bool isBlockPointer = false;
unsigned numPointers = 0;
for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
unsigned chunkIndex = i;
DeclaratorChunk &chunk = declarator.getTypeObject(chunkIndex);
switch (chunk.Kind) {
case DeclaratorChunk::Paren:
// Ignore parens.
break;
case DeclaratorChunk::Reference:
case DeclaratorChunk::Pointer:
// Count the number of pointers. Treat references
// interchangeably as pointers; if they're mis-ordered, normal
// type building will discover that.
outermostPointerIndex = chunkIndex;
numPointers++;
break;
case DeclaratorChunk::BlockPointer:
// If we have a pointer to block pointer, that's an acceptable
// indirect reference; anything else is not an application of
// the rules.
if (numPointers != 1) return;
numPointers++;
outermostPointerIndex = chunkIndex;
isBlockPointer = true;
// We don't care about pointer structure in return values here.
goto done;
case DeclaratorChunk::Array: // suppress if written (id[])?
case DeclaratorChunk::Function:
case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Pipe:
return;
}
}
done:
// If we have *one* pointer, then we want to throw the qualifier on
// the declaration-specifiers, which means that it needs to be a
// retainable object type.
if (numPointers == 1) {
// If it's not a retainable object type, the rule doesn't apply.
if (!declSpecType->isObjCRetainableType()) return;
// If it already has lifetime, don't do anything.
if (declSpecType.getObjCLifetime()) return;
// Otherwise, modify the type in-place.
Qualifiers qs;
if (declSpecType->isObjCARCImplicitlyUnretainedType())
qs.addObjCLifetime(Qualifiers::OCL_ExplicitNone);
else
qs.addObjCLifetime(Qualifiers::OCL_Autoreleasing);
declSpecType = S.Context.getQualifiedType(declSpecType, qs);
// If we have *two* pointers, then we want to throw the qualifier on
// the outermost pointer.
} else if (numPointers == 2) {
// If we don't have a block pointer, we need to check whether the
// declaration-specifiers gave us something that will turn into a
// retainable object pointer after we slap the first pointer on it.
if (!isBlockPointer && !declSpecType->isObjCObjectType())
return;
// Look for an explicit lifetime attribute there.
DeclaratorChunk &chunk = declarator.getTypeObject(outermostPointerIndex);
if (chunk.Kind != DeclaratorChunk::Pointer &&
chunk.Kind != DeclaratorChunk::BlockPointer)
return;
for (const ParsedAttr &AL : chunk.getAttrs())
if (AL.getKind() == ParsedAttr::AT_ObjCOwnership)
return;
transferARCOwnershipToDeclaratorChunk(state, Qualifiers::OCL_Autoreleasing,
outermostPointerIndex);
// Any other number of pointers/references does not trigger the rule.
} else return;
// TODO: mark whether we did this inference?
}
void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
SourceLocation FallbackLoc,
SourceLocation ConstQualLoc,
SourceLocation VolatileQualLoc,
SourceLocation RestrictQualLoc,
SourceLocation AtomicQualLoc,
SourceLocation UnalignedQualLoc) {
if (!Quals)
return;
struct Qual {
const char *Name;
unsigned Mask;
SourceLocation Loc;
} const QualKinds[5] = {
{ "const", DeclSpec::TQ_const, ConstQualLoc },
{ "volatile", DeclSpec::TQ_volatile, VolatileQualLoc },
{ "restrict", DeclSpec::TQ_restrict, RestrictQualLoc },
{ "__unaligned", DeclSpec::TQ_unaligned, UnalignedQualLoc },
{ "_Atomic", DeclSpec::TQ_atomic, AtomicQualLoc }
};
SmallString<32> QualStr;
unsigned NumQuals = 0;
SourceLocation Loc;
FixItHint FixIts[5];
// Build a string naming the redundant qualifiers.
for (auto &E : QualKinds) {
if (Quals & E.Mask) {
if (!QualStr.empty()) QualStr += ' ';
QualStr += E.Name;
// If we have a location for the qualifier, offer a fixit.
SourceLocation QualLoc = E.Loc;
if (QualLoc.isValid()) {
FixIts[NumQuals] = FixItHint::CreateRemoval(QualLoc);
if (Loc.isInvalid() ||
getSourceManager().isBeforeInTranslationUnit(QualLoc, Loc))
Loc = QualLoc;
}
++NumQuals;
}
}
Diag(Loc.isInvalid() ? FallbackLoc : Loc, DiagID)
<< QualStr << NumQuals << FixIts[0] << FixIts[1] << FixIts[2] << FixIts[3];
}
// Diagnose pointless type qualifiers on the return type of a function.
static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
Declarator &D,
unsigned FunctionChunkIndex) {
if (D.getTypeObject(FunctionChunkIndex).Fun.hasTrailingReturnType()) {
// FIXME: TypeSourceInfo doesn't preserve location information for
// qualifiers.
S.diagnoseIgnoredQualifiers(diag::warn_qual_return_type,
RetTy.getLocalCVRQualifiers(),
D.getIdentifierLoc());
return;
}
for (unsigned OuterChunkIndex = FunctionChunkIndex + 1,
End = D.getNumTypeObjects();
OuterChunkIndex != End; ++OuterChunkIndex) {
DeclaratorChunk &OuterChunk = D.getTypeObject(OuterChunkIndex);
switch (OuterChunk.Kind) {
case DeclaratorChunk::Paren:
continue;
case DeclaratorChunk::Pointer: {
DeclaratorChunk::PointerTypeInfo &PTI = OuterChunk.Ptr;
S.diagnoseIgnoredQualifiers(
diag::warn_qual_return_type,
PTI.TypeQuals,
SourceLocation(),
SourceLocation::getFromRawEncoding(PTI.ConstQualLoc),
SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc),
SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc),
SourceLocation::getFromRawEncoding(PTI.AtomicQualLoc),
SourceLocation::getFromRawEncoding(PTI.UnalignedQualLoc));
return;
}
case DeclaratorChunk::Function:
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::Reference:
case DeclaratorChunk::Array:
case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Pipe:
// FIXME: We can't currently provide an accurate source location and a
// fix-it hint for these.
unsigned AtomicQual = RetTy->isAtomicType() ? DeclSpec::TQ_atomic : 0;
S.diagnoseIgnoredQualifiers(diag::warn_qual_return_type,
RetTy.getCVRQualifiers() | AtomicQual,
D.getIdentifierLoc());
return;
}
llvm_unreachable("unknown declarator chunk kind");
}
// If the qualifiers come from a conversion function type, don't diagnose
// them -- they're not necessarily redundant, since such a conversion
// operator can be explicitly called as "x.operator const int()".
if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId)
return;
// Just parens all the way out to the decl specifiers. Diagnose any qualifiers
// which are present there.
S.diagnoseIgnoredQualifiers(diag::warn_qual_return_type,
D.getDeclSpec().getTypeQualifiers(),
D.getIdentifierLoc(),
D.getDeclSpec().getConstSpecLoc(),
D.getDeclSpec().getVolatileSpecLoc(),
D.getDeclSpec().getRestrictSpecLoc(),
D.getDeclSpec().getAtomicSpecLoc(),
D.getDeclSpec().getUnalignedSpecLoc());
}
static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
TypeSourceInfo *&ReturnTypeInfo) {
Sema &SemaRef = state.getSema();
Declarator &D = state.getDeclarator();
QualType T;
ReturnTypeInfo = nullptr;
// The TagDecl owned by the DeclSpec.
TagDecl *OwnedTagDecl = nullptr;
switch (D.getName().getKind()) {
case UnqualifiedIdKind::IK_ImplicitSelfParam:
case UnqualifiedIdKind::IK_OperatorFunctionId:
case UnqualifiedIdKind::IK_Identifier:
case UnqualifiedIdKind::IK_LiteralOperatorId:
case UnqualifiedIdKind::IK_TemplateId:
T = ConvertDeclSpecToType(state);
if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
OwnedTagDecl = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
// Owned declaration is embedded in declarator.
OwnedTagDecl->setEmbeddedInDeclarator(true);
}
break;
case UnqualifiedIdKind::IK_ConstructorName:
case UnqualifiedIdKind::IK_ConstructorTemplateId:
case UnqualifiedIdKind::IK_DestructorName:
// Constructors and destructors don't have return types. Use
// "void" instead.
T = SemaRef.Context.VoidTy;
processTypeAttrs(state, T, TAL_DeclSpec,
D.getMutableDeclSpec().getAttributes());
break;
case UnqualifiedIdKind::IK_DeductionGuideName:
// Deduction guides have a trailing return type and no type in their
// decl-specifier sequence. Use a placeholder return type for now.
T = SemaRef.Context.DependentTy;
break;
case UnqualifiedIdKind::IK_ConversionFunctionId:
// The result type of a conversion function is the type that it
// converts to.
T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId,
&ReturnTypeInfo);
break;
}
if (!D.getAttributes().empty())
distributeTypeAttrsFromDeclarator(state, T);
// C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
if (DeducedType *Deduced = T->getContainedDeducedType()) {
AutoType *Auto = dyn_cast<AutoType>(Deduced);
int Error = -1;
// Is this a 'auto' or 'decltype(auto)' type (as opposed to __auto_type or
// class template argument deduction)?
bool IsCXXAutoType =
(Auto && Auto->getKeyword() != AutoTypeKeyword::GNUAutoType);
bool IsDeducedReturnType = false;
switch (D.getContext()) {
case DeclaratorContext::LambdaExprContext:
// Declared return type of a lambda-declarator is implicit and is always
// 'auto'.
break;
case DeclaratorContext::ObjCParameterContext:
case DeclaratorContext::ObjCResultContext:
case DeclaratorContext::PrototypeContext:
Error = 0;
break;
case DeclaratorContext::LambdaExprParameterContext:
// In C++14, generic lambdas allow 'auto' in their parameters.
if (!SemaRef.getLangOpts().CPlusPlus14 ||
!Auto || Auto->getKeyword() != AutoTypeKeyword::Auto)
Error = 16;
else {
// If auto is mentioned in a lambda parameter context, convert it to a
// template parameter type.
sema::LambdaScopeInfo *LSI = SemaRef.getCurLambda();
assert(LSI && "No LambdaScopeInfo on the stack!");
const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
const bool IsParameterPack = D.hasEllipsis();
// Create the TemplateTypeParmDecl here to retrieve the corresponding
// template parameter type. Template parameters are temporarily added
// to the TU until the associated TemplateDecl is created.
TemplateTypeParmDecl *CorrespondingTemplateParam =
TemplateTypeParmDecl::Create(
SemaRef.Context, SemaRef.Context.getTranslationUnitDecl(),
/*KeyLoc*/ SourceLocation(), /*NameLoc*/ D.getBeginLoc(),
TemplateParameterDepth, AutoParameterPosition,
/*Identifier*/ nullptr, false, IsParameterPack);
LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
// Replace the 'auto' in the function parameter with this invented
// template type parameter.
// FIXME: Retain some type sugar to indicate that this was written
// as 'auto'.
T = SemaRef.ReplaceAutoType(
T, QualType(CorrespondingTemplateParam->getTypeForDecl(), 0));
}
break;
case DeclaratorContext::MemberContext: {
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
D.isFunctionDeclarator())
break;
bool Cxx = SemaRef.getLangOpts().CPlusPlus;
switch (cast<TagDecl>(SemaRef.CurContext)->getTagKind()) {
case TTK_Enum: llvm_unreachable("unhandled tag kind");
case TTK_Struct: Error = Cxx ? 1 : 2; /* Struct member */ break;
case TTK_Union: Error = Cxx ? 3 : 4; /* Union member */ break;
case TTK_Class: Error = 5; /* Class member */ break;
case TTK_Interface: Error = 6; /* Interface member */ break;
}
if (D.getDeclSpec().isFriendSpecified())
Error = 20; // Friend type
break;
}
case DeclaratorContext::CXXCatchContext:
case DeclaratorContext::ObjCCatchContext:
Error = 7; // Exception declaration
break;
case DeclaratorContext::TemplateParamContext:
if (isa<DeducedTemplateSpecializationType>(Deduced))
Error = 19; // Template parameter
else if (!SemaRef.getLangOpts().CPlusPlus17)
Error = 8; // Template parameter (until C++17)
break;
case DeclaratorContext::BlockLiteralContext:
Error = 9; // Block literal
break;
case DeclaratorContext::TemplateArgContext:
// Within a template argument list, a deduced template specialization
// type will be reinterpreted as a template template argument.
if (isa<DeducedTemplateSpecializationType>(Deduced) &&
!D.getNumTypeObjects() &&
D.getDeclSpec().getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier)
break;
LLVM_FALLTHROUGH;
case DeclaratorContext::TemplateTypeArgContext:
Error = 10; // Template type argument
break;
case DeclaratorContext::AliasDeclContext:
case DeclaratorContext::AliasTemplateContext:
Error = 12; // Type alias
break;
case DeclaratorContext::TrailingReturnContext:
case DeclaratorContext::TrailingReturnVarContext:
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
Error = 13; // Function return type
IsDeducedReturnType = true;
break;
case DeclaratorContext::ConversionIdContext:
if (!SemaRef.getLangOpts().CPlusPlus14 || !IsCXXAutoType)
Error = 14; // conversion-type-id
IsDeducedReturnType = true;
break;
case DeclaratorContext::FunctionalCastContext:
if (isa<DeducedTemplateSpecializationType>(Deduced))
break;
LLVM_FALLTHROUGH;
case DeclaratorContext::TypeNameContext:
Error = 15; // Generic
break;
case DeclaratorContext::FileContext:
case DeclaratorContext::BlockContext:
case DeclaratorContext::ForContext:
case DeclaratorContext::InitStmtContext:
case DeclaratorContext::ConditionContext:
// FIXME: P0091R3 (erroneously) does not permit class template argument
// deduction in conditions, for-init-statements, and other declarations
// that are not simple-declarations.
break;
case DeclaratorContext::CXXNewContext:
// FIXME: P0091R3 does not permit class template argument deduction here,
// but we follow GCC and allow it anyway.
if (!IsCXXAutoType && !isa<DeducedTemplateSpecializationType>(Deduced))
Error = 17; // 'new' type
break;
case DeclaratorContext::KNRTypeListContext:
Error = 18; // K&R function parameter
break;
}
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
Error = 11;
// In Objective-C it is an error to use 'auto' on a function declarator
// (and everywhere for '__auto_type').
if (D.isFunctionDeclarator() &&
(!SemaRef.getLangOpts().CPlusPlus11 || !IsCXXAutoType))
Error = 13;
bool HaveTrailing = false;
// C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator
// contains a trailing return type. That is only legal at the outermost
// level. Check all declarator chunks (outermost first) anyway, to give
// better diagnostics.
// We don't support '__auto_type' with trailing return types.
// FIXME: Should we only do this for 'auto' and not 'decltype(auto)'?
if (SemaRef.getLangOpts().CPlusPlus11 && IsCXXAutoType &&
D.hasTrailingReturnType()) {
HaveTrailing = true;
Error = -1;
}
SourceRange AutoRange = D.getDeclSpec().getTypeSpecTypeLoc();
if (D.getName().getKind() == UnqualifiedIdKind::IK_ConversionFunctionId)
AutoRange = D.getName().getSourceRange();
if (Error != -1) {
unsigned Kind;
if (Auto) {
switch (Auto->getKeyword()) {
case AutoTypeKeyword::Auto: Kind = 0; break;
case AutoTypeKeyword::DecltypeAuto: Kind = 1; break;
case AutoTypeKeyword::GNUAutoType: Kind = 2; break;
}
} else {
assert(isa<DeducedTemplateSpecializationType>(Deduced) &&
"unknown auto type");
Kind = 3;
}
auto *DTST = dyn_cast<DeducedTemplateSpecializationType>(Deduced);
TemplateName TN = DTST ? DTST->getTemplateName() : TemplateName();
SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed)
<< Kind << Error << (int)SemaRef.getTemplateNameKindForDiagnostics(TN)
<< QualType(Deduced, 0) << AutoRange;
if (auto *TD = TN.getAsTemplateDecl())
SemaRef.Diag(TD->getLocation(), diag::note_template_decl_here);
T = SemaRef.Context.IntTy;
D.setInvalidType(true);
} else if (!HaveTrailing &&
D.getContext() != DeclaratorContext::LambdaExprContext) {
// If there was a trailing return type, we already got
// warn_cxx98_compat_trailing_return_type in the parser.
SemaRef.Diag(AutoRange.getBegin(),
D.getContext() ==
DeclaratorContext::LambdaExprParameterContext
? diag::warn_cxx11_compat_generic_lambda
: IsDeducedReturnType
? diag::warn_cxx11_compat_deduced_return_type
: diag::warn_cxx98_compat_auto_type_specifier)
<< AutoRange;
}
}
if (SemaRef.getLangOpts().CPlusPlus &&
OwnedTagDecl && OwnedTagDecl->isCompleteDefinition()) {
// Check the contexts where C++ forbids the declaration of a new class
// or enumeration in a type-specifier-seq.
unsigned DiagID = 0;
switch (D.getContext()) {
case DeclaratorContext::TrailingReturnContext:
case DeclaratorContext::TrailingReturnVarContext:
// Class and enumeration definitions are syntactically not allowed in
// trailing return types.
llvm_unreachable("parser should not have allowed this");
break;
case DeclaratorContext::FileContext:
case DeclaratorContext::MemberContext:
case DeclaratorContext::BlockContext:
case DeclaratorContext::ForContext:
case DeclaratorContext::InitStmtContext:
case DeclaratorContext::BlockLiteralContext:
case DeclaratorContext::LambdaExprContext:
// C++11 [dcl.type]p3:
// A type-specifier-seq shall not define a class or enumeration unless
// it appears in the type-id of an alias-declaration (7.1.3) that is not
// the declaration of a template-declaration.
case DeclaratorContext::AliasDeclContext:
break;
case DeclaratorContext::AliasTemplateContext:
DiagID = diag::err_type_defined_in_alias_template;
break;
case DeclaratorContext::TypeNameContext:
case DeclaratorContext::FunctionalCastContext:
case DeclaratorContext::ConversionIdContext:
case DeclaratorContext::TemplateParamContext:
case DeclaratorContext::CXXNewContext:
case DeclaratorContext::CXXCatchContext:
case DeclaratorContext::ObjCCatchContext:
case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
DiagID = diag::err_type_defined_in_type_specifier;
break;
case DeclaratorContext::PrototypeContext:
case DeclaratorContext::LambdaExprParameterContext:
case DeclaratorContext::ObjCParameterContext:
case DeclaratorContext::ObjCResultContext:
case DeclaratorContext::KNRTypeListContext:
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
DiagID = diag::err_type_defined_in_param_type;
break;
case DeclaratorContext::ConditionContext:
// C++ 6.4p2:
// The type-specifier-seq shall not contain typedef and shall not declare
// a new class or enumeration.
DiagID = diag::err_type_defined_in_condition;
break;
}
if (DiagID != 0) {
SemaRef.Diag(OwnedTagDecl->getLocation(), DiagID)
<< SemaRef.Context.getTypeDeclType(OwnedTagDecl);
D.setInvalidType(true);
}
}
assert(!T.isNull() && "This function should not return a null type");
return T;
}
/// Produce an appropriate diagnostic for an ambiguity between a function
/// declarator and a C++ direct-initializer.
static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
DeclaratorChunk &DeclType, QualType RT) {
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
assert(FTI.isAmbiguous && "no direct-initializer / function ambiguity");
// If the return type is void there is no ambiguity.
if (RT->isVoidType())
return;
// An initializer for a non-class type can have at most one argument.
if (!RT->isRecordType() && FTI.NumParams > 1)
return;
// An initializer for a reference must have exactly one argument.
if (RT->isReferenceType() && FTI.NumParams != 1)
return;
// Only warn if this declarator is declaring a function at block scope, and
// doesn't have a storage class (such as 'extern') specified.
if (!D.isFunctionDeclarator() ||
D.getFunctionDefinitionKind() != FDK_Declaration ||
!S.CurContext->isFunctionOrMethod() ||
D.getDeclSpec().getStorageClassSpec()
!= DeclSpec::SCS_unspecified)
return;
// Inside a condition, a direct initializer is not permitted. We allow one to
// be parsed in order to give better diagnostics in condition parsing.
if (D.getContext() == DeclaratorContext::ConditionContext)
return;
SourceRange ParenRange(DeclType.Loc, DeclType.EndLoc);
S.Diag(DeclType.Loc,
FTI.NumParams ? diag::warn_parens_disambiguated_as_function_declaration
: diag::warn_empty_parens_are_function_decl)
<< ParenRange;
// If the declaration looks like:
// T var1,
// f();
// and name lookup finds a function named 'f', then the ',' was
// probably intended to be a ';'.
if (!D.isFirstDeclarator() && D.getIdentifier()) {
FullSourceLoc Comma(D.getCommaLoc(), S.SourceMgr);
FullSourceLoc Name(D.getIdentifierLoc(), S.SourceMgr);
if (Comma.getFileID() != Name.getFileID() ||
Comma.getSpellingLineNumber() != Name.getSpellingLineNumber()) {
LookupResult Result(S, D.getIdentifier(), SourceLocation(),
Sema::LookupOrdinaryName);
if (S.LookupName(Result, S.getCurScope()))
S.Diag(D.getCommaLoc(), diag::note_empty_parens_function_call)
<< FixItHint::CreateReplacement(D.getCommaLoc(), ";")
<< D.getIdentifier();
Result.suppressDiagnostics();
}
}
if (FTI.NumParams > 0) {
// For a declaration with parameters, eg. "T var(T());", suggest adding
// parens around the first parameter to turn the declaration into a
// variable declaration.
SourceRange Range = FTI.Params[0].Param->getSourceRange();
SourceLocation B = Range.getBegin();
SourceLocation E = S.getLocForEndOfToken(Range.getEnd());
// FIXME: Maybe we should suggest adding braces instead of parens
// in C++11 for classes that don't have an initializer_list constructor.
S.Diag(B, diag::note_additional_parens_for_variable_declaration)
<< FixItHint::CreateInsertion(B, "(")
<< FixItHint::CreateInsertion(E, ")");
} else {
// For a declaration without parameters, eg. "T var();", suggest replacing
// the parens with an initializer to turn the declaration into a variable
// declaration.
const CXXRecordDecl *RD = RT->getAsCXXRecordDecl();
// Empty parens mean value-initialization, and no parens mean
// default initialization. These are equivalent if the default
// constructor is user-provided or if zero-initialization is a
// no-op.
if (RD && RD->hasDefinition() &&
(RD->isEmpty() || RD->hasUserProvidedDefaultConstructor()))
S.Diag(DeclType.Loc, diag::note_empty_parens_default_ctor)
<< FixItHint::CreateRemoval(ParenRange);
else {
std::string Init =
S.getFixItZeroInitializerForType(RT, ParenRange.getBegin());
if (Init.empty() && S.LangOpts.CPlusPlus11)
Init = "{}";
if (!Init.empty())
S.Diag(DeclType.Loc, diag::note_empty_parens_zero_initialize)
<< FixItHint::CreateReplacement(ParenRange, Init);
}
}
}
/// Produce an appropriate diagnostic for a declarator with top-level
/// parentheses.
static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
DeclaratorChunk &Paren = D.getTypeObject(D.getNumTypeObjects() - 1);
assert(Paren.Kind == DeclaratorChunk::Paren &&
"do not have redundant top-level parentheses");
// This is a syntactic check; we're not interested in cases that arise
// during template instantiation.
if (S.inTemplateInstantiation())
return;
// Check whether this could be intended to be a construction of a temporary
// object in C++ via a function-style cast.
bool CouldBeTemporaryObject =
S.getLangOpts().CPlusPlus && D.isExpressionContext() &&
!D.isInvalidType() && D.getIdentifier() &&
D.getDeclSpec().getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
(T->isRecordType() || T->isDependentType()) &&
D.getDeclSpec().getTypeQualifiers() == 0 && D.isFirstDeclarator();
bool StartsWithDeclaratorId = true;
for (auto &C : D.type_objects()) {
switch (C.Kind) {
case DeclaratorChunk::Paren:
if (&C == &Paren)
continue;
LLVM_FALLTHROUGH;
case DeclaratorChunk::Pointer:
StartsWithDeclaratorId = false;
continue;
case DeclaratorChunk::Array:
if (!C.Arr.NumElts)
CouldBeTemporaryObject = false;
continue;
case DeclaratorChunk::Reference:
// FIXME: Suppress the warning here if there is no initializer; we're
// going to give an error anyway.
// We assume that something like 'T (&x) = y;' is highly likely to not
// be intended to be a temporary object.
CouldBeTemporaryObject = false;
StartsWithDeclaratorId = false;
continue;
case DeclaratorChunk::Function:
// In a new-type-id, function chunks require parentheses.
if (D.getContext() == DeclaratorContext::CXXNewContext)
return;
// FIXME: "A(f())" deserves a vexing-parse warning, not just a
// redundant-parens warning, but we don't know whether the function
// chunk was syntactically valid as an expression here.
CouldBeTemporaryObject = false;
continue;
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Pipe:
// These cannot appear in expressions.
CouldBeTemporaryObject = false;
StartsWithDeclaratorId = false;
continue;
}
}
// FIXME: If there is an initializer, assume that this is not intended to be
// a construction of a temporary object.
// Check whether the name has already been declared; if not, this is not a
// function-style cast.
if (CouldBeTemporaryObject) {
LookupResult Result(S, D.getIdentifier(), SourceLocation(),
Sema::LookupOrdinaryName);
if (!S.LookupName(Result, S.getCurScope()))
CouldBeTemporaryObject = false;
Result.suppressDiagnostics();
}
SourceRange ParenRange(Paren.Loc, Paren.EndLoc);
if (!CouldBeTemporaryObject) {
// If we have A (::B), the parentheses affect the meaning of the program.
// Suppress the warning in that case. Don't bother looking at the DeclSpec
// here: even (e.g.) "int ::x" is visually ambiguous even though it's
// formally unambiguous.
if (StartsWithDeclaratorId && D.getCXXScopeSpec().isValid()) {
for (NestedNameSpecifier *NNS = D.getCXXScopeSpec().getScopeRep(); NNS;
NNS = NNS->getPrefix()) {
if (NNS->getKind() == NestedNameSpecifier::Global)
return;
}
}
S.Diag(Paren.Loc, diag::warn_redundant_parens_around_declarator)
<< ParenRange << FixItHint::CreateRemoval(Paren.Loc)
<< FixItHint::CreateRemoval(Paren.EndLoc);
return;
}
S.Diag(Paren.Loc, diag::warn_parens_disambiguated_as_variable_declaration)
<< ParenRange << D.getIdentifier();
auto *RD = T->getAsCXXRecordDecl();
if (!RD || !RD->hasDefinition() || RD->hasNonTrivialDestructor())
S.Diag(Paren.Loc, diag::note_raii_guard_add_name)
<< FixItHint::CreateInsertion(Paren.Loc, " varname") << T
<< D.getIdentifier();
// FIXME: A cast to void is probably a better suggestion in cases where it's
// valid (when there is no initializer and we're not in a condition).
S.Diag(D.getBeginLoc(), diag::note_function_style_cast_add_parentheses)
<< FixItHint::CreateInsertion(D.getBeginLoc(), "(")
<< FixItHint::CreateInsertion(S.getLocForEndOfToken(D.getEndLoc()), ")");
S.Diag(Paren.Loc, diag::note_remove_parens_for_variable_declaration)
<< FixItHint::CreateRemoval(Paren.Loc)
<< FixItHint::CreateRemoval(Paren.EndLoc);
}
/// Helper for figuring out the default CC for a function declarator type. If
/// this is the outermost chunk, then we can determine the CC from the
/// declarator context. If not, then this could be either a member function
/// type or normal function type.
static CallingConv getCCForDeclaratorChunk(
Sema &S, Declarator &D, const ParsedAttributesView &AttrList,
const DeclaratorChunk::FunctionTypeInfo &FTI, unsigned ChunkIndex) {
assert(D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function);
// Check for an explicit CC attribute.
for (const ParsedAttr &AL : AttrList) {
switch (AL.getKind()) {
CALLING_CONV_ATTRS_CASELIST : {
// Ignore attributes that don't validate or can't apply to the
// function type. We'll diagnose the failure to apply them in
// handleFunctionTypeAttr.
CallingConv CC;
if (!S.CheckCallingConvAttr(AL, CC) &&
(!FTI.isVariadic || supportsVariadicCall(CC))) {
return CC;
}
break;
}
default:
break;
}
}
bool IsCXXInstanceMethod = false;
if (S.getLangOpts().CPlusPlus) {
// Look inwards through parentheses to see if this chunk will form a
// member pointer type or if we're the declarator. Any type attributes
// between here and there will override the CC we choose here.
unsigned I = ChunkIndex;
bool FoundNonParen = false;
while (I && !FoundNonParen) {
--I;
if (D.getTypeObject(I).Kind != DeclaratorChunk::Paren)
FoundNonParen = true;
}
if (FoundNonParen) {
// If we're not the declarator, we're a regular function type unless we're
// in a member pointer.
IsCXXInstanceMethod =
D.getTypeObject(I).Kind == DeclaratorChunk::MemberPointer;
} else if (D.getContext() == DeclaratorContext::LambdaExprContext) {
// This can only be a call operator for a lambda, which is an instance
// method.
IsCXXInstanceMethod = true;
} else {
// We're the innermost decl chunk, so must be a function declarator.
assert(D.isFunctionDeclarator());
// If we're inside a record, we're declaring a method, but it could be
// explicitly or implicitly static.
IsCXXInstanceMethod =
D.isFirstDeclarationOfMember() &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
!D.isStaticMember();
}
}
CallingConv CC = S.Context.getDefaultCallingConvention(FTI.isVariadic,
IsCXXInstanceMethod);
// Attribute AT_OpenCLKernel affects the calling convention for SPIR
// and AMDGPU targets, hence it cannot be treated as a calling
// convention attribute. This is the simplest place to infer
// calling convention for OpenCL kernels.
if (S.getLangOpts().OpenCL) {
for (const ParsedAttr &AL : D.getDeclSpec().getAttributes()) {
if (AL.getKind() == ParsedAttr::AT_OpenCLKernel) {
CC = CC_OpenCLKernel;
break;
}
}
}
return CC;
}
namespace {
/// A simple notion of pointer kinds, which matches up with the various
/// pointer declarators.
enum class SimplePointerKind {
Pointer,
BlockPointer,
MemberPointer,
Array,
};
} // end anonymous namespace
IdentifierInfo *Sema::getNullabilityKeyword(NullabilityKind nullability) {
switch (nullability) {
case NullabilityKind::NonNull:
if (!Ident__Nonnull)
Ident__Nonnull = PP.getIdentifierInfo("_Nonnull");
return Ident__Nonnull;
case NullabilityKind::Nullable:
if (!Ident__Nullable)
Ident__Nullable = PP.getIdentifierInfo("_Nullable");
return Ident__Nullable;
case NullabilityKind::Unspecified:
if (!Ident__Null_unspecified)
Ident__Null_unspecified = PP.getIdentifierInfo("_Null_unspecified");
return Ident__Null_unspecified;
}
llvm_unreachable("Unknown nullability kind.");
}
/// Retrieve the identifier "NSError".
IdentifierInfo *Sema::getNSErrorIdent() {
if (!Ident_NSError)
Ident_NSError = PP.getIdentifierInfo("NSError");
return Ident_NSError;
}
/// Check whether there is a nullability attribute of any kind in the given
/// attribute list.
static bool hasNullabilityAttr(const ParsedAttributesView &attrs) {
for (const ParsedAttr &AL : attrs) {
if (AL.getKind() == ParsedAttr::AT_TypeNonNull ||
AL.getKind() == ParsedAttr::AT_TypeNullable ||
AL.getKind() == ParsedAttr::AT_TypeNullUnspecified)
return true;
}
return false;
}
namespace {
/// Describes the kind of a pointer a declarator describes.
enum class PointerDeclaratorKind {
// Not a pointer.
NonPointer,
// Single-level pointer.
SingleLevelPointer,
// Multi-level pointer (of any pointer kind).
MultiLevelPointer,
// CFFooRef*
MaybePointerToCFRef,
// CFErrorRef*
CFErrorRefPointer,
// NSError**
NSErrorPointerPointer,
};
/// Describes a declarator chunk wrapping a pointer that marks inference as
/// unexpected.
// These values must be kept in sync with diagnostics.
enum class PointerWrappingDeclaratorKind {
/// Pointer is top-level.
None = -1,
/// Pointer is an array element.
Array = 0,
/// Pointer is the referent type of a C++ reference.
Reference = 1
};
} // end anonymous namespace
/// Classify the given declarator, whose type-specified is \c type, based on
/// what kind of pointer it refers to.
///
/// This is used to determine the default nullability.
static PointerDeclaratorKind
classifyPointerDeclarator(Sema &S, QualType type, Declarator &declarator,
PointerWrappingDeclaratorKind &wrappingKind) {
unsigned numNormalPointers = 0;
// For any dependent type, we consider it a non-pointer.
if (type->isDependentType())
return PointerDeclaratorKind::NonPointer;
// Look through the declarator chunks to identify pointers.
for (unsigned i = 0, n = declarator.getNumTypeObjects(); i != n; ++i) {
DeclaratorChunk &chunk = declarator.getTypeObject(i);
switch (chunk.Kind) {
case DeclaratorChunk::Array:
if (numNormalPointers == 0)
wrappingKind = PointerWrappingDeclaratorKind::Array;
break;
case DeclaratorChunk::Function:
case DeclaratorChunk::Pipe:
break;
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::MemberPointer:
return numNormalPointers > 0 ? PointerDeclaratorKind::MultiLevelPointer
: PointerDeclaratorKind::SingleLevelPointer;
case DeclaratorChunk::Paren:
break;
case DeclaratorChunk::Reference:
if (numNormalPointers == 0)
wrappingKind = PointerWrappingDeclaratorKind::Reference;
break;
case DeclaratorChunk::Pointer:
++numNormalPointers;
if (numNormalPointers > 2)
return PointerDeclaratorKind::MultiLevelPointer;
break;
}
}
// Then, dig into the type specifier itself.
unsigned numTypeSpecifierPointers = 0;
do {
// Decompose normal pointers.
if (auto ptrType = type->getAs<PointerType>()) {
++numNormalPointers;
if (numNormalPointers > 2)
return PointerDeclaratorKind::MultiLevelPointer;
type = ptrType->getPointeeType();
++numTypeSpecifierPointers;
continue;
}
// Decompose block pointers.
if (type->getAs<BlockPointerType>()) {
return numNormalPointers > 0 ? PointerDeclaratorKind::MultiLevelPointer
: PointerDeclaratorKind::SingleLevelPointer;
}
// Decompose member pointers.
if (type->getAs<MemberPointerType>()) {
return numNormalPointers > 0 ? PointerDeclaratorKind::MultiLevelPointer
: PointerDeclaratorKind::SingleLevelPointer;
}
// Look at Objective-C object pointers.
if (auto objcObjectPtr = type->getAs<ObjCObjectPointerType>()) {
++numNormalPointers;
++numTypeSpecifierPointers;
// If this is NSError**, report that.
if (auto objcClassDecl = objcObjectPtr->getInterfaceDecl()) {
if (objcClassDecl->getIdentifier() == S.getNSErrorIdent() &&
numNormalPointers == 2 && numTypeSpecifierPointers < 2) {
return PointerDeclaratorKind::NSErrorPointerPointer;
}
}
break;
}
// Look at Objective-C class types.
if (auto objcClass = type->getAs<ObjCInterfaceType>()) {
if (objcClass->getInterface()->getIdentifier() == S.getNSErrorIdent()) {
if (numNormalPointers == 2 && numTypeSpecifierPointers < 2)
return PointerDeclaratorKind::NSErrorPointerPointer;
}
break;
}
// If at this point we haven't seen a pointer, we won't see one.
if (numNormalPointers == 0)
return PointerDeclaratorKind::NonPointer;
if (auto recordType = type->getAs<RecordType>()) {
RecordDecl *recordDecl = recordType->getDecl();
bool isCFError = false;
if (S.CFError) {
// If we already know about CFError, test it directly.
isCFError = (S.CFError == recordDecl);
} else {
// Check whether this is CFError, which we identify based on its bridge
// to NSError. CFErrorRef used to be declared with "objc_bridge" but is
// now declared with "objc_bridge_mutable", so look for either one of
// the two attributes.
if (recordDecl->getTagKind() == TTK_Struct && numNormalPointers > 0) {
IdentifierInfo *bridgedType = nullptr;
if (auto bridgeAttr = recordDecl->getAttr<ObjCBridgeAttr>())
bridgedType = bridgeAttr->getBridgedType();
else if (auto bridgeAttr =
recordDecl->getAttr<ObjCBridgeMutableAttr>())
bridgedType = bridgeAttr->getBridgedType();
if (bridgedType == S.getNSErrorIdent()) {
S.CFError = recordDecl;
isCFError = true;
}
}
}
// If this is CFErrorRef*, report it as such.
if (isCFError && numNormalPointers == 2 && numTypeSpecifierPointers < 2) {
return PointerDeclaratorKind::CFErrorRefPointer;
}
break;
}
break;
} while (true);
switch (numNormalPointers) {
case 0:
return PointerDeclaratorKind::NonPointer;
case 1:
return PointerDeclaratorKind::SingleLevelPointer;
case 2:
return PointerDeclaratorKind::MaybePointerToCFRef;
default:
return PointerDeclaratorKind::MultiLevelPointer;
}
}
static FileID getNullabilityCompletenessCheckFileID(Sema &S,
SourceLocation loc) {
// If we're anywhere in a function, method, or closure context, don't perform
// completeness checks.
for (DeclContext *ctx = S.CurContext; ctx; ctx = ctx->getParent()) {
if (ctx->isFunctionOrMethod())
return FileID();
if (ctx->isFileContext())
break;
}
// We only care about the expansion location.
loc = S.SourceMgr.getExpansionLoc(loc);
FileID file = S.SourceMgr.getFileID(loc);
if (file.isInvalid())
return FileID();
// Retrieve file information.
bool invalid = false;
const SrcMgr::SLocEntry &sloc = S.SourceMgr.getSLocEntry(file, &invalid);
if (invalid || !sloc.isFile())
return FileID();
// We don't want to perform completeness checks on the main file or in
// system headers.
const SrcMgr::FileInfo &fileInfo = sloc.getFile();
if (fileInfo.getIncludeLoc().isInvalid())
return FileID();
if (fileInfo.getFileCharacteristic() != SrcMgr::C_User &&
S.Diags.getSuppressSystemWarnings()) {
return FileID();
}
return file;
}
/// Creates a fix-it to insert a C-style nullability keyword at \p pointerLoc,
/// taking into account whitespace before and after.
static void fixItNullability(Sema &S, DiagnosticBuilder &Diag,
SourceLocation PointerLoc,
NullabilityKind Nullability) {
assert(PointerLoc.isValid());
if (PointerLoc.isMacroID())
return;
SourceLocation FixItLoc = S.getLocForEndOfToken(PointerLoc);
if (!FixItLoc.isValid() || FixItLoc == PointerLoc)
return;
const char *NextChar = S.SourceMgr.getCharacterData(FixItLoc);
if (!NextChar)
return;
SmallString<32> InsertionTextBuf{" "};
InsertionTextBuf += getNullabilitySpelling(Nullability);
InsertionTextBuf += " ";
StringRef InsertionText = InsertionTextBuf.str();
if (isWhitespace(*NextChar)) {
InsertionText = InsertionText.drop_back();
} else if (NextChar[-1] == '[') {
if (NextChar[0] == ']')
InsertionText = InsertionText.drop_back().drop_front();
else
InsertionText = InsertionText.drop_front();
} else if (!isIdentifierBody(NextChar[0], /*allow dollar*/true) &&
!isIdentifierBody(NextChar[-1], /*allow dollar*/true)) {
InsertionText = InsertionText.drop_back().drop_front();
}
Diag << FixItHint::CreateInsertion(FixItLoc, InsertionText);
}
static void emitNullabilityConsistencyWarning(Sema &S,
SimplePointerKind PointerKind,
SourceLocation PointerLoc,
SourceLocation PointerEndLoc) {
assert(PointerLoc.isValid());
if (PointerKind == SimplePointerKind::Array) {
S.Diag(PointerLoc, diag::warn_nullability_missing_array);
} else {
S.Diag(PointerLoc, diag::warn_nullability_missing)
<< static_cast<unsigned>(PointerKind);
}
auto FixItLoc = PointerEndLoc.isValid() ? PointerEndLoc : PointerLoc;
if (FixItLoc.isMacroID())
return;
auto addFixIt = [&](NullabilityKind Nullability) {
auto Diag = S.Diag(FixItLoc, diag::note_nullability_fix_it);
Diag << static_cast<unsigned>(Nullability);
Diag << static_cast<unsigned>(PointerKind);
fixItNullability(S, Diag, FixItLoc, Nullability);
};
addFixIt(NullabilityKind::Nullable);
addFixIt(NullabilityKind::NonNull);
}
/// Complains about missing nullability if the file containing \p pointerLoc
/// has other uses of nullability (either the keywords or the \c assume_nonnull
/// pragma).
///
/// If the file has \e not seen other uses of nullability, this particular
/// pointer is saved for possible later diagnosis. See recordNullabilitySeen().
static void
checkNullabilityConsistency(Sema &S, SimplePointerKind pointerKind,
SourceLocation pointerLoc,
SourceLocation pointerEndLoc = SourceLocation()) {
// Determine which file we're performing consistency checking for.
FileID file = getNullabilityCompletenessCheckFileID(S, pointerLoc);
if (file.isInvalid())
return;
// If we haven't seen any type nullability in this file, we won't warn now
// about anything.
FileNullability &fileNullability = S.NullabilityMap[file];
if (!fileNullability.SawTypeNullability) {
// If this is the first pointer declarator in the file, and the appropriate
// warning is on, record it in case we need to diagnose it retroactively.
diag::kind diagKind;
if (pointerKind == SimplePointerKind::Array)
diagKind = diag::warn_nullability_missing_array;
else
diagKind = diag::warn_nullability_missing;
if (fileNullability.PointerLoc.isInvalid() &&
!S.Context.getDiagnostics().isIgnored(diagKind, pointerLoc)) {
fileNullability.PointerLoc = pointerLoc;
fileNullability.PointerEndLoc = pointerEndLoc;
fileNullability.PointerKind = static_cast<unsigned>(pointerKind);
}
return;
}
// Complain about missing nullability.
emitNullabilityConsistencyWarning(S, pointerKind, pointerLoc, pointerEndLoc);
}
/// Marks that a nullability feature has been used in the file containing
/// \p loc.
///
/// If this file already had pointer types in it that were missing nullability,
/// the first such instance is retroactively diagnosed.
///
/// \sa checkNullabilityConsistency
static void recordNullabilitySeen(Sema &S, SourceLocation loc) {
FileID file = getNullabilityCompletenessCheckFileID(S, loc);
if (file.isInvalid())
return;
FileNullability &fileNullability = S.NullabilityMap[file];
if (fileNullability.SawTypeNullability)
return;
fileNullability.SawTypeNullability = true;
// If we haven't seen any type nullability before, now we have. Retroactively
// diagnose the first unannotated pointer, if there was one.
if (fileNullability.PointerLoc.isInvalid())
return;
auto kind = static_cast<SimplePointerKind>(fileNullability.PointerKind);
emitNullabilityConsistencyWarning(S, kind, fileNullability.PointerLoc,
fileNullability.PointerEndLoc);
}
/// Returns true if any of the declarator chunks before \p endIndex include a
/// level of indirection: array, pointer, reference, or pointer-to-member.
///
/// Because declarator chunks are stored in outer-to-inner order, testing
/// every chunk before \p endIndex is testing all chunks that embed the current
/// chunk as part of their type.
///
/// It is legal to pass the result of Declarator::getNumTypeObjects() as the
/// end index, in which case all chunks are tested.
static bool hasOuterPointerLikeChunk(const Declarator &D, unsigned endIndex) {
unsigned i = endIndex;
while (i != 0) {
// Walk outwards along the declarator chunks.
--i;
const DeclaratorChunk &DC = D.getTypeObject(i);
switch (DC.Kind) {
case DeclaratorChunk::Paren:
break;
case DeclaratorChunk::Array:
case DeclaratorChunk::Pointer:
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
return true;
case DeclaratorChunk::Function:
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::Pipe:
// These are invalid anyway, so just ignore.
break;
}
}
return false;
}
static bool IsNoDerefableChunk(DeclaratorChunk Chunk) {
return (Chunk.Kind == DeclaratorChunk::Pointer ||
Chunk.Kind == DeclaratorChunk::Array);
}
template<typename AttrT>
static AttrT *createSimpleAttr(ASTContext &Ctx, ParsedAttr &Attr) {
Attr.setUsedAsTypeAttr();
return ::new (Ctx)
AttrT(Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex());
}
static Attr *createNullabilityAttr(ASTContext &Ctx, ParsedAttr &Attr,
NullabilityKind NK) {
switch (NK) {
case NullabilityKind::NonNull:
return createSimpleAttr<TypeNonNullAttr>(Ctx, Attr);
case NullabilityKind::Nullable:
return createSimpleAttr<TypeNullableAttr>(Ctx, Attr);
case NullabilityKind::Unspecified:
return createSimpleAttr<TypeNullUnspecifiedAttr>(Ctx, Attr);
}
llvm_unreachable("unknown NullabilityKind");
}
static TypeSourceInfo *
GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
QualType T, TypeSourceInfo *ReturnTypeInfo);
static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType declSpecType,
TypeSourceInfo *TInfo) {
// The TypeSourceInfo that this function returns will not be a null type.
// If there is an error, this function will fill in a dummy type as fallback.
QualType T = declSpecType;
Declarator &D = state.getDeclarator();
Sema &S = state.getSema();
ASTContext &Context = S.Context;
const LangOptions &LangOpts = S.getLangOpts();
// The name we're declaring, if any.
DeclarationName Name;
if (D.getIdentifier())
Name = D.getIdentifier();
// Does this declaration declare a typedef-name?
bool IsTypedefName =
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef ||
D.getContext() == DeclaratorContext::AliasDeclContext ||
D.getContext() == DeclaratorContext::AliasTemplateContext;
// Does T refer to a function type with a cv-qualifier or a ref-qualifier?
bool IsQualifiedFunction = T->isFunctionProtoType() &&
(!T->castAs<FunctionProtoType>()->getTypeQuals().empty() ||
T->castAs<FunctionProtoType>()->getRefQualifier() != RQ_None);
// If T is 'decltype(auto)', the only declarators we can have are parens
// and at most one function declarator if this is a function declaration.
// If T is a deduced class template specialization type, we can have no
// declarator chunks at all.
if (auto *DT = T->getAs<DeducedType>()) {
const AutoType *AT = T->getAs<AutoType>();
bool IsClassTemplateDeduction = isa<DeducedTemplateSpecializationType>(DT);
if ((AT && AT->isDecltypeAuto()) || IsClassTemplateDeduction) {
for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {
unsigned Index = E - I - 1;
DeclaratorChunk &DeclChunk = D.getTypeObject(Index);
unsigned DiagId = IsClassTemplateDeduction
? diag::err_deduced_class_template_compound_type
: diag::err_decltype_auto_compound_type;
unsigned DiagKind = 0;
switch (DeclChunk.Kind) {
case DeclaratorChunk::Paren:
// FIXME: Rejecting this is a little silly.
if (IsClassTemplateDeduction) {
DiagKind = 4;
break;
}
continue;
case DeclaratorChunk::Function: {
if (IsClassTemplateDeduction) {
DiagKind = 3;
break;
}
unsigned FnIndex;
if (D.isFunctionDeclarationContext() &&
D.isFunctionDeclarator(FnIndex) && FnIndex == Index)
continue;
DiagId = diag::err_decltype_auto_function_declarator_not_declaration;
break;
}
case DeclaratorChunk::Pointer:
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::MemberPointer:
DiagKind = 0;
break;
case DeclaratorChunk::Reference:
DiagKind = 1;
break;
case DeclaratorChunk::Array:
DiagKind = 2;
break;
case DeclaratorChunk::Pipe:
break;
}
S.Diag(DeclChunk.Loc, DiagId) << DiagKind;
D.setInvalidType(true);
break;
}
}
}
// Determine whether we should infer _Nonnull on pointer types.
Optional<NullabilityKind> inferNullability;
bool inferNullabilityCS = false;
bool inferNullabilityInnerOnly = false;
bool inferNullabilityInnerOnlyComplete = false;
// Are we in an assume-nonnull region?
bool inAssumeNonNullRegion = false;
SourceLocation assumeNonNullLoc = S.PP.getPragmaAssumeNonNullLoc();
if (assumeNonNullLoc.isValid()) {
inAssumeNonNullRegion = true;
recordNullabilitySeen(S, assumeNonNullLoc);
}
// Whether to complain about missing nullability specifiers or not.
enum {
/// Never complain.
CAMN_No,
/// Complain on the inner pointers (but not the outermost
/// pointer).
CAMN_InnerPointers,
/// Complain about any pointers that don't have nullability
/// specified or inferred.
CAMN_Yes
} complainAboutMissingNullability = CAMN_No;
unsigned NumPointersRemaining = 0;
auto complainAboutInferringWithinChunk = PointerWrappingDeclaratorKind::None;
if (IsTypedefName) {
// For typedefs, we do not infer any nullability (the default),
// and we only complain about missing nullability specifiers on
// inner pointers.
complainAboutMissingNullability = CAMN_InnerPointers;
if (T->canHaveNullability(/*ResultIfUnknown*/false) &&
!T->getNullability(S.Context)) {
// Note that we allow but don't require nullability on dependent types.
++NumPointersRemaining;
}
for (unsigned i = 0, n = D.getNumTypeObjects(); i != n; ++i) {
DeclaratorChunk &chunk = D.getTypeObject(i);
switch (chunk.Kind) {
case DeclaratorChunk::Array:
case DeclaratorChunk::Function:
case DeclaratorChunk::Pipe:
break;
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::MemberPointer:
++NumPointersRemaining;
break;
case DeclaratorChunk::Paren:
case DeclaratorChunk::Reference:
continue;
case DeclaratorChunk::Pointer:
++NumPointersRemaining;
continue;
}
}
} else {
bool isFunctionOrMethod = false;
switch (auto context = state.getDeclarator().getContext()) {
case DeclaratorContext::ObjCParameterContext:
case DeclaratorContext::ObjCResultContext:
case DeclaratorContext::PrototypeContext:
case DeclaratorContext::TrailingReturnContext:
case DeclaratorContext::TrailingReturnVarContext:
isFunctionOrMethod = true;
LLVM_FALLTHROUGH;
case DeclaratorContext::MemberContext:
if (state.getDeclarator().isObjCIvar() && !isFunctionOrMethod) {
complainAboutMissingNullability = CAMN_No;
break;
}
// Weak properties are inferred to be nullable.
if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) {
inferNullability = NullabilityKind::Nullable;
break;
}
LLVM_FALLTHROUGH;
case DeclaratorContext::FileContext:
case DeclaratorContext::KNRTypeListContext: {
complainAboutMissingNullability = CAMN_Yes;
// Nullability inference depends on the type and declarator.
auto wrappingKind = PointerWrappingDeclaratorKind::None;
switch (classifyPointerDeclarator(S, T, D, wrappingKind)) {
case PointerDeclaratorKind::NonPointer:
case PointerDeclaratorKind::MultiLevelPointer:
// Cannot infer nullability.
break;
case PointerDeclaratorKind::SingleLevelPointer:
// Infer _Nonnull if we are in an assumes-nonnull region.
if (inAssumeNonNullRegion) {
complainAboutInferringWithinChunk = wrappingKind;
inferNullability = NullabilityKind::NonNull;
inferNullabilityCS =
(context == DeclaratorContext::ObjCParameterContext ||
context == DeclaratorContext::ObjCResultContext);
}
break;
case PointerDeclaratorKind::CFErrorRefPointer:
case PointerDeclaratorKind::NSErrorPointerPointer:
// Within a function or method signature, infer _Nullable at both
// levels.
if (isFunctionOrMethod && inAssumeNonNullRegion)
inferNullability = NullabilityKind::Nullable;
break;
case PointerDeclaratorKind::MaybePointerToCFRef:
if (isFunctionOrMethod) {
// On pointer-to-pointer parameters marked cf_returns_retained or
// cf_returns_not_retained, if the outer pointer is explicit then
// infer the inner pointer as _Nullable.
auto hasCFReturnsAttr =
[](const ParsedAttributesView &AttrList) -> bool {
return AttrList.hasAttribute(ParsedAttr::AT_CFReturnsRetained) ||
AttrList.hasAttribute(ParsedAttr::AT_CFReturnsNotRetained);
};
if (const auto *InnermostChunk = D.getInnermostNonParenChunk()) {
if (hasCFReturnsAttr(D.getAttributes()) ||
hasCFReturnsAttr(InnermostChunk->getAttrs()) ||
hasCFReturnsAttr(D.getDeclSpec().getAttributes())) {
inferNullability = NullabilityKind::Nullable;
inferNullabilityInnerOnly = true;
}
}
}
break;
}
break;
}
case DeclaratorContext::ConversionIdContext:
complainAboutMissingNullability = CAMN_Yes;
break;
case DeclaratorContext::AliasDeclContext:
case DeclaratorContext::AliasTemplateContext:
case DeclaratorContext::BlockContext:
case DeclaratorContext::BlockLiteralContext:
case DeclaratorContext::ConditionContext:
case DeclaratorContext::CXXCatchContext:
case DeclaratorContext::CXXNewContext:
case DeclaratorContext::ForContext:
case DeclaratorContext::InitStmtContext:
case DeclaratorContext::LambdaExprContext:
case DeclaratorContext::LambdaExprParameterContext:
case DeclaratorContext::ObjCCatchContext:
case DeclaratorContext::TemplateParamContext:
case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
case DeclaratorContext::TypeNameContext:
case DeclaratorContext::FunctionalCastContext:
// Don't infer in these contexts.
break;
}
}
// Local function that returns true if its argument looks like a va_list.
auto isVaList = [&S](QualType T) -> bool {
auto *typedefTy = T->getAs<TypedefType>();
if (!typedefTy)
return false;
TypedefDecl *vaListTypedef = S.Context.getBuiltinVaListDecl();
do {
if (typedefTy->getDecl() == vaListTypedef)
return true;
if (auto *name = typedefTy->getDecl()->getIdentifier())
if (name->isStr("va_list"))
return true;
typedefTy = typedefTy->desugar()->getAs<TypedefType>();
} while (typedefTy);
return false;
};
// Local function that checks the nullability for a given pointer declarator.
// Returns true if _Nonnull was inferred.
auto inferPointerNullability =
[&](SimplePointerKind pointerKind, SourceLocation pointerLoc,
SourceLocation pointerEndLoc,
ParsedAttributesView &attrs) -> ParsedAttr * {
// We've seen a pointer.
if (NumPointersRemaining > 0)
--NumPointersRemaining;
// If a nullability attribute is present, there's nothing to do.
if (hasNullabilityAttr(attrs))
return nullptr;
// If we're supposed to infer nullability, do so now.
if (inferNullability && !inferNullabilityInnerOnlyComplete) {
ParsedAttr::Syntax syntax = inferNullabilityCS
? ParsedAttr::AS_ContextSensitiveKeyword
: ParsedAttr::AS_Keyword;
ParsedAttr *nullabilityAttr =
state.getDeclarator().getAttributePool().create(
S.getNullabilityKeyword(*inferNullability),
SourceRange(pointerLoc), nullptr, SourceLocation(), nullptr, 0,
syntax);
attrs.addAtEnd(nullabilityAttr);
if (inferNullabilityCS) {
state.getDeclarator().getMutableDeclSpec().getObjCQualifiers()
->setObjCDeclQualifier(ObjCDeclSpec::DQ_CSNullability);
}
if (pointerLoc.isValid() &&
complainAboutInferringWithinChunk !=
PointerWrappingDeclaratorKind::None) {
auto Diag =
S.Diag(pointerLoc, diag::warn_nullability_inferred_on_nested_type);
Diag << static_cast<int>(complainAboutInferringWithinChunk);
fixItNullability(S, Diag, pointerLoc, NullabilityKind::NonNull);
}
if (inferNullabilityInnerOnly)
inferNullabilityInnerOnlyComplete = true;
return nullabilityAttr;
}
// If we're supposed to complain about missing nullability, do so
// now if it's truly missing.
switch (complainAboutMissingNullability) {
case CAMN_No:
break;
case CAMN_InnerPointers:
if (NumPointersRemaining == 0)
break;
LLVM_FALLTHROUGH;
case CAMN_Yes:
checkNullabilityConsistency(S, pointerKind, pointerLoc, pointerEndLoc);
}
return nullptr;
};
// If the type itself could have nullability but does not, infer pointer
// nullability and perform consistency checking.
if (S.CodeSynthesisContexts.empty()) {
if (T->canHaveNullability(/*ResultIfUnknown*/false) &&
!T->getNullability(S.Context)) {
if (isVaList(T)) {
// Record that we've seen a pointer, but do nothing else.
if (NumPointersRemaining > 0)
--NumPointersRemaining;
} else {
SimplePointerKind pointerKind = SimplePointerKind::Pointer;
if (T->isBlockPointerType())
pointerKind = SimplePointerKind::BlockPointer;
else if (T->isMemberPointerType())
pointerKind = SimplePointerKind::MemberPointer;
if (auto *attr = inferPointerNullability(
pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(),
D.getDeclSpec().getEndLoc(),
D.getMutableDeclSpec().getAttributes())) {
T = state.getAttributedType(
createNullabilityAttr(Context, *attr, *inferNullability), T, T);
}
}
}
if (complainAboutMissingNullability == CAMN_Yes &&
T->isArrayType() && !T->getNullability(S.Context) && !isVaList(T) &&
D.isPrototypeContext() &&
!hasOuterPointerLikeChunk(D, D.getNumTypeObjects())) {
checkNullabilityConsistency(S, SimplePointerKind::Array,
D.getDeclSpec().getTypeSpecTypeLoc());
}
}
bool ExpectNoDerefChunk =
state.getCurrentAttributes().hasAttribute(ParsedAttr::AT_NoDeref);
// Walk the DeclTypeInfo, building the recursive type as we go.
// DeclTypeInfos are ordered from the identifier out, which is
// opposite of what we want :).
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
unsigned chunkIndex = e - i - 1;
state.setCurrentChunkIndex(chunkIndex);
DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
IsQualifiedFunction &= DeclType.Kind == DeclaratorChunk::Paren;
switch (DeclType.Kind) {
case DeclaratorChunk::Paren:
if (i == 0)
warnAboutRedundantParens(S, D, T);
T = S.BuildParenType(T);
break;
case DeclaratorChunk::BlockPointer:
// If blocks are disabled, emit an error.
if (!LangOpts.Blocks)
S.Diag(DeclType.Loc, diag::err_blocks_disable) << LangOpts.OpenCL;
// Handle pointer nullability.
inferPointerNullability(SimplePointerKind::BlockPointer, DeclType.Loc,
DeclType.EndLoc, DeclType.getAttrs());
T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name);
if (DeclType.Cls.TypeQuals || LangOpts.OpenCL) {
// OpenCL v2.0, s6.12.5 - Block variable declarations are implicitly
// qualified with const.
if (LangOpts.OpenCL)
DeclType.Cls.TypeQuals |= DeclSpec::TQ_const;
T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Cls.TypeQuals);
}
break;
case DeclaratorChunk::Pointer:
// Verify that we're not building a pointer to pointer to function with
// exception specification.
if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
D.setInvalidType(true);
// Build the type anyway.
}
// Handle pointer nullability
inferPointerNullability(SimplePointerKind::Pointer, DeclType.Loc,
DeclType.EndLoc, DeclType.getAttrs());
if (LangOpts.ObjC && T->getAs<ObjCObjectType>()) {
T = Context.getObjCObjectPointerType(T);
if (DeclType.Ptr.TypeQuals)
T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
break;
}
// OpenCL v2.0 s6.9b - Pointer to image/sampler cannot be used.
// OpenCL v2.0 s6.13.16.1 - Pointer to pipe cannot be used.
// OpenCL v2.0 s6.12.5 - Pointers to Blocks are not allowed.
if (LangOpts.OpenCL) {
if (T->isImageType() || T->isSamplerT() || T->isPipeType() ||
T->isBlockPointerType()) {
S.Diag(D.getIdentifierLoc(), diag::err_opencl_pointer_to_type) << T;
D.setInvalidType(true);
}
}
T = S.BuildPointerType(T, DeclType.Loc, Name);
if (DeclType.Ptr.TypeQuals)
T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
break;
case DeclaratorChunk::Reference: {
// Verify that we're not building a reference to pointer to function with
// exception specification.
if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
D.setInvalidType(true);
// Build the type anyway.
}
T = S.BuildReferenceType(T, DeclType.Ref.LValueRef, DeclType.Loc, Name);
if (DeclType.Ref.HasRestrict)
T = S.BuildQualifiedType(T, DeclType.Loc, Qualifiers::Restrict);
break;
}
case DeclaratorChunk::Array: {
// Verify that we're not building an array of pointers to function with
// exception specification.
if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
D.setInvalidType(true);
// Build the type anyway.
}
DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
Expr *ArraySize = static_cast<Expr*>(ATI.NumElts);
ArrayType::ArraySizeModifier ASM;
if (ATI.isStar)
ASM = ArrayType::Star;
else if (ATI.hasStatic)
ASM = ArrayType::Static;
else
ASM = ArrayType::Normal;
if (ASM == ArrayType::Star && !D.isPrototypeContext()) {
// FIXME: This check isn't quite right: it allows star in prototypes
// for function definitions, and disallows some edge cases detailed
// in http://gcc.gnu.org/ml/gcc-patches/2009-02/msg00133.html
S.Diag(DeclType.Loc, diag::err_array_star_outside_prototype);
ASM = ArrayType::Normal;
D.setInvalidType(true);
}
// C99 6.7.5.2p1: The optional type qualifiers and the keyword static
// shall appear only in a declaration of a function parameter with an
// array type, ...
if (ASM == ArrayType::Static || ATI.TypeQuals) {
if (!(D.isPrototypeContext() ||
D.getContext() == DeclaratorContext::KNRTypeListContext)) {
S.Diag(DeclType.Loc, diag::err_array_static_outside_prototype) <<
(ASM == ArrayType::Static ? "'static'" : "type qualifier");
// Remove the 'static' and the type qualifiers.
if (ASM == ArrayType::Static)
ASM = ArrayType::Normal;
ATI.TypeQuals = 0;
D.setInvalidType(true);
}
// C99 6.7.5.2p1: ... and then only in the outermost array type
// derivation.
if (hasOuterPointerLikeChunk(D, chunkIndex)) {
S.Diag(DeclType.Loc, diag::err_array_static_not_outermost) <<
(ASM == ArrayType::Static ? "'static'" : "type qualifier");
if (ASM == ArrayType::Static)
ASM = ArrayType::Normal;
ATI.TypeQuals = 0;
D.setInvalidType(true);
}
}
const AutoType *AT = T->getContainedAutoType();
// Allow arrays of auto if we are a generic lambda parameter.
// i.e. [](auto (&array)[5]) { return array[0]; }; OK
if (AT &&
D.getContext() != DeclaratorContext::LambdaExprParameterContext) {
// We've already diagnosed this for decltype(auto).
if (!AT->isDecltypeAuto())
S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)
<< getPrintableNameForEntity(Name) << T;
T = QualType();
break;
}
// Array parameters can be marked nullable as well, although it's not
// necessary if they're marked 'static'.
if (complainAboutMissingNullability == CAMN_Yes &&
!hasNullabilityAttr(DeclType.getAttrs()) &&
ASM != ArrayType::Static &&
D.isPrototypeContext() &&
!hasOuterPointerLikeChunk(D, chunkIndex)) {
checkNullabilityConsistency(S, SimplePointerKind::Array, DeclType.Loc);
}
T = S.BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals,
SourceRange(DeclType.Loc, DeclType.EndLoc), Name);
break;
}
case DeclaratorChunk::Function: {
// If the function declarator has a prototype (i.e. it is not () and
// does not have a K&R-style identifier list), then the arguments are part
// of the type, otherwise the argument list is ().
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
IsQualifiedFunction =
FTI.hasMethodTypeQualifiers() || FTI.hasRefQualifier();
// Check for auto functions and trailing return type and adjust the
// return type accordingly.
if (!D.isInvalidType()) {
// trailing-return-type is only required if we're declaring a function,
// and not, for instance, a pointer to a function.
if (D.getDeclSpec().hasAutoTypeSpec() &&
!FTI.hasTrailingReturnType() && chunkIndex == 0) {
if (!S.getLangOpts().CPlusPlus14) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto
? diag::err_auto_missing_trailing_return
: diag::err_deduced_return_type);
T = Context.IntTy;
D.setInvalidType(true);
} else {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::warn_cxx11_compat_deduced_return_type);
}
} else if (FTI.hasTrailingReturnType()) {
// T must be exactly 'auto' at this point. See CWG issue 681.
if (isa<ParenType>(T)) {
S.Diag(D.getBeginLoc(), diag::err_trailing_return_in_parens)
<< T << D.getSourceRange();
D.setInvalidType(true);
} else if (D.getName().getKind() ==
UnqualifiedIdKind::IK_DeductionGuideName) {
if (T != Context.DependentTy) {
S.Diag(D.getDeclSpec().getBeginLoc(),
diag::err_deduction_guide_with_complex_decl)
<< D.getSourceRange();
D.setInvalidType(true);
}
} else if (D.getContext() != DeclaratorContext::LambdaExprContext &&
(T.hasQualifiers() || !isa<AutoType>(T) ||
cast<AutoType>(T)->getKeyword() !=
AutoTypeKeyword::Auto)) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_trailing_return_without_auto)
<< T << D.getDeclSpec().getSourceRange();
D.setInvalidType(true);
}
T = S.GetTypeFromParser(FTI.getTrailingReturnType(), &TInfo);
if (T.isNull()) {
// An error occurred parsing the trailing return type.
T = Context.IntTy;
D.setInvalidType(true);
}
} else {
// This function type is not the type of the entity being declared,
// so checking the 'auto' is not the responsibility of this chunk.
}
}
// C99 6.7.5.3p1: The return type may not be a function or array type.
// For conversion functions, we'll diagnose this particular error later.
if (!D.isInvalidType() && (T->isArrayType() || T->isFunctionType()) &&
(D.getName().getKind() !=
UnqualifiedIdKind::IK_ConversionFunctionId)) {
unsigned diagID = diag::err_func_returning_array_function;
// Last processing chunk in block context means this function chunk
// represents the block.
if (chunkIndex == 0 &&
D.getContext() == DeclaratorContext::BlockLiteralContext)
diagID = diag::err_block_returning_array_function;
S.Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
T = Context.IntTy;
D.setInvalidType(true);
}
// Do not allow returning half FP value.
// FIXME: This really should be in BuildFunctionType.
if (T->isHalfType()) {
if (S.getLangOpts().OpenCL) {
if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
<< T << 0 /*pointer hint*/;
D.setInvalidType(true);
}
} else if (!S.getLangOpts().HalfArgsAndReturns) {
S.Diag(D.getIdentifierLoc(),
diag::err_parameters_retval_cannot_have_fp16_type) << 1;
D.setInvalidType(true);
}
}
if (LangOpts.OpenCL) {
// OpenCL v2.0 s6.12.5 - A block cannot be the return value of a
// function.
if (T->isBlockPointerType() || T->isImageType() || T->isSamplerT() ||
T->isPipeType()) {
S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
<< T << 1 /*hint off*/;
D.setInvalidType(true);
}
// OpenCL doesn't support variadic functions and blocks
// (s6.9.e and s6.12.5 OpenCL v2.0) except for printf.
// We also allow here any toolchain reserved identifiers.
if (FTI.isVariadic &&
!(D.getIdentifier() &&
((D.getIdentifier()->getName() == "printf" &&
LangOpts.OpenCLVersion >= 120) ||
D.getIdentifier()->getName().startswith("__")))) {
S.Diag(D.getIdentifierLoc(), diag::err_opencl_variadic_function);
D.setInvalidType(true);
}
}
// Methods cannot return interface types. All ObjC objects are
// passed by reference.
if (T->isObjCObjectType()) {
SourceLocation DiagLoc, FixitLoc;
if (TInfo) {
DiagLoc = TInfo->getTypeLoc().getBeginLoc();
FixitLoc = S.getLocForEndOfToken(TInfo->getTypeLoc().getEndLoc());
} else {
DiagLoc = D.getDeclSpec().getTypeSpecTypeLoc();
FixitLoc = S.getLocForEndOfToken(D.getDeclSpec().getEndLoc());
}
S.Diag(DiagLoc, diag::err_object_cannot_be_passed_returned_by_value)
<< 0 << T
<< FixItHint::CreateInsertion(FixitLoc, "*");
T = Context.getObjCObjectPointerType(T);
if (TInfo) {
TypeLocBuilder TLB;
TLB.pushFullCopy(TInfo->getTypeLoc());
ObjCObjectPointerTypeLoc TLoc = TLB.push<ObjCObjectPointerTypeLoc>(T);
TLoc.setStarLoc(FixitLoc);
TInfo = TLB.getTypeSourceInfo(Context, T);
}
D.setInvalidType(true);
}
// cv-qualifiers on return types are pointless except when the type is a
// class type in C++.
if ((T.getCVRQualifiers() || T->isAtomicType()) &&
!(S.getLangOpts().CPlusPlus &&
(T->isDependentType() || T->isRecordType()))) {
if (T->isVoidType() && !S.getLangOpts().CPlusPlus &&
D.getFunctionDefinitionKind() == FDK_Definition) {
// [6.9.1/3] qualified void return is invalid on a C
// function definition. Apparently ok on declarations and
// in C++ though (!)
S.Diag(DeclType.Loc, diag::err_func_returning_qualified_void) << T;
} else
diagnoseRedundantReturnTypeQualifiers(S, T, D, chunkIndex);
}
// Objective-C ARC ownership qualifiers are ignored on the function
// return type (by type canonicalization). Complain if this attribute
// was written here.
if (T.getQualifiers().hasObjCLifetime()) {
SourceLocation AttrLoc;
if (chunkIndex + 1 < D.getNumTypeObjects()) {
DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
for (const ParsedAttr &AL : ReturnTypeChunk.getAttrs()) {
if (AL.getKind() == ParsedAttr::AT_ObjCOwnership) {
AttrLoc = AL.getLoc();
break;
}
}
}
if (AttrLoc.isInvalid()) {
for (const ParsedAttr &AL : D.getDeclSpec().getAttributes()) {
if (AL.getKind() == ParsedAttr::AT_ObjCOwnership) {
AttrLoc = AL.getLoc();
break;
}
}
}
if (AttrLoc.isValid()) {
// The ownership attributes are almost always written via
// the predefined
// __strong/__weak/__autoreleasing/__unsafe_unretained.
if (AttrLoc.isMacroID())
AttrLoc =
S.SourceMgr.getImmediateExpansionRange(AttrLoc).getBegin();
S.Diag(AttrLoc, diag::warn_arc_lifetime_result_type)
<< T.getQualifiers().getObjCLifetime();
}
}
if (LangOpts.CPlusPlus && D.getDeclSpec().hasTagDefinition()) {
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
S.Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
<< Context.getTypeDeclType(Tag);
}
// Exception specs are not allowed in typedefs. Complain, but add it
// anyway.
if (IsTypedefName && FTI.getExceptionSpecType() && !LangOpts.CPlusPlus17)
S.Diag(FTI.getExceptionSpecLocBeg(),
diag::err_exception_spec_in_typedef)
<< (D.getContext() == DeclaratorContext::AliasDeclContext ||
D.getContext() == DeclaratorContext::AliasTemplateContext);
// If we see "T var();" or "T var(T());" at block scope, it is probably
// an attempt to initialize a variable, not a function declaration.
if (FTI.isAmbiguous)
warnAboutAmbiguousFunction(S, D, DeclType, T);
FunctionType::ExtInfo EI(
getCCForDeclaratorChunk(S, D, DeclType.getAttrs(), FTI, chunkIndex));
if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus
&& !LangOpts.OpenCL) {
// Simple void foo(), where the incoming T is the result type.
T = Context.getFunctionNoProtoType(T, EI);
} else {
// We allow a zero-parameter variadic function in C if the
// function is marked with the "overloadable" attribute. Scan
// for this attribute now.
if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus)
if (!D.getAttributes().hasAttribute(ParsedAttr::AT_Overloadable))
S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_param);
if (FTI.NumParams && FTI.Params[0].Param == nullptr) {
// C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function
// definition.
S.Diag(FTI.Params[0].IdentLoc,
diag::err_ident_list_in_fn_declaration);
D.setInvalidType(true);
// Recover by creating a K&R-style function type.
T = Context.getFunctionNoProtoType(T, EI);
break;
}
FunctionProtoType::ExtProtoInfo EPI;
EPI.ExtInfo = EI;
EPI.Variadic = FTI.isVariadic;
EPI.HasTrailingReturn = FTI.hasTrailingReturnType();
EPI.TypeQuals.addCVRUQualifiers(
FTI.MethodQualifiers ? FTI.MethodQualifiers->getTypeQualifiers()
: 0);
EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None
: FTI.RefQualifierIsLValueRef? RQ_LValue
: RQ_RValue;
// Otherwise, we have a function with a parameter list that is
// potentially variadic.
SmallVector<QualType, 16> ParamTys;
ParamTys.reserve(FTI.NumParams);
SmallVector<FunctionProtoType::ExtParameterInfo, 16>
ExtParameterInfos(FTI.NumParams);
bool HasAnyInterestingExtParameterInfos = false;
for (unsigned i = 0, e = FTI.NumParams; i != e; ++i) {
ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
QualType ParamTy = Param->getType();
assert(!ParamTy.isNull() && "Couldn't parse type?");
// Look for 'void'. void is allowed only as a single parameter to a
// function with no other parameters (C99 6.7.5.3p10). We record
// int(void) as a FunctionProtoType with an empty parameter list.
if (ParamTy->isVoidType()) {
// If this is something like 'float(int, void)', reject it. 'void'
// is an incomplete type (C99 6.2.5p19) and function decls cannot
// have parameters of incomplete type.
if (FTI.NumParams != 1 || FTI.isVariadic) {
S.Diag(DeclType.Loc, diag::err_void_only_param);
ParamTy = Context.IntTy;
Param->setType(ParamTy);
} else if (FTI.Params[i].Ident) {
// Reject, but continue to parse 'int(void abc)'.
S.Diag(FTI.Params[i].IdentLoc, diag::err_param_with_void_type);
ParamTy = Context.IntTy;
Param->setType(ParamTy);
} else {
// Reject, but continue to parse 'float(const void)'.
if (ParamTy.hasQualifiers())
S.Diag(DeclType.Loc, diag::err_void_param_qualified);
// Do not add 'void' to the list.
break;
}
} else if (ParamTy->isHalfType()) {
// Disallow half FP parameters.
// FIXME: This really should be in BuildFunctionType.
if (S.getLangOpts().OpenCL) {
if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
S.Diag(Param->getLocation(),
diag::err_opencl_half_param) << ParamTy;
D.setInvalidType();
Param->setInvalidDecl();
}
} else if (!S.getLangOpts().HalfArgsAndReturns) {
S.Diag(Param->getLocation(),
diag::err_parameters_retval_cannot_have_fp16_type) << 0;
D.setInvalidType();
}
} else if (!FTI.hasPrototype) {
if (ParamTy->isPromotableIntegerType()) {
ParamTy = Context.getPromotedIntegerType(ParamTy);
Param->setKNRPromoted(true);
} else if (const BuiltinType* BTy = ParamTy->getAs<BuiltinType>()) {
if (BTy->getKind() == BuiltinType::Float) {
ParamTy = Context.DoubleTy;
Param->setKNRPromoted(true);
}
}
}
if (LangOpts.ObjCAutoRefCount && Param->hasAttr<NSConsumedAttr>()) {
ExtParameterInfos[i] = ExtParameterInfos[i].withIsConsumed(true);
HasAnyInterestingExtParameterInfos = true;
}
if (auto attr = Param->getAttr<ParameterABIAttr>()) {
ExtParameterInfos[i] =
ExtParameterInfos[i].withABI(attr->getABI());
HasAnyInterestingExtParameterInfos = true;
}
if (Param->hasAttr<PassObjectSizeAttr>()) {
ExtParameterInfos[i] = ExtParameterInfos[i].withHasPassObjectSize();
HasAnyInterestingExtParameterInfos = true;
}
if (Param->hasAttr<NoEscapeAttr>()) {
ExtParameterInfos[i] = ExtParameterInfos[i].withIsNoEscape(true);
HasAnyInterestingExtParameterInfos = true;
}
ParamTys.push_back(ParamTy);
}
if (HasAnyInterestingExtParameterInfos) {
EPI.ExtParameterInfos = ExtParameterInfos.data();
checkExtParameterInfos(S, ParamTys, EPI,
[&](unsigned i) { return FTI.Params[i].Param->getLocation(); });
}
SmallVector<QualType, 4> Exceptions;
SmallVector<ParsedType, 2> DynamicExceptions;
SmallVector<SourceRange, 2> DynamicExceptionRanges;
Expr *NoexceptExpr = nullptr;
if (FTI.getExceptionSpecType() == EST_Dynamic) {
// FIXME: It's rather inefficient to have to split into two vectors
// here.
unsigned N = FTI.getNumExceptions();
DynamicExceptions.reserve(N);
DynamicExceptionRanges.reserve(N);
for (unsigned I = 0; I != N; ++I) {
DynamicExceptions.push_back(FTI.Exceptions[I].Ty);
DynamicExceptionRanges.push_back(FTI.Exceptions[I].Range);
}
} else if (isComputedNoexcept(FTI.getExceptionSpecType())) {
NoexceptExpr = FTI.NoexceptExpr;
}
S.checkExceptionSpecification(D.isFunctionDeclarationContext(),
FTI.getExceptionSpecType(),
DynamicExceptions,
DynamicExceptionRanges,
NoexceptExpr,
Exceptions,
EPI.ExceptionSpec);
const auto &Spec = D.getCXXScopeSpec();
// OpenCLCPlusPlus: A class member function has an address space.
if (state.getSema().getLangOpts().OpenCLCPlusPlus &&
((!Spec.isEmpty() &&
Spec.getScopeRep()->getKind() == NestedNameSpecifier::TypeSpec) ||
state.getDeclarator().getContext() ==
DeclaratorContext::MemberContext)) {
LangAS CurAS = EPI.TypeQuals.getAddressSpace();
// If a class member function's address space is not set, set it to
// __generic.
LangAS AS =
(CurAS == LangAS::Default ? LangAS::opencl_generic : CurAS);
EPI.TypeQuals.addAddressSpace(AS);
}
T = Context.getFunctionType(T, ParamTys, EPI);
}
break;
}
case DeclaratorChunk::MemberPointer: {
// The scope spec must refer to a class, or be dependent.
CXXScopeSpec &SS = DeclType.Mem.Scope();
QualType ClsType;
// Handle pointer nullability.
inferPointerNullability(SimplePointerKind::MemberPointer, DeclType.Loc,
DeclType.EndLoc, DeclType.getAttrs());
if (SS.isInvalid()) {
// Avoid emitting extra errors if we already errored on the scope.
D.setInvalidType(true);
} else if (S.isDependentScopeSpecifier(SS) ||
dyn_cast_or_null<CXXRecordDecl>(S.computeDeclContext(SS))) {
NestedNameSpecifier *NNS = SS.getScopeRep();
NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
ClsType = Context.getDependentNameType(ETK_None, NNSPrefix,
NNS->getAsIdentifier());
break;
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
case NestedNameSpecifier::Super:
llvm_unreachable("Nested-name-specifier must name a type");
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
ClsType = QualType(NNS->getAsType(), 0);
// Note: if the NNS has a prefix and ClsType is a nondependent
// TemplateSpecializationType, then the NNS prefix is NOT included
// in ClsType; hence we wrap ClsType into an ElaboratedType.
// NOTE: in particular, no wrap occurs if ClsType already is an
// Elaborated, DependentName, or DependentTemplateSpecialization.
if (NNSPrefix && isa<TemplateSpecializationType>(NNS->getAsType()))
ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType);
break;
}
} else {
S.Diag(DeclType.Mem.Scope().getBeginLoc(),
diag::err_illegal_decl_mempointer_in_nonclass)
<< (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
<< DeclType.Mem.Scope().getRange();
D.setInvalidType(true);
}
if (!ClsType.isNull())
T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc,
D.getIdentifier());
if (T.isNull()) {
T = Context.IntTy;
D.setInvalidType(true);
} else if (DeclType.Mem.TypeQuals) {
T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Mem.TypeQuals);
}
break;
}
case DeclaratorChunk::Pipe: {
T = S.BuildReadPipeType(T, DeclType.Loc);
processTypeAttrs(state, T, TAL_DeclSpec,
D.getMutableDeclSpec().getAttributes());
break;
}
}
if (T.isNull()) {
D.setInvalidType(true);
T = Context.IntTy;
}
// See if there are any attributes on this declarator chunk.
processTypeAttrs(state, T, TAL_DeclChunk, DeclType.getAttrs());
if (DeclType.Kind != DeclaratorChunk::Paren) {
if (ExpectNoDerefChunk) {
if (!IsNoDerefableChunk(DeclType))
S.Diag(DeclType.Loc, diag::warn_noderef_on_non_pointer_or_array);
ExpectNoDerefChunk = false;
}
ExpectNoDerefChunk = state.didParseNoDeref();
}
}
if (ExpectNoDerefChunk)
S.Diag(state.getDeclarator().getBeginLoc(),
diag::warn_noderef_on_non_pointer_or_array);
// GNU warning -Wstrict-prototypes
// Warn if a function declaration is without a prototype.
// This warning is issued for all kinds of unprototyped function
// declarations (i.e. function type typedef, function pointer etc.)
// C99 6.7.5.3p14:
// The empty list in a function declarator that is not part of a definition
// of that function specifies that no information about the number or types
// of the parameters is supplied.
if (!LangOpts.CPlusPlus && D.getFunctionDefinitionKind() == FDK_Declaration) {
bool IsBlock = false;
for (const DeclaratorChunk &DeclType : D.type_objects()) {
switch (DeclType.Kind) {
case DeclaratorChunk::BlockPointer:
IsBlock = true;
break;
case DeclaratorChunk::Function: {
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
if (FTI.NumParams == 0 && !FTI.isVariadic)
S.Diag(DeclType.Loc, diag::warn_strict_prototypes)
<< IsBlock
<< FixItHint::CreateInsertion(FTI.getRParenLoc(), "void");
IsBlock = false;
break;
}
default:
break;
}
}
}
assert(!T.isNull() && "T must not be null after this point");
if (LangOpts.CPlusPlus && T->isFunctionType()) {
const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>();
assert(FnTy && "Why oh why is there not a FunctionProtoType here?");
// C++ 8.3.5p4:
// A cv-qualifier-seq shall only be part of the function type
// for a nonstatic member function, the function type to which a pointer
// to member refers, or the top-level function type of a function typedef
// declaration.
//
// Core issue 547 also allows cv-qualifiers on function types that are
// top-level template type arguments.
enum { NonMember, Member, DeductionGuide } Kind = NonMember;
if (D.getName().getKind() == UnqualifiedIdKind::IK_DeductionGuideName)
Kind = DeductionGuide;
else if (!D.getCXXScopeSpec().isSet()) {
if ((D.getContext() == DeclaratorContext::MemberContext ||
D.getContext() == DeclaratorContext::LambdaExprContext) &&
!D.getDeclSpec().isFriendSpecified())
Kind = Member;
} else {
DeclContext *DC = S.computeDeclContext(D.getCXXScopeSpec());
if (!DC || DC->isRecord())
Kind = Member;
}
// C++11 [dcl.fct]p6 (w/DR1417):
// An attempt to specify a function type with a cv-qualifier-seq or a
// ref-qualifier (including by typedef-name) is ill-formed unless it is:
// - the function type for a non-static member function,
// - the function type to which a pointer to member refers,
// - the top-level function type of a function typedef declaration or
// alias-declaration,
// - the type-id in the default argument of a type-parameter, or
// - the type-id of a template-argument for a type-parameter
//
// FIXME: Checking this here is insufficient. We accept-invalid on:
//
// template<typename T> struct S { void f(T); };
// S<int() const> s;
//
// ... for instance.
if (IsQualifiedFunction &&
!(Kind == Member &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) &&
!IsTypedefName &&
D.getContext() != DeclaratorContext::TemplateArgContext &&
D.getContext() != DeclaratorContext::TemplateTypeArgContext) {
SourceLocation Loc = D.getBeginLoc();
SourceRange RemovalRange;
unsigned I;
if (D.isFunctionDeclarator(I)) {
SmallVector<SourceLocation, 4> RemovalLocs;
const DeclaratorChunk &Chunk = D.getTypeObject(I);
assert(Chunk.Kind == DeclaratorChunk::Function);
if (Chunk.Fun.hasRefQualifier())
RemovalLocs.push_back(Chunk.Fun.getRefQualifierLoc());
if (Chunk.Fun.hasMethodTypeQualifiers())
Chunk.Fun.MethodQualifiers->forEachQualifier(
[&](DeclSpec::TQ TypeQual, StringRef QualName,
SourceLocation SL) { RemovalLocs.push_back(SL); });
if (!RemovalLocs.empty()) {
llvm::sort(RemovalLocs,
BeforeThanCompare<SourceLocation>(S.getSourceManager()));
RemovalRange = SourceRange(RemovalLocs.front(), RemovalLocs.back());
Loc = RemovalLocs.front();
}
}
S.Diag(Loc, diag::err_invalid_qualified_function_type)
<< Kind << D.isFunctionDeclarator() << T
<< getFunctionQualifiersAsString(FnTy)
<< FixItHint::CreateRemoval(RemovalRange);
// Strip the cv-qualifiers and ref-qualifiers from the type.
FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
EPI.TypeQuals.removeCVRQualifiers();
EPI.RefQualifier = RQ_None;
T = Context.getFunctionType(FnTy->getReturnType(), FnTy->getParamTypes(),
EPI);
// Rebuild any parens around the identifier in the function type.
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
if (D.getTypeObject(i).Kind != DeclaratorChunk::Paren)
break;
T = S.BuildParenType(T);
}
}
}
// Apply any undistributed attributes from the declarator.
processTypeAttrs(state, T, TAL_DeclName, D.getAttributes());
// Diagnose any ignored type attributes.
state.diagnoseIgnoredTypeAttrs(T);
// C++0x [dcl.constexpr]p9:
// A constexpr specifier used in an object declaration declares the object
// as const.
if (D.getDeclSpec().isConstexprSpecified() && T->isObjectType()) {
T.addConst();
}
// If there was an ellipsis in the declarator, the declaration declares a
// parameter pack whose type may be a pack expansion type.
if (D.hasEllipsis()) {
// C++0x [dcl.fct]p13:
// A declarator-id or abstract-declarator containing an ellipsis shall
// only be used in a parameter-declaration. Such a parameter-declaration
// is a parameter pack (14.5.3). [...]
switch (D.getContext()) {
case DeclaratorContext::PrototypeContext:
case DeclaratorContext::LambdaExprParameterContext:
// C++0x [dcl.fct]p13:
// [...] When it is part of a parameter-declaration-clause, the
// parameter pack is a function parameter pack (14.5.3). The type T
// of the declarator-id of the function parameter pack shall contain
// a template parameter pack; each template parameter pack in T is
// expanded by the function parameter pack.
//
// We represent function parameter packs as function parameters whose
// type is a pack expansion.
if (!T->containsUnexpandedParameterPack()) {
S.Diag(D.getEllipsisLoc(),
diag::err_function_parameter_pack_without_parameter_packs)
<< T << D.getSourceRange();
D.setEllipsisLoc(SourceLocation());
} else {
T = Context.getPackExpansionType(T, None);
}
break;
case DeclaratorContext::TemplateParamContext:
// C++0x [temp.param]p15:
// If a template-parameter is a [...] is a parameter-declaration that
// declares a parameter pack (8.3.5), then the template-parameter is a
// template parameter pack (14.5.3).
//
// Note: core issue 778 clarifies that, if there are any unexpanded
// parameter packs in the type of the non-type template parameter, then
// it expands those parameter packs.
if (T->containsUnexpandedParameterPack())
T = Context.getPackExpansionType(T, None);
else
S.Diag(D.getEllipsisLoc(),
LangOpts.CPlusPlus11
? diag::warn_cxx98_compat_variadic_templates
: diag::ext_variadic_templates);
break;
case DeclaratorContext::FileContext:
case DeclaratorContext::KNRTypeListContext:
case DeclaratorContext::ObjCParameterContext: // FIXME: special diagnostic
// here?
case DeclaratorContext::ObjCResultContext: // FIXME: special diagnostic
// here?
case DeclaratorContext::TypeNameContext:
case DeclaratorContext::FunctionalCastContext:
case DeclaratorContext::CXXNewContext:
case DeclaratorContext::AliasDeclContext:
case DeclaratorContext::AliasTemplateContext:
case DeclaratorContext::MemberContext:
case DeclaratorContext::BlockContext:
case DeclaratorContext::ForContext:
case DeclaratorContext::InitStmtContext:
case DeclaratorContext::ConditionContext:
case DeclaratorContext::CXXCatchContext:
case DeclaratorContext::ObjCCatchContext:
case DeclaratorContext::BlockLiteralContext:
case DeclaratorContext::LambdaExprContext:
case DeclaratorContext::ConversionIdContext:
case DeclaratorContext::TrailingReturnContext:
case DeclaratorContext::TrailingReturnVarContext:
case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
// FIXME: We may want to allow parameter packs in block-literal contexts
// in the future.
S.Diag(D.getEllipsisLoc(),
diag::err_ellipsis_in_declarator_not_parameter);
D.setEllipsisLoc(SourceLocation());
break;
}
}
assert(!T.isNull() && "T must not be null at the end of this function");
if (D.isInvalidType())
return Context.getTrivialTypeSourceInfo(T);
return GetTypeSourceInfoForDeclarator(state, T, TInfo);
}
/// GetTypeForDeclarator - Convert the type for the specified
/// declarator to Type instances.
///
/// The result of this call will never be null, but the associated
/// type may be a null type if there's an unrecoverable error.
TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
// Determine the type of the declarator. Not all forms of declarator
// have a type.
TypeProcessingState state(*this, D);
TypeSourceInfo *ReturnTypeInfo = nullptr;
QualType T = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
if (D.isPrototypeContext() && getLangOpts().ObjCAutoRefCount)
inferARCWriteback(state, T);
return GetFullTypeForDeclarator(state, T, ReturnTypeInfo);
}
static void transferARCOwnershipToDeclSpec(Sema &S,
QualType &declSpecTy,
Qualifiers::ObjCLifetime ownership) {
if (declSpecTy->isObjCRetainableType() &&
declSpecTy.getObjCLifetime() == Qualifiers::OCL_None) {
Qualifiers qs;
qs.addObjCLifetime(ownership);
declSpecTy = S.Context.getQualifiedType(declSpecTy, qs);
}
}
static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
Qualifiers::ObjCLifetime ownership,
unsigned chunkIndex) {
Sema &S = state.getSema();
Declarator &D = state.getDeclarator();
// Look for an explicit lifetime attribute.
DeclaratorChunk &chunk = D.getTypeObject(chunkIndex);
if (chunk.getAttrs().hasAttribute(ParsedAttr::AT_ObjCOwnership))
return;
const char *attrStr = nullptr;
switch (ownership) {
case Qualifiers::OCL_None: llvm_unreachable("no ownership!");
case Qualifiers::OCL_ExplicitNone: attrStr = "none"; break;
case Qualifiers::OCL_Strong: attrStr = "strong"; break;
case Qualifiers::OCL_Weak: attrStr = "weak"; break;
case Qualifiers::OCL_Autoreleasing: attrStr = "autoreleasing"; break;
}
IdentifierLoc *Arg = new (S.Context) IdentifierLoc;
Arg->Ident = &S.Context.Idents.get(attrStr);
Arg->Loc = SourceLocation();
ArgsUnion Args(Arg);
// If there wasn't one, add one (with an invalid source location
// so that we don't make an AttributedType for it).
ParsedAttr *attr = D.getAttributePool().create(
&S.Context.Idents.get("objc_ownership"), SourceLocation(),
/*scope*/ nullptr, SourceLocation(),
/*args*/ &Args, 1, ParsedAttr::AS_GNU);
chunk.getAttrs().addAtEnd(attr);
// TODO: mark whether we did this inference?
}
/// Used for transferring ownership in casts resulting in l-values.
static void transferARCOwnership(TypeProcessingState &state,
QualType &declSpecTy,
Qualifiers::ObjCLifetime ownership) {
Sema &S = state.getSema();
Declarator &D = state.getDeclarator();
int inner = -1;
bool hasIndirection = false;
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
DeclaratorChunk &chunk = D.getTypeObject(i);
switch (chunk.Kind) {
case DeclaratorChunk::Paren:
// Ignore parens.
break;
case DeclaratorChunk::Array:
case DeclaratorChunk::Reference:
case DeclaratorChunk::Pointer:
if (inner != -1)
hasIndirection = true;
inner = i;
break;
case DeclaratorChunk::BlockPointer:
if (inner != -1)
transferARCOwnershipToDeclaratorChunk(state, ownership, i);
return;
case DeclaratorChunk::Function:
case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Pipe:
return;
}
}
if (inner == -1)
return;
DeclaratorChunk &chunk = D.getTypeObject(inner);
if (chunk.Kind == DeclaratorChunk::Pointer) {
if (declSpecTy->isObjCRetainableType())
return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
if (declSpecTy->isObjCObjectType() && hasIndirection)
return transferARCOwnershipToDeclaratorChunk(state, ownership, inner);
} else {
assert(chunk.Kind == DeclaratorChunk::Array ||
chunk.Kind == DeclaratorChunk::Reference);
return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
}
}
TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
TypeProcessingState state(*this, D);
TypeSourceInfo *ReturnTypeInfo = nullptr;
QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
if (getLangOpts().ObjC) {
Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy);
if (ownership != Qualifiers::OCL_None)
transferARCOwnership(state, declSpecTy, ownership);
}
return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo);
}
static void fillAttributedTypeLoc(AttributedTypeLoc TL,
TypeProcessingState &State) {
TL.setAttr(State.takeAttrForAttributedType(TL.getTypePtr()));
}
namespace {
class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
ASTContext &Context;
TypeProcessingState &State;
const DeclSpec &DS;
public:
TypeSpecLocFiller(ASTContext &Context, TypeProcessingState &State,
const DeclSpec &DS)
: Context(Context), State(State), DS(DS) {}
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
Visit(TL.getModifiedLoc());
fillAttributedTypeLoc(TL, State);
}
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
Visit(TL.getUnqualifiedLoc());
}
void VisitTypedefTypeLoc(TypedefTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeLoc());
}
void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeLoc());
// FIXME. We should have DS.getTypeSpecTypeEndLoc(). But, it requires
// addition field. What we have is good enough for dispay of location
// of 'fixit' on interface name.
TL.setNameEndLoc(DS.getEndLoc());
}
void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
TypeSourceInfo *RepTInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &RepTInfo);
TL.copy(RepTInfo->getTypeLoc());
}
void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
TypeSourceInfo *RepTInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &RepTInfo);
TL.copy(RepTInfo->getTypeLoc());
}
void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
// If we got no declarator info from previous Sema routines,
// just fill with the typespec loc.
if (!TInfo) {
TL.initialize(Context, DS.getTypeSpecTypeNameLoc());
return;
}
TypeLoc OldTL = TInfo->getTypeLoc();
if (TInfo->getType()->getAs<ElaboratedType>()) {
ElaboratedTypeLoc ElabTL = OldTL.castAs<ElaboratedTypeLoc>();
TemplateSpecializationTypeLoc NamedTL = ElabTL.getNamedTypeLoc()
.castAs<TemplateSpecializationTypeLoc>();
TL.copy(NamedTL);
} else {
TL.copy(OldTL.castAs<TemplateSpecializationTypeLoc>());
assert(TL.getRAngleLoc() == OldTL.castAs<TemplateSpecializationTypeLoc>().getRAngleLoc());
}
}
void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
}
void VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType);
TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
assert(DS.getRepAsType());
TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.setUnderlyingTInfo(TInfo);
}
void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
// FIXME: This holds only because we only have one unary transform.
assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType);
TL.setKWLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
assert(DS.getRepAsType());
TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.setUnderlyingTInfo(TInfo);
}
void VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
// By default, use the source location of the type specifier.
TL.setBuiltinLoc(DS.getTypeSpecTypeLoc());
if (TL.needsExtraLocalData()) {
// Set info for the written builtin specifiers.
TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs();
// Try to have a meaningful source location.
if (TL.getWrittenSignSpec() != TSS_unspecified)
TL.expandBuiltinRange(DS.getTypeSpecSignLoc());
if (TL.getWrittenWidthSpec() != TSW_unspecified)
TL.expandBuiltinRange(DS.getTypeSpecWidthRange());
}
}
void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
ElaboratedTypeKeyword Keyword
= TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
if (DS.getTypeSpecType() == TST_typename) {
TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
if (TInfo) {
TL.copy(TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>());
return;
}
}
TL.setElaboratedKeywordLoc(Keyword != ETK_None
? DS.getTypeSpecTypeLoc()
: SourceLocation());
const CXXScopeSpec& SS = DS.getTypeSpecScope();
TL.setQualifierLoc(SS.getWithLocInContext(Context));
Visit(TL.getNextTypeLoc().getUnqualifiedLoc());
}
void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
assert(DS.getTypeSpecType() == TST_typename);
TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
assert(TInfo);
TL.copy(TInfo->getTypeLoc().castAs<DependentNameTypeLoc>());
}
void VisitDependentTemplateSpecializationTypeLoc(
DependentTemplateSpecializationTypeLoc TL) {
assert(DS.getTypeSpecType() == TST_typename);
TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
assert(TInfo);
TL.copy(
TInfo->getTypeLoc().castAs<DependentTemplateSpecializationTypeLoc>());
}
void VisitTagTypeLoc(TagTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
}
void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
// An AtomicTypeLoc can come from either an _Atomic(...) type specifier
// or an _Atomic qualifier.
if (DS.getTypeSpecType() == DeclSpec::TST_atomic) {
TL.setKWLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
assert(TInfo);
TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
} else {
TL.setKWLoc(DS.getAtomicSpecLoc());
// No parens, to indicate this was spelled as an _Atomic qualifier.
TL.setParensRange(SourceRange());
Visit(TL.getValueLoc());
}
}
void VisitPipeTypeLoc(PipeTypeLoc TL) {
TL.setKWLoc(DS.getTypeSpecTypeLoc());
TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
}
void VisitTypeLoc(TypeLoc TL) {
// FIXME: add other typespec types and change this to an assert.
TL.initialize(Context, DS.getTypeSpecTypeLoc());
}
};
class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
ASTContext &Context;
TypeProcessingState &State;
const DeclaratorChunk &Chunk;
public:
DeclaratorLocFiller(ASTContext &Context, TypeProcessingState &State,
const DeclaratorChunk &Chunk)
: Context(Context), State(State), Chunk(Chunk) {}
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
llvm_unreachable("qualified type locs not expected here!");
}
void VisitDecayedTypeLoc(DecayedTypeLoc TL) {
llvm_unreachable("decayed type locs not expected here!");
}
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
fillAttributedTypeLoc(TL, State);
}
void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
// nothing
}
void VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::BlockPointer);
TL.setCaretLoc(Chunk.Loc);
}
void VisitPointerTypeLoc(PointerTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Pointer);
TL.setStarLoc(Chunk.Loc);
}
void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Pointer);
TL.setStarLoc(Chunk.Loc);
}
void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
const CXXScopeSpec& SS = Chunk.Mem.Scope();
NestedNameSpecifierLoc NNSLoc = SS.getWithLocInContext(Context);
const Type* ClsTy = TL.getClass();
QualType ClsQT = QualType(ClsTy, 0);
TypeSourceInfo *ClsTInfo = Context.CreateTypeSourceInfo(ClsQT, 0);
// Now copy source location info into the type loc component.
TypeLoc ClsTL = ClsTInfo->getTypeLoc();
switch (NNSLoc.getNestedNameSpecifier()->getKind()) {
case NestedNameSpecifier::Identifier:
assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc");
{
DependentNameTypeLoc DNTLoc = ClsTL.castAs<DependentNameTypeLoc>();
DNTLoc.setElaboratedKeywordLoc(SourceLocation());
DNTLoc.setQualifierLoc(NNSLoc.getPrefix());
DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc());
}
break;
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
if (isa<ElaboratedType>(ClsTy)) {
ElaboratedTypeLoc ETLoc = ClsTL.castAs<ElaboratedTypeLoc>();
ETLoc.setElaboratedKeywordLoc(SourceLocation());
ETLoc.setQualifierLoc(NNSLoc.getPrefix());
TypeLoc NamedTL = ETLoc.getNamedTypeLoc();
NamedTL.initializeFullCopy(NNSLoc.getTypeLoc());
} else {
ClsTL.initializeFullCopy(NNSLoc.getTypeLoc());
}
break;
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
case NestedNameSpecifier::Super:
llvm_unreachable("Nested-name-specifier must name a type");
}
// Finally fill in MemberPointerLocInfo fields.
TL.setStarLoc(Chunk.Loc);
TL.setClassTInfo(ClsTInfo);
}
void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Reference);
// 'Amp' is misleading: this might have been originally
/// spelled with AmpAmp.
TL.setAmpLoc(Chunk.Loc);
}
void VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Reference);
assert(!Chunk.Ref.LValueRef);
TL.setAmpAmpLoc(Chunk.Loc);
}
void VisitArrayTypeLoc(ArrayTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Array);
TL.setLBracketLoc(Chunk.Loc);
TL.setRBracketLoc(Chunk.EndLoc);
TL.setSizeExpr(static_cast<Expr*>(Chunk.Arr.NumElts));
}
void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Function);
TL.setLocalRangeBegin(Chunk.Loc);
TL.setLocalRangeEnd(Chunk.EndLoc);
const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
TL.setLParenLoc(FTI.getLParenLoc());
TL.setRParenLoc(FTI.getRParenLoc());
for (unsigned i = 0, e = TL.getNumParams(), tpi = 0; i != e; ++i) {
ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);
TL.setParam(tpi++, Param);
}
TL.setExceptionSpecRange(FTI.getExceptionSpecRange());
}
void VisitParenTypeLoc(ParenTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Paren);
TL.setLParenLoc(Chunk.Loc);
TL.setRParenLoc(Chunk.EndLoc);
}
void VisitPipeTypeLoc(PipeTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Pipe);
TL.setKWLoc(Chunk.Loc);
}
void VisitTypeLoc(TypeLoc TL) {
llvm_unreachable("unsupported TypeLoc kind in declarator!");
}
};
} // end anonymous namespace
static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) {
SourceLocation Loc;
switch (Chunk.Kind) {
case DeclaratorChunk::Function:
case DeclaratorChunk::Array:
case DeclaratorChunk::Paren:
case DeclaratorChunk::Pipe:
llvm_unreachable("cannot be _Atomic qualified");
case DeclaratorChunk::Pointer:
Loc = SourceLocation::getFromRawEncoding(Chunk.Ptr.AtomicQualLoc);
break;
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
// FIXME: Provide a source location for the _Atomic keyword.
break;
}
ATL.setKWLoc(Loc);
ATL.setParensRange(SourceRange());
}
static void
fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL,
const ParsedAttributesView &Attrs) {
for (const ParsedAttr &AL : Attrs) {
if (AL.getKind() == ParsedAttr::AT_AddressSpace) {
DASTL.setAttrNameLoc(AL.getLoc());
DASTL.setAttrExprOperand(AL.getArgAsExpr(0));
DASTL.setAttrOperandParensRange(SourceRange());
return;
}
}
llvm_unreachable(
"no address_space attribute found at the expected location!");
}
/// Create and instantiate a TypeSourceInfo with type source information.
///
/// \param T QualType referring to the type as written in source code.
///
/// \param ReturnTypeInfo For declarators whose return type does not show
/// up in the normal place in the declaration specifiers (such as a C++
/// conversion function), this pointer will refer to a type source information
/// for that return type.
static TypeSourceInfo *
GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
QualType T, TypeSourceInfo *ReturnTypeInfo) {
Sema &S = State.getSema();
Declarator &D = State.getDeclarator();
TypeSourceInfo *TInfo = S.Context.CreateTypeSourceInfo(T);
UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
// Handle parameter packs whose type is a pack expansion.
if (isa<PackExpansionType>(T)) {
CurrTL.castAs<PackExpansionTypeLoc>().setEllipsisLoc(D.getEllipsisLoc());
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
// An AtomicTypeLoc might be produced by an atomic qualifier in this
// declarator chunk.
if (AtomicTypeLoc ATL = CurrTL.getAs<AtomicTypeLoc>()) {
fillAtomicQualLoc(ATL, D.getTypeObject(i));
CurrTL = ATL.getValueLoc().getUnqualifiedLoc();
}
while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
fillAttributedTypeLoc(TL, State);
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
}
while (DependentAddressSpaceTypeLoc TL =
CurrTL.getAs<DependentAddressSpaceTypeLoc>()) {
fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs());
CurrTL = TL.getPointeeTypeLoc().getUnqualifiedLoc();
}
// FIXME: Ordering here?
while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>())
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
DeclaratorLocFiller(S.Context, State, D.getTypeObject(i)).Visit(CurrTL);
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
// If we have different source information for the return type, use
// that. This really only applies to C++ conversion functions.
if (ReturnTypeInfo) {
TypeLoc TL = ReturnTypeInfo->getTypeLoc();
assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());
} else {
TypeSpecLocFiller(S.Context, State, D.getDeclSpec()).Visit(CurrTL);
}
return TInfo;
}
/// Create a LocInfoType to hold the given QualType and TypeSourceInfo.
ParsedType Sema::CreateParsedType(QualType T, TypeSourceInfo *TInfo) {
// FIXME: LocInfoTypes are "transient", only needed for passing to/from Parser
// and Sema during declaration parsing. Try deallocating/caching them when
// it's appropriate, instead of allocating them and keeping them around.
LocInfoType *LocT = (LocInfoType*)BumpAlloc.Allocate(sizeof(LocInfoType),
TypeAlignment);
new (LocT) LocInfoType(T, TInfo);
assert(LocT->getTypeClass() != T->getTypeClass() &&
"LocInfoType's TypeClass conflicts with an existing Type class");
return ParsedType::make(QualType(LocT, 0));
}
void LocInfoType::getAsStringInternal(std::string &Str,
const PrintingPolicy &Policy) const {
llvm_unreachable("LocInfoType leaked into the type system; an opaque TypeTy*"
" was used directly instead of getting the QualType through"
" GetTypeFromParser");
}
TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
// C99 6.7.6: Type names have no identifier. This is already validated by
// the parser.
assert(D.getIdentifier() == nullptr &&
"Type name should have no identifier!");
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType T = TInfo->getType();
if (D.isInvalidType())
return true;
// Make sure there are no unused decl attributes on the declarator.
// We don't want to do this for ObjC parameters because we're going
// to apply them to the actual parameter declaration.
// Likewise, we don't want to do this for alias declarations, because
// we are actually going to build a declaration from this eventually.
if (D.getContext() != DeclaratorContext::ObjCParameterContext &&
D.getContext() != DeclaratorContext::AliasDeclContext &&
D.getContext() != DeclaratorContext::AliasTemplateContext)
checkUnusedDeclAttributes(D);
if (getLangOpts().CPlusPlus) {
// Check that there are no default arguments (C++ only).
CheckExtraCXXDefaultArguments(D);
}
return CreateParsedType(T, TInfo);
}
ParsedType Sema::ActOnObjCInstanceType(SourceLocation Loc) {
QualType T = Context.getObjCInstanceType();
TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
return CreateParsedType(T, TInfo);
}
//===----------------------------------------------------------------------===//
// Type Attribute Processing
//===----------------------------------------------------------------------===//
/// BuildAddressSpaceAttr - Builds a DependentAddressSpaceType if an expression
/// is uninstantiated. If instantiated it will apply the appropriate address space
/// to the type. This function allows dependent template variables to be used in
/// conjunction with the address_space attribute
QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
SourceLocation AttrLoc) {
if (!AddrSpace->isValueDependent()) {
llvm::APSInt addrSpace(32);
if (!AddrSpace->isIntegerConstantExpr(addrSpace, Context)) {
Diag(AttrLoc, diag::err_attribute_argument_type)
<< "'address_space'" << AANT_ArgumentIntegerConstant
<< AddrSpace->getSourceRange();
return QualType();
}
// Bounds checking.
if (addrSpace.isSigned()) {
if (addrSpace.isNegative()) {
Diag(AttrLoc, diag::err_attribute_address_space_negative)
<< AddrSpace->getSourceRange();
return QualType();
}
addrSpace.setIsSigned(false);
}
llvm::APSInt max(addrSpace.getBitWidth());
max =
Qualifiers::MaxAddressSpace - (unsigned)LangAS::FirstTargetAddressSpace;
if (addrSpace > max) {
Diag(AttrLoc, diag::err_attribute_address_space_too_high)
<< (unsigned)max.getZExtValue() << AddrSpace->getSourceRange();
return QualType();
}
LangAS ASIdx =
getLangASFromTargetAS(static_cast<unsigned>(addrSpace.getZExtValue()));
// If this type is already address space qualified with a different
// address space, reject it.
// ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified
// by qualifiers for two or more different address spaces."
if (T.getAddressSpace() != LangAS::Default) {
if (T.getAddressSpace() != ASIdx) {
Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers);
return QualType();
} else
// Emit a warning if they are identical; it's likely unintended.
Diag(AttrLoc,
diag::warn_attribute_address_multiple_identical_qualifiers);
}
return Context.getAddrSpaceQualType(T, ASIdx);
}
// A check with similar intentions as checking if a type already has an
// address space except for on a dependent types, basically if the
// current type is already a DependentAddressSpaceType then its already
// lined up to have another address space on it and we can't have
// multiple address spaces on the one pointer indirection
if (T->getAs<DependentAddressSpaceType>()) {
Diag(AttrLoc, diag::err_attribute_address_multiple_qualifiers);
return QualType();
}
return Context.getDependentAddressSpaceType(T, AddrSpace, AttrLoc);
}
/// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the
/// specified type. The attribute contains 1 argument, the id of the address
/// space for the type.
static void HandleAddressSpaceTypeAttribute(QualType &Type,
const ParsedAttr &Attr,
TypeProcessingState &State) {
Sema &S = State.getSema();
// ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be
// qualified by an address-space qualifier."
if (Type->isFunctionType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_function_type);
Attr.setInvalid();
return;
}
LangAS ASIdx;
if (Attr.getKind() == ParsedAttr::AT_AddressSpace) {
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr
<< 1;
Attr.setInvalid();
return;
}
Expr *ASArgExpr;
if (Attr.isArgIdent(0)) {
// Special case where the argument is a template id.
CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
UnqualifiedId id;
id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
ExprResult AddrSpace = S.ActOnIdExpression(
S.getCurScope(), SS, TemplateKWLoc, id, false, false);
if (AddrSpace.isInvalid())
return;
ASArgExpr = static_cast<Expr *>(AddrSpace.get());
} else {
ASArgExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
}
// Create the DependentAddressSpaceType or append an address space onto
// the type.
QualType T = S.BuildAddressSpaceAttr(Type, ASArgExpr, Attr.getLoc());
if (!T.isNull()) {
ASTContext &Ctx = S.Context;
auto *ASAttr = ::new (Ctx) AddressSpaceAttr(
Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex(),
static_cast<unsigned>(T.getQualifiers().getAddressSpace()));
Type = State.getAttributedType(ASAttr, T, T);
} else {
Attr.setInvalid();
}
} else {
// The keyword-based type attributes imply which address space to use.
switch (Attr.getKind()) {
case ParsedAttr::AT_OpenCLGlobalAddressSpace:
ASIdx = LangAS::opencl_global; break;
case ParsedAttr::AT_OpenCLLocalAddressSpace:
ASIdx = LangAS::opencl_local; break;
case ParsedAttr::AT_OpenCLConstantAddressSpace:
ASIdx = LangAS::opencl_constant; break;
case ParsedAttr::AT_OpenCLGenericAddressSpace:
ASIdx = LangAS::opencl_generic; break;
case ParsedAttr::AT_OpenCLPrivateAddressSpace:
ASIdx = LangAS::opencl_private; break;
default:
llvm_unreachable("Invalid address space");
}
// If this type is already address space qualified with a different
// address space, reject it.
// ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified by
// qualifiers for two or more different address spaces."
if (Type.getAddressSpace() != LangAS::Default) {
if (Type.getAddressSpace() != ASIdx) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
Attr.setInvalid();
return;
} else
// Emit a warning if they are identical; it's likely unintended.
S.Diag(Attr.getLoc(),
diag::warn_attribute_address_multiple_identical_qualifiers);
}
Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
}
}
/// Does this type have a "direct" ownership qualifier? That is,
/// is it written like "__strong id", as opposed to something like
/// "typeof(foo)", where that happens to be strong?
static bool hasDirectOwnershipQualifier(QualType type) {
// Fast path: no qualifier at all.
assert(type.getQualifiers().hasObjCLifetime());
while (true) {
// __strong id
if (const AttributedType *attr = dyn_cast<AttributedType>(type)) {
if (attr->getAttrKind() == attr::ObjCOwnership)
return true;
type = attr->getModifiedType();
// X *__strong (...)
} else if (const ParenType *paren = dyn_cast<ParenType>(type)) {
type = paren->getInnerType();
// That's it for things we want to complain about. In particular,
// we do not want to look through typedefs, typeof(expr),
// typeof(type), or any other way that the type is somehow
// abstracted.
} else {
return false;
}
}
}
/// handleObjCOwnershipTypeAttr - Process an objc_ownership
/// attribute on the specified type.
///
/// Returns 'true' if the attribute was handled.
static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
ParsedAttr &attr, QualType &type) {
bool NonObjCPointer = false;
if (!type->isDependentType() && !type->isUndeducedType()) {
if (const PointerType *ptr = type->getAs<PointerType>()) {
QualType pointee = ptr->getPointeeType();
if (pointee->isObjCRetainableType() || pointee->isPointerType())
return false;
// It is important not to lose the source info that there was an attribute
// applied to non-objc pointer. We will create an attributed type but
// its type will be the same as the original type.
NonObjCPointer = true;
} else if (!type->isObjCRetainableType()) {
return false;
}
// Don't accept an ownership attribute in the declspec if it would
// just be the return type of a block pointer.
if (state.isProcessingDeclSpec()) {
Declarator &D = state.getDeclarator();
if (maybeMovePastReturnType(D, D.getNumTypeObjects(),
/*onlyBlockPointers=*/true))
return false;
}
}
Sema &S = state.getSema();
SourceLocation AttrLoc = attr.getLoc();
if (AttrLoc.isMacroID())
AttrLoc =
S.getSourceManager().getImmediateExpansionRange(AttrLoc).getBegin();
if (!attr.isArgIdent(0)) {
S.Diag(AttrLoc, diag::err_attribute_argument_type) << attr
<< AANT_ArgumentString;
attr.setInvalid();
return true;
}
IdentifierInfo *II = attr.getArgAsIdent(0)->Ident;
Qualifiers::ObjCLifetime lifetime;
if (II->isStr("none"))
lifetime = Qualifiers::OCL_ExplicitNone;
else if (II->isStr("strong"))
lifetime = Qualifiers::OCL_Strong;
else if (II->isStr("weak"))
lifetime = Qualifiers::OCL_Weak;
else if (II->isStr("autoreleasing"))
lifetime = Qualifiers::OCL_Autoreleasing;
else {
S.Diag(AttrLoc, diag::warn_attribute_type_not_supported)
<< attr.getName() << II;
attr.setInvalid();
return true;
}
// Just ignore lifetime attributes other than __weak and __unsafe_unretained
// outside of ARC mode.
if (!S.getLangOpts().ObjCAutoRefCount &&
lifetime != Qualifiers::OCL_Weak &&
lifetime != Qualifiers::OCL_ExplicitNone) {
return true;
}
SplitQualType underlyingType = type.split();
// Check for redundant/conflicting ownership qualifiers.
if (Qualifiers::ObjCLifetime previousLifetime
= type.getQualifiers().getObjCLifetime()) {
// If it's written directly, that's an error.
if (hasDirectOwnershipQualifier(type)) {
S.Diag(AttrLoc, diag::err_attr_objc_ownership_redundant)
<< type;
return true;
}
// Otherwise, if the qualifiers actually conflict, pull sugar off
// and remove the ObjCLifetime qualifiers.
if (previousLifetime != lifetime) {
// It's possible to have multiple local ObjCLifetime qualifiers. We
// can't stop after we reach a type that is directly qualified.
const Type *prevTy = nullptr;
while (!prevTy || prevTy != underlyingType.Ty) {
prevTy = underlyingType.Ty;
underlyingType = underlyingType.getSingleStepDesugaredType();
}
underlyingType.Quals.removeObjCLifetime();
}
}
underlyingType.Quals.addObjCLifetime(lifetime);
if (NonObjCPointer) {
StringRef name = attr.getName()->getName();
switch (lifetime) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
break;
case Qualifiers::OCL_Strong: name = "__strong"; break;
case Qualifiers::OCL_Weak: name = "__weak"; break;
case Qualifiers::OCL_Autoreleasing: name = "__autoreleasing"; break;
}
S.Diag(AttrLoc, diag::warn_type_attribute_wrong_type) << name
<< TDS_ObjCObjOrBlock << type;
}
// Don't actually add the __unsafe_unretained qualifier in non-ARC files,
// because having both 'T' and '__unsafe_unretained T' exist in the type
// system causes unfortunate widespread consistency problems. (For example,
// they're not considered compatible types, and we mangle them identicially
// as template arguments.) These problems are all individually fixable,
// but it's easier to just not add the qualifier and instead sniff it out
// in specific places using isObjCInertUnsafeUnretainedType().
//
// Doing this does means we miss some trivial consistency checks that
// would've triggered in ARC, but that's better than trying to solve all
// the coexistence problems with __unsafe_unretained.
if (!S.getLangOpts().ObjCAutoRefCount &&
lifetime == Qualifiers::OCL_ExplicitNone) {
type = state.getAttributedType(
createSimpleAttr<ObjCInertUnsafeUnretainedAttr>(S.Context, attr),
type, type);
return true;
}
QualType origType = type;
if (!NonObjCPointer)
type = S.Context.getQualifiedType(underlyingType);
// If we have a valid source location for the attribute, use an
// AttributedType instead.
if (AttrLoc.isValid()) {
type = state.getAttributedType(::new (S.Context) ObjCOwnershipAttr(
attr.getRange(), S.Context, II,
attr.getAttributeSpellingListIndex()),
origType, type);
}
auto diagnoseOrDelay = [](Sema &S, SourceLocation loc,
unsigned diagnostic, QualType type) {
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
S.DelayedDiagnostics.add(
sema::DelayedDiagnostic::makeForbiddenType(
S.getSourceManager().getExpansionLoc(loc),
diagnostic, type, /*ignored*/ 0));
} else {
S.Diag(loc, diagnostic);
}
};
// Sometimes, __weak isn't allowed.
if (lifetime == Qualifiers::OCL_Weak &&
!S.getLangOpts().ObjCWeak && !NonObjCPointer) {
// Use a specialized diagnostic if the runtime just doesn't support them.
unsigned diagnostic =
(S.getLangOpts().ObjCWeakRuntime ? diag::err_arc_weak_disabled
: diag::err_arc_weak_no_runtime);
// In any case, delay the diagnostic until we know what we're parsing.
diagnoseOrDelay(S, AttrLoc, diagnostic, type);
attr.setInvalid();
return true;
}
// Forbid __weak for class objects marked as
// objc_arc_weak_reference_unavailable
if (lifetime == Qualifiers::OCL_Weak) {
if (const ObjCObjectPointerType *ObjT =
type->getAs<ObjCObjectPointerType>()) {
if (ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl()) {
if (Class->isArcWeakrefUnavailable()) {
S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
S.Diag(ObjT->getInterfaceDecl()->getLocation(),
diag::note_class_declared);
}
}
}
}
return true;
}
/// handleObjCGCTypeAttr - Process the __attribute__((objc_gc)) type
/// attribute on the specified type. Returns true to indicate that
/// the attribute was handled, false to indicate that the type does
/// not permit the attribute.
static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
QualType &type) {
Sema &S = state.getSema();
// Delay if this isn't some kind of pointer.
if (!type->isPointerType() &&
!type->isObjCObjectPointerType() &&
!type->isBlockPointerType())
return false;
if (type.getObjCGCAttr() != Qualifiers::GCNone) {
S.Diag(attr.getLoc(), diag::err_attribute_multiple_objc_gc);
attr.setInvalid();
return true;
}
// Check the attribute arguments.
if (!attr.isArgIdent(0)) {
S.Diag(attr.getLoc(), diag::err_attribute_argument_type)
<< attr << AANT_ArgumentString;
attr.setInvalid();
return true;
}
Qualifiers::GC GCAttr;
if (attr.getNumArgs() > 1) {
S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << attr
<< 1;
attr.setInvalid();
return true;
}
IdentifierInfo *II = attr.getArgAsIdent(0)->Ident;
if (II->isStr("weak"))
GCAttr = Qualifiers::Weak;
else if (II->isStr("strong"))
GCAttr = Qualifiers::Strong;
else {
S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported)
<< attr.getName() << II;
attr.setInvalid();
return true;
}
QualType origType = type;
type = S.Context.getObjCGCQualType(origType, GCAttr);
// Make an attributed type to preserve the source information.
if (attr.getLoc().isValid())
type = state.getAttributedType(
::new (S.Context) ObjCGCAttr(attr.getRange(), S.Context, II,
attr.getAttributeSpellingListIndex()),
origType, type);
return true;
}
namespace {
/// A helper class to unwrap a type down to a function for the
/// purposes of applying attributes there.
///
/// Use:
/// FunctionTypeUnwrapper unwrapped(SemaRef, T);
/// if (unwrapped.isFunctionType()) {
/// const FunctionType *fn = unwrapped.get();
/// // change fn somehow
/// T = unwrapped.wrap(fn);
/// }
struct FunctionTypeUnwrapper {
enum WrapKind {
Desugar,
Attributed,
Parens,
Pointer,
BlockPointer,
Reference,
MemberPointer
};
QualType Original;
const FunctionType *Fn;
SmallVector<unsigned char /*WrapKind*/, 8> Stack;
FunctionTypeUnwrapper(Sema &S, QualType T) : Original(T) {
while (true) {
const Type *Ty = T.getTypePtr();
if (isa<FunctionType>(Ty)) {
Fn = cast<FunctionType>(Ty);
return;
} else if (isa<ParenType>(Ty)) {
T = cast<ParenType>(Ty)->getInnerType();
Stack.push_back(Parens);
} else if (isa<PointerType>(Ty)) {
T = cast<PointerType>(Ty)->getPointeeType();
Stack.push_back(Pointer);
} else if (isa<BlockPointerType>(Ty)) {
T = cast<BlockPointerType>(Ty)->getPointeeType();
Stack.push_back(BlockPointer);
} else if (isa<MemberPointerType>(Ty)) {
T = cast<MemberPointerType>(Ty)->getPointeeType();
Stack.push_back(MemberPointer);
} else if (isa<ReferenceType>(Ty)) {
T = cast<ReferenceType>(Ty)->getPointeeType();
Stack.push_back(Reference);
} else if (isa<AttributedType>(Ty)) {
T = cast<AttributedType>(Ty)->getEquivalentType();
Stack.push_back(Attributed);
} else {
const Type *DTy = Ty->getUnqualifiedDesugaredType();
if (Ty == DTy) {
Fn = nullptr;
return;
}
T = QualType(DTy, 0);
Stack.push_back(Desugar);
}
}
}
bool isFunctionType() const { return (Fn != nullptr); }
const FunctionType *get() const { return Fn; }
QualType wrap(Sema &S, const FunctionType *New) {
// If T wasn't modified from the unwrapped type, do nothing.
if (New == get()) return Original;
Fn = New;
return wrap(S.Context, Original, 0);
}
private:
QualType wrap(ASTContext &C, QualType Old, unsigned I) {
if (I == Stack.size())
return C.getQualifiedType(Fn, Old.getQualifiers());
// Build up the inner type, applying the qualifiers from the old
// type to the new type.
SplitQualType SplitOld = Old.split();
// As a special case, tail-recurse if there are no qualifiers.
if (SplitOld.Quals.empty())
return wrap(C, SplitOld.Ty, I);
return C.getQualifiedType(wrap(C, SplitOld.Ty, I), SplitOld.Quals);
}
QualType wrap(ASTContext &C, const Type *Old, unsigned I) {
if (I == Stack.size()) return QualType(Fn, 0);
switch (static_cast<WrapKind>(Stack[I++])) {
case Desugar:
// This is the point at which we potentially lose source
// information.
return wrap(C, Old->getUnqualifiedDesugaredType(), I);
case Attributed:
return wrap(C, cast<AttributedType>(Old)->getEquivalentType(), I);
case Parens: {
QualType New = wrap(C, cast<ParenType>(Old)->getInnerType(), I);
return C.getParenType(New);
}
case Pointer: {
QualType New = wrap(C, cast<PointerType>(Old)->getPointeeType(), I);
return C.getPointerType(New);
}
case BlockPointer: {
QualType New = wrap(C, cast<BlockPointerType>(Old)->getPointeeType(),I);
return C.getBlockPointerType(New);
}
case MemberPointer: {
const MemberPointerType *OldMPT = cast<MemberPointerType>(Old);
QualType New = wrap(C, OldMPT->getPointeeType(), I);
return C.getMemberPointerType(New, OldMPT->getClass());
}
case Reference: {
const ReferenceType *OldRef = cast<ReferenceType>(Old);
QualType New = wrap(C, OldRef->getPointeeType(), I);
if (isa<LValueReferenceType>(OldRef))
return C.getLValueReferenceType(New, OldRef->isSpelledAsLValue());
else
return C.getRValueReferenceType(New);
}
}
llvm_unreachable("unknown wrapping kind");
}
};
} // end anonymous namespace
static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
ParsedAttr &PAttr, QualType &Type) {
Sema &S = State.getSema();
Attr *A;
switch (PAttr.getKind()) {
default: llvm_unreachable("Unknown attribute kind");
case ParsedAttr::AT_Ptr32:
A = createSimpleAttr<Ptr32Attr>(S.Context, PAttr);
break;
case ParsedAttr::AT_Ptr64:
A = createSimpleAttr<Ptr64Attr>(S.Context, PAttr);
break;
case ParsedAttr::AT_SPtr:
A = createSimpleAttr<SPtrAttr>(S.Context, PAttr);
break;
case ParsedAttr::AT_UPtr:
A = createSimpleAttr<UPtrAttr>(S.Context, PAttr);
break;
}
attr::Kind NewAttrKind = A->getKind();
QualType Desugared = Type;
const AttributedType *AT = dyn_cast<AttributedType>(Type);
while (AT) {
attr::Kind CurAttrKind = AT->getAttrKind();
// You cannot specify duplicate type attributes, so if the attribute has
// already been applied, flag it.
if (NewAttrKind == CurAttrKind) {
S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact)
<< PAttr.getName();
return true;
}
// You cannot have both __sptr and __uptr on the same type, nor can you
// have __ptr32 and __ptr64.
if ((CurAttrKind == attr::Ptr32 && NewAttrKind == attr::Ptr64) ||
(CurAttrKind == attr::Ptr64 && NewAttrKind == attr::Ptr32)) {
S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
<< "'__ptr32'" << "'__ptr64'";
return true;
} else if ((CurAttrKind == attr::SPtr && NewAttrKind == attr::UPtr) ||
(CurAttrKind == attr::UPtr && NewAttrKind == attr::SPtr)) {
S.Diag(PAttr.getLoc(), diag::err_attributes_are_not_compatible)
<< "'__sptr'" << "'__uptr'";
return true;
}
Desugared = AT->getEquivalentType();
AT = dyn_cast<AttributedType>(Desugared);
}
// Pointer type qualifiers can only operate on pointer types, but not
// pointer-to-member types.
//
// FIXME: Should we really be disallowing this attribute if there is any
// type sugar between it and the pointer (other than attributes)? Eg, this
// disallows the attribute on a parenthesized pointer.
// And if so, should we really allow *any* type attribute?
if (!isa<PointerType>(Desugared)) {
if (Type->isMemberPointerType())
S.Diag(PAttr.getLoc(), diag::err_attribute_no_member_pointers) << PAttr;
else
S.Diag(PAttr.getLoc(), diag::err_attribute_pointers_only) << PAttr << 0;
return true;
}
Type = State.getAttributedType(A, Type, Type);
return false;
}
/// Map a nullability attribute kind to a nullability kind.
static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) {
switch (kind) {
case ParsedAttr::AT_TypeNonNull:
return NullabilityKind::NonNull;
case ParsedAttr::AT_TypeNullable:
return NullabilityKind::Nullable;
case ParsedAttr::AT_TypeNullUnspecified:
return NullabilityKind::Unspecified;
default:
llvm_unreachable("not a nullability attribute kind");
}
}
/// Applies a nullability type specifier to the given type, if possible.
///
/// \param state The type processing state.
///
/// \param type The type to which the nullability specifier will be
/// added. On success, this type will be updated appropriately.
///
/// \param attr The attribute as written on the type.
///
/// \param allowOnArrayType Whether to accept nullability specifiers on an
/// array type (e.g., because it will decay to a pointer).
///
/// \returns true if a problem has been diagnosed, false on success.
static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
QualType &type,
ParsedAttr &attr,
bool allowOnArrayType) {
Sema &S = state.getSema();
NullabilityKind nullability = mapNullabilityAttrKind(attr.getKind());
SourceLocation nullabilityLoc = attr.getLoc();
bool isContextSensitive = attr.isContextSensitiveKeywordAttribute();
recordNullabilitySeen(S, nullabilityLoc);
// Check for existing nullability attributes on the type.
QualType desugared = type;
while (auto attributed = dyn_cast<AttributedType>(desugared.getTypePtr())) {
// Check whether there is already a null
if (auto existingNullability = attributed->getImmediateNullability()) {
// Duplicated nullability.
if (nullability == *existingNullability) {
S.Diag(nullabilityLoc, diag::warn_nullability_duplicate)
<< DiagNullabilityKind(nullability, isContextSensitive)
<< FixItHint::CreateRemoval(nullabilityLoc);
break;
}
// Conflicting nullability.
S.Diag(nullabilityLoc, diag::err_nullability_conflicting)
<< DiagNullabilityKind(nullability, isContextSensitive)
<< DiagNullabilityKind(*existingNullability, false);
return true;
}
desugared = attributed->getModifiedType();
}
// If there is already a different nullability specifier, complain.
// This (unlike the code above) looks through typedefs that might
// have nullability specifiers on them, which means we cannot
// provide a useful Fix-It.
if (auto existingNullability = desugared->getNullability(S.Context)) {
if (nullability != *existingNullability) {
S.Diag(nullabilityLoc, diag::err_nullability_conflicting)
<< DiagNullabilityKind(nullability, isContextSensitive)
<< DiagNullabilityKind(*existingNullability, false);
// Try to find the typedef with the existing nullability specifier.
if (auto typedefType = desugared->getAs<TypedefType>()) {
TypedefNameDecl *typedefDecl = typedefType->getDecl();
QualType underlyingType = typedefDecl->getUnderlyingType();
if (auto typedefNullability
= AttributedType::stripOuterNullability(underlyingType)) {
if (*typedefNullability == *existingNullability) {
S.Diag(typedefDecl->getLocation(), diag::note_nullability_here)
<< DiagNullabilityKind(*existingNullability, false);
}
}
}
return true;
}
}
// If this definitely isn't a pointer type, reject the specifier.
if (!desugared->canHaveNullability() &&
!(allowOnArrayType && desugared->isArrayType())) {
S.Diag(nullabilityLoc, diag::err_nullability_nonpointer)
<< DiagNullabilityKind(nullability, isContextSensitive) << type;
return true;
}
// For the context-sensitive keywords/Objective-C property
// attributes, require that the type be a single-level pointer.
if (isContextSensitive) {
// Make sure that the pointee isn't itself a pointer type.
const Type *pointeeType;
if (desugared->isArrayType())
pointeeType = desugared->getArrayElementTypeNoTypeQual();
else
pointeeType = desugared->getPointeeType().getTypePtr();
if (pointeeType->isAnyPointerType() ||
pointeeType->isObjCObjectPointerType() ||
pointeeType->isMemberPointerType()) {
S.Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
<< DiagNullabilityKind(nullability, true)
<< type;
S.Diag(nullabilityLoc, diag::note_nullability_type_specifier)
<< DiagNullabilityKind(nullability, false)
<< type
<< FixItHint::CreateReplacement(nullabilityLoc,
getNullabilitySpelling(nullability));
return true;
}
}
// Form the attributed type.
type = state.getAttributedType(
createNullabilityAttr(S.Context, attr, nullability), type, type);
return false;
}
/// Check the application of the Objective-C '__kindof' qualifier to
/// the given type.
static bool checkObjCKindOfType(TypeProcessingState &state, QualType &type,
ParsedAttr &attr) {
Sema &S = state.getSema();
if (isa<ObjCTypeParamType>(type)) {
// Build the attributed type to record where __kindof occurred.
type = state.getAttributedType(
createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, type);
return false;
}
// Find out if it's an Objective-C object or object pointer type;
const ObjCObjectPointerType *ptrType = type->getAs<ObjCObjectPointerType>();
const ObjCObjectType *objType = ptrType ? ptrType->getObjectType()
: type->getAs<ObjCObjectType>();
// If not, we can't apply __kindof.
if (!objType) {
// FIXME: Handle dependent types that aren't yet object types.
S.Diag(attr.getLoc(), diag::err_objc_kindof_nonobject)
<< type;
return true;
}
// Rebuild the "equivalent" type, which pushes __kindof down into
// the object type.
// There is no need to apply kindof on an unqualified id type.
QualType equivType = S.Context.getObjCObjectType(
objType->getBaseType(), objType->getTypeArgsAsWritten(),
objType->getProtocols(),
/*isKindOf=*/objType->isObjCUnqualifiedId() ? false : true);
// If we started with an object pointer type, rebuild it.
if (ptrType) {
equivType = S.Context.getObjCObjectPointerType(equivType);
if (auto nullability = type->getNullability(S.Context)) {
// We create a nullability attribute from the __kindof attribute.
// Make sure that will make sense.
assert(attr.getAttributeSpellingListIndex() == 0 &&
"multiple spellings for __kindof?");
Attr *A = createNullabilityAttr(S.Context, attr, *nullability);
A->setImplicit(true);
equivType = state.getAttributedType(A, equivType, equivType);
}
}
// Build the attributed type to record where __kindof occurred.
type = state.getAttributedType(
createSimpleAttr<ObjCKindOfAttr>(S.Context, attr), type, equivType);
return false;
}
/// Distribute a nullability type attribute that cannot be applied to
/// the type specifier to a pointer, block pointer, or member pointer
/// declarator, complaining if necessary.
///
/// \returns true if the nullability annotation was distributed, false
/// otherwise.
static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
QualType type, ParsedAttr &attr) {
Declarator &declarator = state.getDeclarator();
/// Attempt to move the attribute to the specified chunk.
auto moveToChunk = [&](DeclaratorChunk &chunk, bool inFunction) -> bool {
// If there is already a nullability attribute there, don't add
// one.
if (hasNullabilityAttr(chunk.getAttrs()))
return false;
// Complain about the nullability qualifier being in the wrong
// place.
enum {
PK_Pointer,
PK_BlockPointer,
PK_MemberPointer,
PK_FunctionPointer,
PK_MemberFunctionPointer,
} pointerKind
= chunk.Kind == DeclaratorChunk::Pointer ? (inFunction ? PK_FunctionPointer
: PK_Pointer)
: chunk.Kind == DeclaratorChunk::BlockPointer ? PK_BlockPointer
: inFunction? PK_MemberFunctionPointer : PK_MemberPointer;
auto diag = state.getSema().Diag(attr.getLoc(),
diag::warn_nullability_declspec)
<< DiagNullabilityKind(mapNullabilityAttrKind(attr.getKind()),
attr.isContextSensitiveKeywordAttribute())
<< type
<< static_cast<unsigned>(pointerKind);
// FIXME: MemberPointer chunks don't carry the location of the *.
if (chunk.Kind != DeclaratorChunk::MemberPointer) {
diag << FixItHint::CreateRemoval(attr.getLoc())
<< FixItHint::CreateInsertion(
state.getSema().getPreprocessor()
.getLocForEndOfToken(chunk.Loc),
" " + attr.getName()->getName().str() + " ");
}
moveAttrFromListToList(attr, state.getCurrentAttributes(),
chunk.getAttrs());
return true;
};
// Move it to the outermost pointer, member pointer, or block
// pointer declarator.
for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
switch (chunk.Kind) {
case DeclaratorChunk::Pointer:
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::MemberPointer:
return moveToChunk(chunk, false);
case DeclaratorChunk::Paren:
case DeclaratorChunk::Array:
continue;
case DeclaratorChunk::Function:
// Try to move past the return type to a function/block/member
// function pointer.
if (DeclaratorChunk *dest = maybeMovePastReturnType(
declarator, i,
/*onlyBlockPointers=*/false)) {
return moveToChunk(*dest, true);
}
return false;
// Don't walk through these.
case DeclaratorChunk::Reference:
case DeclaratorChunk::Pipe:
return false;
}
}
return false;
}
static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) {
assert(!Attr.isInvalid());
switch (Attr.getKind()) {
default:
llvm_unreachable("not a calling convention attribute");
case ParsedAttr::AT_CDecl:
return createSimpleAttr<CDeclAttr>(Ctx, Attr);
case ParsedAttr::AT_FastCall:
return createSimpleAttr<FastCallAttr>(Ctx, Attr);
case ParsedAttr::AT_StdCall:
return createSimpleAttr<StdCallAttr>(Ctx, Attr);
case ParsedAttr::AT_ThisCall:
return createSimpleAttr<ThisCallAttr>(Ctx, Attr);
case ParsedAttr::AT_RegCall:
return createSimpleAttr<RegCallAttr>(Ctx, Attr);
case ParsedAttr::AT_Pascal:
return createSimpleAttr<PascalAttr>(Ctx, Attr);
case ParsedAttr::AT_SwiftCall:
return createSimpleAttr<SwiftCallAttr>(Ctx, Attr);
case ParsedAttr::AT_VectorCall:
return createSimpleAttr<VectorCallAttr>(Ctx, Attr);
case ParsedAttr::AT_AArch64VectorPcs:
return createSimpleAttr<AArch64VectorPcsAttr>(Ctx, Attr);
case ParsedAttr::AT_Pcs: {
// The attribute may have had a fixit applied where we treated an
// identifier as a string literal. The contents of the string are valid,
// but the form may not be.
StringRef Str;
if (Attr.isArgExpr(0))
Str = cast<StringLiteral>(Attr.getArgAsExpr(0))->getString();
else
Str = Attr.getArgAsIdent(0)->Ident->getName();
PcsAttr::PCSType Type;
if (!PcsAttr::ConvertStrToPCSType(Str, Type))
llvm_unreachable("already validated the attribute");
return ::new (Ctx) PcsAttr(Attr.getRange(), Ctx, Type,
Attr.getAttributeSpellingListIndex());
}
case ParsedAttr::AT_IntelOclBicc:
return createSimpleAttr<IntelOclBiccAttr>(Ctx, Attr);
case ParsedAttr::AT_MSABI:
return createSimpleAttr<MSABIAttr>(Ctx, Attr);
case ParsedAttr::AT_SysVABI:
return createSimpleAttr<SysVABIAttr>(Ctx, Attr);
case ParsedAttr::AT_PreserveMost:
return createSimpleAttr<PreserveMostAttr>(Ctx, Attr);
case ParsedAttr::AT_PreserveAll:
return createSimpleAttr<PreserveAllAttr>(Ctx, Attr);
}
llvm_unreachable("unexpected attribute kind!");
}
/// Process an individual function attribute. Returns true to
/// indicate that the attribute was handled, false if it wasn't.
static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
QualType &type) {
Sema &S = state.getSema();
FunctionTypeUnwrapper unwrapped(S, type);
if (attr.getKind() == ParsedAttr::AT_NoReturn) {
if (S.CheckAttrNoArgs(attr))
return true;
// Delay if this is not a function type.
if (!unwrapped.isFunctionType())
return false;
// Otherwise we can process right away.
FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withNoReturn(true);
type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
return true;
}
// ns_returns_retained is not always a type attribute, but if we got
// here, we're treating it as one right now.
if (attr.getKind() == ParsedAttr::AT_NSReturnsRetained) {
if (attr.getNumArgs()) return true;
// Delay if this is not a function type.
if (!unwrapped.isFunctionType())
return false;
// Check whether the return type is reasonable.
if (S.checkNSReturnsRetainedReturnType(attr.getLoc(),
unwrapped.get()->getReturnType()))
return true;
// Only actually change the underlying type in ARC builds.
QualType origType = type;
if (state.getSema().getLangOpts().ObjCAutoRefCount) {
FunctionType::ExtInfo EI
= unwrapped.get()->getExtInfo().withProducesResult(true);
type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
}
type = state.getAttributedType(
createSimpleAttr<NSReturnsRetainedAttr>(S.Context, attr),
origType, type);
return true;
}
if (attr.getKind() == ParsedAttr::AT_AnyX86NoCallerSavedRegisters) {
if (S.CheckAttrTarget(attr) || S.CheckAttrNoArgs(attr))
return true;
// Delay if this is not a function type.
if (!unwrapped.isFunctionType())
return false;
FunctionType::ExtInfo EI =
unwrapped.get()->getExtInfo().withNoCallerSavedRegs(true);
type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
return true;
}
if (attr.getKind() == ParsedAttr::AT_AnyX86NoCfCheck) {
if (!S.getLangOpts().CFProtectionBranch) {
S.Diag(attr.getLoc(), diag::warn_nocf_check_attribute_ignored);
attr.setInvalid();
return true;
}
if (S.CheckAttrTarget(attr) || S.CheckAttrNoArgs(attr))
return true;
// If this is not a function type, warning will be asserted by subject
// check.
if (!unwrapped.isFunctionType())
return true;
FunctionType::ExtInfo EI =
unwrapped.get()->getExtInfo().withNoCfCheck(true);
type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
return true;
}
if (attr.getKind() == ParsedAttr::AT_Regparm) {
unsigned value;
if (S.CheckRegparmAttr(attr, value))
return true;
// Delay if this is not a function type.
if (!unwrapped.isFunctionType())
return false;
// Diagnose regparm with fastcall.
const FunctionType *fn = unwrapped.get();
CallingConv CC = fn->getCallConv();
if (CC == CC_X86FastCall) {
S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
<< FunctionType::getNameForCallConv(CC)
<< "regparm";
attr.setInvalid();
return true;
}
FunctionType::ExtInfo EI =
unwrapped.get()->getExtInfo().withRegParm(value);
type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
return true;
}
// Delay if the type didn't work out to a function.
if (!unwrapped.isFunctionType()) return false;
// Otherwise, a calling convention.
CallingConv CC;
if (S.CheckCallingConvAttr(attr, CC))
return true;
const FunctionType *fn = unwrapped.get();
CallingConv CCOld = fn->getCallConv();
Attr *CCAttr = getCCTypeAttr(S.Context, attr);
if (CCOld != CC) {
// Error out on when there's already an attribute on the type
// and the CCs don't match.
if (S.getCallingConvAttributedType(type)) {
S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
<< FunctionType::getNameForCallConv(CC)
<< FunctionType::getNameForCallConv(CCOld);
attr.setInvalid();
return true;
}
}
// Diagnose use of variadic functions with calling conventions that
// don't support them (e.g. because they're callee-cleanup).
// We delay warning about this on unprototyped function declarations
// until after redeclaration checking, just in case we pick up a
// prototype that way. And apparently we also "delay" warning about
// unprototyped function types in general, despite not necessarily having
// much ability to diagnose it later.
if (!supportsVariadicCall(CC)) {
const FunctionProtoType *FnP = dyn_cast<FunctionProtoType>(fn);
if (FnP && FnP->isVariadic()) {
unsigned DiagID = diag::err_cconv_varargs;
// stdcall and fastcall are ignored with a warning for GCC and MS
// compatibility.
bool IsInvalid = true;
if (CC == CC_X86StdCall || CC == CC_X86FastCall) {
DiagID = diag::warn_cconv_varargs;
IsInvalid = false;
}
S.Diag(attr.getLoc(), DiagID) << FunctionType::getNameForCallConv(CC);
if (IsInvalid) attr.setInvalid();
return true;
}
}
// Also diagnose fastcall with regparm.
if (CC == CC_X86FastCall && fn->getHasRegParm()) {
S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
<< "regparm" << FunctionType::getNameForCallConv(CC_X86FastCall);
attr.setInvalid();
return true;
}
// Modify the CC from the wrapped function type, wrap it all back, and then
// wrap the whole thing in an AttributedType as written. The modified type
// might have a different CC if we ignored the attribute.
QualType Equivalent;
if (CCOld == CC) {
Equivalent = type;
} else {
auto EI = unwrapped.get()->getExtInfo().withCallingConv(CC);
Equivalent =
unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
}
type = state.getAttributedType(CCAttr, type, Equivalent);
return true;
}
bool Sema::hasExplicitCallingConv(QualType &T) {
QualType R = T.IgnoreParens();
while (const AttributedType *AT = dyn_cast<AttributedType>(R)) {
if (AT->isCallingConv())
return true;
R = AT->getModifiedType().IgnoreParens();
}
return false;
}
void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor,
SourceLocation Loc) {
FunctionTypeUnwrapper Unwrapped(*this, T);
const FunctionType *FT = Unwrapped.get();
bool IsVariadic = (isa<FunctionProtoType>(FT) &&
cast<FunctionProtoType>(FT)->isVariadic());
CallingConv CurCC = FT->getCallConv();
CallingConv ToCC = Context.getDefaultCallingConvention(IsVariadic, !IsStatic);
if (CurCC == ToCC)
return;
// MS compiler ignores explicit calling convention attributes on structors. We
// should do the same.
if (Context.getTargetInfo().getCXXABI().isMicrosoft() && IsCtorOrDtor) {
// Issue a warning on ignored calling convention -- except of __stdcall.
// Again, this is what MS compiler does.
if (CurCC != CC_X86StdCall)
Diag(Loc, diag::warn_cconv_structors)
<< FunctionType::getNameForCallConv(CurCC);
// Default adjustment.
} else {
// Only adjust types with the default convention. For example, on Windows
// we should adjust a __cdecl type to __thiscall for instance methods, and a
// __thiscall type to __cdecl for static methods.
CallingConv DefaultCC =
Context.getDefaultCallingConvention(IsVariadic, IsStatic);
if (CurCC != DefaultCC || DefaultCC == ToCC)
return;
if (hasExplicitCallingConv(T))
return;
}
FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(ToCC));
QualType Wrapped = Unwrapped.wrap(*this, FT);
T = Context.getAdjustedType(T, Wrapped);
}
/// HandleVectorSizeAttribute - this attribute is only applicable to integral
/// and float scalars, although arrays, pointers, and function return values are
/// allowed in conjunction with this construct. Aggregates with this attribute
/// are invalid, even if they are of the same size as a corresponding scalar.
/// The raw attribute should contain precisely 1 argument, the vector size for
/// the variable, measured in bytes. If curType and rawAttr are well formed,
/// this routine will return a new vector type.
static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S) {
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr
<< 1;
Attr.setInvalid();
return;
}
Expr *SizeExpr;
// Special case where the argument is a template id.
if (Attr.isArgIdent(0)) {
CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
UnqualifiedId Id;
Id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
Id, false, false);
if (Size.isInvalid())
return;
SizeExpr = Size.get();
} else {
SizeExpr = Attr.getArgAsExpr(0);
}
QualType T = S.BuildVectorType(CurType, SizeExpr, Attr.getLoc());
if (!T.isNull())
CurType = T;
else
Attr.setInvalid();
}
/// Process the OpenCL-like ext_vector_type attribute when it occurs on
/// a type.
static void HandleExtVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr
<< 1;
return;
}
Expr *sizeExpr;
// Special case where the argument is a template id.
if (Attr.isArgIdent(0)) {
CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
UnqualifiedId id;
id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
id, false, false);
if (Size.isInvalid())
return;
sizeExpr = Size.get();
} else {
sizeExpr = Attr.getArgAsExpr(0);
}
// Create the vector type.
QualType T = S.BuildExtVectorType(CurType, sizeExpr, Attr.getLoc());
if (!T.isNull())
CurType = T;
}
static bool isPermittedNeonBaseType(QualType &Ty,
VectorType::VectorKind VecKind, Sema &S) {
const BuiltinType *BTy = Ty->getAs<BuiltinType>();
if (!BTy)
return false;
llvm::Triple Triple = S.Context.getTargetInfo().getTriple();
// Signed poly is mathematically wrong, but has been baked into some ABIs by
// now.
bool IsPolyUnsigned = Triple.getArch() == llvm::Triple::aarch64 ||
Triple.getArch() == llvm::Triple::aarch64_be;
if (VecKind == VectorType::NeonPolyVector) {
if (IsPolyUnsigned) {
// AArch64 polynomial vectors are unsigned and support poly64.
return BTy->getKind() == BuiltinType::UChar ||
BTy->getKind() == BuiltinType::UShort ||
BTy->getKind() == BuiltinType::ULong ||
BTy->getKind() == BuiltinType::ULongLong;
} else {
// AArch32 polynomial vector are signed.
return BTy->getKind() == BuiltinType::SChar ||
BTy->getKind() == BuiltinType::Short;
}
}
// Non-polynomial vector types: the usual suspects are allowed, as well as
// float64_t on AArch64.
bool Is64Bit = Triple.getArch() == llvm::Triple::aarch64 ||
Triple.getArch() == llvm::Triple::aarch64_be;
if (Is64Bit && BTy->getKind() == BuiltinType::Double)
return true;
return BTy->getKind() == BuiltinType::SChar ||
BTy->getKind() == BuiltinType::UChar ||
BTy->getKind() == BuiltinType::Short ||
BTy->getKind() == BuiltinType::UShort ||
BTy->getKind() == BuiltinType::Int ||
BTy->getKind() == BuiltinType::UInt ||
BTy->getKind() == BuiltinType::Long ||
BTy->getKind() == BuiltinType::ULong ||
BTy->getKind() == BuiltinType::LongLong ||
BTy->getKind() == BuiltinType::ULongLong ||
BTy->getKind() == BuiltinType::Float ||
BTy->getKind() == BuiltinType::Half;
}
/// HandleNeonVectorTypeAttr - The "neon_vector_type" and
/// "neon_polyvector_type" attributes are used to create vector types that
/// are mangled according to ARM's ABI. Otherwise, these types are identical
/// to those created with the "vector_size" attribute. Unlike "vector_size"
/// the argument to these Neon attributes is the number of vector elements,
/// not the vector size in bytes. The vector width and element type must
/// match one of the standard Neon vector types.
static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S, VectorType::VectorKind VecKind) {
// Target must have NEON
if (!S.Context.getTargetInfo().hasFeature("neon")) {
S.Diag(Attr.getLoc(), diag::err_attribute_unsupported) << Attr;
Attr.setInvalid();
return;
}
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr
<< 1;
Attr.setInvalid();
return;
}
// The number of elements must be an ICE.
Expr *numEltsExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
llvm::APSInt numEltsInt(32);
if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() ||
!numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
<< Attr << AANT_ArgumentIntegerConstant
<< numEltsExpr->getSourceRange();
Attr.setInvalid();
return;
}
// Only certain element types are supported for Neon vectors.
if (!isPermittedNeonBaseType(CurType, VecKind, S)) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
Attr.setInvalid();
return;
}
// The total size of the vector must be 64 or 128 bits.
unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
unsigned numElts = static_cast<unsigned>(numEltsInt.getZExtValue());
unsigned vecSize = typeSize * numElts;
if (vecSize != 64 && vecSize != 128) {
S.Diag(Attr.getLoc(), diag::err_attribute_bad_neon_vector_size) << CurType;
Attr.setInvalid();
return;
}
CurType = S.Context.getVectorType(CurType, numElts, VecKind);
}
/// Handle OpenCL Access Qualifier Attribute.
static void HandleOpenCLAccessAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S) {
// OpenCL v2.0 s6.6 - Access qualifier can be used only for image and pipe type.
if (!(CurType->isImageType() || CurType->isPipeType())) {
S.Diag(Attr.getLoc(), diag::err_opencl_invalid_access_qualifier);
Attr.setInvalid();
return;
}
if (const TypedefType* TypedefTy = CurType->getAs<TypedefType>()) {
QualType BaseTy = TypedefTy->desugar();
std::string PrevAccessQual;
if (BaseTy->isPipeType()) {
if (TypedefTy->getDecl()->hasAttr<OpenCLAccessAttr>()) {
OpenCLAccessAttr *Attr =
TypedefTy->getDecl()->getAttr<OpenCLAccessAttr>();
PrevAccessQual = Attr->getSpelling();
} else {
PrevAccessQual = "read_only";
}
} else if (const BuiltinType* ImgType = BaseTy->getAs<BuiltinType>()) {
switch (ImgType->getKind()) {
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id: \
PrevAccessQual = #Access; \
break;
#include "clang/Basic/OpenCLImageTypes.def"
default:
llvm_unreachable("Unable to find corresponding image type.");
}
} else {
llvm_unreachable("unexpected type");
}
StringRef AttrName = Attr.getName()->getName();
if (PrevAccessQual == AttrName.ltrim("_")) {
// Duplicated qualifiers
S.Diag(Attr.getLoc(), diag::warn_duplicate_declspec)
<< AttrName << Attr.getRange();
} else {
// Contradicting qualifiers
S.Diag(Attr.getLoc(), diag::err_opencl_multiple_access_qualifiers);
}
S.Diag(TypedefTy->getDecl()->getBeginLoc(),
diag::note_opencl_typedef_access_qualifier) << PrevAccessQual;
} else if (CurType->isPipeType()) {
if (Attr.getSemanticSpelling() == OpenCLAccessAttr::Keyword_write_only) {
QualType ElemType = CurType->getAs<PipeType>()->getElementType();
CurType = S.Context.getWritePipeType(ElemType);
}
}
}
static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State,
QualType &T, TypeAttrLocation TAL) {
Declarator &D = State.getDeclarator();
// Handle the cases where address space should not be deduced.
//
// The pointee type of a pointer type is always deduced since a pointer always
// points to some memory location which should has an address space.
//
// There are situations that at the point of certain declarations, the address
// space may be unknown and better to be left as default. For example, when
// defining a typedef or struct type, they are not associated with any
// specific address space. Later on, they may be used with any address space
// to declare a variable.
//
// The return value of a function is r-value, therefore should not have
// address space.
//
// The void type does not occupy memory, therefore should not have address
// space, except when it is used as a pointee type.
//
// Since LLVM assumes function type is in default address space, it should not
// have address space.
auto ChunkIndex = State.getCurrentChunkIndex();
bool IsPointee =
ChunkIndex > 0 &&
(D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Pointer ||
D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer ||
D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Reference);
bool IsFuncReturnType =
ChunkIndex > 0 &&
D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Function;
bool IsFuncType =
ChunkIndex < D.getNumTypeObjects() &&
D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function;
if ( // Do not deduce addr space for function return type and function type,
// otherwise it will fail some sema check.
IsFuncReturnType || IsFuncType ||
// Do not deduce addr space for member types of struct, except the pointee
// type of a pointer member type.
(D.getContext() == DeclaratorContext::MemberContext && !IsPointee) ||
// Do not deduce addr space for types used to define a typedef and the
// typedef itself, except the pointee type of a pointer type which is used
// to define the typedef.
(D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef &&
!IsPointee) ||
// Do not deduce addr space of the void type, e.g. in f(void), otherwise
// it will fail some sema check.
(T->isVoidType() && !IsPointee) ||
// Do not deduce address spaces for dependent types because they might end
// up instantiating to a type with an explicit address space qualifier.
T->isDependentType())
return;
LangAS ImpAddr = LangAS::Default;
// Put OpenCL automatic variable in private address space.
// OpenCL v1.2 s6.5:
// The default address space name for arguments to a function in a
// program, or local variables of a function is __private. All function
// arguments shall be in the __private address space.
if (State.getSema().getLangOpts().OpenCLVersion <= 120 &&
!State.getSema().getLangOpts().OpenCLCPlusPlus) {
ImpAddr = LangAS::opencl_private;
} else {
// If address space is not set, OpenCL 2.0 defines non private default
// address spaces for some cases:
// OpenCL 2.0, section 6.5:
// The address space for a variable at program scope or a static variable
// inside a function can either be __global or __constant, but defaults to
// __global if not specified.
// (...)
// Pointers that are declared without pointing to a named address space
// point to the generic address space.
if (IsPointee) {
ImpAddr = LangAS::opencl_generic;
} else {
if (D.getContext() == DeclaratorContext::TemplateArgContext) {
// Do not deduce address space for non-pointee type in template arg.
} else if (D.getContext() == DeclaratorContext::FileContext) {
ImpAddr = LangAS::opencl_global;
} else {
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern) {
ImpAddr = LangAS::opencl_global;
} else {
ImpAddr = LangAS::opencl_private;
}
}
}
}
T = State.getSema().Context.getAddrSpaceQualType(T, ImpAddr);
}
static void HandleLifetimeBoundAttr(TypeProcessingState &State,
QualType &CurType,
ParsedAttr &Attr) {
if (State.getDeclarator().isDeclarationOfFunction()) {
CurType = State.getAttributedType(
createSimpleAttr<LifetimeBoundAttr>(State.getSema().Context, Attr),
CurType, CurType);
} else {
Attr.diagnoseAppertainsTo(State.getSema(), nullptr);
}
}
static void processTypeAttrs(TypeProcessingState &state, QualType &type,
TypeAttrLocation TAL,
ParsedAttributesView &attrs) {
// Scan through and apply attributes to this type where it makes sense. Some
// attributes (such as __address_space__, __vector_size__, etc) apply to the
// type, but others can be present in the type specifiers even though they
// apply to the decl. Here we apply type attributes and ignore the rest.
// This loop modifies the list pretty frequently, but we still need to make
// sure we visit every element once. Copy the attributes list, and iterate
// over that.
ParsedAttributesView AttrsCopy{attrs};
state.setParsedNoDeref(false);
for (ParsedAttr &attr : AttrsCopy) {
// Skip attributes that were marked to be invalid.
if (attr.isInvalid())
continue;
if (attr.isCXX11Attribute()) {
// [[gnu::...]] attributes are treated as declaration attributes, so may
// not appertain to a DeclaratorChunk. If we handle them as type
// attributes, accept them in that position and diagnose the GCC
// incompatibility.
if (attr.isGNUScope()) {
bool IsTypeAttr = attr.isTypeAttr();
if (TAL == TAL_DeclChunk) {
state.getSema().Diag(attr.getLoc(),
IsTypeAttr
? diag::warn_gcc_ignores_type_attr
: diag::warn_cxx11_gnu_attribute_on_type)
<< attr.getName();
if (!IsTypeAttr)
continue;
}
} else if (TAL != TAL_DeclChunk) {
// Otherwise, only consider type processing for a C++11 attribute if
// it's actually been applied to a type.
continue;
}
}
// If this is an attribute we can handle, do so now,
// otherwise, add it to the FnAttrs list for rechaining.
switch (attr.getKind()) {
default:
// A C++11 attribute on a declarator chunk must appertain to a type.
if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk) {
state.getSema().Diag(attr.getLoc(), diag::err_attribute_not_type_attr)
<< attr;
attr.setUsedAsTypeAttr();
}
break;
case ParsedAttr::UnknownAttribute:
if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk)
state.getSema().Diag(attr.getLoc(),
diag::warn_unknown_attribute_ignored)
<< attr.getName();
break;
case ParsedAttr::IgnoredAttribute:
break;
case ParsedAttr::AT_MayAlias:
// FIXME: This attribute needs to actually be handled, but if we ignore
// it it breaks large amounts of Linux software.
attr.setUsedAsTypeAttr();
break;
case ParsedAttr::AT_OpenCLPrivateAddressSpace:
case ParsedAttr::AT_OpenCLGlobalAddressSpace:
case ParsedAttr::AT_OpenCLLocalAddressSpace:
case ParsedAttr::AT_OpenCLConstantAddressSpace:
case ParsedAttr::AT_OpenCLGenericAddressSpace:
case ParsedAttr::AT_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state);
attr.setUsedAsTypeAttr();
break;
OBJC_POINTER_TYPE_ATTRS_CASELIST:
if (!handleObjCPointerTypeAttr(state, attr, type))
distributeObjCPointerTypeAttr(state, attr, type);
attr.setUsedAsTypeAttr();
break;
case ParsedAttr::AT_VectorSize:
HandleVectorSizeAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
case ParsedAttr::AT_ExtVectorType:
HandleExtVectorTypeAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
case ParsedAttr::AT_NeonVectorType:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
VectorType::NeonVector);
attr.setUsedAsTypeAttr();
break;
case ParsedAttr::AT_NeonPolyVectorType:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
VectorType::NeonPolyVector);
attr.setUsedAsTypeAttr();
break;
case ParsedAttr::AT_OpenCLAccess:
HandleOpenCLAccessAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
case ParsedAttr::AT_LifetimeBound:
if (TAL == TAL_DeclChunk)
HandleLifetimeBoundAttr(state, type, attr);
break;
case ParsedAttr::AT_NoDeref: {
ASTContext &Ctx = state.getSema().Context;
type = state.getAttributedType(createSimpleAttr<NoDerefAttr>(Ctx, attr),
type, type);
attr.setUsedAsTypeAttr();
state.setParsedNoDeref(true);
break;
}
MS_TYPE_ATTRS_CASELIST:
if (!handleMSPointerTypeQualifierAttr(state, attr, type))
attr.setUsedAsTypeAttr();
break;
NULLABILITY_TYPE_ATTRS_CASELIST:
// Either add nullability here or try to distribute it. We
// don't want to distribute the nullability specifier past any
// dependent type, because that complicates the user model.
if (type->canHaveNullability() || type->isDependentType() ||
type->isArrayType() ||
!distributeNullabilityTypeAttr(state, type, attr)) {
unsigned endIndex;
if (TAL == TAL_DeclChunk)
endIndex = state.getCurrentChunkIndex();
else
endIndex = state.getDeclarator().getNumTypeObjects();
bool allowOnArrayType =
state.getDeclarator().isPrototypeContext() &&
!hasOuterPointerLikeChunk(state.getDeclarator(), endIndex);
if (checkNullabilityTypeSpecifier(
state,
type,
attr,
allowOnArrayType)) {
attr.setInvalid();
}
attr.setUsedAsTypeAttr();
}
break;
case ParsedAttr::AT_ObjCKindOf:
// '__kindof' must be part of the decl-specifiers.
switch (TAL) {
case TAL_DeclSpec:
break;
case TAL_DeclChunk:
case TAL_DeclName:
state.getSema().Diag(attr.getLoc(),
diag::err_objc_kindof_wrong_position)
<< FixItHint::CreateRemoval(attr.getLoc())
<< FixItHint::CreateInsertion(
state.getDeclarator().getDeclSpec().getBeginLoc(),
"__kindof ");
break;
}
// Apply it regardless.
if (checkObjCKindOfType(state, type, attr))
attr.setInvalid();
break;
FUNCTION_TYPE_ATTRS_CASELIST:
attr.setUsedAsTypeAttr();
// Never process function type attributes as part of the
// declaration-specifiers.
if (TAL == TAL_DeclSpec)
distributeFunctionTypeAttrFromDeclSpec(state, attr, type);
// Otherwise, handle the possible delays.
else if (!handleFunctionTypeAttr(state, attr, type))
distributeFunctionTypeAttr(state, attr, type);
break;
}
}
if (!state.getSema().getLangOpts().OpenCL ||
type.getAddressSpace() != LangAS::Default)
return;
deduceOpenCLImplicitAddrSpace(state, type, TAL);
}
void Sema::completeExprArrayBound(Expr *E) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) {
auto *Def = Var->getDefinition();
if (!Def) {
SourceLocation PointOfInstantiation = E->getExprLoc();
InstantiateVariableDefinition(PointOfInstantiation, Var);
Def = Var->getDefinition();
// If we don't already have a point of instantiation, and we managed
// to instantiate a definition, this is the point of instantiation.
// Otherwise, we don't request an end-of-TU instantiation, so this is
// not a point of instantiation.
// FIXME: Is this really the right behavior?
if (Var->getPointOfInstantiation().isInvalid() && Def) {
assert(Var->getTemplateSpecializationKind() ==
TSK_ImplicitInstantiation &&
"explicit instantiation with no point of instantiation");
Var->setTemplateSpecializationKind(
Var->getTemplateSpecializationKind(), PointOfInstantiation);
}
}
// Update the type to the definition's type both here and within the
// expression.
if (Def) {
DRE->setDecl(Def);
QualType T = Def->getType();
DRE->setType(T);
// FIXME: Update the type on all intervening expressions.
E->setType(T);
}
// We still go on to try to complete the type independently, as it
// may also require instantiations or diagnostics if it remains
// incomplete.
}
}
}
}
/// Ensure that the type of the given expression is complete.
///
/// This routine checks whether the expression \p E has a complete type. If the
/// expression refers to an instantiable construct, that instantiation is
/// performed as needed to complete its type. Furthermore
/// Sema::RequireCompleteType is called for the expression's type (or in the
/// case of a reference type, the referred-to type).
///
/// \param E The expression whose type is required to be complete.
/// \param Diagnoser The object that will emit a diagnostic if the type is
/// incomplete.
///
/// \returns \c true if the type of \p E is incomplete and diagnosed, \c false
/// otherwise.
bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser) {
QualType T = E->getType();
// Incomplete array types may be completed by the initializer attached to
// their definitions. For static data members of class templates and for
// variable templates, we need to instantiate the definition to get this
// initializer and complete the type.
if (T->isIncompleteArrayType()) {
completeExprArrayBound(E);
T = E->getType();
}
// FIXME: Are there other cases which require instantiating something other
// than the type to complete the type of an expression?
return RequireCompleteType(E->getExprLoc(), T, Diagnoser);
}
bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
BoundTypeDiagnoser<> Diagnoser(DiagID);
return RequireCompleteExprType(E, Diagnoser);
}
/// Ensure that the type T is a complete type.
///
/// This routine checks whether the type @p T is complete in any
/// context where a complete type is required. If @p T is a complete
/// type, returns false. If @p T is a class template specialization,
/// this routine then attempts to perform class template
/// instantiation. If instantiation fails, or if @p T is incomplete
/// and cannot be completed, issues the diagnostic @p diag (giving it
/// the type @p T) and returns true.
///
/// @param Loc The location in the source that the incomplete type
/// diagnostic should refer to.
///
/// @param T The type that this routine is examining for completeness.
///
/// @returns @c true if @p T is incomplete and a diagnostic was emitted,
/// @c false otherwise.
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser) {
if (RequireCompleteTypeImpl(Loc, T, &Diagnoser))
return true;
if (const TagType *Tag = T->getAs<TagType>()) {
if (!Tag->getDecl()->isCompleteDefinitionRequired()) {
Tag->getDecl()->setCompleteDefinitionRequired();
Consumer.HandleTagDeclRequiredDefinition(Tag->getDecl());
}
}
return false;
}
bool Sema::hasStructuralCompatLayout(Decl *D, Decl *Suggested) {
llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls;
if (!Suggested)
return false;
// FIXME: Add a specific mode for C11 6.2.7/1 in StructuralEquivalenceContext
// and isolate from other C++ specific checks.
StructuralEquivalenceContext Ctx(
D->getASTContext(), Suggested->getASTContext(), NonEquivalentDecls,
StructuralEquivalenceKind::Default,
false /*StrictTypeSpelling*/, true /*Complain*/,
true /*ErrorOnTagTypeMismatch*/);
return Ctx.IsEquivalent(D, Suggested);
}
/// Determine whether there is any declaration of \p D that was ever a
/// definition (perhaps before module merging) and is currently visible.
/// \param D The definition of the entity.
/// \param Suggested Filled in with the declaration that should be made visible
/// in order to provide a definition of this entity.
/// \param OnlyNeedComplete If \c true, we only need the type to be complete,
/// not defined. This only matters for enums with a fixed underlying
/// type, since in all other cases, a type is complete if and only if it
/// is defined.
bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
bool OnlyNeedComplete) {
// Easy case: if we don't have modules, all declarations are visible.
if (!getLangOpts().Modules && !getLangOpts().ModulesLocalVisibility)
return true;
// If this definition was instantiated from a template, map back to the
// pattern from which it was instantiated.
if (isa<TagDecl>(D) && cast<TagDecl>(D)->isBeingDefined()) {
// We're in the middle of defining it; this definition should be treated
// as visible.
return true;
} else if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
if (auto *Pattern = RD->getTemplateInstantiationPattern())
RD = Pattern;
D = RD->getDefinition();
} else if (auto *ED = dyn_cast<EnumDecl>(D)) {
if (auto *Pattern = ED->getTemplateInstantiationPattern())
ED = Pattern;
if (OnlyNeedComplete && ED->isFixed()) {
// If the enum has a fixed underlying type, and we're only looking for a
// complete type (not a definition), any visible declaration of it will
// do.
*Suggested = nullptr;
for (auto *Redecl : ED->redecls()) {
if (isVisible(Redecl))
return true;
if (Redecl->isThisDeclarationADefinition() ||
(Redecl->isCanonicalDecl() && !*Suggested))
*Suggested = Redecl;
}
return false;
}
D = ED->getDefinition();
} else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
if (auto *Pattern = FD->getTemplateInstantiationPattern())
FD = Pattern;
D = FD->getDefinition();
} else if (auto *VD = dyn_cast<VarDecl>(D)) {
if (auto *Pattern = VD->getTemplateInstantiationPattern())
VD = Pattern;
D = VD->getDefinition();
}
assert(D && "missing definition for pattern of instantiated definition");
*Suggested = D;
auto DefinitionIsVisible = [&] {
// The (primary) definition might be in a visible module.
if (isVisible(D))
return true;
// A visible module might have a merged definition instead.
if (D->isModulePrivate() ? hasMergedDefinitionInCurrentModule(D)
: hasVisibleMergedDefinition(D)) {
if (CodeSynthesisContexts.empty() &&
!getLangOpts().ModulesLocalVisibility) {
// Cache the fact that this definition is implicitly visible because
// there is a visible merged definition.
D->setVisibleDespiteOwningModule();
}
return true;
}
return false;
};
if (DefinitionIsVisible())
return true;
// The external source may have additional definitions of this entity that are
// visible, so complete the redeclaration chain now and ask again.
if (auto *Source = Context.getExternalSource()) {
Source->CompleteRedeclChain(D);
return DefinitionIsVisible();
}
return false;
}
/// Locks in the inheritance model for the given class and all of its bases.
static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
RD = RD->getMostRecentNonInjectedDecl();
if (!RD->hasAttr<MSInheritanceAttr>()) {
MSInheritanceAttr::Spelling IM;
switch (S.MSPointerToMemberRepresentationMethod) {
case LangOptions::PPTMK_BestCase:
IM = RD->calculateInheritanceModel();
break;
case LangOptions::PPTMK_FullGeneralitySingleInheritance:
IM = MSInheritanceAttr::Keyword_single_inheritance;
break;
case LangOptions::PPTMK_FullGeneralityMultipleInheritance:
IM = MSInheritanceAttr::Keyword_multiple_inheritance;
break;
case LangOptions::PPTMK_FullGeneralityVirtualInheritance:
IM = MSInheritanceAttr::Keyword_unspecified_inheritance;
break;
}
RD->addAttr(MSInheritanceAttr::CreateImplicit(
S.getASTContext(), IM,
/*BestCase=*/S.MSPointerToMemberRepresentationMethod ==
LangOptions::PPTMK_BestCase,
S.ImplicitMSInheritanceAttrLoc.isValid()
? S.ImplicitMSInheritanceAttrLoc
: RD->getSourceRange()));
S.Consumer.AssignInheritanceModel(RD);
}
}
/// The implementation of RequireCompleteType
bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
TypeDiagnoser *Diagnoser) {
// FIXME: Add this assertion to make sure we always get instantiation points.
// assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType");
// FIXME: Add this assertion to help us flush out problems with
// checking for dependent types and type-dependent expressions.
//
// assert(!T->isDependentType() &&
// "Can't ask whether a dependent type is complete");
if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
if (!MPTy->getClass()->isDependentType()) {
if (getLangOpts().CompleteMemberPointers &&
!MPTy->getClass()->getAsCXXRecordDecl()->isBeingDefined() &&
RequireCompleteType(Loc, QualType(MPTy->getClass(), 0),
diag::err_memptr_incomplete))
return true;
// We lock in the inheritance model once somebody has asked us to ensure
// that a pointer-to-member type is complete.
if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
(void)isCompleteType(Loc, QualType(MPTy->getClass(), 0));
assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
}
}
}
NamedDecl *Def = nullptr;
bool Incomplete = T->isIncompleteType(&Def);
// Check that any necessary explicit specializations are visible. For an
// enum, we just need the declaration, so don't check this.
if (Def && !isa<EnumDecl>(Def))
checkSpecializationVisibility(Loc, Def);
// If we have a complete type, we're done.
if (!Incomplete) {
// If we know about the definition but it is not visible, complain.
NamedDecl *SuggestedDef = nullptr;
if (Def &&
!hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true)) {
// If the user is going to see an error here, recover by making the
// definition visible.
bool TreatAsComplete = Diagnoser && !isSFINAEContext();
if (Diagnoser && SuggestedDef)
diagnoseMissingImport(Loc, SuggestedDef, MissingImportKind::Definition,
/*Recover*/TreatAsComplete);
return !TreatAsComplete;
} else if (Def && !TemplateInstCallbacks.empty()) {
CodeSynthesisContext TempInst;
TempInst.Kind = CodeSynthesisContext::Memoization;
TempInst.Template = Def;
TempInst.Entity = Def;
TempInst.PointOfInstantiation = Loc;
atTemplateBegin(TemplateInstCallbacks, *this, TempInst);
atTemplateEnd(TemplateInstCallbacks, *this, TempInst);
}
return false;
}
TagDecl *Tag = dyn_cast_or_null<TagDecl>(Def);
ObjCInterfaceDecl *IFace = dyn_cast_or_null<ObjCInterfaceDecl>(Def);
// Give the external source a chance to provide a definition of the type.
// This is kept separate from completing the redeclaration chain so that
// external sources such as LLDB can avoid synthesizing a type definition
// unless it's actually needed.
if (Tag || IFace) {
// Avoid diagnosing invalid decls as incomplete.
if (Def->isInvalidDecl())
return true;
// Give the external AST source a chance to complete the type.
if (auto *Source = Context.getExternalSource()) {
if (Tag && Tag->hasExternalLexicalStorage())
Source->CompleteType(Tag);
if (IFace && IFace->hasExternalLexicalStorage())
Source->CompleteType(IFace);
// If the external source completed the type, go through the motions
// again to ensure we're allowed to use the completed type.
if (!T->isIncompleteType())
return RequireCompleteTypeImpl(Loc, T, Diagnoser);
}
}
// If we have a class template specialization or a class member of a
// class template specialization, or an array with known size of such,
// try to instantiate it.
if (auto *RD = dyn_cast_or_null<CXXRecordDecl>(Tag)) {
bool Instantiated = false;
bool Diagnosed = false;
if (RD->isDependentContext()) {
// Don't try to instantiate a dependent class (eg, a member template of
// an instantiated class template specialization).
// FIXME: Can this ever happen?
} else if (auto *ClassTemplateSpec =
dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) {
Diagnosed = InstantiateClassTemplateSpecialization(
Loc, ClassTemplateSpec, TSK_ImplicitInstantiation,
/*Complain=*/Diagnoser);
Instantiated = true;
}
} else {
CXXRecordDecl *Pattern = RD->getInstantiatedFromMemberClass();
if (!RD->isBeingDefined() && Pattern) {
MemberSpecializationInfo *MSI = RD->getMemberSpecializationInfo();
assert(MSI && "Missing member specialization information?");
// This record was instantiated from a class within a template.
if (MSI->getTemplateSpecializationKind() !=
TSK_ExplicitSpecialization) {
Diagnosed = InstantiateClass(Loc, RD, Pattern,
getTemplateInstantiationArgs(RD),
TSK_ImplicitInstantiation,
/*Complain=*/Diagnoser);
Instantiated = true;
}
}
}
if (Instantiated) {
// Instantiate* might have already complained that the template is not
// defined, if we asked it to.
if (Diagnoser && Diagnosed)
return true;
// If we instantiated a definition, check that it's usable, even if
// instantiation produced an error, so that repeated calls to this
// function give consistent answers.
if (!T->isIncompleteType())
return RequireCompleteTypeImpl(Loc, T, Diagnoser);
}
}
// FIXME: If we didn't instantiate a definition because of an explicit
// specialization declaration, check that it's visible.
if (!Diagnoser)
return true;
Diagnoser->diagnose(*this, Loc, T);
// If the type was a forward declaration of a class/struct/union
// type, produce a note.
if (Tag && !Tag->isInvalidDecl())
Diag(Tag->getLocation(),
Tag->isBeingDefined() ? diag::note_type_being_defined
: diag::note_forward_declaration)
<< Context.getTagDeclType(Tag);
// If the Objective-C class was a forward declaration, produce a note.
if (IFace && !IFace->isInvalidDecl())
Diag(IFace->getLocation(), diag::note_forward_class);
// If we have external information that we can use to suggest a fix,
// produce a note.
if (ExternalSource)
ExternalSource->MaybeDiagnoseMissingCompleteType(Loc, T);
return true;
}
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
unsigned DiagID) {
BoundTypeDiagnoser<> Diagnoser(DiagID);
return RequireCompleteType(Loc, T, Diagnoser);
}
/// Get diagnostic %select index for tag kind for
/// literal type diagnostic message.
/// WARNING: Indexes apply to particular diagnostics only!
///
/// \returns diagnostic %select index.
static unsigned getLiteralDiagFromTagKind(TagTypeKind Tag) {
switch (Tag) {
case TTK_Struct: return 0;
case TTK_Interface: return 1;
case TTK_Class: return 2;
default: llvm_unreachable("Invalid tag kind for literal type diagnostic!");
}
}
/// Ensure that the type T is a literal type.
///
/// This routine checks whether the type @p T is a literal type. If @p T is an
/// incomplete type, an attempt is made to complete it. If @p T is a literal
/// type, or @p AllowIncompleteType is true and @p T is an incomplete type,
/// returns false. Otherwise, this routine issues the diagnostic @p PD (giving
/// it the type @p T), along with notes explaining why the type is not a
/// literal type, and returns true.
///
/// @param Loc The location in the source that the non-literal type
/// diagnostic should refer to.
///
/// @param T The type that this routine is examining for literalness.
///
/// @param Diagnoser Emits a diagnostic if T is not a literal type.
///
/// @returns @c true if @p T is not a literal type and a diagnostic was emitted,
/// @c false otherwise.
bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser) {
assert(!T->isDependentType() && "type should not be dependent");
QualType ElemType = Context.getBaseElementType(T);
if ((isCompleteType(Loc, ElemType) || ElemType->isVoidType()) &&
T->isLiteralType(Context))
return false;
Diagnoser.diagnose(*this, Loc, T);
if (T->isVariableArrayType())
return true;
const RecordType *RT = ElemType->getAs<RecordType>();
if (!RT)
return true;
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
// A partially-defined class type can't be a literal type, because a literal
// class type must have a trivial destructor (which can't be checked until
// the class definition is complete).
if (RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T))
return true;
// [expr.prim.lambda]p3:
// This class type is [not] a literal type.
if (RD->isLambda() && !getLangOpts().CPlusPlus17) {
Diag(RD->getLocation(), diag::note_non_literal_lambda);
return true;
}
// If the class has virtual base classes, then it's not an aggregate, and
// cannot have any constexpr constructors or a trivial default constructor,
// so is non-literal. This is better to diagnose than the resulting absence
// of constexpr constructors.
if (RD->getNumVBases()) {
Diag(RD->getLocation(), diag::note_non_literal_virtual_base)
<< getLiteralDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
for (const auto &I : RD->vbases())
Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here)
<< I.getSourceRange();
} else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor() &&
!RD->hasTrivialDefaultConstructor()) {
Diag(RD->getLocation(), diag::note_non_literal_no_constexpr_ctors) << RD;
} else if (RD->hasNonLiteralTypeFieldsOrBases()) {
for (const auto &I : RD->bases()) {
if (!I.getType()->isLiteralType(Context)) {
Diag(I.getBeginLoc(), diag::note_non_literal_base_class)
<< RD << I.getType() << I.getSourceRange();
return true;
}
}
for (const auto *I : RD->fields()) {
if (!I->getType()->isLiteralType(Context) ||
I->getType().isVolatileQualified()) {
Diag(I->getLocation(), diag::note_non_literal_field)
<< RD << I << I->getType()
<< I->getType().isVolatileQualified();
return true;
}
}
} else if (!RD->hasTrivialDestructor()) {
// All fields and bases are of literal types, so have trivial destructors.
// If this class's destructor is non-trivial it must be user-declared.
CXXDestructorDecl *Dtor = RD->getDestructor();
assert(Dtor && "class has literal fields and bases but no dtor?");
if (!Dtor)
return true;
Diag(Dtor->getLocation(), Dtor->isUserProvided() ?
diag::note_non_literal_user_provided_dtor :
diag::note_non_literal_nontrivial_dtor) << RD;
if (!Dtor->isUserProvided())
SpecialMemberIsTrivial(Dtor, CXXDestructor, TAH_IgnoreTrivialABI,
/*Diagnose*/true);
}
return true;
}
bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID) {
BoundTypeDiagnoser<> Diagnoser(DiagID);
return RequireLiteralType(Loc, T, Diagnoser);
}
/// Retrieve a version of the type 'T' that is elaborated by Keyword, qualified
/// by the nested-name-specifier contained in SS, and that is (re)declared by
/// OwnedTagDecl, which is nullptr if this is not a (re)declaration.
QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
const CXXScopeSpec &SS, QualType T,
TagDecl *OwnedTagDecl) {
if (T.isNull())
return T;
NestedNameSpecifier *NNS;
if (SS.isValid())
NNS = SS.getScopeRep();
else {
if (Keyword == ETK_None)
return T;
NNS = nullptr;
}
return Context.getElaboratedType(Keyword, NNS, T, OwnedTagDecl);
}
QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
assert(!E->hasPlaceholderType() && "unexpected placeholder");
if (!getLangOpts().CPlusPlus && E->refersToBitField())
Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 2;
if (!E->isTypeDependent()) {
QualType T = E->getType();
if (const TagType *TT = T->getAs<TagType>())
DiagnoseUseOfDecl(TT->getDecl(), E->getExprLoc());
}
return Context.getTypeOfExprType(E);
}
/// getDecltypeForExpr - Given an expr, will return the decltype for
/// that expression, according to the rules in C++11
/// [dcl.type.simple]p4 and C++11 [expr.lambda.prim]p18.
static QualType getDecltypeForExpr(Sema &S, Expr *E) {
if (E->isTypeDependent())
return S.Context.DependentTy;
// C++11 [dcl.type.simple]p4:
// The type denoted by decltype(e) is defined as follows:
//
// - if e is an unparenthesized id-expression or an unparenthesized class
// member access (5.2.5), decltype(e) is the type of the entity named
// by e. If there is no such entity, or if e names a set of overloaded
// functions, the program is ill-formed;
//
// We apply the same rules for Objective-C ivar and property references.
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
const ValueDecl *VD = DRE->getDecl();
return VD->getType();
} else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
if (const ValueDecl *VD = ME->getMemberDecl())
if (isa<FieldDecl>(VD) || isa<VarDecl>(VD))
return VD->getType();
} else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(E)) {
return IR->getDecl()->getType();
} else if (const ObjCPropertyRefExpr *PR = dyn_cast<ObjCPropertyRefExpr>(E)) {
if (PR->isExplicitProperty())
return PR->getExplicitProperty()->getType();
} else if (auto *PE = dyn_cast<PredefinedExpr>(E)) {
return PE->getType();
}
// C++11 [expr.lambda.prim]p18:
// Every occurrence of decltype((x)) where x is a possibly
// parenthesized id-expression that names an entity of automatic
// storage duration is treated as if x were transformed into an
// access to a corresponding data member of the closure type that
// would have been declared if x were an odr-use of the denoted
// entity.
using namespace sema;
if (S.getCurLambda()) {
if (isa<ParenExpr>(E)) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
QualType T = S.getCapturedDeclRefType(Var, DRE->getLocation());
if (!T.isNull())
return S.Context.getLValueReferenceType(T);
}
}
}
}
// C++11 [dcl.type.simple]p4:
// [...]
QualType T = E->getType();
switch (E->getValueKind()) {
// - otherwise, if e is an xvalue, decltype(e) is T&&, where T is the
// type of e;
case VK_XValue: T = S.Context.getRValueReferenceType(T); break;
// - otherwise, if e is an lvalue, decltype(e) is T&, where T is the
// type of e;
case VK_LValue: T = S.Context.getLValueReferenceType(T); break;
// - otherwise, decltype(e) is the type of e.
case VK_RValue: break;
}
return T;
}
QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc,
bool AsUnevaluated) {
assert(!E->hasPlaceholderType() && "unexpected placeholder");
if (AsUnevaluated && CodeSynthesisContexts.empty() &&
E->HasSideEffects(Context, false)) {
// The expression operand for decltype is in an unevaluated expression
// context, so side effects could result in unintended consequences.
Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
}
return Context.getDecltypeType(E, getDecltypeForExpr(*this, E));
}
QualType Sema::BuildUnaryTransformType(QualType BaseType,
UnaryTransformType::UTTKind UKind,
SourceLocation Loc) {
switch (UKind) {
case UnaryTransformType::EnumUnderlyingType:
if (!BaseType->isDependentType() && !BaseType->isEnumeralType()) {
Diag(Loc, diag::err_only_enums_have_underlying_types);
return QualType();
} else {
QualType Underlying = BaseType;
if (!BaseType->isDependentType()) {
// The enum could be incomplete if we're parsing its definition or
// recovering from an error.
NamedDecl *FwdDecl = nullptr;
if (BaseType->isIncompleteType(&FwdDecl)) {
Diag(Loc, diag::err_underlying_type_of_incomplete_enum) << BaseType;
Diag(FwdDecl->getLocation(), diag::note_forward_declaration) << FwdDecl;
return QualType();
}
EnumDecl *ED = BaseType->getAs<EnumType>()->getDecl();
assert(ED && "EnumType has no EnumDecl");
DiagnoseUseOfDecl(ED, Loc);
Underlying = ED->getIntegerType();
assert(!Underlying.isNull());
}
return Context.getUnaryTransformType(BaseType, Underlying,
UnaryTransformType::EnumUnderlyingType);
}
}
llvm_unreachable("unknown unary transform type");
}
QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
if (!T->isDependentType()) {
// FIXME: It isn't entirely clear whether incomplete atomic types
// are allowed or not; for simplicity, ban them for the moment.
if (RequireCompleteType(Loc, T, diag::err_atomic_specifier_bad_type, 0))
return QualType();
int DisallowedKind = -1;
if (T->isArrayType())
DisallowedKind = 1;
else if (T->isFunctionType())
DisallowedKind = 2;
else if (T->isReferenceType())
DisallowedKind = 3;
else if (T->isAtomicType())
DisallowedKind = 4;
else if (T.hasQualifiers())
DisallowedKind = 5;
else if (!T.isTriviallyCopyableType(Context))
// Some other non-trivially-copyable type (probably a C++ class)
DisallowedKind = 6;
if (DisallowedKind != -1) {
Diag(Loc, diag::err_atomic_specifier_bad_type) << DisallowedKind << T;
return QualType();
}
// FIXME: Do we need any handling for ARC here?
}
// Build the pointer type.
return Context.getAtomicType(T);
}
Index: vendor/clang/dist-release_80/lib/Tooling/ArgumentsAdjusters.cpp
===================================================================
--- vendor/clang/dist-release_80/lib/Tooling/ArgumentsAdjusters.cpp (revision 343795)
+++ vendor/clang/dist-release_80/lib/Tooling/ArgumentsAdjusters.cpp (revision 343796)
@@ -1,112 +1,134 @@
//===- ArgumentsAdjusters.cpp - Command line arguments adjuster -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains definitions of classes which implement ArgumentsAdjuster
// interface.
//
//===----------------------------------------------------------------------===//
#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include <cstddef>
namespace clang {
namespace tooling {
/// Add -fsyntax-only option to the command line arguments.
ArgumentsAdjuster getClangSyntaxOnlyAdjuster() {
return [](const CommandLineArguments &Args, StringRef /*unused*/) {
CommandLineArguments AdjustedArgs;
for (size_t i = 0, e = Args.size(); i < e; ++i) {
StringRef Arg = Args[i];
// FIXME: Remove options that generate output.
if (!Arg.startswith("-fcolor-diagnostics") &&
!Arg.startswith("-fdiagnostics-color"))
AdjustedArgs.push_back(Args[i]);
}
AdjustedArgs.push_back("-fsyntax-only");
return AdjustedArgs;
};
}
ArgumentsAdjuster getClangStripOutputAdjuster() {
return [](const CommandLineArguments &Args, StringRef /*unused*/) {
CommandLineArguments AdjustedArgs;
for (size_t i = 0, e = Args.size(); i < e; ++i) {
StringRef Arg = Args[i];
if (!Arg.startswith("-o"))
AdjustedArgs.push_back(Args[i]);
if (Arg == "-o") {
// Output is specified as -o foo. Skip the next argument too.
++i;
}
// Else, the output is specified as -ofoo. Just do nothing.
}
return AdjustedArgs;
};
}
ArgumentsAdjuster getClangStripDependencyFileAdjuster() {
return [](const CommandLineArguments &Args, StringRef /*unused*/) {
CommandLineArguments AdjustedArgs;
for (size_t i = 0, e = Args.size(); i < e; ++i) {
StringRef Arg = Args[i];
// All dependency-file options begin with -M. These include -MM,
// -MF, -MG, -MP, -MT, -MQ, -MD, and -MMD.
if (!Arg.startswith("-M")) {
AdjustedArgs.push_back(Args[i]);
continue;
}
if (Arg == "-MF" || Arg == "-MT" || Arg == "-MQ")
// These flags take an argument: -MX foo. Skip the next argument also.
++i;
}
return AdjustedArgs;
};
}
ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra,
ArgumentInsertPosition Pos) {
return [Extra, Pos](const CommandLineArguments &Args, StringRef /*unused*/) {
CommandLineArguments Return(Args);
CommandLineArguments::iterator I;
if (Pos == ArgumentInsertPosition::END) {
I = Return.end();
} else {
I = Return.begin();
++I; // To leave the program name in place
}
Return.insert(I, Extra.begin(), Extra.end());
return Return;
};
}
ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra,
ArgumentInsertPosition Pos) {
return getInsertArgumentAdjuster(CommandLineArguments(1, Extra), Pos);
}
ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,
ArgumentsAdjuster Second) {
if (!First)
return Second;
if (!Second)
return First;
return [First, Second](const CommandLineArguments &Args, StringRef File) {
return Second(First(Args, File), File);
};
}
+ArgumentsAdjuster getStripPluginsAdjuster() {
+ return [](const CommandLineArguments &Args, StringRef /*unused*/) {
+ CommandLineArguments AdjustedArgs;
+ for (size_t I = 0, E = Args.size(); I != E; I++) {
+ // According to https://clang.llvm.org/docs/ClangPlugins.html
+ // plugin arguments are in the form:
+ // -Xclang {-load, -plugin, -plugin-arg-<plugin-name>, -add-plugin}
+ // -Xclang <arbitrary-argument>
+ if (I + 4 < E && Args[I] == "-Xclang" &&
+ (Args[I + 1] == "-load" || Args[I + 1] == "-plugin" ||
+ llvm::StringRef(Args[I + 1]).startswith("-plugin-arg-") ||
+ Args[I + 1] == "-add-plugin") &&
+ Args[I + 2] == "-Xclang") {
+ I += 3;
+ continue;
+ }
+ AdjustedArgs.push_back(Args[I]);
+ }
+ return AdjustedArgs;
+ };
+}
+
} // end namespace tooling
} // end namespace clang
Index: vendor/clang/dist-release_80/test/AST/float16.cpp
===================================================================
--- vendor/clang/dist-release_80/test/AST/float16.cpp (revision 343795)
+++ vendor/clang/dist-release_80/test/AST/float16.cpp (revision 343796)
@@ -1,326 +1,326 @@
-// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s --strict-whitespace
-// RUN: %clang_cc1 -std=c++11 -ast-dump -fnative-half-type %s | FileCheck %s --check-prefix=CHECK-NATIVE --strict-whitespace
+// RUN: %clang_cc1 -std=c++11 -ast-dump -triple aarch64-linux-gnu %s | FileCheck %s --strict-whitespace
+// RUN: %clang_cc1 -std=c++11 -ast-dump -triple aarch64-linux-gnu -fnative-half-type %s | FileCheck %s --check-prefix=CHECK-NATIVE --strict-whitespace
/* Various contexts where type _Float16 can appear. */
/* Namespace */
namespace {
_Float16 f1n;
_Float16 f2n = 33.f16;
_Float16 arr1n[10];
_Float16 arr2n[] = { 1.2, 3.0, 3.e4 };
const volatile _Float16 func1n(const _Float16 &arg) {
return arg + f2n + arr1n[4] - arr2n[1];
}
}
//CHECK: |-NamespaceDecl
//CHECK-NEXT: | |-VarDecl {{.*}} f1n '_Float16'
//CHECK-NEXT: | |-VarDecl {{.*}} f2n '_Float16' cinit
//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 3.300000e+01
//CHECK-NEXT: | |-VarDecl {{.*}} arr1n '_Float16 [10]'
//CHECK-NEXT: | |-VarDecl {{.*}} arr2n '_Float16 [3]' cinit
//CHECK-NEXT: | | `-InitListExpr {{.*}} '_Float16 [3]'
//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
//CHECK-NEXT: | | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00
//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
//CHECK-NEXT: | | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00
//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+04
//CHECK-NEXT: | `-FunctionDecl {{.*}} func1n 'const volatile _Float16 (const _Float16 &)'
/* File */
_Float16 f1f;
_Float16 f2f = 32.4;
_Float16 arr1f[10];
_Float16 arr2f[] = { -1.2, -3.0, -3.e4 };
_Float16 func1f(_Float16 arg);
//CHECK: |-VarDecl {{.*}} f1f '_Float16'
//CHECK-NEXT: |-VarDecl {{.*}} f2f '_Float16' cinit
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 3.240000e+01
//CHECK-NEXT: |-VarDecl {{.*}} arr1f '_Float16 [10]'
//CHECK-NEXT: |-VarDecl {{.*}} arr2f '_Float16 [3]' cinit
//CHECK-NEXT: | `-InitListExpr {{.*}} '_Float16 [3]'
//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
//CHECK-NEXT: | | `-UnaryOperator {{.*}} 'double' prefix '-'
//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00
//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
//CHECK-NEXT: | | `-UnaryOperator {{.*}} 'double' prefix '-'
//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
//CHECK-NEXT: | `-UnaryOperator {{.*}} 'double' prefix '-'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 3.000000e+04
//CHECK-NEXT: |-FunctionDecl {{.*}} func1f '_Float16 (_Float16)'
//CHECK-NEXT: | `-ParmVarDecl {{.*}} arg '_Float16'
// Mixing __fp16 and Float16 types:
// The _Float16 type is first converted to __fp16 type and then the operation
// is completed as if both operands were of __fp16 type.
__fp16 B = -0.1;
auto C = -1.0f16 + B;
// When we do *not* have native half types, we expect __fp16 to be promoted to
// float, and consequently also _Float16 promotions to float:
//CHECK: -VarDecl {{.*}} used B '__fp16' cinit
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__fp16' <FloatingCast>
//CHECK-NEXT: | `-UnaryOperator {{.*}} 'double' prefix '-'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 1.000000e-01
//CHECK-NEXT: |-VarDecl {{.*}} C 'float':'float' cinit
//CHECK-NEXT: | `-BinaryOperator {{.*}} 'float' '+'
//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'float' <FloatingCast>
//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16' prefix '-'
//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'float' <FloatingCast>
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__fp16' <LValueToRValue>
//CHECK-NEXT: | `-DeclRefExpr {{.*}} '__fp16' lvalue Var 0x{{.*}} 'B' '__fp16'
// When do have native half types, we expect to see promotions to fp16:
//CHECK-NATIVE: |-VarDecl {{.*}} used B '__fp16' cinit
//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' <FloatingCast>
//CHECK-NATIVE: | `-UnaryOperator {{.*}} 'double' prefix '-'
//CHECK-NATIVE: | `-FloatingLiteral {{.*}} 'double' 1.000000e-01
//CHECK-NATIVE: |-VarDecl {{.*}} C '__fp16':'__fp16' cinit
//CHECK-NATIVE: | `-BinaryOperator {{.*}} '__fp16' '+'
//CHECK-NATIVE: | |-ImplicitCastExpr {{.*}} '__fp16' <FloatingCast>
//CHECK-NATIVE: | | `-UnaryOperator {{.*}} '_Float16' prefix '-'
//CHECK-NATIVE: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00
//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' <LValueToRValue>
//CHECK-NATIVE: | `-DeclRefExpr {{.*}} '__fp16' lvalue Var 0x{{.*}} 'B' '__fp16'
/* Class */
class C1 {
_Float16 f1c;
static const _Float16 f2c;
volatile _Float16 f3c;
public:
C1(_Float16 arg) : f1c(arg), f3c(arg) { }
_Float16 func1c(_Float16 arg ) {
return f1c + arg;
}
static _Float16 func2c(_Float16 arg) {
return arg * C1::f2c;
}
};
//CHECK: |-CXXRecordDecl {{.*}} referenced class C1 definition
//CHECK: | |-CXXRecordDecl {{.*}} implicit referenced class C1
//CHECK-NEXT: | |-FieldDecl {{.*}} referenced f1c '_Float16'
//CHECK-NEXT: | |-VarDecl {{.*}} used f2c 'const _Float16' static
//CHECK-NEXT: | |-FieldDecl {{.*}} f3c 'volatile _Float16'
//CHECK-NEXT: | |-AccessSpecDecl
//CHECK-NEXT: | |-CXXConstructorDecl {{.*}} used C1 'void (_Float16)
//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16'
//CHECK-NEXT: | | |-CXXCtorInitializer Field {{.*}} 'f1c' '_Float16'
//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
//CHECK-NEXT: | | |-CXXCtorInitializer Field {{.*}} 'f3c' 'volatile _Float16'
//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
//CHECK-NEXT: | | `-CompoundStmt
//CHECK-NEXT: | |-CXXMethodDecl {{.*}} used func1c '_Float16 (_Float16)
//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16'
//CHECK-NEXT: | | `-CompoundStmt
//CHECK-NEXT: | | `-ReturnStmt
//CHECK-NEXT: | | `-BinaryOperator {{.*}} '_Float16' '+'
//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue ->f1c 0x{{.*}}
//CHECK-NEXT: | | | `-CXXThisExpr {{.*}} 'C1 *' this
//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
//CHECK-NEXT: | |-CXXMethodDecl {{.*}} used func2c '_Float16 (_Float16)' static
//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16'
//CHECK-NEXT: | | `-CompoundStmt
//CHECK-NEXT: | | `-ReturnStmt
//CHECK-NEXT: | | `-BinaryOperator {{.*}} '_Float16' '*'
//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'const _Float16' lvalue Var 0x{{.*}} 'f2c' 'const _Float16'
/* Template */
template <class C> C func1t(C arg) {
return arg * 2.f16;
}
//CHECK: |-FunctionTemplateDecl {{.*}} func1t
//CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} C
//CHECK-NEXT: | |-FunctionDecl {{.*}} func1t 'C (C)'
//CHECK-NEXT: | | |-ParmVarDecl {{.*}} referenced arg 'C'
//CHECK-NEXT: | | `-CompoundStmt
//CHECK-NEXT: | | `-ReturnStmt
//CHECK-NEXT: | | `-BinaryOperator {{.*}} '<dependent type>' '*'
//CHECK-NEXT: | | |-DeclRefExpr {{.*}} 'C' lvalue ParmVar {{.*}} 'arg' 'C'
//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00
//CHECK-NEXT: | `-FunctionDecl {{.*}} used func1t '_Float16 (_Float16)'
//CHECK-NEXT: | |-TemplateArgument type '_Float16'
//CHECK-NEXT: | |-ParmVarDecl {{.*}} used arg '_Float16':'_Float16'
//CHECK-NEXT: | `-CompoundStmt
//CHECK-NEXT: | `-ReturnStmt
//CHECK-NEXT: | `-BinaryOperator {{.*}} '_Float16' '*'
//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16':'_Float16' <LValueToRValue>
//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16':'_Float16' lvalue ParmVar {{.*}} 'arg' '_Float16':'_Float16'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00
template <class C> struct S1 {
C mem1;
};
//CHECK: |-ClassTemplateDecl {{.*}} S1
//CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} referenced class depth 0 index 0 C
//CHECK-NEXT: | |-CXXRecordDecl {{.*}} struct S1 definition
//CHECK: | | |-CXXRecordDecl {{.*}} implicit struct S1
//CHECK-NEXT: | | `-FieldDecl {{.*}} mem1 'C'
//CHECK-NEXT: | `-ClassTemplateSpecialization {{.*}} 'S1'
template <> struct S1<_Float16> {
_Float16 mem2;
};
/* Local */
extern int printf (const char *__restrict __format, ...);
int main(void) {
_Float16 f1l = 1e3f16;
//CHECK: | `-VarDecl {{.*}} used f1l '_Float16' cinit
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+03
_Float16 f2l = -0.f16;
//CHECK: | `-VarDecl {{.*}} used f2l '_Float16' cinit
//CHECK-NEXT: | `-UnaryOperator {{.*}} '_Float16' prefix '-'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 0.000000e+00
_Float16 f3l = 1.000976562;
//CHECK: | `-VarDecl {{.*}} used f3l '_Float16' cinit
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 1.000977e+00
C1 c1(f1l);
//CHECK: | `-VarDecl{{.*}} used c1 'C1' callinit
//CHECK-NEXT: | `-CXXConstructExpr {{.*}} 'C1' 'void (_Float16)
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var 0x{{.*}} 'f1l' '_Float16'
S1<_Float16> s1 = { 132.f16 };
//CHECK: | `-VarDecl {{.*}} used s1 'S1<_Float16>':'S1<_Float16>' cinit
//CHECK-NEXT: | `-InitListExpr {{.*}} 'S1<_Float16>':'S1<_Float16>'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.320000e+02
_Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) +
func1t(f1l) + s1.mem2 - f1n + f2n;
//CHECK: | `-VarDecl {{.*}} used f4l '_Float16' cinit
//CHECK-NEXT: | `-BinaryOperator {{.*}} '_Float16' '+'
//CHECK-NEXT: | |-BinaryOperator {{.*}} '_Float16' '-'
//CHECK-NEXT: | | |-BinaryOperator {{.*}} '_Float16' '+'
//CHECK-NEXT: | | | |-BinaryOperator {{.*}} '_Float16' '+'
//CHECK-NEXT: | | | | |-BinaryOperator {{.*}} '_Float16' '+'
//CHECK-NEXT: | | | | | |-BinaryOperator {{.*}} '_Float16' '+'
//CHECK-NEXT: | | | | | | |-BinaryOperator {{.*}} '_Float16' '+'
//CHECK-NEXT: | | | | | | | |-CallExpr {{.*}} '_Float16'
//CHECK-NEXT: | | | | | | | | |-ImplicitCastExpr {{.*}} 'const volatile _Float16 (*)(const _Float16 &)' <FunctionToPointerDecay>
//CHECK-NEXT: | | | | | | | | | `-DeclRefExpr {{.*}} 'const volatile _Float16 (const _Float16 &)' lvalue Function {{.*}} 'func1n' 'const volatile _Float16 (const _Float16 &)'
//CHECK-NEXT: | | | | | | | | `-ImplicitCastExpr {{.*}} 'const _Float16' lvalue <NoOp>
//CHECK-NEXT: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'
//CHECK-NEXT: | | | | | | | `-CallExpr {{.*}} '_Float16'
//CHECK-NEXT: | | | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
//CHECK-NEXT: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1f' '_Float16 (_Float16)'
//CHECK-NEXT: | | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16'
//CHECK-NEXT: | | | | | | `-CXXMemberCallExpr {{.*}} '_Float16'
//CHECK-NEXT: | | | | | | |-MemberExpr {{.*}} '<bound member function type>' .func1c {{.*}}
//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} 'C1' lvalue Var {{.*}} 'c1' 'C1'
//CHECK-NEXT: | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16'
//CHECK-NEXT: | | | | | `-CallExpr {{.*}} '_Float16'
//CHECK-NEXT: | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
//CHECK-NEXT: | | | | | | `-MemberExpr {{.*}} '_Float16 (_Float16)' lvalue .func2c {{.*}}
//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} 'C1' lvalue Var {{.*}} 'c1' 'C1'
//CHECK-NEXT: | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'
//CHECK-NEXT: | | | | `-CallExpr {{.*}} '_Float16':'_Float16'
//CHECK-NEXT: | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t')
//CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'
//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue .mem2 {{.*}}
//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'S1<_Float16>':'S1<_Float16>' lvalue Var {{.*}} 's1' 'S1<_Float16>':'S1<_Float16>'
//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1n' '_Float16'
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
auto f5l = -1.f16, *f6l = &f2l, f7l = func1t(f3l);
//CHECK: | |-VarDecl {{.*}} f5l '_Float16':'_Float16' cinit
//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16' prefix '-'
//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00
//CHECK-NEXT: | |-VarDecl {{.*}} f6l '_Float16 *' cinit
//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16 *' prefix '&'
//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16'
//CHECK-NEXT: | `-VarDecl {{.*}} f7l '_Float16':'_Float16' cinit
//CHECK-NEXT: | `-CallExpr {{.*}} '_Float16':'_Float16'
//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t')
//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16'
_Float16 f8l = f4l++;
//CHECK: | `-VarDecl {{.*}} f8l '_Float16' cinit
//CHECK-NEXT: | `-UnaryOperator {{.*}} '_Float16' postfix '++'
//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f4l' '_Float16'
_Float16 arr1l[] = { -1.f16, -0.f16, -11.f16 };
//CHECK: `-VarDecl {{.*}} arr1l '_Float16 [3]' cinit
//CHECK-NEXT: `-InitListExpr {{.*}} '_Float16 [3]'
//CHECK-NEXT: |-UnaryOperator {{.*}} '_Float16' prefix '-'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00
//CHECK-NEXT: |-UnaryOperator {{.*}} '_Float16' prefix '-'
//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 0.000000e+00
//CHECK-NEXT: `-UnaryOperator {{.*}} '_Float16' prefix '-'
//CHECK-NEXT: `-FloatingLiteral {{.*}} '_Float16' 1.100000e+01
float cvtf = f2n;
//CHECK: `-VarDecl {{.*}} cvtf 'float' cinit
//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'float' <FloatingCast>
//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
double cvtd = f2n;
//CHECK: `-VarDecl {{.*}} cvtd 'double' cinit
//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'double' <FloatingCast>
//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
long double cvtld = f2n;
//CHECK: `-VarDecl {{.*}} cvtld 'long double' cinit
//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'long double' <FloatingCast>
//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
_Float16 f2h = 42.0f;
//CHECK: `-VarDecl {{.*}} f2h '_Float16' cinit
//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
//CHECK-NEXT: `-FloatingLiteral {{.*}} 'float' 4.200000e+01
_Float16 d2h = 42.0;
//CHECK: `-VarDecl {{.*}} d2h '_Float16' cinit
//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
//CHECK-NEXT: `-FloatingLiteral {{.*}} 'double' 4.200000e+01
_Float16 ld2h = 42.0l;
//CHECK: `-VarDecl {{.*}} ld2h '_Float16' cinit
//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
//CHECK-NEXT: `-FloatingLiteral {{.*}} 'long double' 4.200000e+01
}
Index: vendor/clang/dist-release_80/test/CXX/dcl.dcl/dcl.attr/dcl.align/p8.cpp
===================================================================
--- vendor/clang/dist-release_80/test/CXX/dcl.dcl/dcl.attr/dcl.align/p8.cpp (revision 343795)
+++ vendor/clang/dist-release_80/test/CXX/dcl.dcl/dcl.attr/dcl.align/p8.cpp (revision 343796)
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -std=c++11 -verify %s
+// RUN: %clang_cc1 -std=c++11 -verify %s -triple x86_64-linux-gnu
alignas(double) void f(); // expected-error {{'alignas' attribute only applies to variables, data members and tag types}}
alignas(double) unsigned char c[sizeof(double)]; // expected-note {{previous}}
extern unsigned char c[sizeof(double)];
alignas(float) extern unsigned char c[sizeof(double)]; // expected-error {{different alignment}}
Index: vendor/clang/dist-release_80/test/CodeCompletion/crash-null-type.cpp
===================================================================
--- vendor/clang/dist-release_80/test/CodeCompletion/crash-null-type.cpp (nonexistent)
+++ vendor/clang/dist-release_80/test/CodeCompletion/crash-null-type.cpp (revision 343796)
@@ -0,0 +1,8 @@
+void test() {
+ for (auto [loopVar] : y) { // y has to be unresolved
+ loopVa
+ }
+}
+// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:3:11 %s -o - \
+// RUN: | FileCheck %s
+// CHECK: COMPLETION: loopVar
Index: vendor/clang/dist-release_80/test/CodeGen/arm64-crc32.c
===================================================================
--- vendor/clang/dist-release_80/test/CodeGen/arm64-crc32.c (revision 343795)
+++ vendor/clang/dist-release_80/test/CodeGen/arm64-crc32.c (revision 343796)
@@ -1,55 +1,58 @@
// REQUIRES: aarch64-registered-target
// RUN: %clang_cc1 -triple arm64-none-linux-gnu \
// RUN: -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-windows \
+// RUN: -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
+#include <stdint.h>
-int crc32b(int a, char b)
+uint32_t crc32b(uint32_t a, uint8_t b)
{
return __builtin_arm_crc32b(a,b);
// CHECK: [[T0:%[0-9]+]] = zext i8 %b to i32
// CHECK: call i32 @llvm.aarch64.crc32b(i32 %a, i32 [[T0]])
}
-int crc32cb(int a, char b)
+uint32_t crc32cb(uint32_t a, uint8_t b)
{
return __builtin_arm_crc32cb(a,b);
// CHECK: [[T0:%[0-9]+]] = zext i8 %b to i32
// CHECK: call i32 @llvm.aarch64.crc32cb(i32 %a, i32 [[T0]])
}
-int crc32h(int a, short b)
+uint32_t crc32h(uint32_t a, uint16_t b)
{
return __builtin_arm_crc32h(a,b);
// CHECK: [[T0:%[0-9]+]] = zext i16 %b to i32
// CHECK: call i32 @llvm.aarch64.crc32h(i32 %a, i32 [[T0]])
}
-int crc32ch(int a, short b)
+uint32_t crc32ch(uint32_t a, uint16_t b)
{
return __builtin_arm_crc32ch(a,b);
// CHECK: [[T0:%[0-9]+]] = zext i16 %b to i32
// CHECK: call i32 @llvm.aarch64.crc32ch(i32 %a, i32 [[T0]])
}
-int crc32w(int a, int b)
+uint32_t crc32w(uint32_t a, uint32_t b)
{
return __builtin_arm_crc32w(a,b);
// CHECK: call i32 @llvm.aarch64.crc32w(i32 %a, i32 %b)
}
-int crc32cw(int a, int b)
+uint32_t crc32cw(uint32_t a, uint32_t b)
{
return __builtin_arm_crc32cw(a,b);
// CHECK: call i32 @llvm.aarch64.crc32cw(i32 %a, i32 %b)
}
-int crc32d(int a, long b)
+uint32_t crc32d(uint32_t a, uint64_t b)
{
return __builtin_arm_crc32d(a,b);
// CHECK: call i32 @llvm.aarch64.crc32x(i32 %a, i64 %b)
}
-int crc32cd(int a, long b)
+uint32_t crc32cd(uint32_t a, uint64_t b)
{
return __builtin_arm_crc32cd(a,b);
// CHECK: call i32 @llvm.aarch64.crc32cx(i32 %a, i64 %b)
}
Index: vendor/clang/dist-release_80/test/CodeGen/builtins-arm64.c
===================================================================
--- vendor/clang/dist-release_80/test/CodeGen/builtins-arm64.c (revision 343795)
+++ vendor/clang/dist-release_80/test/CodeGen/builtins-arm64.c (revision 343796)
@@ -1,86 +1,103 @@
-// RUN: %clang_cc1 -triple arm64-unknown-linux -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-unknown-linux -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LINUX
+// RUN: %clang_cc1 -triple aarch64-windows -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-WIN
+#include <stdint.h>
void f0(void *a, void *b) {
__clear_cache(a,b);
// CHECK: call {{.*}} @__clear_cache
}
void *tp (void) {
return __builtin_thread_pointer ();
// CHECK: call {{.*}} @llvm.thread.pointer()
}
// CHECK: call {{.*}} @llvm.bitreverse.i32(i32 %a)
unsigned rbit(unsigned a) {
return __builtin_arm_rbit(a);
}
+// CHECK-WIN: [[A64:%[^ ]+]] = zext i32 %a to i64
+// CHECK-WIN: call i64 @llvm.bitreverse.i64(i64 [[A64]])
+// CHECK-LINUX: call i64 @llvm.bitreverse.i64(i64 %a)
+unsigned long rbitl(unsigned long a) {
+ return __builtin_arm_rbit64(a);
+}
+
// CHECK: call {{.*}} @llvm.bitreverse.i64(i64 %a)
-unsigned long long rbit64(unsigned long long a) {
+uint64_t rbit64(uint64_t a) {
return __builtin_arm_rbit64(a);
}
void hints() {
__builtin_arm_nop(); //CHECK: call {{.*}} @llvm.aarch64.hint(i32 0)
__builtin_arm_yield(); //CHECK: call {{.*}} @llvm.aarch64.hint(i32 1)
__builtin_arm_wfe(); //CHECK: call {{.*}} @llvm.aarch64.hint(i32 2)
__builtin_arm_wfi(); //CHECK: call {{.*}} @llvm.aarch64.hint(i32 3)
__builtin_arm_sev(); //CHECK: call {{.*}} @llvm.aarch64.hint(i32 4)
__builtin_arm_sevl(); //CHECK: call {{.*}} @llvm.aarch64.hint(i32 5)
}
void barriers() {
__builtin_arm_dmb(1); //CHECK: call {{.*}} @llvm.aarch64.dmb(i32 1)
__builtin_arm_dsb(2); //CHECK: call {{.*}} @llvm.aarch64.dsb(i32 2)
__builtin_arm_isb(3); //CHECK: call {{.*}} @llvm.aarch64.isb(i32 3)
}
void prefetch() {
__builtin_arm_prefetch(0, 1, 2, 0, 1); // pstl3keep
// CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 1, i32 1, i32 1)
__builtin_arm_prefetch(0, 0, 0, 1, 1); // pldl1keep
// CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 0, i32 0, i32 1)
__builtin_arm_prefetch(0, 0, 0, 1, 1); // pldl1strm
// CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 0, i32 0, i32 1)
__builtin_arm_prefetch(0, 0, 0, 0, 0); // plil1keep
// CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 0, i32 3, i32 0)
}
-unsigned rsr() {
+__typeof__(__builtin_arm_rsr("1:2:3:4:5")) rsr(void);
+
+uint32_t rsr() {
// CHECK: [[V0:[%A-Za-z0-9.]+]] = call i64 @llvm.read_register.i64(metadata ![[M0:[0-9]]])
// CHECK-NEXT: trunc i64 [[V0]] to i32
return __builtin_arm_rsr("1:2:3:4:5");
}
-unsigned long rsr64() {
+__typeof__(__builtin_arm_rsr64("1:2:3:4:5")) rsr64(void);
+
+uint64_t rsr64(void) {
// CHECK: call i64 @llvm.read_register.i64(metadata ![[M0:[0-9]]])
return __builtin_arm_rsr64("1:2:3:4:5");
}
void *rsrp() {
// CHECK: [[V0:[%A-Za-z0-9.]+]] = call i64 @llvm.read_register.i64(metadata ![[M0:[0-9]]])
// CHECK-NEXT: inttoptr i64 [[V0]] to i8*
return __builtin_arm_rsrp("1:2:3:4:5");
}
+__typeof__(__builtin_arm_wsr("1:2:3:4:5", 0)) wsr(unsigned);
+
void wsr(unsigned v) {
// CHECK: [[V0:[%A-Za-z0-9.]+]] = zext i32 %v to i64
// CHECK-NEXT: call void @llvm.write_register.i64(metadata ![[M0:[0-9]]], i64 [[V0]])
__builtin_arm_wsr("1:2:3:4:5", v);
}
-void wsr64(unsigned long v) {
+__typeof__(__builtin_arm_wsr64("1:2:3:4:5", 0)) wsr64(uint64_t);
+
+void wsr64(uint64_t v) {
// CHECK: call void @llvm.write_register.i64(metadata ![[M0:[0-9]]], i64 %v)
__builtin_arm_wsr64("1:2:3:4:5", v);
}
void wsrp(void *v) {
// CHECK: [[V0:[%A-Za-z0-9.]+]] = ptrtoint i8* %v to i64
// CHECK-NEXT: call void @llvm.write_register.i64(metadata ![[M0:[0-9]]], i64 [[V0]])
__builtin_arm_wsrp("1:2:3:4:5", v);
}
// CHECK: ![[M0]] = !{!"1:2:3:4:5"}
Index: vendor/clang/dist-release_80/test/CodeGenCXX/float16-declarations.cpp
===================================================================
--- vendor/clang/dist-release_80/test/CodeGenCXX/float16-declarations.cpp (revision 343795)
+++ vendor/clang/dist-release_80/test/CodeGenCXX/float16-declarations.cpp (revision 343796)
@@ -1,149 +1,143 @@
// RUN: %clang -std=c++11 --target=aarch64-arm--eabi -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH64
-// RUN: %clang -std=c++11 --target=x86_64 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X86
/* Various contexts where type _Float16 can appear. */
/* Namespace */
namespace {
_Float16 f1n;
// CHECK-DAG: @_ZN12_GLOBAL__N_13f1nE = internal global half 0xH0000, align 2
_Float16 f2n = 33.f16;
// CHECK-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global half 0xH5020, align 2
_Float16 arr1n[10];
// CHECK-AARCH64-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x half] zeroinitializer, align 2
-// CHECK-X86-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x half] zeroinitializer, align 16
_Float16 arr2n[] = { 1.2, 3.0, 3.e4 };
// CHECK-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x half] [half 0xH3CCD, half 0xH4200, half 0xH7753], align 2
const volatile _Float16 func1n(const _Float16 &arg) {
return arg + f2n + arr1n[4] - arr2n[1];
}
}
/* File */
_Float16 f1f;
// CHECK-AARCH64-DAG: @f1f = dso_local global half 0xH0000, align 2
-// CHECK-X86-DAG: @f1f = dso_local global half 0xH0000, align 2
_Float16 f2f = 32.4;
// CHECK-DAG: @f2f = dso_local global half 0xH500D, align 2
_Float16 arr1f[10];
// CHECK-AARCH64-DAG: @arr1f = dso_local global [10 x half] zeroinitializer, align 2
-// CHECK-X86-DAG: @arr1f = dso_local global [10 x half] zeroinitializer, align 16
_Float16 arr2f[] = { -1.2, -3.0, -3.e4 };
// CHECK-DAG: @arr2f = dso_local global [3 x half] [half 0xHBCCD, half 0xHC200, half 0xHF753], align 2
_Float16 func1f(_Float16 arg);
/* Class */
class C1 {
_Float16 f1c;
static const _Float16 f2c;
// CHECK-DAG: @_ZN2C13f2cE = external dso_local constant half, align 2
volatile _Float16 f3c;
public:
C1(_Float16 arg) : f1c(arg), f3c(arg) { }
// Check that we mangle _Float16 to DF16_
// CHECK-DAG: define linkonce_odr dso_local void @_ZN2C1C2EDF16_(%class.C1*{{.*}}, half{{.*}})
_Float16 func1c(_Float16 arg ) {
return f1c + arg;
}
// CHECK-DAG: define linkonce_odr dso_local half @_ZN2C16func1cEDF16_(%class.C1*{{.*}}, half{{.*}})
static _Float16 func2c(_Float16 arg) {
return arg * C1::f2c;
}
// CHECK-DAG: define linkonce_odr dso_local half @_ZN2C16func2cEDF16_(half{{.*}})
};
/* Template */
template <class C> C func1t(C arg) {
return arg * 2.f16;
}
// CHECK-DAG: define linkonce_odr dso_local half @_Z6func1tIDF16_ET_S0_(half{{.*}})
template <class C> struct S1 {
C mem1;
};
template <> struct S1<_Float16> {
_Float16 mem2;
};
/* Local */
extern int printf (const char *__restrict __format, ...);
int main(void) {
_Float16 f1l = 1e3f16;
// CHECK-DAG: store half 0xH63D0, half* %{{.*}}, align 2
_Float16 f2l = -0.f16;
// CHECK-DAG: store half 0xH8000, half* %{{.*}}, align 2
_Float16 f3l = 1.000976562;
// CHECK-DAG: store half 0xH3C01, half* %{{.*}}, align 2
C1 c1(f1l);
// CHECK-DAG: [[F1L:%[a-z0-9]+]] = load half, half* %{{.*}}, align 2
// CHECK-DAG: call void @_ZN2C1C2EDF16_(%class.C1* %{{.*}}, half %{{.*}})
S1<_Float16> s1 = { 132.f16 };
// CHECK-DAG: @__const.main.s1 = private unnamed_addr constant %struct.S1 { half 0xH5820 }, align 2
// CHECK-DAG: [[S1:%[0-9]+]] = bitcast %struct.S1* %{{.*}} to i8*
// CHECK-DAG: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 2 [[S1]], i8* align 2 bitcast (%struct.S1* @__const.main.s1 to i8*), i64 2, i1 false)
_Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) +
func1t(f1l) + s1.mem2 - f1n + f2n;
auto f5l = -1.f16, *f6l = &f2l, f7l = func1t(f3l);
// CHECK-DAG: store half 0xHBC00, half* %{{.*}}, align 2
// CHECK-DAG: store half* %{{.*}}, half** %{{.*}}, align 8
_Float16 f8l = f4l++;
// CHECK-DAG: %{{.*}} = load half, half* %{{.*}}, align 2
// CHECK-DAG: [[INC:%[a-z0-9]+]] = fadd half {{.*}}, 0xH3C00
// CHECK-DAG: store half [[INC]], half* %{{.*}}, align 2
_Float16 arr1l[] = { -1.f16, -0.f16, -11.f16 };
// CHECK-DAG: @__const.main.arr1l = private unnamed_addr constant [3 x half] [half 0xHBC00, half 0xH8000, half 0xHC980], align 2
float cvtf = f2n;
//CHECK-DAG: [[H2F:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to float
//CHECK-DAG: store float [[H2F]], float* %{{.*}}, align 4
double cvtd = f2n;
//CHECK-DAG: [[H2D:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to double
//CHECK-DAG: store double [[H2D]], double* %{{.*}}, align 8
long double cvtld = f2n;
//CHECK-AARCh64-DAG: [[H2LD:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to fp128
//CHECK-AARCh64-DAG: store fp128 [[H2LD]], fp128* %{{.*}}, align 16
-//CHECK-X86-DAG: [[H2LD:%[a-z0-9]+]] = fpext half {{%[0-9]+}} to x86_fp80
-//CHECK-X86-DAG: store x86_fp80 [[H2LD]], x86_fp80* %{{.*}}, align 16
_Float16 f2h = 42.0f;
//CHECK-DAG: store half 0xH5140, half* %{{.*}}, align 2
_Float16 d2h = 42.0;
//CHECK-DAG: store half 0xH5140, half* %{{.*}}, align 2
_Float16 ld2h = 42.0l;
//CHECK-DAG:store half 0xH5140, half* %{{.*}}, align 2
}
Index: vendor/clang/dist-release_80/test/CodeGenCXX/mangle-ms.cpp
===================================================================
--- vendor/clang/dist-release_80/test/CodeGenCXX/mangle-ms.cpp (revision 343795)
+++ vendor/clang/dist-release_80/test/CodeGenCXX/mangle-ms.cpp (revision 343796)
@@ -1,497 +1,500 @@
// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=i386-pc-win32 -std=c++98 | FileCheck %s
// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=x86_64-pc-win32 -std=c++98| FileCheck -check-prefix X64 %s
+// RUN: %clang_cc1 -fblocks -emit-llvm %s -o - -triple=aarch64-pc-win32 -std=c++98 -DARM | FileCheck -check-prefixes=X64,ARM %s
int a;
// CHECK-DAG: @"?a@@3HA"
extern "C++" {
static int __attribute__((used)) ignore_transparent_context;
// CHECK-DAG: @ignore_transparent_context
}
namespace N {
int b;
// CHECK-DAG: @"?b@N@@3HA"
namespace {
int anonymous;
// CHECK-DAG: @"?anonymous@?A0x{{[^@]*}}@N@@3HA"
}
}
static int c;
// CHECK-DAG: @c
int _c(void) {return N::anonymous + c;}
// CHECK-DAG: @"?_c@@YAHXZ"
// X64-DAG: @"?_c@@YAHXZ"
const int &NeedsReferenceTemporary = 2;
// CHECK-DAG: @"?NeedsReferenceTemporary@@3ABHB" = dso_local constant i32* @"?$RT1@NeedsReferenceTemporary@@3ABHB"
// X64-DAG: @"?NeedsReferenceTemporary@@3AEBHEB" = dso_local constant i32* @"?$RT1@NeedsReferenceTemporary@@3AEBHEB"
class foo {
static const short d;
// CHECK-DAG: @"?d@foo@@0FB"
protected:
static volatile long e;
// CHECK-DAG: @"?e@foo@@1JC"
public:
static const volatile char f;
// CHECK-DAG: @"?f@foo@@2DD"
int operator+(int a);
foo(){}
// CHECK-DAG: @"??0foo@@QAE@XZ"
// X64-DAG: @"??0foo@@QEAA@XZ"
~foo(){}
// CHECK-DAG: @"??1foo@@QAE@XZ"
// X64-DAG: @"??1foo@@QEAA@XZ
foo(int i){}
// CHECK-DAG: @"??0foo@@QAE@H@Z"
// X64-DAG: @"??0foo@@QEAA@H@Z"
foo(char *q){}
// CHECK-DAG: @"??0foo@@QAE@PAD@Z"
// X64-DAG: @"??0foo@@QEAA@PEAD@Z"
static foo* static_method() { return 0; }
}f,s1(1),s2((char*)0);
typedef foo (foo2);
struct bar {
static int g;
};
union baz {
int a;
char b;
double c;
};
enum quux {
qone,
qtwo,
qthree
};
foo bar() { return foo(); }
// CHECK-DAG: @"?bar@@YA?AVfoo@@XZ"
// X64-DAG: @"?bar@@YA?AVfoo@@XZ"
int foo::operator+(int a) {
// CHECK-DAG: @"??Hfoo@@QAEHH@Z"
// X64-DAG: @"??Hfoo@@QEAAHH@Z"
foo::static_method();
// CHECK-DAG: @"?static_method@foo@@SAPAV1@XZ"
// X64-DAG: @"?static_method@foo@@SAPEAV1@XZ"
bar();
return a;
}
const short foo::d = 0;
volatile long foo::e;
const volatile char foo::f = 'C';
int bar::g;
// CHECK-DAG: @"?g@bar@@2HA"
extern int * const h1 = &a;
// CHECK-DAG: @"?h1@@3QAHA"
extern const int * const h2 = &a;
// CHECK-DAG: @"?h2@@3QBHB"
extern int * const __restrict h3 = &a;
// CHECK-DAG: @"?h3@@3QIAHIA"
// X64-DAG: @"?h3@@3QEIAHEIA"
int i[10][20];
// CHECK-DAG: @"?i@@3PAY0BE@HA"
typedef int (*FunT)(int, int);
FunT FunArr[10][20];
// CHECK-DAG: @"?FunArr@@3PAY0BE@P6AHHH@ZA"
// X64-DAG: @"?FunArr@@3PAY0BE@P6AHHH@ZA"
int (__stdcall *j)(signed char, unsigned char);
// CHECK-DAG: @"?j@@3P6GHCE@ZA"
const volatile char foo2::*k;
// CHECK-DAG: @"?k@@3PTfoo@@DT1@"
// X64-DAG: @"?k@@3PETfoo@@DET1@"
int (foo2::*l)(int);
// CHECK-DAG: @"?l@@3P8foo@@AEHH@ZQ1@"
// Ensure typedef CV qualifiers are mangled correctly
typedef const int cInt;
typedef volatile int vInt;
typedef const volatile int cvInt;
extern cInt g_cInt = 1;
vInt g_vInt = 2;
cvInt g_cvInt = 3;
// CHECK-DAG: @"?g_cInt@@3HB"
// CHECK-DAG: @"?g_vInt@@3HC"
// CHECK-DAG: @"?g_cvInt@@3HD"
// Static functions are mangled, too.
// Also make sure calling conventions, arglists, and throw specs work.
static void __stdcall alpha(float a, double b) throw() {}
bool __fastcall beta(long long a, wchar_t b) throw(signed char, unsigned char) {
// CHECK-DAG: @"?beta@@YI_N_J_W@Z"
// X64-DAG: @"?beta@@YA_N_J_W@Z"
alpha(0.f, 0.0);
return false;
}
// CHECK-DAG: @"?alpha@@YGXMN@Z"
// X64-DAG: @"?alpha@@YAXMN@Z"
// Make sure tag-type mangling works.
void gamma(class foo, struct bar, union baz, enum quux) {}
// CHECK-DAG: @"?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
// X64-DAG: @"?gamma@@YAXVfoo@@Ubar@@Tbaz@@W4quux@@@Z"
// Make sure pointer/reference-type mangling works.
void delta(int * const a, const long &) {}
// CHECK-DAG: @"?delta@@YAXQAHABJ@Z"
// X64-DAG: @"?delta@@YAXQEAHAEBJ@Z"
// Array mangling.
void epsilon(int a[][10][20]) {}
// CHECK-DAG: @"?epsilon@@YAXQAY19BE@H@Z"
// X64-DAG: @"?epsilon@@YAXQEAY19BE@H@Z"
void zeta(int (*)(int, int)) {}
// CHECK-DAG: @"?zeta@@YAXP6AHHH@Z@Z"
// X64-DAG: @"?zeta@@YAXP6AHHH@Z@Z"
// Blocks mangling (Clang extension). A block should be mangled slightly
// differently from a similar function pointer.
void eta(int (^)(int, int)) {}
// CHECK-DAG: @"?eta@@YAXP_EAHHH@Z@Z"
typedef int theta_arg(int,int);
void theta(theta_arg^ block) {}
// CHECK-DAG: @"?theta@@YAXP_EAHHH@Z@Z"
void operator_new_delete() {
char *ptr = new char;
// CHECK-DAG: @"??2@YAPAXI@Z"
delete ptr;
// CHECK-DAG: @"??3@YAXPAX@Z"
char *array = new char[42];
// CHECK-DAG: @"??_U@YAPAXI@Z"
delete [] array;
// CHECK-DAG: @"??_V@YAXPAX@Z"
}
// PR13022
void (redundant_parens)();
void redundant_parens_use() { redundant_parens(); }
// CHECK-DAG: @"?redundant_parens@@YAXXZ"
// X64-DAG: @"?redundant_parens@@YAXXZ"
// PR13047
typedef double RGB[3];
RGB color1;
// CHECK-DAG: @"?color1@@3PANA"
extern const RGB color2 = {};
// CHECK-DAG: @"?color2@@3QBNB"
extern RGB const color3[5] = {};
// CHECK-DAG: @"?color3@@3QAY02$$CBNA"
extern RGB const ((color4)[5]) = {};
// CHECK-DAG: @"?color4@@3QAY02$$CBNA"
struct B;
volatile int B::* volatile memptr1;
// X64-DAG: @"?memptr1@@3RESB@@HES1@"
volatile int B::* memptr2;
// X64-DAG: @"?memptr2@@3PESB@@HES1@"
int B::* volatile memptr3;
// X64-DAG: @"?memptr3@@3REQB@@HEQ1@"
typedef int (*fun)();
volatile fun B::* volatile funmemptr1;
// X64-DAG: @"?funmemptr1@@3RESB@@R6AHXZES1@"
volatile fun B::* funmemptr2;
// X64-DAG: @"?funmemptr2@@3PESB@@R6AHXZES1@"
fun B::* volatile funmemptr3;
// X64-DAG: @"?funmemptr3@@3REQB@@P6AHXZEQ1@"
void (B::* volatile memptrtofun1)();
// X64-DAG: @"?memptrtofun1@@3R8B@@EAAXXZEQ1@"
const void (B::* memptrtofun2)();
// X64-DAG: @"?memptrtofun2@@3P8B@@EAAXXZEQ1@"
volatile void (B::* memptrtofun3)();
// X64-DAG: @"?memptrtofun3@@3P8B@@EAAXXZEQ1@"
int (B::* volatile memptrtofun4)();
// X64-DAG: @"?memptrtofun4@@3R8B@@EAAHXZEQ1@"
volatile int (B::* memptrtofun5)();
// X64-DAG: @"?memptrtofun5@@3P8B@@EAA?CHXZEQ1@"
const int (B::* memptrtofun6)();
// X64-DAG: @"?memptrtofun6@@3P8B@@EAA?BHXZEQ1@"
fun (B::* volatile memptrtofun7)();
// X64-DAG: @"?memptrtofun7@@3R8B@@EAAP6AHXZXZEQ1@"
volatile fun (B::* memptrtofun8)();
// X64-DAG: @"?memptrtofun8@@3P8B@@EAAR6AHXZXZEQ1@"
const fun (B::* memptrtofun9)();
// X64-DAG: @"?memptrtofun9@@3P8B@@EAAQ6AHXZXZEQ1@"
// PR12603
enum E {};
// CHECK-DAG: "?fooE@@YA?AW4E@@XZ"
// X64-DAG: "?fooE@@YA?AW4E@@XZ"
E fooE() { return E(); }
class X {};
// CHECK-DAG: "?fooX@@YA?AVX@@XZ"
// X64-DAG: "?fooX@@YA?AVX@@XZ"
X fooX() { return X(); }
namespace PR13182 {
extern char s0[];
// CHECK-DAG: @"?s0@PR13182@@3PADA"
extern char s1[42];
// CHECK-DAG: @"?s1@PR13182@@3PADA"
extern const char s2[];
// CHECK-DAG: @"?s2@PR13182@@3QBDB"
extern const char s3[42];
// CHECK-DAG: @"?s3@PR13182@@3QBDB"
extern volatile char s4[];
// CHECK-DAG: @"?s4@PR13182@@3RCDC"
extern const volatile char s5[];
// CHECK-DAG: @"?s5@PR13182@@3SDDD"
extern const char* const* s6;
// CHECK-DAG: @"?s6@PR13182@@3PBQBDB"
char foo() {
return s0[0] + s1[0] + s2[0] + s3[0] + s4[0] + s5[0] + s6[0][0];
}
}
extern "C" inline void extern_c_func() {
static int local;
// CHECK-DAG: @"?local@?1??extern_c_func@@9@4HA"
// X64-DAG: @"?local@?1??extern_c_func@@9@4HA"
}
void call_extern_c_func() {
extern_c_func();
}
int main() { return 0; }
// CHECK-DAG: @main
// X64-DAG: @main
int wmain() { return 0; }
// CHECK-DAG: @wmain
// X64-DAG: @wmain
int WinMain() { return 0; }
// CHECK-DAG: @WinMain
// X64-DAG: @WinMain
int wWinMain() { return 0; }
// CHECK-DAG: @wWinMain
// X64-DAG: @wWinMain
int DllMain() { return 0; }
// CHECK-DAG: @DllMain
// X64-DAG: @DllMain
inline int inline_function_with_local_type() {
static struct {
int a_field;
} static_variable_in_inline_function = { 20 }, second_static = { 40 };
// CHECK: @"?static_variable_in_inline_function@?1??inline_function_with_local_type@@YAHXZ@4U<unnamed-type-static_variable_in_inline_function>@?1??1@YAHXZ@A"
return static_variable_in_inline_function.a_field + second_static.a_field;
}
int call_inline_function_with_local_type() {
return inline_function_with_local_type();
}
template <typename T>
inline int templated_inline_function_with_local_type() {
static struct {
int a_field;
} static_variable_in_templated_inline_function = { 20 },
second_static = { 40 };
// CHECK: @"?static_variable_in_templated_inline_function@?1???$templated_inline_function_with_local_type@H@@YAHXZ@4U<unnamed-type-static_variable_in_templated_inline_function>@?1???$templated_inline_function_with_local_type@H@@YAHXZ@A"
return static_variable_in_templated_inline_function.a_field +
second_static.a_field;
}
int call_templated_inline_function_with_local_type() {
return templated_inline_function_with_local_type<int>();
}
// PR17371
struct OverloadedNewDelete {
// __cdecl
void *operator new(__SIZE_TYPE__);
void *operator new[](__SIZE_TYPE__);
void operator delete(void *);
void operator delete[](void *);
// __thiscall
int operator+(int);
};
void *OverloadedNewDelete::operator new(__SIZE_TYPE__ s) { return 0; }
void *OverloadedNewDelete::operator new[](__SIZE_TYPE__ s) { return 0; }
void OverloadedNewDelete::operator delete(void *) { }
void OverloadedNewDelete::operator delete[](void *) { }
int OverloadedNewDelete::operator+(int x) { return x; };
// CHECK-DAG: ??2OverloadedNewDelete@@SAPAXI@Z
// CHECK-DAG: ??_UOverloadedNewDelete@@SAPAXI@Z
// CHECK-DAG: ??3OverloadedNewDelete@@SAXPAX@Z
// CHECK-DAG: ??_VOverloadedNewDelete@@SAXPAX@Z
// CHECK-DAG: ??HOverloadedNewDelete@@QAEHH@Z
// X64-DAG: ??2OverloadedNewDelete@@SAPEAX_K@Z
// X64-DAG: ??_UOverloadedNewDelete@@SAPEAX_K@Z
// X64-DAG: ??3OverloadedNewDelete@@SAXPEAX@Z
// X64-DAG: ??_VOverloadedNewDelete@@SAXPEAX@Z
// X64-DAG: ??HOverloadedNewDelete@@QEAAHH@Z
// Indirecting the function type through a typedef will require a calling
// convention adjustment before building the method decl.
typedef void *__thiscall OperatorNewType(__SIZE_TYPE__);
typedef void __thiscall OperatorDeleteType(void *);
struct TypedefNewDelete {
OperatorNewType operator new;
OperatorNewType operator new[];
OperatorDeleteType operator delete;
OperatorDeleteType operator delete[];
};
void *TypedefNewDelete::operator new(__SIZE_TYPE__ s) { return 0; }
void *TypedefNewDelete::operator new[](__SIZE_TYPE__ s) { return 0; }
void TypedefNewDelete::operator delete(void *) { }
void TypedefNewDelete::operator delete[](void *) { }
// CHECK-DAG: ??2TypedefNewDelete@@SAPAXI@Z
// CHECK-DAG: ??_UTypedefNewDelete@@SAPAXI@Z
// CHECK-DAG: ??3TypedefNewDelete@@SAXPAX@Z
// CHECK-DAG: ??_VTypedefNewDelete@@SAXPAX@Z
void __vectorcall vector_func() { }
// CHECK-DAG: @"?vector_func@@YQXXZ"
template <void (*)(void)>
void fn_tmpl() {}
template void fn_tmpl<extern_c_func>();
// CHECK-DAG: @"??$fn_tmpl@$1?extern_c_func@@YAXXZ@@YAXXZ"
extern "C" void __attribute__((overloadable)) overloaded_fn() {}
// CHECK-DAG: @"?overloaded_fn@@$$J0YAXXZ"
extern "C" void overloaded_fn2() {}
// CHECK-DAG: @overloaded_fn2
//
extern "C" void __attribute__((overloadable)) overloaded_fn3();
extern "C" void overloaded_fn3() {}
// CHECK-DAG: @overloaded_fn3
namespace UnnamedType {
struct S {
typedef struct {} *T1[1];
typedef struct {} T2;
typedef struct {} *T3, T4;
using T5 = struct {};
using T6 = struct {} *;
};
void f(S::T1) {}
void f(S::T2) {}
void f(S::T3) {}
void f(S::T4) {}
void f(S::T5) {}
void f(S::T6) {}
// CHECK-DAG: @"?f@UnnamedType@@YAXQAPAU<unnamed-type-T1>@S@1@@Z"
// CHECK-DAG: @"?f@UnnamedType@@YAXUT2@S@1@@Z"
// CHECK-DAG: @"?f@UnnamedType@@YAXPAUT4@S@1@@Z"
// CHECK-DAG: @"?f@UnnamedType@@YAXUT4@S@1@@Z"
// CHECK-DAG: @"?f@UnnamedType@@YAXUT5@S@1@@Z"
// CHECK-DAG: @"?f@UnnamedType@@YAXPAU<unnamed-type-T6>@S@1@@Z"
// X64-DAG: @"?f@UnnamedType@@YAXQEAPEAU<unnamed-type-T1>@S@1@@Z"
// X64-DAG: @"?f@UnnamedType@@YAXUT2@S@1@@Z"
// X64-DAG: @"?f@UnnamedType@@YAXPEAUT4@S@1@@Z"(%"struct.UnnamedType::S::T4"
// X64-DAG: @"?f@UnnamedType@@YAXUT4@S@1@@Z"
// X64-DAG: @"?f@UnnamedType@@YAXUT5@S@1@@Z"
// X64-DAG: @"?f@UnnamedType@@YAXPEAU<unnamed-type-T6>@S@1@@Z"
}
namespace PassObjectSize {
// NOTE: This mangling is subject to change.
// Reiterating from the comment in MicrosoftMangle, the scheme is pretend a
// parameter of type __clang::__pass_object_sizeN exists after each pass object
// size param P, where N is the Type of the pass_object_size attribute on P.
//
// e.g. we want to mangle:
// void foo(void *const __attribute__((pass_object_size(0))));
// as if it were
// namespace __clang { enum __pass_object_size0 : size_t {}; }
// void foo(void *const, __clang::__pass_object_size0);
// where __clang is a top-level namespace.
// CHECK-DAG: define dso_local i32 @"?foo@PassObjectSize@@YAHQAHW4__pass_object_size0@__clang@@@Z"
int foo(int *const i __attribute__((pass_object_size(0)))) { return 0; }
// CHECK-DAG: define dso_local i32 @"?bar@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@@Z"
int bar(int *const i __attribute__((pass_object_size(1)))) { return 0; }
// CHECK-DAG: define dso_local i32 @"?qux@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@0W4__pass_object_size0@3@@Z"
int qux(int *const i __attribute__((pass_object_size(1))), int *const j __attribute__((pass_object_size(0)))) { return 0; }
// CHECK-DAG: define dso_local i32 @"?zot@PassObjectSize@@YAHQAHW4__pass_object_size1@__clang@@01@Z"
int zot(int *const i __attribute__((pass_object_size(1))), int *const j __attribute__((pass_object_size(1)))) { return 0; }
}
namespace Atomic {
// CHECK-DAG: define dso_local void @"?f@Atomic@@YAXU?$_Atomic@H@__clang@@@Z"(
void f(_Atomic(int)) {}
}
namespace Complex {
// CHECK-DAG: define dso_local void @"?f@Complex@@YAXU?$_Complex@H@__clang@@@Z"(
void f(_Complex int) {}
}
+#ifdef ARM
namespace Float16 {
-// CHECK-DAG: define dso_local void @"?f@Float16@@YAXU_Float16@__clang@@@Z"(
+// ARM-DAG: define dso_local void @"?f@Float16@@YAXU_Float16@__clang@@@Z"(
void f(_Float16) {}
}
+#endif // ARM
namespace PR26029 {
template <class>
struct L {
L() {}
};
template <class>
class H;
struct M : L<H<int *> > {};
template <class>
struct H {};
template <class GT>
void m_fn3() {
(H<GT *>());
M();
}
void runOnFunction() {
L<H<int *> > b;
m_fn3<int>();
}
// CHECK-DAG: call {{.*}} @"??0?$L@V?$H@PAH@PR26029@@@PR26029@@QAE@XZ"
}
Index: vendor/clang/dist-release_80/test/CodeGenCXX/trivial_abi.cpp
===================================================================
--- vendor/clang/dist-release_80/test/CodeGenCXX/trivial_abi.cpp (revision 343795)
+++ vendor/clang/dist-release_80/test/CodeGenCXX/trivial_abi.cpp (revision 343796)
@@ -1,254 +1,239 @@
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++17 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++17 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s
// CHECK: %[[STRUCT_SMALL:.*]] = type { i32* }
// CHECK: %[[STRUCT_LARGE:.*]] = type { i32*, [128 x i32] }
// CHECK: %[[STRUCT_TRIVIAL:.*]] = type { i32 }
// CHECK: %[[STRUCT_NONTRIVIAL:.*]] = type { i32 }
struct __attribute__((trivial_abi)) Small {
int *p;
Small();
~Small();
Small(const Small &) noexcept;
Small &operator=(const Small &);
};
struct __attribute__((trivial_abi)) Large {
int *p;
int a[128];
Large();
~Large();
Large(const Large &) noexcept;
Large &operator=(const Large &);
};
struct Trivial {
int a;
};
struct NonTrivial {
NonTrivial();
~NonTrivial();
int a;
};
struct HasTrivial {
Small s;
Trivial m;
};
struct HasNonTrivial {
Small s;
NonTrivial m;
};
-struct __attribute__((trivial_abi)) CopyMoveDeleted {
- CopyMoveDeleted(int);
- CopyMoveDeleted(const CopyMoveDeleted &) = delete;
- CopyMoveDeleted(CopyMoveDeleted &&) = delete;
- int a;
-};
-
// CHECK: define void @_Z14testParamSmall5Small(i64 %[[A_COERCE:.*]])
// CHECK: %[[A:.*]] = alloca %[[STRUCT_SMALL]], align 8
// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[A]], i32 0, i32 0
// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to i32*
// CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8
// CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[A]])
// CHECK: ret void
// CHECK: }
void testParamSmall(Small a) noexcept {
}
// CHECK: define i64 @_Z15testReturnSmallv()
// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
// CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[RETVAL]])
// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[RETVAL]], i32 0, i32 0
// CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8
// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64
// CHECK: ret i64 %[[COERCE_VAL_PI]]
// CHECK: }
Small testReturnSmall() {
Small t;
return t;
}
// CHECK: define void @_Z14testCallSmall0v()
// CHECK: %[[T:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8
// CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[T]])
// CHECK: %[[CALL1:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1ERKS_(%[[STRUCT_SMALL]]* %[[AGG_TMP]], %[[STRUCT_SMALL]]* dereferenceable(8) %[[T]])
// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0
// CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8
// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64
// CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]])
// CHECK: %[[CALL2:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[T]])
// CHECK: ret void
// CHECK: }
void testCallSmall0() {
Small t;
testParamSmall(t);
}
// CHECK: define void @_Z14testCallSmall1v()
// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
// CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv()
// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0
// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32*
// CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8
// CHECK: %[[COERCE_DIVE1:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0
// CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE1]], align 8
// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64
// CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]])
// CHECK: ret void
// CHECK: }
void testCallSmall1() {
testParamSmall(testReturnSmall());
}
// CHECK: define void @_Z16testIgnoredSmallv()
// CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8
// CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv()
// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP_ENSURED]], i32 0, i32 0
// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32*
// CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8
// CHECK: %[[CALL1:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP_ENSURED]])
// CHECK: ret void
// CHECK: }
void testIgnoredSmall() {
testReturnSmall();
}
// CHECK: define void @_Z14testParamLarge5Large(%[[STRUCT_LARGE:.*]]* %[[A:.*]])
// CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[A]])
// CHECK: ret void
// CHECK: }
void testParamLarge(Large a) noexcept {
}
// CHECK: define void @_Z15testReturnLargev(%[[STRUCT_LARGE:.*]]* noalias sret %[[AGG_RESULT:.*]])
// CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_RESULT]])
// CHECK: ret void
// CHECK: }
Large testReturnLarge() {
Large t;
return t;
}
// CHECK: define void @_Z14testCallLarge0v()
// CHECK: %[[T:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8
// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8
// CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[T]])
// CHECK: %[[CALL1:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1ERKS_(%[[STRUCT_LARGE]]* %[[AGG_TMP]], %[[STRUCT_LARGE]]* dereferenceable(520) %[[T]])
// CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[AGG_TMP]])
// CHECK: %[[CALL2:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[T]])
// CHECK: ret void
// CHECK: }
void testCallLarge0() {
Large t;
testParamLarge(t);
}
// CHECK: define void @_Z14testCallLarge1v()
// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8
// CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret %[[AGG_TMP]])
// CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[AGG_TMP]])
// CHECK: ret void
// CHECK: }
void testCallLarge1() {
testParamLarge(testReturnLarge());
}
// CHECK: define void @_Z16testIgnoredLargev()
// CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8
// CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret %[[AGG_TMP_ENSURED]])
// CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP_ENSURED]])
// CHECK: ret void
// CHECK: }
void testIgnoredLarge() {
testReturnLarge();
}
// CHECK: define i64 @_Z20testReturnHasTrivialv()
// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_TRIVIAL:.*]], align 4
// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_TRIVIAL]], %[[STRUCT_TRIVIAL]]* %[[RETVAL]], i32 0, i32 0
// CHECK: %[[V0:.*]] = load i32, i32* %[[COERCE_DIVE]], align 4
// CHECK: %[[COERCE_VAL_II:.*]] = zext i32 %[[V0]] to i64
// CHECK: ret i64 %[[COERCE_VAL_II]]
// CHECK: }
Trivial testReturnHasTrivial() {
Trivial t;
return t;
}
// CHECK: define void @_Z23testReturnHasNonTrivialv(%[[STRUCT_NONTRIVIAL:.*]]* noalias sret %[[AGG_RESULT:.*]])
// CHECK: %[[CALL:.*]] = call %[[STRUCT_NONTRIVIAL]]* @_ZN10NonTrivialC1Ev(%[[STRUCT_NONTRIVIAL]]* %[[AGG_RESULT]])
// CHECK: ret void
// CHECK: }
NonTrivial testReturnHasNonTrivial() {
NonTrivial t;
return t;
}
// CHECK: define void @_Z18testExceptionSmallv()
// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8
// CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_SMALL]], align 8
// CHECK: call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP]])
// CHECK: invoke %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP1]])
// CHECK: call void @_Z20calleeExceptionSmall5SmallS_(i64 %{{.*}}, i64 %{{.*}})
// CHECK-NEXT: ret void
// CHECK: landingpad { i8*, i32 }
// CHECK: call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP]])
// CHECK: br
// CHECK: resume { i8*, i32 }
void calleeExceptionSmall(Small, Small);
void testExceptionSmall() {
calleeExceptionSmall(Small(), Small());
}
// CHECK: define void @_Z18testExceptionLargev()
// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8
// CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_LARGE]], align 8
// CHECK: call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP]])
// CHECK: invoke %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP1]])
// CHECK: call void @_Z20calleeExceptionLarge5LargeS_(%[[STRUCT_LARGE]]* %[[AGG_TMP]], %[[STRUCT_LARGE]]* %[[AGG_TMP1]])
// CHECK-NEXT: ret void
// CHECK: landingpad { i8*, i32 }
// CHECK: call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP]])
// CHECK: br
// CHECK: resume { i8*, i32 }
void calleeExceptionLarge(Large, Large);
void testExceptionLarge() {
calleeExceptionLarge(Large(), Large());
-}
-
-// A class with deleted copy and move constructors can still be passed or
-// returned in registers if the class is annotated with trivial_abi.
-
-// CHECK: define i64 @_Z19testCopyMoveDeletedi(i32 %
-CopyMoveDeleted testCopyMoveDeleted(int a) {
- return a;
}
Index: vendor/clang/dist-release_80/test/CodeGenOpenCL/printf.cl
===================================================================
--- vendor/clang/dist-release_80/test/CodeGenOpenCL/printf.cl (revision 343795)
+++ vendor/clang/dist-release_80/test/CodeGenOpenCL/printf.cl (revision 343796)
@@ -1,39 +1,37 @@
// RUN: %clang_cc1 -cl-std=CL1.2 -cl-ext=-+cl_khr_fp64 -triple spir-unknown-unknown -disable-llvm-passes -emit-llvm -o - %s | FileCheck -check-prefixes=FP64,ALL %s
// RUN: %clang_cc1 -cl-std=CL1.2 -cl-ext=-cl_khr_fp64 -triple spir-unknown-unknown -disable-llvm-passes -emit-llvm -o - %s | FileCheck -check-prefixes=NOFP64,ALL %s
typedef __attribute__((ext_vector_type(2))) float float2;
typedef __attribute__((ext_vector_type(2))) half half2;
#ifdef cl_khr_fp64
typedef __attribute__((ext_vector_type(2))) double double2;
#endif
int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
// ALL-LABEL: @test_printf_float2(
-// FP64: %conv = fpext <2 x float> %0 to <2 x double>
-// FP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x double> %conv)
+// FP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([7 x i8], [7 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x float> %0)
-// NOFP64: call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x float> %0)
+
+// NOFP64: call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([7 x i8], [7 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x float> %0)
kernel void test_printf_float2(float2 arg) {
- printf("%v2f", arg);
+ printf("%v2hlf", arg);
}
// ALL-LABEL: @test_printf_half2(
-// FP64: %conv = fpext <2 x half> %0 to <2 x double>
-// FP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x double> %conv) #2
+// FP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(2)* @.str.1, i32 0, i32 0), <2 x half> %0)
-// NOFP64: %conv = fpext <2 x half> %0 to <2 x float>
-// NOFP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x float> %conv) #2
+// NOFP64: %call = call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(2)* @.str.1, i32 0, i32 0), <2 x half> %0)
kernel void test_printf_half2(half2 arg) {
- printf("%v2f", arg);
+ printf("%v2hf", arg);
}
#ifdef cl_khr_fp64
// FP64-LABEL: @test_printf_double2(
-// FP64: call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([5 x i8], [5 x i8] addrspace(2)* @.str, i32 0, i32 0), <2 x double> %0) #2
+// FP64: call spir_func i32 (i8 addrspace(2)*, ...) @printf(i8 addrspace(2)* getelementptr inbounds ([6 x i8], [6 x i8] addrspace(2)* @.str.2, i32 0, i32 0), <2 x double> %0)
kernel void test_printf_double2(double2 arg) {
- printf("%v2f", arg);
+ printf("%v2lf", arg);
}
#endif
Index: vendor/clang/dist-release_80/test/Driver/mips-features.c
===================================================================
--- vendor/clang/dist-release_80/test/Driver/mips-features.c (revision 343795)
+++ vendor/clang/dist-release_80/test/Driver/mips-features.c (revision 343796)
@@ -1,446 +1,458 @@
// Check handling MIPS specific features options.
//
// -mabicalls
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-abicalls -mabicalls 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MABICALLS %s
// CHECK-MABICALLS: "-target-feature" "-noabicalls"
//
// -mno-abicalls
// RUN: %clang -target mips-linux-gnu -### -c %s -mabicalls -mno-abicalls 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MNOABICALLS %s
// CHECK-MNOABICALLS: "-target-feature" "+noabicalls"
//
// -mno-abicalls non-PIC N64
// RUN: %clang -target mips64-linux-gnu -### -c -fno-PIC -mno-abicalls %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MNOABICALLS-N64NPIC %s
// CHECK-MNOABICALLS-N64NPIC: "-target-feature" "+noabicalls"
//
// -mgpopt
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-gpopt -mgpopt -Wno-unsupported-gpopt 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MGPOPT-DEF-ABICALLS %s
// CHECK-MGPOPT-DEF-ABICALLS-NOT: "-mllvm" "-mgpopt"
//
// -mabicalls -mgpopt
// RUN: %clang -target mips-linux-gnu -### -c %s -mabicalls -mno-gpopt -mgpopt -Wno-unsupported-gpopt 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MGPOPT-EXPLICIT-ABICALLS %s
// CHECK-MGPOPT-EXPLICIT-ABICALLS-NOT: "-mllvm" "-mgpopt"
//
// -mno-abicalls -mgpopt
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-abicalls -mno-gpopt -mgpopt 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MGPOPT %s
// CHECK-MGPOPT: "-mllvm" "-mgpopt"
//
// -mno-abicalls -mno-gpopt
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-abicalls -mgpopt -mno-gpopt 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MNOGPOPT %s
// CHECK-MNOGPOPT-NOT: "-mllvm" "-mgpopt"
//
// -mno-abicalls
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-abicalls 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MGPOPTDEF %s
// CHECK-MGPOPTDEF: "-mllvm" "-mgpopt"
//
// -mgpopt -mno-abicalls -mlocal-sdata
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-abicalls -mno-gpopt -mgpopt -mno-local-sdata -mlocal-sdata 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MLOCALSDATA %s
// CHECK-MLOCALSDATA: "-mllvm" "-mlocal-sdata=1"
//
// -mgpopt -mno-abicalls -mno-local-sdata
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-abicalls -mno-gpopt -mgpopt -mlocal-sdata -mno-local-sdata 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MNOLOCALSDATA %s
// CHECK-MNOLOCALSDATA: "-mllvm" "-mlocal-sdata=0"
//
// -mgpopt -mno-abicalls
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-abicalls -mgpopt 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MLOCALSDATADEF %s
// CHECK-MLOCALSDATADEF-NOT: "-mllvm" "-mlocal-sdata"
//
// -mno-abicalls -mgpopt -mextern-sdata
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-abicalls -mgpopt -mno-extern-sdata -mextern-sdata 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MEXTERNSDATA %s
// CHECK-MEXTERNSDATA: "-mllvm" "-mextern-sdata=1"
//
// -mno-abicalls -mgpopt -mno-extern-sdata
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-abicalls -mgpopt -mextern-sdata -mno-extern-sdata 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MNOEXTERNSDATA %s
// CHECK-MNOEXTERNSDATA: "-mllvm" "-mextern-sdata=0"
//
// -mno-abicalls -mgpopt
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-abicalls -mgpopt 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MEXTERNSDATADEF %s
// CHECK-MEXTERNSDATADEF-NOT: "-mllvm" "-mextern-sdata"
//
// -mno-abicalls -mgpopt -membedded-data
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-abicalls -mgpopt -mno-embedded-data -membedded-data 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MEMBEDDEDDATA %s
// CHECK-MEMBEDDEDDATA: "-mllvm" "-membedded-data=1"
//
// -mno-abicalls -mgpopt -mno-embedded-data
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-abicalls -mgpopt -membedded-data -mno-embedded-data 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MNOEMBEDDEDDATA %s
// CHECK-MNOEMBEDDEDDATA: "-mllvm" "-membedded-data=0"
//
// -mno-abicalls -mgpopt
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-abicalls -mgpopt 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MEMBEDDEDDATADEF %s
// CHECK-MEMBEDDEDDATADEF-NOT: "-mllvm" "-membedded-data"
//
// MIPS64 + N64: -fno-pic -> -mno-abicalls -mgpopt
// RUN: %clang -target mips64-mti-elf -mabi=64 -### -c %s -fno-pic -mno-abicalls 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-N64-GPOPT %s
// CHECK-N64-GPOPT: "-target-feature" "+noabicalls"
// CHECK-N64-GPOPT: "-mllvm" "-mgpopt"
//
// MIPS64 + N64: -fno-pic -mno-gpopt
// RUN: %clang -target mips64-mti-elf -mabi=64 -### -c %s -fno-pic -mno-abicalls -mno-gpopt 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-N64-MNO-GPOPT %s
// CHECK-N64-MNO-GPOPT: "-target-feature" "+noabicalls"
// CHECK-N64-MNO-GPOPT-NOT: "-mllvm" "-mgpopt"
//
// MIPS64 + N64: -mgpopt (-fpic is implicit)
// RUN: %clang -target mips64-mti-linux-gnu -mabi=64 -### -c %s -mgpopt 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-N64-PIC-GPOPT %s
// CHECK-N64-PIC-GPOPT-NOT: "-mllvm" "-mgpopt"
// CHECK-N64-PIC-GPOPT: ignoring '-mgpopt' option as it cannot be used with the implicit usage of -mabicalls
//
// -mips16
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mno-mips16 -mips16 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MIPS16 %s
// CHECK-MIPS16: "-target-feature" "+mips16"
//
// -mno-mips16
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mips16 -mno-mips16 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOMIPS16 %s
// CHECK-NOMIPS16: "-target-feature" "-mips16"
//
// -mmicromips
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mno-micromips -mmicromips 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MICROMIPS %s
// CHECK-MICROMIPS: "-target-feature" "+micromips"
//
// -mno-micromips
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mmicromips -mno-micromips 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOMICROMIPS %s
// CHECK-NOMICROMIPS: "-target-feature" "-micromips"
//
// -mdsp
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mno-dsp -mdsp 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MDSP %s
// CHECK-MDSP: "-target-feature" "+dsp"
//
// -mno-dsp
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mdsp -mno-dsp 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOMDSP %s
// CHECK-NOMDSP: "-target-feature" "-dsp"
//
// -mdspr2
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mno-dspr2 -mdspr2 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MDSPR2 %s
// CHECK-MDSPR2: "-target-feature" "+dspr2"
//
// -mno-dspr2
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mdspr2 -mno-dspr2 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOMDSPR2 %s
// CHECK-NOMDSPR2: "-target-feature" "-dspr2"
//
// -mmsa
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mno-msa -mmsa 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MMSA %s
// CHECK-MMSA: "-target-feature" "+msa"
//
// -mno-msa
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mmsa -mno-msa 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOMMSA %s
// CHECK-NOMMSA: "-target-feature" "-msa"
//
// -mmt
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mno-mt -mmt 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MMT %s
// CHECK-MMT: "-target-feature" "+mt"
//
// -mno-mt
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mmt -mno-mt 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOMMT %s
// CHECK-NOMMT: "-target-feature" "-mt"
//
// -modd-spreg
// RUN: %clang -target mips-linux-gnu -### -c %s -mno-odd-spreg -modd-spreg 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MODDSPREG %s
// CHECK-MODDSPREG: "-target-feature" "-nooddspreg"
//
// -mno-odd-spreg
// RUN: %clang -target mips-linux-gnu -### -c %s -modd-spreg -mno-odd-spreg 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOMODDSPREG %s
// CHECK-NOMODDSPREG: "-target-feature" "+nooddspreg"
//
// -mfpxx
// RUN: %clang -target mips-linux-gnu -### -c %s -mfpxx 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MFPXX %s
// CHECK-MFPXX: "-target-feature" "+fpxx"
// CHECK-MFPXX: "-target-feature" "+nooddspreg"
//
// -mfpxx -modd-spreg
// RUN: %clang -target mips-linux-gnu -### -c %s -mfpxx -modd-spreg 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MFPXX-ODDSPREG %s
// CHECK-MFPXX-ODDSPREG: "-target-feature" "+fpxx"
// CHECK-MFPXX-ODDSPREG: "-target-feature" "-nooddspreg"
//
// -mfp64
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mfp32 -mfp64 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MFP64 %s
// CHECK-MFP64: "-target-feature" "+fp64"
//
// -mfp32
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mfp64 -mfp32 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOMFP64 %s
// CHECK-NOMFP64: "-target-feature" "-fp64"
//
// -mnan=2008
// RUN: %clang -target mips-linux-gnu -march=mips32r3 -### -c %s \
// RUN: -mnan=legacy -mnan=2008 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NAN2008 %s
// CHECK-NAN2008: "-target-feature" "+nan2008"
//
// -mnan=legacy
// RUN: %clang -target mips-linux-gnu -march=mips32r3 -### -c %s \
// RUN: -mnan=2008 -mnan=legacy 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NANLEGACY %s
// CHECK-NANLEGACY: "-target-feature" "-nan2008"
//
// -mabs=2008 on pre R2
// RUN: %clang -target mips-linux-gnu -march=mips32 -### -c %s \
// RUN: -mabs=2008 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-ABSLEGACY %s
//
// -mabs=2008
// RUN: %clang -target mips-linux-gnu -march=mips32r3 -### -c %s \
// RUN: -mabs=2008 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-ABS2008 %s
//
// -mabs=legacy
// RUN: %clang -target mips-linux-gnu -march=mips32r3 -### -c %s \
// RUN: -mabs=legacy 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-ABSLEGACY %s
//
// -mabs=legacy on R6
// RUN: %clang -target mips-linux-gnu -march=mips32r6 -### -c %s \
// RUN: -mabs=legacy 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-ABS2008 %s
//
// CHECK-ABSLEGACY: "-target-feature" "-abs2008"
// CHECK-ABSLEGACY-NOT: "-target-feature" "+abs2008"
// CHECK-ABS2008: "-target-feature" "+abs2008"
// CHECK-ABS2008-NOT: "-target-feature" "-abs2008"
//
// -mcompact-branches=never
// RUN: %clang -target mips-linux-gnu -march=mips32r6 -### -c %s \
// RUN: -mcompact-branches=never 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-CBNEVER %s
// CHECK-CBNEVER: "-mllvm" "-mips-compact-branches=never"
//
// -mcompact-branches=optimal
// RUN: %clang -target mips-linux-gnu -march=mips32r6 -### -c %s \
// RUN: -mcompact-branches=optimal 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-CBOPTIMAL %s
// CHECK-CBOPTIMAL: "-mllvm" "-mips-compact-branches=optimal"
//
// -mcompact-branches=always
// RUN: %clang -target mips-linux-gnu -march=mips32r6 -### -c %s \
// RUN: -mcompact-branches=always 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-CBALWAYS %s
// CHECK-CBALWAYS: "-mllvm" "-mips-compact-branches=always"
//
// -mxgot
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mno-xgot -mxgot 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-XGOT %s
// CHECK-XGOT: "-mllvm" "-mxgot"
//
// -mno-xgot
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mxgot -mno-xgot 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOXGOT %s
// CHECK-NOXGOT-NOT: "-mllvm" "-mxgot"
//
// -mldc1-sdc1
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mno-ldc1-sdc1 -mldc1-sdc1 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-LDC1SDC1 %s
// CHECK-LDC1SDC1-NOT: "-mllvm" "-mno-ldc1-sdc1"
//
// -mno-ldc1-sdc1
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mldc1-sdc1 -mno-ldc1-sdc1 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOLDC1SDC1 %s
// CHECK-NOLDC1SDC1: "-mllvm" "-mno-ldc1-sdc1"
//
// -mcheck-zero-division
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mno-check-zero-division -mcheck-zero-division 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-ZERODIV %s
// CHECK-ZERODIV-NOT: "-mllvm" "-mno-check-zero-division"
//
// -mno-check-zero-division
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -mcheck-zero-division -mno-check-zero-division 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NOZERODIV %s
// CHECK-NOZERODIV: "-mllvm" "-mno-check-zero-division"
//
// -G
// RUN: %clang -target mips-linux-gnu -### -c %s \
// RUN: -G 16 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MIPS-G %s
// CHECK-MIPS-G: "-mllvm" "-mips-ssection-threshold=16"
//
// -msoft-float (unknown vendor)
// RUN: %clang -target mips-linux-gnu -### -c %s -msoft-float 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-SOFTFLOAT %s
// CHECK-SOFTFLOAT: "-target-feature" "+soft-float"
// CHECK-SOFTFLOAT-NOT: "-target-feature" "+fpxx"
//
// -msoft-float -mfpxx (unknown vendor)
// RUN: %clang -target mips-linux-gnu -### -c %s -msoft-float -mfpxx 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-SOFTFLOAT-FPXX %s
// CHECK-SOFTFLOAT-FPXX: "-target-feature" "+soft-float"
// CHECK-SOFTFLOAT-FPXX: "-target-feature" "+fpxx"
//
// -msoft-float (MTI)
// RUN: %clang -target mips-mti-linux-gnu -### -c %s -msoft-float 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MTI-SOFTFLOAT %s
// CHECK-MTI-SOFTFLOAT: "-target-feature" "+soft-float"
// CHECK-MTI-SOFTFLOAT-NOT: "-target-feature" "+fpxx"
//
// -msoft-float -mfpxx (MTI)
// RUN: %clang -target mips-mti-linux-gnu -### -c %s -msoft-float -mfpxx 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MTI-SOFTFLOAT-FPXX %s
// CHECK-MTI-SOFTFLOAT-FPXX: "-target-feature" "+soft-float"
// CHECK-MTI-SOFTFLOAT-FPXX: "-target-feature" "+fpxx"
//
// -msoft-float (IMG)
// RUN: %clang -target mips-img-linux-gnu -### -c %s -msoft-float 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-IMG-SOFTFLOAT %s
// CHECK-IMG-SOFTFLOAT: "-target-feature" "+soft-float"
// CHECK-IMG-SOFTFLOAT-NOT: "-target-feature" "+fpxx"
//
// -msoft-float -mfpxx (IMG)
// RUN: %clang -target mips-img-linux-gnu -### -c %s -msoft-float -mfpxx 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-IMG-SOFTFLOAT-FPXX %s
// CHECK-IMG-SOFTFLOAT-FPXX: "-target-feature" "+soft-float"
// CHECK-IMG-SOFTFLOAT-FPXX: "-target-feature" "+fpxx"
//
// -msingle-float (unknown vendor)
// RUN: %clang -target mips-linux-gnu -### -c %s -msingle-float 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-SINGLEFLOAT %s
// CHECK-SINGLEFLOAT: "-target-feature" "+single-float"
// CHECK-SINGLEFLOAT-NOT: "-target-feature" "+fpxx"
//
// -msingle-float -mfpxx (unknown vendor)
// RUN: %clang -target mips-linux-gnu -### -c %s -msingle-float -mfpxx 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-SINGLEFLOAT-FPXX %s
// CHECK-SINGLEFLOAT-FPXX: "-target-feature" "+single-float"
// CHECK-SINGLEFLOAT-FPXX: "-target-feature" "+fpxx"
//
// -msingle-float (MTI)
// RUN: %clang -target mips-mti-linux-gnu -### -c %s -msingle-float 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MTI-SINGLEFLOAT %s
// CHECK-MTI-SINGLEFLOAT: "-target-feature" "+single-float"
// CHECK-MTI-SINGLEFLOAT-NOT: "-target-feature" "+fpxx"
//
// -msingle-float -mfpxx (MTI)
// RUN: %clang -target mips-mti-linux-gnu -### -c %s -msingle-float -mfpxx 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-MTI-SINGLEFLOAT-FPXX %s
// CHECK-MTI-SINGLEFLOAT-FPXX: "-target-feature" "+single-float"
// CHECK-MTI-SINGLEFLOAT-FPXX: "-target-feature" "+fpxx"
//
// -msingle-float (IMG)
// RUN: %clang -target mips-img-linux-gnu -### -c %s -msingle-float 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-IMG-SINGLEFLOAT %s
// CHECK-IMG-SINGLEFLOAT: "-target-feature" "+single-float"
// CHECK-IMG-SINGLEFLOAT-NOT: "-target-feature" "+fpxx"
//
// -msingle-float -mfpxx (IMG)
// RUN: %clang -target mips-img-linux-gnu -### -c %s -msingle-float -mfpxx 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-IMG-SINGLEFLOAT-FPXX %s
// CHECK-IMG-SINGLEFLOAT-FPXX: "-target-feature" "+single-float"
// CHECK-IMG-SINGLEFLOAT-FPXX: "-target-feature" "+fpxx"
// -mlong-call
// RUN: %clang -target mips-img-linux-gnu -### -c %s \
// RUN: -mno-abicalls -mlong-calls 2>&1 \
// RUN: | FileCheck --check-prefix=LONG-CALLS-ON %s
// RUN: %clang -target mips-img-linux-gnu -### -c %s \
// RUN: -mno-abicalls -mno-long-calls 2>&1 \
// RUN: | FileCheck --check-prefix=LONG-CALLS-OFF %s
// RUN: %clang -target mips-img-linux-gnu -### -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=LONG-CALLS-DEF %s
// RUN: %clang -target mips-img-linux-gnu -### -c %s -mlong-calls 2>&1 \
// RUN: | FileCheck --check-prefix=LONG-CALLS-DEF %s
// LONG-CALLS-ON: "-target-feature" "+long-calls"
// LONG-CALLS-OFF: "-target-feature" "-long-calls"
// LONG-CALLS-DEF-NOT: "long-calls"
//
// -mbranch-likely
// RUN: %clang -target -mips-mti-linux-gnu -### -c %s -mbranch-likely 2>&1 \
// RUN: | FileCheck --check-prefix=BRANCH-LIKELY %s
// BRANCH-LIKELY: argument unused during compilation: '-mbranch-likely'
//
// -mno-branch-likely
// RUN: %clang -target -mips-mti-linux-gnu -### -c %s -mno-branch-likely 2>&1 \
// RUN: | FileCheck --check-prefix=NO-BRANCH-LIKELY %s
// NO-BRANCH-LIKELY: argument unused during compilation: '-mno-branch-likely'
// -mindirect-jump=hazard
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
// RUN: -mindirect-jump=hazard 2>&1 \
// RUN: | FileCheck --check-prefix=INDIRECT-BH %s
// INDIRECT-BH: "-target-feature" "+use-indirect-jump-hazard"
//
// -mcrc
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
// RUN: -mno-crc -mcrc 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-CRC %s
// CHECK-CRC: "-target-feature" "+crc"
//
// -mno-crc
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
// RUN: -mcrc -mno-crc 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NO-CRC %s
// CHECK-NO-CRC: "-target-feature" "-crc"
//
// -mvirt
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
// RUN: -mno-virt -mvirt 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-VIRT %s
// CHECK-VIRT: "-target-feature" "+virt"
//
// -mno-virt
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
// RUN: -mvirt -mno-virt 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NO-VIRT %s
// CHECK-NO-VIRT: "-target-feature" "-virt"
//
// -mginv
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
// RUN: -mno-ginv -mginv 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-GINV %s
// CHECK-GINV: "-target-feature" "+ginv"
//
// -mno-ginv
// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
// RUN: -mginv -mno-ginv 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-NO-GINV %s
// CHECK-NO-GINV: "-target-feature" "-ginv"
+//
+// -mrelax-pic-calls
+// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
+// RUN: -mno-relax-pic-calls -mrelax-pic-calls 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-RELAX-PIC-CALLS %s
+// CHECK-RELAX-PIC-CALLS-NOT: "-mllvm" "-mips-jalr-reloc=0"
+//
+// -mno-relax-pic-calls
+// RUN: %clang -target mips-unknown-linux-gnu -### -c %s \
+// RUN: -mrelax-pic-calls -mno-relax-pic-calls 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-NO-RELAX-PIC-CALLS %s
+// CHECK-NO-RELAX-PIC-CALLS: "-mllvm" "-mips-jalr-reloc=0"
Index: vendor/clang/dist-release_80/test/Lexer/half-literal.cpp
===================================================================
--- vendor/clang/dist-release_80/test/Lexer/half-literal.cpp (revision 343795)
+++ vendor/clang/dist-release_80/test/Lexer/half-literal.cpp (revision 343796)
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s
+// RUN: %clang_cc1 -fsyntax-only -verify -pedantic -triple aarch64-linux-gnu %s
float a = 1.0h; // expected-error{{no matching literal operator for call to 'operator""h' with argument of type 'long double' or 'const char *', and no matching literal operator template}}
float b = 1.0H; // expected-error{{invalid suffix 'H' on floating constant}}
_Float16 c = 1.f166; // expected-error{{invalid suffix 'f166' on floating constant}}
_Float16 d = 1.f1; // expected-error{{invalid suffix 'f1' on floating constant}}
Index: vendor/clang/dist-release_80/test/PCH/leakfiles
===================================================================
--- vendor/clang/dist-release_80/test/PCH/leakfiles (nonexistent)
+++ vendor/clang/dist-release_80/test/PCH/leakfiles (revision 343796)
@@ -0,0 +1,29 @@
+// Test that compiling using a PCH doesn't leak file descriptors.
+// https://bugs.chromium.org/p/chromium/issues/detail?id=924225
+//
+// This test requires bash loops and ulimit.
+// REQUIRES: shell
+// UNSUPPORTED: win32
+//
+// Set up source files. lib/lib.h includes lots of lib*.h files in that dir.
+// client.c includes lib/lib.h, and also the individual files directly.
+//
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: cd %t
+// RUN: mkdir lib
+// RUN: for i in {1..300}; do touch lib/lib$i.h; done
+// RUN: for i in {1..300}; do echo "#include \"lib$i.h\"" >> lib/lib.h; done
+// RUN: echo "#include \"lib/lib.h\"" > client.c
+// RUN: for i in {1..300}; do echo "#include \"lib/lib$i.h\"" >> client.c; done
+//
+// We want to verify that we don't hold all the files open at the same time.
+// This is important e.g. on mac, which has a low default FD limit.
+// RUN: ulimit -n 100
+//
+// Test without PCH.
+// RUN: %clang_cc1 -fsyntax-only -Ilib/ client.c
+//
+// Test with PCH.
+// RUN: %clang_cc1 -emit-pch -o pch -Ilib/ client.c
+// RUN: %clang_cc1 -include-pch pch -Ilib/ client.c -fsyntax-only
Index: vendor/clang/dist-release_80/test/Preprocessor/init.c
===================================================================
--- vendor/clang/dist-release_80/test/Preprocessor/init.c (revision 343795)
+++ vendor/clang/dist-release_80/test/Preprocessor/init.c (revision 343796)
@@ -1,10474 +1,10190 @@
// RUN: %clang_cc1 -E -dM -x assembler-with-cpp < /dev/null | FileCheck -match-full-lines -check-prefix ASM %s
//
// ASM:#define __ASSEMBLER__ 1
//
//
// RUN: %clang_cc1 -fblocks -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix BLOCKS %s
//
// BLOCKS:#define __BLOCKS__ 1
// BLOCKS:#define __block __attribute__((__blocks__(byref)))
//
//
// RUN: %clang_cc1 -x c++ -std=c++2a -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX2A %s
//
// CXX2A:#define __GNUG__ {{.*}}
// CXX2A:#define __GXX_EXPERIMENTAL_CXX0X__ 1
// CXX2A:#define __GXX_RTTI 1
// CXX2A:#define __GXX_WEAK__ 1
// CXX2A:#define __cplusplus 201707L
// CXX2A:#define __private_extern__ extern
//
// RUN: %clang_cc1 -x c++ -std=c++1z -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX1Z %s
//
// CXX1Z:#define __GNUG__ {{.*}}
// CXX1Z:#define __GXX_EXPERIMENTAL_CXX0X__ 1
// CXX1Z:#define __GXX_RTTI 1
// CXX1Z:#define __GXX_WEAK__ 1
// CXX1Z:#define __cplusplus 201703L
// CXX1Z:#define __private_extern__ extern
//
//
// RUN: %clang_cc1 -x c++ -std=c++1y -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX1Y %s
//
// CXX1Y:#define __GNUG__ {{.*}}
// CXX1Y:#define __GXX_EXPERIMENTAL_CXX0X__ 1
// CXX1Y:#define __GXX_RTTI 1
// CXX1Y:#define __GXX_WEAK__ 1
// CXX1Y:#define __cplusplus 201402L
// CXX1Y:#define __private_extern__ extern
//
//
// RUN: %clang_cc1 -x c++ -std=c++11 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX11 %s
//
// CXX11:#define __GNUG__ {{.*}}
// CXX11:#define __GXX_EXPERIMENTAL_CXX0X__ 1
// CXX11:#define __GXX_RTTI 1
// CXX11:#define __GXX_WEAK__ 1
// CXX11:#define __cplusplus 201103L
// CXX11:#define __private_extern__ extern
//
//
// RUN: %clang_cc1 -x c++ -std=c++98 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix CXX98 %s
//
// CXX98:#define __GNUG__ {{.*}}
// CXX98:#define __GXX_RTTI 1
// CXX98:#define __GXX_WEAK__ 1
// CXX98:#define __cplusplus 199711L
// CXX98:#define __private_extern__ extern
//
//
// RUN: %clang_cc1 -fdeprecated-macro -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix DEPRECATED %s
//
// DEPRECATED:#define __DEPRECATED 1
//
//
// RUN: %clang_cc1 -std=c99 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C99 %s
//
// C99:#define __STDC_VERSION__ 199901L
// C99:#define __STRICT_ANSI__ 1
// C99-NOT: __GXX_EXPERIMENTAL_CXX0X__
// C99-NOT: __GXX_RTTI
// C99-NOT: __GXX_WEAK__
// C99-NOT: __cplusplus
//
//
// RUN: %clang_cc1 -std=c11 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C11 %s
// RUN: %clang_cc1 -std=c1x -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C11 %s
// RUN: %clang_cc1 -std=iso9899:2011 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C11 %s
// RUN: %clang_cc1 -std=iso9899:201x -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C11 %s
//
// C11:#define __STDC_UTF_16__ 1
// C11:#define __STDC_UTF_32__ 1
// C11:#define __STDC_VERSION__ 201112L
// C11:#define __STRICT_ANSI__ 1
// C11-NOT: __GXX_EXPERIMENTAL_CXX0X__
// C11-NOT: __GXX_RTTI
// C11-NOT: __GXX_WEAK__
// C11-NOT: __cplusplus
//
//
// RUN: %clang_cc1 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix COMMON %s
//
// COMMON:#define __CONSTANT_CFSTRINGS__ 1
// COMMON:#define __FINITE_MATH_ONLY__ 0
// COMMON:#define __GNUC_MINOR__ {{.*}}
// COMMON:#define __GNUC_PATCHLEVEL__ {{.*}}
// COMMON:#define __GNUC_STDC_INLINE__ 1
// COMMON:#define __GNUC__ {{.*}}
// COMMON:#define __GXX_ABI_VERSION {{.*}}
// COMMON:#define __ORDER_BIG_ENDIAN__ 4321
// COMMON:#define __ORDER_LITTLE_ENDIAN__ 1234
// COMMON:#define __ORDER_PDP_ENDIAN__ 3412
// COMMON:#define __STDC_HOSTED__ 1
// COMMON:#define __STDC__ 1
// COMMON:#define __VERSION__ {{.*}}
// COMMON:#define __clang__ 1
// COMMON:#define __clang_major__ {{[0-9]+}}
// COMMON:#define __clang_minor__ {{[0-9]+}}
// COMMON:#define __clang_patchlevel__ {{[0-9]+}}
// COMMON:#define __clang_version__ {{.*}}
// COMMON:#define __llvm__ 1
//
// RUN: %clang_cc1 -E -dM -triple=x86_64-pc-win32 < /dev/null | FileCheck -match-full-lines -check-prefix C-DEFAULT %s
// RUN: %clang_cc1 -E -dM -triple=x86_64-pc-linux-gnu < /dev/null | FileCheck -match-full-lines -check-prefix C-DEFAULT %s
// RUN: %clang_cc1 -E -dM -triple=x86_64-apple-darwin < /dev/null | FileCheck -match-full-lines -check-prefix C-DEFAULT %s
// RUN: %clang_cc1 -E -dM -triple=armv7a-apple-darwin < /dev/null | FileCheck -match-full-lines -check-prefix C-DEFAULT %s
//
// C-DEFAULT:#define __STDC_VERSION__ 201112L
//
// RUN: %clang_cc1 -ffreestanding -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix FREESTANDING %s
// FREESTANDING:#define __STDC_HOSTED__ 0
//
// RUN: %clang_cc1 -x c++ -std=gnu++2a -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX2A %s
//
// GXX2A:#define __GNUG__ {{.*}}
// GXX2A:#define __GXX_WEAK__ 1
// GXX2A:#define __cplusplus 201707L
// GXX2A:#define __private_extern__ extern
//
//
// RUN: %clang_cc1 -x c++ -std=gnu++1z -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX1Z %s
//
// GXX1Z:#define __GNUG__ {{.*}}
// GXX1Z:#define __GXX_WEAK__ 1
// GXX1Z:#define __cplusplus 201703L
// GXX1Z:#define __private_extern__ extern
//
//
// RUN: %clang_cc1 -x c++ -std=gnu++1y -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX1Y %s
//
// GXX1Y:#define __GNUG__ {{.*}}
// GXX1Y:#define __GXX_WEAK__ 1
// GXX1Y:#define __cplusplus 201402L
// GXX1Y:#define __private_extern__ extern
//
//
// RUN: %clang_cc1 -x c++ -std=gnu++11 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX11 %s
//
// GXX11:#define __GNUG__ {{.*}}
// GXX11:#define __GXX_WEAK__ 1
// GXX11:#define __cplusplus 201103L
// GXX11:#define __private_extern__ extern
//
//
// RUN: %clang_cc1 -x c++ -std=gnu++98 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GXX98 %s
//
// GXX98:#define __GNUG__ {{.*}}
// GXX98:#define __GXX_WEAK__ 1
// GXX98:#define __cplusplus 199711L
// GXX98:#define __private_extern__ extern
//
//
// RUN: %clang_cc1 -std=iso9899:199409 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix C94 %s
//
// C94:#define __STDC_VERSION__ 199409L
//
//
// RUN: %clang_cc1 -fms-extensions -triple i686-pc-win32 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix MSEXT %s
//
// MSEXT-NOT:#define __STDC__
// MSEXT:#define _INTEGRAL_MAX_BITS 64
// MSEXT-NOT:#define _NATIVE_WCHAR_T_DEFINED 1
// MSEXT-NOT:#define _WCHAR_T_DEFINED 1
//
//
// RUN: %clang_cc1 -x c++ -fms-extensions -triple i686-pc-win32 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix MSEXT-CXX %s
//
// MSEXT-CXX:#define _NATIVE_WCHAR_T_DEFINED 1
// MSEXT-CXX:#define _WCHAR_T_DEFINED 1
// MSEXT-CXX:#define __BOOL_DEFINED 1
//
//
// RUN: %clang_cc1 -x c++ -fno-wchar -fms-extensions -triple i686-pc-win32 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix MSEXT-CXX-NOWCHAR %s
//
// MSEXT-CXX-NOWCHAR-NOT:#define _NATIVE_WCHAR_T_DEFINED 1
// MSEXT-CXX-NOWCHAR-NOT:#define _WCHAR_T_DEFINED 1
// MSEXT-CXX-NOWCHAR:#define __BOOL_DEFINED 1
//
//
// RUN: %clang_cc1 -x objective-c -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix OBJC %s
//
// OBJC:#define OBJC_NEW_PROPERTIES 1
// OBJC:#define __NEXT_RUNTIME__ 1
// OBJC:#define __OBJC__ 1
//
//
// RUN: %clang_cc1 -x objective-c -fobjc-gc -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix OBJCGC %s
//
// OBJCGC:#define __OBJC_GC__ 1
//
//
// RUN: %clang_cc1 -x objective-c -fobjc-exceptions -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix NONFRAGILE %s
//
// NONFRAGILE:#define OBJC_ZEROCOST_EXCEPTIONS 1
// NONFRAGILE:#define __OBJC2__ 1
//
//
// RUN: %clang_cc1 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix O0 %s
//
// O0:#define __NO_INLINE__ 1
// O0-NOT:#define __OPTIMIZE_SIZE__
// O0-NOT:#define __OPTIMIZE__
//
//
// RUN: %clang_cc1 -fno-inline -O3 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix NO_INLINE %s
//
// NO_INLINE:#define __NO_INLINE__ 1
// NO_INLINE-NOT:#define __OPTIMIZE_SIZE__
// NO_INLINE:#define __OPTIMIZE__ 1
//
//
// RUN: %clang_cc1 -O1 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix O1 %s
//
// O1-NOT:#define __OPTIMIZE_SIZE__
// O1:#define __OPTIMIZE__ 1
//
//
// RUN: %clang_cc1 -Og -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix Og %s
//
// Og-NOT:#define __OPTIMIZE_SIZE__
// Og :#define __OPTIMIZE__ 1
//
//
// RUN: %clang_cc1 -Os -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix Os %s
//
// Os:#define __OPTIMIZE_SIZE__ 1
// Os:#define __OPTIMIZE__ 1
//
//
// RUN: %clang_cc1 -Oz -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix Oz %s
//
// Oz:#define __OPTIMIZE_SIZE__ 1
// Oz:#define __OPTIMIZE__ 1
//
//
// RUN: %clang_cc1 -fpascal-strings -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix PASCAL %s
//
// PASCAL:#define __PASCAL_STRINGS__ 1
//
//
// RUN: %clang_cc1 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix SCHAR %s
//
// SCHAR:#define __STDC__ 1
// SCHAR-NOT:#define __UNSIGNED_CHAR__
// SCHAR:#define __clang__ 1
//
// RUN: %clang_cc1 -E -dM -fwchar-type=short -fno-signed-wchar < /dev/null | FileCheck -match-full-lines -check-prefix SHORTWCHAR %s
// wchar_t is u16 for targeting Win32.
// RUN: %clang_cc1 -E -dM -fwchar-type=short -fno-signed-wchar -triple=x86_64-w64-mingw32 < /dev/null | FileCheck -match-full-lines -check-prefix SHORTWCHAR %s
// RUN: %clang_cc1 -dM -fwchar-type=short -fno-signed-wchar -triple=x86_64-unknown-windows-cygnus -E /dev/null | FileCheck -match-full-lines -check-prefix SHORTWCHAR %s
//
// SHORTWCHAR: #define __SIZEOF_WCHAR_T__ 2
// SHORTWCHAR: #define __WCHAR_MAX__ 65535
// SHORTWCHAR: #define __WCHAR_TYPE__ unsigned short
// SHORTWCHAR: #define __WCHAR_WIDTH__ 16
//
// RUN: %clang_cc1 -E -dM -fwchar-type=int -triple=i686-unknown-unknown < /dev/null | FileCheck -match-full-lines -check-prefix SHORTWCHAR2 %s
// RUN: %clang_cc1 -E -dM -fwchar-type=int -triple=x86_64-unknown-unknown < /dev/null | FileCheck -match-full-lines -check-prefix SHORTWCHAR2 %s
//
// SHORTWCHAR2: #define __SIZEOF_WCHAR_T__ 4
// SHORTWCHAR2: #define __WCHAR_WIDTH__ 32
// Other definitions vary from platform to platform
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64 %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64 %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=arm64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64 -check-prefix AARCH64-CXX %s
//
// AARCH64:#define _LP64 1
// AARCH64-NOT:#define __AARCH64EB__ 1
// AARCH64:#define __AARCH64EL__ 1
// AARCH64-NOT:#define __AARCH_BIG_ENDIAN 1
// AARCH64:#define __ARM_64BIT_STATE 1
// AARCH64:#define __ARM_ARCH 8
// AARCH64:#define __ARM_ARCH_ISA_A64 1
// AARCH64-NOT:#define __ARM_BIG_ENDIAN 1
// AARCH64:#define __BIGGEST_ALIGNMENT__ 16
// AARCH64:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// AARCH64:#define __CHAR16_TYPE__ unsigned short
// AARCH64:#define __CHAR32_TYPE__ unsigned int
// AARCH64:#define __CHAR_BIT__ 8
// AARCH64:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// AARCH64:#define __DBL_DIG__ 15
// AARCH64:#define __DBL_EPSILON__ 2.2204460492503131e-16
// AARCH64:#define __DBL_HAS_DENORM__ 1
// AARCH64:#define __DBL_HAS_INFINITY__ 1
// AARCH64:#define __DBL_HAS_QUIET_NAN__ 1
// AARCH64:#define __DBL_MANT_DIG__ 53
// AARCH64:#define __DBL_MAX_10_EXP__ 308
// AARCH64:#define __DBL_MAX_EXP__ 1024
// AARCH64:#define __DBL_MAX__ 1.7976931348623157e+308
// AARCH64:#define __DBL_MIN_10_EXP__ (-307)
// AARCH64:#define __DBL_MIN_EXP__ (-1021)
// AARCH64:#define __DBL_MIN__ 2.2250738585072014e-308
// AARCH64:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// AARCH64:#define __FLT16_DECIMAL_DIG__ 5
// AARCH64:#define __FLT16_DENORM_MIN__ 5.9604644775390625e-8F16
// AARCH64:#define __FLT16_DIG__ 3
// AARCH64:#define __FLT16_EPSILON__ 9.765625e-4F16
// AARCH64:#define __FLT16_HAS_DENORM__ 1
// AARCH64:#define __FLT16_HAS_INFINITY__ 1
// AARCH64:#define __FLT16_HAS_QUIET_NAN__ 1
// AARCH64:#define __FLT16_MANT_DIG__ 11
// AARCH64:#define __FLT16_MAX_10_EXP__ 4
// AARCH64:#define __FLT16_MAX_EXP__ 15
// AARCH64:#define __FLT16_MAX__ 6.5504e+4F16
// AARCH64:#define __FLT16_MIN_10_EXP__ (-13)
// AARCH64:#define __FLT16_MIN_EXP__ (-14)
// AARCH64:#define __FLT16_MIN__ 6.103515625e-5F16
// AARCH64:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// AARCH64:#define __FLT_DIG__ 6
// AARCH64:#define __FLT_EPSILON__ 1.19209290e-7F
// AARCH64:#define __FLT_EVAL_METHOD__ 0
// AARCH64:#define __FLT_HAS_DENORM__ 1
// AARCH64:#define __FLT_HAS_INFINITY__ 1
// AARCH64:#define __FLT_HAS_QUIET_NAN__ 1
// AARCH64:#define __FLT_MANT_DIG__ 24
// AARCH64:#define __FLT_MAX_10_EXP__ 38
// AARCH64:#define __FLT_MAX_EXP__ 128
// AARCH64:#define __FLT_MAX__ 3.40282347e+38F
// AARCH64:#define __FLT_MIN_10_EXP__ (-37)
// AARCH64:#define __FLT_MIN_EXP__ (-125)
// AARCH64:#define __FLT_MIN__ 1.17549435e-38F
// AARCH64:#define __FLT_RADIX__ 2
// AARCH64:#define __INT16_C_SUFFIX__
// AARCH64:#define __INT16_FMTd__ "hd"
// AARCH64:#define __INT16_FMTi__ "hi"
// AARCH64:#define __INT16_MAX__ 32767
// AARCH64:#define __INT16_TYPE__ short
// AARCH64:#define __INT32_C_SUFFIX__
// AARCH64:#define __INT32_FMTd__ "d"
// AARCH64:#define __INT32_FMTi__ "i"
// AARCH64:#define __INT32_MAX__ 2147483647
// AARCH64:#define __INT32_TYPE__ int
// AARCH64:#define __INT64_C_SUFFIX__ L
// AARCH64:#define __INT64_FMTd__ "ld"
// AARCH64:#define __INT64_FMTi__ "li"
// AARCH64:#define __INT64_MAX__ 9223372036854775807L
// AARCH64:#define __INT64_TYPE__ long int
// AARCH64:#define __INT8_C_SUFFIX__
// AARCH64:#define __INT8_FMTd__ "hhd"
// AARCH64:#define __INT8_FMTi__ "hhi"
// AARCH64:#define __INT8_MAX__ 127
// AARCH64:#define __INT8_TYPE__ signed char
// AARCH64:#define __INTMAX_C_SUFFIX__ L
// AARCH64:#define __INTMAX_FMTd__ "ld"
// AARCH64:#define __INTMAX_FMTi__ "li"
// AARCH64:#define __INTMAX_MAX__ 9223372036854775807L
// AARCH64:#define __INTMAX_TYPE__ long int
// AARCH64:#define __INTMAX_WIDTH__ 64
// AARCH64:#define __INTPTR_FMTd__ "ld"
// AARCH64:#define __INTPTR_FMTi__ "li"
// AARCH64:#define __INTPTR_MAX__ 9223372036854775807L
// AARCH64:#define __INTPTR_TYPE__ long int
// AARCH64:#define __INTPTR_WIDTH__ 64
// AARCH64:#define __INT_FAST16_FMTd__ "hd"
// AARCH64:#define __INT_FAST16_FMTi__ "hi"
// AARCH64:#define __INT_FAST16_MAX__ 32767
// AARCH64:#define __INT_FAST16_TYPE__ short
// AARCH64:#define __INT_FAST32_FMTd__ "d"
// AARCH64:#define __INT_FAST32_FMTi__ "i"
// AARCH64:#define __INT_FAST32_MAX__ 2147483647
// AARCH64:#define __INT_FAST32_TYPE__ int
// AARCH64:#define __INT_FAST64_FMTd__ "ld"
// AARCH64:#define __INT_FAST64_FMTi__ "li"
// AARCH64:#define __INT_FAST64_MAX__ 9223372036854775807L
// AARCH64:#define __INT_FAST64_TYPE__ long int
// AARCH64:#define __INT_FAST8_FMTd__ "hhd"
// AARCH64:#define __INT_FAST8_FMTi__ "hhi"
// AARCH64:#define __INT_FAST8_MAX__ 127
// AARCH64:#define __INT_FAST8_TYPE__ signed char
// AARCH64:#define __INT_LEAST16_FMTd__ "hd"
// AARCH64:#define __INT_LEAST16_FMTi__ "hi"
// AARCH64:#define __INT_LEAST16_MAX__ 32767
// AARCH64:#define __INT_LEAST16_TYPE__ short
// AARCH64:#define __INT_LEAST32_FMTd__ "d"
// AARCH64:#define __INT_LEAST32_FMTi__ "i"
// AARCH64:#define __INT_LEAST32_MAX__ 2147483647
// AARCH64:#define __INT_LEAST32_TYPE__ int
// AARCH64:#define __INT_LEAST64_FMTd__ "ld"
// AARCH64:#define __INT_LEAST64_FMTi__ "li"
// AARCH64:#define __INT_LEAST64_MAX__ 9223372036854775807L
// AARCH64:#define __INT_LEAST64_TYPE__ long int
// AARCH64:#define __INT_LEAST8_FMTd__ "hhd"
// AARCH64:#define __INT_LEAST8_FMTi__ "hhi"
// AARCH64:#define __INT_LEAST8_MAX__ 127
// AARCH64:#define __INT_LEAST8_TYPE__ signed char
// AARCH64:#define __INT_MAX__ 2147483647
// AARCH64:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
// AARCH64:#define __LDBL_DIG__ 33
// AARCH64:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// AARCH64:#define __LDBL_HAS_DENORM__ 1
// AARCH64:#define __LDBL_HAS_INFINITY__ 1
// AARCH64:#define __LDBL_HAS_QUIET_NAN__ 1
// AARCH64:#define __LDBL_MANT_DIG__ 113
// AARCH64:#define __LDBL_MAX_10_EXP__ 4932
// AARCH64:#define __LDBL_MAX_EXP__ 16384
// AARCH64:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
// AARCH64:#define __LDBL_MIN_10_EXP__ (-4931)
// AARCH64:#define __LDBL_MIN_EXP__ (-16381)
// AARCH64:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// AARCH64:#define __LONG_LONG_MAX__ 9223372036854775807LL
// AARCH64:#define __LONG_MAX__ 9223372036854775807L
// AARCH64:#define __LP64__ 1
// AARCH64:#define __POINTER_WIDTH__ 64
// AARCH64:#define __PTRDIFF_TYPE__ long int
// AARCH64:#define __PTRDIFF_WIDTH__ 64
// AARCH64:#define __SCHAR_MAX__ 127
// AARCH64:#define __SHRT_MAX__ 32767
// AARCH64:#define __SIG_ATOMIC_MAX__ 2147483647
// AARCH64:#define __SIG_ATOMIC_WIDTH__ 32
// AARCH64:#define __SIZEOF_DOUBLE__ 8
// AARCH64:#define __SIZEOF_FLOAT__ 4
// AARCH64:#define __SIZEOF_INT128__ 16
// AARCH64:#define __SIZEOF_INT__ 4
// AARCH64:#define __SIZEOF_LONG_DOUBLE__ 16
// AARCH64:#define __SIZEOF_LONG_LONG__ 8
// AARCH64:#define __SIZEOF_LONG__ 8
// AARCH64:#define __SIZEOF_POINTER__ 8
// AARCH64:#define __SIZEOF_PTRDIFF_T__ 8
// AARCH64:#define __SIZEOF_SHORT__ 2
// AARCH64:#define __SIZEOF_SIZE_T__ 8
// AARCH64:#define __SIZEOF_WCHAR_T__ 4
// AARCH64:#define __SIZEOF_WINT_T__ 4
// AARCH64:#define __SIZE_MAX__ 18446744073709551615UL
// AARCH64:#define __SIZE_TYPE__ long unsigned int
// AARCH64:#define __SIZE_WIDTH__ 64
// AARCH64-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL
// AARCH64:#define __UINT16_C_SUFFIX__
// AARCH64:#define __UINT16_MAX__ 65535
// AARCH64:#define __UINT16_TYPE__ unsigned short
// AARCH64:#define __UINT32_C_SUFFIX__ U
// AARCH64:#define __UINT32_MAX__ 4294967295U
// AARCH64:#define __UINT32_TYPE__ unsigned int
// AARCH64:#define __UINT64_C_SUFFIX__ UL
// AARCH64:#define __UINT64_MAX__ 18446744073709551615UL
// AARCH64:#define __UINT64_TYPE__ long unsigned int
// AARCH64:#define __UINT8_C_SUFFIX__
// AARCH64:#define __UINT8_MAX__ 255
// AARCH64:#define __UINT8_TYPE__ unsigned char
// AARCH64:#define __UINTMAX_C_SUFFIX__ UL
// AARCH64:#define __UINTMAX_MAX__ 18446744073709551615UL
// AARCH64:#define __UINTMAX_TYPE__ long unsigned int
// AARCH64:#define __UINTMAX_WIDTH__ 64
// AARCH64:#define __UINTPTR_MAX__ 18446744073709551615UL
// AARCH64:#define __UINTPTR_TYPE__ long unsigned int
// AARCH64:#define __UINTPTR_WIDTH__ 64
// AARCH64:#define __UINT_FAST16_MAX__ 65535
// AARCH64:#define __UINT_FAST16_TYPE__ unsigned short
// AARCH64:#define __UINT_FAST32_MAX__ 4294967295U
// AARCH64:#define __UINT_FAST32_TYPE__ unsigned int
// AARCH64:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// AARCH64:#define __UINT_FAST64_TYPE__ long unsigned int
// AARCH64:#define __UINT_FAST8_MAX__ 255
// AARCH64:#define __UINT_FAST8_TYPE__ unsigned char
// AARCH64:#define __UINT_LEAST16_MAX__ 65535
// AARCH64:#define __UINT_LEAST16_TYPE__ unsigned short
// AARCH64:#define __UINT_LEAST32_MAX__ 4294967295U
// AARCH64:#define __UINT_LEAST32_TYPE__ unsigned int
// AARCH64:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// AARCH64:#define __UINT_LEAST64_TYPE__ long unsigned int
// AARCH64:#define __UINT_LEAST8_MAX__ 255
// AARCH64:#define __UINT_LEAST8_TYPE__ unsigned char
// AARCH64:#define __USER_LABEL_PREFIX__
// AARCH64:#define __WCHAR_MAX__ 4294967295U
// AARCH64:#define __WCHAR_TYPE__ unsigned int
// AARCH64:#define __WCHAR_UNSIGNED__ 1
// AARCH64:#define __WCHAR_WIDTH__ 32
// AARCH64:#define __WINT_TYPE__ int
// AARCH64:#define __WINT_WIDTH__ 32
// AARCH64:#define __aarch64__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64_be-none-none < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64-BE %s
//
// AARCH64-BE:#define _LP64 1
// AARCH64-BE:#define __AARCH64EB__ 1
// AARCH64-BE-NOT:#define __AARCH64EL__ 1
// AARCH64-BE:#define __AARCH_BIG_ENDIAN 1
// AARCH64-BE:#define __ARM_64BIT_STATE 1
// AARCH64-BE:#define __ARM_ARCH 8
// AARCH64-BE:#define __ARM_ARCH_ISA_A64 1
// AARCH64-BE:#define __ARM_BIG_ENDIAN 1
// AARCH64-BE:#define __BIGGEST_ALIGNMENT__ 16
// AARCH64-BE:#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
// AARCH64-BE:#define __CHAR16_TYPE__ unsigned short
// AARCH64-BE:#define __CHAR32_TYPE__ unsigned int
// AARCH64-BE:#define __CHAR_BIT__ 8
// AARCH64-BE:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// AARCH64-BE:#define __DBL_DIG__ 15
// AARCH64-BE:#define __DBL_EPSILON__ 2.2204460492503131e-16
// AARCH64-BE:#define __DBL_HAS_DENORM__ 1
// AARCH64-BE:#define __DBL_HAS_INFINITY__ 1
// AARCH64-BE:#define __DBL_HAS_QUIET_NAN__ 1
// AARCH64-BE:#define __DBL_MANT_DIG__ 53
// AARCH64-BE:#define __DBL_MAX_10_EXP__ 308
// AARCH64-BE:#define __DBL_MAX_EXP__ 1024
// AARCH64-BE:#define __DBL_MAX__ 1.7976931348623157e+308
// AARCH64-BE:#define __DBL_MIN_10_EXP__ (-307)
// AARCH64-BE:#define __DBL_MIN_EXP__ (-1021)
// AARCH64-BE:#define __DBL_MIN__ 2.2250738585072014e-308
// AARCH64-BE:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// AARCH64-BE:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// AARCH64-BE:#define __FLT_DIG__ 6
// AARCH64-BE:#define __FLT_EPSILON__ 1.19209290e-7F
// AARCH64-BE:#define __FLT_EVAL_METHOD__ 0
// AARCH64-BE:#define __FLT_HAS_DENORM__ 1
// AARCH64-BE:#define __FLT_HAS_INFINITY__ 1
// AARCH64-BE:#define __FLT_HAS_QUIET_NAN__ 1
// AARCH64-BE:#define __FLT_MANT_DIG__ 24
// AARCH64-BE:#define __FLT_MAX_10_EXP__ 38
// AARCH64-BE:#define __FLT_MAX_EXP__ 128
// AARCH64-BE:#define __FLT_MAX__ 3.40282347e+38F
// AARCH64-BE:#define __FLT_MIN_10_EXP__ (-37)
// AARCH64-BE:#define __FLT_MIN_EXP__ (-125)
// AARCH64-BE:#define __FLT_MIN__ 1.17549435e-38F
// AARCH64-BE:#define __FLT_RADIX__ 2
// AARCH64-BE:#define __INT16_C_SUFFIX__
// AARCH64-BE:#define __INT16_FMTd__ "hd"
// AARCH64-BE:#define __INT16_FMTi__ "hi"
// AARCH64-BE:#define __INT16_MAX__ 32767
// AARCH64-BE:#define __INT16_TYPE__ short
// AARCH64-BE:#define __INT32_C_SUFFIX__
// AARCH64-BE:#define __INT32_FMTd__ "d"
// AARCH64-BE:#define __INT32_FMTi__ "i"
// AARCH64-BE:#define __INT32_MAX__ 2147483647
// AARCH64-BE:#define __INT32_TYPE__ int
// AARCH64-BE:#define __INT64_C_SUFFIX__ L
// AARCH64-BE:#define __INT64_FMTd__ "ld"
// AARCH64-BE:#define __INT64_FMTi__ "li"
// AARCH64-BE:#define __INT64_MAX__ 9223372036854775807L
// AARCH64-BE:#define __INT64_TYPE__ long int
// AARCH64-BE:#define __INT8_C_SUFFIX__
// AARCH64-BE:#define __INT8_FMTd__ "hhd"
// AARCH64-BE:#define __INT8_FMTi__ "hhi"
// AARCH64-BE:#define __INT8_MAX__ 127
// AARCH64-BE:#define __INT8_TYPE__ signed char
// AARCH64-BE:#define __INTMAX_C_SUFFIX__ L
// AARCH64-BE:#define __INTMAX_FMTd__ "ld"
// AARCH64-BE:#define __INTMAX_FMTi__ "li"
// AARCH64-BE:#define __INTMAX_MAX__ 9223372036854775807L
// AARCH64-BE:#define __INTMAX_TYPE__ long int
// AARCH64-BE:#define __INTMAX_WIDTH__ 64
// AARCH64-BE:#define __INTPTR_FMTd__ "ld"
// AARCH64-BE:#define __INTPTR_FMTi__ "li"
// AARCH64-BE:#define __INTPTR_MAX__ 9223372036854775807L
// AARCH64-BE:#define __INTPTR_TYPE__ long int
// AARCH64-BE:#define __INTPTR_WIDTH__ 64
// AARCH64-BE:#define __INT_FAST16_FMTd__ "hd"
// AARCH64-BE:#define __INT_FAST16_FMTi__ "hi"
// AARCH64-BE:#define __INT_FAST16_MAX__ 32767
// AARCH64-BE:#define __INT_FAST16_TYPE__ short
// AARCH64-BE:#define __INT_FAST32_FMTd__ "d"
// AARCH64-BE:#define __INT_FAST32_FMTi__ "i"
// AARCH64-BE:#define __INT_FAST32_MAX__ 2147483647
// AARCH64-BE:#define __INT_FAST32_TYPE__ int
// AARCH64-BE:#define __INT_FAST64_FMTd__ "ld"
// AARCH64-BE:#define __INT_FAST64_FMTi__ "li"
// AARCH64-BE:#define __INT_FAST64_MAX__ 9223372036854775807L
// AARCH64-BE:#define __INT_FAST64_TYPE__ long int
// AARCH64-BE:#define __INT_FAST8_FMTd__ "hhd"
// AARCH64-BE:#define __INT_FAST8_FMTi__ "hhi"
// AARCH64-BE:#define __INT_FAST8_MAX__ 127
// AARCH64-BE:#define __INT_FAST8_TYPE__ signed char
// AARCH64-BE:#define __INT_LEAST16_FMTd__ "hd"
// AARCH64-BE:#define __INT_LEAST16_FMTi__ "hi"
// AARCH64-BE:#define __INT_LEAST16_MAX__ 32767
// AARCH64-BE:#define __INT_LEAST16_TYPE__ short
// AARCH64-BE:#define __INT_LEAST32_FMTd__ "d"
// AARCH64-BE:#define __INT_LEAST32_FMTi__ "i"
// AARCH64-BE:#define __INT_LEAST32_MAX__ 2147483647
// AARCH64-BE:#define __INT_LEAST32_TYPE__ int
// AARCH64-BE:#define __INT_LEAST64_FMTd__ "ld"
// AARCH64-BE:#define __INT_LEAST64_FMTi__ "li"
// AARCH64-BE:#define __INT_LEAST64_MAX__ 9223372036854775807L
// AARCH64-BE:#define __INT_LEAST64_TYPE__ long int
// AARCH64-BE:#define __INT_LEAST8_FMTd__ "hhd"
// AARCH64-BE:#define __INT_LEAST8_FMTi__ "hhi"
// AARCH64-BE:#define __INT_LEAST8_MAX__ 127
// AARCH64-BE:#define __INT_LEAST8_TYPE__ signed char
// AARCH64-BE:#define __INT_MAX__ 2147483647
// AARCH64-BE:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
// AARCH64-BE:#define __LDBL_DIG__ 33
// AARCH64-BE:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// AARCH64-BE:#define __LDBL_HAS_DENORM__ 1
// AARCH64-BE:#define __LDBL_HAS_INFINITY__ 1
// AARCH64-BE:#define __LDBL_HAS_QUIET_NAN__ 1
// AARCH64-BE:#define __LDBL_MANT_DIG__ 113
// AARCH64-BE:#define __LDBL_MAX_10_EXP__ 4932
// AARCH64-BE:#define __LDBL_MAX_EXP__ 16384
// AARCH64-BE:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
// AARCH64-BE:#define __LDBL_MIN_10_EXP__ (-4931)
// AARCH64-BE:#define __LDBL_MIN_EXP__ (-16381)
// AARCH64-BE:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// AARCH64-BE:#define __LONG_LONG_MAX__ 9223372036854775807LL
// AARCH64-BE:#define __LONG_MAX__ 9223372036854775807L
// AARCH64-BE:#define __LP64__ 1
// AARCH64-BE:#define __POINTER_WIDTH__ 64
// AARCH64-BE:#define __PTRDIFF_TYPE__ long int
// AARCH64-BE:#define __PTRDIFF_WIDTH__ 64
// AARCH64-BE:#define __SCHAR_MAX__ 127
// AARCH64-BE:#define __SHRT_MAX__ 32767
// AARCH64-BE:#define __SIG_ATOMIC_MAX__ 2147483647
// AARCH64-BE:#define __SIG_ATOMIC_WIDTH__ 32
// AARCH64-BE:#define __SIZEOF_DOUBLE__ 8
// AARCH64-BE:#define __SIZEOF_FLOAT__ 4
// AARCH64-BE:#define __SIZEOF_INT128__ 16
// AARCH64-BE:#define __SIZEOF_INT__ 4
// AARCH64-BE:#define __SIZEOF_LONG_DOUBLE__ 16
// AARCH64-BE:#define __SIZEOF_LONG_LONG__ 8
// AARCH64-BE:#define __SIZEOF_LONG__ 8
// AARCH64-BE:#define __SIZEOF_POINTER__ 8
// AARCH64-BE:#define __SIZEOF_PTRDIFF_T__ 8
// AARCH64-BE:#define __SIZEOF_SHORT__ 2
// AARCH64-BE:#define __SIZEOF_SIZE_T__ 8
// AARCH64-BE:#define __SIZEOF_WCHAR_T__ 4
// AARCH64-BE:#define __SIZEOF_WINT_T__ 4
// AARCH64-BE:#define __SIZE_MAX__ 18446744073709551615UL
// AARCH64-BE:#define __SIZE_TYPE__ long unsigned int
// AARCH64-BE:#define __SIZE_WIDTH__ 64
// AARCH64-BE:#define __UINT16_C_SUFFIX__
// AARCH64-BE:#define __UINT16_MAX__ 65535
// AARCH64-BE:#define __UINT16_TYPE__ unsigned short
// AARCH64-BE:#define __UINT32_C_SUFFIX__ U
// AARCH64-BE:#define __UINT32_MAX__ 4294967295U
// AARCH64-BE:#define __UINT32_TYPE__ unsigned int
// AARCH64-BE:#define __UINT64_C_SUFFIX__ UL
// AARCH64-BE:#define __UINT64_MAX__ 18446744073709551615UL
// AARCH64-BE:#define __UINT64_TYPE__ long unsigned int
// AARCH64-BE:#define __UINT8_C_SUFFIX__
// AARCH64-BE:#define __UINT8_MAX__ 255
// AARCH64-BE:#define __UINT8_TYPE__ unsigned char
// AARCH64-BE:#define __UINTMAX_C_SUFFIX__ UL
// AARCH64-BE:#define __UINTMAX_MAX__ 18446744073709551615UL
// AARCH64-BE:#define __UINTMAX_TYPE__ long unsigned int
// AARCH64-BE:#define __UINTMAX_WIDTH__ 64
// AARCH64-BE:#define __UINTPTR_MAX__ 18446744073709551615UL
// AARCH64-BE:#define __UINTPTR_TYPE__ long unsigned int
// AARCH64-BE:#define __UINTPTR_WIDTH__ 64
// AARCH64-BE:#define __UINT_FAST16_MAX__ 65535
// AARCH64-BE:#define __UINT_FAST16_TYPE__ unsigned short
// AARCH64-BE:#define __UINT_FAST32_MAX__ 4294967295U
// AARCH64-BE:#define __UINT_FAST32_TYPE__ unsigned int
// AARCH64-BE:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// AARCH64-BE:#define __UINT_FAST64_TYPE__ long unsigned int
// AARCH64-BE:#define __UINT_FAST8_MAX__ 255
// AARCH64-BE:#define __UINT_FAST8_TYPE__ unsigned char
// AARCH64-BE:#define __UINT_LEAST16_MAX__ 65535
// AARCH64-BE:#define __UINT_LEAST16_TYPE__ unsigned short
// AARCH64-BE:#define __UINT_LEAST32_MAX__ 4294967295U
// AARCH64-BE:#define __UINT_LEAST32_TYPE__ unsigned int
// AARCH64-BE:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// AARCH64-BE:#define __UINT_LEAST64_TYPE__ long unsigned int
// AARCH64-BE:#define __UINT_LEAST8_MAX__ 255
// AARCH64-BE:#define __UINT_LEAST8_TYPE__ unsigned char
// AARCH64-BE:#define __USER_LABEL_PREFIX__
// AARCH64-BE:#define __WCHAR_MAX__ 4294967295U
// AARCH64-BE:#define __WCHAR_TYPE__ unsigned int
// AARCH64-BE:#define __WCHAR_UNSIGNED__ 1
// AARCH64-BE:#define __WCHAR_WIDTH__ 32
// AARCH64-BE:#define __WINT_TYPE__ int
// AARCH64-BE:#define __WINT_WIDTH__ 32
// AARCH64-BE:#define __aarch64__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-netbsd < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64-NETBSD %s
//
// AARCH64-NETBSD:#define _LP64 1
// AARCH64-NETBSD-NOT:#define __AARCH64EB__ 1
// AARCH64-NETBSD:#define __AARCH64EL__ 1
// AARCH64-NETBSD-NOT:#define __AARCH_BIG_ENDIAN 1
// AARCH64-NETBSD:#define __ARM_64BIT_STATE 1
// AARCH64-NETBSD:#define __ARM_ARCH 8
// AARCH64-NETBSD:#define __ARM_ARCH_ISA_A64 1
// AARCH64-NETBSD-NOT:#define __ARM_BIG_ENDIAN 1
// AARCH64-NETBSD:#define __BIGGEST_ALIGNMENT__ 16
// AARCH64-NETBSD:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// AARCH64-NETBSD:#define __CHAR16_TYPE__ unsigned short
// AARCH64-NETBSD:#define __CHAR32_TYPE__ unsigned int
// AARCH64-NETBSD:#define __CHAR_BIT__ 8
// AARCH64-NETBSD:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// AARCH64-NETBSD:#define __DBL_DIG__ 15
// AARCH64-NETBSD:#define __DBL_EPSILON__ 2.2204460492503131e-16
// AARCH64-NETBSD:#define __DBL_HAS_DENORM__ 1
// AARCH64-NETBSD:#define __DBL_HAS_INFINITY__ 1
// AARCH64-NETBSD:#define __DBL_HAS_QUIET_NAN__ 1
// AARCH64-NETBSD:#define __DBL_MANT_DIG__ 53
// AARCH64-NETBSD:#define __DBL_MAX_10_EXP__ 308
// AARCH64-NETBSD:#define __DBL_MAX_EXP__ 1024
// AARCH64-NETBSD:#define __DBL_MAX__ 1.7976931348623157e+308
// AARCH64-NETBSD:#define __DBL_MIN_10_EXP__ (-307)
// AARCH64-NETBSD:#define __DBL_MIN_EXP__ (-1021)
// AARCH64-NETBSD:#define __DBL_MIN__ 2.2250738585072014e-308
// AARCH64-NETBSD:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// AARCH64-NETBSD:#define __ELF__ 1
// AARCH64-NETBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// AARCH64-NETBSD:#define __FLT_DIG__ 6
// AARCH64-NETBSD:#define __FLT_EPSILON__ 1.19209290e-7F
// AARCH64-NETBSD:#define __FLT_EVAL_METHOD__ 0
// AARCH64-NETBSD:#define __FLT_HAS_DENORM__ 1
// AARCH64-NETBSD:#define __FLT_HAS_INFINITY__ 1
// AARCH64-NETBSD:#define __FLT_HAS_QUIET_NAN__ 1
// AARCH64-NETBSD:#define __FLT_MANT_DIG__ 24
// AARCH64-NETBSD:#define __FLT_MAX_10_EXP__ 38
// AARCH64-NETBSD:#define __FLT_MAX_EXP__ 128
// AARCH64-NETBSD:#define __FLT_MAX__ 3.40282347e+38F
// AARCH64-NETBSD:#define __FLT_MIN_10_EXP__ (-37)
// AARCH64-NETBSD:#define __FLT_MIN_EXP__ (-125)
// AARCH64-NETBSD:#define __FLT_MIN__ 1.17549435e-38F
// AARCH64-NETBSD:#define __FLT_RADIX__ 2
// AARCH64-NETBSD:#define __INT16_C_SUFFIX__
// AARCH64-NETBSD:#define __INT16_FMTd__ "hd"
// AARCH64-NETBSD:#define __INT16_FMTi__ "hi"
// AARCH64-NETBSD:#define __INT16_MAX__ 32767
// AARCH64-NETBSD:#define __INT16_TYPE__ short
// AARCH64-NETBSD:#define __INT32_C_SUFFIX__
// AARCH64-NETBSD:#define __INT32_FMTd__ "d"
// AARCH64-NETBSD:#define __INT32_FMTi__ "i"
// AARCH64-NETBSD:#define __INT32_MAX__ 2147483647
// AARCH64-NETBSD:#define __INT32_TYPE__ int
// AARCH64-NETBSD:#define __INT64_C_SUFFIX__ L
// AARCH64-NETBSD:#define __INT64_FMTd__ "ld"
// AARCH64-NETBSD:#define __INT64_FMTi__ "li"
// AARCH64-NETBSD:#define __INT64_MAX__ 9223372036854775807L
// AARCH64-NETBSD:#define __INT64_TYPE__ long int
// AARCH64-NETBSD:#define __INT8_C_SUFFIX__
// AARCH64-NETBSD:#define __INT8_FMTd__ "hhd"
// AARCH64-NETBSD:#define __INT8_FMTi__ "hhi"
// AARCH64-NETBSD:#define __INT8_MAX__ 127
// AARCH64-NETBSD:#define __INT8_TYPE__ signed char
// AARCH64-NETBSD:#define __INTMAX_C_SUFFIX__ L
// AARCH64-NETBSD:#define __INTMAX_FMTd__ "ld"
// AARCH64-NETBSD:#define __INTMAX_FMTi__ "li"
// AARCH64-NETBSD:#define __INTMAX_MAX__ 9223372036854775807L
// AARCH64-NETBSD:#define __INTMAX_TYPE__ long int
// AARCH64-NETBSD:#define __INTMAX_WIDTH__ 64
// AARCH64-NETBSD:#define __INTPTR_FMTd__ "ld"
// AARCH64-NETBSD:#define __INTPTR_FMTi__ "li"
// AARCH64-NETBSD:#define __INTPTR_MAX__ 9223372036854775807L
// AARCH64-NETBSD:#define __INTPTR_TYPE__ long int
// AARCH64-NETBSD:#define __INTPTR_WIDTH__ 64
// AARCH64-NETBSD:#define __INT_FAST16_FMTd__ "hd"
// AARCH64-NETBSD:#define __INT_FAST16_FMTi__ "hi"
// AARCH64-NETBSD:#define __INT_FAST16_MAX__ 32767
// AARCH64-NETBSD:#define __INT_FAST16_TYPE__ short
// AARCH64-NETBSD:#define __INT_FAST32_FMTd__ "d"
// AARCH64-NETBSD:#define __INT_FAST32_FMTi__ "i"
// AARCH64-NETBSD:#define __INT_FAST32_MAX__ 2147483647
// AARCH64-NETBSD:#define __INT_FAST32_TYPE__ int
// AARCH64-NETBSD:#define __INT_FAST64_FMTd__ "ld"
// AARCH64-NETBSD:#define __INT_FAST64_FMTi__ "li"
// AARCH64-NETBSD:#define __INT_FAST64_MAX__ 9223372036854775807L
// AARCH64-NETBSD:#define __INT_FAST64_TYPE__ long int
// AARCH64-NETBSD:#define __INT_FAST8_FMTd__ "hhd"
// AARCH64-NETBSD:#define __INT_FAST8_FMTi__ "hhi"
// AARCH64-NETBSD:#define __INT_FAST8_MAX__ 127
// AARCH64-NETBSD:#define __INT_FAST8_TYPE__ signed char
// AARCH64-NETBSD:#define __INT_LEAST16_FMTd__ "hd"
// AARCH64-NETBSD:#define __INT_LEAST16_FMTi__ "hi"
// AARCH64-NETBSD:#define __INT_LEAST16_MAX__ 32767
// AARCH64-NETBSD:#define __INT_LEAST16_TYPE__ short
// AARCH64-NETBSD:#define __INT_LEAST32_FMTd__ "d"
// AARCH64-NETBSD:#define __INT_LEAST32_FMTi__ "i"
// AARCH64-NETBSD:#define __INT_LEAST32_MAX__ 2147483647
// AARCH64-NETBSD:#define __INT_LEAST32_TYPE__ int
// AARCH64-NETBSD:#define __INT_LEAST64_FMTd__ "ld"
// AARCH64-NETBSD:#define __INT_LEAST64_FMTi__ "li"
// AARCH64-NETBSD:#define __INT_LEAST64_MAX__ 9223372036854775807L
// AARCH64-NETBSD:#define __INT_LEAST64_TYPE__ long int
// AARCH64-NETBSD:#define __INT_LEAST8_FMTd__ "hhd"
// AARCH64-NETBSD:#define __INT_LEAST8_FMTi__ "hhi"
// AARCH64-NETBSD:#define __INT_LEAST8_MAX__ 127
// AARCH64-NETBSD:#define __INT_LEAST8_TYPE__ signed char
// AARCH64-NETBSD:#define __INT_MAX__ 2147483647
// AARCH64-NETBSD:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
// AARCH64-NETBSD:#define __LDBL_DIG__ 33
// AARCH64-NETBSD:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// AARCH64-NETBSD:#define __LDBL_HAS_DENORM__ 1
// AARCH64-NETBSD:#define __LDBL_HAS_INFINITY__ 1
// AARCH64-NETBSD:#define __LDBL_HAS_QUIET_NAN__ 1
// AARCH64-NETBSD:#define __LDBL_MANT_DIG__ 113
// AARCH64-NETBSD:#define __LDBL_MAX_10_EXP__ 4932
// AARCH64-NETBSD:#define __LDBL_MAX_EXP__ 16384
// AARCH64-NETBSD:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
// AARCH64-NETBSD:#define __LDBL_MIN_10_EXP__ (-4931)
// AARCH64-NETBSD:#define __LDBL_MIN_EXP__ (-16381)
// AARCH64-NETBSD:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// AARCH64-NETBSD:#define __LITTLE_ENDIAN__ 1
// AARCH64-NETBSD:#define __LONG_LONG_MAX__ 9223372036854775807LL
// AARCH64-NETBSD:#define __LONG_MAX__ 9223372036854775807L
// AARCH64-NETBSD:#define __LP64__ 1
// AARCH64-NETBSD:#define __NetBSD__ 1
// AARCH64-NETBSD:#define __POINTER_WIDTH__ 64
// AARCH64-NETBSD:#define __PTRDIFF_TYPE__ long int
// AARCH64-NETBSD:#define __PTRDIFF_WIDTH__ 64
// AARCH64-NETBSD:#define __SCHAR_MAX__ 127
// AARCH64-NETBSD:#define __SHRT_MAX__ 32767
// AARCH64-NETBSD:#define __SIG_ATOMIC_MAX__ 2147483647
// AARCH64-NETBSD:#define __SIG_ATOMIC_WIDTH__ 32
// AARCH64-NETBSD:#define __SIZEOF_DOUBLE__ 8
// AARCH64-NETBSD:#define __SIZEOF_FLOAT__ 4
// AARCH64-NETBSD:#define __SIZEOF_INT__ 4
// AARCH64-NETBSD:#define __SIZEOF_LONG_DOUBLE__ 16
// AARCH64-NETBSD:#define __SIZEOF_LONG_LONG__ 8
// AARCH64-NETBSD:#define __SIZEOF_LONG__ 8
// AARCH64-NETBSD:#define __SIZEOF_POINTER__ 8
// AARCH64-NETBSD:#define __SIZEOF_PTRDIFF_T__ 8
// AARCH64-NETBSD:#define __SIZEOF_SHORT__ 2
// AARCH64-NETBSD:#define __SIZEOF_SIZE_T__ 8
// AARCH64-NETBSD:#define __SIZEOF_WCHAR_T__ 4
// AARCH64-NETBSD:#define __SIZEOF_WINT_T__ 4
// AARCH64-NETBSD:#define __SIZE_MAX__ 18446744073709551615UL
// AARCH64-NETBSD:#define __SIZE_TYPE__ long unsigned int
// AARCH64-NETBSD:#define __SIZE_WIDTH__ 64
// AARCH64-NETBSD:#define __UINT16_C_SUFFIX__
// AARCH64-NETBSD:#define __UINT16_MAX__ 65535
// AARCH64-NETBSD:#define __UINT16_TYPE__ unsigned short
// AARCH64-NETBSD:#define __UINT32_C_SUFFIX__ U
// AARCH64-NETBSD:#define __UINT32_MAX__ 4294967295U
// AARCH64-NETBSD:#define __UINT32_TYPE__ unsigned int
// AARCH64-NETBSD:#define __UINT64_C_SUFFIX__ UL
// AARCH64-NETBSD:#define __UINT64_MAX__ 18446744073709551615UL
// AARCH64-NETBSD:#define __UINT64_TYPE__ long unsigned int
// AARCH64-NETBSD:#define __UINT8_C_SUFFIX__
// AARCH64-NETBSD:#define __UINT8_MAX__ 255
// AARCH64-NETBSD:#define __UINT8_TYPE__ unsigned char
// AARCH64-NETBSD:#define __UINTMAX_C_SUFFIX__ UL
// AARCH64-NETBSD:#define __UINTMAX_MAX__ 18446744073709551615UL
// AARCH64-NETBSD:#define __UINTMAX_TYPE__ long unsigned int
// AARCH64-NETBSD:#define __UINTMAX_WIDTH__ 64
// AARCH64-NETBSD:#define __UINTPTR_MAX__ 18446744073709551615UL
// AARCH64-NETBSD:#define __UINTPTR_TYPE__ long unsigned int
// AARCH64-NETBSD:#define __UINTPTR_WIDTH__ 64
// AARCH64-NETBSD:#define __UINT_FAST16_MAX__ 65535
// AARCH64-NETBSD:#define __UINT_FAST16_TYPE__ unsigned short
// AARCH64-NETBSD:#define __UINT_FAST32_MAX__ 4294967295U
// AARCH64-NETBSD:#define __UINT_FAST32_TYPE__ unsigned int
// AARCH64-NETBSD:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// AARCH64-NETBSD:#define __UINT_FAST64_TYPE__ long unsigned int
// AARCH64-NETBSD:#define __UINT_FAST8_MAX__ 255
// AARCH64-NETBSD:#define __UINT_FAST8_TYPE__ unsigned char
// AARCH64-NETBSD:#define __UINT_LEAST16_MAX__ 65535
// AARCH64-NETBSD:#define __UINT_LEAST16_TYPE__ unsigned short
// AARCH64-NETBSD:#define __UINT_LEAST32_MAX__ 4294967295U
// AARCH64-NETBSD:#define __UINT_LEAST32_TYPE__ unsigned int
// AARCH64-NETBSD:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// AARCH64-NETBSD:#define __UINT_LEAST64_TYPE__ long unsigned int
// AARCH64-NETBSD:#define __UINT_LEAST8_MAX__ 255
// AARCH64-NETBSD:#define __UINT_LEAST8_TYPE__ unsigned char
// AARCH64-NETBSD:#define __USER_LABEL_PREFIX__
// AARCH64-NETBSD:#define __WCHAR_MAX__ 2147483647
// AARCH64-NETBSD:#define __WCHAR_TYPE__ int
// AARCH64-NETBSD:#define __WCHAR_WIDTH__ 32
// AARCH64-NETBSD:#define __WINT_TYPE__ int
// AARCH64-NETBSD:#define __WINT_WIDTH__ 32
// AARCH64-NETBSD:#define __aarch64__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-openbsd < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64-OPENBSD %s
//
// AARCH64-OPENBSD:#define _LP64 1
// AARCH64-OPENBSD-NOT:#define __AARCH64EB__ 1
// AARCH64-OPENBSD:#define __AARCH64EL__ 1
// AARCH64-OPENBSD-NOT:#define __AARCH_BIG_ENDIAN 1
// AARCH64-OPENBSD:#define __ARM_64BIT_STATE 1
// AARCH64-OPENBSD:#define __ARM_ARCH 8
// AARCH64-OPENBSD:#define __ARM_ARCH_ISA_A64 1
// AARCH64-OPENBSD-NOT:#define __ARM_BIG_ENDIAN 1
// AARCH64-OPENBSD:#define __BIGGEST_ALIGNMENT__ 16
// AARCH64-OPENBSD:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// AARCH64-OPENBSD:#define __CHAR16_TYPE__ unsigned short
// AARCH64-OPENBSD:#define __CHAR32_TYPE__ unsigned int
// AARCH64-OPENBSD:#define __CHAR_BIT__ 8
// AARCH64-OPENBSD:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// AARCH64-OPENBSD:#define __DBL_DIG__ 15
// AARCH64-OPENBSD:#define __DBL_EPSILON__ 2.2204460492503131e-16
// AARCH64-OPENBSD:#define __DBL_HAS_DENORM__ 1
// AARCH64-OPENBSD:#define __DBL_HAS_INFINITY__ 1
// AARCH64-OPENBSD:#define __DBL_HAS_QUIET_NAN__ 1
// AARCH64-OPENBSD:#define __DBL_MANT_DIG__ 53
// AARCH64-OPENBSD:#define __DBL_MAX_10_EXP__ 308
// AARCH64-OPENBSD:#define __DBL_MAX_EXP__ 1024
// AARCH64-OPENBSD:#define __DBL_MAX__ 1.7976931348623157e+308
// AARCH64-OPENBSD:#define __DBL_MIN_10_EXP__ (-307)
// AARCH64-OPENBSD:#define __DBL_MIN_EXP__ (-1021)
// AARCH64-OPENBSD:#define __DBL_MIN__ 2.2250738585072014e-308
// AARCH64-OPENBSD:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// AARCH64-OPENBSD:#define __ELF__ 1
// AARCH64-OPENBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// AARCH64-OPENBSD:#define __FLT_DIG__ 6
// AARCH64-OPENBSD:#define __FLT_EPSILON__ 1.19209290e-7F
// AARCH64-OPENBSD:#define __FLT_EVAL_METHOD__ 0
// AARCH64-OPENBSD:#define __FLT_HAS_DENORM__ 1
// AARCH64-OPENBSD:#define __FLT_HAS_INFINITY__ 1
// AARCH64-OPENBSD:#define __FLT_HAS_QUIET_NAN__ 1
// AARCH64-OPENBSD:#define __FLT_MANT_DIG__ 24
// AARCH64-OPENBSD:#define __FLT_MAX_10_EXP__ 38
// AARCH64-OPENBSD:#define __FLT_MAX_EXP__ 128
// AARCH64-OPENBSD:#define __FLT_MAX__ 3.40282347e+38F
// AARCH64-OPENBSD:#define __FLT_MIN_10_EXP__ (-37)
// AARCH64-OPENBSD:#define __FLT_MIN_EXP__ (-125)
// AARCH64-OPENBSD:#define __FLT_MIN__ 1.17549435e-38F
// AARCH64-OPENBSD:#define __FLT_RADIX__ 2
// AARCH64-OPENBSD:#define __INT16_C_SUFFIX__
// AARCH64-OPENBSD:#define __INT16_FMTd__ "hd"
// AARCH64-OPENBSD:#define __INT16_FMTi__ "hi"
// AARCH64-OPENBSD:#define __INT16_MAX__ 32767
// AARCH64-OPENBSD:#define __INT16_TYPE__ short
// AARCH64-OPENBSD:#define __INT32_C_SUFFIX__
// AARCH64-OPENBSD:#define __INT32_FMTd__ "d"
// AARCH64-OPENBSD:#define __INT32_FMTi__ "i"
// AARCH64-OPENBSD:#define __INT32_MAX__ 2147483647
// AARCH64-OPENBSD:#define __INT32_TYPE__ int
// AARCH64-OPENBSD:#define __INT64_C_SUFFIX__ LL
// AARCH64-OPENBSD:#define __INT64_FMTd__ "lld"
// AARCH64-OPENBSD:#define __INT64_FMTi__ "lli"
// AARCH64-OPENBSD:#define __INT64_MAX__ 9223372036854775807LL
// AARCH64-OPENBSD:#define __INT64_TYPE__ long long int
// AARCH64-OPENBSD:#define __INT8_C_SUFFIX__
// AARCH64-OPENBSD:#define __INT8_FMTd__ "hhd"
// AARCH64-OPENBSD:#define __INT8_FMTi__ "hhi"
// AARCH64-OPENBSD:#define __INT8_MAX__ 127
// AARCH64-OPENBSD:#define __INT8_TYPE__ signed char
// AARCH64-OPENBSD:#define __INTMAX_C_SUFFIX__ LL
// AARCH64-OPENBSD:#define __INTMAX_FMTd__ "lld"
// AARCH64-OPENBSD:#define __INTMAX_FMTi__ "lli"
// AARCH64-OPENBSD:#define __INTMAX_MAX__ 9223372036854775807LL
// AARCH64-OPENBSD:#define __INTMAX_TYPE__ long long int
// AARCH64-OPENBSD:#define __INTMAX_WIDTH__ 64
// AARCH64-OPENBSD:#define __INTPTR_FMTd__ "ld"
// AARCH64-OPENBSD:#define __INTPTR_FMTi__ "li"
// AARCH64-OPENBSD:#define __INTPTR_MAX__ 9223372036854775807L
// AARCH64-OPENBSD:#define __INTPTR_TYPE__ long int
// AARCH64-OPENBSD:#define __INTPTR_WIDTH__ 64
// AARCH64-OPENBSD:#define __INT_FAST16_FMTd__ "hd"
// AARCH64-OPENBSD:#define __INT_FAST16_FMTi__ "hi"
// AARCH64-OPENBSD:#define __INT_FAST16_MAX__ 32767
// AARCH64-OPENBSD:#define __INT_FAST16_TYPE__ short
// AARCH64-OPENBSD:#define __INT_FAST32_FMTd__ "d"
// AARCH64-OPENBSD:#define __INT_FAST32_FMTi__ "i"
// AARCH64-OPENBSD:#define __INT_FAST32_MAX__ 2147483647
// AARCH64-OPENBSD:#define __INT_FAST32_TYPE__ int
// AARCH64-OPENBSD:#define __INT_FAST64_FMTd__ "ld"
// AARCH64-OPENBSD:#define __INT_FAST64_FMTi__ "li"
// AARCH64-OPENBSD:#define __INT_FAST64_MAX__ 9223372036854775807L
// AARCH64-OPENBSD:#define __INT_FAST64_TYPE__ long int
// AARCH64-OPENBSD:#define __INT_FAST8_FMTd__ "hhd"
// AARCH64-OPENBSD:#define __INT_FAST8_FMTi__ "hhi"
// AARCH64-OPENBSD:#define __INT_FAST8_MAX__ 127
// AARCH64-OPENBSD:#define __INT_FAST8_TYPE__ signed char
// AARCH64-OPENBSD:#define __INT_LEAST16_FMTd__ "hd"
// AARCH64-OPENBSD:#define __INT_LEAST16_FMTi__ "hi"
// AARCH64-OPENBSD:#define __INT_LEAST16_MAX__ 32767
// AARCH64-OPENBSD:#define __INT_LEAST16_TYPE__ short
// AARCH64-OPENBSD:#define __INT_LEAST32_FMTd__ "d"
// AARCH64-OPENBSD:#define __INT_LEAST32_FMTi__ "i"
// AARCH64-OPENBSD:#define __INT_LEAST32_MAX__ 2147483647
// AARCH64-OPENBSD:#define __INT_LEAST32_TYPE__ int
// AARCH64-OPENBSD:#define __INT_LEAST64_FMTd__ "ld"
// AARCH64-OPENBSD:#define __INT_LEAST64_FMTi__ "li"
// AARCH64-OPENBSD:#define __INT_LEAST64_MAX__ 9223372036854775807L
// AARCH64-OPENBSD:#define __INT_LEAST64_TYPE__ long int
// AARCH64-OPENBSD:#define __INT_LEAST8_FMTd__ "hhd"
// AARCH64-OPENBSD:#define __INT_LEAST8_FMTi__ "hhi"
// AARCH64-OPENBSD:#define __INT_LEAST8_MAX__ 127
// AARCH64-OPENBSD:#define __INT_LEAST8_TYPE__ signed char
// AARCH64-OPENBSD:#define __INT_MAX__ 2147483647
// AARCH64-OPENBSD:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
// AARCH64-OPENBSD:#define __LDBL_DIG__ 33
// AARCH64-OPENBSD:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// AARCH64-OPENBSD:#define __LDBL_HAS_DENORM__ 1
// AARCH64-OPENBSD:#define __LDBL_HAS_INFINITY__ 1
// AARCH64-OPENBSD:#define __LDBL_HAS_QUIET_NAN__ 1
// AARCH64-OPENBSD:#define __LDBL_MANT_DIG__ 113
// AARCH64-OPENBSD:#define __LDBL_MAX_10_EXP__ 4932
// AARCH64-OPENBSD:#define __LDBL_MAX_EXP__ 16384
// AARCH64-OPENBSD:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
// AARCH64-OPENBSD:#define __LDBL_MIN_10_EXP__ (-4931)
// AARCH64-OPENBSD:#define __LDBL_MIN_EXP__ (-16381)
// AARCH64-OPENBSD:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// AARCH64-OPENBSD:#define __LITTLE_ENDIAN__ 1
// AARCH64-OPENBSD:#define __LONG_LONG_MAX__ 9223372036854775807LL
// AARCH64-OPENBSD:#define __LONG_MAX__ 9223372036854775807L
// AARCH64-OPENBSD:#define __LP64__ 1
// AARCH64-OPENBSD:#define __OpenBSD__ 1
// AARCH64-OPENBSD:#define __POINTER_WIDTH__ 64
// AARCH64-OPENBSD:#define __PTRDIFF_TYPE__ long int
// AARCH64-OPENBSD:#define __PTRDIFF_WIDTH__ 64
// AARCH64-OPENBSD:#define __SCHAR_MAX__ 127
// AARCH64-OPENBSD:#define __SHRT_MAX__ 32767
// AARCH64-OPENBSD:#define __SIG_ATOMIC_MAX__ 2147483647
// AARCH64-OPENBSD:#define __SIG_ATOMIC_WIDTH__ 32
// AARCH64-OPENBSD:#define __SIZEOF_DOUBLE__ 8
// AARCH64-OPENBSD:#define __SIZEOF_FLOAT__ 4
// AARCH64-OPENBSD:#define __SIZEOF_INT__ 4
// AARCH64-OPENBSD:#define __SIZEOF_LONG_DOUBLE__ 16
// AARCH64-OPENBSD:#define __SIZEOF_LONG_LONG__ 8
// AARCH64-OPENBSD:#define __SIZEOF_LONG__ 8
// AARCH64-OPENBSD:#define __SIZEOF_POINTER__ 8
// AARCH64-OPENBSD:#define __SIZEOF_PTRDIFF_T__ 8
// AARCH64-OPENBSD:#define __SIZEOF_SHORT__ 2
// AARCH64-OPENBSD:#define __SIZEOF_SIZE_T__ 8
// AARCH64-OPENBSD:#define __SIZEOF_WCHAR_T__ 4
// AARCH64-OPENBSD:#define __SIZEOF_WINT_T__ 4
// AARCH64-OPENBSD:#define __SIZE_MAX__ 18446744073709551615UL
// AARCH64-OPENBSD:#define __SIZE_TYPE__ long unsigned int
// AARCH64-OPENBSD:#define __SIZE_WIDTH__ 64
// AARCH64-OPENBSD:#define __UINT16_C_SUFFIX__
// AARCH64-OPENBSD:#define __UINT16_MAX__ 65535
// AARCH64-OPENBSD:#define __UINT16_TYPE__ unsigned short
// AARCH64-OPENBSD:#define __UINT32_C_SUFFIX__ U
// AARCH64-OPENBSD:#define __UINT32_MAX__ 4294967295U
// AARCH64-OPENBSD:#define __UINT32_TYPE__ unsigned int
// AARCH64-OPENBSD:#define __UINT64_C_SUFFIX__ ULL
// AARCH64-OPENBSD:#define __UINT64_MAX__ 18446744073709551615ULL
// AARCH64-OPENBSD:#define __UINT64_TYPE__ long long unsigned int
// AARCH64-OPENBSD:#define __UINT8_C_SUFFIX__
// AARCH64-OPENBSD:#define __UINT8_MAX__ 255
// AARCH64-OPENBSD:#define __UINT8_TYPE__ unsigned char
// AARCH64-OPENBSD:#define __UINTMAX_C_SUFFIX__ ULL
// AARCH64-OPENBSD:#define __UINTMAX_MAX__ 18446744073709551615ULL
// AARCH64-OPENBSD:#define __UINTMAX_TYPE__ long long unsigned int
// AARCH64-OPENBSD:#define __UINTMAX_WIDTH__ 64
// AARCH64-OPENBSD:#define __UINTPTR_MAX__ 18446744073709551615UL
// AARCH64-OPENBSD:#define __UINTPTR_TYPE__ long unsigned int
// AARCH64-OPENBSD:#define __UINTPTR_WIDTH__ 64
// AARCH64-OPENBSD:#define __UINT_FAST16_MAX__ 65535
// AARCH64-OPENBSD:#define __UINT_FAST16_TYPE__ unsigned short
// AARCH64-OPENBSD:#define __UINT_FAST32_MAX__ 4294967295U
// AARCH64-OPENBSD:#define __UINT_FAST32_TYPE__ unsigned int
// AARCH64-OPENBSD:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// AARCH64-OPENBSD:#define __UINT_FAST64_TYPE__ long unsigned int
// AARCH64-OPENBSD:#define __UINT_FAST8_MAX__ 255
// AARCH64-OPENBSD:#define __UINT_FAST8_TYPE__ unsigned char
// AARCH64-OPENBSD:#define __UINT_LEAST16_MAX__ 65535
// AARCH64-OPENBSD:#define __UINT_LEAST16_TYPE__ unsigned short
// AARCH64-OPENBSD:#define __UINT_LEAST32_MAX__ 4294967295U
// AARCH64-OPENBSD:#define __UINT_LEAST32_TYPE__ unsigned int
// AARCH64-OPENBSD:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// AARCH64-OPENBSD:#define __UINT_LEAST64_TYPE__ long unsigned int
// AARCH64-OPENBSD:#define __UINT_LEAST8_MAX__ 255
// AARCH64-OPENBSD:#define __UINT_LEAST8_TYPE__ unsigned char
// AARCH64-OPENBSD:#define __USER_LABEL_PREFIX__
// AARCH64-OPENBSD:#define __WCHAR_MAX__ 2147483647
// AARCH64-OPENBSD:#define __WCHAR_TYPE__ int
// AARCH64-OPENBSD:#define __WCHAR_WIDTH__ 32
// AARCH64-OPENBSD:#define __WINT_TYPE__ int
// AARCH64-OPENBSD:#define __WINT_WIDTH__ 32
// AARCH64-OPENBSD:#define __aarch64__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-freebsd11 < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64-FREEBSD %s
//
// AARCH64-FREEBSD:#define _LP64 1
// AARCH64-FREEBSD-NOT:#define __AARCH64EB__ 1
// AARCH64-FREEBSD:#define __AARCH64EL__ 1
// AARCH64-FREEBSD-NOT:#define __AARCH_BIG_ENDIAN 1
// AARCH64-FREEBSD:#define __ARM_64BIT_STATE 1
// AARCH64-FREEBSD:#define __ARM_ARCH 8
// AARCH64-FREEBSD:#define __ARM_ARCH_ISA_A64 1
// AARCH64-FREEBSD-NOT:#define __ARM_BIG_ENDIAN 1
// AARCH64-FREEBSD:#define __BIGGEST_ALIGNMENT__ 16
// AARCH64-FREEBSD:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// AARCH64-FREEBSD:#define __CHAR16_TYPE__ unsigned short
// AARCH64-FREEBSD:#define __CHAR32_TYPE__ unsigned int
// AARCH64-FREEBSD:#define __CHAR_BIT__ 8
// AARCH64-FREEBSD:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// AARCH64-FREEBSD:#define __DBL_DIG__ 15
// AARCH64-FREEBSD:#define __DBL_EPSILON__ 2.2204460492503131e-16
// AARCH64-FREEBSD:#define __DBL_HAS_DENORM__ 1
// AARCH64-FREEBSD:#define __DBL_HAS_INFINITY__ 1
// AARCH64-FREEBSD:#define __DBL_HAS_QUIET_NAN__ 1
// AARCH64-FREEBSD:#define __DBL_MANT_DIG__ 53
// AARCH64-FREEBSD:#define __DBL_MAX_10_EXP__ 308
// AARCH64-FREEBSD:#define __DBL_MAX_EXP__ 1024
// AARCH64-FREEBSD:#define __DBL_MAX__ 1.7976931348623157e+308
// AARCH64-FREEBSD:#define __DBL_MIN_10_EXP__ (-307)
// AARCH64-FREEBSD:#define __DBL_MIN_EXP__ (-1021)
// AARCH64-FREEBSD:#define __DBL_MIN__ 2.2250738585072014e-308
// AARCH64-FREEBSD:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// AARCH64-FREEBSD:#define __ELF__ 1
// AARCH64-FREEBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// AARCH64-FREEBSD:#define __FLT_DIG__ 6
// AARCH64-FREEBSD:#define __FLT_EPSILON__ 1.19209290e-7F
// AARCH64-FREEBSD:#define __FLT_EVAL_METHOD__ 0
// AARCH64-FREEBSD:#define __FLT_HAS_DENORM__ 1
// AARCH64-FREEBSD:#define __FLT_HAS_INFINITY__ 1
// AARCH64-FREEBSD:#define __FLT_HAS_QUIET_NAN__ 1
// AARCH64-FREEBSD:#define __FLT_MANT_DIG__ 24
// AARCH64-FREEBSD:#define __FLT_MAX_10_EXP__ 38
// AARCH64-FREEBSD:#define __FLT_MAX_EXP__ 128
// AARCH64-FREEBSD:#define __FLT_MAX__ 3.40282347e+38F
// AARCH64-FREEBSD:#define __FLT_MIN_10_EXP__ (-37)
// AARCH64-FREEBSD:#define __FLT_MIN_EXP__ (-125)
// AARCH64-FREEBSD:#define __FLT_MIN__ 1.17549435e-38F
// AARCH64-FREEBSD:#define __FLT_RADIX__ 2
// AARCH64-FREEBSD:#define __FreeBSD__ 11
// AARCH64-FREEBSD:#define __INT16_C_SUFFIX__
// AARCH64-FREEBSD:#define __INT16_FMTd__ "hd"
// AARCH64-FREEBSD:#define __INT16_FMTi__ "hi"
// AARCH64-FREEBSD:#define __INT16_MAX__ 32767
// AARCH64-FREEBSD:#define __INT16_TYPE__ short
// AARCH64-FREEBSD:#define __INT32_C_SUFFIX__
// AARCH64-FREEBSD:#define __INT32_FMTd__ "d"
// AARCH64-FREEBSD:#define __INT32_FMTi__ "i"
// AARCH64-FREEBSD:#define __INT32_MAX__ 2147483647
// AARCH64-FREEBSD:#define __INT32_TYPE__ int
// AARCH64-FREEBSD:#define __INT64_C_SUFFIX__ L
// AARCH64-FREEBSD:#define __INT64_FMTd__ "ld"
// AARCH64-FREEBSD:#define __INT64_FMTi__ "li"
// AARCH64-FREEBSD:#define __INT64_MAX__ 9223372036854775807L
// AARCH64-FREEBSD:#define __INT64_TYPE__ long int
// AARCH64-FREEBSD:#define __INT8_C_SUFFIX__
// AARCH64-FREEBSD:#define __INT8_FMTd__ "hhd"
// AARCH64-FREEBSD:#define __INT8_FMTi__ "hhi"
// AARCH64-FREEBSD:#define __INT8_MAX__ 127
// AARCH64-FREEBSD:#define __INT8_TYPE__ signed char
// AARCH64-FREEBSD:#define __INTMAX_C_SUFFIX__ L
// AARCH64-FREEBSD:#define __INTMAX_FMTd__ "ld"
// AARCH64-FREEBSD:#define __INTMAX_FMTi__ "li"
// AARCH64-FREEBSD:#define __INTMAX_MAX__ 9223372036854775807L
// AARCH64-FREEBSD:#define __INTMAX_TYPE__ long int
// AARCH64-FREEBSD:#define __INTMAX_WIDTH__ 64
// AARCH64-FREEBSD:#define __INTPTR_FMTd__ "ld"
// AARCH64-FREEBSD:#define __INTPTR_FMTi__ "li"
// AARCH64-FREEBSD:#define __INTPTR_MAX__ 9223372036854775807L
// AARCH64-FREEBSD:#define __INTPTR_TYPE__ long int
// AARCH64-FREEBSD:#define __INTPTR_WIDTH__ 64
// AARCH64-FREEBSD:#define __INT_FAST16_FMTd__ "hd"
// AARCH64-FREEBSD:#define __INT_FAST16_FMTi__ "hi"
// AARCH64-FREEBSD:#define __INT_FAST16_MAX__ 32767
// AARCH64-FREEBSD:#define __INT_FAST16_TYPE__ short
// AARCH64-FREEBSD:#define __INT_FAST32_FMTd__ "d"
// AARCH64-FREEBSD:#define __INT_FAST32_FMTi__ "i"
// AARCH64-FREEBSD:#define __INT_FAST32_MAX__ 2147483647
// AARCH64-FREEBSD:#define __INT_FAST32_TYPE__ int
// AARCH64-FREEBSD:#define __INT_FAST64_FMTd__ "ld"
// AARCH64-FREEBSD:#define __INT_FAST64_FMTi__ "li"
// AARCH64-FREEBSD:#define __INT_FAST64_MAX__ 9223372036854775807L
// AARCH64-FREEBSD:#define __INT_FAST64_TYPE__ long int
// AARCH64-FREEBSD:#define __INT_FAST8_FMTd__ "hhd"
// AARCH64-FREEBSD:#define __INT_FAST8_FMTi__ "hhi"
// AARCH64-FREEBSD:#define __INT_FAST8_MAX__ 127
// AARCH64-FREEBSD:#define __INT_FAST8_TYPE__ signed char
// AARCH64-FREEBSD:#define __INT_LEAST16_FMTd__ "hd"
// AARCH64-FREEBSD:#define __INT_LEAST16_FMTi__ "hi"
// AARCH64-FREEBSD:#define __INT_LEAST16_MAX__ 32767
// AARCH64-FREEBSD:#define __INT_LEAST16_TYPE__ short
// AARCH64-FREEBSD:#define __INT_LEAST32_FMTd__ "d"
// AARCH64-FREEBSD:#define __INT_LEAST32_FMTi__ "i"
// AARCH64-FREEBSD:#define __INT_LEAST32_MAX__ 2147483647
// AARCH64-FREEBSD:#define __INT_LEAST32_TYPE__ int
// AARCH64-FREEBSD:#define __INT_LEAST64_FMTd__ "ld"
// AARCH64-FREEBSD:#define __INT_LEAST64_FMTi__ "li"
// AARCH64-FREEBSD:#define __INT_LEAST64_MAX__ 9223372036854775807L
// AARCH64-FREEBSD:#define __INT_LEAST64_TYPE__ long int
// AARCH64-FREEBSD:#define __INT_LEAST8_FMTd__ "hhd"
// AARCH64-FREEBSD:#define __INT_LEAST8_FMTi__ "hhi"
// AARCH64-FREEBSD:#define __INT_LEAST8_MAX__ 127
// AARCH64-FREEBSD:#define __INT_LEAST8_TYPE__ signed char
// AARCH64-FREEBSD:#define __INT_MAX__ 2147483647
// AARCH64-FREEBSD:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
// AARCH64-FREEBSD:#define __LDBL_DIG__ 33
// AARCH64-FREEBSD:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// AARCH64-FREEBSD:#define __LDBL_HAS_DENORM__ 1
// AARCH64-FREEBSD:#define __LDBL_HAS_INFINITY__ 1
// AARCH64-FREEBSD:#define __LDBL_HAS_QUIET_NAN__ 1
// AARCH64-FREEBSD:#define __LDBL_MANT_DIG__ 113
// AARCH64-FREEBSD:#define __LDBL_MAX_10_EXP__ 4932
// AARCH64-FREEBSD:#define __LDBL_MAX_EXP__ 16384
// AARCH64-FREEBSD:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
// AARCH64-FREEBSD:#define __LDBL_MIN_10_EXP__ (-4931)
// AARCH64-FREEBSD:#define __LDBL_MIN_EXP__ (-16381)
// AARCH64-FREEBSD:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// AARCH64-FREEBSD:#define __LITTLE_ENDIAN__ 1
// AARCH64-FREEBSD:#define __LONG_LONG_MAX__ 9223372036854775807LL
// AARCH64-FREEBSD:#define __LONG_MAX__ 9223372036854775807L
// AARCH64-FREEBSD:#define __LP64__ 1
// AARCH64-FREEBSD:#define __POINTER_WIDTH__ 64
// AARCH64-FREEBSD:#define __PTRDIFF_TYPE__ long int
// AARCH64-FREEBSD:#define __PTRDIFF_WIDTH__ 64
// AARCH64-FREEBSD:#define __SCHAR_MAX__ 127
// AARCH64-FREEBSD:#define __SHRT_MAX__ 32767
// AARCH64-FREEBSD:#define __SIG_ATOMIC_MAX__ 2147483647
// AARCH64-FREEBSD:#define __SIG_ATOMIC_WIDTH__ 32
// AARCH64-FREEBSD:#define __SIZEOF_DOUBLE__ 8
// AARCH64-FREEBSD:#define __SIZEOF_FLOAT__ 4
// AARCH64-FREEBSD:#define __SIZEOF_INT128__ 16
// AARCH64-FREEBSD:#define __SIZEOF_INT__ 4
// AARCH64-FREEBSD:#define __SIZEOF_LONG_DOUBLE__ 16
// AARCH64-FREEBSD:#define __SIZEOF_LONG_LONG__ 8
// AARCH64-FREEBSD:#define __SIZEOF_LONG__ 8
// AARCH64-FREEBSD:#define __SIZEOF_POINTER__ 8
// AARCH64-FREEBSD:#define __SIZEOF_PTRDIFF_T__ 8
// AARCH64-FREEBSD:#define __SIZEOF_SHORT__ 2
// AARCH64-FREEBSD:#define __SIZEOF_SIZE_T__ 8
// AARCH64-FREEBSD:#define __SIZEOF_WCHAR_T__ 4
// AARCH64-FREEBSD:#define __SIZEOF_WINT_T__ 4
// AARCH64-FREEBSD:#define __SIZE_MAX__ 18446744073709551615UL
// AARCH64-FREEBSD:#define __SIZE_TYPE__ long unsigned int
// AARCH64-FREEBSD:#define __SIZE_WIDTH__ 64
// AARCH64-FREEBSD:#define __UINT16_C_SUFFIX__
// AARCH64-FREEBSD:#define __UINT16_MAX__ 65535
// AARCH64-FREEBSD:#define __UINT16_TYPE__ unsigned short
// AARCH64-FREEBSD:#define __UINT32_C_SUFFIX__ U
// AARCH64-FREEBSD:#define __UINT32_MAX__ 4294967295U
// AARCH64-FREEBSD:#define __UINT32_TYPE__ unsigned int
// AARCH64-FREEBSD:#define __UINT64_C_SUFFIX__ UL
// AARCH64-FREEBSD:#define __UINT64_MAX__ 18446744073709551615UL
// AARCH64-FREEBSD:#define __UINT64_TYPE__ long unsigned int
// AARCH64-FREEBSD:#define __UINT8_C_SUFFIX__
// AARCH64-FREEBSD:#define __UINT8_MAX__ 255
// AARCH64-FREEBSD:#define __UINT8_TYPE__ unsigned char
// AARCH64-FREEBSD:#define __UINTMAX_C_SUFFIX__ UL
// AARCH64-FREEBSD:#define __UINTMAX_MAX__ 18446744073709551615UL
// AARCH64-FREEBSD:#define __UINTMAX_TYPE__ long unsigned int
// AARCH64-FREEBSD:#define __UINTMAX_WIDTH__ 64
// AARCH64-FREEBSD:#define __UINTPTR_MAX__ 18446744073709551615UL
// AARCH64-FREEBSD:#define __UINTPTR_TYPE__ long unsigned int
// AARCH64-FREEBSD:#define __UINTPTR_WIDTH__ 64
// AARCH64-FREEBSD:#define __UINT_FAST16_MAX__ 65535
// AARCH64-FREEBSD:#define __UINT_FAST16_TYPE__ unsigned short
// AARCH64-FREEBSD:#define __UINT_FAST32_MAX__ 4294967295U
// AARCH64-FREEBSD:#define __UINT_FAST32_TYPE__ unsigned int
// AARCH64-FREEBSD:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// AARCH64-FREEBSD:#define __UINT_FAST64_TYPE__ long unsigned int
// AARCH64-FREEBSD:#define __UINT_FAST8_MAX__ 255
// AARCH64-FREEBSD:#define __UINT_FAST8_TYPE__ unsigned char
// AARCH64-FREEBSD:#define __UINT_LEAST16_MAX__ 65535
// AARCH64-FREEBSD:#define __UINT_LEAST16_TYPE__ unsigned short
// AARCH64-FREEBSD:#define __UINT_LEAST32_MAX__ 4294967295U
// AARCH64-FREEBSD:#define __UINT_LEAST32_TYPE__ unsigned int
// AARCH64-FREEBSD:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// AARCH64-FREEBSD:#define __UINT_LEAST64_TYPE__ long unsigned int
// AARCH64-FREEBSD:#define __UINT_LEAST8_MAX__ 255
// AARCH64-FREEBSD:#define __UINT_LEAST8_TYPE__ unsigned char
// AARCH64-FREEBSD:#define __USER_LABEL_PREFIX__
// AARCH64-FREEBSD:#define __WCHAR_MAX__ 4294967295U
// AARCH64-FREEBSD:#define __WCHAR_TYPE__ unsigned int
// AARCH64-FREEBSD:#define __WCHAR_UNSIGNED__ 1
// AARCH64-FREEBSD:#define __WCHAR_WIDTH__ 32
// AARCH64-FREEBSD:#define __WINT_MAX__ 2147483647
// AARCH64-FREEBSD:#define __WINT_TYPE__ int
// AARCH64-FREEBSD:#define __WINT_WIDTH__ 32
// AARCH64-FREEBSD:#define __aarch64__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-apple-ios7.0 < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64-DARWIN %s
//
// AARCH64-DARWIN: #define _LP64 1
// AARCH64-DARWIN-NOT: #define __AARCH64EB__ 1
// AARCH64-DARWIN: #define __AARCH64EL__ 1
// AARCH64-DARWIN-NOT: #define __AARCH_BIG_ENDIAN 1
// AARCH64-DARWIN: #define __ARM_64BIT_STATE 1
// AARCH64-DARWIN: #define __ARM_ARCH 8
// AARCH64-DARWIN: #define __ARM_ARCH_ISA_A64 1
// AARCH64-DARWIN-NOT: #define __ARM_BIG_ENDIAN 1
// AARCH64-DARWIN: #define __BIGGEST_ALIGNMENT__ 8
// AARCH64-DARWIN: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// AARCH64-DARWIN: #define __CHAR16_TYPE__ unsigned short
// AARCH64-DARWIN: #define __CHAR32_TYPE__ unsigned int
// AARCH64-DARWIN: #define __CHAR_BIT__ 8
// AARCH64-DARWIN: #define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// AARCH64-DARWIN: #define __DBL_DIG__ 15
// AARCH64-DARWIN: #define __DBL_EPSILON__ 2.2204460492503131e-16
// AARCH64-DARWIN: #define __DBL_HAS_DENORM__ 1
// AARCH64-DARWIN: #define __DBL_HAS_INFINITY__ 1
// AARCH64-DARWIN: #define __DBL_HAS_QUIET_NAN__ 1
// AARCH64-DARWIN: #define __DBL_MANT_DIG__ 53
// AARCH64-DARWIN: #define __DBL_MAX_10_EXP__ 308
// AARCH64-DARWIN: #define __DBL_MAX_EXP__ 1024
// AARCH64-DARWIN: #define __DBL_MAX__ 1.7976931348623157e+308
// AARCH64-DARWIN: #define __DBL_MIN_10_EXP__ (-307)
// AARCH64-DARWIN: #define __DBL_MIN_EXP__ (-1021)
// AARCH64-DARWIN: #define __DBL_MIN__ 2.2250738585072014e-308
// AARCH64-DARWIN: #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// AARCH64-DARWIN: #define __FLT_DENORM_MIN__ 1.40129846e-45F
// AARCH64-DARWIN: #define __FLT_DIG__ 6
// AARCH64-DARWIN: #define __FLT_EPSILON__ 1.19209290e-7F
// AARCH64-DARWIN: #define __FLT_EVAL_METHOD__ 0
// AARCH64-DARWIN: #define __FLT_HAS_DENORM__ 1
// AARCH64-DARWIN: #define __FLT_HAS_INFINITY__ 1
// AARCH64-DARWIN: #define __FLT_HAS_QUIET_NAN__ 1
// AARCH64-DARWIN: #define __FLT_MANT_DIG__ 24
// AARCH64-DARWIN: #define __FLT_MAX_10_EXP__ 38
// AARCH64-DARWIN: #define __FLT_MAX_EXP__ 128
// AARCH64-DARWIN: #define __FLT_MAX__ 3.40282347e+38F
// AARCH64-DARWIN: #define __FLT_MIN_10_EXP__ (-37)
// AARCH64-DARWIN: #define __FLT_MIN_EXP__ (-125)
// AARCH64-DARWIN: #define __FLT_MIN__ 1.17549435e-38F
// AARCH64-DARWIN: #define __FLT_RADIX__ 2
// AARCH64-DARWIN: #define __INT16_C_SUFFIX__
// AARCH64-DARWIN: #define __INT16_FMTd__ "hd"
// AARCH64-DARWIN: #define __INT16_FMTi__ "hi"
// AARCH64-DARWIN: #define __INT16_MAX__ 32767
// AARCH64-DARWIN: #define __INT16_TYPE__ short
// AARCH64-DARWIN: #define __INT32_C_SUFFIX__
// AARCH64-DARWIN: #define __INT32_FMTd__ "d"
// AARCH64-DARWIN: #define __INT32_FMTi__ "i"
// AARCH64-DARWIN: #define __INT32_MAX__ 2147483647
// AARCH64-DARWIN: #define __INT32_TYPE__ int
// AARCH64-DARWIN: #define __INT64_C_SUFFIX__ LL
// AARCH64-DARWIN: #define __INT64_FMTd__ "lld"
// AARCH64-DARWIN: #define __INT64_FMTi__ "lli"
// AARCH64-DARWIN: #define __INT64_MAX__ 9223372036854775807LL
// AARCH64-DARWIN: #define __INT64_TYPE__ long long int
// AARCH64-DARWIN: #define __INT8_C_SUFFIX__
// AARCH64-DARWIN: #define __INT8_FMTd__ "hhd"
// AARCH64-DARWIN: #define __INT8_FMTi__ "hhi"
// AARCH64-DARWIN: #define __INT8_MAX__ 127
// AARCH64-DARWIN: #define __INT8_TYPE__ signed char
// AARCH64-DARWIN: #define __INTMAX_C_SUFFIX__ L
// AARCH64-DARWIN: #define __INTMAX_FMTd__ "ld"
// AARCH64-DARWIN: #define __INTMAX_FMTi__ "li"
// AARCH64-DARWIN: #define __INTMAX_MAX__ 9223372036854775807L
// AARCH64-DARWIN: #define __INTMAX_TYPE__ long int
// AARCH64-DARWIN: #define __INTMAX_WIDTH__ 64
// AARCH64-DARWIN: #define __INTPTR_FMTd__ "ld"
// AARCH64-DARWIN: #define __INTPTR_FMTi__ "li"
// AARCH64-DARWIN: #define __INTPTR_MAX__ 9223372036854775807L
// AARCH64-DARWIN: #define __INTPTR_TYPE__ long int
// AARCH64-DARWIN: #define __INTPTR_WIDTH__ 64
// AARCH64-DARWIN: #define __INT_FAST16_FMTd__ "hd"
// AARCH64-DARWIN: #define __INT_FAST16_FMTi__ "hi"
// AARCH64-DARWIN: #define __INT_FAST16_MAX__ 32767
// AARCH64-DARWIN: #define __INT_FAST16_TYPE__ short
// AARCH64-DARWIN: #define __INT_FAST32_FMTd__ "d"
// AARCH64-DARWIN: #define __INT_FAST32_FMTi__ "i"
// AARCH64-DARWIN: #define __INT_FAST32_MAX__ 2147483647
// AARCH64-DARWIN: #define __INT_FAST32_TYPE__ int
// AARCH64-DARWIN: #define __INT_FAST64_FMTd__ "lld"
// AARCH64-DARWIN: #define __INT_FAST64_FMTi__ "lli"
// AARCH64-DARWIN: #define __INT_FAST64_MAX__ 9223372036854775807LL
// AARCH64-DARWIN: #define __INT_FAST64_TYPE__ long long int
// AARCH64-DARWIN: #define __INT_FAST8_FMTd__ "hhd"
// AARCH64-DARWIN: #define __INT_FAST8_FMTi__ "hhi"
// AARCH64-DARWIN: #define __INT_FAST8_MAX__ 127
// AARCH64-DARWIN: #define __INT_FAST8_TYPE__ signed char
// AARCH64-DARWIN: #define __INT_LEAST16_FMTd__ "hd"
// AARCH64-DARWIN: #define __INT_LEAST16_FMTi__ "hi"
// AARCH64-DARWIN: #define __INT_LEAST16_MAX__ 32767
// AARCH64-DARWIN: #define __INT_LEAST16_TYPE__ short
// AARCH64-DARWIN: #define __INT_LEAST32_FMTd__ "d"
// AARCH64-DARWIN: #define __INT_LEAST32_FMTi__ "i"
// AARCH64-DARWIN: #define __INT_LEAST32_MAX__ 2147483647
// AARCH64-DARWIN: #define __INT_LEAST32_TYPE__ int
// AARCH64-DARWIN: #define __INT_LEAST64_FMTd__ "lld"
// AARCH64-DARWIN: #define __INT_LEAST64_FMTi__ "lli"
// AARCH64-DARWIN: #define __INT_LEAST64_MAX__ 9223372036854775807LL
// AARCH64-DARWIN: #define __INT_LEAST64_TYPE__ long long int
// AARCH64-DARWIN: #define __INT_LEAST8_FMTd__ "hhd"
// AARCH64-DARWIN: #define __INT_LEAST8_FMTi__ "hhi"
// AARCH64-DARWIN: #define __INT_LEAST8_MAX__ 127
// AARCH64-DARWIN: #define __INT_LEAST8_TYPE__ signed char
// AARCH64-DARWIN: #define __INT_MAX__ 2147483647
// AARCH64-DARWIN: #define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
// AARCH64-DARWIN: #define __LDBL_DIG__ 15
// AARCH64-DARWIN: #define __LDBL_EPSILON__ 2.2204460492503131e-16L
// AARCH64-DARWIN: #define __LDBL_HAS_DENORM__ 1
// AARCH64-DARWIN: #define __LDBL_HAS_INFINITY__ 1
// AARCH64-DARWIN: #define __LDBL_HAS_QUIET_NAN__ 1
// AARCH64-DARWIN: #define __LDBL_MANT_DIG__ 53
// AARCH64-DARWIN: #define __LDBL_MAX_10_EXP__ 308
// AARCH64-DARWIN: #define __LDBL_MAX_EXP__ 1024
// AARCH64-DARWIN: #define __LDBL_MAX__ 1.7976931348623157e+308L
// AARCH64-DARWIN: #define __LDBL_MIN_10_EXP__ (-307)
// AARCH64-DARWIN: #define __LDBL_MIN_EXP__ (-1021)
// AARCH64-DARWIN: #define __LDBL_MIN__ 2.2250738585072014e-308L
// AARCH64-DARWIN: #define __LONG_LONG_MAX__ 9223372036854775807LL
// AARCH64-DARWIN: #define __LONG_MAX__ 9223372036854775807L
// AARCH64-DARWIN: #define __LP64__ 1
// AARCH64-DARWIN: #define __POINTER_WIDTH__ 64
// AARCH64-DARWIN: #define __PTRDIFF_TYPE__ long int
// AARCH64-DARWIN: #define __PTRDIFF_WIDTH__ 64
// AARCH64-DARWIN: #define __SCHAR_MAX__ 127
// AARCH64-DARWIN: #define __SHRT_MAX__ 32767
// AARCH64-DARWIN: #define __SIG_ATOMIC_MAX__ 2147483647
// AARCH64-DARWIN: #define __SIG_ATOMIC_WIDTH__ 32
// AARCH64-DARWIN: #define __SIZEOF_DOUBLE__ 8
// AARCH64-DARWIN: #define __SIZEOF_FLOAT__ 4
// AARCH64-DARWIN: #define __SIZEOF_INT128__ 16
// AARCH64-DARWIN: #define __SIZEOF_INT__ 4
// AARCH64-DARWIN: #define __SIZEOF_LONG_DOUBLE__ 8
// AARCH64-DARWIN: #define __SIZEOF_LONG_LONG__ 8
// AARCH64-DARWIN: #define __SIZEOF_LONG__ 8
// AARCH64-DARWIN: #define __SIZEOF_POINTER__ 8
// AARCH64-DARWIN: #define __SIZEOF_PTRDIFF_T__ 8
// AARCH64-DARWIN: #define __SIZEOF_SHORT__ 2
// AARCH64-DARWIN: #define __SIZEOF_SIZE_T__ 8
// AARCH64-DARWIN: #define __SIZEOF_WCHAR_T__ 4
// AARCH64-DARWIN: #define __SIZEOF_WINT_T__ 4
// AARCH64-DARWIN: #define __SIZE_MAX__ 18446744073709551615UL
// AARCH64-DARWIN: #define __SIZE_TYPE__ long unsigned int
// AARCH64-DARWIN: #define __SIZE_WIDTH__ 64
// AARCH64-DARWIN: #define __UINT16_C_SUFFIX__
// AARCH64-DARWIN: #define __UINT16_MAX__ 65535
// AARCH64-DARWIN: #define __UINT16_TYPE__ unsigned short
// AARCH64-DARWIN: #define __UINT32_C_SUFFIX__ U
// AARCH64-DARWIN: #define __UINT32_MAX__ 4294967295U
// AARCH64-DARWIN: #define __UINT32_TYPE__ unsigned int
// AARCH64-DARWIN: #define __UINT64_C_SUFFIX__ ULL
// AARCH64-DARWIN: #define __UINT64_MAX__ 18446744073709551615ULL
// AARCH64-DARWIN: #define __UINT64_TYPE__ long long unsigned int
// AARCH64-DARWIN: #define __UINT8_C_SUFFIX__
// AARCH64-DARWIN: #define __UINT8_MAX__ 255
// AARCH64-DARWIN: #define __UINT8_TYPE__ unsigned char
// AARCH64-DARWIN: #define __UINTMAX_C_SUFFIX__ UL
// AARCH64-DARWIN: #define __UINTMAX_MAX__ 18446744073709551615UL
// AARCH64-DARWIN: #define __UINTMAX_TYPE__ long unsigned int
// AARCH64-DARWIN: #define __UINTMAX_WIDTH__ 64
// AARCH64-DARWIN: #define __UINTPTR_MAX__ 18446744073709551615UL
// AARCH64-DARWIN: #define __UINTPTR_TYPE__ long unsigned int
// AARCH64-DARWIN: #define __UINTPTR_WIDTH__ 64
// AARCH64-DARWIN: #define __UINT_FAST16_MAX__ 65535
// AARCH64-DARWIN: #define __UINT_FAST16_TYPE__ unsigned short
// AARCH64-DARWIN: #define __UINT_FAST32_MAX__ 4294967295U
// AARCH64-DARWIN: #define __UINT_FAST32_TYPE__ unsigned int
// AARCH64-DARWIN: #define __UINT_FAST64_MAX__ 18446744073709551615ULL
// AARCH64-DARWIN: #define __UINT_FAST64_TYPE__ long long unsigned int
// AARCH64-DARWIN: #define __UINT_FAST8_MAX__ 255
// AARCH64-DARWIN: #define __UINT_FAST8_TYPE__ unsigned char
// AARCH64-DARWIN: #define __UINT_LEAST16_MAX__ 65535
// AARCH64-DARWIN: #define __UINT_LEAST16_TYPE__ unsigned short
// AARCH64-DARWIN: #define __UINT_LEAST32_MAX__ 4294967295U
// AARCH64-DARWIN: #define __UINT_LEAST32_TYPE__ unsigned int
// AARCH64-DARWIN: #define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// AARCH64-DARWIN: #define __UINT_LEAST64_TYPE__ long long unsigned int
// AARCH64-DARWIN: #define __UINT_LEAST8_MAX__ 255
// AARCH64-DARWIN: #define __UINT_LEAST8_TYPE__ unsigned char
// AARCH64-DARWIN: #define __USER_LABEL_PREFIX__ _
// AARCH64-DARWIN: #define __WCHAR_MAX__ 2147483647
// AARCH64-DARWIN: #define __WCHAR_TYPE__ int
// AARCH64-DARWIN-NOT: #define __WCHAR_UNSIGNED__
// AARCH64-DARWIN: #define __WCHAR_WIDTH__ 32
// AARCH64-DARWIN: #define __WINT_TYPE__ int
// AARCH64-DARWIN: #define __WINT_WIDTH__ 32
// AARCH64-DARWIN: #define __aarch64__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=thumbv7-windows-msvc < /dev/null | FileCheck -match-full-lines -check-prefix ARM-MSVC %s
//
// ARM-MSVC: #define _M_ARM_NT 1
// ARM-MSVC: #define _WIN32 1
// ARM-MSVC-NOT:#define __ARM_DWARF_EH__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-windows-msvc < /dev/null | FileCheck -match-full-lines -check-prefix AARCH64-MSVC %s
//
// AARCH64-MSVC: #define _INTEGRAL_MAX_BITS 64
// AARCH64-MSVC-NOT: #define _LP64 1
// AARCH64-MSVC: #define _M_ARM64 1
// AARCH64-MSVC: #define _WIN32 1
// AARCH64-MSVC: #define _WIN64 1
// AARCH64-MSVC: #define __AARCH64EL__ 1
// AARCH64-MSVC: #define __ARM_64BIT_STATE 1
// AARCH64-MSVC: #define __ARM_ACLE 200
// AARCH64-MSVC: #define __ARM_ALIGN_MAX_STACK_PWR 4
// AARCH64-MSVC: #define __ARM_ARCH 8
// AARCH64-MSVC: #define __ARM_ARCH_ISA_A64 1
// AARCH64-MSVC: #define __ARM_ARCH_PROFILE 'A'
// AARCH64-MSVC: #define __ARM_FEATURE_CLZ 1
// AARCH64-MSVC: #define __ARM_FEATURE_DIRECTED_ROUNDING 1
// AARCH64-MSVC: #define __ARM_FEATURE_DIV 1
// AARCH64-MSVC: #define __ARM_FEATURE_FMA 1
// AARCH64-MSVC: #define __ARM_FEATURE_IDIV 1
// AARCH64-MSVC: #define __ARM_FEATURE_LDREX 0xF
// AARCH64-MSVC: #define __ARM_FEATURE_NUMERIC_MAXMIN 1
// AARCH64-MSVC: #define __ARM_FEATURE_UNALIGNED 1
// AARCH64-MSVC: #define __ARM_FP 0xE
// AARCH64-MSVC: #define __ARM_FP16_ARGS 1
// AARCH64-MSVC: #define __ARM_FP16_FORMAT_IEEE 1
// AARCH64-MSVC: #define __ARM_PCS_AAPCS64 1
// AARCH64-MSVC: #define __ARM_SIZEOF_MINIMAL_ENUM 4
// AARCH64-MSVC: #define __ARM_SIZEOF_WCHAR_T 4
// AARCH64-MSVC: #define __BIGGEST_ALIGNMENT__ 16
// AARCH64-MSVC: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// AARCH64-MSVC: #define __CHAR16_TYPE__ unsigned short
// AARCH64-MSVC: #define __CHAR32_TYPE__ unsigned int
// AARCH64-MSVC: #define __CHAR_BIT__ 8
// AARCH64-MSVC: #define __CONSTANT_CFSTRINGS__ 1
// AARCH64-MSVC: #define __DBL_DECIMAL_DIG__ 17
// AARCH64-MSVC: #define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// AARCH64-MSVC: #define __DBL_DIG__ 15
// AARCH64-MSVC: #define __DBL_EPSILON__ 2.2204460492503131e-16
// AARCH64-MSVC: #define __DBL_HAS_DENORM__ 1
// AARCH64-MSVC: #define __DBL_HAS_INFINITY__ 1
// AARCH64-MSVC: #define __DBL_HAS_QUIET_NAN__ 1
// AARCH64-MSVC: #define __DBL_MANT_DIG__ 53
// AARCH64-MSVC: #define __DBL_MAX_10_EXP__ 308
// AARCH64-MSVC: #define __DBL_MAX_EXP__ 1024
// AARCH64-MSVC: #define __DBL_MAX__ 1.7976931348623157e+308
// AARCH64-MSVC: #define __DBL_MIN_10_EXP__ (-307)
// AARCH64-MSVC: #define __DBL_MIN_EXP__ (-1021)
// AARCH64-MSVC: #define __DBL_MIN__ 2.2250738585072014e-308
// AARCH64-MSVC: #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// AARCH64-MSVC: #define __FINITE_MATH_ONLY__ 0
// AARCH64-MSVC: #define __FLT_DECIMAL_DIG__ 9
// AARCH64-MSVC: #define __FLT_DENORM_MIN__ 1.40129846e-45F
// AARCH64-MSVC: #define __FLT_DIG__ 6
// AARCH64-MSVC: #define __FLT_EPSILON__ 1.19209290e-7F
// AARCH64-MSVC: #define __FLT_EVAL_METHOD__ 0
// AARCH64-MSVC: #define __FLT_HAS_DENORM__ 1
// AARCH64-MSVC: #define __FLT_HAS_INFINITY__ 1
// AARCH64-MSVC: #define __FLT_HAS_QUIET_NAN__ 1
// AARCH64-MSVC: #define __FLT_MANT_DIG__ 24
// AARCH64-MSVC: #define __FLT_MAX_10_EXP__ 38
// AARCH64-MSVC: #define __FLT_MAX_EXP__ 128
// AARCH64-MSVC: #define __FLT_MAX__ 3.40282347e+38F
// AARCH64-MSVC: #define __FLT_MIN_10_EXP__ (-37)
// AARCH64-MSVC: #define __FLT_MIN_EXP__ (-125)
// AARCH64-MSVC: #define __FLT_MIN__ 1.17549435e-38F
// AARCH64-MSVC: #define __FLT_RADIX__ 2
// AARCH64-MSVC: #define __INT_MAX__ 2147483647
// AARCH64-MSVC: #define __LDBL_DECIMAL_DIG__ 17
// AARCH64-MSVC: #define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
// AARCH64-MSVC: #define __LDBL_DIG__ 15
// AARCH64-MSVC: #define __LDBL_EPSILON__ 2.2204460492503131e-16L
// AARCH64-MSVC: #define __LDBL_HAS_DENORM__ 1
// AARCH64-MSVC: #define __LDBL_HAS_INFINITY__ 1
// AARCH64-MSVC: #define __LDBL_HAS_QUIET_NAN__ 1
// AARCH64-MSVC: #define __LDBL_MANT_DIG__ 53
// AARCH64-MSVC: #define __LDBL_MAX_10_EXP__ 308
// AARCH64-MSVC: #define __LDBL_MAX_EXP__ 1024
// AARCH64-MSVC: #define __LDBL_MAX__ 1.7976931348623157e+308L
// AARCH64-MSVC: #define __LDBL_MIN_10_EXP__ (-307)
// AARCH64-MSVC: #define __LDBL_MIN_EXP__ (-1021)
// AARCH64-MSVC: #define __LDBL_MIN__ 2.2250738585072014e-308L
// AARCH64-MSVC: #define __LITTLE_ENDIAN__ 1
// AARCH64-MSVC: #define __LONG_LONG_MAX__ 9223372036854775807LL
// AARCH64-MSVC: #define __LONG_MAX__ 2147483647L
// AARCH64-MSVC-NOT: #define __LP64__ 1
// AARCH64-MSVC: #define __NO_INLINE__ 1
// AARCH64-MSVC: #define __OBJC_BOOL_IS_BOOL 0
// AARCH64-MSVC: #define __ORDER_BIG_ENDIAN__ 4321
// AARCH64-MSVC: #define __ORDER_LITTLE_ENDIAN__ 1234
// AARCH64-MSVC: #define __ORDER_PDP_ENDIAN__ 3412
// AARCH64-MSVC: #define __POINTER_WIDTH__ 64
// AARCH64-MSVC: #define __PRAGMA_REDEFINE_EXTNAME 1
// AARCH64-MSVC: #define __SCHAR_MAX__ 127
// AARCH64-MSVC: #define __SHRT_MAX__ 32767
// AARCH64-MSVC: #define __SIG_ATOMIC_MAX__ 2147483647
// AARCH64-MSVC: #define __SIG_ATOMIC_WIDTH__ 32
// AARCH64-MSVC: #define __SIZEOF_DOUBLE__ 8
// AARCH64-MSVC: #define __SIZEOF_FLOAT__ 4
// AARCH64-MSVC: #define __SIZEOF_INT128__ 16
// AARCH64-MSVC: #define __SIZEOF_INT__ 4
// AARCH64-MSVC: #define __SIZEOF_LONG_DOUBLE__ 8
// AARCH64-MSVC: #define __SIZEOF_LONG_LONG__ 8
// AARCH64-MSVC: #define __SIZEOF_LONG__ 4
// AARCH64-MSVC: #define __SIZEOF_POINTER__ 8
// AARCH64-MSVC: #define __SIZEOF_PTRDIFF_T__ 8
// AARCH64-MSVC: #define __SIZEOF_SHORT__ 2
// AARCH64-MSVC: #define __SIZEOF_SIZE_T__ 8
// AARCH64-MSVC: #define __SIZEOF_WCHAR_T__ 2
// AARCH64-MSVC: #define __SIZEOF_WINT_T__ 2
// AARCH64-MSVC: #define __SIZE_MAX__ 18446744073709551615ULL
// AARCH64-MSVC: #define __SIZE_TYPE__ long long unsigned int
// AARCH64-MSVC: #define __SIZE_WIDTH__ 64
// AARCH64-MSVC: #define __STDC_HOSTED__ 0
// AARCH64-MSVC: #define __STDC_UTF_16__ 1
// AARCH64-MSVC: #define __STDC_UTF_32__ 1
// AARCH64-MSVC: #define __STDC_VERSION__ 201112L
// AARCH64-MSVC: #define __STDC__ 1
// AARCH64-MSVC: #define __UINT16_C_SUFFIX__
// AARCH64-MSVC: #define __UINT16_MAX__ 65535
// AARCH64-MSVC: #define __UINT16_TYPE__ unsigned short
// AARCH64-MSVC: #define __UINT32_C_SUFFIX__ U
// AARCH64-MSVC: #define __UINT32_MAX__ 4294967295U
// AARCH64-MSVC: #define __UINT32_TYPE__ unsigned int
// AARCH64-MSVC: #define __UINT64_C_SUFFIX__ ULL
// AARCH64-MSVC: #define __UINT64_MAX__ 18446744073709551615ULL
// AARCH64-MSVC: #define __UINT64_TYPE__ long long unsigned int
// AARCH64-MSVC: #define __UINT8_C_SUFFIX__
// AARCH64-MSVC: #define __UINT8_MAX__ 255
// AARCH64-MSVC: #define __UINT8_TYPE__ unsigned char
// AARCH64-MSVC: #define __UINTMAX_C_SUFFIX__ ULL
// AARCH64-MSVC: #define __UINTMAX_MAX__ 18446744073709551615ULL
// AARCH64-MSVC: #define __UINTMAX_TYPE__ long long unsigned int
// AARCH64-MSVC: #define __UINTMAX_WIDTH__ 64
// AARCH64-MSVC: #define __UINTPTR_MAX__ 18446744073709551615ULL
// AARCH64-MSVC: #define __UINTPTR_TYPE__ long long unsigned int
// AARCH64-MSVC: #define __UINTPTR_WIDTH__ 64
// AARCH64-MSVC: #define __UINT_FAST16_MAX__ 65535
// AARCH64-MSVC: #define __UINT_FAST16_TYPE__ unsigned short
// AARCH64-MSVC: #define __UINT_FAST32_MAX__ 4294967295U
// AARCH64-MSVC: #define __UINT_FAST32_TYPE__ unsigned int
// AARCH64-MSVC: #define __UINT_FAST64_MAX__ 18446744073709551615ULL
// AARCH64-MSVC: #define __UINT_FAST64_TYPE__ long long unsigned int
// AARCH64-MSVC: #define __UINT_FAST8_MAX__ 255
// AARCH64-MSVC: #define __UINT_FAST8_TYPE__ unsigned char
// AARCH64-MSVC: #define __UINT_LEAST16_MAX__ 65535
// AARCH64-MSVC: #define __UINT_LEAST16_TYPE__ unsigned short
// AARCH64-MSVC: #define __UINT_LEAST32_MAX__ 4294967295U
// AARCH64-MSVC: #define __UINT_LEAST32_TYPE__ unsigned int
// AARCH64-MSVC: #define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// AARCH64-MSVC: #define __UINT_LEAST64_TYPE__ long long unsigned int
// AARCH64-MSVC: #define __UINT_LEAST8_MAX__ 255
// AARCH64-MSVC: #define __UINT_LEAST8_TYPE__ unsigned char
// AARCH64-MSVC: #define __USER_LABEL_PREFIX__
// AARCH64-MSVC: #define __WCHAR_MAX__ 65535
// AARCH64-MSVC: #define __WCHAR_TYPE__ unsigned short
// AARCH64-MSVC: #define __WCHAR_UNSIGNED__ 1
// AARCH64-MSVC: #define __WCHAR_WIDTH__ 16
// AARCH64-MSVC: #define __WINT_TYPE__ unsigned short
// AARCH64-MSVC: #define __WINT_WIDTH__ 16
// AARCH64-MSVC: #define __aarch64__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-none-none < /dev/null | FileCheck -match-full-lines -check-prefix ARM %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=arm-none-none < /dev/null | FileCheck -match-full-lines -check-prefix ARM -check-prefix ARM-CXX %s
//
// ARM-NOT:#define _LP64
// ARM:#define __APCS_32__ 1
// ARM-NOT:#define __ARMEB__ 1
// ARM:#define __ARMEL__ 1
// ARM:#define __ARM_ARCH_4T__ 1
// ARM-NOT:#define __ARM_BIG_ENDIAN 1
// ARM:#define __BIGGEST_ALIGNMENT__ 8
// ARM:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// ARM:#define __CHAR16_TYPE__ unsigned short
// ARM:#define __CHAR32_TYPE__ unsigned int
// ARM:#define __CHAR_BIT__ 8
// ARM:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// ARM:#define __DBL_DIG__ 15
// ARM:#define __DBL_EPSILON__ 2.2204460492503131e-16
// ARM:#define __DBL_HAS_DENORM__ 1
// ARM:#define __DBL_HAS_INFINITY__ 1
// ARM:#define __DBL_HAS_QUIET_NAN__ 1
// ARM:#define __DBL_MANT_DIG__ 53
// ARM:#define __DBL_MAX_10_EXP__ 308
// ARM:#define __DBL_MAX_EXP__ 1024
// ARM:#define __DBL_MAX__ 1.7976931348623157e+308
// ARM:#define __DBL_MIN_10_EXP__ (-307)
// ARM:#define __DBL_MIN_EXP__ (-1021)
// ARM:#define __DBL_MIN__ 2.2250738585072014e-308
// ARM:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// ARM:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// ARM:#define __FLT_DIG__ 6
// ARM:#define __FLT_EPSILON__ 1.19209290e-7F
// ARM:#define __FLT_EVAL_METHOD__ 0
// ARM:#define __FLT_HAS_DENORM__ 1
// ARM:#define __FLT_HAS_INFINITY__ 1
// ARM:#define __FLT_HAS_QUIET_NAN__ 1
// ARM:#define __FLT_MANT_DIG__ 24
// ARM:#define __FLT_MAX_10_EXP__ 38
// ARM:#define __FLT_MAX_EXP__ 128
// ARM:#define __FLT_MAX__ 3.40282347e+38F
// ARM:#define __FLT_MIN_10_EXP__ (-37)
// ARM:#define __FLT_MIN_EXP__ (-125)
// ARM:#define __FLT_MIN__ 1.17549435e-38F
// ARM:#define __FLT_RADIX__ 2
// ARM:#define __INT16_C_SUFFIX__
// ARM:#define __INT16_FMTd__ "hd"
// ARM:#define __INT16_FMTi__ "hi"
// ARM:#define __INT16_MAX__ 32767
// ARM:#define __INT16_TYPE__ short
// ARM:#define __INT32_C_SUFFIX__
// ARM:#define __INT32_FMTd__ "d"
// ARM:#define __INT32_FMTi__ "i"
// ARM:#define __INT32_MAX__ 2147483647
// ARM:#define __INT32_TYPE__ int
// ARM:#define __INT64_C_SUFFIX__ LL
// ARM:#define __INT64_FMTd__ "lld"
// ARM:#define __INT64_FMTi__ "lli"
// ARM:#define __INT64_MAX__ 9223372036854775807LL
// ARM:#define __INT64_TYPE__ long long int
// ARM:#define __INT8_C_SUFFIX__
// ARM:#define __INT8_FMTd__ "hhd"
// ARM:#define __INT8_FMTi__ "hhi"
// ARM:#define __INT8_MAX__ 127
// ARM:#define __INT8_TYPE__ signed char
// ARM:#define __INTMAX_C_SUFFIX__ LL
// ARM:#define __INTMAX_FMTd__ "lld"
// ARM:#define __INTMAX_FMTi__ "lli"
// ARM:#define __INTMAX_MAX__ 9223372036854775807LL
// ARM:#define __INTMAX_TYPE__ long long int
// ARM:#define __INTMAX_WIDTH__ 64
// ARM:#define __INTPTR_FMTd__ "d"
// ARM:#define __INTPTR_FMTi__ "i"
// ARM:#define __INTPTR_MAX__ 2147483647
// ARM:#define __INTPTR_TYPE__ int
// ARM:#define __INTPTR_WIDTH__ 32
// ARM:#define __INT_FAST16_FMTd__ "hd"
// ARM:#define __INT_FAST16_FMTi__ "hi"
// ARM:#define __INT_FAST16_MAX__ 32767
// ARM:#define __INT_FAST16_TYPE__ short
// ARM:#define __INT_FAST32_FMTd__ "d"
// ARM:#define __INT_FAST32_FMTi__ "i"
// ARM:#define __INT_FAST32_MAX__ 2147483647
// ARM:#define __INT_FAST32_TYPE__ int
// ARM:#define __INT_FAST64_FMTd__ "lld"
// ARM:#define __INT_FAST64_FMTi__ "lli"
// ARM:#define __INT_FAST64_MAX__ 9223372036854775807LL
// ARM:#define __INT_FAST64_TYPE__ long long int
// ARM:#define __INT_FAST8_FMTd__ "hhd"
// ARM:#define __INT_FAST8_FMTi__ "hhi"
// ARM:#define __INT_FAST8_MAX__ 127
// ARM:#define __INT_FAST8_TYPE__ signed char
// ARM:#define __INT_LEAST16_FMTd__ "hd"
// ARM:#define __INT_LEAST16_FMTi__ "hi"
// ARM:#define __INT_LEAST16_MAX__ 32767
// ARM:#define __INT_LEAST16_TYPE__ short
// ARM:#define __INT_LEAST32_FMTd__ "d"
// ARM:#define __INT_LEAST32_FMTi__ "i"
// ARM:#define __INT_LEAST32_MAX__ 2147483647
// ARM:#define __INT_LEAST32_TYPE__ int
// ARM:#define __INT_LEAST64_FMTd__ "lld"
// ARM:#define __INT_LEAST64_FMTi__ "lli"
// ARM:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// ARM:#define __INT_LEAST64_TYPE__ long long int
// ARM:#define __INT_LEAST8_FMTd__ "hhd"
// ARM:#define __INT_LEAST8_FMTi__ "hhi"
// ARM:#define __INT_LEAST8_MAX__ 127
// ARM:#define __INT_LEAST8_TYPE__ signed char
// ARM:#define __INT_MAX__ 2147483647
// ARM:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
// ARM:#define __LDBL_DIG__ 15
// ARM:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
// ARM:#define __LDBL_HAS_DENORM__ 1
// ARM:#define __LDBL_HAS_INFINITY__ 1
// ARM:#define __LDBL_HAS_QUIET_NAN__ 1
// ARM:#define __LDBL_MANT_DIG__ 53
// ARM:#define __LDBL_MAX_10_EXP__ 308
// ARM:#define __LDBL_MAX_EXP__ 1024
// ARM:#define __LDBL_MAX__ 1.7976931348623157e+308L
// ARM:#define __LDBL_MIN_10_EXP__ (-307)
// ARM:#define __LDBL_MIN_EXP__ (-1021)
// ARM:#define __LDBL_MIN__ 2.2250738585072014e-308L
// ARM:#define __LITTLE_ENDIAN__ 1
// ARM:#define __LONG_LONG_MAX__ 9223372036854775807LL
// ARM:#define __LONG_MAX__ 2147483647L
// ARM-NOT:#define __LP64__
// ARM:#define __POINTER_WIDTH__ 32
// ARM:#define __PTRDIFF_TYPE__ int
// ARM:#define __PTRDIFF_WIDTH__ 32
// ARM:#define __REGISTER_PREFIX__
// ARM:#define __SCHAR_MAX__ 127
// ARM:#define __SHRT_MAX__ 32767
// ARM:#define __SIG_ATOMIC_MAX__ 2147483647
// ARM:#define __SIG_ATOMIC_WIDTH__ 32
// ARM:#define __SIZEOF_DOUBLE__ 8
// ARM:#define __SIZEOF_FLOAT__ 4
// ARM:#define __SIZEOF_INT__ 4
// ARM:#define __SIZEOF_LONG_DOUBLE__ 8
// ARM:#define __SIZEOF_LONG_LONG__ 8
// ARM:#define __SIZEOF_LONG__ 4
// ARM:#define __SIZEOF_POINTER__ 4
// ARM:#define __SIZEOF_PTRDIFF_T__ 4
// ARM:#define __SIZEOF_SHORT__ 2
// ARM:#define __SIZEOF_SIZE_T__ 4
// ARM:#define __SIZEOF_WCHAR_T__ 4
// ARM:#define __SIZEOF_WINT_T__ 4
// ARM:#define __SIZE_MAX__ 4294967295U
// ARM:#define __SIZE_TYPE__ unsigned int
// ARM:#define __SIZE_WIDTH__ 32
// ARM-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
// ARM:#define __UINT16_C_SUFFIX__
// ARM:#define __UINT16_MAX__ 65535
// ARM:#define __UINT16_TYPE__ unsigned short
// ARM:#define __UINT32_C_SUFFIX__ U
// ARM:#define __UINT32_MAX__ 4294967295U
// ARM:#define __UINT32_TYPE__ unsigned int
// ARM:#define __UINT64_C_SUFFIX__ ULL
// ARM:#define __UINT64_MAX__ 18446744073709551615ULL
// ARM:#define __UINT64_TYPE__ long long unsigned int
// ARM:#define __UINT8_C_SUFFIX__
// ARM:#define __UINT8_MAX__ 255
// ARM:#define __UINT8_TYPE__ unsigned char
// ARM:#define __UINTMAX_C_SUFFIX__ ULL
// ARM:#define __UINTMAX_MAX__ 18446744073709551615ULL
// ARM:#define __UINTMAX_TYPE__ long long unsigned int
// ARM:#define __UINTMAX_WIDTH__ 64
// ARM:#define __UINTPTR_MAX__ 4294967295U
// ARM:#define __UINTPTR_TYPE__ unsigned int
// ARM:#define __UINTPTR_WIDTH__ 32
// ARM:#define __UINT_FAST16_MAX__ 65535
// ARM:#define __UINT_FAST16_TYPE__ unsigned short
// ARM:#define __UINT_FAST32_MAX__ 4294967295U
// ARM:#define __UINT_FAST32_TYPE__ unsigned int
// ARM:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// ARM:#define __UINT_FAST64_TYPE__ long long unsigned int
// ARM:#define __UINT_FAST8_MAX__ 255
// ARM:#define __UINT_FAST8_TYPE__ unsigned char
// ARM:#define __UINT_LEAST16_MAX__ 65535
// ARM:#define __UINT_LEAST16_TYPE__ unsigned short
// ARM:#define __UINT_LEAST32_MAX__ 4294967295U
// ARM:#define __UINT_LEAST32_TYPE__ unsigned int
// ARM:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// ARM:#define __UINT_LEAST64_TYPE__ long long unsigned int
// ARM:#define __UINT_LEAST8_MAX__ 255
// ARM:#define __UINT_LEAST8_TYPE__ unsigned char
// ARM:#define __USER_LABEL_PREFIX__
// ARM:#define __WCHAR_MAX__ 4294967295U
// ARM:#define __WCHAR_TYPE__ unsigned int
// ARM:#define __WCHAR_WIDTH__ 32
// ARM:#define __WINT_TYPE__ int
// ARM:#define __WINT_WIDTH__ 32
// ARM:#define __arm 1
// ARM:#define __arm__ 1
// RUN: %clang_cc1 -dM -ffreestanding -triple arm-none-none -target-abi apcs-gnu -E /dev/null -o - | FileCheck -match-full-lines -check-prefix ARM-APCS-GNU %s
// ARM-APCS-GNU: #define __INTPTR_TYPE__ int
// ARM-APCS-GNU: #define __PTRDIFF_TYPE__ int
// ARM-APCS-GNU: #define __SIZE_TYPE__ unsigned int
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=armeb-none-none < /dev/null | FileCheck -match-full-lines -check-prefix ARM-BE %s
//
// ARM-BE-NOT:#define _LP64
// ARM-BE:#define __APCS_32__ 1
// ARM-BE:#define __ARMEB__ 1
// ARM-BE-NOT:#define __ARMEL__ 1
// ARM-BE:#define __ARM_ARCH_4T__ 1
// ARM-BE:#define __ARM_BIG_ENDIAN 1
// ARM-BE:#define __BIGGEST_ALIGNMENT__ 8
// ARM-BE:#define __BIG_ENDIAN__ 1
// ARM-BE:#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
// ARM-BE:#define __CHAR16_TYPE__ unsigned short
// ARM-BE:#define __CHAR32_TYPE__ unsigned int
// ARM-BE:#define __CHAR_BIT__ 8
// ARM-BE:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// ARM-BE:#define __DBL_DIG__ 15
// ARM-BE:#define __DBL_EPSILON__ 2.2204460492503131e-16
// ARM-BE:#define __DBL_HAS_DENORM__ 1
// ARM-BE:#define __DBL_HAS_INFINITY__ 1
// ARM-BE:#define __DBL_HAS_QUIET_NAN__ 1
// ARM-BE:#define __DBL_MANT_DIG__ 53
// ARM-BE:#define __DBL_MAX_10_EXP__ 308
// ARM-BE:#define __DBL_MAX_EXP__ 1024
// ARM-BE:#define __DBL_MAX__ 1.7976931348623157e+308
// ARM-BE:#define __DBL_MIN_10_EXP__ (-307)
// ARM-BE:#define __DBL_MIN_EXP__ (-1021)
// ARM-BE:#define __DBL_MIN__ 2.2250738585072014e-308
// ARM-BE:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// ARM-BE:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// ARM-BE:#define __FLT_DIG__ 6
// ARM-BE:#define __FLT_EPSILON__ 1.19209290e-7F
// ARM-BE:#define __FLT_EVAL_METHOD__ 0
// ARM-BE:#define __FLT_HAS_DENORM__ 1
// ARM-BE:#define __FLT_HAS_INFINITY__ 1
// ARM-BE:#define __FLT_HAS_QUIET_NAN__ 1
// ARM-BE:#define __FLT_MANT_DIG__ 24
// ARM-BE:#define __FLT_MAX_10_EXP__ 38
// ARM-BE:#define __FLT_MAX_EXP__ 128
// ARM-BE:#define __FLT_MAX__ 3.40282347e+38F
// ARM-BE:#define __FLT_MIN_10_EXP__ (-37)
// ARM-BE:#define __FLT_MIN_EXP__ (-125)
// ARM-BE:#define __FLT_MIN__ 1.17549435e-38F
// ARM-BE:#define __FLT_RADIX__ 2
// ARM-BE:#define __INT16_C_SUFFIX__
// ARM-BE:#define __INT16_FMTd__ "hd"
// ARM-BE:#define __INT16_FMTi__ "hi"
// ARM-BE:#define __INT16_MAX__ 32767
// ARM-BE:#define __INT16_TYPE__ short
// ARM-BE:#define __INT32_C_SUFFIX__
// ARM-BE:#define __INT32_FMTd__ "d"
// ARM-BE:#define __INT32_FMTi__ "i"
// ARM-BE:#define __INT32_MAX__ 2147483647
// ARM-BE:#define __INT32_TYPE__ int
// ARM-BE:#define __INT64_C_SUFFIX__ LL
// ARM-BE:#define __INT64_FMTd__ "lld"
// ARM-BE:#define __INT64_FMTi__ "lli"
// ARM-BE:#define __INT64_MAX__ 9223372036854775807LL
// ARM-BE:#define __INT64_TYPE__ long long int
// ARM-BE:#define __INT8_C_SUFFIX__
// ARM-BE:#define __INT8_FMTd__ "hhd"
// ARM-BE:#define __INT8_FMTi__ "hhi"
// ARM-BE:#define __INT8_MAX__ 127
// ARM-BE:#define __INT8_TYPE__ signed char
// ARM-BE:#define __INTMAX_C_SUFFIX__ LL
// ARM-BE:#define __INTMAX_FMTd__ "lld"
// ARM-BE:#define __INTMAX_FMTi__ "lli"
// ARM-BE:#define __INTMAX_MAX__ 9223372036854775807LL
// ARM-BE:#define __INTMAX_TYPE__ long long int
// ARM-BE:#define __INTMAX_WIDTH__ 64
// ARM-BE:#define __INTPTR_FMTd__ "d"
// ARM-BE:#define __INTPTR_FMTi__ "i"
// ARM-BE:#define __INTPTR_MAX__ 2147483647
// ARM-BE:#define __INTPTR_TYPE__ int
// ARM-BE:#define __INTPTR_WIDTH__ 32
// ARM-BE:#define __INT_FAST16_FMTd__ "hd"
// ARM-BE:#define __INT_FAST16_FMTi__ "hi"
// ARM-BE:#define __INT_FAST16_MAX__ 32767
// ARM-BE:#define __INT_FAST16_TYPE__ short
// ARM-BE:#define __INT_FAST32_FMTd__ "d"
// ARM-BE:#define __INT_FAST32_FMTi__ "i"
// ARM-BE:#define __INT_FAST32_MAX__ 2147483647
// ARM-BE:#define __INT_FAST32_TYPE__ int
// ARM-BE:#define __INT_FAST64_FMTd__ "lld"
// ARM-BE:#define __INT_FAST64_FMTi__ "lli"
// ARM-BE:#define __INT_FAST64_MAX__ 9223372036854775807LL
// ARM-BE:#define __INT_FAST64_TYPE__ long long int
// ARM-BE:#define __INT_FAST8_FMTd__ "hhd"
// ARM-BE:#define __INT_FAST8_FMTi__ "hhi"
// ARM-BE:#define __INT_FAST8_MAX__ 127
// ARM-BE:#define __INT_FAST8_TYPE__ signed char
// ARM-BE:#define __INT_LEAST16_FMTd__ "hd"
// ARM-BE:#define __INT_LEAST16_FMTi__ "hi"
// ARM-BE:#define __INT_LEAST16_MAX__ 32767
// ARM-BE:#define __INT_LEAST16_TYPE__ short
// ARM-BE:#define __INT_LEAST32_FMTd__ "d"
// ARM-BE:#define __INT_LEAST32_FMTi__ "i"
// ARM-BE:#define __INT_LEAST32_MAX__ 2147483647
// ARM-BE:#define __INT_LEAST32_TYPE__ int
// ARM-BE:#define __INT_LEAST64_FMTd__ "lld"
// ARM-BE:#define __INT_LEAST64_FMTi__ "lli"
// ARM-BE:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// ARM-BE:#define __INT_LEAST64_TYPE__ long long int
// ARM-BE:#define __INT_LEAST8_FMTd__ "hhd"
// ARM-BE:#define __INT_LEAST8_FMTi__ "hhi"
// ARM-BE:#define __INT_LEAST8_MAX__ 127
// ARM-BE:#define __INT_LEAST8_TYPE__ signed char
// ARM-BE:#define __INT_MAX__ 2147483647
// ARM-BE:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
// ARM-BE:#define __LDBL_DIG__ 15
// ARM-BE:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
// ARM-BE:#define __LDBL_HAS_DENORM__ 1
// ARM-BE:#define __LDBL_HAS_INFINITY__ 1
// ARM-BE:#define __LDBL_HAS_QUIET_NAN__ 1
// ARM-BE:#define __LDBL_MANT_DIG__ 53
// ARM-BE:#define __LDBL_MAX_10_EXP__ 308
// ARM-BE:#define __LDBL_MAX_EXP__ 1024
// ARM-BE:#define __LDBL_MAX__ 1.7976931348623157e+308L
// ARM-BE:#define __LDBL_MIN_10_EXP__ (-307)
// ARM-BE:#define __LDBL_MIN_EXP__ (-1021)
// ARM-BE:#define __LDBL_MIN__ 2.2250738585072014e-308L
// ARM-BE:#define __LONG_LONG_MAX__ 9223372036854775807LL
// ARM-BE:#define __LONG_MAX__ 2147483647L
// ARM-BE-NOT:#define __LP64__
// ARM-BE:#define __POINTER_WIDTH__ 32
// ARM-BE:#define __PTRDIFF_TYPE__ int
// ARM-BE:#define __PTRDIFF_WIDTH__ 32
// ARM-BE:#define __REGISTER_PREFIX__
// ARM-BE:#define __SCHAR_MAX__ 127
// ARM-BE:#define __SHRT_MAX__ 32767
// ARM-BE:#define __SIG_ATOMIC_MAX__ 2147483647
// ARM-BE:#define __SIG_ATOMIC_WIDTH__ 32
// ARM-BE:#define __SIZEOF_DOUBLE__ 8
// ARM-BE:#define __SIZEOF_FLOAT__ 4
// ARM-BE:#define __SIZEOF_INT__ 4
// ARM-BE:#define __SIZEOF_LONG_DOUBLE__ 8
// ARM-BE:#define __SIZEOF_LONG_LONG__ 8
// ARM-BE:#define __SIZEOF_LONG__ 4
// ARM-BE:#define __SIZEOF_POINTER__ 4
// ARM-BE:#define __SIZEOF_PTRDIFF_T__ 4
// ARM-BE:#define __SIZEOF_SHORT__ 2
// ARM-BE:#define __SIZEOF_SIZE_T__ 4
// ARM-BE:#define __SIZEOF_WCHAR_T__ 4
// ARM-BE:#define __SIZEOF_WINT_T__ 4
// ARM-BE:#define __SIZE_MAX__ 4294967295U
// ARM-BE:#define __SIZE_TYPE__ unsigned int
// ARM-BE:#define __SIZE_WIDTH__ 32
// ARM-BE:#define __UINT16_C_SUFFIX__
// ARM-BE:#define __UINT16_MAX__ 65535
// ARM-BE:#define __UINT16_TYPE__ unsigned short
// ARM-BE:#define __UINT32_C_SUFFIX__ U
// ARM-BE:#define __UINT32_MAX__ 4294967295U
// ARM-BE:#define __UINT32_TYPE__ unsigned int
// ARM-BE:#define __UINT64_C_SUFFIX__ ULL
// ARM-BE:#define __UINT64_MAX__ 18446744073709551615ULL
// ARM-BE:#define __UINT64_TYPE__ long long unsigned int
// ARM-BE:#define __UINT8_C_SUFFIX__
// ARM-BE:#define __UINT8_MAX__ 255
// ARM-BE:#define __UINT8_TYPE__ unsigned char
// ARM-BE:#define __UINTMAX_C_SUFFIX__ ULL
// ARM-BE:#define __UINTMAX_MAX__ 18446744073709551615ULL
// ARM-BE:#define __UINTMAX_TYPE__ long long unsigned int
// ARM-BE:#define __UINTMAX_WIDTH__ 64
// ARM-BE:#define __UINTPTR_MAX__ 4294967295U
// ARM-BE:#define __UINTPTR_TYPE__ unsigned int
// ARM-BE:#define __UINTPTR_WIDTH__ 32
// ARM-BE:#define __UINT_FAST16_MAX__ 65535
// ARM-BE:#define __UINT_FAST16_TYPE__ unsigned short
// ARM-BE:#define __UINT_FAST32_MAX__ 4294967295U
// ARM-BE:#define __UINT_FAST32_TYPE__ unsigned int
// ARM-BE:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// ARM-BE:#define __UINT_FAST64_TYPE__ long long unsigned int
// ARM-BE:#define __UINT_FAST8_MAX__ 255
// ARM-BE:#define __UINT_FAST8_TYPE__ unsigned char
// ARM-BE:#define __UINT_LEAST16_MAX__ 65535
// ARM-BE:#define __UINT_LEAST16_TYPE__ unsigned short
// ARM-BE:#define __UINT_LEAST32_MAX__ 4294967295U
// ARM-BE:#define __UINT_LEAST32_TYPE__ unsigned int
// ARM-BE:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// ARM-BE:#define __UINT_LEAST64_TYPE__ long long unsigned int
// ARM-BE:#define __UINT_LEAST8_MAX__ 255
// ARM-BE:#define __UINT_LEAST8_TYPE__ unsigned char
// ARM-BE:#define __USER_LABEL_PREFIX__
// ARM-BE:#define __WCHAR_MAX__ 4294967295U
// ARM-BE:#define __WCHAR_TYPE__ unsigned int
// ARM-BE:#define __WCHAR_WIDTH__ 32
// ARM-BE:#define __WINT_TYPE__ int
// ARM-BE:#define __WINT_WIDTH__ 32
// ARM-BE:#define __arm 1
// ARM-BE:#define __arm__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-none-linux-gnueabi -target-feature +soft-float -target-feature +soft-float-abi < /dev/null | FileCheck -match-full-lines -check-prefix ARMEABISOFTFP %s
//
// ARMEABISOFTFP-NOT:#define _LP64
// ARMEABISOFTFP:#define __APCS_32__ 1
// ARMEABISOFTFP-NOT:#define __ARMEB__ 1
// ARMEABISOFTFP:#define __ARMEL__ 1
// ARMEABISOFTFP:#define __ARM_ARCH 4
// ARMEABISOFTFP:#define __ARM_ARCH_4T__ 1
// ARMEABISOFTFP-NOT:#define __ARM_BIG_ENDIAN 1
// ARMEABISOFTFP:#define __ARM_EABI__ 1
// ARMEABISOFTFP:#define __ARM_PCS 1
// ARMEABISOFTFP-NOT:#define __ARM_PCS_VFP 1
// ARMEABISOFTFP:#define __BIGGEST_ALIGNMENT__ 8
// ARMEABISOFTFP:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// ARMEABISOFTFP:#define __CHAR16_TYPE__ unsigned short
// ARMEABISOFTFP:#define __CHAR32_TYPE__ unsigned int
// ARMEABISOFTFP:#define __CHAR_BIT__ 8
// ARMEABISOFTFP:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// ARMEABISOFTFP:#define __DBL_DIG__ 15
// ARMEABISOFTFP:#define __DBL_EPSILON__ 2.2204460492503131e-16
// ARMEABISOFTFP:#define __DBL_HAS_DENORM__ 1
// ARMEABISOFTFP:#define __DBL_HAS_INFINITY__ 1
// ARMEABISOFTFP:#define __DBL_HAS_QUIET_NAN__ 1
// ARMEABISOFTFP:#define __DBL_MANT_DIG__ 53
// ARMEABISOFTFP:#define __DBL_MAX_10_EXP__ 308
// ARMEABISOFTFP:#define __DBL_MAX_EXP__ 1024
// ARMEABISOFTFP:#define __DBL_MAX__ 1.7976931348623157e+308
// ARMEABISOFTFP:#define __DBL_MIN_10_EXP__ (-307)
// ARMEABISOFTFP:#define __DBL_MIN_EXP__ (-1021)
// ARMEABISOFTFP:#define __DBL_MIN__ 2.2250738585072014e-308
// ARMEABISOFTFP:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// ARMEABISOFTFP:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// ARMEABISOFTFP:#define __FLT_DIG__ 6
// ARMEABISOFTFP:#define __FLT_EPSILON__ 1.19209290e-7F
// ARMEABISOFTFP:#define __FLT_EVAL_METHOD__ 0
// ARMEABISOFTFP:#define __FLT_HAS_DENORM__ 1
// ARMEABISOFTFP:#define __FLT_HAS_INFINITY__ 1
// ARMEABISOFTFP:#define __FLT_HAS_QUIET_NAN__ 1
// ARMEABISOFTFP:#define __FLT_MANT_DIG__ 24
// ARMEABISOFTFP:#define __FLT_MAX_10_EXP__ 38
// ARMEABISOFTFP:#define __FLT_MAX_EXP__ 128
// ARMEABISOFTFP:#define __FLT_MAX__ 3.40282347e+38F
// ARMEABISOFTFP:#define __FLT_MIN_10_EXP__ (-37)
// ARMEABISOFTFP:#define __FLT_MIN_EXP__ (-125)
// ARMEABISOFTFP:#define __FLT_MIN__ 1.17549435e-38F
// ARMEABISOFTFP:#define __FLT_RADIX__ 2
// ARMEABISOFTFP:#define __INT16_C_SUFFIX__
// ARMEABISOFTFP:#define __INT16_FMTd__ "hd"
// ARMEABISOFTFP:#define __INT16_FMTi__ "hi"
// ARMEABISOFTFP:#define __INT16_MAX__ 32767
// ARMEABISOFTFP:#define __INT16_TYPE__ short
// ARMEABISOFTFP:#define __INT32_C_SUFFIX__
// ARMEABISOFTFP:#define __INT32_FMTd__ "d"
// ARMEABISOFTFP:#define __INT32_FMTi__ "i"
// ARMEABISOFTFP:#define __INT32_MAX__ 2147483647
// ARMEABISOFTFP:#define __INT32_TYPE__ int
// ARMEABISOFTFP:#define __INT64_C_SUFFIX__ LL
// ARMEABISOFTFP:#define __INT64_FMTd__ "lld"
// ARMEABISOFTFP:#define __INT64_FMTi__ "lli"
// ARMEABISOFTFP:#define __INT64_MAX__ 9223372036854775807LL
// ARMEABISOFTFP:#define __INT64_TYPE__ long long int
// ARMEABISOFTFP:#define __INT8_C_SUFFIX__
// ARMEABISOFTFP:#define __INT8_FMTd__ "hhd"
// ARMEABISOFTFP:#define __INT8_FMTi__ "hhi"
// ARMEABISOFTFP:#define __INT8_MAX__ 127
// ARMEABISOFTFP:#define __INT8_TYPE__ signed char
// ARMEABISOFTFP:#define __INTMAX_C_SUFFIX__ LL
// ARMEABISOFTFP:#define __INTMAX_FMTd__ "lld"
// ARMEABISOFTFP:#define __INTMAX_FMTi__ "lli"
// ARMEABISOFTFP:#define __INTMAX_MAX__ 9223372036854775807LL
// ARMEABISOFTFP:#define __INTMAX_TYPE__ long long int
// ARMEABISOFTFP:#define __INTMAX_WIDTH__ 64
// ARMEABISOFTFP:#define __INTPTR_FMTd__ "d"
// ARMEABISOFTFP:#define __INTPTR_FMTi__ "i"
// ARMEABISOFTFP:#define __INTPTR_MAX__ 2147483647
// ARMEABISOFTFP:#define __INTPTR_TYPE__ int
// ARMEABISOFTFP:#define __INTPTR_WIDTH__ 32
// ARMEABISOFTFP:#define __INT_FAST16_FMTd__ "hd"
// ARMEABISOFTFP:#define __INT_FAST16_FMTi__ "hi"
// ARMEABISOFTFP:#define __INT_FAST16_MAX__ 32767
// ARMEABISOFTFP:#define __INT_FAST16_TYPE__ short
// ARMEABISOFTFP:#define __INT_FAST32_FMTd__ "d"
// ARMEABISOFTFP:#define __INT_FAST32_FMTi__ "i"
// ARMEABISOFTFP:#define __INT_FAST32_MAX__ 2147483647
// ARMEABISOFTFP:#define __INT_FAST32_TYPE__ int
// ARMEABISOFTFP:#define __INT_FAST64_FMTd__ "lld"
// ARMEABISOFTFP:#define __INT_FAST64_FMTi__ "lli"
// ARMEABISOFTFP:#define __INT_FAST64_MAX__ 9223372036854775807LL
// ARMEABISOFTFP:#define __INT_FAST64_TYPE__ long long int
// ARMEABISOFTFP:#define __INT_FAST8_FMTd__ "hhd"
// ARMEABISOFTFP:#define __INT_FAST8_FMTi__ "hhi"
// ARMEABISOFTFP:#define __INT_FAST8_MAX__ 127
// ARMEABISOFTFP:#define __INT_FAST8_TYPE__ signed char
// ARMEABISOFTFP:#define __INT_LEAST16_FMTd__ "hd"
// ARMEABISOFTFP:#define __INT_LEAST16_FMTi__ "hi"
// ARMEABISOFTFP:#define __INT_LEAST16_MAX__ 32767
// ARMEABISOFTFP:#define __INT_LEAST16_TYPE__ short
// ARMEABISOFTFP:#define __INT_LEAST32_FMTd__ "d"
// ARMEABISOFTFP:#define __INT_LEAST32_FMTi__ "i"
// ARMEABISOFTFP:#define __INT_LEAST32_MAX__ 2147483647
// ARMEABISOFTFP:#define __INT_LEAST32_TYPE__ int
// ARMEABISOFTFP:#define __INT_LEAST64_FMTd__ "lld"
// ARMEABISOFTFP:#define __INT_LEAST64_FMTi__ "lli"
// ARMEABISOFTFP:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// ARMEABISOFTFP:#define __INT_LEAST64_TYPE__ long long int
// ARMEABISOFTFP:#define __INT_LEAST8_FMTd__ "hhd"
// ARMEABISOFTFP:#define __INT_LEAST8_FMTi__ "hhi"
// ARMEABISOFTFP:#define __INT_LEAST8_MAX__ 127
// ARMEABISOFTFP:#define __INT_LEAST8_TYPE__ signed char
// ARMEABISOFTFP:#define __INT_MAX__ 2147483647
// ARMEABISOFTFP:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
// ARMEABISOFTFP:#define __LDBL_DIG__ 15
// ARMEABISOFTFP:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
// ARMEABISOFTFP:#define __LDBL_HAS_DENORM__ 1
// ARMEABISOFTFP:#define __LDBL_HAS_INFINITY__ 1
// ARMEABISOFTFP:#define __LDBL_HAS_QUIET_NAN__ 1
// ARMEABISOFTFP:#define __LDBL_MANT_DIG__ 53
// ARMEABISOFTFP:#define __LDBL_MAX_10_EXP__ 308
// ARMEABISOFTFP:#define __LDBL_MAX_EXP__ 1024
// ARMEABISOFTFP:#define __LDBL_MAX__ 1.7976931348623157e+308L
// ARMEABISOFTFP:#define __LDBL_MIN_10_EXP__ (-307)
// ARMEABISOFTFP:#define __LDBL_MIN_EXP__ (-1021)
// ARMEABISOFTFP:#define __LDBL_MIN__ 2.2250738585072014e-308L
// ARMEABISOFTFP:#define __LITTLE_ENDIAN__ 1
// ARMEABISOFTFP:#define __LONG_LONG_MAX__ 9223372036854775807LL
// ARMEABISOFTFP:#define __LONG_MAX__ 2147483647L
// ARMEABISOFTFP-NOT:#define __LP64__
// ARMEABISOFTFP:#define __POINTER_WIDTH__ 32
// ARMEABISOFTFP:#define __PTRDIFF_TYPE__ int
// ARMEABISOFTFP:#define __PTRDIFF_WIDTH__ 32
// ARMEABISOFTFP:#define __REGISTER_PREFIX__
// ARMEABISOFTFP:#define __SCHAR_MAX__ 127
// ARMEABISOFTFP:#define __SHRT_MAX__ 32767
// ARMEABISOFTFP:#define __SIG_ATOMIC_MAX__ 2147483647
// ARMEABISOFTFP:#define __SIG_ATOMIC_WIDTH__ 32
// ARMEABISOFTFP:#define __SIZEOF_DOUBLE__ 8
// ARMEABISOFTFP:#define __SIZEOF_FLOAT__ 4
// ARMEABISOFTFP:#define __SIZEOF_INT__ 4
// ARMEABISOFTFP:#define __SIZEOF_LONG_DOUBLE__ 8
// ARMEABISOFTFP:#define __SIZEOF_LONG_LONG__ 8
// ARMEABISOFTFP:#define __SIZEOF_LONG__ 4
// ARMEABISOFTFP:#define __SIZEOF_POINTER__ 4
// ARMEABISOFTFP:#define __SIZEOF_PTRDIFF_T__ 4
// ARMEABISOFTFP:#define __SIZEOF_SHORT__ 2
// ARMEABISOFTFP:#define __SIZEOF_SIZE_T__ 4
// ARMEABISOFTFP:#define __SIZEOF_WCHAR_T__ 4
// ARMEABISOFTFP:#define __SIZEOF_WINT_T__ 4
// ARMEABISOFTFP:#define __SIZE_MAX__ 4294967295U
// ARMEABISOFTFP:#define __SIZE_TYPE__ unsigned int
// ARMEABISOFTFP:#define __SIZE_WIDTH__ 32
// ARMEABISOFTFP:#define __SOFTFP__ 1
// ARMEABISOFTFP:#define __UINT16_C_SUFFIX__
// ARMEABISOFTFP:#define __UINT16_MAX__ 65535
// ARMEABISOFTFP:#define __UINT16_TYPE__ unsigned short
// ARMEABISOFTFP:#define __UINT32_C_SUFFIX__ U
// ARMEABISOFTFP:#define __UINT32_MAX__ 4294967295U
// ARMEABISOFTFP:#define __UINT32_TYPE__ unsigned int
// ARMEABISOFTFP:#define __UINT64_C_SUFFIX__ ULL
// ARMEABISOFTFP:#define __UINT64_MAX__ 18446744073709551615ULL
// ARMEABISOFTFP:#define __UINT64_TYPE__ long long unsigned int
// ARMEABISOFTFP:#define __UINT8_C_SUFFIX__
// ARMEABISOFTFP:#define __UINT8_MAX__ 255
// ARMEABISOFTFP:#define __UINT8_TYPE__ unsigned char
// ARMEABISOFTFP:#define __UINTMAX_C_SUFFIX__ ULL
// ARMEABISOFTFP:#define __UINTMAX_MAX__ 18446744073709551615ULL
// ARMEABISOFTFP:#define __UINTMAX_TYPE__ long long unsigned int
// ARMEABISOFTFP:#define __UINTMAX_WIDTH__ 64
// ARMEABISOFTFP:#define __UINTPTR_MAX__ 4294967295U
// ARMEABISOFTFP:#define __UINTPTR_TYPE__ unsigned int
// ARMEABISOFTFP:#define __UINTPTR_WIDTH__ 32
// ARMEABISOFTFP:#define __UINT_FAST16_MAX__ 65535
// ARMEABISOFTFP:#define __UINT_FAST16_TYPE__ unsigned short
// ARMEABISOFTFP:#define __UINT_FAST32_MAX__ 4294967295U
// ARMEABISOFTFP:#define __UINT_FAST32_TYPE__ unsigned int
// ARMEABISOFTFP:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// ARMEABISOFTFP:#define __UINT_FAST64_TYPE__ long long unsigned int
// ARMEABISOFTFP:#define __UINT_FAST8_MAX__ 255
// ARMEABISOFTFP:#define __UINT_FAST8_TYPE__ unsigned char
// ARMEABISOFTFP:#define __UINT_LEAST16_MAX__ 65535
// ARMEABISOFTFP:#define __UINT_LEAST16_TYPE__ unsigned short
// ARMEABISOFTFP:#define __UINT_LEAST32_MAX__ 4294967295U
// ARMEABISOFTFP:#define __UINT_LEAST32_TYPE__ unsigned int
// ARMEABISOFTFP:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// ARMEABISOFTFP:#define __UINT_LEAST64_TYPE__ long long unsigned int
// ARMEABISOFTFP:#define __UINT_LEAST8_MAX__ 255
// ARMEABISOFTFP:#define __UINT_LEAST8_TYPE__ unsigned char
// ARMEABISOFTFP:#define __USER_LABEL_PREFIX__
// ARMEABISOFTFP:#define __WCHAR_MAX__ 4294967295U
// ARMEABISOFTFP:#define __WCHAR_TYPE__ unsigned int
// ARMEABISOFTFP:#define __WCHAR_WIDTH__ 32
// ARMEABISOFTFP:#define __WINT_TYPE__ unsigned int
// ARMEABISOFTFP:#define __WINT_WIDTH__ 32
// ARMEABISOFTFP:#define __arm 1
// ARMEABISOFTFP:#define __arm__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-none-linux-gnueabi < /dev/null | FileCheck -match-full-lines -check-prefix ARMEABIHARDFP %s
//
// ARMEABIHARDFP-NOT:#define _LP64
// ARMEABIHARDFP:#define __APCS_32__ 1
// ARMEABIHARDFP-NOT:#define __ARMEB__ 1
// ARMEABIHARDFP:#define __ARMEL__ 1
// ARMEABIHARDFP:#define __ARM_ARCH 4
// ARMEABIHARDFP:#define __ARM_ARCH_4T__ 1
// ARMEABIHARDFP-NOT:#define __ARM_BIG_ENDIAN 1
// ARMEABIHARDFP:#define __ARM_EABI__ 1
// ARMEABIHARDFP:#define __ARM_PCS 1
// ARMEABIHARDFP:#define __ARM_PCS_VFP 1
// ARMEABIHARDFP:#define __BIGGEST_ALIGNMENT__ 8
// ARMEABIHARDFP:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// ARMEABIHARDFP:#define __CHAR16_TYPE__ unsigned short
// ARMEABIHARDFP:#define __CHAR32_TYPE__ unsigned int
// ARMEABIHARDFP:#define __CHAR_BIT__ 8
// ARMEABIHARDFP:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// ARMEABIHARDFP:#define __DBL_DIG__ 15
// ARMEABIHARDFP:#define __DBL_EPSILON__ 2.2204460492503131e-16
// ARMEABIHARDFP:#define __DBL_HAS_DENORM__ 1
// ARMEABIHARDFP:#define __DBL_HAS_INFINITY__ 1
// ARMEABIHARDFP:#define __DBL_HAS_QUIET_NAN__ 1
// ARMEABIHARDFP:#define __DBL_MANT_DIG__ 53
// ARMEABIHARDFP:#define __DBL_MAX_10_EXP__ 308
// ARMEABIHARDFP:#define __DBL_MAX_EXP__ 1024
// ARMEABIHARDFP:#define __DBL_MAX__ 1.7976931348623157e+308
// ARMEABIHARDFP:#define __DBL_MIN_10_EXP__ (-307)
// ARMEABIHARDFP:#define __DBL_MIN_EXP__ (-1021)
// ARMEABIHARDFP:#define __DBL_MIN__ 2.2250738585072014e-308
// ARMEABIHARDFP:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// ARMEABIHARDFP:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// ARMEABIHARDFP:#define __FLT_DIG__ 6
// ARMEABIHARDFP:#define __FLT_EPSILON__ 1.19209290e-7F
// ARMEABIHARDFP:#define __FLT_EVAL_METHOD__ 0
// ARMEABIHARDFP:#define __FLT_HAS_DENORM__ 1
// ARMEABIHARDFP:#define __FLT_HAS_INFINITY__ 1
// ARMEABIHARDFP:#define __FLT_HAS_QUIET_NAN__ 1
// ARMEABIHARDFP:#define __FLT_MANT_DIG__ 24
// ARMEABIHARDFP:#define __FLT_MAX_10_EXP__ 38
// ARMEABIHARDFP:#define __FLT_MAX_EXP__ 128
// ARMEABIHARDFP:#define __FLT_MAX__ 3.40282347e+38F
// ARMEABIHARDFP:#define __FLT_MIN_10_EXP__ (-37)
// ARMEABIHARDFP:#define __FLT_MIN_EXP__ (-125)
// ARMEABIHARDFP:#define __FLT_MIN__ 1.17549435e-38F
// ARMEABIHARDFP:#define __FLT_RADIX__ 2
// ARMEABIHARDFP:#define __INT16_C_SUFFIX__
// ARMEABIHARDFP:#define __INT16_FMTd__ "hd"
// ARMEABIHARDFP:#define __INT16_FMTi__ "hi"
// ARMEABIHARDFP:#define __INT16_MAX__ 32767
// ARMEABIHARDFP:#define __INT16_TYPE__ short
// ARMEABIHARDFP:#define __INT32_C_SUFFIX__
// ARMEABIHARDFP:#define __INT32_FMTd__ "d"
// ARMEABIHARDFP:#define __INT32_FMTi__ "i"
// ARMEABIHARDFP:#define __INT32_MAX__ 2147483647
// ARMEABIHARDFP:#define __INT32_TYPE__ int
// ARMEABIHARDFP:#define __INT64_C_SUFFIX__ LL
// ARMEABIHARDFP:#define __INT64_FMTd__ "lld"
// ARMEABIHARDFP:#define __INT64_FMTi__ "lli"
// ARMEABIHARDFP:#define __INT64_MAX__ 9223372036854775807LL
// ARMEABIHARDFP:#define __INT64_TYPE__ long long int
// ARMEABIHARDFP:#define __INT8_C_SUFFIX__
// ARMEABIHARDFP:#define __INT8_FMTd__ "hhd"
// ARMEABIHARDFP:#define __INT8_FMTi__ "hhi"
// ARMEABIHARDFP:#define __INT8_MAX__ 127
// ARMEABIHARDFP:#define __INT8_TYPE__ signed char
// ARMEABIHARDFP:#define __INTMAX_C_SUFFIX__ LL
// ARMEABIHARDFP:#define __INTMAX_FMTd__ "lld"
// ARMEABIHARDFP:#define __INTMAX_FMTi__ "lli"
// ARMEABIHARDFP:#define __INTMAX_MAX__ 9223372036854775807LL
// ARMEABIHARDFP:#define __INTMAX_TYPE__ long long int
// ARMEABIHARDFP:#define __INTMAX_WIDTH__ 64
// ARMEABIHARDFP:#define __INTPTR_FMTd__ "d"
// ARMEABIHARDFP:#define __INTPTR_FMTi__ "i"
// ARMEABIHARDFP:#define __INTPTR_MAX__ 2147483647
// ARMEABIHARDFP:#define __INTPTR_TYPE__ int
// ARMEABIHARDFP:#define __INTPTR_WIDTH__ 32
// ARMEABIHARDFP:#define __INT_FAST16_FMTd__ "hd"
// ARMEABIHARDFP:#define __INT_FAST16_FMTi__ "hi"
// ARMEABIHARDFP:#define __INT_FAST16_MAX__ 32767
// ARMEABIHARDFP:#define __INT_FAST16_TYPE__ short
// ARMEABIHARDFP:#define __INT_FAST32_FMTd__ "d"
// ARMEABIHARDFP:#define __INT_FAST32_FMTi__ "i"
// ARMEABIHARDFP:#define __INT_FAST32_MAX__ 2147483647
// ARMEABIHARDFP:#define __INT_FAST32_TYPE__ int
// ARMEABIHARDFP:#define __INT_FAST64_FMTd__ "lld"
// ARMEABIHARDFP:#define __INT_FAST64_FMTi__ "lli"
// ARMEABIHARDFP:#define __INT_FAST64_MAX__ 9223372036854775807LL
// ARMEABIHARDFP:#define __INT_FAST64_TYPE__ long long int
// ARMEABIHARDFP:#define __INT_FAST8_FMTd__ "hhd"
// ARMEABIHARDFP:#define __INT_FAST8_FMTi__ "hhi"
// ARMEABIHARDFP:#define __INT_FAST8_MAX__ 127
// ARMEABIHARDFP:#define __INT_FAST8_TYPE__ signed char
// ARMEABIHARDFP:#define __INT_LEAST16_FMTd__ "hd"
// ARMEABIHARDFP:#define __INT_LEAST16_FMTi__ "hi"
// ARMEABIHARDFP:#define __INT_LEAST16_MAX__ 32767
// ARMEABIHARDFP:#define __INT_LEAST16_TYPE__ short
// ARMEABIHARDFP:#define __INT_LEAST32_FMTd__ "d"
// ARMEABIHARDFP:#define __INT_LEAST32_FMTi__ "i"
// ARMEABIHARDFP:#define __INT_LEAST32_MAX__ 2147483647
// ARMEABIHARDFP:#define __INT_LEAST32_TYPE__ int
// ARMEABIHARDFP:#define __INT_LEAST64_FMTd__ "lld"
// ARMEABIHARDFP:#define __INT_LEAST64_FMTi__ "lli"
// ARMEABIHARDFP:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// ARMEABIHARDFP:#define __INT_LEAST64_TYPE__ long long int
// ARMEABIHARDFP:#define __INT_LEAST8_FMTd__ "hhd"
// ARMEABIHARDFP:#define __INT_LEAST8_FMTi__ "hhi"
// ARMEABIHARDFP:#define __INT_LEAST8_MAX__ 127
// ARMEABIHARDFP:#define __INT_LEAST8_TYPE__ signed char
// ARMEABIHARDFP:#define __INT_MAX__ 2147483647
// ARMEABIHARDFP:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
// ARMEABIHARDFP:#define __LDBL_DIG__ 15
// ARMEABIHARDFP:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
// ARMEABIHARDFP:#define __LDBL_HAS_DENORM__ 1
// ARMEABIHARDFP:#define __LDBL_HAS_INFINITY__ 1
// ARMEABIHARDFP:#define __LDBL_HAS_QUIET_NAN__ 1
// ARMEABIHARDFP:#define __LDBL_MANT_DIG__ 53
// ARMEABIHARDFP:#define __LDBL_MAX_10_EXP__ 308
// ARMEABIHARDFP:#define __LDBL_MAX_EXP__ 1024
// ARMEABIHARDFP:#define __LDBL_MAX__ 1.7976931348623157e+308L
// ARMEABIHARDFP:#define __LDBL_MIN_10_EXP__ (-307)
// ARMEABIHARDFP:#define __LDBL_MIN_EXP__ (-1021)
// ARMEABIHARDFP:#define __LDBL_MIN__ 2.2250738585072014e-308L
// ARMEABIHARDFP:#define __LITTLE_ENDIAN__ 1
// ARMEABIHARDFP:#define __LONG_LONG_MAX__ 9223372036854775807LL
// ARMEABIHARDFP:#define __LONG_MAX__ 2147483647L
// ARMEABIHARDFP-NOT:#define __LP64__
// ARMEABIHARDFP:#define __POINTER_WIDTH__ 32
// ARMEABIHARDFP:#define __PTRDIFF_TYPE__ int
// ARMEABIHARDFP:#define __PTRDIFF_WIDTH__ 32
// ARMEABIHARDFP:#define __REGISTER_PREFIX__
// ARMEABIHARDFP:#define __SCHAR_MAX__ 127
// ARMEABIHARDFP:#define __SHRT_MAX__ 32767
// ARMEABIHARDFP:#define __SIG_ATOMIC_MAX__ 2147483647
// ARMEABIHARDFP:#define __SIG_ATOMIC_WIDTH__ 32
// ARMEABIHARDFP:#define __SIZEOF_DOUBLE__ 8
// ARMEABIHARDFP:#define __SIZEOF_FLOAT__ 4
// ARMEABIHARDFP:#define __SIZEOF_INT__ 4
// ARMEABIHARDFP:#define __SIZEOF_LONG_DOUBLE__ 8
// ARMEABIHARDFP:#define __SIZEOF_LONG_LONG__ 8
// ARMEABIHARDFP:#define __SIZEOF_LONG__ 4
// ARMEABIHARDFP:#define __SIZEOF_POINTER__ 4
// ARMEABIHARDFP:#define __SIZEOF_PTRDIFF_T__ 4
// ARMEABIHARDFP:#define __SIZEOF_SHORT__ 2
// ARMEABIHARDFP:#define __SIZEOF_SIZE_T__ 4
// ARMEABIHARDFP:#define __SIZEOF_WCHAR_T__ 4
// ARMEABIHARDFP:#define __SIZEOF_WINT_T__ 4
// ARMEABIHARDFP:#define __SIZE_MAX__ 4294967295U
// ARMEABIHARDFP:#define __SIZE_TYPE__ unsigned int
// ARMEABIHARDFP:#define __SIZE_WIDTH__ 32
// ARMEABIHARDFP-NOT:#define __SOFTFP__ 1
// ARMEABIHARDFP:#define __UINT16_C_SUFFIX__
// ARMEABIHARDFP:#define __UINT16_MAX__ 65535
// ARMEABIHARDFP:#define __UINT16_TYPE__ unsigned short
// ARMEABIHARDFP:#define __UINT32_C_SUFFIX__ U
// ARMEABIHARDFP:#define __UINT32_MAX__ 4294967295U
// ARMEABIHARDFP:#define __UINT32_TYPE__ unsigned int
// ARMEABIHARDFP:#define __UINT64_C_SUFFIX__ ULL
// ARMEABIHARDFP:#define __UINT64_MAX__ 18446744073709551615ULL
// ARMEABIHARDFP:#define __UINT64_TYPE__ long long unsigned int
// ARMEABIHARDFP:#define __UINT8_C_SUFFIX__
// ARMEABIHARDFP:#define __UINT8_MAX__ 255
// ARMEABIHARDFP:#define __UINT8_TYPE__ unsigned char
// ARMEABIHARDFP:#define __UINTMAX_C_SUFFIX__ ULL
// ARMEABIHARDFP:#define __UINTMAX_MAX__ 18446744073709551615ULL
// ARMEABIHARDFP:#define __UINTMAX_TYPE__ long long unsigned int
// ARMEABIHARDFP:#define __UINTMAX_WIDTH__ 64
// ARMEABIHARDFP:#define __UINTPTR_MAX__ 4294967295U
// ARMEABIHARDFP:#define __UINTPTR_TYPE__ unsigned int
// ARMEABIHARDFP:#define __UINTPTR_WIDTH__ 32
// ARMEABIHARDFP:#define __UINT_FAST16_MAX__ 65535
// ARMEABIHARDFP:#define __UINT_FAST16_TYPE__ unsigned short
// ARMEABIHARDFP:#define __UINT_FAST32_MAX__ 4294967295U
// ARMEABIHARDFP:#define __UINT_FAST32_TYPE__ unsigned int
// ARMEABIHARDFP:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// ARMEABIHARDFP:#define __UINT_FAST64_TYPE__ long long unsigned int
// ARMEABIHARDFP:#define __UINT_FAST8_MAX__ 255
// ARMEABIHARDFP:#define __UINT_FAST8_TYPE__ unsigned char
// ARMEABIHARDFP:#define __UINT_LEAST16_MAX__ 65535
// ARMEABIHARDFP:#define __UINT_LEAST16_TYPE__ unsigned short
// ARMEABIHARDFP:#define __UINT_LEAST32_MAX__ 4294967295U
// ARMEABIHARDFP:#define __UINT_LEAST32_TYPE__ unsigned int
// ARMEABIHARDFP:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// ARMEABIHARDFP:#define __UINT_LEAST64_TYPE__ long long unsigned int
// ARMEABIHARDFP:#define __UINT_LEAST8_MAX__ 255
// ARMEABIHARDFP:#define __UINT_LEAST8_TYPE__ unsigned char
// ARMEABIHARDFP:#define __USER_LABEL_PREFIX__
// ARMEABIHARDFP:#define __WCHAR_MAX__ 4294967295U
// ARMEABIHARDFP:#define __WCHAR_TYPE__ unsigned int
// ARMEABIHARDFP:#define __WCHAR_WIDTH__ 32
// ARMEABIHARDFP:#define __WINT_TYPE__ unsigned int
// ARMEABIHARDFP:#define __WINT_WIDTH__ 32
// ARMEABIHARDFP:#define __arm 1
// ARMEABIHARDFP:#define __arm__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=armv6-unknown-cloudabi-eabihf < /dev/null | FileCheck -match-full-lines -check-prefix ARMV6-CLOUDABI %s
//
// ARMV6-CLOUDABI:#define __CloudABI__ 1
// ARMV6-CLOUDABI:#define __arm__ 1
// RUN: %clang -E -dM -ffreestanding -target arm-netbsd-eabi %s -o - | FileCheck -match-full-lines -check-prefix ARM-NETBSD %s
// ARM-NETBSD-NOT:#define _LP64
// ARM-NETBSD:#define __APCS_32__ 1
// ARM-NETBSD-NOT:#define __ARMEB__ 1
// ARM-NETBSD:#define __ARMEL__ 1
// ARM-NETBSD:#define __ARM_ARCH_5TE__ 1
// ARM-NETBSD:#define __ARM_DWARF_EH__ 1
// ARM-NETBSD:#define __ARM_EABI__ 1
// ARM-NETBSD-NOT:#define __ARM_BIG_ENDIAN 1
// ARM-NETBSD:#define __BIGGEST_ALIGNMENT__ 8
// ARM-NETBSD:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// ARM-NETBSD:#define __CHAR16_TYPE__ unsigned short
// ARM-NETBSD:#define __CHAR32_TYPE__ unsigned int
// ARM-NETBSD:#define __CHAR_BIT__ 8
// ARM-NETBSD:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// ARM-NETBSD:#define __DBL_DIG__ 15
// ARM-NETBSD:#define __DBL_EPSILON__ 2.2204460492503131e-16
// ARM-NETBSD:#define __DBL_HAS_DENORM__ 1
// ARM-NETBSD:#define __DBL_HAS_INFINITY__ 1
// ARM-NETBSD:#define __DBL_HAS_QUIET_NAN__ 1
// ARM-NETBSD:#define __DBL_MANT_DIG__ 53
// ARM-NETBSD:#define __DBL_MAX_10_EXP__ 308
// ARM-NETBSD:#define __DBL_MAX_EXP__ 1024
// ARM-NETBSD:#define __DBL_MAX__ 1.7976931348623157e+308
// ARM-NETBSD:#define __DBL_MIN_10_EXP__ (-307)
// ARM-NETBSD:#define __DBL_MIN_EXP__ (-1021)
// ARM-NETBSD:#define __DBL_MIN__ 2.2250738585072014e-308
// ARM-NETBSD:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// ARM-NETBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// ARM-NETBSD:#define __FLT_DIG__ 6
// ARM-NETBSD:#define __FLT_EPSILON__ 1.19209290e-7F
// ARM-NETBSD:#define __FLT_EVAL_METHOD__ 0
// ARM-NETBSD:#define __FLT_HAS_DENORM__ 1
// ARM-NETBSD:#define __FLT_HAS_INFINITY__ 1
// ARM-NETBSD:#define __FLT_HAS_QUIET_NAN__ 1
// ARM-NETBSD:#define __FLT_MANT_DIG__ 24
// ARM-NETBSD:#define __FLT_MAX_10_EXP__ 38
// ARM-NETBSD:#define __FLT_MAX_EXP__ 128
// ARM-NETBSD:#define __FLT_MAX__ 3.40282347e+38F
// ARM-NETBSD:#define __FLT_MIN_10_EXP__ (-37)
// ARM-NETBSD:#define __FLT_MIN_EXP__ (-125)
// ARM-NETBSD:#define __FLT_MIN__ 1.17549435e-38F
// ARM-NETBSD:#define __FLT_RADIX__ 2
// ARM-NETBSD:#define __INT16_C_SUFFIX__
// ARM-NETBSD:#define __INT16_FMTd__ "hd"
// ARM-NETBSD:#define __INT16_FMTi__ "hi"
// ARM-NETBSD:#define __INT16_MAX__ 32767
// ARM-NETBSD:#define __INT16_TYPE__ short
// ARM-NETBSD:#define __INT32_C_SUFFIX__
// ARM-NETBSD:#define __INT32_FMTd__ "d"
// ARM-NETBSD:#define __INT32_FMTi__ "i"
// ARM-NETBSD:#define __INT32_MAX__ 2147483647
// ARM-NETBSD:#define __INT32_TYPE__ int
// ARM-NETBSD:#define __INT64_C_SUFFIX__ LL
// ARM-NETBSD:#define __INT64_FMTd__ "lld"
// ARM-NETBSD:#define __INT64_FMTi__ "lli"
// ARM-NETBSD:#define __INT64_MAX__ 9223372036854775807LL
// ARM-NETBSD:#define __INT64_TYPE__ long long int
// ARM-NETBSD:#define __INT8_C_SUFFIX__
// ARM-NETBSD:#define __INT8_FMTd__ "hhd"
// ARM-NETBSD:#define __INT8_FMTi__ "hhi"
// ARM-NETBSD:#define __INT8_MAX__ 127
// ARM-NETBSD:#define __INT8_TYPE__ signed char
// ARM-NETBSD:#define __INTMAX_C_SUFFIX__ LL
// ARM-NETBSD:#define __INTMAX_FMTd__ "lld"
// ARM-NETBSD:#define __INTMAX_FMTi__ "lli"
// ARM-NETBSD:#define __INTMAX_MAX__ 9223372036854775807LL
// ARM-NETBSD:#define __INTMAX_TYPE__ long long int
// ARM-NETBSD:#define __INTMAX_WIDTH__ 64
// ARM-NETBSD:#define __INTPTR_FMTd__ "ld"
// ARM-NETBSD:#define __INTPTR_FMTi__ "li"
// ARM-NETBSD:#define __INTPTR_MAX__ 2147483647L
// ARM-NETBSD:#define __INTPTR_TYPE__ long int
// ARM-NETBSD:#define __INTPTR_WIDTH__ 32
// ARM-NETBSD:#define __INT_FAST16_FMTd__ "hd"
// ARM-NETBSD:#define __INT_FAST16_FMTi__ "hi"
// ARM-NETBSD:#define __INT_FAST16_MAX__ 32767
// ARM-NETBSD:#define __INT_FAST16_TYPE__ short
// ARM-NETBSD:#define __INT_FAST32_FMTd__ "d"
// ARM-NETBSD:#define __INT_FAST32_FMTi__ "i"
// ARM-NETBSD:#define __INT_FAST32_MAX__ 2147483647
// ARM-NETBSD:#define __INT_FAST32_TYPE__ int
// ARM-NETBSD:#define __INT_FAST64_FMTd__ "lld"
// ARM-NETBSD:#define __INT_FAST64_FMTi__ "lli"
// ARM-NETBSD:#define __INT_FAST64_MAX__ 9223372036854775807LL
// ARM-NETBSD:#define __INT_FAST64_TYPE__ long long int
// ARM-NETBSD:#define __INT_FAST8_FMTd__ "hhd"
// ARM-NETBSD:#define __INT_FAST8_FMTi__ "hhi"
// ARM-NETBSD:#define __INT_FAST8_MAX__ 127
// ARM-NETBSD:#define __INT_FAST8_TYPE__ signed char
// ARM-NETBSD:#define __INT_LEAST16_FMTd__ "hd"
// ARM-NETBSD:#define __INT_LEAST16_FMTi__ "hi"
// ARM-NETBSD:#define __INT_LEAST16_MAX__ 32767
// ARM-NETBSD:#define __INT_LEAST16_TYPE__ short
// ARM-NETBSD:#define __INT_LEAST32_FMTd__ "d"
// ARM-NETBSD:#define __INT_LEAST32_FMTi__ "i"
// ARM-NETBSD:#define __INT_LEAST32_MAX__ 2147483647
// ARM-NETBSD:#define __INT_LEAST32_TYPE__ int
// ARM-NETBSD:#define __INT_LEAST64_FMTd__ "lld"
// ARM-NETBSD:#define __INT_LEAST64_FMTi__ "lli"
// ARM-NETBSD:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// ARM-NETBSD:#define __INT_LEAST64_TYPE__ long long int
// ARM-NETBSD:#define __INT_LEAST8_FMTd__ "hhd"
// ARM-NETBSD:#define __INT_LEAST8_FMTi__ "hhi"
// ARM-NETBSD:#define __INT_LEAST8_MAX__ 127
// ARM-NETBSD:#define __INT_LEAST8_TYPE__ signed char
// ARM-NETBSD:#define __INT_MAX__ 2147483647
// ARM-NETBSD:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
// ARM-NETBSD:#define __LDBL_DIG__ 15
// ARM-NETBSD:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
// ARM-NETBSD:#define __LDBL_HAS_DENORM__ 1
// ARM-NETBSD:#define __LDBL_HAS_INFINITY__ 1
// ARM-NETBSD:#define __LDBL_HAS_QUIET_NAN__ 1
// ARM-NETBSD:#define __LDBL_MANT_DIG__ 53
// ARM-NETBSD:#define __LDBL_MAX_10_EXP__ 308
// ARM-NETBSD:#define __LDBL_MAX_EXP__ 1024
// ARM-NETBSD:#define __LDBL_MAX__ 1.7976931348623157e+308L
// ARM-NETBSD:#define __LDBL_MIN_10_EXP__ (-307)
// ARM-NETBSD:#define __LDBL_MIN_EXP__ (-1021)
// ARM-NETBSD:#define __LDBL_MIN__ 2.2250738585072014e-308L
// ARM-NETBSD:#define __LITTLE_ENDIAN__ 1
// ARM-NETBSD:#define __LONG_LONG_MAX__ 9223372036854775807LL
// ARM-NETBSD:#define __LONG_MAX__ 2147483647L
// ARM-NETBSD-NOT:#define __LP64__
// ARM-NETBSD:#define __POINTER_WIDTH__ 32
// ARM-NETBSD:#define __PTRDIFF_TYPE__ long int
// ARM-NETBSD:#define __PTRDIFF_WIDTH__ 32
// ARM-NETBSD:#define __REGISTER_PREFIX__
// ARM-NETBSD:#define __SCHAR_MAX__ 127
// ARM-NETBSD:#define __SHRT_MAX__ 32767
// ARM-NETBSD:#define __SIG_ATOMIC_MAX__ 2147483647
// ARM-NETBSD:#define __SIG_ATOMIC_WIDTH__ 32
// ARM-NETBSD:#define __SIZEOF_DOUBLE__ 8
// ARM-NETBSD:#define __SIZEOF_FLOAT__ 4
// ARM-NETBSD:#define __SIZEOF_INT__ 4
// ARM-NETBSD:#define __SIZEOF_LONG_DOUBLE__ 8
// ARM-NETBSD:#define __SIZEOF_LONG_LONG__ 8
// ARM-NETBSD:#define __SIZEOF_LONG__ 4
// ARM-NETBSD:#define __SIZEOF_POINTER__ 4
// ARM-NETBSD:#define __SIZEOF_PTRDIFF_T__ 4
// ARM-NETBSD:#define __SIZEOF_SHORT__ 2
// ARM-NETBSD:#define __SIZEOF_SIZE_T__ 4
// ARM-NETBSD:#define __SIZEOF_WCHAR_T__ 4
// ARM-NETBSD:#define __SIZEOF_WINT_T__ 4
// ARM-NETBSD:#define __SIZE_MAX__ 4294967295UL
// ARM-NETBSD:#define __SIZE_TYPE__ long unsigned int
// ARM-NETBSD:#define __SIZE_WIDTH__ 32
// ARM-NETBSD:#define __SOFTFP__ 1
// ARM-NETBSD:#define __UINT16_C_SUFFIX__
// ARM-NETBSD:#define __UINT16_MAX__ 65535
// ARM-NETBSD:#define __UINT16_TYPE__ unsigned short
// ARM-NETBSD:#define __UINT32_C_SUFFIX__ U
// ARM-NETBSD:#define __UINT32_MAX__ 4294967295U
// ARM-NETBSD:#define __UINT32_TYPE__ unsigned int
// ARM-NETBSD:#define __UINT64_C_SUFFIX__ ULL
// ARM-NETBSD:#define __UINT64_MAX__ 18446744073709551615ULL
// ARM-NETBSD:#define __UINT64_TYPE__ long long unsigned int
// ARM-NETBSD:#define __UINT8_C_SUFFIX__
// ARM-NETBSD:#define __UINT8_MAX__ 255
// ARM-NETBSD:#define __UINT8_TYPE__ unsigned char
// ARM-NETBSD:#define __UINTMAX_C_SUFFIX__ ULL
// ARM-NETBSD:#define __UINTMAX_MAX__ 18446744073709551615ULL
// ARM-NETBSD:#define __UINTMAX_TYPE__ long long unsigned int
// ARM-NETBSD:#define __UINTMAX_WIDTH__ 64
// ARM-NETBSD:#define __UINTPTR_MAX__ 4294967295UL
// ARM-NETBSD:#define __UINTPTR_TYPE__ long unsigned int
// ARM-NETBSD:#define __UINTPTR_WIDTH__ 32
// ARM-NETBSD:#define __UINT_FAST16_MAX__ 65535
// ARM-NETBSD:#define __UINT_FAST16_TYPE__ unsigned short
// ARM-NETBSD:#define __UINT_FAST32_MAX__ 4294967295U
// ARM-NETBSD:#define __UINT_FAST32_TYPE__ unsigned int
// ARM-NETBSD:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// ARM-NETBSD:#define __UINT_FAST64_TYPE__ long long unsigned int
// ARM-NETBSD:#define __UINT_FAST8_MAX__ 255
// ARM-NETBSD:#define __UINT_FAST8_TYPE__ unsigned char
// ARM-NETBSD:#define __UINT_LEAST16_MAX__ 65535
// ARM-NETBSD:#define __UINT_LEAST16_TYPE__ unsigned short
// ARM-NETBSD:#define __UINT_LEAST32_MAX__ 4294967295U
// ARM-NETBSD:#define __UINT_LEAST32_TYPE__ unsigned int
// ARM-NETBSD:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// ARM-NETBSD:#define __UINT_LEAST64_TYPE__ long long unsigned int
// ARM-NETBSD:#define __UINT_LEAST8_MAX__ 255
// ARM-NETBSD:#define __UINT_LEAST8_TYPE__ unsigned char
// ARM-NETBSD:#define __USER_LABEL_PREFIX__
// ARM-NETBSD:#define __WCHAR_MAX__ 2147483647
// ARM-NETBSD:#define __WCHAR_TYPE__ int
// ARM-NETBSD:#define __WCHAR_WIDTH__ 32
// ARM-NETBSD:#define __WINT_TYPE__ int
// ARM-NETBSD:#define __WINT_WIDTH__ 32
// ARM-NETBSD:#define __arm 1
// ARM-NETBSD:#define __arm__ 1
// RUN: %clang -E -dM -ffreestanding -target arm-netbsd-eabihf %s -o - | FileCheck -match-full-lines -check-prefix ARMHF-NETBSD %s
// ARMHF-NETBSD:#define __SIZE_WIDTH__ 32
// ARMHF-NETBSD-NOT:#define __SOFTFP__ 1
// ARMHF-NETBSD:#define __UINT16_C_SUFFIX__
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-none-eabi < /dev/null | FileCheck -match-full-lines -check-prefix ARM-NONE-EABI %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-none-eabihf < /dev/null | FileCheck -match-full-lines -check-prefix ARM-NONE-EABI %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-none-eabi < /dev/null | FileCheck -match-full-lines -check-prefix ARM-NONE-EABI %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-none-eabihf < /dev/null | FileCheck -match-full-lines -check-prefix ARM-NONE-EABI %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-none-elf < /dev/null | FileCheck -match-full-lines -check-prefix ARM-NONE-EABI %s
// ARM-NONE-EABI: #define __ELF__ 1
// No MachO targets use the full EABI, even if AAPCS is used.
// RUN: %clang -target x86_64-apple-darwin -arch armv7s -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARM-MACHO-NO-EABI %s
// RUN: %clang -target x86_64-apple-darwin -arch armv6m -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARM-MACHO-NO-EABI %s
// RUN: %clang -target x86_64-apple-darwin -arch armv7m -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARM-MACHO-NO-EABI %s
// RUN: %clang -target x86_64-apple-darwin -arch armv7em -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARM-MACHO-NO-EABI %s
// RUN: %clang -target x86_64-apple-darwin -arch armv7 -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARM-MACHO-NO-EABI %s
// ARM-MACHO-NO-EABI-NOT: #define __ARM_EABI__ 1
// Check that -mhwdiv works properly for targets which don't have the hwdiv feature enabled by default.
// RUN: %clang -target arm -mhwdiv=arm -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMHWDIV-ARM %s
// ARMHWDIV-ARM:#define __ARM_ARCH_EXT_IDIV__ 1
// RUN: %clang -target arm -mthumb -mhwdiv=thumb -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=THUMBHWDIV-THUMB %s
// THUMBHWDIV-THUMB:#define __ARM_ARCH_EXT_IDIV__ 1
// RUN: %clang -target arm -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARM-FALSE %s
// ARM-FALSE-NOT:#define __ARM_ARCH_EXT_IDIV__
// RUN: %clang -target arm -mthumb -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=THUMB-FALSE %s
// THUMB-FALSE-NOT:#define __ARM_ARCH_EXT_IDIV__
// RUN: %clang -target arm -mhwdiv=thumb -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=THUMBHWDIV-ARM-FALSE %s
// THUMBHWDIV-ARM-FALSE-NOT:#define __ARM_ARCH_EXT_IDIV__
// RUN: %clang -target arm -mthumb -mhwdiv=arm -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=ARMHWDIV-THUMB-FALSE %s
// ARMHWDIV-THUMB-FALSE-NOT:#define __ARM_ARCH_EXT_IDIV__
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=armv8-none-none < /dev/null | FileCheck -match-full-lines -check-prefix ARMv8 %s
// ARMv8: #define __THUMB_INTERWORK__ 1
// ARMv8-NOT: #define __thumb2__
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=armebv8-none-none < /dev/null | FileCheck -match-full-lines -check-prefix ARMebv8 %s
// ARMebv8: #define __THUMB_INTERWORK__ 1
// ARMebv8-NOT: #define __thumb2__
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=thumbv8 < /dev/null | FileCheck -match-full-lines -check-prefix Thumbv8 %s
// Thumbv8: #define __THUMB_INTERWORK__ 1
// Thumbv8: #define __thumb2__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=thumbebv8 < /dev/null | FileCheck -match-full-lines -check-prefix Thumbebv8 %s
// Thumbebv8: #define __THUMB_INTERWORK__ 1
// Thumbebv8: #define __thumb2__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=thumbv5 < /dev/null | FileCheck -match-full-lines -check-prefix Thumbv5 %s
// Thumbv5: #define __THUMB_INTERWORK__ 1
// Thumbv5-NOT: #define __thumb2__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=thumbv6t2 < /dev/null | FileCheck -match-full-lines -check-prefix Thumbv6t2 %s
// Thumbv6t2: #define __THUMB_INTERWORK__ 1
// Thumbv6t2: #define __thumb2__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=thumbv7 < /dev/null | FileCheck -match-full-lines -check-prefix Thumbv7 %s
// Thumbv7: #define __THUMB_INTERWORK__ 1
// Thumbv7: #define __thumb2__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=thumbebv7 < /dev/null | FileCheck -match-full-lines -check-prefix Thumbebv7 %s
// Thumbebv7: #define __THUMB_INTERWORK__ 1
// Thumbebv7: #define __thumb2__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=thumbv7-pc-windows-gnu -fdwarf-exceptions %s -o - | FileCheck -match-full-lines -check-prefix THUMB-MINGW %s
// THUMB-MINGW:#define __ARM_DWARF_EH__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-none-none < /dev/null | FileCheck -match-full-lines -check-prefix I386 %s
//
// I386-NOT:#define _LP64
// I386:#define __BIGGEST_ALIGNMENT__ 16
// I386:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// I386:#define __CHAR16_TYPE__ unsigned short
// I386:#define __CHAR32_TYPE__ unsigned int
// I386:#define __CHAR_BIT__ 8
// I386:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// I386:#define __DBL_DIG__ 15
// I386:#define __DBL_EPSILON__ 2.2204460492503131e-16
// I386:#define __DBL_HAS_DENORM__ 1
// I386:#define __DBL_HAS_INFINITY__ 1
// I386:#define __DBL_HAS_QUIET_NAN__ 1
// I386:#define __DBL_MANT_DIG__ 53
// I386:#define __DBL_MAX_10_EXP__ 308
// I386:#define __DBL_MAX_EXP__ 1024
// I386:#define __DBL_MAX__ 1.7976931348623157e+308
// I386:#define __DBL_MIN_10_EXP__ (-307)
// I386:#define __DBL_MIN_EXP__ (-1021)
// I386:#define __DBL_MIN__ 2.2250738585072014e-308
// I386:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// I386:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// I386:#define __FLT_DIG__ 6
// I386:#define __FLT_EPSILON__ 1.19209290e-7F
// I386:#define __FLT_EVAL_METHOD__ 2
// I386:#define __FLT_HAS_DENORM__ 1
// I386:#define __FLT_HAS_INFINITY__ 1
// I386:#define __FLT_HAS_QUIET_NAN__ 1
// I386:#define __FLT_MANT_DIG__ 24
// I386:#define __FLT_MAX_10_EXP__ 38
// I386:#define __FLT_MAX_EXP__ 128
// I386:#define __FLT_MAX__ 3.40282347e+38F
// I386:#define __FLT_MIN_10_EXP__ (-37)
// I386:#define __FLT_MIN_EXP__ (-125)
// I386:#define __FLT_MIN__ 1.17549435e-38F
// I386:#define __FLT_RADIX__ 2
// I386:#define __INT16_C_SUFFIX__
// I386:#define __INT16_FMTd__ "hd"
// I386:#define __INT16_FMTi__ "hi"
// I386:#define __INT16_MAX__ 32767
// I386:#define __INT16_TYPE__ short
// I386:#define __INT32_C_SUFFIX__
// I386:#define __INT32_FMTd__ "d"
// I386:#define __INT32_FMTi__ "i"
// I386:#define __INT32_MAX__ 2147483647
// I386:#define __INT32_TYPE__ int
// I386:#define __INT64_C_SUFFIX__ LL
// I386:#define __INT64_FMTd__ "lld"
// I386:#define __INT64_FMTi__ "lli"
// I386:#define __INT64_MAX__ 9223372036854775807LL
// I386:#define __INT64_TYPE__ long long int
// I386:#define __INT8_C_SUFFIX__
// I386:#define __INT8_FMTd__ "hhd"
// I386:#define __INT8_FMTi__ "hhi"
// I386:#define __INT8_MAX__ 127
// I386:#define __INT8_TYPE__ signed char
// I386:#define __INTMAX_C_SUFFIX__ LL
// I386:#define __INTMAX_FMTd__ "lld"
// I386:#define __INTMAX_FMTi__ "lli"
// I386:#define __INTMAX_MAX__ 9223372036854775807LL
// I386:#define __INTMAX_TYPE__ long long int
// I386:#define __INTMAX_WIDTH__ 64
// I386:#define __INTPTR_FMTd__ "d"
// I386:#define __INTPTR_FMTi__ "i"
// I386:#define __INTPTR_MAX__ 2147483647
// I386:#define __INTPTR_TYPE__ int
// I386:#define __INTPTR_WIDTH__ 32
// I386:#define __INT_FAST16_FMTd__ "hd"
// I386:#define __INT_FAST16_FMTi__ "hi"
// I386:#define __INT_FAST16_MAX__ 32767
// I386:#define __INT_FAST16_TYPE__ short
// I386:#define __INT_FAST32_FMTd__ "d"
// I386:#define __INT_FAST32_FMTi__ "i"
// I386:#define __INT_FAST32_MAX__ 2147483647
// I386:#define __INT_FAST32_TYPE__ int
// I386:#define __INT_FAST64_FMTd__ "lld"
// I386:#define __INT_FAST64_FMTi__ "lli"
// I386:#define __INT_FAST64_MAX__ 9223372036854775807LL
// I386:#define __INT_FAST64_TYPE__ long long int
// I386:#define __INT_FAST8_FMTd__ "hhd"
// I386:#define __INT_FAST8_FMTi__ "hhi"
// I386:#define __INT_FAST8_MAX__ 127
// I386:#define __INT_FAST8_TYPE__ signed char
// I386:#define __INT_LEAST16_FMTd__ "hd"
// I386:#define __INT_LEAST16_FMTi__ "hi"
// I386:#define __INT_LEAST16_MAX__ 32767
// I386:#define __INT_LEAST16_TYPE__ short
// I386:#define __INT_LEAST32_FMTd__ "d"
// I386:#define __INT_LEAST32_FMTi__ "i"
// I386:#define __INT_LEAST32_MAX__ 2147483647
// I386:#define __INT_LEAST32_TYPE__ int
// I386:#define __INT_LEAST64_FMTd__ "lld"
// I386:#define __INT_LEAST64_FMTi__ "lli"
// I386:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// I386:#define __INT_LEAST64_TYPE__ long long int
// I386:#define __INT_LEAST8_FMTd__ "hhd"
// I386:#define __INT_LEAST8_FMTi__ "hhi"
// I386:#define __INT_LEAST8_MAX__ 127
// I386:#define __INT_LEAST8_TYPE__ signed char
// I386:#define __INT_MAX__ 2147483647
// I386:#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
// I386:#define __LDBL_DIG__ 18
// I386:#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
// I386:#define __LDBL_HAS_DENORM__ 1
// I386:#define __LDBL_HAS_INFINITY__ 1
// I386:#define __LDBL_HAS_QUIET_NAN__ 1
// I386:#define __LDBL_MANT_DIG__ 64
// I386:#define __LDBL_MAX_10_EXP__ 4932
// I386:#define __LDBL_MAX_EXP__ 16384
// I386:#define __LDBL_MAX__ 1.18973149535723176502e+4932L
// I386:#define __LDBL_MIN_10_EXP__ (-4931)
// I386:#define __LDBL_MIN_EXP__ (-16381)
// I386:#define __LDBL_MIN__ 3.36210314311209350626e-4932L
// I386:#define __LITTLE_ENDIAN__ 1
// I386:#define __LONG_LONG_MAX__ 9223372036854775807LL
// I386:#define __LONG_MAX__ 2147483647L
// I386-NOT:#define __LP64__
// I386:#define __NO_MATH_INLINES 1
// I386:#define __POINTER_WIDTH__ 32
// I386:#define __PTRDIFF_TYPE__ int
// I386:#define __PTRDIFF_WIDTH__ 32
// I386:#define __REGISTER_PREFIX__
// I386:#define __SCHAR_MAX__ 127
// I386:#define __SHRT_MAX__ 32767
// I386:#define __SIG_ATOMIC_MAX__ 2147483647
// I386:#define __SIG_ATOMIC_WIDTH__ 32
// I386:#define __SIZEOF_DOUBLE__ 8
// I386:#define __SIZEOF_FLOAT__ 4
// I386:#define __SIZEOF_INT__ 4
// I386:#define __SIZEOF_LONG_DOUBLE__ 12
// I386:#define __SIZEOF_LONG_LONG__ 8
// I386:#define __SIZEOF_LONG__ 4
// I386:#define __SIZEOF_POINTER__ 4
// I386:#define __SIZEOF_PTRDIFF_T__ 4
// I386:#define __SIZEOF_SHORT__ 2
// I386:#define __SIZEOF_SIZE_T__ 4
// I386:#define __SIZEOF_WCHAR_T__ 4
// I386:#define __SIZEOF_WINT_T__ 4
// I386:#define __SIZE_MAX__ 4294967295U
// I386:#define __SIZE_TYPE__ unsigned int
// I386:#define __SIZE_WIDTH__ 32
// I386:#define __UINT16_C_SUFFIX__
// I386:#define __UINT16_MAX__ 65535
// I386:#define __UINT16_TYPE__ unsigned short
// I386:#define __UINT32_C_SUFFIX__ U
// I386:#define __UINT32_MAX__ 4294967295U
// I386:#define __UINT32_TYPE__ unsigned int
// I386:#define __UINT64_C_SUFFIX__ ULL
// I386:#define __UINT64_MAX__ 18446744073709551615ULL
// I386:#define __UINT64_TYPE__ long long unsigned int
// I386:#define __UINT8_C_SUFFIX__
// I386:#define __UINT8_MAX__ 255
// I386:#define __UINT8_TYPE__ unsigned char
// I386:#define __UINTMAX_C_SUFFIX__ ULL
// I386:#define __UINTMAX_MAX__ 18446744073709551615ULL
// I386:#define __UINTMAX_TYPE__ long long unsigned int
// I386:#define __UINTMAX_WIDTH__ 64
// I386:#define __UINTPTR_MAX__ 4294967295U
// I386:#define __UINTPTR_TYPE__ unsigned int
// I386:#define __UINTPTR_WIDTH__ 32
// I386:#define __UINT_FAST16_MAX__ 65535
// I386:#define __UINT_FAST16_TYPE__ unsigned short
// I386:#define __UINT_FAST32_MAX__ 4294967295U
// I386:#define __UINT_FAST32_TYPE__ unsigned int
// I386:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// I386:#define __UINT_FAST64_TYPE__ long long unsigned int
// I386:#define __UINT_FAST8_MAX__ 255
// I386:#define __UINT_FAST8_TYPE__ unsigned char
// I386:#define __UINT_LEAST16_MAX__ 65535
// I386:#define __UINT_LEAST16_TYPE__ unsigned short
// I386:#define __UINT_LEAST32_MAX__ 4294967295U
// I386:#define __UINT_LEAST32_TYPE__ unsigned int
// I386:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// I386:#define __UINT_LEAST64_TYPE__ long long unsigned int
// I386:#define __UINT_LEAST8_MAX__ 255
// I386:#define __UINT_LEAST8_TYPE__ unsigned char
// I386:#define __USER_LABEL_PREFIX__
// I386:#define __WCHAR_MAX__ 2147483647
// I386:#define __WCHAR_TYPE__ int
// I386:#define __WCHAR_WIDTH__ 32
// I386:#define __WINT_TYPE__ int
// I386:#define __WINT_WIDTH__ 32
// I386:#define __i386 1
// I386:#define __i386__ 1
// I386:#define i386 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-pc-linux-gnu -target-cpu pentium4 < /dev/null | FileCheck -match-full-lines -check-prefix I386-LINUX %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=i386-pc-linux-gnu -target-cpu pentium4 < /dev/null | FileCheck -match-full-lines -check-prefix I386-LINUX -check-prefix I386-LINUX-CXX %s
//
// I386-LINUX-NOT:#define _LP64
// I386-LINUX:#define __BIGGEST_ALIGNMENT__ 16
// I386-LINUX:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// I386-LINUX:#define __CHAR16_TYPE__ unsigned short
// I386-LINUX:#define __CHAR32_TYPE__ unsigned int
// I386-LINUX:#define __CHAR_BIT__ 8
// I386-LINUX:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// I386-LINUX:#define __DBL_DIG__ 15
// I386-LINUX:#define __DBL_EPSILON__ 2.2204460492503131e-16
// I386-LINUX:#define __DBL_HAS_DENORM__ 1
// I386-LINUX:#define __DBL_HAS_INFINITY__ 1
// I386-LINUX:#define __DBL_HAS_QUIET_NAN__ 1
// I386-LINUX:#define __DBL_MANT_DIG__ 53
// I386-LINUX:#define __DBL_MAX_10_EXP__ 308
// I386-LINUX:#define __DBL_MAX_EXP__ 1024
// I386-LINUX:#define __DBL_MAX__ 1.7976931348623157e+308
// I386-LINUX:#define __DBL_MIN_10_EXP__ (-307)
// I386-LINUX:#define __DBL_MIN_EXP__ (-1021)
// I386-LINUX:#define __DBL_MIN__ 2.2250738585072014e-308
// I386-LINUX:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// I386-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// I386-LINUX:#define __FLT_DIG__ 6
// I386-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F
// I386-LINUX:#define __FLT_EVAL_METHOD__ 0
// I386-LINUX:#define __FLT_HAS_DENORM__ 1
// I386-LINUX:#define __FLT_HAS_INFINITY__ 1
// I386-LINUX:#define __FLT_HAS_QUIET_NAN__ 1
// I386-LINUX:#define __FLT_MANT_DIG__ 24
// I386-LINUX:#define __FLT_MAX_10_EXP__ 38
// I386-LINUX:#define __FLT_MAX_EXP__ 128
// I386-LINUX:#define __FLT_MAX__ 3.40282347e+38F
// I386-LINUX:#define __FLT_MIN_10_EXP__ (-37)
// I386-LINUX:#define __FLT_MIN_EXP__ (-125)
// I386-LINUX:#define __FLT_MIN__ 1.17549435e-38F
// I386-LINUX:#define __FLT_RADIX__ 2
// I386-LINUX:#define __INT16_C_SUFFIX__
// I386-LINUX:#define __INT16_FMTd__ "hd"
// I386-LINUX:#define __INT16_FMTi__ "hi"
// I386-LINUX:#define __INT16_MAX__ 32767
// I386-LINUX:#define __INT16_TYPE__ short
// I386-LINUX:#define __INT32_C_SUFFIX__
// I386-LINUX:#define __INT32_FMTd__ "d"
// I386-LINUX:#define __INT32_FMTi__ "i"
// I386-LINUX:#define __INT32_MAX__ 2147483647
// I386-LINUX:#define __INT32_TYPE__ int
// I386-LINUX:#define __INT64_C_SUFFIX__ LL
// I386-LINUX:#define __INT64_FMTd__ "lld"
// I386-LINUX:#define __INT64_FMTi__ "lli"
// I386-LINUX:#define __INT64_MAX__ 9223372036854775807LL
// I386-LINUX:#define __INT64_TYPE__ long long int
// I386-LINUX:#define __INT8_C_SUFFIX__
// I386-LINUX:#define __INT8_FMTd__ "hhd"
// I386-LINUX:#define __INT8_FMTi__ "hhi"
// I386-LINUX:#define __INT8_MAX__ 127
// I386-LINUX:#define __INT8_TYPE__ signed char
// I386-LINUX:#define __INTMAX_C_SUFFIX__ LL
// I386-LINUX:#define __INTMAX_FMTd__ "lld"
// I386-LINUX:#define __INTMAX_FMTi__ "lli"
// I386-LINUX:#define __INTMAX_MAX__ 9223372036854775807LL
// I386-LINUX:#define __INTMAX_TYPE__ long long int
// I386-LINUX:#define __INTMAX_WIDTH__ 64
// I386-LINUX:#define __INTPTR_FMTd__ "d"
// I386-LINUX:#define __INTPTR_FMTi__ "i"
// I386-LINUX:#define __INTPTR_MAX__ 2147483647
// I386-LINUX:#define __INTPTR_TYPE__ int
// I386-LINUX:#define __INTPTR_WIDTH__ 32
// I386-LINUX:#define __INT_FAST16_FMTd__ "hd"
// I386-LINUX:#define __INT_FAST16_FMTi__ "hi"
// I386-LINUX:#define __INT_FAST16_MAX__ 32767
// I386-LINUX:#define __INT_FAST16_TYPE__ short
// I386-LINUX:#define __INT_FAST32_FMTd__ "d"
// I386-LINUX:#define __INT_FAST32_FMTi__ "i"
// I386-LINUX:#define __INT_FAST32_MAX__ 2147483647
// I386-LINUX:#define __INT_FAST32_TYPE__ int
// I386-LINUX:#define __INT_FAST64_FMTd__ "lld"
// I386-LINUX:#define __INT_FAST64_FMTi__ "lli"
// I386-LINUX:#define __INT_FAST64_MAX__ 9223372036854775807LL
// I386-LINUX:#define __INT_FAST64_TYPE__ long long int
// I386-LINUX:#define __INT_FAST8_FMTd__ "hhd"
// I386-LINUX:#define __INT_FAST8_FMTi__ "hhi"
// I386-LINUX:#define __INT_FAST8_MAX__ 127
// I386-LINUX:#define __INT_FAST8_TYPE__ signed char
// I386-LINUX:#define __INT_LEAST16_FMTd__ "hd"
// I386-LINUX:#define __INT_LEAST16_FMTi__ "hi"
// I386-LINUX:#define __INT_LEAST16_MAX__ 32767
// I386-LINUX:#define __INT_LEAST16_TYPE__ short
// I386-LINUX:#define __INT_LEAST32_FMTd__ "d"
// I386-LINUX:#define __INT_LEAST32_FMTi__ "i"
// I386-LINUX:#define __INT_LEAST32_MAX__ 2147483647
// I386-LINUX:#define __INT_LEAST32_TYPE__ int
// I386-LINUX:#define __INT_LEAST64_FMTd__ "lld"
// I386-LINUX:#define __INT_LEAST64_FMTi__ "lli"
// I386-LINUX:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// I386-LINUX:#define __INT_LEAST64_TYPE__ long long int
// I386-LINUX:#define __INT_LEAST8_FMTd__ "hhd"
// I386-LINUX:#define __INT_LEAST8_FMTi__ "hhi"
// I386-LINUX:#define __INT_LEAST8_MAX__ 127
// I386-LINUX:#define __INT_LEAST8_TYPE__ signed char
// I386-LINUX:#define __INT_MAX__ 2147483647
// I386-LINUX:#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
// I386-LINUX:#define __LDBL_DIG__ 18
// I386-LINUX:#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
// I386-LINUX:#define __LDBL_HAS_DENORM__ 1
// I386-LINUX:#define __LDBL_HAS_INFINITY__ 1
// I386-LINUX:#define __LDBL_HAS_QUIET_NAN__ 1
// I386-LINUX:#define __LDBL_MANT_DIG__ 64
// I386-LINUX:#define __LDBL_MAX_10_EXP__ 4932
// I386-LINUX:#define __LDBL_MAX_EXP__ 16384
// I386-LINUX:#define __LDBL_MAX__ 1.18973149535723176502e+4932L
// I386-LINUX:#define __LDBL_MIN_10_EXP__ (-4931)
// I386-LINUX:#define __LDBL_MIN_EXP__ (-16381)
// I386-LINUX:#define __LDBL_MIN__ 3.36210314311209350626e-4932L
// I386-LINUX:#define __LITTLE_ENDIAN__ 1
// I386-LINUX:#define __LONG_LONG_MAX__ 9223372036854775807LL
// I386-LINUX:#define __LONG_MAX__ 2147483647L
// I386-LINUX-NOT:#define __LP64__
// I386-LINUX:#define __NO_MATH_INLINES 1
// I386-LINUX:#define __POINTER_WIDTH__ 32
// I386-LINUX:#define __PTRDIFF_TYPE__ int
// I386-LINUX:#define __PTRDIFF_WIDTH__ 32
// I386-LINUX:#define __REGISTER_PREFIX__
// I386-LINUX:#define __SCHAR_MAX__ 127
// I386-LINUX:#define __SHRT_MAX__ 32767
// I386-LINUX:#define __SIG_ATOMIC_MAX__ 2147483647
// I386-LINUX:#define __SIG_ATOMIC_WIDTH__ 32
// I386-LINUX:#define __SIZEOF_DOUBLE__ 8
// I386-LINUX:#define __SIZEOF_FLOAT__ 4
// I386-LINUX:#define __SIZEOF_INT__ 4
// I386-LINUX:#define __SIZEOF_LONG_DOUBLE__ 12
// I386-LINUX:#define __SIZEOF_LONG_LONG__ 8
// I386-LINUX:#define __SIZEOF_LONG__ 4
// I386-LINUX:#define __SIZEOF_POINTER__ 4
// I386-LINUX:#define __SIZEOF_PTRDIFF_T__ 4
// I386-LINUX:#define __SIZEOF_SHORT__ 2
// I386-LINUX:#define __SIZEOF_SIZE_T__ 4
// I386-LINUX:#define __SIZEOF_WCHAR_T__ 4
// I386-LINUX:#define __SIZEOF_WINT_T__ 4
// I386-LINUX:#define __SIZE_MAX__ 4294967295U
// I386-LINUX:#define __SIZE_TYPE__ unsigned int
// I386-LINUX:#define __SIZE_WIDTH__ 32
// I386-LINUX-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
// I386-LINUX:#define __UINT16_C_SUFFIX__
// I386-LINUX:#define __UINT16_MAX__ 65535
// I386-LINUX:#define __UINT16_TYPE__ unsigned short
// I386-LINUX:#define __UINT32_C_SUFFIX__ U
// I386-LINUX:#define __UINT32_MAX__ 4294967295U
// I386-LINUX:#define __UINT32_TYPE__ unsigned int
// I386-LINUX:#define __UINT64_C_SUFFIX__ ULL
// I386-LINUX:#define __UINT64_MAX__ 18446744073709551615ULL
// I386-LINUX:#define __UINT64_TYPE__ long long unsigned int
// I386-LINUX:#define __UINT8_C_SUFFIX__
// I386-LINUX:#define __UINT8_MAX__ 255
// I386-LINUX:#define __UINT8_TYPE__ unsigned char
// I386-LINUX:#define __UINTMAX_C_SUFFIX__ ULL
// I386-LINUX:#define __UINTMAX_MAX__ 18446744073709551615ULL
// I386-LINUX:#define __UINTMAX_TYPE__ long long unsigned int
// I386-LINUX:#define __UINTMAX_WIDTH__ 64
// I386-LINUX:#define __UINTPTR_MAX__ 4294967295U
// I386-LINUX:#define __UINTPTR_TYPE__ unsigned int
// I386-LINUX:#define __UINTPTR_WIDTH__ 32
// I386-LINUX:#define __UINT_FAST16_MAX__ 65535
// I386-LINUX:#define __UINT_FAST16_TYPE__ unsigned short
// I386-LINUX:#define __UINT_FAST32_MAX__ 4294967295U
// I386-LINUX:#define __UINT_FAST32_TYPE__ unsigned int
// I386-LINUX:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// I386-LINUX:#define __UINT_FAST64_TYPE__ long long unsigned int
// I386-LINUX:#define __UINT_FAST8_MAX__ 255
// I386-LINUX:#define __UINT_FAST8_TYPE__ unsigned char
// I386-LINUX:#define __UINT_LEAST16_MAX__ 65535
// I386-LINUX:#define __UINT_LEAST16_TYPE__ unsigned short
// I386-LINUX:#define __UINT_LEAST32_MAX__ 4294967295U
// I386-LINUX:#define __UINT_LEAST32_TYPE__ unsigned int
// I386-LINUX:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// I386-LINUX:#define __UINT_LEAST64_TYPE__ long long unsigned int
// I386-LINUX:#define __UINT_LEAST8_MAX__ 255
// I386-LINUX:#define __UINT_LEAST8_TYPE__ unsigned char
// I386-LINUX:#define __USER_LABEL_PREFIX__
// I386-LINUX:#define __WCHAR_MAX__ 2147483647
// I386-LINUX:#define __WCHAR_TYPE__ int
// I386-LINUX:#define __WCHAR_WIDTH__ 32
// I386-LINUX:#define __WINT_TYPE__ unsigned int
// I386-LINUX:#define __WINT_WIDTH__ 32
// I386-LINUX:#define __i386 1
// I386-LINUX:#define __i386__ 1
// I386-LINUX:#define i386 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-netbsd < /dev/null | FileCheck -match-full-lines -check-prefix I386-NETBSD %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=i386-netbsd < /dev/null | FileCheck -match-full-lines -check-prefix I386-NETBSD -check-prefix I386-NETBSD-CXX %s
//
// I386-NETBSD-NOT:#define _LP64
// I386-NETBSD:#define __BIGGEST_ALIGNMENT__ 16
// I386-NETBSD:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// I386-NETBSD:#define __CHAR16_TYPE__ unsigned short
// I386-NETBSD:#define __CHAR32_TYPE__ unsigned int
// I386-NETBSD:#define __CHAR_BIT__ 8
// I386-NETBSD:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// I386-NETBSD:#define __DBL_DIG__ 15
// I386-NETBSD:#define __DBL_EPSILON__ 2.2204460492503131e-16
// I386-NETBSD:#define __DBL_HAS_DENORM__ 1
// I386-NETBSD:#define __DBL_HAS_INFINITY__ 1
// I386-NETBSD:#define __DBL_HAS_QUIET_NAN__ 1
// I386-NETBSD:#define __DBL_MANT_DIG__ 53
// I386-NETBSD:#define __DBL_MAX_10_EXP__ 308
// I386-NETBSD:#define __DBL_MAX_EXP__ 1024
// I386-NETBSD:#define __DBL_MAX__ 1.7976931348623157e+308
// I386-NETBSD:#define __DBL_MIN_10_EXP__ (-307)
// I386-NETBSD:#define __DBL_MIN_EXP__ (-1021)
// I386-NETBSD:#define __DBL_MIN__ 2.2250738585072014e-308
// I386-NETBSD:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// I386-NETBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// I386-NETBSD:#define __FLT_DIG__ 6
// I386-NETBSD:#define __FLT_EPSILON__ 1.19209290e-7F
// I386-NETBSD:#define __FLT_EVAL_METHOD__ 2
// I386-NETBSD:#define __FLT_HAS_DENORM__ 1
// I386-NETBSD:#define __FLT_HAS_INFINITY__ 1
// I386-NETBSD:#define __FLT_HAS_QUIET_NAN__ 1
// I386-NETBSD:#define __FLT_MANT_DIG__ 24
// I386-NETBSD:#define __FLT_MAX_10_EXP__ 38
// I386-NETBSD:#define __FLT_MAX_EXP__ 128
// I386-NETBSD:#define __FLT_MAX__ 3.40282347e+38F
// I386-NETBSD:#define __FLT_MIN_10_EXP__ (-37)
// I386-NETBSD:#define __FLT_MIN_EXP__ (-125)
// I386-NETBSD:#define __FLT_MIN__ 1.17549435e-38F
// I386-NETBSD:#define __FLT_RADIX__ 2
// I386-NETBSD:#define __INT16_C_SUFFIX__
// I386-NETBSD:#define __INT16_FMTd__ "hd"
// I386-NETBSD:#define __INT16_FMTi__ "hi"
// I386-NETBSD:#define __INT16_MAX__ 32767
// I386-NETBSD:#define __INT16_TYPE__ short
// I386-NETBSD:#define __INT32_C_SUFFIX__
// I386-NETBSD:#define __INT32_FMTd__ "d"
// I386-NETBSD:#define __INT32_FMTi__ "i"
// I386-NETBSD:#define __INT32_MAX__ 2147483647
// I386-NETBSD:#define __INT32_TYPE__ int
// I386-NETBSD:#define __INT64_C_SUFFIX__ LL
// I386-NETBSD:#define __INT64_FMTd__ "lld"
// I386-NETBSD:#define __INT64_FMTi__ "lli"
// I386-NETBSD:#define __INT64_MAX__ 9223372036854775807LL
// I386-NETBSD:#define __INT64_TYPE__ long long int
// I386-NETBSD:#define __INT8_C_SUFFIX__
// I386-NETBSD:#define __INT8_FMTd__ "hhd"
// I386-NETBSD:#define __INT8_FMTi__ "hhi"
// I386-NETBSD:#define __INT8_MAX__ 127
// I386-NETBSD:#define __INT8_TYPE__ signed char
// I386-NETBSD:#define __INTMAX_C_SUFFIX__ LL
// I386-NETBSD:#define __INTMAX_FMTd__ "lld"
// I386-NETBSD:#define __INTMAX_FMTi__ "lli"
// I386-NETBSD:#define __INTMAX_MAX__ 9223372036854775807LL
// I386-NETBSD:#define __INTMAX_TYPE__ long long int
// I386-NETBSD:#define __INTMAX_WIDTH__ 64
// I386-NETBSD:#define __INTPTR_FMTd__ "d"
// I386-NETBSD:#define __INTPTR_FMTi__ "i"
// I386-NETBSD:#define __INTPTR_MAX__ 2147483647
// I386-NETBSD:#define __INTPTR_TYPE__ int
// I386-NETBSD:#define __INTPTR_WIDTH__ 32
// I386-NETBSD:#define __INT_FAST16_FMTd__ "hd"
// I386-NETBSD:#define __INT_FAST16_FMTi__ "hi"
// I386-NETBSD:#define __INT_FAST16_MAX__ 32767
// I386-NETBSD:#define __INT_FAST16_TYPE__ short
// I386-NETBSD:#define __INT_FAST32_FMTd__ "d"
// I386-NETBSD:#define __INT_FAST32_FMTi__ "i"
// I386-NETBSD:#define __INT_FAST32_MAX__ 2147483647
// I386-NETBSD:#define __INT_FAST32_TYPE__ int
// I386-NETBSD:#define __INT_FAST64_FMTd__ "lld"
// I386-NETBSD:#define __INT_FAST64_FMTi__ "lli"
// I386-NETBSD:#define __INT_FAST64_MAX__ 9223372036854775807LL
// I386-NETBSD:#define __INT_FAST64_TYPE__ long long int
// I386-NETBSD:#define __INT_FAST8_FMTd__ "hhd"
// I386-NETBSD:#define __INT_FAST8_FMTi__ "hhi"
// I386-NETBSD:#define __INT_FAST8_MAX__ 127
// I386-NETBSD:#define __INT_FAST8_TYPE__ signed char
// I386-NETBSD:#define __INT_LEAST16_FMTd__ "hd"
// I386-NETBSD:#define __INT_LEAST16_FMTi__ "hi"
// I386-NETBSD:#define __INT_LEAST16_MAX__ 32767
// I386-NETBSD:#define __INT_LEAST16_TYPE__ short
// I386-NETBSD:#define __INT_LEAST32_FMTd__ "d"
// I386-NETBSD:#define __INT_LEAST32_FMTi__ "i"
// I386-NETBSD:#define __INT_LEAST32_MAX__ 2147483647
// I386-NETBSD:#define __INT_LEAST32_TYPE__ int
// I386-NETBSD:#define __INT_LEAST64_FMTd__ "lld"
// I386-NETBSD:#define __INT_LEAST64_FMTi__ "lli"
// I386-NETBSD:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// I386-NETBSD:#define __INT_LEAST64_TYPE__ long long int
// I386-NETBSD:#define __INT_LEAST8_FMTd__ "hhd"
// I386-NETBSD:#define __INT_LEAST8_FMTi__ "hhi"
// I386-NETBSD:#define __INT_LEAST8_MAX__ 127
// I386-NETBSD:#define __INT_LEAST8_TYPE__ signed char
// I386-NETBSD:#define __INT_MAX__ 2147483647
// I386-NETBSD:#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
// I386-NETBSD:#define __LDBL_DIG__ 18
// I386-NETBSD:#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
// I386-NETBSD:#define __LDBL_HAS_DENORM__ 1
// I386-NETBSD:#define __LDBL_HAS_INFINITY__ 1
// I386-NETBSD:#define __LDBL_HAS_QUIET_NAN__ 1
// I386-NETBSD:#define __LDBL_MANT_DIG__ 64
// I386-NETBSD:#define __LDBL_MAX_10_EXP__ 4932
// I386-NETBSD:#define __LDBL_MAX_EXP__ 16384
// I386-NETBSD:#define __LDBL_MAX__ 1.18973149535723176502e+4932L
// I386-NETBSD:#define __LDBL_MIN_10_EXP__ (-4931)
// I386-NETBSD:#define __LDBL_MIN_EXP__ (-16381)
// I386-NETBSD:#define __LDBL_MIN__ 3.36210314311209350626e-4932L
// I386-NETBSD:#define __LITTLE_ENDIAN__ 1
// I386-NETBSD:#define __LONG_LONG_MAX__ 9223372036854775807LL
// I386-NETBSD:#define __LONG_MAX__ 2147483647L
// I386-NETBSD-NOT:#define __LP64__
// I386-NETBSD:#define __NO_MATH_INLINES 1
// I386-NETBSD:#define __POINTER_WIDTH__ 32
// I386-NETBSD:#define __PTRDIFF_TYPE__ int
// I386-NETBSD:#define __PTRDIFF_WIDTH__ 32
// I386-NETBSD:#define __REGISTER_PREFIX__
// I386-NETBSD:#define __SCHAR_MAX__ 127
// I386-NETBSD:#define __SHRT_MAX__ 32767
// I386-NETBSD:#define __SIG_ATOMIC_MAX__ 2147483647
// I386-NETBSD:#define __SIG_ATOMIC_WIDTH__ 32
// I386-NETBSD:#define __SIZEOF_DOUBLE__ 8
// I386-NETBSD:#define __SIZEOF_FLOAT__ 4
// I386-NETBSD:#define __SIZEOF_INT__ 4
// I386-NETBSD:#define __SIZEOF_LONG_DOUBLE__ 12
// I386-NETBSD:#define __SIZEOF_LONG_LONG__ 8
// I386-NETBSD:#define __SIZEOF_LONG__ 4
// I386-NETBSD:#define __SIZEOF_POINTER__ 4
// I386-NETBSD:#define __SIZEOF_PTRDIFF_T__ 4
// I386-NETBSD:#define __SIZEOF_SHORT__ 2
// I386-NETBSD:#define __SIZEOF_SIZE_T__ 4
// I386-NETBSD:#define __SIZEOF_WCHAR_T__ 4
// I386-NETBSD:#define __SIZEOF_WINT_T__ 4
// I386-NETBSD:#define __SIZE_MAX__ 4294967295U
// I386-NETBSD:#define __SIZE_TYPE__ unsigned int
// I386-NETBSD:#define __SIZE_WIDTH__ 32
// I386-NETBSD-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 4U
// I386-NETBSD:#define __UINT16_C_SUFFIX__
// I386-NETBSD:#define __UINT16_MAX__ 65535
// I386-NETBSD:#define __UINT16_TYPE__ unsigned short
// I386-NETBSD:#define __UINT32_C_SUFFIX__ U
// I386-NETBSD:#define __UINT32_MAX__ 4294967295U
// I386-NETBSD:#define __UINT32_TYPE__ unsigned int
// I386-NETBSD:#define __UINT64_C_SUFFIX__ ULL
// I386-NETBSD:#define __UINT64_MAX__ 18446744073709551615ULL
// I386-NETBSD:#define __UINT64_TYPE__ long long unsigned int
// I386-NETBSD:#define __UINT8_C_SUFFIX__
// I386-NETBSD:#define __UINT8_MAX__ 255
// I386-NETBSD:#define __UINT8_TYPE__ unsigned char
// I386-NETBSD:#define __UINTMAX_C_SUFFIX__ ULL
// I386-NETBSD:#define __UINTMAX_MAX__ 18446744073709551615ULL
// I386-NETBSD:#define __UINTMAX_TYPE__ long long unsigned int
// I386-NETBSD:#define __UINTMAX_WIDTH__ 64
// I386-NETBSD:#define __UINTPTR_MAX__ 4294967295U
// I386-NETBSD:#define __UINTPTR_TYPE__ unsigned int
// I386-NETBSD:#define __UINTPTR_WIDTH__ 32
// I386-NETBSD:#define __UINT_FAST16_MAX__ 65535
// I386-NETBSD:#define __UINT_FAST16_TYPE__ unsigned short
// I386-NETBSD:#define __UINT_FAST32_MAX__ 4294967295U
// I386-NETBSD:#define __UINT_FAST32_TYPE__ unsigned int
// I386-NETBSD:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// I386-NETBSD:#define __UINT_FAST64_TYPE__ long long unsigned int
// I386-NETBSD:#define __UINT_FAST8_MAX__ 255
// I386-NETBSD:#define __UINT_FAST8_TYPE__ unsigned char
// I386-NETBSD:#define __UINT_LEAST16_MAX__ 65535
// I386-NETBSD:#define __UINT_LEAST16_TYPE__ unsigned short
// I386-NETBSD:#define __UINT_LEAST32_MAX__ 4294967295U
// I386-NETBSD:#define __UINT_LEAST32_TYPE__ unsigned int
// I386-NETBSD:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// I386-NETBSD:#define __UINT_LEAST64_TYPE__ long long unsigned int
// I386-NETBSD:#define __UINT_LEAST8_MAX__ 255
// I386-NETBSD:#define __UINT_LEAST8_TYPE__ unsigned char
// I386-NETBSD:#define __USER_LABEL_PREFIX__
// I386-NETBSD:#define __WCHAR_MAX__ 2147483647
// I386-NETBSD:#define __WCHAR_TYPE__ int
// I386-NETBSD:#define __WCHAR_WIDTH__ 32
// I386-NETBSD:#define __WINT_TYPE__ int
// I386-NETBSD:#define __WINT_WIDTH__ 32
// I386-NETBSD:#define __i386 1
// I386-NETBSD:#define __i386__ 1
// I386-NETBSD:#define i386 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-netbsd -target-feature +sse2 < /dev/null | FileCheck -match-full-lines -check-prefix I386-NETBSD-SSE %s
// I386-NETBSD-SSE:#define __FLT_EVAL_METHOD__ 0
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-netbsd6 < /dev/null | FileCheck -match-full-lines -check-prefix I386-NETBSD6 %s
// I386-NETBSD6:#define __FLT_EVAL_METHOD__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-netbsd6 -target-feature +sse2 < /dev/null | FileCheck -match-full-lines -check-prefix I386-NETBSD6-SSE %s
// I386-NETBSD6-SSE:#define __FLT_EVAL_METHOD__ 1
// RUN: %clang_cc1 -E -dM -triple=i686-pc-mingw32 < /dev/null | FileCheck -match-full-lines -check-prefix I386-DECLSPEC %s
// RUN: %clang_cc1 -E -dM -fms-extensions -triple=i686-pc-mingw32 < /dev/null | FileCheck -match-full-lines -check-prefix I386-DECLSPEC %s
// RUN: %clang_cc1 -E -dM -triple=i686-unknown-cygwin < /dev/null | FileCheck -match-full-lines -check-prefix I386-DECLSPEC %s
// RUN: %clang_cc1 -E -dM -fms-extensions -triple=i686-unknown-cygwin < /dev/null | FileCheck -match-full-lines -check-prefix I386-DECLSPEC %s
// I386-DECLSPEC: #define __declspec{{.*}}
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MIPS32BE -check-prefix MIPS32BE-C %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=mips-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MIPS32BE -check-prefix MIPS32BE-CXX %s
//
// MIPS32BE:#define MIPSEB 1
// MIPS32BE:#define _ABIO32 1
// MIPS32BE-NOT:#define _LP64
// MIPS32BE:#define _MIPSEB 1
// MIPS32BE:#define _MIPS_ARCH "mips32r2"
// MIPS32BE:#define _MIPS_ARCH_MIPS32R2 1
// MIPS32BE:#define _MIPS_FPSET 16
// MIPS32BE:#define _MIPS_SIM _ABIO32
// MIPS32BE:#define _MIPS_SZINT 32
// MIPS32BE:#define _MIPS_SZLONG 32
// MIPS32BE:#define _MIPS_SZPTR 32
// MIPS32BE:#define __BIGGEST_ALIGNMENT__ 8
// MIPS32BE:#define __BIG_ENDIAN__ 1
// MIPS32BE:#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
// MIPS32BE:#define __CHAR16_TYPE__ unsigned short
// MIPS32BE:#define __CHAR32_TYPE__ unsigned int
// MIPS32BE:#define __CHAR_BIT__ 8
// MIPS32BE:#define __CONSTANT_CFSTRINGS__ 1
// MIPS32BE:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// MIPS32BE:#define __DBL_DIG__ 15
// MIPS32BE:#define __DBL_EPSILON__ 2.2204460492503131e-16
// MIPS32BE:#define __DBL_HAS_DENORM__ 1
// MIPS32BE:#define __DBL_HAS_INFINITY__ 1
// MIPS32BE:#define __DBL_HAS_QUIET_NAN__ 1
// MIPS32BE:#define __DBL_MANT_DIG__ 53
// MIPS32BE:#define __DBL_MAX_10_EXP__ 308
// MIPS32BE:#define __DBL_MAX_EXP__ 1024
// MIPS32BE:#define __DBL_MAX__ 1.7976931348623157e+308
// MIPS32BE:#define __DBL_MIN_10_EXP__ (-307)
// MIPS32BE:#define __DBL_MIN_EXP__ (-1021)
// MIPS32BE:#define __DBL_MIN__ 2.2250738585072014e-308
// MIPS32BE:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// MIPS32BE:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// MIPS32BE:#define __FLT_DIG__ 6
// MIPS32BE:#define __FLT_EPSILON__ 1.19209290e-7F
// MIPS32BE:#define __FLT_EVAL_METHOD__ 0
// MIPS32BE:#define __FLT_HAS_DENORM__ 1
// MIPS32BE:#define __FLT_HAS_INFINITY__ 1
// MIPS32BE:#define __FLT_HAS_QUIET_NAN__ 1
// MIPS32BE:#define __FLT_MANT_DIG__ 24
// MIPS32BE:#define __FLT_MAX_10_EXP__ 38
// MIPS32BE:#define __FLT_MAX_EXP__ 128
// MIPS32BE:#define __FLT_MAX__ 3.40282347e+38F
// MIPS32BE:#define __FLT_MIN_10_EXP__ (-37)
// MIPS32BE:#define __FLT_MIN_EXP__ (-125)
// MIPS32BE:#define __FLT_MIN__ 1.17549435e-38F
// MIPS32BE:#define __FLT_RADIX__ 2
// MIPS32BE:#define __INT16_C_SUFFIX__
// MIPS32BE:#define __INT16_FMTd__ "hd"
// MIPS32BE:#define __INT16_FMTi__ "hi"
// MIPS32BE:#define __INT16_MAX__ 32767
// MIPS32BE:#define __INT16_TYPE__ short
// MIPS32BE:#define __INT32_C_SUFFIX__
// MIPS32BE:#define __INT32_FMTd__ "d"
// MIPS32BE:#define __INT32_FMTi__ "i"
// MIPS32BE:#define __INT32_MAX__ 2147483647
// MIPS32BE:#define __INT32_TYPE__ int
// MIPS32BE:#define __INT64_C_SUFFIX__ LL
// MIPS32BE:#define __INT64_FMTd__ "lld"
// MIPS32BE:#define __INT64_FMTi__ "lli"
// MIPS32BE:#define __INT64_MAX__ 9223372036854775807LL
// MIPS32BE:#define __INT64_TYPE__ long long int
// MIPS32BE:#define __INT8_C_SUFFIX__
// MIPS32BE:#define __INT8_FMTd__ "hhd"
// MIPS32BE:#define __INT8_FMTi__ "hhi"
// MIPS32BE:#define __INT8_MAX__ 127
// MIPS32BE:#define __INT8_TYPE__ signed char
// MIPS32BE:#define __INTMAX_C_SUFFIX__ LL
// MIPS32BE:#define __INTMAX_FMTd__ "lld"
// MIPS32BE:#define __INTMAX_FMTi__ "lli"
// MIPS32BE:#define __INTMAX_MAX__ 9223372036854775807LL
// MIPS32BE:#define __INTMAX_TYPE__ long long int
// MIPS32BE:#define __INTMAX_WIDTH__ 64
// MIPS32BE:#define __INTPTR_FMTd__ "ld"
// MIPS32BE:#define __INTPTR_FMTi__ "li"
// MIPS32BE:#define __INTPTR_MAX__ 2147483647L
// MIPS32BE:#define __INTPTR_TYPE__ long int
// MIPS32BE:#define __INTPTR_WIDTH__ 32
// MIPS32BE:#define __INT_FAST16_FMTd__ "hd"
// MIPS32BE:#define __INT_FAST16_FMTi__ "hi"
// MIPS32BE:#define __INT_FAST16_MAX__ 32767
// MIPS32BE:#define __INT_FAST16_TYPE__ short
// MIPS32BE:#define __INT_FAST32_FMTd__ "d"
// MIPS32BE:#define __INT_FAST32_FMTi__ "i"
// MIPS32BE:#define __INT_FAST32_MAX__ 2147483647
// MIPS32BE:#define __INT_FAST32_TYPE__ int
// MIPS32BE:#define __INT_FAST64_FMTd__ "lld"
// MIPS32BE:#define __INT_FAST64_FMTi__ "lli"
// MIPS32BE:#define __INT_FAST64_MAX__ 9223372036854775807LL
// MIPS32BE:#define __INT_FAST64_TYPE__ long long int
// MIPS32BE:#define __INT_FAST8_FMTd__ "hhd"
// MIPS32BE:#define __INT_FAST8_FMTi__ "hhi"
// MIPS32BE:#define __INT_FAST8_MAX__ 127
// MIPS32BE:#define __INT_FAST8_TYPE__ signed char
// MIPS32BE:#define __INT_LEAST16_FMTd__ "hd"
// MIPS32BE:#define __INT_LEAST16_FMTi__ "hi"
// MIPS32BE:#define __INT_LEAST16_MAX__ 32767
// MIPS32BE:#define __INT_LEAST16_TYPE__ short
// MIPS32BE:#define __INT_LEAST32_FMTd__ "d"
// MIPS32BE:#define __INT_LEAST32_FMTi__ "i"
// MIPS32BE:#define __INT_LEAST32_MAX__ 2147483647
// MIPS32BE:#define __INT_LEAST32_TYPE__ int
// MIPS32BE:#define __INT_LEAST64_FMTd__ "lld"
// MIPS32BE:#define __INT_LEAST64_FMTi__ "lli"
// MIPS32BE:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// MIPS32BE:#define __INT_LEAST64_TYPE__ long long int
// MIPS32BE:#define __INT_LEAST8_FMTd__ "hhd"
// MIPS32BE:#define __INT_LEAST8_FMTi__ "hhi"
// MIPS32BE:#define __INT_LEAST8_MAX__ 127
// MIPS32BE:#define __INT_LEAST8_TYPE__ signed char
// MIPS32BE:#define __INT_MAX__ 2147483647
// MIPS32BE:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
// MIPS32BE:#define __LDBL_DIG__ 15
// MIPS32BE:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
// MIPS32BE:#define __LDBL_HAS_DENORM__ 1
// MIPS32BE:#define __LDBL_HAS_INFINITY__ 1
// MIPS32BE:#define __LDBL_HAS_QUIET_NAN__ 1
// MIPS32BE:#define __LDBL_MANT_DIG__ 53
// MIPS32BE:#define __LDBL_MAX_10_EXP__ 308
// MIPS32BE:#define __LDBL_MAX_EXP__ 1024
// MIPS32BE:#define __LDBL_MAX__ 1.7976931348623157e+308L
// MIPS32BE:#define __LDBL_MIN_10_EXP__ (-307)
// MIPS32BE:#define __LDBL_MIN_EXP__ (-1021)
// MIPS32BE:#define __LDBL_MIN__ 2.2250738585072014e-308L
// MIPS32BE:#define __LONG_LONG_MAX__ 9223372036854775807LL
// MIPS32BE:#define __LONG_MAX__ 2147483647L
// MIPS32BE-NOT:#define __LP64__
// MIPS32BE:#define __MIPSEB 1
// MIPS32BE:#define __MIPSEB__ 1
// MIPS32BE:#define __POINTER_WIDTH__ 32
// MIPS32BE:#define __PRAGMA_REDEFINE_EXTNAME 1
// MIPS32BE:#define __PTRDIFF_TYPE__ int
// MIPS32BE:#define __PTRDIFF_WIDTH__ 32
// MIPS32BE:#define __REGISTER_PREFIX__
// MIPS32BE:#define __SCHAR_MAX__ 127
// MIPS32BE:#define __SHRT_MAX__ 32767
// MIPS32BE:#define __SIG_ATOMIC_MAX__ 2147483647
// MIPS32BE:#define __SIG_ATOMIC_WIDTH__ 32
// MIPS32BE:#define __SIZEOF_DOUBLE__ 8
// MIPS32BE:#define __SIZEOF_FLOAT__ 4
// MIPS32BE:#define __SIZEOF_INT__ 4
// MIPS32BE:#define __SIZEOF_LONG_DOUBLE__ 8
// MIPS32BE:#define __SIZEOF_LONG_LONG__ 8
// MIPS32BE:#define __SIZEOF_LONG__ 4
// MIPS32BE:#define __SIZEOF_POINTER__ 4
// MIPS32BE:#define __SIZEOF_PTRDIFF_T__ 4
// MIPS32BE:#define __SIZEOF_SHORT__ 2
// MIPS32BE:#define __SIZEOF_SIZE_T__ 4
// MIPS32BE:#define __SIZEOF_WCHAR_T__ 4
// MIPS32BE:#define __SIZEOF_WINT_T__ 4
// MIPS32BE:#define __SIZE_MAX__ 4294967295U
// MIPS32BE:#define __SIZE_TYPE__ unsigned int
// MIPS32BE:#define __SIZE_WIDTH__ 32
// MIPS32BE-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
// MIPS32BE:#define __STDC_HOSTED__ 0
// MIPS32BE-C:#define __STDC_VERSION__ 201112L
// MIPS32BE:#define __STDC__ 1
// MIPS32BE:#define __UINT16_C_SUFFIX__
// MIPS32BE:#define __UINT16_MAX__ 65535
// MIPS32BE:#define __UINT16_TYPE__ unsigned short
// MIPS32BE:#define __UINT32_C_SUFFIX__ U
// MIPS32BE:#define __UINT32_MAX__ 4294967295U
// MIPS32BE:#define __UINT32_TYPE__ unsigned int
// MIPS32BE:#define __UINT64_C_SUFFIX__ ULL
// MIPS32BE:#define __UINT64_MAX__ 18446744073709551615ULL
// MIPS32BE:#define __UINT64_TYPE__ long long unsigned int
// MIPS32BE:#define __UINT8_C_SUFFIX__
// MIPS32BE:#define __UINT8_MAX__ 255
// MIPS32BE:#define __UINT8_TYPE__ unsigned char
// MIPS32BE:#define __UINTMAX_C_SUFFIX__ ULL
// MIPS32BE:#define __UINTMAX_MAX__ 18446744073709551615ULL
// MIPS32BE:#define __UINTMAX_TYPE__ long long unsigned int
// MIPS32BE:#define __UINTMAX_WIDTH__ 64
// MIPS32BE:#define __UINTPTR_MAX__ 4294967295UL
// MIPS32BE:#define __UINTPTR_TYPE__ long unsigned int
// MIPS32BE:#define __UINTPTR_WIDTH__ 32
// MIPS32BE:#define __UINT_FAST16_MAX__ 65535
// MIPS32BE:#define __UINT_FAST16_TYPE__ unsigned short
// MIPS32BE:#define __UINT_FAST32_MAX__ 4294967295U
// MIPS32BE:#define __UINT_FAST32_TYPE__ unsigned int
// MIPS32BE:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// MIPS32BE:#define __UINT_FAST64_TYPE__ long long unsigned int
// MIPS32BE:#define __UINT_FAST8_MAX__ 255
// MIPS32BE:#define __UINT_FAST8_TYPE__ unsigned char
// MIPS32BE:#define __UINT_LEAST16_MAX__ 65535
// MIPS32BE:#define __UINT_LEAST16_TYPE__ unsigned short
// MIPS32BE:#define __UINT_LEAST32_MAX__ 4294967295U
// MIPS32BE:#define __UINT_LEAST32_TYPE__ unsigned int
// MIPS32BE:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// MIPS32BE:#define __UINT_LEAST64_TYPE__ long long unsigned int
// MIPS32BE:#define __UINT_LEAST8_MAX__ 255
// MIPS32BE:#define __UINT_LEAST8_TYPE__ unsigned char
// MIPS32BE:#define __USER_LABEL_PREFIX__
// MIPS32BE:#define __WCHAR_MAX__ 2147483647
// MIPS32BE:#define __WCHAR_TYPE__ int
// MIPS32BE:#define __WCHAR_WIDTH__ 32
// MIPS32BE:#define __WINT_TYPE__ int
// MIPS32BE:#define __WINT_WIDTH__ 32
// MIPS32BE:#define __clang__ 1
// MIPS32BE:#define __llvm__ 1
// MIPS32BE:#define __mips 32
// MIPS32BE:#define __mips__ 1
// MIPS32BE:#define __mips_abicalls 1
// MIPS32BE:#define __mips_fpr 0
// MIPS32BE:#define __mips_hard_float 1
// MIPS32BE:#define __mips_o32 1
// MIPS32BE:#define _mips 1
// MIPS32BE:#define mips 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mipsel-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MIPS32EL %s
//
// MIPS32EL:#define MIPSEL 1
// MIPS32EL:#define _ABIO32 1
// MIPS32EL-NOT:#define _LP64
// MIPS32EL:#define _MIPSEL 1
// MIPS32EL:#define _MIPS_ARCH "mips32r2"
// MIPS32EL:#define _MIPS_ARCH_MIPS32R2 1
// MIPS32EL:#define _MIPS_FPSET 16
// MIPS32EL:#define _MIPS_SIM _ABIO32
// MIPS32EL:#define _MIPS_SZINT 32
// MIPS32EL:#define _MIPS_SZLONG 32
// MIPS32EL:#define _MIPS_SZPTR 32
// MIPS32EL:#define __BIGGEST_ALIGNMENT__ 8
// MIPS32EL:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// MIPS32EL:#define __CHAR16_TYPE__ unsigned short
// MIPS32EL:#define __CHAR32_TYPE__ unsigned int
// MIPS32EL:#define __CHAR_BIT__ 8
// MIPS32EL:#define __CONSTANT_CFSTRINGS__ 1
// MIPS32EL:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// MIPS32EL:#define __DBL_DIG__ 15
// MIPS32EL:#define __DBL_EPSILON__ 2.2204460492503131e-16
// MIPS32EL:#define __DBL_HAS_DENORM__ 1
// MIPS32EL:#define __DBL_HAS_INFINITY__ 1
// MIPS32EL:#define __DBL_HAS_QUIET_NAN__ 1
// MIPS32EL:#define __DBL_MANT_DIG__ 53
// MIPS32EL:#define __DBL_MAX_10_EXP__ 308
// MIPS32EL:#define __DBL_MAX_EXP__ 1024
// MIPS32EL:#define __DBL_MAX__ 1.7976931348623157e+308
// MIPS32EL:#define __DBL_MIN_10_EXP__ (-307)
// MIPS32EL:#define __DBL_MIN_EXP__ (-1021)
// MIPS32EL:#define __DBL_MIN__ 2.2250738585072014e-308
// MIPS32EL:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// MIPS32EL:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// MIPS32EL:#define __FLT_DIG__ 6
// MIPS32EL:#define __FLT_EPSILON__ 1.19209290e-7F
// MIPS32EL:#define __FLT_EVAL_METHOD__ 0
// MIPS32EL:#define __FLT_HAS_DENORM__ 1
// MIPS32EL:#define __FLT_HAS_INFINITY__ 1
// MIPS32EL:#define __FLT_HAS_QUIET_NAN__ 1
// MIPS32EL:#define __FLT_MANT_DIG__ 24
// MIPS32EL:#define __FLT_MAX_10_EXP__ 38
// MIPS32EL:#define __FLT_MAX_EXP__ 128
// MIPS32EL:#define __FLT_MAX__ 3.40282347e+38F
// MIPS32EL:#define __FLT_MIN_10_EXP__ (-37)
// MIPS32EL:#define __FLT_MIN_EXP__ (-125)
// MIPS32EL:#define __FLT_MIN__ 1.17549435e-38F
// MIPS32EL:#define __FLT_RADIX__ 2
// MIPS32EL:#define __INT16_C_SUFFIX__
// MIPS32EL:#define __INT16_FMTd__ "hd"
// MIPS32EL:#define __INT16_FMTi__ "hi"
// MIPS32EL:#define __INT16_MAX__ 32767
// MIPS32EL:#define __INT16_TYPE__ short
// MIPS32EL:#define __INT32_C_SUFFIX__
// MIPS32EL:#define __INT32_FMTd__ "d"
// MIPS32EL:#define __INT32_FMTi__ "i"
// MIPS32EL:#define __INT32_MAX__ 2147483647
// MIPS32EL:#define __INT32_TYPE__ int
// MIPS32EL:#define __INT64_C_SUFFIX__ LL
// MIPS32EL:#define __INT64_FMTd__ "lld"
// MIPS32EL:#define __INT64_FMTi__ "lli"
// MIPS32EL:#define __INT64_MAX__ 9223372036854775807LL
// MIPS32EL:#define __INT64_TYPE__ long long int
// MIPS32EL:#define __INT8_C_SUFFIX__
// MIPS32EL:#define __INT8_FMTd__ "hhd"
// MIPS32EL:#define __INT8_FMTi__ "hhi"
// MIPS32EL:#define __INT8_MAX__ 127
// MIPS32EL:#define __INT8_TYPE__ signed char
// MIPS32EL:#define __INTMAX_C_SUFFIX__ LL
// MIPS32EL:#define __INTMAX_FMTd__ "lld"
// MIPS32EL:#define __INTMAX_FMTi__ "lli"
// MIPS32EL:#define __INTMAX_MAX__ 9223372036854775807LL
// MIPS32EL:#define __INTMAX_TYPE__ long long int
// MIPS32EL:#define __INTMAX_WIDTH__ 64
// MIPS32EL:#define __INTPTR_FMTd__ "ld"
// MIPS32EL:#define __INTPTR_FMTi__ "li"
// MIPS32EL:#define __INTPTR_MAX__ 2147483647L
// MIPS32EL:#define __INTPTR_TYPE__ long int
// MIPS32EL:#define __INTPTR_WIDTH__ 32
// MIPS32EL:#define __INT_FAST16_FMTd__ "hd"
// MIPS32EL:#define __INT_FAST16_FMTi__ "hi"
// MIPS32EL:#define __INT_FAST16_MAX__ 32767
// MIPS32EL:#define __INT_FAST16_TYPE__ short
// MIPS32EL:#define __INT_FAST32_FMTd__ "d"
// MIPS32EL:#define __INT_FAST32_FMTi__ "i"
// MIPS32EL:#define __INT_FAST32_MAX__ 2147483647
// MIPS32EL:#define __INT_FAST32_TYPE__ int
// MIPS32EL:#define __INT_FAST64_FMTd__ "lld"
// MIPS32EL:#define __INT_FAST64_FMTi__ "lli"
// MIPS32EL:#define __INT_FAST64_MAX__ 9223372036854775807LL
// MIPS32EL:#define __INT_FAST64_TYPE__ long long int
// MIPS32EL:#define __INT_FAST8_FMTd__ "hhd"
// MIPS32EL:#define __INT_FAST8_FMTi__ "hhi"
// MIPS32EL:#define __INT_FAST8_MAX__ 127
// MIPS32EL:#define __INT_FAST8_TYPE__ signed char
// MIPS32EL:#define __INT_LEAST16_FMTd__ "hd"
// MIPS32EL:#define __INT_LEAST16_FMTi__ "hi"
// MIPS32EL:#define __INT_LEAST16_MAX__ 32767
// MIPS32EL:#define __INT_LEAST16_TYPE__ short
// MIPS32EL:#define __INT_LEAST32_FMTd__ "d"
// MIPS32EL:#define __INT_LEAST32_FMTi__ "i"
// MIPS32EL:#define __INT_LEAST32_MAX__ 2147483647
// MIPS32EL:#define __INT_LEAST32_TYPE__ int
// MIPS32EL:#define __INT_LEAST64_FMTd__ "lld"
// MIPS32EL:#define __INT_LEAST64_FMTi__ "lli"
// MIPS32EL:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// MIPS32EL:#define __INT_LEAST64_TYPE__ long long int
// MIPS32EL:#define __INT_LEAST8_FMTd__ "hhd"
// MIPS32EL:#define __INT_LEAST8_FMTi__ "hhi"
// MIPS32EL:#define __INT_LEAST8_MAX__ 127
// MIPS32EL:#define __INT_LEAST8_TYPE__ signed char
// MIPS32EL:#define __INT_MAX__ 2147483647
// MIPS32EL:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
// MIPS32EL:#define __LDBL_DIG__ 15
// MIPS32EL:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
// MIPS32EL:#define __LDBL_HAS_DENORM__ 1
// MIPS32EL:#define __LDBL_HAS_INFINITY__ 1
// MIPS32EL:#define __LDBL_HAS_QUIET_NAN__ 1
// MIPS32EL:#define __LDBL_MANT_DIG__ 53
// MIPS32EL:#define __LDBL_MAX_10_EXP__ 308
// MIPS32EL:#define __LDBL_MAX_EXP__ 1024
// MIPS32EL:#define __LDBL_MAX__ 1.7976931348623157e+308L
// MIPS32EL:#define __LDBL_MIN_10_EXP__ (-307)
// MIPS32EL:#define __LDBL_MIN_EXP__ (-1021)
// MIPS32EL:#define __LDBL_MIN__ 2.2250738585072014e-308L
// MIPS32EL:#define __LITTLE_ENDIAN__ 1
// MIPS32EL:#define __LONG_LONG_MAX__ 9223372036854775807LL
// MIPS32EL:#define __LONG_MAX__ 2147483647L
// MIPS32EL-NOT:#define __LP64__
// MIPS32EL:#define __MIPSEL 1
// MIPS32EL:#define __MIPSEL__ 1
// MIPS32EL:#define __POINTER_WIDTH__ 32
// MIPS32EL:#define __PRAGMA_REDEFINE_EXTNAME 1
// MIPS32EL:#define __PTRDIFF_TYPE__ int
// MIPS32EL:#define __PTRDIFF_WIDTH__ 32
// MIPS32EL:#define __REGISTER_PREFIX__
// MIPS32EL:#define __SCHAR_MAX__ 127
// MIPS32EL:#define __SHRT_MAX__ 32767
// MIPS32EL:#define __SIG_ATOMIC_MAX__ 2147483647
// MIPS32EL:#define __SIG_ATOMIC_WIDTH__ 32
// MIPS32EL:#define __SIZEOF_DOUBLE__ 8
// MIPS32EL:#define __SIZEOF_FLOAT__ 4
// MIPS32EL:#define __SIZEOF_INT__ 4
// MIPS32EL:#define __SIZEOF_LONG_DOUBLE__ 8
// MIPS32EL:#define __SIZEOF_LONG_LONG__ 8
// MIPS32EL:#define __SIZEOF_LONG__ 4
// MIPS32EL:#define __SIZEOF_POINTER__ 4
// MIPS32EL:#define __SIZEOF_PTRDIFF_T__ 4
// MIPS32EL:#define __SIZEOF_SHORT__ 2
// MIPS32EL:#define __SIZEOF_SIZE_T__ 4
// MIPS32EL:#define __SIZEOF_WCHAR_T__ 4
// MIPS32EL:#define __SIZEOF_WINT_T__ 4
// MIPS32EL:#define __SIZE_MAX__ 4294967295U
// MIPS32EL:#define __SIZE_TYPE__ unsigned int
// MIPS32EL:#define __SIZE_WIDTH__ 32
// MIPS32EL:#define __UINT16_C_SUFFIX__
// MIPS32EL:#define __UINT16_MAX__ 65535
// MIPS32EL:#define __UINT16_TYPE__ unsigned short
// MIPS32EL:#define __UINT32_C_SUFFIX__ U
// MIPS32EL:#define __UINT32_MAX__ 4294967295U
// MIPS32EL:#define __UINT32_TYPE__ unsigned int
// MIPS32EL:#define __UINT64_C_SUFFIX__ ULL
// MIPS32EL:#define __UINT64_MAX__ 18446744073709551615ULL
// MIPS32EL:#define __UINT64_TYPE__ long long unsigned int
// MIPS32EL:#define __UINT8_C_SUFFIX__
// MIPS32EL:#define __UINT8_MAX__ 255
// MIPS32EL:#define __UINT8_TYPE__ unsigned char
// MIPS32EL:#define __UINTMAX_C_SUFFIX__ ULL
// MIPS32EL:#define __UINTMAX_MAX__ 18446744073709551615ULL
// MIPS32EL:#define __UINTMAX_TYPE__ long long unsigned int
// MIPS32EL:#define __UINTMAX_WIDTH__ 64
// MIPS32EL:#define __UINTPTR_MAX__ 4294967295UL
// MIPS32EL:#define __UINTPTR_TYPE__ long unsigned int
// MIPS32EL:#define __UINTPTR_WIDTH__ 32
// MIPS32EL:#define __UINT_FAST16_MAX__ 65535
// MIPS32EL:#define __UINT_FAST16_TYPE__ unsigned short
// MIPS32EL:#define __UINT_FAST32_MAX__ 4294967295U
// MIPS32EL:#define __UINT_FAST32_TYPE__ unsigned int
// MIPS32EL:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// MIPS32EL:#define __UINT_FAST64_TYPE__ long long unsigned int
// MIPS32EL:#define __UINT_FAST8_MAX__ 255
// MIPS32EL:#define __UINT_FAST8_TYPE__ unsigned char
// MIPS32EL:#define __UINT_LEAST16_MAX__ 65535
// MIPS32EL:#define __UINT_LEAST16_TYPE__ unsigned short
// MIPS32EL:#define __UINT_LEAST32_MAX__ 4294967295U
// MIPS32EL:#define __UINT_LEAST32_TYPE__ unsigned int
// MIPS32EL:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// MIPS32EL:#define __UINT_LEAST64_TYPE__ long long unsigned int
// MIPS32EL:#define __UINT_LEAST8_MAX__ 255
// MIPS32EL:#define __UINT_LEAST8_TYPE__ unsigned char
// MIPS32EL:#define __USER_LABEL_PREFIX__
// MIPS32EL:#define __WCHAR_MAX__ 2147483647
// MIPS32EL:#define __WCHAR_TYPE__ int
// MIPS32EL:#define __WCHAR_WIDTH__ 32
// MIPS32EL:#define __WINT_TYPE__ int
// MIPS32EL:#define __WINT_WIDTH__ 32
// MIPS32EL:#define __clang__ 1
// MIPS32EL:#define __llvm__ 1
// MIPS32EL:#define __mips 32
// MIPS32EL:#define __mips__ 1
// MIPS32EL:#define __mips_abicalls 1
// MIPS32EL:#define __mips_fpr 0
// MIPS32EL:#define __mips_hard_float 1
// MIPS32EL:#define __mips_o32 1
// MIPS32EL:#define _mips 1
// MIPS32EL:#define mips 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding \
// RUN: -triple=mips64-none-none -target-abi n32 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPSN32BE -check-prefix MIPSN32BE-C %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding \
// RUN: -triple=mips64-none-none -target-abi n32 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPSN32BE -check-prefix MIPSN32BE-CXX %s
//
// MIPSN32BE: #define MIPSEB 1
// MIPSN32BE: #define _ABIN32 2
// MIPSN32BE: #define _ILP32 1
// MIPSN32BE: #define _MIPSEB 1
// MIPSN32BE: #define _MIPS_ARCH "mips64r2"
// MIPSN32BE: #define _MIPS_ARCH_MIPS64R2 1
// MIPSN32BE: #define _MIPS_FPSET 32
// MIPSN32BE: #define _MIPS_ISA _MIPS_ISA_MIPS64
// MIPSN32BE: #define _MIPS_SIM _ABIN32
// MIPSN32BE: #define _MIPS_SZINT 32
// MIPSN32BE: #define _MIPS_SZLONG 32
// MIPSN32BE: #define _MIPS_SZPTR 32
// MIPSN32BE: #define __ATOMIC_ACQUIRE 2
// MIPSN32BE: #define __ATOMIC_ACQ_REL 4
// MIPSN32BE: #define __ATOMIC_CONSUME 1
// MIPSN32BE: #define __ATOMIC_RELAXED 0
// MIPSN32BE: #define __ATOMIC_RELEASE 3
// MIPSN32BE: #define __ATOMIC_SEQ_CST 5
// MIPSN32BE: #define __BIG_ENDIAN__ 1
// MIPSN32BE: #define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
// MIPSN32BE: #define __CHAR16_TYPE__ unsigned short
// MIPSN32BE: #define __CHAR32_TYPE__ unsigned int
// MIPSN32BE: #define __CHAR_BIT__ 8
// MIPSN32BE: #define __CONSTANT_CFSTRINGS__ 1
// MIPSN32BE: #define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// MIPSN32BE: #define __DBL_DIG__ 15
// MIPSN32BE: #define __DBL_EPSILON__ 2.2204460492503131e-16
// MIPSN32BE: #define __DBL_HAS_DENORM__ 1
// MIPSN32BE: #define __DBL_HAS_INFINITY__ 1
// MIPSN32BE: #define __DBL_HAS_QUIET_NAN__ 1
// MIPSN32BE: #define __DBL_MANT_DIG__ 53
// MIPSN32BE: #define __DBL_MAX_10_EXP__ 308
// MIPSN32BE: #define __DBL_MAX_EXP__ 1024
// MIPSN32BE: #define __DBL_MAX__ 1.7976931348623157e+308
// MIPSN32BE: #define __DBL_MIN_10_EXP__ (-307)
// MIPSN32BE: #define __DBL_MIN_EXP__ (-1021)
// MIPSN32BE: #define __DBL_MIN__ 2.2250738585072014e-308
// MIPSN32BE: #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// MIPSN32BE: #define __FINITE_MATH_ONLY__ 0
// MIPSN32BE: #define __FLT_DENORM_MIN__ 1.40129846e-45F
// MIPSN32BE: #define __FLT_DIG__ 6
// MIPSN32BE: #define __FLT_EPSILON__ 1.19209290e-7F
// MIPSN32BE: #define __FLT_EVAL_METHOD__ 0
// MIPSN32BE: #define __FLT_HAS_DENORM__ 1
// MIPSN32BE: #define __FLT_HAS_INFINITY__ 1
// MIPSN32BE: #define __FLT_HAS_QUIET_NAN__ 1
// MIPSN32BE: #define __FLT_MANT_DIG__ 24
// MIPSN32BE: #define __FLT_MAX_10_EXP__ 38
// MIPSN32BE: #define __FLT_MAX_EXP__ 128
// MIPSN32BE: #define __FLT_MAX__ 3.40282347e+38F
// MIPSN32BE: #define __FLT_MIN_10_EXP__ (-37)
// MIPSN32BE: #define __FLT_MIN_EXP__ (-125)
// MIPSN32BE: #define __FLT_MIN__ 1.17549435e-38F
// MIPSN32BE: #define __FLT_RADIX__ 2
// MIPSN32BE: #define __GCC_ATOMIC_BOOL_LOCK_FREE 2
// MIPSN32BE: #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
// MIPSN32BE: #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
// MIPSN32BE: #define __GCC_ATOMIC_CHAR_LOCK_FREE 2
// MIPSN32BE: #define __GCC_ATOMIC_INT_LOCK_FREE 2
// MIPSN32BE: #define __GCC_ATOMIC_LLONG_LOCK_FREE 2
// MIPSN32BE: #define __GCC_ATOMIC_LONG_LOCK_FREE 2
// MIPSN32BE: #define __GCC_ATOMIC_POINTER_LOCK_FREE 2
// MIPSN32BE: #define __GCC_ATOMIC_SHORT_LOCK_FREE 2
// MIPSN32BE: #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
// MIPSN32BE: #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
// MIPSN32BE: #define __GNUC_MINOR__ 2
// MIPSN32BE: #define __GNUC_PATCHLEVEL__ 1
// MIPSN32BE-C: #define __GNUC_STDC_INLINE__ 1
// MIPSN32BE: #define __GNUC__ 4
// MIPSN32BE: #define __GXX_ABI_VERSION 1002
// MIPSN32BE: #define __ILP32__ 1
// MIPSN32BE: #define __INT16_C_SUFFIX__
// MIPSN32BE: #define __INT16_FMTd__ "hd"
// MIPSN32BE: #define __INT16_FMTi__ "hi"
// MIPSN32BE: #define __INT16_MAX__ 32767
// MIPSN32BE: #define __INT16_TYPE__ short
// MIPSN32BE: #define __INT32_C_SUFFIX__
// MIPSN32BE: #define __INT32_FMTd__ "d"
// MIPSN32BE: #define __INT32_FMTi__ "i"
// MIPSN32BE: #define __INT32_MAX__ 2147483647
// MIPSN32BE: #define __INT32_TYPE__ int
// MIPSN32BE: #define __INT64_C_SUFFIX__ LL
// MIPSN32BE: #define __INT64_FMTd__ "lld"
// MIPSN32BE: #define __INT64_FMTi__ "lli"
// MIPSN32BE: #define __INT64_MAX__ 9223372036854775807LL
// MIPSN32BE: #define __INT64_TYPE__ long long int
// MIPSN32BE: #define __INT8_C_SUFFIX__
// MIPSN32BE: #define __INT8_FMTd__ "hhd"
// MIPSN32BE: #define __INT8_FMTi__ "hhi"
// MIPSN32BE: #define __INT8_MAX__ 127
// MIPSN32BE: #define __INT8_TYPE__ signed char
// MIPSN32BE: #define __INTMAX_C_SUFFIX__ LL
// MIPSN32BE: #define __INTMAX_FMTd__ "lld"
// MIPSN32BE: #define __INTMAX_FMTi__ "lli"
// MIPSN32BE: #define __INTMAX_MAX__ 9223372036854775807LL
// MIPSN32BE: #define __INTMAX_TYPE__ long long int
// MIPSN32BE: #define __INTMAX_WIDTH__ 64
// MIPSN32BE: #define __INTPTR_FMTd__ "ld"
// MIPSN32BE: #define __INTPTR_FMTi__ "li"
// MIPSN32BE: #define __INTPTR_MAX__ 2147483647L
// MIPSN32BE: #define __INTPTR_TYPE__ long int
// MIPSN32BE: #define __INTPTR_WIDTH__ 32
// MIPSN32BE: #define __INT_FAST16_FMTd__ "hd"
// MIPSN32BE: #define __INT_FAST16_FMTi__ "hi"
// MIPSN32BE: #define __INT_FAST16_MAX__ 32767
// MIPSN32BE: #define __INT_FAST16_TYPE__ short
// MIPSN32BE: #define __INT_FAST32_FMTd__ "d"
// MIPSN32BE: #define __INT_FAST32_FMTi__ "i"
// MIPSN32BE: #define __INT_FAST32_MAX__ 2147483647
// MIPSN32BE: #define __INT_FAST32_TYPE__ int
// MIPSN32BE: #define __INT_FAST64_FMTd__ "lld"
// MIPSN32BE: #define __INT_FAST64_FMTi__ "lli"
// MIPSN32BE: #define __INT_FAST64_MAX__ 9223372036854775807LL
// MIPSN32BE: #define __INT_FAST64_TYPE__ long long int
// MIPSN32BE: #define __INT_FAST8_FMTd__ "hhd"
// MIPSN32BE: #define __INT_FAST8_FMTi__ "hhi"
// MIPSN32BE: #define __INT_FAST8_MAX__ 127
// MIPSN32BE: #define __INT_FAST8_TYPE__ signed char
// MIPSN32BE: #define __INT_LEAST16_FMTd__ "hd"
// MIPSN32BE: #define __INT_LEAST16_FMTi__ "hi"
// MIPSN32BE: #define __INT_LEAST16_MAX__ 32767
// MIPSN32BE: #define __INT_LEAST16_TYPE__ short
// MIPSN32BE: #define __INT_LEAST32_FMTd__ "d"
// MIPSN32BE: #define __INT_LEAST32_FMTi__ "i"
// MIPSN32BE: #define __INT_LEAST32_MAX__ 2147483647
// MIPSN32BE: #define __INT_LEAST32_TYPE__ int
// MIPSN32BE: #define __INT_LEAST64_FMTd__ "lld"
// MIPSN32BE: #define __INT_LEAST64_FMTi__ "lli"
// MIPSN32BE: #define __INT_LEAST64_MAX__ 9223372036854775807LL
// MIPSN32BE: #define __INT_LEAST64_TYPE__ long long int
// MIPSN32BE: #define __INT_LEAST8_FMTd__ "hhd"
// MIPSN32BE: #define __INT_LEAST8_FMTi__ "hhi"
// MIPSN32BE: #define __INT_LEAST8_MAX__ 127
// MIPSN32BE: #define __INT_LEAST8_TYPE__ signed char
// MIPSN32BE: #define __INT_MAX__ 2147483647
// MIPSN32BE: #define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
// MIPSN32BE: #define __LDBL_DIG__ 33
// MIPSN32BE: #define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// MIPSN32BE: #define __LDBL_HAS_DENORM__ 1
// MIPSN32BE: #define __LDBL_HAS_INFINITY__ 1
// MIPSN32BE: #define __LDBL_HAS_QUIET_NAN__ 1
// MIPSN32BE: #define __LDBL_MANT_DIG__ 113
// MIPSN32BE: #define __LDBL_MAX_10_EXP__ 4932
// MIPSN32BE: #define __LDBL_MAX_EXP__ 16384
// MIPSN32BE: #define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
// MIPSN32BE: #define __LDBL_MIN_10_EXP__ (-4931)
// MIPSN32BE: #define __LDBL_MIN_EXP__ (-16381)
// MIPSN32BE: #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// MIPSN32BE: #define __LONG_LONG_MAX__ 9223372036854775807LL
// MIPSN32BE: #define __LONG_MAX__ 2147483647L
// MIPSN32BE: #define __MIPSEB 1
// MIPSN32BE: #define __MIPSEB__ 1
// MIPSN32BE: #define __NO_INLINE__ 1
// MIPSN32BE: #define __ORDER_BIG_ENDIAN__ 4321
// MIPSN32BE: #define __ORDER_LITTLE_ENDIAN__ 1234
// MIPSN32BE: #define __ORDER_PDP_ENDIAN__ 3412
// MIPSN32BE: #define __POINTER_WIDTH__ 32
// MIPSN32BE: #define __PRAGMA_REDEFINE_EXTNAME 1
// MIPSN32BE: #define __PTRDIFF_FMTd__ "d"
// MIPSN32BE: #define __PTRDIFF_FMTi__ "i"
// MIPSN32BE: #define __PTRDIFF_MAX__ 2147483647
// MIPSN32BE: #define __PTRDIFF_TYPE__ int
// MIPSN32BE: #define __PTRDIFF_WIDTH__ 32
// MIPSN32BE: #define __REGISTER_PREFIX__
// MIPSN32BE: #define __SCHAR_MAX__ 127
// MIPSN32BE: #define __SHRT_MAX__ 32767
// MIPSN32BE: #define __SIG_ATOMIC_MAX__ 2147483647
// MIPSN32BE: #define __SIG_ATOMIC_WIDTH__ 32
// MIPSN32BE: #define __SIZEOF_DOUBLE__ 8
// MIPSN32BE: #define __SIZEOF_FLOAT__ 4
// MIPSN32BE: #define __SIZEOF_INT__ 4
// MIPSN32BE: #define __SIZEOF_LONG_DOUBLE__ 16
// MIPSN32BE: #define __SIZEOF_LONG_LONG__ 8
// MIPSN32BE: #define __SIZEOF_LONG__ 4
// MIPSN32BE: #define __SIZEOF_POINTER__ 4
// MIPSN32BE: #define __SIZEOF_PTRDIFF_T__ 4
// MIPSN32BE: #define __SIZEOF_SHORT__ 2
// MIPSN32BE: #define __SIZEOF_SIZE_T__ 4
// MIPSN32BE: #define __SIZEOF_WCHAR_T__ 4
// MIPSN32BE: #define __SIZEOF_WINT_T__ 4
// MIPSN32BE: #define __SIZE_FMTX__ "X"
// MIPSN32BE: #define __SIZE_FMTo__ "o"
// MIPSN32BE: #define __SIZE_FMTu__ "u"
// MIPSN32BE: #define __SIZE_FMTx__ "x"
// MIPSN32BE: #define __SIZE_MAX__ 4294967295U
// MIPSN32BE: #define __SIZE_TYPE__ unsigned int
// MIPSN32BE: #define __SIZE_WIDTH__ 32
// MIPSN32BE-CXX: #define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16U
// MIPSN32BE: #define __STDC_HOSTED__ 0
// MIPSN32BE: #define __STDC_UTF_16__ 1
// MIPSN32BE: #define __STDC_UTF_32__ 1
// MIPSN32BE-C: #define __STDC_VERSION__ 201112L
// MIPSN32BE: #define __STDC__ 1
// MIPSN32BE: #define __UINT16_C_SUFFIX__
// MIPSN32BE: #define __UINT16_FMTX__ "hX"
// MIPSN32BE: #define __UINT16_FMTo__ "ho"
// MIPSN32BE: #define __UINT16_FMTu__ "hu"
// MIPSN32BE: #define __UINT16_FMTx__ "hx"
// MIPSN32BE: #define __UINT16_MAX__ 65535
// MIPSN32BE: #define __UINT16_TYPE__ unsigned short
// MIPSN32BE: #define __UINT32_C_SUFFIX__ U
// MIPSN32BE: #define __UINT32_FMTX__ "X"
// MIPSN32BE: #define __UINT32_FMTo__ "o"
// MIPSN32BE: #define __UINT32_FMTu__ "u"
// MIPSN32BE: #define __UINT32_FMTx__ "x"
// MIPSN32BE: #define __UINT32_MAX__ 4294967295U
// MIPSN32BE: #define __UINT32_TYPE__ unsigned int
// MIPSN32BE: #define __UINT64_C_SUFFIX__ ULL
// MIPSN32BE: #define __UINT64_FMTX__ "llX"
// MIPSN32BE: #define __UINT64_FMTo__ "llo"
// MIPSN32BE: #define __UINT64_FMTu__ "llu"
// MIPSN32BE: #define __UINT64_FMTx__ "llx"
// MIPSN32BE: #define __UINT64_MAX__ 18446744073709551615ULL
// MIPSN32BE: #define __UINT64_TYPE__ long long unsigned int
// MIPSN32BE: #define __UINT8_C_SUFFIX__
// MIPSN32BE: #define __UINT8_FMTX__ "hhX"
// MIPSN32BE: #define __UINT8_FMTo__ "hho"
// MIPSN32BE: #define __UINT8_FMTu__ "hhu"
// MIPSN32BE: #define __UINT8_FMTx__ "hhx"
// MIPSN32BE: #define __UINT8_MAX__ 255
// MIPSN32BE: #define __UINT8_TYPE__ unsigned char
// MIPSN32BE: #define __UINTMAX_C_SUFFIX__ ULL
// MIPSN32BE: #define __UINTMAX_FMTX__ "llX"
// MIPSN32BE: #define __UINTMAX_FMTo__ "llo"
// MIPSN32BE: #define __UINTMAX_FMTu__ "llu"
// MIPSN32BE: #define __UINTMAX_FMTx__ "llx"
// MIPSN32BE: #define __UINTMAX_MAX__ 18446744073709551615ULL
// MIPSN32BE: #define __UINTMAX_TYPE__ long long unsigned int
// MIPSN32BE: #define __UINTMAX_WIDTH__ 64
// MIPSN32BE: #define __UINTPTR_FMTX__ "lX"
// MIPSN32BE: #define __UINTPTR_FMTo__ "lo"
// MIPSN32BE: #define __UINTPTR_FMTu__ "lu"
// MIPSN32BE: #define __UINTPTR_FMTx__ "lx"
// MIPSN32BE: #define __UINTPTR_MAX__ 4294967295UL
// MIPSN32BE: #define __UINTPTR_TYPE__ long unsigned int
// MIPSN32BE: #define __UINTPTR_WIDTH__ 32
// MIPSN32BE: #define __UINT_FAST16_FMTX__ "hX"
// MIPSN32BE: #define __UINT_FAST16_FMTo__ "ho"
// MIPSN32BE: #define __UINT_FAST16_FMTu__ "hu"
// MIPSN32BE: #define __UINT_FAST16_FMTx__ "hx"
// MIPSN32BE: #define __UINT_FAST16_MAX__ 65535
// MIPSN32BE: #define __UINT_FAST16_TYPE__ unsigned short
// MIPSN32BE: #define __UINT_FAST32_FMTX__ "X"
// MIPSN32BE: #define __UINT_FAST32_FMTo__ "o"
// MIPSN32BE: #define __UINT_FAST32_FMTu__ "u"
// MIPSN32BE: #define __UINT_FAST32_FMTx__ "x"
// MIPSN32BE: #define __UINT_FAST32_MAX__ 4294967295U
// MIPSN32BE: #define __UINT_FAST32_TYPE__ unsigned int
// MIPSN32BE: #define __UINT_FAST64_FMTX__ "llX"
// MIPSN32BE: #define __UINT_FAST64_FMTo__ "llo"
// MIPSN32BE: #define __UINT_FAST64_FMTu__ "llu"
// MIPSN32BE: #define __UINT_FAST64_FMTx__ "llx"
// MIPSN32BE: #define __UINT_FAST64_MAX__ 18446744073709551615ULL
// MIPSN32BE: #define __UINT_FAST64_TYPE__ long long unsigned int
// MIPSN32BE: #define __UINT_FAST8_FMTX__ "hhX"
// MIPSN32BE: #define __UINT_FAST8_FMTo__ "hho"
// MIPSN32BE: #define __UINT_FAST8_FMTu__ "hhu"
// MIPSN32BE: #define __UINT_FAST8_FMTx__ "hhx"
// MIPSN32BE: #define __UINT_FAST8_MAX__ 255
// MIPSN32BE: #define __UINT_FAST8_TYPE__ unsigned char
// MIPSN32BE: #define __UINT_LEAST16_FMTX__ "hX"
// MIPSN32BE: #define __UINT_LEAST16_FMTo__ "ho"
// MIPSN32BE: #define __UINT_LEAST16_FMTu__ "hu"
// MIPSN32BE: #define __UINT_LEAST16_FMTx__ "hx"
// MIPSN32BE: #define __UINT_LEAST16_MAX__ 65535
// MIPSN32BE: #define __UINT_LEAST16_TYPE__ unsigned short
// MIPSN32BE: #define __UINT_LEAST32_FMTX__ "X"
// MIPSN32BE: #define __UINT_LEAST32_FMTo__ "o"
// MIPSN32BE: #define __UINT_LEAST32_FMTu__ "u"
// MIPSN32BE: #define __UINT_LEAST32_FMTx__ "x"
// MIPSN32BE: #define __UINT_LEAST32_MAX__ 4294967295U
// MIPSN32BE: #define __UINT_LEAST32_TYPE__ unsigned int
// MIPSN32BE: #define __UINT_LEAST64_FMTX__ "llX"
// MIPSN32BE: #define __UINT_LEAST64_FMTo__ "llo"
// MIPSN32BE: #define __UINT_LEAST64_FMTu__ "llu"
// MIPSN32BE: #define __UINT_LEAST64_FMTx__ "llx"
// MIPSN32BE: #define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// MIPSN32BE: #define __UINT_LEAST64_TYPE__ long long unsigned int
// MIPSN32BE: #define __UINT_LEAST8_FMTX__ "hhX"
// MIPSN32BE: #define __UINT_LEAST8_FMTo__ "hho"
// MIPSN32BE: #define __UINT_LEAST8_FMTu__ "hhu"
// MIPSN32BE: #define __UINT_LEAST8_FMTx__ "hhx"
// MIPSN32BE: #define __UINT_LEAST8_MAX__ 255
// MIPSN32BE: #define __UINT_LEAST8_TYPE__ unsigned char
// MIPSN32BE: #define __USER_LABEL_PREFIX__
// MIPSN32BE: #define __WCHAR_MAX__ 2147483647
// MIPSN32BE: #define __WCHAR_TYPE__ int
// MIPSN32BE: #define __WCHAR_WIDTH__ 32
// MIPSN32BE: #define __WINT_TYPE__ int
// MIPSN32BE: #define __WINT_WIDTH__ 32
// MIPSN32BE: #define __clang__ 1
// MIPSN32BE: #define __llvm__ 1
// MIPSN32BE: #define __mips 64
// MIPSN32BE: #define __mips64 1
// MIPSN32BE: #define __mips64__ 1
// MIPSN32BE: #define __mips__ 1
// MIPSN32BE: #define __mips_abicalls 1
// MIPSN32BE: #define __mips_fpr 64
// MIPSN32BE: #define __mips_hard_float 1
// MIPSN32BE: #define __mips_isa_rev 2
// MIPSN32BE: #define __mips_n32 1
// MIPSN32BE: #define _mips 1
// MIPSN32BE: #define mips 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding \
// RUN: -triple=mips64el-none-none -target-abi n32 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPSN32EL %s
//
// MIPSN32EL: #define MIPSEL 1
// MIPSN32EL: #define _ABIN32 2
// MIPSN32EL: #define _ILP32 1
// MIPSN32EL: #define _MIPSEL 1
// MIPSN32EL: #define _MIPS_ARCH "mips64r2"
// MIPSN32EL: #define _MIPS_ARCH_MIPS64R2 1
// MIPSN32EL: #define _MIPS_FPSET 32
// MIPSN32EL: #define _MIPS_ISA _MIPS_ISA_MIPS64
// MIPSN32EL: #define _MIPS_SIM _ABIN32
// MIPSN32EL: #define _MIPS_SZINT 32
// MIPSN32EL: #define _MIPS_SZLONG 32
// MIPSN32EL: #define _MIPS_SZPTR 32
// MIPSN32EL: #define __ATOMIC_ACQUIRE 2
// MIPSN32EL: #define __ATOMIC_ACQ_REL 4
// MIPSN32EL: #define __ATOMIC_CONSUME 1
// MIPSN32EL: #define __ATOMIC_RELAXED 0
// MIPSN32EL: #define __ATOMIC_RELEASE 3
// MIPSN32EL: #define __ATOMIC_SEQ_CST 5
// MIPSN32EL: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// MIPSN32EL: #define __CHAR16_TYPE__ unsigned short
// MIPSN32EL: #define __CHAR32_TYPE__ unsigned int
// MIPSN32EL: #define __CHAR_BIT__ 8
// MIPSN32EL: #define __CONSTANT_CFSTRINGS__ 1
// MIPSN32EL: #define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// MIPSN32EL: #define __DBL_DIG__ 15
// MIPSN32EL: #define __DBL_EPSILON__ 2.2204460492503131e-16
// MIPSN32EL: #define __DBL_HAS_DENORM__ 1
// MIPSN32EL: #define __DBL_HAS_INFINITY__ 1
// MIPSN32EL: #define __DBL_HAS_QUIET_NAN__ 1
// MIPSN32EL: #define __DBL_MANT_DIG__ 53
// MIPSN32EL: #define __DBL_MAX_10_EXP__ 308
// MIPSN32EL: #define __DBL_MAX_EXP__ 1024
// MIPSN32EL: #define __DBL_MAX__ 1.7976931348623157e+308
// MIPSN32EL: #define __DBL_MIN_10_EXP__ (-307)
// MIPSN32EL: #define __DBL_MIN_EXP__ (-1021)
// MIPSN32EL: #define __DBL_MIN__ 2.2250738585072014e-308
// MIPSN32EL: #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// MIPSN32EL: #define __FINITE_MATH_ONLY__ 0
// MIPSN32EL: #define __FLT_DENORM_MIN__ 1.40129846e-45F
// MIPSN32EL: #define __FLT_DIG__ 6
// MIPSN32EL: #define __FLT_EPSILON__ 1.19209290e-7F
// MIPSN32EL: #define __FLT_EVAL_METHOD__ 0
// MIPSN32EL: #define __FLT_HAS_DENORM__ 1
// MIPSN32EL: #define __FLT_HAS_INFINITY__ 1
// MIPSN32EL: #define __FLT_HAS_QUIET_NAN__ 1
// MIPSN32EL: #define __FLT_MANT_DIG__ 24
// MIPSN32EL: #define __FLT_MAX_10_EXP__ 38
// MIPSN32EL: #define __FLT_MAX_EXP__ 128
// MIPSN32EL: #define __FLT_MAX__ 3.40282347e+38F
// MIPSN32EL: #define __FLT_MIN_10_EXP__ (-37)
// MIPSN32EL: #define __FLT_MIN_EXP__ (-125)
// MIPSN32EL: #define __FLT_MIN__ 1.17549435e-38F
// MIPSN32EL: #define __FLT_RADIX__ 2
// MIPSN32EL: #define __GCC_ATOMIC_BOOL_LOCK_FREE 2
// MIPSN32EL: #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
// MIPSN32EL: #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
// MIPSN32EL: #define __GCC_ATOMIC_CHAR_LOCK_FREE 2
// MIPSN32EL: #define __GCC_ATOMIC_INT_LOCK_FREE 2
// MIPSN32EL: #define __GCC_ATOMIC_LLONG_LOCK_FREE 2
// MIPSN32EL: #define __GCC_ATOMIC_LONG_LOCK_FREE 2
// MIPSN32EL: #define __GCC_ATOMIC_POINTER_LOCK_FREE 2
// MIPSN32EL: #define __GCC_ATOMIC_SHORT_LOCK_FREE 2
// MIPSN32EL: #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
// MIPSN32EL: #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
// MIPSN32EL: #define __GNUC_MINOR__ 2
// MIPSN32EL: #define __GNUC_PATCHLEVEL__ 1
// MIPSN32EL: #define __GNUC_STDC_INLINE__ 1
// MIPSN32EL: #define __GNUC__ 4
// MIPSN32EL: #define __GXX_ABI_VERSION 1002
// MIPSN32EL: #define __ILP32__ 1
// MIPSN32EL: #define __INT16_C_SUFFIX__
// MIPSN32EL: #define __INT16_FMTd__ "hd"
// MIPSN32EL: #define __INT16_FMTi__ "hi"
// MIPSN32EL: #define __INT16_MAX__ 32767
// MIPSN32EL: #define __INT16_TYPE__ short
// MIPSN32EL: #define __INT32_C_SUFFIX__
// MIPSN32EL: #define __INT32_FMTd__ "d"
// MIPSN32EL: #define __INT32_FMTi__ "i"
// MIPSN32EL: #define __INT32_MAX__ 2147483647
// MIPSN32EL: #define __INT32_TYPE__ int
// MIPSN32EL: #define __INT64_C_SUFFIX__ LL
// MIPSN32EL: #define __INT64_FMTd__ "lld"
// MIPSN32EL: #define __INT64_FMTi__ "lli"
// MIPSN32EL: #define __INT64_MAX__ 9223372036854775807LL
// MIPSN32EL: #define __INT64_TYPE__ long long int
// MIPSN32EL: #define __INT8_C_SUFFIX__
// MIPSN32EL: #define __INT8_FMTd__ "hhd"
// MIPSN32EL: #define __INT8_FMTi__ "hhi"
// MIPSN32EL: #define __INT8_MAX__ 127
// MIPSN32EL: #define __INT8_TYPE__ signed char
// MIPSN32EL: #define __INTMAX_C_SUFFIX__ LL
// MIPSN32EL: #define __INTMAX_FMTd__ "lld"
// MIPSN32EL: #define __INTMAX_FMTi__ "lli"
// MIPSN32EL: #define __INTMAX_MAX__ 9223372036854775807LL
// MIPSN32EL: #define __INTMAX_TYPE__ long long int
// MIPSN32EL: #define __INTMAX_WIDTH__ 64
// MIPSN32EL: #define __INTPTR_FMTd__ "ld"
// MIPSN32EL: #define __INTPTR_FMTi__ "li"
// MIPSN32EL: #define __INTPTR_MAX__ 2147483647L
// MIPSN32EL: #define __INTPTR_TYPE__ long int
// MIPSN32EL: #define __INTPTR_WIDTH__ 32
// MIPSN32EL: #define __INT_FAST16_FMTd__ "hd"
// MIPSN32EL: #define __INT_FAST16_FMTi__ "hi"
// MIPSN32EL: #define __INT_FAST16_MAX__ 32767
// MIPSN32EL: #define __INT_FAST16_TYPE__ short
// MIPSN32EL: #define __INT_FAST32_FMTd__ "d"
// MIPSN32EL: #define __INT_FAST32_FMTi__ "i"
// MIPSN32EL: #define __INT_FAST32_MAX__ 2147483647
// MIPSN32EL: #define __INT_FAST32_TYPE__ int
// MIPSN32EL: #define __INT_FAST64_FMTd__ "lld"
// MIPSN32EL: #define __INT_FAST64_FMTi__ "lli"
// MIPSN32EL: #define __INT_FAST64_MAX__ 9223372036854775807LL
// MIPSN32EL: #define __INT_FAST64_TYPE__ long long int
// MIPSN32EL: #define __INT_FAST8_FMTd__ "hhd"
// MIPSN32EL: #define __INT_FAST8_FMTi__ "hhi"
// MIPSN32EL: #define __INT_FAST8_MAX__ 127
// MIPSN32EL: #define __INT_FAST8_TYPE__ signed char
// MIPSN32EL: #define __INT_LEAST16_FMTd__ "hd"
// MIPSN32EL: #define __INT_LEAST16_FMTi__ "hi"
// MIPSN32EL: #define __INT_LEAST16_MAX__ 32767
// MIPSN32EL: #define __INT_LEAST16_TYPE__ short
// MIPSN32EL: #define __INT_LEAST32_FMTd__ "d"
// MIPSN32EL: #define __INT_LEAST32_FMTi__ "i"
// MIPSN32EL: #define __INT_LEAST32_MAX__ 2147483647
// MIPSN32EL: #define __INT_LEAST32_TYPE__ int
// MIPSN32EL: #define __INT_LEAST64_FMTd__ "lld"
// MIPSN32EL: #define __INT_LEAST64_FMTi__ "lli"
// MIPSN32EL: #define __INT_LEAST64_MAX__ 9223372036854775807LL
// MIPSN32EL: #define __INT_LEAST64_TYPE__ long long int
// MIPSN32EL: #define __INT_LEAST8_FMTd__ "hhd"
// MIPSN32EL: #define __INT_LEAST8_FMTi__ "hhi"
// MIPSN32EL: #define __INT_LEAST8_MAX__ 127
// MIPSN32EL: #define __INT_LEAST8_TYPE__ signed char
// MIPSN32EL: #define __INT_MAX__ 2147483647
// MIPSN32EL: #define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
// MIPSN32EL: #define __LDBL_DIG__ 33
// MIPSN32EL: #define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// MIPSN32EL: #define __LDBL_HAS_DENORM__ 1
// MIPSN32EL: #define __LDBL_HAS_INFINITY__ 1
// MIPSN32EL: #define __LDBL_HAS_QUIET_NAN__ 1
// MIPSN32EL: #define __LDBL_MANT_DIG__ 113
// MIPSN32EL: #define __LDBL_MAX_10_EXP__ 4932
// MIPSN32EL: #define __LDBL_MAX_EXP__ 16384
// MIPSN32EL: #define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
// MIPSN32EL: #define __LDBL_MIN_10_EXP__ (-4931)
// MIPSN32EL: #define __LDBL_MIN_EXP__ (-16381)
// MIPSN32EL: #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// MIPSN32EL: #define __LITTLE_ENDIAN__ 1
// MIPSN32EL: #define __LONG_LONG_MAX__ 9223372036854775807LL
// MIPSN32EL: #define __LONG_MAX__ 2147483647L
// MIPSN32EL: #define __MIPSEL 1
// MIPSN32EL: #define __MIPSEL__ 1
// MIPSN32EL: #define __NO_INLINE__ 1
// MIPSN32EL: #define __ORDER_BIG_ENDIAN__ 4321
// MIPSN32EL: #define __ORDER_LITTLE_ENDIAN__ 1234
// MIPSN32EL: #define __ORDER_PDP_ENDIAN__ 3412
// MIPSN32EL: #define __POINTER_WIDTH__ 32
// MIPSN32EL: #define __PRAGMA_REDEFINE_EXTNAME 1
// MIPSN32EL: #define __PTRDIFF_FMTd__ "d"
// MIPSN32EL: #define __PTRDIFF_FMTi__ "i"
// MIPSN32EL: #define __PTRDIFF_MAX__ 2147483647
// MIPSN32EL: #define __PTRDIFF_TYPE__ int
// MIPSN32EL: #define __PTRDIFF_WIDTH__ 32
// MIPSN32EL: #define __REGISTER_PREFIX__
// MIPSN32EL: #define __SCHAR_MAX__ 127
// MIPSN32EL: #define __SHRT_MAX__ 32767
// MIPSN32EL: #define __SIG_ATOMIC_MAX__ 2147483647
// MIPSN32EL: #define __SIG_ATOMIC_WIDTH__ 32
// MIPSN32EL: #define __SIZEOF_DOUBLE__ 8
// MIPSN32EL: #define __SIZEOF_FLOAT__ 4
// MIPSN32EL: #define __SIZEOF_INT__ 4
// MIPSN32EL: #define __SIZEOF_LONG_DOUBLE__ 16
// MIPSN32EL: #define __SIZEOF_LONG_LONG__ 8
// MIPSN32EL: #define __SIZEOF_LONG__ 4
// MIPSN32EL: #define __SIZEOF_POINTER__ 4
// MIPSN32EL: #define __SIZEOF_PTRDIFF_T__ 4
// MIPSN32EL: #define __SIZEOF_SHORT__ 2
// MIPSN32EL: #define __SIZEOF_SIZE_T__ 4
// MIPSN32EL: #define __SIZEOF_WCHAR_T__ 4
// MIPSN32EL: #define __SIZEOF_WINT_T__ 4
// MIPSN32EL: #define __SIZE_FMTX__ "X"
// MIPSN32EL: #define __SIZE_FMTo__ "o"
// MIPSN32EL: #define __SIZE_FMTu__ "u"
// MIPSN32EL: #define __SIZE_FMTx__ "x"
// MIPSN32EL: #define __SIZE_MAX__ 4294967295U
// MIPSN32EL: #define __SIZE_TYPE__ unsigned int
// MIPSN32EL: #define __SIZE_WIDTH__ 32
// MIPSN32EL: #define __STDC_HOSTED__ 0
// MIPSN32EL: #define __STDC_UTF_16__ 1
// MIPSN32EL: #define __STDC_UTF_32__ 1
// MIPSN32EL: #define __STDC_VERSION__ 201112L
// MIPSN32EL: #define __STDC__ 1
// MIPSN32EL: #define __UINT16_C_SUFFIX__
// MIPSN32EL: #define __UINT16_FMTX__ "hX"
// MIPSN32EL: #define __UINT16_FMTo__ "ho"
// MIPSN32EL: #define __UINT16_FMTu__ "hu"
// MIPSN32EL: #define __UINT16_FMTx__ "hx"
// MIPSN32EL: #define __UINT16_MAX__ 65535
// MIPSN32EL: #define __UINT16_TYPE__ unsigned short
// MIPSN32EL: #define __UINT32_C_SUFFIX__ U
// MIPSN32EL: #define __UINT32_FMTX__ "X"
// MIPSN32EL: #define __UINT32_FMTo__ "o"
// MIPSN32EL: #define __UINT32_FMTu__ "u"
// MIPSN32EL: #define __UINT32_FMTx__ "x"
// MIPSN32EL: #define __UINT32_MAX__ 4294967295U
// MIPSN32EL: #define __UINT32_TYPE__ unsigned int
// MIPSN32EL: #define __UINT64_C_SUFFIX__ ULL
// MIPSN32EL: #define __UINT64_FMTX__ "llX"
// MIPSN32EL: #define __UINT64_FMTo__ "llo"
// MIPSN32EL: #define __UINT64_FMTu__ "llu"
// MIPSN32EL: #define __UINT64_FMTx__ "llx"
// MIPSN32EL: #define __UINT64_MAX__ 18446744073709551615ULL
// MIPSN32EL: #define __UINT64_TYPE__ long long unsigned int
// MIPSN32EL: #define __UINT8_C_SUFFIX__
// MIPSN32EL: #define __UINT8_FMTX__ "hhX"
// MIPSN32EL: #define __UINT8_FMTo__ "hho"
// MIPSN32EL: #define __UINT8_FMTu__ "hhu"
// MIPSN32EL: #define __UINT8_FMTx__ "hhx"
// MIPSN32EL: #define __UINT8_MAX__ 255
// MIPSN32EL: #define __UINT8_TYPE__ unsigned char
// MIPSN32EL: #define __UINTMAX_C_SUFFIX__ ULL
// MIPSN32EL: #define __UINTMAX_FMTX__ "llX"
// MIPSN32EL: #define __UINTMAX_FMTo__ "llo"
// MIPSN32EL: #define __UINTMAX_FMTu__ "llu"
// MIPSN32EL: #define __UINTMAX_FMTx__ "llx"
// MIPSN32EL: #define __UINTMAX_MAX__ 18446744073709551615ULL
// MIPSN32EL: #define __UINTMAX_TYPE__ long long unsigned int
// MIPSN32EL: #define __UINTMAX_WIDTH__ 64
// MIPSN32EL: #define __UINTPTR_FMTX__ "lX"
// MIPSN32EL: #define __UINTPTR_FMTo__ "lo"
// MIPSN32EL: #define __UINTPTR_FMTu__ "lu"
// MIPSN32EL: #define __UINTPTR_FMTx__ "lx"
// MIPSN32EL: #define __UINTPTR_MAX__ 4294967295UL
// MIPSN32EL: #define __UINTPTR_TYPE__ long unsigned int
// MIPSN32EL: #define __UINTPTR_WIDTH__ 32
// MIPSN32EL: #define __UINT_FAST16_FMTX__ "hX"
// MIPSN32EL: #define __UINT_FAST16_FMTo__ "ho"
// MIPSN32EL: #define __UINT_FAST16_FMTu__ "hu"
// MIPSN32EL: #define __UINT_FAST16_FMTx__ "hx"
// MIPSN32EL: #define __UINT_FAST16_MAX__ 65535
// MIPSN32EL: #define __UINT_FAST16_TYPE__ unsigned short
// MIPSN32EL: #define __UINT_FAST32_FMTX__ "X"
// MIPSN32EL: #define __UINT_FAST32_FMTo__ "o"
// MIPSN32EL: #define __UINT_FAST32_FMTu__ "u"
// MIPSN32EL: #define __UINT_FAST32_FMTx__ "x"
// MIPSN32EL: #define __UINT_FAST32_MAX__ 4294967295U
// MIPSN32EL: #define __UINT_FAST32_TYPE__ unsigned int
// MIPSN32EL: #define __UINT_FAST64_FMTX__ "llX"
// MIPSN32EL: #define __UINT_FAST64_FMTo__ "llo"
// MIPSN32EL: #define __UINT_FAST64_FMTu__ "llu"
// MIPSN32EL: #define __UINT_FAST64_FMTx__ "llx"
// MIPSN32EL: #define __UINT_FAST64_MAX__ 18446744073709551615ULL
// MIPSN32EL: #define __UINT_FAST64_TYPE__ long long unsigned int
// MIPSN32EL: #define __UINT_FAST8_FMTX__ "hhX"
// MIPSN32EL: #define __UINT_FAST8_FMTo__ "hho"
// MIPSN32EL: #define __UINT_FAST8_FMTu__ "hhu"
// MIPSN32EL: #define __UINT_FAST8_FMTx__ "hhx"
// MIPSN32EL: #define __UINT_FAST8_MAX__ 255
// MIPSN32EL: #define __UINT_FAST8_TYPE__ unsigned char
// MIPSN32EL: #define __UINT_LEAST16_FMTX__ "hX"
// MIPSN32EL: #define __UINT_LEAST16_FMTo__ "ho"
// MIPSN32EL: #define __UINT_LEAST16_FMTu__ "hu"
// MIPSN32EL: #define __UINT_LEAST16_FMTx__ "hx"
// MIPSN32EL: #define __UINT_LEAST16_MAX__ 65535
// MIPSN32EL: #define __UINT_LEAST16_TYPE__ unsigned short
// MIPSN32EL: #define __UINT_LEAST32_FMTX__ "X"
// MIPSN32EL: #define __UINT_LEAST32_FMTo__ "o"
// MIPSN32EL: #define __UINT_LEAST32_FMTu__ "u"
// MIPSN32EL: #define __UINT_LEAST32_FMTx__ "x"
// MIPSN32EL: #define __UINT_LEAST32_MAX__ 4294967295U
// MIPSN32EL: #define __UINT_LEAST32_TYPE__ unsigned int
// MIPSN32EL: #define __UINT_LEAST64_FMTX__ "llX"
// MIPSN32EL: #define __UINT_LEAST64_FMTo__ "llo"
// MIPSN32EL: #define __UINT_LEAST64_FMTu__ "llu"
// MIPSN32EL: #define __UINT_LEAST64_FMTx__ "llx"
// MIPSN32EL: #define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// MIPSN32EL: #define __UINT_LEAST64_TYPE__ long long unsigned int
// MIPSN32EL: #define __UINT_LEAST8_FMTX__ "hhX"
// MIPSN32EL: #define __UINT_LEAST8_FMTo__ "hho"
// MIPSN32EL: #define __UINT_LEAST8_FMTu__ "hhu"
// MIPSN32EL: #define __UINT_LEAST8_FMTx__ "hhx"
// MIPSN32EL: #define __UINT_LEAST8_MAX__ 255
// MIPSN32EL: #define __UINT_LEAST8_TYPE__ unsigned char
// MIPSN32EL: #define __USER_LABEL_PREFIX__
// MIPSN32EL: #define __WCHAR_MAX__ 2147483647
// MIPSN32EL: #define __WCHAR_TYPE__ int
// MIPSN32EL: #define __WCHAR_WIDTH__ 32
// MIPSN32EL: #define __WINT_TYPE__ int
// MIPSN32EL: #define __WINT_WIDTH__ 32
// MIPSN32EL: #define __clang__ 1
// MIPSN32EL: #define __llvm__ 1
// MIPSN32EL: #define __mips 64
// MIPSN32EL: #define __mips64 1
// MIPSN32EL: #define __mips64__ 1
// MIPSN32EL: #define __mips__ 1
// MIPSN32EL: #define __mips_abicalls 1
// MIPSN32EL: #define __mips_fpr 64
// MIPSN32EL: #define __mips_hard_float 1
// MIPSN32EL: #define __mips_isa_rev 2
// MIPSN32EL: #define __mips_n32 1
// MIPSN32EL: #define _mips 1
// MIPSN32EL: #define mips 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MIPS64BE %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=mips64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MIPS64BE -check-prefix MIPS64BE-CXX %s
//
// MIPS64BE:#define MIPSEB 1
// MIPS64BE:#define _ABI64 3
// MIPS64BE:#define _LP64 1
// MIPS64BE:#define _MIPSEB 1
// MIPS64BE:#define _MIPS_ARCH "mips64r2"
// MIPS64BE:#define _MIPS_ARCH_MIPS64R2 1
// MIPS64BE:#define _MIPS_FPSET 32
// MIPS64BE:#define _MIPS_SIM _ABI64
// MIPS64BE:#define _MIPS_SZINT 32
// MIPS64BE:#define _MIPS_SZLONG 64
// MIPS64BE:#define _MIPS_SZPTR 64
// MIPS64BE:#define __BIGGEST_ALIGNMENT__ 16
// MIPS64BE:#define __BIG_ENDIAN__ 1
// MIPS64BE:#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
// MIPS64BE:#define __CHAR16_TYPE__ unsigned short
// MIPS64BE:#define __CHAR32_TYPE__ unsigned int
// MIPS64BE:#define __CHAR_BIT__ 8
// MIPS64BE:#define __CONSTANT_CFSTRINGS__ 1
// MIPS64BE:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// MIPS64BE:#define __DBL_DIG__ 15
// MIPS64BE:#define __DBL_EPSILON__ 2.2204460492503131e-16
// MIPS64BE:#define __DBL_HAS_DENORM__ 1
// MIPS64BE:#define __DBL_HAS_INFINITY__ 1
// MIPS64BE:#define __DBL_HAS_QUIET_NAN__ 1
// MIPS64BE:#define __DBL_MANT_DIG__ 53
// MIPS64BE:#define __DBL_MAX_10_EXP__ 308
// MIPS64BE:#define __DBL_MAX_EXP__ 1024
// MIPS64BE:#define __DBL_MAX__ 1.7976931348623157e+308
// MIPS64BE:#define __DBL_MIN_10_EXP__ (-307)
// MIPS64BE:#define __DBL_MIN_EXP__ (-1021)
// MIPS64BE:#define __DBL_MIN__ 2.2250738585072014e-308
// MIPS64BE:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// MIPS64BE:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// MIPS64BE:#define __FLT_DIG__ 6
// MIPS64BE:#define __FLT_EPSILON__ 1.19209290e-7F
// MIPS64BE:#define __FLT_EVAL_METHOD__ 0
// MIPS64BE:#define __FLT_HAS_DENORM__ 1
// MIPS64BE:#define __FLT_HAS_INFINITY__ 1
// MIPS64BE:#define __FLT_HAS_QUIET_NAN__ 1
// MIPS64BE:#define __FLT_MANT_DIG__ 24
// MIPS64BE:#define __FLT_MAX_10_EXP__ 38
// MIPS64BE:#define __FLT_MAX_EXP__ 128
// MIPS64BE:#define __FLT_MAX__ 3.40282347e+38F
// MIPS64BE:#define __FLT_MIN_10_EXP__ (-37)
// MIPS64BE:#define __FLT_MIN_EXP__ (-125)
// MIPS64BE:#define __FLT_MIN__ 1.17549435e-38F
// MIPS64BE:#define __FLT_RADIX__ 2
// MIPS64BE:#define __INT16_C_SUFFIX__
// MIPS64BE:#define __INT16_FMTd__ "hd"
// MIPS64BE:#define __INT16_FMTi__ "hi"
// MIPS64BE:#define __INT16_MAX__ 32767
// MIPS64BE:#define __INT16_TYPE__ short
// MIPS64BE:#define __INT32_C_SUFFIX__
// MIPS64BE:#define __INT32_FMTd__ "d"
// MIPS64BE:#define __INT32_FMTi__ "i"
// MIPS64BE:#define __INT32_MAX__ 2147483647
// MIPS64BE:#define __INT32_TYPE__ int
// MIPS64BE:#define __INT64_C_SUFFIX__ L
// MIPS64BE:#define __INT64_FMTd__ "ld"
// MIPS64BE:#define __INT64_FMTi__ "li"
// MIPS64BE:#define __INT64_MAX__ 9223372036854775807L
// MIPS64BE:#define __INT64_TYPE__ long int
// MIPS64BE:#define __INT8_C_SUFFIX__
// MIPS64BE:#define __INT8_FMTd__ "hhd"
// MIPS64BE:#define __INT8_FMTi__ "hhi"
// MIPS64BE:#define __INT8_MAX__ 127
// MIPS64BE:#define __INT8_TYPE__ signed char
// MIPS64BE:#define __INTMAX_C_SUFFIX__ L
// MIPS64BE:#define __INTMAX_FMTd__ "ld"
// MIPS64BE:#define __INTMAX_FMTi__ "li"
// MIPS64BE:#define __INTMAX_MAX__ 9223372036854775807L
// MIPS64BE:#define __INTMAX_TYPE__ long int
// MIPS64BE:#define __INTMAX_WIDTH__ 64
// MIPS64BE:#define __INTPTR_FMTd__ "ld"
// MIPS64BE:#define __INTPTR_FMTi__ "li"
// MIPS64BE:#define __INTPTR_MAX__ 9223372036854775807L
// MIPS64BE:#define __INTPTR_TYPE__ long int
// MIPS64BE:#define __INTPTR_WIDTH__ 64
// MIPS64BE:#define __INT_FAST16_FMTd__ "hd"
// MIPS64BE:#define __INT_FAST16_FMTi__ "hi"
// MIPS64BE:#define __INT_FAST16_MAX__ 32767
// MIPS64BE:#define __INT_FAST16_TYPE__ short
// MIPS64BE:#define __INT_FAST32_FMTd__ "d"
// MIPS64BE:#define __INT_FAST32_FMTi__ "i"
// MIPS64BE:#define __INT_FAST32_MAX__ 2147483647
// MIPS64BE:#define __INT_FAST32_TYPE__ int
// MIPS64BE:#define __INT_FAST64_FMTd__ "ld"
// MIPS64BE:#define __INT_FAST64_FMTi__ "li"
// MIPS64BE:#define __INT_FAST64_MAX__ 9223372036854775807L
// MIPS64BE:#define __INT_FAST64_TYPE__ long int
// MIPS64BE:#define __INT_FAST8_FMTd__ "hhd"
// MIPS64BE:#define __INT_FAST8_FMTi__ "hhi"
// MIPS64BE:#define __INT_FAST8_MAX__ 127
// MIPS64BE:#define __INT_FAST8_TYPE__ signed char
// MIPS64BE:#define __INT_LEAST16_FMTd__ "hd"
// MIPS64BE:#define __INT_LEAST16_FMTi__ "hi"
// MIPS64BE:#define __INT_LEAST16_MAX__ 32767
// MIPS64BE:#define __INT_LEAST16_TYPE__ short
// MIPS64BE:#define __INT_LEAST32_FMTd__ "d"
// MIPS64BE:#define __INT_LEAST32_FMTi__ "i"
// MIPS64BE:#define __INT_LEAST32_MAX__ 2147483647
// MIPS64BE:#define __INT_LEAST32_TYPE__ int
// MIPS64BE:#define __INT_LEAST64_FMTd__ "ld"
// MIPS64BE:#define __INT_LEAST64_FMTi__ "li"
// MIPS64BE:#define __INT_LEAST64_MAX__ 9223372036854775807L
// MIPS64BE:#define __INT_LEAST64_TYPE__ long int
// MIPS64BE:#define __INT_LEAST8_FMTd__ "hhd"
// MIPS64BE:#define __INT_LEAST8_FMTi__ "hhi"
// MIPS64BE:#define __INT_LEAST8_MAX__ 127
// MIPS64BE:#define __INT_LEAST8_TYPE__ signed char
// MIPS64BE:#define __INT_MAX__ 2147483647
// MIPS64BE:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
// MIPS64BE:#define __LDBL_DIG__ 33
// MIPS64BE:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// MIPS64BE:#define __LDBL_HAS_DENORM__ 1
// MIPS64BE:#define __LDBL_HAS_INFINITY__ 1
// MIPS64BE:#define __LDBL_HAS_QUIET_NAN__ 1
// MIPS64BE:#define __LDBL_MANT_DIG__ 113
// MIPS64BE:#define __LDBL_MAX_10_EXP__ 4932
// MIPS64BE:#define __LDBL_MAX_EXP__ 16384
// MIPS64BE:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
// MIPS64BE:#define __LDBL_MIN_10_EXP__ (-4931)
// MIPS64BE:#define __LDBL_MIN_EXP__ (-16381)
// MIPS64BE:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// MIPS64BE:#define __LONG_LONG_MAX__ 9223372036854775807LL
// MIPS64BE:#define __LONG_MAX__ 9223372036854775807L
// MIPS64BE:#define __LP64__ 1
// MIPS64BE:#define __MIPSEB 1
// MIPS64BE:#define __MIPSEB__ 1
// MIPS64BE:#define __POINTER_WIDTH__ 64
// MIPS64BE:#define __PRAGMA_REDEFINE_EXTNAME 1
// MIPS64BE:#define __PTRDIFF_TYPE__ long int
// MIPS64BE:#define __PTRDIFF_WIDTH__ 64
// MIPS64BE:#define __REGISTER_PREFIX__
// MIPS64BE:#define __SCHAR_MAX__ 127
// MIPS64BE:#define __SHRT_MAX__ 32767
// MIPS64BE:#define __SIG_ATOMIC_MAX__ 2147483647
// MIPS64BE:#define __SIG_ATOMIC_WIDTH__ 32
// MIPS64BE:#define __SIZEOF_DOUBLE__ 8
// MIPS64BE:#define __SIZEOF_FLOAT__ 4
// MIPS64BE:#define __SIZEOF_INT128__ 16
// MIPS64BE:#define __SIZEOF_INT__ 4
// MIPS64BE:#define __SIZEOF_LONG_DOUBLE__ 16
// MIPS64BE:#define __SIZEOF_LONG_LONG__ 8
// MIPS64BE:#define __SIZEOF_LONG__ 8
// MIPS64BE:#define __SIZEOF_POINTER__ 8
// MIPS64BE:#define __SIZEOF_PTRDIFF_T__ 8
// MIPS64BE:#define __SIZEOF_SHORT__ 2
// MIPS64BE:#define __SIZEOF_SIZE_T__ 8
// MIPS64BE:#define __SIZEOF_WCHAR_T__ 4
// MIPS64BE:#define __SIZEOF_WINT_T__ 4
// MIPS64BE:#define __SIZE_MAX__ 18446744073709551615UL
// MIPS64BE:#define __SIZE_TYPE__ long unsigned int
// MIPS64BE:#define __SIZE_WIDTH__ 64
// MIPS64BE-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL
// MIPS64BE:#define __UINT16_C_SUFFIX__
// MIPS64BE:#define __UINT16_MAX__ 65535
// MIPS64BE:#define __UINT16_TYPE__ unsigned short
// MIPS64BE:#define __UINT32_C_SUFFIX__ U
// MIPS64BE:#define __UINT32_MAX__ 4294967295U
// MIPS64BE:#define __UINT32_TYPE__ unsigned int
// MIPS64BE:#define __UINT64_C_SUFFIX__ UL
// MIPS64BE:#define __UINT64_MAX__ 18446744073709551615UL
// MIPS64BE:#define __UINT64_TYPE__ long unsigned int
// MIPS64BE:#define __UINT8_C_SUFFIX__
// MIPS64BE:#define __UINT8_MAX__ 255
// MIPS64BE:#define __UINT8_TYPE__ unsigned char
// MIPS64BE:#define __UINTMAX_C_SUFFIX__ UL
// MIPS64BE:#define __UINTMAX_MAX__ 18446744073709551615UL
// MIPS64BE:#define __UINTMAX_TYPE__ long unsigned int
// MIPS64BE:#define __UINTMAX_WIDTH__ 64
// MIPS64BE:#define __UINTPTR_MAX__ 18446744073709551615UL
// MIPS64BE:#define __UINTPTR_TYPE__ long unsigned int
// MIPS64BE:#define __UINTPTR_WIDTH__ 64
// MIPS64BE:#define __UINT_FAST16_MAX__ 65535
// MIPS64BE:#define __UINT_FAST16_TYPE__ unsigned short
// MIPS64BE:#define __UINT_FAST32_MAX__ 4294967295U
// MIPS64BE:#define __UINT_FAST32_TYPE__ unsigned int
// MIPS64BE:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// MIPS64BE:#define __UINT_FAST64_TYPE__ long unsigned int
// MIPS64BE:#define __UINT_FAST8_MAX__ 255
// MIPS64BE:#define __UINT_FAST8_TYPE__ unsigned char
// MIPS64BE:#define __UINT_LEAST16_MAX__ 65535
// MIPS64BE:#define __UINT_LEAST16_TYPE__ unsigned short
// MIPS64BE:#define __UINT_LEAST32_MAX__ 4294967295U
// MIPS64BE:#define __UINT_LEAST32_TYPE__ unsigned int
// MIPS64BE:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// MIPS64BE:#define __UINT_LEAST64_TYPE__ long unsigned int
// MIPS64BE:#define __UINT_LEAST8_MAX__ 255
// MIPS64BE:#define __UINT_LEAST8_TYPE__ unsigned char
// MIPS64BE:#define __USER_LABEL_PREFIX__
// MIPS64BE:#define __WCHAR_MAX__ 2147483647
// MIPS64BE:#define __WCHAR_TYPE__ int
// MIPS64BE:#define __WCHAR_WIDTH__ 32
// MIPS64BE:#define __WINT_TYPE__ int
// MIPS64BE:#define __WINT_WIDTH__ 32
// MIPS64BE:#define __clang__ 1
// MIPS64BE:#define __llvm__ 1
// MIPS64BE:#define __mips 64
// MIPS64BE:#define __mips64 1
// MIPS64BE:#define __mips64__ 1
// MIPS64BE:#define __mips__ 1
// MIPS64BE:#define __mips_abicalls 1
// MIPS64BE:#define __mips_fpr 64
// MIPS64BE:#define __mips_hard_float 1
// MIPS64BE:#define __mips_n64 1
// MIPS64BE:#define _mips 1
// MIPS64BE:#define mips 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips64el-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MIPS64EL %s
//
// MIPS64EL:#define MIPSEL 1
// MIPS64EL:#define _ABI64 3
// MIPS64EL:#define _LP64 1
// MIPS64EL:#define _MIPSEL 1
// MIPS64EL:#define _MIPS_ARCH "mips64r2"
// MIPS64EL:#define _MIPS_ARCH_MIPS64R2 1
// MIPS64EL:#define _MIPS_FPSET 32
// MIPS64EL:#define _MIPS_SIM _ABI64
// MIPS64EL:#define _MIPS_SZINT 32
// MIPS64EL:#define _MIPS_SZLONG 64
// MIPS64EL:#define _MIPS_SZPTR 64
// MIPS64EL:#define __BIGGEST_ALIGNMENT__ 16
// MIPS64EL:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// MIPS64EL:#define __CHAR16_TYPE__ unsigned short
// MIPS64EL:#define __CHAR32_TYPE__ unsigned int
// MIPS64EL:#define __CHAR_BIT__ 8
// MIPS64EL:#define __CONSTANT_CFSTRINGS__ 1
// MIPS64EL:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// MIPS64EL:#define __DBL_DIG__ 15
// MIPS64EL:#define __DBL_EPSILON__ 2.2204460492503131e-16
// MIPS64EL:#define __DBL_HAS_DENORM__ 1
// MIPS64EL:#define __DBL_HAS_INFINITY__ 1
// MIPS64EL:#define __DBL_HAS_QUIET_NAN__ 1
// MIPS64EL:#define __DBL_MANT_DIG__ 53
// MIPS64EL:#define __DBL_MAX_10_EXP__ 308
// MIPS64EL:#define __DBL_MAX_EXP__ 1024
// MIPS64EL:#define __DBL_MAX__ 1.7976931348623157e+308
// MIPS64EL:#define __DBL_MIN_10_EXP__ (-307)
// MIPS64EL:#define __DBL_MIN_EXP__ (-1021)
// MIPS64EL:#define __DBL_MIN__ 2.2250738585072014e-308
// MIPS64EL:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// MIPS64EL:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// MIPS64EL:#define __FLT_DIG__ 6
// MIPS64EL:#define __FLT_EPSILON__ 1.19209290e-7F
// MIPS64EL:#define __FLT_EVAL_METHOD__ 0
// MIPS64EL:#define __FLT_HAS_DENORM__ 1
// MIPS64EL:#define __FLT_HAS_INFINITY__ 1
// MIPS64EL:#define __FLT_HAS_QUIET_NAN__ 1
// MIPS64EL:#define __FLT_MANT_DIG__ 24
// MIPS64EL:#define __FLT_MAX_10_EXP__ 38
// MIPS64EL:#define __FLT_MAX_EXP__ 128
// MIPS64EL:#define __FLT_MAX__ 3.40282347e+38F
// MIPS64EL:#define __FLT_MIN_10_EXP__ (-37)
// MIPS64EL:#define __FLT_MIN_EXP__ (-125)
// MIPS64EL:#define __FLT_MIN__ 1.17549435e-38F
// MIPS64EL:#define __FLT_RADIX__ 2
// MIPS64EL:#define __INT16_C_SUFFIX__
// MIPS64EL:#define __INT16_FMTd__ "hd"
// MIPS64EL:#define __INT16_FMTi__ "hi"
// MIPS64EL:#define __INT16_MAX__ 32767
// MIPS64EL:#define __INT16_TYPE__ short
// MIPS64EL:#define __INT32_C_SUFFIX__
// MIPS64EL:#define __INT32_FMTd__ "d"
// MIPS64EL:#define __INT32_FMTi__ "i"
// MIPS64EL:#define __INT32_MAX__ 2147483647
// MIPS64EL:#define __INT32_TYPE__ int
// MIPS64EL:#define __INT64_C_SUFFIX__ L
// MIPS64EL:#define __INT64_FMTd__ "ld"
// MIPS64EL:#define __INT64_FMTi__ "li"
// MIPS64EL:#define __INT64_MAX__ 9223372036854775807L
// MIPS64EL:#define __INT64_TYPE__ long int
// MIPS64EL:#define __INT8_C_SUFFIX__
// MIPS64EL:#define __INT8_FMTd__ "hhd"
// MIPS64EL:#define __INT8_FMTi__ "hhi"
// MIPS64EL:#define __INT8_MAX__ 127
// MIPS64EL:#define __INT8_TYPE__ signed char
// MIPS64EL:#define __INTMAX_C_SUFFIX__ L
// MIPS64EL:#define __INTMAX_FMTd__ "ld"
// MIPS64EL:#define __INTMAX_FMTi__ "li"
// MIPS64EL:#define __INTMAX_MAX__ 9223372036854775807L
// MIPS64EL:#define __INTMAX_TYPE__ long int
// MIPS64EL:#define __INTMAX_WIDTH__ 64
// MIPS64EL:#define __INTPTR_FMTd__ "ld"
// MIPS64EL:#define __INTPTR_FMTi__ "li"
// MIPS64EL:#define __INTPTR_MAX__ 9223372036854775807L
// MIPS64EL:#define __INTPTR_TYPE__ long int
// MIPS64EL:#define __INTPTR_WIDTH__ 64
// MIPS64EL:#define __INT_FAST16_FMTd__ "hd"
// MIPS64EL:#define __INT_FAST16_FMTi__ "hi"
// MIPS64EL:#define __INT_FAST16_MAX__ 32767
// MIPS64EL:#define __INT_FAST16_TYPE__ short
// MIPS64EL:#define __INT_FAST32_FMTd__ "d"
// MIPS64EL:#define __INT_FAST32_FMTi__ "i"
// MIPS64EL:#define __INT_FAST32_MAX__ 2147483647
// MIPS64EL:#define __INT_FAST32_TYPE__ int
// MIPS64EL:#define __INT_FAST64_FMTd__ "ld"
// MIPS64EL:#define __INT_FAST64_FMTi__ "li"
// MIPS64EL:#define __INT_FAST64_MAX__ 9223372036854775807L
// MIPS64EL:#define __INT_FAST64_TYPE__ long int
// MIPS64EL:#define __INT_FAST8_FMTd__ "hhd"
// MIPS64EL:#define __INT_FAST8_FMTi__ "hhi"
// MIPS64EL:#define __INT_FAST8_MAX__ 127
// MIPS64EL:#define __INT_FAST8_TYPE__ signed char
// MIPS64EL:#define __INT_LEAST16_FMTd__ "hd"
// MIPS64EL:#define __INT_LEAST16_FMTi__ "hi"
// MIPS64EL:#define __INT_LEAST16_MAX__ 32767
// MIPS64EL:#define __INT_LEAST16_TYPE__ short
// MIPS64EL:#define __INT_LEAST32_FMTd__ "d"
// MIPS64EL:#define __INT_LEAST32_FMTi__ "i"
// MIPS64EL:#define __INT_LEAST32_MAX__ 2147483647
// MIPS64EL:#define __INT_LEAST32_TYPE__ int
// MIPS64EL:#define __INT_LEAST64_FMTd__ "ld"
// MIPS64EL:#define __INT_LEAST64_FMTi__ "li"
// MIPS64EL:#define __INT_LEAST64_MAX__ 9223372036854775807L
// MIPS64EL:#define __INT_LEAST64_TYPE__ long int
// MIPS64EL:#define __INT_LEAST8_FMTd__ "hhd"
// MIPS64EL:#define __INT_LEAST8_FMTi__ "hhi"
// MIPS64EL:#define __INT_LEAST8_MAX__ 127
// MIPS64EL:#define __INT_LEAST8_TYPE__ signed char
// MIPS64EL:#define __INT_MAX__ 2147483647
// MIPS64EL:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
// MIPS64EL:#define __LDBL_DIG__ 33
// MIPS64EL:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// MIPS64EL:#define __LDBL_HAS_DENORM__ 1
// MIPS64EL:#define __LDBL_HAS_INFINITY__ 1
// MIPS64EL:#define __LDBL_HAS_QUIET_NAN__ 1
// MIPS64EL:#define __LDBL_MANT_DIG__ 113
// MIPS64EL:#define __LDBL_MAX_10_EXP__ 4932
// MIPS64EL:#define __LDBL_MAX_EXP__ 16384
// MIPS64EL:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
// MIPS64EL:#define __LDBL_MIN_10_EXP__ (-4931)
// MIPS64EL:#define __LDBL_MIN_EXP__ (-16381)
// MIPS64EL:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// MIPS64EL:#define __LITTLE_ENDIAN__ 1
// MIPS64EL:#define __LONG_LONG_MAX__ 9223372036854775807LL
// MIPS64EL:#define __LONG_MAX__ 9223372036854775807L
// MIPS64EL:#define __LP64__ 1
// MIPS64EL:#define __MIPSEL 1
// MIPS64EL:#define __MIPSEL__ 1
// MIPS64EL:#define __POINTER_WIDTH__ 64
// MIPS64EL:#define __PRAGMA_REDEFINE_EXTNAME 1
// MIPS64EL:#define __PTRDIFF_TYPE__ long int
// MIPS64EL:#define __PTRDIFF_WIDTH__ 64
// MIPS64EL:#define __REGISTER_PREFIX__
// MIPS64EL:#define __SCHAR_MAX__ 127
// MIPS64EL:#define __SHRT_MAX__ 32767
// MIPS64EL:#define __SIG_ATOMIC_MAX__ 2147483647
// MIPS64EL:#define __SIG_ATOMIC_WIDTH__ 32
// MIPS64EL:#define __SIZEOF_DOUBLE__ 8
// MIPS64EL:#define __SIZEOF_FLOAT__ 4
// MIPS64EL:#define __SIZEOF_INT128__ 16
// MIPS64EL:#define __SIZEOF_INT__ 4
// MIPS64EL:#define __SIZEOF_LONG_DOUBLE__ 16
// MIPS64EL:#define __SIZEOF_LONG_LONG__ 8
// MIPS64EL:#define __SIZEOF_LONG__ 8
// MIPS64EL:#define __SIZEOF_POINTER__ 8
// MIPS64EL:#define __SIZEOF_PTRDIFF_T__ 8
// MIPS64EL:#define __SIZEOF_SHORT__ 2
// MIPS64EL:#define __SIZEOF_SIZE_T__ 8
// MIPS64EL:#define __SIZEOF_WCHAR_T__ 4
// MIPS64EL:#define __SIZEOF_WINT_T__ 4
// MIPS64EL:#define __SIZE_MAX__ 18446744073709551615UL
// MIPS64EL:#define __SIZE_TYPE__ long unsigned int
// MIPS64EL:#define __SIZE_WIDTH__ 64
// MIPS64EL:#define __UINT16_C_SUFFIX__
// MIPS64EL:#define __UINT16_MAX__ 65535
// MIPS64EL:#define __UINT16_TYPE__ unsigned short
// MIPS64EL:#define __UINT32_C_SUFFIX__ U
// MIPS64EL:#define __UINT32_MAX__ 4294967295U
// MIPS64EL:#define __UINT32_TYPE__ unsigned int
// MIPS64EL:#define __UINT64_C_SUFFIX__ UL
// MIPS64EL:#define __UINT64_MAX__ 18446744073709551615UL
// MIPS64EL:#define __UINT64_TYPE__ long unsigned int
// MIPS64EL:#define __UINT8_C_SUFFIX__
// MIPS64EL:#define __UINT8_MAX__ 255
// MIPS64EL:#define __UINT8_TYPE__ unsigned char
// MIPS64EL:#define __UINTMAX_C_SUFFIX__ UL
// MIPS64EL:#define __UINTMAX_MAX__ 18446744073709551615UL
// MIPS64EL:#define __UINTMAX_TYPE__ long unsigned int
// MIPS64EL:#define __UINTMAX_WIDTH__ 64
// MIPS64EL:#define __UINTPTR_MAX__ 18446744073709551615UL
// MIPS64EL:#define __UINTPTR_TYPE__ long unsigned int
// MIPS64EL:#define __UINTPTR_WIDTH__ 64
// MIPS64EL:#define __UINT_FAST16_MAX__ 65535
// MIPS64EL:#define __UINT_FAST16_TYPE__ unsigned short
// MIPS64EL:#define __UINT_FAST32_MAX__ 4294967295U
// MIPS64EL:#define __UINT_FAST32_TYPE__ unsigned int
// MIPS64EL:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// MIPS64EL:#define __UINT_FAST64_TYPE__ long unsigned int
// MIPS64EL:#define __UINT_FAST8_MAX__ 255
// MIPS64EL:#define __UINT_FAST8_TYPE__ unsigned char
// MIPS64EL:#define __UINT_LEAST16_MAX__ 65535
// MIPS64EL:#define __UINT_LEAST16_TYPE__ unsigned short
// MIPS64EL:#define __UINT_LEAST32_MAX__ 4294967295U
// MIPS64EL:#define __UINT_LEAST32_TYPE__ unsigned int
// MIPS64EL:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// MIPS64EL:#define __UINT_LEAST64_TYPE__ long unsigned int
// MIPS64EL:#define __UINT_LEAST8_MAX__ 255
// MIPS64EL:#define __UINT_LEAST8_TYPE__ unsigned char
// MIPS64EL:#define __USER_LABEL_PREFIX__
// MIPS64EL:#define __WCHAR_MAX__ 2147483647
// MIPS64EL:#define __WCHAR_TYPE__ int
// MIPS64EL:#define __WCHAR_WIDTH__ 32
// MIPS64EL:#define __WINT_TYPE__ int
// MIPS64EL:#define __WINT_WIDTH__ 32
// MIPS64EL:#define __clang__ 1
// MIPS64EL:#define __llvm__ 1
// MIPS64EL:#define __mips 64
// MIPS64EL:#define __mips64 1
// MIPS64EL:#define __mips64__ 1
// MIPS64EL:#define __mips__ 1
// MIPS64EL:#define __mips_abicalls 1
// MIPS64EL:#define __mips_fpr 64
// MIPS64EL:#define __mips_hard_float 1
// MIPS64EL:#define __mips_n64 1
// MIPS64EL:#define _mips 1
// MIPS64EL:#define mips 1
//
// Check MIPS arch and isa macros
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips-none-none \
// RUN: < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ARCH-DEF32 %s
//
// MIPS-ARCH-DEF32:#define _MIPS_ARCH "mips32r2"
// MIPS-ARCH-DEF32:#define _MIPS_ARCH_MIPS32R2 1
// MIPS-ARCH-DEF32:#define _MIPS_ISA _MIPS_ISA_MIPS32
// MIPS-ARCH-DEF32:#define __mips_isa_rev 2
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips-none-nones \
// RUN: -target-cpu mips32 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ARCH-32 %s
//
// MIPS-ARCH-32:#define _MIPS_ARCH "mips32"
// MIPS-ARCH-32:#define _MIPS_ARCH_MIPS32 1
// MIPS-ARCH-32:#define _MIPS_ISA _MIPS_ISA_MIPS32
// MIPS-ARCH-32:#define __mips_isa_rev 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips-none-none \
// RUN: -target-cpu mips32r2 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ARCH-32R2 %s
//
// MIPS-ARCH-32R2:#define _MIPS_ARCH "mips32r2"
// MIPS-ARCH-32R2:#define _MIPS_ARCH_MIPS32R2 1
// MIPS-ARCH-32R2:#define _MIPS_ISA _MIPS_ISA_MIPS32
// MIPS-ARCH-32R2:#define __mips_isa_rev 2
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips-none-none \
// RUN: -target-cpu mips32r3 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ARCH-32R3 %s
//
// MIPS-ARCH-32R3:#define _MIPS_ARCH "mips32r3"
// MIPS-ARCH-32R3:#define _MIPS_ARCH_MIPS32R3 1
// MIPS-ARCH-32R3:#define _MIPS_ISA _MIPS_ISA_MIPS32
// MIPS-ARCH-32R3:#define __mips_isa_rev 3
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips-none-none \
// RUN: -target-cpu mips32r5 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ARCH-32R5 %s
//
// MIPS-ARCH-32R5:#define _MIPS_ARCH "mips32r5"
// MIPS-ARCH-32R5:#define _MIPS_ARCH_MIPS32R5 1
// MIPS-ARCH-32R5:#define _MIPS_ISA _MIPS_ISA_MIPS32
// MIPS-ARCH-32R5:#define __mips_isa_rev 5
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips-none-none \
// RUN: -target-cpu mips32r6 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ARCH-32R6 %s
//
// MIPS-ARCH-32R6:#define _MIPS_ARCH "mips32r6"
// MIPS-ARCH-32R6:#define _MIPS_ARCH_MIPS32R6 1
// MIPS-ARCH-32R6:#define _MIPS_ISA _MIPS_ISA_MIPS32
// MIPS-ARCH-32R6:#define __mips_isa_rev 6
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips64-none-none \
// RUN: < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ARCH-DEF64 %s
//
// MIPS-ARCH-DEF64:#define _MIPS_ARCH "mips64r2"
// MIPS-ARCH-DEF64:#define _MIPS_ARCH_MIPS64R2 1
// MIPS-ARCH-DEF64:#define _MIPS_ISA _MIPS_ISA_MIPS64
// MIPS-ARCH-DEF64:#define __mips_isa_rev 2
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips64-none-none \
// RUN: -target-cpu mips64 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ARCH-64 %s
//
// MIPS-ARCH-64:#define _MIPS_ARCH "mips64"
// MIPS-ARCH-64:#define _MIPS_ARCH_MIPS64 1
// MIPS-ARCH-64:#define _MIPS_ISA _MIPS_ISA_MIPS64
// MIPS-ARCH-64:#define __mips_isa_rev 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips64-none-none \
// RUN: -target-cpu mips64r2 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ARCH-64R2 %s
//
// MIPS-ARCH-64R2:#define _MIPS_ARCH "mips64r2"
// MIPS-ARCH-64R2:#define _MIPS_ARCH_MIPS64R2 1
// MIPS-ARCH-64R2:#define _MIPS_ISA _MIPS_ISA_MIPS64
// MIPS-ARCH-64R2:#define __mips_isa_rev 2
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips64-none-none \
// RUN: -target-cpu mips64r3 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ARCH-64R3 %s
//
// MIPS-ARCH-64R3:#define _MIPS_ARCH "mips64r3"
// MIPS-ARCH-64R3:#define _MIPS_ARCH_MIPS64R3 1
// MIPS-ARCH-64R3:#define _MIPS_ISA _MIPS_ISA_MIPS64
// MIPS-ARCH-64R3:#define __mips_isa_rev 3
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips64-none-none \
// RUN: -target-cpu mips64r5 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ARCH-64R5 %s
//
// MIPS-ARCH-64R5:#define _MIPS_ARCH "mips64r5"
// MIPS-ARCH-64R5:#define _MIPS_ARCH_MIPS64R5 1
// MIPS-ARCH-64R5:#define _MIPS_ISA _MIPS_ISA_MIPS64
// MIPS-ARCH-64R5:#define __mips_isa_rev 5
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips64-none-none \
// RUN: -target-cpu mips64r6 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ARCH-64R6 %s
//
// MIPS-ARCH-64R6:#define _MIPS_ARCH "mips64r6"
// MIPS-ARCH-64R6:#define _MIPS_ARCH_MIPS64R6 1
// MIPS-ARCH-64R6:#define _MIPS_ISA _MIPS_ISA_MIPS64
// MIPS-ARCH-64R6:#define __mips_isa_rev 6
//
// Check MIPS float ABI macros
//
// RUN: %clang_cc1 -E -dM -ffreestanding \
// RUN: -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-FABI-HARD %s
// MIPS-FABI-HARD:#define __mips_hard_float 1
//
// RUN: %clang_cc1 -target-feature +soft-float -E -dM -ffreestanding \
// RUN: -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-FABI-SOFT %s
// MIPS-FABI-SOFT:#define __mips_soft_float 1
//
// RUN: %clang_cc1 -target-feature +single-float -E -dM -ffreestanding \
// RUN: -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-FABI-SINGLE %s
// MIPS-FABI-SINGLE:#define __mips_hard_float 1
// MIPS-FABI-SINGLE:#define __mips_single_float 1
//
// RUN: %clang_cc1 -target-feature +soft-float -target-feature +single-float \
// RUN: -E -dM -ffreestanding -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-FABI-SINGLE-SOFT %s
// MIPS-FABI-SINGLE-SOFT:#define __mips_single_float 1
// MIPS-FABI-SINGLE-SOFT:#define __mips_soft_float 1
//
// Check MIPS features macros
//
// RUN: %clang_cc1 -target-feature +mips16 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS16 %s
// MIPS16:#define __mips16 1
//
// RUN: %clang_cc1 -target-feature -mips16 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix NOMIPS16 %s
// NOMIPS16-NOT:#define __mips16 1
//
// RUN: %clang_cc1 -target-feature +micromips \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MICROMIPS %s
// MICROMIPS:#define __mips_micromips 1
//
// RUN: %clang_cc1 -target-feature -micromips \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix NOMICROMIPS %s
// NOMICROMIPS-NOT:#define __mips_micromips 1
//
// RUN: %clang_cc1 -target-feature +dsp \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-DSP %s
// MIPS-DSP:#define __mips_dsp 1
// MIPS-DSP:#define __mips_dsp_rev 1
// MIPS-DSP-NOT:#define __mips_dspr2 1
//
// RUN: %clang_cc1 -target-feature +dspr2 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-DSPR2 %s
// MIPS-DSPR2:#define __mips_dsp 1
// MIPS-DSPR2:#define __mips_dsp_rev 2
// MIPS-DSPR2:#define __mips_dspr2 1
//
// RUN: %clang_cc1 -target-feature +msa \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-MSA %s
// MIPS-MSA:#define __mips_msa 1
//
// RUN: %clang_cc1 -target-feature +nomadd4 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-NOMADD4 %s
// MIPS-NOMADD4:#define __mips_no_madd4 1
//
// RUN: %clang_cc1 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-MADD4 %s
// MIPS-MADD4-NOT:#define __mips_no_madd4 1
//
// RUN: %clang_cc1 -target-cpu mips32r3 -target-feature +nan2008 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-NAN2008 %s
// MIPS-NAN2008:#define __mips_nan2008 1
//
// RUN: %clang_cc1 -target-cpu mips32r3 -target-feature -nan2008 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix NOMIPS-NAN2008 %s
// NOMIPS-NAN2008-NOT:#define __mips_nan2008 1
//
// RUN: %clang_cc1 -target-cpu mips32r3 -target-feature +abs2008 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ABS2008 %s
// MIPS-ABS2008:#define __mips_abs2008 1
//
// RUN: %clang_cc1 -target-cpu mips32r3 -target-feature -abs2008 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix NOMIPS-ABS2008 %s
// NOMIPS-ABS2008-NOT:#define __mips_abs2008 1
//
// RUN: %clang_cc1 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS32-NOFP %s
// MIPS32-NOFP:#define __mips_fpr 0
//
// RUN: %clang_cc1 -target-feature +fpxx \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS32-MFPXX %s
// MIPS32-MFPXX:#define __mips_fpr 0
//
// RUN: %clang_cc1 -target-cpu mips32r6 -target-feature +fpxx \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS32R6-MFPXX %s
// MIPS32R6-MFPXX:#define __mips_fpr 0
//
// RUN: %clang_cc1 \
// RUN: -E -dM -triple=mips64-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS64-NOFP %s
// MIPS64-NOFP:#define __mips_fpr 64
//
// RUN: not %clang_cc1 -target-feature -fp64 \
// RUN: -E -dM -triple=mips64-none-none < /dev/null 2>&1 \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS64-MFP32 %s
// MIPS64-MFP32:error: option '-mfpxx' cannot be specified with 'mips64r2'
//
// RUN: not %clang_cc1 -target-feature +fpxx \
// RUN: -E -dM -triple=mips64-none-none < /dev/null 2>&1 \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS64-MFPXX %s
// MIPS64-MFPXX:error: '-mfpxx' can only be used with the 'o32' ABI
//
// RUN: not %clang_cc1 -target-cpu mips64r6 -target-feature +fpxx \
// RUN: -E -dM -triple=mips64-none-none < /dev/null 2>&1 \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS64R6-MFPXX %s
// MIPS64R6-MFPXX:error: '-mfpxx' can only be used with the 'o32' ABI
//
// RUN: %clang_cc1 -target-feature -fp64 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS32-MFP32 %s
// MIPS32-MFP32:#define _MIPS_FPSET 16
// MIPS32-MFP32:#define __mips_fpr 32
//
// RUN: %clang_cc1 -target-feature +fp64 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS32-MFP64 %s
// MIPS32-MFP64:#define _MIPS_FPSET 32
// MIPS32-MFP64:#define __mips_fpr 64
//
// RUN: %clang_cc1 -target-feature +single-float \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS32-MFP32SF %s
// MIPS32-MFP32SF:#define _MIPS_FPSET 32
// MIPS32-MFP32SF:#define __mips_fpr 0
//
// RUN: %clang_cc1 -target-feature +fp64 \
// RUN: -E -dM -triple=mips64-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS64-MFP64 %s
// MIPS64-MFP64:#define _MIPS_FPSET 32
// MIPS64-MFP64:#define __mips_fpr 64
//
// RUN: %clang_cc1 -target-feature -fp64 -target-feature +single-float \
// RUN: -E -dM -triple=mips64-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS64-NOMFP64 %s
// MIPS64-NOMFP64:#define _MIPS_FPSET 32
// MIPS64-NOMFP64:#define __mips_fpr 32
//
// RUN: %clang_cc1 -target-cpu mips32r6 \
// RUN: -E -dM -triple=mips-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-XXR6 %s
// RUN: %clang_cc1 -target-cpu mips64r6 \
// RUN: -E -dM -triple=mips64-none-none < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-XXR6 %s
// MIPS-XXR6:#define _MIPS_FPSET 32
// MIPS-XXR6:#define __mips_fpr 64
// MIPS-XXR6:#define __mips_nan2008 1
//
// RUN: %clang_cc1 -target-cpu mips32 \
// RUN: -E -dM -triple=mips-unknown-netbsd -mrelocation-model pic < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ABICALLS-NETBSD %s
// MIPS-ABICALLS-NETBSD-NOT: #define __ABICALLS__ 1
// MIPS-ABICALLS-NETBSD: #define __mips_abicalls 1
//
// RUN: %clang_cc1 -target-cpu mips64 \
// RUN: -E -dM -triple=mips64-unknown-netbsd -mrelocation-model pic < \
// RUN: /dev/null | FileCheck -match-full-lines \
// RUN: -check-prefix MIPS-ABICALLS-NETBSD64 %s
// MIPS-ABICALLS-NETBSD64-NOT: #define __ABICALLS__ 1
// MIPS-ABICALLS-NETBSD64: #define __mips_abicalls 1
//
// RUN: %clang_cc1 -target-cpu mips32 \
// RUN: -E -dM -triple=mips-unknown-freebsd -mrelocation-model pic < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ABICALLS-FREEBSD %s
// MIPS-ABICALLS-FREEBSD: #define __ABICALLS__ 1
// MIPS-ABICALLS-FREEBSD: #define __mips_abicalls 1
//
// RUN: %clang_cc1 -target-cpu mips64 \
// RUN: -E -dM -triple=mips64-unknown-freebsd -mrelocation-model pic < \
// RUN: /dev/null | FileCheck -match-full-lines \
// RUN: -check-prefix MIPS-ABICALLS-FREEBSD64 %s
// MIPS-ABICALLS-FREEBSD64: #define __ABICALLS__ 1
// MIPS-ABICALLS-FREEBSD64: #define __mips_abicalls 1
//
// RUN: %clang_cc1 -target-cpu mips32 \
// RUN: -E -dM -triple=mips-unknown-openbsd -mrelocation-model pic < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MIPS-ABICALLS-OPENBSD %s
// MIPS-ABICALLS-OPENBSD: #define __ABICALLS__ 1
// MIPS-ABICALLS-OPENBSD: #define __mips_abicalls 1
//
// RUN: %clang_cc1 -target-cpu mips64 \
// RUN: -E -dM -triple=mips64-unknown-openbsd -mrelocation-model pic < \
// RUN: /dev/null | FileCheck -match-full-lines \
// RUN: -check-prefix MIPS-ABICALLS-OPENBSD64 %s
// MIPS-ABICALLS-OPENBSD64: #define __ABICALLS__ 1
// MIPS-ABICALLS-OPENBSD64: #define __mips_abicalls 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=msp430-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MSP430 %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=msp430-none-none < /dev/null | FileCheck -match-full-lines -check-prefix MSP430 -check-prefix MSP430-CXX %s
//
// MSP430:#define MSP430 1
// MSP430-NOT:#define _LP64
// MSP430:#define __BIGGEST_ALIGNMENT__ 2
// MSP430:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// MSP430:#define __CHAR16_TYPE__ unsigned short
// MSP430:#define __CHAR32_TYPE__ unsigned int
// MSP430:#define __CHAR_BIT__ 8
// MSP430:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// MSP430:#define __DBL_DIG__ 15
// MSP430:#define __DBL_EPSILON__ 2.2204460492503131e-16
// MSP430:#define __DBL_HAS_DENORM__ 1
// MSP430:#define __DBL_HAS_INFINITY__ 1
// MSP430:#define __DBL_HAS_QUIET_NAN__ 1
// MSP430:#define __DBL_MANT_DIG__ 53
// MSP430:#define __DBL_MAX_10_EXP__ 308
// MSP430:#define __DBL_MAX_EXP__ 1024
// MSP430:#define __DBL_MAX__ 1.7976931348623157e+308
// MSP430:#define __DBL_MIN_10_EXP__ (-307)
// MSP430:#define __DBL_MIN_EXP__ (-1021)
// MSP430:#define __DBL_MIN__ 2.2250738585072014e-308
// MSP430:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// MSP430:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// MSP430:#define __FLT_DIG__ 6
// MSP430:#define __FLT_EPSILON__ 1.19209290e-7F
// MSP430:#define __FLT_EVAL_METHOD__ 0
// MSP430:#define __FLT_HAS_DENORM__ 1
// MSP430:#define __FLT_HAS_INFINITY__ 1
// MSP430:#define __FLT_HAS_QUIET_NAN__ 1
// MSP430:#define __FLT_MANT_DIG__ 24
// MSP430:#define __FLT_MAX_10_EXP__ 38
// MSP430:#define __FLT_MAX_EXP__ 128
// MSP430:#define __FLT_MAX__ 3.40282347e+38F
// MSP430:#define __FLT_MIN_10_EXP__ (-37)
// MSP430:#define __FLT_MIN_EXP__ (-125)
// MSP430:#define __FLT_MIN__ 1.17549435e-38F
// MSP430:#define __FLT_RADIX__ 2
// MSP430:#define __INT16_C_SUFFIX__
// MSP430:#define __INT16_FMTd__ "hd"
// MSP430:#define __INT16_FMTi__ "hi"
// MSP430:#define __INT16_MAX__ 32767
// MSP430:#define __INT16_TYPE__ short
// MSP430:#define __INT32_C_SUFFIX__ L
// MSP430:#define __INT32_FMTd__ "ld"
// MSP430:#define __INT32_FMTi__ "li"
// MSP430:#define __INT32_MAX__ 2147483647L
// MSP430:#define __INT32_TYPE__ long int
// MSP430:#define __INT64_C_SUFFIX__ LL
// MSP430:#define __INT64_FMTd__ "lld"
// MSP430:#define __INT64_FMTi__ "lli"
// MSP430:#define __INT64_MAX__ 9223372036854775807LL
// MSP430:#define __INT64_TYPE__ long long int
// MSP430:#define __INT8_C_SUFFIX__
// MSP430:#define __INT8_FMTd__ "hhd"
// MSP430:#define __INT8_FMTi__ "hhi"
// MSP430:#define __INT8_MAX__ 127
// MSP430:#define __INT8_TYPE__ signed char
// MSP430:#define __INTMAX_C_SUFFIX__ LL
// MSP430:#define __INTMAX_FMTd__ "lld"
// MSP430:#define __INTMAX_FMTi__ "lli"
// MSP430:#define __INTMAX_MAX__ 9223372036854775807LL
// MSP430:#define __INTMAX_TYPE__ long long int
// MSP430:#define __INTMAX_WIDTH__ 64
// MSP430:#define __INTPTR_FMTd__ "d"
// MSP430:#define __INTPTR_FMTi__ "i"
// MSP430:#define __INTPTR_MAX__ 32767
// MSP430:#define __INTPTR_TYPE__ int
// MSP430:#define __INTPTR_WIDTH__ 16
// MSP430:#define __INT_FAST16_FMTd__ "hd"
// MSP430:#define __INT_FAST16_FMTi__ "hi"
// MSP430:#define __INT_FAST16_MAX__ 32767
// MSP430:#define __INT_FAST16_TYPE__ short
// MSP430:#define __INT_FAST32_FMTd__ "ld"
// MSP430:#define __INT_FAST32_FMTi__ "li"
// MSP430:#define __INT_FAST32_MAX__ 2147483647L
// MSP430:#define __INT_FAST32_TYPE__ long int
// MSP430:#define __INT_FAST64_FMTd__ "lld"
// MSP430:#define __INT_FAST64_FMTi__ "lli"
// MSP430:#define __INT_FAST64_MAX__ 9223372036854775807LL
// MSP430:#define __INT_FAST64_TYPE__ long long int
// MSP430:#define __INT_FAST8_FMTd__ "hhd"
// MSP430:#define __INT_FAST8_FMTi__ "hhi"
// MSP430:#define __INT_FAST8_MAX__ 127
// MSP430:#define __INT_FAST8_TYPE__ signed char
// MSP430:#define __INT_LEAST16_FMTd__ "hd"
// MSP430:#define __INT_LEAST16_FMTi__ "hi"
// MSP430:#define __INT_LEAST16_MAX__ 32767
// MSP430:#define __INT_LEAST16_TYPE__ short
// MSP430:#define __INT_LEAST32_FMTd__ "ld"
// MSP430:#define __INT_LEAST32_FMTi__ "li"
// MSP430:#define __INT_LEAST32_MAX__ 2147483647L
// MSP430:#define __INT_LEAST32_TYPE__ long int
// MSP430:#define __INT_LEAST64_FMTd__ "lld"
// MSP430:#define __INT_LEAST64_FMTi__ "lli"
// MSP430:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// MSP430:#define __INT_LEAST64_TYPE__ long long int
// MSP430:#define __INT_LEAST8_FMTd__ "hhd"
// MSP430:#define __INT_LEAST8_FMTi__ "hhi"
// MSP430:#define __INT_LEAST8_MAX__ 127
// MSP430:#define __INT_LEAST8_TYPE__ signed char
// MSP430:#define __INT_MAX__ 32767
// MSP430:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
// MSP430:#define __LDBL_DIG__ 15
// MSP430:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
// MSP430:#define __LDBL_HAS_DENORM__ 1
// MSP430:#define __LDBL_HAS_INFINITY__ 1
// MSP430:#define __LDBL_HAS_QUIET_NAN__ 1
// MSP430:#define __LDBL_MANT_DIG__ 53
// MSP430:#define __LDBL_MAX_10_EXP__ 308
// MSP430:#define __LDBL_MAX_EXP__ 1024
// MSP430:#define __LDBL_MAX__ 1.7976931348623157e+308L
// MSP430:#define __LDBL_MIN_10_EXP__ (-307)
// MSP430:#define __LDBL_MIN_EXP__ (-1021)
// MSP430:#define __LDBL_MIN__ 2.2250738585072014e-308L
// MSP430:#define __LITTLE_ENDIAN__ 1
// MSP430:#define __LONG_LONG_MAX__ 9223372036854775807LL
// MSP430:#define __LONG_MAX__ 2147483647L
// MSP430-NOT:#define __LP64__
// MSP430:#define __MSP430__ 1
// MSP430:#define __POINTER_WIDTH__ 16
// MSP430:#define __PTRDIFF_TYPE__ int
// MSP430:#define __PTRDIFF_WIDTH__ 16
// MSP430:#define __SCHAR_MAX__ 127
// MSP430:#define __SHRT_MAX__ 32767
// MSP430:#define __SIG_ATOMIC_MAX__ 2147483647L
// MSP430:#define __SIG_ATOMIC_WIDTH__ 32
// MSP430:#define __SIZEOF_DOUBLE__ 8
// MSP430:#define __SIZEOF_FLOAT__ 4
// MSP430:#define __SIZEOF_INT__ 2
// MSP430:#define __SIZEOF_LONG_DOUBLE__ 8
// MSP430:#define __SIZEOF_LONG_LONG__ 8
// MSP430:#define __SIZEOF_LONG__ 4
// MSP430:#define __SIZEOF_POINTER__ 2
// MSP430:#define __SIZEOF_PTRDIFF_T__ 2
// MSP430:#define __SIZEOF_SHORT__ 2
// MSP430:#define __SIZEOF_SIZE_T__ 2
// MSP430:#define __SIZEOF_WCHAR_T__ 2
// MSP430:#define __SIZEOF_WINT_T__ 2
// MSP430:#define __SIZE_MAX__ 65535U
// MSP430:#define __SIZE_TYPE__ unsigned int
// MSP430:#define __SIZE_WIDTH__ 16
// MSP430-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
// MSP430:#define __UINT16_C_SUFFIX__ U
// MSP430:#define __UINT16_MAX__ 65535U
// MSP430:#define __UINT16_TYPE__ unsigned short
// MSP430:#define __UINT32_C_SUFFIX__ UL
// MSP430:#define __UINT32_MAX__ 4294967295UL
// MSP430:#define __UINT32_TYPE__ long unsigned int
// MSP430:#define __UINT64_C_SUFFIX__ ULL
// MSP430:#define __UINT64_MAX__ 18446744073709551615ULL
// MSP430:#define __UINT64_TYPE__ long long unsigned int
// MSP430:#define __UINT8_C_SUFFIX__
// MSP430:#define __UINT8_MAX__ 255
// MSP430:#define __UINT8_TYPE__ unsigned char
// MSP430:#define __UINTMAX_C_SUFFIX__ ULL
// MSP430:#define __UINTMAX_MAX__ 18446744073709551615ULL
// MSP430:#define __UINTMAX_TYPE__ long long unsigned int
// MSP430:#define __UINTMAX_WIDTH__ 64
// MSP430:#define __UINTPTR_MAX__ 65535U
// MSP430:#define __UINTPTR_TYPE__ unsigned int
// MSP430:#define __UINTPTR_WIDTH__ 16
// MSP430:#define __UINT_FAST16_MAX__ 65535U
// MSP430:#define __UINT_FAST16_TYPE__ unsigned short
// MSP430:#define __UINT_FAST32_MAX__ 4294967295UL
// MSP430:#define __UINT_FAST32_TYPE__ long unsigned int
// MSP430:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// MSP430:#define __UINT_FAST64_TYPE__ long long unsigned int
// MSP430:#define __UINT_FAST8_MAX__ 255
// MSP430:#define __UINT_FAST8_TYPE__ unsigned char
// MSP430:#define __UINT_LEAST16_MAX__ 65535U
// MSP430:#define __UINT_LEAST16_TYPE__ unsigned short
// MSP430:#define __UINT_LEAST32_MAX__ 4294967295UL
// MSP430:#define __UINT_LEAST32_TYPE__ long unsigned int
// MSP430:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// MSP430:#define __UINT_LEAST64_TYPE__ long long unsigned int
// MSP430:#define __UINT_LEAST8_MAX__ 255
// MSP430:#define __UINT_LEAST8_TYPE__ unsigned char
// MSP430:#define __USER_LABEL_PREFIX__
// MSP430:#define __WCHAR_MAX__ 32767
// MSP430:#define __WCHAR_TYPE__ int
// MSP430:#define __WCHAR_WIDTH__ 16
// MSP430:#define __WINT_TYPE__ int
// MSP430:#define __WINT_WIDTH__ 16
// MSP430:#define __clang__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=nvptx-none-none < /dev/null | FileCheck -match-full-lines -check-prefix NVPTX32 %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=nvptx-none-none < /dev/null | FileCheck -match-full-lines -check-prefix NVPTX32 -check-prefix NVPTX32-CXX %s
//
// NVPTX32-NOT:#define _LP64
// NVPTX32:#define __BIGGEST_ALIGNMENT__ 8
// NVPTX32:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// NVPTX32:#define __CHAR16_TYPE__ unsigned short
// NVPTX32:#define __CHAR32_TYPE__ unsigned int
// NVPTX32:#define __CHAR_BIT__ 8
// NVPTX32:#define __CONSTANT_CFSTRINGS__ 1
// NVPTX32:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// NVPTX32:#define __DBL_DIG__ 15
// NVPTX32:#define __DBL_EPSILON__ 2.2204460492503131e-16
// NVPTX32:#define __DBL_HAS_DENORM__ 1
// NVPTX32:#define __DBL_HAS_INFINITY__ 1
// NVPTX32:#define __DBL_HAS_QUIET_NAN__ 1
// NVPTX32:#define __DBL_MANT_DIG__ 53
// NVPTX32:#define __DBL_MAX_10_EXP__ 308
// NVPTX32:#define __DBL_MAX_EXP__ 1024
// NVPTX32:#define __DBL_MAX__ 1.7976931348623157e+308
// NVPTX32:#define __DBL_MIN_10_EXP__ (-307)
// NVPTX32:#define __DBL_MIN_EXP__ (-1021)
// NVPTX32:#define __DBL_MIN__ 2.2250738585072014e-308
// NVPTX32:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// NVPTX32:#define __FINITE_MATH_ONLY__ 0
// NVPTX32:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// NVPTX32:#define __FLT_DIG__ 6
// NVPTX32:#define __FLT_EPSILON__ 1.19209290e-7F
// NVPTX32:#define __FLT_EVAL_METHOD__ 0
// NVPTX32:#define __FLT_HAS_DENORM__ 1
// NVPTX32:#define __FLT_HAS_INFINITY__ 1
// NVPTX32:#define __FLT_HAS_QUIET_NAN__ 1
// NVPTX32:#define __FLT_MANT_DIG__ 24
// NVPTX32:#define __FLT_MAX_10_EXP__ 38
// NVPTX32:#define __FLT_MAX_EXP__ 128
// NVPTX32:#define __FLT_MAX__ 3.40282347e+38F
// NVPTX32:#define __FLT_MIN_10_EXP__ (-37)
// NVPTX32:#define __FLT_MIN_EXP__ (-125)
// NVPTX32:#define __FLT_MIN__ 1.17549435e-38F
// NVPTX32:#define __FLT_RADIX__ 2
// NVPTX32:#define __INT16_C_SUFFIX__
// NVPTX32:#define __INT16_FMTd__ "hd"
// NVPTX32:#define __INT16_FMTi__ "hi"
// NVPTX32:#define __INT16_MAX__ 32767
// NVPTX32:#define __INT16_TYPE__ short
// NVPTX32:#define __INT32_C_SUFFIX__
// NVPTX32:#define __INT32_FMTd__ "d"
// NVPTX32:#define __INT32_FMTi__ "i"
// NVPTX32:#define __INT32_MAX__ 2147483647
// NVPTX32:#define __INT32_TYPE__ int
// NVPTX32:#define __INT64_C_SUFFIX__ LL
// NVPTX32:#define __INT64_FMTd__ "lld"
// NVPTX32:#define __INT64_FMTi__ "lli"
// NVPTX32:#define __INT64_MAX__ 9223372036854775807LL
// NVPTX32:#define __INT64_TYPE__ long long int
// NVPTX32:#define __INT8_C_SUFFIX__
// NVPTX32:#define __INT8_FMTd__ "hhd"
// NVPTX32:#define __INT8_FMTi__ "hhi"
// NVPTX32:#define __INT8_MAX__ 127
// NVPTX32:#define __INT8_TYPE__ signed char
// NVPTX32:#define __INTMAX_C_SUFFIX__ LL
// NVPTX32:#define __INTMAX_FMTd__ "lld"
// NVPTX32:#define __INTMAX_FMTi__ "lli"
// NVPTX32:#define __INTMAX_MAX__ 9223372036854775807LL
// NVPTX32:#define __INTMAX_TYPE__ long long int
// NVPTX32:#define __INTMAX_WIDTH__ 64
// NVPTX32:#define __INTPTR_FMTd__ "d"
// NVPTX32:#define __INTPTR_FMTi__ "i"
// NVPTX32:#define __INTPTR_MAX__ 2147483647
// NVPTX32:#define __INTPTR_TYPE__ int
// NVPTX32:#define __INTPTR_WIDTH__ 32
// NVPTX32:#define __INT_FAST16_FMTd__ "hd"
// NVPTX32:#define __INT_FAST16_FMTi__ "hi"
// NVPTX32:#define __INT_FAST16_MAX__ 32767
// NVPTX32:#define __INT_FAST16_TYPE__ short
// NVPTX32:#define __INT_FAST32_FMTd__ "d"
// NVPTX32:#define __INT_FAST32_FMTi__ "i"
// NVPTX32:#define __INT_FAST32_MAX__ 2147483647
// NVPTX32:#define __INT_FAST32_TYPE__ int
// NVPTX32:#define __INT_FAST64_FMTd__ "lld"
// NVPTX32:#define __INT_FAST64_FMTi__ "lli"
// NVPTX32:#define __INT_FAST64_MAX__ 9223372036854775807LL
// NVPTX32:#define __INT_FAST64_TYPE__ long long int
// NVPTX32:#define __INT_FAST8_FMTd__ "hhd"
// NVPTX32:#define __INT_FAST8_FMTi__ "hhi"
// NVPTX32:#define __INT_FAST8_MAX__ 127
// NVPTX32:#define __INT_FAST8_TYPE__ signed char
// NVPTX32:#define __INT_LEAST16_FMTd__ "hd"
// NVPTX32:#define __INT_LEAST16_FMTi__ "hi"
// NVPTX32:#define __INT_LEAST16_MAX__ 32767
// NVPTX32:#define __INT_LEAST16_TYPE__ short
// NVPTX32:#define __INT_LEAST32_FMTd__ "d"
// NVPTX32:#define __INT_LEAST32_FMTi__ "i"
// NVPTX32:#define __INT_LEAST32_MAX__ 2147483647
// NVPTX32:#define __INT_LEAST32_TYPE__ int
// NVPTX32:#define __INT_LEAST64_FMTd__ "lld"
// NVPTX32:#define __INT_LEAST64_FMTi__ "lli"
// NVPTX32:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// NVPTX32:#define __INT_LEAST64_TYPE__ long long int
// NVPTX32:#define __INT_LEAST8_FMTd__ "hhd"
// NVPTX32:#define __INT_LEAST8_FMTi__ "hhi"
// NVPTX32:#define __INT_LEAST8_MAX__ 127
// NVPTX32:#define __INT_LEAST8_TYPE__ signed char
// NVPTX32:#define __INT_MAX__ 2147483647
// NVPTX32:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
// NVPTX32:#define __LDBL_DIG__ 15
// NVPTX32:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
// NVPTX32:#define __LDBL_HAS_DENORM__ 1
// NVPTX32:#define __LDBL_HAS_INFINITY__ 1
// NVPTX32:#define __LDBL_HAS_QUIET_NAN__ 1
// NVPTX32:#define __LDBL_MANT_DIG__ 53
// NVPTX32:#define __LDBL_MAX_10_EXP__ 308
// NVPTX32:#define __LDBL_MAX_EXP__ 1024
// NVPTX32:#define __LDBL_MAX__ 1.7976931348623157e+308L
// NVPTX32:#define __LDBL_MIN_10_EXP__ (-307)
// NVPTX32:#define __LDBL_MIN_EXP__ (-1021)
// NVPTX32:#define __LDBL_MIN__ 2.2250738585072014e-308L
// NVPTX32:#define __LITTLE_ENDIAN__ 1
// NVPTX32:#define __LONG_LONG_MAX__ 9223372036854775807LL
// NVPTX32:#define __LONG_MAX__ 2147483647L
// NVPTX32-NOT:#define __LP64__
// NVPTX32:#define __NVPTX__ 1
// NVPTX32:#define __POINTER_WIDTH__ 32
// NVPTX32:#define __PRAGMA_REDEFINE_EXTNAME 1
// NVPTX32:#define __PTRDIFF_TYPE__ int
// NVPTX32:#define __PTRDIFF_WIDTH__ 32
// NVPTX32:#define __PTX__ 1
// NVPTX32:#define __SCHAR_MAX__ 127
// NVPTX32:#define __SHRT_MAX__ 32767
// NVPTX32:#define __SIG_ATOMIC_MAX__ 2147483647
// NVPTX32:#define __SIG_ATOMIC_WIDTH__ 32
// NVPTX32:#define __SIZEOF_DOUBLE__ 8
// NVPTX32:#define __SIZEOF_FLOAT__ 4
// NVPTX32:#define __SIZEOF_INT__ 4
// NVPTX32:#define __SIZEOF_LONG_DOUBLE__ 8
// NVPTX32:#define __SIZEOF_LONG_LONG__ 8
// NVPTX32:#define __SIZEOF_LONG__ 4
// NVPTX32:#define __SIZEOF_POINTER__ 4
// NVPTX32:#define __SIZEOF_PTRDIFF_T__ 4
// NVPTX32:#define __SIZEOF_SHORT__ 2
// NVPTX32:#define __SIZEOF_SIZE_T__ 4
// NVPTX32:#define __SIZEOF_WCHAR_T__ 4
// NVPTX32:#define __SIZEOF_WINT_T__ 4
// NVPTX32:#define __SIZE_MAX__ 4294967295U
// NVPTX32:#define __SIZE_TYPE__ unsigned int
// NVPTX32:#define __SIZE_WIDTH__ 32
// NVPTX32-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
// NVPTX32:#define __UINT16_C_SUFFIX__
// NVPTX32:#define __UINT16_MAX__ 65535
// NVPTX32:#define __UINT16_TYPE__ unsigned short
// NVPTX32:#define __UINT32_C_SUFFIX__ U
// NVPTX32:#define __UINT32_MAX__ 4294967295U
// NVPTX32:#define __UINT32_TYPE__ unsigned int
// NVPTX32:#define __UINT64_C_SUFFIX__ ULL
// NVPTX32:#define __UINT64_MAX__ 18446744073709551615ULL
// NVPTX32:#define __UINT64_TYPE__ long long unsigned int
// NVPTX32:#define __UINT8_C_SUFFIX__
// NVPTX32:#define __UINT8_MAX__ 255
// NVPTX32:#define __UINT8_TYPE__ unsigned char
// NVPTX32:#define __UINTMAX_C_SUFFIX__ ULL
// NVPTX32:#define __UINTMAX_MAX__ 18446744073709551615ULL
// NVPTX32:#define __UINTMAX_TYPE__ long long unsigned int
// NVPTX32:#define __UINTMAX_WIDTH__ 64
// NVPTX32:#define __UINTPTR_MAX__ 4294967295U
// NVPTX32:#define __UINTPTR_TYPE__ unsigned int
// NVPTX32:#define __UINTPTR_WIDTH__ 32
// NVPTX32:#define __UINT_FAST16_MAX__ 65535
// NVPTX32:#define __UINT_FAST16_TYPE__ unsigned short
// NVPTX32:#define __UINT_FAST32_MAX__ 4294967295U
// NVPTX32:#define __UINT_FAST32_TYPE__ unsigned int
// NVPTX32:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// NVPTX32:#define __UINT_FAST64_TYPE__ long long unsigned int
// NVPTX32:#define __UINT_FAST8_MAX__ 255
// NVPTX32:#define __UINT_FAST8_TYPE__ unsigned char
// NVPTX32:#define __UINT_LEAST16_MAX__ 65535
// NVPTX32:#define __UINT_LEAST16_TYPE__ unsigned short
// NVPTX32:#define __UINT_LEAST32_MAX__ 4294967295U
// NVPTX32:#define __UINT_LEAST32_TYPE__ unsigned int
// NVPTX32:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// NVPTX32:#define __UINT_LEAST64_TYPE__ long long unsigned int
// NVPTX32:#define __UINT_LEAST8_MAX__ 255
// NVPTX32:#define __UINT_LEAST8_TYPE__ unsigned char
// NVPTX32:#define __USER_LABEL_PREFIX__
// NVPTX32:#define __WCHAR_MAX__ 2147483647
// NVPTX32:#define __WCHAR_TYPE__ int
// NVPTX32:#define __WCHAR_WIDTH__ 32
// NVPTX32:#define __WINT_TYPE__ int
// NVPTX32:#define __WINT_WIDTH__ 32
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=nvptx64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix NVPTX64 %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=nvptx64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix NVPTX64 -check-prefix NVPTX64-CXX %s
//
// NVPTX64:#define _LP64 1
// NVPTX64:#define __BIGGEST_ALIGNMENT__ 8
// NVPTX64:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// NVPTX64:#define __CHAR16_TYPE__ unsigned short
// NVPTX64:#define __CHAR32_TYPE__ unsigned int
// NVPTX64:#define __CHAR_BIT__ 8
// NVPTX64:#define __CONSTANT_CFSTRINGS__ 1
// NVPTX64:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// NVPTX64:#define __DBL_DIG__ 15
// NVPTX64:#define __DBL_EPSILON__ 2.2204460492503131e-16
// NVPTX64:#define __DBL_HAS_DENORM__ 1
// NVPTX64:#define __DBL_HAS_INFINITY__ 1
// NVPTX64:#define __DBL_HAS_QUIET_NAN__ 1
// NVPTX64:#define __DBL_MANT_DIG__ 53
// NVPTX64:#define __DBL_MAX_10_EXP__ 308
// NVPTX64:#define __DBL_MAX_EXP__ 1024
// NVPTX64:#define __DBL_MAX__ 1.7976931348623157e+308
// NVPTX64:#define __DBL_MIN_10_EXP__ (-307)
// NVPTX64:#define __DBL_MIN_EXP__ (-1021)
// NVPTX64:#define __DBL_MIN__ 2.2250738585072014e-308
// NVPTX64:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// NVPTX64:#define __FINITE_MATH_ONLY__ 0
// NVPTX64:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// NVPTX64:#define __FLT_DIG__ 6
// NVPTX64:#define __FLT_EPSILON__ 1.19209290e-7F
// NVPTX64:#define __FLT_EVAL_METHOD__ 0
// NVPTX64:#define __FLT_HAS_DENORM__ 1
// NVPTX64:#define __FLT_HAS_INFINITY__ 1
// NVPTX64:#define __FLT_HAS_QUIET_NAN__ 1
// NVPTX64:#define __FLT_MANT_DIG__ 24
// NVPTX64:#define __FLT_MAX_10_EXP__ 38
// NVPTX64:#define __FLT_MAX_EXP__ 128
// NVPTX64:#define __FLT_MAX__ 3.40282347e+38F
// NVPTX64:#define __FLT_MIN_10_EXP__ (-37)
// NVPTX64:#define __FLT_MIN_EXP__ (-125)
// NVPTX64:#define __FLT_MIN__ 1.17549435e-38F
// NVPTX64:#define __FLT_RADIX__ 2
// NVPTX64:#define __INT16_C_SUFFIX__
// NVPTX64:#define __INT16_FMTd__ "hd"
// NVPTX64:#define __INT16_FMTi__ "hi"
// NVPTX64:#define __INT16_MAX__ 32767
// NVPTX64:#define __INT16_TYPE__ short
// NVPTX64:#define __INT32_C_SUFFIX__
// NVPTX64:#define __INT32_FMTd__ "d"
// NVPTX64:#define __INT32_FMTi__ "i"
// NVPTX64:#define __INT32_MAX__ 2147483647
// NVPTX64:#define __INT32_TYPE__ int
// NVPTX64:#define __INT64_C_SUFFIX__ LL
// NVPTX64:#define __INT64_FMTd__ "lld"
// NVPTX64:#define __INT64_FMTi__ "lli"
// NVPTX64:#define __INT64_MAX__ 9223372036854775807LL
// NVPTX64:#define __INT64_TYPE__ long long int
// NVPTX64:#define __INT8_C_SUFFIX__
// NVPTX64:#define __INT8_FMTd__ "hhd"
// NVPTX64:#define __INT8_FMTi__ "hhi"
// NVPTX64:#define __INT8_MAX__ 127
// NVPTX64:#define __INT8_TYPE__ signed char
// NVPTX64:#define __INTMAX_C_SUFFIX__ LL
// NVPTX64:#define __INTMAX_FMTd__ "lld"
// NVPTX64:#define __INTMAX_FMTi__ "lli"
// NVPTX64:#define __INTMAX_MAX__ 9223372036854775807LL
// NVPTX64:#define __INTMAX_TYPE__ long long int
// NVPTX64:#define __INTMAX_WIDTH__ 64
// NVPTX64:#define __INTPTR_FMTd__ "ld"
// NVPTX64:#define __INTPTR_FMTi__ "li"
// NVPTX64:#define __INTPTR_MAX__ 9223372036854775807L
// NVPTX64:#define __INTPTR_TYPE__ long int
// NVPTX64:#define __INTPTR_WIDTH__ 64
// NVPTX64:#define __INT_FAST16_FMTd__ "hd"
// NVPTX64:#define __INT_FAST16_FMTi__ "hi"
// NVPTX64:#define __INT_FAST16_MAX__ 32767
// NVPTX64:#define __INT_FAST16_TYPE__ short
// NVPTX64:#define __INT_FAST32_FMTd__ "d"
// NVPTX64:#define __INT_FAST32_FMTi__ "i"
// NVPTX64:#define __INT_FAST32_MAX__ 2147483647
// NVPTX64:#define __INT_FAST32_TYPE__ int
// NVPTX64:#define __INT_FAST64_FMTd__ "ld"
// NVPTX64:#define __INT_FAST64_FMTi__ "li"
// NVPTX64:#define __INT_FAST64_MAX__ 9223372036854775807L
// NVPTX64:#define __INT_FAST64_TYPE__ long int
// NVPTX64:#define __INT_FAST8_FMTd__ "hhd"
// NVPTX64:#define __INT_FAST8_FMTi__ "hhi"
// NVPTX64:#define __INT_FAST8_MAX__ 127
// NVPTX64:#define __INT_FAST8_TYPE__ signed char
// NVPTX64:#define __INT_LEAST16_FMTd__ "hd"
// NVPTX64:#define __INT_LEAST16_FMTi__ "hi"
// NVPTX64:#define __INT_LEAST16_MAX__ 32767
// NVPTX64:#define __INT_LEAST16_TYPE__ short
// NVPTX64:#define __INT_LEAST32_FMTd__ "d"
// NVPTX64:#define __INT_LEAST32_FMTi__ "i"
// NVPTX64:#define __INT_LEAST32_MAX__ 2147483647
// NVPTX64:#define __INT_LEAST32_TYPE__ int
// NVPTX64:#define __INT_LEAST64_FMTd__ "ld"
// NVPTX64:#define __INT_LEAST64_FMTi__ "li"
// NVPTX64:#define __INT_LEAST64_MAX__ 9223372036854775807L
// NVPTX64:#define __INT_LEAST64_TYPE__ long int
// NVPTX64:#define __INT_LEAST8_FMTd__ "hhd"
// NVPTX64:#define __INT_LEAST8_FMTi__ "hhi"
// NVPTX64:#define __INT_LEAST8_MAX__ 127
// NVPTX64:#define __INT_LEAST8_TYPE__ signed char
// NVPTX64:#define __INT_MAX__ 2147483647
// NVPTX64:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
// NVPTX64:#define __LDBL_DIG__ 15
// NVPTX64:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
// NVPTX64:#define __LDBL_HAS_DENORM__ 1
// NVPTX64:#define __LDBL_HAS_INFINITY__ 1
// NVPTX64:#define __LDBL_HAS_QUIET_NAN__ 1
// NVPTX64:#define __LDBL_MANT_DIG__ 53
// NVPTX64:#define __LDBL_MAX_10_EXP__ 308
// NVPTX64:#define __LDBL_MAX_EXP__ 1024
// NVPTX64:#define __LDBL_MAX__ 1.7976931348623157e+308L
// NVPTX64:#define __LDBL_MIN_10_EXP__ (-307)
// NVPTX64:#define __LDBL_MIN_EXP__ (-1021)
// NVPTX64:#define __LDBL_MIN__ 2.2250738585072014e-308L
// NVPTX64:#define __LITTLE_ENDIAN__ 1
// NVPTX64:#define __LONG_LONG_MAX__ 9223372036854775807LL
// NVPTX64:#define __LONG_MAX__ 9223372036854775807L
// NVPTX64:#define __LP64__ 1
// NVPTX64:#define __NVPTX__ 1
// NVPTX64:#define __POINTER_WIDTH__ 64
// NVPTX64:#define __PRAGMA_REDEFINE_EXTNAME 1
// NVPTX64:#define __PTRDIFF_TYPE__ long int
// NVPTX64:#define __PTRDIFF_WIDTH__ 64
// NVPTX64:#define __PTX__ 1
// NVPTX64:#define __SCHAR_MAX__ 127
// NVPTX64:#define __SHRT_MAX__ 32767
// NVPTX64:#define __SIG_ATOMIC_MAX__ 2147483647
// NVPTX64:#define __SIG_ATOMIC_WIDTH__ 32
// NVPTX64:#define __SIZEOF_DOUBLE__ 8
// NVPTX64:#define __SIZEOF_FLOAT__ 4
// NVPTX64:#define __SIZEOF_INT__ 4
// NVPTX64:#define __SIZEOF_LONG_DOUBLE__ 8
// NVPTX64:#define __SIZEOF_LONG_LONG__ 8
// NVPTX64:#define __SIZEOF_LONG__ 8
// NVPTX64:#define __SIZEOF_POINTER__ 8
// NVPTX64:#define __SIZEOF_PTRDIFF_T__ 8
// NVPTX64:#define __SIZEOF_SHORT__ 2
// NVPTX64:#define __SIZEOF_SIZE_T__ 8
// NVPTX64:#define __SIZEOF_WCHAR_T__ 4
// NVPTX64:#define __SIZEOF_WINT_T__ 4
// NVPTX64:#define __SIZE_MAX__ 18446744073709551615UL
// NVPTX64:#define __SIZE_TYPE__ long unsigned int
// NVPTX64:#define __SIZE_WIDTH__ 64
// NVPTX64-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8UL
// NVPTX64:#define __UINT16_C_SUFFIX__
// NVPTX64:#define __UINT16_MAX__ 65535
// NVPTX64:#define __UINT16_TYPE__ unsigned short
// NVPTX64:#define __UINT32_C_SUFFIX__ U
// NVPTX64:#define __UINT32_MAX__ 4294967295U
// NVPTX64:#define __UINT32_TYPE__ unsigned int
// NVPTX64:#define __UINT64_C_SUFFIX__ ULL
// NVPTX64:#define __UINT64_MAX__ 18446744073709551615ULL
// NVPTX64:#define __UINT64_TYPE__ long long unsigned int
// NVPTX64:#define __UINT8_C_SUFFIX__
// NVPTX64:#define __UINT8_MAX__ 255
// NVPTX64:#define __UINT8_TYPE__ unsigned char
// NVPTX64:#define __UINTMAX_C_SUFFIX__ ULL
// NVPTX64:#define __UINTMAX_MAX__ 18446744073709551615ULL
// NVPTX64:#define __UINTMAX_TYPE__ long long unsigned int
// NVPTX64:#define __UINTMAX_WIDTH__ 64
// NVPTX64:#define __UINTPTR_MAX__ 18446744073709551615UL
// NVPTX64:#define __UINTPTR_TYPE__ long unsigned int
// NVPTX64:#define __UINTPTR_WIDTH__ 64
// NVPTX64:#define __UINT_FAST16_MAX__ 65535
// NVPTX64:#define __UINT_FAST16_TYPE__ unsigned short
// NVPTX64:#define __UINT_FAST32_MAX__ 4294967295U
// NVPTX64:#define __UINT_FAST32_TYPE__ unsigned int
// NVPTX64:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// NVPTX64:#define __UINT_FAST64_TYPE__ long unsigned int
// NVPTX64:#define __UINT_FAST8_MAX__ 255
// NVPTX64:#define __UINT_FAST8_TYPE__ unsigned char
// NVPTX64:#define __UINT_LEAST16_MAX__ 65535
// NVPTX64:#define __UINT_LEAST16_TYPE__ unsigned short
// NVPTX64:#define __UINT_LEAST32_MAX__ 4294967295U
// NVPTX64:#define __UINT_LEAST32_TYPE__ unsigned int
// NVPTX64:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// NVPTX64:#define __UINT_LEAST64_TYPE__ long unsigned int
// NVPTX64:#define __UINT_LEAST8_MAX__ 255
// NVPTX64:#define __UINT_LEAST8_TYPE__ unsigned char
// NVPTX64:#define __USER_LABEL_PREFIX__
// NVPTX64:#define __WCHAR_MAX__ 2147483647
// NVPTX64:#define __WCHAR_TYPE__ int
// NVPTX64:#define __WCHAR_WIDTH__ 32
// NVPTX64:#define __WINT_TYPE__ int
// NVPTX64:#define __WINT_WIDTH__ 32
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc-none-none -target-cpu 603e < /dev/null | FileCheck -match-full-lines -check-prefix PPC603E %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=powerpc-none-none -target-cpu 603e < /dev/null | FileCheck -match-full-lines -check-prefix PPC603E-CXX %s
//
// PPC603E:#define _ARCH_603 1
// PPC603E:#define _ARCH_603E 1
// PPC603E:#define _ARCH_PPC 1
// PPC603E:#define _ARCH_PPCGR 1
// PPC603E:#define _BIG_ENDIAN 1
// PPC603E-NOT:#define _LP64
// PPC603E:#define __BIGGEST_ALIGNMENT__ 16
// PPC603E:#define __BIG_ENDIAN__ 1
// PPC603E:#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
// PPC603E:#define __CHAR16_TYPE__ unsigned short
// PPC603E:#define __CHAR32_TYPE__ unsigned int
// PPC603E:#define __CHAR_BIT__ 8
// PPC603E:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// PPC603E:#define __DBL_DIG__ 15
// PPC603E:#define __DBL_EPSILON__ 2.2204460492503131e-16
// PPC603E:#define __DBL_HAS_DENORM__ 1
// PPC603E:#define __DBL_HAS_INFINITY__ 1
// PPC603E:#define __DBL_HAS_QUIET_NAN__ 1
// PPC603E:#define __DBL_MANT_DIG__ 53
// PPC603E:#define __DBL_MAX_10_EXP__ 308
// PPC603E:#define __DBL_MAX_EXP__ 1024
// PPC603E:#define __DBL_MAX__ 1.7976931348623157e+308
// PPC603E:#define __DBL_MIN_10_EXP__ (-307)
// PPC603E:#define __DBL_MIN_EXP__ (-1021)
// PPC603E:#define __DBL_MIN__ 2.2250738585072014e-308
// PPC603E:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// PPC603E:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC603E:#define __FLT_DIG__ 6
// PPC603E:#define __FLT_EPSILON__ 1.19209290e-7F
// PPC603E:#define __FLT_EVAL_METHOD__ 0
// PPC603E:#define __FLT_HAS_DENORM__ 1
// PPC603E:#define __FLT_HAS_INFINITY__ 1
// PPC603E:#define __FLT_HAS_QUIET_NAN__ 1
// PPC603E:#define __FLT_MANT_DIG__ 24
// PPC603E:#define __FLT_MAX_10_EXP__ 38
// PPC603E:#define __FLT_MAX_EXP__ 128
// PPC603E:#define __FLT_MAX__ 3.40282347e+38F
// PPC603E:#define __FLT_MIN_10_EXP__ (-37)
// PPC603E:#define __FLT_MIN_EXP__ (-125)
// PPC603E:#define __FLT_MIN__ 1.17549435e-38F
// PPC603E:#define __FLT_RADIX__ 2
// PPC603E:#define __INT16_C_SUFFIX__
// PPC603E:#define __INT16_FMTd__ "hd"
// PPC603E:#define __INT16_FMTi__ "hi"
// PPC603E:#define __INT16_MAX__ 32767
// PPC603E:#define __INT16_TYPE__ short
// PPC603E:#define __INT32_C_SUFFIX__
// PPC603E:#define __INT32_FMTd__ "d"
// PPC603E:#define __INT32_FMTi__ "i"
// PPC603E:#define __INT32_MAX__ 2147483647
// PPC603E:#define __INT32_TYPE__ int
// PPC603E:#define __INT64_C_SUFFIX__ LL
// PPC603E:#define __INT64_FMTd__ "lld"
// PPC603E:#define __INT64_FMTi__ "lli"
// PPC603E:#define __INT64_MAX__ 9223372036854775807LL
// PPC603E:#define __INT64_TYPE__ long long int
// PPC603E:#define __INT8_C_SUFFIX__
// PPC603E:#define __INT8_FMTd__ "hhd"
// PPC603E:#define __INT8_FMTi__ "hhi"
// PPC603E:#define __INT8_MAX__ 127
// PPC603E:#define __INT8_TYPE__ signed char
// PPC603E:#define __INTMAX_C_SUFFIX__ LL
// PPC603E:#define __INTMAX_FMTd__ "lld"
// PPC603E:#define __INTMAX_FMTi__ "lli"
// PPC603E:#define __INTMAX_MAX__ 9223372036854775807LL
// PPC603E:#define __INTMAX_TYPE__ long long int
// PPC603E:#define __INTMAX_WIDTH__ 64
// PPC603E:#define __INTPTR_FMTd__ "ld"
// PPC603E:#define __INTPTR_FMTi__ "li"
// PPC603E:#define __INTPTR_MAX__ 2147483647L
// PPC603E:#define __INTPTR_TYPE__ long int
// PPC603E:#define __INTPTR_WIDTH__ 32
// PPC603E:#define __INT_FAST16_FMTd__ "hd"
// PPC603E:#define __INT_FAST16_FMTi__ "hi"
// PPC603E:#define __INT_FAST16_MAX__ 32767
// PPC603E:#define __INT_FAST16_TYPE__ short
// PPC603E:#define __INT_FAST32_FMTd__ "d"
// PPC603E:#define __INT_FAST32_FMTi__ "i"
// PPC603E:#define __INT_FAST32_MAX__ 2147483647
// PPC603E:#define __INT_FAST32_TYPE__ int
// PPC603E:#define __INT_FAST64_FMTd__ "lld"
// PPC603E:#define __INT_FAST64_FMTi__ "lli"
// PPC603E:#define __INT_FAST64_MAX__ 9223372036854775807LL
// PPC603E:#define __INT_FAST64_TYPE__ long long int
// PPC603E:#define __INT_FAST8_FMTd__ "hhd"
// PPC603E:#define __INT_FAST8_FMTi__ "hhi"
// PPC603E:#define __INT_FAST8_MAX__ 127
// PPC603E:#define __INT_FAST8_TYPE__ signed char
// PPC603E:#define __INT_LEAST16_FMTd__ "hd"
// PPC603E:#define __INT_LEAST16_FMTi__ "hi"
// PPC603E:#define __INT_LEAST16_MAX__ 32767
// PPC603E:#define __INT_LEAST16_TYPE__ short
// PPC603E:#define __INT_LEAST32_FMTd__ "d"
// PPC603E:#define __INT_LEAST32_FMTi__ "i"
// PPC603E:#define __INT_LEAST32_MAX__ 2147483647
// PPC603E:#define __INT_LEAST32_TYPE__ int
// PPC603E:#define __INT_LEAST64_FMTd__ "lld"
// PPC603E:#define __INT_LEAST64_FMTi__ "lli"
// PPC603E:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// PPC603E:#define __INT_LEAST64_TYPE__ long long int
// PPC603E:#define __INT_LEAST8_FMTd__ "hhd"
// PPC603E:#define __INT_LEAST8_FMTi__ "hhi"
// PPC603E:#define __INT_LEAST8_MAX__ 127
// PPC603E:#define __INT_LEAST8_TYPE__ signed char
// PPC603E:#define __INT_MAX__ 2147483647
// PPC603E:#define __LDBL_DENORM_MIN__ 4.94065645841246544176568792868221e-324L
// PPC603E:#define __LDBL_DIG__ 31
// PPC603E:#define __LDBL_EPSILON__ 4.94065645841246544176568792868221e-324L
// PPC603E:#define __LDBL_HAS_DENORM__ 1
// PPC603E:#define __LDBL_HAS_INFINITY__ 1
// PPC603E:#define __LDBL_HAS_QUIET_NAN__ 1
// PPC603E:#define __LDBL_MANT_DIG__ 106
// PPC603E:#define __LDBL_MAX_10_EXP__ 308
// PPC603E:#define __LDBL_MAX_EXP__ 1024
// PPC603E:#define __LDBL_MAX__ 1.79769313486231580793728971405301e+308L
// PPC603E:#define __LDBL_MIN_10_EXP__ (-291)
// PPC603E:#define __LDBL_MIN_EXP__ (-968)
// PPC603E:#define __LDBL_MIN__ 2.00416836000897277799610805135016e-292L
// PPC603E:#define __LONGDOUBLE128 1
// PPC603E:#define __LONG_DOUBLE_128__ 1
// PPC603E:#define __LONG_LONG_MAX__ 9223372036854775807LL
// PPC603E:#define __LONG_MAX__ 2147483647L
// PPC603E-NOT:#define __LP64__
// PPC603E:#define __NATURAL_ALIGNMENT__ 1
// PPC603E:#define __POINTER_WIDTH__ 32
// PPC603E:#define __POWERPC__ 1
// PPC603E:#define __PPC__ 1
// PPC603E:#define __PTRDIFF_TYPE__ long int
// PPC603E:#define __PTRDIFF_WIDTH__ 32
// PPC603E:#define __REGISTER_PREFIX__
// PPC603E:#define __SCHAR_MAX__ 127
// PPC603E:#define __SHRT_MAX__ 32767
// PPC603E:#define __SIG_ATOMIC_MAX__ 2147483647
// PPC603E:#define __SIG_ATOMIC_WIDTH__ 32
// PPC603E:#define __SIZEOF_DOUBLE__ 8
// PPC603E:#define __SIZEOF_FLOAT__ 4
// PPC603E:#define __SIZEOF_INT__ 4
// PPC603E:#define __SIZEOF_LONG_DOUBLE__ 16
// PPC603E:#define __SIZEOF_LONG_LONG__ 8
// PPC603E:#define __SIZEOF_LONG__ 4
// PPC603E:#define __SIZEOF_POINTER__ 4
// PPC603E:#define __SIZEOF_PTRDIFF_T__ 4
// PPC603E:#define __SIZEOF_SHORT__ 2
// PPC603E:#define __SIZEOF_SIZE_T__ 4
// PPC603E:#define __SIZEOF_WCHAR_T__ 4
// PPC603E:#define __SIZEOF_WINT_T__ 4
// PPC603E:#define __SIZE_MAX__ 4294967295UL
// PPC603E:#define __SIZE_TYPE__ long unsigned int
// PPC603E:#define __SIZE_WIDTH__ 32
// PPC603E-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL
// PPC603E:#define __UINT16_C_SUFFIX__
// PPC603E:#define __UINT16_MAX__ 65535
// PPC603E:#define __UINT16_TYPE__ unsigned short
// PPC603E:#define __UINT32_C_SUFFIX__ U
// PPC603E:#define __UINT32_MAX__ 4294967295U
// PPC603E:#define __UINT32_TYPE__ unsigned int
// PPC603E:#define __UINT64_C_SUFFIX__ ULL
// PPC603E:#define __UINT64_MAX__ 18446744073709551615ULL
// PPC603E:#define __UINT64_TYPE__ long long unsigned int
// PPC603E:#define __UINT8_C_SUFFIX__
// PPC603E:#define __UINT8_MAX__ 255
// PPC603E:#define __UINT8_TYPE__ unsigned char
// PPC603E:#define __UINTMAX_C_SUFFIX__ ULL
// PPC603E:#define __UINTMAX_MAX__ 18446744073709551615ULL
// PPC603E:#define __UINTMAX_TYPE__ long long unsigned int
// PPC603E:#define __UINTMAX_WIDTH__ 64
// PPC603E:#define __UINTPTR_MAX__ 4294967295UL
// PPC603E:#define __UINTPTR_TYPE__ long unsigned int
// PPC603E:#define __UINTPTR_WIDTH__ 32
// PPC603E:#define __UINT_FAST16_MAX__ 65535
// PPC603E:#define __UINT_FAST16_TYPE__ unsigned short
// PPC603E:#define __UINT_FAST32_MAX__ 4294967295U
// PPC603E:#define __UINT_FAST32_TYPE__ unsigned int
// PPC603E:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// PPC603E:#define __UINT_FAST64_TYPE__ long long unsigned int
// PPC603E:#define __UINT_FAST8_MAX__ 255
// PPC603E:#define __UINT_FAST8_TYPE__ unsigned char
// PPC603E:#define __UINT_LEAST16_MAX__ 65535
// PPC603E:#define __UINT_LEAST16_TYPE__ unsigned short
// PPC603E:#define __UINT_LEAST32_MAX__ 4294967295U
// PPC603E:#define __UINT_LEAST32_TYPE__ unsigned int
// PPC603E:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// PPC603E:#define __UINT_LEAST64_TYPE__ long long unsigned int
// PPC603E:#define __UINT_LEAST8_MAX__ 255
// PPC603E:#define __UINT_LEAST8_TYPE__ unsigned char
// PPC603E:#define __USER_LABEL_PREFIX__
// PPC603E:#define __WCHAR_MAX__ 2147483647
// PPC603E:#define __WCHAR_TYPE__ int
// PPC603E:#define __WCHAR_WIDTH__ 32
// PPC603E:#define __WINT_TYPE__ int
// PPC603E:#define __WINT_WIDTH__ 32
// PPC603E:#define __powerpc__ 1
// PPC603E:#define __ppc__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr7 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPC64 %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr7 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPC64 -check-prefix PPC64-CXX %s
//
// PPC64:#define _ARCH_PPC 1
// PPC64:#define _ARCH_PPC64 1
// PPC64:#define _ARCH_PPCGR 1
// PPC64:#define _ARCH_PPCSQ 1
// PPC64:#define _ARCH_PWR4 1
// PPC64:#define _ARCH_PWR5 1
// PPC64:#define _ARCH_PWR6 1
// PPC64:#define _ARCH_PWR7 1
// PPC64:#define _BIG_ENDIAN 1
// PPC64:#define _LP64 1
// PPC64:#define __BIGGEST_ALIGNMENT__ 16
// PPC64:#define __BIG_ENDIAN__ 1
// PPC64:#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
// PPC64:#define __CHAR16_TYPE__ unsigned short
// PPC64:#define __CHAR32_TYPE__ unsigned int
// PPC64:#define __CHAR_BIT__ 8
// PPC64:#define __CHAR_UNSIGNED__ 1
// PPC64:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// PPC64:#define __DBL_DIG__ 15
// PPC64:#define __DBL_EPSILON__ 2.2204460492503131e-16
// PPC64:#define __DBL_HAS_DENORM__ 1
// PPC64:#define __DBL_HAS_INFINITY__ 1
// PPC64:#define __DBL_HAS_QUIET_NAN__ 1
// PPC64:#define __DBL_MANT_DIG__ 53
// PPC64:#define __DBL_MAX_10_EXP__ 308
// PPC64:#define __DBL_MAX_EXP__ 1024
// PPC64:#define __DBL_MAX__ 1.7976931348623157e+308
// PPC64:#define __DBL_MIN_10_EXP__ (-307)
// PPC64:#define __DBL_MIN_EXP__ (-1021)
// PPC64:#define __DBL_MIN__ 2.2250738585072014e-308
// PPC64:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// PPC64:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC64:#define __FLT_DIG__ 6
// PPC64:#define __FLT_EPSILON__ 1.19209290e-7F
// PPC64:#define __FLT_EVAL_METHOD__ 0
// PPC64:#define __FLT_HAS_DENORM__ 1
// PPC64:#define __FLT_HAS_INFINITY__ 1
// PPC64:#define __FLT_HAS_QUIET_NAN__ 1
// PPC64:#define __FLT_MANT_DIG__ 24
// PPC64:#define __FLT_MAX_10_EXP__ 38
// PPC64:#define __FLT_MAX_EXP__ 128
// PPC64:#define __FLT_MAX__ 3.40282347e+38F
// PPC64:#define __FLT_MIN_10_EXP__ (-37)
// PPC64:#define __FLT_MIN_EXP__ (-125)
// PPC64:#define __FLT_MIN__ 1.17549435e-38F
// PPC64:#define __FLT_RADIX__ 2
// PPC64:#define __HAVE_BSWAP__ 1
// PPC64:#define __INT16_C_SUFFIX__
// PPC64:#define __INT16_FMTd__ "hd"
// PPC64:#define __INT16_FMTi__ "hi"
// PPC64:#define __INT16_MAX__ 32767
// PPC64:#define __INT16_TYPE__ short
// PPC64:#define __INT32_C_SUFFIX__
// PPC64:#define __INT32_FMTd__ "d"
// PPC64:#define __INT32_FMTi__ "i"
// PPC64:#define __INT32_MAX__ 2147483647
// PPC64:#define __INT32_TYPE__ int
// PPC64:#define __INT64_C_SUFFIX__ L
// PPC64:#define __INT64_FMTd__ "ld"
// PPC64:#define __INT64_FMTi__ "li"
// PPC64:#define __INT64_MAX__ 9223372036854775807L
// PPC64:#define __INT64_TYPE__ long int
// PPC64:#define __INT8_C_SUFFIX__
// PPC64:#define __INT8_FMTd__ "hhd"
// PPC64:#define __INT8_FMTi__ "hhi"
// PPC64:#define __INT8_MAX__ 127
// PPC64:#define __INT8_TYPE__ signed char
// PPC64:#define __INTMAX_C_SUFFIX__ L
// PPC64:#define __INTMAX_FMTd__ "ld"
// PPC64:#define __INTMAX_FMTi__ "li"
// PPC64:#define __INTMAX_MAX__ 9223372036854775807L
// PPC64:#define __INTMAX_TYPE__ long int
// PPC64:#define __INTMAX_WIDTH__ 64
// PPC64:#define __INTPTR_FMTd__ "ld"
// PPC64:#define __INTPTR_FMTi__ "li"
// PPC64:#define __INTPTR_MAX__ 9223372036854775807L
// PPC64:#define __INTPTR_TYPE__ long int
// PPC64:#define __INTPTR_WIDTH__ 64
// PPC64:#define __INT_FAST16_FMTd__ "hd"
// PPC64:#define __INT_FAST16_FMTi__ "hi"
// PPC64:#define __INT_FAST16_MAX__ 32767
// PPC64:#define __INT_FAST16_TYPE__ short
// PPC64:#define __INT_FAST32_FMTd__ "d"
// PPC64:#define __INT_FAST32_FMTi__ "i"
// PPC64:#define __INT_FAST32_MAX__ 2147483647
// PPC64:#define __INT_FAST32_TYPE__ int
// PPC64:#define __INT_FAST64_FMTd__ "ld"
// PPC64:#define __INT_FAST64_FMTi__ "li"
// PPC64:#define __INT_FAST64_MAX__ 9223372036854775807L
// PPC64:#define __INT_FAST64_TYPE__ long int
// PPC64:#define __INT_FAST8_FMTd__ "hhd"
// PPC64:#define __INT_FAST8_FMTi__ "hhi"
// PPC64:#define __INT_FAST8_MAX__ 127
// PPC64:#define __INT_FAST8_TYPE__ signed char
// PPC64:#define __INT_LEAST16_FMTd__ "hd"
// PPC64:#define __INT_LEAST16_FMTi__ "hi"
// PPC64:#define __INT_LEAST16_MAX__ 32767
// PPC64:#define __INT_LEAST16_TYPE__ short
// PPC64:#define __INT_LEAST32_FMTd__ "d"
// PPC64:#define __INT_LEAST32_FMTi__ "i"
// PPC64:#define __INT_LEAST32_MAX__ 2147483647
// PPC64:#define __INT_LEAST32_TYPE__ int
// PPC64:#define __INT_LEAST64_FMTd__ "ld"
// PPC64:#define __INT_LEAST64_FMTi__ "li"
// PPC64:#define __INT_LEAST64_MAX__ 9223372036854775807L
// PPC64:#define __INT_LEAST64_TYPE__ long int
// PPC64:#define __INT_LEAST8_FMTd__ "hhd"
// PPC64:#define __INT_LEAST8_FMTi__ "hhi"
// PPC64:#define __INT_LEAST8_MAX__ 127
// PPC64:#define __INT_LEAST8_TYPE__ signed char
// PPC64:#define __INT_MAX__ 2147483647
// PPC64:#define __LDBL_DENORM_MIN__ 4.94065645841246544176568792868221e-324L
// PPC64:#define __LDBL_DIG__ 31
// PPC64:#define __LDBL_EPSILON__ 4.94065645841246544176568792868221e-324L
// PPC64:#define __LDBL_HAS_DENORM__ 1
// PPC64:#define __LDBL_HAS_INFINITY__ 1
// PPC64:#define __LDBL_HAS_QUIET_NAN__ 1
// PPC64:#define __LDBL_MANT_DIG__ 106
// PPC64:#define __LDBL_MAX_10_EXP__ 308
// PPC64:#define __LDBL_MAX_EXP__ 1024
// PPC64:#define __LDBL_MAX__ 1.79769313486231580793728971405301e+308L
// PPC64:#define __LDBL_MIN_10_EXP__ (-291)
// PPC64:#define __LDBL_MIN_EXP__ (-968)
// PPC64:#define __LDBL_MIN__ 2.00416836000897277799610805135016e-292L
// PPC64:#define __LONGDOUBLE128 1
// PPC64:#define __LONG_DOUBLE_128__ 1
// PPC64:#define __LONG_LONG_MAX__ 9223372036854775807LL
// PPC64:#define __LONG_MAX__ 9223372036854775807L
// PPC64:#define __LP64__ 1
// PPC64:#define __NATURAL_ALIGNMENT__ 1
// PPC64:#define __POINTER_WIDTH__ 64
// PPC64:#define __POWERPC__ 1
// PPC64:#define __PPC64__ 1
// PPC64:#define __PPC__ 1
// PPC64:#define __PTRDIFF_TYPE__ long int
// PPC64:#define __PTRDIFF_WIDTH__ 64
// PPC64:#define __REGISTER_PREFIX__
// PPC64:#define __SCHAR_MAX__ 127
// PPC64:#define __SHRT_MAX__ 32767
// PPC64:#define __SIG_ATOMIC_MAX__ 2147483647
// PPC64:#define __SIG_ATOMIC_WIDTH__ 32
// PPC64:#define __SIZEOF_DOUBLE__ 8
// PPC64:#define __SIZEOF_FLOAT__ 4
// PPC64:#define __SIZEOF_INT__ 4
// PPC64:#define __SIZEOF_LONG_DOUBLE__ 16
// PPC64:#define __SIZEOF_LONG_LONG__ 8
// PPC64:#define __SIZEOF_LONG__ 8
// PPC64:#define __SIZEOF_POINTER__ 8
// PPC64:#define __SIZEOF_PTRDIFF_T__ 8
// PPC64:#define __SIZEOF_SHORT__ 2
// PPC64:#define __SIZEOF_SIZE_T__ 8
// PPC64:#define __SIZEOF_WCHAR_T__ 4
// PPC64:#define __SIZEOF_WINT_T__ 4
// PPC64:#define __SIZE_MAX__ 18446744073709551615UL
// PPC64:#define __SIZE_TYPE__ long unsigned int
// PPC64:#define __SIZE_WIDTH__ 64
// PPC64-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL
// PPC64:#define __UINT16_C_SUFFIX__
// PPC64:#define __UINT16_MAX__ 65535
// PPC64:#define __UINT16_TYPE__ unsigned short
// PPC64:#define __UINT32_C_SUFFIX__ U
// PPC64:#define __UINT32_MAX__ 4294967295U
// PPC64:#define __UINT32_TYPE__ unsigned int
// PPC64:#define __UINT64_C_SUFFIX__ UL
// PPC64:#define __UINT64_MAX__ 18446744073709551615UL
// PPC64:#define __UINT64_TYPE__ long unsigned int
// PPC64:#define __UINT8_C_SUFFIX__
// PPC64:#define __UINT8_MAX__ 255
// PPC64:#define __UINT8_TYPE__ unsigned char
// PPC64:#define __UINTMAX_C_SUFFIX__ UL
// PPC64:#define __UINTMAX_MAX__ 18446744073709551615UL
// PPC64:#define __UINTMAX_TYPE__ long unsigned int
// PPC64:#define __UINTMAX_WIDTH__ 64
// PPC64:#define __UINTPTR_MAX__ 18446744073709551615UL
// PPC64:#define __UINTPTR_TYPE__ long unsigned int
// PPC64:#define __UINTPTR_WIDTH__ 64
// PPC64:#define __UINT_FAST16_MAX__ 65535
// PPC64:#define __UINT_FAST16_TYPE__ unsigned short
// PPC64:#define __UINT_FAST32_MAX__ 4294967295U
// PPC64:#define __UINT_FAST32_TYPE__ unsigned int
// PPC64:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// PPC64:#define __UINT_FAST64_TYPE__ long unsigned int
// PPC64:#define __UINT_FAST8_MAX__ 255
// PPC64:#define __UINT_FAST8_TYPE__ unsigned char
// PPC64:#define __UINT_LEAST16_MAX__ 65535
// PPC64:#define __UINT_LEAST16_TYPE__ unsigned short
// PPC64:#define __UINT_LEAST32_MAX__ 4294967295U
// PPC64:#define __UINT_LEAST32_TYPE__ unsigned int
// PPC64:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// PPC64:#define __UINT_LEAST64_TYPE__ long unsigned int
// PPC64:#define __UINT_LEAST8_MAX__ 255
// PPC64:#define __UINT_LEAST8_TYPE__ unsigned char
// PPC64:#define __USER_LABEL_PREFIX__
// PPC64:#define __WCHAR_MAX__ 2147483647
// PPC64:#define __WCHAR_TYPE__ int
// PPC64:#define __WCHAR_WIDTH__ 32
// PPC64:#define __WINT_TYPE__ int
// PPC64:#define __WINT_WIDTH__ 32
// PPC64:#define __ppc64__ 1
// PPC64:#define __ppc__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64le-none-none -target-cpu pwr7 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPC64LE %s
//
// PPC64LE:#define _ARCH_PPC 1
// PPC64LE:#define _ARCH_PPC64 1
// PPC64LE:#define _ARCH_PPCGR 1
// PPC64LE:#define _ARCH_PPCSQ 1
// PPC64LE:#define _ARCH_PWR4 1
// PPC64LE:#define _ARCH_PWR5 1
// PPC64LE:#define _ARCH_PWR5X 1
// PPC64LE:#define _ARCH_PWR6 1
// PPC64LE:#define _ARCH_PWR6X 1
// PPC64LE:#define _ARCH_PWR7 1
// PPC64LE:#define _CALL_ELF 2
// PPC64LE:#define _LITTLE_ENDIAN 1
// PPC64LE:#define _LP64 1
// PPC64LE:#define __BIGGEST_ALIGNMENT__ 16
// PPC64LE:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// PPC64LE:#define __CHAR16_TYPE__ unsigned short
// PPC64LE:#define __CHAR32_TYPE__ unsigned int
// PPC64LE:#define __CHAR_BIT__ 8
// PPC64LE:#define __CHAR_UNSIGNED__ 1
// PPC64LE:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// PPC64LE:#define __DBL_DIG__ 15
// PPC64LE:#define __DBL_EPSILON__ 2.2204460492503131e-16
// PPC64LE:#define __DBL_HAS_DENORM__ 1
// PPC64LE:#define __DBL_HAS_INFINITY__ 1
// PPC64LE:#define __DBL_HAS_QUIET_NAN__ 1
// PPC64LE:#define __DBL_MANT_DIG__ 53
// PPC64LE:#define __DBL_MAX_10_EXP__ 308
// PPC64LE:#define __DBL_MAX_EXP__ 1024
// PPC64LE:#define __DBL_MAX__ 1.7976931348623157e+308
// PPC64LE:#define __DBL_MIN_10_EXP__ (-307)
// PPC64LE:#define __DBL_MIN_EXP__ (-1021)
// PPC64LE:#define __DBL_MIN__ 2.2250738585072014e-308
// PPC64LE:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// PPC64LE:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC64LE:#define __FLT_DIG__ 6
// PPC64LE:#define __FLT_EPSILON__ 1.19209290e-7F
// PPC64LE:#define __FLT_EVAL_METHOD__ 0
// PPC64LE:#define __FLT_HAS_DENORM__ 1
// PPC64LE:#define __FLT_HAS_INFINITY__ 1
// PPC64LE:#define __FLT_HAS_QUIET_NAN__ 1
// PPC64LE:#define __FLT_MANT_DIG__ 24
// PPC64LE:#define __FLT_MAX_10_EXP__ 38
// PPC64LE:#define __FLT_MAX_EXP__ 128
// PPC64LE:#define __FLT_MAX__ 3.40282347e+38F
// PPC64LE:#define __FLT_MIN_10_EXP__ (-37)
// PPC64LE:#define __FLT_MIN_EXP__ (-125)
// PPC64LE:#define __FLT_MIN__ 1.17549435e-38F
// PPC64LE:#define __FLT_RADIX__ 2
// PPC64LE:#define __HAVE_BSWAP__ 1
// PPC64LE:#define __INT16_C_SUFFIX__
// PPC64LE:#define __INT16_FMTd__ "hd"
// PPC64LE:#define __INT16_FMTi__ "hi"
// PPC64LE:#define __INT16_MAX__ 32767
// PPC64LE:#define __INT16_TYPE__ short
// PPC64LE:#define __INT32_C_SUFFIX__
// PPC64LE:#define __INT32_FMTd__ "d"
// PPC64LE:#define __INT32_FMTi__ "i"
// PPC64LE:#define __INT32_MAX__ 2147483647
// PPC64LE:#define __INT32_TYPE__ int
// PPC64LE:#define __INT64_C_SUFFIX__ L
// PPC64LE:#define __INT64_FMTd__ "ld"
// PPC64LE:#define __INT64_FMTi__ "li"
// PPC64LE:#define __INT64_MAX__ 9223372036854775807L
// PPC64LE:#define __INT64_TYPE__ long int
// PPC64LE:#define __INT8_C_SUFFIX__
// PPC64LE:#define __INT8_FMTd__ "hhd"
// PPC64LE:#define __INT8_FMTi__ "hhi"
// PPC64LE:#define __INT8_MAX__ 127
// PPC64LE:#define __INT8_TYPE__ signed char
// PPC64LE:#define __INTMAX_C_SUFFIX__ L
// PPC64LE:#define __INTMAX_FMTd__ "ld"
// PPC64LE:#define __INTMAX_FMTi__ "li"
// PPC64LE:#define __INTMAX_MAX__ 9223372036854775807L
// PPC64LE:#define __INTMAX_TYPE__ long int
// PPC64LE:#define __INTMAX_WIDTH__ 64
// PPC64LE:#define __INTPTR_FMTd__ "ld"
// PPC64LE:#define __INTPTR_FMTi__ "li"
// PPC64LE:#define __INTPTR_MAX__ 9223372036854775807L
// PPC64LE:#define __INTPTR_TYPE__ long int
// PPC64LE:#define __INTPTR_WIDTH__ 64
// PPC64LE:#define __INT_FAST16_FMTd__ "hd"
// PPC64LE:#define __INT_FAST16_FMTi__ "hi"
// PPC64LE:#define __INT_FAST16_MAX__ 32767
// PPC64LE:#define __INT_FAST16_TYPE__ short
// PPC64LE:#define __INT_FAST32_FMTd__ "d"
// PPC64LE:#define __INT_FAST32_FMTi__ "i"
// PPC64LE:#define __INT_FAST32_MAX__ 2147483647
// PPC64LE:#define __INT_FAST32_TYPE__ int
// PPC64LE:#define __INT_FAST64_FMTd__ "ld"
// PPC64LE:#define __INT_FAST64_FMTi__ "li"
// PPC64LE:#define __INT_FAST64_MAX__ 9223372036854775807L
// PPC64LE:#define __INT_FAST64_TYPE__ long int
// PPC64LE:#define __INT_FAST8_FMTd__ "hhd"
// PPC64LE:#define __INT_FAST8_FMTi__ "hhi"
// PPC64LE:#define __INT_FAST8_MAX__ 127
// PPC64LE:#define __INT_FAST8_TYPE__ signed char
// PPC64LE:#define __INT_LEAST16_FMTd__ "hd"
// PPC64LE:#define __INT_LEAST16_FMTi__ "hi"
// PPC64LE:#define __INT_LEAST16_MAX__ 32767
// PPC64LE:#define __INT_LEAST16_TYPE__ short
// PPC64LE:#define __INT_LEAST32_FMTd__ "d"
// PPC64LE:#define __INT_LEAST32_FMTi__ "i"
// PPC64LE:#define __INT_LEAST32_MAX__ 2147483647
// PPC64LE:#define __INT_LEAST32_TYPE__ int
// PPC64LE:#define __INT_LEAST64_FMTd__ "ld"
// PPC64LE:#define __INT_LEAST64_FMTi__ "li"
// PPC64LE:#define __INT_LEAST64_MAX__ 9223372036854775807L
// PPC64LE:#define __INT_LEAST64_TYPE__ long int
// PPC64LE:#define __INT_LEAST8_FMTd__ "hhd"
// PPC64LE:#define __INT_LEAST8_FMTi__ "hhi"
// PPC64LE:#define __INT_LEAST8_MAX__ 127
// PPC64LE:#define __INT_LEAST8_TYPE__ signed char
// PPC64LE:#define __INT_MAX__ 2147483647
// PPC64LE:#define __LDBL_DENORM_MIN__ 4.94065645841246544176568792868221e-324L
// PPC64LE:#define __LDBL_DIG__ 31
// PPC64LE:#define __LDBL_EPSILON__ 4.94065645841246544176568792868221e-324L
// PPC64LE:#define __LDBL_HAS_DENORM__ 1
// PPC64LE:#define __LDBL_HAS_INFINITY__ 1
// PPC64LE:#define __LDBL_HAS_QUIET_NAN__ 1
// PPC64LE:#define __LDBL_MANT_DIG__ 106
// PPC64LE:#define __LDBL_MAX_10_EXP__ 308
// PPC64LE:#define __LDBL_MAX_EXP__ 1024
// PPC64LE:#define __LDBL_MAX__ 1.79769313486231580793728971405301e+308L
// PPC64LE:#define __LDBL_MIN_10_EXP__ (-291)
// PPC64LE:#define __LDBL_MIN_EXP__ (-968)
// PPC64LE:#define __LDBL_MIN__ 2.00416836000897277799610805135016e-292L
// PPC64LE:#define __LITTLE_ENDIAN__ 1
// PPC64LE:#define __LONGDOUBLE128 1
// PPC64LE:#define __LONG_DOUBLE_128__ 1
// PPC64LE:#define __LONG_LONG_MAX__ 9223372036854775807LL
// PPC64LE:#define __LONG_MAX__ 9223372036854775807L
// PPC64LE:#define __LP64__ 1
// PPC64LE:#define __NATURAL_ALIGNMENT__ 1
// PPC64LE:#define __POINTER_WIDTH__ 64
// PPC64LE:#define __POWERPC__ 1
// PPC64LE:#define __PPC64__ 1
// PPC64LE:#define __PPC__ 1
// PPC64LE:#define __PTRDIFF_TYPE__ long int
// PPC64LE:#define __PTRDIFF_WIDTH__ 64
// PPC64LE:#define __REGISTER_PREFIX__
// PPC64LE:#define __SCHAR_MAX__ 127
// PPC64LE:#define __SHRT_MAX__ 32767
// PPC64LE:#define __SIG_ATOMIC_MAX__ 2147483647
// PPC64LE:#define __SIG_ATOMIC_WIDTH__ 32
// PPC64LE:#define __SIZEOF_DOUBLE__ 8
// PPC64LE:#define __SIZEOF_FLOAT__ 4
// PPC64LE:#define __SIZEOF_INT__ 4
// PPC64LE:#define __SIZEOF_LONG_DOUBLE__ 16
// PPC64LE:#define __SIZEOF_LONG_LONG__ 8
// PPC64LE:#define __SIZEOF_LONG__ 8
// PPC64LE:#define __SIZEOF_POINTER__ 8
// PPC64LE:#define __SIZEOF_PTRDIFF_T__ 8
// PPC64LE:#define __SIZEOF_SHORT__ 2
// PPC64LE:#define __SIZEOF_SIZE_T__ 8
// PPC64LE:#define __SIZEOF_WCHAR_T__ 4
// PPC64LE:#define __SIZEOF_WINT_T__ 4
// PPC64LE:#define __SIZE_MAX__ 18446744073709551615UL
// PPC64LE:#define __SIZE_TYPE__ long unsigned int
// PPC64LE:#define __SIZE_WIDTH__ 64
// PPC64LE:#define __STRUCT_PARM_ALIGN__ 16
// PPC64LE:#define __UINT16_C_SUFFIX__
// PPC64LE:#define __UINT16_MAX__ 65535
// PPC64LE:#define __UINT16_TYPE__ unsigned short
// PPC64LE:#define __UINT32_C_SUFFIX__ U
// PPC64LE:#define __UINT32_MAX__ 4294967295U
// PPC64LE:#define __UINT32_TYPE__ unsigned int
// PPC64LE:#define __UINT64_C_SUFFIX__ UL
// PPC64LE:#define __UINT64_MAX__ 18446744073709551615UL
// PPC64LE:#define __UINT64_TYPE__ long unsigned int
// PPC64LE:#define __UINT8_C_SUFFIX__
// PPC64LE:#define __UINT8_MAX__ 255
// PPC64LE:#define __UINT8_TYPE__ unsigned char
// PPC64LE:#define __UINTMAX_C_SUFFIX__ UL
// PPC64LE:#define __UINTMAX_MAX__ 18446744073709551615UL
// PPC64LE:#define __UINTMAX_TYPE__ long unsigned int
// PPC64LE:#define __UINTMAX_WIDTH__ 64
// PPC64LE:#define __UINTPTR_MAX__ 18446744073709551615UL
// PPC64LE:#define __UINTPTR_TYPE__ long unsigned int
// PPC64LE:#define __UINTPTR_WIDTH__ 64
// PPC64LE:#define __UINT_FAST16_MAX__ 65535
// PPC64LE:#define __UINT_FAST16_TYPE__ unsigned short
// PPC64LE:#define __UINT_FAST32_MAX__ 4294967295U
// PPC64LE:#define __UINT_FAST32_TYPE__ unsigned int
// PPC64LE:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// PPC64LE:#define __UINT_FAST64_TYPE__ long unsigned int
// PPC64LE:#define __UINT_FAST8_MAX__ 255
// PPC64LE:#define __UINT_FAST8_TYPE__ unsigned char
// PPC64LE:#define __UINT_LEAST16_MAX__ 65535
// PPC64LE:#define __UINT_LEAST16_TYPE__ unsigned short
// PPC64LE:#define __UINT_LEAST32_MAX__ 4294967295U
// PPC64LE:#define __UINT_LEAST32_TYPE__ unsigned int
// PPC64LE:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// PPC64LE:#define __UINT_LEAST64_TYPE__ long unsigned int
// PPC64LE:#define __UINT_LEAST8_MAX__ 255
// PPC64LE:#define __UINT_LEAST8_TYPE__ unsigned char
// PPC64LE:#define __USER_LABEL_PREFIX__
// PPC64LE:#define __WCHAR_MAX__ 2147483647
// PPC64LE:#define __WCHAR_TYPE__ int
// PPC64LE:#define __WCHAR_WIDTH__ 32
// PPC64LE:#define __WINT_TYPE__ int
// PPC64LE:#define __WINT_WIDTH__ 32
// PPC64LE:#define __ppc64__ 1
// PPC64LE:#define __ppc__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu a2q -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCA2Q %s
//
// PPCA2Q:#define _ARCH_A2 1
// PPCA2Q:#define _ARCH_A2Q 1
// PPCA2Q:#define _ARCH_PPC 1
// PPCA2Q:#define _ARCH_PPC64 1
// PPCA2Q:#define _ARCH_QP 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-bgq-linux -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCBGQ %s
//
// PPCBGQ:#define __THW_BLUEGENE__ 1
// PPCBGQ:#define __TOS_BGQ__ 1
// PPCBGQ:#define __bg__ 1
// PPCBGQ:#define __bgq__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu 630 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPC630 %s
//
// PPC630:#define _ARCH_630 1
// PPC630:#define _ARCH_PPC 1
// PPC630:#define _ARCH_PPC64 1
// PPC630:#define _ARCH_PPCGR 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr3 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPWR3 %s
//
// PPCPWR3:#define _ARCH_PPC 1
// PPCPWR3:#define _ARCH_PPC64 1
// PPCPWR3:#define _ARCH_PPCGR 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu power3 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPOWER3 %s
//
// PPCPOWER3:#define _ARCH_PPC 1
// PPCPOWER3:#define _ARCH_PPC64 1
// PPCPOWER3:#define _ARCH_PPCGR 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr4 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPWR4 %s
//
// PPCPWR4:#define _ARCH_PPC 1
// PPCPWR4:#define _ARCH_PPC64 1
// PPCPWR4:#define _ARCH_PPCGR 1
// PPCPWR4:#define _ARCH_PPCSQ 1
// PPCPWR4:#define _ARCH_PWR4 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu power4 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPOWER4 %s
//
// PPCPOWER4:#define _ARCH_PPC 1
// PPCPOWER4:#define _ARCH_PPC64 1
// PPCPOWER4:#define _ARCH_PPCGR 1
// PPCPOWER4:#define _ARCH_PPCSQ 1
// PPCPOWER4:#define _ARCH_PWR4 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr5 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPWR5 %s
//
// PPCPWR5:#define _ARCH_PPC 1
// PPCPWR5:#define _ARCH_PPC64 1
// PPCPWR5:#define _ARCH_PPCGR 1
// PPCPWR5:#define _ARCH_PPCSQ 1
// PPCPWR5:#define _ARCH_PWR4 1
// PPCPWR5:#define _ARCH_PWR5 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu power5 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPOWER5 %s
//
// PPCPOWER5:#define _ARCH_PPC 1
// PPCPOWER5:#define _ARCH_PPC64 1
// PPCPOWER5:#define _ARCH_PPCGR 1
// PPCPOWER5:#define _ARCH_PPCSQ 1
// PPCPOWER5:#define _ARCH_PWR4 1
// PPCPOWER5:#define _ARCH_PWR5 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr5x -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPWR5X %s
//
// PPCPWR5X:#define _ARCH_PPC 1
// PPCPWR5X:#define _ARCH_PPC64 1
// PPCPWR5X:#define _ARCH_PPCGR 1
// PPCPWR5X:#define _ARCH_PPCSQ 1
// PPCPWR5X:#define _ARCH_PWR4 1
// PPCPWR5X:#define _ARCH_PWR5 1
// PPCPWR5X:#define _ARCH_PWR5X 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu power5x -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPOWER5X %s
//
// PPCPOWER5X:#define _ARCH_PPC 1
// PPCPOWER5X:#define _ARCH_PPC64 1
// PPCPOWER5X:#define _ARCH_PPCGR 1
// PPCPOWER5X:#define _ARCH_PPCSQ 1
// PPCPOWER5X:#define _ARCH_PWR4 1
// PPCPOWER5X:#define _ARCH_PWR5 1
// PPCPOWER5X:#define _ARCH_PWR5X 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr6 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPWR6 %s
//
// PPCPWR6:#define _ARCH_PPC 1
// PPCPWR6:#define _ARCH_PPC64 1
// PPCPWR6:#define _ARCH_PPCGR 1
// PPCPWR6:#define _ARCH_PPCSQ 1
// PPCPWR6:#define _ARCH_PWR4 1
// PPCPWR6:#define _ARCH_PWR5 1
// PPCPWR6:#define _ARCH_PWR5X 1
// PPCPWR6:#define _ARCH_PWR6 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu power6 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPOWER6 %s
//
// PPCPOWER6:#define _ARCH_PPC 1
// PPCPOWER6:#define _ARCH_PPC64 1
// PPCPOWER6:#define _ARCH_PPCGR 1
// PPCPOWER6:#define _ARCH_PPCSQ 1
// PPCPOWER6:#define _ARCH_PWR4 1
// PPCPOWER6:#define _ARCH_PWR5 1
// PPCPOWER6:#define _ARCH_PWR5X 1
// PPCPOWER6:#define _ARCH_PWR6 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr6x -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPWR6X %s
//
// PPCPWR6X:#define _ARCH_PPC 1
// PPCPWR6X:#define _ARCH_PPC64 1
// PPCPWR6X:#define _ARCH_PPCGR 1
// PPCPWR6X:#define _ARCH_PPCSQ 1
// PPCPWR6X:#define _ARCH_PWR4 1
// PPCPWR6X:#define _ARCH_PWR5 1
// PPCPWR6X:#define _ARCH_PWR5X 1
// PPCPWR6X:#define _ARCH_PWR6 1
// PPCPWR6X:#define _ARCH_PWR6X 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu power6x -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPOWER6X %s
//
// PPCPOWER6X:#define _ARCH_PPC 1
// PPCPOWER6X:#define _ARCH_PPC64 1
// PPCPOWER6X:#define _ARCH_PPCGR 1
// PPCPOWER6X:#define _ARCH_PPCSQ 1
// PPCPOWER6X:#define _ARCH_PWR4 1
// PPCPOWER6X:#define _ARCH_PWR5 1
// PPCPOWER6X:#define _ARCH_PWR5X 1
// PPCPOWER6X:#define _ARCH_PWR6 1
// PPCPOWER6X:#define _ARCH_PWR6X 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr7 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPWR7 %s
//
// PPCPWR7:#define _ARCH_PPC 1
// PPCPWR7:#define _ARCH_PPC64 1
// PPCPWR7:#define _ARCH_PPCGR 1
// PPCPWR7:#define _ARCH_PPCSQ 1
// PPCPWR7:#define _ARCH_PWR4 1
// PPCPWR7:#define _ARCH_PWR5 1
// PPCPWR7:#define _ARCH_PWR5X 1
// PPCPWR7:#define _ARCH_PWR6 1
// PPCPWR7:#define _ARCH_PWR6X 1
// PPCPWR7:#define _ARCH_PWR7 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu power7 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPOWER7 %s
//
// PPCPOWER7:#define _ARCH_PPC 1
// PPCPOWER7:#define _ARCH_PPC64 1
// PPCPOWER7:#define _ARCH_PPCGR 1
// PPCPOWER7:#define _ARCH_PPCSQ 1
// PPCPOWER7:#define _ARCH_PWR4 1
// PPCPOWER7:#define _ARCH_PWR5 1
// PPCPOWER7:#define _ARCH_PWR5X 1
// PPCPOWER7:#define _ARCH_PWR6 1
// PPCPOWER7:#define _ARCH_PWR6X 1
// PPCPOWER7:#define _ARCH_PWR7 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr8 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPWR8 %s
//
// PPCPWR8:#define _ARCH_PPC 1
// PPCPWR8:#define _ARCH_PPC64 1
// PPCPWR8:#define _ARCH_PPCGR 1
// PPCPWR8:#define _ARCH_PPCSQ 1
// PPCPWR8:#define _ARCH_PWR4 1
// PPCPWR8:#define _ARCH_PWR5 1
// PPCPWR8:#define _ARCH_PWR5X 1
// PPCPWR8:#define _ARCH_PWR6 1
// PPCPWR8:#define _ARCH_PWR6X 1
// PPCPWR8:#define _ARCH_PWR7 1
// PPCPWR8:#define _ARCH_PWR8 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu power8 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPOWER8 %s
//
// ppc64le also defaults to power8.
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64le-none-none -target-cpu ppc64le -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPOWER8 %s
//
// PPCPOWER8:#define _ARCH_PPC 1
// PPCPOWER8:#define _ARCH_PPC64 1
// PPCPOWER8:#define _ARCH_PPCGR 1
// PPCPOWER8:#define _ARCH_PPCSQ 1
// PPCPOWER8:#define _ARCH_PWR4 1
// PPCPOWER8:#define _ARCH_PWR5 1
// PPCPOWER8:#define _ARCH_PWR5X 1
// PPCPOWER8:#define _ARCH_PWR6 1
// PPCPOWER8:#define _ARCH_PWR6X 1
// PPCPOWER8:#define _ARCH_PWR7 1
// PPCPOWER8:#define _ARCH_PWR8 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu pwr9 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPWR9 %s
//
// PPCPWR9:#define _ARCH_PPC 1
// PPCPWR9:#define _ARCH_PPC64 1
// PPCPWR9:#define _ARCH_PPCGR 1
// PPCPWR9:#define _ARCH_PPCSQ 1
// PPCPWR9:#define _ARCH_PWR4 1
// PPCPWR9:#define _ARCH_PWR5 1
// PPCPWR9:#define _ARCH_PWR5X 1
// PPCPWR9:#define _ARCH_PWR6 1
// PPCPWR9:#define _ARCH_PWR6X 1
// PPCPWR9:#define _ARCH_PWR7 1
// PPCPWR9:#define _ARCH_PWR9 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-cpu power9 -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPCPOWER9 %s
//
// PPCPOWER9:#define _ARCH_PPC 1
// PPCPOWER9:#define _ARCH_PPC64 1
// PPCPOWER9:#define _ARCH_PPCGR 1
// PPCPOWER9:#define _ARCH_PPCSQ 1
// PPCPOWER9:#define _ARCH_PWR4 1
// PPCPOWER9:#define _ARCH_PWR5 1
// PPCPOWER9:#define _ARCH_PWR5X 1
// PPCPOWER9:#define _ARCH_PWR6 1
// PPCPOWER9:#define _ARCH_PWR6X 1
// PPCPOWER9:#define _ARCH_PWR7 1
// PPCPOWER9:#define _ARCH_PWR9 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-none-none -target-feature +float128 -target-cpu power9 -fno-signed-char < /dev/null | FileCheck -check-prefix PPC-FLOAT128 %s
// PPC-FLOAT128:#define __FLOAT128__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-linux-gnu -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-LINUX %s
//
// PPC64-LINUX:#define _ARCH_PPC 1
// PPC64-LINUX:#define _ARCH_PPC64 1
// PPC64-LINUX:#define _BIG_ENDIAN 1
// PPC64-LINUX:#define _CALL_LINUX 1
// PPC64-LINUX:#define _LP64 1
// PPC64-LINUX:#define __BIGGEST_ALIGNMENT__ 16
// PPC64-LINUX:#define __BIG_ENDIAN__ 1
// PPC64-LINUX:#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
// PPC64-LINUX:#define __CHAR16_TYPE__ unsigned short
// PPC64-LINUX:#define __CHAR32_TYPE__ unsigned int
// PPC64-LINUX:#define __CHAR_BIT__ 8
// PPC64-LINUX:#define __CHAR_UNSIGNED__ 1
// PPC64-LINUX:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// PPC64-LINUX:#define __DBL_DIG__ 15
// PPC64-LINUX:#define __DBL_EPSILON__ 2.2204460492503131e-16
// PPC64-LINUX:#define __DBL_HAS_DENORM__ 1
// PPC64-LINUX:#define __DBL_HAS_INFINITY__ 1
// PPC64-LINUX:#define __DBL_HAS_QUIET_NAN__ 1
// PPC64-LINUX:#define __DBL_MANT_DIG__ 53
// PPC64-LINUX:#define __DBL_MAX_10_EXP__ 308
// PPC64-LINUX:#define __DBL_MAX_EXP__ 1024
// PPC64-LINUX:#define __DBL_MAX__ 1.7976931348623157e+308
// PPC64-LINUX:#define __DBL_MIN_10_EXP__ (-307)
// PPC64-LINUX:#define __DBL_MIN_EXP__ (-1021)
// PPC64-LINUX:#define __DBL_MIN__ 2.2250738585072014e-308
// PPC64-LINUX:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// PPC64-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC64-LINUX:#define __FLT_DIG__ 6
// PPC64-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F
// PPC64-LINUX:#define __FLT_EVAL_METHOD__ 0
// PPC64-LINUX:#define __FLT_HAS_DENORM__ 1
// PPC64-LINUX:#define __FLT_HAS_INFINITY__ 1
// PPC64-LINUX:#define __FLT_HAS_QUIET_NAN__ 1
// PPC64-LINUX:#define __FLT_MANT_DIG__ 24
// PPC64-LINUX:#define __FLT_MAX_10_EXP__ 38
// PPC64-LINUX:#define __FLT_MAX_EXP__ 128
// PPC64-LINUX:#define __FLT_MAX__ 3.40282347e+38F
// PPC64-LINUX:#define __FLT_MIN_10_EXP__ (-37)
// PPC64-LINUX:#define __FLT_MIN_EXP__ (-125)
// PPC64-LINUX:#define __FLT_MIN__ 1.17549435e-38F
// PPC64-LINUX:#define __FLT_RADIX__ 2
// PPC64-LINUX:#define __HAVE_BSWAP__ 1
// PPC64-LINUX:#define __INT16_C_SUFFIX__
// PPC64-LINUX:#define __INT16_FMTd__ "hd"
// PPC64-LINUX:#define __INT16_FMTi__ "hi"
// PPC64-LINUX:#define __INT16_MAX__ 32767
// PPC64-LINUX:#define __INT16_TYPE__ short
// PPC64-LINUX:#define __INT32_C_SUFFIX__
// PPC64-LINUX:#define __INT32_FMTd__ "d"
// PPC64-LINUX:#define __INT32_FMTi__ "i"
// PPC64-LINUX:#define __INT32_MAX__ 2147483647
// PPC64-LINUX:#define __INT32_TYPE__ int
// PPC64-LINUX:#define __INT64_C_SUFFIX__ L
// PPC64-LINUX:#define __INT64_FMTd__ "ld"
// PPC64-LINUX:#define __INT64_FMTi__ "li"
// PPC64-LINUX:#define __INT64_MAX__ 9223372036854775807L
// PPC64-LINUX:#define __INT64_TYPE__ long int
// PPC64-LINUX:#define __INT8_C_SUFFIX__
// PPC64-LINUX:#define __INT8_FMTd__ "hhd"
// PPC64-LINUX:#define __INT8_FMTi__ "hhi"
// PPC64-LINUX:#define __INT8_MAX__ 127
// PPC64-LINUX:#define __INT8_TYPE__ signed char
// PPC64-LINUX:#define __INTMAX_C_SUFFIX__ L
// PPC64-LINUX:#define __INTMAX_FMTd__ "ld"
// PPC64-LINUX:#define __INTMAX_FMTi__ "li"
// PPC64-LINUX:#define __INTMAX_MAX__ 9223372036854775807L
// PPC64-LINUX:#define __INTMAX_TYPE__ long int
// PPC64-LINUX:#define __INTMAX_WIDTH__ 64
// PPC64-LINUX:#define __INTPTR_FMTd__ "ld"
// PPC64-LINUX:#define __INTPTR_FMTi__ "li"
// PPC64-LINUX:#define __INTPTR_MAX__ 9223372036854775807L
// PPC64-LINUX:#define __INTPTR_TYPE__ long int
// PPC64-LINUX:#define __INTPTR_WIDTH__ 64
// PPC64-LINUX:#define __INT_FAST16_FMTd__ "hd"
// PPC64-LINUX:#define __INT_FAST16_FMTi__ "hi"
// PPC64-LINUX:#define __INT_FAST16_MAX__ 32767
// PPC64-LINUX:#define __INT_FAST16_TYPE__ short
// PPC64-LINUX:#define __INT_FAST32_FMTd__ "d"
// PPC64-LINUX:#define __INT_FAST32_FMTi__ "i"
// PPC64-LINUX:#define __INT_FAST32_MAX__ 2147483647
// PPC64-LINUX:#define __INT_FAST32_TYPE__ int
// PPC64-LINUX:#define __INT_FAST64_FMTd__ "ld"
// PPC64-LINUX:#define __INT_FAST64_FMTi__ "li"
// PPC64-LINUX:#define __INT_FAST64_MAX__ 9223372036854775807L
// PPC64-LINUX:#define __INT_FAST64_TYPE__ long int
// PPC64-LINUX:#define __INT_FAST8_FMTd__ "hhd"
// PPC64-LINUX:#define __INT_FAST8_FMTi__ "hhi"
// PPC64-LINUX:#define __INT_FAST8_MAX__ 127
// PPC64-LINUX:#define __INT_FAST8_TYPE__ signed char
// PPC64-LINUX:#define __INT_LEAST16_FMTd__ "hd"
// PPC64-LINUX:#define __INT_LEAST16_FMTi__ "hi"
// PPC64-LINUX:#define __INT_LEAST16_MAX__ 32767
// PPC64-LINUX:#define __INT_LEAST16_TYPE__ short
// PPC64-LINUX:#define __INT_LEAST32_FMTd__ "d"
// PPC64-LINUX:#define __INT_LEAST32_FMTi__ "i"
// PPC64-LINUX:#define __INT_LEAST32_MAX__ 2147483647
// PPC64-LINUX:#define __INT_LEAST32_TYPE__ int
// PPC64-LINUX:#define __INT_LEAST64_FMTd__ "ld"
// PPC64-LINUX:#define __INT_LEAST64_FMTi__ "li"
// PPC64-LINUX:#define __INT_LEAST64_MAX__ 9223372036854775807L
// PPC64-LINUX:#define __INT_LEAST64_TYPE__ long int
// PPC64-LINUX:#define __INT_LEAST8_FMTd__ "hhd"
// PPC64-LINUX:#define __INT_LEAST8_FMTi__ "hhi"
// PPC64-LINUX:#define __INT_LEAST8_MAX__ 127
// PPC64-LINUX:#define __INT_LEAST8_TYPE__ signed char
// PPC64-LINUX:#define __INT_MAX__ 2147483647
// PPC64-LINUX:#define __LDBL_DENORM_MIN__ 4.94065645841246544176568792868221e-324L
// PPC64-LINUX:#define __LDBL_DIG__ 31
// PPC64-LINUX:#define __LDBL_EPSILON__ 4.94065645841246544176568792868221e-324L
// PPC64-LINUX:#define __LDBL_HAS_DENORM__ 1
// PPC64-LINUX:#define __LDBL_HAS_INFINITY__ 1
// PPC64-LINUX:#define __LDBL_HAS_QUIET_NAN__ 1
// PPC64-LINUX:#define __LDBL_MANT_DIG__ 106
// PPC64-LINUX:#define __LDBL_MAX_10_EXP__ 308
// PPC64-LINUX:#define __LDBL_MAX_EXP__ 1024
// PPC64-LINUX:#define __LDBL_MAX__ 1.79769313486231580793728971405301e+308L
// PPC64-LINUX:#define __LDBL_MIN_10_EXP__ (-291)
// PPC64-LINUX:#define __LDBL_MIN_EXP__ (-968)
// PPC64-LINUX:#define __LDBL_MIN__ 2.00416836000897277799610805135016e-292L
// PPC64-LINUX:#define __LONGDOUBLE128 1
// PPC64-LINUX:#define __LONG_DOUBLE_128__ 1
// PPC64-LINUX:#define __LONG_LONG_MAX__ 9223372036854775807LL
// PPC64-LINUX:#define __LONG_MAX__ 9223372036854775807L
// PPC64-LINUX:#define __LP64__ 1
// PPC64-LINUX:#define __NATURAL_ALIGNMENT__ 1
// PPC64-LINUX:#define __POINTER_WIDTH__ 64
// PPC64-LINUX:#define __POWERPC__ 1
// PPC64-LINUX:#define __PPC64__ 1
// PPC64-LINUX:#define __PPC__ 1
// PPC64-LINUX:#define __PTRDIFF_TYPE__ long int
// PPC64-LINUX:#define __PTRDIFF_WIDTH__ 64
// PPC64-LINUX:#define __REGISTER_PREFIX__
// PPC64-LINUX:#define __SCHAR_MAX__ 127
// PPC64-LINUX:#define __SHRT_MAX__ 32767
// PPC64-LINUX:#define __SIG_ATOMIC_MAX__ 2147483647
// PPC64-LINUX:#define __SIG_ATOMIC_WIDTH__ 32
// PPC64-LINUX:#define __SIZEOF_DOUBLE__ 8
// PPC64-LINUX:#define __SIZEOF_FLOAT__ 4
// PPC64-LINUX:#define __SIZEOF_INT__ 4
// PPC64-LINUX:#define __SIZEOF_LONG_DOUBLE__ 16
// PPC64-LINUX:#define __SIZEOF_LONG_LONG__ 8
// PPC64-LINUX:#define __SIZEOF_LONG__ 8
// PPC64-LINUX:#define __SIZEOF_POINTER__ 8
// PPC64-LINUX:#define __SIZEOF_PTRDIFF_T__ 8
// PPC64-LINUX:#define __SIZEOF_SHORT__ 2
// PPC64-LINUX:#define __SIZEOF_SIZE_T__ 8
// PPC64-LINUX:#define __SIZEOF_WCHAR_T__ 4
// PPC64-LINUX:#define __SIZEOF_WINT_T__ 4
// PPC64-LINUX:#define __SIZE_MAX__ 18446744073709551615UL
// PPC64-LINUX:#define __SIZE_TYPE__ long unsigned int
// PPC64-LINUX:#define __SIZE_WIDTH__ 64
// PPC64-LINUX:#define __UINT16_C_SUFFIX__
// PPC64-LINUX:#define __UINT16_MAX__ 65535
// PPC64-LINUX:#define __UINT16_TYPE__ unsigned short
// PPC64-LINUX:#define __UINT32_C_SUFFIX__ U
// PPC64-LINUX:#define __UINT32_MAX__ 4294967295U
// PPC64-LINUX:#define __UINT32_TYPE__ unsigned int
// PPC64-LINUX:#define __UINT64_C_SUFFIX__ UL
// PPC64-LINUX:#define __UINT64_MAX__ 18446744073709551615UL
// PPC64-LINUX:#define __UINT64_TYPE__ long unsigned int
// PPC64-LINUX:#define __UINT8_C_SUFFIX__
// PPC64-LINUX:#define __UINT8_MAX__ 255
// PPC64-LINUX:#define __UINT8_TYPE__ unsigned char
// PPC64-LINUX:#define __UINTMAX_C_SUFFIX__ UL
// PPC64-LINUX:#define __UINTMAX_MAX__ 18446744073709551615UL
// PPC64-LINUX:#define __UINTMAX_TYPE__ long unsigned int
// PPC64-LINUX:#define __UINTMAX_WIDTH__ 64
// PPC64-LINUX:#define __UINTPTR_MAX__ 18446744073709551615UL
// PPC64-LINUX:#define __UINTPTR_TYPE__ long unsigned int
// PPC64-LINUX:#define __UINTPTR_WIDTH__ 64
// PPC64-LINUX:#define __UINT_FAST16_MAX__ 65535
// PPC64-LINUX:#define __UINT_FAST16_TYPE__ unsigned short
// PPC64-LINUX:#define __UINT_FAST32_MAX__ 4294967295U
// PPC64-LINUX:#define __UINT_FAST32_TYPE__ unsigned int
// PPC64-LINUX:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// PPC64-LINUX:#define __UINT_FAST64_TYPE__ long unsigned int
// PPC64-LINUX:#define __UINT_FAST8_MAX__ 255
// PPC64-LINUX:#define __UINT_FAST8_TYPE__ unsigned char
// PPC64-LINUX:#define __UINT_LEAST16_MAX__ 65535
// PPC64-LINUX:#define __UINT_LEAST16_TYPE__ unsigned short
// PPC64-LINUX:#define __UINT_LEAST32_MAX__ 4294967295U
// PPC64-LINUX:#define __UINT_LEAST32_TYPE__ unsigned int
// PPC64-LINUX:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// PPC64-LINUX:#define __UINT_LEAST64_TYPE__ long unsigned int
// PPC64-LINUX:#define __UINT_LEAST8_MAX__ 255
// PPC64-LINUX:#define __UINT_LEAST8_TYPE__ unsigned char
// PPC64-LINUX:#define __USER_LABEL_PREFIX__
// PPC64-LINUX:#define __WCHAR_MAX__ 2147483647
// PPC64-LINUX:#define __WCHAR_TYPE__ int
// PPC64-LINUX:#define __WCHAR_WIDTH__ 32
// PPC64-LINUX:#define __WINT_TYPE__ unsigned int
// PPC64-LINUX:#define __WINT_UNSIGNED__ 1
// PPC64-LINUX:#define __WINT_WIDTH__ 32
// PPC64-LINUX:#define __powerpc64__ 1
// PPC64-LINUX:#define __powerpc__ 1
// PPC64-LINUX:#define __ppc64__ 1
// PPC64-LINUX:#define __ppc__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-linux-gnu < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-ELFv1 %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-linux-gnu -target-abi elfv1 < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-ELFv1 %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-linux-gnu -target-abi elfv1-qpx < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-ELFv1 %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-linux-gnu -target-abi elfv2 < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-ELFv2 %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64le-unknown-linux-gnu < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-ELFv2 %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64le-unknown-linux-gnu -target-abi elfv1 < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-ELFv1 %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64le-unknown-linux-gnu -target-abi elfv2 < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-ELFv2 %s
// PPC64-ELFv1:#define _CALL_ELF 1
// PPC64-ELFv2:#define _CALL_ELF 2
//
// Most of this is encompassed in other places.
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64le-unknown-linux-gnu -target-abi elfv2 < /dev/null | FileCheck -match-full-lines -check-prefix PPC64LE-LINUX %s
//
// PPC64LE-LINUX:#define _CALL_LINUX 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc-none-none -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPC %s
//
// PPC:#define _ARCH_PPC 1
// PPC:#define _BIG_ENDIAN 1
// PPC-NOT:#define _LP64
// PPC:#define __BIGGEST_ALIGNMENT__ 16
// PPC:#define __BIG_ENDIAN__ 1
// PPC:#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
// PPC:#define __CHAR16_TYPE__ unsigned short
// PPC:#define __CHAR32_TYPE__ unsigned int
// PPC:#define __CHAR_BIT__ 8
// PPC:#define __CHAR_UNSIGNED__ 1
// PPC:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// PPC:#define __DBL_DIG__ 15
// PPC:#define __DBL_EPSILON__ 2.2204460492503131e-16
// PPC:#define __DBL_HAS_DENORM__ 1
// PPC:#define __DBL_HAS_INFINITY__ 1
// PPC:#define __DBL_HAS_QUIET_NAN__ 1
// PPC:#define __DBL_MANT_DIG__ 53
// PPC:#define __DBL_MAX_10_EXP__ 308
// PPC:#define __DBL_MAX_EXP__ 1024
// PPC:#define __DBL_MAX__ 1.7976931348623157e+308
// PPC:#define __DBL_MIN_10_EXP__ (-307)
// PPC:#define __DBL_MIN_EXP__ (-1021)
// PPC:#define __DBL_MIN__ 2.2250738585072014e-308
// PPC:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// PPC:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC:#define __FLT_DIG__ 6
// PPC:#define __FLT_EPSILON__ 1.19209290e-7F
// PPC:#define __FLT_EVAL_METHOD__ 0
// PPC:#define __FLT_HAS_DENORM__ 1
// PPC:#define __FLT_HAS_INFINITY__ 1
// PPC:#define __FLT_HAS_QUIET_NAN__ 1
// PPC:#define __FLT_MANT_DIG__ 24
// PPC:#define __FLT_MAX_10_EXP__ 38
// PPC:#define __FLT_MAX_EXP__ 128
// PPC:#define __FLT_MAX__ 3.40282347e+38F
// PPC:#define __FLT_MIN_10_EXP__ (-37)
// PPC:#define __FLT_MIN_EXP__ (-125)
// PPC:#define __FLT_MIN__ 1.17549435e-38F
// PPC:#define __FLT_RADIX__ 2
// PPC:#define __HAVE_BSWAP__ 1
// PPC:#define __INT16_C_SUFFIX__
// PPC:#define __INT16_FMTd__ "hd"
// PPC:#define __INT16_FMTi__ "hi"
// PPC:#define __INT16_MAX__ 32767
// PPC:#define __INT16_TYPE__ short
// PPC:#define __INT32_C_SUFFIX__
// PPC:#define __INT32_FMTd__ "d"
// PPC:#define __INT32_FMTi__ "i"
// PPC:#define __INT32_MAX__ 2147483647
// PPC:#define __INT32_TYPE__ int
// PPC:#define __INT64_C_SUFFIX__ LL
// PPC:#define __INT64_FMTd__ "lld"
// PPC:#define __INT64_FMTi__ "lli"
// PPC:#define __INT64_MAX__ 9223372036854775807LL
// PPC:#define __INT64_TYPE__ long long int
// PPC:#define __INT8_C_SUFFIX__
// PPC:#define __INT8_FMTd__ "hhd"
// PPC:#define __INT8_FMTi__ "hhi"
// PPC:#define __INT8_MAX__ 127
// PPC:#define __INT8_TYPE__ signed char
// PPC:#define __INTMAX_C_SUFFIX__ LL
// PPC:#define __INTMAX_FMTd__ "lld"
// PPC:#define __INTMAX_FMTi__ "lli"
// PPC:#define __INTMAX_MAX__ 9223372036854775807LL
// PPC:#define __INTMAX_TYPE__ long long int
// PPC:#define __INTMAX_WIDTH__ 64
// PPC:#define __INTPTR_FMTd__ "ld"
// PPC:#define __INTPTR_FMTi__ "li"
// PPC:#define __INTPTR_MAX__ 2147483647L
// PPC:#define __INTPTR_TYPE__ long int
// PPC:#define __INTPTR_WIDTH__ 32
// PPC:#define __INT_FAST16_FMTd__ "hd"
// PPC:#define __INT_FAST16_FMTi__ "hi"
// PPC:#define __INT_FAST16_MAX__ 32767
// PPC:#define __INT_FAST16_TYPE__ short
// PPC:#define __INT_FAST32_FMTd__ "d"
// PPC:#define __INT_FAST32_FMTi__ "i"
// PPC:#define __INT_FAST32_MAX__ 2147483647
// PPC:#define __INT_FAST32_TYPE__ int
// PPC:#define __INT_FAST64_FMTd__ "lld"
// PPC:#define __INT_FAST64_FMTi__ "lli"
// PPC:#define __INT_FAST64_MAX__ 9223372036854775807LL
// PPC:#define __INT_FAST64_TYPE__ long long int
// PPC:#define __INT_FAST8_FMTd__ "hhd"
// PPC:#define __INT_FAST8_FMTi__ "hhi"
// PPC:#define __INT_FAST8_MAX__ 127
// PPC:#define __INT_FAST8_TYPE__ signed char
// PPC:#define __INT_LEAST16_FMTd__ "hd"
// PPC:#define __INT_LEAST16_FMTi__ "hi"
// PPC:#define __INT_LEAST16_MAX__ 32767
// PPC:#define __INT_LEAST16_TYPE__ short
// PPC:#define __INT_LEAST32_FMTd__ "d"
// PPC:#define __INT_LEAST32_FMTi__ "i"
// PPC:#define __INT_LEAST32_MAX__ 2147483647
// PPC:#define __INT_LEAST32_TYPE__ int
// PPC:#define __INT_LEAST64_FMTd__ "lld"
// PPC:#define __INT_LEAST64_FMTi__ "lli"
// PPC:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// PPC:#define __INT_LEAST64_TYPE__ long long int
// PPC:#define __INT_LEAST8_FMTd__ "hhd"
// PPC:#define __INT_LEAST8_FMTi__ "hhi"
// PPC:#define __INT_LEAST8_MAX__ 127
// PPC:#define __INT_LEAST8_TYPE__ signed char
// PPC:#define __INT_MAX__ 2147483647
// PPC:#define __LDBL_DENORM_MIN__ 4.94065645841246544176568792868221e-324L
// PPC:#define __LDBL_DIG__ 31
// PPC:#define __LDBL_EPSILON__ 4.94065645841246544176568792868221e-324L
// PPC:#define __LDBL_HAS_DENORM__ 1
// PPC:#define __LDBL_HAS_INFINITY__ 1
// PPC:#define __LDBL_HAS_QUIET_NAN__ 1
// PPC:#define __LDBL_MANT_DIG__ 106
// PPC:#define __LDBL_MAX_10_EXP__ 308
// PPC:#define __LDBL_MAX_EXP__ 1024
// PPC:#define __LDBL_MAX__ 1.79769313486231580793728971405301e+308L
// PPC:#define __LDBL_MIN_10_EXP__ (-291)
// PPC:#define __LDBL_MIN_EXP__ (-968)
// PPC:#define __LDBL_MIN__ 2.00416836000897277799610805135016e-292L
// PPC:#define __LONGDOUBLE128 1
// PPC:#define __LONG_DOUBLE_128__ 1
// PPC:#define __LONG_LONG_MAX__ 9223372036854775807LL
// PPC:#define __LONG_MAX__ 2147483647L
// PPC-NOT:#define __LP64__
// PPC:#define __NATURAL_ALIGNMENT__ 1
// PPC:#define __POINTER_WIDTH__ 32
// PPC:#define __POWERPC__ 1
// PPC:#define __PPC__ 1
// PPC:#define __PTRDIFF_TYPE__ long int
// PPC:#define __PTRDIFF_WIDTH__ 32
// PPC:#define __REGISTER_PREFIX__
// PPC:#define __SCHAR_MAX__ 127
// PPC:#define __SHRT_MAX__ 32767
// PPC:#define __SIG_ATOMIC_MAX__ 2147483647
// PPC:#define __SIG_ATOMIC_WIDTH__ 32
// PPC:#define __SIZEOF_DOUBLE__ 8
// PPC:#define __SIZEOF_FLOAT__ 4
// PPC:#define __SIZEOF_INT__ 4
// PPC:#define __SIZEOF_LONG_DOUBLE__ 16
// PPC:#define __SIZEOF_LONG_LONG__ 8
// PPC:#define __SIZEOF_LONG__ 4
// PPC:#define __SIZEOF_POINTER__ 4
// PPC:#define __SIZEOF_PTRDIFF_T__ 4
// PPC:#define __SIZEOF_SHORT__ 2
// PPC:#define __SIZEOF_SIZE_T__ 4
// PPC:#define __SIZEOF_WCHAR_T__ 4
// PPC:#define __SIZEOF_WINT_T__ 4
// PPC:#define __SIZE_MAX__ 4294967295UL
// PPC:#define __SIZE_TYPE__ long unsigned int
// PPC:#define __SIZE_WIDTH__ 32
// PPC:#define __UINT16_C_SUFFIX__
// PPC:#define __UINT16_MAX__ 65535
// PPC:#define __UINT16_TYPE__ unsigned short
// PPC:#define __UINT32_C_SUFFIX__ U
// PPC:#define __UINT32_MAX__ 4294967295U
// PPC:#define __UINT32_TYPE__ unsigned int
// PPC:#define __UINT64_C_SUFFIX__ ULL
// PPC:#define __UINT64_MAX__ 18446744073709551615ULL
// PPC:#define __UINT64_TYPE__ long long unsigned int
// PPC:#define __UINT8_C_SUFFIX__
// PPC:#define __UINT8_MAX__ 255
// PPC:#define __UINT8_TYPE__ unsigned char
// PPC:#define __UINTMAX_C_SUFFIX__ ULL
// PPC:#define __UINTMAX_MAX__ 18446744073709551615ULL
// PPC:#define __UINTMAX_TYPE__ long long unsigned int
// PPC:#define __UINTMAX_WIDTH__ 64
// PPC:#define __UINTPTR_MAX__ 4294967295UL
// PPC:#define __UINTPTR_TYPE__ long unsigned int
// PPC:#define __UINTPTR_WIDTH__ 32
// PPC:#define __UINT_FAST16_MAX__ 65535
// PPC:#define __UINT_FAST16_TYPE__ unsigned short
// PPC:#define __UINT_FAST32_MAX__ 4294967295U
// PPC:#define __UINT_FAST32_TYPE__ unsigned int
// PPC:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// PPC:#define __UINT_FAST64_TYPE__ long long unsigned int
// PPC:#define __UINT_FAST8_MAX__ 255
// PPC:#define __UINT_FAST8_TYPE__ unsigned char
// PPC:#define __UINT_LEAST16_MAX__ 65535
// PPC:#define __UINT_LEAST16_TYPE__ unsigned short
// PPC:#define __UINT_LEAST32_MAX__ 4294967295U
// PPC:#define __UINT_LEAST32_TYPE__ unsigned int
// PPC:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// PPC:#define __UINT_LEAST64_TYPE__ long long unsigned int
// PPC:#define __UINT_LEAST8_MAX__ 255
// PPC:#define __UINT_LEAST8_TYPE__ unsigned char
// PPC:#define __USER_LABEL_PREFIX__
// PPC:#define __WCHAR_MAX__ 2147483647
// PPC:#define __WCHAR_TYPE__ int
// PPC:#define __WCHAR_WIDTH__ 32
// PPC:#define __WINT_TYPE__ int
// PPC:#define __WINT_WIDTH__ 32
// PPC:#define __ppc__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc-unknown-linux-gnu -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPC-LINUX %s
//
// PPC-LINUX:#define _ARCH_PPC 1
// PPC-LINUX:#define _BIG_ENDIAN 1
// PPC-LINUX-NOT:#define _LP64
// PPC-LINUX:#define __BIGGEST_ALIGNMENT__ 16
// PPC-LINUX:#define __BIG_ENDIAN__ 1
// PPC-LINUX:#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
// PPC-LINUX:#define __CHAR16_TYPE__ unsigned short
// PPC-LINUX:#define __CHAR32_TYPE__ unsigned int
// PPC-LINUX:#define __CHAR_BIT__ 8
// PPC-LINUX:#define __CHAR_UNSIGNED__ 1
// PPC-LINUX:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// PPC-LINUX:#define __DBL_DIG__ 15
// PPC-LINUX:#define __DBL_EPSILON__ 2.2204460492503131e-16
// PPC-LINUX:#define __DBL_HAS_DENORM__ 1
// PPC-LINUX:#define __DBL_HAS_INFINITY__ 1
// PPC-LINUX:#define __DBL_HAS_QUIET_NAN__ 1
// PPC-LINUX:#define __DBL_MANT_DIG__ 53
// PPC-LINUX:#define __DBL_MAX_10_EXP__ 308
// PPC-LINUX:#define __DBL_MAX_EXP__ 1024
// PPC-LINUX:#define __DBL_MAX__ 1.7976931348623157e+308
// PPC-LINUX:#define __DBL_MIN_10_EXP__ (-307)
// PPC-LINUX:#define __DBL_MIN_EXP__ (-1021)
// PPC-LINUX:#define __DBL_MIN__ 2.2250738585072014e-308
// PPC-LINUX:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// PPC-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC-LINUX:#define __FLT_DIG__ 6
// PPC-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F
// PPC-LINUX:#define __FLT_EVAL_METHOD__ 0
// PPC-LINUX:#define __FLT_HAS_DENORM__ 1
// PPC-LINUX:#define __FLT_HAS_INFINITY__ 1
// PPC-LINUX:#define __FLT_HAS_QUIET_NAN__ 1
// PPC-LINUX:#define __FLT_MANT_DIG__ 24
// PPC-LINUX:#define __FLT_MAX_10_EXP__ 38
// PPC-LINUX:#define __FLT_MAX_EXP__ 128
// PPC-LINUX:#define __FLT_MAX__ 3.40282347e+38F
// PPC-LINUX:#define __FLT_MIN_10_EXP__ (-37)
// PPC-LINUX:#define __FLT_MIN_EXP__ (-125)
// PPC-LINUX:#define __FLT_MIN__ 1.17549435e-38F
// PPC-LINUX:#define __FLT_RADIX__ 2
// PPC-LINUX:#define __HAVE_BSWAP__ 1
// PPC-LINUX:#define __INT16_C_SUFFIX__
// PPC-LINUX:#define __INT16_FMTd__ "hd"
// PPC-LINUX:#define __INT16_FMTi__ "hi"
// PPC-LINUX:#define __INT16_MAX__ 32767
// PPC-LINUX:#define __INT16_TYPE__ short
// PPC-LINUX:#define __INT32_C_SUFFIX__
// PPC-LINUX:#define __INT32_FMTd__ "d"
// PPC-LINUX:#define __INT32_FMTi__ "i"
// PPC-LINUX:#define __INT32_MAX__ 2147483647
// PPC-LINUX:#define __INT32_TYPE__ int
// PPC-LINUX:#define __INT64_C_SUFFIX__ LL
// PPC-LINUX:#define __INT64_FMTd__ "lld"
// PPC-LINUX:#define __INT64_FMTi__ "lli"
// PPC-LINUX:#define __INT64_MAX__ 9223372036854775807LL
// PPC-LINUX:#define __INT64_TYPE__ long long int
// PPC-LINUX:#define __INT8_C_SUFFIX__
// PPC-LINUX:#define __INT8_FMTd__ "hhd"
// PPC-LINUX:#define __INT8_FMTi__ "hhi"
// PPC-LINUX:#define __INT8_MAX__ 127
// PPC-LINUX:#define __INT8_TYPE__ signed char
// PPC-LINUX:#define __INTMAX_C_SUFFIX__ LL
// PPC-LINUX:#define __INTMAX_FMTd__ "lld"
// PPC-LINUX:#define __INTMAX_FMTi__ "lli"
// PPC-LINUX:#define __INTMAX_MAX__ 9223372036854775807LL
// PPC-LINUX:#define __INTMAX_TYPE__ long long int
// PPC-LINUX:#define __INTMAX_WIDTH__ 64
// PPC-LINUX:#define __INTPTR_FMTd__ "d"
// PPC-LINUX:#define __INTPTR_FMTi__ "i"
// PPC-LINUX:#define __INTPTR_MAX__ 2147483647
// PPC-LINUX:#define __INTPTR_TYPE__ int
// PPC-LINUX:#define __INTPTR_WIDTH__ 32
// PPC-LINUX:#define __INT_FAST16_FMTd__ "hd"
// PPC-LINUX:#define __INT_FAST16_FMTi__ "hi"
// PPC-LINUX:#define __INT_FAST16_MAX__ 32767
// PPC-LINUX:#define __INT_FAST16_TYPE__ short
// PPC-LINUX:#define __INT_FAST32_FMTd__ "d"
// PPC-LINUX:#define __INT_FAST32_FMTi__ "i"
// PPC-LINUX:#define __INT_FAST32_MAX__ 2147483647
// PPC-LINUX:#define __INT_FAST32_TYPE__ int
// PPC-LINUX:#define __INT_FAST64_FMTd__ "lld"
// PPC-LINUX:#define __INT_FAST64_FMTi__ "lli"
// PPC-LINUX:#define __INT_FAST64_MAX__ 9223372036854775807LL
// PPC-LINUX:#define __INT_FAST64_TYPE__ long long int
// PPC-LINUX:#define __INT_FAST8_FMTd__ "hhd"
// PPC-LINUX:#define __INT_FAST8_FMTi__ "hhi"
// PPC-LINUX:#define __INT_FAST8_MAX__ 127
// PPC-LINUX:#define __INT_FAST8_TYPE__ signed char
// PPC-LINUX:#define __INT_LEAST16_FMTd__ "hd"
// PPC-LINUX:#define __INT_LEAST16_FMTi__ "hi"
// PPC-LINUX:#define __INT_LEAST16_MAX__ 32767
// PPC-LINUX:#define __INT_LEAST16_TYPE__ short
// PPC-LINUX:#define __INT_LEAST32_FMTd__ "d"
// PPC-LINUX:#define __INT_LEAST32_FMTi__ "i"
// PPC-LINUX:#define __INT_LEAST32_MAX__ 2147483647
// PPC-LINUX:#define __INT_LEAST32_TYPE__ int
// PPC-LINUX:#define __INT_LEAST64_FMTd__ "lld"
// PPC-LINUX:#define __INT_LEAST64_FMTi__ "lli"
// PPC-LINUX:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// PPC-LINUX:#define __INT_LEAST64_TYPE__ long long int
// PPC-LINUX:#define __INT_LEAST8_FMTd__ "hhd"
// PPC-LINUX:#define __INT_LEAST8_FMTi__ "hhi"
// PPC-LINUX:#define __INT_LEAST8_MAX__ 127
// PPC-LINUX:#define __INT_LEAST8_TYPE__ signed char
// PPC-LINUX:#define __INT_MAX__ 2147483647
// PPC-LINUX:#define __LDBL_DENORM_MIN__ 4.94065645841246544176568792868221e-324L
// PPC-LINUX:#define __LDBL_DIG__ 31
// PPC-LINUX:#define __LDBL_EPSILON__ 4.94065645841246544176568792868221e-324L
// PPC-LINUX:#define __LDBL_HAS_DENORM__ 1
// PPC-LINUX:#define __LDBL_HAS_INFINITY__ 1
// PPC-LINUX:#define __LDBL_HAS_QUIET_NAN__ 1
// PPC-LINUX:#define __LDBL_MANT_DIG__ 106
// PPC-LINUX:#define __LDBL_MAX_10_EXP__ 308
// PPC-LINUX:#define __LDBL_MAX_EXP__ 1024
// PPC-LINUX:#define __LDBL_MAX__ 1.79769313486231580793728971405301e+308L
// PPC-LINUX:#define __LDBL_MIN_10_EXP__ (-291)
// PPC-LINUX:#define __LDBL_MIN_EXP__ (-968)
// PPC-LINUX:#define __LDBL_MIN__ 2.00416836000897277799610805135016e-292L
// PPC-LINUX:#define __LONGDOUBLE128 1
// PPC-LINUX:#define __LONG_DOUBLE_128__ 1
// PPC-LINUX:#define __LONG_LONG_MAX__ 9223372036854775807LL
// PPC-LINUX:#define __LONG_MAX__ 2147483647L
// PPC-LINUX-NOT:#define __LP64__
// PPC-LINUX:#define __NATURAL_ALIGNMENT__ 1
// PPC-LINUX:#define __POINTER_WIDTH__ 32
// PPC-LINUX:#define __POWERPC__ 1
// PPC-LINUX:#define __PPC__ 1
// PPC-LINUX:#define __PTRDIFF_TYPE__ int
// PPC-LINUX:#define __PTRDIFF_WIDTH__ 32
// PPC-LINUX:#define __REGISTER_PREFIX__
// PPC-LINUX:#define __SCHAR_MAX__ 127
// PPC-LINUX:#define __SHRT_MAX__ 32767
// PPC-LINUX:#define __SIG_ATOMIC_MAX__ 2147483647
// PPC-LINUX:#define __SIG_ATOMIC_WIDTH__ 32
// PPC-LINUX:#define __SIZEOF_DOUBLE__ 8
// PPC-LINUX:#define __SIZEOF_FLOAT__ 4
// PPC-LINUX:#define __SIZEOF_INT__ 4
// PPC-LINUX:#define __SIZEOF_LONG_DOUBLE__ 16
// PPC-LINUX:#define __SIZEOF_LONG_LONG__ 8
// PPC-LINUX:#define __SIZEOF_LONG__ 4
// PPC-LINUX:#define __SIZEOF_POINTER__ 4
// PPC-LINUX:#define __SIZEOF_PTRDIFF_T__ 4
// PPC-LINUX:#define __SIZEOF_SHORT__ 2
// PPC-LINUX:#define __SIZEOF_SIZE_T__ 4
// PPC-LINUX:#define __SIZEOF_WCHAR_T__ 4
// PPC-LINUX:#define __SIZEOF_WINT_T__ 4
// PPC-LINUX:#define __SIZE_MAX__ 4294967295U
// PPC-LINUX:#define __SIZE_TYPE__ unsigned int
// PPC-LINUX:#define __SIZE_WIDTH__ 32
// PPC-LINUX:#define __UINT16_C_SUFFIX__
// PPC-LINUX:#define __UINT16_MAX__ 65535
// PPC-LINUX:#define __UINT16_TYPE__ unsigned short
// PPC-LINUX:#define __UINT32_C_SUFFIX__ U
// PPC-LINUX:#define __UINT32_MAX__ 4294967295U
// PPC-LINUX:#define __UINT32_TYPE__ unsigned int
// PPC-LINUX:#define __UINT64_C_SUFFIX__ ULL
// PPC-LINUX:#define __UINT64_MAX__ 18446744073709551615ULL
// PPC-LINUX:#define __UINT64_TYPE__ long long unsigned int
// PPC-LINUX:#define __UINT8_C_SUFFIX__
// PPC-LINUX:#define __UINT8_MAX__ 255
// PPC-LINUX:#define __UINT8_TYPE__ unsigned char
// PPC-LINUX:#define __UINTMAX_C_SUFFIX__ ULL
// PPC-LINUX:#define __UINTMAX_MAX__ 18446744073709551615ULL
// PPC-LINUX:#define __UINTMAX_TYPE__ long long unsigned int
// PPC-LINUX:#define __UINTMAX_WIDTH__ 64
// PPC-LINUX:#define __UINTPTR_MAX__ 4294967295U
// PPC-LINUX:#define __UINTPTR_TYPE__ unsigned int
// PPC-LINUX:#define __UINTPTR_WIDTH__ 32
// PPC-LINUX:#define __UINT_FAST16_MAX__ 65535
// PPC-LINUX:#define __UINT_FAST16_TYPE__ unsigned short
// PPC-LINUX:#define __UINT_FAST32_MAX__ 4294967295U
// PPC-LINUX:#define __UINT_FAST32_TYPE__ unsigned int
// PPC-LINUX:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// PPC-LINUX:#define __UINT_FAST64_TYPE__ long long unsigned int
// PPC-LINUX:#define __UINT_FAST8_MAX__ 255
// PPC-LINUX:#define __UINT_FAST8_TYPE__ unsigned char
// PPC-LINUX:#define __UINT_LEAST16_MAX__ 65535
// PPC-LINUX:#define __UINT_LEAST16_TYPE__ unsigned short
// PPC-LINUX:#define __UINT_LEAST32_MAX__ 4294967295U
// PPC-LINUX:#define __UINT_LEAST32_TYPE__ unsigned int
// PPC-LINUX:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// PPC-LINUX:#define __UINT_LEAST64_TYPE__ long long unsigned int
// PPC-LINUX:#define __UINT_LEAST8_MAX__ 255
// PPC-LINUX:#define __UINT_LEAST8_TYPE__ unsigned char
// PPC-LINUX:#define __USER_LABEL_PREFIX__
// PPC-LINUX:#define __WCHAR_MAX__ 2147483647
// PPC-LINUX:#define __WCHAR_TYPE__ int
// PPC-LINUX:#define __WCHAR_WIDTH__ 32
// PPC-LINUX:#define __WINT_TYPE__ unsigned int
// PPC-LINUX:#define __WINT_UNSIGNED__ 1
// PPC-LINUX:#define __WINT_WIDTH__ 32
// PPC-LINUX:#define __powerpc__ 1
// PPC-LINUX:#define __ppc__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc-unknown-linux-gnu -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix PPC32-LINUX %s
//
// PPC32-LINUX-NOT: _CALL_LINUX
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc-apple-darwin8 < /dev/null | FileCheck -match-full-lines -check-prefix PPC-DARWIN %s
//
// PPC-DARWIN:#define _ARCH_PPC 1
// PPC-DARWIN:#define _BIG_ENDIAN 1
// PPC-DARWIN:#define __BIGGEST_ALIGNMENT__ 16
// PPC-DARWIN:#define __BIG_ENDIAN__ 1
// PPC-DARWIN:#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
// PPC-DARWIN:#define __CHAR16_TYPE__ unsigned short
// PPC-DARWIN:#define __CHAR32_TYPE__ unsigned int
// PPC-DARWIN:#define __CHAR_BIT__ 8
// PPC-DARWIN:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// PPC-DARWIN:#define __DBL_DIG__ 15
// PPC-DARWIN:#define __DBL_EPSILON__ 2.2204460492503131e-16
// PPC-DARWIN:#define __DBL_HAS_DENORM__ 1
// PPC-DARWIN:#define __DBL_HAS_INFINITY__ 1
// PPC-DARWIN:#define __DBL_HAS_QUIET_NAN__ 1
// PPC-DARWIN:#define __DBL_MANT_DIG__ 53
// PPC-DARWIN:#define __DBL_MAX_10_EXP__ 308
// PPC-DARWIN:#define __DBL_MAX_EXP__ 1024
// PPC-DARWIN:#define __DBL_MAX__ 1.7976931348623157e+308
// PPC-DARWIN:#define __DBL_MIN_10_EXP__ (-307)
// PPC-DARWIN:#define __DBL_MIN_EXP__ (-1021)
// PPC-DARWIN:#define __DBL_MIN__ 2.2250738585072014e-308
// PPC-DARWIN:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// PPC-DARWIN:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PPC-DARWIN:#define __FLT_DIG__ 6
// PPC-DARWIN:#define __FLT_EPSILON__ 1.19209290e-7F
// PPC-DARWIN:#define __FLT_EVAL_METHOD__ 0
// PPC-DARWIN:#define __FLT_HAS_DENORM__ 1
// PPC-DARWIN:#define __FLT_HAS_INFINITY__ 1
// PPC-DARWIN:#define __FLT_HAS_QUIET_NAN__ 1
// PPC-DARWIN:#define __FLT_MANT_DIG__ 24
// PPC-DARWIN:#define __FLT_MAX_10_EXP__ 38
// PPC-DARWIN:#define __FLT_MAX_EXP__ 128
// PPC-DARWIN:#define __FLT_MAX__ 3.40282347e+38F
// PPC-DARWIN:#define __FLT_MIN_10_EXP__ (-37)
// PPC-DARWIN:#define __FLT_MIN_EXP__ (-125)
// PPC-DARWIN:#define __FLT_MIN__ 1.17549435e-38F
// PPC-DARWIN:#define __FLT_RADIX__ 2
// PPC-DARWIN:#define __HAVE_BSWAP__ 1
// PPC-DARWIN:#define __INT16_C_SUFFIX__
// PPC-DARWIN:#define __INT16_FMTd__ "hd"
// PPC-DARWIN:#define __INT16_FMTi__ "hi"
// PPC-DARWIN:#define __INT16_MAX__ 32767
// PPC-DARWIN:#define __INT16_TYPE__ short
// PPC-DARWIN:#define __INT32_C_SUFFIX__
// PPC-DARWIN:#define __INT32_FMTd__ "d"
// PPC-DARWIN:#define __INT32_FMTi__ "i"
// PPC-DARWIN:#define __INT32_MAX__ 2147483647
// PPC-DARWIN:#define __INT32_TYPE__ int
// PPC-DARWIN:#define __INT64_C_SUFFIX__ LL
// PPC-DARWIN:#define __INT64_FMTd__ "lld"
// PPC-DARWIN:#define __INT64_FMTi__ "lli"
// PPC-DARWIN:#define __INT64_MAX__ 9223372036854775807LL
// PPC-DARWIN:#define __INT64_TYPE__ long long int
// PPC-DARWIN:#define __INT8_C_SUFFIX__
// PPC-DARWIN:#define __INT8_FMTd__ "hhd"
// PPC-DARWIN:#define __INT8_FMTi__ "hhi"
// PPC-DARWIN:#define __INT8_MAX__ 127
// PPC-DARWIN:#define __INT8_TYPE__ signed char
// PPC-DARWIN:#define __INTMAX_C_SUFFIX__ LL
// PPC-DARWIN:#define __INTMAX_FMTd__ "lld"
// PPC-DARWIN:#define __INTMAX_FMTi__ "lli"
// PPC-DARWIN:#define __INTMAX_MAX__ 9223372036854775807LL
// PPC-DARWIN:#define __INTMAX_TYPE__ long long int
// PPC-DARWIN:#define __INTMAX_WIDTH__ 64
// PPC-DARWIN:#define __INTPTR_FMTd__ "ld"
// PPC-DARWIN:#define __INTPTR_FMTi__ "li"
// PPC-DARWIN:#define __INTPTR_MAX__ 2147483647L
// PPC-DARWIN:#define __INTPTR_TYPE__ long int
// PPC-DARWIN:#define __INTPTR_WIDTH__ 32
// PPC-DARWIN:#define __INT_FAST16_FMTd__ "hd"
// PPC-DARWIN:#define __INT_FAST16_FMTi__ "hi"
// PPC-DARWIN:#define __INT_FAST16_MAX__ 32767
// PPC-DARWIN:#define __INT_FAST16_TYPE__ short
// PPC-DARWIN:#define __INT_FAST32_FMTd__ "d"
// PPC-DARWIN:#define __INT_FAST32_FMTi__ "i"
// PPC-DARWIN:#define __INT_FAST32_MAX__ 2147483647
// PPC-DARWIN:#define __INT_FAST32_TYPE__ int
// PPC-DARWIN:#define __INT_FAST64_FMTd__ "lld"
// PPC-DARWIN:#define __INT_FAST64_FMTi__ "lli"
// PPC-DARWIN:#define __INT_FAST64_MAX__ 9223372036854775807LL
// PPC-DARWIN:#define __INT_FAST64_TYPE__ long long int
// PPC-DARWIN:#define __INT_FAST8_FMTd__ "hhd"
// PPC-DARWIN:#define __INT_FAST8_FMTi__ "hhi"
// PPC-DARWIN:#define __INT_FAST8_MAX__ 127
// PPC-DARWIN:#define __INT_FAST8_TYPE__ signed char
// PPC-DARWIN:#define __INT_LEAST16_FMTd__ "hd"
// PPC-DARWIN:#define __INT_LEAST16_FMTi__ "hi"
// PPC-DARWIN:#define __INT_LEAST16_MAX__ 32767
// PPC-DARWIN:#define __INT_LEAST16_TYPE__ short
// PPC-DARWIN:#define __INT_LEAST32_FMTd__ "d"
// PPC-DARWIN:#define __INT_LEAST32_FMTi__ "i"
// PPC-DARWIN:#define __INT_LEAST32_MAX__ 2147483647
// PPC-DARWIN:#define __INT_LEAST32_TYPE__ int
// PPC-DARWIN:#define __INT_LEAST64_FMTd__ "lld"
// PPC-DARWIN:#define __INT_LEAST64_FMTi__ "lli"
// PPC-DARWIN:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// PPC-DARWIN:#define __INT_LEAST64_TYPE__ long long int
// PPC-DARWIN:#define __INT_LEAST8_FMTd__ "hhd"
// PPC-DARWIN:#define __INT_LEAST8_FMTi__ "hhi"
// PPC-DARWIN:#define __INT_LEAST8_MAX__ 127
// PPC-DARWIN:#define __INT_LEAST8_TYPE__ signed char
// PPC-DARWIN:#define __INT_MAX__ 2147483647
// PPC-DARWIN:#define __LDBL_DENORM_MIN__ 4.94065645841246544176568792868221e-324L
// PPC-DARWIN:#define __LDBL_DIG__ 31
// PPC-DARWIN:#define __LDBL_EPSILON__ 4.94065645841246544176568792868221e-324L
// PPC-DARWIN:#define __LDBL_HAS_DENORM__ 1
// PPC-DARWIN:#define __LDBL_HAS_INFINITY__ 1
// PPC-DARWIN:#define __LDBL_HAS_QUIET_NAN__ 1
// PPC-DARWIN:#define __LDBL_MANT_DIG__ 106
// PPC-DARWIN:#define __LDBL_MAX_10_EXP__ 308
// PPC-DARWIN:#define __LDBL_MAX_EXP__ 1024
// PPC-DARWIN:#define __LDBL_MAX__ 1.79769313486231580793728971405301e+308L
// PPC-DARWIN:#define __LDBL_MIN_10_EXP__ (-291)
// PPC-DARWIN:#define __LDBL_MIN_EXP__ (-968)
// PPC-DARWIN:#define __LDBL_MIN__ 2.00416836000897277799610805135016e-292L
// PPC-DARWIN:#define __LONGDOUBLE128 1
// PPC-DARWIN:#define __LONG_DOUBLE_128__ 1
// PPC-DARWIN:#define __LONG_LONG_MAX__ 9223372036854775807LL
// PPC-DARWIN:#define __LONG_MAX__ 2147483647L
// PPC-DARWIN:#define __MACH__ 1
// PPC-DARWIN:#define __NATURAL_ALIGNMENT__ 1
// PPC-DARWIN:#define __ORDER_BIG_ENDIAN__ 4321
// PPC-DARWIN:#define __ORDER_LITTLE_ENDIAN__ 1234
// PPC-DARWIN:#define __ORDER_PDP_ENDIAN__ 3412
// PPC-DARWIN:#define __POINTER_WIDTH__ 32
// PPC-DARWIN:#define __POWERPC__ 1
// PPC-DARWIN:#define __PPC__ 1
// PPC-DARWIN:#define __PTRDIFF_TYPE__ int
// PPC-DARWIN:#define __PTRDIFF_WIDTH__ 32
// PPC-DARWIN:#define __REGISTER_PREFIX__
// PPC-DARWIN:#define __SCHAR_MAX__ 127
// PPC-DARWIN:#define __SHRT_MAX__ 32767
// PPC-DARWIN:#define __SIG_ATOMIC_MAX__ 2147483647
// PPC-DARWIN:#define __SIG_ATOMIC_WIDTH__ 32
// PPC-DARWIN:#define __SIZEOF_DOUBLE__ 8
// PPC-DARWIN:#define __SIZEOF_FLOAT__ 4
// PPC-DARWIN:#define __SIZEOF_INT__ 4
// PPC-DARWIN:#define __SIZEOF_LONG_DOUBLE__ 16
// PPC-DARWIN:#define __SIZEOF_LONG_LONG__ 8
// PPC-DARWIN:#define __SIZEOF_LONG__ 4
// PPC-DARWIN:#define __SIZEOF_POINTER__ 4
// PPC-DARWIN:#define __SIZEOF_PTRDIFF_T__ 4
// PPC-DARWIN:#define __SIZEOF_SHORT__ 2
// PPC-DARWIN:#define __SIZEOF_SIZE_T__ 4
// PPC-DARWIN:#define __SIZEOF_WCHAR_T__ 4
// PPC-DARWIN:#define __SIZEOF_WINT_T__ 4
// PPC-DARWIN:#define __SIZE_MAX__ 4294967295UL
// PPC-DARWIN:#define __SIZE_TYPE__ long unsigned int
// PPC-DARWIN:#define __SIZE_WIDTH__ 32
// PPC-DARWIN:#define __STDC_HOSTED__ 0
// PPC-DARWIN:#define __STDC_VERSION__ 201112L
// PPC-DARWIN:#define __STDC__ 1
// PPC-DARWIN:#define __UINT16_C_SUFFIX__
// PPC-DARWIN:#define __UINT16_MAX__ 65535
// PPC-DARWIN:#define __UINT16_TYPE__ unsigned short
// PPC-DARWIN:#define __UINT32_C_SUFFIX__ U
// PPC-DARWIN:#define __UINT32_MAX__ 4294967295U
// PPC-DARWIN:#define __UINT32_TYPE__ unsigned int
// PPC-DARWIN:#define __UINT64_C_SUFFIX__ ULL
// PPC-DARWIN:#define __UINT64_MAX__ 18446744073709551615ULL
// PPC-DARWIN:#define __UINT64_TYPE__ long long unsigned int
// PPC-DARWIN:#define __UINT8_C_SUFFIX__
// PPC-DARWIN:#define __UINT8_MAX__ 255
// PPC-DARWIN:#define __UINT8_TYPE__ unsigned char
// PPC-DARWIN:#define __UINTMAX_C_SUFFIX__ ULL
// PPC-DARWIN:#define __UINTMAX_MAX__ 18446744073709551615ULL
// PPC-DARWIN:#define __UINTMAX_TYPE__ long long unsigned int
// PPC-DARWIN:#define __UINTMAX_WIDTH__ 64
// PPC-DARWIN:#define __UINTPTR_MAX__ 4294967295UL
// PPC-DARWIN:#define __UINTPTR_TYPE__ long unsigned int
// PPC-DARWIN:#define __UINTPTR_WIDTH__ 32
// PPC-DARWIN:#define __UINT_FAST16_MAX__ 65535
// PPC-DARWIN:#define __UINT_FAST16_TYPE__ unsigned short
// PPC-DARWIN:#define __UINT_FAST32_MAX__ 4294967295U
// PPC-DARWIN:#define __UINT_FAST32_TYPE__ unsigned int
// PPC-DARWIN:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// PPC-DARWIN:#define __UINT_FAST64_TYPE__ long long unsigned int
// PPC-DARWIN:#define __UINT_FAST8_MAX__ 255
// PPC-DARWIN:#define __UINT_FAST8_TYPE__ unsigned char
// PPC-DARWIN:#define __UINT_LEAST16_MAX__ 65535
// PPC-DARWIN:#define __UINT_LEAST16_TYPE__ unsigned short
// PPC-DARWIN:#define __UINT_LEAST32_MAX__ 4294967295U
// PPC-DARWIN:#define __UINT_LEAST32_TYPE__ unsigned int
// PPC-DARWIN:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// PPC-DARWIN:#define __UINT_LEAST64_TYPE__ long long unsigned int
// PPC-DARWIN:#define __UINT_LEAST8_MAX__ 255
// PPC-DARWIN:#define __UINT_LEAST8_TYPE__ unsigned char
// PPC-DARWIN:#define __USER_LABEL_PREFIX__ _
// PPC-DARWIN:#define __WCHAR_MAX__ 2147483647
// PPC-DARWIN:#define __WCHAR_TYPE__ int
// PPC-DARWIN:#define __WCHAR_WIDTH__ 32
// PPC-DARWIN:#define __WINT_TYPE__ int
// PPC-DARWIN:#define __WINT_WIDTH__ 32
// PPC-DARWIN:#define __powerpc__ 1
// PPC-DARWIN:#define __ppc__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-apple-darwin8 < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-DARWIN %s
// PPC64-DARWIN:#define __STRUCT_PARM_ALIGN__ 16
// RUN: %clang_cc1 -x cl -E -dM -ffreestanding -triple=amdgcn < /dev/null | FileCheck -match-full-lines -check-prefix AMDGCN --check-prefix AMDGPU %s
// RUN: %clang_cc1 -x cl -E -dM -ffreestanding -triple=r600 -target-cpu caicos < /dev/null | FileCheck -match-full-lines --check-prefix AMDGPU %s
//
// AMDGPU:#define __ENDIAN_LITTLE__ 1
// AMDGPU:#define cl_khr_byte_addressable_store 1
// AMDGCN:#define cl_khr_fp64 1
// AMDGPU:#define cl_khr_global_int32_base_atomics 1
// AMDGPU:#define cl_khr_global_int32_extended_atomics 1
// AMDGPU:#define cl_khr_local_int32_base_atomics 1
// AMDGPU:#define cl_khr_local_int32_extended_atomics 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=s390x-none-none -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix S390X %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=s390x-none-none -fno-signed-char < /dev/null | FileCheck -match-full-lines -check-prefix S390X -check-prefix S390X-CXX %s
//
// S390X:#define __BIGGEST_ALIGNMENT__ 8
// S390X:#define __CHAR16_TYPE__ unsigned short
// S390X:#define __CHAR32_TYPE__ unsigned int
// S390X:#define __CHAR_BIT__ 8
// S390X:#define __CHAR_UNSIGNED__ 1
// S390X:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// S390X:#define __DBL_DIG__ 15
// S390X:#define __DBL_EPSILON__ 2.2204460492503131e-16
// S390X:#define __DBL_HAS_DENORM__ 1
// S390X:#define __DBL_HAS_INFINITY__ 1
// S390X:#define __DBL_HAS_QUIET_NAN__ 1
// S390X:#define __DBL_MANT_DIG__ 53
// S390X:#define __DBL_MAX_10_EXP__ 308
// S390X:#define __DBL_MAX_EXP__ 1024
// S390X:#define __DBL_MAX__ 1.7976931348623157e+308
// S390X:#define __DBL_MIN_10_EXP__ (-307)
// S390X:#define __DBL_MIN_EXP__ (-1021)
// S390X:#define __DBL_MIN__ 2.2250738585072014e-308
// S390X:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// S390X:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// S390X:#define __FLT_DIG__ 6
// S390X:#define __FLT_EPSILON__ 1.19209290e-7F
// S390X:#define __FLT_EVAL_METHOD__ 0
// S390X:#define __FLT_HAS_DENORM__ 1
// S390X:#define __FLT_HAS_INFINITY__ 1
// S390X:#define __FLT_HAS_QUIET_NAN__ 1
// S390X:#define __FLT_MANT_DIG__ 24
// S390X:#define __FLT_MAX_10_EXP__ 38
// S390X:#define __FLT_MAX_EXP__ 128
// S390X:#define __FLT_MAX__ 3.40282347e+38F
// S390X:#define __FLT_MIN_10_EXP__ (-37)
// S390X:#define __FLT_MIN_EXP__ (-125)
// S390X:#define __FLT_MIN__ 1.17549435e-38F
// S390X:#define __FLT_RADIX__ 2
// S390X:#define __INT16_C_SUFFIX__
// S390X:#define __INT16_FMTd__ "hd"
// S390X:#define __INT16_FMTi__ "hi"
// S390X:#define __INT16_MAX__ 32767
// S390X:#define __INT16_TYPE__ short
// S390X:#define __INT32_C_SUFFIX__
// S390X:#define __INT32_FMTd__ "d"
// S390X:#define __INT32_FMTi__ "i"
// S390X:#define __INT32_MAX__ 2147483647
// S390X:#define __INT32_TYPE__ int
// S390X:#define __INT64_C_SUFFIX__ L
// S390X:#define __INT64_FMTd__ "ld"
// S390X:#define __INT64_FMTi__ "li"
// S390X:#define __INT64_MAX__ 9223372036854775807L
// S390X:#define __INT64_TYPE__ long int
// S390X:#define __INT8_C_SUFFIX__
// S390X:#define __INT8_FMTd__ "hhd"
// S390X:#define __INT8_FMTi__ "hhi"
// S390X:#define __INT8_MAX__ 127
// S390X:#define __INT8_TYPE__ signed char
// S390X:#define __INTMAX_C_SUFFIX__ L
// S390X:#define __INTMAX_FMTd__ "ld"
// S390X:#define __INTMAX_FMTi__ "li"
// S390X:#define __INTMAX_MAX__ 9223372036854775807L
// S390X:#define __INTMAX_TYPE__ long int
// S390X:#define __INTMAX_WIDTH__ 64
// S390X:#define __INTPTR_FMTd__ "ld"
// S390X:#define __INTPTR_FMTi__ "li"
// S390X:#define __INTPTR_MAX__ 9223372036854775807L
// S390X:#define __INTPTR_TYPE__ long int
// S390X:#define __INTPTR_WIDTH__ 64
// S390X:#define __INT_FAST16_FMTd__ "hd"
// S390X:#define __INT_FAST16_FMTi__ "hi"
// S390X:#define __INT_FAST16_MAX__ 32767
// S390X:#define __INT_FAST16_TYPE__ short
// S390X:#define __INT_FAST32_FMTd__ "d"
// S390X:#define __INT_FAST32_FMTi__ "i"
// S390X:#define __INT_FAST32_MAX__ 2147483647
// S390X:#define __INT_FAST32_TYPE__ int
// S390X:#define __INT_FAST64_FMTd__ "ld"
// S390X:#define __INT_FAST64_FMTi__ "li"
// S390X:#define __INT_FAST64_MAX__ 9223372036854775807L
// S390X:#define __INT_FAST64_TYPE__ long int
// S390X:#define __INT_FAST8_FMTd__ "hhd"
// S390X:#define __INT_FAST8_FMTi__ "hhi"
// S390X:#define __INT_FAST8_MAX__ 127
// S390X:#define __INT_FAST8_TYPE__ signed char
// S390X:#define __INT_LEAST16_FMTd__ "hd"
// S390X:#define __INT_LEAST16_FMTi__ "hi"
// S390X:#define __INT_LEAST16_MAX__ 32767
// S390X:#define __INT_LEAST16_TYPE__ short
// S390X:#define __INT_LEAST32_FMTd__ "d"
// S390X:#define __INT_LEAST32_FMTi__ "i"
// S390X:#define __INT_LEAST32_MAX__ 2147483647
// S390X:#define __INT_LEAST32_TYPE__ int
// S390X:#define __INT_LEAST64_FMTd__ "ld"
// S390X:#define __INT_LEAST64_FMTi__ "li"
// S390X:#define __INT_LEAST64_MAX__ 9223372036854775807L
// S390X:#define __INT_LEAST64_TYPE__ long int
// S390X:#define __INT_LEAST8_FMTd__ "hhd"
// S390X:#define __INT_LEAST8_FMTi__ "hhi"
// S390X:#define __INT_LEAST8_MAX__ 127
// S390X:#define __INT_LEAST8_TYPE__ signed char
// S390X:#define __INT_MAX__ 2147483647
// S390X:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
// S390X:#define __LDBL_DIG__ 33
// S390X:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// S390X:#define __LDBL_HAS_DENORM__ 1
// S390X:#define __LDBL_HAS_INFINITY__ 1
// S390X:#define __LDBL_HAS_QUIET_NAN__ 1
// S390X:#define __LDBL_MANT_DIG__ 113
// S390X:#define __LDBL_MAX_10_EXP__ 4932
// S390X:#define __LDBL_MAX_EXP__ 16384
// S390X:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
// S390X:#define __LDBL_MIN_10_EXP__ (-4931)
// S390X:#define __LDBL_MIN_EXP__ (-16381)
// S390X:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// S390X:#define __LONG_LONG_MAX__ 9223372036854775807LL
// S390X:#define __LONG_MAX__ 9223372036854775807L
// S390X:#define __NO_INLINE__ 1
// S390X:#define __POINTER_WIDTH__ 64
// S390X:#define __PTRDIFF_TYPE__ long int
// S390X:#define __PTRDIFF_WIDTH__ 64
// S390X:#define __SCHAR_MAX__ 127
// S390X:#define __SHRT_MAX__ 32767
// S390X:#define __SIG_ATOMIC_MAX__ 2147483647
// S390X:#define __SIG_ATOMIC_WIDTH__ 32
// S390X:#define __SIZEOF_DOUBLE__ 8
// S390X:#define __SIZEOF_FLOAT__ 4
// S390X:#define __SIZEOF_INT__ 4
// S390X:#define __SIZEOF_LONG_DOUBLE__ 16
// S390X:#define __SIZEOF_LONG_LONG__ 8
// S390X:#define __SIZEOF_LONG__ 8
// S390X:#define __SIZEOF_POINTER__ 8
// S390X:#define __SIZEOF_PTRDIFF_T__ 8
// S390X:#define __SIZEOF_SHORT__ 2
// S390X:#define __SIZEOF_SIZE_T__ 8
// S390X:#define __SIZEOF_WCHAR_T__ 4
// S390X:#define __SIZEOF_WINT_T__ 4
// S390X:#define __SIZE_TYPE__ long unsigned int
// S390X:#define __SIZE_WIDTH__ 64
// S390X-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8UL
// S390X:#define __UINT16_C_SUFFIX__
// S390X:#define __UINT16_MAX__ 65535
// S390X:#define __UINT16_TYPE__ unsigned short
// S390X:#define __UINT32_C_SUFFIX__ U
// S390X:#define __UINT32_MAX__ 4294967295U
// S390X:#define __UINT32_TYPE__ unsigned int
// S390X:#define __UINT64_C_SUFFIX__ UL
// S390X:#define __UINT64_MAX__ 18446744073709551615UL
// S390X:#define __UINT64_TYPE__ long unsigned int
// S390X:#define __UINT8_C_SUFFIX__
// S390X:#define __UINT8_MAX__ 255
// S390X:#define __UINT8_TYPE__ unsigned char
// S390X:#define __UINTMAX_C_SUFFIX__ UL
// S390X:#define __UINTMAX_MAX__ 18446744073709551615UL
// S390X:#define __UINTMAX_TYPE__ long unsigned int
// S390X:#define __UINTMAX_WIDTH__ 64
// S390X:#define __UINTPTR_MAX__ 18446744073709551615UL
// S390X:#define __UINTPTR_TYPE__ long unsigned int
// S390X:#define __UINTPTR_WIDTH__ 64
// S390X:#define __UINT_FAST16_MAX__ 65535
// S390X:#define __UINT_FAST16_TYPE__ unsigned short
// S390X:#define __UINT_FAST32_MAX__ 4294967295U
// S390X:#define __UINT_FAST32_TYPE__ unsigned int
// S390X:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// S390X:#define __UINT_FAST64_TYPE__ long unsigned int
// S390X:#define __UINT_FAST8_MAX__ 255
// S390X:#define __UINT_FAST8_TYPE__ unsigned char
// S390X:#define __UINT_LEAST16_MAX__ 65535
// S390X:#define __UINT_LEAST16_TYPE__ unsigned short
// S390X:#define __UINT_LEAST32_MAX__ 4294967295U
// S390X:#define __UINT_LEAST32_TYPE__ unsigned int
// S390X:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// S390X:#define __UINT_LEAST64_TYPE__ long unsigned int
// S390X:#define __UINT_LEAST8_MAX__ 255
// S390X:#define __UINT_LEAST8_TYPE__ unsigned char
// S390X:#define __USER_LABEL_PREFIX__
// S390X:#define __WCHAR_MAX__ 2147483647
// S390X:#define __WCHAR_TYPE__ int
// S390X:#define __WCHAR_WIDTH__ 32
// S390X:#define __WINT_TYPE__ int
// S390X:#define __WINT_WIDTH__ 32
// S390X:#define __s390__ 1
// S390X:#define __s390x__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=sparc-none-none < /dev/null | FileCheck -match-full-lines -check-prefix SPARC -check-prefix SPARC-DEFAULT %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=sparc-rtems-elf < /dev/null | FileCheck -match-full-lines -check-prefix SPARC -check-prefix SPARC-DEFAULT %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=sparc-none-netbsd < /dev/null | FileCheck -match-full-lines -check-prefix SPARC -check-prefix SPARC-NETOPENBSD %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=sparc-none-openbsd < /dev/null | FileCheck -match-full-lines -check-prefix SPARC -check-prefix SPARC-NETOPENBSD %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=sparc-none-none < /dev/null | FileCheck -match-full-lines -check-prefix SPARC -check-prefix SPARC-DEFAULT -check-prefix SPARC-DEFAULT-CXX %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=sparc-none-openbsd < /dev/null | FileCheck -match-full-lines -check-prefix SPARC -check-prefix SPARC-NETOPENBSD -check-prefix SPARC-NETOPENBSD-CXX %s
//
// SPARC-NOT:#define _LP64
// SPARC:#define __BIGGEST_ALIGNMENT__ 8
// SPARC:#define __BIG_ENDIAN__ 1
// SPARC:#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
// SPARC:#define __CHAR16_TYPE__ unsigned short
// SPARC:#define __CHAR32_TYPE__ unsigned int
// SPARC:#define __CHAR_BIT__ 8
// SPARC:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// SPARC:#define __DBL_DIG__ 15
// SPARC:#define __DBL_EPSILON__ 2.2204460492503131e-16
// SPARC:#define __DBL_HAS_DENORM__ 1
// SPARC:#define __DBL_HAS_INFINITY__ 1
// SPARC:#define __DBL_HAS_QUIET_NAN__ 1
// SPARC:#define __DBL_MANT_DIG__ 53
// SPARC:#define __DBL_MAX_10_EXP__ 308
// SPARC:#define __DBL_MAX_EXP__ 1024
// SPARC:#define __DBL_MAX__ 1.7976931348623157e+308
// SPARC:#define __DBL_MIN_10_EXP__ (-307)
// SPARC:#define __DBL_MIN_EXP__ (-1021)
// SPARC:#define __DBL_MIN__ 2.2250738585072014e-308
// SPARC:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// SPARC:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// SPARC:#define __FLT_DIG__ 6
// SPARC:#define __FLT_EPSILON__ 1.19209290e-7F
// SPARC:#define __FLT_EVAL_METHOD__ 0
// SPARC:#define __FLT_HAS_DENORM__ 1
// SPARC:#define __FLT_HAS_INFINITY__ 1
// SPARC:#define __FLT_HAS_QUIET_NAN__ 1
// SPARC:#define __FLT_MANT_DIG__ 24
// SPARC:#define __FLT_MAX_10_EXP__ 38
// SPARC:#define __FLT_MAX_EXP__ 128
// SPARC:#define __FLT_MAX__ 3.40282347e+38F
// SPARC:#define __FLT_MIN_10_EXP__ (-37)
// SPARC:#define __FLT_MIN_EXP__ (-125)
// SPARC:#define __FLT_MIN__ 1.17549435e-38F
// SPARC:#define __FLT_RADIX__ 2
// SPARC:#define __GCC_ATOMIC_LLONG_LOCK_FREE 1
// SPARC:#define __INT16_C_SUFFIX__
// SPARC:#define __INT16_FMTd__ "hd"
// SPARC:#define __INT16_FMTi__ "hi"
// SPARC:#define __INT16_MAX__ 32767
// SPARC:#define __INT16_TYPE__ short
// SPARC:#define __INT32_C_SUFFIX__
// SPARC:#define __INT32_FMTd__ "d"
// SPARC:#define __INT32_FMTi__ "i"
// SPARC:#define __INT32_MAX__ 2147483647
// SPARC:#define __INT32_TYPE__ int
// SPARC:#define __INT64_C_SUFFIX__ LL
// SPARC:#define __INT64_FMTd__ "lld"
// SPARC:#define __INT64_FMTi__ "lli"
// SPARC:#define __INT64_MAX__ 9223372036854775807LL
// SPARC:#define __INT64_TYPE__ long long int
// SPARC:#define __INT8_C_SUFFIX__
// SPARC:#define __INT8_FMTd__ "hhd"
// SPARC:#define __INT8_FMTi__ "hhi"
// SPARC:#define __INT8_MAX__ 127
// SPARC:#define __INT8_TYPE__ signed char
// SPARC:#define __INTMAX_C_SUFFIX__ LL
// SPARC:#define __INTMAX_FMTd__ "lld"
// SPARC:#define __INTMAX_FMTi__ "lli"
// SPARC:#define __INTMAX_MAX__ 9223372036854775807LL
// SPARC:#define __INTMAX_TYPE__ long long int
// SPARC:#define __INTMAX_WIDTH__ 64
// SPARC-DEFAULT:#define __INTPTR_FMTd__ "d"
// SPARC-DEFAULT:#define __INTPTR_FMTi__ "i"
// SPARC-DEFAULT:#define __INTPTR_MAX__ 2147483647
// SPARC-DEFAULT:#define __INTPTR_TYPE__ int
// SPARC-NETOPENBSD:#define __INTPTR_FMTd__ "ld"
// SPARC-NETOPENBSD:#define __INTPTR_FMTi__ "li"
// SPARC-NETOPENBSD:#define __INTPTR_MAX__ 2147483647L
// SPARC-NETOPENBSD:#define __INTPTR_TYPE__ long int
// SPARC:#define __INTPTR_WIDTH__ 32
// SPARC:#define __INT_FAST16_FMTd__ "hd"
// SPARC:#define __INT_FAST16_FMTi__ "hi"
// SPARC:#define __INT_FAST16_MAX__ 32767
// SPARC:#define __INT_FAST16_TYPE__ short
// SPARC:#define __INT_FAST32_FMTd__ "d"
// SPARC:#define __INT_FAST32_FMTi__ "i"
// SPARC:#define __INT_FAST32_MAX__ 2147483647
// SPARC:#define __INT_FAST32_TYPE__ int
// SPARC:#define __INT_FAST64_FMTd__ "lld"
// SPARC:#define __INT_FAST64_FMTi__ "lli"
// SPARC:#define __INT_FAST64_MAX__ 9223372036854775807LL
// SPARC:#define __INT_FAST64_TYPE__ long long int
// SPARC:#define __INT_FAST8_FMTd__ "hhd"
// SPARC:#define __INT_FAST8_FMTi__ "hhi"
// SPARC:#define __INT_FAST8_MAX__ 127
// SPARC:#define __INT_FAST8_TYPE__ signed char
// SPARC:#define __INT_LEAST16_FMTd__ "hd"
// SPARC:#define __INT_LEAST16_FMTi__ "hi"
// SPARC:#define __INT_LEAST16_MAX__ 32767
// SPARC:#define __INT_LEAST16_TYPE__ short
// SPARC:#define __INT_LEAST32_FMTd__ "d"
// SPARC:#define __INT_LEAST32_FMTi__ "i"
// SPARC:#define __INT_LEAST32_MAX__ 2147483647
// SPARC:#define __INT_LEAST32_TYPE__ int
// SPARC:#define __INT_LEAST64_FMTd__ "lld"
// SPARC:#define __INT_LEAST64_FMTi__ "lli"
// SPARC:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// SPARC:#define __INT_LEAST64_TYPE__ long long int
// SPARC:#define __INT_LEAST8_FMTd__ "hhd"
// SPARC:#define __INT_LEAST8_FMTi__ "hhi"
// SPARC:#define __INT_LEAST8_MAX__ 127
// SPARC:#define __INT_LEAST8_TYPE__ signed char
// SPARC:#define __INT_MAX__ 2147483647
// SPARC:#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
// SPARC:#define __LDBL_DIG__ 15
// SPARC:#define __LDBL_EPSILON__ 2.2204460492503131e-16L
// SPARC:#define __LDBL_HAS_DENORM__ 1
// SPARC:#define __LDBL_HAS_INFINITY__ 1
// SPARC:#define __LDBL_HAS_QUIET_NAN__ 1
// SPARC:#define __LDBL_MANT_DIG__ 53
// SPARC:#define __LDBL_MAX_10_EXP__ 308
// SPARC:#define __LDBL_MAX_EXP__ 1024
// SPARC:#define __LDBL_MAX__ 1.7976931348623157e+308L
// SPARC:#define __LDBL_MIN_10_EXP__ (-307)
// SPARC:#define __LDBL_MIN_EXP__ (-1021)
// SPARC:#define __LDBL_MIN__ 2.2250738585072014e-308L
// SPARC:#define __LONG_LONG_MAX__ 9223372036854775807LL
// SPARC:#define __LONG_MAX__ 2147483647L
// SPARC-NOT:#define __LP64__
// SPARC:#define __POINTER_WIDTH__ 32
// SPARC-DEFAULT:#define __PTRDIFF_TYPE__ int
// SPARC-NETOPENBSD:#define __PTRDIFF_TYPE__ long int
// SPARC:#define __PTRDIFF_WIDTH__ 32
// SPARC:#define __REGISTER_PREFIX__
// SPARC:#define __SCHAR_MAX__ 127
// SPARC:#define __SHRT_MAX__ 32767
// SPARC:#define __SIG_ATOMIC_MAX__ 2147483647
// SPARC:#define __SIG_ATOMIC_WIDTH__ 32
// SPARC:#define __SIZEOF_DOUBLE__ 8
// SPARC:#define __SIZEOF_FLOAT__ 4
// SPARC:#define __SIZEOF_INT__ 4
// SPARC:#define __SIZEOF_LONG_DOUBLE__ 8
// SPARC:#define __SIZEOF_LONG_LONG__ 8
// SPARC:#define __SIZEOF_LONG__ 4
// SPARC:#define __SIZEOF_POINTER__ 4
// SPARC:#define __SIZEOF_PTRDIFF_T__ 4
// SPARC:#define __SIZEOF_SHORT__ 2
// SPARC:#define __SIZEOF_SIZE_T__ 4
// SPARC:#define __SIZEOF_WCHAR_T__ 4
// SPARC:#define __SIZEOF_WINT_T__ 4
// SPARC-DEFAULT:#define __SIZE_MAX__ 4294967295U
// SPARC-DEFAULT:#define __SIZE_TYPE__ unsigned int
// SPARC-NETOPENBSD:#define __SIZE_MAX__ 4294967295UL
// SPARC-NETOPENBSD:#define __SIZE_TYPE__ long unsigned int
// SPARC:#define __SIZE_WIDTH__ 32
// SPARC-DEFAULT-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
// SPARC-NETOPENBSD-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8UL
// SPARC:#define __UINT16_C_SUFFIX__
// SPARC:#define __UINT16_MAX__ 65535
// SPARC:#define __UINT16_TYPE__ unsigned short
// SPARC:#define __UINT32_C_SUFFIX__ U
// SPARC:#define __UINT32_MAX__ 4294967295U
// SPARC:#define __UINT32_TYPE__ unsigned int
// SPARC:#define __UINT64_C_SUFFIX__ ULL
// SPARC:#define __UINT64_MAX__ 18446744073709551615ULL
// SPARC:#define __UINT64_TYPE__ long long unsigned int
// SPARC:#define __UINT8_C_SUFFIX__
// SPARC:#define __UINT8_MAX__ 255
// SPARC:#define __UINT8_TYPE__ unsigned char
// SPARC:#define __UINTMAX_C_SUFFIX__ ULL
// SPARC:#define __UINTMAX_MAX__ 18446744073709551615ULL
// SPARC:#define __UINTMAX_TYPE__ long long unsigned int
// SPARC:#define __UINTMAX_WIDTH__ 64
// SPARC-DEFAULT:#define __UINTPTR_MAX__ 4294967295U
// SPARC-DEFAULT:#define __UINTPTR_TYPE__ unsigned int
// SPARC-NETOPENBSD:#define __UINTPTR_MAX__ 4294967295UL
// SPARC-NETOPENBSD:#define __UINTPTR_TYPE__ long unsigned int
// SPARC:#define __UINTPTR_WIDTH__ 32
// SPARC:#define __UINT_FAST16_MAX__ 65535
// SPARC:#define __UINT_FAST16_TYPE__ unsigned short
// SPARC:#define __UINT_FAST32_MAX__ 4294967295U
// SPARC:#define __UINT_FAST32_TYPE__ unsigned int
// SPARC:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// SPARC:#define __UINT_FAST64_TYPE__ long long unsigned int
// SPARC:#define __UINT_FAST8_MAX__ 255
// SPARC:#define __UINT_FAST8_TYPE__ unsigned char
// SPARC:#define __UINT_LEAST16_MAX__ 65535
// SPARC:#define __UINT_LEAST16_TYPE__ unsigned short
// SPARC:#define __UINT_LEAST32_MAX__ 4294967295U
// SPARC:#define __UINT_LEAST32_TYPE__ unsigned int
// SPARC:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// SPARC:#define __UINT_LEAST64_TYPE__ long long unsigned int
// SPARC:#define __UINT_LEAST8_MAX__ 255
// SPARC:#define __UINT_LEAST8_TYPE__ unsigned char
// SPARC:#define __USER_LABEL_PREFIX__
// SPARC:#define __VERSION__ "4.2.1 Compatible{{.*}}
// SPARC:#define __WCHAR_MAX__ 2147483647
// SPARC:#define __WCHAR_TYPE__ int
// SPARC:#define __WCHAR_WIDTH__ 32
// SPARC:#define __WINT_TYPE__ int
// SPARC:#define __WINT_WIDTH__ 32
// SPARC:#define __sparc 1
// SPARC:#define __sparc__ 1
// SPARC:#define __sparcv8 1
// SPARC:#define sparc 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=tce-none-none < /dev/null | FileCheck -match-full-lines -check-prefix TCE %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=tce-none-none < /dev/null | FileCheck -match-full-lines -check-prefix TCE -check-prefix TCE-CXX %s
//
// TCE-NOT:#define _LP64
// TCE:#define __BIGGEST_ALIGNMENT__ 4
// TCE:#define __BIG_ENDIAN__ 1
// TCE:#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
// TCE:#define __CHAR16_TYPE__ unsigned short
// TCE:#define __CHAR32_TYPE__ unsigned int
// TCE:#define __CHAR_BIT__ 8
// TCE:#define __DBL_DENORM_MIN__ 1.40129846e-45
// TCE:#define __DBL_DIG__ 6
// TCE:#define __DBL_EPSILON__ 1.19209290e-7
// TCE:#define __DBL_HAS_DENORM__ 1
// TCE:#define __DBL_HAS_INFINITY__ 1
// TCE:#define __DBL_HAS_QUIET_NAN__ 1
// TCE:#define __DBL_MANT_DIG__ 24
// TCE:#define __DBL_MAX_10_EXP__ 38
// TCE:#define __DBL_MAX_EXP__ 128
// TCE:#define __DBL_MAX__ 3.40282347e+38
// TCE:#define __DBL_MIN_10_EXP__ (-37)
// TCE:#define __DBL_MIN_EXP__ (-125)
// TCE:#define __DBL_MIN__ 1.17549435e-38
// TCE:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// TCE:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// TCE:#define __FLT_DIG__ 6
// TCE:#define __FLT_EPSILON__ 1.19209290e-7F
// TCE:#define __FLT_EVAL_METHOD__ 0
// TCE:#define __FLT_HAS_DENORM__ 1
// TCE:#define __FLT_HAS_INFINITY__ 1
// TCE:#define __FLT_HAS_QUIET_NAN__ 1
// TCE:#define __FLT_MANT_DIG__ 24
// TCE:#define __FLT_MAX_10_EXP__ 38
// TCE:#define __FLT_MAX_EXP__ 128
// TCE:#define __FLT_MAX__ 3.40282347e+38F
// TCE:#define __FLT_MIN_10_EXP__ (-37)
// TCE:#define __FLT_MIN_EXP__ (-125)
// TCE:#define __FLT_MIN__ 1.17549435e-38F
// TCE:#define __FLT_RADIX__ 2
// TCE:#define __INT16_C_SUFFIX__
// TCE:#define __INT16_FMTd__ "hd"
// TCE:#define __INT16_FMTi__ "hi"
// TCE:#define __INT16_MAX__ 32767
// TCE:#define __INT16_TYPE__ short
// TCE:#define __INT32_C_SUFFIX__
// TCE:#define __INT32_FMTd__ "d"
// TCE:#define __INT32_FMTi__ "i"
// TCE:#define __INT32_MAX__ 2147483647
// TCE:#define __INT32_TYPE__ int
// TCE:#define __INT8_C_SUFFIX__
// TCE:#define __INT8_FMTd__ "hhd"
// TCE:#define __INT8_FMTi__ "hhi"
// TCE:#define __INT8_MAX__ 127
// TCE:#define __INT8_TYPE__ signed char
// TCE:#define __INTMAX_C_SUFFIX__ L
// TCE:#define __INTMAX_FMTd__ "ld"
// TCE:#define __INTMAX_FMTi__ "li"
// TCE:#define __INTMAX_MAX__ 2147483647L
// TCE:#define __INTMAX_TYPE__ long int
// TCE:#define __INTMAX_WIDTH__ 32
// TCE:#define __INTPTR_FMTd__ "d"
// TCE:#define __INTPTR_FMTi__ "i"
// TCE:#define __INTPTR_MAX__ 2147483647
// TCE:#define __INTPTR_TYPE__ int
// TCE:#define __INTPTR_WIDTH__ 32
// TCE:#define __INT_FAST16_FMTd__ "hd"
// TCE:#define __INT_FAST16_FMTi__ "hi"
// TCE:#define __INT_FAST16_MAX__ 32767
// TCE:#define __INT_FAST16_TYPE__ short
// TCE:#define __INT_FAST32_FMTd__ "d"
// TCE:#define __INT_FAST32_FMTi__ "i"
// TCE:#define __INT_FAST32_MAX__ 2147483647
// TCE:#define __INT_FAST32_TYPE__ int
// TCE:#define __INT_FAST8_FMTd__ "hhd"
// TCE:#define __INT_FAST8_FMTi__ "hhi"
// TCE:#define __INT_FAST8_MAX__ 127
// TCE:#define __INT_FAST8_TYPE__ signed char
// TCE:#define __INT_LEAST16_FMTd__ "hd"
// TCE:#define __INT_LEAST16_FMTi__ "hi"
// TCE:#define __INT_LEAST16_MAX__ 32767
// TCE:#define __INT_LEAST16_TYPE__ short
// TCE:#define __INT_LEAST32_FMTd__ "d"
// TCE:#define __INT_LEAST32_FMTi__ "i"
// TCE:#define __INT_LEAST32_MAX__ 2147483647
// TCE:#define __INT_LEAST32_TYPE__ int
// TCE:#define __INT_LEAST8_FMTd__ "hhd"
// TCE:#define __INT_LEAST8_FMTi__ "hhi"
// TCE:#define __INT_LEAST8_MAX__ 127
// TCE:#define __INT_LEAST8_TYPE__ signed char
// TCE:#define __INT_MAX__ 2147483647
// TCE:#define __LDBL_DENORM_MIN__ 1.40129846e-45L
// TCE:#define __LDBL_DIG__ 6
// TCE:#define __LDBL_EPSILON__ 1.19209290e-7L
// TCE:#define __LDBL_HAS_DENORM__ 1
// TCE:#define __LDBL_HAS_INFINITY__ 1
// TCE:#define __LDBL_HAS_QUIET_NAN__ 1
// TCE:#define __LDBL_MANT_DIG__ 24
// TCE:#define __LDBL_MAX_10_EXP__ 38
// TCE:#define __LDBL_MAX_EXP__ 128
// TCE:#define __LDBL_MAX__ 3.40282347e+38L
// TCE:#define __LDBL_MIN_10_EXP__ (-37)
// TCE:#define __LDBL_MIN_EXP__ (-125)
// TCE:#define __LDBL_MIN__ 1.17549435e-38L
// TCE:#define __LONG_LONG_MAX__ 2147483647LL
// TCE:#define __LONG_MAX__ 2147483647L
// TCE-NOT:#define __LP64__
// TCE:#define __POINTER_WIDTH__ 32
// TCE:#define __PTRDIFF_TYPE__ int
// TCE:#define __PTRDIFF_WIDTH__ 32
// TCE:#define __SCHAR_MAX__ 127
// TCE:#define __SHRT_MAX__ 32767
// TCE:#define __SIG_ATOMIC_MAX__ 2147483647
// TCE:#define __SIG_ATOMIC_WIDTH__ 32
// TCE:#define __SIZEOF_DOUBLE__ 4
// TCE:#define __SIZEOF_FLOAT__ 4
// TCE:#define __SIZEOF_INT__ 4
// TCE:#define __SIZEOF_LONG_DOUBLE__ 4
// TCE:#define __SIZEOF_LONG_LONG__ 4
// TCE:#define __SIZEOF_LONG__ 4
// TCE:#define __SIZEOF_POINTER__ 4
// TCE:#define __SIZEOF_PTRDIFF_T__ 4
// TCE:#define __SIZEOF_SHORT__ 2
// TCE:#define __SIZEOF_SIZE_T__ 4
// TCE:#define __SIZEOF_WCHAR_T__ 4
// TCE:#define __SIZEOF_WINT_T__ 4
// TCE:#define __SIZE_MAX__ 4294967295U
// TCE:#define __SIZE_TYPE__ unsigned int
// TCE:#define __SIZE_WIDTH__ 32
// TCE-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 4U
// TCE:#define __TCE_V1__ 1
// TCE:#define __TCE__ 1
// TCE:#define __UINT16_C_SUFFIX__
// TCE:#define __UINT16_MAX__ 65535
// TCE:#define __UINT16_TYPE__ unsigned short
// TCE:#define __UINT32_C_SUFFIX__ U
// TCE:#define __UINT32_MAX__ 4294967295U
// TCE:#define __UINT32_TYPE__ unsigned int
// TCE:#define __UINT8_C_SUFFIX__
// TCE:#define __UINT8_MAX__ 255
// TCE:#define __UINT8_TYPE__ unsigned char
// TCE:#define __UINTMAX_C_SUFFIX__ UL
// TCE:#define __UINTMAX_MAX__ 4294967295UL
// TCE:#define __UINTMAX_TYPE__ long unsigned int
// TCE:#define __UINTMAX_WIDTH__ 32
// TCE:#define __UINTPTR_MAX__ 4294967295U
// TCE:#define __UINTPTR_TYPE__ unsigned int
// TCE:#define __UINTPTR_WIDTH__ 32
// TCE:#define __UINT_FAST16_MAX__ 65535
// TCE:#define __UINT_FAST16_TYPE__ unsigned short
// TCE:#define __UINT_FAST32_MAX__ 4294967295U
// TCE:#define __UINT_FAST32_TYPE__ unsigned int
// TCE:#define __UINT_FAST8_MAX__ 255
// TCE:#define __UINT_FAST8_TYPE__ unsigned char
// TCE:#define __UINT_LEAST16_MAX__ 65535
// TCE:#define __UINT_LEAST16_TYPE__ unsigned short
// TCE:#define __UINT_LEAST32_MAX__ 4294967295U
// TCE:#define __UINT_LEAST32_TYPE__ unsigned int
// TCE:#define __UINT_LEAST8_MAX__ 255
// TCE:#define __UINT_LEAST8_TYPE__ unsigned char
// TCE:#define __USER_LABEL_PREFIX__
// TCE:#define __WCHAR_MAX__ 2147483647
// TCE:#define __WCHAR_TYPE__ int
// TCE:#define __WCHAR_WIDTH__ 32
// TCE:#define __WINT_TYPE__ int
// TCE:#define __WINT_WIDTH__ 32
// TCE:#define __tce 1
// TCE:#define __tce__ 1
// TCE:#define tce 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix X86_64 %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=x86_64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix X86_64 -check-prefix X86_64-CXX %s
//
// X86_64:#define _LP64 1
// X86_64-NOT:#define _LP32 1
// X86_64:#define __BIGGEST_ALIGNMENT__ 16
// X86_64:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// X86_64:#define __CHAR16_TYPE__ unsigned short
// X86_64:#define __CHAR32_TYPE__ unsigned int
// X86_64:#define __CHAR_BIT__ 8
// X86_64:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// X86_64:#define __DBL_DIG__ 15
// X86_64:#define __DBL_EPSILON__ 2.2204460492503131e-16
// X86_64:#define __DBL_HAS_DENORM__ 1
// X86_64:#define __DBL_HAS_INFINITY__ 1
// X86_64:#define __DBL_HAS_QUIET_NAN__ 1
// X86_64:#define __DBL_MANT_DIG__ 53
// X86_64:#define __DBL_MAX_10_EXP__ 308
// X86_64:#define __DBL_MAX_EXP__ 1024
// X86_64:#define __DBL_MAX__ 1.7976931348623157e+308
// X86_64:#define __DBL_MIN_10_EXP__ (-307)
// X86_64:#define __DBL_MIN_EXP__ (-1021)
// X86_64:#define __DBL_MIN__ 2.2250738585072014e-308
// X86_64:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// X86_64:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// X86_64:#define __FLT_DIG__ 6
// X86_64:#define __FLT_EPSILON__ 1.19209290e-7F
// X86_64:#define __FLT_EVAL_METHOD__ 0
// X86_64:#define __FLT_HAS_DENORM__ 1
// X86_64:#define __FLT_HAS_INFINITY__ 1
// X86_64:#define __FLT_HAS_QUIET_NAN__ 1
// X86_64:#define __FLT_MANT_DIG__ 24
// X86_64:#define __FLT_MAX_10_EXP__ 38
// X86_64:#define __FLT_MAX_EXP__ 128
// X86_64:#define __FLT_MAX__ 3.40282347e+38F
// X86_64:#define __FLT_MIN_10_EXP__ (-37)
// X86_64:#define __FLT_MIN_EXP__ (-125)
// X86_64:#define __FLT_MIN__ 1.17549435e-38F
// X86_64:#define __FLT_RADIX__ 2
// X86_64:#define __INT16_C_SUFFIX__
// X86_64:#define __INT16_FMTd__ "hd"
// X86_64:#define __INT16_FMTi__ "hi"
// X86_64:#define __INT16_MAX__ 32767
// X86_64:#define __INT16_TYPE__ short
// X86_64:#define __INT32_C_SUFFIX__
// X86_64:#define __INT32_FMTd__ "d"
// X86_64:#define __INT32_FMTi__ "i"
// X86_64:#define __INT32_MAX__ 2147483647
// X86_64:#define __INT32_TYPE__ int
// X86_64:#define __INT64_C_SUFFIX__ L
// X86_64:#define __INT64_FMTd__ "ld"
// X86_64:#define __INT64_FMTi__ "li"
// X86_64:#define __INT64_MAX__ 9223372036854775807L
// X86_64:#define __INT64_TYPE__ long int
// X86_64:#define __INT8_C_SUFFIX__
// X86_64:#define __INT8_FMTd__ "hhd"
// X86_64:#define __INT8_FMTi__ "hhi"
// X86_64:#define __INT8_MAX__ 127
// X86_64:#define __INT8_TYPE__ signed char
// X86_64:#define __INTMAX_C_SUFFIX__ L
// X86_64:#define __INTMAX_FMTd__ "ld"
// X86_64:#define __INTMAX_FMTi__ "li"
// X86_64:#define __INTMAX_MAX__ 9223372036854775807L
// X86_64:#define __INTMAX_TYPE__ long int
// X86_64:#define __INTMAX_WIDTH__ 64
// X86_64:#define __INTPTR_FMTd__ "ld"
// X86_64:#define __INTPTR_FMTi__ "li"
// X86_64:#define __INTPTR_MAX__ 9223372036854775807L
// X86_64:#define __INTPTR_TYPE__ long int
// X86_64:#define __INTPTR_WIDTH__ 64
// X86_64:#define __INT_FAST16_FMTd__ "hd"
// X86_64:#define __INT_FAST16_FMTi__ "hi"
// X86_64:#define __INT_FAST16_MAX__ 32767
// X86_64:#define __INT_FAST16_TYPE__ short
// X86_64:#define __INT_FAST32_FMTd__ "d"
// X86_64:#define __INT_FAST32_FMTi__ "i"
// X86_64:#define __INT_FAST32_MAX__ 2147483647
// X86_64:#define __INT_FAST32_TYPE__ int
// X86_64:#define __INT_FAST64_FMTd__ "ld"
// X86_64:#define __INT_FAST64_FMTi__ "li"
// X86_64:#define __INT_FAST64_MAX__ 9223372036854775807L
// X86_64:#define __INT_FAST64_TYPE__ long int
// X86_64:#define __INT_FAST8_FMTd__ "hhd"
// X86_64:#define __INT_FAST8_FMTi__ "hhi"
// X86_64:#define __INT_FAST8_MAX__ 127
// X86_64:#define __INT_FAST8_TYPE__ signed char
// X86_64:#define __INT_LEAST16_FMTd__ "hd"
// X86_64:#define __INT_LEAST16_FMTi__ "hi"
// X86_64:#define __INT_LEAST16_MAX__ 32767
// X86_64:#define __INT_LEAST16_TYPE__ short
// X86_64:#define __INT_LEAST32_FMTd__ "d"
// X86_64:#define __INT_LEAST32_FMTi__ "i"
// X86_64:#define __INT_LEAST32_MAX__ 2147483647
// X86_64:#define __INT_LEAST32_TYPE__ int
// X86_64:#define __INT_LEAST64_FMTd__ "ld"
// X86_64:#define __INT_LEAST64_FMTi__ "li"
// X86_64:#define __INT_LEAST64_MAX__ 9223372036854775807L
// X86_64:#define __INT_LEAST64_TYPE__ long int
// X86_64:#define __INT_LEAST8_FMTd__ "hhd"
// X86_64:#define __INT_LEAST8_FMTi__ "hhi"
// X86_64:#define __INT_LEAST8_MAX__ 127
// X86_64:#define __INT_LEAST8_TYPE__ signed char
// X86_64:#define __INT_MAX__ 2147483647
// X86_64:#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
// X86_64:#define __LDBL_DIG__ 18
// X86_64:#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
// X86_64:#define __LDBL_HAS_DENORM__ 1
// X86_64:#define __LDBL_HAS_INFINITY__ 1
// X86_64:#define __LDBL_HAS_QUIET_NAN__ 1
// X86_64:#define __LDBL_MANT_DIG__ 64
// X86_64:#define __LDBL_MAX_10_EXP__ 4932
// X86_64:#define __LDBL_MAX_EXP__ 16384
// X86_64:#define __LDBL_MAX__ 1.18973149535723176502e+4932L
// X86_64:#define __LDBL_MIN_10_EXP__ (-4931)
// X86_64:#define __LDBL_MIN_EXP__ (-16381)
// X86_64:#define __LDBL_MIN__ 3.36210314311209350626e-4932L
// X86_64:#define __LITTLE_ENDIAN__ 1
// X86_64:#define __LONG_LONG_MAX__ 9223372036854775807LL
// X86_64:#define __LONG_MAX__ 9223372036854775807L
// X86_64:#define __LP64__ 1
// X86_64-NOT:#define __ILP32__ 1
// X86_64:#define __MMX__ 1
// X86_64:#define __NO_MATH_INLINES 1
// X86_64:#define __POINTER_WIDTH__ 64
// X86_64:#define __PTRDIFF_TYPE__ long int
// X86_64:#define __PTRDIFF_WIDTH__ 64
// X86_64:#define __REGISTER_PREFIX__
// X86_64:#define __SCHAR_MAX__ 127
// X86_64:#define __SHRT_MAX__ 32767
// X86_64:#define __SIG_ATOMIC_MAX__ 2147483647
// X86_64:#define __SIG_ATOMIC_WIDTH__ 32
// X86_64:#define __SIZEOF_DOUBLE__ 8
// X86_64:#define __SIZEOF_FLOAT__ 4
// X86_64:#define __SIZEOF_INT__ 4
// X86_64:#define __SIZEOF_LONG_DOUBLE__ 16
// X86_64:#define __SIZEOF_LONG_LONG__ 8
// X86_64:#define __SIZEOF_LONG__ 8
// X86_64:#define __SIZEOF_POINTER__ 8
// X86_64:#define __SIZEOF_PTRDIFF_T__ 8
// X86_64:#define __SIZEOF_SHORT__ 2
// X86_64:#define __SIZEOF_SIZE_T__ 8
// X86_64:#define __SIZEOF_WCHAR_T__ 4
// X86_64:#define __SIZEOF_WINT_T__ 4
// X86_64:#define __SIZE_MAX__ 18446744073709551615UL
// X86_64:#define __SIZE_TYPE__ long unsigned int
// X86_64:#define __SIZE_WIDTH__ 64
// X86_64:#define __SSE2_MATH__ 1
// X86_64:#define __SSE2__ 1
// X86_64:#define __SSE_MATH__ 1
// X86_64:#define __SSE__ 1
// X86_64-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL
// X86_64:#define __UINT16_C_SUFFIX__
// X86_64:#define __UINT16_MAX__ 65535
// X86_64:#define __UINT16_TYPE__ unsigned short
// X86_64:#define __UINT32_C_SUFFIX__ U
// X86_64:#define __UINT32_MAX__ 4294967295U
// X86_64:#define __UINT32_TYPE__ unsigned int
// X86_64:#define __UINT64_C_SUFFIX__ UL
// X86_64:#define __UINT64_MAX__ 18446744073709551615UL
// X86_64:#define __UINT64_TYPE__ long unsigned int
// X86_64:#define __UINT8_C_SUFFIX__
// X86_64:#define __UINT8_MAX__ 255
// X86_64:#define __UINT8_TYPE__ unsigned char
// X86_64:#define __UINTMAX_C_SUFFIX__ UL
// X86_64:#define __UINTMAX_MAX__ 18446744073709551615UL
// X86_64:#define __UINTMAX_TYPE__ long unsigned int
// X86_64:#define __UINTMAX_WIDTH__ 64
// X86_64:#define __UINTPTR_MAX__ 18446744073709551615UL
// X86_64:#define __UINTPTR_TYPE__ long unsigned int
// X86_64:#define __UINTPTR_WIDTH__ 64
// X86_64:#define __UINT_FAST16_MAX__ 65535
// X86_64:#define __UINT_FAST16_TYPE__ unsigned short
// X86_64:#define __UINT_FAST32_MAX__ 4294967295U
// X86_64:#define __UINT_FAST32_TYPE__ unsigned int
// X86_64:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// X86_64:#define __UINT_FAST64_TYPE__ long unsigned int
// X86_64:#define __UINT_FAST8_MAX__ 255
// X86_64:#define __UINT_FAST8_TYPE__ unsigned char
// X86_64:#define __UINT_LEAST16_MAX__ 65535
// X86_64:#define __UINT_LEAST16_TYPE__ unsigned short
// X86_64:#define __UINT_LEAST32_MAX__ 4294967295U
// X86_64:#define __UINT_LEAST32_TYPE__ unsigned int
// X86_64:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// X86_64:#define __UINT_LEAST64_TYPE__ long unsigned int
// X86_64:#define __UINT_LEAST8_MAX__ 255
// X86_64:#define __UINT_LEAST8_TYPE__ unsigned char
// X86_64:#define __USER_LABEL_PREFIX__
// X86_64:#define __WCHAR_MAX__ 2147483647
// X86_64:#define __WCHAR_TYPE__ int
// X86_64:#define __WCHAR_WIDTH__ 32
// X86_64:#define __WINT_TYPE__ int
// X86_64:#define __WINT_WIDTH__ 32
// X86_64:#define __amd64 1
// X86_64:#define __amd64__ 1
// X86_64:#define __code_model_small_ 1
// X86_64:#define __x86_64 1
// X86_64:#define __x86_64__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64h-none-none < /dev/null | FileCheck -match-full-lines -check-prefix X86_64H %s
//
// X86_64H:#define __x86_64 1
// X86_64H:#define __x86_64__ 1
// X86_64H:#define __x86_64h 1
// X86_64H:#define __x86_64h__ 1
//
// RUN: %clang -xc - -E -dM -mcmodel=medium --target=i386-unknown-linux < /dev/null | FileCheck -match-full-lines -check-prefix X86_MEDIUM %s
// X86_MEDIUM:#define __code_model_medium_ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-none-none-gnux32 < /dev/null | FileCheck -match-full-lines -check-prefix X32 %s
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=x86_64-none-none-gnux32 < /dev/null | FileCheck -match-full-lines -check-prefix X32 -check-prefix X32-CXX %s
//
// X32:#define _ILP32 1
// X32-NOT:#define _LP64 1
// X32:#define __BIGGEST_ALIGNMENT__ 16
// X32:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// X32:#define __CHAR16_TYPE__ unsigned short
// X32:#define __CHAR32_TYPE__ unsigned int
// X32:#define __CHAR_BIT__ 8
// X32:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// X32:#define __DBL_DIG__ 15
// X32:#define __DBL_EPSILON__ 2.2204460492503131e-16
// X32:#define __DBL_HAS_DENORM__ 1
// X32:#define __DBL_HAS_INFINITY__ 1
// X32:#define __DBL_HAS_QUIET_NAN__ 1
// X32:#define __DBL_MANT_DIG__ 53
// X32:#define __DBL_MAX_10_EXP__ 308
// X32:#define __DBL_MAX_EXP__ 1024
// X32:#define __DBL_MAX__ 1.7976931348623157e+308
// X32:#define __DBL_MIN_10_EXP__ (-307)
// X32:#define __DBL_MIN_EXP__ (-1021)
// X32:#define __DBL_MIN__ 2.2250738585072014e-308
// X32:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// X32:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// X32:#define __FLT_DIG__ 6
// X32:#define __FLT_EPSILON__ 1.19209290e-7F
// X32:#define __FLT_EVAL_METHOD__ 0
// X32:#define __FLT_HAS_DENORM__ 1
// X32:#define __FLT_HAS_INFINITY__ 1
// X32:#define __FLT_HAS_QUIET_NAN__ 1
// X32:#define __FLT_MANT_DIG__ 24
// X32:#define __FLT_MAX_10_EXP__ 38
// X32:#define __FLT_MAX_EXP__ 128
// X32:#define __FLT_MAX__ 3.40282347e+38F
// X32:#define __FLT_MIN_10_EXP__ (-37)
// X32:#define __FLT_MIN_EXP__ (-125)
// X32:#define __FLT_MIN__ 1.17549435e-38F
// X32:#define __FLT_RADIX__ 2
// X32:#define __ILP32__ 1
// X32-NOT:#define __LP64__ 1
// X32:#define __INT16_C_SUFFIX__
// X32:#define __INT16_FMTd__ "hd"
// X32:#define __INT16_FMTi__ "hi"
// X32:#define __INT16_MAX__ 32767
// X32:#define __INT16_TYPE__ short
// X32:#define __INT32_C_SUFFIX__
// X32:#define __INT32_FMTd__ "d"
// X32:#define __INT32_FMTi__ "i"
// X32:#define __INT32_MAX__ 2147483647
// X32:#define __INT32_TYPE__ int
// X32:#define __INT64_C_SUFFIX__ LL
// X32:#define __INT64_FMTd__ "lld"
// X32:#define __INT64_FMTi__ "lli"
// X32:#define __INT64_MAX__ 9223372036854775807LL
// X32:#define __INT64_TYPE__ long long int
// X32:#define __INT8_C_SUFFIX__
// X32:#define __INT8_FMTd__ "hhd"
// X32:#define __INT8_FMTi__ "hhi"
// X32:#define __INT8_MAX__ 127
// X32:#define __INT8_TYPE__ signed char
// X32:#define __INTMAX_C_SUFFIX__ LL
// X32:#define __INTMAX_FMTd__ "lld"
// X32:#define __INTMAX_FMTi__ "lli"
// X32:#define __INTMAX_MAX__ 9223372036854775807LL
// X32:#define __INTMAX_TYPE__ long long int
// X32:#define __INTMAX_WIDTH__ 64
// X32:#define __INTPTR_FMTd__ "d"
// X32:#define __INTPTR_FMTi__ "i"
// X32:#define __INTPTR_MAX__ 2147483647
// X32:#define __INTPTR_TYPE__ int
// X32:#define __INTPTR_WIDTH__ 32
// X32:#define __INT_FAST16_FMTd__ "hd"
// X32:#define __INT_FAST16_FMTi__ "hi"
// X32:#define __INT_FAST16_MAX__ 32767
// X32:#define __INT_FAST16_TYPE__ short
// X32:#define __INT_FAST32_FMTd__ "d"
// X32:#define __INT_FAST32_FMTi__ "i"
// X32:#define __INT_FAST32_MAX__ 2147483647
// X32:#define __INT_FAST32_TYPE__ int
// X32:#define __INT_FAST64_FMTd__ "lld"
// X32:#define __INT_FAST64_FMTi__ "lli"
// X32:#define __INT_FAST64_MAX__ 9223372036854775807LL
// X32:#define __INT_FAST64_TYPE__ long long int
// X32:#define __INT_FAST8_FMTd__ "hhd"
// X32:#define __INT_FAST8_FMTi__ "hhi"
// X32:#define __INT_FAST8_MAX__ 127
// X32:#define __INT_FAST8_TYPE__ signed char
// X32:#define __INT_LEAST16_FMTd__ "hd"
// X32:#define __INT_LEAST16_FMTi__ "hi"
// X32:#define __INT_LEAST16_MAX__ 32767
// X32:#define __INT_LEAST16_TYPE__ short
// X32:#define __INT_LEAST32_FMTd__ "d"
// X32:#define __INT_LEAST32_FMTi__ "i"
// X32:#define __INT_LEAST32_MAX__ 2147483647
// X32:#define __INT_LEAST32_TYPE__ int
// X32:#define __INT_LEAST64_FMTd__ "lld"
// X32:#define __INT_LEAST64_FMTi__ "lli"
// X32:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// X32:#define __INT_LEAST64_TYPE__ long long int
// X32:#define __INT_LEAST8_FMTd__ "hhd"
// X32:#define __INT_LEAST8_FMTi__ "hhi"
// X32:#define __INT_LEAST8_MAX__ 127
// X32:#define __INT_LEAST8_TYPE__ signed char
// X32:#define __INT_MAX__ 2147483647
// X32:#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
// X32:#define __LDBL_DIG__ 18
// X32:#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
// X32:#define __LDBL_HAS_DENORM__ 1
// X32:#define __LDBL_HAS_INFINITY__ 1
// X32:#define __LDBL_HAS_QUIET_NAN__ 1
// X32:#define __LDBL_MANT_DIG__ 64
// X32:#define __LDBL_MAX_10_EXP__ 4932
// X32:#define __LDBL_MAX_EXP__ 16384
// X32:#define __LDBL_MAX__ 1.18973149535723176502e+4932L
// X32:#define __LDBL_MIN_10_EXP__ (-4931)
// X32:#define __LDBL_MIN_EXP__ (-16381)
// X32:#define __LDBL_MIN__ 3.36210314311209350626e-4932L
// X32:#define __LITTLE_ENDIAN__ 1
// X32:#define __LONG_LONG_MAX__ 9223372036854775807LL
// X32:#define __LONG_MAX__ 2147483647L
// X32:#define __MMX__ 1
// X32:#define __NO_MATH_INLINES 1
// X32:#define __POINTER_WIDTH__ 32
// X32:#define __PTRDIFF_TYPE__ int
// X32:#define __PTRDIFF_WIDTH__ 32
// X32:#define __REGISTER_PREFIX__
// X32:#define __SCHAR_MAX__ 127
// X32:#define __SHRT_MAX__ 32767
// X32:#define __SIG_ATOMIC_MAX__ 2147483647
// X32:#define __SIG_ATOMIC_WIDTH__ 32
// X32:#define __SIZEOF_DOUBLE__ 8
// X32:#define __SIZEOF_FLOAT__ 4
// X32:#define __SIZEOF_INT__ 4
// X32:#define __SIZEOF_LONG_DOUBLE__ 16
// X32:#define __SIZEOF_LONG_LONG__ 8
// X32:#define __SIZEOF_LONG__ 4
// X32:#define __SIZEOF_POINTER__ 4
// X32:#define __SIZEOF_PTRDIFF_T__ 4
// X32:#define __SIZEOF_SHORT__ 2
// X32:#define __SIZEOF_SIZE_T__ 4
// X32:#define __SIZEOF_WCHAR_T__ 4
// X32:#define __SIZEOF_WINT_T__ 4
// X32:#define __SIZE_MAX__ 4294967295U
// X32:#define __SIZE_TYPE__ unsigned int
// X32:#define __SIZE_WIDTH__ 32
// X32:#define __SSE2_MATH__ 1
// X32:#define __SSE2__ 1
// X32:#define __SSE_MATH__ 1
// X32:#define __SSE__ 1
// X32-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16U
// X32:#define __UINT16_C_SUFFIX__
// X32:#define __UINT16_MAX__ 65535
// X32:#define __UINT16_TYPE__ unsigned short
// X32:#define __UINT32_C_SUFFIX__ U
// X32:#define __UINT32_MAX__ 4294967295U
// X32:#define __UINT32_TYPE__ unsigned int
// X32:#define __UINT64_C_SUFFIX__ ULL
// X32:#define __UINT64_MAX__ 18446744073709551615ULL
// X32:#define __UINT64_TYPE__ long long unsigned int
// X32:#define __UINT8_C_SUFFIX__
// X32:#define __UINT8_MAX__ 255
// X32:#define __UINT8_TYPE__ unsigned char
// X32:#define __UINTMAX_C_SUFFIX__ ULL
// X32:#define __UINTMAX_MAX__ 18446744073709551615ULL
// X32:#define __UINTMAX_TYPE__ long long unsigned int
// X32:#define __UINTMAX_WIDTH__ 64
// X32:#define __UINTPTR_MAX__ 4294967295U
// X32:#define __UINTPTR_TYPE__ unsigned int
// X32:#define __UINTPTR_WIDTH__ 32
// X32:#define __UINT_FAST16_MAX__ 65535
// X32:#define __UINT_FAST16_TYPE__ unsigned short
// X32:#define __UINT_FAST32_MAX__ 4294967295U
// X32:#define __UINT_FAST32_TYPE__ unsigned int
// X32:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// X32:#define __UINT_FAST64_TYPE__ long long unsigned int
// X32:#define __UINT_FAST8_MAX__ 255
// X32:#define __UINT_FAST8_TYPE__ unsigned char
// X32:#define __UINT_LEAST16_MAX__ 65535
// X32:#define __UINT_LEAST16_TYPE__ unsigned short
// X32:#define __UINT_LEAST32_MAX__ 4294967295U
// X32:#define __UINT_LEAST32_TYPE__ unsigned int
// X32:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// X32:#define __UINT_LEAST64_TYPE__ long long unsigned int
// X32:#define __UINT_LEAST8_MAX__ 255
// X32:#define __UINT_LEAST8_TYPE__ unsigned char
// X32:#define __USER_LABEL_PREFIX__
// X32:#define __WCHAR_MAX__ 2147483647
// X32:#define __WCHAR_TYPE__ int
// X32:#define __WCHAR_WIDTH__ 32
// X32:#define __WINT_TYPE__ int
// X32:#define __WINT_WIDTH__ 32
// X32:#define __amd64 1
// X32:#define __amd64__ 1
// X32:#define __x86_64 1
// X32:#define __x86_64__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-unknown-cloudabi < /dev/null | FileCheck -match-full-lines -check-prefix X86_64-CLOUDABI %s
//
// X86_64-CLOUDABI:#define _LP64 1
// X86_64-CLOUDABI:#define __ATOMIC_ACQUIRE 2
// X86_64-CLOUDABI:#define __ATOMIC_ACQ_REL 4
// X86_64-CLOUDABI:#define __ATOMIC_CONSUME 1
// X86_64-CLOUDABI:#define __ATOMIC_RELAXED 0
// X86_64-CLOUDABI:#define __ATOMIC_RELEASE 3
// X86_64-CLOUDABI:#define __ATOMIC_SEQ_CST 5
// X86_64-CLOUDABI:#define __BIGGEST_ALIGNMENT__ 16
// X86_64-CLOUDABI:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// X86_64-CLOUDABI:#define __CHAR16_TYPE__ unsigned short
// X86_64-CLOUDABI:#define __CHAR32_TYPE__ unsigned int
// X86_64-CLOUDABI:#define __CHAR_BIT__ 8
// X86_64-CLOUDABI:#define __CONSTANT_CFSTRINGS__ 1
// X86_64-CLOUDABI:#define __CloudABI__ 1
// X86_64-CLOUDABI:#define __DBL_DECIMAL_DIG__ 17
// X86_64-CLOUDABI:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// X86_64-CLOUDABI:#define __DBL_DIG__ 15
// X86_64-CLOUDABI:#define __DBL_EPSILON__ 2.2204460492503131e-16
// X86_64-CLOUDABI:#define __DBL_HAS_DENORM__ 1
// X86_64-CLOUDABI:#define __DBL_HAS_INFINITY__ 1
// X86_64-CLOUDABI:#define __DBL_HAS_QUIET_NAN__ 1
// X86_64-CLOUDABI:#define __DBL_MANT_DIG__ 53
// X86_64-CLOUDABI:#define __DBL_MAX_10_EXP__ 308
// X86_64-CLOUDABI:#define __DBL_MAX_EXP__ 1024
// X86_64-CLOUDABI:#define __DBL_MAX__ 1.7976931348623157e+308
// X86_64-CLOUDABI:#define __DBL_MIN_10_EXP__ (-307)
// X86_64-CLOUDABI:#define __DBL_MIN_EXP__ (-1021)
// X86_64-CLOUDABI:#define __DBL_MIN__ 2.2250738585072014e-308
// X86_64-CLOUDABI:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// X86_64-CLOUDABI:#define __ELF__ 1
// X86_64-CLOUDABI:#define __FINITE_MATH_ONLY__ 0
// X86_64-CLOUDABI:#define __FLT_DECIMAL_DIG__ 9
// X86_64-CLOUDABI:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// X86_64-CLOUDABI:#define __FLT_DIG__ 6
// X86_64-CLOUDABI:#define __FLT_EPSILON__ 1.19209290e-7F
// X86_64-CLOUDABI:#define __FLT_EVAL_METHOD__ 0
// X86_64-CLOUDABI:#define __FLT_HAS_DENORM__ 1
// X86_64-CLOUDABI:#define __FLT_HAS_INFINITY__ 1
// X86_64-CLOUDABI:#define __FLT_HAS_QUIET_NAN__ 1
// X86_64-CLOUDABI:#define __FLT_MANT_DIG__ 24
// X86_64-CLOUDABI:#define __FLT_MAX_10_EXP__ 38
// X86_64-CLOUDABI:#define __FLT_MAX_EXP__ 128
// X86_64-CLOUDABI:#define __FLT_MAX__ 3.40282347e+38F
// X86_64-CLOUDABI:#define __FLT_MIN_10_EXP__ (-37)
// X86_64-CLOUDABI:#define __FLT_MIN_EXP__ (-125)
// X86_64-CLOUDABI:#define __FLT_MIN__ 1.17549435e-38F
// X86_64-CLOUDABI:#define __FLT_RADIX__ 2
// X86_64-CLOUDABI:#define __GCC_ATOMIC_BOOL_LOCK_FREE 2
// X86_64-CLOUDABI:#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
// X86_64-CLOUDABI:#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
// X86_64-CLOUDABI:#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
// X86_64-CLOUDABI:#define __GCC_ATOMIC_INT_LOCK_FREE 2
// X86_64-CLOUDABI:#define __GCC_ATOMIC_LLONG_LOCK_FREE 2
// X86_64-CLOUDABI:#define __GCC_ATOMIC_LONG_LOCK_FREE 2
// X86_64-CLOUDABI:#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
// X86_64-CLOUDABI:#define __GCC_ATOMIC_SHORT_LOCK_FREE 2
// X86_64-CLOUDABI:#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
// X86_64-CLOUDABI:#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
// X86_64-CLOUDABI:#define __GNUC_MINOR__ 2
// X86_64-CLOUDABI:#define __GNUC_PATCHLEVEL__ 1
// X86_64-CLOUDABI:#define __GNUC_STDC_INLINE__ 1
// X86_64-CLOUDABI:#define __GNUC__ 4
// X86_64-CLOUDABI:#define __GXX_ABI_VERSION 1002
// X86_64-CLOUDABI:#define __INT16_C_SUFFIX__
// X86_64-CLOUDABI:#define __INT16_FMTd__ "hd"
// X86_64-CLOUDABI:#define __INT16_FMTi__ "hi"
// X86_64-CLOUDABI:#define __INT16_MAX__ 32767
// X86_64-CLOUDABI:#define __INT16_TYPE__ short
// X86_64-CLOUDABI:#define __INT32_C_SUFFIX__
// X86_64-CLOUDABI:#define __INT32_FMTd__ "d"
// X86_64-CLOUDABI:#define __INT32_FMTi__ "i"
// X86_64-CLOUDABI:#define __INT32_MAX__ 2147483647
// X86_64-CLOUDABI:#define __INT32_TYPE__ int
// X86_64-CLOUDABI:#define __INT64_C_SUFFIX__ L
// X86_64-CLOUDABI:#define __INT64_FMTd__ "ld"
// X86_64-CLOUDABI:#define __INT64_FMTi__ "li"
// X86_64-CLOUDABI:#define __INT64_MAX__ 9223372036854775807L
// X86_64-CLOUDABI:#define __INT64_TYPE__ long int
// X86_64-CLOUDABI:#define __INT8_C_SUFFIX__
// X86_64-CLOUDABI:#define __INT8_FMTd__ "hhd"
// X86_64-CLOUDABI:#define __INT8_FMTi__ "hhi"
// X86_64-CLOUDABI:#define __INT8_MAX__ 127
// X86_64-CLOUDABI:#define __INT8_TYPE__ signed char
// X86_64-CLOUDABI:#define __INTMAX_C_SUFFIX__ L
// X86_64-CLOUDABI:#define __INTMAX_FMTd__ "ld"
// X86_64-CLOUDABI:#define __INTMAX_FMTi__ "li"
// X86_64-CLOUDABI:#define __INTMAX_MAX__ 9223372036854775807L
// X86_64-CLOUDABI:#define __INTMAX_TYPE__ long int
// X86_64-CLOUDABI:#define __INTMAX_WIDTH__ 64
// X86_64-CLOUDABI:#define __INTPTR_FMTd__ "ld"
// X86_64-CLOUDABI:#define __INTPTR_FMTi__ "li"
// X86_64-CLOUDABI:#define __INTPTR_MAX__ 9223372036854775807L
// X86_64-CLOUDABI:#define __INTPTR_TYPE__ long int
// X86_64-CLOUDABI:#define __INTPTR_WIDTH__ 64
// X86_64-CLOUDABI:#define __INT_FAST16_FMTd__ "hd"
// X86_64-CLOUDABI:#define __INT_FAST16_FMTi__ "hi"
// X86_64-CLOUDABI:#define __INT_FAST16_MAX__ 32767
// X86_64-CLOUDABI:#define __INT_FAST16_TYPE__ short
// X86_64-CLOUDABI:#define __INT_FAST32_FMTd__ "d"
// X86_64-CLOUDABI:#define __INT_FAST32_FMTi__ "i"
// X86_64-CLOUDABI:#define __INT_FAST32_MAX__ 2147483647
// X86_64-CLOUDABI:#define __INT_FAST32_TYPE__ int
// X86_64-CLOUDABI:#define __INT_FAST64_FMTd__ "ld"
// X86_64-CLOUDABI:#define __INT_FAST64_FMTi__ "li"
// X86_64-CLOUDABI:#define __INT_FAST64_MAX__ 9223372036854775807L
// X86_64-CLOUDABI:#define __INT_FAST64_TYPE__ long int
// X86_64-CLOUDABI:#define __INT_FAST8_FMTd__ "hhd"
// X86_64-CLOUDABI:#define __INT_FAST8_FMTi__ "hhi"
// X86_64-CLOUDABI:#define __INT_FAST8_MAX__ 127
// X86_64-CLOUDABI:#define __INT_FAST8_TYPE__ signed char
// X86_64-CLOUDABI:#define __INT_LEAST16_FMTd__ "hd"
// X86_64-CLOUDABI:#define __INT_LEAST16_FMTi__ "hi"
// X86_64-CLOUDABI:#define __INT_LEAST16_MAX__ 32767
// X86_64-CLOUDABI:#define __INT_LEAST16_TYPE__ short
// X86_64-CLOUDABI:#define __INT_LEAST32_FMTd__ "d"
// X86_64-CLOUDABI:#define __INT_LEAST32_FMTi__ "i"
// X86_64-CLOUDABI:#define __INT_LEAST32_MAX__ 2147483647
// X86_64-CLOUDABI:#define __INT_LEAST32_TYPE__ int
// X86_64-CLOUDABI:#define __INT_LEAST64_FMTd__ "ld"
// X86_64-CLOUDABI:#define __INT_LEAST64_FMTi__ "li"
// X86_64-CLOUDABI:#define __INT_LEAST64_MAX__ 9223372036854775807L
// X86_64-CLOUDABI:#define __INT_LEAST64_TYPE__ long int
// X86_64-CLOUDABI:#define __INT_LEAST8_FMTd__ "hhd"
// X86_64-CLOUDABI:#define __INT_LEAST8_FMTi__ "hhi"
// X86_64-CLOUDABI:#define __INT_LEAST8_MAX__ 127
// X86_64-CLOUDABI:#define __INT_LEAST8_TYPE__ signed char
// X86_64-CLOUDABI:#define __INT_MAX__ 2147483647
// X86_64-CLOUDABI:#define __LDBL_DECIMAL_DIG__ 21
// X86_64-CLOUDABI:#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
// X86_64-CLOUDABI:#define __LDBL_DIG__ 18
// X86_64-CLOUDABI:#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
// X86_64-CLOUDABI:#define __LDBL_HAS_DENORM__ 1
// X86_64-CLOUDABI:#define __LDBL_HAS_INFINITY__ 1
// X86_64-CLOUDABI:#define __LDBL_HAS_QUIET_NAN__ 1
// X86_64-CLOUDABI:#define __LDBL_MANT_DIG__ 64
// X86_64-CLOUDABI:#define __LDBL_MAX_10_EXP__ 4932
// X86_64-CLOUDABI:#define __LDBL_MAX_EXP__ 16384
// X86_64-CLOUDABI:#define __LDBL_MAX__ 1.18973149535723176502e+4932L
// X86_64-CLOUDABI:#define __LDBL_MIN_10_EXP__ (-4931)
// X86_64-CLOUDABI:#define __LDBL_MIN_EXP__ (-16381)
// X86_64-CLOUDABI:#define __LDBL_MIN__ 3.36210314311209350626e-4932L
// X86_64-CLOUDABI:#define __LITTLE_ENDIAN__ 1
// X86_64-CLOUDABI:#define __LONG_LONG_MAX__ 9223372036854775807LL
// X86_64-CLOUDABI:#define __LONG_MAX__ 9223372036854775807L
// X86_64-CLOUDABI:#define __LP64__ 1
// X86_64-CLOUDABI:#define __MMX__ 1
// X86_64-CLOUDABI:#define __NO_INLINE__ 1
// X86_64-CLOUDABI:#define __NO_MATH_INLINES 1
// X86_64-CLOUDABI:#define __ORDER_BIG_ENDIAN__ 4321
// X86_64-CLOUDABI:#define __ORDER_LITTLE_ENDIAN__ 1234
// X86_64-CLOUDABI:#define __ORDER_PDP_ENDIAN__ 3412
// X86_64-CLOUDABI:#define __POINTER_WIDTH__ 64
// X86_64-CLOUDABI:#define __PRAGMA_REDEFINE_EXTNAME 1
// X86_64-CLOUDABI:#define __PTRDIFF_FMTd__ "ld"
// X86_64-CLOUDABI:#define __PTRDIFF_FMTi__ "li"
// X86_64-CLOUDABI:#define __PTRDIFF_MAX__ 9223372036854775807L
// X86_64-CLOUDABI:#define __PTRDIFF_TYPE__ long int
// X86_64-CLOUDABI:#define __PTRDIFF_WIDTH__ 64
// X86_64-CLOUDABI:#define __REGISTER_PREFIX__
// X86_64-CLOUDABI:#define __SCHAR_MAX__ 127
// X86_64-CLOUDABI:#define __SHRT_MAX__ 32767
// X86_64-CLOUDABI:#define __SIG_ATOMIC_MAX__ 2147483647
// X86_64-CLOUDABI:#define __SIG_ATOMIC_WIDTH__ 32
// X86_64-CLOUDABI:#define __SIZEOF_DOUBLE__ 8
// X86_64-CLOUDABI:#define __SIZEOF_FLOAT__ 4
// X86_64-CLOUDABI:#define __SIZEOF_INT128__ 16
// X86_64-CLOUDABI:#define __SIZEOF_INT__ 4
// X86_64-CLOUDABI:#define __SIZEOF_LONG_DOUBLE__ 16
// X86_64-CLOUDABI:#define __SIZEOF_LONG_LONG__ 8
// X86_64-CLOUDABI:#define __SIZEOF_LONG__ 8
// X86_64-CLOUDABI:#define __SIZEOF_POINTER__ 8
// X86_64-CLOUDABI:#define __SIZEOF_PTRDIFF_T__ 8
// X86_64-CLOUDABI:#define __SIZEOF_SHORT__ 2
// X86_64-CLOUDABI:#define __SIZEOF_SIZE_T__ 8
// X86_64-CLOUDABI:#define __SIZEOF_WCHAR_T__ 4
// X86_64-CLOUDABI:#define __SIZEOF_WINT_T__ 4
// X86_64-CLOUDABI:#define __SIZE_FMTX__ "lX"
// X86_64-CLOUDABI:#define __SIZE_FMTo__ "lo"
// X86_64-CLOUDABI:#define __SIZE_FMTu__ "lu"
// X86_64-CLOUDABI:#define __SIZE_FMTx__ "lx"
// X86_64-CLOUDABI:#define __SIZE_MAX__ 18446744073709551615UL
// X86_64-CLOUDABI:#define __SIZE_TYPE__ long unsigned int
// X86_64-CLOUDABI:#define __SIZE_WIDTH__ 64
// X86_64-CLOUDABI:#define __SSE2_MATH__ 1
// X86_64-CLOUDABI:#define __SSE2__ 1
// X86_64-CLOUDABI:#define __SSE_MATH__ 1
// X86_64-CLOUDABI:#define __SSE__ 1
// X86_64-CLOUDABI:#define __STDC_HOSTED__ 0
// X86_64-CLOUDABI:#define __STDC_ISO_10646__ 201206L
// X86_64-CLOUDABI:#define __STDC_UTF_16__ 1
// X86_64-CLOUDABI:#define __STDC_UTF_32__ 1
// X86_64-CLOUDABI:#define __STDC_VERSION__ 201112L
// X86_64-CLOUDABI:#define __STDC__ 1
// X86_64-CLOUDABI:#define __UINT16_C_SUFFIX__
// X86_64-CLOUDABI:#define __UINT16_FMTX__ "hX"
// X86_64-CLOUDABI:#define __UINT16_FMTo__ "ho"
// X86_64-CLOUDABI:#define __UINT16_FMTu__ "hu"
// X86_64-CLOUDABI:#define __UINT16_FMTx__ "hx"
// X86_64-CLOUDABI:#define __UINT16_MAX__ 65535
// X86_64-CLOUDABI:#define __UINT16_TYPE__ unsigned short
// X86_64-CLOUDABI:#define __UINT32_C_SUFFIX__ U
// X86_64-CLOUDABI:#define __UINT32_FMTX__ "X"
// X86_64-CLOUDABI:#define __UINT32_FMTo__ "o"
// X86_64-CLOUDABI:#define __UINT32_FMTu__ "u"
// X86_64-CLOUDABI:#define __UINT32_FMTx__ "x"
// X86_64-CLOUDABI:#define __UINT32_MAX__ 4294967295U
// X86_64-CLOUDABI:#define __UINT32_TYPE__ unsigned int
// X86_64-CLOUDABI:#define __UINT64_C_SUFFIX__ UL
// X86_64-CLOUDABI:#define __UINT64_FMTX__ "lX"
// X86_64-CLOUDABI:#define __UINT64_FMTo__ "lo"
// X86_64-CLOUDABI:#define __UINT64_FMTu__ "lu"
// X86_64-CLOUDABI:#define __UINT64_FMTx__ "lx"
// X86_64-CLOUDABI:#define __UINT64_MAX__ 18446744073709551615UL
// X86_64-CLOUDABI:#define __UINT64_TYPE__ long unsigned int
// X86_64-CLOUDABI:#define __UINT8_C_SUFFIX__
// X86_64-CLOUDABI:#define __UINT8_FMTX__ "hhX"
// X86_64-CLOUDABI:#define __UINT8_FMTo__ "hho"
// X86_64-CLOUDABI:#define __UINT8_FMTu__ "hhu"
// X86_64-CLOUDABI:#define __UINT8_FMTx__ "hhx"
// X86_64-CLOUDABI:#define __UINT8_MAX__ 255
// X86_64-CLOUDABI:#define __UINT8_TYPE__ unsigned char
// X86_64-CLOUDABI:#define __UINTMAX_C_SUFFIX__ UL
// X86_64-CLOUDABI:#define __UINTMAX_FMTX__ "lX"
// X86_64-CLOUDABI:#define __UINTMAX_FMTo__ "lo"
// X86_64-CLOUDABI:#define __UINTMAX_FMTu__ "lu"
// X86_64-CLOUDABI:#define __UINTMAX_FMTx__ "lx"
// X86_64-CLOUDABI:#define __UINTMAX_MAX__ 18446744073709551615UL
// X86_64-CLOUDABI:#define __UINTMAX_TYPE__ long unsigned int
// X86_64-CLOUDABI:#define __UINTMAX_WIDTH__ 64
// X86_64-CLOUDABI:#define __UINTPTR_FMTX__ "lX"
// X86_64-CLOUDABI:#define __UINTPTR_FMTo__ "lo"
// X86_64-CLOUDABI:#define __UINTPTR_FMTu__ "lu"
// X86_64-CLOUDABI:#define __UINTPTR_FMTx__ "lx"
// X86_64-CLOUDABI:#define __UINTPTR_MAX__ 18446744073709551615UL
// X86_64-CLOUDABI:#define __UINTPTR_TYPE__ long unsigned int
// X86_64-CLOUDABI:#define __UINTPTR_WIDTH__ 64
// X86_64-CLOUDABI:#define __UINT_FAST16_FMTX__ "hX"
// X86_64-CLOUDABI:#define __UINT_FAST16_FMTo__ "ho"
// X86_64-CLOUDABI:#define __UINT_FAST16_FMTu__ "hu"
// X86_64-CLOUDABI:#define __UINT_FAST16_FMTx__ "hx"
// X86_64-CLOUDABI:#define __UINT_FAST16_MAX__ 65535
// X86_64-CLOUDABI:#define __UINT_FAST16_TYPE__ unsigned short
// X86_64-CLOUDABI:#define __UINT_FAST32_FMTX__ "X"
// X86_64-CLOUDABI:#define __UINT_FAST32_FMTo__ "o"
// X86_64-CLOUDABI:#define __UINT_FAST32_FMTu__ "u"
// X86_64-CLOUDABI:#define __UINT_FAST32_FMTx__ "x"
// X86_64-CLOUDABI:#define __UINT_FAST32_MAX__ 4294967295U
// X86_64-CLOUDABI:#define __UINT_FAST32_TYPE__ unsigned int
// X86_64-CLOUDABI:#define __UINT_FAST64_FMTX__ "lX"
// X86_64-CLOUDABI:#define __UINT_FAST64_FMTo__ "lo"
// X86_64-CLOUDABI:#define __UINT_FAST64_FMTu__ "lu"
// X86_64-CLOUDABI:#define __UINT_FAST64_FMTx__ "lx"
// X86_64-CLOUDABI:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// X86_64-CLOUDABI:#define __UINT_FAST64_TYPE__ long unsigned int
// X86_64-CLOUDABI:#define __UINT_FAST8_FMTX__ "hhX"
// X86_64-CLOUDABI:#define __UINT_FAST8_FMTo__ "hho"
// X86_64-CLOUDABI:#define __UINT_FAST8_FMTu__ "hhu"
// X86_64-CLOUDABI:#define __UINT_FAST8_FMTx__ "hhx"
// X86_64-CLOUDABI:#define __UINT_FAST8_MAX__ 255
// X86_64-CLOUDABI:#define __UINT_FAST8_TYPE__ unsigned char
// X86_64-CLOUDABI:#define __UINT_LEAST16_FMTX__ "hX"
// X86_64-CLOUDABI:#define __UINT_LEAST16_FMTo__ "ho"
// X86_64-CLOUDABI:#define __UINT_LEAST16_FMTu__ "hu"
// X86_64-CLOUDABI:#define __UINT_LEAST16_FMTx__ "hx"
// X86_64-CLOUDABI:#define __UINT_LEAST16_MAX__ 65535
// X86_64-CLOUDABI:#define __UINT_LEAST16_TYPE__ unsigned short
// X86_64-CLOUDABI:#define __UINT_LEAST32_FMTX__ "X"
// X86_64-CLOUDABI:#define __UINT_LEAST32_FMTo__ "o"
// X86_64-CLOUDABI:#define __UINT_LEAST32_FMTu__ "u"
// X86_64-CLOUDABI:#define __UINT_LEAST32_FMTx__ "x"
// X86_64-CLOUDABI:#define __UINT_LEAST32_MAX__ 4294967295U
// X86_64-CLOUDABI:#define __UINT_LEAST32_TYPE__ unsigned int
// X86_64-CLOUDABI:#define __UINT_LEAST64_FMTX__ "lX"
// X86_64-CLOUDABI:#define __UINT_LEAST64_FMTo__ "lo"
// X86_64-CLOUDABI:#define __UINT_LEAST64_FMTu__ "lu"
// X86_64-CLOUDABI:#define __UINT_LEAST64_FMTx__ "lx"
// X86_64-CLOUDABI:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// X86_64-CLOUDABI:#define __UINT_LEAST64_TYPE__ long unsigned int
// X86_64-CLOUDABI:#define __UINT_LEAST8_FMTX__ "hhX"
// X86_64-CLOUDABI:#define __UINT_LEAST8_FMTo__ "hho"
// X86_64-CLOUDABI:#define __UINT_LEAST8_FMTu__ "hhu"
// X86_64-CLOUDABI:#define __UINT_LEAST8_FMTx__ "hhx"
// X86_64-CLOUDABI:#define __UINT_LEAST8_MAX__ 255
// X86_64-CLOUDABI:#define __UINT_LEAST8_TYPE__ unsigned char
// X86_64-CLOUDABI:#define __USER_LABEL_PREFIX__
// X86_64-CLOUDABI:#define __VERSION__ "4.2.1 Compatible{{.*}}
// X86_64-CLOUDABI:#define __WCHAR_MAX__ 2147483647
// X86_64-CLOUDABI:#define __WCHAR_TYPE__ int
// X86_64-CLOUDABI:#define __WCHAR_WIDTH__ 32
// X86_64-CLOUDABI:#define __WINT_MAX__ 2147483647
// X86_64-CLOUDABI:#define __WINT_TYPE__ int
// X86_64-CLOUDABI:#define __WINT_WIDTH__ 32
// X86_64-CLOUDABI:#define __amd64 1
// X86_64-CLOUDABI:#define __amd64__ 1
// X86_64-CLOUDABI:#define __clang__ 1
// X86_64-CLOUDABI:#define __clang_major__ {{.*}}
// X86_64-CLOUDABI:#define __clang_minor__ {{.*}}
// X86_64-CLOUDABI:#define __clang_patchlevel__ {{.*}}
// X86_64-CLOUDABI:#define __clang_version__ {{.*}}
// X86_64-CLOUDABI:#define __llvm__ 1
// X86_64-CLOUDABI:#define __x86_64 1
// X86_64-CLOUDABI:#define __x86_64__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-pc-linux-gnu < /dev/null | FileCheck -match-full-lines -check-prefix X86_64-LINUX %s
//
// X86_64-LINUX:#define _LP64 1
// X86_64-LINUX:#define __BIGGEST_ALIGNMENT__ 16
// X86_64-LINUX:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// X86_64-LINUX:#define __CHAR16_TYPE__ unsigned short
// X86_64-LINUX:#define __CHAR32_TYPE__ unsigned int
// X86_64-LINUX:#define __CHAR_BIT__ 8
// X86_64-LINUX:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// X86_64-LINUX:#define __DBL_DIG__ 15
// X86_64-LINUX:#define __DBL_EPSILON__ 2.2204460492503131e-16
// X86_64-LINUX:#define __DBL_HAS_DENORM__ 1
// X86_64-LINUX:#define __DBL_HAS_INFINITY__ 1
// X86_64-LINUX:#define __DBL_HAS_QUIET_NAN__ 1
// X86_64-LINUX:#define __DBL_MANT_DIG__ 53
// X86_64-LINUX:#define __DBL_MAX_10_EXP__ 308
// X86_64-LINUX:#define __DBL_MAX_EXP__ 1024
// X86_64-LINUX:#define __DBL_MAX__ 1.7976931348623157e+308
// X86_64-LINUX:#define __DBL_MIN_10_EXP__ (-307)
// X86_64-LINUX:#define __DBL_MIN_EXP__ (-1021)
// X86_64-LINUX:#define __DBL_MIN__ 2.2250738585072014e-308
// X86_64-LINUX:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// X86_64-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// X86_64-LINUX:#define __FLT_DIG__ 6
// X86_64-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F
// X86_64-LINUX:#define __FLT_EVAL_METHOD__ 0
// X86_64-LINUX:#define __FLT_HAS_DENORM__ 1
// X86_64-LINUX:#define __FLT_HAS_INFINITY__ 1
// X86_64-LINUX:#define __FLT_HAS_QUIET_NAN__ 1
// X86_64-LINUX:#define __FLT_MANT_DIG__ 24
// X86_64-LINUX:#define __FLT_MAX_10_EXP__ 38
// X86_64-LINUX:#define __FLT_MAX_EXP__ 128
// X86_64-LINUX:#define __FLT_MAX__ 3.40282347e+38F
// X86_64-LINUX:#define __FLT_MIN_10_EXP__ (-37)
// X86_64-LINUX:#define __FLT_MIN_EXP__ (-125)
// X86_64-LINUX:#define __FLT_MIN__ 1.17549435e-38F
// X86_64-LINUX:#define __FLT_RADIX__ 2
// X86_64-LINUX:#define __INT16_C_SUFFIX__
// X86_64-LINUX:#define __INT16_FMTd__ "hd"
// X86_64-LINUX:#define __INT16_FMTi__ "hi"
// X86_64-LINUX:#define __INT16_MAX__ 32767
// X86_64-LINUX:#define __INT16_TYPE__ short
// X86_64-LINUX:#define __INT32_C_SUFFIX__
// X86_64-LINUX:#define __INT32_FMTd__ "d"
// X86_64-LINUX:#define __INT32_FMTi__ "i"
// X86_64-LINUX:#define __INT32_MAX__ 2147483647
// X86_64-LINUX:#define __INT32_TYPE__ int
// X86_64-LINUX:#define __INT64_C_SUFFIX__ L
// X86_64-LINUX:#define __INT64_FMTd__ "ld"
// X86_64-LINUX:#define __INT64_FMTi__ "li"
// X86_64-LINUX:#define __INT64_MAX__ 9223372036854775807L
// X86_64-LINUX:#define __INT64_TYPE__ long int
// X86_64-LINUX:#define __INT8_C_SUFFIX__
// X86_64-LINUX:#define __INT8_FMTd__ "hhd"
// X86_64-LINUX:#define __INT8_FMTi__ "hhi"
// X86_64-LINUX:#define __INT8_MAX__ 127
// X86_64-LINUX:#define __INT8_TYPE__ signed char
// X86_64-LINUX:#define __INTMAX_C_SUFFIX__ L
// X86_64-LINUX:#define __INTMAX_FMTd__ "ld"
// X86_64-LINUX:#define __INTMAX_FMTi__ "li"
// X86_64-LINUX:#define __INTMAX_MAX__ 9223372036854775807L
// X86_64-LINUX:#define __INTMAX_TYPE__ long int
// X86_64-LINUX:#define __INTMAX_WIDTH__ 64
// X86_64-LINUX:#define __INTPTR_FMTd__ "ld"
// X86_64-LINUX:#define __INTPTR_FMTi__ "li"
// X86_64-LINUX:#define __INTPTR_MAX__ 9223372036854775807L
// X86_64-LINUX:#define __INTPTR_TYPE__ long int
// X86_64-LINUX:#define __INTPTR_WIDTH__ 64
// X86_64-LINUX:#define __INT_FAST16_FMTd__ "hd"
// X86_64-LINUX:#define __INT_FAST16_FMTi__ "hi"
// X86_64-LINUX:#define __INT_FAST16_MAX__ 32767
// X86_64-LINUX:#define __INT_FAST16_TYPE__ short
// X86_64-LINUX:#define __INT_FAST32_FMTd__ "d"
// X86_64-LINUX:#define __INT_FAST32_FMTi__ "i"
// X86_64-LINUX:#define __INT_FAST32_MAX__ 2147483647
// X86_64-LINUX:#define __INT_FAST32_TYPE__ int
// X86_64-LINUX:#define __INT_FAST64_FMTd__ "ld"
// X86_64-LINUX:#define __INT_FAST64_FMTi__ "li"
// X86_64-LINUX:#define __INT_FAST64_MAX__ 9223372036854775807L
// X86_64-LINUX:#define __INT_FAST64_TYPE__ long int
// X86_64-LINUX:#define __INT_FAST8_FMTd__ "hhd"
// X86_64-LINUX:#define __INT_FAST8_FMTi__ "hhi"
// X86_64-LINUX:#define __INT_FAST8_MAX__ 127
// X86_64-LINUX:#define __INT_FAST8_TYPE__ signed char
// X86_64-LINUX:#define __INT_LEAST16_FMTd__ "hd"
// X86_64-LINUX:#define __INT_LEAST16_FMTi__ "hi"
// X86_64-LINUX:#define __INT_LEAST16_MAX__ 32767
// X86_64-LINUX:#define __INT_LEAST16_TYPE__ short
// X86_64-LINUX:#define __INT_LEAST32_FMTd__ "d"
// X86_64-LINUX:#define __INT_LEAST32_FMTi__ "i"
// X86_64-LINUX:#define __INT_LEAST32_MAX__ 2147483647
// X86_64-LINUX:#define __INT_LEAST32_TYPE__ int
// X86_64-LINUX:#define __INT_LEAST64_FMTd__ "ld"
// X86_64-LINUX:#define __INT_LEAST64_FMTi__ "li"
// X86_64-LINUX:#define __INT_LEAST64_MAX__ 9223372036854775807L
// X86_64-LINUX:#define __INT_LEAST64_TYPE__ long int
// X86_64-LINUX:#define __INT_LEAST8_FMTd__ "hhd"
// X86_64-LINUX:#define __INT_LEAST8_FMTi__ "hhi"
// X86_64-LINUX:#define __INT_LEAST8_MAX__ 127
// X86_64-LINUX:#define __INT_LEAST8_TYPE__ signed char
// X86_64-LINUX:#define __INT_MAX__ 2147483647
// X86_64-LINUX:#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
// X86_64-LINUX:#define __LDBL_DIG__ 18
// X86_64-LINUX:#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
// X86_64-LINUX:#define __LDBL_HAS_DENORM__ 1
// X86_64-LINUX:#define __LDBL_HAS_INFINITY__ 1
// X86_64-LINUX:#define __LDBL_HAS_QUIET_NAN__ 1
// X86_64-LINUX:#define __LDBL_MANT_DIG__ 64
// X86_64-LINUX:#define __LDBL_MAX_10_EXP__ 4932
// X86_64-LINUX:#define __LDBL_MAX_EXP__ 16384
// X86_64-LINUX:#define __LDBL_MAX__ 1.18973149535723176502e+4932L
// X86_64-LINUX:#define __LDBL_MIN_10_EXP__ (-4931)
// X86_64-LINUX:#define __LDBL_MIN_EXP__ (-16381)
// X86_64-LINUX:#define __LDBL_MIN__ 3.36210314311209350626e-4932L
// X86_64-LINUX:#define __LITTLE_ENDIAN__ 1
// X86_64-LINUX:#define __LONG_LONG_MAX__ 9223372036854775807LL
// X86_64-LINUX:#define __LONG_MAX__ 9223372036854775807L
// X86_64-LINUX:#define __LP64__ 1
// X86_64-LINUX:#define __MMX__ 1
// X86_64-LINUX:#define __NO_MATH_INLINES 1
// X86_64-LINUX:#define __POINTER_WIDTH__ 64
// X86_64-LINUX:#define __PTRDIFF_TYPE__ long int
// X86_64-LINUX:#define __PTRDIFF_WIDTH__ 64
// X86_64-LINUX:#define __REGISTER_PREFIX__
// X86_64-LINUX:#define __SCHAR_MAX__ 127
// X86_64-LINUX:#define __SHRT_MAX__ 32767
// X86_64-LINUX:#define __SIG_ATOMIC_MAX__ 2147483647
// X86_64-LINUX:#define __SIG_ATOMIC_WIDTH__ 32
// X86_64-LINUX:#define __SIZEOF_DOUBLE__ 8
// X86_64-LINUX:#define __SIZEOF_FLOAT__ 4
// X86_64-LINUX:#define __SIZEOF_INT__ 4
// X86_64-LINUX:#define __SIZEOF_LONG_DOUBLE__ 16
// X86_64-LINUX:#define __SIZEOF_LONG_LONG__ 8
// X86_64-LINUX:#define __SIZEOF_LONG__ 8
// X86_64-LINUX:#define __SIZEOF_POINTER__ 8
// X86_64-LINUX:#define __SIZEOF_PTRDIFF_T__ 8
// X86_64-LINUX:#define __SIZEOF_SHORT__ 2
// X86_64-LINUX:#define __SIZEOF_SIZE_T__ 8
// X86_64-LINUX:#define __SIZEOF_WCHAR_T__ 4
// X86_64-LINUX:#define __SIZEOF_WINT_T__ 4
// X86_64-LINUX:#define __SIZE_MAX__ 18446744073709551615UL
// X86_64-LINUX:#define __SIZE_TYPE__ long unsigned int
// X86_64-LINUX:#define __SIZE_WIDTH__ 64
// X86_64-LINUX:#define __SSE2_MATH__ 1
// X86_64-LINUX:#define __SSE2__ 1
// X86_64-LINUX:#define __SSE_MATH__ 1
// X86_64-LINUX:#define __SSE__ 1
// X86_64-LINUX:#define __UINT16_C_SUFFIX__
// X86_64-LINUX:#define __UINT16_MAX__ 65535
// X86_64-LINUX:#define __UINT16_TYPE__ unsigned short
// X86_64-LINUX:#define __UINT32_C_SUFFIX__ U
// X86_64-LINUX:#define __UINT32_MAX__ 4294967295U
// X86_64-LINUX:#define __UINT32_TYPE__ unsigned int
// X86_64-LINUX:#define __UINT64_C_SUFFIX__ UL
// X86_64-LINUX:#define __UINT64_MAX__ 18446744073709551615UL
// X86_64-LINUX:#define __UINT64_TYPE__ long unsigned int
// X86_64-LINUX:#define __UINT8_C_SUFFIX__
// X86_64-LINUX:#define __UINT8_MAX__ 255
// X86_64-LINUX:#define __UINT8_TYPE__ unsigned char
// X86_64-LINUX:#define __UINTMAX_C_SUFFIX__ UL
// X86_64-LINUX:#define __UINTMAX_MAX__ 18446744073709551615UL
// X86_64-LINUX:#define __UINTMAX_TYPE__ long unsigned int
// X86_64-LINUX:#define __UINTMAX_WIDTH__ 64
// X86_64-LINUX:#define __UINTPTR_MAX__ 18446744073709551615UL
// X86_64-LINUX:#define __UINTPTR_TYPE__ long unsigned int
// X86_64-LINUX:#define __UINTPTR_WIDTH__ 64
// X86_64-LINUX:#define __UINT_FAST16_MAX__ 65535
// X86_64-LINUX:#define __UINT_FAST16_TYPE__ unsigned short
// X86_64-LINUX:#define __UINT_FAST32_MAX__ 4294967295U
// X86_64-LINUX:#define __UINT_FAST32_TYPE__ unsigned int
// X86_64-LINUX:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// X86_64-LINUX:#define __UINT_FAST64_TYPE__ long unsigned int
// X86_64-LINUX:#define __UINT_FAST8_MAX__ 255
// X86_64-LINUX:#define __UINT_FAST8_TYPE__ unsigned char
// X86_64-LINUX:#define __UINT_LEAST16_MAX__ 65535
// X86_64-LINUX:#define __UINT_LEAST16_TYPE__ unsigned short
// X86_64-LINUX:#define __UINT_LEAST32_MAX__ 4294967295U
// X86_64-LINUX:#define __UINT_LEAST32_TYPE__ unsigned int
// X86_64-LINUX:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// X86_64-LINUX:#define __UINT_LEAST64_TYPE__ long unsigned int
// X86_64-LINUX:#define __UINT_LEAST8_MAX__ 255
// X86_64-LINUX:#define __UINT_LEAST8_TYPE__ unsigned char
// X86_64-LINUX:#define __USER_LABEL_PREFIX__
// X86_64-LINUX:#define __WCHAR_MAX__ 2147483647
// X86_64-LINUX:#define __WCHAR_TYPE__ int
// X86_64-LINUX:#define __WCHAR_WIDTH__ 32
// X86_64-LINUX:#define __WINT_TYPE__ unsigned int
// X86_64-LINUX:#define __WINT_WIDTH__ 32
// X86_64-LINUX:#define __amd64 1
// X86_64-LINUX:#define __amd64__ 1
// X86_64-LINUX:#define __x86_64 1
// X86_64-LINUX:#define __x86_64__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-unknown-freebsd9.1 < /dev/null | FileCheck -match-full-lines -check-prefix X86_64-FREEBSD %s
//
// X86_64-FREEBSD:#define __DBL_DECIMAL_DIG__ 17
// X86_64-FREEBSD:#define __FLT_DECIMAL_DIG__ 9
// X86_64-FREEBSD:#define __FreeBSD__ 9
// X86_64-FREEBSD:#define __FreeBSD_cc_version 900001
// X86_64-FREEBSD:#define __LDBL_DECIMAL_DIG__ 21
// X86_64-FREEBSD:#define __STDC_MB_MIGHT_NEQ_WC__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-netbsd < /dev/null | FileCheck -match-full-lines -check-prefix X86_64-NETBSD %s
//
// X86_64-NETBSD:#define _LP64 1
// X86_64-NETBSD:#define __BIGGEST_ALIGNMENT__ 16
// X86_64-NETBSD:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// X86_64-NETBSD:#define __CHAR16_TYPE__ unsigned short
// X86_64-NETBSD:#define __CHAR32_TYPE__ unsigned int
// X86_64-NETBSD:#define __CHAR_BIT__ 8
// X86_64-NETBSD:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// X86_64-NETBSD:#define __DBL_DIG__ 15
// X86_64-NETBSD:#define __DBL_EPSILON__ 2.2204460492503131e-16
// X86_64-NETBSD:#define __DBL_HAS_DENORM__ 1
// X86_64-NETBSD:#define __DBL_HAS_INFINITY__ 1
// X86_64-NETBSD:#define __DBL_HAS_QUIET_NAN__ 1
// X86_64-NETBSD:#define __DBL_MANT_DIG__ 53
// X86_64-NETBSD:#define __DBL_MAX_10_EXP__ 308
// X86_64-NETBSD:#define __DBL_MAX_EXP__ 1024
// X86_64-NETBSD:#define __DBL_MAX__ 1.7976931348623157e+308
// X86_64-NETBSD:#define __DBL_MIN_10_EXP__ (-307)
// X86_64-NETBSD:#define __DBL_MIN_EXP__ (-1021)
// X86_64-NETBSD:#define __DBL_MIN__ 2.2250738585072014e-308
// X86_64-NETBSD:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// X86_64-NETBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// X86_64-NETBSD:#define __FLT_DIG__ 6
// X86_64-NETBSD:#define __FLT_EPSILON__ 1.19209290e-7F
// X86_64-NETBSD:#define __FLT_EVAL_METHOD__ 0
// X86_64-NETBSD:#define __FLT_HAS_DENORM__ 1
// X86_64-NETBSD:#define __FLT_HAS_INFINITY__ 1
// X86_64-NETBSD:#define __FLT_HAS_QUIET_NAN__ 1
// X86_64-NETBSD:#define __FLT_MANT_DIG__ 24
// X86_64-NETBSD:#define __FLT_MAX_10_EXP__ 38
// X86_64-NETBSD:#define __FLT_MAX_EXP__ 128
// X86_64-NETBSD:#define __FLT_MAX__ 3.40282347e+38F
// X86_64-NETBSD:#define __FLT_MIN_10_EXP__ (-37)
// X86_64-NETBSD:#define __FLT_MIN_EXP__ (-125)
// X86_64-NETBSD:#define __FLT_MIN__ 1.17549435e-38F
// X86_64-NETBSD:#define __FLT_RADIX__ 2
// X86_64-NETBSD:#define __INT16_C_SUFFIX__
// X86_64-NETBSD:#define __INT16_FMTd__ "hd"
// X86_64-NETBSD:#define __INT16_FMTi__ "hi"
// X86_64-NETBSD:#define __INT16_MAX__ 32767
// X86_64-NETBSD:#define __INT16_TYPE__ short
// X86_64-NETBSD:#define __INT32_C_SUFFIX__
// X86_64-NETBSD:#define __INT32_FMTd__ "d"
// X86_64-NETBSD:#define __INT32_FMTi__ "i"
// X86_64-NETBSD:#define __INT32_MAX__ 2147483647
// X86_64-NETBSD:#define __INT32_TYPE__ int
// X86_64-NETBSD:#define __INT64_C_SUFFIX__ L
// X86_64-NETBSD:#define __INT64_FMTd__ "ld"
// X86_64-NETBSD:#define __INT64_FMTi__ "li"
// X86_64-NETBSD:#define __INT64_MAX__ 9223372036854775807L
// X86_64-NETBSD:#define __INT64_TYPE__ long int
// X86_64-NETBSD:#define __INT8_C_SUFFIX__
// X86_64-NETBSD:#define __INT8_FMTd__ "hhd"
// X86_64-NETBSD:#define __INT8_FMTi__ "hhi"
// X86_64-NETBSD:#define __INT8_MAX__ 127
// X86_64-NETBSD:#define __INT8_TYPE__ signed char
// X86_64-NETBSD:#define __INTMAX_C_SUFFIX__ L
// X86_64-NETBSD:#define __INTMAX_FMTd__ "ld"
// X86_64-NETBSD:#define __INTMAX_FMTi__ "li"
// X86_64-NETBSD:#define __INTMAX_MAX__ 9223372036854775807L
// X86_64-NETBSD:#define __INTMAX_TYPE__ long int
// X86_64-NETBSD:#define __INTMAX_WIDTH__ 64
// X86_64-NETBSD:#define __INTPTR_FMTd__ "ld"
// X86_64-NETBSD:#define __INTPTR_FMTi__ "li"
// X86_64-NETBSD:#define __INTPTR_MAX__ 9223372036854775807L
// X86_64-NETBSD:#define __INTPTR_TYPE__ long int
// X86_64-NETBSD:#define __INTPTR_WIDTH__ 64
// X86_64-NETBSD:#define __INT_FAST16_FMTd__ "hd"
// X86_64-NETBSD:#define __INT_FAST16_FMTi__ "hi"
// X86_64-NETBSD:#define __INT_FAST16_MAX__ 32767
// X86_64-NETBSD:#define __INT_FAST16_TYPE__ short
// X86_64-NETBSD:#define __INT_FAST32_FMTd__ "d"
// X86_64-NETBSD:#define __INT_FAST32_FMTi__ "i"
// X86_64-NETBSD:#define __INT_FAST32_MAX__ 2147483647
// X86_64-NETBSD:#define __INT_FAST32_TYPE__ int
// X86_64-NETBSD:#define __INT_FAST64_FMTd__ "ld"
// X86_64-NETBSD:#define __INT_FAST64_FMTi__ "li"
// X86_64-NETBSD:#define __INT_FAST64_MAX__ 9223372036854775807L
// X86_64-NETBSD:#define __INT_FAST64_TYPE__ long int
// X86_64-NETBSD:#define __INT_FAST8_FMTd__ "hhd"
// X86_64-NETBSD:#define __INT_FAST8_FMTi__ "hhi"
// X86_64-NETBSD:#define __INT_FAST8_MAX__ 127
// X86_64-NETBSD:#define __INT_FAST8_TYPE__ signed char
// X86_64-NETBSD:#define __INT_LEAST16_FMTd__ "hd"
// X86_64-NETBSD:#define __INT_LEAST16_FMTi__ "hi"
// X86_64-NETBSD:#define __INT_LEAST16_MAX__ 32767
// X86_64-NETBSD:#define __INT_LEAST16_TYPE__ short
// X86_64-NETBSD:#define __INT_LEAST32_FMTd__ "d"
// X86_64-NETBSD:#define __INT_LEAST32_FMTi__ "i"
// X86_64-NETBSD:#define __INT_LEAST32_MAX__ 2147483647
// X86_64-NETBSD:#define __INT_LEAST32_TYPE__ int
// X86_64-NETBSD:#define __INT_LEAST64_FMTd__ "ld"
// X86_64-NETBSD:#define __INT_LEAST64_FMTi__ "li"
// X86_64-NETBSD:#define __INT_LEAST64_MAX__ 9223372036854775807L
// X86_64-NETBSD:#define __INT_LEAST64_TYPE__ long int
// X86_64-NETBSD:#define __INT_LEAST8_FMTd__ "hhd"
// X86_64-NETBSD:#define __INT_LEAST8_FMTi__ "hhi"
// X86_64-NETBSD:#define __INT_LEAST8_MAX__ 127
// X86_64-NETBSD:#define __INT_LEAST8_TYPE__ signed char
// X86_64-NETBSD:#define __INT_MAX__ 2147483647
// X86_64-NETBSD:#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
// X86_64-NETBSD:#define __LDBL_DIG__ 18
// X86_64-NETBSD:#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
// X86_64-NETBSD:#define __LDBL_HAS_DENORM__ 1
// X86_64-NETBSD:#define __LDBL_HAS_INFINITY__ 1
// X86_64-NETBSD:#define __LDBL_HAS_QUIET_NAN__ 1
// X86_64-NETBSD:#define __LDBL_MANT_DIG__ 64
// X86_64-NETBSD:#define __LDBL_MAX_10_EXP__ 4932
// X86_64-NETBSD:#define __LDBL_MAX_EXP__ 16384
// X86_64-NETBSD:#define __LDBL_MAX__ 1.18973149535723176502e+4932L
// X86_64-NETBSD:#define __LDBL_MIN_10_EXP__ (-4931)
// X86_64-NETBSD:#define __LDBL_MIN_EXP__ (-16381)
// X86_64-NETBSD:#define __LDBL_MIN__ 3.36210314311209350626e-4932L
// X86_64-NETBSD:#define __LITTLE_ENDIAN__ 1
// X86_64-NETBSD:#define __LONG_LONG_MAX__ 9223372036854775807LL
// X86_64-NETBSD:#define __LONG_MAX__ 9223372036854775807L
// X86_64-NETBSD:#define __LP64__ 1
// X86_64-NETBSD:#define __MMX__ 1
// X86_64-NETBSD:#define __NO_MATH_INLINES 1
// X86_64-NETBSD:#define __POINTER_WIDTH__ 64
// X86_64-NETBSD:#define __PTRDIFF_TYPE__ long int
// X86_64-NETBSD:#define __PTRDIFF_WIDTH__ 64
// X86_64-NETBSD:#define __REGISTER_PREFIX__
// X86_64-NETBSD:#define __SCHAR_MAX__ 127
// X86_64-NETBSD:#define __SHRT_MAX__ 32767
// X86_64-NETBSD:#define __SIG_ATOMIC_MAX__ 2147483647
// X86_64-NETBSD:#define __SIG_ATOMIC_WIDTH__ 32
// X86_64-NETBSD:#define __SIZEOF_DOUBLE__ 8
// X86_64-NETBSD:#define __SIZEOF_FLOAT__ 4
// X86_64-NETBSD:#define __SIZEOF_INT__ 4
// X86_64-NETBSD:#define __SIZEOF_LONG_DOUBLE__ 16
// X86_64-NETBSD:#define __SIZEOF_LONG_LONG__ 8
// X86_64-NETBSD:#define __SIZEOF_LONG__ 8
// X86_64-NETBSD:#define __SIZEOF_POINTER__ 8
// X86_64-NETBSD:#define __SIZEOF_PTRDIFF_T__ 8
// X86_64-NETBSD:#define __SIZEOF_SHORT__ 2
// X86_64-NETBSD:#define __SIZEOF_SIZE_T__ 8
// X86_64-NETBSD:#define __SIZEOF_WCHAR_T__ 4
// X86_64-NETBSD:#define __SIZEOF_WINT_T__ 4
// X86_64-NETBSD:#define __SIZE_MAX__ 18446744073709551615UL
// X86_64-NETBSD:#define __SIZE_TYPE__ long unsigned int
// X86_64-NETBSD:#define __SIZE_WIDTH__ 64
// X86_64-NETBSD:#define __SSE2_MATH__ 1
// X86_64-NETBSD:#define __SSE2__ 1
// X86_64-NETBSD:#define __SSE_MATH__ 1
// X86_64-NETBSD:#define __SSE__ 1
// X86_64-NETBSD:#define __UINT16_C_SUFFIX__
// X86_64-NETBSD:#define __UINT16_MAX__ 65535
// X86_64-NETBSD:#define __UINT16_TYPE__ unsigned short
// X86_64-NETBSD:#define __UINT32_C_SUFFIX__ U
// X86_64-NETBSD:#define __UINT32_MAX__ 4294967295U
// X86_64-NETBSD:#define __UINT32_TYPE__ unsigned int
// X86_64-NETBSD:#define __UINT64_C_SUFFIX__ UL
// X86_64-NETBSD:#define __UINT64_MAX__ 18446744073709551615UL
// X86_64-NETBSD:#define __UINT64_TYPE__ long unsigned int
// X86_64-NETBSD:#define __UINT8_C_SUFFIX__
// X86_64-NETBSD:#define __UINT8_MAX__ 255
// X86_64-NETBSD:#define __UINT8_TYPE__ unsigned char
// X86_64-NETBSD:#define __UINTMAX_C_SUFFIX__ UL
// X86_64-NETBSD:#define __UINTMAX_MAX__ 18446744073709551615UL
// X86_64-NETBSD:#define __UINTMAX_TYPE__ long unsigned int
// X86_64-NETBSD:#define __UINTMAX_WIDTH__ 64
// X86_64-NETBSD:#define __UINTPTR_MAX__ 18446744073709551615UL
// X86_64-NETBSD:#define __UINTPTR_TYPE__ long unsigned int
// X86_64-NETBSD:#define __UINTPTR_WIDTH__ 64
// X86_64-NETBSD:#define __UINT_FAST16_MAX__ 65535
// X86_64-NETBSD:#define __UINT_FAST16_TYPE__ unsigned short
// X86_64-NETBSD:#define __UINT_FAST32_MAX__ 4294967295U
// X86_64-NETBSD:#define __UINT_FAST32_TYPE__ unsigned int
// X86_64-NETBSD:#define __UINT_FAST64_MAX__ 18446744073709551615UL
// X86_64-NETBSD:#define __UINT_FAST64_TYPE__ long unsigned int
// X86_64-NETBSD:#define __UINT_FAST8_MAX__ 255
// X86_64-NETBSD:#define __UINT_FAST8_TYPE__ unsigned char
// X86_64-NETBSD:#define __UINT_LEAST16_MAX__ 65535
// X86_64-NETBSD:#define __UINT_LEAST16_TYPE__ unsigned short
// X86_64-NETBSD:#define __UINT_LEAST32_MAX__ 4294967295U
// X86_64-NETBSD:#define __UINT_LEAST32_TYPE__ unsigned int
// X86_64-NETBSD:#define __UINT_LEAST64_MAX__ 18446744073709551615UL
// X86_64-NETBSD:#define __UINT_LEAST64_TYPE__ long unsigned int
// X86_64-NETBSD:#define __UINT_LEAST8_MAX__ 255
// X86_64-NETBSD:#define __UINT_LEAST8_TYPE__ unsigned char
// X86_64-NETBSD:#define __USER_LABEL_PREFIX__
// X86_64-NETBSD:#define __WCHAR_MAX__ 2147483647
// X86_64-NETBSD:#define __WCHAR_TYPE__ int
// X86_64-NETBSD:#define __WCHAR_WIDTH__ 32
// X86_64-NETBSD:#define __WINT_TYPE__ int
// X86_64-NETBSD:#define __WINT_WIDTH__ 32
// X86_64-NETBSD:#define __amd64 1
// X86_64-NETBSD:#define __amd64__ 1
// X86_64-NETBSD:#define __x86_64 1
// X86_64-NETBSD:#define __x86_64__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-scei-ps4 < /dev/null | FileCheck -match-full-lines -check-prefix PS4 %s
//
// PS4:#define _LP64 1
// PS4:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// PS4:#define __CHAR16_TYPE__ unsigned short
// PS4:#define __CHAR32_TYPE__ unsigned int
// PS4:#define __CHAR_BIT__ 8
// PS4:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// PS4:#define __DBL_DIG__ 15
// PS4:#define __DBL_EPSILON__ 2.2204460492503131e-16
// PS4:#define __DBL_HAS_DENORM__ 1
// PS4:#define __DBL_HAS_INFINITY__ 1
// PS4:#define __DBL_HAS_QUIET_NAN__ 1
// PS4:#define __DBL_MANT_DIG__ 53
// PS4:#define __DBL_MAX_10_EXP__ 308
// PS4:#define __DBL_MAX_EXP__ 1024
// PS4:#define __DBL_MAX__ 1.7976931348623157e+308
// PS4:#define __DBL_MIN_10_EXP__ (-307)
// PS4:#define __DBL_MIN_EXP__ (-1021)
// PS4:#define __DBL_MIN__ 2.2250738585072014e-308
// PS4:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// PS4:#define __ELF__ 1
// PS4:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// PS4:#define __FLT_DIG__ 6
// PS4:#define __FLT_EPSILON__ 1.19209290e-7F
// PS4:#define __FLT_EVAL_METHOD__ 0
// PS4:#define __FLT_HAS_DENORM__ 1
// PS4:#define __FLT_HAS_INFINITY__ 1
// PS4:#define __FLT_HAS_QUIET_NAN__ 1
// PS4:#define __FLT_MANT_DIG__ 24
// PS4:#define __FLT_MAX_10_EXP__ 38
// PS4:#define __FLT_MAX_EXP__ 128
// PS4:#define __FLT_MAX__ 3.40282347e+38F
// PS4:#define __FLT_MIN_10_EXP__ (-37)
// PS4:#define __FLT_MIN_EXP__ (-125)
// PS4:#define __FLT_MIN__ 1.17549435e-38F
// PS4:#define __FLT_RADIX__ 2
// PS4:#define __FreeBSD__ 9
// PS4:#define __FreeBSD_cc_version 900001
// PS4:#define __INT16_TYPE__ short
// PS4:#define __INT32_TYPE__ int
// PS4:#define __INT64_C_SUFFIX__ L
// PS4:#define __INT64_TYPE__ long int
// PS4:#define __INT8_TYPE__ signed char
// PS4:#define __INTMAX_MAX__ 9223372036854775807L
// PS4:#define __INTMAX_TYPE__ long int
// PS4:#define __INTMAX_WIDTH__ 64
// PS4:#define __INTPTR_TYPE__ long int
// PS4:#define __INTPTR_WIDTH__ 64
// PS4:#define __INT_MAX__ 2147483647
// PS4:#define __KPRINTF_ATTRIBUTE__ 1
// PS4:#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
// PS4:#define __LDBL_DIG__ 18
// PS4:#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
// PS4:#define __LDBL_HAS_DENORM__ 1
// PS4:#define __LDBL_HAS_INFINITY__ 1
// PS4:#define __LDBL_HAS_QUIET_NAN__ 1
// PS4:#define __LDBL_MANT_DIG__ 64
// PS4:#define __LDBL_MAX_10_EXP__ 4932
// PS4:#define __LDBL_MAX_EXP__ 16384
// PS4:#define __LDBL_MAX__ 1.18973149535723176502e+4932L
// PS4:#define __LDBL_MIN_10_EXP__ (-4931)
// PS4:#define __LDBL_MIN_EXP__ (-16381)
// PS4:#define __LDBL_MIN__ 3.36210314311209350626e-4932L
// PS4:#define __LITTLE_ENDIAN__ 1
// PS4:#define __LONG_LONG_MAX__ 9223372036854775807LL
// PS4:#define __LONG_MAX__ 9223372036854775807L
// PS4:#define __LP64__ 1
// PS4:#define __MMX__ 1
// PS4:#define __NO_MATH_INLINES 1
// PS4:#define __ORBIS__ 1
// PS4:#define __POINTER_WIDTH__ 64
// PS4:#define __PTRDIFF_MAX__ 9223372036854775807L
// PS4:#define __PTRDIFF_TYPE__ long int
// PS4:#define __PTRDIFF_WIDTH__ 64
// PS4:#define __REGISTER_PREFIX__
// PS4:#define __SCHAR_MAX__ 127
// PS4:#define __SHRT_MAX__ 32767
// PS4:#define __SIG_ATOMIC_MAX__ 2147483647
// PS4:#define __SIG_ATOMIC_WIDTH__ 32
// PS4:#define __SIZEOF_DOUBLE__ 8
// PS4:#define __SIZEOF_FLOAT__ 4
// PS4:#define __SIZEOF_INT__ 4
// PS4:#define __SIZEOF_LONG_DOUBLE__ 16
// PS4:#define __SIZEOF_LONG_LONG__ 8
// PS4:#define __SIZEOF_LONG__ 8
// PS4:#define __SIZEOF_POINTER__ 8
// PS4:#define __SIZEOF_PTRDIFF_T__ 8
// PS4:#define __SIZEOF_SHORT__ 2
// PS4:#define __SIZEOF_SIZE_T__ 8
// PS4:#define __SIZEOF_WCHAR_T__ 2
// PS4:#define __SIZEOF_WINT_T__ 4
// PS4:#define __SIZE_TYPE__ long unsigned int
// PS4:#define __SIZE_WIDTH__ 64
// PS4:#define __SSE2_MATH__ 1
// PS4:#define __SSE2__ 1
// PS4:#define __SSE_MATH__ 1
// PS4:#define __SSE__ 1
// PS4:#define __STDC_VERSION__ 199901L
// PS4:#define __UINTMAX_TYPE__ long unsigned int
// PS4:#define __USER_LABEL_PREFIX__
// PS4:#define __WCHAR_MAX__ 65535
// PS4:#define __WCHAR_TYPE__ unsigned short
// PS4:#define __WCHAR_UNSIGNED__ 1
// PS4:#define __WCHAR_WIDTH__ 16
// PS4:#define __WINT_TYPE__ int
// PS4:#define __WINT_WIDTH__ 32
// PS4:#define __amd64 1
// PS4:#define __amd64__ 1
// PS4:#define __unix 1
// PS4:#define __unix__ 1
// PS4:#define __x86_64 1
// PS4:#define __x86_64__ 1
// PS4:#define unix 1
//
// RUN: %clang_cc1 -x c++ -E -dM -ffreestanding -triple=x86_64-scei-ps4 < /dev/null | FileCheck -match-full-lines -check-prefix PS4-CXX %s
// PS4-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 32UL
//
// RUN: %clang_cc1 -E -dM -triple=x86_64-pc-mingw32 < /dev/null | FileCheck -match-full-lines -check-prefix X86-64-DECLSPEC %s
// RUN: %clang_cc1 -E -dM -fms-extensions -triple=x86_64-unknown-mingw32 < /dev/null | FileCheck -match-full-lines -check-prefix X86-64-DECLSPEC %s
// X86-64-DECLSPEC: #define __declspec{{.*}}
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=sparc64-none-none < /dev/null | FileCheck -match-full-lines -check-prefix SPARCV9 %s
// SPARCV9:#define __INT64_TYPE__ long int
// SPARCV9:#define __INTMAX_C_SUFFIX__ L
// SPARCV9:#define __INTMAX_TYPE__ long int
// SPARCV9:#define __INTPTR_TYPE__ long int
// SPARCV9:#define __LONG_MAX__ 9223372036854775807L
// SPARCV9:#define __LP64__ 1
// SPARCV9:#define __SIZEOF_LONG__ 8
// SPARCV9:#define __SIZEOF_POINTER__ 8
// SPARCV9:#define __UINTPTR_TYPE__ long unsigned int
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=sparc64-none-openbsd < /dev/null | FileCheck -match-full-lines -check-prefix SPARC64-OBSD %s
// SPARC64-OBSD:#define __INT64_TYPE__ long long int
// SPARC64-OBSD:#define __INTMAX_C_SUFFIX__ LL
// SPARC64-OBSD:#define __INTMAX_TYPE__ long long int
// SPARC64-OBSD:#define __UINTMAX_C_SUFFIX__ ULL
// SPARC64-OBSD:#define __UINTMAX_TYPE__ long long unsigned int
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=x86_64-pc-kfreebsd-gnu < /dev/null | FileCheck -match-full-lines -check-prefix KFREEBSD-DEFINE %s
// KFREEBSD-DEFINE:#define __FreeBSD_kernel__ 1
// KFREEBSD-DEFINE:#define __GLIBC__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i686-pc-kfreebsd-gnu < /dev/null | FileCheck -match-full-lines -check-prefix KFREEBSDI686-DEFINE %s
// KFREEBSDI686-DEFINE:#define __FreeBSD_kernel__ 1
// KFREEBSDI686-DEFINE:#define __GLIBC__ 1
//
// RUN: %clang_cc1 -x c++ -triple i686-pc-linux-gnu -fobjc-runtime=gcc -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GNUSOURCE %s
// RUN: %clang_cc1 -x c++ -triple sparc-rtems-elf -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GNUSOURCE %s
// GNUSOURCE:#define _GNU_SOURCE 1
//
// Check that the GNUstep Objective-C ABI defines exist and are clamped at the
// highest supported version.
// RUN: %clang_cc1 -x objective-c -triple i386-unknown-freebsd -fobjc-runtime=gnustep-1.9 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GNUSTEP1 %s
// GNUSTEP1:#define __OBJC_GNUSTEP_RUNTIME_ABI__ 18
// RUN: %clang_cc1 -x objective-c -triple i386-unknown-freebsd -fobjc-runtime=gnustep-2.5 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix GNUSTEP2 %s
// GNUSTEP2:#define __OBJC_GNUSTEP_RUNTIME_ABI__ 20
//
// RUN: %clang_cc1 -x c++ -std=c++98 -fno-rtti -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix NORTTI %s
// NORTTI: #define __GXX_ABI_VERSION {{.*}}
// NORTTI-NOT:#define __GXX_RTTI
// NORTTI:#define __STDC__ 1
//
// RUN: %clang_cc1 -triple arm-linux-androideabi -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix ANDROID %s
// ANDROID-NOT:#define __ANDROID_API__
// ANDROID:#define __ANDROID__ 1
// ANDROID-NOT:#define __gnu_linux__
//
// RUN: %clang_cc1 -x c++ -triple i686-linux-android -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix I386-ANDROID-CXX %s
// I386-ANDROID-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
//
// RUN: %clang_cc1 -x c++ -triple x86_64-linux-android -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix X86_64-ANDROID-CXX %s
// X86_64-ANDROID-CXX:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16UL
//
// RUN: %clang_cc1 -triple arm-linux-androideabi20 -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix ANDROID20 %s
// ANDROID20:#define __ANDROID_API__ 20
// ANDROID20:#define __ANDROID__ 1
// ANDROID-NOT:#define __gnu_linux__
//
// RUN: %clang_cc1 -triple lanai-unknown-unknown -E -dM < /dev/null | FileCheck -match-full-lines -check-prefix LANAI %s
// LANAI: #define __lanai__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=amd64-unknown-openbsd6.1 < /dev/null | FileCheck -match-full-lines -check-prefix OPENBSD %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=aarch64-unknown-openbsd6.1 < /dev/null | FileCheck -match-full-lines -check-prefix OPENBSD %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=arm-unknown-openbsd6.1-gnueabi < /dev/null | FileCheck -match-full-lines -check-prefix OPENBSD %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-unknown-openbsd6.1 < /dev/null | FileCheck -match-full-lines -check-prefix OPENBSD %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc-unknown-openbsd6.1 < /dev/null | FileCheck -match-full-lines -check-prefix OPENBSD %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips64-unknown-openbsd6.1 < /dev/null | FileCheck -match-full-lines -check-prefix OPENBSD %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=mips64el-unknown-openbsd6.1 < /dev/null | FileCheck -match-full-lines -check-prefix OPENBSD %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=sparc64-unknown-openbsd6.1 < /dev/null | FileCheck -match-full-lines -check-prefix OPENBSD %s
// OPENBSD:#define __ELF__ 1
// OPENBSD:#define __INT16_TYPE__ short
// OPENBSD:#define __INT32_TYPE__ int
// OPENBSD:#define __INT64_TYPE__ long long int
// OPENBSD:#define __INT8_TYPE__ signed char
// OPENBSD:#define __INTMAX_TYPE__ long long int
// OPENBSD:#define __INTPTR_TYPE__ long int
// OPENBSD:#define __OpenBSD__ 1
// OPENBSD:#define __PTRDIFF_TYPE__ long int
// OPENBSD:#define __SIZE_TYPE__ long unsigned int
// OPENBSD:#define __UINT16_TYPE__ unsigned short
// OPENBSD:#define __UINT32_TYPE__ unsigned int
// OPENBSD:#define __UINT64_TYPE__ long long unsigned int
// OPENBSD:#define __UINT8_TYPE__ unsigned char
// OPENBSD:#define __UINTMAX_TYPE__ long long unsigned int
// OPENBSD:#define __UINTPTR_TYPE__ long unsigned int
// OPENBSD:#define __WCHAR_TYPE__ int
// OPENBSD:#define __WINT_TYPE__ int
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-freebsd < /dev/null | FileCheck -match-full-lines -check-prefix PPC64-FREEBSD %s
// PPC64-FREEBSD-NOT: #define __LONG_DOUBLE_128__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=xcore-none-none < /dev/null | FileCheck -match-full-lines -check-prefix XCORE %s
// XCORE:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// XCORE:#define __LITTLE_ENDIAN__ 1
// XCORE:#define __XS1B__ 1
//
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=wasm32-unknown-unknown \
// RUN: < /dev/null \
-// RUN: | FileCheck -match-full-lines -check-prefix=WEBASSEMBLY32 %s
+// RUN: | FileCheck -match-full-lines -check-prefixes=WEBASSEMBLY,WEBASSEMBLY32 %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=wasm64-unknown-unknown \
+// RUN: < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefixes=WEBASSEMBLY,WEBASSEMBLY64 %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=wasm32-unknown-wasi \
+// RUN: < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefixes=WEBASSEMBLY,WEBASSEMBLY32,WEBASSEMBLY-WASI %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -triple=wasm64-unknown-wasi \
+// RUN: < /dev/null \
+// RUN: | FileCheck -match-full-lines -check-prefixes=WEBASSEMBLY,WEBASSEMBLY64,WEBASSEMBLY-WASI %s
//
// WEBASSEMBLY32:#define _ILP32 1
// WEBASSEMBLY32-NOT:#define _LP64
-// WEBASSEMBLY32-NEXT:#define __ATOMIC_ACQUIRE 2
-// WEBASSEMBLY32-NEXT:#define __ATOMIC_ACQ_REL 4
-// WEBASSEMBLY32-NEXT:#define __ATOMIC_CONSUME 1
-// WEBASSEMBLY32-NEXT:#define __ATOMIC_RELAXED 0
-// WEBASSEMBLY32-NEXT:#define __ATOMIC_RELEASE 3
-// WEBASSEMBLY32-NEXT:#define __ATOMIC_SEQ_CST 5
-// WEBASSEMBLY32-NEXT:#define __BIGGEST_ALIGNMENT__ 16
-// WEBASSEMBLY32-NEXT:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
-// WEBASSEMBLY32-NEXT:#define __CHAR16_TYPE__ unsigned short
-// WEBASSEMBLY32-NEXT:#define __CHAR32_TYPE__ unsigned int
-// WEBASSEMBLY32-NEXT:#define __CHAR_BIT__ 8
-// WEBASSEMBLY32-NOT:#define __CHAR_UNSIGNED__
-// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_BOOL_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_CHAR_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_INT_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_LLONG_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_LONG_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_POINTER_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_SHORT_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __CONSTANT_CFSTRINGS__ 1
-// WEBASSEMBLY32-NEXT:#define __DBL_DECIMAL_DIG__ 17
-// WEBASSEMBLY32-NEXT:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
-// WEBASSEMBLY32-NEXT:#define __DBL_DIG__ 15
-// WEBASSEMBLY32-NEXT:#define __DBL_EPSILON__ 2.2204460492503131e-16
-// WEBASSEMBLY32-NEXT:#define __DBL_HAS_DENORM__ 1
-// WEBASSEMBLY32-NEXT:#define __DBL_HAS_INFINITY__ 1
-// WEBASSEMBLY32-NEXT:#define __DBL_HAS_QUIET_NAN__ 1
-// WEBASSEMBLY32-NEXT:#define __DBL_MANT_DIG__ 53
-// WEBASSEMBLY32-NEXT:#define __DBL_MAX_10_EXP__ 308
-// WEBASSEMBLY32-NEXT:#define __DBL_MAX_EXP__ 1024
-// WEBASSEMBLY32-NEXT:#define __DBL_MAX__ 1.7976931348623157e+308
-// WEBASSEMBLY32-NEXT:#define __DBL_MIN_10_EXP__ (-307)
-// WEBASSEMBLY32-NEXT:#define __DBL_MIN_EXP__ (-1021)
-// WEBASSEMBLY32-NEXT:#define __DBL_MIN__ 2.2250738585072014e-308
-// WEBASSEMBLY32-NEXT:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
-// WEBASSEMBLY32-NOT:#define __ELF__
-// WEBASSEMBLY32-NEXT:#define __FINITE_MATH_ONLY__ 0
-// WEBASSEMBLY32:#define __FLT_DECIMAL_DIG__ 9
-// WEBASSEMBLY32-NEXT:#define __FLT_DENORM_MIN__ 1.40129846e-45F
-// WEBASSEMBLY32-NEXT:#define __FLT_DIG__ 6
-// WEBASSEMBLY32-NEXT:#define __FLT_EPSILON__ 1.19209290e-7F
-// WEBASSEMBLY32-NEXT:#define __FLT_EVAL_METHOD__ 0
-// WEBASSEMBLY32-NEXT:#define __FLT_HAS_DENORM__ 1
-// WEBASSEMBLY32-NEXT:#define __FLT_HAS_INFINITY__ 1
-// WEBASSEMBLY32-NEXT:#define __FLT_HAS_QUIET_NAN__ 1
-// WEBASSEMBLY32-NEXT:#define __FLT_MANT_DIG__ 24
-// WEBASSEMBLY32-NEXT:#define __FLT_MAX_10_EXP__ 38
-// WEBASSEMBLY32-NEXT:#define __FLT_MAX_EXP__ 128
-// WEBASSEMBLY32-NEXT:#define __FLT_MAX__ 3.40282347e+38F
-// WEBASSEMBLY32-NEXT:#define __FLT_MIN_10_EXP__ (-37)
-// WEBASSEMBLY32-NEXT:#define __FLT_MIN_EXP__ (-125)
-// WEBASSEMBLY32-NEXT:#define __FLT_MIN__ 1.17549435e-38F
-// WEBASSEMBLY32-NEXT:#define __FLT_RADIX__ 2
-// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_BOOL_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_INT_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_LLONG_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_LONG_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_SHORT_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
-// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
-// WEBASSEMBLY32-NEXT:#define __GNUC_MINOR__ {{.*}}
-// WEBASSEMBLY32-NEXT:#define __GNUC_PATCHLEVEL__ {{.*}}
-// WEBASSEMBLY32-NEXT:#define __GNUC_STDC_INLINE__ 1
-// WEBASSEMBLY32-NEXT:#define __GNUC__ {{.*}}
-// WEBASSEMBLY32-NEXT:#define __GXX_ABI_VERSION 1002
+// WEBASSEMBLY64-NOT:#define _ILP32
+// WEBASSEMBLY64:#define _LP64 1
+// WEBASSEMBLY-NEXT:#define __ATOMIC_ACQUIRE 2
+// WEBASSEMBLY-NEXT:#define __ATOMIC_ACQ_REL 4
+// WEBASSEMBLY-NEXT:#define __ATOMIC_CONSUME 1
+// WEBASSEMBLY-NEXT:#define __ATOMIC_RELAXED 0
+// WEBASSEMBLY-NEXT:#define __ATOMIC_RELEASE 3
+// WEBASSEMBLY-NEXT:#define __ATOMIC_SEQ_CST 5
+// WEBASSEMBLY-NEXT:#define __BIGGEST_ALIGNMENT__ 16
+// WEBASSEMBLY-NEXT:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+// WEBASSEMBLY-NEXT:#define __CHAR16_TYPE__ unsigned short
+// WEBASSEMBLY-NEXT:#define __CHAR32_TYPE__ unsigned int
+// WEBASSEMBLY-NEXT:#define __CHAR_BIT__ 8
+// WEBASSEMBLY-NOT:#define __CHAR_UNSIGNED__
+// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_BOOL_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_CHAR_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_INT_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_LLONG_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_LONG_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_POINTER_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_SHORT_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __CONSTANT_CFSTRINGS__ 1
+// WEBASSEMBLY-NEXT:#define __DBL_DECIMAL_DIG__ 17
+// WEBASSEMBLY-NEXT:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+// WEBASSEMBLY-NEXT:#define __DBL_DIG__ 15
+// WEBASSEMBLY-NEXT:#define __DBL_EPSILON__ 2.2204460492503131e-16
+// WEBASSEMBLY-NEXT:#define __DBL_HAS_DENORM__ 1
+// WEBASSEMBLY-NEXT:#define __DBL_HAS_INFINITY__ 1
+// WEBASSEMBLY-NEXT:#define __DBL_HAS_QUIET_NAN__ 1
+// WEBASSEMBLY-NEXT:#define __DBL_MANT_DIG__ 53
+// WEBASSEMBLY-NEXT:#define __DBL_MAX_10_EXP__ 308
+// WEBASSEMBLY-NEXT:#define __DBL_MAX_EXP__ 1024
+// WEBASSEMBLY-NEXT:#define __DBL_MAX__ 1.7976931348623157e+308
+// WEBASSEMBLY-NEXT:#define __DBL_MIN_10_EXP__ (-307)
+// WEBASSEMBLY-NEXT:#define __DBL_MIN_EXP__ (-1021)
+// WEBASSEMBLY-NEXT:#define __DBL_MIN__ 2.2250738585072014e-308
+// WEBASSEMBLY-NEXT:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
+// WEBASSEMBLY-NOT:#define __ELF__
+// WEBASSEMBLY-NEXT:#define __FINITE_MATH_ONLY__ 0
+// WEBASSEMBLY-NEXT:#define __FLT16_DECIMAL_DIG__ 5
+// WEBASSEMBLY-NEXT:#define __FLT16_DENORM_MIN__ 5.9604644775390625e-8F16
+// WEBASSEMBLY-NEXT:#define __FLT16_DIG__ 3
+// WEBASSEMBLY-NEXT:#define __FLT16_EPSILON__ 9.765625e-4F16
+// WEBASSEMBLY-NEXT:#define __FLT16_HAS_DENORM__ 1
+// WEBASSEMBLY-NEXT:#define __FLT16_HAS_INFINITY__ 1
+// WEBASSEMBLY-NEXT:#define __FLT16_HAS_QUIET_NAN__ 1
+// WEBASSEMBLY-NEXT:#define __FLT16_MANT_DIG__ 11
+// WEBASSEMBLY-NEXT:#define __FLT16_MAX_10_EXP__ 4
+// WEBASSEMBLY-NEXT:#define __FLT16_MAX_EXP__ 15
+// WEBASSEMBLY-NEXT:#define __FLT16_MAX__ 6.5504e+4F16
+// WEBASSEMBLY-NEXT:#define __FLT16_MIN_10_EXP__ (-13)
+// WEBASSEMBLY-NEXT:#define __FLT16_MIN_EXP__ (-14)
+// WEBASSEMBLY-NEXT:#define __FLT16_MIN__ 6.103515625e-5F16
+// WEBASSEMBLY-NEXT:#define __FLT_DECIMAL_DIG__ 9
+// WEBASSEMBLY-NEXT:#define __FLT_DENORM_MIN__ 1.40129846e-45F
+// WEBASSEMBLY-NEXT:#define __FLT_DIG__ 6
+// WEBASSEMBLY-NEXT:#define __FLT_EPSILON__ 1.19209290e-7F
+// WEBASSEMBLY-NEXT:#define __FLT_EVAL_METHOD__ 0
+// WEBASSEMBLY-NEXT:#define __FLT_HAS_DENORM__ 1
+// WEBASSEMBLY-NEXT:#define __FLT_HAS_INFINITY__ 1
+// WEBASSEMBLY-NEXT:#define __FLT_HAS_QUIET_NAN__ 1
+// WEBASSEMBLY-NEXT:#define __FLT_MANT_DIG__ 24
+// WEBASSEMBLY-NEXT:#define __FLT_MAX_10_EXP__ 38
+// WEBASSEMBLY-NEXT:#define __FLT_MAX_EXP__ 128
+// WEBASSEMBLY-NEXT:#define __FLT_MAX__ 3.40282347e+38F
+// WEBASSEMBLY-NEXT:#define __FLT_MIN_10_EXP__ (-37)
+// WEBASSEMBLY-NEXT:#define __FLT_MIN_EXP__ (-125)
+// WEBASSEMBLY-NEXT:#define __FLT_MIN__ 1.17549435e-38F
+// WEBASSEMBLY-NEXT:#define __FLT_RADIX__ 2
+// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_BOOL_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_INT_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_LLONG_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_LONG_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_SHORT_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+// WEBASSEMBLY-NEXT:#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+// WEBASSEMBLY-NEXT:#define __GNUC_MINOR__ {{.*}}
+// WEBASSEMBLY-NEXT:#define __GNUC_PATCHLEVEL__ {{.*}}
+// WEBASSEMBLY-NEXT:#define __GNUC_STDC_INLINE__ 1
+// WEBASSEMBLY-NEXT:#define __GNUC__ {{.*}}
+// WEBASSEMBLY-NEXT:#define __GXX_ABI_VERSION 1002
// WEBASSEMBLY32-NEXT:#define __ILP32__ 1
-// WEBASSEMBLY32-NEXT:#define __INT16_C_SUFFIX__
-// WEBASSEMBLY32-NEXT:#define __INT16_FMTd__ "hd"
-// WEBASSEMBLY32-NEXT:#define __INT16_FMTi__ "hi"
-// WEBASSEMBLY32-NEXT:#define __INT16_MAX__ 32767
-// WEBASSEMBLY32-NEXT:#define __INT16_TYPE__ short
-// WEBASSEMBLY32-NEXT:#define __INT32_C_SUFFIX__
-// WEBASSEMBLY32-NEXT:#define __INT32_FMTd__ "d"
-// WEBASSEMBLY32-NEXT:#define __INT32_FMTi__ "i"
-// WEBASSEMBLY32-NEXT:#define __INT32_MAX__ 2147483647
-// WEBASSEMBLY32-NEXT:#define __INT32_TYPE__ int
-// WEBASSEMBLY32-NEXT:#define __INT64_C_SUFFIX__ LL
-// WEBASSEMBLY32-NEXT:#define __INT64_FMTd__ "lld"
-// WEBASSEMBLY32-NEXT:#define __INT64_FMTi__ "lli"
-// WEBASSEMBLY32-NEXT:#define __INT64_MAX__ 9223372036854775807LL
-// WEBASSEMBLY32-NEXT:#define __INT64_TYPE__ long long int
-// WEBASSEMBLY32-NEXT:#define __INT8_C_SUFFIX__
-// WEBASSEMBLY32-NEXT:#define __INT8_FMTd__ "hhd"
-// WEBASSEMBLY32-NEXT:#define __INT8_FMTi__ "hhi"
-// WEBASSEMBLY32-NEXT:#define __INT8_MAX__ 127
-// WEBASSEMBLY32-NEXT:#define __INT8_TYPE__ signed char
-// WEBASSEMBLY32-NEXT:#define __INTMAX_C_SUFFIX__ LL
-// WEBASSEMBLY32-NEXT:#define __INTMAX_FMTd__ "lld"
-// WEBASSEMBLY32-NEXT:#define __INTMAX_FMTi__ "lli"
-// WEBASSEMBLY32-NEXT:#define __INTMAX_MAX__ 9223372036854775807LL
-// WEBASSEMBLY32-NEXT:#define __INTMAX_TYPE__ long long int
-// WEBASSEMBLY32-NEXT:#define __INTMAX_WIDTH__ 64
-// WEBASSEMBLY32-NEXT:#define __INTPTR_FMTd__ "ld"
-// WEBASSEMBLY32-NEXT:#define __INTPTR_FMTi__ "li"
+// WEBASSEMBLY64-NOT:#define __ILP32__
+// WEBASSEMBLY-NEXT:#define __INT16_C_SUFFIX__
+// WEBASSEMBLY-NEXT:#define __INT16_FMTd__ "hd"
+// WEBASSEMBLY-NEXT:#define __INT16_FMTi__ "hi"
+// WEBASSEMBLY-NEXT:#define __INT16_MAX__ 32767
+// WEBASSEMBLY-NEXT:#define __INT16_TYPE__ short
+// WEBASSEMBLY-NEXT:#define __INT32_C_SUFFIX__
+// WEBASSEMBLY-NEXT:#define __INT32_FMTd__ "d"
+// WEBASSEMBLY-NEXT:#define __INT32_FMTi__ "i"
+// WEBASSEMBLY-NEXT:#define __INT32_MAX__ 2147483647
+// WEBASSEMBLY-NEXT:#define __INT32_TYPE__ int
+// WEBASSEMBLY-NEXT:#define __INT64_C_SUFFIX__ LL
+// WEBASSEMBLY-NEXT:#define __INT64_FMTd__ "lld"
+// WEBASSEMBLY-NEXT:#define __INT64_FMTi__ "lli"
+// WEBASSEMBLY-NEXT:#define __INT64_MAX__ 9223372036854775807LL
+// WEBASSEMBLY-NEXT:#define __INT64_TYPE__ long long int
+// WEBASSEMBLY-NEXT:#define __INT8_C_SUFFIX__
+// WEBASSEMBLY-NEXT:#define __INT8_FMTd__ "hhd"
+// WEBASSEMBLY-NEXT:#define __INT8_FMTi__ "hhi"
+// WEBASSEMBLY-NEXT:#define __INT8_MAX__ 127
+// WEBASSEMBLY-NEXT:#define __INT8_TYPE__ signed char
+// WEBASSEMBLY-NEXT:#define __INTMAX_C_SUFFIX__ LL
+// WEBASSEMBLY-NEXT:#define __INTMAX_FMTd__ "lld"
+// WEBASSEMBLY-NEXT:#define __INTMAX_FMTi__ "lli"
+// WEBASSEMBLY-NEXT:#define __INTMAX_MAX__ 9223372036854775807LL
+// WEBASSEMBLY-NEXT:#define __INTMAX_TYPE__ long long int
+// WEBASSEMBLY-NEXT:#define __INTMAX_WIDTH__ 64
+// WEBASSEMBLY-NEXT:#define __INTPTR_FMTd__ "ld"
+// WEBASSEMBLY-NEXT:#define __INTPTR_FMTi__ "li"
// WEBASSEMBLY32-NEXT:#define __INTPTR_MAX__ 2147483647L
-// WEBASSEMBLY32-NEXT:#define __INTPTR_TYPE__ long int
+// WEBASSEMBLY64-NEXT:#define __INTPTR_MAX__ 9223372036854775807L
+// WEBASSEMBLY-NEXT:#define __INTPTR_TYPE__ long int
// WEBASSEMBLY32-NEXT:#define __INTPTR_WIDTH__ 32
-// WEBASSEMBLY32-NEXT:#define __INT_FAST16_FMTd__ "hd"
-// WEBASSEMBLY32-NEXT:#define __INT_FAST16_FMTi__ "hi"
-// WEBASSEMBLY32-NEXT:#define __INT_FAST16_MAX__ 32767
-// WEBASSEMBLY32-NEXT:#define __INT_FAST16_TYPE__ short
-// WEBASSEMBLY32-NEXT:#define __INT_FAST32_FMTd__ "d"
-// WEBASSEMBLY32-NEXT:#define __INT_FAST32_FMTi__ "i"
-// WEBASSEMBLY32-NEXT:#define __INT_FAST32_MAX__ 2147483647
-// WEBASSEMBLY32-NEXT:#define __INT_FAST32_TYPE__ int
-// WEBASSEMBLY32-NEXT:#define __INT_FAST64_FMTd__ "lld"
-// WEBASSEMBLY32-NEXT:#define __INT_FAST64_FMTi__ "lli"
-// WEBASSEMBLY32-NEXT:#define __INT_FAST64_MAX__ 9223372036854775807LL
-// WEBASSEMBLY32-NEXT:#define __INT_FAST64_TYPE__ long long int
-// WEBASSEMBLY32-NEXT:#define __INT_FAST8_FMTd__ "hhd"
-// WEBASSEMBLY32-NEXT:#define __INT_FAST8_FMTi__ "hhi"
-// WEBASSEMBLY32-NEXT:#define __INT_FAST8_MAX__ 127
-// WEBASSEMBLY32-NEXT:#define __INT_FAST8_TYPE__ signed char
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST16_FMTd__ "hd"
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST16_FMTi__ "hi"
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST16_MAX__ 32767
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST16_TYPE__ short
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST32_FMTd__ "d"
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST32_FMTi__ "i"
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST32_MAX__ 2147483647
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST32_TYPE__ int
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST64_FMTd__ "lld"
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST64_FMTi__ "lli"
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST64_MAX__ 9223372036854775807LL
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST64_TYPE__ long long int
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST8_FMTd__ "hhd"
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST8_FMTi__ "hhi"
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST8_MAX__ 127
-// WEBASSEMBLY32-NEXT:#define __INT_LEAST8_TYPE__ signed char
-// WEBASSEMBLY32-NEXT:#define __INT_MAX__ 2147483647
-// WEBASSEMBLY32-NEXT:#define __LDBL_DECIMAL_DIG__ 36
-// WEBASSEMBLY32-NEXT:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
-// WEBASSEMBLY32-NEXT:#define __LDBL_DIG__ 33
-// WEBASSEMBLY32-NEXT:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
-// WEBASSEMBLY32-NEXT:#define __LDBL_HAS_DENORM__ 1
-// WEBASSEMBLY32-NEXT:#define __LDBL_HAS_INFINITY__ 1
-// WEBASSEMBLY32-NEXT:#define __LDBL_HAS_QUIET_NAN__ 1
-// WEBASSEMBLY32-NEXT:#define __LDBL_MANT_DIG__ 113
-// WEBASSEMBLY32-NEXT:#define __LDBL_MAX_10_EXP__ 4932
-// WEBASSEMBLY32-NEXT:#define __LDBL_MAX_EXP__ 16384
-// WEBASSEMBLY32-NEXT:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
-// WEBASSEMBLY32-NEXT:#define __LDBL_MIN_10_EXP__ (-4931)
-// WEBASSEMBLY32-NEXT:#define __LDBL_MIN_EXP__ (-16381)
-// WEBASSEMBLY32-NEXT:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
-// WEBASSEMBLY32-NEXT:#define __LITTLE_ENDIAN__ 1
-// WEBASSEMBLY32-NEXT:#define __LONG_LONG_MAX__ 9223372036854775807LL
+// WEBASSEMBLY64-NEXT:#define __INTPTR_WIDTH__ 64
+// WEBASSEMBLY-NEXT:#define __INT_FAST16_FMTd__ "hd"
+// WEBASSEMBLY-NEXT:#define __INT_FAST16_FMTi__ "hi"
+// WEBASSEMBLY-NEXT:#define __INT_FAST16_MAX__ 32767
+// WEBASSEMBLY-NEXT:#define __INT_FAST16_TYPE__ short
+// WEBASSEMBLY-NEXT:#define __INT_FAST32_FMTd__ "d"
+// WEBASSEMBLY-NEXT:#define __INT_FAST32_FMTi__ "i"
+// WEBASSEMBLY-NEXT:#define __INT_FAST32_MAX__ 2147483647
+// WEBASSEMBLY-NEXT:#define __INT_FAST32_TYPE__ int
+// WEBASSEMBLY-NEXT:#define __INT_FAST64_FMTd__ "lld"
+// WEBASSEMBLY-NEXT:#define __INT_FAST64_FMTi__ "lli"
+// WEBASSEMBLY-NEXT:#define __INT_FAST64_MAX__ 9223372036854775807LL
+// WEBASSEMBLY-NEXT:#define __INT_FAST64_TYPE__ long long int
+// WEBASSEMBLY-NEXT:#define __INT_FAST8_FMTd__ "hhd"
+// WEBASSEMBLY-NEXT:#define __INT_FAST8_FMTi__ "hhi"
+// WEBASSEMBLY-NEXT:#define __INT_FAST8_MAX__ 127
+// WEBASSEMBLY-NEXT:#define __INT_FAST8_TYPE__ signed char
+// WEBASSEMBLY-NEXT:#define __INT_LEAST16_FMTd__ "hd"
+// WEBASSEMBLY-NEXT:#define __INT_LEAST16_FMTi__ "hi"
+// WEBASSEMBLY-NEXT:#define __INT_LEAST16_MAX__ 32767
+// WEBASSEMBLY-NEXT:#define __INT_LEAST16_TYPE__ short
+// WEBASSEMBLY-NEXT:#define __INT_LEAST32_FMTd__ "d"
+// WEBASSEMBLY-NEXT:#define __INT_LEAST32_FMTi__ "i"
+// WEBASSEMBLY-NEXT:#define __INT_LEAST32_MAX__ 2147483647
+// WEBASSEMBLY-NEXT:#define __INT_LEAST32_TYPE__ int
+// WEBASSEMBLY-NEXT:#define __INT_LEAST64_FMTd__ "lld"
+// WEBASSEMBLY-NEXT:#define __INT_LEAST64_FMTi__ "lli"
+// WEBASSEMBLY-NEXT:#define __INT_LEAST64_MAX__ 9223372036854775807LL
+// WEBASSEMBLY-NEXT:#define __INT_LEAST64_TYPE__ long long int
+// WEBASSEMBLY-NEXT:#define __INT_LEAST8_FMTd__ "hhd"
+// WEBASSEMBLY-NEXT:#define __INT_LEAST8_FMTi__ "hhi"
+// WEBASSEMBLY-NEXT:#define __INT_LEAST8_MAX__ 127
+// WEBASSEMBLY-NEXT:#define __INT_LEAST8_TYPE__ signed char
+// WEBASSEMBLY-NEXT:#define __INT_MAX__ 2147483647
+// WEBASSEMBLY-NEXT:#define __LDBL_DECIMAL_DIG__ 36
+// WEBASSEMBLY-NEXT:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
+// WEBASSEMBLY-NEXT:#define __LDBL_DIG__ 33
+// WEBASSEMBLY-NEXT:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
+// WEBASSEMBLY-NEXT:#define __LDBL_HAS_DENORM__ 1
+// WEBASSEMBLY-NEXT:#define __LDBL_HAS_INFINITY__ 1
+// WEBASSEMBLY-NEXT:#define __LDBL_HAS_QUIET_NAN__ 1
+// WEBASSEMBLY-NEXT:#define __LDBL_MANT_DIG__ 113
+// WEBASSEMBLY-NEXT:#define __LDBL_MAX_10_EXP__ 4932
+// WEBASSEMBLY-NEXT:#define __LDBL_MAX_EXP__ 16384
+// WEBASSEMBLY-NEXT:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
+// WEBASSEMBLY-NEXT:#define __LDBL_MIN_10_EXP__ (-4931)
+// WEBASSEMBLY-NEXT:#define __LDBL_MIN_EXP__ (-16381)
+// WEBASSEMBLY-NEXT:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
+// WEBASSEMBLY-NEXT:#define __LITTLE_ENDIAN__ 1
+// WEBASSEMBLY-NEXT:#define __LONG_LONG_MAX__ 9223372036854775807LL
// WEBASSEMBLY32-NEXT:#define __LONG_MAX__ 2147483647L
// WEBASSEMBLY32-NOT:#define __LP64__
-// WEBASSEMBLY32-NEXT:#define __NO_INLINE__ 1
-// WEBASSEMBLY32-NEXT:#define __OBJC_BOOL_IS_BOOL 0
-// WEBASSEMBLY32-NEXT:#define __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES 3
-// WEBASSEMBLY32-NEXT:#define __OPENCL_MEMORY_SCOPE_DEVICE 2
-// WEBASSEMBLY32-NEXT:#define __OPENCL_MEMORY_SCOPE_SUB_GROUP 4
-// WEBASSEMBLY32-NEXT:#define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1
-// WEBASSEMBLY32-NEXT:#define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0
-// WEBASSEMBLY32-NEXT:#define __ORDER_BIG_ENDIAN__ 4321
-// WEBASSEMBLY32-NEXT:#define __ORDER_LITTLE_ENDIAN__ 1234
-// WEBASSEMBLY32-NEXT:#define __ORDER_PDP_ENDIAN__ 3412
+// WEBASSEMBLY64-NEXT:#define __LONG_MAX__ 9223372036854775807L
+// WEBASSEMBLY64-NEXT:#define __LP64__ 1
+// WEBASSEMBLY-NEXT:#define __NO_INLINE__ 1
+// WEBASSEMBLY-NEXT:#define __OBJC_BOOL_IS_BOOL 0
+// WEBASSEMBLY-NEXT:#define __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES 3
+// WEBASSEMBLY-NEXT:#define __OPENCL_MEMORY_SCOPE_DEVICE 2
+// WEBASSEMBLY-NEXT:#define __OPENCL_MEMORY_SCOPE_SUB_GROUP 4
+// WEBASSEMBLY-NEXT:#define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1
+// WEBASSEMBLY-NEXT:#define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0
+// WEBASSEMBLY-NEXT:#define __ORDER_BIG_ENDIAN__ 4321
+// WEBASSEMBLY-NEXT:#define __ORDER_LITTLE_ENDIAN__ 1234
+// WEBASSEMBLY-NEXT:#define __ORDER_PDP_ENDIAN__ 3412
// WEBASSEMBLY32-NEXT:#define __POINTER_WIDTH__ 32
-// WEBASSEMBLY32-NEXT:#define __PRAGMA_REDEFINE_EXTNAME 1
-// WEBASSEMBLY32-NEXT:#define __PTRDIFF_FMTd__ "ld"
-// WEBASSEMBLY32-NEXT:#define __PTRDIFF_FMTi__ "li"
+// WEBASSEMBLY64-NEXT:#define __POINTER_WIDTH__ 64
+// WEBASSEMBLY-NEXT:#define __PRAGMA_REDEFINE_EXTNAME 1
+// WEBASSEMBLY-NEXT:#define __PTRDIFF_FMTd__ "ld"
+// WEBASSEMBLY-NEXT:#define __PTRDIFF_FMTi__ "li"
// WEBASSEMBLY32-NEXT:#define __PTRDIFF_MAX__ 2147483647L
-// WEBASSEMBLY32-NEXT:#define __PTRDIFF_TYPE__ long int
+// WEBASSEMBLY64-NEXT:#define __PTRDIFF_MAX__ 9223372036854775807L
+// WEBASSEMBLY-NEXT:#define __PTRDIFF_TYPE__ long int
// WEBASSEMBLY32-NEXT:#define __PTRDIFF_WIDTH__ 32
-// WEBASSEMBLY32-NOT:#define __REGISTER_PREFIX__
-// WEBASSEMBLY32-NEXT:#define __SCHAR_MAX__ 127
-// WEBASSEMBLY32-NEXT:#define __SHRT_MAX__ 32767
+// WEBASSEMBLY64-NEXT:#define __PTRDIFF_WIDTH__ 64
+// WEBASSEMBLY-NOT:#define __REGISTER_PREFIX__
+// WEBASSEMBLY-NEXT:#define __SCHAR_MAX__ 127
+// WEBASSEMBLY-NEXT:#define __SHRT_MAX__ 32767
// WEBASSEMBLY32-NEXT:#define __SIG_ATOMIC_MAX__ 2147483647L
// WEBASSEMBLY32-NEXT:#define __SIG_ATOMIC_WIDTH__ 32
-// WEBASSEMBLY32-NEXT:#define __SIZEOF_DOUBLE__ 8
-// WEBASSEMBLY32-NEXT:#define __SIZEOF_FLOAT__ 4
-// WEBASSEMBLY32-NEXT:#define __SIZEOF_INT128__ 16
-// WEBASSEMBLY32-NEXT:#define __SIZEOF_INT__ 4
-// WEBASSEMBLY32-NEXT:#define __SIZEOF_LONG_DOUBLE__ 16
-// WEBASSEMBLY32-NEXT:#define __SIZEOF_LONG_LONG__ 8
+// WEBASSEMBLY64-NEXT:#define __SIG_ATOMIC_MAX__ 9223372036854775807L
+// WEBASSEMBLY64-NEXT:#define __SIG_ATOMIC_WIDTH__ 64
+// WEBASSEMBLY-NEXT:#define __SIZEOF_DOUBLE__ 8
+// WEBASSEMBLY-NEXT:#define __SIZEOF_FLOAT__ 4
+// WEBASSEMBLY-NEXT:#define __SIZEOF_INT128__ 16
+// WEBASSEMBLY-NEXT:#define __SIZEOF_INT__ 4
+// WEBASSEMBLY-NEXT:#define __SIZEOF_LONG_DOUBLE__ 16
+// WEBASSEMBLY-NEXT:#define __SIZEOF_LONG_LONG__ 8
// WEBASSEMBLY32-NEXT:#define __SIZEOF_LONG__ 4
// WEBASSEMBLY32-NEXT:#define __SIZEOF_POINTER__ 4
// WEBASSEMBLY32-NEXT:#define __SIZEOF_PTRDIFF_T__ 4
-// WEBASSEMBLY32-NEXT:#define __SIZEOF_SHORT__ 2
-// WEBASSEMBLY32-NEXT:#define __SIZEOF_SIZE_T__ 4
-// WEBASSEMBLY32-NEXT:#define __SIZEOF_WCHAR_T__ 4
-// WEBASSEMBLY32-NEXT:#define __SIZEOF_WINT_T__ 4
-// WEBASSEMBLY32-NEXT:#define __SIZE_FMTX__ "lX"
-// WEBASSEMBLY32-NEXT:#define __SIZE_FMTo__ "lo"
-// WEBASSEMBLY32-NEXT:#define __SIZE_FMTu__ "lu"
-// WEBASSEMBLY32-NEXT:#define __SIZE_FMTx__ "lx"
-// WEBASSEMBLY32-NEXT:#define __SIZE_MAX__ 4294967295UL
-// WEBASSEMBLY32-NEXT:#define __SIZE_TYPE__ long unsigned int
-// WEBASSEMBLY32-NEXT:#define __SIZE_WIDTH__ 32
-// WEBASSEMBLY32-NEXT:#define __STDC_HOSTED__ 0
-// WEBASSEMBLY32-NOT:#define __STDC_MB_MIGHT_NEQ_WC__
-// WEBASSEMBLY32-NOT:#define __STDC_NO_ATOMICS__
-// WEBASSEMBLY32-NOT:#define __STDC_NO_COMPLEX__
-// WEBASSEMBLY32-NOT:#define __STDC_NO_VLA__
-// WEBASSEMBLY32-NOT:#define __STDC_NO_THREADS__
-// WEBASSEMBLY32-NEXT:#define __STDC_UTF_16__ 1
-// WEBASSEMBLY32-NEXT:#define __STDC_UTF_32__ 1
-// WEBASSEMBLY32-NEXT:#define __STDC_VERSION__ 201112L
-// WEBASSEMBLY32-NEXT:#define __STDC__ 1
-// WEBASSEMBLY32-NEXT:#define __UINT16_C_SUFFIX__
-// WEBASSEMBLY32-NEXT:#define __UINT16_FMTX__ "hX"
-// WEBASSEMBLY32-NEXT:#define __UINT16_FMTo__ "ho"
-// WEBASSEMBLY32-NEXT:#define __UINT16_FMTu__ "hu"
-// WEBASSEMBLY32-NEXT:#define __UINT16_FMTx__ "hx"
-// WEBASSEMBLY32-NEXT:#define __UINT16_MAX__ 65535
-// WEBASSEMBLY32-NEXT:#define __UINT16_TYPE__ unsigned short
-// WEBASSEMBLY32-NEXT:#define __UINT32_C_SUFFIX__ U
-// WEBASSEMBLY32-NEXT:#define __UINT32_FMTX__ "X"
-// WEBASSEMBLY32-NEXT:#define __UINT32_FMTo__ "o"
-// WEBASSEMBLY32-NEXT:#define __UINT32_FMTu__ "u"
-// WEBASSEMBLY32-NEXT:#define __UINT32_FMTx__ "x"
-// WEBASSEMBLY32-NEXT:#define __UINT32_MAX__ 4294967295U
-// WEBASSEMBLY32-NEXT:#define __UINT32_TYPE__ unsigned int
-// WEBASSEMBLY32-NEXT:#define __UINT64_C_SUFFIX__ ULL
-// WEBASSEMBLY32-NEXT:#define __UINT64_FMTX__ "llX"
-// WEBASSEMBLY32-NEXT:#define __UINT64_FMTo__ "llo"
-// WEBASSEMBLY32-NEXT:#define __UINT64_FMTu__ "llu"
-// WEBASSEMBLY32-NEXT:#define __UINT64_FMTx__ "llx"
-// WEBASSEMBLY32-NEXT:#define __UINT64_MAX__ 18446744073709551615ULL
-// WEBASSEMBLY32-NEXT:#define __UINT64_TYPE__ long long unsigned int
-// WEBASSEMBLY32-NEXT:#define __UINT8_C_SUFFIX__
-// WEBASSEMBLY32-NEXT:#define __UINT8_FMTX__ "hhX"
-// WEBASSEMBLY32-NEXT:#define __UINT8_FMTo__ "hho"
-// WEBASSEMBLY32-NEXT:#define __UINT8_FMTu__ "hhu"
-// WEBASSEMBLY32-NEXT:#define __UINT8_FMTx__ "hhx"
-// WEBASSEMBLY32-NEXT:#define __UINT8_MAX__ 255
-// WEBASSEMBLY32-NEXT:#define __UINT8_TYPE__ unsigned char
-// WEBASSEMBLY32-NEXT:#define __UINTMAX_C_SUFFIX__ ULL
-// WEBASSEMBLY32-NEXT:#define __UINTMAX_FMTX__ "llX"
-// WEBASSEMBLY32-NEXT:#define __UINTMAX_FMTo__ "llo"
-// WEBASSEMBLY32-NEXT:#define __UINTMAX_FMTu__ "llu"
-// WEBASSEMBLY32-NEXT:#define __UINTMAX_FMTx__ "llx"
-// WEBASSEMBLY32-NEXT:#define __UINTMAX_MAX__ 18446744073709551615ULL
-// WEBASSEMBLY32-NEXT:#define __UINTMAX_TYPE__ long long unsigned int
-// WEBASSEMBLY32-NEXT:#define __UINTMAX_WIDTH__ 64
-// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTX__ "lX"
-// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTo__ "lo"
-// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTu__ "lu"
-// WEBASSEMBLY32-NEXT:#define __UINTPTR_FMTx__ "lx"
-// WEBASSEMBLY32-NEXT:#define __UINTPTR_MAX__ 4294967295UL
-// WEBASSEMBLY32-NEXT:#define __UINTPTR_TYPE__ long unsigned int
-// WEBASSEMBLY32-NEXT:#define __UINTPTR_WIDTH__ 32
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_FMTX__ "hX"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_FMTo__ "ho"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_FMTu__ "hu"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_FMTx__ "hx"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_MAX__ 65535
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST16_TYPE__ unsigned short
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST32_FMTX__ "X"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST32_FMTo__ "o"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST32_FMTu__ "u"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST32_FMTx__ "x"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST32_MAX__ 4294967295U
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST32_TYPE__ unsigned int
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST64_FMTX__ "llX"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST64_FMTo__ "llo"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST64_FMTu__ "llu"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST64_FMTx__ "llx"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST64_TYPE__ long long unsigned int
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST8_FMTX__ "hhX"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST8_FMTo__ "hho"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST8_FMTu__ "hhu"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST8_FMTx__ "hhx"
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST8_MAX__ 255
-// WEBASSEMBLY32-NEXT:#define __UINT_FAST8_TYPE__ unsigned char
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST16_FMTX__ "hX"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST16_FMTo__ "ho"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST16_FMTu__ "hu"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST16_FMTx__ "hx"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST16_MAX__ 65535
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST16_TYPE__ unsigned short
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST32_FMTX__ "X"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST32_FMTo__ "o"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST32_FMTu__ "u"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST32_FMTx__ "x"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST32_MAX__ 4294967295U
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST32_TYPE__ unsigned int
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST64_FMTX__ "llX"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST64_FMTo__ "llo"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST64_FMTu__ "llu"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST64_FMTx__ "llx"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST64_TYPE__ long long unsigned int
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST8_FMTX__ "hhX"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST8_FMTo__ "hho"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST8_FMTu__ "hhu"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST8_FMTx__ "hhx"
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST8_MAX__ 255
-// WEBASSEMBLY32-NEXT:#define __UINT_LEAST8_TYPE__ unsigned char
-// WEBASSEMBLY32-NEXT:#define __USER_LABEL_PREFIX__
-// WEBASSEMBLY32-NEXT:#define __VERSION__ "{{.*}}"
-// WEBASSEMBLY32-NEXT:#define __WCHAR_MAX__ 2147483647
-// WEBASSEMBLY32-NEXT:#define __WCHAR_TYPE__ int
-// WEBASSEMBLY32-NOT:#define __WCHAR_UNSIGNED__
-// WEBASSEMBLY32-NEXT:#define __WCHAR_WIDTH__ 32
-// WEBASSEMBLY32-NEXT:#define __WINT_MAX__ 2147483647
-// WEBASSEMBLY32-NEXT:#define __WINT_TYPE__ int
-// WEBASSEMBLY32-NOT:#define __WINT_UNSIGNED__
-// WEBASSEMBLY32-NEXT:#define __WINT_WIDTH__ 32
-// WEBASSEMBLY32-NEXT:#define __clang__ 1
-// WEBASSEMBLY32-NEXT:#define __clang_major__ {{.*}}
-// WEBASSEMBLY32-NEXT:#define __clang_minor__ {{.*}}
-// WEBASSEMBLY32-NEXT:#define __clang_patchlevel__ {{.*}}
-// WEBASSEMBLY32-NEXT:#define __clang_version__ "{{.*}}"
-// WEBASSEMBLY32-NEXT:#define __llvm__ 1
-// WEBASSEMBLY32-NOT:#define __wasm_simd128__
-// WEBASSEMBLY32-NOT:#define __wasm_simd256__
-// WEBASSEMBLY32-NOT:#define __wasm_simd512__
-// WEBASSEMBLY32-NOT:#define __unix
-// WEBASSEMBLY32-NOT:#define __unix__
-// WEBASSEMBLY32-NEXT:#define __wasm 1
-// WEBASSEMBLY32-NEXT:#define __wasm32 1
-// WEBASSEMBLY32-NEXT:#define __wasm32__ 1
-// WEBASSEMBLY32-NOT:#define __wasm64
-// WEBASSEMBLY32-NOT:#define __wasm64__
-// WEBASSEMBLY32-NEXT:#define __wasm__ 1
-//
-// RUN: %clang_cc1 -E -dM -ffreestanding -triple=wasm64-unknown-unknown \
-// RUN: < /dev/null \
-// RUN: | FileCheck -match-full-lines -check-prefix=WEBASSEMBLY64 %s
-//
-// WEBASSEMBLY64-NOT:#define _ILP32
-// WEBASSEMBLY64:#define _LP64 1
-// WEBASSEMBLY64-NEXT:#define __ATOMIC_ACQUIRE 2
-// WEBASSEMBLY64-NEXT:#define __ATOMIC_ACQ_REL 4
-// WEBASSEMBLY64-NEXT:#define __ATOMIC_CONSUME 1
-// WEBASSEMBLY64-NEXT:#define __ATOMIC_RELAXED 0
-// WEBASSEMBLY64-NEXT:#define __ATOMIC_RELEASE 3
-// WEBASSEMBLY64-NEXT:#define __ATOMIC_SEQ_CST 5
-// WEBASSEMBLY64-NEXT:#define __BIGGEST_ALIGNMENT__ 16
-// WEBASSEMBLY64-NEXT:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
-// WEBASSEMBLY64-NEXT:#define __CHAR16_TYPE__ unsigned short
-// WEBASSEMBLY64-NEXT:#define __CHAR32_TYPE__ unsigned int
-// WEBASSEMBLY64-NEXT:#define __CHAR_BIT__ 8
-// WEBASSEMBLY64-NOT:#define __CHAR_UNSIGNED__
-// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_BOOL_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_CHAR_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_INT_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_LLONG_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_LONG_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_POINTER_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_SHORT_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __CONSTANT_CFSTRINGS__ 1
-// WEBASSEMBLY64-NEXT:#define __DBL_DECIMAL_DIG__ 17
-// WEBASSEMBLY64-NEXT:#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
-// WEBASSEMBLY64-NEXT:#define __DBL_DIG__ 15
-// WEBASSEMBLY64-NEXT:#define __DBL_EPSILON__ 2.2204460492503131e-16
-// WEBASSEMBLY64-NEXT:#define __DBL_HAS_DENORM__ 1
-// WEBASSEMBLY64-NEXT:#define __DBL_HAS_INFINITY__ 1
-// WEBASSEMBLY64-NEXT:#define __DBL_HAS_QUIET_NAN__ 1
-// WEBASSEMBLY64-NEXT:#define __DBL_MANT_DIG__ 53
-// WEBASSEMBLY64-NEXT:#define __DBL_MAX_10_EXP__ 308
-// WEBASSEMBLY64-NEXT:#define __DBL_MAX_EXP__ 1024
-// WEBASSEMBLY64-NEXT:#define __DBL_MAX__ 1.7976931348623157e+308
-// WEBASSEMBLY64-NEXT:#define __DBL_MIN_10_EXP__ (-307)
-// WEBASSEMBLY64-NEXT:#define __DBL_MIN_EXP__ (-1021)
-// WEBASSEMBLY64-NEXT:#define __DBL_MIN__ 2.2250738585072014e-308
-// WEBASSEMBLY64-NEXT:#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
-// WEBASSEMBLY64-NOT:#define __ELF__
-// WEBASSEMBLY64-NEXT:#define __FINITE_MATH_ONLY__ 0
-// WEBASSEMBLY64:#define __FLT_DECIMAL_DIG__ 9
-// WEBASSEMBLY64-NEXT:#define __FLT_DENORM_MIN__ 1.40129846e-45F
-// WEBASSEMBLY64-NEXT:#define __FLT_DIG__ 6
-// WEBASSEMBLY64-NEXT:#define __FLT_EPSILON__ 1.19209290e-7F
-// WEBASSEMBLY64-NEXT:#define __FLT_EVAL_METHOD__ 0
-// WEBASSEMBLY64-NEXT:#define __FLT_HAS_DENORM__ 1
-// WEBASSEMBLY64-NEXT:#define __FLT_HAS_INFINITY__ 1
-// WEBASSEMBLY64-NEXT:#define __FLT_HAS_QUIET_NAN__ 1
-// WEBASSEMBLY64-NEXT:#define __FLT_MANT_DIG__ 24
-// WEBASSEMBLY64-NEXT:#define __FLT_MAX_10_EXP__ 38
-// WEBASSEMBLY64-NEXT:#define __FLT_MAX_EXP__ 128
-// WEBASSEMBLY64-NEXT:#define __FLT_MAX__ 3.40282347e+38F
-// WEBASSEMBLY64-NEXT:#define __FLT_MIN_10_EXP__ (-37)
-// WEBASSEMBLY64-NEXT:#define __FLT_MIN_EXP__ (-125)
-// WEBASSEMBLY64-NEXT:#define __FLT_MIN__ 1.17549435e-38F
-// WEBASSEMBLY64-NEXT:#define __FLT_RADIX__ 2
-// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_BOOL_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_INT_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_LLONG_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_LONG_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_SHORT_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
-// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
-// WEBASSEMBLY64-NEXT:#define __GNUC_MINOR__ {{.*}}
-// WEBASSEMBLY64-NEXT:#define __GNUC_PATCHLEVEL__ {{.*}}
-// WEBASSEMBLY64-NEXT:#define __GNUC_STDC_INLINE__ 1
-// WEBASSEMBLY64-NEXT:#define __GNUC__ {{.}}
-// WEBASSEMBLY64-NEXT:#define __GXX_ABI_VERSION 1002
-// WEBASSEMBLY64-NOT:#define __ILP32__
-// WEBASSEMBLY64-NEXT:#define __INT16_C_SUFFIX__
-// WEBASSEMBLY64-NEXT:#define __INT16_FMTd__ "hd"
-// WEBASSEMBLY64-NEXT:#define __INT16_FMTi__ "hi"
-// WEBASSEMBLY64-NEXT:#define __INT16_MAX__ 32767
-// WEBASSEMBLY64-NEXT:#define __INT16_TYPE__ short
-// WEBASSEMBLY64-NEXT:#define __INT32_C_SUFFIX__
-// WEBASSEMBLY64-NEXT:#define __INT32_FMTd__ "d"
-// WEBASSEMBLY64-NEXT:#define __INT32_FMTi__ "i"
-// WEBASSEMBLY64-NEXT:#define __INT32_MAX__ 2147483647
-// WEBASSEMBLY64-NEXT:#define __INT32_TYPE__ int
-// WEBASSEMBLY64-NEXT:#define __INT64_C_SUFFIX__ LL
-// WEBASSEMBLY64-NEXT:#define __INT64_FMTd__ "lld"
-// WEBASSEMBLY64-NEXT:#define __INT64_FMTi__ "lli"
-// WEBASSEMBLY64-NEXT:#define __INT64_MAX__ 9223372036854775807LL
-// WEBASSEMBLY64-NEXT:#define __INT64_TYPE__ long long int
-// WEBASSEMBLY64-NEXT:#define __INT8_C_SUFFIX__
-// WEBASSEMBLY64-NEXT:#define __INT8_FMTd__ "hhd"
-// WEBASSEMBLY64-NEXT:#define __INT8_FMTi__ "hhi"
-// WEBASSEMBLY64-NEXT:#define __INT8_MAX__ 127
-// WEBASSEMBLY64-NEXT:#define __INT8_TYPE__ signed char
-// WEBASSEMBLY64-NEXT:#define __INTMAX_C_SUFFIX__ LL
-// WEBASSEMBLY64-NEXT:#define __INTMAX_FMTd__ "lld"
-// WEBASSEMBLY64-NEXT:#define __INTMAX_FMTi__ "lli"
-// WEBASSEMBLY64-NEXT:#define __INTMAX_MAX__ 9223372036854775807LL
-// WEBASSEMBLY64-NEXT:#define __INTMAX_TYPE__ long long int
-// WEBASSEMBLY64-NEXT:#define __INTMAX_WIDTH__ 64
-// WEBASSEMBLY64-NEXT:#define __INTPTR_FMTd__ "ld"
-// WEBASSEMBLY64-NEXT:#define __INTPTR_FMTi__ "li"
-// WEBASSEMBLY64-NEXT:#define __INTPTR_MAX__ 9223372036854775807L
-// WEBASSEMBLY64-NEXT:#define __INTPTR_TYPE__ long int
-// WEBASSEMBLY64-NEXT:#define __INTPTR_WIDTH__ 64
-// WEBASSEMBLY64-NEXT:#define __INT_FAST16_FMTd__ "hd"
-// WEBASSEMBLY64-NEXT:#define __INT_FAST16_FMTi__ "hi"
-// WEBASSEMBLY64-NEXT:#define __INT_FAST16_MAX__ 32767
-// WEBASSEMBLY64-NEXT:#define __INT_FAST16_TYPE__ short
-// WEBASSEMBLY64-NEXT:#define __INT_FAST32_FMTd__ "d"
-// WEBASSEMBLY64-NEXT:#define __INT_FAST32_FMTi__ "i"
-// WEBASSEMBLY64-NEXT:#define __INT_FAST32_MAX__ 2147483647
-// WEBASSEMBLY64-NEXT:#define __INT_FAST32_TYPE__ int
-// WEBASSEMBLY64-NEXT:#define __INT_FAST64_FMTd__ "lld"
-// WEBASSEMBLY64-NEXT:#define __INT_FAST64_FMTi__ "lli"
-// WEBASSEMBLY64-NEXT:#define __INT_FAST64_MAX__ 9223372036854775807LL
-// WEBASSEMBLY64-NEXT:#define __INT_FAST64_TYPE__ long long int
-// WEBASSEMBLY64-NEXT:#define __INT_FAST8_FMTd__ "hhd"
-// WEBASSEMBLY64-NEXT:#define __INT_FAST8_FMTi__ "hhi"
-// WEBASSEMBLY64-NEXT:#define __INT_FAST8_MAX__ 127
-// WEBASSEMBLY64-NEXT:#define __INT_FAST8_TYPE__ signed char
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST16_FMTd__ "hd"
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST16_FMTi__ "hi"
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST16_MAX__ 32767
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST16_TYPE__ short
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST32_FMTd__ "d"
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST32_FMTi__ "i"
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST32_MAX__ 2147483647
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST32_TYPE__ int
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST64_FMTd__ "lld"
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST64_FMTi__ "lli"
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST64_MAX__ 9223372036854775807LL
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST64_TYPE__ long long int
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST8_FMTd__ "hhd"
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST8_FMTi__ "hhi"
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST8_MAX__ 127
-// WEBASSEMBLY64-NEXT:#define __INT_LEAST8_TYPE__ signed char
-// WEBASSEMBLY64-NEXT:#define __INT_MAX__ 2147483647
-// WEBASSEMBLY64-NEXT:#define __LDBL_DECIMAL_DIG__ 36
-// WEBASSEMBLY64-NEXT:#define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
-// WEBASSEMBLY64-NEXT:#define __LDBL_DIG__ 33
-// WEBASSEMBLY64-NEXT:#define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
-// WEBASSEMBLY64-NEXT:#define __LDBL_HAS_DENORM__ 1
-// WEBASSEMBLY64-NEXT:#define __LDBL_HAS_INFINITY__ 1
-// WEBASSEMBLY64-NEXT:#define __LDBL_HAS_QUIET_NAN__ 1
-// WEBASSEMBLY64-NEXT:#define __LDBL_MANT_DIG__ 113
-// WEBASSEMBLY64-NEXT:#define __LDBL_MAX_10_EXP__ 4932
-// WEBASSEMBLY64-NEXT:#define __LDBL_MAX_EXP__ 16384
-// WEBASSEMBLY64-NEXT:#define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
-// WEBASSEMBLY64-NEXT:#define __LDBL_MIN_10_EXP__ (-4931)
-// WEBASSEMBLY64-NEXT:#define __LDBL_MIN_EXP__ (-16381)
-// WEBASSEMBLY64-NEXT:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
-// WEBASSEMBLY64-NEXT:#define __LITTLE_ENDIAN__ 1
-// WEBASSEMBLY64-NEXT:#define __LONG_LONG_MAX__ 9223372036854775807LL
-// WEBASSEMBLY64-NEXT:#define __LONG_MAX__ 9223372036854775807L
-// WEBASSEMBLY64-NEXT:#define __LP64__ 1
-// WEBASSEMBLY64-NEXT:#define __NO_INLINE__ 1
-// WEBASSEMBLY64-NEXT:#define __OBJC_BOOL_IS_BOOL 0
-// WEBASSEMBLY64-NEXT:#define __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES 3
-// WEBASSEMBLY64-NEXT:#define __OPENCL_MEMORY_SCOPE_DEVICE 2
-// WEBASSEMBLY64-NEXT:#define __OPENCL_MEMORY_SCOPE_SUB_GROUP 4
-// WEBASSEMBLY64-NEXT:#define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1
-// WEBASSEMBLY64-NEXT:#define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0
-// WEBASSEMBLY64-NEXT:#define __ORDER_BIG_ENDIAN__ 4321
-// WEBASSEMBLY64-NEXT:#define __ORDER_LITTLE_ENDIAN__ 1234
-// WEBASSEMBLY64-NEXT:#define __ORDER_PDP_ENDIAN__ 3412
-// WEBASSEMBLY64-NEXT:#define __POINTER_WIDTH__ 64
-// WEBASSEMBLY64-NEXT:#define __PRAGMA_REDEFINE_EXTNAME 1
-// WEBASSEMBLY64-NEXT:#define __PTRDIFF_FMTd__ "ld"
-// WEBASSEMBLY64-NEXT:#define __PTRDIFF_FMTi__ "li"
-// WEBASSEMBLY64-NEXT:#define __PTRDIFF_MAX__ 9223372036854775807L
-// WEBASSEMBLY64-NEXT:#define __PTRDIFF_TYPE__ long int
-// WEBASSEMBLY64-NEXT:#define __PTRDIFF_WIDTH__ 64
-// WEBASSEMBLY64-NOT:#define __REGISTER_PREFIX__
-// WEBASSEMBLY64-NEXT:#define __SCHAR_MAX__ 127
-// WEBASSEMBLY64-NEXT:#define __SHRT_MAX__ 32767
-// WEBASSEMBLY64-NEXT:#define __SIG_ATOMIC_MAX__ 9223372036854775807L
-// WEBASSEMBLY64-NEXT:#define __SIG_ATOMIC_WIDTH__ 64
-// WEBASSEMBLY64-NEXT:#define __SIZEOF_DOUBLE__ 8
-// WEBASSEMBLY64-NEXT:#define __SIZEOF_FLOAT__ 4
-// WEBASSEMBLY64-NEXT:#define __SIZEOF_INT128__ 16
-// WEBASSEMBLY64-NEXT:#define __SIZEOF_INT__ 4
-// WEBASSEMBLY64-NEXT:#define __SIZEOF_LONG_DOUBLE__ 16
-// WEBASSEMBLY64-NEXT:#define __SIZEOF_LONG_LONG__ 8
// WEBASSEMBLY64-NEXT:#define __SIZEOF_LONG__ 8
// WEBASSEMBLY64-NEXT:#define __SIZEOF_POINTER__ 8
// WEBASSEMBLY64-NEXT:#define __SIZEOF_PTRDIFF_T__ 8
-// WEBASSEMBLY64-NEXT:#define __SIZEOF_SHORT__ 2
+// WEBASSEMBLY-NEXT:#define __SIZEOF_SHORT__ 2
+// WEBASSEMBLY32-NEXT:#define __SIZEOF_SIZE_T__ 4
// WEBASSEMBLY64-NEXT:#define __SIZEOF_SIZE_T__ 8
-// WEBASSEMBLY64-NEXT:#define __SIZEOF_WCHAR_T__ 4
-// WEBASSEMBLY64-NEXT:#define __SIZEOF_WINT_T__ 4
-// WEBASSEMBLY64-NEXT:#define __SIZE_FMTX__ "lX"
-// WEBASSEMBLY64-NEXT:#define __SIZE_FMTo__ "lo"
-// WEBASSEMBLY64-NEXT:#define __SIZE_FMTu__ "lu"
-// WEBASSEMBLY64-NEXT:#define __SIZE_FMTx__ "lx"
+// WEBASSEMBLY-NEXT:#define __SIZEOF_WCHAR_T__ 4
+// WEBASSEMBLY-NEXT:#define __SIZEOF_WINT_T__ 4
+// WEBASSEMBLY-NEXT:#define __SIZE_FMTX__ "lX"
+// WEBASSEMBLY-NEXT:#define __SIZE_FMTo__ "lo"
+// WEBASSEMBLY-NEXT:#define __SIZE_FMTu__ "lu"
+// WEBASSEMBLY-NEXT:#define __SIZE_FMTx__ "lx"
+// WEBASSEMBLY32-NEXT:#define __SIZE_MAX__ 4294967295UL
// WEBASSEMBLY64-NEXT:#define __SIZE_MAX__ 18446744073709551615UL
-// WEBASSEMBLY64-NEXT:#define __SIZE_TYPE__ long unsigned int
+// WEBASSEMBLY-NEXT:#define __SIZE_TYPE__ long unsigned int
+// WEBASSEMBLY32-NEXT:#define __SIZE_WIDTH__ 32
// WEBASSEMBLY64-NEXT:#define __SIZE_WIDTH__ 64
-// WEBASSEMBLY64-NEXT:#define __STDC_HOSTED__ 0
-// WEBASSEMBLY64-NOT:#define __STDC_MB_MIGHT_NEQ_WC__
-// WEBASSEMBLY64-NOT:#define __STDC_NO_ATOMICS__
-// WEBASSEMBLY64-NOT:#define __STDC_NO_COMPLEX__
-// WEBASSEMBLY64-NOT:#define __STDC_NO_VLA__
-// WEBASSEMBLY64-NOT:#define __STDC_NO_THREADS__
-// WEBASSEMBLY64-NEXT:#define __STDC_UTF_16__ 1
-// WEBASSEMBLY64-NEXT:#define __STDC_UTF_32__ 1
-// WEBASSEMBLY64-NEXT:#define __STDC_VERSION__ 201112L
-// WEBASSEMBLY64-NEXT:#define __STDC__ 1
-// WEBASSEMBLY64-NEXT:#define __UINT16_C_SUFFIX__
-// WEBASSEMBLY64-NEXT:#define __UINT16_FMTX__ "hX"
-// WEBASSEMBLY64-NEXT:#define __UINT16_FMTo__ "ho"
-// WEBASSEMBLY64-NEXT:#define __UINT16_FMTu__ "hu"
-// WEBASSEMBLY64-NEXT:#define __UINT16_FMTx__ "hx"
-// WEBASSEMBLY64-NEXT:#define __UINT16_MAX__ 65535
-// WEBASSEMBLY64-NEXT:#define __UINT16_TYPE__ unsigned short
-// WEBASSEMBLY64-NEXT:#define __UINT32_C_SUFFIX__ U
-// WEBASSEMBLY64-NEXT:#define __UINT32_FMTX__ "X"
-// WEBASSEMBLY64-NEXT:#define __UINT32_FMTo__ "o"
-// WEBASSEMBLY64-NEXT:#define __UINT32_FMTu__ "u"
-// WEBASSEMBLY64-NEXT:#define __UINT32_FMTx__ "x"
-// WEBASSEMBLY64-NEXT:#define __UINT32_MAX__ 4294967295U
-// WEBASSEMBLY64-NEXT:#define __UINT32_TYPE__ unsigned int
-// WEBASSEMBLY64-NEXT:#define __UINT64_C_SUFFIX__ ULL
-// WEBASSEMBLY64-NEXT:#define __UINT64_FMTX__ "llX"
-// WEBASSEMBLY64-NEXT:#define __UINT64_FMTo__ "llo"
-// WEBASSEMBLY64-NEXT:#define __UINT64_FMTu__ "llu"
-// WEBASSEMBLY64-NEXT:#define __UINT64_FMTx__ "llx"
-// WEBASSEMBLY64-NEXT:#define __UINT64_MAX__ 18446744073709551615ULL
-// WEBASSEMBLY64-NEXT:#define __UINT64_TYPE__ long long unsigned int
-// WEBASSEMBLY64-NEXT:#define __UINT8_C_SUFFIX__
-// WEBASSEMBLY64-NEXT:#define __UINT8_FMTX__ "hhX"
-// WEBASSEMBLY64-NEXT:#define __UINT8_FMTo__ "hho"
-// WEBASSEMBLY64-NEXT:#define __UINT8_FMTu__ "hhu"
-// WEBASSEMBLY64-NEXT:#define __UINT8_FMTx__ "hhx"
-// WEBASSEMBLY64-NEXT:#define __UINT8_MAX__ 255
-// WEBASSEMBLY64-NEXT:#define __UINT8_TYPE__ unsigned char
-// WEBASSEMBLY64-NEXT:#define __UINTMAX_C_SUFFIX__ ULL
-// WEBASSEMBLY64-NEXT:#define __UINTMAX_FMTX__ "llX"
-// WEBASSEMBLY64-NEXT:#define __UINTMAX_FMTo__ "llo"
-// WEBASSEMBLY64-NEXT:#define __UINTMAX_FMTu__ "llu"
-// WEBASSEMBLY64-NEXT:#define __UINTMAX_FMTx__ "llx"
-// WEBASSEMBLY64-NEXT:#define __UINTMAX_MAX__ 18446744073709551615ULL
-// WEBASSEMBLY64-NEXT:#define __UINTMAX_TYPE__ long long unsigned int
-// WEBASSEMBLY64-NEXT:#define __UINTMAX_WIDTH__ 64
-// WEBASSEMBLY64-NEXT:#define __UINTPTR_FMTX__ "lX"
-// WEBASSEMBLY64-NEXT:#define __UINTPTR_FMTo__ "lo"
-// WEBASSEMBLY64-NEXT:#define __UINTPTR_FMTu__ "lu"
-// WEBASSEMBLY64-NEXT:#define __UINTPTR_FMTx__ "lx"
+// WEBASSEMBLY-NEXT:#define __STDC_HOSTED__ 0
+// WEBASSEMBLY-NOT:#define __STDC_MB_MIGHT_NEQ_WC__
+// WEBASSEMBLY-NOT:#define __STDC_NO_ATOMICS__
+// WEBASSEMBLY-NOT:#define __STDC_NO_COMPLEX__
+// WEBASSEMBLY-NOT:#define __STDC_NO_VLA__
+// WEBASSEMBLY-NOT:#define __STDC_NO_THREADS__
+// WEBASSEMBLY-NEXT:#define __STDC_UTF_16__ 1
+// WEBASSEMBLY-NEXT:#define __STDC_UTF_32__ 1
+// WEBASSEMBLY-NEXT:#define __STDC_VERSION__ 201112L
+// WEBASSEMBLY-NEXT:#define __STDC__ 1
+// WEBASSEMBLY-NEXT:#define __UINT16_C_SUFFIX__
+// WEBASSEMBLY-NEXT:#define __UINT16_FMTX__ "hX"
+// WEBASSEMBLY-NEXT:#define __UINT16_FMTo__ "ho"
+// WEBASSEMBLY-NEXT:#define __UINT16_FMTu__ "hu"
+// WEBASSEMBLY-NEXT:#define __UINT16_FMTx__ "hx"
+// WEBASSEMBLY-NEXT:#define __UINT16_MAX__ 65535
+// WEBASSEMBLY-NEXT:#define __UINT16_TYPE__ unsigned short
+// WEBASSEMBLY-NEXT:#define __UINT32_C_SUFFIX__ U
+// WEBASSEMBLY-NEXT:#define __UINT32_FMTX__ "X"
+// WEBASSEMBLY-NEXT:#define __UINT32_FMTo__ "o"
+// WEBASSEMBLY-NEXT:#define __UINT32_FMTu__ "u"
+// WEBASSEMBLY-NEXT:#define __UINT32_FMTx__ "x"
+// WEBASSEMBLY-NEXT:#define __UINT32_MAX__ 4294967295U
+// WEBASSEMBLY-NEXT:#define __UINT32_TYPE__ unsigned int
+// WEBASSEMBLY-NEXT:#define __UINT64_C_SUFFIX__ ULL
+// WEBASSEMBLY-NEXT:#define __UINT64_FMTX__ "llX"
+// WEBASSEMBLY-NEXT:#define __UINT64_FMTo__ "llo"
+// WEBASSEMBLY-NEXT:#define __UINT64_FMTu__ "llu"
+// WEBASSEMBLY-NEXT:#define __UINT64_FMTx__ "llx"
+// WEBASSEMBLY-NEXT:#define __UINT64_MAX__ 18446744073709551615ULL
+// WEBASSEMBLY-NEXT:#define __UINT64_TYPE__ long long unsigned int
+// WEBASSEMBLY-NEXT:#define __UINT8_C_SUFFIX__
+// WEBASSEMBLY-NEXT:#define __UINT8_FMTX__ "hhX"
+// WEBASSEMBLY-NEXT:#define __UINT8_FMTo__ "hho"
+// WEBASSEMBLY-NEXT:#define __UINT8_FMTu__ "hhu"
+// WEBASSEMBLY-NEXT:#define __UINT8_FMTx__ "hhx"
+// WEBASSEMBLY-NEXT:#define __UINT8_MAX__ 255
+// WEBASSEMBLY-NEXT:#define __UINT8_TYPE__ unsigned char
+// WEBASSEMBLY-NEXT:#define __UINTMAX_C_SUFFIX__ ULL
+// WEBASSEMBLY-NEXT:#define __UINTMAX_FMTX__ "llX"
+// WEBASSEMBLY-NEXT:#define __UINTMAX_FMTo__ "llo"
+// WEBASSEMBLY-NEXT:#define __UINTMAX_FMTu__ "llu"
+// WEBASSEMBLY-NEXT:#define __UINTMAX_FMTx__ "llx"
+// WEBASSEMBLY-NEXT:#define __UINTMAX_MAX__ 18446744073709551615ULL
+// WEBASSEMBLY-NEXT:#define __UINTMAX_TYPE__ long long unsigned int
+// WEBASSEMBLY-NEXT:#define __UINTMAX_WIDTH__ 64
+// WEBASSEMBLY-NEXT:#define __UINTPTR_FMTX__ "lX"
+// WEBASSEMBLY-NEXT:#define __UINTPTR_FMTo__ "lo"
+// WEBASSEMBLY-NEXT:#define __UINTPTR_FMTu__ "lu"
+// WEBASSEMBLY-NEXT:#define __UINTPTR_FMTx__ "lx"
+// WEBASSEMBLY32-NEXT:#define __UINTPTR_MAX__ 4294967295UL
// WEBASSEMBLY64-NEXT:#define __UINTPTR_MAX__ 18446744073709551615UL
-// WEBASSEMBLY64-NEXT:#define __UINTPTR_TYPE__ long unsigned int
+// WEBASSEMBLY-NEXT:#define __UINTPTR_TYPE__ long unsigned int
+// WEBASSEMBLY32-NEXT:#define __UINTPTR_WIDTH__ 32
// WEBASSEMBLY64-NEXT:#define __UINTPTR_WIDTH__ 64
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST16_FMTX__ "hX"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST16_FMTo__ "ho"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST16_FMTu__ "hu"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST16_FMTx__ "hx"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST16_MAX__ 65535
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST16_TYPE__ unsigned short
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST32_FMTX__ "X"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST32_FMTo__ "o"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST32_FMTu__ "u"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST32_FMTx__ "x"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST32_MAX__ 4294967295U
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST32_TYPE__ unsigned int
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST64_FMTX__ "llX"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST64_FMTo__ "llo"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST64_FMTu__ "llu"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST64_FMTx__ "llx"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST64_TYPE__ long long unsigned int
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST8_FMTX__ "hhX"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST8_FMTo__ "hho"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST8_FMTu__ "hhu"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST8_FMTx__ "hhx"
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST8_MAX__ 255
-// WEBASSEMBLY64-NEXT:#define __UINT_FAST8_TYPE__ unsigned char
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST16_FMTX__ "hX"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST16_FMTo__ "ho"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST16_FMTu__ "hu"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST16_FMTx__ "hx"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST16_MAX__ 65535
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST16_TYPE__ unsigned short
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST32_FMTX__ "X"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST32_FMTo__ "o"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST32_FMTu__ "u"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST32_FMTx__ "x"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST32_MAX__ 4294967295U
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST32_TYPE__ unsigned int
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST64_FMTX__ "llX"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST64_FMTo__ "llo"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST64_FMTu__ "llu"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST64_FMTx__ "llx"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST64_TYPE__ long long unsigned int
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST8_FMTX__ "hhX"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST8_FMTo__ "hho"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST8_FMTu__ "hhu"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST8_FMTx__ "hhx"
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST8_MAX__ 255
-// WEBASSEMBLY64-NEXT:#define __UINT_LEAST8_TYPE__ unsigned char
-// WEBASSEMBLY64-NEXT:#define __USER_LABEL_PREFIX__
-// WEBASSEMBLY64-NEXT:#define __VERSION__ "{{.*}}"
-// WEBASSEMBLY64-NEXT:#define __WCHAR_MAX__ 2147483647
-// WEBASSEMBLY64-NEXT:#define __WCHAR_TYPE__ int
-// WEBASSEMBLY64-NOT:#define __WCHAR_UNSIGNED__
-// WEBASSEMBLY64-NEXT:#define __WCHAR_WIDTH__ 32
-// WEBASSEMBLY64-NEXT:#define __WINT_MAX__ 2147483647
-// WEBASSEMBLY64-NEXT:#define __WINT_TYPE__ int
-// WEBASSEMBLY64-NOT:#define __WINT_UNSIGNED__
-// WEBASSEMBLY64-NEXT:#define __WINT_WIDTH__ 32
-// WEBASSEMBLY64-NEXT:#define __clang__ 1
-// WEBASSEMBLY64-NEXT:#define __clang_major__ {{.*}}
-// WEBASSEMBLY64-NEXT:#define __clang_minor__ {{.*}}
-// WEBASSEMBLY64-NEXT:#define __clang_patchlevel__ {{.*}}
-// WEBASSEMBLY64-NEXT:#define __clang_version__ "{{.*}}"
-// WEBASSEMBLY64-NEXT:#define __llvm__ 1
-// WEBASSEMBLY64-NOT:#define __wasm_simd128__
-// WEBASSEMBLY64-NOT:#define __wasm_simd256__
-// WEBASSEMBLY64-NOT:#define __wasm_simd512__
-// WEBASSEMBLY64-NOT:#define __unix
-// WEBASSEMBLY64-NOT:#define __unix__
-// WEBASSEMBLY64-NEXT:#define __wasm 1
+// WEBASSEMBLY-NEXT:#define __UINT_FAST16_FMTX__ "hX"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST16_FMTo__ "ho"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST16_FMTu__ "hu"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST16_FMTx__ "hx"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST16_MAX__ 65535
+// WEBASSEMBLY-NEXT:#define __UINT_FAST16_TYPE__ unsigned short
+// WEBASSEMBLY-NEXT:#define __UINT_FAST32_FMTX__ "X"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST32_FMTo__ "o"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST32_FMTu__ "u"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST32_FMTx__ "x"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST32_MAX__ 4294967295U
+// WEBASSEMBLY-NEXT:#define __UINT_FAST32_TYPE__ unsigned int
+// WEBASSEMBLY-NEXT:#define __UINT_FAST64_FMTX__ "llX"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST64_FMTo__ "llo"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST64_FMTu__ "llu"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST64_FMTx__ "llx"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
+// WEBASSEMBLY-NEXT:#define __UINT_FAST64_TYPE__ long long unsigned int
+// WEBASSEMBLY-NEXT:#define __UINT_FAST8_FMTX__ "hhX"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST8_FMTo__ "hho"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST8_FMTu__ "hhu"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST8_FMTx__ "hhx"
+// WEBASSEMBLY-NEXT:#define __UINT_FAST8_MAX__ 255
+// WEBASSEMBLY-NEXT:#define __UINT_FAST8_TYPE__ unsigned char
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST16_FMTX__ "hX"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST16_FMTo__ "ho"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST16_FMTu__ "hu"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST16_FMTx__ "hx"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST16_MAX__ 65535
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST16_TYPE__ unsigned short
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST32_FMTX__ "X"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST32_FMTo__ "o"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST32_FMTu__ "u"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST32_FMTx__ "x"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST32_MAX__ 4294967295U
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST32_TYPE__ unsigned int
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST64_FMTX__ "llX"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST64_FMTo__ "llo"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST64_FMTu__ "llu"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST64_FMTx__ "llx"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST64_TYPE__ long long unsigned int
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST8_FMTX__ "hhX"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST8_FMTo__ "hho"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST8_FMTu__ "hhu"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST8_FMTx__ "hhx"
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST8_MAX__ 255
+// WEBASSEMBLY-NEXT:#define __UINT_LEAST8_TYPE__ unsigned char
+// WEBASSEMBLY-NEXT:#define __USER_LABEL_PREFIX__
+// WEBASSEMBLY-NEXT:#define __VERSION__ "{{.*}}"
+// WEBASSEMBLY-NEXT:#define __WCHAR_MAX__ 2147483647
+// WEBASSEMBLY-NEXT:#define __WCHAR_TYPE__ int
+// WEBASSEMBLY-NOT:#define __WCHAR_UNSIGNED__
+// WEBASSEMBLY-NEXT:#define __WCHAR_WIDTH__ 32
+// WEBASSEMBLY-NEXT:#define __WINT_MAX__ 2147483647
+// WEBASSEMBLY-NEXT:#define __WINT_TYPE__ int
+// WEBASSEMBLY-NOT:#define __WINT_UNSIGNED__
+// WEBASSEMBLY-NEXT:#define __WINT_WIDTH__ 32
+// WEBASSEMBLY-NEXT:#define __clang__ 1
+// WEBASSEMBLY-NEXT:#define __clang_major__ {{.*}}
+// WEBASSEMBLY-NEXT:#define __clang_minor__ {{.*}}
+// WEBASSEMBLY-NEXT:#define __clang_patchlevel__ {{.*}}
+// WEBASSEMBLY-NEXT:#define __clang_version__ "{{.*}}"
+// WEBASSEMBLY-NEXT:#define __llvm__ 1
+// WEBASSEMBLY-NOT:#define __unix
+// WEBASSEMBLY-NOT:#define __unix__
+// WEBASSEMBLY-WASI-NEXT:#define __wasi__ 1
+// WEBASSEMBLY-NOT:#define __wasm_simd128__
+// WEBASSEMBLY-NOT:#define __wasm_simd256__
+// WEBASSEMBLY-NOT:#define __wasm_simd512__
+// WEBASSEMBLY-NEXT:#define __wasm 1
+// WEBASSEMBLY32-NEXT:#define __wasm32 1
// WEBASSEMBLY64-NOT:#define __wasm32
+// WEBASSEMBLY32-NEXT:#define __wasm32__ 1
// WEBASSEMBLY64-NOT:#define __wasm32__
+// WEBASSEMBLY32-NOT:#define __wasm64__
+// WEBASSEMBLY32-NOT:#define __wasm64
// WEBASSEMBLY64-NEXT:#define __wasm64 1
// WEBASSEMBLY64-NEXT:#define __wasm64__ 1
-// WEBASSEMBLY64-NEXT:#define __wasm__ 1
+// WEBASSEMBLY-NEXT:#define __wasm__ 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple i686-windows-cygnus < /dev/null | FileCheck -match-full-lines -check-prefix CYGWIN-X32 %s
// CYGWIN-X32: #define __USER_LABEL_PREFIX__ _
// RUN: %clang_cc1 -E -dM -ffreestanding -triple x86_64-windows-cygnus < /dev/null | FileCheck -match-full-lines -check-prefix CYGWIN-X64 %s
// CYGWIN-X64: #define __USER_LABEL_PREFIX__
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=avr \
// RUN: < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix=AVR %s
//
// AVR:#define __ATOMIC_ACQUIRE 2
// AVR:#define __ATOMIC_ACQ_REL 4
// AVR:#define __ATOMIC_CONSUME 1
// AVR:#define __ATOMIC_RELAXED 0
// AVR:#define __ATOMIC_RELEASE 3
// AVR:#define __ATOMIC_SEQ_CST 5
// AVR:#define __AVR__ 1
// AVR:#define __BIGGEST_ALIGNMENT__ 1
// AVR:#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// AVR:#define __CHAR16_TYPE__ unsigned int
// AVR:#define __CHAR32_TYPE__ long unsigned int
// AVR:#define __CHAR_BIT__ 8
// AVR:#define __DBL_DECIMAL_DIG__ 9
// AVR:#define __DBL_DENORM_MIN__ 1.40129846e-45
// AVR:#define __DBL_DIG__ 6
// AVR:#define __DBL_EPSILON__ 1.19209290e-7
// AVR:#define __DBL_HAS_DENORM__ 1
// AVR:#define __DBL_HAS_INFINITY__ 1
// AVR:#define __DBL_HAS_QUIET_NAN__ 1
// AVR:#define __DBL_MANT_DIG__ 24
// AVR:#define __DBL_MAX_10_EXP__ 38
// AVR:#define __DBL_MAX_EXP__ 128
// AVR:#define __DBL_MAX__ 3.40282347e+38
// AVR:#define __DBL_MIN_10_EXP__ (-37)
// AVR:#define __DBL_MIN_EXP__ (-125)
// AVR:#define __DBL_MIN__ 1.17549435e-38
// AVR:#define __FINITE_MATH_ONLY__ 0
// AVR:#define __FLT_DECIMAL_DIG__ 9
// AVR:#define __FLT_DENORM_MIN__ 1.40129846e-45F
// AVR:#define __FLT_DIG__ 6
// AVR:#define __FLT_EPSILON__ 1.19209290e-7F
// AVR:#define __FLT_EVAL_METHOD__ 0
// AVR:#define __FLT_HAS_DENORM__ 1
// AVR:#define __FLT_HAS_INFINITY__ 1
// AVR:#define __FLT_HAS_QUIET_NAN__ 1
// AVR:#define __FLT_MANT_DIG__ 24
// AVR:#define __FLT_MAX_10_EXP__ 38
// AVR:#define __FLT_MAX_EXP__ 128
// AVR:#define __FLT_MAX__ 3.40282347e+38F
// AVR:#define __FLT_MIN_10_EXP__ (-37)
// AVR:#define __FLT_MIN_EXP__ (-125)
// AVR:#define __FLT_MIN__ 1.17549435e-38F
// AVR:#define __FLT_RADIX__ 2
// AVR:#define __GCC_ATOMIC_BOOL_LOCK_FREE 1
// AVR:#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 1
// AVR:#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 1
// AVR:#define __GCC_ATOMIC_CHAR_LOCK_FREE 1
// AVR:#define __GCC_ATOMIC_INT_LOCK_FREE 1
// AVR:#define __GCC_ATOMIC_LLONG_LOCK_FREE 1
// AVR:#define __GCC_ATOMIC_LONG_LOCK_FREE 1
// AVR:#define __GCC_ATOMIC_POINTER_LOCK_FREE 1
// AVR:#define __GCC_ATOMIC_SHORT_LOCK_FREE 1
// AVR:#define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
// AVR:#define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 1
// AVR:#define __GXX_ABI_VERSION 1002
// AVR:#define __INT16_C_SUFFIX__
// AVR:#define __INT16_MAX__ 32767
// AVR:#define __INT16_TYPE__ short
// AVR:#define __INT32_C_SUFFIX__ L
// AVR:#define __INT32_MAX__ 2147483647L
// AVR:#define __INT32_TYPE__ long int
// AVR:#define __INT64_C_SUFFIX__ LL
// AVR:#define __INT64_MAX__ 9223372036854775807LL
// AVR:#define __INT64_TYPE__ long long int
// AVR:#define __INT8_C_SUFFIX__
// AVR:#define __INT8_MAX__ 127
// AVR:#define __INT8_TYPE__ signed char
// AVR:#define __INTMAX_C_SUFFIX__ LL
// AVR:#define __INTMAX_MAX__ 9223372036854775807LL
// AVR:#define __INTMAX_TYPE__ long long int
// AVR:#define __INTPTR_MAX__ 32767
// AVR:#define __INTPTR_TYPE__ int
// AVR:#define __INT_FAST16_MAX__ 32767
// AVR:#define __INT_FAST16_TYPE__ int
// AVR:#define __INT_FAST32_MAX__ 2147483647L
// AVR:#define __INT_FAST32_TYPE__ long int
// AVR:#define __INT_FAST64_MAX__ 9223372036854775807LL
// AVR:#define __INT_FAST64_TYPE__ long long int
// AVR:#define __INT_FAST8_MAX__ 127
// AVR:#define __INT_FAST8_TYPE__ signed char
// AVR:#define __INT_LEAST16_MAX__ 32767
// AVR:#define __INT_LEAST16_TYPE__ int
// AVR:#define __INT_LEAST32_MAX__ 2147483647L
// AVR:#define __INT_LEAST32_TYPE__ long int
// AVR:#define __INT_LEAST64_MAX__ 9223372036854775807LL
// AVR:#define __INT_LEAST64_TYPE__ long long int
// AVR:#define __INT_LEAST8_MAX__ 127
// AVR:#define __INT_LEAST8_TYPE__ signed char
// AVR:#define __INT_MAX__ 32767
// AVR:#define __LDBL_DECIMAL_DIG__ 9
// AVR:#define __LDBL_DENORM_MIN__ 1.40129846e-45L
// AVR:#define __LDBL_DIG__ 6
// AVR:#define __LDBL_EPSILON__ 1.19209290e-7L
// AVR:#define __LDBL_HAS_DENORM__ 1
// AVR:#define __LDBL_HAS_INFINITY__ 1
// AVR:#define __LDBL_HAS_QUIET_NAN__ 1
// AVR:#define __LDBL_MANT_DIG__ 24
// AVR:#define __LDBL_MAX_10_EXP__ 38
// AVR:#define __LDBL_MAX_EXP__ 128
// AVR:#define __LDBL_MAX__ 3.40282347e+38L
// AVR:#define __LDBL_MIN_10_EXP__ (-37)
// AVR:#define __LDBL_MIN_EXP__ (-125)
// AVR:#define __LDBL_MIN__ 1.17549435e-38L
// AVR:#define __LONG_LONG_MAX__ 9223372036854775807LL
// AVR:#define __LONG_MAX__ 2147483647L
// AVR:#define __NO_INLINE__ 1
// AVR:#define __ORDER_BIG_ENDIAN__ 4321
// AVR:#define __ORDER_LITTLE_ENDIAN__ 1234
// AVR:#define __ORDER_PDP_ENDIAN__ 3412
// AVR:#define __PRAGMA_REDEFINE_EXTNAME 1
// AVR:#define __PTRDIFF_MAX__ 32767
// AVR:#define __PTRDIFF_TYPE__ int
// AVR:#define __SCHAR_MAX__ 127
// AVR:#define __SHRT_MAX__ 32767
// AVR:#define __SIG_ATOMIC_MAX__ 127
// AVR:#define __SIG_ATOMIC_WIDTH__ 8
// AVR:#define __SIZEOF_DOUBLE__ 4
// AVR:#define __SIZEOF_FLOAT__ 4
// AVR:#define __SIZEOF_INT__ 2
// AVR:#define __SIZEOF_LONG_DOUBLE__ 4
// AVR:#define __SIZEOF_LONG_LONG__ 8
// AVR:#define __SIZEOF_LONG__ 4
// AVR:#define __SIZEOF_POINTER__ 2
// AVR:#define __SIZEOF_PTRDIFF_T__ 2
// AVR:#define __SIZEOF_SHORT__ 2
// AVR:#define __SIZEOF_SIZE_T__ 2
// AVR:#define __SIZEOF_WCHAR_T__ 2
// AVR:#define __SIZEOF_WINT_T__ 2
// AVR:#define __SIZE_MAX__ 65535U
// AVR:#define __SIZE_TYPE__ unsigned int
// AVR:#define __STDC__ 1
// AVR:#define __UINT16_MAX__ 65535U
// AVR:#define __UINT16_TYPE__ unsigned short
// AVR:#define __UINT32_C_SUFFIX__ UL
// AVR:#define __UINT32_MAX__ 4294967295UL
// AVR:#define __UINT32_TYPE__ long unsigned int
// AVR:#define __UINT64_C_SUFFIX__ ULL
// AVR:#define __UINT64_MAX__ 18446744073709551615ULL
// AVR:#define __UINT64_TYPE__ long long unsigned int
// AVR:#define __UINT8_C_SUFFIX__
// AVR:#define __UINT8_MAX__ 255
// AVR:#define __UINT8_TYPE__ unsigned char
// AVR:#define __UINTMAX_C_SUFFIX__ ULL
// AVR:#define __UINTMAX_MAX__ 18446744073709551615ULL
// AVR:#define __UINTMAX_TYPE__ long long unsigned int
// AVR:#define __UINTPTR_MAX__ 65535U
// AVR:#define __UINTPTR_TYPE__ unsigned int
// AVR:#define __UINT_FAST16_MAX__ 65535U
// AVR:#define __UINT_FAST16_TYPE__ unsigned int
// AVR:#define __UINT_FAST32_MAX__ 4294967295UL
// AVR:#define __UINT_FAST32_TYPE__ long unsigned int
// AVR:#define __UINT_FAST64_MAX__ 18446744073709551615ULL
// AVR:#define __UINT_FAST64_TYPE__ long long unsigned int
// AVR:#define __UINT_FAST8_MAX__ 255
// AVR:#define __UINT_FAST8_TYPE__ unsigned char
// AVR:#define __UINT_LEAST16_MAX__ 65535U
// AVR:#define __UINT_LEAST16_TYPE__ unsigned int
// AVR:#define __UINT_LEAST32_MAX__ 4294967295UL
// AVR:#define __UINT_LEAST32_TYPE__ long unsigned int
// AVR:#define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// AVR:#define __UINT_LEAST64_TYPE__ long long unsigned int
// AVR:#define __UINT_LEAST8_MAX__ 255
// AVR:#define __UINT_LEAST8_TYPE__ unsigned char
// AVR:#define __USER_LABEL_PREFIX__
// AVR:#define __WCHAR_MAX__ 32767
// AVR:#define __WCHAR_TYPE__ int
// AVR:#define __WINT_TYPE__ int
// RUN: %clang_cc1 -E -dM -ffreestanding \
// RUN: -triple i686-windows-msvc -fms-compatibility -x c++ < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MSVC-X32 %s
// RUN: %clang_cc1 -E -dM -ffreestanding \
// RUN: -triple x86_64-windows-msvc -fms-compatibility -x c++ < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix MSVC-X64 %s
// MSVC-X32:#define __CLANG_ATOMIC_BOOL_LOCK_FREE 2
// MSVC-X32-NEXT:#define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2
// MSVC-X32-NEXT:#define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2
// MSVC-X32-NEXT:#define __CLANG_ATOMIC_CHAR_LOCK_FREE 2
// MSVC-X32-NEXT:#define __CLANG_ATOMIC_INT_LOCK_FREE 2
// MSVC-X32-NEXT:#define __CLANG_ATOMIC_LLONG_LOCK_FREE 2
// MSVC-X32-NEXT:#define __CLANG_ATOMIC_LONG_LOCK_FREE 2
// MSVC-X32-NEXT:#define __CLANG_ATOMIC_POINTER_LOCK_FREE 2
// MSVC-X32-NEXT:#define __CLANG_ATOMIC_SHORT_LOCK_FREE 2
// MSVC-X32-NEXT:#define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2
// MSVC-X32-NOT:#define __GCC_ATOMIC{{.*}}
// MSVC-X32:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 8U
// MSVC-X64:#define __CLANG_ATOMIC_BOOL_LOCK_FREE 2
// MSVC-X64-NEXT:#define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2
// MSVC-X64-NEXT:#define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2
// MSVC-X64-NEXT:#define __CLANG_ATOMIC_CHAR_LOCK_FREE 2
// MSVC-X64-NEXT:#define __CLANG_ATOMIC_INT_LOCK_FREE 2
// MSVC-X64-NEXT:#define __CLANG_ATOMIC_LLONG_LOCK_FREE 2
// MSVC-X64-NEXT:#define __CLANG_ATOMIC_LONG_LOCK_FREE 2
// MSVC-X64-NEXT:#define __CLANG_ATOMIC_POINTER_LOCK_FREE 2
// MSVC-X64-NEXT:#define __CLANG_ATOMIC_SHORT_LOCK_FREE 2
// MSVC-X64-NEXT:#define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2
// MSVC-X64-NOT:#define __GCC_ATOMIC{{.*}}
// MSVC-X64:#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 16ULL
// RUN: %clang_cc1 -E -dM -ffreestanding \
// RUN: -triple=aarch64-apple-ios9 < /dev/null \
// RUN: | FileCheck -check-prefix=DARWIN %s
// RUN: %clang_cc1 -E -dM -ffreestanding \
// RUN: -triple=aarch64-apple-macosx10.12 < /dev/null \
// RUN: | FileCheck -check-prefix=DARWIN %s
// DARWIN:#define __STDC_NO_THREADS__ 1
// RUN: %clang_cc1 -triple i386-apple-macosx -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix MACOS-32 %s
// RUN: %clang_cc1 -triple x86_64-apple-macosx -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix MACOS-64 %s
// MACOS-32: #define __INTPTR_TYPE__ long int
// MACOS-32: #define __PTRDIFF_TYPE__ int
// MACOS-32: #define __SIZE_TYPE__ long unsigned int
// MACOS-64: #define __INTPTR_TYPE__ long int
// MACOS-64: #define __PTRDIFF_TYPE__ long int
// MACOS-64: #define __SIZE_TYPE__ long unsigned int
// RUN: %clang_cc1 -triple i386-apple-ios-simulator -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix IOS-32 %s
// RUN: %clang_cc1 -triple armv7-apple-ios -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix IOS-32 %s
// RUN: %clang_cc1 -triple x86_64-apple-ios-simulator -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix IOS-64 %s
// RUN: %clang_cc1 -triple arm64-apple-ios -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix IOS-64 %s
// IOS-32: #define __INTPTR_TYPE__ long int
// IOS-32: #define __PTRDIFF_TYPE__ int
// IOS-32: #define __SIZE_TYPE__ long unsigned int
// IOS-64: #define __INTPTR_TYPE__ long int
// IOS-64: #define __PTRDIFF_TYPE__ long int
// IOS-64: #define __SIZE_TYPE__ long unsigned int
// RUN: %clang_cc1 -triple i386-apple-tvos-simulator -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix TVOS-32 %s
// RUN: %clang_cc1 -triple armv7-apple-tvos -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix TVOS-32 %s
// RUN: %clang_cc1 -triple x86_64-apple-tvos-simulator -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix TVOS-64 %s
// RUN: %clang_cc1 -triple arm64-apple-tvos -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix TVOS-64 %s
// TVOS-32: #define __INTPTR_TYPE__ long int
// TVOS-32: #define __PTRDIFF_TYPE__ int
// TVOS-32: #define __SIZE_TYPE__ long unsigned int
// TVOS-64: #define __INTPTR_TYPE__ long int
// TVOS-64: #define __PTRDIFF_TYPE__ long int
// TVOS-64: #define __SIZE_TYPE__ long unsigned int
// RUN: %clang_cc1 -triple i386-apple-watchos-simulator -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix WATCHOS-32 %s
// RUN: %clang_cc1 -triple armv7k-apple-watchos -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix WATCHOS-64 %s
// RUN: %clang_cc1 -triple x86_64-apple-watchos-simulator -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix WATCHOS-64 %s
// RUN: %clang_cc1 -triple arm64-apple-watchos -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix WATCHOS-64 %s
// WATCHOS-32: #define __INTPTR_TYPE__ long int
// WATCHOS-32: #define __PTRDIFF_TYPE__ int
// WATCHOS-32: #define __SIZE_TYPE__ long unsigned int
// WATCHOS-64: #define __INTPTR_TYPE__ long int
// WATCHOS-64: #define __PTRDIFF_TYPE__ long int
// WATCHOS-64: #define __SIZE_TYPE__ long unsigned int
// RUN: %clang_cc1 -triple armv7-apple-none-macho -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix ARM-DARWIN-BAREMETAL-32 %s
// RUN: %clang_cc1 -triple arm64-apple-none-macho -ffreestanding -dM -E /dev/null -o - | FileCheck -match-full-lines -check-prefix ARM-DARWIN-BAREMETAL-64 %s
// ARM-DARWIN-BAREMETAL-32: #define __INTPTR_TYPE__ long int
// ARM-DARWIN-BAREMETAL-32: #define __PTRDIFF_TYPE__ int
// ARM-DARWIN-BAREMETAL-32: #define __SIZE_TYPE__ long unsigned int
// ARM-DARWIN-BAREMETAL-64: #define __INTPTR_TYPE__ long int
// ARM-DARWIN-BAREMETAL-64: #define __PTRDIFF_TYPE__ long int
// ARM-DARWIN-BAREMETAL-64: #define __SIZE_TYPE__ long unsigned int
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=riscv32 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix=RISCV32 %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=riscv32-unknown-linux < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefixes=RISCV32,RISCV32-LINUX %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=riscv32 \
// RUN: -fforce-enable-int128 < /dev/null | FileCheck -match-full-lines \
// RUN: -check-prefixes=RISCV32,RISCV32-INT128 %s
// RISCV32: #define _ILP32 1
// RISCV32: #define __ATOMIC_ACQUIRE 2
// RISCV32: #define __ATOMIC_ACQ_REL 4
// RISCV32: #define __ATOMIC_CONSUME 1
// RISCV32: #define __ATOMIC_RELAXED 0
// RISCV32: #define __ATOMIC_RELEASE 3
// RISCV32: #define __ATOMIC_SEQ_CST 5
// RISCV32: #define __BIGGEST_ALIGNMENT__ 16
// RISCV32: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// RISCV32: #define __CHAR16_TYPE__ unsigned short
// RISCV32: #define __CHAR32_TYPE__ unsigned int
// RISCV32: #define __CHAR_BIT__ 8
// RISCV32: #define __DBL_DECIMAL_DIG__ 17
// RISCV32: #define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// RISCV32: #define __DBL_DIG__ 15
// RISCV32: #define __DBL_EPSILON__ 2.2204460492503131e-16
// RISCV32: #define __DBL_HAS_DENORM__ 1
// RISCV32: #define __DBL_HAS_INFINITY__ 1
// RISCV32: #define __DBL_HAS_QUIET_NAN__ 1
// RISCV32: #define __DBL_MANT_DIG__ 53
// RISCV32: #define __DBL_MAX_10_EXP__ 308
// RISCV32: #define __DBL_MAX_EXP__ 1024
// RISCV32: #define __DBL_MAX__ 1.7976931348623157e+308
// RISCV32: #define __DBL_MIN_10_EXP__ (-307)
// RISCV32: #define __DBL_MIN_EXP__ (-1021)
// RISCV32: #define __DBL_MIN__ 2.2250738585072014e-308
// RISCV32: #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// RISCV32: #define __ELF__ 1
// RISCV32: #define __FINITE_MATH_ONLY__ 0
// RISCV32: #define __FLT_DECIMAL_DIG__ 9
// RISCV32: #define __FLT_DENORM_MIN__ 1.40129846e-45F
// RISCV32: #define __FLT_DIG__ 6
// RISCV32: #define __FLT_EPSILON__ 1.19209290e-7F
// RISCV32: #define __FLT_EVAL_METHOD__ 0
// RISCV32: #define __FLT_HAS_DENORM__ 1
// RISCV32: #define __FLT_HAS_INFINITY__ 1
// RISCV32: #define __FLT_HAS_QUIET_NAN__ 1
// RISCV32: #define __FLT_MANT_DIG__ 24
// RISCV32: #define __FLT_MAX_10_EXP__ 38
// RISCV32: #define __FLT_MAX_EXP__ 128
// RISCV32: #define __FLT_MAX__ 3.40282347e+38F
// RISCV32: #define __FLT_MIN_10_EXP__ (-37)
// RISCV32: #define __FLT_MIN_EXP__ (-125)
// RISCV32: #define __FLT_MIN__ 1.17549435e-38F
// RISCV32: #define __FLT_RADIX__ 2
// RISCV32: #define __GCC_ATOMIC_BOOL_LOCK_FREE 1
// RISCV32: #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 1
// RISCV32: #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 1
// RISCV32: #define __GCC_ATOMIC_CHAR_LOCK_FREE 1
// RISCV32: #define __GCC_ATOMIC_INT_LOCK_FREE 1
// RISCV32: #define __GCC_ATOMIC_LLONG_LOCK_FREE 1
// RISCV32: #define __GCC_ATOMIC_LONG_LOCK_FREE 1
// RISCV32: #define __GCC_ATOMIC_POINTER_LOCK_FREE 1
// RISCV32: #define __GCC_ATOMIC_SHORT_LOCK_FREE 1
// RISCV32: #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
// RISCV32: #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 1
// RISCV32: #define __GNUC_MINOR__ {{.*}}
// RISCV32: #define __GNUC_PATCHLEVEL__ {{.*}}
// RISCV32: #define __GNUC_STDC_INLINE__ 1
// RISCV32: #define __GNUC__ {{.*}}
// RISCV32: #define __GXX_ABI_VERSION {{.*}}
// RISCV32: #define __ILP32__ 1
// RISCV32: #define __INT16_C_SUFFIX__
// RISCV32: #define __INT16_MAX__ 32767
// RISCV32: #define __INT16_TYPE__ short
// RISCV32: #define __INT32_C_SUFFIX__
// RISCV32: #define __INT32_MAX__ 2147483647
// RISCV32: #define __INT32_TYPE__ int
// RISCV32: #define __INT64_C_SUFFIX__ LL
// RISCV32: #define __INT64_MAX__ 9223372036854775807LL
// RISCV32: #define __INT64_TYPE__ long long int
// RISCV32: #define __INT8_C_SUFFIX__
// RISCV32: #define __INT8_MAX__ 127
// RISCV32: #define __INT8_TYPE__ signed char
// RISCV32: #define __INTMAX_C_SUFFIX__ LL
// RISCV32: #define __INTMAX_MAX__ 9223372036854775807LL
// RISCV32: #define __INTMAX_TYPE__ long long int
// RISCV32: #define __INTMAX_WIDTH__ 64
// RISCV32: #define __INTPTR_MAX__ 2147483647
// RISCV32: #define __INTPTR_TYPE__ int
// RISCV32: #define __INTPTR_WIDTH__ 32
// TODO: RISC-V GCC defines INT_FAST16 as int
// RISCV32: #define __INT_FAST16_MAX__ 32767
// RISCV32: #define __INT_FAST16_TYPE__ short
// RISCV32: #define __INT_FAST32_MAX__ 2147483647
// RISCV32: #define __INT_FAST32_TYPE__ int
// RISCV32: #define __INT_FAST64_MAX__ 9223372036854775807LL
// RISCV32: #define __INT_FAST64_TYPE__ long long int
// TODO: RISC-V GCC defines INT_FAST8 as int
// RISCV32: #define __INT_FAST8_MAX__ 127
// RISCV32: #define __INT_FAST8_TYPE__ signed char
// RISCV32: #define __INT_LEAST16_MAX__ 32767
// RISCV32: #define __INT_LEAST16_TYPE__ short
// RISCV32: #define __INT_LEAST32_MAX__ 2147483647
// RISCV32: #define __INT_LEAST32_TYPE__ int
// RISCV32: #define __INT_LEAST64_MAX__ 9223372036854775807LL
// RISCV32: #define __INT_LEAST64_TYPE__ long long int
// RISCV32: #define __INT_LEAST8_MAX__ 127
// RISCV32: #define __INT_LEAST8_TYPE__ signed char
// RISCV32: #define __INT_MAX__ 2147483647
// RISCV32: #define __LDBL_DECIMAL_DIG__ 36
// RISCV32: #define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
// RISCV32: #define __LDBL_DIG__ 33
// RISCV32: #define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// RISCV32: #define __LDBL_HAS_DENORM__ 1
// RISCV32: #define __LDBL_HAS_INFINITY__ 1
// RISCV32: #define __LDBL_HAS_QUIET_NAN__ 1
// RISCV32: #define __LDBL_MANT_DIG__ 113
// RISCV32: #define __LDBL_MAX_10_EXP__ 4932
// RISCV32: #define __LDBL_MAX_EXP__ 16384
// RISCV32: #define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
// RISCV32: #define __LDBL_MIN_10_EXP__ (-4931)
// RISCV32: #define __LDBL_MIN_EXP__ (-16381)
// RISCV32: #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// RISCV32: #define __LITTLE_ENDIAN__ 1
// RISCV32: #define __LONG_LONG_MAX__ 9223372036854775807LL
// RISCV32: #define __LONG_MAX__ 2147483647L
// RISCV32: #define __NO_INLINE__ 1
// RISCV32: #define __POINTER_WIDTH__ 32
// RISCV32: #define __PRAGMA_REDEFINE_EXTNAME 1
// RISCV32: #define __PTRDIFF_MAX__ 2147483647
// RISCV32: #define __PTRDIFF_TYPE__ int
// RISCV32: #define __PTRDIFF_WIDTH__ 32
// RISCV32: #define __SCHAR_MAX__ 127
// RISCV32: #define __SHRT_MAX__ 32767
// RISCV32: #define __SIG_ATOMIC_MAX__ 2147483647
// RISCV32: #define __SIG_ATOMIC_WIDTH__ 32
// RISCV32: #define __SIZEOF_DOUBLE__ 8
// RISCV32: #define __SIZEOF_FLOAT__ 4
// RISCV32-INT128: #define __SIZEOF_INT128__ 16
// RISCV32: #define __SIZEOF_INT__ 4
// RISCV32: #define __SIZEOF_LONG_DOUBLE__ 16
// RISCV32: #define __SIZEOF_LONG_LONG__ 8
// RISCV32: #define __SIZEOF_LONG__ 4
// RISCV32: #define __SIZEOF_POINTER__ 4
// RISCV32: #define __SIZEOF_PTRDIFF_T__ 4
// RISCV32: #define __SIZEOF_SHORT__ 2
// RISCV32: #define __SIZEOF_SIZE_T__ 4
// RISCV32: #define __SIZEOF_WCHAR_T__ 4
// RISCV32: #define __SIZEOF_WINT_T__ 4
// RISCV32: #define __SIZE_MAX__ 4294967295U
// RISCV32: #define __SIZE_TYPE__ unsigned int
// RISCV32: #define __SIZE_WIDTH__ 32
// RISCV32: #define __STDC_HOSTED__ 0
// RISCV32: #define __STDC_UTF_16__ 1
// RISCV32: #define __STDC_UTF_32__ 1
// RISCV32: #define __STDC_VERSION__ 201112L
// RISCV32: #define __STDC__ 1
// RISCV32: #define __UINT16_C_SUFFIX__
// RISCV32: #define __UINT16_MAX__ 65535
// RISCV32: #define __UINT16_TYPE__ unsigned short
// RISCV32: #define __UINT32_C_SUFFIX__ U
// RISCV32: #define __UINT32_MAX__ 4294967295U
// RISCV32: #define __UINT32_TYPE__ unsigned int
// RISCV32: #define __UINT64_C_SUFFIX__ ULL
// RISCV32: #define __UINT64_MAX__ 18446744073709551615ULL
// RISCV32: #define __UINT64_TYPE__ long long unsigned int
// RISCV32: #define __UINT8_C_SUFFIX__
// RISCV32: #define __UINT8_MAX__ 255
// RISCV32: #define __UINT8_TYPE__ unsigned char
// RISCV32: #define __UINTMAX_C_SUFFIX__ ULL
// RISCV32: #define __UINTMAX_MAX__ 18446744073709551615ULL
// RISCV32: #define __UINTMAX_TYPE__ long long unsigned int
// RISCV32: #define __UINTMAX_WIDTH__ 64
// RISCV32: #define __UINTPTR_MAX__ 4294967295U
// RISCV32: #define __UINTPTR_TYPE__ unsigned int
// RISCV32: #define __UINTPTR_WIDTH__ 32
// TODO: RISC-V GCC defines UINT_FAST16 to be unsigned int
// RISCV32: #define __UINT_FAST16_MAX__ 65535
// RISCV32: #define __UINT_FAST16_TYPE__ unsigned short
// RISCV32: #define __UINT_FAST32_MAX__ 4294967295U
// RISCV32: #define __UINT_FAST32_TYPE__ unsigned int
// RISCV32: #define __UINT_FAST64_MAX__ 18446744073709551615ULL
// RISCV32: #define __UINT_FAST64_TYPE__ long long unsigned int
// TODO: RISC-V GCC defines UINT_FAST8 to be unsigned int
// RISCV32: #define __UINT_FAST8_MAX__ 255
// RISCV32: #define __UINT_FAST8_TYPE__ unsigned char
// RISCV32: #define __UINT_LEAST16_MAX__ 65535
// RISCV32: #define __UINT_LEAST16_TYPE__ unsigned short
// RISCV32: #define __UINT_LEAST32_MAX__ 4294967295U
// RISCV32: #define __UINT_LEAST32_TYPE__ unsigned int
// RISCV32: #define __UINT_LEAST64_MAX__ 18446744073709551615ULL
// RISCV32: #define __UINT_LEAST64_TYPE__ long long unsigned int
// RISCV32: #define __UINT_LEAST8_MAX__ 255
// RISCV32: #define __UINT_LEAST8_TYPE__ unsigned char
// RISCV32: #define __USER_LABEL_PREFIX__
// RISCV32: #define __WCHAR_MAX__ 2147483647
// RISCV32: #define __WCHAR_TYPE__ int
// RISCV32: #define __WCHAR_WIDTH__ 32
// RISCV32: #define __WINT_TYPE__ unsigned int
// RISCV32: #define __WINT_UNSIGNED__ 1
// RISCV32: #define __WINT_WIDTH__ 32
// RISCV32-LINUX: #define __gnu_linux__ 1
// RISCV32-LINUX: #define __linux 1
// RISCV32-LINUX: #define __linux__ 1
// RISCV32: #define __riscv 1
// RISCV32: #define __riscv_cmodel_medlow 1
// RISCV32: #define __riscv_float_abi_soft 1
// RISCV32: #define __riscv_xlen 32
// RISCV32-LINUX: #define __unix 1
// RISCV32-LINUX: #define __unix__ 1
// RISCV32-LINUX: #define linux 1
// RISCV32-LINUX: #define unix 1
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=riscv64 < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefix=RISCV64 %s
// RUN: %clang_cc1 -E -dM -ffreestanding -triple=riscv64-unknown-linux < /dev/null \
// RUN: | FileCheck -match-full-lines -check-prefixes=RISCV64,RISCV64-LINUX %s
// RISCV64: #define _LP64 1
// RISCV64: #define __ATOMIC_ACQUIRE 2
// RISCV64: #define __ATOMIC_ACQ_REL 4
// RISCV64: #define __ATOMIC_CONSUME 1
// RISCV64: #define __ATOMIC_RELAXED 0
// RISCV64: #define __ATOMIC_RELEASE 3
// RISCV64: #define __ATOMIC_SEQ_CST 5
// RISCV64: #define __BIGGEST_ALIGNMENT__ 16
// RISCV64: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
// RISCV64: #define __CHAR16_TYPE__ unsigned short
// RISCV64: #define __CHAR32_TYPE__ unsigned int
// RISCV64: #define __CHAR_BIT__ 8
// RISCV64: #define __DBL_DECIMAL_DIG__ 17
// RISCV64: #define __DBL_DENORM_MIN__ 4.9406564584124654e-324
// RISCV64: #define __DBL_DIG__ 15
// RISCV64: #define __DBL_EPSILON__ 2.2204460492503131e-16
// RISCV64: #define __DBL_HAS_DENORM__ 1
// RISCV64: #define __DBL_HAS_INFINITY__ 1
// RISCV64: #define __DBL_HAS_QUIET_NAN__ 1
// RISCV64: #define __DBL_MANT_DIG__ 53
// RISCV64: #define __DBL_MAX_10_EXP__ 308
// RISCV64: #define __DBL_MAX_EXP__ 1024
// RISCV64: #define __DBL_MAX__ 1.7976931348623157e+308
// RISCV64: #define __DBL_MIN_10_EXP__ (-307)
// RISCV64: #define __DBL_MIN_EXP__ (-1021)
// RISCV64: #define __DBL_MIN__ 2.2250738585072014e-308
// RISCV64: #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
// RISCV64: #define __ELF__ 1
// RISCV64: #define __FINITE_MATH_ONLY__ 0
// RISCV64: #define __FLT_DECIMAL_DIG__ 9
// RISCV64: #define __FLT_DENORM_MIN__ 1.40129846e-45F
// RISCV64: #define __FLT_DIG__ 6
// RISCV64: #define __FLT_EPSILON__ 1.19209290e-7F
// RISCV64: #define __FLT_EVAL_METHOD__ 0
// RISCV64: #define __FLT_HAS_DENORM__ 1
// RISCV64: #define __FLT_HAS_INFINITY__ 1
// RISCV64: #define __FLT_HAS_QUIET_NAN__ 1
// RISCV64: #define __FLT_MANT_DIG__ 24
// RISCV64: #define __FLT_MAX_10_EXP__ 38
// RISCV64: #define __FLT_MAX_EXP__ 128
// RISCV64: #define __FLT_MAX__ 3.40282347e+38F
// RISCV64: #define __FLT_MIN_10_EXP__ (-37)
// RISCV64: #define __FLT_MIN_EXP__ (-125)
// RISCV64: #define __FLT_MIN__ 1.17549435e-38F
// RISCV64: #define __FLT_RADIX__ 2
// RISCV64: #define __GCC_ATOMIC_BOOL_LOCK_FREE 1
// RISCV64: #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 1
// RISCV64: #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 1
// RISCV64: #define __GCC_ATOMIC_CHAR_LOCK_FREE 1
// RISCV64: #define __GCC_ATOMIC_INT_LOCK_FREE 1
// RISCV64: #define __GCC_ATOMIC_LLONG_LOCK_FREE 1
// RISCV64: #define __GCC_ATOMIC_LONG_LOCK_FREE 1
// RISCV64: #define __GCC_ATOMIC_POINTER_LOCK_FREE 1
// RISCV64: #define __GCC_ATOMIC_SHORT_LOCK_FREE 1
// RISCV64: #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
// RISCV64: #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 1
// RISCV64: #define __GNUC_MINOR__ {{.*}}
// RISCV64: #define __GNUC_PATCHLEVEL__ {{.*}}
// RISCV64: #define __GNUC_STDC_INLINE__ 1
// RISCV64: #define __GNUC__ {{.*}}
// RISCV64: #define __GXX_ABI_VERSION {{.*}}
// RISCV64: #define __INT16_C_SUFFIX__
// RISCV64: #define __INT16_MAX__ 32767
// RISCV64: #define __INT16_TYPE__ short
// RISCV64: #define __INT32_C_SUFFIX__
// RISCV64: #define __INT32_MAX__ 2147483647
// RISCV64: #define __INT32_TYPE__ int
// RISCV64: #define __INT64_C_SUFFIX__ L
// RISCV64: #define __INT64_MAX__ 9223372036854775807L
// RISCV64: #define __INT64_TYPE__ long int
// RISCV64: #define __INT8_C_SUFFIX__
// RISCV64: #define __INT8_MAX__ 127
// RISCV64: #define __INT8_TYPE__ signed char
// RISCV64: #define __INTMAX_C_SUFFIX__ L
// RISCV64: #define __INTMAX_MAX__ 9223372036854775807L
// RISCV64: #define __INTMAX_TYPE__ long int
// RISCV64: #define __INTMAX_WIDTH__ 64
// RISCV64: #define __INTPTR_MAX__ 9223372036854775807L
// RISCV64: #define __INTPTR_TYPE__ long int
// RISCV64: #define __INTPTR_WIDTH__ 64
// TODO: RISC-V GCC defines INT_FAST16 as int
// RISCV64: #define __INT_FAST16_MAX__ 32767
// RISCV64: #define __INT_FAST16_TYPE__ short
// RISCV64: #define __INT_FAST32_MAX__ 2147483647
// RISCV64: #define __INT_FAST32_TYPE__ int
// RISCV64: #define __INT_FAST64_MAX__ 9223372036854775807L
// RISCV64: #define __INT_FAST64_TYPE__ long int
// TODO: RISC-V GCC defines INT_FAST8 as int
// RISCV64: #define __INT_FAST8_MAX__ 127
// RISCV64: #define __INT_FAST8_TYPE__ signed char
// RISCV64: #define __INT_LEAST16_MAX__ 32767
// RISCV64: #define __INT_LEAST16_TYPE__ short
// RISCV64: #define __INT_LEAST32_MAX__ 2147483647
// RISCV64: #define __INT_LEAST32_TYPE__ int
// RISCV64: #define __INT_LEAST64_MAX__ 9223372036854775807L
// RISCV64: #define __INT_LEAST64_TYPE__ long int
// RISCV64: #define __INT_LEAST8_MAX__ 127
// RISCV64: #define __INT_LEAST8_TYPE__ signed char
// RISCV64: #define __INT_MAX__ 2147483647
// RISCV64: #define __LDBL_DECIMAL_DIG__ 36
// RISCV64: #define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L
// RISCV64: #define __LDBL_DIG__ 33
// RISCV64: #define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L
// RISCV64: #define __LDBL_HAS_DENORM__ 1
// RISCV64: #define __LDBL_HAS_INFINITY__ 1
// RISCV64: #define __LDBL_HAS_QUIET_NAN__ 1
// RISCV64: #define __LDBL_MANT_DIG__ 113
// RISCV64: #define __LDBL_MAX_10_EXP__ 4932
// RISCV64: #define __LDBL_MAX_EXP__ 16384
// RISCV64: #define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L
// RISCV64: #define __LDBL_MIN_10_EXP__ (-4931)
// RISCV64: #define __LDBL_MIN_EXP__ (-16381)
// RISCV64: #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
// RISCV64: #define __LITTLE_ENDIAN__ 1
// RISCV64: #define __LONG_LONG_MAX__ 9223372036854775807LL
// RISCV64: #define __LONG_MAX__ 9223372036854775807L
// RISCV64: #define __LP64__ 1
// RISCV64: #define __NO_INLINE__ 1
// RISCV64: #define __POINTER_WIDTH__ 64
// RISCV64: #define __PRAGMA_REDEFINE_EXTNAME 1
// RISCV64: #define __PTRDIFF_MAX__ 9223372036854775807L
// RISCV64: #define __PTRDIFF_TYPE__ long int
// RISCV64: #define __PTRDIFF_WIDTH__ 64
// RISCV64: #define __SCHAR_MAX__ 127
// RISCV64: #define __SHRT_MAX__ 32767
// RISCV64: #define __SIG_ATOMIC_MAX__ 2147483647
// RISCV64: #define __SIG_ATOMIC_WIDTH__ 32
// RISCV64: #define __SIZEOF_DOUBLE__ 8
// RISCV64: #define __SIZEOF_FLOAT__ 4
// RISCV64: #define __SIZEOF_INT__ 4
// RISCV64: #define __SIZEOF_LONG_DOUBLE__ 16
// RISCV64: #define __SIZEOF_LONG_LONG__ 8
// RISCV64: #define __SIZEOF_LONG__ 8
// RISCV64: #define __SIZEOF_POINTER__ 8
// RISCV64: #define __SIZEOF_PTRDIFF_T__ 8
// RISCV64: #define __SIZEOF_SHORT__ 2
// RISCV64: #define __SIZEOF_SIZE_T__ 8
// RISCV64: #define __SIZEOF_WCHAR_T__ 4
// RISCV64: #define __SIZEOF_WINT_T__ 4
// RISCV64: #define __SIZE_MAX__ 18446744073709551615UL
// RISCV64: #define __SIZE_TYPE__ long unsigned int
// RISCV64: #define __SIZE_WIDTH__ 64
// RISCV64: #define __STDC_HOSTED__ 0
// RISCV64: #define __STDC_UTF_16__ 1
// RISCV64: #define __STDC_UTF_32__ 1
// RISCV64: #define __STDC_VERSION__ 201112L
// RISCV64: #define __STDC__ 1
// RISCV64: #define __UINT16_C_SUFFIX__
// RISCV64: #define __UINT16_MAX__ 65535
// RISCV64: #define __UINT16_TYPE__ unsigned short
// RISCV64: #define __UINT32_C_SUFFIX__ U
// RISCV64: #define __UINT32_MAX__ 4294967295U
// RISCV64: #define __UINT32_TYPE__ unsigned int
// RISCV64: #define __UINT64_C_SUFFIX__ UL
// RISCV64: #define __UINT64_MAX__ 18446744073709551615UL
// RISCV64: #define __UINT64_TYPE__ long unsigned int
// RISCV64: #define __UINT8_C_SUFFIX__
// RISCV64: #define __UINT8_MAX__ 255
// RISCV64: #define __UINT8_TYPE__ unsigned char
// RISCV64: #define __UINTMAX_C_SUFFIX__ UL
// RISCV64: #define __UINTMAX_MAX__ 18446744073709551615UL
// RISCV64: #define __UINTMAX_TYPE__ long unsigned int
// RISCV64: #define __UINTMAX_WIDTH__ 64
// RISCV64: #define __UINTPTR_MAX__ 18446744073709551615UL
// RISCV64: #define __UINTPTR_TYPE__ long unsigned int
// RISCV64: #define __UINTPTR_WIDTH__ 64
// TODO: RISC-V GCC defines UINT_FAST16 to be unsigned int
// RISCV64: #define __UINT_FAST16_MAX__ 65535
// RISCV64: #define __UINT_FAST16_TYPE__ unsigned short
// RISCV64: #define __UINT_FAST32_MAX__ 4294967295U
// RISCV64: #define __UINT_FAST32_TYPE__ unsigned int
// RISCV64: #define __UINT_FAST64_MAX__ 18446744073709551615UL
// RISCV64: #define __UINT_FAST64_TYPE__ long unsigned int
// TODO: RISC-V GCC defines UINT_FAST8 to be unsigned int
// RISCV64: #define __UINT_FAST8_MAX__ 255
// RISCV64: #define __UINT_FAST8_TYPE__ unsigned char
// RISCV64: #define __UINT_LEAST16_MAX__ 65535
// RISCV64: #define __UINT_LEAST16_TYPE__ unsigned short
// RISCV64: #define __UINT_LEAST32_MAX__ 4294967295U
// RISCV64: #define __UINT_LEAST32_TYPE__ unsigned int
// RISCV64: #define __UINT_LEAST64_MAX__ 18446744073709551615UL
// RISCV64: #define __UINT_LEAST64_TYPE__ long unsigned int
// RISCV64: #define __UINT_LEAST8_MAX__ 255
// RISCV64: #define __UINT_LEAST8_TYPE__ unsigned char
// RISCV64: #define __USER_LABEL_PREFIX__
// RISCV64: #define __WCHAR_MAX__ 2147483647
// RISCV64: #define __WCHAR_TYPE__ int
// RISCV64: #define __WCHAR_WIDTH__ 32
// RISCV64: #define __WINT_TYPE__ unsigned int
// RISCV64: #define __WINT_UNSIGNED__ 1
// RISCV64: #define __WINT_WIDTH__ 32
// RISCV64-LINUX: #define __gnu_linux__ 1
// RISCV64-LINUX: #define __linux 1
// RISCV64-LINUX: #define __linux__ 1
// RISCV64: #define __riscv 1
// RISCV64: #define __riscv_cmodel_medlow 1
// RISCV64: #define __riscv_float_abi_soft 1
// RISCV64: #define __riscv_xlen 64
// RISCV64-LINUX: #define __unix 1
// RISCV64-LINUX: #define __unix__ 1
// RISCV64-LINUX: #define linux 1
// RISCV64-LINUX: #define unix 1
Index: vendor/clang/dist-release_80/test/Sema/Float16.c
===================================================================
--- vendor/clang/dist-release_80/test/Sema/Float16.c (nonexistent)
+++ vendor/clang/dist-release_80/test/Sema/Float16.c (revision 343796)
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux-pc %s
+// RUN: %clang_cc1 -fsyntax-only -verify -triple spir-unknown-unknown %s -DHAVE
+// RUN: %clang_cc1 -fsyntax-only -verify -triple armv7a-linux-gnu %s -DHAVE
+// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-linux-gnu %s -DHAVE
+
+#ifdef HAVE
+// expected-no-diagnostics
+#else
+// expected-error@+2{{_Float16 is not supported on this target}}
+#endif // HAVE
+_Float16 f;
Index: vendor/clang/dist-release_80/test/SemaCXX/Float16.cpp
===================================================================
--- vendor/clang/dist-release_80/test/SemaCXX/Float16.cpp (nonexistent)
+++ vendor/clang/dist-release_80/test/SemaCXX/Float16.cpp (revision 343796)
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux-pc %s
+// RUN: %clang_cc1 -fsyntax-only -verify -triple spir-unknown-unknown %s -DHAVE
+// RUN: %clang_cc1 -fsyntax-only -verify -triple armv7a-linux-gnu %s -DHAVE
+// RUN: %clang_cc1 -fsyntax-only -verify -triple aarch64-linux-gnu %s -DHAVE
+
+#ifdef HAVE
+// expected-no-diagnostics
+#endif // HAVE
+
+#ifndef HAVE
+// expected-error@+2{{_Float16 is not supported on this target}}
+#endif // !HAVE
+_Float16 f;
+
+#ifndef HAVE
+// expected-error@+2{{invalid suffix 'F16' on floating constant}}
+#endif // !HAVE
+const auto g = 1.1F16;
Index: vendor/clang/dist-release_80/test/SemaCXX/PR40395.cpp
===================================================================
--- vendor/clang/dist-release_80/test/SemaCXX/PR40395.cpp (nonexistent)
+++ vendor/clang/dist-release_80/test/SemaCXX/PR40395.cpp (revision 343796)
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -std=c++17 -fms-extensions -triple=x86_64-pc-win32 -verify %s
+// expected-no-diagnostics
+
+// PR40395 - ConstantExpr shouldn't cause the template object to infinitely
+// expand.
+struct _GUID {};
+struct __declspec(uuid("{AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA}")) B {};
+
+template <const _GUID* piid>
+struct A {
+ virtual void baz() { A<piid>(); }
+};
+
+void f() {
+ A<&__uuidof(B)>();
+}
Index: vendor/clang/dist-release_80/test/SemaCXX/cxx1z-decomposition.cpp
===================================================================
--- vendor/clang/dist-release_80/test/SemaCXX/cxx1z-decomposition.cpp (revision 343795)
+++ vendor/clang/dist-release_80/test/SemaCXX/cxx1z-decomposition.cpp (revision 343796)
@@ -1,84 +1,101 @@
// RUN: %clang_cc1 -std=c++1z -verify %s
void use_from_own_init() {
auto [a] = a; // expected-error {{binding 'a' cannot appear in the initializer of its own decomposition declaration}}
}
// As a Clang extension, _Complex can be decomposed.
float decompose_complex(_Complex float cf) {
static _Complex float scf;
auto &[sre, sim] = scf;
// ok, this is references initialized by constant expressions all the way down
static_assert(&sre == &__real scf);
static_assert(&sim == &__imag scf);
auto [re, im] = cf;
return re*re + im*im;
}
// As a Clang extension, vector types can be decomposed.
typedef float vf3 __attribute__((ext_vector_type(3)));
float decompose_vector(vf3 v) {
auto [x, y, z] = v;
auto *p = &x; // expected-error {{address of vector element requested}}
return x + y + z;
}
struct S { int a, b; };
constexpr int f(S s) {
auto &[a, b] = s;
return a * 10 + b;
}
static_assert(f({1, 2}) == 12);
constexpr bool g(S &&s) {
auto &[a, b] = s;
return &a == &s.a && &b == &s.b && &a != &b;
}
static_assert(g({1, 2}));
void enclosing() {
struct S { int a; };
auto [n] = S(); // expected-note 2{{'n' declared here}}
struct Q { int f() { return n; } }; // expected-error {{reference to local binding 'n' declared in enclosing function}}
// FIXME: This is probably supposed to be valid, but we do not have clear rules on how it's supposed to work.
(void) [&] { return n; }; // expected-error {{reference to local binding 'n' declared in enclosing function}}
(void) [n] {}; // expected-error {{'n' in capture list does not name a variable}}
}
void bitfield() {
struct { int a : 3, : 4, b : 5; } a;
auto &[x, y] = a;
auto &[p, q, r] = a; // expected-error {{decomposes into 2 elements, but 3 names were provided}}
}
void for_range() {
int x = 1;
for (auto[a, b] : x) { // expected-error {{invalid range expression of type 'int'; no viable 'begin' function available}}
a++;
}
int y[5];
for (auto[c] : y) { // expected-error {{cannot decompose non-class, non-array type 'int'}}
c++;
}
}
int error_recovery() {
auto [foobar]; // expected-error {{requires an initializer}}
return foobar_; // expected-error {{undeclared identifier 'foobar_'}}
}
// PR32172
template <class T> void dependent_foreach(T t) {
for (auto [a,b,c] : t)
a,b,c;
}
struct PR37352 {
int n;
void f() { static auto [a] = *this; } // expected-error {{cannot be declared 'static'}}
};
+namespace instantiate_template {
+
+template <typename T1, typename T2>
+struct pair {
+ T1 a;
+ T2 b;
+};
+
+const pair<int, int> &f1();
+
+int f2() {
+ const auto &[a, b] = f1();
+ return a + b;
+}
+
+} // namespace instantiate_template
+
// FIXME: by-value array copies
Index: vendor/clang/dist-release_80/test/SemaObjC/enum-fixed-type.m
===================================================================
--- vendor/clang/dist-release_80/test/SemaObjC/enum-fixed-type.m (revision 343795)
+++ vendor/clang/dist-release_80/test/SemaObjC/enum-fixed-type.m (revision 343796)
@@ -1,50 +1,52 @@
// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify -xc %s
+#ifdef __OBJC__
#if !__has_feature(objc_fixed_enum)
# error Enumerations with a fixed underlying type are not supported
+#endif
#endif
#if !__has_extension(cxx_fixed_enum)
# error Enumerations with a fixed underlying type are not supported
#endif
typedef long Integer;
typedef enum : Integer { Enumerator1, Enumerator2 } Enumeration;
int array[sizeof(Enumeration) == sizeof(long)? 1 : -1];
enum Color { Red, Green, Blue };
struct X {
enum Color : 4;
enum Color field1: 4;
enum Other : Integer field2;
enum Other : Integer field3 : 4;
enum : Integer { Blah, Blarg } field4 : 4;
};
void test() {
long value = 2;
Enumeration e = value;
}
// <rdar://10381507>
typedef enum : long { Foo } IntegerEnum;
int arr[(sizeof(__typeof__(Foo)) == sizeof(__typeof__(IntegerEnum)))? 1 : -1];
int arr1[(sizeof(__typeof__(Foo)) == sizeof(__typeof__(long)))? 1 : -1];
int arr2[(sizeof(__typeof__(IntegerEnum)) == sizeof(__typeof__(long)))? 1 : -1];
// <rdar://problem/10760113>
typedef enum : long long { Bar = -1 } LongLongEnum;
int arr3[(long long)Bar == (long long)-1 ? 1 : -1];
typedef enum : Integer { BaseElem } BaseEnum;
typedef enum : BaseEnum { DerivedElem } DerivedEnum; // expected-error {{non-integral type 'BaseEnum' is an invalid underlying type}}
// <rdar://problem/24999533>
enum MyEnum : _Bool {
MyThing = 0
};
Index: vendor/clang/dist-release_80/test/SemaOpenCL/printf-format-string-warnings.cl
===================================================================
--- vendor/clang/dist-release_80/test/SemaOpenCL/printf-format-string-warnings.cl (revision 343795)
+++ vendor/clang/dist-release_80/test/SemaOpenCL/printf-format-string-warnings.cl (revision 343796)
@@ -1,13 +1,14 @@
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0 -finclude-default-header
-// Make sure warnings are produced based on printf format strings.
+// FIXME: Make sure warnings are produced based on printf format strings.
+// expected-no-diagnostics
kernel void format_string_warnings(__constant char* arg) {
- printf("%d", arg); // expected-warning {{format specifies type 'int' but the argument has type '__constant char *'}}
+ printf("%d", arg);
- printf("not enough arguments %d %d", 4); // expected-warning {{more '%' conversions than data arguments}}
+ printf("not enough arguments %d %d", 4);
- printf("too many arguments", 4); // expected-warning {{data argument not used by format string}}
+ printf("too many arguments", 4);
}
Index: vendor/clang/dist-release_80/test/SemaOpenCL/printf-format-strings.cl
===================================================================
--- vendor/clang/dist-release_80/test/SemaOpenCL/printf-format-strings.cl (revision 343795)
+++ vendor/clang/dist-release_80/test/SemaOpenCL/printf-format-strings.cl (revision 343796)
@@ -1,94 +1,94 @@
// RUN: %clang_cc1 -cl-std=CL1.2 -cl-ext=+cl_khr_fp64 -fsyntax-only -verify %s
// RUN: %clang_cc1 -cl-std=CL1.2 -cl-ext=-cl_khr_fp64 -fsyntax-only -verify %s
typedef __attribute__((ext_vector_type(2))) float float2;
typedef __attribute__((ext_vector_type(4))) float float4;
typedef __attribute__((ext_vector_type(2))) int int2;
typedef __attribute__((ext_vector_type(4))) int int4;
typedef __attribute__((ext_vector_type(16))) int int16;
int printf(__constant const char* st, ...) __attribute__((format(printf, 1, 2)));
kernel void format_v4f32(float4 arg)
{
#ifdef cl_khr_fp64
- printf("%v4f\n", arg);
+ printf("%v4f\n", arg); // expected-warning{{format specifies type 'double __attribute__((ext_vector_type(4)))' but the argument has type 'float4' (vector of 4 'float' values)}}
// Precision modifier
- printf("%.2v4f\n", arg);
+ printf("%.2v4f\n", arg); // expected-warning{{format specifies type 'double __attribute__((ext_vector_type(4)))' but the argument has type 'float4' (vector of 4 'float' values)}}
#else
// FIXME: These should not warn, and the type should be expected to be float.
printf("%v4f\n", arg); // expected-warning {{double __attribute__((ext_vector_type(4)))' but the argument has type 'float4' (vector of 4 'float' values)}}
// Precision modifier
printf("%.2v4f\n", arg); // expected-warning {{double __attribute__((ext_vector_type(4)))' but the argument has type 'float4' (vector of 4 'float' values)}}
#endif
}
kernel void format_only_v(int arg)
{
printf("%v", arg); // expected-warning {{incomplete format specifier}}
}
kernel void format_missing_num(int arg)
{
printf("%v4", arg); // expected-warning {{incomplete format specifier}}
}
kernel void format_not_num(int arg)
{
printf("%vNd", arg); // expected-warning {{incomplete format specifier}}
printf("%v*d", arg); // expected-warning {{incomplete format specifier}}
}
kernel void format_v16i32(int16 arg)
{
printf("%v16d\n", arg);
}
kernel void format_v4i32_scalar(int arg)
{
printf("%v4d\n", arg); // expected-warning {{format specifies type 'int __attribute__((ext_vector_type(4)))' but the argument has type 'int'}}
}
kernel void format_v4i32_wrong_num_elts_2_to_4(int2 arg)
{
printf("%v4d\n", arg); // expected-warning {{format specifies type 'int __attribute__((ext_vector_type(4)))' but the argument has type 'int2' (vector of 2 'int' values)}}
}
kernel void format_missing_num_elts_format(int4 arg)
{
printf("%vd\n", arg); // expected-warning {{incomplete format specifier}}
}
kernel void format_v4f32_scalar(float arg)
{
printf("%v4f\n", arg); // expected-warning {{format specifies type 'double __attribute__((ext_vector_type(4)))' but the argument has type 'float'}}
}
kernel void format_v4f32_wrong_num_elts(float2 arg)
{
printf("%v4f\n", arg); // expected-warning {{format specifies type 'double __attribute__((ext_vector_type(4)))' but the argument has type 'float2' (vector of 2 'float' values)}}
}
kernel void format_missing_num_elts(float4 arg)
{
printf("%vf\n", arg); // expected-warning {{incomplete format specifier}}
}
kernel void vector_precision_modifier_v4i32_to_v4f32(int4 arg)
{
printf("%.2v4f\n", arg); // expected-warning {{format specifies type 'double __attribute__((ext_vector_type(4)))' but the argument has type 'int4' (vector of 4 'int' values)}}
}
kernel void invalid_Y(int4 arg)
{
printf("%v4Y\n", arg); // expected-warning {{invalid conversion specifier 'Y'}}
}
// FIXME: This should warn
kernel void crash_on_s(int4 arg)
{
printf("%v4s\n", arg);
}
Index: vendor/clang/dist-release_80/unittests/Basic/FileManagerTest.cpp
===================================================================
--- vendor/clang/dist-release_80/unittests/Basic/FileManagerTest.cpp (revision 343795)
+++ vendor/clang/dist-release_80/unittests/Basic/FileManagerTest.cpp (revision 343796)
@@ -1,377 +1,350 @@
//===- unittests/Basic/FileMangerTest.cpp ------------ FileManger tests ---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/FileSystemStatCache.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace clang;
namespace {
// Used to create a fake file system for running the tests with such
// that the tests are not affected by the structure/contents of the
// file system on the machine running the tests.
class FakeStatCache : public FileSystemStatCache {
private:
// Maps a file/directory path to its desired stat result. Anything
// not in this map is considered to not exist in the file system.
llvm::StringMap<FileData, llvm::BumpPtrAllocator> StatCalls;
void InjectFileOrDirectory(const char *Path, ino_t INode, bool IsFile) {
#ifndef _WIN32
SmallString<128> NormalizedPath(Path);
llvm::sys::path::native(NormalizedPath);
Path = NormalizedPath.c_str();
#endif
FileData Data;
Data.Name = Path;
Data.Size = 0;
Data.ModTime = 0;
Data.UniqueID = llvm::sys::fs::UniqueID(1, INode);
Data.IsDirectory = !IsFile;
Data.IsNamedPipe = false;
Data.InPCH = false;
StatCalls[Path] = Data;
}
public:
// Inject a file with the given inode value to the fake file system.
void InjectFile(const char *Path, ino_t INode) {
InjectFileOrDirectory(Path, INode, /*IsFile=*/true);
}
// Inject a directory with the given inode value to the fake file system.
void InjectDirectory(const char *Path, ino_t INode) {
InjectFileOrDirectory(Path, INode, /*IsFile=*/false);
}
// Implement FileSystemStatCache::getStat().
LookupResult getStat(StringRef Path, FileData &Data, bool isFile,
std::unique_ptr<llvm::vfs::File> *F,
llvm::vfs::FileSystem &FS) override {
#ifndef _WIN32
SmallString<128> NormalizedPath(Path);
llvm::sys::path::native(NormalizedPath);
Path = NormalizedPath.c_str();
#endif
if (StatCalls.count(Path) != 0) {
Data = StatCalls[Path];
return CacheExists;
}
return CacheMissing; // This means the file/directory doesn't exist.
}
};
// The test fixture.
class FileManagerTest : public ::testing::Test {
protected:
FileManagerTest() : manager(options) {
}
FileSystemOptions options;
FileManager manager;
};
// When a virtual file is added, its getDir() field is set correctly
// (not NULL, correct name).
TEST_F(FileManagerTest, getVirtualFileSetsTheDirFieldCorrectly) {
const FileEntry *file = manager.getVirtualFile("foo.cpp", 42, 0);
ASSERT_TRUE(file != nullptr);
const DirectoryEntry *dir = file->getDir();
ASSERT_TRUE(dir != nullptr);
EXPECT_EQ(".", dir->getName());
file = manager.getVirtualFile("x/y/z.cpp", 42, 0);
ASSERT_TRUE(file != nullptr);
dir = file->getDir();
ASSERT_TRUE(dir != nullptr);
EXPECT_EQ("x/y", dir->getName());
}
// Before any virtual file is added, no virtual directory exists.
TEST_F(FileManagerTest, NoVirtualDirectoryExistsBeforeAVirtualFileIsAdded) {
// An empty FakeStatCache causes all stat calls made by the
// FileManager to report "file/directory doesn't exist". This
// avoids the possibility of the result of this test being affected
// by what's in the real file system.
manager.setStatCache(llvm::make_unique<FakeStatCache>());
EXPECT_EQ(nullptr, manager.getDirectory("virtual/dir/foo"));
EXPECT_EQ(nullptr, manager.getDirectory("virtual/dir"));
EXPECT_EQ(nullptr, manager.getDirectory("virtual"));
}
// When a virtual file is added, all of its ancestors should be created.
TEST_F(FileManagerTest, getVirtualFileCreatesDirectoryEntriesForAncestors) {
// Fake an empty real file system.
manager.setStatCache(llvm::make_unique<FakeStatCache>());
manager.getVirtualFile("virtual/dir/bar.h", 100, 0);
EXPECT_EQ(nullptr, manager.getDirectory("virtual/dir/foo"));
const DirectoryEntry *dir = manager.getDirectory("virtual/dir");
ASSERT_TRUE(dir != nullptr);
EXPECT_EQ("virtual/dir", dir->getName());
dir = manager.getDirectory("virtual");
ASSERT_TRUE(dir != nullptr);
EXPECT_EQ("virtual", dir->getName());
}
// getFile() returns non-NULL if a real file exists at the given path.
TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingRealFile) {
// Inject fake files into the file system.
auto statCache = llvm::make_unique<FakeStatCache>();
statCache->InjectDirectory("/tmp", 42);
statCache->InjectFile("/tmp/test", 43);
#ifdef _WIN32
const char *DirName = "C:.";
const char *FileName = "C:test";
statCache->InjectDirectory(DirName, 44);
statCache->InjectFile(FileName, 45);
#endif
manager.setStatCache(std::move(statCache));
const FileEntry *file = manager.getFile("/tmp/test");
ASSERT_TRUE(file != nullptr);
ASSERT_TRUE(file->isValid());
EXPECT_EQ("/tmp/test", file->getName());
const DirectoryEntry *dir = file->getDir();
ASSERT_TRUE(dir != nullptr);
EXPECT_EQ("/tmp", dir->getName());
#ifdef _WIN32
file = manager.getFile(FileName);
ASSERT_TRUE(file != NULL);
dir = file->getDir();
ASSERT_TRUE(dir != NULL);
EXPECT_EQ(DirName, dir->getName());
#endif
}
// getFile() returns non-NULL if a virtual file exists at the given path.
TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingVirtualFile) {
// Fake an empty real file system.
manager.setStatCache(llvm::make_unique<FakeStatCache>());
manager.getVirtualFile("virtual/dir/bar.h", 100, 0);
const FileEntry *file = manager.getFile("virtual/dir/bar.h");
ASSERT_TRUE(file != nullptr);
ASSERT_TRUE(file->isValid());
EXPECT_EQ("virtual/dir/bar.h", file->getName());
const DirectoryEntry *dir = file->getDir();
ASSERT_TRUE(dir != nullptr);
EXPECT_EQ("virtual/dir", dir->getName());
}
// getFile() returns different FileEntries for different paths when
// there's no aliasing.
TEST_F(FileManagerTest, getFileReturnsDifferentFileEntriesForDifferentFiles) {
// Inject two fake files into the file system. Different inodes
// mean the files are not symlinked together.
auto statCache = llvm::make_unique<FakeStatCache>();
statCache->InjectDirectory(".", 41);
statCache->InjectFile("foo.cpp", 42);
statCache->InjectFile("bar.cpp", 43);
manager.setStatCache(std::move(statCache));
const FileEntry *fileFoo = manager.getFile("foo.cpp");
const FileEntry *fileBar = manager.getFile("bar.cpp");
ASSERT_TRUE(fileFoo != nullptr);
ASSERT_TRUE(fileFoo->isValid());
ASSERT_TRUE(fileBar != nullptr);
ASSERT_TRUE(fileBar->isValid());
EXPECT_NE(fileFoo, fileBar);
}
// getFile() returns NULL if neither a real file nor a virtual file
// exists at the given path.
TEST_F(FileManagerTest, getFileReturnsNULLForNonexistentFile) {
// Inject a fake foo.cpp into the file system.
auto statCache = llvm::make_unique<FakeStatCache>();
statCache->InjectDirectory(".", 41);
statCache->InjectFile("foo.cpp", 42);
manager.setStatCache(std::move(statCache));
// Create a virtual bar.cpp file.
manager.getVirtualFile("bar.cpp", 200, 0);
const FileEntry *file = manager.getFile("xyz.txt");
EXPECT_EQ(nullptr, file);
}
-// When calling getFile(OpenFile=false); getFile(OpenFile=true) the file is
-// opened for the second call.
-TEST_F(FileManagerTest, getFileDefersOpen) {
- llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS(
- new llvm::vfs::InMemoryFileSystem());
- FS->addFile("/tmp/test", 0, llvm::MemoryBuffer::getMemBufferCopy("test"));
- FS->addFile("/tmp/testv", 0, llvm::MemoryBuffer::getMemBufferCopy("testv"));
- FileManager manager(options, FS);
-
- const FileEntry *file = manager.getFile("/tmp/test", /*OpenFile=*/false);
- ASSERT_TRUE(file != nullptr);
- ASSERT_TRUE(file->isValid());
- // "real path name" reveals whether the file was actually opened.
- EXPECT_FALSE(file->isOpenForTests());
-
- file = manager.getFile("/tmp/test", /*OpenFile=*/true);
- ASSERT_TRUE(file != nullptr);
- ASSERT_TRUE(file->isValid());
- EXPECT_TRUE(file->isOpenForTests());
-
- // However we should never try to open a file previously opened as virtual.
- ASSERT_TRUE(manager.getVirtualFile("/tmp/testv", 5, 0));
- ASSERT_TRUE(manager.getFile("/tmp/testv", /*OpenFile=*/false));
- file = manager.getFile("/tmp/testv", /*OpenFile=*/true);
- EXPECT_FALSE(file->isOpenForTests());
-}
-
// The following tests apply to Unix-like system only.
#ifndef _WIN32
// getFile() returns the same FileEntry for real files that are aliases.
TEST_F(FileManagerTest, getFileReturnsSameFileEntryForAliasedRealFiles) {
// Inject two real files with the same inode.
auto statCache = llvm::make_unique<FakeStatCache>();
statCache->InjectDirectory("abc", 41);
statCache->InjectFile("abc/foo.cpp", 42);
statCache->InjectFile("abc/bar.cpp", 42);
manager.setStatCache(std::move(statCache));
EXPECT_EQ(manager.getFile("abc/foo.cpp"), manager.getFile("abc/bar.cpp"));
}
// getFile() returns the same FileEntry for virtual files that have
// corresponding real files that are aliases.
TEST_F(FileManagerTest, getFileReturnsSameFileEntryForAliasedVirtualFiles) {
// Inject two real files with the same inode.
auto statCache = llvm::make_unique<FakeStatCache>();
statCache->InjectDirectory("abc", 41);
statCache->InjectFile("abc/foo.cpp", 42);
statCache->InjectFile("abc/bar.cpp", 42);
manager.setStatCache(std::move(statCache));
ASSERT_TRUE(manager.getVirtualFile("abc/foo.cpp", 100, 0)->isValid());
ASSERT_TRUE(manager.getVirtualFile("abc/bar.cpp", 200, 0)->isValid());
EXPECT_EQ(manager.getFile("abc/foo.cpp"), manager.getFile("abc/bar.cpp"));
}
// getFile() Should return the same entry as getVirtualFile if the file actually
// is a virtual file, even if the name is not exactly the same (but is after
// normalisation done by the file system, like on Windows). This can be checked
// here by checking the size.
TEST_F(FileManagerTest, getVirtualFileWithDifferentName) {
// Inject fake files into the file system.
auto statCache = llvm::make_unique<FakeStatCache>();
statCache->InjectDirectory("c:\\tmp", 42);
statCache->InjectFile("c:\\tmp\\test", 43);
manager.setStatCache(std::move(statCache));
// Inject the virtual file:
const FileEntry *file1 = manager.getVirtualFile("c:\\tmp\\test", 123, 1);
ASSERT_TRUE(file1 != nullptr);
ASSERT_TRUE(file1->isValid());
EXPECT_EQ(43U, file1->getUniqueID().getFile());
EXPECT_EQ(123, file1->getSize());
// Lookup the virtual file with a different name:
const FileEntry *file2 = manager.getFile("c:/tmp/test", 100, 1);
ASSERT_TRUE(file2 != nullptr);
ASSERT_TRUE(file2->isValid());
// Check that it's the same UFE:
EXPECT_EQ(file1, file2);
EXPECT_EQ(43U, file2->getUniqueID().getFile());
// Check that the contents of the UFE are not overwritten by the entry in the
// filesystem:
EXPECT_EQ(123, file2->getSize());
}
#endif // !_WIN32
TEST_F(FileManagerTest, makeAbsoluteUsesVFS) {
SmallString<64> CustomWorkingDir;
#ifdef _WIN32
CustomWorkingDir = "C:";
#else
CustomWorkingDir = "/";
#endif
llvm::sys::path::append(CustomWorkingDir, "some", "weird", "path");
auto FS = IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>(
new llvm::vfs::InMemoryFileSystem);
// setCurrentworkingdirectory must finish without error.
ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir));
FileSystemOptions Opts;
FileManager Manager(Opts, FS);
SmallString<64> Path("a/foo.cpp");
SmallString<64> ExpectedResult(CustomWorkingDir);
llvm::sys::path::append(ExpectedResult, Path);
ASSERT_TRUE(Manager.makeAbsolutePath(Path));
EXPECT_EQ(Path, ExpectedResult);
}
// getVirtualFile should always fill the real path.
TEST_F(FileManagerTest, getVirtualFileFillsRealPathName) {
SmallString<64> CustomWorkingDir;
#ifdef _WIN32
CustomWorkingDir = "C:/";
#else
CustomWorkingDir = "/";
#endif
auto FS = IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>(
new llvm::vfs::InMemoryFileSystem);
// setCurrentworkingdirectory must finish without error.
ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir));
FileSystemOptions Opts;
FileManager Manager(Opts, FS);
// Inject fake files into the file system.
auto statCache = llvm::make_unique<FakeStatCache>();
statCache->InjectDirectory("/tmp", 42);
statCache->InjectFile("/tmp/test", 43);
Manager.setStatCache(std::move(statCache));
// Check for real path.
const FileEntry *file = Manager.getVirtualFile("/tmp/test", 123, 1);
ASSERT_TRUE(file != nullptr);
ASSERT_TRUE(file->isValid());
SmallString<64> ExpectedResult = CustomWorkingDir;
llvm::sys::path::append(ExpectedResult, "tmp", "test");
EXPECT_EQ(file->tryGetRealPathName(), ExpectedResult);
}
} // anonymous namespace
Index: vendor/clang/dist-release_80/unittests/Tooling/ToolingTest.cpp
===================================================================
--- vendor/clang/dist-release_80/unittests/Tooling/ToolingTest.cpp (revision 343795)
+++ vendor/clang/dist-release_80/unittests/Tooling/ToolingTest.cpp (revision 343796)
@@ -1,611 +1,642 @@
//===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "gtest/gtest.h"
#include <algorithm>
#include <string>
namespace clang {
namespace tooling {
namespace {
/// Takes an ast consumer and returns it from CreateASTConsumer. This only
/// works with single translation unit compilations.
class TestAction : public clang::ASTFrontendAction {
public:
/// Takes ownership of TestConsumer.
explicit TestAction(std::unique_ptr<clang::ASTConsumer> TestConsumer)
: TestConsumer(std::move(TestConsumer)) {}
protected:
std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance &compiler,
StringRef dummy) override {
/// TestConsumer will be deleted by the framework calling us.
return std::move(TestConsumer);
}
private:
std::unique_ptr<clang::ASTConsumer> TestConsumer;
};
class FindTopLevelDeclConsumer : public clang::ASTConsumer {
public:
explicit FindTopLevelDeclConsumer(bool *FoundTopLevelDecl)
: FoundTopLevelDecl(FoundTopLevelDecl) {}
bool HandleTopLevelDecl(clang::DeclGroupRef DeclGroup) override {
*FoundTopLevelDecl = true;
return true;
}
private:
bool * const FoundTopLevelDecl;
};
} // end namespace
TEST(runToolOnCode, FindsNoTopLevelDeclOnEmptyCode) {
bool FoundTopLevelDecl = false;
EXPECT_TRUE(
runToolOnCode(new TestAction(llvm::make_unique<FindTopLevelDeclConsumer>(
&FoundTopLevelDecl)),
""));
EXPECT_FALSE(FoundTopLevelDecl);
}
namespace {
class FindClassDeclXConsumer : public clang::ASTConsumer {
public:
FindClassDeclXConsumer(bool *FoundClassDeclX)
: FoundClassDeclX(FoundClassDeclX) {}
bool HandleTopLevelDecl(clang::DeclGroupRef GroupRef) override {
if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(
*GroupRef.begin())) {
if (Record->getName() == "X") {
*FoundClassDeclX = true;
}
}
return true;
}
private:
bool *FoundClassDeclX;
};
bool FindClassDeclX(ASTUnit *AST) {
for (std::vector<Decl *>::iterator i = AST->top_level_begin(),
e = AST->top_level_end();
i != e; ++i) {
if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(*i)) {
if (Record->getName() == "X") {
return true;
}
}
}
return false;
}
} // end namespace
TEST(runToolOnCode, FindsClassDecl) {
bool FoundClassDeclX = false;
EXPECT_TRUE(
runToolOnCode(new TestAction(llvm::make_unique<FindClassDeclXConsumer>(
&FoundClassDeclX)),
"class X;"));
EXPECT_TRUE(FoundClassDeclX);
FoundClassDeclX = false;
EXPECT_TRUE(
runToolOnCode(new TestAction(llvm::make_unique<FindClassDeclXConsumer>(
&FoundClassDeclX)),
"class Y;"));
EXPECT_FALSE(FoundClassDeclX);
}
TEST(buildASTFromCode, FindsClassDecl) {
std::unique_ptr<ASTUnit> AST = buildASTFromCode("class X;");
ASSERT_TRUE(AST.get());
EXPECT_TRUE(FindClassDeclX(AST.get()));
AST = buildASTFromCode("class Y;");
ASSERT_TRUE(AST.get());
EXPECT_FALSE(FindClassDeclX(AST.get()));
}
TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromType) {
std::unique_ptr<FrontendActionFactory> Factory(
newFrontendActionFactory<SyntaxOnlyAction>());
std::unique_ptr<FrontendAction> Action(Factory->create());
EXPECT_TRUE(Action.get() != nullptr);
}
struct IndependentFrontendActionCreator {
std::unique_ptr<ASTConsumer> newASTConsumer() {
return llvm::make_unique<FindTopLevelDeclConsumer>(nullptr);
}
};
TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromFactoryType) {
IndependentFrontendActionCreator Creator;
std::unique_ptr<FrontendActionFactory> Factory(
newFrontendActionFactory(&Creator));
std::unique_ptr<FrontendAction> Action(Factory->create());
EXPECT_TRUE(Action.get() != nullptr);
}
TEST(ToolInvocation, TestMapVirtualFile) {
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem(
new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
new llvm::vfs::InMemoryFileSystem);
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
llvm::IntrusiveRefCntPtr<FileManager> Files(
new FileManager(FileSystemOptions(), OverlayFileSystem));
std::vector<std::string> Args;
Args.push_back("tool-executable");
Args.push_back("-Idef");
Args.push_back("-fsyntax-only");
Args.push_back("test.cpp");
clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction,
Files.get());
InMemoryFileSystem->addFile(
"test.cpp", 0, llvm::MemoryBuffer::getMemBuffer("#include <abc>\n"));
InMemoryFileSystem->addFile("def/abc", 0,
llvm::MemoryBuffer::getMemBuffer("\n"));
EXPECT_TRUE(Invocation.run());
}
TEST(ToolInvocation, TestVirtualModulesCompilation) {
// FIXME: Currently, this only tests that we don't exit with an error if a
// mapped module.map is found on the include path. In the future, expand this
// test to run a full modules enabled compilation, so we make sure we can
// rerun modules compilations with a virtual file system.
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem(
new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
new llvm::vfs::InMemoryFileSystem);
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
llvm::IntrusiveRefCntPtr<FileManager> Files(
new FileManager(FileSystemOptions(), OverlayFileSystem));
std::vector<std::string> Args;
Args.push_back("tool-executable");
Args.push_back("-Idef");
Args.push_back("-fsyntax-only");
Args.push_back("test.cpp");
clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction,
Files.get());
InMemoryFileSystem->addFile(
"test.cpp", 0, llvm::MemoryBuffer::getMemBuffer("#include <abc>\n"));
InMemoryFileSystem->addFile("def/abc", 0,
llvm::MemoryBuffer::getMemBuffer("\n"));
// Add a module.map file in the include directory of our header, so we trigger
// the module.map header search logic.
InMemoryFileSystem->addFile("def/module.map", 0,
llvm::MemoryBuffer::getMemBuffer("\n"));
EXPECT_TRUE(Invocation.run());
}
struct VerifyEndCallback : public SourceFileCallbacks {
VerifyEndCallback() : BeginCalled(0), EndCalled(0), Matched(false) {}
bool handleBeginSource(CompilerInstance &CI) override {
++BeginCalled;
return true;
}
void handleEndSource() override { ++EndCalled; }
std::unique_ptr<ASTConsumer> newASTConsumer() {
return llvm::make_unique<FindTopLevelDeclConsumer>(&Matched);
}
unsigned BeginCalled;
unsigned EndCalled;
bool Matched;
};
#if !defined(_WIN32)
TEST(newFrontendActionFactory, InjectsSourceFileCallbacks) {
VerifyEndCallback EndCallback;
FixedCompilationDatabase Compilations("/", std::vector<std::string>());
std::vector<std::string> Sources;
Sources.push_back("/a.cc");
Sources.push_back("/b.cc");
ClangTool Tool(Compilations, Sources);
Tool.mapVirtualFile("/a.cc", "void a() {}");
Tool.mapVirtualFile("/b.cc", "void b() {}");
std::unique_ptr<FrontendActionFactory> Action(
newFrontendActionFactory(&EndCallback, &EndCallback));
Tool.run(Action.get());
EXPECT_TRUE(EndCallback.Matched);
EXPECT_EQ(2u, EndCallback.BeginCalled);
EXPECT_EQ(2u, EndCallback.EndCalled);
}
#endif
struct SkipBodyConsumer : public clang::ASTConsumer {
/// Skip the 'skipMe' function.
bool shouldSkipFunctionBody(Decl *D) override {
NamedDecl *F = dyn_cast<NamedDecl>(D);
return F && F->getNameAsString() == "skipMe";
}
};
struct SkipBodyAction : public clang::ASTFrontendAction {
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
StringRef) override {
Compiler.getFrontendOpts().SkipFunctionBodies = true;
return llvm::make_unique<SkipBodyConsumer>();
}
};
TEST(runToolOnCode, TestSkipFunctionBody) {
std::vector<std::string> Args = {"-std=c++11"};
std::vector<std::string> Args2 = {"-fno-delayed-template-parsing"};
EXPECT_TRUE(runToolOnCode(new SkipBodyAction,
"int skipMe() { an_error_here }"));
EXPECT_FALSE(runToolOnCode(new SkipBodyAction,
"int skipMeNot() { an_error_here }"));
// Test constructors with initializers
EXPECT_TRUE(runToolOnCodeWithArgs(
new SkipBodyAction,
"struct skipMe { skipMe() : an_error() { more error } };", Args));
EXPECT_TRUE(runToolOnCodeWithArgs(
new SkipBodyAction, "struct skipMe { skipMe(); };"
"skipMe::skipMe() : an_error([](){;}) { more error }",
Args));
EXPECT_TRUE(runToolOnCodeWithArgs(
new SkipBodyAction, "struct skipMe { skipMe(); };"
"skipMe::skipMe() : an_error{[](){;}} { more error }",
Args));
EXPECT_TRUE(runToolOnCodeWithArgs(
new SkipBodyAction,
"struct skipMe { skipMe(); };"
"skipMe::skipMe() : a<b<c>(e)>>(), f{}, g() { error }",
Args));
EXPECT_TRUE(runToolOnCodeWithArgs(
new SkipBodyAction, "struct skipMe { skipMe() : bases()... { error } };",
Args));
EXPECT_FALSE(runToolOnCodeWithArgs(
new SkipBodyAction, "struct skipMeNot { skipMeNot() : an_error() { } };",
Args));
EXPECT_FALSE(runToolOnCodeWithArgs(new SkipBodyAction,
"struct skipMeNot { skipMeNot(); };"
"skipMeNot::skipMeNot() : an_error() { }",
Args));
// Try/catch
EXPECT_TRUE(runToolOnCode(
new SkipBodyAction,
"void skipMe() try { an_error() } catch(error) { error };"));
EXPECT_TRUE(runToolOnCode(
new SkipBodyAction,
"struct S { void skipMe() try { an_error() } catch(error) { error } };"));
EXPECT_TRUE(
runToolOnCode(new SkipBodyAction,
"void skipMe() try { an_error() } catch(error) { error; }"
"catch(error) { error } catch (error) { }"));
EXPECT_FALSE(runToolOnCode(
new SkipBodyAction,
"void skipMe() try something;")); // don't crash while parsing
// Template
EXPECT_TRUE(runToolOnCode(
new SkipBodyAction, "template<typename T> int skipMe() { an_error_here }"
"int x = skipMe<int>();"));
EXPECT_FALSE(runToolOnCodeWithArgs(
new SkipBodyAction,
"template<typename T> int skipMeNot() { an_error_here }", Args2));
}
TEST(runToolOnCodeWithArgs, TestNoDepFile) {
llvm::SmallString<32> DepFilePath;
ASSERT_FALSE(llvm::sys::fs::getPotentiallyUniqueTempFileName("depfile", "d",
DepFilePath));
std::vector<std::string> Args;
Args.push_back("-MMD");
Args.push_back("-MT");
Args.push_back(DepFilePath.str());
Args.push_back("-MF");
Args.push_back(DepFilePath.str());
EXPECT_TRUE(runToolOnCodeWithArgs(new SkipBodyAction, "", Args));
EXPECT_FALSE(llvm::sys::fs::exists(DepFilePath.str()));
EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str()));
}
struct CheckColoredDiagnosticsAction : public clang::ASTFrontendAction {
CheckColoredDiagnosticsAction(bool ShouldShowColor)
: ShouldShowColor(ShouldShowColor) {}
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
StringRef) override {
if (Compiler.getDiagnosticOpts().ShowColors != ShouldShowColor)
Compiler.getDiagnostics().Report(
Compiler.getDiagnostics().getCustomDiagID(
DiagnosticsEngine::Fatal,
"getDiagnosticOpts().ShowColors != ShouldShowColor"));
return llvm::make_unique<ASTConsumer>();
}
private:
bool ShouldShowColor = true;
};
TEST(runToolOnCodeWithArgs, DiagnosticsColor) {
EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "",
{"-fcolor-diagnostics"}));
EXPECT_TRUE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false),
"", {"-fno-color-diagnostics"}));
EXPECT_TRUE(
runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(true), "",
{"-fno-color-diagnostics", "-fcolor-diagnostics"}));
EXPECT_TRUE(
runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false), "",
{"-fcolor-diagnostics", "-fno-color-diagnostics"}));
EXPECT_TRUE(runToolOnCodeWithArgs(
new CheckColoredDiagnosticsAction(true), "",
{"-fno-color-diagnostics", "-fdiagnostics-color=always"}));
// Check that this test would fail if ShowColors is not what it should.
EXPECT_FALSE(runToolOnCodeWithArgs(new CheckColoredDiagnosticsAction(false),
"", {"-fcolor-diagnostics"}));
}
TEST(ClangToolTest, ArgumentAdjusters) {
FixedCompilationDatabase Compilations("/", std::vector<std::string>());
ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
Tool.mapVirtualFile("/a.cc", "void a() {}");
std::unique_ptr<FrontendActionFactory> Action(
newFrontendActionFactory<SyntaxOnlyAction>());
bool Found = false;
bool Ran = false;
ArgumentsAdjuster CheckSyntaxOnlyAdjuster =
[&Found, &Ran](const CommandLineArguments &Args, StringRef /*unused*/) {
Ran = true;
if (std::find(Args.begin(), Args.end(), "-fsyntax-only") != Args.end())
Found = true;
return Args;
};
Tool.appendArgumentsAdjuster(CheckSyntaxOnlyAdjuster);
Tool.run(Action.get());
EXPECT_TRUE(Ran);
EXPECT_TRUE(Found);
Ran = Found = false;
Tool.clearArgumentsAdjusters();
Tool.appendArgumentsAdjuster(CheckSyntaxOnlyAdjuster);
Tool.appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster());
Tool.run(Action.get());
EXPECT_TRUE(Ran);
EXPECT_FALSE(Found);
}
TEST(ClangToolTest, BaseVirtualFileSystemUsage) {
FixedCompilationDatabase Compilations("/", std::vector<std::string>());
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem(
new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
new llvm::vfs::InMemoryFileSystem);
OverlayFileSystem->pushOverlay(InMemoryFileSystem);
InMemoryFileSystem->addFile(
"a.cpp", 0, llvm::MemoryBuffer::getMemBuffer("int main() {}"));
ClangTool Tool(Compilations, std::vector<std::string>(1, "a.cpp"),
std::make_shared<PCHContainerOperations>(), OverlayFileSystem);
std::unique_ptr<FrontendActionFactory> Action(
newFrontendActionFactory<SyntaxOnlyAction>());
EXPECT_EQ(0, Tool.run(Action.get()));
}
// Check getClangStripDependencyFileAdjuster doesn't strip args after -MD/-MMD.
TEST(ClangToolTest, StripDependencyFileAdjuster) {
FixedCompilationDatabase Compilations("/", {"-MD", "-c", "-MMD", "-w"});
ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
Tool.mapVirtualFile("/a.cc", "void a() {}");
std::unique_ptr<FrontendActionFactory> Action(
newFrontendActionFactory<SyntaxOnlyAction>());
CommandLineArguments FinalArgs;
ArgumentsAdjuster CheckFlagsAdjuster =
[&FinalArgs](const CommandLineArguments &Args, StringRef /*unused*/) {
FinalArgs = Args;
return Args;
};
Tool.clearArgumentsAdjusters();
Tool.appendArgumentsAdjuster(getClangStripDependencyFileAdjuster());
Tool.appendArgumentsAdjuster(CheckFlagsAdjuster);
Tool.run(Action.get());
auto HasFlag = [&FinalArgs](const std::string &Flag) {
return std::find(FinalArgs.begin(), FinalArgs.end(), Flag) !=
FinalArgs.end();
};
EXPECT_FALSE(HasFlag("-MD"));
EXPECT_FALSE(HasFlag("-MMD"));
EXPECT_TRUE(HasFlag("-c"));
EXPECT_TRUE(HasFlag("-w"));
}
+// Check getClangStripPluginsAdjuster strips plugin related args.
+TEST(ClangToolTest, StripPluginsAdjuster) {
+ FixedCompilationDatabase Compilations(
+ "/", {"-Xclang", "-add-plugin", "-Xclang", "random-plugin"});
+
+ ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
+ Tool.mapVirtualFile("/a.cc", "void a() {}");
+
+ std::unique_ptr<FrontendActionFactory> Action(
+ newFrontendActionFactory<SyntaxOnlyAction>());
+
+ CommandLineArguments FinalArgs;
+ ArgumentsAdjuster CheckFlagsAdjuster =
+ [&FinalArgs](const CommandLineArguments &Args, StringRef /*unused*/) {
+ FinalArgs = Args;
+ return Args;
+ };
+ Tool.clearArgumentsAdjusters();
+ Tool.appendArgumentsAdjuster(getStripPluginsAdjuster());
+ Tool.appendArgumentsAdjuster(CheckFlagsAdjuster);
+ Tool.run(Action.get());
+
+ auto HasFlag = [&FinalArgs](const std::string &Flag) {
+ return std::find(FinalArgs.begin(), FinalArgs.end(), Flag) !=
+ FinalArgs.end();
+ };
+ EXPECT_FALSE(HasFlag("-Xclang"));
+ EXPECT_FALSE(HasFlag("-add-plugin"));
+ EXPECT_FALSE(HasFlag("-random-plugin"));
+}
+
namespace {
/// Find a target name such that looking for it in TargetRegistry by that name
/// returns the same target. We expect that there is at least one target
/// configured with this property.
std::string getAnyTarget() {
llvm::InitializeAllTargets();
for (const auto &Target : llvm::TargetRegistry::targets()) {
std::string Error;
StringRef TargetName(Target.getName());
if (TargetName == "x86-64")
TargetName = "x86_64";
if (llvm::TargetRegistry::lookupTarget(TargetName, Error) == &Target) {
return TargetName;
}
}
return "";
}
}
TEST(addTargetAndModeForProgramName, AddsTargetAndMode) {
std::string Target = getAnyTarget();
ASSERT_FALSE(Target.empty());
std::vector<std::string> Args = {"clang", "-foo"};
addTargetAndModeForProgramName(Args, "");
EXPECT_EQ((std::vector<std::string>{"clang", "-foo"}), Args);
addTargetAndModeForProgramName(Args, Target + "-g++");
EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target,
"--driver-mode=g++", "-foo"}),
Args);
}
TEST(addTargetAndModeForProgramName, PathIgnored) {
std::string Target = getAnyTarget();
ASSERT_FALSE(Target.empty());
SmallString<32> ToolPath;
llvm::sys::path::append(ToolPath, "foo", "bar", Target + "-g++");
std::vector<std::string> Args = {"clang", "-foo"};
addTargetAndModeForProgramName(Args, ToolPath);
EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target,
"--driver-mode=g++", "-foo"}),
Args);
}
TEST(addTargetAndModeForProgramName, IgnoresExistingTarget) {
std::string Target = getAnyTarget();
ASSERT_FALSE(Target.empty());
std::vector<std::string> Args = {"clang", "-foo", "-target", "something"};
addTargetAndModeForProgramName(Args, Target + "-g++");
EXPECT_EQ((std::vector<std::string>{"clang", "--driver-mode=g++", "-foo",
"-target", "something"}),
Args);
std::vector<std::string> ArgsAlt = {"clang", "-foo", "-target=something"};
addTargetAndModeForProgramName(ArgsAlt, Target + "-g++");
EXPECT_EQ((std::vector<std::string>{"clang", "--driver-mode=g++", "-foo",
"-target=something"}),
ArgsAlt);
}
TEST(addTargetAndModeForProgramName, IgnoresExistingMode) {
std::string Target = getAnyTarget();
ASSERT_FALSE(Target.empty());
std::vector<std::string> Args = {"clang", "-foo", "--driver-mode=abc"};
addTargetAndModeForProgramName(Args, Target + "-g++");
EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target, "-foo",
"--driver-mode=abc"}),
Args);
std::vector<std::string> ArgsAlt = {"clang", "-foo", "--driver-mode", "abc"};
addTargetAndModeForProgramName(ArgsAlt, Target + "-g++");
EXPECT_EQ((std::vector<std::string>{"clang", "-target", Target, "-foo",
"--driver-mode", "abc"}),
ArgsAlt);
}
#ifndef _WIN32
TEST(ClangToolTest, BuildASTs) {
FixedCompilationDatabase Compilations("/", std::vector<std::string>());
std::vector<std::string> Sources;
Sources.push_back("/a.cc");
Sources.push_back("/b.cc");
ClangTool Tool(Compilations, Sources);
Tool.mapVirtualFile("/a.cc", "void a() {}");
Tool.mapVirtualFile("/b.cc", "void b() {}");
std::vector<std::unique_ptr<ASTUnit>> ASTs;
EXPECT_EQ(0, Tool.buildASTs(ASTs));
EXPECT_EQ(2u, ASTs.size());
}
struct TestDiagnosticConsumer : public DiagnosticConsumer {
TestDiagnosticConsumer() : NumDiagnosticsSeen(0) {}
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) override {
++NumDiagnosticsSeen;
}
unsigned NumDiagnosticsSeen;
};
TEST(ClangToolTest, InjectDiagnosticConsumer) {
FixedCompilationDatabase Compilations("/", std::vector<std::string>());
ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
Tool.mapVirtualFile("/a.cc", "int x = undeclared;");
TestDiagnosticConsumer Consumer;
Tool.setDiagnosticConsumer(&Consumer);
std::unique_ptr<FrontendActionFactory> Action(
newFrontendActionFactory<SyntaxOnlyAction>());
Tool.run(Action.get());
EXPECT_EQ(1u, Consumer.NumDiagnosticsSeen);
}
TEST(ClangToolTest, InjectDiagnosticConsumerInBuildASTs) {
FixedCompilationDatabase Compilations("/", std::vector<std::string>());
ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
Tool.mapVirtualFile("/a.cc", "int x = undeclared;");
TestDiagnosticConsumer Consumer;
Tool.setDiagnosticConsumer(&Consumer);
std::vector<std::unique_ptr<ASTUnit>> ASTs;
Tool.buildASTs(ASTs);
EXPECT_EQ(1u, ASTs.size());
EXPECT_EQ(1u, Consumer.NumDiagnosticsSeen);
}
#endif
TEST(runToolOnCode, TestResetDiagnostics) {
// This is a tool that resets the diagnostic during the compilation.
struct ResetDiagnosticAction : public clang::ASTFrontendAction {
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &Compiler,
StringRef) override {
struct Consumer : public clang::ASTConsumer {
bool HandleTopLevelDecl(clang::DeclGroupRef D) override {
auto &Diags = (*D.begin())->getASTContext().getDiagnostics();
// Ignore any error
Diags.Reset();
// Disable warnings because computing the CFG might crash.
Diags.setIgnoreAllWarnings(true);
return true;
}
};
return llvm::make_unique<Consumer>();
}
};
// Should not crash
EXPECT_FALSE(
runToolOnCode(new ResetDiagnosticAction,
"struct Foo { Foo(int); ~Foo(); struct Fwd _fwd; };"
"void func() { long x; Foo f(x); }"));
}
} // end namespace tooling
} // end namespace clang

File Metadata

Mime Type
application/octet-stream
Expires
Tue, Jun 4, 10:06 AM (1 d, 23 h)
Storage Engine
chunks
Storage Format
Chunks
Storage Handle
AV7yv4BBpX.T
Default Alt Text
(4 MB)

Event Timeline