diff --git a/.ci/generate_test_report.py b/.ci/generate_test_report.py
index ff601a0cde106..6f2137e7803bb 100644
--- a/.ci/generate_test_report.py
+++ b/.ci/generate_test_report.py
@@ -19,12 +19,13 @@ def junit_from_xml(xml):
class TestReports(unittest.TestCase):
def test_title_only(self):
- self.assertEqual(_generate_report("Foo", []), ("", "success"))
+ self.assertEqual(_generate_report("Foo", 0, []), ("", "success"))
def test_no_tests_in_testsuite(self):
self.assertEqual(
_generate_report(
"Foo",
+ 1,
[
junit_from_xml(
dedent(
@@ -45,6 +46,7 @@ def test_no_failures(self):
self.assertEqual(
_generate_report(
"Foo",
+ 0,
[
junit_from_xml(
dedent(
@@ -70,10 +72,51 @@ def test_no_failures(self):
),
)
+ def test_no_failures_build_failed(self):
+ self.assertEqual(
+ _generate_report(
+ "Foo",
+ 1,
+ [
+ junit_from_xml(
+ dedent(
+ """\
+
+
+
+
+
+ """
+ )
+ )
+ ],
+ buildkite_info={
+ "BUILDKITE_ORGANIZATION_SLUG": "organization_slug",
+ "BUILDKITE_PIPELINE_SLUG": "pipeline_slug",
+ "BUILDKITE_BUILD_NUMBER": "build_number",
+ "BUILDKITE_JOB_ID": "job_id",
+ },
+ ),
+ (
+ dedent(
+ """\
+ # Foo
+
+ * 1 test passed
+
+ All tests passed but another part of the build **failed**.
+
+ [Download](https://buildkite.com/organizations/organization_slug/pipelines/pipeline_slug/builds/build_number/jobs/job_id/download.txt) the build's log file to see the details."""
+ ),
+ "error",
+ ),
+ )
+
def test_report_single_file_single_testsuite(self):
self.assertEqual(
_generate_report(
"Foo",
+ 1,
[
junit_from_xml(
dedent(
@@ -166,6 +209,7 @@ def test_report_single_file_multiple_testsuites(self):
self.assertEqual(
_generate_report(
"ABC and DEF",
+ 1,
[
junit_from_xml(
dedent(
@@ -198,6 +242,7 @@ def test_report_multiple_files_multiple_testsuites(self):
self.assertEqual(
_generate_report(
"ABC and DEF",
+ 1,
[
junit_from_xml(
dedent(
@@ -238,6 +283,7 @@ def test_report_dont_list_failures(self):
self.assertEqual(
_generate_report(
"Foo",
+ 1,
[
junit_from_xml(
dedent(
@@ -272,6 +318,7 @@ def test_report_dont_list_failures_link_to_log(self):
self.assertEqual(
_generate_report(
"Foo",
+ 1,
[
junit_from_xml(
dedent(
@@ -312,6 +359,7 @@ def test_report_size_limit(self):
self.assertEqual(
_generate_report(
"Foo",
+ 1,
[
junit_from_xml(
dedent(
@@ -351,12 +399,18 @@ def test_report_size_limit(self):
# and output will not be.
def _generate_report(
title,
+ return_code,
junit_objects,
size_limit=1024 * 1024,
list_failures=True,
buildkite_info=None,
):
if not junit_objects:
+ # Note that we do not post an empty report, therefore we can ignore a
+ # non-zero return code in situations like this.
+ #
+ # If we were going to post a report, then yes, it would be misleading
+ # to say we succeeded when the final return code was non-zero.
return ("", "success")
failures = {}
@@ -385,7 +439,11 @@ def _generate_report(
if not tests_run:
return ("", None)
- style = "error" if tests_failed else "success"
+ style = "success"
+ # Either tests failed, or all tests passed but something failed to build.
+ if tests_failed or return_code != 0:
+ style = "error"
+
report = [f"# {title}", ""]
tests_passed = tests_run - tests_skipped - tests_failed
@@ -400,17 +458,17 @@ def plural(num_tests):
if tests_failed:
report.append(f"* {tests_failed} {plural(tests_failed)} failed")
- if not list_failures:
- if buildkite_info is not None:
- log_url = (
- "https://buildkite.com/organizations/{BUILDKITE_ORGANIZATION_SLUG}/"
- "pipelines/{BUILDKITE_PIPELINE_SLUG}/builds/{BUILDKITE_BUILD_NUMBER}/"
- "jobs/{BUILDKITE_JOB_ID}/download.txt".format(**buildkite_info)
- )
- download_text = f"[Download]({log_url})"
- else:
- download_text = "Download"
+ if buildkite_info is not None:
+ log_url = (
+ "https://buildkite.com/organizations/{BUILDKITE_ORGANIZATION_SLUG}/"
+ "pipelines/{BUILDKITE_PIPELINE_SLUG}/builds/{BUILDKITE_BUILD_NUMBER}/"
+ "jobs/{BUILDKITE_JOB_ID}/download.txt".format(**buildkite_info)
+ )
+ download_text = f"[Download]({log_url})"
+ else:
+ download_text = "Download"
+ if not list_failures:
report.extend(
[
"",
@@ -435,11 +493,23 @@ def plural(num_tests):
"",
]
)
+ elif return_code != 0:
+ # No tests failed but the build was in a failed state. Bring this to the user's
+ # attention.
+ report.extend(
+ [
+ "",
+ "All tests passed but another part of the build **failed**.",
+ "",
+ f"{download_text} the build's log file to see the details.",
+ ]
+ )
report = "\n".join(report)
if len(report.encode("utf-8")) > size_limit:
return _generate_report(
title,
+ return_code,
junit_objects,
size_limit,
list_failures=False,
@@ -449,9 +519,10 @@ def plural(num_tests):
return report, style
-def generate_report(title, junit_files, buildkite_info):
+def generate_report(title, return_code, junit_files, buildkite_info):
return _generate_report(
title,
+ return_code,
[JUnitXml.fromfile(p) for p in junit_files],
buildkite_info=buildkite_info,
)
@@ -463,6 +534,7 @@ def generate_report(title, junit_files, buildkite_info):
"title", help="Title of the test report, without Markdown formatting."
)
parser.add_argument("context", help="Annotation context to write to.")
+ parser.add_argument("return_code", help="The build's return code.", type=int)
parser.add_argument("junit_files", help="Paths to JUnit report files.", nargs="*")
args = parser.parse_args()
@@ -477,7 +549,9 @@ def generate_report(title, junit_files, buildkite_info):
if len(buildkite_info) != len(env_var_names):
buildkite_info = None
- report, style = generate_report(args.title, args.junit_files, buildkite_info)
+ report, style = generate_report(
+ args.title, args.return_code, args.junit_files, buildkite_info
+ )
if report:
p = subprocess.Popen(
diff --git a/.ci/monolithic-linux.sh b/.ci/monolithic-linux.sh
index 4bfebd5f75279..55741bc831046 100755
--- a/.ci/monolithic-linux.sh
+++ b/.ci/monolithic-linux.sh
@@ -29,6 +29,8 @@ if [[ -n "${CLEAR_CACHE:-}" ]]; then
fi
function at-exit {
+ retcode=$?
+
mkdir -p artifacts
ccache --print-stats > artifacts/ccache_stats.txt
@@ -37,7 +39,7 @@ function at-exit {
if command -v buildkite-agent 2>&1 >/dev/null
then
python3 "${MONOREPO_ROOT}"/.ci/generate_test_report.py ":linux: Linux x64 Test Results" \
- "linux-x64-test-results" "${BUILD_DIR}"/test-results.*.xml
+ "linux-x64-test-results" $retcode "${BUILD_DIR}"/test-results.*.xml
fi
}
trap at-exit EXIT
diff --git a/.ci/monolithic-windows.sh b/.ci/monolithic-windows.sh
index 25cdd2f419f47..68303a3ea153a 100755
--- a/.ci/monolithic-windows.sh
+++ b/.ci/monolithic-windows.sh
@@ -28,6 +28,8 @@ fi
sccache --zero-stats
function at-exit {
+ retcode=$?
+
mkdir -p artifacts
sccache --show-stats >> artifacts/sccache_stats.txt
@@ -36,7 +38,7 @@ function at-exit {
if command -v buildkite-agent 2>&1 >/dev/null
then
python "${MONOREPO_ROOT}"/.ci/generate_test_report.py ":windows: Windows x64 Test Results" \
- "windows-x64-test-results" "${BUILD_DIR}"/test-results.*.xml
+ "windows-x64-test-results" $retcode "${BUILD_DIR}"/test-results.*.xml
fi
}
trap at-exit EXIT
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index e020710c7aa4f..2eb0777dbdc6c 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2137,8 +2137,8 @@ method; it specifies that the method expects its ``self`` parameter to have a
- (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
-`_.
+Further examples of these attributes are available in the static analyzer's
+`list of annotations for analysis `__.
Query for these features with ``__has_attribute(ns_consumed)``,
``__has_attribute(ns_returns_retained)``, etc.
@@ -4792,8 +4792,8 @@ 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 `_. These attributes are documented
-in the analyzer's `list of source-level annotations
-`_.
+in the analyzer's `list of annotations for analysis
+`__.
Extensions for Dynamic Analysis
diff --git a/clang/docs/Modules.rst b/clang/docs/Modules.rst
index 06294e3c58a4f..69a45b7fd9ace 100644
--- a/clang/docs/Modules.rst
+++ b/clang/docs/Modules.rst
@@ -152,7 +152,7 @@ first include path that would refer to the current file. ``#include_next`` is
interpreted as if the current file had been found in that path.
If this search finds a file named by a module map, the ``#include_next``
directive is translated into an import, just like for a ``#include``
-directive.``
+directive.
Module maps
-----------
diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst
index a1cb7fe359ebf..673c34bf08a4a 100644
--- a/clang/docs/OpenMPSupport.rst
+++ b/clang/docs/OpenMPSupport.rst
@@ -286,6 +286,8 @@ implementation.
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| memory management | 'allocator' modifier for allocate clause | :good:`done` | https://github.com/llvm/llvm-project/pull/114883 |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| memory management | 'align' modifier for allocate clause | :good:`done` | https://github.com/llvm/llvm-project/pull/121814 |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| memory management | new memory management routines | :none:`unclaimed` | |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| memory management | changes to omp_alloctrait_key enum | :none:`unclaimed` | |
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a14fb189c8e13..9eeb872aa57d7 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -58,6 +58,29 @@ code bases.
containing strict-aliasing violations. The new default behavior can be
disabled using ``-fno-pointer-tbaa``.
+- Clang will now more aggressively use undefined behavior on pointer addition
+ overflow for optimization purposes. For example, a check like
+ ``ptr + unsigned_offset < ptr`` will now optimize to ``false``, because
+ ``ptr + unsigned_offset`` will cause undefined behavior if it overflows (or
+ advances past the end of the object).
+
+ Previously, ``ptr + unsigned_offset < ptr`` was optimized (by both Clang and
+ GCC) to ``(ssize_t)unsigned_offset < 0``. This also results in an incorrect
+ overflow check, but in a way that is less apparent when only testing with
+ pointers in the low half of the address space.
+
+ To avoid pointer addition overflow, it is necessary to perform the addition
+ on integers, for example using
+ ``(uintptr_t)ptr + unsigned_offset < (uintptr_t)ptr``. Sometimes, it is also
+ possible to rewrite checks by only comparing the offset. For example,
+ ``ptr + offset < end_ptr && ptr + offset >= ptr`` can be written as
+ ``offset < (uintptr_t)(end_ptr - ptr)``.
+
+ Undefined behavior due to pointer addition overflow can be reliably detected
+ using ``-fsanitize=pointer-overflow``. It is also possible to use
+ ``-fno-strict-overflow`` to opt-in to a language dialect where signed integer
+ and pointer overflow are well-defined.
+
C/C++ Language Potentially Breaking Changes
-------------------------------------------
@@ -1347,6 +1370,7 @@ OpenMP Support
always build support for AMDGPU and NVPTX targets.
- Added support for combined masked constructs 'omp parallel masked taskloop',
'omp parallel masked taskloop simd','omp masked taskloop' and 'omp masked taskloop simd' directive.
+- Added support for align-modifier in 'allocate' clause.
Improvements
^^^^^^^^^^^^
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 4de288250f3ad..260e84910c6f7 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -1364,10 +1364,8 @@ Controlling Static Analyzer Diagnostics
While not strictly part of the compiler, the diagnostics from Clang's
`static analyzer `_ can also be
influenced by the user via changes to the source code. See the available
-`annotations `_ and the
-analyzer's `FAQ
-page `_ for more
-information.
+`annotations `_ and the analyzer's
+`FAQ page `_ for more information.
.. _usersmanual-precompiled-headers:
diff --git a/clang/www/analyzer/images/example_attribute_nonnull.png b/clang/docs/analyzer/images/example_attribute_nonnull.png
similarity index 100%
rename from clang/www/analyzer/images/example_attribute_nonnull.png
rename to clang/docs/analyzer/images/example_attribute_nonnull.png
diff --git a/clang/www/analyzer/images/example_cf_returns_retained.png b/clang/docs/analyzer/images/example_cf_returns_retained.png
similarity index 100%
rename from clang/www/analyzer/images/example_cf_returns_retained.png
rename to clang/docs/analyzer/images/example_cf_returns_retained.png
diff --git a/clang/www/analyzer/images/example_custom_assert.png b/clang/docs/analyzer/images/example_custom_assert.png
similarity index 100%
rename from clang/www/analyzer/images/example_custom_assert.png
rename to clang/docs/analyzer/images/example_custom_assert.png
diff --git a/clang/www/analyzer/images/example_ns_returns_retained.png b/clang/docs/analyzer/images/example_ns_returns_retained.png
similarity index 100%
rename from clang/www/analyzer/images/example_ns_returns_retained.png
rename to clang/docs/analyzer/images/example_ns_returns_retained.png
diff --git a/clang/www/analyzer/images/example_null_pointer.png b/clang/docs/analyzer/images/example_null_pointer.png
similarity index 100%
rename from clang/www/analyzer/images/example_null_pointer.png
rename to clang/docs/analyzer/images/example_null_pointer.png
diff --git a/clang/www/analyzer/images/example_use_assert.png b/clang/docs/analyzer/images/example_use_assert.png
similarity index 100%
rename from clang/www/analyzer/images/example_use_assert.png
rename to clang/docs/analyzer/images/example_use_assert.png
diff --git a/clang/docs/analyzer/user-docs.rst b/clang/docs/analyzer/user-docs.rst
index dd53ae143148c..e265f033a2c54 100644
--- a/clang/docs/analyzer/user-docs.rst
+++ b/clang/docs/analyzer/user-docs.rst
@@ -12,4 +12,5 @@ Contents:
user-docs/FilingBugs
user-docs/CrossTranslationUnit
user-docs/TaintAnalysisConfiguration
+ user-docs/Annotations
user-docs/FAQ
diff --git a/clang/docs/analyzer/user-docs/Annotations.rst b/clang/docs/analyzer/user-docs/Annotations.rst
new file mode 100644
index 0000000000000..d87e8f4df99c3
--- /dev/null
+++ b/clang/docs/analyzer/user-docs/Annotations.rst
@@ -0,0 +1,689 @@
+==================
+Source Annotations
+==================
+
+The Clang frontend supports several source-level annotations in the form of
+`GCC-style attributes `_
+and pragmas that can help make using the Clang Static Analyzer more useful.
+These annotations can both help suppress false positives as well as enhance the
+analyzer's ability to find bugs.
+
+This page gives a practical overview of such annotations. For more technical
+specifics regarding Clang-specific annotations please see the Clang's list of
+`language extensions `_.
+Details of "standard" GCC attributes (that Clang also supports) can
+be found in the `GCC manual `_, with the
+majority of the relevant attributes being in the section on
+`function attributes `_.
+
+Note that attributes that are labeled **Clang-specific** are not
+recognized by GCC. Their use can be conditioned using preprocessor macros
+(examples included on this page).
+
+.. contents::
+ :local:
+
+Annotations to Enhance Generic Checks
+_____________________________________
+
+Null Pointer Checking
+#####################
+
+Attribute 'nonnull'
+-------------------
+
+The analyzer recognizes the GCC attribute 'nonnull', which indicates that a
+function expects that a given function parameter is not a null pointer.
+Specific details of the syntax of using the 'nonnull' attribute can be found in
+`GCC's documentation `_.
+
+Both the Clang compiler and GCC will flag warnings for simple cases where a
+null pointer is directly being passed to a function with a 'nonnull' parameter
+(e.g., as a constant). The analyzer extends this checking by using its deeper
+symbolic analysis to track what pointer values are potentially null and then
+flag warnings when they are passed in a function call via a 'nonnull'
+parameter.
+
+**Example**
+
+.. code-block:: c
+
+ int bar(int*p, int q, int *r) __attribute__((nonnull(1,3)));
+
+ int foo(int *p, int *q) {
+ return !p ? bar(q, 2, p)
+ : bar(p, 2, q);
+ }
+
+Running ``scan-build`` over this source produces the following output:
+
+.. image:: ../images/example_attribute_nonnull.png
+
+.. _custom_assertion_handlers:
+
+Custom Assertion Handlers
+#########################
+
+The analyzer exploits code assertions by pruning off paths where the
+assertion condition is false. The idea is capture any program invariants
+specified in the assertion that the developer may know but is not immediately
+apparent in the code itself. In this way assertions make implicit assumptions
+explicit in the code, which not only makes the analyzer more accurate when
+finding bugs, but can help others better able to understand your code as well.
+It can also help remove certain kinds of analyzer false positives by pruning off
+false paths.
+
+In order to exploit assertions, however, the analyzer must understand when it
+encounters an "assertion handler". Typically assertions are
+implemented with a macro, with the macro performing a check for the assertion
+condition and, when the check fails, calling an assertion handler. For
+example, consider the following code fragment:
+
+.. code-block: c
+
+ void foo(int *p) {
+ assert(p != NULL);
+ }
+
+When this code is preprocessed on Mac OS X it expands to the following:
+
+.. code-block: c
+
+ void foo(int *p) {
+ (__builtin_expect(!(p != NULL), 0) ? __assert_rtn(__func__, "t.c", 4, "p != NULL") : (void)0);
+ }
+
+In this example, the assertion handler is ``__assert_rtn``. When called,
+most assertion handlers typically print an error and terminate the program. The
+analyzer can exploit such semantics by ending the analysis of a path once it
+hits a call to an assertion handler.
+
+The trick, however, is that the analyzer needs to know that a called function
+is an assertion handler; otherwise the analyzer might assume the function call
+returns and it will continue analyzing the path where the assertion condition
+failed. This can lead to false positives, as the assertion condition usually
+implies a safety condition (e.g., a pointer is not null) prior to performing
+some action that depends on that condition (e.g., dereferencing a pointer).
+
+The analyzer knows about several well-known assertion handlers, but can
+automatically infer if a function should be treated as an assertion handler if
+it is annotated with the 'noreturn' attribute or the (Clang-specific)
+'analyzer_noreturn' attribute. Note that, currently, clang does not support
+these attributes on Objective-C methods and C++ methods.
+
+Attribute 'noreturn'
+--------------------
+
+The 'noreturn' attribute is a GCC attribute that can be placed on the
+declarations of functions. It means exactly what its name implies: a function
+with a 'noreturn' attribute should never return.
+
+Specific details of the syntax of using the 'noreturn' attribute can be found
+in `GCC's documentation `__.
+
+Not only does the analyzer exploit this information when pruning false paths,
+but the compiler also takes it seriously and will generate different code (and
+possibly better optimized) under the assumption that the function does not
+return.
+
+**Example**
+
+On Mac OS X, the function prototype for ``__assert_rtn`` (declared in
+``assert.h``) is specifically annotated with the 'noreturn' attribute:
+
+.. code-block: c
+
+ void __assert_rtn(const char *, const char *, int, const char *) __attribute__((__noreturn__));
+
+Attribute 'analyzer_noreturn' (Clang-specific)
+----------------------------------------------
+
+The Clang-specific 'analyzer_noreturn' attribute is almost identical to
+'noreturn' except that it is ignored by the compiler for the purposes of code
+generation.
+
+This attribute is useful for annotating assertion handlers that actually
+*can* return, but for the purpose of using the analyzer we want to
+pretend that such functions do not return.
+
+Because this attribute is Clang-specific, its use should be conditioned with
+the use of preprocessor macros.
+
+**Example**
+
+.. code-block: c
+
+ #ifndef CLANG_ANALYZER_NORETURN
+ #if __has_feature(attribute_analyzer_noreturn)
+ #define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
+ #else
+ #define CLANG_ANALYZER_NORETURN
+ #endif
+ #endif
+
+ void my_assert_rtn(const char *, const char *, int, const char *) CLANG_ANALYZER_NORETURN;
+
+Mac OS X API Annotations
+________________________
+
+.. _cocoa_mem:
+
+Cocoa & Core Foundation Memory Management Annotations
+#####################################################
+
+The analyzer supports the proper management of retain counts for
+both Cocoa and Core Foundation objects. This checking is largely based on
+enforcing Cocoa and Core Foundation naming conventions for Objective-C methods
+(Cocoa) and C functions (Core Foundation). Not strictly following these
+conventions can cause the analyzer to miss bugs or flag false positives.
+
+One can educate the analyzer (and others who read your code) about methods or
+functions that deviate from the Cocoa and Core Foundation conventions using the
+attributes described here. However, you should consider using proper naming
+conventions or the `objc_method_family `_
+attribute, if applicable.
+
+.. _ns_returns_retained:
+
+Attribute 'ns_returns_retained' (Clang-specific)
+------------------------------------------------
+
+The GCC-style (Clang-specific) attribute 'ns_returns_retained' allows one to
+annotate an Objective-C method or C function as returning a retained Cocoa
+object that the caller is responsible for releasing (via sending a
+``release`` message to the object). The Foundation framework defines a
+macro ``NS_RETURNS_RETAINED`` that is functionally equivalent to the
+one shown below.
+
+**Placing on Objective-C methods**: For Objective-C methods, this
+annotation essentially tells the analyzer to treat the method as if its name
+begins with "alloc" or "new" or contains the word
+"copy".
+
+**Placing on C functions**: For C functions returning Cocoa objects, the
+analyzer typically does not make any assumptions about whether or not the object
+is returned retained. Explicitly adding the 'ns_returns_retained' attribute to C
+functions allows the analyzer to perform extra checking.
+
+**Example**
+
+.. code-block: objc
+
+ #import ;
+
+ #ifndef __has_feature // Optional.
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+ #endif
+
+ #ifndef NS_RETURNS_RETAINED
+ #if __has_feature(attribute_ns_returns_retained)
+ #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
+ #else
+ #define NS_RETURNS_RETAINED
+ #endif
+ #endif
+
+ @interface MyClass : NSObject {}
+ - (NSString*) returnsRetained NS_RETURNS_RETAINED;
+ - (NSString*) alsoReturnsRetained;
+ @end
+
+ @implementation MyClass
+ - (NSString*) returnsRetained {
+ return [[NSString alloc] initWithCString:"no leak here"];
+ }
+ - (NSString*) alsoReturnsRetained {
+ return [[NSString alloc] initWithCString:"flag a leak"];
+ }
+ @end
+
+Running ``scan-build`` on this source file produces the following output:
+
+.. image:: ../images/example_ns_returns_retained.png
+
+.. _ns_returns_not_retained:
+
+Attribute 'ns_returns_not_retained' (Clang-specific)
+----------------------------------------------------
+
+The 'ns_returns_not_retained' attribute is the complement of
+'`ns_returns_retained`_'. Where a function or method may appear to obey the
+Cocoa conventions and return a retained Cocoa object, this attribute can be
+used to indicate that the object reference returned should not be considered as
+an "owning" reference being returned to the caller. The Foundation
+framework defines a macro ``NS_RETURNS_NOT_RETAINED`` that is functionally
+equivalent to the one shown below.
+
+Usage is identical to `ns_returns_retained`_. When using the
+attribute, be sure to declare it within the proper macro that checks for
+its availability, as it is not available in earlier versions of the analyzer:
+
+.. code-block:objc
+
+ #ifndef __has_feature // Optional.
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+ #endif
+
+ #ifndef NS_RETURNS_NOT_RETAINED
+ #if __has_feature(attribute_ns_returns_not_retained)
+ #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
+ #else
+ #define NS_RETURNS_NOT_RETAINED
+ #endif
+ #endif
+
+.. _cf_returns_retained:
+
+Attribute 'cf_returns_retained' (Clang-specific)
+------------------------------------------------
+
+The GCC-style (Clang-specific) attribute 'cf_returns_retained' allows one to
+annotate an Objective-C method or C function as returning a retained Core
+Foundation object that the caller is responsible for releasing. The
+CoreFoundation framework defines a macro ``CF_RETURNS_RETAINED`` that is
+functionally equivalent to the one shown below.
+
+**Placing on Objective-C methods**: With respect to Objective-C methods.,
+this attribute is identical in its behavior and usage to 'ns_returns_retained'
+except for the distinction of returning a Core Foundation object instead of a
+Cocoa object.
+
+This distinction is important for the following reason: as Core Foundation is a
+C API, the analyzer cannot always tell that a pointer return value refers to a
+Core Foundation object. In contrast, it is trivial for the analyzer to
+recognize if a pointer refers to a Cocoa object (given the Objective-C type
+system).
+
+**Placing on C functions**: When placing the attribute
+'cf_returns_retained' on the declarations of C functions, the analyzer
+interprets the function as:
+
+1. Returning a Core Foundation Object
+2. Treating the function as if it its name contained the keywords
+ "create" or "copy". This means the returned object as a
+ +1 retain count that must be released by the caller, either by sending a
+ ``release`` message (via toll-free bridging to an Objective-C object
+ pointer), or calling ``CFRelease`` or a similar function.
+
+**Example**
+
+.. code-block:objc
+
+ #import
+
+ #ifndef __has_feature // Optional.
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+ #endif
+
+ #ifndef CF_RETURNS_RETAINED
+ #if __has_feature(attribute_cf_returns_retained)
+ #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
+ #else
+ #define CF_RETURNS_RETAINED
+ #endif
+ #endif
+
+ @interface MyClass : NSObject {}
+ - (NSDate*) returnsCFRetained CF_RETURNS_RETAINED;
+ - (NSDate*) alsoReturnsRetained;
+ - (NSDate*) returnsNSRetained NS_RETURNS_RETAINED;
+ @end
+
+ CF_RETURNS_RETAINED
+ CFDateRef returnsRetainedCFDate() {
+ return CFDateCreate(0, CFAbsoluteTimeGetCurrent());
+ }
+
+ @implementation MyClass
+ - (NSDate*) returnsCFRetained {
+ return (NSDate*) returnsRetainedCFDate(); // No leak.
+ }
+
+ - (NSDate*) alsoReturnsRetained {
+ return (NSDate*) returnsRetainedCFDate(); // Always report a leak.
+ }
+
+ - (NSDate*) returnsNSRetained {
+ return (NSDate*) returnsRetainedCFDate(); // Report a leak when using GC.
+ }
+ @end
+
+Running ``scan-build`` on this example produces the following output:
+
+.. image:: ../images/example_cf_returns_retained.png
+
+Attribute 'cf_returns_not_retained' (Clang-specific)
+----------------------------------------------------
+
+The 'cf_returns_not_retained' attribute is the complement of
+'`cf_returns_retained`_'. Where a function or method may appear to obey the
+Core Foundation or Cocoa conventions and return a retained Core Foundation
+object, this attribute can be used to indicate that the object reference
+returned should not be considered as an "owning" reference being
+returned to the caller. The CoreFoundation framework defines a macro
+**``CF_RETURNS_NOT_RETAINED``** that is functionally equivalent to the one
+shown below.
+
+Usage is identical to cf_returns_retained_. When using the attribute, be sure
+to declare it within the proper macro that checks for its availability, as it
+is not available in earlier versions of the analyzer:
+
+.. code-block:objc
+
+ #ifndef __has_feature // Optional.
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+ #endif
+
+ #ifndef CF_RETURNS_NOT_RETAINED
+ #if __has_feature(attribute_cf_returns_not_retained)
+ #define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
+ #else
+ #define CF_RETURNS_NOT_RETAINED
+ #endif
+ #endif
+
+.. _ns_consumed:
+
+Attribute 'ns_consumed' (Clang-specific)
+----------------------------------------
+
+The 'ns_consumed' attribute can be placed on a specific parameter in either
+the declaration of a function or an Objective-C method. It indicates to the
+static analyzer that a ``release`` message is implicitly sent to the
+parameter upon completion of the call to the given function or method. The
+Foundation framework defines a macro ``NS_RELEASES_ARGUMENT`` that
+is functionally equivalent to the ``NS_CONSUMED`` macro shown below.
+
+**Example**
+
+.. code-block:objc
+
+ #ifndef __has_feature // Optional.
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+ #endif
+
+ #ifndef NS_CONSUMED
+ #if __has_feature(attribute_ns_consumed)
+ #define NS_CONSUMED __attribute__((ns_consumed))
+ #else
+ #define NS_CONSUMED
+ #endif
+ #endif
+
+ void consume_ns(id NS_CONSUMED x);
+
+ void test() {
+ id x = [[NSObject alloc] init];
+ consume_ns(x); // No leak!
+ }
+
+ @interface Foo : NSObject
+ + (void) releaseArg:(id) NS_CONSUMED x;
+ + (void) releaseSecondArg:(id)x second:(id) NS_CONSUMED y;
+ @end
+
+ void test_method() {
+ id x = [[NSObject alloc] init];
+ [Foo releaseArg:x]; // No leak!
+ }
+
+ void test_method2() {
+ id a = [[NSObject alloc] init];
+ id b = [[NSObject alloc] init];
+ [Foo releaseSecondArg:a second:b]; // 'a' is leaked, but 'b' is released.
+ }
+
+Attribute 'cf_consumed' (Clang-specific)
+----------------------------------------
+
+The 'cf_consumed' attribute is practically identical to ns_consumed_. The
+attribute can be placed on a specific parameter in either the declaration of a
+function or an Objective-C method. It indicates to the static analyzer that the
+object reference is implicitly passed to a call to ``CFRelease`` upon
+completion of the call to the given function or method. The CoreFoundation
+framework defines a macro ``CF_RELEASES_ARGUMENT`` that is functionally
+equivalent to the ``CF_CONSUMED`` macro shown below.
+
+Operationally this attribute is nearly identical to 'ns_consumed'.
+
+**Example**
+
+.. code-block:objc
+
+ #ifndef __has_feature // Optional.
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+ #endif
+
+ #ifndef CF_CONSUMED
+ #if __has_feature(attribute_cf_consumed)
+ #define CF_CONSUMED __attribute__((cf_consumed))
+ #else
+ #define CF_CONSUMED
+ #endif
+ #endif
+
+ void consume_cf(id CF_CONSUMED x);
+ void consume_CFDate(CFDateRef CF_CONSUMED x);
+
+ void test() {
+ id x = [[NSObject alloc] init];
+ consume_cf(x); // No leak!
+ }
+
+ void test2() {
+ CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent());
+ consume_CFDate(date); // No leak, including under GC!
+
+ }
+
+ @interface Foo : NSObject
+ + (void) releaseArg:(CFDateRef) CF_CONSUMED x;
+ @end
+
+ void test_method() {
+ CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent());
+ [Foo releaseArg:date]; // No leak!
+ }
+
+.. _ns_consumes_self:
+
+Attribute 'ns_consumes_self' (Clang-specific)
+---------------------------------------------
+
+The 'ns_consumes_self' attribute can be placed only on an Objective-C method
+declaration. It indicates that the receiver of the message is
+"consumed" (a single reference count decremented) after the message
+is sent. This matches the semantics of all "init" methods.
+
+One use of this attribute is declare your own init-like methods that do not
+follow the standard Cocoa naming conventions.
+
+**Example**
+
+.. code-block:objc
+ #ifndef __has_feature
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+ #endif
+
+ #ifndef NS_CONSUMES_SELF
+ #if __has_feature((attribute_ns_consumes_self))
+ #define NS_CONSUMES_SELF __attribute__((ns_consumes_self))
+ #else
+ #define NS_CONSUMES_SELF
+ #endif
+ #endif
+
+ @interface MyClass : NSObject
+ - initWith:(MyClass *)x;
+ - nonstandardInitWith:(MyClass *)x NS_CONSUMES_SELF NS_RETURNS_RETAINED;
+ @end
+
+In this example, ``-nonstandardInitWith:`` has the same ownership
+semantics as the init method ``-initWith:``. The static analyzer will
+observe that the method consumes the receiver, and then returns an object with
+a +1 retain count.
+
+The Foundation framework defines a macro ``NS_REPLACES_RECEIVER`` which is
+functionally equivalent to the combination of ``NS_CONSUMES_SELF`` and
+``NS_RETURNS_RETAINED`` shown above.
+
+Libkern Memory Management Annotations
+#####################################
+
+`Libkern `_
+requires developers to inherit all heap allocated objects from ``OSObject`` and
+to perform manual reference counting. The reference counting model is very
+similar to MRR (manual retain-release) mode in
+`Objective-C `_
+or to CoreFoundation reference counting.
+Freshly-allocated objects start with a reference count of 1, and calls to
+``retain`` increment it, while calls to ``release`` decrement it. The object is
+deallocated whenever its reference count reaches zero.
+
+Manually incrementing and decrementing reference counts is error-prone:
+over-retains lead to leaks, and over-releases lead to uses-after-free.
+The analyzer can help the programmer to check for unbalanced
+retain/release calls.
+
+The reference count checking is based on the principle of *locality*: it should
+be possible to establish correctness (lack of leaks/uses after free) by looking
+at each function body, and the declarations (not the definitions) of all the
+functions it interacts with.
+
+In order to support such reasoning, it should be possible to *summarize* the
+behavior of each function, with respect to reference count of its returned
+values and attributes.
+
+By default, the following summaries are assumed:
+
+- All functions starting with ``get`` or ``Get``, unless they are returning
+ subclasses of ``OSIterator``, are assumed to be returning at +0. That is, the
+ caller has no reference count *obligations* with respect to the reference
+ count of the returned object and should leave it untouched.
+
+- All other functions are assumed to return at +1. That is, the caller has an
+ *obligation* to release such objects.
+
+- Functions are assumed not to change the reference count of their parameters,
+ including the implicit ``this`` parameter.
+
+These summaries can be overriden with the following
+`attributes `_:
+
+Attribute 'os_returns_retained'
+-------------------------------
+
+The ``os_returns_retained`` attribute (accessed through the macro
+``LIBKERN_RETURNS_RETAINED``) plays a role identical to `ns_returns_retained`_
+for functions returning ``OSObject`` subclasses. The attribute indicates that
+it is a callers responsibility to release the returned object.
+
+Attribute 'os_returns_not_retained'
+-----------------------------------
+
+The ``os_returns_not_retained`` attribute (accessed through the macro
+``LIBKERN_RETURNS_NOT_RETAINED``) plays a role identical to
+`ns_returns_not_retained`_ for functions returning ``OSObject`` subclasses. The
+attribute indicates that the caller should not change the retain count of the
+returned object.
+
+
+**Example**
+
+.. code-block:objc
+
+ class MyClass {
+ OSObject *f;
+ LIBKERN_RETURNS_NOT_RETAINED OSObject *myFieldGetter();
+ }
+
+
+ // Note that the annotation only has to be applied to the function declaration.
+ OSObject * MyClass::myFieldGetter() {
+ return f;
+ }
+
+Attribute 'os_consumed'
+-----------------------
+
+Similarly to `ns_consumed`_ attribute, ``os_consumed`` (accessed through
+``LIBKERN_CONSUMED``) attribute, applied to a parameter, indicates that the
+call to the function *consumes* the parameter: the callee should either release
+it or store it and release it in the destructor, while the caller should assume
+one is subtracted from the reference count after the call.
+
+.. code-block:objc
+ IOReturn addToList(LIBKERN_CONSUMED IOPMinformee *newInformee);
+
+Attribute 'os_consumes_this'
+----------------------------
+
+Similarly to `ns_consumes_self`_, the ``os_consumes_self`` attribute indicates
+that the method call *consumes* the implicit ``this`` argument: the caller
+should assume one was subtracted from the reference count of the object after
+the call, and the callee has on obligation to either release the argument, or
+store it and eventually release it in the destructor.
+
+
+.. code-block:objc
+ void addThisToList(OSArray *givenList) LIBKERN_CONSUMES_THIS;
+
+Out Parameters
+--------------
+
+A function can also return an object to a caller by a means of an out parameter
+(a pointer-to-OSObject-pointer is passed, and a callee writes a pointer to an
+object into an argument). Currently the analyzer does not track unannotated out
+parameters by default, but with annotations we distinguish four separate cases:
+
+**1. Non-retained out parameters**, identified using
+``LIBKERN_RETURNS_NOT_RETAINED`` applied to parameters, e.g.:
+
+.. code-block:objc
+ void getterViaOutParam(LIBKERN_RETURNS_NOT_RETAINED OSObject **obj)
+
+Such functions write a non-retained object into an out parameter, and the
+caller has no further obligations.
+
+**2. Retained out parameters**, identified using ``LIBKERN_RETURNS_RETAINED``:
+
+.. code-block:objc
+ void getterViaOutParam(LIBKERN_RETURNS_NOT_RETAINED OSObject **obj)
+
+In such cases a retained object is written into an out parameter, which the caller has then to release in order to avoid a leak.
+
+These two cases are simple - but in practice a functions returning an
+out-parameter usually also return a return code, and then an out parameter may
+or may not be written, which conditionally depends on the exit code, e.g.:
+
+.. code-block:objc
+ bool maybeCreateObject(LIBKERN_RETURNS_RETAINED OSObject **obj);
+
+For such functions, the usual semantics is that an object is written into on "success", and not written into on "failure".
+
+For ``LIBKERN_RETURNS_RETAINED`` we assume the following definition of
+success:
+
+- For functions returning ``OSReturn`` or ``IOReturn`` (any typedef to
+ ``kern_return_t``) success is defined as having an output of zero
+ (``kIOReturnSuccess`` is zero).
+
+- For all others, success is non-zero (e.g. non-nullptr for pointers)
+
+**3. Retained out parameters on zero return** The annotation
+``LIBKERN_RETURNS_RETAINED_ON_ZERO`` states that a retained object is written
+into if and only if the function returns a zero value:
+
+.. code-block:objc
+ bool OSUnserializeXML(void *data, LIBKERN_RETURNS_RETAINED_ON_ZERO OSString **errString);
+
+Then the caller has to release an object if the function has returned zero.
+
+**4. Retained out parameters on non-zero return** Similarly,
+``LIBKERN_RETURNS_RETAINED_ON_NONZERO`` specifies that a retained object is
+written into the parameter if and only if the function has returned a non-zero
+value.
+
+Note that for non-retained out parameters conditionals do not matter, as the
+caller has no obligations regardless of whether an object is written into or
+not.
diff --git a/clang/docs/analyzer/user-docs/FAQ.rst b/clang/docs/analyzer/user-docs/FAQ.rst
index af52e99c91d68..58eac783efccd 100644
--- a/clang/docs/analyzer/user-docs/FAQ.rst
+++ b/clang/docs/analyzer/user-docs/FAQ.rst
@@ -9,7 +9,9 @@ Custom Assertions
Q: How do I tell the analyzer that I do not want the bug being reported here since my custom error handler will safely end the execution before the bug is reached?
-You can tell the analyzer that this path is unreachable by teaching it about your `custom assertion handlers `_. For example, you can modify the code segment as following:
+.. image:: ../images/example_custom_assert.png
+
+You can tell the analyzer that this path is unreachable by teaching it about your `custom assertion handlers `__. For example, you can modify the code segment as following:
.. code-block:: c
@@ -25,6 +27,8 @@ Null Pointer Dereference
Q: The analyzer reports a null dereference, but I know that the pointer is never null. How can I tell the analyzer that a pointer can never be null?
+.. image:: ../images/example_null_pointer.png
+
The reason the analyzer often thinks that a pointer can be null is because the preceding code checked compared it against null. If you are absolutely sure that it cannot be null, remove the preceding check and, preferably, add an assertion as well. For example:
.. code-block:: c
@@ -143,6 +147,8 @@ Ensuring Loop Body Execution
Q: The analyzer assumes that a loop body is never entered. How can I tell it that the loop body will be entered at least once?
+.. image:: ../images/example_use_assert.png
+
In cases where you know that a loop will always be entered at least once, you can use assertions to inform the analyzer. For example:
.. code-block:: c
@@ -162,7 +168,7 @@ Suppressing Specific Warnings
Q: How can I suppress a specific analyzer warning?
-When you encounter an analyzer bug/false positive, check if it's one of the issues discussed above or if the analyzer `annotations `_ can resolve the issue by helping the static analyzer understand the code better. Second, please `report it `_ to help us improve user experience.
+When you encounter an analyzer bug/false positive, check if it's one of the issues discussed above or if the analyzer `annotations `__ can resolve the issue by helping the static analyzer understand the code better. Second, please `report it `_ to help us improve user experience.
Sometimes there's really no "good" way to eliminate the issue. In such cases you can "silence" it directly by annotating the problematic line of code with the help of Clang attribute 'suppress':
@@ -192,6 +198,8 @@ Sometimes there's really no "good" way to eliminate the issue. In such cases you
return *result; // as well as this leak path
}
+.. _exclude_code:
+
Excluding Code from Analysis
----------------------------
diff --git a/clang/examples/Attribute/Attribute.cpp b/clang/examples/Attribute/Attribute.cpp
index 3b90724ad2220..625f1645afbff 100644
--- a/clang/examples/Attribute/Attribute.cpp
+++ b/clang/examples/Attribute/Attribute.cpp
@@ -42,8 +42,8 @@ struct ExampleAttrInfo : public ParsedAttrInfo {
const Decl *D) const override {
// This attribute appertains to functions only.
if (!isa(D)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
- << Attr << Attr.isRegularKeywordAttribute() << "functions";
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr << Attr.isRegularKeywordAttribute() << ExpectedFunction;
return false;
}
return true;
@@ -99,8 +99,9 @@ struct ExampleAttrInfo : public ParsedAttrInfo {
const Stmt *St) const override {
// This attribute appertains to for loop statements only.
if (!isa(St)) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
- << Attr << Attr.isRegularKeywordAttribute() << "for loop statements";
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr << Attr.isRegularKeywordAttribute()
+ << ExpectedForLoopStatement;
return false;
}
return true;
diff --git a/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp b/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp
index 12d4c311586e6..f206a84ab1311 100644
--- a/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp
+++ b/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp
@@ -168,8 +168,9 @@ struct CallSuperAttrInfo : public ParsedAttrInfo {
const Decl *D) const override {
const auto *TheMethod = dyn_cast_or_null(D);
if (!TheMethod || !TheMethod->isVirtual()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
- << Attr << Attr.isRegularKeywordAttribute() << "virtual functions";
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr << Attr.isRegularKeywordAttribute()
+ << ExpectedVirtualFunction;
return false;
}
MarkedMethods.insert(TheMethod);
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 82932e098c86f..77abd8b657a61 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -1334,7 +1334,7 @@ class DeclListNode {
reference operator*() const {
assert(Ptr && "dereferencing end() iterator");
- if (DeclListNode *CurNode = Ptr.dyn_cast())
+ if (DeclListNode *CurNode = dyn_cast(Ptr))
return CurNode->D;
return cast(Ptr);
}
@@ -1344,7 +1344,7 @@ class DeclListNode {
inline iterator &operator++() { // ++It
assert(!Ptr.isNull() && "Advancing empty iterator");
- if (DeclListNode *CurNode = Ptr.dyn_cast())
+ if (DeclListNode *CurNode = dyn_cast(Ptr))
Ptr = CurNode->Rest;
else
Ptr = nullptr;
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index d2f5267e4da5e..b9088eff3bb52 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -498,6 +498,9 @@ class OMPAllocateClause final
/// Allocator specified in the clause, or 'nullptr' if the default one is
/// used.
Expr *Allocator = nullptr;
+ /// Alignment specified in the clause, or 'nullptr' if the default one is
+ /// used.
+ Expr *Alignment = nullptr;
/// Position of the ':' delimiter in the clause;
SourceLocation ColonLoc;
/// Modifier of 'allocate' clause.
@@ -505,6 +508,41 @@ class OMPAllocateClause final
/// Location of allocator modifier if any.
SourceLocation AllocatorModifierLoc;
+ // ----------------------------------------------------------------------------
+
+ /// Modifiers for 'allocate' clause.
+ enum { FIRST, SECOND, NUM_MODIFIERS };
+ OpenMPAllocateClauseModifier Modifiers[NUM_MODIFIERS];
+
+ /// Locations of modifiers.
+ SourceLocation ModifiersLoc[NUM_MODIFIERS];
+
+ /// Set the first allocate modifier.
+ ///
+ /// \param M Allocate modifier.
+ void setFirstAllocateModifier(OpenMPAllocateClauseModifier M) {
+ Modifiers[FIRST] = M;
+ }
+
+ /// Set the second allocate modifier.
+ ///
+ /// \param M Allocate modifier.
+ void setSecondAllocateModifier(OpenMPAllocateClauseModifier M) {
+ Modifiers[SECOND] = M;
+ }
+
+ /// Set location of the first allocate modifier.
+ void setFirstAllocateModifierLoc(SourceLocation Loc) {
+ ModifiersLoc[FIRST] = Loc;
+ }
+
+ /// Set location of the second allocate modifier.
+ void setSecondAllocateModifierLoc(SourceLocation Loc) {
+ ModifiersLoc[SECOND] = Loc;
+ }
+
+ // ----------------------------------------------------------------------------
+
/// Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
@@ -514,15 +552,20 @@ class OMPAllocateClause final
/// \param EndLoc Ending location of the clause.
/// \param N Number of the variables in the clause.
OMPAllocateClause(SourceLocation StartLoc, SourceLocation LParenLoc,
- Expr *Allocator, SourceLocation ColonLoc,
- OpenMPAllocateClauseModifier AllocatorModifier,
- SourceLocation AllocatorModifierLoc, SourceLocation EndLoc,
+ Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc,
+ OpenMPAllocateClauseModifier Modifier1,
+ SourceLocation Modifier1Loc,
+ OpenMPAllocateClauseModifier Modifier2,
+ SourceLocation Modifier2Loc, SourceLocation EndLoc,
unsigned N)
: OMPVarListClause(llvm::omp::OMPC_allocate, StartLoc,
LParenLoc, EndLoc, N),
- Allocator(Allocator), ColonLoc(ColonLoc),
- AllocatorModifier(AllocatorModifier),
- AllocatorModifierLoc(AllocatorModifierLoc) {}
+ Allocator(Allocator), Alignment(Alignment), ColonLoc(ColonLoc) {
+ Modifiers[FIRST] = Modifier1;
+ Modifiers[SECOND] = Modifier2;
+ ModifiersLoc[FIRST] = Modifier1Loc;
+ ModifiersLoc[SECOND] = Modifier2Loc;
+ }
/// Build an empty clause.
///
@@ -530,7 +573,10 @@ class OMPAllocateClause final
explicit OMPAllocateClause(unsigned N)
: OMPVarListClause(llvm::omp::OMPC_allocate,
SourceLocation(), SourceLocation(),
- SourceLocation(), N) {}
+ SourceLocation(), N) {
+ Modifiers[FIRST] = OMPC_ALLOCATE_unknown;
+ Modifiers[SECOND] = OMPC_ALLOCATE_unknown;
+ }
/// Sets location of ':' symbol in clause.
void setColonLoc(SourceLocation CL) { ColonLoc = CL; }
@@ -539,6 +585,7 @@ class OMPAllocateClause final
void setAllocatorModifier(OpenMPAllocateClauseModifier AM) {
AllocatorModifier = AM;
}
+ void setAlignment(Expr *A) { Alignment = A; }
public:
/// Creates clause with a list of variables \a VL.
@@ -554,19 +601,42 @@ class OMPAllocateClause final
/// \param VL List of references to the variables.
static OMPAllocateClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
- Expr *Allocator, SourceLocation ColonLoc,
- OpenMPAllocateClauseModifier AllocatorModifier,
- SourceLocation AllocatorModifierLoc, SourceLocation EndLoc,
- ArrayRef VL);
+ Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc,
+ OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc,
+ OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc,
+ SourceLocation EndLoc, ArrayRef VL);
/// Returns the allocator expression or nullptr, if no allocator is specified.
Expr *getAllocator() const { return Allocator; }
+ /// Returns the alignment expression or nullptr, if no alignment specified.
+ Expr *getAlignment() const { return Alignment; }
+
/// Return 'allocate' modifier.
OpenMPAllocateClauseModifier getAllocatorModifier() const {
return AllocatorModifier;
}
+ /// Get the first modifier of the clause.
+ OpenMPAllocateClauseModifier getFirstAllocateModifier() const {
+ return Modifiers[FIRST];
+ }
+
+ /// Get location of first modifier of the clause.
+ SourceLocation getFirstAllocateModifierLoc() const {
+ return ModifiersLoc[FIRST];
+ }
+
+ /// Get the second modifier of the clause.
+ OpenMPAllocateClauseModifier getSecondAllocateModifier() const {
+ return Modifiers[SECOND];
+ }
+
+ /// Get location of second modifier of the clause.
+ SourceLocation getSecondAllocateModifierLoc() const {
+ return ModifiersLoc[SECOND];
+ }
+
/// Returns the location of the ':' delimiter.
SourceLocation getColonLoc() const { return ColonLoc; }
/// Return the location of the modifier.
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index c0632aaa51625..a752d94b06fad 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4353,6 +4353,16 @@ def HLSLLoopHint: StmtAttr {
let Documentation = [HLSLLoopHintDocs, HLSLUnrollHintDocs];
}
+def HLSLControlFlowHint: StmtAttr {
+ /// [branch]
+ /// [flatten]
+ let Spellings = [Microsoft<"branch">, Microsoft<"flatten">];
+ let Subjects = SubjectList<[IfStmt],
+ ErrorDiag, "'if' statements">;
+ let LangOpts = [HLSL];
+ let Documentation = [InternalOnly];
+}
+
def CapturedRecord : InheritableAttr {
// This attribute has no spellings as it is only ever created implicitly.
let Spellings = [];
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 953ff9a700e51..e10f24e239ece 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -1461,7 +1461,7 @@ Mind that many more checkers are affected by dynamic memory modeling changes to
some extent.
Further reading for other annotations:
-`Source Annotations in the Clang Static Analyzer `_.
+`Source Annotations in the Clang Static Analyzer `_.
}];
}
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 86fcae209c40d..3309f59a981fc 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1658,6 +1658,8 @@ def warn_omp_depend_in_ordered_deprecated : Warning<"'depend' clause for"
def warn_omp_invalid_attribute_for_ompx_attributes : Warning<"'ompx_attribute' clause only allows "
"'amdgpu_flat_work_group_size', 'amdgpu_waves_per_eu', and 'launch_bounds'; "
"%0 is ignored">, InGroup;
+def err_omp_duplicate_modifier : Error<"duplicate modifier '%0' in '%1' clause">;
+def err_omp_expected_modifier : Error<"expected modifier in '%0' clause">;
// Pragma loop support.
def err_pragma_loop_missing_argument : Error<
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f04381a32a415..8be4f946dce1c 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3799,7 +3799,14 @@ def warn_attribute_wrong_decl_type : Warning<
"|types and namespaces"
"|variables, functions and classes"
"|kernel functions"
- "|non-K&R-style functions}2">,
+ "|non-K&R-style functions"
+ "|for loop statements"
+ "|virtual functions"
+ "|parameters and implicit object parameters"
+ "|non-member functions"
+ "|functions, classes, or enumerations"
+ "|classes"
+ "|typedefs}2">,
InGroup;
def err_attribute_wrong_decl_type : Error;
def warn_type_attribute_wrong_type : Warning<
diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def
index 3f25e7aafe23b..76a861f416fd5 100644
--- a/clang/include/clang/Basic/OpenMPKinds.def
+++ b/clang/include/clang/Basic/OpenMPKinds.def
@@ -219,6 +219,7 @@ OPENMP_NUMTASKS_MODIFIER(strict)
// Modifiers for 'allocate' clause.
OPENMP_ALLOCATE_MODIFIER(allocator)
+OPENMP_ALLOCATE_MODIFIER(align)
// Modifiers for the 'doacross' clause.
OPENMP_DOACROSS_MODIFIER(source)
diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h
index 900ad6ca6d66f..3e5da2a6abc01 100644
--- a/clang/include/clang/Basic/OpenMPKinds.h
+++ b/clang/include/clang/Basic/OpenMPKinds.h
@@ -230,6 +230,10 @@ enum OpenMPAllocateClauseModifier {
OMPC_ALLOCATE_unknown
};
+/// Number of allowed allocate-modifiers.
+static constexpr unsigned NumberOfOMPAllocateClauseModifiers =
+ OMPC_ALLOCATE_unknown;
+
/// Contains 'interop' data for 'append_args' and 'init' clauses.
class Expr;
struct OMPInteropInfo final {
diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td
index 1c6bdb8cad2d1..47f1754aeb629 100644
--- a/clang/include/clang/Basic/arm_sve.td
+++ b/clang/include/clang/Basic/arm_sve.td
@@ -1988,7 +1988,7 @@ def SVSM4E : SInst<"svsm4e[_{d}]", "ddd", "Ui", MergeNone, "aarch64_sve_sm
def SVSM4EKEY : SInst<"svsm4ekey[_{d}]", "ddd", "Ui", MergeNone, "aarch64_sve_sm4ekey", [IsOverloadNone]>;
}
-let SVETargetGuard = "sve2-bitperm", SMETargetGuard = InvalidMode in {
+let SVETargetGuard = "sve2,sve-bitperm", SMETargetGuard = InvalidMode in {
def SVBDEP : SInst<"svbdep[_{d}]", "ddd", "UcUsUiUl", MergeNone, "aarch64_sve_bdep_x">;
def SVBDEP_N : SInst<"svbdep[_n_{d}]", "dda", "UcUsUiUl", MergeNone, "aarch64_sve_bdep_x">;
def SVBEXT : SInst<"svbext[_{d}]", "ddd", "UcUsUiUl", MergeNone, "aarch64_sve_bext_x">;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 80360216c9503..bbf5c0e7e7fd1 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5756,6 +5756,8 @@ def print_multi_directory : Flag<["-", "--"], "print-multi-directory">;
def print_multi_lib : Flag<["-", "--"], "print-multi-lib">;
def print_multi_flags : Flag<["-", "--"], "print-multi-flags-experimental">,
HelpText<"Print the flags used for selecting multilibs (experimental)">;
+def fmultilib_flag : Joined<["-", "--"], "fmultilib-flag=">,
+ Visibility<[ClangOption]>;
def print_multi_os_directory : Flag<["-", "--"], "print-multi-os-directory">,
Flags<[Unsupported]>;
def print_target_triple : Flag<["-", "--"], "print-target-triple">,
diff --git a/clang/include/clang/Frontend/Utils.h b/clang/include/clang/Frontend/Utils.h
index 8ed17179c9824..604e42067a3f1 100644
--- a/clang/include/clang/Frontend/Utils.h
+++ b/clang/include/clang/Frontend/Utils.h
@@ -120,7 +120,6 @@ class DependencyFileGenerator : public DependencyCollector {
private:
void outputDependencyFile(DiagnosticsEngine &Diags);
- llvm::IntrusiveRefCntPtr FS;
std::string OutputFile;
std::vector Targets;
bool IncludeSystemHeaders;
diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h
index 4fa5fbdb5a7f6..e1faab205f647 100644
--- a/clang/include/clang/Sema/ParsedAttr.h
+++ b/clang/include/clang/Sema/ParsedAttr.h
@@ -1099,6 +1099,13 @@ enum AttributeDeclKind {
ExpectedFunctionVariableOrClass,
ExpectedKernelFunction,
ExpectedFunctionWithProtoType,
+ ExpectedForLoopStatement,
+ ExpectedVirtualFunction,
+ ExpectedParameterOrImplicitObjectParameter,
+ ExpectedNonMemberFunction,
+ ExpectedFunctionOrClassOrEnum,
+ ExpectedClass,
+ ExpectedTypedef,
};
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h
index 3d1cc4fab1c10..a056a96f50233 100644
--- a/clang/include/clang/Sema/SemaOpenMP.h
+++ b/clang/include/clang/Sema/SemaOpenMP.h
@@ -1148,7 +1148,12 @@ class SemaOpenMP : public SemaBase {
SourceLocation OmpAllMemoryLoc;
SourceLocation
StepModifierLoc; /// 'step' modifier location for linear clause
- OpenMPAllocateClauseModifier AllocClauseModifier = OMPC_ALLOCATE_unknown;
+ SmallVector
+ AllocClauseModifiers;
+ SmallVector
+ AllocClauseModifiersLoc;
+ Expr *AllocateAlignment = nullptr;
};
OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
@@ -1166,10 +1171,15 @@ class SemaOpenMP : public SemaBase {
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// Called on well-formed 'allocate' clause.
- OMPClause *ActOnOpenMPAllocateClause(
- Expr *Allocator, OpenMPAllocateClauseModifier ACModifier,
- ArrayRef VarList, SourceLocation StartLoc,
- SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
+ OMPClause *
+ ActOnOpenMPAllocateClause(Expr *Allocator, Expr *Alignment,
+ OpenMPAllocateClauseModifier FirstModifier,
+ SourceLocation FirstModifierLoc,
+ OpenMPAllocateClauseModifier SecondModifier,
+ SourceLocation SecondModifierLoc,
+ ArrayRef VarList, SourceLocation StartLoc,
+ SourceLocation ColonLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc);
/// Called on well-formed 'private' clause.
OMPClause *ActOnOpenMPPrivateClause(ArrayRef VarList,
SourceLocation StartLoc,
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 26d33b0d94795..dec4c7221bc77 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3165,6 +3165,7 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
if (Error Err = ImportImplicitMethods(DCXX, FoundCXX))
return std::move(Err);
}
+ // FIXME: We can return FoundDef here.
}
PrevDecl = FoundRecord->getMostRecentDecl();
break;
@@ -9064,9 +9065,26 @@ ASTImporter::findDeclsInToCtx(DeclContext *DC, DeclarationName Name) {
// We can diagnose this only if we search in the redecl context.
DeclContext *ReDC = DC->getRedeclContext();
if (SharedState->getLookupTable()) {
- ASTImporterLookupTable::LookupResult LookupResult =
- SharedState->getLookupTable()->lookup(ReDC, Name);
- return FoundDeclsTy(LookupResult.begin(), LookupResult.end());
+ if (ReDC->isNamespace()) {
+ // Namespaces can be reopened.
+ // Lookup table does not handle this, we must search here in all linked
+ // namespaces.
+ FoundDeclsTy Result;
+ SmallVector NSChain =
+ getCanonicalForwardRedeclChain(
+ dyn_cast(ReDC));
+ for (auto *D : NSChain) {
+ ASTImporterLookupTable::LookupResult LookupResult =
+ SharedState->getLookupTable()->lookup(dyn_cast(D),
+ Name);
+ Result.append(LookupResult.begin(), LookupResult.end());
+ }
+ return Result;
+ } else {
+ ASTImporterLookupTable::LookupResult LookupResult =
+ SharedState->getLookupTable()->lookup(ReDC, Name);
+ return FoundDeclsTy(LookupResult.begin(), LookupResult.end());
+ }
} else {
DeclContext::lookup_result NoloadLookupResult = ReDC->noload_lookup(Name);
FoundDeclsTy Result(NoloadLookupResult.begin(), NoloadLookupResult.end());
diff --git a/clang/lib/AST/ASTImporterLookupTable.cpp b/clang/lib/AST/ASTImporterLookupTable.cpp
index 07d39dcee2583..4ed3198d7ea62 100644
--- a/clang/lib/AST/ASTImporterLookupTable.cpp
+++ b/clang/lib/AST/ASTImporterLookupTable.cpp
@@ -115,8 +115,9 @@ void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
#ifndef NDEBUG
if (!EraseResult) {
std::string Message =
- llvm::formatv("Trying to remove not contained Decl '{0}' of type {1}",
- Name.getAsString(), DC->getDeclKindName())
+ llvm::formatv(
+ "Trying to remove not contained Decl '{0}' of type {1} from a {2}",
+ Name.getAsString(), ND->getDeclKindName(), DC->getDeclKindName())
.str();
llvm_unreachable(Message.c_str());
}
@@ -125,18 +126,18 @@ void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
void ASTImporterLookupTable::add(NamedDecl *ND) {
assert(ND);
- DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
+ DeclContext *DC = ND->getDeclContext();
add(DC, ND);
- DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
+ DeclContext *ReDC = DC->getRedeclContext();
if (DC != ReDC)
add(ReDC, ND);
}
void ASTImporterLookupTable::remove(NamedDecl *ND) {
assert(ND);
- DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
+ DeclContext *DC = ND->getDeclContext();
remove(DC, ND);
- DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
+ DeclContext *ReDC = DC->getRedeclContext();
if (DC != ReDC)
remove(ReDC, ND);
}
@@ -161,7 +162,7 @@ void ASTImporterLookupTable::updateForced(NamedDecl *ND, DeclContext *OldDC) {
ASTImporterLookupTable::LookupResult
ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
- auto DCI = LookupTable.find(DC->getPrimaryContext());
+ auto DCI = LookupTable.find(DC);
if (DCI == LookupTable.end())
return {};
@@ -178,7 +179,7 @@ bool ASTImporterLookupTable::contains(DeclContext *DC, NamedDecl *ND) const {
}
void ASTImporterLookupTable::dump(DeclContext *DC) const {
- auto DCI = LookupTable.find(DC->getPrimaryContext());
+ auto DCI = LookupTable.find(DC);
if (DCI == LookupTable.end())
llvm::errs() << "empty\n";
const auto &FoundNameMap = DCI->second;
@@ -196,8 +197,7 @@ void ASTImporterLookupTable::dump(DeclContext *DC) const {
void ASTImporterLookupTable::dump() const {
for (const auto &Entry : LookupTable) {
DeclContext *DC = Entry.first;
- StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
- llvm::errs() << "== DC:" << cast(DC) << Primary << "\n";
+ llvm::errs() << "== DC:" << cast(DC) << "\n";
dump(DC);
}
}
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 4246ba95d827f..532933d6183ce 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -1019,19 +1019,18 @@ OMPPartialClause *OMPPartialClause::CreateEmpty(const ASTContext &C) {
return new (C) OMPPartialClause();
}
-OMPAllocateClause *
-OMPAllocateClause::Create(const ASTContext &C, SourceLocation StartLoc,
- SourceLocation LParenLoc, Expr *Allocator,
- SourceLocation ColonLoc,
- OpenMPAllocateClauseModifier AllocatorModifier,
- SourceLocation AllocatorModifierLoc,
- SourceLocation EndLoc, ArrayRef VL) {
+OMPAllocateClause *OMPAllocateClause::Create(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
+ Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc,
+ OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc,
+ OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc,
+ SourceLocation EndLoc, ArrayRef VL) {
// Allocate space for private variables and initializer expressions.
void *Mem = C.Allocate(totalSizeToAlloc(VL.size()));
auto *Clause = new (Mem) OMPAllocateClause(
- StartLoc, LParenLoc, Allocator, ColonLoc, AllocatorModifier,
- AllocatorModifierLoc, EndLoc, VL.size());
+ StartLoc, LParenLoc, Allocator, Alignment, ColonLoc, Modifier1,
+ Modifier1Loc, Modifier2, Modifier2Loc, EndLoc, VL.size());
Clause->setVarRefs(VL);
return Clause;
@@ -2245,21 +2244,48 @@ void OMPClausePrinter::VisitOMPClauseList(T *Node, char StartSym) {
void OMPClausePrinter::VisitOMPAllocateClause(OMPAllocateClause *Node) {
if (Node->varlist_empty())
return;
+
+ Expr *FirstModifier = nullptr;
+ Expr *SecondModifier = nullptr;
+ auto FirstAllocMod = Node->getFirstAllocateModifier();
+ auto SecondAllocMod = Node->getSecondAllocateModifier();
+ bool FirstUnknown = FirstAllocMod == OMPC_ALLOCATE_unknown;
+ bool SecondUnknown = SecondAllocMod == OMPC_ALLOCATE_unknown;
+ if (FirstAllocMod == OMPC_ALLOCATE_allocator ||
+ (FirstAllocMod == OMPC_ALLOCATE_unknown && Node->getAllocator())) {
+ FirstModifier = Node->getAllocator();
+ SecondModifier = Node->getAlignment();
+ } else {
+ FirstModifier = Node->getAlignment();
+ SecondModifier = Node->getAllocator();
+ }
+
OS << "allocate";
- OpenMPAllocateClauseModifier Modifier = Node->getAllocatorModifier();
- if (Expr *Allocator = Node->getAllocator()) {
+ // If we have any explicit modifiers.
+ if (FirstModifier) {
OS << "(";
- if (Modifier == OMPC_ALLOCATE_allocator) {
- OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), Modifier);
+ if (!FirstUnknown) {
+ OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(), FirstAllocMod);
OS << "(";
- Allocator->printPretty(OS, nullptr, Policy, 0);
+ }
+ FirstModifier->printPretty(OS, nullptr, Policy, 0);
+ if (!FirstUnknown)
OS << ")";
- } else {
- Allocator->printPretty(OS, nullptr, Policy, 0);
+ if (SecondModifier) {
+ OS << ", ";
+ if (!SecondUnknown) {
+ OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
+ SecondAllocMod);
+ OS << "(";
+ }
+ SecondModifier->printPretty(OS, nullptr, Policy, 0);
+ if (!SecondUnknown)
+ OS << ")";
}
OS << ":";
VisitOMPClauseList(Node, ' ');
} else {
+ // No modifiers. Just print the variable list.
VisitOMPClauseList(Node, '(');
}
OS << ")";
diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp
index 050daee1168d4..13cd7e26dc16f 100644
--- a/clang/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp
@@ -336,7 +336,7 @@ til::SExpr *SExprBuilder::translateDeclRefExpr(const DeclRefExpr *DRE,
: (cast(D)->getCanonicalDecl() == Canonical)) {
// Substitute call arguments for references to function parameters
if (const Expr *const *FunArgs =
- Ctx->FunArgs.dyn_cast()) {
+ dyn_cast(Ctx->FunArgs)) {
assert(I < Ctx->NumArgs);
return translate(FunArgs[I], Ctx->Prev);
}
diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index 1bf58661d0efc..4e211deb9faba 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -485,7 +485,7 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
if (HasSVE2 && HasSVEAES)
Builder.defineMacro("__ARM_FEATURE_SVE2_AES", "1");
- if (HasSVE2 && HasSVE2BitPerm)
+ if (HasSVE2 && HasSVEBitPerm)
Builder.defineMacro("__ARM_FEATURE_SVE2_BITPERM", "1");
if (HasSVE2 && HasSVE2SHA3)
@@ -769,7 +769,7 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const {
.Case("f64mm", FPU & SveMode && HasMatmulFP64)
.Case("sve2", FPU & SveMode && HasSVE2)
.Case("sve-aes", HasSVEAES)
- .Case("sve2-bitperm", FPU & SveMode && HasSVE2BitPerm)
+ .Case("sve-bitperm", FPU & HasSVEBitPerm)
.Case("sve2-sha3", FPU & SveMode && HasSVE2SHA3)
.Case("sve2-sm4", FPU & SveMode && HasSVE2SM4)
.Case("sve2p1", FPU & SveMode && HasSVE2p1)
@@ -881,12 +881,10 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector &Features,
}
if (Feature == "+sve-b16b16")
HasSVEB16B16 = true;
- if (Feature == "+sve2-bitperm") {
+ if (Feature == "+sve-bitperm") {
FPU |= NeonMode;
- FPU |= SveMode;
HasFullFP16 = true;
- HasSVE2 = true;
- HasSVE2BitPerm = true;
+ HasSVEBitPerm = true;
}
if (Feature == "+f32mm") {
FPU |= NeonMode;
diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h
index cedf3286806ac..ecf80b23a508c 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -82,7 +82,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
bool HasSVE2SHA3 = false;
bool HasSVE2SM4 = false;
bool HasSVEB16B16 = false;
- bool HasSVE2BitPerm = false;
+ bool HasSVEBitPerm = false;
bool HasMatmulFP64 = false;
bool HasMatmulFP32 = false;
bool HasLSE = false;
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index bcf6db1467ffc..79e6bf3d24dff 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -85,6 +85,7 @@
#include "llvm/Transforms/Scalar/JumpThreading.h"
#include "llvm/Transforms/Utils/Debugify.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
+#include
#include
#include
using namespace clang;
@@ -119,6 +120,9 @@ static cl::opt ClPGOColdFuncAttr(
extern cl::opt ProfileCorrelate;
} // namespace llvm
+namespace clang {
+extern llvm::cl::opt ClSanitizeGuardChecks;
+}
namespace {
@@ -1023,6 +1027,14 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
PB.registerScalarOptimizerLateEPCallback([this](FunctionPassManager &FPM,
OptimizationLevel Level) {
BoundsCheckingPass::Options Options;
+ if (CodeGenOpts.SanitizeSkipHotCutoffs[SanitizerKind::SO_LocalBounds] ||
+ ClSanitizeGuardChecks) {
+ static_assert(SanitizerKind::SO_LocalBounds <=
+ std::numeric_limits<
+ decltype(Options.GuardKind)::value_type>::max(),
+ "Update type of llvm.allow.ubsan.check.");
+ Options.GuardKind = SanitizerKind::SO_LocalBounds;
+ }
Options.Merge =
CodeGenOpts.SanitizeMergeHandlers.has(SanitizerKind::LocalBounds);
if (!CodeGenOpts.SanitizeTrap.has(SanitizerKind::LocalBounds)) {
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 0fde4d8ee296b..e0cf6ca69f0df 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -4507,7 +4507,7 @@ void CodeGenFunction::EmitCallArgs(
// First, if a prototype was provided, use those argument types.
bool IsVariadic = false;
if (Prototype.P) {
- const auto *MD = Prototype.P.dyn_cast();
+ const auto *MD = dyn_cast(Prototype.P);
if (MD) {
IsVariadic = MD->isVariadic();
ExplicitCC = getCallingConventionForDecl(
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 060d02b7f1487..6e5a21c8f01e7 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -52,11 +52,13 @@
using namespace clang;
using namespace CodeGen;
+namespace clang {
// TODO: Introduce frontend options to enabled per sanitizers, similar to
// `fsanitize-trap`.
-static llvm::cl::opt ClSanitizeGuardChecks(
+llvm::cl::opt ClSanitizeGuardChecks(
"ubsan-guard-checks", llvm::cl::Optional,
llvm::cl::desc("Guard UBSAN checks with `llvm.allow.ubsan.check()`."));
+} // namespace clang
//===--------------------------------------------------------------------===//
// Defines for metadata
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index ee10e586d9250..4ba8ee1ca17d4 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -332,7 +332,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef Attrs) {
EmitOMPMasterTaskLoopDirective(cast(*S));
break;
case Stmt::OMPMaskedTaskLoopDirectiveClass:
- llvm_unreachable("masked taskloop directive not supported yet.");
+ EmitOMPMaskedTaskLoopDirective(cast(*S));
break;
case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
EmitOMPMasterTaskLoopSimdDirective(
@@ -760,6 +760,8 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
bool noinline = false;
bool alwaysinline = false;
bool noconvergent = false;
+ HLSLControlFlowHintAttr::Spelling flattenOrBranch =
+ HLSLControlFlowHintAttr::SpellingNotCalculated;
const CallExpr *musttail = nullptr;
for (const auto *A : S.getAttrs()) {
@@ -791,6 +793,9 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
Builder.CreateAssumption(AssumptionVal);
}
} break;
+ case attr::HLSLControlFlowHint: {
+ flattenOrBranch = cast(A)->getSemanticSpelling();
+ } break;
}
}
SaveAndRestore save_nomerge(InNoMergeAttributedStmt, nomerge);
@@ -798,6 +803,7 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
SaveAndRestore save_alwaysinline(InAlwaysInlineAttributedStmt, alwaysinline);
SaveAndRestore save_noconvergent(InNoConvergentAttributedStmt, noconvergent);
SaveAndRestore save_musttail(MustTailCall, musttail);
+ SaveAndRestore save_flattenOrBranch(HLSLControlFlowAttr, flattenOrBranch);
EmitStmt(S.getSubStmt(), S.getAttrs());
}
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 94daf059edba0..2b4ca65e169a6 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -7982,6 +7982,18 @@ void CodeGenFunction::EmitOMPMasterTaskLoopDirective(
CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
}
+void CodeGenFunction::EmitOMPMaskedTaskLoopDirective(
+ const OMPMaskedTaskLoopDirective &S) {
+ auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+ Action.Enter(CGF);
+ EmitOMPTaskLoopBasedDirective(S);
+ };
+ auto LPCRegion =
+ CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
+ OMPLexicalScope Scope(*this, S, std::nullopt, /*EmitPreInitStmt=*/false);
+ CGM.getOpenMPRuntime().emitMaskedRegion(*this, CodeGen, S.getBeginLoc());
+}
+
void CodeGenFunction::EmitOMPMasterTaskLoopSimdDirective(
const OMPMasterTaskLoopSimdDirective &S) {
auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index d6f3716afabdf..11fdddba1144b 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -40,6 +40,7 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/FPEnv.h"
+#include "llvm/IR/Instruction.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
@@ -2086,7 +2087,30 @@ void CodeGenFunction::EmitBranchOnBoolExpr(
Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount);
}
- Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable);
+ llvm::Instruction *BrInst = Builder.CreateCondBr(CondV, TrueBlock, FalseBlock,
+ Weights, Unpredictable);
+ switch (HLSLControlFlowAttr) {
+ case HLSLControlFlowHintAttr::Microsoft_branch:
+ case HLSLControlFlowHintAttr::Microsoft_flatten: {
+ llvm::MDBuilder MDHelper(CGM.getLLVMContext());
+
+ llvm::ConstantInt *BranchHintConstant =
+ HLSLControlFlowAttr ==
+ HLSLControlFlowHintAttr::Spelling::Microsoft_branch
+ ? llvm::ConstantInt::get(CGM.Int32Ty, 1)
+ : llvm::ConstantInt::get(CGM.Int32Ty, 2);
+
+ SmallVector Vals(
+ {MDHelper.createString("hlsl.controlflow.hint"),
+ MDHelper.createConstant(BranchHintConstant)});
+ BrInst->setMetadata("hlsl.controlflow.hint",
+ llvm::MDNode::get(CGM.getLLVMContext(), Vals));
+ break;
+ }
+ // This is required to avoid warnings during compilation
+ case HLSLControlFlowHintAttr::SpellingNotCalculated:
+ break;
+ }
}
/// ErrorUnsupported - Print out an error that codegen doesn't support the
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 86328db345508..b115c15bf01a9 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -615,6 +615,10 @@ class CodeGenFunction : public CodeGenTypeCache {
/// True if the current statement has noconvergent attribute.
bool InNoConvergentAttributedStmt = false;
+ /// HLSL Branch attribute.
+ HLSLControlFlowHintAttr::Spelling HLSLControlFlowAttr =
+ HLSLControlFlowHintAttr::SpellingNotCalculated;
+
// The CallExpr within the current statement that the musttail attribute
// applies to. nullptr if there is no 'musttail' on the current statement.
const CallExpr *MustTailCall = nullptr;
@@ -3870,6 +3874,7 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S);
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S);
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S);
+ void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &S);
void
EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S);
void
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 10df730744b08..9a947f32283c3 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -6398,6 +6398,11 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
if (auto P = SearchPaths(TC.getFilePaths()))
return *P;
+ SmallString<128> R2(ResourceDir);
+ llvm::sys::path::append(R2, "..", "..", Name);
+ if (llvm::sys::fs::exists(Twine(R2)))
+ return std::string(R2);
+
return std::string(Name);
}
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 2b4df64f2789d..acf9d264d631b 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -196,6 +196,15 @@ bool ToolChain::defaultToIEEELongDouble() const {
return PPC_LINUX_DEFAULT_IEEELONGDOUBLE && getTriple().isOSLinux();
}
+static void processMultilibCustomFlags(Multilib::flags_list &List,
+ const llvm::opt::ArgList &Args) {
+ for (const Arg *MultilibFlagArg :
+ Args.filtered(options::OPT_fmultilib_flag)) {
+ List.push_back(MultilibFlagArg->getAsString(Args));
+ MultilibFlagArg->claim();
+ }
+}
+
static void getAArch64MultilibFlags(const Driver &D,
const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
@@ -246,6 +255,8 @@ static void getAArch64MultilibFlags(const Driver &D,
if (ABIArg) {
Result.push_back(ABIArg->getAsString(Args));
}
+
+ processMultilibCustomFlags(Result, Args);
}
static void getARMMultilibFlags(const Driver &D,
@@ -313,6 +324,7 @@ static void getARMMultilibFlags(const Driver &D,
if (Endian->getOption().matches(options::OPT_mbig_endian))
Result.push_back(Endian->getAsString(Args));
}
+ processMultilibCustomFlags(Result, Args);
}
static void getRISCVMultilibFlags(const Driver &D, const llvm::Triple &Triple,
diff --git a/clang/lib/Frontend/DependencyFile.cpp b/clang/lib/Frontend/DependencyFile.cpp
index 8a36d835d82b3..15fa7de35df97 100644
--- a/clang/lib/Frontend/DependencyFile.cpp
+++ b/clang/lib/Frontend/DependencyFile.cpp
@@ -23,10 +23,8 @@
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include
-#include
using namespace clang;
@@ -238,7 +236,6 @@ void DependencyFileGenerator::attachToPreprocessor(Preprocessor &PP) {
PP.SetSuppressIncludeNotFoundError(true);
DependencyCollector::attachToPreprocessor(PP);
- FS = PP.getFileManager().getVirtualFileSystemPtr();
}
bool DependencyFileGenerator::sawDependency(StringRef Filename, bool FromModule,
@@ -315,22 +312,11 @@ void DependencyFileGenerator::finishedMainFile(DiagnosticsEngine &Diags) {
/// https://msdn.microsoft.com/en-us/library/dd9y37ha.aspx for NMake info,
/// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
/// for Windows file-naming info.
-static void printFilename(raw_ostream &OS, llvm::vfs::FileSystem *FS,
- StringRef Filename,
+static void PrintFilename(raw_ostream &OS, StringRef Filename,
DependencyOutputFormat OutputFormat) {
// Convert filename to platform native path
llvm::SmallString<256> NativePath;
llvm::sys::path::native(Filename.str(), NativePath);
- // Resolve absolute path. Make and Ninja canonicalize paths
- // without checking for symbolic links in the path, for performance concerns.
- // If there is something like `/bin/../lib64` -> `/usr/lib64`
- // (where `/bin` links to `/usr/bin`), Make will see them as `/lib64`.
- if (FS != nullptr && llvm::sys::path::is_absolute(NativePath)) {
- llvm::SmallString<256> NativePathTmp = NativePath;
- std::error_code EC = FS->getRealPath(NativePathTmp, NativePath);
- if (EC)
- NativePath = NativePathTmp;
- }
if (OutputFormat == DependencyOutputFormat::NMake) {
// Add quotes if needed. These are the characters listed as "special" to
@@ -414,7 +400,7 @@ void DependencyFileGenerator::outputDependencyFile(llvm::raw_ostream &OS) {
Columns = 2;
}
OS << ' ';
- printFilename(OS, FS.get(), File, OutputFormat);
+ PrintFilename(OS, File, OutputFormat);
Columns += N + 1;
}
OS << '\n';
@@ -425,7 +411,7 @@ void DependencyFileGenerator::outputDependencyFile(llvm::raw_ostream &OS) {
for (auto I = Files.begin(), E = Files.end(); I != E; ++I) {
if (Index++ == InputFileIndex)
continue;
- printFilename(OS, FS.get(), *I, OutputFormat);
+ PrintFilename(OS, *I, OutputFormat);
OS << ":\n";
}
}
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 7f3f6d568e28c..f136d5007e8a5 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -24,6 +24,7 @@
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/EnterExpressionEvaluationContext.h"
#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaCUDA.h"
@@ -3708,9 +3709,9 @@ void Parser::ParseDeclarationSpecifiers(
continue;
if (PA.getKind() == ParsedAttr::AT_LifetimeBound)
- Diag(PA.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ Diag(PA.getLoc(), diag::err_attribute_wrong_decl_type)
<< PA << PA.isRegularKeywordAttribute()
- << "parameters and implicit object parameters";
+ << ExpectedParameterOrImplicitObjectParameter;
else
Diag(PA.getLoc(), diag::err_attribute_not_type_attr)
<< PA << PA.isRegularKeywordAttribute();
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index b4e973bc84a7b..89b83938f352d 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -4530,32 +4530,88 @@ static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data,
}
/// Parse 'allocate' clause modifiers.
-/// If allocator-modifier exists, return an expression for it and set
-/// Data field noting modifier was specified.
-///
+/// If allocator-modifier exists, return an expression for it. For both
+/// allocator and align modifiers, set Data fields as appropriate.
static ExprResult
parseOpenMPAllocateClauseModifiers(Parser &P, OpenMPClauseKind Kind,
SemaOpenMP::OpenMPVarListDataTy &Data) {
const Token &Tok = P.getCurToken();
Preprocessor &PP = P.getPreprocessor();
ExprResult Tail;
- auto Modifier = static_cast(
+ ExprResult Val;
+ SourceLocation RLoc;
+ bool AllocatorSeen = false;
+ bool AlignSeen = false;
+ SourceLocation CurrentModifierLoc = Tok.getLocation();
+ auto CurrentModifier = static_cast(
getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), P.getLangOpts()));
- if (Modifier == OMPC_ALLOCATE_allocator) {
- Data.AllocClauseModifier = Modifier;
+
+ // Modifiers did not exist before 5.1
+ if (P.getLangOpts().OpenMP < 51)
+ return P.ParseAssignmentExpression();
+
+ // An allocator-simple-modifier is exclusive and must appear alone. See
+ // OpenMP6.0 spec, pg. 313, L1 on Modifiers, as well as Table 5.1, pg. 50,
+ // description of "exclusive" property. If we don't recognized an explicit
+ // simple-/complex- modifier, assume we're looking at expression
+ // representing allocator and consider ourselves done.
+ if (CurrentModifier == OMPC_ALLOCATE_unknown)
+ return P.ParseAssignmentExpression();
+
+ do {
P.ConsumeToken();
- BalancedDelimiterTracker AllocateT(P, tok::l_paren,
- tok::annot_pragma_openmp_end);
if (Tok.is(tok::l_paren)) {
- AllocateT.consumeOpen();
- Tail = P.ParseAssignmentExpression();
- AllocateT.consumeClose();
+ switch (CurrentModifier) {
+ case OMPC_ALLOCATE_allocator: {
+ if (AllocatorSeen) {
+ P.Diag(Tok, diag::err_omp_duplicate_modifier)
+ << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
+ << getOpenMPClauseName(Kind);
+ } else {
+ Data.AllocClauseModifiers.push_back(CurrentModifier);
+ Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
+ }
+ BalancedDelimiterTracker AllocateT(P, tok::l_paren,
+ tok::annot_pragma_openmp_end);
+ AllocateT.consumeOpen();
+ Tail = P.ParseAssignmentExpression();
+ AllocateT.consumeClose();
+ AllocatorSeen = true;
+ break;
+ }
+ case OMPC_ALLOCATE_align: {
+ if (AlignSeen) {
+ P.Diag(Tok, diag::err_omp_duplicate_modifier)
+ << getOpenMPSimpleClauseTypeName(OMPC_allocate, CurrentModifier)
+ << getOpenMPClauseName(Kind);
+ } else {
+ Data.AllocClauseModifiers.push_back(CurrentModifier);
+ Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);
+ }
+ Val = P.ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
+ if (Val.isUsable())
+ Data.AllocateAlignment = Val.get();
+ AlignSeen = true;
+ break;
+ }
+ default:
+ llvm_unreachable("Unexpected allocate modifier");
+ }
} else {
P.Diag(Tok, diag::err_expected) << tok::l_paren;
}
- } else {
- Tail = P.ParseAssignmentExpression();
- }
+ if (Tok.isNot(tok::comma))
+ break;
+ P.ConsumeToken();
+ CurrentModifierLoc = Tok.getLocation();
+ CurrentModifier = static_cast(
+ getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), P.getLangOpts()));
+ // A modifier followed by a comma implies another modifier.
+ if (CurrentModifier == OMPC_ALLOCATE_unknown) {
+ P.Diag(Tok, diag::err_omp_expected_modifier) << getOpenMPClauseName(Kind);
+ break;
+ }
+ } while (!AllocatorSeen || !AlignSeen);
return Tail;
}
@@ -4832,7 +4888,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
} else if (Kind == OMPC_allocate ||
(Kind == OMPC_affinity && Tok.is(tok::identifier) &&
PP.getSpelling(Tok) == "iterator")) {
- // Handle optional allocator expression followed by colon delimiter.
+ // Handle optional allocator and align modifiers followed by colon
+ // delimiter.
ColonProtectionRAIIObject ColonRAII(*this);
TentativeParsingAction TPA(*this);
// OpenMP 5.0, 2.10.1, task Construct.
@@ -4849,19 +4906,18 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Tail = Actions.CorrectDelayedTyposInExpr(Tail);
Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
/*DiscardedValue=*/false);
- if (Tail.isUsable()) {
+ if (Tail.isUsable() || Data.AllocateAlignment) {
if (Tok.is(tok::colon)) {
- Data.DepModOrTailExpr = Tail.get();
+ Data.DepModOrTailExpr = Tail.isUsable() ? Tail.get() : nullptr;
Data.ColonLoc = ConsumeToken();
TPA.Commit();
} else {
// Colon not found, parse only list of variables.
TPA.Revert();
- if (Kind == OMPC_allocate &&
- Data.AllocClauseModifier == OMPC_ALLOCATE_allocator) {
+ if (Kind == OMPC_allocate && Data.AllocClauseModifiers.size()) {
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
- Diag(Tok, diag::err_modifier_expected_colon) << "allocator";
+ Diag(Tok, diag::err_modifier_expected_colon) << "allocate clause";
}
}
} else {
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index bb4d33560b93b..c1663f2d15c88 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -1868,8 +1868,8 @@ static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// This form is not allowed to be written on a member function (static or
// nonstatic) when in Microsoft compatibility mode.
if (S.getLangOpts().MSVCCompat && isa(D)) {
- S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type_str)
- << AL << AL.isRegularKeywordAttribute() << "non-member functions";
+ S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type)
+ << AL << AL.isRegularKeywordAttribute() << ExpectedNonMemberFunction;
return;
}
}
@@ -2761,9 +2761,9 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) {
// The standard attribute cannot be applied to variable declarations such
// as a function pointer.
if (isa(D))
- S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str)
+ S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
<< AL << AL.isRegularKeywordAttribute()
- << "functions, classes, or enumerations";
+ << ExpectedFunctionOrClassOrEnum;
// If this is spelled as the standard C++17 attribute, but not in C++17,
// warn about using it as an extension. If there are attribute arguments,
@@ -5555,8 +5555,8 @@ static void handleNullableTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
if (auto *CRD = dyn_cast(D);
!CRD || !(CRD->isClass() || CRD->isStruct())) {
- S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type_str)
- << AL << AL.isRegularKeywordAttribute() << "classes";
+ S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type)
+ << AL << AL.isRegularKeywordAttribute() << ExpectedClass;
return;
}
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 66ff92f554fc4..b83b2b12f4a23 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -5320,6 +5320,8 @@ static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
Expr *SimpleRefExpr = E;
auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
ValueDecl *VD = Res.first;
+ if (!VD)
+ continue;
DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
if (!isOpenMPPrivate(Data.CKind)) {
S.Diag(E->getExprLoc(),
@@ -5330,10 +5332,8 @@ static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
AllocatorKind, AC->getAllocator()))
continue;
- // Placeholder until allocate clause supports align modifier.
- Expr *Alignment = nullptr;
applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
- Alignment, E->getSourceRange());
+ AC->getAlignment(), E->getSourceRange());
}
}
}
@@ -15617,7 +15617,9 @@ ExprResult SemaOpenMP::VerifyPositiveIntegerConstantInClause(
<< E->getSourceRange();
return ExprError();
}
- if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
+ if ((CKind == OMPC_aligned || CKind == OMPC_align ||
+ CKind == OMPC_allocate) &&
+ !Result.isPowerOf2()) {
Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
<< E->getSourceRange();
return ExprError();
@@ -17153,11 +17155,26 @@ OMPClause *SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
case OMPC_has_device_addr:
Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
break;
- case OMPC_allocate:
- Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr,
- Data.AllocClauseModifier, VarList, StartLoc,
- LParenLoc, ColonLoc, EndLoc);
+ case OMPC_allocate: {
+ OpenMPAllocateClauseModifier Modifier1 = OMPC_ALLOCATE_unknown;
+ OpenMPAllocateClauseModifier Modifier2 = OMPC_ALLOCATE_unknown;
+ SourceLocation Modifier1Loc, Modifier2Loc;
+ if (!Data.AllocClauseModifiers.empty()) {
+ assert(Data.AllocClauseModifiers.size() <= 2 &&
+ "More allocate modifiers than expected");
+ Modifier1 = Data.AllocClauseModifiers[0];
+ Modifier1Loc = Data.AllocClauseModifiersLoc[0];
+ if (Data.AllocClauseModifiers.size() == 2) {
+ Modifier2 = Data.AllocClauseModifiers[1];
+ Modifier2Loc = Data.AllocClauseModifiersLoc[1];
+ }
+ }
+ Res = ActOnOpenMPAllocateClause(
+ Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc,
+ Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
+ EndLoc);
break;
+ }
case OMPC_nontemporal:
Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
break;
@@ -23163,32 +23180,37 @@ SemaOpenMP::ActOnOpenMPHasDeviceAddrClause(ArrayRef VarList,
}
OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause(
- Expr *Allocator, OpenMPAllocateClauseModifier AllocClauseModifier,
- ArrayRef VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation ColonLoc, SourceLocation EndLoc) {
-
+ Expr *Allocator, Expr *Alignment,
+ OpenMPAllocateClauseModifier FirstAllocateModifier,
+ SourceLocation FirstAllocateModifierLoc,
+ OpenMPAllocateClauseModifier SecondAllocateModifier,
+ SourceLocation SecondAllocateModifierLoc, ArrayRef VarList,
+ SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
+ SourceLocation EndLoc) {
if (Allocator) {
// Allocator expression is dependent - skip it for now and build the
// allocator when instantiated.
- if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
- Allocator->isInstantiationDependent() ||
- Allocator->containsUnexpandedParameterPack())
- return nullptr;
- // OpenMP [2.11.4 allocate Clause, Description]
- // allocator is an expression of omp_allocator_handle_t type.
- if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack))
- return nullptr;
+ bool AllocDependent =
+ (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
+ Allocator->isInstantiationDependent() ||
+ Allocator->containsUnexpandedParameterPack());
+ if (!AllocDependent) {
+ // OpenMP [2.11.4 allocate Clause, Description]
+ // allocator is an expression of omp_allocator_handle_t type.
+ if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack))
+ return nullptr;
- ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
- if (AllocatorRes.isInvalid())
- return nullptr;
- AllocatorRes = SemaRef.PerformImplicitConversion(
- AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
- AssignmentAction::Initializing,
- /*AllowExplicit=*/true);
- if (AllocatorRes.isInvalid())
- return nullptr;
- Allocator = AllocatorRes.get();
+ ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
+ if (AllocatorRes.isInvalid())
+ return nullptr;
+ AllocatorRes = SemaRef.PerformImplicitConversion(
+ AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
+ AssignmentAction::Initializing,
+ /*AllowExplicit=*/true);
+ if (AllocatorRes.isInvalid())
+ return nullptr;
+ Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
+ }
} else {
// OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
// allocate clauses that appear on a target construct or on constructs in a
@@ -23199,6 +23221,17 @@ OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause(
!DSAStack->hasRequiresDeclWithClause())
SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
}
+ if (Alignment) {
+ bool AlignmentDependent = Alignment->isTypeDependent() ||
+ Alignment->isValueDependent() ||
+ Alignment->isInstantiationDependent() ||
+ Alignment->containsUnexpandedParameterPack();
+ if (!AlignmentDependent) {
+ ExprResult AlignResult =
+ VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
+ Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
+ }
+ }
// Analyze and build list of variables.
SmallVector Vars;
for (Expr *RefExpr : VarList) {
@@ -23230,11 +23263,10 @@ OMPClause *SemaOpenMP::ActOnOpenMPAllocateClause(
if (Allocator)
DSAStack->addInnerAllocatorExpr(Allocator);
- OpenMPAllocateClauseModifier AllocatorModifier = AllocClauseModifier;
- SourceLocation AllocatorModifierLoc;
- return OMPAllocateClause::Create(getASTContext(), StartLoc, LParenLoc,
- Allocator, ColonLoc, AllocatorModifier,
- AllocatorModifierLoc, EndLoc, Vars);
+ return OMPAllocateClause::Create(
+ getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
+ FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
+ SecondAllocateModifierLoc, EndLoc, Vars);
}
OMPClause *SemaOpenMP::ActOnOpenMPNontemporalClause(ArrayRef VarList,
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 106e2430de901..422d8abc1028a 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -619,6 +619,12 @@ static Attr *handleHLSLLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A,
return ::new (S.Context) HLSLLoopHintAttr(S.Context, A, UnrollFactor);
}
+static Attr *handleHLSLControlFlowHint(Sema &S, Stmt *St, const ParsedAttr &A,
+ SourceRange Range) {
+
+ return ::new (S.Context) HLSLControlFlowHintAttr(S.Context, A);
+}
+
static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
SourceRange Range) {
if (A.isInvalid() || A.getKind() == ParsedAttr::IgnoredAttribute)
@@ -655,6 +661,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
return handleLoopHintAttr(S, St, A, Range);
case ParsedAttr::AT_HLSLLoopHint:
return handleHLSLLoopHintAttr(S, St, A, Range);
+ case ParsedAttr::AT_HLSLControlFlowHint:
+ return handleHLSLControlFlowHint(S, St, A, Range);
case ParsedAttr::AT_OpenCLUnrollHint:
return handleOpenCLUnrollHint(S, St, A, Range);
case ParsedAttr::AT_Suppress:
diff --git a/clang/lib/Sema/SemaSwift.cpp b/clang/lib/Sema/SemaSwift.cpp
index 24fdfb8e57dc3..fe72d6c85c37a 100644
--- a/clang/lib/Sema/SemaSwift.cpp
+++ b/clang/lib/Sema/SemaSwift.cpp
@@ -650,8 +650,8 @@ void SemaSwift::handleNewType(Decl *D, const ParsedAttr &AL) {
}
if (!isa(D)) {
- Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str)
- << AL << AL.isRegularKeywordAttribute() << "typedefs";
+ Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << AL << AL.isRegularKeywordAttribute() << ExpectedTypedef;
return;
}
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index e3ec327c1b364..2ccf5a8e1d6f3 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -7983,8 +7983,9 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
if (!FnTy) {
// SME ACLE attributes are not supported on K&R-style unprototyped C
// functions.
- S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
- attr << attr.isRegularKeywordAttribute() << ExpectedFunctionWithProtoType;
+ S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << attr << attr.isRegularKeywordAttribute()
+ << ExpectedFunctionWithProtoType;
attr.setInvalid();
return false;
}
@@ -8676,9 +8677,9 @@ static void HandleLifetimeBoundAttr(TypeProcessingState &State,
CurType, CurType);
return;
}
- State.getSema().Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str)
+ State.getSema().Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr << Attr.isRegularKeywordAttribute()
- << "parameters and implicit object parameters";
+ << ExpectedParameterOrImplicitObjectParameter;
}
static void HandleLifetimeCaptureByAttr(TypeProcessingState &State,
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 4a3c739ecbeab..4fae2ccb5f6d0 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -2075,15 +2075,18 @@ class TreeTransform {
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
- OMPClause *RebuildOMPAllocateClause(Expr *Allocate,
- OpenMPAllocateClauseModifier ACModifier,
- ArrayRef VarList,
- SourceLocation StartLoc,
- SourceLocation LParenLoc,
- SourceLocation ColonLoc,
- SourceLocation EndLoc) {
+ OMPClause *
+ RebuildOMPAllocateClause(Expr *Allocate, Expr *Alignment,
+ OpenMPAllocateClauseModifier FirstModifier,
+ SourceLocation FirstModifierLoc,
+ OpenMPAllocateClauseModifier SecondModifier,
+ SourceLocation SecondModifierLoc,
+ ArrayRef VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation ColonLoc,
+ SourceLocation EndLoc) {
return getSema().OpenMP().ActOnOpenMPAllocateClause(
- Allocate, ACModifier, VarList, StartLoc, LParenLoc, ColonLoc, EndLoc);
+ Allocate, Alignment, FirstModifier, FirstModifierLoc, SecondModifier,
+ SecondModifierLoc, VarList, StartLoc, LParenLoc, ColonLoc, EndLoc);
}
/// Build a new OpenMP 'num_teams' clause.
@@ -11224,6 +11227,13 @@ TreeTransform::TransformOMPAllocateClause(OMPAllocateClause *C) {
return nullptr;
Allocator = AllocatorRes.get();
}
+ Expr *Alignment = C->getAlignment();
+ if (Alignment) {
+ ExprResult AlignmentRes = getDerived().TransformExpr(Alignment);
+ if (AlignmentRes.isInvalid())
+ return nullptr;
+ Alignment = AlignmentRes.get();
+ }
llvm::SmallVector Vars;
Vars.reserve(C->varlist_size());
for (auto *VE : C->varlist()) {
@@ -11233,7 +11243,9 @@ TreeTransform::TransformOMPAllocateClause(OMPAllocateClause *C) {
Vars.push_back(EVar.get());
}
return getDerived().RebuildOMPAllocateClause(
- Allocator, C->getAllocatorModifier(), Vars, C->getBeginLoc(),
+ Allocator, Alignment, C->getFirstAllocateModifier(),
+ C->getFirstAllocateModifierLoc(), C->getSecondAllocateModifier(),
+ C->getSecondAllocateModifierLoc(), Vars, C->getBeginLoc(),
C->getLParenLoc(), C->getColonLoc(), C->getEndLoc());
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index b53f99732cacc..7361cace49dd7 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -11824,10 +11824,12 @@ void OMPClauseReader::VisitOMPMapClause(OMPMapClause *C) {
}
void OMPClauseReader::VisitOMPAllocateClause(OMPAllocateClause *C) {
- C->setAllocatorModifier(Record.readEnum());
+ C->setFirstAllocateModifier(Record.readEnum());
+ C->setSecondAllocateModifier(Record.readEnum());
C->setLParenLoc(Record.readSourceLocation());
C->setColonLoc(Record.readSourceLocation());
C->setAllocator(Record.readSubExpr());
+ C->setAlignment(Record.readSubExpr());
unsigned NumVars = C->varlist_size();
SmallVector Vars;
Vars.reserve(NumVars);
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 39004fd4d4c37..345d496a93312 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -7924,10 +7924,12 @@ void OMPClauseWriter::VisitOMPMapClause(OMPMapClause *C) {
void OMPClauseWriter::VisitOMPAllocateClause(OMPAllocateClause *C) {
Record.push_back(C->varlist_size());
- Record.writeEnum(C->getAllocatorModifier());
+ Record.writeEnum(C->getFirstAllocateModifier());
+ Record.writeEnum(C->getSecondAllocateModifier());
Record.AddSourceLocation(C->getLParenLoc());
Record.AddSourceLocation(C->getColonLoc());
Record.AddStmt(C->getAllocator());
+ Record.AddStmt(C->getAlignment());
for (auto *VE : C->varlist())
Record.AddStmt(VE);
}
diff --git a/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl b/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl
new file mode 100644
index 0000000000000..a36779c05fbc9
--- /dev/null
+++ b/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-compute -ast-dump %s | FileCheck %s
+
+// CHECK: FunctionDecl 0x{{[0-9A-Fa-f]+}} <{{.*}}> {{.*}} used branch 'int (int)'
+// CHECK: AttributedStmt 0x{{[0-9A-Fa-f]+}} <
+// CHECK-NEXT: -HLSLControlFlowHintAttr 0x{{[0-9A-Fa-f]+}} <{{.*}}> branch
+export int branch(int X){
+ int resp;
+ [branch] if (X > 0) {
+ resp = -X;
+ } else {
+ resp = X * 2;
+ }
+
+ return resp;
+}
+
+// CHECK: FunctionDecl 0x{{[0-9A-Fa-f]+}} <{{.*}}> {{.*}} used flatten 'int (int)'
+// CHECK: AttributedStmt 0x{{[0-9A-Fa-f]+}} <
+// CHECK-NEXT: -HLSLControlFlowHintAttr 0x{{[0-9A-Fa-f]+}} <{{.*}}> flatten
+export int flatten(int X){
+ int resp;
+ [flatten] if (X > 0) {
+ resp = -X;
+ } else {
+ resp = X * 2;
+ }
+
+ return resp;
+}
+
+// CHECK: FunctionDecl 0x{{[0-9A-Fa-f]+}} <{{.*}}> {{.*}} used no_attr 'int (int)'
+// CHECK-NOT: AttributedStmt 0x{{[0-9A-Fa-f]+}} <
+// CHECK-NOT: -HLSLControlFlowHintAttr
+export int no_attr(int X){
+ int resp;
+ if (X > 0) {
+ resp = -X;
+ } else {
+ resp = X * 2;
+ }
+
+ return resp;
+}
diff --git a/clang/test/CXX/drs/cwg1xx.cpp b/clang/test/CXX/drs/cwg1xx.cpp
index 98eb86c929009..15bcc20b7fa2a 100644
--- a/clang/test/CXX/drs/cwg1xx.cpp
+++ b/clang/test/CXX/drs/cwg1xx.cpp
@@ -1076,6 +1076,26 @@ namespace cwg169 { // cwg169: 3.4
};
} // namespace cwg169
+namespace cwg170 { // cwg170: 3.1
+#if __cplusplus >= 201103L
+struct A {};
+struct B : A { int i; };
+struct C : A {};
+struct D : C {};
+
+constexpr int f(int A::*) { return 0; }
+constexpr int g(int C::*) { return 0; }
+constexpr int h(int D::*) { return 0; }
+
+constexpr auto p = static_cast(&B::i);
+constexpr auto q = f(p);
+constexpr auto r = g(p);
+// since-cxx11-error@-1 {{constexpr variable 'r' must be initialized by a constant expression}}
+constexpr auto s = h(p);
+// since-cxx11-error@-1 {{constexpr variable 's' must be initialized by a constant expression}}
+#endif
+} // namespace cwg170
+
namespace { // cwg171: 3.4
int cwg171a;
}
diff --git a/clang/test/CodeGen/AArch64/fmv-dependencies.c b/clang/test/CodeGen/AArch64/fmv-dependencies.c
index 097b85e989d86..8dda3b647fcd0 100644
--- a/clang/test/CodeGen/AArch64/fmv-dependencies.c
+++ b/clang/test/CodeGen/AArch64/fmv-dependencies.c
@@ -192,7 +192,7 @@ int caller() {
// CHECK: attributes #[[sve]] = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+v8a"
// CHECK: attributes #[[sve2]] = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+sve2,+v8a"
// CHECK: attributes #[[sve2_aes]] = { {{.*}} "target-features"="+aes,+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+sve-aes,+sve2,+sve2-aes,+v8a"
-// CHECK: attributes #[[sve2_bitperm]] = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+sve2,+sve2-bitperm,+v8a"
+// CHECK: attributes #[[sve2_bitperm]] = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+outline-atomics,+sve,+sve-bitperm,+sve2,+sve2-bitperm,+v8a"
// CHECK: attributes #[[sve2_sha3]] = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+outline-atomics,+sha2,+sha3,+sve,+sve2,+sve2-sha3,+v8a"
// CHECK: attributes #[[sve2_sm4]] = { {{.*}} "target-features"="+fp-armv8,+fullfp16,+neon,+outline-atomics,+sm4,+sve,+sve2,+sve2-sm4,+v8a"
// CHECK: attributes #[[wfxt]] = { {{.*}} "target-features"="+fp-armv8,+neon,+outline-atomics,+v8a,+wfxt"
diff --git a/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sve2_fp8_fdot.c b/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sve2_fp8_fdot.c
index 950a19115811e..2f3994df03784 100644
--- a/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sve2_fp8_fdot.c
+++ b/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sve2_fp8_fdot.c
@@ -1,12 +1,12 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2 -target-feature +fp8 -target-feature +fp8dot2 -target-feature +fp8dot4 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s
-// RUN: %clang_cc1 -x c++ -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +fp8 -target-feature +ssve-fp8dot2 -target-feature +ssve-fp8dot4 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CHECK-CXX
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2 -target-feature +fp8dot2 -target-feature +fp8dot4 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s
+// RUN: %clang_cc1 -x c++ -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +ssve-fp8dot2 -target-feature +ssve-fp8dot4 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CHECK-CXX
-// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2 -target-feature +fp8 -target-feature +fp8dot2 -target-feature +fp8dot4 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s
-// RUN: %clang_cc1 -x c++ -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +fp8 -target-feature +ssve-fp8dot2 -target-feature +ssve-fp8dot4 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CHECK-CXX
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2 -target-feature +fp8dot2 -target-feature +fp8dot4 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s
+// RUN: %clang_cc1 -x c++ -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +ssve-fp8dot2 -target-feature +ssve-fp8dot4 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CHECK-CXX
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2 -target-feature +fp8 -target-feature +fp8dot2 -target-feature +fp8dot4 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sme2 -target-feature +fp8 -target-feature +ssve-fp8dot2 -target-feature +ssve-fp8dot4 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +sve2 -target-feature +fp8dot2 -target-feature +fp8dot4 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +ssve-fp8dot2 -target-feature +ssve-fp8dot4 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
// REQUIRES: aarch64-registered-target
diff --git a/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sve2_fp8_reinterpret.c b/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sve2_fp8_reinterpret.c
new file mode 100644
index 0000000000000..7c70bcf6b4d66
--- /dev/null
+++ b/clang/test/CodeGen/AArch64/fp8-intrinsics/acle_sve2_fp8_reinterpret.c
@@ -0,0 +1,3182 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +fp8 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg | FileCheck %s
+// RUN: %clang_cc1 -x c++ -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +fp8 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg | FileCheck %s -check-prefix=CHECK-CXX
+
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +fp8 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg | FileCheck %s
+// RUN: %clang_cc1 -x c++ -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +fp8 -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | opt -S -p mem2reg | FileCheck %s -check-prefix=CHECK-CXX
+
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +fp8 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +fp8 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
+
+// REQUIRES: aarch64-registered-target
+
+#ifdef __ARM_FEATURE_SME
+#include
+#else
+#include
+#endif
+
+#ifdef SVE_OVERLOADED_FORMS
+#define SVE_ACLE_FUNC(A1, A2_UNUSED) A1
+#else
+#define SVE_ACLE_FUNC(A1, A2) A1##A2
+#endif
+
+#ifdef __ARM_FEATURE_SME
+#define STREAMING __arm_streaming
+#else
+#define STREAMING
+#endif
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_s8_mf8(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret [[OP]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z25test_svreinterpret_s8_mf8u13__SVMfloat8_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: ret [[OP]]
+//
+svint8_t test_svreinterpret_s8_mf8(svmfloat8_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_s8, _mf8)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_u8_mf8(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret [[OP]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z25test_svreinterpret_u8_mf8u13__SVMfloat8_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: ret [[OP]]
+//
+svuint8_t test_svreinterpret_u8_mf8(svmfloat8_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_u8, _mf8)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_mf8_s8(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret [[OP]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z25test_svreinterpret_mf8_s8u10__SVInt8_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: ret [[OP]]
+//
+svmfloat8_t test_svreinterpret_mf8_s8(svint8_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_mf8, _s8)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_mf8_u8(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret [[OP]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z25test_svreinterpret_mf8_u8u11__SVUint8_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: ret [[OP]]
+//
+svmfloat8_t test_svreinterpret_mf8_u8(svuint8_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_mf8, _u8)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_mf8_mf8(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: ret [[OP]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z26test_svreinterpret_mf8_mf8u13__SVMfloat8_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: ret [[OP]]
+//
+svmfloat8_t test_svreinterpret_mf8_mf8(svmfloat8_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_mf8, _mf8)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_mf8_s16(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-NEXT: ret [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z26test_svreinterpret_mf8_s16u11__SVInt16_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-CXX-NEXT: ret [[TMP0]]
+//
+svmfloat8_t test_svreinterpret_mf8_s16(svint16_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_mf8, _s16)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_mf8_u16(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-NEXT: ret [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z26test_svreinterpret_mf8_u16u12__SVUint16_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-CXX-NEXT: ret [[TMP0]]
+//
+svmfloat8_t test_svreinterpret_mf8_u16(svuint16_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_mf8, _u16)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_mf8_s32(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-NEXT: ret [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z26test_svreinterpret_mf8_s32u11__SVInt32_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-CXX-NEXT: ret [[TMP0]]
+//
+svmfloat8_t test_svreinterpret_mf8_s32(svint32_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_mf8, _s32)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_mf8_u32(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-NEXT: ret [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z26test_svreinterpret_mf8_u32u12__SVUint32_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-CXX-NEXT: ret [[TMP0]]
+//
+svmfloat8_t test_svreinterpret_mf8_u32(svuint32_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_mf8, _u32)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_mf8_s64(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-NEXT: ret [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z26test_svreinterpret_mf8_s64u11__SVInt64_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-CXX-NEXT: ret [[TMP0]]
+//
+svmfloat8_t test_svreinterpret_mf8_s64(svint64_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_mf8, _s64)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_mf8_u64(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-NEXT: ret [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z26test_svreinterpret_mf8_u64u12__SVUint64_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-CXX-NEXT: ret [[TMP0]]
+//
+svmfloat8_t test_svreinterpret_mf8_u64(svuint64_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_mf8, _u64)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_mf8_f16(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-NEXT: ret [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z26test_svreinterpret_mf8_f16u13__SVFloat16_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-CXX-NEXT: ret [[TMP0]]
+//
+svmfloat8_t test_svreinterpret_mf8_f16(svfloat16_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_mf8, _f16)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_mf8_bf16(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-NEXT: ret [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z27test_svreinterpret_mf8_bf16u14__SVBfloat16_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-CXX-NEXT: ret [[TMP0]]
+//
+svmfloat8_t test_svreinterpret_mf8_bf16(svbfloat16_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_mf8, _bf16)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_mf8_f32(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-NEXT: ret [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z26test_svreinterpret_mf8_f32u13__SVFloat32_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-CXX-NEXT: ret [[TMP0]]
+//
+svmfloat8_t test_svreinterpret_mf8_f32(svfloat32_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_mf8, _f32)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_mf8_f64(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-NEXT: ret [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z26test_svreinterpret_mf8_f64u13__SVFloat64_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-CXX-NEXT: ret [[TMP0]]
+//
+svmfloat8_t test_svreinterpret_mf8_f64(svfloat64_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_mf8, _f64)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_s16_mf8(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-NEXT: ret [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z26test_svreinterpret_s16_mf8u13__SVMfloat8_t(
+// CHECK-CXX-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-CXX-NEXT: [[ENTRY:.*:]]
+// CHECK-CXX-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-CXX-NEXT: ret [[TMP0]]
+//
+svint16_t test_svreinterpret_s16_mf8(svmfloat8_t op) STREAMING {
+ return SVE_ACLE_FUNC(svreinterpret_s16, _mf8)(op);
+}
+
+// CHECK-LABEL: define dso_local @test_svreinterpret_u16_mf8(
+// CHECK-SAME: [[OP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT: [[ENTRY:.*:]]
+// CHECK-NEXT: [[TMP0:%.*]] = bitcast [[OP]] to
+// CHECK-NEXT: ret [[TMP0]]
+//
+// CHECK-CXX-LABEL: define dso_local @_Z26test_svreinterpret_u16_mf8u13__SVMfloat8_t(
+// CHECK-CXX-SAME: