diff --git a/.github/workflows/containers/github-action-ci/Dockerfile b/.github/workflows/containers/github-action-ci/Dockerfile index 58355d261c43c..3757e603f8a10 100644 --- a/.github/workflows/containers/github-action-ci/Dockerfile +++ b/.github/workflows/containers/github-action-ci/Dockerfile @@ -57,6 +57,7 @@ RUN apt-get update && \ nodejs \ perl-modules \ python3-psutil \ + sudo \ # These are needed by the premerge pipeline. Pip is used to install # dependent python packages and ccache is used for build caching. File and @@ -66,6 +67,16 @@ RUN apt-get update && \ file \ tzdata +# Install sccache as it is needed by most of the project test workflows and +# cannot be installed by the ccache action when executing as a non-root user. +# TODO(boomanaiden154): This should be switched to being installed with apt +# once we bump to Ubuntu 24.04. +RUN curl -L 'https://github.com/mozilla/sccache/releases/download/v0.7.6/sccache-v0.7.6-x86_64-unknown-linux-musl.tar.gz' > /tmp/sccache.tar.gz && \ + echo "2902a5e44c3342132f07b62e70cca75d9b23252922faf3b924f449808cc1ae58 /tmp/sccache.tar.gz" | sha256sum -c && \ + tar xzf /tmp/sccache.tar.gz -O --wildcards '*/sccache' > '/usr/local/bin/sccache' && \ + rm /tmp/sccache.tar.gz && \ + chmod +x /usr/local/bin/sccache + ENV LLVM_SYSROOT=$LLVM_SYSROOT ENV PATH=${LLVM_SYSROOT}/bin:${PATH} @@ -73,5 +84,11 @@ ENV PATH=${LLVM_SYSROOT}/bin:${PATH} # permissions issues in some tests. Set the user id to 1001 as that is the # user id that Github Actions uses to perform the checkout action. RUN useradd gha -u 1001 -m -s /bin/bash + +# Also add the user to passwordless sudoers so that we can install software +# later on without having to rebuild the container. +RUN adduser gha sudo +RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers + USER gha diff --git a/.github/workflows/premerge.yaml b/.github/workflows/premerge.yaml index 7a9762812cc18..261dc8bbb97e0 100644 --- a/.github/workflows/premerge.yaml +++ b/.github/workflows/premerge.yaml @@ -31,6 +31,12 @@ jobs: - name: Setup ccache uses: hendrikmuhs/ccache-action@v1.2.14 - name: Build and Test + # Mark the job as a success even if the step fails so that people do + # not get notified while the new premerge pipeline is in an + # experimental state. + # TODO(boomanaiden154): Remove this once the pipeline is stable and we + # are ready for people to start recieving notifications. + continue-on-error: true run: | git config --global --add safe.directory '*' diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedLocalNonTrivialVariableCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedLocalNonTrivialVariableCheck.cpp index 37baae7a6f0c3..ac494152fdfdb 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedLocalNonTrivialVariableCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedLocalNonTrivialVariableCheck.cpp @@ -15,6 +15,7 @@ #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/ASTMatchers/ASTMatchersMacros.h" +#include "clang/Basic/LangOptions.h" using namespace clang::ast_matchers; using namespace clang::tidy::matchers; @@ -29,6 +30,13 @@ static constexpr StringRef DefaultIncludeTypeRegex = AST_MATCHER(VarDecl, isLocalVarDecl) { return Node.isLocalVarDecl(); } AST_MATCHER(VarDecl, isReferenced) { return Node.isReferenced(); } +AST_MATCHER(VarDecl, explicitMarkUnused) { + // Implementations should not emit a warning that a name-independent + // declaration is used or unused. + LangOptions const &LangOpts = Finder->getASTContext().getLangOpts(); + return Node.hasAttr() || + (LangOpts.CPlusPlus26 && Node.isPlaceholderVar(LangOpts)); +} AST_MATCHER(Type, isReferenceType) { return Node.isReferenceType(); } AST_MATCHER(QualType, isTrivial) { return Node.isTrivialType(Finder->getASTContext()) || @@ -60,7 +68,7 @@ void UnusedLocalNonTrivialVariableCheck::registerMatchers(MatchFinder *Finder) { varDecl(isLocalVarDecl(), unless(isReferenced()), unless(isExceptionVariable()), hasLocalStorage(), isDefinition(), unless(hasType(isReferenceType())), unless(hasType(isTrivial())), - unless(hasAttr(attr::Kind::Unused)), + unless(explicitMarkUnused()), hasType(hasUnqualifiedDesugaredType( anyOf(recordType(hasDeclaration(namedDecl( matchesAnyListedName(IncludeTypes), diff --git a/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp b/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp index 49a94045ea487..2c7f50d8c9e4c 100644 --- a/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp +++ b/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp @@ -208,12 +208,13 @@ TEST_F(LSPTest, ClangTidyRename) { Annotations Source(R"cpp( void [[foo]]() {} )cpp"); - Opts.ClangTidyProvider = [](tidy::ClangTidyOptions &ClangTidyOpts, - llvm::StringRef) { + constexpr auto ClangTidyProvider = [](tidy::ClangTidyOptions &ClangTidyOpts, + llvm::StringRef) { ClangTidyOpts.Checks = {"-*,readability-identifier-naming"}; ClangTidyOpts.CheckOptions["readability-identifier-naming.FunctionCase"] = "CamelCase"; }; + Opts.ClangTidyProvider = ClangTidyProvider; auto &Client = start(); Client.didOpen("foo.hpp", Header.code()); Client.didOpen("foo.cpp", Source.code()); @@ -266,10 +267,11 @@ TEST_F(LSPTest, ClangTidyCrash_Issue109367) { // This test requires clang-tidy checks to be linked in. if (!CLANGD_TIDY_CHECKS) return; - Opts.ClangTidyProvider = [](tidy::ClangTidyOptions &ClangTidyOpts, - llvm::StringRef) { + constexpr auto ClangTidyProvider = [](tidy::ClangTidyOptions &ClangTidyOpts, + llvm::StringRef) { ClangTidyOpts.Checks = {"-*,boost-use-ranges"}; }; + Opts.ClangTidyProvider = ClangTidyProvider; // Check that registering the boost-use-ranges checker's matchers // on two different threads does not cause a crash. auto &Client = start(); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 35cb3e387e4e6..19c59f5b32eed 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -241,6 +241,10 @@ Changes in existing checks ` check to allow specifying additional functions to match. +- Improved :doc:`bugprone-unused-local-non-trivial-variable + ` check to avoid + false positives when using name-independent variables after C++26. + - Improved :doc:`bugprone-use-after-move ` to avoid triggering on ``reset()`` calls on moved-from ``std::optional`` and ``std::any`` objects, @@ -346,6 +350,10 @@ Changes in existing checks file path for anonymous enums in the diagnostic, and by fixing a typo in the diagnostic. +- Improved :doc:`readability-identifier-naming + ` check to + validate ``namespace`` aliases. + - Improved :doc:`readability-implicit-bool-conversion ` check by adding the option `UseUpperCaseLiteralSuffix` to select the @@ -356,10 +364,6 @@ Changes in existing checks ` check to remove `->`, when redundant `get()` is removed. -- Improved :doc:`readability-identifier-naming - ` check to - validate ``namespace`` aliases. - Removed checks ^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-local-non-trivial-variable.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-local-non-trivial-variable.rst index 9f283de78fbde..672eab62b4af6 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-local-non-trivial-variable.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-local-non-trivial-variable.rst @@ -12,6 +12,7 @@ The following types of variables are excluded from this check: * static or thread local * structured bindings * variables with ``[[maybe_unused]]`` attribute +* name-independent variables This check can be configured to warn on all non-trivial variables by setting `IncludeTypes` to `.*`, and excluding specific types using `ExcludeTypes`. diff --git a/clang-tools-extra/include-cleaner/lib/Analysis.cpp b/clang-tools-extra/include-cleaner/lib/Analysis.cpp index 16013f53894e8..e3a4834cb19ae 100644 --- a/clang-tools-extra/include-cleaner/lib/Analysis.cpp +++ b/clang-tools-extra/include-cleaner/lib/Analysis.cpp @@ -85,8 +85,9 @@ analyze(llvm::ArrayRef ASTRoots, const auto MainFile = *SM.getFileEntryRefForID(SM.getMainFileID()); llvm::DenseSet Used; llvm::StringMap
Missing; + constexpr auto DefaultHeaderFilter = [](llvm::StringRef) { return false; }; if (!HeaderFilter) - HeaderFilter = [](llvm::StringRef) { return false; }; + HeaderFilter = DefaultHeaderFilter; OptionalDirectoryEntryRef ResourceDir = PP.getHeaderSearchInfo().getModuleMap().getBuiltinDir(); walkUsed(ASTRoots, MacroRefs, PI, PP, diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable-name-independence.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable-name-independence.cpp new file mode 100644 index 0000000000000..bcc8b810acabf --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-local-non-trivial-variable-name-independence.cpp @@ -0,0 +1,21 @@ +// RUN: %check_clang_tidy -std=c++23 -check-suffixes=,CXX23 %s bugprone-unused-local-non-trivial-variable %t -- \ +// RUN: -config="{CheckOptions: {bugprone-unused-local-non-trivial-variable.IncludeTypes: '::async::Foo'}}" \ +// RUN: -- +// RUN: %check_clang_tidy -std=c++26 %s bugprone-unused-local-non-trivial-variable %t -- \ +// RUN: -config="{CheckOptions: {bugprone-unused-local-non-trivial-variable.IncludeTypes: '::async::Foo'}}" \ +// RUN: -- + +namespace async { +class Foo { + public: + ~Foo(); + private: +}; +} // namespace async + +void check() { + async::Foo C; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: unused local variable 'C' of type 'async::Foo' [bugprone-unused-local-non-trivial-variable] + async::Foo _; + // CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: unused local variable '_' of type 'async::Foo' [bugprone-unused-local-non-trivial-variable] +} diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 18f9e7d6c0ea0..48dfd9cac0033 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -3462,6 +3462,21 @@

Narrowing Matchers

+Matcher<DependentNameType>hasDependentNamestd::string N +
Matches the dependent name of a DependentNameType.
+
+Matches the dependent name of a DependentNameType
+
+Given:
+
+  template <typename T< struct declToImport {
+    typedef typename T::type dependent_name;
+  };
+
+dependentNameType(hasDependentName("type")) matches `T::type`
+
+ + Matcher<CXXDependentScopeMemberExpr>memberHasSameNameAsBoundNodestd::string BindingID
Matches template-dependent, but known, member names against an already-bound
 node
diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst
index 481362dba3f51..a1cb7fe359ebf 100644
--- a/clang/docs/OpenMPSupport.rst
+++ b/clang/docs/OpenMPSupport.rst
@@ -320,7 +320,9 @@ implementation.
 +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
 | misc                         | nothing directive                                            | :good:`done`             | D123286                                                               |
 +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
-| misc                         | masked construct and related combined constructs             | :part:`worked on`        | D99995, D100514                                                       |
+| misc                         | masked construct and related combined constructs             | :good:`done`             | D99995, D100514, PR-121741(parallel_masked_taskloop)                  |
+|                              |                                                              |                          | PR-121746(parallel_masked_task_loop_simd),PR-121914(masked_taskloop)  |
+|                              |                                                              |                          | PR-121916(masked_taskloop_simd)                                       |
 +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
 | misc                         | default(firstprivate) & default(private)                     | :good:`done`             | D75591 (firstprivate), D125912 (private)                              |
 +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
@@ -343,6 +345,124 @@ implementation.
 | task                         | nowait clause on taskwait                                    | :part:`partial`          | parsing/sema done: D131830, D141531                                   |
 +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
 
+
+.. _OpenMP 6.0 implementation details:
+
+OpenMP 6.0 Implementation Details
+=================================
+
+The following table provides a quick overview over various OpenMP 6.0 features
+and their implementation status. Please post on the
+`Discourse forums (Runtimes - OpenMP category)`_ for more
+information or if you want to help with the
+implementation.
+
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+|Feature                                                      | C/C++ Status              |  Fortran Status           | Reviews                                                                  |
++=============================================================+===========================+===========================+==========================================================================+
+| free-agent threads                                          | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Recording of task graphs                                    | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Parallel inductions                                         | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| init_complete for scan directive                            | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Loop transformation constructs                              | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| work distribute construct                                   | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| task_iteration                                              | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| memscope clause for atomic and flush                        | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| transparent clause (hull tasks)                             | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| rule-based compound directives                              | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| C23, C++23                                                  | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Fortran 2023                                                | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| decl attribute for declarative directives                   | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| C attribute syntax                                          | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| pure directives in DO CONCURRENT                            | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Optional argument for all clauses                           | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Function references for locator list items                  | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| All clauses accept directive name modifier                  | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Extensions to depobj construct                              | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Extensions to atomic construct                              | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Private reductions                                          | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Self maps                                                   | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Release map type for declare mapper                         | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Extensions to interop construct                             | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| no_openmp_constructs                                        | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| safe_sync and progress with identifier and API              | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| OpenMP directives in concurrent loop regions                | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| atomics constructs on concurrent loop regions               | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Loop construct with DO CONCURRENT                           | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| device_type clause for target construct                     | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| nowait for ancestor target directives                       | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| New API for devices' num_teams/thread_limit                 | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Host and device environment variables                       | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| num_threads ICV and clause accepts list                     | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Numeric names for environment variables                     | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Increment between places for OMP_PLACES                     | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| OMP_AVAILABLE_DEVICES envirable                             | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Traits for default device envirable                         | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Optionally omit array length expression                     | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Canonical loop sequences                                    | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Clarifications to Fortran map semantics                     | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| default clause at target construct                          | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| ref count update use_device_{ptr, addr}                     | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Clarifications to implicit reductions                       | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| ref modifier for map clauses                                | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| map-type modifiers in arbitrary position                    | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| atomic constructs in loop region                            | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Lift nesting restriction on concurrent loop                 | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| priority clause for target constructs                       | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| changes to target_data construct                            | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+| Non-const do_not_sync for nowait/nogroup                    | :none:`unclaimed`         | :none:`unclaimed`         |                                                                          |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
+
 OpenMP Extensions
 =================
 
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 93915e5db7d13..c50260b548851 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -553,6 +553,8 @@ Attribute Changes in Clang
 - Clang now permits the usage of the placement new operator in ``[[msvc::constexpr]]``
   context outside of the std namespace. (#GH74924)
 
+- Clang now disallows the use of attributes after the namespace name. (#GH121407)
+
 Improvements to Clang's diagnostics
 -----------------------------------
 
@@ -767,6 +769,9 @@ Bug Fixes in This Version
 - Fixed a crash when passing the variable length array type to ``va_arg`` (#GH119360).
 - Fixed a failed assertion when using ``__attribute__((noderef))`` on an
   ``_Atomic``-qualified type (#GH116124).
+- No longer incorrectly diagnosing use of a deleted destructor when the
+  selected overload of ``operator delete`` for that type is a destroying delete
+  (#GH46818).
 - No longer return ``false`` for ``noexcept`` expressions involving a
   ``delete`` which resolves to a destroying delete but the type of the object
   being deleted has a potentially throwing destructor (#GH118660).
@@ -1130,7 +1135,7 @@ AST Matchers
 
 - Add ``dependentTemplateSpecializationType`` matcher to match a dependent template specialization type.
 
-- Add ``hasDependentName`` matcher to match the dependent name of a DependentScopeDeclRefExpr.
+- Add ``hasDependentName`` matcher to match the dependent name of a DependentScopeDeclRefExpr or DependentNameType.
 
 clang-format
 ------------
@@ -1283,6 +1288,12 @@ Sanitizers
   by the compiler (for example,
   ``-fno-sanitize-merge=bool,enum,array-bounds,local-bounds``).
 
+- Changed ``-fsanitize=pointer-overflow`` to no longer report ``NULL + 0`` as
+  undefined behavior in C, in line with
+  `N3322 `_,
+  and matching the previous behavior for C++.
+  ``NULL + non_zero`` continues to be reported as undefined behavior.
+
 Python Binding Changes
 ----------------------
 - Fixed an issue that led to crashes when calling ``Type.get_exception_specification_kind``.
@@ -1297,6 +1308,8 @@ OpenMP Support
 - Changed the OpenMP DeviceRTL to use 'generic' IR. The
   ``LIBOMPTARGET_DEVICE_ARCHITECTURES`` CMake argument is now unused and will
   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.
 
 Improvements
 ^^^^^^^^^^^^
diff --git a/clang/docs/UndefinedBehaviorSanitizer.rst b/clang/docs/UndefinedBehaviorSanitizer.rst
index b9ee4484fb9ae..c4895fb9722bf 100644
--- a/clang/docs/UndefinedBehaviorSanitizer.rst
+++ b/clang/docs/UndefinedBehaviorSanitizer.rst
@@ -177,7 +177,7 @@ Available checks are:
      problems at higher optimization levels.
   -  ``-fsanitize=pointer-overflow``: Performing pointer arithmetic which
      overflows, or where either the old or new pointer value is a null pointer
-     (or in C, when they both are).
+     (excluding the case where both are null pointers).
   -  ``-fsanitize=return``: In C++, reaching the end of a
      value-returning function without returning a value.
   -  ``-fsanitize=returns-nonnull-attribute``: Returning null pointer
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index c232556edeff7..fa3f4ec98eb36 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -2855,6 +2855,11 @@ class CXXDestructorDecl : public CXXMethodDecl {
     return getCanonicalDecl()->OperatorDeleteThisArg;
   }
 
+  /// Will this destructor ever be called when considering which deallocation
+  /// function is associated with the destructor? Can optionally be passed an
+  /// 'operator delete' function declaration to test against specifically.
+  bool isCalledByDelete(const FunctionDecl *OpDel = nullptr) const;
+
   CXXDestructorDecl *getCanonicalDecl() override {
     return cast(FunctionDecl::getCanonicalDecl());
   }
diff --git a/clang/include/clang/AST/OpenACCClause.h b/clang/include/clang/AST/OpenACCClause.h
index adc5e48583d00..4e4dd3447926e 100644
--- a/clang/include/clang/AST/OpenACCClause.h
+++ b/clang/include/clang/AST/OpenACCClause.h
@@ -327,18 +327,89 @@ class OpenACCIfClause : public OpenACCClauseWithCondition {
                                  SourceLocation EndLoc);
 };
 
-/// A 'self' clause, which has an optional condition expression.
-class OpenACCSelfClause : public OpenACCClauseWithCondition {
+/// A 'self' clause, which has an optional condition expression, or, in the
+/// event of an 'update' directive, contains a 'VarList'.
+class OpenACCSelfClause final
+    : public OpenACCClauseWithParams,
+      private llvm::TrailingObjects {
+  friend TrailingObjects;
+  // Holds whether this HAS a condition expression. Lacks a value if this is NOT
+  // a condition-expr self clause.
+  std::optional HasConditionExpr;
+  // Holds the number of stored expressions.  In the case of a condition-expr
+  // self clause, this is expected to be ONE (and there to be 1 trailing
+  // object), whether or not that is null.
+  unsigned NumExprs;
+
   OpenACCSelfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
                     Expr *ConditionExpr, SourceLocation EndLoc);
+  OpenACCSelfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
+                    ArrayRef VarList, SourceLocation EndLoc);
+
+  // Intentionally internal, meant to be an implementation detail of everything
+  // else. All non-internal uses should go through getConditionExpr/getVarList.
+  llvm::ArrayRef getExprs() const {
+    return {getTrailingObjects(), NumExprs};
+  }
 
 public:
   static bool classof(const OpenACCClause *C) {
     return C->getClauseKind() == OpenACCClauseKind::Self;
   }
+
+  bool isConditionExprClause() const { return HasConditionExpr.has_value(); }
+
+  bool hasConditionExpr() const {
+    assert(HasConditionExpr.has_value() &&
+           "VarList Self Clause asked about condition expression");
+    return *HasConditionExpr;
+  }
+
+  const Expr *getConditionExpr() const {
+    assert(HasConditionExpr.has_value() &&
+           "VarList Self Clause asked about condition expression");
+    assert(getExprs().size() == 1 &&
+           "ConditionExpr Self Clause with too many Exprs");
+    return getExprs()[0];
+  }
+
+  Expr *getConditionExpr() {
+    assert(HasConditionExpr.has_value() &&
+           "VarList Self Clause asked about condition expression");
+    assert(getExprs().size() == 1 &&
+           "ConditionExpr Self Clause with too many Exprs");
+    return getExprs()[0];
+  }
+
+  ArrayRef getVarList() {
+    assert(!HasConditionExpr.has_value() &&
+           "Condition Expr self clause asked about var list");
+    return getExprs();
+  }
+  ArrayRef getVarList() const {
+    assert(!HasConditionExpr.has_value() &&
+           "Condition Expr self clause asked about var list");
+    return getExprs();
+  }
+
+  child_range children() {
+    return child_range(
+        reinterpret_cast(getTrailingObjects()),
+        reinterpret_cast(getTrailingObjects() + NumExprs));
+  }
+
+  const_child_range children() const {
+    child_range Children = const_cast(this)->children();
+    return const_child_range(Children.begin(), Children.end());
+  }
+
   static OpenACCSelfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
                                    SourceLocation LParenLoc,
                                    Expr *ConditionExpr, SourceLocation EndLoc);
+  static OpenACCSelfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
+                                   SourceLocation LParenLoc,
+                                   ArrayRef ConditionExpr,
+                                   SourceLocation EndLoc);
 };
 
 /// Represents a clause that has one or more expressions associated with it.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index f10135d7a901f..f32170c93bee2 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -3257,15 +3257,27 @@ AST_MATCHER_P(CXXDependentScopeMemberExpr, memberHasSameNameAsBoundNode,
       });
 }
 
-/// Matches the dependent name of a DependentScopeDeclRefExpr
+/// Matches the dependent name of a DependentScopeDeclRefExpr or
+/// DependentNameType
 ///
 /// Given:
 /// \code
 ///  template  class X : T { void f() { T::v; } };
 /// \endcode
 /// \c dependentScopeDeclRefExpr(hasDependentName("v")) matches `T::v`
-AST_MATCHER_P(DependentScopeDeclRefExpr, hasDependentName, std::string, N) {
-  return Node.getDeclName().getAsString() == N;
+///
+/// Given:
+/// \code
+///  template  struct declToImport {
+///    typedef typename T::type dependent_name;
+///  };
+/// \endcode
+/// \c dependentNameType(hasDependentName("type")) matches `T::type`
+AST_POLYMORPHIC_MATCHER_P(hasDependentName,
+                          AST_POLYMORPHIC_SUPPORTED_TYPES(
+                              DependentScopeDeclRefExpr, DependentNameType),
+                          std::string, N) {
+  return internal::getDependentName(Node) == N;
 }
 
 /// Matches C++ classes that are directly or indirectly derived from a class
@@ -7724,7 +7736,7 @@ AST_MATCHER_P(DecayedType, hasDecayedType, internal::Matcher,
 
 /// Matches a dependent name type
 ///
-/// Example matches  T::type
+/// Example matches T::type
 /// \code
 ///  template  struct declToImport {
 ///    typedef typename T::type dependent_name;
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index 04804d5def046..1f7b5e7cac846 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -2343,6 +2343,14 @@ MatchTemplateArgLocAt(const TemplateSpecializationTypeLoc &Node,
          InnerMatcher.matches(Node.getArgLoc(Index), Finder, Builder);
 }
 
+inline std::string getDependentName(const DependentScopeDeclRefExpr &node) {
+  return node.getDeclName().getAsString();
+}
+
+inline std::string getDependentName(const DependentNameType &node) {
+  return node.getIdentifier()->getName().str();
+}
+
 } // namespace internal
 
 } // namespace ast_matchers
diff --git a/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h b/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h
index 48c5287367739..aaf89f4e94d4a 100644
--- a/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h
+++ b/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h
@@ -13,7 +13,9 @@
 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CACHED_CONST_ACCESSORS_LATTICE_H
 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CACHED_CONST_ACCESSORS_LATTICE_H
 
+#include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
@@ -71,10 +73,27 @@ template  class CachedConstAccessorsLattice : public Base {
   /// Requirements:
   ///
   ///  - `CE` should return a location (GLValue or a record type).
+  ///
+  /// DEPRECATED: switch users to the below overload which takes Callee and Type
+  /// directly.
   StorageLocation *getOrCreateConstMethodReturnStorageLocation(
       const RecordStorageLocation &RecordLoc, const CallExpr *CE,
       Environment &Env, llvm::function_ref Initialize);
 
+  /// Creates or returns a previously created `StorageLocation` associated with
+  /// a const method call `obj.getFoo()` where `RecordLoc` is the
+  /// `RecordStorageLocation` of `obj`, `Callee` is the decl for `getFoo`.
+  ///
+  /// The callback `Initialize` runs on the storage location if newly created.
+  ///
+  /// Requirements:
+  ///
+  ///  - `Callee` should return a location (return type is a reference type or a
+  ///     record type).
+  StorageLocation &getOrCreateConstMethodReturnStorageLocation(
+      const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee,
+      Environment &Env, llvm::function_ref Initialize);
+
   void clearConstMethodReturnValues(const RecordStorageLocation &RecordLoc) {
     ConstMethodReturnValues.erase(&RecordLoc);
   }
@@ -212,6 +231,27 @@ CachedConstAccessorsLattice::getOrCreateConstMethodReturnStorageLocation(
   return &Loc;
 }
 
+template 
+StorageLocation &
+CachedConstAccessorsLattice::getOrCreateConstMethodReturnStorageLocation(
+    const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee,
+    Environment &Env, llvm::function_ref Initialize) {
+  assert(Callee != nullptr);
+  QualType Type = Callee->getReturnType();
+  assert(!Type.isNull());
+  assert(Type->isReferenceType() || Type->isRecordType());
+  auto &ObjMap = ConstMethodReturnStorageLocations[&RecordLoc];
+  auto it = ObjMap.find(Callee);
+  if (it != ObjMap.end())
+    return *it->second;
+
+  StorageLocation &Loc = Env.createStorageLocation(Type.getNonReferenceType());
+  Initialize(Loc);
+
+  ObjMap.insert({Callee, &Loc});
+  return Loc;
+}
+
 } // namespace dataflow
 } // namespace clang
 
diff --git a/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h b/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
index 713494178b97b..fb11c2e230e32 100644
--- a/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
+++ b/clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h
@@ -37,14 +37,13 @@ struct UncheckedOptionalAccessModelOptions {
   /// can't identify when their results are used safely (across calls),
   /// resulting in false positives in all such cases. Note: this option does not
   /// cover access through `operator[]`.
-  /// FIXME: we currently cache and equate the result of const accessors
-  /// returning pointers, so cover the case of operator-> followed by
-  /// operator->, which covers the common case of smart pointers. We also cover
-  /// some limited cases of returning references (if return type is an optional
-  /// type), so cover some cases of operator* followed by operator*. We don't
-  /// cover mixing operator-> and operator*. Once we are confident in this const
-  /// accessor caching, we shouldn't need the IgnoreSmartPointerDereference
-  /// option anymore.
+  ///
+  /// FIXME: we now cache and equate the result of const accessors
+  /// that look like unique_ptr, have both `->` (returning a pointer type) and
+  /// `*` (returning a reference type). This includes mixing `->` and
+  /// `*` in a sequence of calls as long as the object is not modified. Once we
+  /// are confident in this const accessor caching, we shouldn't need the
+  /// IgnoreSmartPointerDereference option anymore.
   bool IgnoreSmartPointerDereference = false;
 };
 
diff --git a/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h b/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h
index 3e4016518eaac..1b116a0cf76ed 100644
--- a/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h
+++ b/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h
@@ -27,8 +27,13 @@
 #include 
 
 #include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
 #include "clang/AST/Stmt.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
+#include "clang/Analysis/FlowSensitive/StorageLocation.h"
+#include "clang/Analysis/FlowSensitive/Value.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
 
 namespace clang::dataflow {
 
@@ -58,6 +63,107 @@ ast_matchers::StatementMatcher isSmartPointerLikeOperatorArrow();
 ast_matchers::StatementMatcher isSmartPointerLikeValueMethodCall();
 ast_matchers::StatementMatcher isSmartPointerLikeGetMethodCall();
 
+// Common transfer functions.
+
+/// Returns the "canonical" callee for smart pointer operators (`*` and `->`)
+/// as a key for caching.
+///
+/// We choose `*` as the canonical one, since it needs a
+/// StorageLocation anyway.
+///
+/// Note: there may be multiple `operator*` (one const, one non-const).
+/// We pick the const one, which the above provided matchers require to exist.
+const FunctionDecl *
+getCanonicalSmartPointerLikeOperatorCallee(const CallExpr *CE);
+
+/// A transfer function for `operator*` (and `value`) calls that can be
+/// cached. Runs the `InitializeLoc` callback to initialize any new
+/// StorageLocations.
+///
+/// Requirements:
+///
+/// - LatticeT should use the `CachedConstAccessorsLattice` mixin.
+template 
+void transferSmartPointerLikeCachedDeref(
+    const CallExpr *DerefExpr, RecordStorageLocation *SmartPointerLoc,
+    TransferState &State,
+    llvm::function_ref InitializeLoc);
+
+/// A transfer function for `operator->` (and `get`) calls that can be cached.
+/// Runs the `InitializeLoc` callback to initialize any new StorageLocations.
+///
+/// Requirements:
+///
+/// - LatticeT should use the `CachedConstAccessorsLattice` mixin.
+template 
+void transferSmartPointerLikeCachedGet(
+    const CallExpr *GetExpr, RecordStorageLocation *SmartPointerLoc,
+    TransferState &State,
+    llvm::function_ref InitializeLoc);
+
+template 
+void transferSmartPointerLikeCachedDeref(
+    const CallExpr *DerefExpr, RecordStorageLocation *SmartPointerLoc,
+    TransferState &State,
+    llvm::function_ref InitializeLoc) {
+  if (State.Env.getStorageLocation(*DerefExpr) != nullptr)
+    return;
+  if (SmartPointerLoc == nullptr)
+    return;
+
+  const FunctionDecl *Callee = DerefExpr->getDirectCallee();
+  if (Callee == nullptr)
+    return;
+  const FunctionDecl *CanonicalCallee =
+      getCanonicalSmartPointerLikeOperatorCallee(DerefExpr);
+  // This shouldn't happen, as we should at least find `Callee` itself.
+  assert(CanonicalCallee != nullptr);
+  if (CanonicalCallee != Callee) {
+    // When using the provided matchers, we should always get a reference to
+    // the same type.
+    assert(CanonicalCallee->getReturnType()->isReferenceType() &&
+           Callee->getReturnType()->isReferenceType());
+    assert(CanonicalCallee->getReturnType()
+               .getNonReferenceType()
+               ->getCanonicalTypeUnqualified() ==
+           Callee->getReturnType()
+               .getNonReferenceType()
+               ->getCanonicalTypeUnqualified());
+  }
+
+  StorageLocation &LocForValue =
+      State.Lattice.getOrCreateConstMethodReturnStorageLocation(
+          *SmartPointerLoc, CanonicalCallee, State.Env, InitializeLoc);
+  State.Env.setStorageLocation(*DerefExpr, LocForValue);
+}
+
+template 
+void transferSmartPointerLikeCachedGet(
+    const CallExpr *GetExpr, RecordStorageLocation *SmartPointerLoc,
+    TransferState &State,
+    llvm::function_ref InitializeLoc) {
+  if (SmartPointerLoc == nullptr)
+    return;
+
+  const FunctionDecl *CanonicalCallee =
+      getCanonicalSmartPointerLikeOperatorCallee(GetExpr);
+
+  if (CanonicalCallee != nullptr) {
+    auto &LocForValue =
+        State.Lattice.getOrCreateConstMethodReturnStorageLocation(
+            *SmartPointerLoc, CanonicalCallee, State.Env, InitializeLoc);
+    State.Env.setValue(*GetExpr,
+                       State.Env.template create(LocForValue));
+  } else {
+    // Otherwise, just cache the pointer value as if it was a const accessor.
+    Value *Val = State.Lattice.getOrCreateConstMethodReturnValue(
+        *SmartPointerLoc, GetExpr, State.Env);
+    if (Val == nullptr)
+      return;
+    State.Env.setValue(*GetExpr, *Val);
+  }
+}
+
 } // namespace clang::dataflow
 
 #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SMARTPOINTERACCESSORCACHING_H
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 6d7f65ab2c613..12faf06597008 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4335,16 +4335,6 @@ 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/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td
index f630698757c5f..ab432606edbc4 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -90,12 +90,18 @@ def note_constexpr_pointer_subtraction_not_same_array : Note<
 def note_constexpr_pointer_subtraction_zero_size : Note<
   "subtraction of pointers to type %0 of zero size">;
 def note_constexpr_pointer_comparison_unspecified : Note<
-  "comparison between '%0' and '%1' has unspecified value">;
+  "comparison between pointers to unrelated objects '%0' and '%1' has unspecified value">;
+def note_constexpr_pointer_arith_unspecified : Note<
+  "arithmetic involving unrelated objects '%0' and '%1' has unspecified value">;
 def note_constexpr_pointer_constant_comparison : Note<
   "comparison of numeric address '%0' with pointer '%1' can only be performed "
   "at runtime">;
 def note_constexpr_literal_comparison : Note<
-  "comparison of addresses of literals has unspecified value">;
+  "comparison of addresses of potentially overlapping literals has unspecified value">;
+def note_constexpr_literal_arith : Note<
+  "arithmetic on addresses of potentially overlapping literals has unspecified value">;
+def note_constexpr_repeated_literal_eval : Note<
+  "repeated evaluation of the same literal expression can produce different objects">;
 def note_constexpr_opaque_call_comparison : Note<
   "comparison against opaque constant address '%0' can only be performed at "
   "runtime">;
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index f2905f30a7c34..43c09cf1f973e 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1531,7 +1531,7 @@ class TargetInfo : public TransferrableTargetInfo,
 
   // Return the target-specific priority for features/cpus/vendors so
   // that they can be properly sorted for checking.
-  virtual unsigned getFMVPriority(ArrayRef Features) const {
+  virtual uint64_t getFMVPriority(ArrayRef Features) const {
     return 0;
   }
 
diff --git a/clang/include/clang/CodeGen/BackendUtil.h b/clang/include/clang/CodeGen/BackendUtil.h
index fc8ed4f011f92..7aa4f9db6c2e4 100644
--- a/clang/include/clang/CodeGen/BackendUtil.h
+++ b/clang/include/clang/CodeGen/BackendUtil.h
@@ -14,46 +14,46 @@
 #include 
 
 namespace llvm {
-  class BitcodeModule;
-  template  class Expected;
-  template  class IntrusiveRefCntPtr;
-  class Module;
-  class MemoryBufferRef;
-  namespace vfs {
-  class FileSystem;
-  } // namespace vfs
-}
+class BitcodeModule;
+template  class Expected;
+template  class IntrusiveRefCntPtr;
+class Module;
+class MemoryBufferRef;
+namespace vfs {
+class FileSystem;
+} // namespace vfs
+} // namespace llvm
 
 namespace clang {
-  class DiagnosticsEngine;
-  class HeaderSearchOptions;
-  class CodeGenOptions;
-  class TargetOptions;
-  class LangOptions;
-  class BackendConsumer;
-
-  enum BackendAction {
-    Backend_EmitAssembly,  ///< Emit native assembly files
-    Backend_EmitBC,        ///< Emit LLVM bitcode files
-    Backend_EmitLL,        ///< Emit human-readable LLVM assembly
-    Backend_EmitNothing,   ///< Don't emit anything (benchmarking mode)
-    Backend_EmitMCNull,    ///< Run CodeGen, but don't emit anything
-    Backend_EmitObj        ///< Emit native object files
-  };
-
-  void EmitBackendOutput(DiagnosticsEngine &Diags, const HeaderSearchOptions &,
-                         const CodeGenOptions &CGOpts,
-                         const TargetOptions &TOpts, const LangOptions &LOpts,
-                         StringRef TDesc, llvm::Module *M, BackendAction Action,
-                         llvm::IntrusiveRefCntPtr VFS,
-                         std::unique_ptr OS,
-                         BackendConsumer *BC = nullptr);
-
-  void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,
-                    llvm::MemoryBufferRef Buf);
-
-  void EmbedObject(llvm::Module *M, const CodeGenOptions &CGOpts,
-                   DiagnosticsEngine &Diags);
-}
+class DiagnosticsEngine;
+class HeaderSearchOptions;
+class CodeGenOptions;
+class TargetOptions;
+class LangOptions;
+class BackendConsumer;
+
+enum BackendAction {
+  Backend_EmitAssembly, ///< Emit native assembly files
+  Backend_EmitBC,       ///< Emit LLVM bitcode files
+  Backend_EmitLL,       ///< Emit human-readable LLVM assembly
+  Backend_EmitNothing,  ///< Don't emit anything (benchmarking mode)
+  Backend_EmitMCNull,   ///< Run CodeGen, but don't emit anything
+  Backend_EmitObj       ///< Emit native object files
+};
+
+void EmitBackendOutput(DiagnosticsEngine &Diags, const HeaderSearchOptions &,
+                       const CodeGenOptions &CGOpts, const TargetOptions &TOpts,
+                       const LangOptions &LOpts, StringRef TDesc,
+                       llvm::Module *M, BackendAction Action,
+                       llvm::IntrusiveRefCntPtr VFS,
+                       std::unique_ptr OS,
+                       BackendConsumer *BC = nullptr);
+
+void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts,
+                  llvm::MemoryBufferRef Buf);
+
+void EmbedObject(llvm::Module *M, const CodeGenOptions &CGOpts,
+                 DiagnosticsEngine &Diags);
+} // namespace clang
 
 #endif
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 0528104f05515..52823430919de 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -6945,6 +6945,9 @@ defm unsigned : OptInFC1FFlag<"unsigned", "Enables UNSIGNED type">;
 def fno_automatic : Flag<["-"], "fno-automatic">, Group,
   HelpText<"Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE">;
 
+def fsave_main_program : Flag<["-"], "fsave-main-program">, Group,
+  HelpText<"Place all variables from the main program in static memory (otherwise scalars may be placed on the stack)">;
+
 defm stack_arrays : BoolOptionWithoutMarshalling<"f", "stack-arrays",
   PosFlag,
   NegFlag>;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 18fd95f77ec22..a41f16f6dc8c9 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13062,7 +13062,6 @@ class Sema final : public SemaBase {
   ///
   /// \param SkipForSpecialization when specified, any template specializations
   /// in a traversal would be ignored.
-  ///
   /// \param ForDefaultArgumentSubstitution indicates we should continue looking
   /// when encountering a specialized member function template, rather than
   /// returning immediately.
@@ -13074,17 +13073,6 @@ class Sema final : public SemaBase {
       bool SkipForSpecialization = false,
       bool ForDefaultArgumentSubstitution = false);
 
-  /// Apart from storing the result to \p Result, this behaves the same as
-  /// another overload.
-  void getTemplateInstantiationArgs(
-      MultiLevelTemplateArgumentList &Result, const NamedDecl *D,
-      const DeclContext *DC = nullptr, bool Final = false,
-      std::optional> Innermost = std::nullopt,
-      bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
-      bool ForConstraintInstantiation = false,
-      bool SkipForSpecialization = false,
-      bool ForDefaultArgumentSubstitution = false);
-
   /// RAII object to handle the state changes required to synthesize
   /// a function body.
   class SynthesizedFunctionScope {
@@ -13354,7 +13342,7 @@ class Sema final : public SemaBase {
   ExprResult
   SubstConstraintExpr(Expr *E,
                       const MultiLevelTemplateArgumentList &TemplateArgs);
-  // Unlike the above, this does not evaluate constraints.
+  // Unlike the above, this does not evaluates constraints.
   ExprResult SubstConstraintExprWithoutSatisfaction(
       Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs);
 
@@ -14475,10 +14463,10 @@ class Sema final : public SemaBase {
       const MultiLevelTemplateArgumentList &TemplateArgs,
       SourceRange TemplateIDRange);
 
-  bool CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation,
-                                        FunctionDecl *Decl,
-                                        ArrayRef TemplateArgs,
-                                        ConstraintSatisfaction &Satisfaction);
+  bool CheckInstantiatedFunctionTemplateConstraints(
+      SourceLocation PointOfInstantiation, FunctionDecl *Decl,
+      ArrayRef TemplateArgs,
+      ConstraintSatisfaction &Satisfaction);
 
   /// \brief Emit diagnostics explaining why a constraint expression was deemed
   /// unsatisfied.
diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h
index 03abf4ab2cec8..0f86d46bc9802 100644
--- a/clang/include/clang/Sema/SemaOpenACC.h
+++ b/clang/include/clang/Sema/SemaOpenACC.h
@@ -409,6 +409,8 @@ class SemaOpenACC : public SemaBase {
               ClauseKind == OpenACCClauseKind::Detach ||
               ClauseKind == OpenACCClauseKind::DevicePtr ||
               ClauseKind == OpenACCClauseKind::Reduction ||
+              (ClauseKind == OpenACCClauseKind::Self &&
+               DirKind == OpenACCDirectiveKind::Update) ||
               ClauseKind == OpenACCClauseKind::FirstPrivate) &&
              "Parsed clause kind does not have a var-list");
 
@@ -551,6 +553,8 @@ class SemaOpenACC : public SemaBase {
               ClauseKind == OpenACCClauseKind::UseDevice ||
               ClauseKind == OpenACCClauseKind::Detach ||
               ClauseKind == OpenACCClauseKind::DevicePtr ||
+              (ClauseKind == OpenACCClauseKind::Self &&
+               DirKind == OpenACCDirectiveKind::Update) ||
               ClauseKind == OpenACCClauseKind::FirstPrivate) &&
              "Parsed clause kind does not have a var-list");
       assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn ||
@@ -590,6 +594,8 @@ class SemaOpenACC : public SemaBase {
               ClauseKind == OpenACCClauseKind::UseDevice ||
               ClauseKind == OpenACCClauseKind::Detach ||
               ClauseKind == OpenACCClauseKind::DevicePtr ||
+              (ClauseKind == OpenACCClauseKind::Self &&
+               DirKind == OpenACCDirectiveKind::Update) ||
               ClauseKind == OpenACCClauseKind::FirstPrivate) &&
              "Parsed clause kind does not have a var-list");
       assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn ||
diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h
index 59a0575ca9803..9800f75f676aa 100644
--- a/clang/include/clang/Sema/Template.h
+++ b/clang/include/clang/Sema/Template.h
@@ -522,12 +522,6 @@ enum class TemplateSubstitutionKind : char {
     llvm::PointerUnion *
     findInstantiationOf(const Decl *D);
 
-    /// Similar to \p findInstantiationOf(), but it wouldn't assert if the
-    /// instantiation was not found within the current instantiation scope. This
-    /// is helpful for on-demand declaration instantiation.
-    llvm::PointerUnion *
-    findInstantiationUnsafe(const Decl *D);
-
     void InstantiatedLocal(const Decl *D, Decl *Inst);
     void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst);
     void MakeInstantiatedLocalArgPack(const Decl *D);
diff --git a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
index 012237e0278f4..ddb078dc16e3c 100644
--- a/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
+++ b/clang/include/clang/Tooling/DependencyScanning/DependencyScanningTool.h
@@ -15,6 +15,7 @@
 #include "clang/Tooling/JSONCompilationDatabase.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/MapVector.h"
+#include 
 #include 
 #include 
 #include 
@@ -25,7 +26,7 @@ namespace dependencies {
 
 /// A callback to lookup module outputs for "-fmodule-file=", "-o" etc.
 using LookupModuleOutputCallback =
-    llvm::function_ref;
+    std::function;
 
 /// Graph of modular dependencies.
 using ModuleDepsGraph = std::vector;
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index af73c658d6a0c..8989e46e4847c 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -2969,6 +2969,28 @@ void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) {
   }
 }
 
+bool CXXDestructorDecl::isCalledByDelete(const FunctionDecl *OpDel) const {
+  // C++20 [expr.delete]p6: If the value of the operand of the delete-
+  // expression is not a null pointer value and the selected deallocation
+  // function (see below) is not a destroying operator delete, the delete-
+  // expression will invoke the destructor (if any) for the object or the
+  // elements of the array being deleted.
+  //
+  // This means we should not look at the destructor for a destroying
+  // delete operator, as that destructor is never called, unless the
+  // destructor is virtual (see [expr.delete]p8.1) because then the
+  // selected operator depends on the dynamic type of the pointer.
+  const FunctionDecl *SelectedOperatorDelete = OpDel ? OpDel : OperatorDelete;
+  if (!SelectedOperatorDelete)
+    return true;
+
+  if (!SelectedOperatorDelete->isDestroyingOperatorDelete())
+    return true;
+
+  // We have a destroying operator delete, so it depends on the dtor.
+  return isVirtual();
+}
+
 void CXXConversionDecl::anchor() {}
 
 CXXConversionDecl *CXXConversionDecl::CreateDeserialized(ASTContext &C,
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index e220f69b3a4f5..5768bb12ee38e 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -14588,8 +14588,24 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
         return Error(E);
       const Expr *LHSExpr = LHSValue.Base.dyn_cast();
       const Expr *RHSExpr = RHSValue.Base.dyn_cast();
+
+      auto DiagArith = [&](unsigned DiagID) {
+        std::string LHS = LHSValue.toString(Info.Ctx, E->getLHS()->getType());
+        std::string RHS = RHSValue.toString(Info.Ctx, E->getRHS()->getType());
+        Info.FFDiag(E, DiagID) << LHS << RHS;
+        if (LHSExpr && LHSExpr == RHSExpr)
+          Info.Note(LHSExpr->getExprLoc(),
+                    diag::note_constexpr_repeated_literal_eval)
+              << LHSExpr->getSourceRange();
+        return false;
+      };
+
       if (!LHSExpr || !RHSExpr)
-        return Error(E);
+        return DiagArith(diag::note_constexpr_pointer_arith_unspecified);
+
+      if (ArePotentiallyOverlappingStringLiterals(Info, LHSValue, RHSValue))
+        return DiagArith(diag::note_constexpr_literal_arith);
+
       const AddrLabelExpr *LHSAddrExpr = dyn_cast(LHSExpr);
       const AddrLabelExpr *RHSAddrExpr = dyn_cast(RHSExpr);
       if (!LHSAddrExpr || !RHSAddrExpr)
diff --git a/clang/lib/AST/OpenACCClause.cpp b/clang/lib/AST/OpenACCClause.cpp
index 76fea1fd47d21..da63b471d9856 100644
--- a/clang/lib/AST/OpenACCClause.cpp
+++ b/clang/lib/AST/OpenACCClause.cpp
@@ -20,7 +20,7 @@ using namespace clang;
 bool OpenACCClauseWithParams::classof(const OpenACCClause *C) {
   return OpenACCDeviceTypeClause::classof(C) ||
          OpenACCClauseWithCondition::classof(C) ||
-         OpenACCClauseWithExprs::classof(C);
+         OpenACCClauseWithExprs::classof(C) || OpenACCSelfClause::classof(C);
 }
 bool OpenACCClauseWithExprs::classof(const OpenACCClause *C) {
   return OpenACCWaitClause::classof(C) || OpenACCNumGangsClause::classof(C) ||
@@ -41,7 +41,7 @@ bool OpenACCClauseWithVarList::classof(const OpenACCClause *C) {
          OpenACCReductionClause::classof(C) || OpenACCCreateClause::classof(C);
 }
 bool OpenACCClauseWithCondition::classof(const OpenACCClause *C) {
-  return OpenACCIfClause::classof(C) || OpenACCSelfClause::classof(C);
+  return OpenACCIfClause::classof(C);
 }
 bool OpenACCClauseWithSingleIntExpr::classof(const OpenACCClause *C) {
   return OpenACCNumWorkersClause::classof(C) ||
@@ -87,19 +87,43 @@ OpenACCSelfClause *OpenACCSelfClause::Create(const ASTContext &C,
                                              SourceLocation LParenLoc,
                                              Expr *ConditionExpr,
                                              SourceLocation EndLoc) {
-  void *Mem = C.Allocate(sizeof(OpenACCIfClause), alignof(OpenACCIfClause));
+  void *Mem = C.Allocate(OpenACCSelfClause::totalSizeToAlloc(1));
   return new (Mem)
       OpenACCSelfClause(BeginLoc, LParenLoc, ConditionExpr, EndLoc);
 }
 
+OpenACCSelfClause *OpenACCSelfClause::Create(const ASTContext &C,
+                                             SourceLocation BeginLoc,
+                                             SourceLocation LParenLoc,
+                                             ArrayRef VarList,
+                                             SourceLocation EndLoc) {
+  void *Mem =
+      C.Allocate(OpenACCSelfClause::totalSizeToAlloc(VarList.size()));
+  return new (Mem) OpenACCSelfClause(BeginLoc, LParenLoc, VarList, EndLoc);
+}
+
+OpenACCSelfClause::OpenACCSelfClause(SourceLocation BeginLoc,
+                                     SourceLocation LParenLoc,
+                                     llvm::ArrayRef VarList,
+                                     SourceLocation EndLoc)
+    : OpenACCClauseWithParams(OpenACCClauseKind::Self, BeginLoc, LParenLoc,
+                              EndLoc),
+      HasConditionExpr(std::nullopt), NumExprs(VarList.size()) {
+  std::uninitialized_copy(VarList.begin(), VarList.end(),
+                          getTrailingObjects());
+}
+
 OpenACCSelfClause::OpenACCSelfClause(SourceLocation BeginLoc,
                                      SourceLocation LParenLoc,
                                      Expr *ConditionExpr, SourceLocation EndLoc)
-    : OpenACCClauseWithCondition(OpenACCClauseKind::Self, BeginLoc, LParenLoc,
-                                 ConditionExpr, EndLoc) {
+    : OpenACCClauseWithParams(OpenACCClauseKind::Self, BeginLoc, LParenLoc,
+                              EndLoc),
+      HasConditionExpr(ConditionExpr != nullptr), NumExprs(1) {
   assert((!ConditionExpr || ConditionExpr->isInstantiationDependent() ||
           ConditionExpr->getType()->isScalarType()) &&
          "Condition expression type not scalar/dependent");
+  std::uninitialized_copy(&ConditionExpr, &ConditionExpr + 1,
+                          getTrailingObjects());
 }
 
 OpenACCClause::child_range OpenACCClause::children() {
@@ -555,9 +579,17 @@ void OpenACCClausePrinter::VisitIfClause(const OpenACCIfClause &C) {
 
 void OpenACCClausePrinter::VisitSelfClause(const OpenACCSelfClause &C) {
   OS << "self";
-  if (const Expr *CondExpr = C.getConditionExpr()) {
+
+  if (C.isConditionExprClause()) {
+    if (const Expr *CondExpr = C.getConditionExpr()) {
+      OS << "(";
+      printExpr(CondExpr);
+      OS << ")";
+    }
+  } else {
     OS << "(";
-    printExpr(CondExpr);
+    llvm::interleaveComma(C.getVarList(), OS,
+                          [&](const Expr *E) { printExpr(E); });
     OS << ")";
   }
 }
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index b68c83f99550b..cd91a7900538b 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2555,8 +2555,13 @@ void OpenACCClauseProfiler::VisitCreateClause(
 }
 
 void OpenACCClauseProfiler::VisitSelfClause(const OpenACCSelfClause &Clause) {
-  if (Clause.hasConditionExpr())
-    Profiler.VisitStmt(Clause.getConditionExpr());
+  if (Clause.isConditionExprClause()) {
+    if (Clause.hasConditionExpr())
+      Profiler.VisitStmt(Clause.getConditionExpr());
+  } else {
+    for (auto *E : Clause.getVarList())
+      Profiler.VisitStmt(E);
+  }
 }
 
 void OpenACCClauseProfiler::VisitFinalizeClause(
diff --git a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
index da5dda063344f..e1394e28cd49a 100644
--- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -25,8 +25,10 @@
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/Formula.h"
 #include "clang/Analysis/FlowSensitive/RecordOps.h"
+#include "clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h"
 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
+#include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Casting.h"
@@ -555,24 +557,25 @@ void handleConstMemberCall(const CallExpr *CE,
                            LatticeTransferState &State) {
   // If the const method returns an optional or reference to an optional.
   if (RecordLoc != nullptr && isSupportedOptionalType(CE->getType())) {
-    StorageLocation *Loc =
+    const FunctionDecl *DirectCallee = CE->getDirectCallee();
+    if (DirectCallee == nullptr)
+      return;
+    StorageLocation &Loc =
         State.Lattice.getOrCreateConstMethodReturnStorageLocation(
-            *RecordLoc, CE, State.Env, [&](StorageLocation &Loc) {
+            *RecordLoc, DirectCallee, State.Env, [&](StorageLocation &Loc) {
               setHasValue(cast(Loc),
                           State.Env.makeAtomicBoolValue(), State.Env);
             });
-    if (Loc == nullptr)
-      return;
     if (CE->isGLValue()) {
       // If the call to the const method returns a reference to an optional,
       // link the call expression to the cached StorageLocation.
-      State.Env.setStorageLocation(*CE, *Loc);
+      State.Env.setStorageLocation(*CE, Loc);
     } else {
       // If the call to the const method returns an optional by value, we
       // need to use CopyRecord to link the optional to the result object
       // of the call expression.
       auto &ResultLoc = State.Env.getResultObjectLocation(*CE);
-      copyRecord(*cast(Loc), ResultLoc, State.Env);
+      copyRecord(cast(Loc), ResultLoc, State.Env);
     }
     return;
   }
@@ -1031,6 +1034,48 @@ auto buildTransferMatchSwitch() {
             transferOptionalAndValueCmp(Cmp, Cmp->getArg(1), State.Env);
           })
 
+      // Smart-pointer-like operator* and operator-> calls that may look like
+      // const accessors (below) but need special handling to allow mixing
+      // the accessor calls.
+      .CaseOfCFGStmt(
+          isSmartPointerLikeOperatorStar(),
+          [](const CXXOperatorCallExpr *E,
+             const MatchFinder::MatchResult &Result,
+             LatticeTransferState &State) {
+            transferSmartPointerLikeCachedDeref(
+                E,
+                dyn_cast_or_null(
+                    getLocBehindPossiblePointer(*E->getArg(0), State.Env)),
+                State, [](StorageLocation &Loc) {});
+          })
+      .CaseOfCFGStmt(
+          isSmartPointerLikeOperatorArrow(),
+          [](const CXXOperatorCallExpr *E,
+             const MatchFinder::MatchResult &Result,
+             LatticeTransferState &State) {
+            transferSmartPointerLikeCachedGet(
+                E,
+                dyn_cast_or_null(
+                    getLocBehindPossiblePointer(*E->getArg(0), State.Env)),
+                State, [](StorageLocation &Loc) {});
+          })
+      .CaseOfCFGStmt(
+          isSmartPointerLikeValueMethodCall(),
+          [](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &Result,
+             LatticeTransferState &State) {
+            transferSmartPointerLikeCachedDeref(
+                E, getImplicitObjectLocation(*E, State.Env), State,
+                [](StorageLocation &Loc) {});
+          })
+      .CaseOfCFGStmt(
+          isSmartPointerLikeGetMethodCall(),
+          [](const CXXMemberCallExpr *E, const MatchFinder::MatchResult &Result,
+             LatticeTransferState &State) {
+            transferSmartPointerLikeCachedGet(
+                E, getImplicitObjectLocation(*E, State.Env), State,
+                [](StorageLocation &Loc) {});
+          })
+
       // const accessor calls
       .CaseOfCFGStmt(isZeroParamConstMemberCall(),
                                         transferValue_ConstMemberCall)
diff --git a/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp b/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp
index a0c81aa933da8..c58bd309545db 100644
--- a/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp
+++ b/clang/lib/Analysis/FlowSensitive/SmartPointerAccessorCaching.cpp
@@ -132,6 +132,7 @@ ast_matchers::StatementMatcher isSmartPointerLikeOperatorArrow() {
       callee(cxxMethodDecl(parameterCountIs(0), returns(pointerType()),
                            ofClass(smartPointerClassWithGetOrValue()))));
 }
+
 ast_matchers::StatementMatcher isSmartPointerLikeValueMethodCall() {
   return cxxMemberCallExpr(callee(
       cxxMethodDecl(parameterCountIs(0), returns(referenceType()),
@@ -144,4 +145,24 @@ ast_matchers::StatementMatcher isSmartPointerLikeGetMethodCall() {
                     ofClass(smartPointerClassWithGet()))));
 }
 
+const FunctionDecl *
+getCanonicalSmartPointerLikeOperatorCallee(const CallExpr *CE) {
+  const FunctionDecl *CanonicalCallee = nullptr;
+  const CXXMethodDecl *Callee =
+      cast_or_null(CE->getDirectCallee());
+  if (Callee == nullptr)
+    return nullptr;
+  const CXXRecordDecl *RD = Callee->getParent();
+  if (RD == nullptr)
+    return nullptr;
+  for (const auto *MD : RD->methods()) {
+    if (MD->getOverloadedOperator() == OO_Star && MD->isConst() &&
+        MD->getNumParams() == 0 && MD->getReturnType()->isReferenceType()) {
+      CanonicalCallee = MD;
+      break;
+    }
+  }
+  return CanonicalCallee;
+}
+
 } // namespace clang::dataflow
diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp
index 53e102bbe4468..2b4b954d0c27a 100644
--- a/clang/lib/Basic/Targets/AArch64.cpp
+++ b/clang/lib/Basic/Targets/AArch64.cpp
@@ -714,7 +714,7 @@ AArch64TargetInfo::getVScaleRange(const LangOptions &LangOpts) const {
   return std::nullopt;
 }
 
-unsigned AArch64TargetInfo::getFMVPriority(ArrayRef Features) const {
+uint64_t AArch64TargetInfo::getFMVPriority(ArrayRef Features) const {
   return llvm::AArch64::getFMVPriority(Features);
 }
 
diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h
index 68a8b1ebad8cd..4e927c0953b1f 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -137,7 +137,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
   void fillValidCPUList(SmallVectorImpl &Values) const override;
   bool setCPU(const std::string &Name) override;
 
-  unsigned getFMVPriority(ArrayRef Features) const override;
+  uint64_t getFMVPriority(ArrayRef Features) const override;
 
   bool useFP16ConversionIntrinsics() const override {
     return false;
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index a541dfedc9b8e..db23b0c228338 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -489,7 +489,7 @@ ParsedTargetAttr RISCVTargetInfo::parseTargetAttr(StringRef Features) const {
   return Ret;
 }
 
-unsigned RISCVTargetInfo::getFMVPriority(ArrayRef Features) const {
+uint64_t RISCVTargetInfo::getFMVPriority(ArrayRef Features) const {
   // Priority is explicitly specified on RISC-V unlike on other targets, where
   // it is derived by all the features of a specific version. Therefore if a
   // feature contains the priority string, then return it immediately.
@@ -501,7 +501,7 @@ unsigned RISCVTargetInfo::getFMVPriority(ArrayRef Features) const {
       Feature = RHS;
     else
       continue;
-    unsigned Priority;
+    uint64_t Priority;
     if (!Feature.getAsInteger(0, Priority))
       return Priority;
   }
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index 68f10e74ba98c..bb3f3a5cda7c6 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -122,7 +122,7 @@ class RISCVTargetInfo : public TargetInfo {
   void fillValidTuneCPUList(SmallVectorImpl &Values) const override;
   bool supportsTargetAttributeTune() const override { return true; }
   ParsedTargetAttr parseTargetAttr(StringRef Str) const override;
-  unsigned getFMVPriority(ArrayRef Features) const override;
+  uint64_t getFMVPriority(ArrayRef Features) const override;
 
   std::pair hardwareInterferenceSizes() const override {
     return std::make_pair(32, 32);
diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp
index d2d92fb864c31..40ad8fd9a0967 100644
--- a/clang/lib/Basic/Targets/X86.cpp
+++ b/clang/lib/Basic/Targets/X86.cpp
@@ -1357,8 +1357,8 @@ static llvm::X86::ProcessorFeatures getFeature(StringRef Name) {
   // correct, so it asserts if the value is out of range.
 }
 
-unsigned X86TargetInfo::getFMVPriority(ArrayRef Features) const {
-  auto getPriority = [](StringRef Feature) -> unsigned {
+uint64_t X86TargetInfo::getFMVPriority(ArrayRef Features) const {
+  auto getPriority = [](StringRef Feature) -> uint64_t {
     // Valid CPUs have a 'key feature' that compares just better than its key
     // feature.
     using namespace llvm::X86;
@@ -1372,7 +1372,7 @@ unsigned X86TargetInfo::getFMVPriority(ArrayRef Features) const {
     return getFeaturePriority(getFeature(Feature)) << 1;
   };
 
-  unsigned Priority = 0;
+  uint64_t Priority = 0;
   for (StringRef Feature : Features)
     if (!Feature.empty())
       Priority = std::max(Priority, getPriority(Feature));
diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h
index 553c452d4ba3c..35aceb1c58e14 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -384,7 +384,7 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
     return CPU != llvm::X86::CK_None;
   }
 
-  unsigned getFMVPriority(ArrayRef Features) const override;
+  uint64_t getFMVPriority(ArrayRef Features) const override;
 
   bool setFPMath(StringRef Name) override;
 
diff --git a/clang/lib/CodeGen/BackendConsumer.h b/clang/lib/CodeGen/BackendConsumer.h
index a023d29cbd1d7..d932a78f469b9 100644
--- a/clang/lib/CodeGen/BackendConsumer.h
+++ b/clang/lib/CodeGen/BackendConsumer.h
@@ -29,17 +29,16 @@ class BackendConsumer : public ASTConsumer {
 
   virtual void anchor();
   DiagnosticsEngine &Diags;
-  BackendAction Action;
   const HeaderSearchOptions &HeaderSearchOpts;
   const CodeGenOptions &CodeGenOpts;
   const TargetOptions &TargetOpts;
   const LangOptions &LangOpts;
   std::unique_ptr AsmOutStream;
-  ASTContext *Context;
+  ASTContext *Context = nullptr;
   IntrusiveRefCntPtr FS;
 
   llvm::Timer LLVMIRGeneration;
-  unsigned LLVMIRGenerationRefCount;
+  unsigned LLVMIRGenerationRefCount = 0;
 
   /// True if we've finished generating IR. This prevents us from generating
   /// additional LLVM IR after emitting output in HandleTranslationUnit. This
@@ -48,6 +47,8 @@ class BackendConsumer : public ASTConsumer {
 
   bool TimerIsEnabled = false;
 
+  BackendAction Action;
+
   std::unique_ptr Gen;
 
   SmallVector LinkModules;
@@ -69,29 +70,12 @@ class BackendConsumer : public ASTConsumer {
   llvm::Module *CurLinkModule = nullptr;
 
 public:
-  BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
-                  IntrusiveRefCntPtr VFS,
-                  const HeaderSearchOptions &HeaderSearchOpts,
-                  const PreprocessorOptions &PPOpts,
-                  const CodeGenOptions &CodeGenOpts,
-                  const TargetOptions &TargetOpts, const LangOptions &LangOpts,
-                  const std::string &InFile,
-                  SmallVector LinkModules,
-                  std::unique_ptr OS, llvm::LLVMContext &C,
-                  CoverageSourceInfo *CoverageInfo = nullptr);
-
-  // This constructor is used in installing an empty BackendConsumer
-  // to use the clang diagnostic handler for IR input files. It avoids
-  // initializing the OS field.
-  BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
+  BackendConsumer(const CompilerInstance &CI, BackendAction Action,
                   IntrusiveRefCntPtr VFS,
-                  const HeaderSearchOptions &HeaderSearchOpts,
-                  const PreprocessorOptions &PPOpts,
-                  const CodeGenOptions &CodeGenOpts,
-                  const TargetOptions &TargetOpts, const LangOptions &LangOpts,
-                  llvm::Module *Module, SmallVector LinkModules,
-                  llvm::LLVMContext &C,
-                  CoverageSourceInfo *CoverageInfo = nullptr);
+                  llvm::LLVMContext &C, SmallVector LinkModules,
+                  StringRef InFile, std::unique_ptr OS,
+                  CoverageSourceInfo *CoverageInfo,
+                  llvm::Module *CurLinkModule = nullptr);
 
   llvm::Module *getModule() const;
   std::unique_ptr takeModule();
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index dcea32969fb99..573be932f8b1a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19212,8 +19212,9 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
     // TODO: Map to an hlsl_device address space.
     llvm::Type *RetTy = llvm::PointerType::getUnqual(getLLVMContext());
 
-    return Builder.CreateIntrinsic(RetTy, Intrinsic::dx_resource_getpointer,
-                                   ArrayRef{HandleOp, IndexOp});
+    return Builder.CreateIntrinsic(
+        RetTy, CGM.getHLSLRuntime().getCreateResourceGetPointerIntrinsic(),
+        ArrayRef{HandleOp, IndexOp});
   }
   case Builtin::BI__builtin_hlsl_all: {
     Value *Op0 = EmitScalarExpr(E->getArg(0));
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 47b21bc9f63f0..6f3ff050cb697 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -361,6 +361,8 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
     return GV;
   }
 
+  PGO.markStmtMaybeUsed(D.getInit()); // FIXME: Too lazy
+
 #ifndef NDEBUG
   CharUnits VarSize = CGM.getContext().getTypeSizeInChars(D.getType()) +
                       D.getFlexibleArrayInitChars(getContext());
@@ -1868,7 +1870,10 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
   // If we are at an unreachable point, we don't need to emit the initializer
   // unless it contains a label.
   if (!HaveInsertPoint()) {
-    if (!Init || !ContainsLabel(Init)) return;
+    if (!Init || !ContainsLabel(Init)) {
+      PGO.markStmtMaybeUsed(Init);
+      return;
+    }
     EnsureInsertPoint();
   }
 
@@ -1979,6 +1984,8 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
     return EmitExprAsInit(Init, &D, lv, capturedByInit);
   }
 
+  PGO.markStmtMaybeUsed(Init);
+
   if (!emission.IsConstantAggregate) {
     // For simple scalar/complex initialization, store the value directly.
     LValue lv = MakeAddrLValue(Loc, type);
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index ba1cba291553b..1bad7a722da07 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5148,6 +5148,7 @@ std::optional HandleConditionalOperatorLValueSimpleCase(
       // If the true case is live, we need to track its region.
       if (CondExprBool)
         CGF.incrementProfileCounter(E);
+      CGF.markStmtMaybeUsed(Dead);
       // If a throw expression we emit it and return an undefined lvalue
       // because it can't be used.
       if (auto *ThrowExpr = dyn_cast(Live->IgnoreParens())) {
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index b282d4e0b32f0..090c4fb3ea39e 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -5003,7 +5003,8 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
         CGF.incrementProfileCounter(E->getRHS());
         CGF.EmitBranch(FBlock);
         CGF.EmitBlock(FBlock);
-      }
+      } else
+        CGF.markStmtMaybeUsed(E->getRHS());
 
       CGF.MCDCLogOpStack.pop_back();
       // If the top of the logical operator nest, update the MCDC bitmap.
@@ -5015,8 +5016,10 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {
     }
 
     // 0 && RHS: If it is safe, just elide the RHS, and return 0/false.
-    if (!CGF.ContainsLabel(E->getRHS()))
+    if (!CGF.ContainsLabel(E->getRHS())) {
+      CGF.markStmtMaybeUsed(E->getRHS());
       return llvm::Constant::getNullValue(ResTy);
+    }
   }
 
   // If the top of the logical operator nest, reset the MCDC temp to 0.
@@ -5143,7 +5146,8 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
         CGF.incrementProfileCounter(E->getRHS());
         CGF.EmitBranch(FBlock);
         CGF.EmitBlock(FBlock);
-      }
+      } else
+        CGF.markStmtMaybeUsed(E->getRHS());
 
       CGF.MCDCLogOpStack.pop_back();
       // If the top of the logical operator nest, update the MCDC bitmap.
@@ -5155,8 +5159,10 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {
     }
 
     // 1 || RHS: If it is safe, just elide the RHS, and return 1/true.
-    if (!CGF.ContainsLabel(E->getRHS()))
+    if (!CGF.ContainsLabel(E->getRHS())) {
+      CGF.markStmtMaybeUsed(E->getRHS());
       return llvm::ConstantInt::get(ResTy, 1);
+    }
   }
 
   // If the top of the logical operator nest, reset the MCDC temp to 0.
@@ -5280,6 +5286,7 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
         CGF.incrementProfileCounter(E);
       }
       Value *Result = Visit(live);
+      CGF.markStmtMaybeUsed(dead);
 
       // If the live part is a throw expression, it acts like it has a void
       // type, so evaluating it returns a null Value*.  However, a conditional
@@ -5834,9 +5841,8 @@ CodeGenFunction::EmitCheckedInBoundsGEP(llvm::Type *ElemTy, Value *Ptr,
 
   auto *Zero = llvm::ConstantInt::getNullValue(IntPtrTy);
 
-  // Common case: if the total offset is zero, and we are using C++ semantics,
-  // where nullptr+0 is defined, don't emit a check.
-  if (EvaluatedGEP.TotalOffset == Zero && CGM.getLangOpts().CPlusPlus)
+  // Common case: if the total offset is zero, don't emit a check.
+  if (EvaluatedGEP.TotalOffset == Zero)
     return GEPVal;
 
   // Now that we've computed the total offset, add it to the base pointer (with
@@ -5847,23 +5853,16 @@ CodeGenFunction::EmitCheckedInBoundsGEP(llvm::Type *ElemTy, Value *Ptr,
   llvm::SmallVector, 2> Checks;
 
   if (PerformNullCheck) {
-    // In C++, if the base pointer evaluates to a null pointer value,
+    // If the base pointer evaluates to a null pointer value,
     // the only valid  pointer this inbounds GEP can produce is also
     // a null pointer, so the offset must also evaluate to zero.
     // Likewise, if we have non-zero base pointer, we can not get null pointer
     // as a result, so the offset can not be -intptr_t(BasePtr).
     // In other words, both pointers are either null, or both are non-null,
     // or the behaviour is undefined.
-    //
-    // C, however, is more strict in this regard, and gives more
-    // optimization opportunities: in C, additionally, nullptr+0 is undefined.
-    // So both the input to the 'gep inbounds' AND the output must not be null.
     auto *BaseIsNotNullptr = Builder.CreateIsNotNull(Ptr);
     auto *ResultIsNotNullptr = Builder.CreateIsNotNull(ComputedGEP);
-    auto *Valid =
-        CGM.getLangOpts().CPlusPlus
-            ? Builder.CreateICmpEQ(BaseIsNotNullptr, ResultIsNotNullptr)
-            : Builder.CreateAnd(BaseIsNotNullptr, ResultIsNotNullptr);
+    auto *Valid = Builder.CreateICmpEQ(BaseIsNotNullptr, ResultIsNotNullptr);
     Checks.emplace_back(Valid, SanitizerKind::PointerOverflow);
   }
 
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index 3d5724118611c..46e472f0aae21 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -104,6 +104,8 @@ class CGHLSLRuntime {
   GENERATE_HLSL_INTRINSIC_FUNCTION(SClamp, sclamp)
   GENERATE_HLSL_INTRINSIC_FUNCTION(UClamp, uclamp)
 
+  GENERATE_HLSL_INTRINSIC_FUNCTION(CreateResourceGetPointer,
+                                   resource_getpointer)
   GENERATE_HLSL_INTRINSIC_FUNCTION(CreateHandleFromBinding,
                                    resource_handlefrombinding)
   GENERATE_HLSL_INTRINSIC_FUNCTION(BufferUpdateCounter, resource_updatecounter)
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 30c3834de139c..1868b57cea903 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -2327,11 +2327,10 @@ void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
   auto *OMPRegionInfo =
       dyn_cast_or_null(CGF.CapturedStmtInfo);
   if (CGF.CGM.getLangOpts().OpenMPIRBuilder) {
-    llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
-        OMPBuilder.createBarrier(CGF.Builder, Kind, ForceSimpleCall,
-                                 EmitChecks);
-    assert(AfterIP && "unexpected error creating barrier");
-    CGF.Builder.restoreIP(*AfterIP);
+    llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
+        cantFail(OMPBuilder.createBarrier(CGF.Builder, Kind, ForceSimpleCall,
+                                          EmitChecks));
+    CGF.Builder.restoreIP(AfterIP);
     return;
   }
 
@@ -5933,10 +5932,9 @@ void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
         return CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc());
       };
 
-  llvm::Error Err = OMPBuilder.emitTargetRegionFunction(
+  cantFail(OMPBuilder.emitTargetRegionFunction(
       EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
-      OutlinedFnID);
-  assert(!Err && "unexpected error creating target region");
+      OutlinedFnID));
 
   if (!OutlinedFn)
     return;
@@ -9409,12 +9407,11 @@ static void emitTargetCallKernelLaunch(
         NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
         DynCGGroupMem, HasNoWait);
 
-    llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
-        OMPRuntime->getOMPBuilder().emitKernelLaunch(
+    llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
+        cantFail(OMPRuntime->getOMPBuilder().emitKernelLaunch(
             CGF.Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
-            RTLoc, AllocaIP);
-    assert(AfterIP && "unexpected error creating kernel launch");
-    CGF.Builder.restoreIP(*AfterIP);
+            RTLoc, AllocaIP));
+    CGF.Builder.restoreIP(AfterIP);
   };
 
   if (RequiresOuterTask)
@@ -10091,12 +10088,11 @@ void CGOpenMPRuntime::emitTargetDataCalls(
   InsertPointTy CodeGenIP(CGF.Builder.GetInsertBlock(),
                           CGF.Builder.GetInsertPoint());
   llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
-  llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
-      OMPBuilder.createTargetData(
+  llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
+      cantFail(OMPBuilder.createTargetData(
           OmpLoc, AllocaIP, CodeGenIP, DeviceID, IfCondVal, Info, GenMapInfoCB,
-          /*MapperFunc=*/nullptr, BodyCB, DeviceAddrCB, CustomMapperCB, RTLoc);
-  assert(AfterIP && "unexpected error creating target data");
-  CGF.Builder.restoreIP(*AfterIP);
+          /*MapperFunc=*/nullptr, BodyCB, DeviceAddrCB, CustomMapperCB, RTLoc));
+  CGF.Builder.restoreIP(AfterIP);
 }
 
 void CGOpenMPRuntime::emitTargetDataStandAloneCall(
diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
index 756f0482b8ea7..dbb19f2a8d825 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
@@ -1752,14 +1752,13 @@ void CGOpenMPRuntimeGPU::emitReduction(
     Idx++;
   }
 
-  llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
-      OMPBuilder.createReductionsGPU(
+  llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
+      cantFail(OMPBuilder.createReductionsGPU(
           OmpLoc, AllocaIP, CodeGenIP, ReductionInfos, false, TeamsReduction,
           DistributeReduction, llvm::OpenMPIRBuilder::ReductionGenCBKind::Clang,
           CGF.getTarget().getGridValue(),
-          C.getLangOpts().OpenMPCUDAReductionBufNum, RTLoc);
-  assert(AfterIP && "unexpected error creating GPU reductions");
-  CGF.Builder.restoreIP(*AfterIP);
+          C.getLangOpts().OpenMPCUDAReductionBufNum, RTLoc));
+  CGF.Builder.restoreIP(AfterIP);
   return;
 }
 
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index c8ff48fc73312..c87ec899798aa 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -76,6 +76,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef Attrs) {
       // Verify that any decl statements were handled as simple, they may be in
       // scope of subsequent reachable statements.
       assert(!isa(*S) && "Unexpected DeclStmt!");
+      PGO.markStmtMaybeUsed(S);
       return;
     }
 
@@ -345,7 +346,8 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef Attrs) {
         cast(*S));
     break;
   case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
-    llvm_unreachable("parallel masked taskloop directive not supported yet.");
+    EmitOMPParallelMaskedTaskLoopDirective(
+        cast(*S));
     break;
   case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
     EmitOMPParallelMasterTaskLoopSimdDirective(
@@ -757,8 +759,6 @@ 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()) {
@@ -790,9 +790,6 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
         Builder.CreateAssumption(AssumptionVal);
       }
     } break;
-    case attr::HLSLControlFlowHint: {
-      flattenOrBranch = cast(A)->getSemanticSpelling();
-    } break;
     }
   }
   SaveAndRestore save_nomerge(InNoMergeAttributedStmt, nomerge);
@@ -800,7 +797,6 @@ 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());
 }
 
@@ -881,6 +877,7 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
         RunCleanupsScope ExecutedScope(*this);
         EmitStmt(Executed);
       }
+      PGO.markStmtMaybeUsed(Skipped);
       return;
     }
   }
@@ -2203,6 +2200,7 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
       for (unsigned i = 0, e = CaseStmts.size(); i != e; ++i)
         EmitStmt(CaseStmts[i]);
       incrementProfileCounter(&S);
+      PGO.markStmtMaybeUsed(S.getBody());
 
       // Now we want to restore the saved switch instance so that nested
       // switches continue to function properly
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 6cb37b20b7aee..4e7b0dcd31ecf 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -1839,11 +1839,10 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
     CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
     llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
         AllocaInsertPt->getParent(), AllocaInsertPt->getIterator());
-    llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
+    llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
         OMPBuilder.createParallel(Builder, AllocaIP, BodyGenCB, PrivCB, FiniCB,
-                                  IfCond, NumThreads, ProcBind, S.hasCancel());
-    assert(AfterIP && "unexpected error creating parallel");
-    Builder.restoreIP(*AfterIP);
+                                  IfCond, NumThreads, ProcBind, S.hasCancel()));
+    Builder.restoreIP(AfterIP);
     return;
   }
 
@@ -2135,10 +2134,8 @@ void CodeGenFunction::EmitOMPCanonicalLoop(const OMPCanonicalLoop *S) {
     return llvm::Error::success();
   };
 
-  llvm::Expected Result =
-      OMPBuilder.createCanonicalLoop(Builder, BodyGen, DistVal);
-  assert(Result && "unexpected error creating canonical loop");
-  llvm::CanonicalLoopInfo *CL = *Result;
+  llvm::CanonicalLoopInfo *CL =
+      cantFail(OMPBuilder.createCanonicalLoop(Builder, BodyGen, DistVal));
 
   // Finish up the loop.
   Builder.restoreIP(CL->getAfterIP());
@@ -4024,13 +4021,11 @@ static void emitOMPForDirective(const OMPLoopDirective &S, CodeGenFunction &CGF,
           CGM.getOpenMPRuntime().getOMPBuilder();
       llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
           CGF.AllocaInsertPt->getParent(), CGF.AllocaInsertPt->getIterator());
-      llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
-          OMPBuilder.applyWorkshareLoop(
-              CGF.Builder.getCurrentDebugLocation(), CLI, AllocaIP,
-              NeedsBarrier, SchedKind, ChunkSize, /*HasSimdModifier=*/false,
-              /*HasMonotonicModifier=*/false, /*HasNonmonotonicModifier=*/false,
-              /*HasOrderedClause=*/false);
-      assert(AfterIP && "unexpected error creating workshare loop");
+      cantFail(OMPBuilder.applyWorkshareLoop(
+          CGF.Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
+          SchedKind, ChunkSize, /*HasSimdModifier=*/false,
+          /*HasMonotonicModifier=*/false, /*HasNonmonotonicModifier=*/false,
+          /*HasOrderedClause=*/false));
       return;
     }
 
@@ -4311,12 +4306,11 @@ void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
     CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
     llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
         AllocaInsertPt->getParent(), AllocaInsertPt->getIterator());
-    llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
-        OMPBuilder.createSections(Builder, AllocaIP, SectionCBVector, PrivCB,
-                                  FiniCB, S.hasCancel(),
-                                  S.getSingleClause());
-    assert(AfterIP && "unexpected error creating sections");
-    Builder.restoreIP(*AfterIP);
+    llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
+        cantFail(OMPBuilder.createSections(
+            Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
+            S.getSingleClause()));
+    Builder.restoreIP(AfterIP);
     return;
   }
   {
@@ -4354,10 +4348,9 @@ void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
 
     LexicalScope Scope(*this, S.getSourceRange());
     EmitStopPoint(&S);
-    llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
-        OMPBuilder.createSection(Builder, BodyGenCB, FiniCB);
-    assert(AfterIP && "unexpected error creating section");
-    Builder.restoreIP(*AfterIP);
+    llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
+        cantFail(OMPBuilder.createSection(Builder, BodyGenCB, FiniCB));
+    Builder.restoreIP(AfterIP);
 
     return;
   }
@@ -4440,10 +4433,9 @@ void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
 
     LexicalScope Scope(*this, S.getSourceRange());
     EmitStopPoint(&S);
-    llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
-        OMPBuilder.createMaster(Builder, BodyGenCB, FiniCB);
-    assert(AfterIP && "unexpected error creating master");
-    Builder.restoreIP(*AfterIP);
+    llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
+        cantFail(OMPBuilder.createMaster(Builder, BodyGenCB, FiniCB));
+    Builder.restoreIP(AfterIP);
 
     return;
   }
@@ -4491,10 +4483,9 @@ void CodeGenFunction::EmitOMPMaskedDirective(const OMPMaskedDirective &S) {
 
     LexicalScope Scope(*this, S.getSourceRange());
     EmitStopPoint(&S);
-    llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
-        OMPBuilder.createMasked(Builder, BodyGenCB, FiniCB, FilterVal);
-    assert(AfterIP && "unexpected error creating masked");
-    Builder.restoreIP(*AfterIP);
+    llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
+        OMPBuilder.createMasked(Builder, BodyGenCB, FiniCB, FilterVal));
+    Builder.restoreIP(AfterIP);
 
     return;
   }
@@ -4535,11 +4526,11 @@ void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
 
     LexicalScope Scope(*this, S.getSourceRange());
     EmitStopPoint(&S);
-    llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
-        OMPBuilder.createCritical(Builder, BodyGenCB, FiniCB,
-                                  S.getDirectiveName().getAsString(), HintInst);
-    assert(AfterIP && "unexpected error creating critical");
-    Builder.restoreIP(*AfterIP);
+    llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
+        cantFail(OMPBuilder.createCritical(Builder, BodyGenCB, FiniCB,
+                                           S.getDirectiveName().getAsString(),
+                                           HintInst));
+    Builder.restoreIP(AfterIP);
 
     return;
   }
@@ -5503,10 +5494,9 @@ void CodeGenFunction::EmitOMPTaskgroupDirective(
     CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
     if (!CapturedStmtInfo)
       CapturedStmtInfo = &CapStmtInfo;
-    llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
-        OMPBuilder.createTaskgroup(Builder, AllocaIP, BodyGenCB);
-    assert(AfterIP && "unexpected error creating taskgroup");
-    Builder.restoreIP(*AfterIP);
+    llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
+        cantFail(OMPBuilder.createTaskgroup(Builder, AllocaIP, BodyGenCB));
+    Builder.restoreIP(AfterIP);
     return;
   }
   auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
@@ -6109,10 +6099,9 @@ void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
       };
 
       OMPLexicalScope Scope(*this, S, OMPD_unknown);
-      llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
-          OMPBuilder.createOrderedThreadsSimd(Builder, BodyGenCB, FiniCB, !C);
-      assert(AfterIP && "unexpected error creating ordered");
-      Builder.restoreIP(*AfterIP);
+      llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
+          OMPBuilder.createOrderedThreadsSimd(Builder, BodyGenCB, FiniCB, !C));
+      Builder.restoreIP(AfterIP);
     }
     return;
   }
@@ -7388,10 +7377,9 @@ void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) {
       if (IfCond)
         IfCondition = EmitScalarExpr(IfCond,
                                      /*IgnoreResultAssign=*/true);
-      llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
-          OMPBuilder.createCancel(Builder, IfCondition, S.getCancelRegion());
-      assert(AfterIP && "unexpected error creating cancel");
-      return Builder.restoreIP(*AfterIP);
+      llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
+          OMPBuilder.createCancel(Builder, IfCondition, S.getCancelRegion()));
+      return Builder.restoreIP(AfterIP);
     }
   }
 
@@ -8024,6 +8012,24 @@ void CodeGenFunction::EmitOMPParallelMasterTaskLoopDirective(
                                  emitEmptyBoundParameters);
 }
 
+void CodeGenFunction::EmitOMPParallelMaskedTaskLoopDirective(
+    const OMPParallelMaskedTaskLoopDirective &S) {
+  auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
+    auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
+                                  PrePostActionTy &Action) {
+      Action.Enter(CGF);
+      CGF.EmitOMPTaskLoopBasedDirective(S);
+    };
+    OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
+    CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
+                                            S.getBeginLoc());
+  };
+  auto LPCRegion =
+      CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
+  emitCommonOMPParallelDirective(*this, S, OMPD_masked_taskloop, CodeGen,
+                                 emitEmptyBoundParameters);
+}
+
 void CodeGenFunction::EmitOMPParallelMasterTaskLoopSimdDirective(
     const OMPParallelMasterTaskLoopSimdDirective &S) {
   auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index cc927f44e0326..f63cb9b082d5b 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -106,46 +106,19 @@ static void reportOptRecordError(Error E, DiagnosticsEngine &Diags,
 }
 
 BackendConsumer::BackendConsumer(
-    BackendAction Action, DiagnosticsEngine &Diags,
-    IntrusiveRefCntPtr VFS,
-    const HeaderSearchOptions &HeaderSearchOpts,
-    const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts,
-    const TargetOptions &TargetOpts, const LangOptions &LangOpts,
-    const std::string &InFile, SmallVector LinkModules,
-    std::unique_ptr OS, LLVMContext &C,
-    CoverageSourceInfo *CoverageInfo)
-    : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts),
-      CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts),
-      AsmOutStream(std::move(OS)), Context(nullptr), FS(VFS),
-      LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
-      LLVMIRGenerationRefCount(0),
-      Gen(CreateLLVMCodeGen(Diags, InFile, std::move(VFS), HeaderSearchOpts,
-                            PPOpts, CodeGenOpts, C, CoverageInfo)),
-      LinkModules(std::move(LinkModules)) {
-  TimerIsEnabled = CodeGenOpts.TimePasses;
-  llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses;
-  llvm::TimePassesPerRun = CodeGenOpts.TimePassesPerRun;
-}
-
-// This constructor is used in installing an empty BackendConsumer
-// to use the clang diagnostic handler for IR input files. It avoids
-// initializing the OS field.
-BackendConsumer::BackendConsumer(
-    BackendAction Action, DiagnosticsEngine &Diags,
-    IntrusiveRefCntPtr VFS,
-    const HeaderSearchOptions &HeaderSearchOpts,
-    const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts,
-    const TargetOptions &TargetOpts, const LangOptions &LangOpts,
-    llvm::Module *Module, SmallVector LinkModules,
-    LLVMContext &C, CoverageSourceInfo *CoverageInfo)
-    : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts),
-      CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts),
-      Context(nullptr), FS(VFS),
-      LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
-      LLVMIRGenerationRefCount(0),
-      Gen(CreateLLVMCodeGen(Diags, "", std::move(VFS), HeaderSearchOpts, PPOpts,
-                            CodeGenOpts, C, CoverageInfo)),
-      LinkModules(std::move(LinkModules)), CurLinkModule(Module) {
+    const CompilerInstance &CI, BackendAction Action,
+    IntrusiveRefCntPtr VFS, LLVMContext &C,
+    SmallVector LinkModules, StringRef InFile,
+    std::unique_ptr OS, CoverageSourceInfo *CoverageInfo,
+    llvm::Module *CurLinkModule)
+    : Diags(CI.getDiagnostics()), HeaderSearchOpts(CI.getHeaderSearchOpts()),
+      CodeGenOpts(CI.getCodeGenOpts()), TargetOpts(CI.getTargetOpts()),
+      LangOpts(CI.getLangOpts()), AsmOutStream(std::move(OS)), FS(VFS),
+      LLVMIRGeneration("irgen", "LLVM IR Generation Time"), Action(Action),
+      Gen(CreateLLVMCodeGen(Diags, InFile, std::move(VFS),
+                            CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(),
+                            CI.getCodeGenOpts(), C, CoverageInfo)),
+      LinkModules(std::move(LinkModules)), CurLinkModule(CurLinkModule) {
   TimerIsEnabled = CodeGenOpts.TimePasses;
   llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses;
   llvm::TimePassesPerRun = CodeGenOpts.TimePassesPerRun;
@@ -1011,10 +984,8 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
         CI.getPreprocessor());
 
   std::unique_ptr Result(new BackendConsumer(
-      BA, CI.getDiagnostics(), &CI.getVirtualFileSystem(),
-      CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(),
-      CI.getTargetOpts(), CI.getLangOpts(), std::string(InFile),
-      std::move(LinkModules), std::move(OS), *VMContext, CoverageInfo));
+      CI, BA, &CI.getVirtualFileSystem(), *VMContext, std::move(LinkModules),
+      InFile, std::move(OS), CoverageInfo));
   BEConsumer = Result.get();
 
   // Enable generating macro debug info only when debug info is not disabled and
@@ -1182,11 +1153,9 @@ void CodeGenAction::ExecuteAction() {
 
   // Set clang diagnostic handler. To do this we need to create a fake
   // BackendConsumer.
-  BackendConsumer Result(BA, CI.getDiagnostics(), &CI.getVirtualFileSystem(),
-                         CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(),
-                         CI.getCodeGenOpts(), CI.getTargetOpts(),
-                         CI.getLangOpts(), TheModule.get(),
-                         std::move(LinkModules), *VMContext, nullptr);
+  BackendConsumer Result(CI, BA, &CI.getVirtualFileSystem(), *VMContext,
+                         std::move(LinkModules), "", nullptr, nullptr,
+                         TheModule.get());
 
   // Link in each pending link module.
   if (!CodeGenOpts.LinkBitcodePostopt && Result.LinkInModules(&*TheModule))
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 067ff55b87ae6..27ec68bd2a872 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -40,7 +40,6 @@
 #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"
@@ -1617,6 +1616,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
   // Emit the standard function epilogue.
   FinishFunction(BodyRange.getEnd());
 
+  PGO.verifyCounterMap();
+
   // If we haven't marked the function nothrow through other means, do
   // a quick pass now to see if we can.
   if (!CurFn->doesNotThrow())
@@ -1739,6 +1740,7 @@ bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
   if (!AllowLabels && CodeGenFunction::ContainsLabel(Cond))
     return false;  // Contains a label.
 
+  PGO.markStmtMaybeUsed(Cond);
   ResultInt = Int;
   return true;
 }
@@ -2084,29 +2086,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(
     Weights = createProfileWeights(TrueCount, CurrentCount - TrueCount);
   }
 
-  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;
-  }
-  case HLSLControlFlowHintAttr::SpellingNotCalculated:
-    break;
-  }
+  Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable);
 }
 
 /// 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 bc612a0bfb32b..457e1477bb2ee 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -615,10 +615,6 @@ 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;
@@ -1624,6 +1620,13 @@ class CodeGenFunction : public CodeGenTypeCache {
                                             uint64_t LoopCount) const;
 
 public:
+  auto getIsCounterPair(const Stmt *S) const { return PGO.getIsCounterPair(S); }
+
+  void markStmtAsUsed(bool Skipped, const Stmt *S) {
+    PGO.markStmtAsUsed(Skipped, S);
+  }
+  void markStmtMaybeUsed(const Stmt *S) { PGO.markStmtMaybeUsed(S); }
+
   /// Increment the profiler's counter for the given statement by \p StepV.
   /// If \p StepV is null, the default increment is 1.
   void incrementProfileCounter(const Stmt *S, llvm::Value *StepV = nullptr) {
@@ -3871,6 +3874,8 @@ class CodeGenFunction : public CodeGenTypeCache {
   EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S);
   void EmitOMPParallelMasterTaskLoopDirective(
       const OMPParallelMasterTaskLoopDirective &S);
+  void EmitOMPParallelMaskedTaskLoopDirective(
+      const OMPParallelMaskedTaskLoopDirective &S);
   void EmitOMPParallelMasterTaskLoopSimdDirective(
       const OMPParallelMasterTaskLoopSimdDirective &S);
   void EmitOMPDistributeDirective(const OMPDistributeDirective &S);
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 5f15f0f48c54e..7db1ed72fa5cd 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4241,7 +4241,7 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
 static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
                                                       llvm::Function *NewFn);
 
-static unsigned getFMVPriority(const TargetInfo &TI,
+static uint64_t getFMVPriority(const TargetInfo &TI,
                                const CodeGenFunction::FMVResolverOption &RO) {
   llvm::SmallVector Features{RO.Features};
   if (RO.Architecture)
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 741b0f17da658..d5ef1a710eb40 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -102,6 +102,50 @@ enum ForDefinition_t : bool {
   ForDefinition = true
 };
 
+/// The Counter with an optional additional Counter for
+/// branches. `Skipped` counter can be calculated with `Executed` and
+/// a common Counter (like `Parent`) as `(Parent-Executed)`.
+///
+/// In SingleByte mode, Counters are binary. Subtraction is not
+/// applicable (but addition is capable). In this case, both
+/// `Executed` and `Skipped` counters are required.  `Skipped` is
+/// `None` by default. It is allocated in the coverage mapping.
+///
+/// There might be cases that `Parent` could be induced with
+/// `(Executed+Skipped)`. This is not always applicable.
+class CounterPair {
+public:
+  /// Optional value.
+  class ValueOpt {
+  private:
+    static constexpr uint32_t None = (1u << 31); /// None is allocated.
+    static constexpr uint32_t Mask = None - 1;
+
+    uint32_t Val;
+
+  public:
+    ValueOpt() : Val(None) {}
+
+    ValueOpt(unsigned InitVal) {
+      assert(!(InitVal & ~Mask));
+      Val = InitVal;
+    }
+
+    bool hasValue() const { return !(Val & None); }
+
+    operator uint32_t() const { return Val; }
+  };
+
+  ValueOpt Executed;
+  ValueOpt Skipped; /// May be None.
+
+  /// Initialized with Skipped=None.
+  CounterPair(unsigned Val) : Executed(Val) {}
+
+  // FIXME: Should work with {None, None}
+  CounterPair() : Executed(0) {}
+};
+
 struct OrderGlobalInitsOrStermFinalizers {
   unsigned int priority;
   unsigned int lex_order;
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 17d7902f0cfbc..792373839107f 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -163,7 +163,7 @@ struct MapRegionCounters : public RecursiveASTVisitor {
   /// The function hash.
   PGOHash Hash;
   /// The map of statements to counters.
-  llvm::DenseMap &CounterMap;
+  llvm::DenseMap &CounterMap;
   /// The state of MC/DC Coverage in this function.
   MCDC::State &MCDCState;
   /// Maximum number of supported MC/DC conditions in a boolean expression.
@@ -174,7 +174,7 @@ struct MapRegionCounters : public RecursiveASTVisitor {
   DiagnosticsEngine &Diag;
 
   MapRegionCounters(PGOHashVersion HashVersion, uint64_t ProfileVersion,
-                    llvm::DenseMap &CounterMap,
+                    llvm::DenseMap &CounterMap,
                     MCDC::State &MCDCState, unsigned MCDCMaxCond,
                     DiagnosticsEngine &Diag)
       : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
@@ -1083,7 +1083,7 @@ void CodeGenPGO::mapRegionCounters(const Decl *D) {
       (CGM.getCodeGenOpts().MCDCCoverage ? CGM.getCodeGenOpts().MCDCMaxConds
                                          : 0);
 
-  RegionCounterMap.reset(new llvm::DenseMap);
+  RegionCounterMap.reset(new llvm::DenseMap);
   RegionMCDCState.reset(new MCDC::State);
   MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap,
                            *RegionMCDCState, MCDCMaxConditions, CGM.getDiags());
@@ -1185,12 +1185,23 @@ CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
   Fn->setEntryCount(FunctionCount);
 }
 
+std::pair CodeGenPGO::getIsCounterPair(const Stmt *S) const {
+  if (!RegionCounterMap)
+    return {false, false};
+
+  auto I = RegionCounterMap->find(S);
+  if (I == RegionCounterMap->end())
+    return {false, false};
+
+  return {I->second.Executed.hasValue(), I->second.Skipped.hasValue()};
+}
+
 void CodeGenPGO::emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
                                            llvm::Value *StepV) {
   if (!RegionCounterMap || !Builder.GetInsertBlock())
     return;
 
-  unsigned Counter = (*RegionCounterMap)[S];
+  unsigned Counter = (*RegionCounterMap)[S].Executed;
 
   // Make sure that pointer to global is passed in with zero addrspace
   // This is relevant during GPU profiling
diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h
index 9d66ffad6f435..1944b640951d5 100644
--- a/clang/lib/CodeGen/CodeGenPGO.h
+++ b/clang/lib/CodeGen/CodeGenPGO.h
@@ -35,7 +35,7 @@ class CodeGenPGO {
   std::array  NumValueSites;
   unsigned NumRegionCounters;
   uint64_t FunctionHash;
-  std::unique_ptr> RegionCounterMap;
+  std::unique_ptr> RegionCounterMap;
   std::unique_ptr> StmtCountMap;
   std::unique_ptr ProfRecord;
   std::unique_ptr RegionMCDCState;
@@ -110,6 +110,7 @@ class CodeGenPGO {
   bool canEmitMCDCCoverage(const CGBuilderTy &Builder);
 
 public:
+  std::pair getIsCounterPair(const Stmt *S) const;
   void emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
                                  llvm::Value *StepV);
   void emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, const Expr *S,
@@ -122,6 +123,18 @@ class CodeGenPGO {
                                 Address MCDCCondBitmapAddr, llvm::Value *Val,
                                 CodeGenFunction &CGF);
 
+  void markStmtAsUsed(bool Skipped, const Stmt *S) {
+    // Do nothing.
+  }
+
+  void markStmtMaybeUsed(const Stmt *S) {
+    // Do nothing.
+  }
+
+  void verifyCounterMap() const {
+    // Do nothing.
+  }
+
   /// Return the region count for the counter at the given index.
   uint64_t getRegionCount(const Stmt *S) {
     if (!RegionCounterMap)
@@ -130,7 +143,7 @@ class CodeGenPGO {
       return 0;
     // With profiles from a differing version of clang we can have mismatched
     // decl counts. Don't crash in such a case.
-    auto Index = (*RegionCounterMap)[S];
+    auto Index = (*RegionCounterMap)[S].Executed;
     if (Index >= RegionCounts.size())
       return 0;
     return RegionCounts[Index];
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index cda218eac34af..f09157771d2b5 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -882,7 +882,7 @@ struct CounterCoverageMappingBuilder
     : public CoverageMappingBuilder,
       public ConstStmtVisitor {
   /// The map of statements to count values.
-  llvm::DenseMap &CounterMap;
+  llvm::DenseMap &CounterMap;
 
   MCDC::State &MCDCState;
 
@@ -919,15 +919,11 @@ struct CounterCoverageMappingBuilder
 
   /// Return a counter for the sum of \c LHS and \c RHS.
   Counter addCounters(Counter LHS, Counter RHS, bool Simplify = true) {
-    assert(!llvm::EnableSingleByteCoverage &&
-           "cannot add counters when single byte coverage mode is enabled");
     return Builder.add(LHS, RHS, Simplify);
   }
 
   Counter addCounters(Counter C1, Counter C2, Counter C3,
                       bool Simplify = true) {
-    assert(!llvm::EnableSingleByteCoverage &&
-           "cannot add counters when single byte coverage mode is enabled");
     return addCounters(addCounters(C1, C2, Simplify), C3, Simplify);
   }
 
@@ -935,7 +931,51 @@ struct CounterCoverageMappingBuilder
   ///
   /// This should only be called on statements that have a dedicated counter.
   Counter getRegionCounter(const Stmt *S) {
-    return Counter::getCounter(CounterMap[S]);
+    return Counter::getCounter(CounterMap[S].Executed);
+  }
+
+  struct BranchCounterPair {
+    Counter Executed; ///< The Counter previously assigned.
+    Counter Skipped;  ///< An expression (Parent-Executed), or equivalent to it.
+  };
+
+  /// Retrieve or assign the pair of Counter(s).
+  ///
+  /// This returns BranchCounterPair {Executed, Skipped}.
+  /// Executed is the Counter associated with S assigned by an earlier
+  /// CounterMapping pass.
+  /// Skipped may be an expression (Executed - ParentCnt) or newly
+  /// assigned Counter in EnableSingleByteCoverage, as subtract
+  /// expressions are not available in this mode.
+  ///
+  /// \param S Key to the CounterMap
+  /// \param ParentCnt The Counter representing how many times S is evaluated.
+  /// \param SkipCntForOld (To be removed later) Optional fake Counter
+  ///                      to override Skipped for adjustment of
+  ///                      expressions in the old behavior of
+  ///                      EnableSingleByteCoverage that is unaware of
+  ///                      Branch coverage.
+  BranchCounterPair
+  getBranchCounterPair(const Stmt *S, Counter ParentCnt,
+                       std::optional SkipCntForOld = std::nullopt) {
+    Counter ExecCnt = getRegionCounter(S);
+
+    // The old behavior of SingleByte is unaware of Branches.
+    // Will be pruned after the migration of SingleByte.
+    if (llvm::EnableSingleByteCoverage) {
+      assert(SkipCntForOld &&
+             "SingleByte must provide SkipCntForOld as a fake Skipped count.");
+      return {ExecCnt, *SkipCntForOld};
+    }
+
+    return {ExecCnt, Builder.subtract(ParentCnt, ExecCnt)};
+  }
+
+  bool IsCounterEqual(Counter OutCount, Counter ParentCount) {
+    if (OutCount == ParentCount)
+      return true;
+
+    return false;
   }
 
   /// Push a region onto the stack.
@@ -1417,7 +1457,7 @@ struct CounterCoverageMappingBuilder
 
   CounterCoverageMappingBuilder(
       CoverageMappingModuleGen &CVM,
-      llvm::DenseMap &CounterMap,
+      llvm::DenseMap &CounterMap,
       MCDC::State &MCDCState, SourceManager &SM, const LangOptions &LangOpts)
       : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap),
         MCDCState(MCDCState), MCDCBuilder(CVM.getCodeGenModule(), MCDCState) {}
@@ -1588,6 +1628,10 @@ struct CounterCoverageMappingBuilder
         llvm::EnableSingleByteCoverage
             ? getRegionCounter(S->getCond())
             : addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
+    auto BranchCount = getBranchCounterPair(S, CondCount, getRegionCounter(S));
+    assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
+           llvm::EnableSingleByteCoverage);
+
     propagateCounts(CondCount, S->getCond());
     adjustForOutOfOrderTraversal(getEnd(S));
 
@@ -1596,13 +1640,11 @@ struct CounterCoverageMappingBuilder
     if (Gap)
       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
 
-    Counter OutCount =
-        llvm::EnableSingleByteCoverage
-            ? getRegionCounter(S)
-            : addCounters(BC.BreakCount,
-                          subtractCounters(CondCount, BodyCount));
-
-    if (OutCount != ParentCount) {
+    assert(
+        !llvm::EnableSingleByteCoverage ||
+        (BC.BreakCount.isZero() && BranchCount.Skipped == getRegionCounter(S)));
+    Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
+    if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
       if (BodyHasTerminateStmt)
@@ -1611,8 +1653,7 @@ struct CounterCoverageMappingBuilder
 
     // Create Branch Region around condition.
     if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(S->getCond(), BodyCount,
-                         subtractCounters(CondCount, BodyCount));
+      createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
   }
 
   void VisitDoStmt(const DoStmt *S) {
@@ -1641,22 +1682,24 @@ struct CounterCoverageMappingBuilder
     Counter CondCount = llvm::EnableSingleByteCoverage
                             ? getRegionCounter(S->getCond())
                             : addCounters(BackedgeCount, BC.ContinueCount);
+    auto BranchCount = getBranchCounterPair(S, CondCount, getRegionCounter(S));
+    assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
+           llvm::EnableSingleByteCoverage);
+
     propagateCounts(CondCount, S->getCond());
 
-    Counter OutCount =
-        llvm::EnableSingleByteCoverage
-            ? getRegionCounter(S)
-            : addCounters(BC.BreakCount,
-                          subtractCounters(CondCount, BodyCount));
-    if (OutCount != ParentCount) {
+    assert(
+        !llvm::EnableSingleByteCoverage ||
+        (BC.BreakCount.isZero() && BranchCount.Skipped == getRegionCounter(S)));
+    Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
+    if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
     }
 
     // Create Branch Region around condition.
     if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(S->getCond(), BodyCount,
-                         subtractCounters(CondCount, BodyCount));
+      createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
 
     if (BodyHasTerminateStmt)
       HasTerminateStmt = true;
@@ -1705,6 +1748,9 @@ struct CounterCoverageMappingBuilder
             : addCounters(
                   addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
                   IncrementBC.ContinueCount);
+    auto BranchCount = getBranchCounterPair(S, CondCount, getRegionCounter(S));
+    assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
+           llvm::EnableSingleByteCoverage);
 
     if (const Expr *Cond = S->getCond()) {
       propagateCounts(CondCount, Cond);
@@ -1716,12 +1762,11 @@ struct CounterCoverageMappingBuilder
     if (Gap)
       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
 
-    Counter OutCount =
-        llvm::EnableSingleByteCoverage
-            ? getRegionCounter(S)
-            : addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
-                          subtractCounters(CondCount, BodyCount));
-    if (OutCount != ParentCount) {
+    assert(!llvm::EnableSingleByteCoverage ||
+           (BodyBC.BreakCount.isZero() && IncrementBC.BreakCount.isZero()));
+    Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
+                                   BranchCount.Skipped);
+    if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
       if (BodyHasTerminateStmt)
@@ -1730,8 +1775,7 @@ struct CounterCoverageMappingBuilder
 
     // Create Branch Region around condition.
     if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(S->getCond(), BodyCount,
-                         subtractCounters(CondCount, BodyCount));
+      createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
   }
 
   void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
@@ -1759,16 +1803,17 @@ struct CounterCoverageMappingBuilder
     if (Gap)
       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
 
-    Counter OutCount;
-    Counter LoopCount;
-    if (llvm::EnableSingleByteCoverage)
-      OutCount = getRegionCounter(S);
-    else {
-      LoopCount = addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
-      OutCount =
-          addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
-    }
-    if (OutCount != ParentCount) {
+    Counter LoopCount =
+        addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
+    auto BranchCount = getBranchCounterPair(S, LoopCount, getRegionCounter(S));
+    assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount ||
+           llvm::EnableSingleByteCoverage);
+    assert(
+        !llvm::EnableSingleByteCoverage ||
+        (BC.BreakCount.isZero() && BranchCount.Skipped == getRegionCounter(S)));
+
+    Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
+    if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
       if (BodyHasTerminateStmt)
@@ -1777,8 +1822,7 @@ struct CounterCoverageMappingBuilder
 
     // Create Branch Region around condition.
     if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(S->getCond(), BodyCount,
-                         subtractCounters(LoopCount, BodyCount));
+      createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
   }
 
   void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
@@ -1800,9 +1844,10 @@ struct CounterCoverageMappingBuilder
 
     Counter LoopCount =
         addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
-    Counter OutCount =
-        addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
-    if (OutCount != ParentCount) {
+    auto BranchCount = getBranchCounterPair(S, LoopCount);
+    assert(BranchCount.Executed.isZero() || BranchCount.Executed == BodyCount);
+    Counter OutCount = addCounters(BC.BreakCount, BranchCount.Skipped);
+    if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
     }
@@ -2010,9 +2055,12 @@ struct CounterCoverageMappingBuilder
     extendRegion(S->getCond());
 
     Counter ParentCount = getRegion().getCounter();
-    Counter ThenCount = llvm::EnableSingleByteCoverage
-                            ? getRegionCounter(S->getThen())
-                            : getRegionCounter(S);
+    auto [ThenCount, ElseCount] =
+        (llvm::EnableSingleByteCoverage
+             ? BranchCounterPair{getRegionCounter(S->getThen()),
+                                 (S->getElse() ? getRegionCounter(S->getElse())
+                                               : Counter::getZero())}
+             : getBranchCounterPair(S, ParentCount));
 
     // Emitting a counter for the condition makes it easier to interpret the
     // counter for the body when looking at the coverage.
@@ -2027,12 +2075,6 @@ struct CounterCoverageMappingBuilder
     extendRegion(S->getThen());
     Counter OutCount = propagateCounts(ThenCount, S->getThen());
 
-    Counter ElseCount;
-    if (!llvm::EnableSingleByteCoverage)
-      ElseCount = subtractCounters(ParentCount, ThenCount);
-    else if (S->getElse())
-      ElseCount = getRegionCounter(S->getElse());
-
     if (const Stmt *Else = S->getElse()) {
       bool ThenHasTerminateStmt = HasTerminateStmt;
       HasTerminateStmt = false;
@@ -2055,15 +2097,14 @@ struct CounterCoverageMappingBuilder
     if (llvm::EnableSingleByteCoverage)
       OutCount = getRegionCounter(S);
 
-    if (OutCount != ParentCount) {
+    if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
     }
 
     if (!llvm::EnableSingleByteCoverage)
       // Create Branch Region around condition.
-      createBranchRegion(S->getCond(), ThenCount,
-                         subtractCounters(ParentCount, ThenCount));
+      createBranchRegion(S->getCond(), ThenCount, ElseCount);
   }
 
   void VisitCXXTryStmt(const CXXTryStmt *S) {
@@ -2089,9 +2130,11 @@ struct CounterCoverageMappingBuilder
     extendRegion(E);
 
     Counter ParentCount = getRegion().getCounter();
-    Counter TrueCount = llvm::EnableSingleByteCoverage
-                            ? getRegionCounter(E->getTrueExpr())
-                            : getRegionCounter(E);
+    auto [TrueCount, FalseCount] =
+        (llvm::EnableSingleByteCoverage
+             ? BranchCounterPair{getRegionCounter(E->getTrueExpr()),
+                                 getRegionCounter(E->getFalseExpr())}
+             : getBranchCounterPair(E, ParentCount));
     Counter OutCount;
 
     if (const auto *BCO = dyn_cast(E)) {
@@ -2110,25 +2153,20 @@ struct CounterCoverageMappingBuilder
     }
 
     extendRegion(E->getFalseExpr());
-    Counter FalseCount = llvm::EnableSingleByteCoverage
-                             ? getRegionCounter(E->getFalseExpr())
-                             : subtractCounters(ParentCount, TrueCount);
-
     Counter FalseOutCount = propagateCounts(FalseCount, E->getFalseExpr());
     if (llvm::EnableSingleByteCoverage)
       OutCount = getRegionCounter(E);
     else
       OutCount = addCounters(OutCount, FalseOutCount);
 
-    if (OutCount != ParentCount) {
+    if (!IsCounterEqual(OutCount, ParentCount)) {
       pushRegion(OutCount);
       GapRegionCounter = OutCount;
     }
 
     // Create Branch Region around condition.
     if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(E->getCond(), TrueCount,
-                         subtractCounters(ParentCount, TrueCount));
+      createBranchRegion(E->getCond(), TrueCount, FalseCount);
   }
 
   void createOrCancelDecision(const BinaryOperator *E, unsigned Since) {
@@ -2227,27 +2265,27 @@ struct CounterCoverageMappingBuilder
     extendRegion(E->getRHS());
     propagateCounts(getRegionCounter(E), E->getRHS());
 
+    if (llvm::EnableSingleByteCoverage)
+      return;
+
     // Track RHS True/False Decision.
     const auto DecisionRHS = MCDCBuilder.back();
 
+    // Extract the Parent Region Counter.
+    Counter ParentCnt = getRegion().getCounter();
+
     // Extract the RHS's Execution Counter.
-    Counter RHSExecCnt = getRegionCounter(E);
+    auto [RHSExecCnt, LHSExitCnt] = getBranchCounterPair(E, ParentCnt);
 
     // Extract the RHS's "True" Instance Counter.
-    Counter RHSTrueCnt = getRegionCounter(E->getRHS());
-
-    // Extract the Parent Region Counter.
-    Counter ParentCnt = getRegion().getCounter();
+    auto [RHSTrueCnt, RHSExitCnt] =
+        getBranchCounterPair(E->getRHS(), RHSExecCnt);
 
     // Create Branch Region around LHS condition.
-    if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(E->getLHS(), RHSExecCnt,
-                         subtractCounters(ParentCnt, RHSExecCnt), DecisionLHS);
+    createBranchRegion(E->getLHS(), RHSExecCnt, LHSExitCnt, DecisionLHS);
 
     // Create Branch Region around RHS condition.
-    if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(E->getRHS(), RHSTrueCnt,
-                         subtractCounters(RHSExecCnt, RHSTrueCnt), DecisionRHS);
+    createBranchRegion(E->getRHS(), RHSTrueCnt, RHSExitCnt, DecisionRHS);
 
     // Create MCDC Decision Region if at top-level (root).
     if (IsRootNode)
@@ -2288,31 +2326,31 @@ struct CounterCoverageMappingBuilder
     extendRegion(E->getRHS());
     propagateCounts(getRegionCounter(E), E->getRHS());
 
+    if (llvm::EnableSingleByteCoverage)
+      return;
+
     // Track RHS True/False Decision.
     const auto DecisionRHS = MCDCBuilder.back();
 
+    // Extract the Parent Region Counter.
+    Counter ParentCnt = getRegion().getCounter();
+
     // Extract the RHS's Execution Counter.
-    Counter RHSExecCnt = getRegionCounter(E);
+    auto [RHSExecCnt, LHSExitCnt] = getBranchCounterPair(E, ParentCnt);
 
     // Extract the RHS's "False" Instance Counter.
-    Counter RHSFalseCnt = getRegionCounter(E->getRHS());
+    auto [RHSFalseCnt, RHSExitCnt] =
+        getBranchCounterPair(E->getRHS(), RHSExecCnt);
 
     if (!shouldVisitRHS(E->getLHS())) {
       GapRegionCounter = OutCount;
     }
 
-    // Extract the Parent Region Counter.
-    Counter ParentCnt = getRegion().getCounter();
-
     // Create Branch Region around LHS condition.
-    if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(E->getLHS(), subtractCounters(ParentCnt, RHSExecCnt),
-                         RHSExecCnt, DecisionLHS);
+    createBranchRegion(E->getLHS(), LHSExitCnt, RHSExecCnt, DecisionLHS);
 
     // Create Branch Region around RHS condition.
-    if (!llvm::EnableSingleByteCoverage)
-      createBranchRegion(E->getRHS(), subtractCounters(RHSExecCnt, RHSFalseCnt),
-                         RHSFalseCnt, DecisionRHS);
+    createBranchRegion(E->getRHS(), RHSExitCnt, RHSFalseCnt, DecisionRHS);
 
     // Create MCDC Decision Region if at top-level (root).
     if (IsRootNode)
diff --git a/clang/lib/CodeGen/CoverageMappingGen.h b/clang/lib/CodeGen/CoverageMappingGen.h
index fe4b93f3af856..0ed50597e1dc3 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.h
+++ b/clang/lib/CodeGen/CoverageMappingGen.h
@@ -95,6 +95,7 @@ class CoverageSourceInfo : public PPCallbacks,
 namespace CodeGen {
 
 class CodeGenModule;
+class CounterPair;
 
 namespace MCDC {
 struct State;
@@ -158,7 +159,7 @@ class CoverageMappingGen {
   CoverageMappingModuleGen &CVM;
   SourceManager &SM;
   const LangOptions &LangOpts;
-  llvm::DenseMap *CounterMap;
+  llvm::DenseMap *CounterMap;
   MCDC::State *MCDCState;
 
 public:
@@ -169,7 +170,7 @@ class CoverageMappingGen {
 
   CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM,
                      const LangOptions &LangOpts,
-                     llvm::DenseMap *CounterMap,
+                     llvm::DenseMap *CounterMap,
                      MCDC::State *MCDCState)
       : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(CounterMap),
         MCDCState(MCDCState) {}
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 528b7d1a9c7b1..04f2664ffeadd 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1503,9 +1503,14 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) {
 
         // Set specific Vulkan version if applicable.
         if (const Arg *A = Args.getLastArg(options::OPT_fspv_target_env_EQ)) {
-          const llvm::StringSet<> ValidValues = {"vulkan1.2", "vulkan1.3"};
-          if (ValidValues.contains(A->getValue())) {
-            T.setOSName(A->getValue());
+          const llvm::StringMap ValidTargets = {
+              {"vulkan1.2", llvm::Triple::SPIRVSubArch_v15},
+              {"vulkan1.3", llvm::Triple::SPIRVSubArch_v16}};
+
+          auto TargetInfo = ValidTargets.find(A->getValue());
+          if (TargetInfo != ValidTargets.end()) {
+            T.setOSName(TargetInfo->getKey());
+            T.setArch(llvm::Triple::spirv, TargetInfo->getValue());
           } else {
             Diag(diag::err_drv_invalid_value)
                 << A->getAsString(Args) << A->getValue();
diff --git a/clang/lib/Driver/OffloadBundler.cpp b/clang/lib/Driver/OffloadBundler.cpp
index 87d7303d938c9..2d6bdff0393be 100644
--- a/clang/lib/Driver/OffloadBundler.cpp
+++ b/clang/lib/Driver/OffloadBundler.cpp
@@ -37,6 +37,7 @@
 #include "llvm/Support/ErrorOr.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MD5.h"
+#include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Program.h"
@@ -63,9 +64,17 @@ using namespace llvm;
 using namespace llvm::object;
 using namespace clang;
 
-static llvm::TimerGroup
-    ClangOffloadBundlerTimerGroup("Clang Offload Bundler Timer Group",
-                                  "Timer group for clang offload bundler");
+namespace {
+struct CreateClangOffloadBundlerTimerGroup {
+  static void *call() {
+    return new TimerGroup("Clang Offload Bundler Timer Group",
+                          "Timer group for clang offload bundler");
+  }
+};
+} // namespace
+static llvm::ManagedStatic
+    ClangOffloadBundlerTimerGroup;
 
 /// Magic string that marks the existence of offloading data.
 #define OFFLOAD_BUNDLER_MAGIC_STR "__CLANG_OFFLOAD_BUNDLE__"
@@ -987,7 +996,7 @@ CompressedOffloadBundle::compress(llvm::compression::Params P,
                              "Compression not supported");
 
   llvm::Timer HashTimer("Hash Calculation Timer", "Hash calculation time",
-                        ClangOffloadBundlerTimerGroup);
+                        *ClangOffloadBundlerTimerGroup);
   if (Verbose)
     HashTimer.startTimer();
   llvm::MD5 Hash;
@@ -1004,7 +1013,7 @@ CompressedOffloadBundle::compress(llvm::compression::Params P,
       Input.getBuffer().size());
 
   llvm::Timer CompressTimer("Compression Timer", "Compression time",
-                            ClangOffloadBundlerTimerGroup);
+                            *ClangOffloadBundlerTimerGroup);
   if (Verbose)
     CompressTimer.startTimer();
   llvm::compression::compress(P, BufferUint8, CompressedBuffer);
@@ -1119,7 +1128,7 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
                              "Unknown compressing method");
 
   llvm::Timer DecompressTimer("Decompression Timer", "Decompression time",
-                              ClangOffloadBundlerTimerGroup);
+                              *ClangOffloadBundlerTimerGroup);
   if (Verbose)
     DecompressTimer.startTimer();
 
@@ -1141,7 +1150,7 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
     // Recalculate MD5 hash for integrity check
     llvm::Timer HashRecalcTimer("Hash Recalculation Timer",
                                 "Hash recalculation time",
-                                ClangOffloadBundlerTimerGroup);
+                                *ClangOffloadBundlerTimerGroup);
     HashRecalcTimer.startTimer();
     llvm::MD5 Hash;
     llvm::MD5::MD5Result Result;
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index a0002371da2f1..c4b5374d3fff9 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5109,6 +5109,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   const llvm::Triple *AuxTriple =
       (IsCuda || IsHIP) ? TC.getAuxTriple() : nullptr;
   bool IsWindowsMSVC = RawTriple.isWindowsMSVCEnvironment();
+  bool IsUEFI = RawTriple.isUEFI();
   bool IsIAMCU = RawTriple.isOSIAMCU();
 
   // Adjust IsWindowsXYZ for CUDA/HIP/SYCL compilations.  Even when compiling in
@@ -7252,7 +7253,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
 
   // -fms-extensions=0 is default.
   if (Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
-                   IsWindowsMSVC))
+                   IsWindowsMSVC || IsUEFI))
     CmdArgs.push_back("-fms-extensions");
 
   // -fms-compatibility=0 is default.
@@ -9281,6 +9282,10 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
   if (const Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ))
     CmdArgs.push_back(Args.MakeArgString(
         Twine("--offload-opt=-pass-remarks-analysis=") + A->getValue()));
+
+  if (Args.getLastArg(options::OPT_ftime_report))
+    CmdArgs.push_back("--device-compiler=-ftime-report");
+
   if (Args.getLastArg(options::OPT_save_temps_EQ))
     CmdArgs.push_back("--save-temps");
 
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 60214c4d59cee..f8967890f722c 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1209,6 +1209,10 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
   if (ImplicitMapSyms)
     CmdArgs.push_back(
         Args.MakeArgString(Twine(PluginOptPrefix) + "-implicit-mapsyms"));
+
+  if (Args.hasArg(options::OPT_ftime_report))
+    CmdArgs.push_back(
+        Args.MakeArgString(Twine(PluginOptPrefix) + "-time-passes"));
 }
 
 void tools::addOpenMPRuntimeLibraryPath(const ToolChain &TC,
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 7034e5b475c1d..75b10e88371ae 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -57,7 +57,8 @@ void Flang::addFortranDialectOptions(const ArgList &Args,
                             options::OPT_fno_automatic,
                             options::OPT_fhermetic_module_files,
                             options::OPT_frealloc_lhs,
-                            options::OPT_fno_realloc_lhs});
+                            options::OPT_fno_realloc_lhs,
+                            options::OPT_fsave_main_program});
 }
 
 void Flang::addPreprocessingOptions(const ArgList &Args,
diff --git a/clang/lib/Headers/cuda_wrappers/cmath b/clang/lib/Headers/cuda_wrappers/cmath
index 45f89beec9b4d..7deca678bf252 100644
--- a/clang/lib/Headers/cuda_wrappers/cmath
+++ b/clang/lib/Headers/cuda_wrappers/cmath
@@ -24,7 +24,11 @@
 #ifndef __CLANG_CUDA_WRAPPERS_CMATH
 #define __CLANG_CUDA_WRAPPERS_CMATH
 
+#if __has_include_next()
 #include_next 
+#else
+#error "Could not find standard C++ header 'cmath'. Add -v to your compilation command to check the include paths being searched. You may need to install the appropriate standard C++ library package corresponding to the search path."
+#endif
 
 #if defined(_LIBCPP_STD_VER)
 
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index f30603feb65c5..fddb8a5729ee8 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -81,26 +81,16 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
 
   ParsedAttributes attrs(AttrFactory);
 
-  auto ReadAttributes = [&] {
-    bool MoreToParse;
-    do {
-      MoreToParse = false;
-      if (Tok.is(tok::kw___attribute)) {
-        ParseGNUAttributes(attrs);
-        MoreToParse = true;
-      }
-      if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
+  while (MaybeParseGNUAttributes(attrs) || isAllowedCXX11AttributeSpecifier()) {
+    if (isAllowedCXX11AttributeSpecifier()) {
+      if (getLangOpts().CPlusPlus11)
         Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
                                     ? diag::warn_cxx14_compat_ns_enum_attribute
                                     : diag::ext_ns_enum_attribute)
             << 0 /*namespace*/;
-        ParseCXX11Attributes(attrs);
-        MoreToParse = true;
-      }
-    } while (MoreToParse);
-  };
-
-  ReadAttributes();
+      ParseCXX11Attributes(attrs);
+    }
+  }
 
   if (Tok.is(tok::identifier)) {
     Ident = Tok.getIdentifierInfo();
@@ -126,7 +116,9 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
     }
   }
 
-  ReadAttributes();
+  DiagnoseAndSkipCXX11Attributes();
+  MaybeParseGNUAttributes(attrs);
+  DiagnoseAndSkipCXX11Attributes();
 
   SourceLocation attrLoc = attrs.Range.getBegin();
 
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index a9deae74cf27c..c79ba97a20077 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -1003,7 +1003,9 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
       // the 'update' clause, so we have to handle it here.  U se an assert to
       // make sure we get the right differentiator.
       assert(DirKind == OpenACCDirectiveKind::Update);
-      [[fallthrough]];
+      ParsedClause.setVarListDetails(ParseOpenACCVarList(ClauseKind),
+                                     /*IsReadOnly=*/false, /*IsZero=*/false);
+      break;
     case OpenACCClauseKind::Device:
     case OpenACCClauseKind::DeviceResident:
     case OpenACCClauseKind::Host:
diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp
index 7109de03cadd1..837414c4840d7 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -281,9 +281,11 @@ template  static bool isRecordWithAttr(QualType Type) {
   return Result;
 }
 
-bool isPointerLikeType(QualType QT) {
-  return isRecordWithAttr(QT) || QT->isPointerType() ||
-         QT->isNullPtrType();
+// Tells whether the type is annotated with [[gsl::Pointer]].
+bool isGLSPointerType(QualType QT) { return isRecordWithAttr(QT); }
+
+static bool isPointerLikeType(QualType QT) {
+  return isGLSPointerType(QT) || QT->isPointerType() || QT->isNullPtrType();
 }
 
 // Decl::isInStdNamespace will return false for iterators in some STL
diff --git a/clang/lib/Sema/CheckExprLifetime.h b/clang/lib/Sema/CheckExprLifetime.h
index 95c249c610977..6351e52a362f1 100644
--- a/clang/lib/Sema/CheckExprLifetime.h
+++ b/clang/lib/Sema/CheckExprLifetime.h
@@ -18,9 +18,8 @@
 
 namespace clang::sema {
 
-// Tells whether the type is annotated with [[gsl::Pointer]] or is a pointer
-// type.
-bool isPointerLikeType(QualType QT);
+// Tells whether the type is annotated with [[gsl::Pointer]].
+bool isGLSPointerType(QualType QT);
 
 /// Describes an entity that is being assigned.
 struct AssignedEntity {
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 44485e71d57a0..6907fa91e28c2 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -284,7 +284,7 @@ void Sema::inferLifetimeCaptureByAttribute(FunctionDecl *FD) {
       // We only apply the lifetime_capture_by attribute to parameters of
       // pointer-like reference types (`const T&`, `T&&`).
       if (PVD->getType()->isReferenceType() &&
-          sema::isPointerLikeType(PVD->getType().getNonReferenceType())) {
+          sema::isGLSPointerType(PVD->getType().getNonReferenceType())) {
         int CaptureByThis[] = {LifetimeCaptureByAttr::THIS};
         PVD->addAttr(
             LifetimeCaptureByAttr::CreateImplicit(Context, CaptureByThis, 1));
@@ -307,8 +307,8 @@ void Sema::inferLifetimeCaptureByAttribute(FunctionDecl *FD) {
       Annotate(MD);
     return;
   }
-  static const llvm::StringSet<> CapturingMethods{"insert", "push",
-                                                  "push_front", "push_back"};
+  static const llvm::StringSet<> CapturingMethods{
+      "insert", "insert_or_assign", "push", "push_front", "push_back"};
   if (!CapturingMethods.contains(MD->getName()))
     return;
   Annotate(MD);
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 10f4920a761f3..539de00bd104f 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -846,7 +846,7 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
                                     bool ForOverloadResolution) {
   // Don't check constraints if the function is dependent. Also don't check if
   // this is a function template specialization, as the call to
-  // CheckFunctionTemplateConstraints after this will check it
+  // CheckinstantiatedFunctionTemplateConstraints after this will check it
   // better.
   if (FD->isDependentContext() ||
       FD->getTemplatedKind() ==
@@ -1111,55 +1111,12 @@ bool Sema::EnsureTemplateArgumentListConstraints(
   return false;
 }
 
-static bool CheckFunctionConstraintsWithoutInstantiation(
-    Sema &SemaRef, SourceLocation PointOfInstantiation,
-    FunctionTemplateDecl *Template, ArrayRef TemplateArgs,
-    ConstraintSatisfaction &Satisfaction) {
-  SmallVector TemplateAC;
-  Template->getAssociatedConstraints(TemplateAC);
-  if (TemplateAC.empty()) {
-    Satisfaction.IsSatisfied = true;
-    return false;
-  }
-
-  LocalInstantiationScope Scope(SemaRef);
-
-  FunctionDecl *FD = Template->getTemplatedDecl();
-  // Collect the list of template arguments relative to the 'primary'
-  // template. We need the entire list, since the constraint is completely
-  // uninstantiated at this point.
-
-  // FIXME: Add TemplateArgs through the 'Innermost' parameter once
-  // the refactoring of getTemplateInstantiationArgs() relands.
-  MultiLevelTemplateArgumentList MLTAL;
-  MLTAL.addOuterTemplateArguments(Template, std::nullopt, /*Final=*/false);
-  SemaRef.getTemplateInstantiationArgs(
-      MLTAL, /*D=*/FD, FD,
-      /*Final=*/false, /*Innermost=*/std::nullopt, /*RelativeToPrimary=*/true,
-      /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
-  MLTAL.replaceInnermostTemplateArguments(Template, TemplateArgs);
-
-  Sema::ContextRAII SavedContext(SemaRef, FD);
-  std::optional ThisScope;
-  if (auto *Method = dyn_cast(FD))
-    ThisScope.emplace(SemaRef, /*Record=*/Method->getParent(),
-                      /*ThisQuals=*/Method->getMethodQualifiers());
-  return SemaRef.CheckConstraintSatisfaction(
-      Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
-}
-
-bool Sema::CheckFunctionTemplateConstraints(
+bool Sema::CheckInstantiatedFunctionTemplateConstraints(
     SourceLocation PointOfInstantiation, FunctionDecl *Decl,
     ArrayRef TemplateArgs,
     ConstraintSatisfaction &Satisfaction) {
   // In most cases we're not going to have constraints, so check for that first.
   FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
-
-  if (!Template)
-    return ::CheckFunctionConstraintsWithoutInstantiation(
-        *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
-        TemplateArgs, Satisfaction);
-
   // Note - code synthesis context for the constraints check is created
   // inside CheckConstraintsSatisfaction.
   SmallVector TemplateAC;
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index ac5d51a1d2ff6..254ad05c5ba74 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1200,21 +1200,29 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
 
   case Expr::CXXDeleteExprClass: {
     auto *DE = cast(S);
-    CanThrowResult CT;
+    CanThrowResult CT = CT_Cannot;
     QualType DTy = DE->getDestroyedType();
     if (DTy.isNull() || DTy->isDependentType()) {
       CT = CT_Dependent;
     } else {
+      // C++20 [expr.delete]p6: If the value of the operand of the delete-
+      // expression is not a null pointer value and the selected deallocation
+      // function (see below) is not a destroying operator delete, the delete-
+      // expression will invoke the destructor (if any) for the object or the
+      // elements of the array being deleted.
       const FunctionDecl *OperatorDelete = DE->getOperatorDelete();
-      CT = canCalleeThrow(*this, DE, OperatorDelete);
-      if (!OperatorDelete->isDestroyingOperatorDelete()) {
-        if (const auto *RD = DTy->getAsCXXRecordDecl()) {
-          if (const CXXDestructorDecl *DD = RD->getDestructor())
-            CT = mergeCanThrow(CT, canCalleeThrow(*this, DE, DD));
-        }
-        if (CT == CT_Can)
-          return CT;
+      if (const auto *RD = DTy->getAsCXXRecordDecl()) {
+        if (const CXXDestructorDecl *DD = RD->getDestructor();
+            DD && DD->isCalledByDelete(OperatorDelete))
+          CT = canCalleeThrow(*this, DE, DD);
       }
+
+      // We always look at the exception specification of the operator delete.
+      CT = mergeCanThrow(CT, canCalleeThrow(*this, DE, OperatorDelete));
+
+      // If we know we can throw, we're done.
+      if (CT == CT_Can)
+        return CT;
     }
     return mergeCanThrow(CT, canSubStmtsThrow(*this, DE));
   }
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index e04ece0bda82e..1e39d69e8b230 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -3792,13 +3792,16 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
               .HasSizeT;
       }
 
-      if (!PointeeRD->hasIrrelevantDestructor())
+      if (!PointeeRD->hasIrrelevantDestructor()) {
         if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
-          MarkFunctionReferenced(StartLoc,
-                                    const_cast(Dtor));
-          if (DiagnoseUseOfDecl(Dtor, StartLoc))
-            return ExprError();
+          if (Dtor->isCalledByDelete(OperatorDelete)) {
+            MarkFunctionReferenced(StartLoc,
+                                   const_cast(Dtor));
+            if (DiagnoseUseOfDecl(Dtor, StartLoc))
+              return ExprError();
+          }
         }
+      }
 
       CheckVirtualDtorCall(PointeeRD->getDestructor(), StartLoc,
                            /*IsDelete=*/true, /*CallCanBeVirtual=*/true,
@@ -3833,8 +3836,9 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
     bool IsVirtualDelete = false;
     if (PointeeRD) {
       if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
-        CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor,
-                              PDiag(diag::err_access_dtor) << PointeeElem);
+        if (Dtor->isCalledByDelete(OperatorDelete))
+          CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor,
+                                PDiag(diag::err_access_dtor) << PointeeElem);
         IsVirtualDelete = Dtor->isVirtual();
       }
     }
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 1edff48331cd6..51a95f99f0624 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -736,14 +736,14 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause(
   // isn't really much to do here.
 
   // If the 'if' clause is true, it makes the 'self' clause have no effect,
-  // diagnose that here.
-  // TODO OpenACC: When we add these two to other constructs, we might not
-  // want to warn on this (for example, 'update').
-  const auto *Itr =
-      llvm::find_if(ExistingClauses, llvm::IsaPred);
-  if (Itr != ExistingClauses.end()) {
-    SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
-    SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
+  // diagnose that here.  This only applies on compute/combined constructs.
+  if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Update) {
+    const auto *Itr =
+        llvm::find_if(ExistingClauses, llvm::IsaPred);
+    if (Itr != ExistingClauses.end()) {
+      SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
+      SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
+    }
   }
 
   return OpenACCIfClause::Create(Ctx, Clause.getBeginLoc(),
@@ -753,16 +753,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause(
 
 OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause(
     SemaOpenACC::OpenACCParsedClause &Clause) {
-  // Restrictions only properly implemented on 'compute' constructs, and
-  // 'compute' constructs are the only construct that can do anything with
-  // this yet, so skip/treat as unimplemented in this case.
-  if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
-    return isNotImplemented();
-
-  // TODO OpenACC: When we implement this for 'update', this takes a
-  // 'var-list' instead of a condition expression, so semantics/handling has
-  // to happen differently here.
-
   // There is no prose in the standard that says duplicates aren't allowed,
   // but this diagnostic is present in other compilers, as well as makes
   // sense.
@@ -770,9 +760,12 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause(
     return nullptr;
 
   // If the 'if' clause is true, it makes the 'self' clause have no effect,
-  // diagnose that here.
-  // TODO OpenACC: When we add these two to other constructs, we might not
-  // want to warn on this (for example, 'update').
+  // diagnose that here.  This only applies on compute/combined constructs.
+  if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Update)
+    return OpenACCSelfClause::Create(Ctx, Clause.getBeginLoc(),
+                                     Clause.getLParenLoc(), Clause.getVarList(),
+                                     Clause.getEndLoc());
+
   const auto *Itr =
       llvm::find_if(ExistingClauses, llvm::IsaPred);
   if (Itr != ExistingClauses.end()) {
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index 422d8abc1028a..106e2430de901 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -619,12 +619,6 @@ 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)
@@ -661,8 +655,6 @@ 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/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 20ec2fbeaa6a8..ce672b00893b0 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4557,6 +4557,9 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
                              const TemplateArgumentListInfo *TemplateArgs) {
   assert(NamedConcept && "A concept template id without a template?");
 
+  if (NamedConcept->isInvalidDecl())
+    return ExprError();
+
   llvm::SmallVector SugaredConverted, CanonicalConverted;
   if (CheckTemplateArgumentList(
           NamedConcept, ConceptNameInfo.getLoc(),
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index acd1151184e42..1c1f6e30ab7b8 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3936,6 +3936,18 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
       Result != TemplateDeductionResult::Success)
     return Result;
 
+  // C++ [temp.deduct.call]p10: [DR1391]
+  //   If deduction succeeds for all parameters that contain
+  //   template-parameters that participate in template argument deduction,
+  //   and all template arguments are explicitly specified, deduced, or
+  //   obtained from default template arguments, remaining parameters are then
+  //   compared with the corresponding arguments. For each remaining parameter
+  //   P with a type that was non-dependent before substitution of any
+  //   explicitly-specified template arguments, if the corresponding argument
+  //   A cannot be implicitly converted to P, deduction fails.
+  if (CheckNonDependent())
+    return TemplateDeductionResult::NonDependentConversionFailure;
+
   // Form the template argument list from the deduced template arguments.
   TemplateArgumentList *SugaredDeducedArgumentList =
       TemplateArgumentList::CreateCopy(Context, SugaredBuilder);
@@ -3965,39 +3977,6 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
     FD = const_cast(FDFriend);
     Owner = FD->getLexicalDeclContext();
   }
-  // C++20 [temp.deduct.general]p5: [CWG2369]
-  //   If the function template has associated constraints, those constraints
-  //   are checked for satisfaction. If the constraints are not satisfied, type
-  //   deduction fails.
-  //
-  // FIXME: We haven't implemented CWG2369 for lambdas yet, because we need
-  // to figure out how to instantiate lambda captures to the scope without
-  // first instantiating the lambda.
-  bool IsLambda = isLambdaCallOperator(FD) || isLambdaConversionOperator(FD);
-  if (!IsLambda && !IsIncomplete) {
-    if (CheckFunctionTemplateConstraints(
-            Info.getLocation(),
-            FunctionTemplate->getCanonicalDecl()->getTemplatedDecl(),
-            CanonicalBuilder, Info.AssociatedConstraintsSatisfaction))
-      return TemplateDeductionResult::MiscellaneousDeductionFailure;
-    if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
-      Info.reset(Info.takeSugared(),
-                 TemplateArgumentList::CreateCopy(Context, CanonicalBuilder));
-      return TemplateDeductionResult::ConstraintsNotSatisfied;
-    }
-  }
-  // C++ [temp.deduct.call]p10: [CWG1391]
-  //   If deduction succeeds for all parameters that contain
-  //   template-parameters that participate in template argument deduction,
-  //   and all template arguments are explicitly specified, deduced, or
-  //   obtained from default template arguments, remaining parameters are then
-  //   compared with the corresponding arguments. For each remaining parameter
-  //   P with a type that was non-dependent before substitution of any
-  //   explicitly-specified template arguments, if the corresponding argument
-  //   A cannot be implicitly converted to P, deduction fails.
-  if (CheckNonDependent())
-    return TemplateDeductionResult::NonDependentConversionFailure;
-
   MultiLevelTemplateArgumentList SubstArgs(
       FunctionTemplate, CanonicalDeducedArgumentList->asArray(),
       /*Final=*/false);
@@ -4032,8 +4011,8 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
   //   ([temp.constr.decl]), those constraints are checked for satisfaction
   //   ([temp.constr.constr]). If the constraints are not satisfied, type
   //   deduction fails.
-  if (IsLambda && !IsIncomplete) {
-    if (CheckFunctionTemplateConstraints(
+  if (!IsIncomplete) {
+    if (CheckInstantiatedFunctionTemplateConstraints(
             Info.getLocation(), Specialization, CanonicalBuilder,
             Info.AssociatedConstraintsSatisfaction))
       return TemplateDeductionResult::MiscellaneousDeductionFailure;
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index 5d6c11a75303d..d42c3765aa534 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -902,12 +902,10 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef,
       Context.getTrivialTypeSourceInfo(
           Context.getDeducedTemplateSpecializationType(
               TemplateName(AliasTemplate), /*DeducedType=*/QualType(),
-              /*IsDependent=*/true),
-          AliasTemplate->getLocation()), // template specialization type whose
-                                         // arguments will be deduced.
+              /*IsDependent=*/true)), // template specialization type whose
+                                      // arguments will be deduced.
       Context.getTrivialTypeSourceInfo(
-          ReturnType, AliasTemplate->getLocation()), // type from which template
-                                                     // arguments are deduced.
+          ReturnType), // type from which template arguments are deduced.
   };
   return TypeTraitExpr::Create(
       Context, Context.getLogicalOperationType(), AliasTemplate->getLocation(),
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index cab9ae79ce5cb..fb0f38df62a74 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -475,21 +475,6 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
   assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
   // Accumulate the set of template argument lists in this structure.
   MultiLevelTemplateArgumentList Result;
-  getTemplateInstantiationArgs(
-      Result, ND, DC, Final, Innermost, RelativeToPrimary, Pattern,
-      ForConstraintInstantiation, SkipForSpecialization,
-      ForDefaultArgumentSubstitution);
-  return Result;
-}
-
-void Sema::getTemplateInstantiationArgs(
-    MultiLevelTemplateArgumentList &Result, const NamedDecl *ND,
-    const DeclContext *DC, bool Final,
-    std::optional> Innermost, bool RelativeToPrimary,
-    const FunctionDecl *Pattern, bool ForConstraintInstantiation,
-    bool SkipForSpecialization, bool ForDefaultArgumentSubstitution) {
-  assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
-  // Accumulate the set of template argument lists in this structure.
 
   using namespace TemplateInstArgsHelpers;
   const Decl *CurDecl = ND;
@@ -550,12 +535,14 @@ void Sema::getTemplateInstantiationArgs(
     }
 
     if (R.IsDone)
-      return;
+      return Result;
     if (R.ClearRelativeToPrimary)
       RelativeToPrimary = false;
     assert(R.NextDecl);
     CurDecl = R.NextDecl;
   }
+
+  return Result;
 }
 
 bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
@@ -1362,19 +1349,6 @@ namespace {
     // Whether an incomplete substituion should be treated as an error.
     bool BailOutOnIncomplete;
 
-  private:
-    bool isSubstitutingConstraints() const {
-      return llvm::any_of(SemaRef.CodeSynthesisContexts, [](auto &Context) {
-        return Context.Kind ==
-               Sema::CodeSynthesisContext::ConstraintSubstitution;
-      });
-    }
-
-    // CWG2770: Function parameters should be instantiated when they are
-    // needed by a satisfaction check of an atomic constraint or
-    // (recursively) by another function parameter.
-    bool maybeInstantiateFunctionParameterToScope(ParmVarDecl *OldParm);
-
   public:
     typedef TreeTransform inherited;
 
@@ -1431,19 +1405,12 @@ namespace {
                                  ArrayRef Unexpanded,
                                  bool &ShouldExpand, bool &RetainExpansion,
                                  std::optional &NumExpansions) {
-      if (SemaRef.CurrentInstantiationScope && isSubstitutingConstraints()) {
-        for (UnexpandedParameterPack ParmPack : Unexpanded) {
-          NamedDecl *VD = ParmPack.first.dyn_cast();
-          if (!isa_and_present(VD))
-            continue;
-          if (maybeInstantiateFunctionParameterToScope(cast(VD)))
-            return true;
-        }
-      }
-
-      return getSema().CheckParameterPacksForExpansion(
-          EllipsisLoc, PatternRange, Unexpanded, TemplateArgs, ShouldExpand,
-          RetainExpansion, NumExpansions);
+      return getSema().CheckParameterPacksForExpansion(EllipsisLoc,
+                                                       PatternRange, Unexpanded,
+                                                       TemplateArgs,
+                                                       ShouldExpand,
+                                                       RetainExpansion,
+                                                       NumExpansions);
     }
 
     void ExpandingFunctionParameterPack(ParmVarDecl *Pack) {
@@ -1944,62 +1911,9 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
     // template parameter.
   }
 
-  if (SemaRef.CurrentInstantiationScope) {
-    if (isSubstitutingConstraints() && isa(D) &&
-        maybeInstantiateFunctionParameterToScope(cast(D)))
-      return nullptr;
-  }
-
   return SemaRef.FindInstantiatedDecl(Loc, cast(D), TemplateArgs);
 }
 
-bool TemplateInstantiator::maybeInstantiateFunctionParameterToScope(
-    ParmVarDecl *OldParm) {
-  if (SemaRef.CurrentInstantiationScope->findInstantiationUnsafe(OldParm))
-    return false;
-  // We're instantiating a function parameter whose associated function template
-  // has not been instantiated at this point for constraint evaluation, so make
-  // sure the instantiated parameters are owned by a function declaration such
-  // that they can be correctly 'captured' in tryCaptureVariable().
-  Sema::ContextRAII Context(SemaRef, OldParm->getDeclContext());
-
-  if (!OldParm->isParameterPack())
-    return !TransformFunctionTypeParam(OldParm, /*indexAdjustment=*/0,
-                                       /*NumExpansions=*/std::nullopt,
-                                       /*ExpectParameterPack=*/false);
-
-  SmallVector Unexpanded;
-
-  // Find the parameter packs that could be expanded.
-  TypeLoc TL = OldParm->getTypeSourceInfo()->getTypeLoc();
-  PackExpansionTypeLoc ExpansionTL = TL.castAs();
-  TypeLoc Pattern = ExpansionTL.getPatternLoc();
-  SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded);
-  assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
-
-  bool ShouldExpand = false;
-  bool RetainExpansion = false;
-  std::optional OrigNumExpansions =
-      ExpansionTL.getTypePtr()->getNumExpansions();
-  std::optional NumExpansions = OrigNumExpansions;
-  if (TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
-                              Pattern.getSourceRange(), Unexpanded,
-                              ShouldExpand, RetainExpansion, NumExpansions))
-    return true;
-
-  assert(ShouldExpand && !RetainExpansion &&
-         "Shouldn't preserve pack expansion when evaluating constraints");
-  ExpandingFunctionParameterPack(OldParm);
-  for (unsigned I = 0; I != *NumExpansions; ++I) {
-    Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I);
-    if (!TransformFunctionTypeParam(OldParm, /*indexAdjustment=*/0,
-                                    /*NumExpansions=*/OrigNumExpansions,
-                                    /*ExpectParameterPack=*/false))
-      return true;
-  }
-  return false;
-}
-
 Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) {
   Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs);
   if (!Inst)
@@ -4677,8 +4591,9 @@ static const Decl *getCanonicalParmVarDecl(const Decl *D) {
   return D;
 }
 
+
 llvm::PointerUnion *
-LocalInstantiationScope::findInstantiationUnsafe(const Decl *D) {
+LocalInstantiationScope::findInstantiationOf(const Decl *D) {
   D = getCanonicalParmVarDecl(D);
   for (LocalInstantiationScope *Current = this; Current;
        Current = Current->Outer) {
@@ -4703,14 +4618,6 @@ LocalInstantiationScope::findInstantiationUnsafe(const Decl *D) {
       break;
   }
 
-  return nullptr;
-}
-
-llvm::PointerUnion *
-LocalInstantiationScope::findInstantiationOf(const Decl *D) {
-  auto *Result = findInstantiationUnsafe(D);
-  if (Result)
-    return Result;
   // If we're performing a partial substitution during template argument
   // deduction, we may not have values for template parameters yet.
   if (isa(D) || isa(D) ||
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index bff1e5bd8f078..d00ad5a35e823 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -713,7 +713,7 @@ class TreeTransform {
   /// variables vector are acceptable.
   ///
   /// LastParamTransformed, if non-null, will be set to the index of the last
-  /// parameter on which transformation was started. In the event of an error,
+  /// parameter on which transfromation was started. In the event of an error,
   /// this will contain the parameter which failed to instantiate.
   ///
   /// Return true on error.
@@ -11647,22 +11647,48 @@ template 
 void OpenACCClauseTransform::VisitSelfClause(
     const OpenACCSelfClause &C) {
 
-  if (C.hasConditionExpr()) {
-    Expr *Cond = const_cast(C.getConditionExpr());
-    Sema::ConditionResult Res =
-        Self.TransformCondition(Cond->getExprLoc(), /*Var=*/nullptr, Cond,
-                                Sema::ConditionKind::Boolean);
+  // If this is an 'update' 'self' clause, this is actually a var list instead.
+  if (ParsedClause.getDirectiveKind() == OpenACCDirectiveKind::Update) {
+    llvm::SmallVector InstantiatedVarList;
+    for (Expr *CurVar : C.getVarList()) {
+      ExprResult Res = Self.TransformExpr(CurVar);
 
-    if (Res.isInvalid() || !Res.get().second)
-      return;
+      if (!Res.isUsable())
+        continue;
 
-    ParsedClause.setConditionDetails(Res.get().second);
-  }
+      Res = Self.getSema().OpenACC().ActOnVar(ParsedClause.getClauseKind(),
+                                              Res.get());
 
-  NewClause = OpenACCSelfClause::Create(
-      Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
-      ParsedClause.getLParenLoc(), ParsedClause.getConditionExpr(),
-      ParsedClause.getEndLoc());
+      if (Res.isUsable())
+        InstantiatedVarList.push_back(Res.get());
+    }
+
+    ParsedClause.setVarListDetails(InstantiatedVarList,
+                                   /*IsReadOnly=*/false, /*IsZero=*/false);
+
+    NewClause = OpenACCSelfClause::Create(
+        Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
+        ParsedClause.getLParenLoc(), ParsedClause.getVarList(),
+        ParsedClause.getEndLoc());
+  } else {
+
+    if (C.hasConditionExpr()) {
+      Expr *Cond = const_cast(C.getConditionExpr());
+      Sema::ConditionResult Res =
+          Self.TransformCondition(Cond->getExprLoc(), /*Var=*/nullptr, Cond,
+                                  Sema::ConditionKind::Boolean);
+
+      if (Res.isInvalid() || !Res.get().second)
+        return;
+
+      ParsedClause.setConditionDetails(Res.get().second);
+    }
+
+    NewClause = OpenACCSelfClause::Create(
+        Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
+        ParsedClause.getLParenLoc(), ParsedClause.getConditionExpr(),
+        ParsedClause.getEndLoc());
+  }
 }
 
 template 
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 0c82e540047f8..0368990ca150d 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -12387,9 +12387,18 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
   }
   case OpenACCClauseKind::Self: {
     SourceLocation LParenLoc = readSourceLocation();
-    Expr *CondExpr = readBool() ? readSubExpr() : nullptr;
-    return OpenACCSelfClause::Create(getContext(), BeginLoc, LParenLoc,
-                                     CondExpr, EndLoc);
+    bool isConditionExprClause = readBool();
+    if (isConditionExprClause) {
+      Expr *CondExpr = readBool() ? readSubExpr() : nullptr;
+      return OpenACCSelfClause::Create(getContext(), BeginLoc, LParenLoc,
+                                       CondExpr, EndLoc);
+    }
+    unsigned NumVars = readInt();
+    llvm::SmallVector VarList;
+    for (unsigned I = 0; I < NumVars; ++I)
+      VarList.push_back(readSubExpr());
+    return OpenACCSelfClause::Create(getContext(), BeginLoc, LParenLoc, VarList,
+                                     EndLoc);
   }
   case OpenACCClauseKind::NumGangs: {
     SourceLocation LParenLoc = readSourceLocation();
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 719bc0d06f5b1..8c60e85c93d70 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2663,7 +2663,8 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
 
   D->setDeclaredWithTypename(Record.readInt());
 
-  if (D->hasTypeConstraint()) {
+  bool TypeConstraintInitialized = D->hasTypeConstraint() && Record.readBool();
+  if (TypeConstraintInitialized) {
     ConceptReference *CR = nullptr;
     if (Record.readBool())
       CR = Record.readConceptReference();
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 39f8b0fd5ba0f..8d9396e28ed50 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -8321,9 +8321,16 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
   case OpenACCClauseKind::Self: {
     const auto *SC = cast(C);
     writeSourceLocation(SC->getLParenLoc());
-    writeBool(SC->hasConditionExpr());
-    if (SC->hasConditionExpr())
-      AddStmt(const_cast(SC->getConditionExpr()));
+    writeBool(SC->isConditionExprClause());
+    if (SC->isConditionExprClause()) {
+      writeBool(SC->hasConditionExpr());
+      if (SC->hasConditionExpr())
+        AddStmt(const_cast(SC->getConditionExpr()));
+    } else {
+      writeUInt32(SC->getVarList().size());
+      for (Expr *E : SC->getVarList())
+        AddStmt(E);
+    }
     return;
   }
   case OpenACCClauseKind::NumGangs: {
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 75c1d9a6d438c..f8ed155ca389d 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1951,7 +1951,8 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
   Record.push_back(D->wasDeclaredWithTypename());
 
   const TypeConstraint *TC = D->getTypeConstraint();
-  assert((bool)TC == D->hasTypeConstraint());
+  if (D->hasTypeConstraint())
+    Record.push_back(/*TypeConstraintInitialized=*/TC != nullptr);
   if (TC) {
     auto *CR = TC->getConceptReference();
     Record.push_back(CR != nullptr);
@@ -1969,7 +1970,7 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
   if (OwnsDefaultArg)
     Record.AddTemplateArgumentLoc(D->getDefaultArgument());
 
-  if (!TC && !OwnsDefaultArg &&
+  if (!D->hasTypeConstraint() && !OwnsDefaultArg &&
       D->getDeclContext() == D->getLexicalDeclContext() &&
       !D->isInvalidDecl() && !D->hasAttrs() &&
       !D->isTopLevelDeclInObjCContainer() && !D->isImplicit() &&
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index 723764010d9a3..7034e8c56bd62 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -1010,7 +1010,7 @@ namespace FunctionStart {
   void a(void) {}
   static_assert(__builtin_function_start(a) == a, ""); // both-error {{not an integral constant expression}} \
                                                        // ref-note {{comparison against opaque constant address '&__builtin_function_start(a)'}} \
-                                                       // expected-note {{comparison of addresses of literals has unspecified value}}
+                                                       // expected-note {{comparison of addresses of potentially overlapping literals has unspecified value}}
 }
 
 namespace BuiltinInImplicitCtor {
diff --git a/clang/test/AST/ByteCode/cxx20.cpp b/clang/test/AST/ByteCode/cxx20.cpp
index dea4055c531d2..268362ceff635 100644
--- a/clang/test/AST/ByteCode/cxx20.cpp
+++ b/clang/test/AST/ByteCode/cxx20.cpp
@@ -115,7 +115,7 @@ constexpr auto name1() { return "name1"; }
 constexpr auto name2() { return "name2"; }
 
 constexpr auto b3 = name1() == name1(); // ref-error {{must be initialized by a constant expression}} \
-                                        // ref-note {{comparison of addresses of literals}}
+                                        // ref-note {{comparison of addresses of potentially overlapping literals}}
 constexpr auto b4 = name1() == name2();
 static_assert(!b4);
 
diff --git a/clang/test/AST/ByteCode/functions.cpp b/clang/test/AST/ByteCode/functions.cpp
index 10bea3a0d017e..66693a1fd7e32 100644
--- a/clang/test/AST/ByteCode/functions.cpp
+++ b/clang/test/AST/ByteCode/functions.cpp
@@ -208,11 +208,11 @@ namespace Comparison {
 
   constexpr bool u13 = pf < pg; // both-warning {{ordered comparison of function pointers}} \
                                 // both-error {{must be initialized by a constant expression}} \
-                                // both-note {{comparison between '&f' and '&g' has unspecified value}}
+                                // both-note {{comparison between pointers to unrelated objects '&f' and '&g' has unspecified value}}
 
   constexpr bool u14 = pf < (void(*)())nullptr; // both-warning {{ordered comparison of function pointers}} \
                                                 // both-error {{must be initialized by a constant expression}} \
-                                                // both-note {{comparison between '&f' and 'nullptr' has unspecified value}}
+                                                // both-note {{comparison between pointers to unrelated objects '&f' and 'nullptr' has unspecified value}}
 
 
 
diff --git a/clang/test/AST/ByteCode/literals.cpp b/clang/test/AST/ByteCode/literals.cpp
index 662823c49cd4a..3d415a93a392a 100644
--- a/clang/test/AST/ByteCode/literals.cpp
+++ b/clang/test/AST/ByteCode/literals.cpp
@@ -194,7 +194,7 @@ namespace PointerComparison {
   constexpr void *qv = (void*)&s.b;
   constexpr bool v1 = null < (int*)0;
   constexpr bool v2 = null < pv; // both-error {{must be initialized by a constant expression}} \
-                                 // both-note {{comparison between 'nullptr' and '&s.a' has unspecified value}}
+                                 // both-note {{comparison between pointers to unrelated objects 'nullptr' and '&s.a' has unspecified value}}
 
   constexpr bool v3 = null == pv; // ok
   constexpr bool v4 = qv == pv; // ok
@@ -202,7 +202,7 @@ namespace PointerComparison {
   constexpr bool v5 = qv >= pv;
   constexpr bool v8 = qv > (void*)&s.a;
   constexpr bool v6 = qv > null; // both-error {{must be initialized by a constant expression}} \
-                                 // both-note {{comparison between '&s.b' and 'nullptr' has unspecified value}}
+                                 // both-note {{comparison between pointers to unrelated objects '&s.b' and 'nullptr' has unspecified value}}
 
   constexpr bool v7 = qv <= (void*)&s.b; // ok
 
diff --git a/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl b/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl
deleted file mode 100644
index a36779c05fbc9..0000000000000
--- a/clang/test/AST/HLSL/HLSLControlFlowHint.hlsl
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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/AST/ast-print-openacc-update-construct.cpp b/clang/test/AST/ast-print-openacc-update-construct.cpp
index ce83bcad003a2..a7f5b2a42285b 100644
--- a/clang/test/AST/ast-print-openacc-update-construct.cpp
+++ b/clang/test/AST/ast-print-openacc-update-construct.cpp
@@ -35,4 +35,7 @@ void uses(bool cond) {
 
 // CHECK: #pragma acc update device_type(J) dtype(K)
 #pragma acc update device_type(J) dtype(K)
+
+// CHECK: #pragma acc update self(I, iPtr, array, array[1], array[1:2])
+#pragma acc update self(I, iPtr, array, array[1], array[1:2])
 }
diff --git a/clang/test/AST/attr-lifetime-capture-by.cpp b/clang/test/AST/attr-lifetime-capture-by.cpp
index 71b348dac764b..b453bef018c0b 100644
--- a/clang/test/AST/attr-lifetime-capture-by.cpp
+++ b/clang/test/AST/attr-lifetime-capture-by.cpp
@@ -80,16 +80,16 @@ std::vector pointers;
 
 // CHECK:       CXXMethodDecl {{.*}} push_back 'void (int *const &)'
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'int *const &'
-// CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
+// CHECK-NOT:               LifetimeCaptureByAttr
 
 // CHECK:       CXXMethodDecl {{.*}} push_back 'void (int *&&)'
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'int *&&'
-// CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
+// CHECK-NOT:               LifetimeCaptureByAttr
 
 // CHECK:       CXXMethodDecl {{.*}} insert 'void (iterator, int *&&)'
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'iterator'
 // CHECK-NEXT:           ParmVarDecl {{.*}} 'int *&&'
-// CHECK-NEXT:               LifetimeCaptureByAttr {{.*}} Implicit
+// CHECK-NOT:               LifetimeCaptureByAttr
 
 std::vector ints;
 // CHECK:   ClassTemplateSpecializationDecl {{.*}} struct vector definition implicit_instantiation
diff --git a/clang/test/Analysis/z3/crosscheck-statistics.c b/clang/test/Analysis/z3/crosscheck-statistics.c
index 7192824c5be31..8db3df169f246 100644
--- a/clang/test/Analysis/z3/crosscheck-statistics.c
+++ b/clang/test/Analysis/z3/crosscheck-statistics.c
@@ -28,6 +28,6 @@ int rejecting(int n, int x) {
 // CHECK-NEXT:  1 BugReporter         - Number of reports passed Z3
 // CHECK-NEXT:  1 BugReporter         - Number of reports refuted by Z3
 
-// CHECK:       1 Z3CrosscheckVisitor - Number of Z3 queries accepting a report
-// CHECK-NEXT:  1 Z3CrosscheckVisitor - Number of Z3 queries rejecting a report
-// CHECK-NEXT:  2 Z3CrosscheckVisitor - Number of Z3 queries done
+// CHECK:       1 Z3CrosscheckOracle - Number of Z3 queries accepting a report
+// CHECK-NEXT:  1 Z3CrosscheckOracle - Number of Z3 queries rejecting a report
+// CHECK-NEXT:  2 Z3CrosscheckOracle - Number of Z3 queries done
diff --git a/clang/test/CXX/drs/cwg23xx.cpp b/clang/test/CXX/drs/cwg23xx.cpp
index d0ec48e3f86cd..d144cf9e4e868 100644
--- a/clang/test/CXX/drs/cwg23xx.cpp
+++ b/clang/test/CXX/drs/cwg23xx.cpp
@@ -365,35 +365,6 @@ struct A {
 #endif
 } // namespace cwg2363
 
-namespace cwg2369 { // cwg2369: partial
-#if __cplusplus >= 202002L
-template  struct Z {
-  typedef typename T::x xx;
-};
-
-template 
-concept C = requires { typename T::A; };
-template  typename Z::xx f(void *, T); // #1
-template  void f(int, T);             // #2
-
-struct A {
-} a;
-
-struct ZZ {
-  template ::xx> operator T *();
-  operator int();
-};
-
-void foo() {
-  ZZ zz;
-  f(1, a); // OK, deduction fails for #1 because there is no conversion from int
-           // to void*
-  f(zz, 42); // OK, deduction fails for #1 because C is not satisfied
-}
-
-#endif
-} // namespace cwg2369
-
 namespace cwg2370 { // cwg2370: no
 namespace N {
 typedef int type;
diff --git a/clang/test/CXX/drs/cwg26xx.cpp b/clang/test/CXX/drs/cwg26xx.cpp
index 23d7635ff9065..efc49b0b502a7 100644
--- a/clang/test/CXX/drs/cwg26xx.cpp
+++ b/clang/test/CXX/drs/cwg26xx.cpp
@@ -319,7 +319,7 @@ void f(T) requires requires { []() { T::invalid; } (); };
 //   since-cxx20-note@-3 {{in instantiation of requirement here}}
 //   since-cxx20-note@-4 {{while substituting template arguments into constraint expression here}}
 //   since-cxx20-note@#cwg2672-f-0 {{while checking constraint satisfaction for template 'f' required here}}
-//   since-cxx20-note@#cwg2672-f-0 {{while substituting deduced template arguments into function template 'f' [with T = int]}}
+//   since-cxx20-note@#cwg2672-f-0 {{in instantiation of function template specialization 'cwg2672::f' requested here}}
 void f(...);
 
 template 
diff --git a/clang/test/CXX/drs/cwg27xx.cpp b/clang/test/CXX/drs/cwg27xx.cpp
index 7caf36a9f23b2..a87d26dfc9acf 100644
--- a/clang/test/CXX/drs/cwg27xx.cpp
+++ b/clang/test/CXX/drs/cwg27xx.cpp
@@ -174,26 +174,6 @@ static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3)
 #endif
 } // namespace cwg2759
 
-namespace cwg2770 { // cwg2770: 20 open 2023-07-14
-#if __cplusplus >= 202002L
-template
-struct B {
-  static_assert(sizeof(T) == 1);
-  using type = int;
-};
-
-template
-int f(T t, typename B::type u) requires (sizeof(t) == 1);
-
-template
-int f(T t, long);
-
-int i = f(1, 2);
-int j = f('a', 2);
-
-#endif
-} // namespace cwg2770
-
 namespace cwg2789 { // cwg2789: 18
 #if __cplusplus >= 202302L
 template 
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index 67160ba571f33..df5ce108aca82 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -510,22 +510,22 @@ namespace UnspecifiedRelations {
   // different objects that are not members of the same array or to different
   // functions, or if only one of them is null, the results of pq, p<=q,
   // and p>=q are unspecified.
-  constexpr bool u1 = p < q; // expected-error {{constant expression}} expected-note {{comparison between '&a' and '&b' has unspecified value}}
-  constexpr bool u2 = p > q; // expected-error {{constant expression}} expected-note {{comparison between '&a' and '&b' has unspecified value}}
-  constexpr bool u3 = p <= q; // expected-error {{constant expression}} expected-note {{comparison between '&a' and '&b' has unspecified value}}
-  constexpr bool u4 = p >= q; // expected-error {{constant expression}} expected-note {{comparison between '&a' and '&b' has unspecified value}}
-  constexpr bool u5 = p < (int*)0; // expected-error {{constant expression}} expected-note {{comparison between '&a' and 'nullptr' has unspecified value}}
-  constexpr bool u6 = p <= (int*)0; // expected-error {{constant expression}} expected-note {{comparison between '&a' and 'nullptr' has unspecified value}}
-  constexpr bool u7 = p > (int*)0; // expected-error {{constant expression}} expected-note {{comparison between '&a' and 'nullptr' has unspecified value}}
-  constexpr bool u8 = p >= (int*)0; // expected-error {{constant expression}} expected-note {{comparison between '&a' and 'nullptr' has unspecified value}}
-  constexpr bool u9 = (int*)0 < q; // expected-error {{constant expression}} expected-note {{comparison between 'nullptr' and '&b' has unspecified value}}
-  constexpr bool u10 = (int*)0 <= q; // expected-error {{constant expression}} expected-note {{comparison between 'nullptr' and '&b' has unspecified value}}
-  constexpr bool u11 = (int*)0 > q; // expected-error {{constant expression}} expected-note {{comparison between 'nullptr' and '&b' has unspecified value}}
-  constexpr bool u12 = (int*)0 >= q; // expected-error {{constant expression}} expected-note {{comparison between 'nullptr' and '&b' has unspecified value}}
+  constexpr bool u1 = p < q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and '&b' has unspecified value}}
+  constexpr bool u2 = p > q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and '&b' has unspecified value}}
+  constexpr bool u3 = p <= q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and '&b' has unspecified value}}
+  constexpr bool u4 = p >= q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and '&b' has unspecified value}}
+  constexpr bool u5 = p < (int*)0; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and 'nullptr' has unspecified value}}
+  constexpr bool u6 = p <= (int*)0; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and 'nullptr' has unspecified value}}
+  constexpr bool u7 = p > (int*)0; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and 'nullptr' has unspecified value}}
+  constexpr bool u8 = p >= (int*)0; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&a' and 'nullptr' has unspecified value}}
+  constexpr bool u9 = (int*)0 < q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects 'nullptr' and '&b' has unspecified value}}
+  constexpr bool u10 = (int*)0 <= q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects 'nullptr' and '&b' has unspecified value}}
+  constexpr bool u11 = (int*)0 > q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects 'nullptr' and '&b' has unspecified value}}
+  constexpr bool u12 = (int*)0 >= q; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects 'nullptr' and '&b' has unspecified value}}
   void f(), g();
 
   constexpr void (*pf)() = &f, (*pg)() = &g;
-  constexpr bool u13 = pf < pg; // expected-error {{constant expression}} expected-note {{comparison between '&f' and '&g' has unspecified value}}
+  constexpr bool u13 = pf < pg; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&f' and '&g' has unspecified value}}
                                 // expected-warning@-1 {{ordered comparison of function pointers}}
   constexpr bool u14 = pf == pg;
 
@@ -578,11 +578,11 @@ namespace UnspecifiedRelations {
   constexpr void *pv = (void*)&s.a;
   constexpr void *qv = (void*)&s.b;
   constexpr bool v1 = null < (int*)0;
-  constexpr bool v2 = null < pv; // expected-error {{constant expression}} expected-note {{comparison between 'nullptr' and '&s.a' has unspecified value}}
+  constexpr bool v2 = null < pv; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects 'nullptr' and '&s.a' has unspecified value}}
   constexpr bool v3 = null == pv;
   constexpr bool v4 = qv == pv;
   constexpr bool v5 = qv >= pv;
-  constexpr bool v6 = qv > null; // expected-error {{constant expression}} expected-note {{comparison between '&s.b' and 'nullptr' has unspecified value}}
+  constexpr bool v6 = qv > null; // expected-error {{constant expression}} expected-note {{comparison between pointers to unrelated objects '&s.b' and 'nullptr' has unspecified value}}
   constexpr bool v7 = qv <= (void*)&s.b;
   constexpr bool v8 = qv > (void*)&s.a;
 }
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp
index a23f7dc595171..763d983d20f61 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp
@@ -154,7 +154,7 @@ void func() {
 
   bar();
   // expected-note@-1 {{while checking constraint satisfaction for template 'bar' required here}} \
-  // expected-note@-1 {{while substituting deduced template arguments into function template 'bar' [with T = int]}}
+  // expected-note@-1 {{in instantiation of function template specialization}}
   // expected-note@#bar {{in instantiation of static data member}}
   // expected-note@#bar {{in instantiation of requirement here}}
   // expected-note@#bar {{while checking the satisfaction of nested requirement requested here}}
diff --git a/clang/test/CXX/expr/expr.unary/expr.delete/p10.cpp b/clang/test/CXX/expr/expr.unary/expr.delete/p10.cpp
index aad2747dd32f2..b8d64fd7eeabb 100644
--- a/clang/test/CXX/expr/expr.unary/expr.delete/p10.cpp
+++ b/clang/test/CXX/expr/expr.unary/expr.delete/p10.cpp
@@ -1,7 +1,14 @@
-// RUN: %clang_cc1 -std=c++1z -verify %s
+// RUN: %clang_cc1 -std=c++20 -verify %s
 
 using size_t = decltype(sizeof(0));
-namespace std { enum class align_val_t : size_t {}; }
+namespace std {
+  enum class align_val_t : size_t {};
+  struct destroying_delete_t {
+    explicit destroying_delete_t() = default;
+  };
+
+  inline constexpr destroying_delete_t destroying_delete{};
+}
 
 // Aligned version is preferred over unaligned version,
 // unsized version is preferred over sized version.
@@ -23,3 +30,41 @@ struct alignas(Align) B {
 };
 void f(B<__STDCPP_DEFAULT_NEW_ALIGNMENT__> *p) { delete p; }
 void f(B<__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2> *p) { delete p; } // expected-error {{deleted}}
+
+// Ensure that a deleted destructor is acceptable when the selected overload
+// for operator delete is a destroying delete. See the comments in GH118660.
+struct S {
+  ~S() = delete;
+  void operator delete(S *, std::destroying_delete_t) noexcept {}
+};
+
+struct T {
+  void operator delete(T *, std::destroying_delete_t) noexcept {}
+private:
+  ~T();
+};
+
+void foo(S *s, T *t) {
+  delete s; // Was rejected, is intended to be accepted.
+  delete t; // Was rejected, is intended to be accepted.
+}
+
+// However, if the destructor is virtual, then it has to be accessible because
+// the behavior depends on which operator delete is selected and that is based
+// on the dynamic type of the pointer.
+struct U {
+  virtual ~U() = delete; // expected-note {{here}}
+  void operator delete(U *, std::destroying_delete_t) noexcept {}
+};
+
+struct V {
+  void operator delete(V *, std::destroying_delete_t) noexcept {}
+private:
+  virtual ~V(); // expected-note {{here}}
+};
+
+void bar(U *u, V *v) {
+  // Both should be rejected because they have virtual destructors.
+  delete u; // expected-error {{attempt to use a deleted function}}
+  delete v; // expected-error {{calling a private destructor of class 'V'}}
+}
diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp
index c41de77986bca..ba8e2dc372e98 100644
--- a/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp
+++ b/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp
@@ -11,7 +11,7 @@ template struct S {
 
 // expected-error@+3{{atomic constraint must be of type 'bool' (found 'S')}}
 // expected-note@#FINST{{while checking constraint satisfaction}}
-// expected-note@#FINST{{while substituting deduced template arguments into function template 'f' [with T = int]}}
+// expected-note@#FINST{{in instantiation of function template specialization}}
 template requires (S{})
 void f(T);
 void f(int);
@@ -19,7 +19,7 @@ void f(int);
 // Ensure this applies to operator && as well.
 // expected-error@+3{{atomic constraint must be of type 'bool' (found 'S')}}
 // expected-note@#F2INST{{while checking constraint satisfaction}}
-// expected-note@#F2INST{{while substituting deduced template arguments into function template 'f2' [with T = int]}}
+// expected-note@#F2INST{{in instantiation of function template specialization}}
 template requires (S{} && true)
 void f2(T);
 void f2(int);
@@ -32,7 +32,7 @@ template requires requires {
   // expected-note@-4{{while checking the satisfaction}}
   // expected-note@-6{{while substituting template arguments}}
   // expected-note@#F3INST{{while checking constraint satisfaction}}
-  // expected-note@#F3INST{{while substituting deduced template arguments into function template 'f3' [with T = int]}}
+  // expected-note@#F3INST{{in instantiation of function template specialization}}
   //
 }
 void f3(T);
diff --git a/clang/test/CodeGen/AArch64/fmv-priority.c b/clang/test/CodeGen/AArch64/fmv-priority.c
new file mode 100644
index 0000000000000..080bb54736a75
--- /dev/null
+++ b/clang/test/CodeGen/AArch64/fmv-priority.c
@@ -0,0 +1,55 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs --version 5
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+// Priority biskmasks after feature dependency expansion:
+//
+// MSB                                                    LSB
+//
+// sme2 | ls64 | sme | bf16 |       |      | fp16 | simd | fp
+// -----+------+-----+------+-------+------+------+------+---
+// sme2 |      | sme | bf16 | rcpc2 | rcpc | fp16 | simd | fp
+//
+// Dependencies should not affect priorities, since a
+// feature can only depend on lower priority features:
+// https://github.com/ARM-software/acle/pull/376
+
+__attribute__((target_version("sme2+ls64"))) int fn(void);
+__attribute__((target_version("sme2+rcpc2"))) int fn(void);
+__attribute__((target_version("default"))) int fn(void) { return 0; }
+
+int call() { return fn(); }
+
+// CHECK-LABEL: define dso_local i32 @fn.default(
+// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    ret i32 0
+//
+//
+// CHECK-LABEL: define dso_local i32 @call(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[CALL:%.*]] = call i32 @fn()
+// CHECK-NEXT:    ret i32 [[CALL]]
+//
+//
+// CHECK-LABEL: define weak_odr ptr @fn.resolver() comdat {
+// CHECK-NEXT:  [[RESOLVER_ENTRY:.*:]]
+// CHECK-NEXT:    call void @__init_cpu_features_resolver()
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 153126785511392000
+// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 153126785511392000
+// CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
+// CHECK-NEXT:    br i1 [[TMP3]], label %[[RESOLVER_RETURN:.*]], label %[[RESOLVER_ELSE:.*]]
+// CHECK:       [[RESOLVER_RETURN]]:
+// CHECK-NEXT:    ret ptr @fn._Mls64Msme2
+// CHECK:       [[RESOLVER_ELSE]]:
+// CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
+// CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 144119586269233920
+// CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 144119586269233920
+// CHECK-NEXT:    [[TMP7:%.*]] = and i1 true, [[TMP6]]
+// CHECK-NEXT:    br i1 [[TMP7]], label %[[RESOLVER_RETURN1:.*]], label %[[RESOLVER_ELSE2:.*]]
+// CHECK:       [[RESOLVER_RETURN1]]:
+// CHECK-NEXT:    ret ptr @fn._Mrcpc2Msme2
+// CHECK:       [[RESOLVER_ELSE2]]:
+// CHECK-NEXT:    ret ptr @fn.default
+//
diff --git a/clang/test/CodeGen/attr-target-clones-aarch64.c b/clang/test/CodeGen/attr-target-clones-aarch64.c
index 50c040f2093b0..b7e3a328db877 100644
--- a/clang/test/CodeGen/attr-target-clones-aarch64.c
+++ b/clang/test/CodeGen/attr-target-clones-aarch64.c
@@ -64,20 +64,20 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 33664
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 33664
+// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 69793284352
+// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 69793284352
 // CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
 // CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
-// CHECK-NEXT:    ret ptr @ftc._MaesMlse
+// CHECK-NEXT:    ret ptr @ftc._Msve2
 // CHECK:       resolver_else:
 // CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 69793284352
-// CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 69793284352
+// CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 33664
+// CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 33664
 // CHECK-NEXT:    [[TMP7:%.*]] = and i1 true, [[TMP6]]
 // CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK:       resolver_return1:
-// CHECK-NEXT:    ret ptr @ftc._Msve2
+// CHECK-NEXT:    ret ptr @ftc._MaesMlse
 // CHECK:       resolver_else2:
 // CHECK-NEXT:    ret ptr @ftc.default
 //
@@ -411,20 +411,20 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 70369817985280
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 70369817985280
+// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 1125899906842624
+// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1125899906842624
 // CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
 // CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
-// CHECK-NEXT:    ret ptr @ftc_inline3._MsbMsve
+// CHECK-NEXT:    ret ptr @ftc_inline3._Mbti
 // CHECK:       resolver_else:
 // CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 1125899906842624
-// CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 1125899906842624
+// CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 70369817985280
+// CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 70369817985280
 // CHECK-NEXT:    [[TMP7:%.*]] = and i1 true, [[TMP6]]
 // CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK:       resolver_return1:
-// CHECK-NEXT:    ret ptr @ftc_inline3._Mbti
+// CHECK-NEXT:    ret ptr @ftc_inline3._MsbMsve
 // CHECK:       resolver_else2:
 // CHECK-NEXT:    ret ptr @ftc_inline3.default
 //
@@ -521,20 +521,20 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
 // CHECK-MTE-BTI-NEXT:  resolver_entry:
 // CHECK-MTE-BTI-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-MTE-BTI-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-MTE-BTI-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 33664
-// CHECK-MTE-BTI-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 33664
+// CHECK-MTE-BTI-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 69793284352
+// CHECK-MTE-BTI-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 69793284352
 // CHECK-MTE-BTI-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
 // CHECK-MTE-BTI-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK-MTE-BTI:       resolver_return:
-// CHECK-MTE-BTI-NEXT:    ret ptr @ftc._MaesMlse
+// CHECK-MTE-BTI-NEXT:    ret ptr @ftc._Msve2
 // CHECK-MTE-BTI:       resolver_else:
 // CHECK-MTE-BTI-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-MTE-BTI-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 69793284352
-// CHECK-MTE-BTI-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 69793284352
+// CHECK-MTE-BTI-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 33664
+// CHECK-MTE-BTI-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 33664
 // CHECK-MTE-BTI-NEXT:    [[TMP7:%.*]] = and i1 true, [[TMP6]]
 // CHECK-MTE-BTI-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK-MTE-BTI:       resolver_return1:
-// CHECK-MTE-BTI-NEXT:    ret ptr @ftc._Msve2
+// CHECK-MTE-BTI-NEXT:    ret ptr @ftc._MaesMlse
 // CHECK-MTE-BTI:       resolver_else2:
 // CHECK-MTE-BTI-NEXT:    ret ptr @ftc.default
 //
@@ -868,20 +868,20 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
 // CHECK-MTE-BTI-NEXT:  resolver_entry:
 // CHECK-MTE-BTI-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-MTE-BTI-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-MTE-BTI-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 70369817985280
-// CHECK-MTE-BTI-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 70369817985280
+// CHECK-MTE-BTI-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 1125899906842624
+// CHECK-MTE-BTI-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 1125899906842624
 // CHECK-MTE-BTI-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
 // CHECK-MTE-BTI-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK-MTE-BTI:       resolver_return:
-// CHECK-MTE-BTI-NEXT:    ret ptr @ftc_inline3._MsbMsve
+// CHECK-MTE-BTI-NEXT:    ret ptr @ftc_inline3._Mbti
 // CHECK-MTE-BTI:       resolver_else:
 // CHECK-MTE-BTI-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-MTE-BTI-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 1125899906842624
-// CHECK-MTE-BTI-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 1125899906842624
+// CHECK-MTE-BTI-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 70369817985280
+// CHECK-MTE-BTI-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 70369817985280
 // CHECK-MTE-BTI-NEXT:    [[TMP7:%.*]] = and i1 true, [[TMP6]]
 // CHECK-MTE-BTI-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK-MTE-BTI:       resolver_return1:
-// CHECK-MTE-BTI-NEXT:    ret ptr @ftc_inline3._Mbti
+// CHECK-MTE-BTI-NEXT:    ret ptr @ftc_inline3._MsbMsve
 // CHECK-MTE-BTI:       resolver_else2:
 // CHECK-MTE-BTI-NEXT:    ret ptr @ftc_inline3.default
 //
diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c
index 2862151ea2943..336d8b0a4dffa 100644
--- a/clang/test/CodeGen/attr-target-version.c
+++ b/clang/test/CodeGen/attr-target-version.c
@@ -463,12 +463,12 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 66315
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 66315
+// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 144119586256651008
+// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 144119586256651008
 // CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
 // CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
-// CHECK-NEXT:    ret ptr @fmv._MflagmMfp16fmlMrng
+// CHECK-NEXT:    ret ptr @fmv._Msme2
 // CHECK:       resolver_else:
 // CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 72061992218723078
@@ -479,60 +479,60 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK-NEXT:    ret ptr @fmv._Mflagm2Msme-i16i64
 // CHECK:       resolver_else2:
 // CHECK-NEXT:    [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 9007199254741776
-// CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 9007199254741776
+// CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 9007199254742016
+// CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 9007199254742016
 // CHECK-NEXT:    [[TMP11:%.*]] = and i1 true, [[TMP10]]
 // CHECK-NEXT:    br i1 [[TMP11]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]]
 // CHECK:       resolver_return3:
-// CHECK-NEXT:    ret ptr @fmv._MdotprodMls64
+// CHECK-NEXT:    ret ptr @fmv._McrcMls64
 // CHECK:       resolver_else4:
 // CHECK-NEXT:    [[TMP12:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP13:%.*]] = and i64 [[TMP12]], 9007199254742016
-// CHECK-NEXT:    [[TMP14:%.*]] = icmp eq i64 [[TMP13]], 9007199254742016
+// CHECK-NEXT:    [[TMP13:%.*]] = and i64 [[TMP12]], 9007199254741776
+// CHECK-NEXT:    [[TMP14:%.*]] = icmp eq i64 [[TMP13]], 9007199254741776
 // CHECK-NEXT:    [[TMP15:%.*]] = and i1 true, [[TMP14]]
 // CHECK-NEXT:    br i1 [[TMP15]], label [[RESOLVER_RETURN5:%.*]], label [[RESOLVER_ELSE6:%.*]]
 // CHECK:       resolver_return5:
-// CHECK-NEXT:    ret ptr @fmv._McrcMls64
+// CHECK-NEXT:    ret ptr @fmv._MdotprodMls64
 // CHECK:       resolver_else6:
 // CHECK-NEXT:    [[TMP16:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP17:%.*]] = and i64 [[TMP16]], 17592186110728
-// CHECK-NEXT:    [[TMP18:%.*]] = icmp eq i64 [[TMP17]], 17592186110728
+// CHECK-NEXT:    [[TMP17:%.*]] = and i64 [[TMP16]], 1125899906842624
+// CHECK-NEXT:    [[TMP18:%.*]] = icmp eq i64 [[TMP17]], 1125899906842624
 // CHECK-NEXT:    [[TMP19:%.*]] = and i1 true, [[TMP18]]
 // CHECK-NEXT:    br i1 [[TMP19]], label [[RESOLVER_RETURN7:%.*]], label [[RESOLVER_ELSE8:%.*]]
 // CHECK:       resolver_return7:
-// CHECK-NEXT:    ret ptr @fmv._Mfp16fmlMmemtag
+// CHECK-NEXT:    ret ptr @fmv._Mbti
 // CHECK:       resolver_else8:
 // CHECK-NEXT:    [[TMP20:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP21:%.*]] = and i64 [[TMP20]], 33536
-// CHECK-NEXT:    [[TMP22:%.*]] = icmp eq i64 [[TMP21]], 33536
+// CHECK-NEXT:    [[TMP21:%.*]] = and i64 [[TMP20]], 17592186110728
+// CHECK-NEXT:    [[TMP22:%.*]] = icmp eq i64 [[TMP21]], 17592186110728
 // CHECK-NEXT:    [[TMP23:%.*]] = and i1 true, [[TMP22]]
 // CHECK-NEXT:    br i1 [[TMP23]], label [[RESOLVER_RETURN9:%.*]], label [[RESOLVER_ELSE10:%.*]]
 // CHECK:       resolver_return9:
-// CHECK-NEXT:    ret ptr @fmv._MaesMfp
+// CHECK-NEXT:    ret ptr @fmv._Mfp16fmlMmemtag
 // CHECK:       resolver_else10:
 // CHECK-NEXT:    [[TMP24:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP25:%.*]] = and i64 [[TMP24]], 4992
-// CHECK-NEXT:    [[TMP26:%.*]] = icmp eq i64 [[TMP25]], 4992
+// CHECK-NEXT:    [[TMP25:%.*]] = and i64 [[TMP24]], 66315
+// CHECK-NEXT:    [[TMP26:%.*]] = icmp eq i64 [[TMP25]], 66315
 // CHECK-NEXT:    [[TMP27:%.*]] = and i1 true, [[TMP26]]
 // CHECK-NEXT:    br i1 [[TMP27]], label [[RESOLVER_RETURN11:%.*]], label [[RESOLVER_ELSE12:%.*]]
 // CHECK:       resolver_return11:
-// CHECK-NEXT:    ret ptr @fmv._MlseMsha2
+// CHECK-NEXT:    ret ptr @fmv._MflagmMfp16fmlMrng
 // CHECK:       resolver_else12:
 // CHECK-NEXT:    [[TMP28:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP29:%.*]] = and i64 [[TMP28]], 144119586256651008
-// CHECK-NEXT:    [[TMP30:%.*]] = icmp eq i64 [[TMP29]], 144119586256651008
+// CHECK-NEXT:    [[TMP29:%.*]] = and i64 [[TMP28]], 33536
+// CHECK-NEXT:    [[TMP30:%.*]] = icmp eq i64 [[TMP29]], 33536
 // CHECK-NEXT:    [[TMP31:%.*]] = and i1 true, [[TMP30]]
 // CHECK-NEXT:    br i1 [[TMP31]], label [[RESOLVER_RETURN13:%.*]], label [[RESOLVER_ELSE14:%.*]]
 // CHECK:       resolver_return13:
-// CHECK-NEXT:    ret ptr @fmv._Msme2
+// CHECK-NEXT:    ret ptr @fmv._MaesMfp
 // CHECK:       resolver_else14:
 // CHECK-NEXT:    [[TMP32:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP33:%.*]] = and i64 [[TMP32]], 1125899906842624
-// CHECK-NEXT:    [[TMP34:%.*]] = icmp eq i64 [[TMP33]], 1125899906842624
+// CHECK-NEXT:    [[TMP33:%.*]] = and i64 [[TMP32]], 4992
+// CHECK-NEXT:    [[TMP34:%.*]] = icmp eq i64 [[TMP33]], 4992
 // CHECK-NEXT:    [[TMP35:%.*]] = and i1 true, [[TMP34]]
 // CHECK-NEXT:    br i1 [[TMP35]], label [[RESOLVER_RETURN15:%.*]], label [[RESOLVER_ELSE16:%.*]]
 // CHECK:       resolver_return15:
-// CHECK-NEXT:    ret ptr @fmv._Mbti
+// CHECK-NEXT:    ret ptr @fmv._MlseMsha2
 // CHECK:       resolver_else16:
 // CHECK-NEXT:    ret ptr @fmv.default
 //
@@ -773,60 +773,60 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 4398182892352
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 4398182892352
+// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 864708720653762560
+// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 864708720653762560
 // CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
 // CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
-// CHECK-NEXT:    ret ptr @fmv_inline._MfcmaMfp16MrdmMsme
+// CHECK-NEXT:    ret ptr @fmv_inline._MmemtagMmopsMrcpc3
 // CHECK:       resolver_else:
 // CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 864708720653762560
-// CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 864708720653762560
+// CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 19861002584864
+// CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i64 [[TMP5]], 19861002584864
 // CHECK-NEXT:    [[TMP7:%.*]] = and i1 true, [[TMP6]]
 // CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK:       resolver_return1:
-// CHECK-NEXT:    ret ptr @fmv_inline._MmemtagMmopsMrcpc3
+// CHECK-NEXT:    ret ptr @fmv_inline._MmemtagMsve2-sm4
 // CHECK:       resolver_else2:
 // CHECK-NEXT:    [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 894427038464
-// CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 894427038464
+// CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 4398182892352
+// CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 4398182892352
 // CHECK-NEXT:    [[TMP11:%.*]] = and i1 true, [[TMP10]]
 // CHECK-NEXT:    br i1 [[TMP11]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]]
 // CHECK:       resolver_return3:
-// CHECK-NEXT:    ret ptr @fmv_inline._Msve2Msve2-aesMsve2-bitperm
+// CHECK-NEXT:    ret ptr @fmv_inline._MfcmaMfp16MrdmMsme
 // CHECK:       resolver_else4:
 // CHECK-NEXT:    [[TMP12:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP13:%.*]] = and i64 [[TMP12]], 35433583360
-// CHECK-NEXT:    [[TMP14:%.*]] = icmp eq i64 [[TMP13]], 35433583360
+// CHECK-NEXT:    [[TMP13:%.*]] = and i64 [[TMP12]], 1444182864640
+// CHECK-NEXT:    [[TMP14:%.*]] = icmp eq i64 [[TMP13]], 1444182864640
 // CHECK-NEXT:    [[TMP15:%.*]] = and i1 true, [[TMP14]]
 // CHECK-NEXT:    br i1 [[TMP15]], label [[RESOLVER_RETURN5:%.*]], label [[RESOLVER_ELSE6:%.*]]
 // CHECK:       resolver_return5:
-// CHECK-NEXT:    ret ptr @fmv_inline._MaesMf64mmMsha2
+// CHECK-NEXT:    ret ptr @fmv_inline._Msve2-aesMsve2-sha3
 // CHECK:       resolver_else6:
 // CHECK-NEXT:    [[TMP16:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP17:%.*]] = and i64 [[TMP16]], 18320798464
-// CHECK-NEXT:    [[TMP18:%.*]] = icmp eq i64 [[TMP17]], 18320798464
+// CHECK-NEXT:    [[TMP17:%.*]] = and i64 [[TMP16]], 894427038464
+// CHECK-NEXT:    [[TMP18:%.*]] = icmp eq i64 [[TMP17]], 894427038464
 // CHECK-NEXT:    [[TMP19:%.*]] = and i1 true, [[TMP18]]
 // CHECK-NEXT:    br i1 [[TMP19]], label [[RESOLVER_RETURN7:%.*]], label [[RESOLVER_ELSE8:%.*]]
 // CHECK:       resolver_return7:
-// CHECK-NEXT:    ret ptr @fmv_inline._Mf32mmMi8mmMsha3
+// CHECK-NEXT:    ret ptr @fmv_inline._Msve2Msve2-aesMsve2-bitperm
 // CHECK:       resolver_else8:
 // CHECK-NEXT:    [[TMP20:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP21:%.*]] = and i64 [[TMP20]], 19861002584864
-// CHECK-NEXT:    [[TMP22:%.*]] = icmp eq i64 [[TMP21]], 19861002584864
+// CHECK-NEXT:    [[TMP21:%.*]] = and i64 [[TMP20]], 35433583360
+// CHECK-NEXT:    [[TMP22:%.*]] = icmp eq i64 [[TMP21]], 35433583360
 // CHECK-NEXT:    [[TMP23:%.*]] = and i1 true, [[TMP22]]
 // CHECK-NEXT:    br i1 [[TMP23]], label [[RESOLVER_RETURN9:%.*]], label [[RESOLVER_ELSE10:%.*]]
 // CHECK:       resolver_return9:
-// CHECK-NEXT:    ret ptr @fmv_inline._MmemtagMsve2-sm4
+// CHECK-NEXT:    ret ptr @fmv_inline._MaesMf64mmMsha2
 // CHECK:       resolver_else10:
 // CHECK-NEXT:    [[TMP24:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
-// CHECK-NEXT:    [[TMP25:%.*]] = and i64 [[TMP24]], 1444182864640
-// CHECK-NEXT:    [[TMP26:%.*]] = icmp eq i64 [[TMP25]], 1444182864640
+// CHECK-NEXT:    [[TMP25:%.*]] = and i64 [[TMP24]], 18320798464
+// CHECK-NEXT:    [[TMP26:%.*]] = icmp eq i64 [[TMP25]], 18320798464
 // CHECK-NEXT:    [[TMP27:%.*]] = and i1 true, [[TMP26]]
 // CHECK-NEXT:    br i1 [[TMP27]], label [[RESOLVER_RETURN11:%.*]], label [[RESOLVER_ELSE12:%.*]]
 // CHECK:       resolver_return11:
-// CHECK-NEXT:    ret ptr @fmv_inline._Msve2-aesMsve2-sha3
+// CHECK-NEXT:    ret ptr @fmv_inline._Mf32mmMi8mmMsha3
 // CHECK:       resolver_else12:
 // CHECK-NEXT:    [[TMP28:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP29:%.*]] = and i64 [[TMP28]], 1208025856
diff --git a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset-when-nullptr-is-defined.c b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset-when-nullptr-is-defined.c
index 8a560a47ad1e1..00198b4faf8bc 100644
--- a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset-when-nullptr-is-defined.c
+++ b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset-when-nullptr-is-defined.c
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -x c -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLNOTOK,CHECK-SANITIZE-NULLNOTOK-C,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
-// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLNOTOK,CHECK-SANITIZE-NULLNOTOK-C,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
-// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLNOTOK,CHECK-SANITIZE-NULLNOTOK-C,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLNOTOK,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLNOTOK,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLNOTOK,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
 
 // RUN: %clang_cc1 -x c -fno-delete-null-pointer-checks -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
 // RUN: %clang_cc1 -x c -fno-delete-null-pointer-checks -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLOK,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
@@ -9,9 +9,9 @@
 // RUN: %clang_cc1 -x c -fno-delete-null-pointer-checks -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLOK,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
 
 // RUN: %clang_cc1 -x c++ -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLNOTOK,CHECK-SANITIZE-NULLNOTOK-CPP,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
-// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLNOTOK,CHECK-SANITIZE-NULLNOTOK-CPP,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
-// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLNOTOK,CHECK-SANITIZE-NULLNOTOK-CPP,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLNOTOK,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLNOTOK,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLNOTOK,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
 
 // RUN: %clang_cc1 -x c++ -fno-delete-null-pointer-checks -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
 // RUN: %clang_cc1 -x c++ -fno-delete-null-pointer-checks -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-NULLOK,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
@@ -42,8 +42,7 @@ char *add_unsigned(char *base, unsigned long offset) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], %[[COMPUTED_OFFSET]], !nosanitize
   // CHECK-SANITIZE-NULLNOTOK-NEXT:     %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
   // CHECK-SANITIZE-NULLNOTOK-NEXT:     %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-NULLNOTOK-C-NEXT:   %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-NULLNOTOK-CPP-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NULLNOTOK-NEXT:     %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize
diff --git a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c
index d884993ffb2b3..63b6db2c2adeb 100644
--- a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c
+++ b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c
@@ -1,12 +1,12 @@
 // RUN: %clang_cc1 -x c -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE,CHECK-SANITIZE-C,CHECK-SANITIZE-ANYRECOVER-C,CHECK-SANITIZE-NORECOVER-C,CHECK-SANITIZE-UNREACHABLE-C
-// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER,CHECK-SANITIZE-C,CHECK-SANITIZE-ANYRECOVER-C,CHECK-SANITIZE-RECOVER-C
-// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE,CHECK-SANITIZE-C,CHECK-SANITIZE-TRAP-C,CHECK-SANITIZE-UNREACHABLE-C
+// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
 
 // RUN: %clang_cc1 -x c++ -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE,CHECK-SANITIZE-CPP
-// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER,CHECK-SANITIZE-CPP
-// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE,CHECK-SANITIZE-CPP
+// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
 
 // In C++/LLVM IR, if the base pointer evaluates to a null pointer value,
 // the only valid pointer this inbounds GEP can produce is also a null pointer.
@@ -20,19 +20,15 @@
 // In C, however, offsetting null pointer is completely undefined, even by 0.
 
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_100:.*]] = {{.*}}, i32 100, i32 15 } }
-// CHECK-SANITIZE-ANYRECOVER-C-DAG: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 15 } }
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_300:.*]] = {{.*}}, i32 300, i32 15 } }
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_400:.*]] = {{.*}}, i32 400, i32 15 } }
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_500:.*]] = {{.*}}, i32 500, i32 15 } }
-// CHECK-SANITIZE-ANYRECOVER-C-DAG: @[[LINE_600:.*]] = {{.*}}, i32 600, i32 15 } }
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 15 } }
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 15 } }
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 15 } }
-// CHECK-SANITIZE-ANYRECOVER-C-DAG: @[[LINE_1000:.*]] = {{.*}}, i32 1000, i32 15 } }
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1100:.*]] = {{.*}}, i32 1100, i32 15 } }
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1200:.*]] = {{.*}}, i32 1200, i32 15 } }
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1300:.*]] = {{.*}}, i32 1300, i32 15 } }
-// CHECK-SANITIZE-ANYRECOVER-C-DAG: @[[LINE_1400:.*]] = {{.*}}, i32 1400, i32 15 } }
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1500:.*]] = {{.*}}, i32 1500, i32 15 } }
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1600:.*]] = {{.*}}, i32 1600, i32 15 } }
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1700:.*]] = {{.*}}, i32 1700, i32 15 } }
@@ -59,8 +55,7 @@ char *var_var(char *base, unsigned long offset) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], %[[COMPUTED_OFFSET]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize
@@ -84,21 +79,6 @@ char *var_zero(char *base) {
   // CHECK-NEXT:                          store ptr %[[BASE]], ptr %[[BASE_ADDR]], align 8
   // CHECK-NEXT:                          %[[BASE_RELOADED:.*]] = load ptr, ptr %[[BASE_ADDR]], align 8
   // CHECK-NEXT:                          %[[ADD_PTR:.*]] = getelementptr inbounds nuw i8, ptr %[[BASE_RELOADED]], i64 0
-  // CHECK-SANITIZE-C-NEXT:               %[[BASE_RELOADED_INT:.*]] = ptrtoint ptr %[[BASE_RELOADED]] to i64, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:               %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-C-NEXT:               %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
-  // CHECK-SANITIZE-C-NEXT:               %[[AND_TRUE:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], true, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:               %[[GEP_IS_OKAY:.*]] = and i1 %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL]], %[[AND_TRUE]], !nosanitize
-  // CHECK-SANITIZE-C-NEXT:               br i1 %[[GEP_IS_OKAY]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
-  // CHECK-SANITIZE-C:                  [[HANDLER_POINTER_OVERFLOW]]:
-  // CHECK-SANITIZE-NORECOVER-C-NEXT:     call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_200]], i64 %[[BASE_RELOADED_INT]], i64 %[[COMPUTED_GEP]])
-  // CHECK-SANITIZE-RECOVER-C-NEXT:       call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_200]], i64 %[[BASE_RELOADED_INT]], i64 %[[COMPUTED_GEP]])
-  // CHECK-SANITIZE-TRAP-C-NEXT:          call void @llvm.ubsantrap(i8 19){{.*}}, !nosanitize
-  // CHECK-SANITIZE-UNREACHABLE-C-NEXT:   unreachable, !nosanitize
-  // CHECK-SANITIZE-C:                  [[CONT]]:
   // CHECK-NEXT:                          ret ptr %[[ADD_PTR]]
   static const unsigned long offset = 0;
 #line 200
@@ -116,8 +96,7 @@ char *var_one(char *base) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], 1, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[AND_TRUE:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_IS_OKAY:.*]] = and i1 %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL]], %[[AND_TRUE]], !nosanitize
@@ -145,8 +124,7 @@ char *var_allones(char *base) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], -1, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[AND_TRUE:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_IS_OKAY:.*]] = and i1 %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL]], %[[AND_TRUE]], !nosanitize
@@ -178,8 +156,7 @@ char *nullptr_var(unsigned long offset) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_OFFSET:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 0, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 0, %[[COMPUTED_OFFSET]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 false, %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 false, %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 false, %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], 0, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize
@@ -200,13 +177,6 @@ char *nullptr_var(unsigned long offset) {
 char *nullptr_zero(void) {
   // CHECK:                             define{{.*}} ptr @nullptr_zero()
   // CHECK-NEXT:                        [[ENTRY:.*]]:
-  // CHECK-SANITIZE-C-NEXT:               br i1 false, label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
-  // CHECK-SANITIZE-C:                  [[HANDLER_POINTER_OVERFLOW]]:
-  // CHECK-SANITIZE-NORECOVER-C-NEXT:     call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_600]], i64 0, i64 0)
-  // CHECK-SANITIZE-RECOVER-C-NEXT:       call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_600]], i64 0, i64 0)
-  // CHECK-SANITIZE-TRAP-C-NEXT:          call void @llvm.ubsantrap(i8 19){{.*}}, !nosanitize
-  // CHECK-SANITIZE-UNREACHABLE-C-NEXT:   unreachable, !nosanitize
-  // CHECK-SANITIZE-C:                  [[CONT]]:
   // CHECK-NEXT:                          ret ptr null
   static char *const base = (char *)0;
   static const unsigned long offset = 0;
@@ -218,8 +188,7 @@ char *nullptr_one_BAD(void) {
   // CHECK:                           define{{.*}} ptr @nullptr_one_BAD()
   // CHECK-NEXT:                      [[ENTRY:.*]]:
   // CHECK-SANITIZE-NEXT:             %[[CMP:.*]] = icmp ne i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr null, i64 1) to i64), 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:           %[[COND:.*]] = and i1 false, %[[CMP]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:         %[[COND:.*]] = icmp eq i1 false, %[[CMP]], !nosanitize
+  // CHECK-SANITIZE-NEXT:             %[[COND:.*]] = icmp eq i1 false, %[[CMP]], !nosanitize
   // CHECK-SANITIZE-NEXT:             br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
   // CHECK-SANITIZE:                  [[HANDLER_POINTER_OVERFLOW]]:
   // CHECK-SANITIZE-NORECOVER-NEXT:     call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_700]], i64 0, i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr null, i64 1) to i64))
@@ -238,8 +207,7 @@ char *nullptr_allones_BAD(void) {
   // CHECK:                           define{{.*}} ptr @nullptr_allones_BAD()
   // CHECK-NEXT:                      [[ENTRY:.*]]:
   // CHECK-SANITIZE-NEXT:             %[[CMP:.*]] = icmp ne i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr null, i64 -1) to i64), 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:           %[[COND:.*]] = and i1 false, %[[CMP]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:         %[[COND:.*]] = icmp eq i1 false, %[[CMP]], !nosanitize
+  // CHECK-SANITIZE-NEXT:             %[[COND:.*]] = icmp eq i1 false, %[[CMP]], !nosanitize
   // CHECK-SANITIZE-NEXT:             br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
   // CHECK-SANITIZE:                  [[HANDLER_POINTER_OVERFLOW]]:
   // CHECK-SANITIZE-NORECOVER-NEXT:     call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_800]], i64 0, i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr null, i64 -1) to i64))
@@ -270,8 +238,7 @@ char *one_var(unsigned long offset) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 1, %[[COMPUTED_OFFSET]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[OTHER_IS_NOT_NULL:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], 1, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize
@@ -292,15 +259,6 @@ char *one_var(unsigned long offset) {
 char *one_zero(void) {
   // CHECK:                             define{{.*}} ptr @one_zero()
   // CHECK-NEXT:                        [[ENTRY:.*]]:
-  // CHECK-SANITIZE-C-NEXT:               %[[CMP:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null
-  // CHECK-SANITIZE-C-NEXT:               %[[AND:.*]] = and i1 %[[CMP]], true
-  // CHECK-SANITIZE-C-NEXT:               br i1 %[[AND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
-  // CHECK-SANITIZE-C:                  [[HANDLER_POINTER_OVERFLOW]]:
-  // CHECK-SANITIZE-NORECOVER-C-NEXT:     call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1000]], i64 1, i64 1)
-  // CHECK-SANITIZE-RECOVER-C-NEXT:       call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1000]], i64 1, i64 1)
-  // CHECK-SANITIZE-TRAP-C-NEXT:          call void @llvm.ubsantrap(i8 19){{.*}}, !nosanitize
-  // CHECK-SANITIZE-UNREACHABLE-C-NEXT:   unreachable, !nosanitize
-  // CHECK-SANITIZE-C:                  [[CONT]]:
   // CHECK-NEXT:                          ret ptr inttoptr (i64 1 to ptr)
   static char *const base = (char *)1;
   static const unsigned long offset = 0;
@@ -313,8 +271,7 @@ char *one_one_OK(void) {
   // CHECK-NEXT:                      [[ENTRY:.*]]:
   // CHECK-SANITIZE-NEXT:               %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1), 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[COND:.*]] = and i1 %[[CMP1]], %[[CMP2]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize
   // CHECK-SANITIZE-NEXT:               br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
   // CHECK-SANITIZE:                  [[HANDLER_POINTER_OVERFLOW]]:
   // CHECK-SANITIZE-NORECOVER-NEXT:     call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1100]], i64 1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1))
@@ -334,8 +291,7 @@ char *one_allones_BAD(void) {
   // CHECK-NEXT:                      [[ENTRY:.*]]:
   // CHECK-SANITIZE-NEXT:               %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1), 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[COND:.*]] = and i1 %[[CMP1]], %[[CMP2]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize
   // CHECK-SANITIZE-NEXT:               br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
   // CHECK-SANITIZE:                  [[HANDLER_POINTER_OVERFLOW]]:
   // CHECK-SANITIZE-NORECOVER-NEXT:     call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1200]], i64 1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1))
@@ -366,8 +322,7 @@ char *allones_var(unsigned long offset) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 -1, %[[COMPUTED_OFFSET]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[OTHER_IS_NOT_NULL:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], -1, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize
@@ -388,15 +343,6 @@ char *allones_var(unsigned long offset) {
 char *allones_zero_OK(void) {
   // CHECK:                             define{{.*}} ptr @allones_zero_OK()
   // CHECK-NEXT:                        [[ENTRY:.*]]:
-  // CHECK-SANITIZE-C-NEXT:               %[[CMP:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:               %[[AND:.*]] = and i1 %[[CMP]], true, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:               br i1 %[[AND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
-  // CHECK-SANITIZE-C:                  [[HANDLER_POINTER_OVERFLOW]]:
-  // CHECK-SANITIZE-NORECOVER-C-NEXT:     call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1400]], i64 -1, i64 -1)
-  // CHECK-SANITIZE-RECOVER-C-NEXT:       call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1400]], i64 -1, i64 -1)
-  // CHECK-SANITIZE-TRAP-C-NEXT:          call void @llvm.ubsantrap(i8 19){{.*}}, !nosanitize
-  // CHECK-SANITIZE-UNREACHABLE-C-NEXT:   unreachable, !nosanitize
-  // CHECK-SANITIZE-C:                  [[CONT]]:
   // CHECK-NEXT:                          ret ptr inttoptr (i64 -1 to ptr)
   static char *const base = (char *)-1;
   static const unsigned long offset = 0;
@@ -409,8 +355,7 @@ char *allones_one_BAD(void) {
   // CHECK-NEXT: [[ENTRY:.*]]:
   // CHECK-SANITIZE-NEXT:               %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1), 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[COND:.*]] = and i1 %[[CMP1]], %[[CMP2]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize
   // CHECK-SANITIZE-NEXT:               br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
   // CHECK-SANITIZE:                  [[HANDLER_POINTER_OVERFLOW]]:
   // CHECK-SANITIZE-NORECOVER-NEXT:     call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1500]], i64 -1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1))
@@ -430,8 +375,7 @@ char *allones_allones_OK(void) {
   // CHECK-NEXT: [[ENTRY:.*]]:
   // CHECK-SANITIZE-NEXT:               %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1), 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[COND:.*]] = and i1 %[[CMP1]], %[[CMP2]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize
   // CHECK-SANITIZE-NEXT:               br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
   // CHECK-SANITIZE:                  [[HANDLER_POINTER_OVERFLOW]]:
   // CHECK-SANITIZE-NORECOVER-NEXT:     call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1600]], i64 -1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1))
@@ -470,8 +414,7 @@ char *void_ptr(void *base, unsigned long offset) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], %[[COMPUTED_OFFSET]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize
diff --git a/clang/test/CodeGen/catch-pointer-overflow-volatile.c b/clang/test/CodeGen/catch-pointer-overflow-volatile.c
index 626bbc0db7afb..48a2ba360a4d3 100644
--- a/clang/test/CodeGen/catch-pointer-overflow-volatile.c
+++ b/clang/test/CodeGen/catch-pointer-overflow-volatile.c
@@ -1,12 +1,12 @@
 // RUN: %clang_cc1 -x c -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-C,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
-// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-C,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
-// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-C,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
 
 // RUN: %clang_cc1 -x c++ -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-CPP,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
-// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-CPP,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
-// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-CPP,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
 
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_100:.*]] = {{.*}}, i32 100, i32 15 } }
 
@@ -32,8 +32,7 @@ char *volatile_ptr(char *volatile base, unsigned long offset) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], %[[COMPUTED_OFFSET]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize
diff --git a/clang/test/CodeGen/catch-pointer-overflow.c b/clang/test/CodeGen/catch-pointer-overflow.c
index 1f7f1729098c7..4442994bfaae6 100644
--- a/clang/test/CodeGen/catch-pointer-overflow.c
+++ b/clang/test/CodeGen/catch-pointer-overflow.c
@@ -1,12 +1,12 @@
 // RUN: %clang_cc1 -x c -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-C,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
-// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-C,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
-// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-C,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
 
 // RUN: %clang_cc1 -x c++ -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-CPP,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
-// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-CPP,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
-// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-CPP,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE
+// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER
+// RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE
 
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_100:.*]] = {{.*}}, i32 100, i32 15 } }
 // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 15 } }
@@ -39,8 +39,7 @@ char *add_unsigned(char *base, unsigned long offset) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], %[[COMPUTED_OFFSET]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize
@@ -76,8 +75,7 @@ char *sub_unsigned(char *base, unsigned long offset) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], %[[COMPUTED_OFFSET]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_ULE_BASE:.*]] = icmp ule i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_ULE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize
@@ -112,8 +110,7 @@ char *add_signed(char *base, signed long offset) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], %[[COMPUTED_OFFSET]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[POSORZEROVALID:.*]] = icmp uge i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[POSORZEROOFFSET:.*]] = icmp sge i64 %[[COMPUTED_OFFSET]], 0, !nosanitize
@@ -152,8 +149,7 @@ char *sub_signed(char *base, signed long offset) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], %[[COMPUTED_OFFSET]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[POSORZEROVALID:.*]] = icmp uge i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[POSORZEROOFFSET:.*]] = icmp sge i64 %[[COMPUTED_OFFSET]], 0, !nosanitize
@@ -184,8 +180,7 @@ char *postinc(char *base) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], 1, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[AND_TRUE:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_IS_OKAY:.*]] = and i1 %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL]], %[[AND_TRUE]], !nosanitize
@@ -215,8 +210,7 @@ char *postdec(char *base) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], -1, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_ULE_BASE:.*]] = icmp ule i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[AND_TRUE:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_IS_OKAY:.*]] = and i1 %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL]], %[[AND_TRUE]], !nosanitize
@@ -246,8 +240,7 @@ char *preinc(char *base) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], 1, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[AND_TRUE:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_IS_OKAY:.*]] = and i1 %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL]], %[[AND_TRUE]], !nosanitize
@@ -277,8 +270,7 @@ char *predec(char *base) {
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP:.*]] = add i64 %[[BASE_RELOADED_INT]], -1, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[BASE_IS_NOT_NULLPTR:.*]] = icmp ne ptr %[[BASE_RELOADED]], null, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
-  // CHECK-SANITIZE-C-NEXT:             %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = and i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
-  // CHECK-SANITIZE-CPP-NEXT:           %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
+  // CHECK-SANITIZE-NEXT:               %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[BASE_IS_NOT_NULLPTR]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[COMPUTED_GEP_IS_ULE_BASE:.*]] = icmp ule i64 %[[COMPUTED_GEP]], %[[BASE_RELOADED_INT]], !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[AND_TRUE:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], true, !nosanitize
   // CHECK-SANITIZE-NEXT:               %[[GEP_IS_OKAY:.*]] = and i1 %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL]], %[[AND_TRUE]], !nosanitize
diff --git a/clang/test/CodeGen/tbaa-pointers.c b/clang/test/CodeGen/tbaa-pointers.c
index 6aee2ff3717ac..4aae2552f107a 100644
--- a/clang/test/CodeGen/tbaa-pointers.c
+++ b/clang/test/CodeGen/tbaa-pointers.c
@@ -193,11 +193,10 @@ typedef struct {
 void unamed_struct_typedef(TypedefS *ptr) {
 // COMMON-LABEL: define void @unamed_struct_typedef(
 // COMMON-SAME: ptr noundef [[PTRA:%.+]])
-// COMMON:   [[PTR_ADDR:%.+]]  = alloca ptr, align 8
+// COMMON:        [[PTR_ADDR:%.+]]  = alloca ptr, align 8
 // DISABLE-NEXT:  store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]]
-// DISABLE-NEXT:  [[L0:%.+]] = load ptr, ptr  [[PTR_ADDR]], align 8, !tbaa  [[ANYPTR]]
-// DEFAULT-NEXT:  store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[P1TYPEDEF:!.+]]
-// DEFAULT-NEXT:  [[L0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa  [[P1TYPEDEF]]
+// DEFAULT-NEXT:  store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR:!.+]]
+// COMMON-NEXT:   [[L0:%.+]] = load ptr, ptr [[PTR_ADDR]], align 8, !tbaa  [[ANYPTR]]
 // COMMON-NEXT:   [[GEP:%.+]]  = getelementptr inbounds nuw %struct.TypedefS, ptr [[L0]], i32 0, i32 0
 // COMMON-NEXT:   store i32 0, ptr [[GEP]], align 4
 // COMMON-NEXT:   ret void
@@ -205,6 +204,24 @@ void unamed_struct_typedef(TypedefS *ptr) {
   ptr->i1 = 0;
 }
 
+int void_ptrs(void **ptr) {
+// COMMON-LABEL: define i32 @void_ptrs(
+// COMMON-SAME: ptr noundef [[PTRA:%.+]])
+// COMMON:        [[PTR_ADDR:%.+]]  = alloca ptr, align 8
+// DISABLE-NEXT:  store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[ANYPTR]]
+// DISABLE-NEXT:  [[L0:%.+]] = load ptr, ptr  [[PTR_ADDR]], align 8, !tbaa  [[ANYPTR]]
+// DISABLE-NEXT:  [[L1:%.+]] = load ptr, ptr [[L0]], align 8, !tbaa  [[ANYPTR]]
+// DEFAULT-NEXT:  store ptr [[PTRA]], ptr [[PTR_ADDR]], align 8, !tbaa [[P2VOID:!.+]]
+// DEFAULT-NEXT:  [[L0:%.+]] = load ptr, ptr  [[PTR_ADDR]], align 8, !tbaa  [[P2VOID]]
+// DEFAULT-NEXT:  [[L1:%.+]] = load ptr, ptr [[L0]], align 8, !tbaa  [[P1VOID:!.+]]
+// COMMON-NEXT:   [[BOOL:%.+]] = icmp ne ptr [[L1]], null
+// COMMON-NEXT:   [[BOOL_EXT:%.+]] = zext i1 [[BOOL]] to i64
+// COMMON-NEXT:   [[COND:%.+]] = select i1 [[BOOL]], i32 0, i32 1
+// COMMON-NEXT:   ret i32 [[COND]]
+
+  return *ptr ? 0 : 1;
+}
+
 // DEFAULT: [[P2INT_0]] = !{[[P2INT:!.+]], [[P2INT]], i64 0}
 // DEFAULT: [[P2INT]] = !{!"p2 int", [[ANY_POINTER:!.+]], i64 0}
 // DISABLE: [[ANYPTR]] = !{[[ANY_POINTER:!.+]], [[ANY_POINTER]], i64 0}
@@ -236,4 +253,8 @@ void unamed_struct_typedef(TypedefS *ptr) {
 // DISABLE: [[S2_TY]]  = !{!"S2", [[ANY_POINTER]], i64 0}
 // COMMON:  [[INT_TAG]] = !{[[INT_TY:!.+]], [[INT_TY]], i64 0}
 // COMMON:  [[INT_TY]] = !{!"int", [[CHAR]], i64 0}
-// DEFAULT: [[P1TYPEDEF]] = !{[[ANY_POINTER]],  [[ANY_POINTER]], i64 0}
+// DEFAULT: [[ANYPTR]] = !{[[ANY_POINTER]],  [[ANY_POINTER]], i64 0}
+// DEFAULT: [[P2VOID]] = !{[[P2VOID_TY:!.+]], [[P2VOID_TY]], i64 0}
+// DEFAULT: [[P2VOID_TY]] = !{!"p2 void", [[ANY_POINTER]], i64 0}
+// DEFAULT: [[P1VOID]] = !{[[P1VOID_TY:!.+]], [[P1VOID_TY]], i64 0}
+// DEFAULT: [[P1VOID_TY]] = !{!"p1 void", [[ANY_POINTER]], i64 0}
diff --git a/clang/test/CodeGen/ubsan-pointer-overflow.c b/clang/test/CodeGen/ubsan-pointer-overflow.c
index db247e22c9b51..fd5b236504b16 100644
--- a/clang/test/CodeGen/ubsan-pointer-overflow.c
+++ b/clang/test/CodeGen/ubsan-pointer-overflow.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -x c -triple x86_64-apple-darwin10 -w -emit-llvm -o - %s -fsanitize=pointer-overflow | FileCheck %s --check-prefixes=CHECK,CHECK-C
-// RUN: %clang_cc1 -x c++ -triple x86_64-apple-darwin10 -w -emit-llvm -o - %s -fsanitize=pointer-overflow | FileCheck %s --check-prefixes=CHECK,CHECK-CPP
+// RUN: %clang_cc1 -x c -triple x86_64-apple-darwin10 -w -emit-llvm -o - %s -fsanitize=pointer-overflow | FileCheck %s
+// RUN: %clang_cc1 -x c++ -triple x86_64-apple-darwin10 -w -emit-llvm -o - %s -fsanitize=pointer-overflow | FileCheck %s
 
 #ifdef __cplusplus
 extern "C" {
@@ -110,8 +110,7 @@ void function_pointer_arith(funcptr_t *p, int k) {
 }
 
 // CHECK-LABEL: define{{.*}} void @dont_emit_checks_for_no_op_GEPs
-// CHECK-C: __ubsan_handle_pointer_overflow
-// CHECK-CPP-NOT: __ubsan_handle_pointer_overflow
+// CHECK-NOT: __ubsan_handle_pointer_overflow
 void dont_emit_checks_for_no_op_GEPs(char *p) {
   &p[0];
 
diff --git a/clang/test/CodeGenHLSL/HLSLControlFlowHint.hlsl b/clang/test/CodeGenHLSL/HLSLControlFlowHint.hlsl
deleted file mode 100644
index aa13b27581850..0000000000000
--- a/clang/test/CodeGenHLSL/HLSLControlFlowHint.hlsl
+++ /dev/null
@@ -1,48 +0,0 @@
-// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple spirv-vulkan-library %s -fnative-half-type -emit-llvm -o - | FileCheck %s
-
-// CHECK: define {{.*}} i32 {{.*}}test_branch{{.*}}(i32 {{.*}} [[VALD:%.*]])
-// CHECK: [[PARAM:%.*]] = load i32, ptr [[VALD]].addr, align 4
-// CHECK: [[CMP:%.*]] = icmp sgt i32 [[PARAM]], 0
-// CHECK: br i1 [[CMP]], label %if.then, label %if.else, !hlsl.controlflow.hint [[HINT_BRANCH:![0-9]+]]
-export int test_branch(int X){
-    int resp;
-    [branch] if (X > 0) {
-        resp = -X;
-    } else {
-        resp = X * 2;
-    }
-
-    return resp;
-}
-
-// CHECK: define {{.*}} i32 {{.*}}test_flatten{{.*}}(i32 {{.*}} [[VALD:%.*]])
-// CHECK: [[PARAM:%.*]] = load i32, ptr [[VALD]].addr, align 4
-// CHECK: [[CMP:%.*]] = icmp sgt i32 [[PARAM]], 0
-// CHECK: br i1 [[CMP]], label %if.then, label %if.else, !hlsl.controlflow.hint [[HINT_FLATTEN:![0-9]+]]
-export int test_flatten(int X){
-    int resp;
-    [flatten] if (X > 0) {
-        resp = -X;
-    } else {
-        resp = X * 2;
-    }
-
-    return resp;
-}
-
-// CHECK: define {{.*}} i32 {{.*}}test_no_attr{{.*}}(i32 {{.*}} [[VALD:%.*]])
-// CHECK-NOT: !hlsl.controlflow.hint
-export int test_no_attr(int X){
-    int resp;
-    if (X > 0) {
-        resp = -X;
-    } else {
-        resp = X * 2;
-    }
-
-    return resp;
-}
-
-//CHECK: [[HINT_BRANCH]] = !{!"hlsl.controlflow.hint", i32 1}
-//CHECK: [[HINT_FLATTEN]] = !{!"hlsl.controlflow.hint", i32 2}
diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
index 4428b77dd9ec8..2ad5b82a02912 100644
--- a/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-subscript.hlsl
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=DXC,CHECK
+// RUN: %clang_cc1 -triple spirv1.6-pc-vulkan1.3-compute -emit-llvm -o - -O0 %s | FileCheck %s --check-prefixes=SPIRV,CHECK
 
 RWBuffer In;
 RWBuffer Out;
@@ -7,15 +8,19 @@ RWBuffer Out;
 void main(unsigned GI : SV_GroupIndex) {
   // CHECK: define void @main()
 
-  // CHECK: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
+  // DXC: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
+  // SPIRV: %[[INPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}})
   // CHECK: %[[LOAD:.*]] = load i32, ptr %[[INPTR]]
-  // CHECK: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
+  // DXC: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
+  // SPIRV: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}})
   // CHECK: store i32 %[[LOAD]], ptr %[[OUTPTR]]
   Out[GI] = In[GI];
 
-  // CHECK: %[[INPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
+  // DXC: %[[INPTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
+  // SPIRV: %[[INPTR:.*]] = call ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}})
   // CHECK: %[[LOAD:.*]] = load i32, ptr %[[INPTR]]
-  // CHECK: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
+  // DXC: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_i32_1_0_1t(target("dx.TypedBuffer", i32, 1, 0, 1) %{{.*}}, i32 %{{.*}})
+  // SPIRV: %[[OUTPTR:.*]] = call noundef nonnull align 4 dereferenceable(4) ptr @llvm.spv.resource.getpointer.p0.tspirv.Image_i32_5_2_0_0_2_0t(target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %{{.*}}, i32 %{{.*}})
   // CHECK: store i32 %[[LOAD]], ptr %[[OUTPTR]]
   Out[GI] = In.Load(GI);
 }
diff --git a/clang/test/Driver/amdgpu-openmp-toolchain.c b/clang/test/Driver/amdgpu-openmp-toolchain.c
index f596708047c15..1c2ee26173139 100644
--- a/clang/test/Driver/amdgpu-openmp-toolchain.c
+++ b/clang/test/Driver/amdgpu-openmp-toolchain.c
@@ -81,3 +81,7 @@
 // RUN:   %clang -### --target=x86_64-unknown-linux-gnu -emit-llvm -S -fopenmp --offload-arch=gfx803 \
 // RUN:     -stdlib=libc++ -nogpulib %s 2>&1 | FileCheck %s --check-prefix=LIBCXX
 // LIBCXX-NOT: include/amdgcn-amd-amdhsa/c++/v1
+
+// RUN: %clang -### -target x86_64-pc-linux-gnu -nogpulib  -fopenmp --offload-arch=gfx90a \
+// RUN:   -ftime-report %s 2>&1 | FileCheck %s --check-prefix=CHECK-TIME-REPORT
+// CHECK-TIME-REPORT: clang-linker-wrapper{{.*}}"--device-compiler=-ftime-report"
diff --git a/clang/test/Driver/darwin-embedded-search-paths-libcxx.c b/clang/test/Driver/darwin-embedded-search-paths-libcxx.c
new file mode 100644
index 0000000000000..0f9a8467b061a
--- /dev/null
+++ b/clang/test/Driver/darwin-embedded-search-paths-libcxx.c
@@ -0,0 +1,45 @@
+// REQUIRES: default-cxx-stdlib=libc++
+// UNSUPPORTED: system-windows
+//   Windows is unsupported because we use the Unix path separator `/` in the test.
+
+// Unlike the Darwin driver, the MachO driver doesn't add any framework search paths,
+// only the normal header ones.
+// RUN: %clang -x c -target arm64-apple-none-macho -isysroot %S/Inputs/MacOSX15.1.sdk -### -c %s 2>&1 \
+// RUN: | FileCheck --check-prefixes=CC1,NO-CXX,ULI,CI,UI,NO-FW -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
+
+// Unlike the Darwin driver, the MachO driver doesn't default to libc++, but when
+// CLANG_DEFAULT_CXX_STDLIB is libc++ then the MachO driver should find the search path.
+// RUN: %clang -x c++ -target arm64-apple-none-macho -isysroot %S/Inputs/MacOSX15.1.sdk -### -c %s 2>&1 \
+// RUN: | FileCheck --check-prefixes=CC1,CXX,ULI,CI,UI,NO-FW -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
+
+// If the user requests libc++, the MachO driver should still find the search path.
+// RUN: %clang -x c++ -stdlib=libc++ -target arm64-apple-none-macho -isysroot %S/Inputs/MacOSX15.1.sdk -### -c %s 2>&1 \
+// RUN: | FileCheck --check-prefixes=CC1,CXX,ULI,CI,UI,NO-FW -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
+
+// Verify that embedded uses can swap in alternate usr/include and usr/local/include directories.
+// usr/local/include is specified in the driver as -internal-isystem, however, the driver generated
+// paths come before the paths in the driver arguments. In order to keep usr/local/include in the
+// same position, -isystem has to be used instead of -Xclang -internal-isystem. There isn't an
+// -externc-isystem, but it's ok to use -Xclang -internal-externc-isystem since the driver doesn't
+// use that if -nostdlibinc or -nostdinc is passed.
+// RUN: %clang -x c++ -stdlib=libc++ -target arm64-apple-none-macho -isysroot %S/Inputs/MacOSX15.1.sdk \
+// RUN:        -nostdlibinc -isystem %S/Inputs/MacOSX15.1.sdk/embedded/usr/local/include \
+// RUN:        -Xclang -internal-externc-isystem -Xclang %S/Inputs/MacOSX15.1.sdk/embedded/usr/include \
+// RUN:        -### -c %s 2>&1 | FileCheck --check-prefixes=CC1,NO-CXX,EULI,CI,EUI,NO-FW -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
+
+
+// The ordering of these flags doesn't matter, and so this test is a little
+// fragile. i.e. all of the -internal-isystem paths will be searched before the
+// -internal-externc-isystem ones, and their order on the command line doesn't
+// matter. The line order here is just the current order that the driver writes
+// the cc1 arguments.
+
+// CC1: "-cc1"
+// NO-CXX-NOT: "-internal-isystem" "{{.*}}/include/c++/v1"
+// CXX-SAME: "-internal-isystem" "{{.*}}/include/c++/v1"
+// ULI-SAME: "-internal-isystem" "[[SDKROOT]]/usr/local/include"
+// EULI-SAME: "-isystem" "[[SDKROOT]]/embedded/usr/local/include"
+// CI-SAME: "-internal-isystem" "{{.*}}/clang/{{[[:digit:].]*}}/include"
+// UI-SAME: "-internal-externc-isystem" "[[SDKROOT]]/usr/include"
+// EUI-SAME: "-internal-externc-isystem" "[[SDKROOT]]/embedded/usr/include"
+// NO-FW-NOT: "-internal-iframework"
diff --git a/clang/test/Driver/darwin-embedded-search-paths.c b/clang/test/Driver/darwin-embedded-search-paths.c
index 7ada467d66de4..bd651b7a1cd18 100644
--- a/clang/test/Driver/darwin-embedded-search-paths.c
+++ b/clang/test/Driver/darwin-embedded-search-paths.c
@@ -1,3 +1,4 @@
+// REQUIRES: !(default-cxx-stdlib=libc++)
 // UNSUPPORTED: system-windows
 //   Windows is unsupported because we use the Unix path separator `/` in the test.
 
@@ -6,7 +7,8 @@
 // RUN: %clang -x c -target arm64-apple-none-macho -isysroot %S/Inputs/MacOSX15.1.sdk -### -c %s 2>&1 \
 // RUN: | FileCheck --check-prefixes=CC1,NO-CXX,ULI,CI,UI,NO-FW -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
 
-// Unlike the Darwin driver, the MachO driver doesn't default to libc++
+// Unlike the Darwin driver, the MachO driver doesn't default to libc++, and unless
+// CLANG_DEFAULT_CXX_STDLIB is libc++ it won't add any search paths.
 // RUN: %clang -x c++ -target arm64-apple-none-macho -isysroot %S/Inputs/MacOSX15.1.sdk -### -c %s 2>&1 \
 // RUN: | FileCheck --check-prefixes=CC1,NO-CXX,ULI,CI,UI,NO-FW -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
 
@@ -33,11 +35,12 @@
 // the cc1 arguments.
 
 // CC1: "-cc1"
+// CC1: "-resource-dir" "[[RESOURCE_DIR:[^"]*]]"
 // NO-CXX-NOT: "-internal-isystem" "{{.*}}/include/c++/v1"
 // CXX-SAME: "-internal-isystem" "{{.*}}/include/c++/v1"
 // ULI-SAME: "-internal-isystem" "[[SDKROOT]]/usr/local/include"
 // EULI-SAME: "-isystem" "[[SDKROOT]]/embedded/usr/local/include"
-// CI-SAME: "-internal-isystem" "{{.*}}/clang/{{[[:digit:].]*}}/include"
+// CI-SAME: "-internal-isystem" "[[RESOURCE_DIR]]/include"
 // UI-SAME: "-internal-externc-isystem" "[[SDKROOT]]/usr/include"
 // EUI-SAME: "-internal-externc-isystem" "[[SDKROOT]]/embedded/usr/include"
 // NO-FW-NOT: "-internal-iframework"
diff --git a/clang/test/Driver/dxc_spirv.hlsl b/clang/test/Driver/dxc_spirv.hlsl
index c087ea4b0d709..e6624e5f1b3f6 100644
--- a/clang/test/Driver/dxc_spirv.hlsl
+++ b/clang/test/Driver/dxc_spirv.hlsl
@@ -6,8 +6,8 @@
 // CHECK: "-triple" "spirv-unknown-vulkan-compute"
 // CHECK-SAME: "-x" "hlsl"
 
-// CHECK-VULKAN12: "-triple" "spirv-unknown-vulkan1.2-compute"
+// CHECK-VULKAN12: "-triple" "spirv1.5-unknown-vulkan1.2-compute"
 
-// CHECK-VULKAN13: "-triple" "spirv-unknown-vulkan1.3-compute"
+// CHECK-VULKAN13: "-triple" "spirv1.6-unknown-vulkan1.3-compute"
 
 // CHECK-ERROR: error: invalid value 'vulkan1.0' in '-fspv-target-env=vulkan1.0'
diff --git a/clang/test/Driver/lto.c b/clang/test/Driver/lto.c
index 5be95013f00d7..a85f953af37a8 100644
--- a/clang/test/Driver/lto.c
+++ b/clang/test/Driver/lto.c
@@ -114,3 +114,9 @@
 //
 // CHECK-GISEL:         "-plugin-opt=-global-isel=1"
 // CHECK-DISABLE-GISEL: "-plugin-opt=-global-isel=0"
+
+// -flto passes -time-passes when -ftime-report is passed
+// RUN: %clang --target=x86_64-unknown-linux-gnu -### %s -flto -ftime-report 2> %t
+// RUN: FileCheck --check-prefix=CHECK-TIME-REPORT < %t %s
+
+// CHECK-TIME-REPORT: "-plugin-opt=-time-passes"
diff --git a/clang/test/Driver/riscv-cpus.c b/clang/test/Driver/riscv-cpus.c
index 1b09945620f8c..e97b6940662d9 100644
--- a/clang/test/Driver/riscv-cpus.c
+++ b/clang/test/Driver/riscv-cpus.c
@@ -433,6 +433,19 @@
 // MCPU-SIFIVE-P470-SAME: "-target-feature" "+zvkt"
 // MCPU-SIFIVE-P470-SAME: "-target-abi" "lp64d"
 
+// RUN: %clang -target riscv64 -### -c %s 2>&1 -mcpu=sifive-p550 | FileCheck -check-prefix=MCPU-SIFIVE-P550 %s
+// MCPU-SIFIVE-P550: "-nostdsysteminc" "-target-cpu" "sifive-p550"
+// MCPU-SIFIVE-P550-SAME: "-target-feature" "+m"
+// MCPU-SIFIVE-P550-SAME: "-target-feature" "+a"
+// MCPU-SIFIVE-P550-SAME: "-target-feature" "+f"
+// MCPU-SIFIVE-P550-SAME: "-target-feature" "+d"
+// MCPU-SIFIVE-P550-SAME: "-target-feature" "+c"
+// MCPU-SIFIVE-P550-SAME: "-target-feature" "+zicsr"
+// MCPU-SIFIVE-P550-SAME: "-target-feature" "+zifencei"
+// MCPU-SIFIVE-P550-SAME: "-target-feature" "+zba"
+// MCPU-SIFIVE-P550-SAME: "-target-feature" "+zbb"
+// MCPU-SIFIVE-P550-SAME: "-target-abi" "lp64d"
+
 // RUN: %clang -target riscv64 -### -c %s 2>&1 -mcpu=sifive-p670 | FileCheck -check-prefix=MCPU-SIFIVE-P670 %s
 // MCPU-SIFIVE-P670: "-target-cpu" "sifive-p670"
 // MCPU-SIFIVE-P670-SAME: "-target-feature" "+m"
diff --git a/clang/test/Driver/uefi-constructed-args.c b/clang/test/Driver/uefi-constructed-args.c
index e90857bb6fb5b..3cc5abe697453 100644
--- a/clang/test/Driver/uefi-constructed-args.c
+++ b/clang/test/Driver/uefi-constructed-args.c
@@ -4,6 +4,7 @@
 // CHECK-SAME: "-triple" "x86_64-unknown-uefi"
 // CHECK-SAME: "-mrelocation-model" "pic" "-pic-level" "2"
 // CHECK-SAME: "-mframe-pointer=all"
+// CHECK-SAME: "-fms-extensions"
 // CHECK-NEXT: "-nologo"
 // CHECK-SAME: "-subsystem:efi_application"
 // CHECK-SAME: "-entry:EfiMain"
diff --git a/clang/test/Misc/target-invalid-cpu-note/riscv.c b/clang/test/Misc/target-invalid-cpu-note/riscv.c
index fc8536d99cb80..fb54dcb5b3a93 100644
--- a/clang/test/Misc/target-invalid-cpu-note/riscv.c
+++ b/clang/test/Misc/target-invalid-cpu-note/riscv.c
@@ -29,6 +29,7 @@
 // RISCV64-SAME: {{^}}, rocket-rv64
 // RISCV64-SAME: {{^}}, sifive-p450
 // RISCV64-SAME: {{^}}, sifive-p470
+// RISCV64-SAME: {{^}}, sifive-p550
 // RISCV64-SAME: {{^}}, sifive-p670
 // RISCV64-SAME: {{^}}, sifive-s21
 // RISCV64-SAME: {{^}}, sifive-s51
@@ -77,6 +78,7 @@
 // TUNE-RISCV64-SAME: {{^}}, rocket-rv64
 // TUNE-RISCV64-SAME: {{^}}, sifive-p450
 // TUNE-RISCV64-SAME: {{^}}, sifive-p470
+// TUNE-RISCV64-SAME: {{^}}, sifive-p550
 // TUNE-RISCV64-SAME: {{^}}, sifive-p670
 // TUNE-RISCV64-SAME: {{^}}, sifive-s21
 // TUNE-RISCV64-SAME: {{^}}, sifive-s51
diff --git a/clang/test/OpenMP/parallel_masked_taskloop_codegen.c b/clang/test/OpenMP/parallel_masked_taskloop_codegen.c
new file mode 100644
index 0000000000000..ed89ef92bb768
--- /dev/null
+++ b/clang/test/OpenMP/parallel_masked_taskloop_codegen.c
@@ -0,0 +1,62 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs --prefix-filecheck-ir-name _ --version 5
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -fopenmp-version=52 -x c -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+#define N 100
+void parallel_masked_taskloop(){
+	#pragma omp parallel masked taskloop
+	for( int i = 0; i < N; i++)
+	;
+
+}
+
+int main()
+{
+ parallel_masked_taskloop();
+}
+// CHECK-LABEL: define dso_local void @parallel_masked_taskloop(
+// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB1:[0-9]+]], i32 0, ptr @parallel_masked_taskloop.omp_outlined)
+// CHECK-NEXT:    ret void
+//
+//
+// CHECK-LABEL: define internal void @parallel_masked_taskloop.omp_outlined(
+// CHECK-SAME: ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], ptr noalias noundef [[DOTBOUND_TID_:%.*]]) #[[ATTR1:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    [[AGG_CAPTURED:%.*]] = alloca [[STRUCT_ANON:%.*]], align 1
+// CHECK-NEXT:    [[TMP:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store ptr [[DOTGLOBAL_TID_]], ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK-NEXT:    store ptr [[DOTBOUND_TID_]], ptr [[DOTBOUND_TID__ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[TMP0]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @__kmpc_masked(ptr @[[GLOB1]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
+// CHECK-NEXT:    br i1 [[TMP3]], label %[[OMP_IF_THEN:.*]], label %[[OMP_IF_END:.*]]
+// CHECK:       [[OMP_IF_THEN]]:
+// CHECK-NEXT:    call void @__kmpc_taskgroup(ptr @[[GLOB1]], i32 [[TMP1]])
+// CHECK-NEXT:    [[TMP4:%.*]] = call ptr @__kmpc_omp_task_alloc(ptr @[[GLOB1]], i32 [[TMP1]], i32 1, i64 80, i64 0, ptr @.omp_task_entry.)
+// CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds nuw [[STRUCT_KMP_TASK_T_WITH_PRIVATES:%.*]], ptr [[TMP4]], i32 0, i32 0
+// CHECK-NEXT:    [[TMP6:%.*]] = getelementptr inbounds nuw [[STRUCT_KMP_TASK_T:%.*]], ptr [[TMP5]], i32 0, i32 5
+// CHECK-NEXT:    store i64 0, ptr [[TMP6]], align 8
+// CHECK-NEXT:    [[TMP7:%.*]] = getelementptr inbounds nuw [[STRUCT_KMP_TASK_T]], ptr [[TMP5]], i32 0, i32 6
+// CHECK-NEXT:    store i64 99, ptr [[TMP7]], align 8
+// CHECK-NEXT:    [[TMP8:%.*]] = getelementptr inbounds nuw [[STRUCT_KMP_TASK_T]], ptr [[TMP5]], i32 0, i32 7
+// CHECK-NEXT:    store i64 1, ptr [[TMP8]], align 8
+// CHECK-NEXT:    [[TMP9:%.*]] = getelementptr inbounds nuw [[STRUCT_KMP_TASK_T]], ptr [[TMP5]], i32 0, i32 9
+// CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[TMP9]], i8 0, i64 8, i1 false)
+// CHECK-NEXT:    [[TMP10:%.*]] = load i64, ptr [[TMP8]], align 8
+// CHECK-NEXT:    call void @__kmpc_taskloop(ptr @[[GLOB1]], i32 [[TMP1]], ptr [[TMP4]], i32 1, ptr [[TMP6]], ptr [[TMP7]], i64 [[TMP10]], i32 1, i32 0, i64 0, ptr null)
+// CHECK-NEXT:    call void @__kmpc_end_taskgroup(ptr @[[GLOB1]], i32 [[TMP1]])
+// CHECK-NEXT:    call void @__kmpc_end_masked(ptr @[[GLOB1]], i32 [[TMP1]])
+// CHECK-NEXT:    br label %[[OMP_IF_END]]
+// CHECK:       [[OMP_IF_END]]:
+// CHECK-NEXT:    ret void
+//
+// CHECK-LABEL: define dso_local i32 @main(
+// CHECK-SAME: ) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    call void @parallel_masked_taskloop()
+// CHECK-NEXT:    ret i32 0
+
diff --git a/clang/test/Parser/namespace-attributes.cpp b/clang/test/Parser/namespace-attributes.cpp
index 9f925b742dfeb..11bf8711cfad5 100644
--- a/clang/test/Parser/namespace-attributes.cpp
+++ b/clang/test/Parser/namespace-attributes.cpp
@@ -4,38 +4,34 @@ namespace __attribute__(()) A
 {
 }
 
-namespace A __attribute__(())
+namespace A __attribute__(()) [[]] // expected-error {{an attribute list cannot appear here}}
 {
 }
 
-namespace __attribute__(()) [[]] A
-{
-}
-
-namespace [[]] __attribute__(()) A
+namespace A [[]] __attribute__(()) // expected-error {{an attribute list cannot appear here}}
 {
 }
 
-namespace A __attribute__(()) [[]]
+namespace [[]] A __attribute__(())
 {
 }
 
-namespace A [[]] __attribute__(())
+namespace [[]] __attribute__(()) A
 {
 }
 
-namespace [[]] A __attribute__(())
+namespace __attribute__(()) [[]] A
 {
 }
 
-namespace __attribute__(()) A [[]]
+namespace __attribute__(()) A [[]] // expected-error {{an attribute list cannot appear here}}
 {
 }
 
-namespace A::B __attribute__(()) // expected-error{{attributes cannot be specified on a nested namespace definition}}
+namespace A::B __attribute__(()) // expected-error {{attributes cannot be specified on a nested namespace definition}}
 {
 }
 
-namespace __attribute__(()) A::B // expected-error{{attributes cannot be specified on a nested namespace definition}}
+namespace __attribute__(()) A::B // expected-error {{attributes cannot be specified on a nested namespace definition}}
 {
 }
diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c
index 9b88c147d0faa..73a09697710f9 100644
--- a/clang/test/ParserOpenACC/parse-clauses.c
+++ b/clang/test/ParserOpenACC/parse-clauses.c
@@ -347,14 +347,12 @@ void SelfUpdate() {
 #pragma acc update self
   for(int i = 0; i < 5;++i) {}
 
-  // expected-error@+4{{use of undeclared identifier 'zero'}}
-  // expected-error@+3{{expected ','}}
-  // expected-error@+2{{expected expression}}
-  // expected-warning@+1{{OpenACC clause 'self' not yet implemented, clause ignored}}
+  // expected-error@+3{{use of undeclared identifier 'zero'}}
+  // expected-error@+2{{expected ','}}
+  // expected-error@+1{{expected expression}}
 #pragma acc update self(zero : s.array[s.value : 5], s.value), if_present
   for(int i = 0; i < 5;++i) {}
 
-  // expected-warning@+1{{OpenACC clause 'self' not yet implemented, clause ignored}}
 #pragma acc update self(s.array[s.value : 5], s.value), if_present
   for(int i = 0; i < 5;++i) {}
 }
diff --git a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
index 12b933e63edd7..2877d8d6cd5f9 100644
--- a/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-capture-by.cpp
@@ -406,7 +406,7 @@ void use() {
   strings.insert(strings.begin(), std::string());
 
   std::vector pointers;
-  pointers.push_back(getLifetimeBoundPointer(std::string())); // expected-warning {{object whose reference is captured by 'pointers' will be destroyed at the end of the full-expression}}
+  pointers.push_back(getLifetimeBoundPointer(std::string()));
   pointers.push_back(&local);
 }
 
@@ -451,3 +451,24 @@ void test() {
   T2(1, a); // expected-warning {{object whose reference is captured by}}
 }
 } // namespace on_constructor
+
+namespace GH121391 {
+
+struct Foo {};
+
+template 
+struct Container {
+  const T& tt() [[clang::lifetimebound]];
+};
+template
+struct StatusOr {
+   T* get() [[clang::lifetimebound]];
+};
+StatusOr> getContainer();
+
+void test() {
+  std::vector vv;
+  vv.push_back(getContainer().get()->tt()); // OK
+}
+
+} // namespace GH121391
diff --git a/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp b/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp
index ccc109cbca0f1..71e55c8290ee4 100644
--- a/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp
+++ b/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp
@@ -31,7 +31,7 @@ void function() {
 // expected-note@#3 {{checking the satisfaction of concept 'convertible_to'}}
 // expected-note@#2 {{substituting template arguments into constraint expression here}}
 // expected-note@#5 {{checking constraint satisfaction for template 'compare'}}
-// expected-note@#5 {{while substituting deduced template arguments into function template 'compare' [with IteratorL = Object *, IteratorR = Object *]}}
+// expected-note@#5 {{in instantiation of function template specialization 'compare' requested here}}
 
 // expected-note@#4 {{candidate template ignored: constraints not satisfied [with IteratorL = Object *, IteratorR = Object *]}}
 // We don't know exactly the substituted type for `lhs == rhs`, thus a placeholder 'expr-type' is emitted.
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 0c349333d89d4..c990dc78deb9b 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -380,20 +380,36 @@ static_assert(string == string, "");
 static_assert(string == also_string, "");
 
 // These strings may overlap, and so the result of the comparison is unknown.
-constexpr bool may_overlap_1 = +"foo" == +"foo"; // expected-error {{}} expected-note {{addresses of literals}}
-constexpr bool may_overlap_2 = +"foo" == +"foo\0bar"; // expected-error {{}} expected-note {{addresses of literals}}
-constexpr bool may_overlap_3 = +"foo" == "bar\0foo" + 4; // expected-error {{}} expected-note {{addresses of literals}}
-constexpr bool may_overlap_4 = "xfoo" + 1 == "xfoo" + 1; // expected-error {{}} expected-note {{addresses of literals}}
+constexpr bool may_overlap_1 = +"foo" == +"foo"; // expected-error {{}} expected-note {{addresses of potentially overlapping literals}}
+constexpr bool may_overlap_2 = +"foo" == +"foo\0bar"; // expected-error {{}} expected-note {{addresses of potentially overlapping literals}}
+constexpr bool may_overlap_3 = +"foo" == "bar\0foo" + 4; // expected-error {{}} expected-note {{addresses of potentially overlapping literals}}
+constexpr bool may_overlap_4 = "xfoo" + 1 == "xfoo" + 1; // expected-error {{}} expected-note {{addresses of potentially overlapping literals}}
 
 // These may overlap even though they have different encodings.
 // One of these two comparisons is non-constant, but due to endianness we don't
 // know which one.
 constexpr bool may_overlap_different_encoding[] =
   {fold((const char*)u"A" != (const char*)"xA\0\0\0x" + 1), fold((const char*)u"A" != (const char*)"x\0A\0\0x" + 1)};
-  // expected-error@-2 {{}} expected-note@-1 {{addresses of literals}}
+  // expected-error@-2 {{}} expected-note@-1 {{addresses of potentially overlapping literals}}
 
 }
 
+constexpr const char *getStr() {
+  return "abc"; // expected-note {{repeated evaluation of the same literal expression can produce different objects}}
+}
+constexpr int strMinus() {
+  (void)(getStr() - getStr()); // expected-note {{arithmetic on addresses of potentially overlapping literals has unspecified value}} \
+                               // cxx11-warning {{C++14 extension}}
+  return 0;
+}
+static_assert(strMinus() == 0, ""); // expected-error {{not an integral constant expression}} \
+                                    // expected-note {{in call to}}
+
+constexpr int a = 0;
+constexpr int b = 1;
+constexpr int n = &b - &a; // expected-error {{must be initialized by a constant expression}} \
+                           // expected-note {{arithmetic involving unrelated objects '&b' and '&a' has unspecified value}}
+
 namespace MaterializeTemporary {
 
 constexpr int f(const int &r) { return r; }
diff --git a/clang/test/SemaCXX/constant-expression-cxx14.cpp b/clang/test/SemaCXX/constant-expression-cxx14.cpp
index 936d3600953b9..579883ae52cce 100644
--- a/clang/test/SemaCXX/constant-expression-cxx14.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp
@@ -1315,7 +1315,7 @@ constexpr bool different_in_loop(bool b = false) {
   const char *p[2] = {};
   for (const char *&r : p)
     r = "hello";
-  return p[0] == p[1]; // expected-note {{addresses of literals}}
+  return p[0] == p[1]; // expected-note {{addresses of potentially overlapping literals}}
 }
 constexpr bool check = different_in_loop();
   // expected-error@-1 {{}} expected-note@-1 {{in call}}
diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
index 23c898e6379b0..2d43e46b9e3d7 100644
--- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
+++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
@@ -196,7 +196,7 @@ struct Foo {
 
 template 
 using Bar = Foo; // expected-note {{constraints not satisfied for class template 'Foo'}}
-// expected-note@-1 {{candidate template ignored: could not match}} expected-note@-1 {{candidate template ignored: constraints not satisfied}}
+// expected-note@-1 {{candidate template ignored: could not match}}
 // expected-note@-2 {{implicit deduction guide declared as 'template  requires __is_deducible(test14::Bar, Foo) Bar(Foo) -> Foo'}}
 // expected-note@-3 {{implicit deduction guide declared as 'template  requires __is_deducible(test14::Bar, Foo) Bar(const double (&)[K]) -> Foo'}}
 double abc[3];
diff --git a/clang/test/SemaCXX/cxx23-assume.cpp b/clang/test/SemaCXX/cxx23-assume.cpp
index 726cb3bff652e..7f80cdfe7d452 100644
--- a/clang/test/SemaCXX/cxx23-assume.cpp
+++ b/clang/test/SemaCXX/cxx23-assume.cpp
@@ -129,12 +129,12 @@ constexpr int f5() requires (!C) { return 2; } // expected-note 4 {{while che
 
 static_assert(f5() == 1);
 static_assert(f5() == 1); // expected-note 3 {{while checking constraint satisfaction}}
-                             // expected-note@-1 3 {{while substituting deduced template arguments}}
+                             // expected-note@-1 3 {{in instantiation of}}
                              // expected-error@-2 {{no matching function for call}}
 
 static_assert(f5() == 2);
-static_assert(f5() == 1); // expected-note {{while checking constraint satisfaction}} expected-note {{while substituting deduced template arguments}}
-static_assert(f5() == 2); // expected-note {{while checking constraint satisfaction}} expected-note {{while substituting deduced template arguments}}
+static_assert(f5() == 1); // expected-note {{while checking constraint satisfaction}} expected-note {{in instantiation of}}
+static_assert(f5() == 2); // expected-note {{while checking constraint satisfaction}} expected-note {{in instantiation of}}
 
 // Do not validate assumptions whose evaluation would have side-effects.
 constexpr int foo() {
diff --git a/clang/test/SemaCXX/cxx2a-destroying-delete.cpp b/clang/test/SemaCXX/cxx2a-destroying-delete.cpp
index 25b985ef11d15..bf0a64a77385c 100644
--- a/clang/test/SemaCXX/cxx2a-destroying-delete.cpp
+++ b/clang/test/SemaCXX/cxx2a-destroying-delete.cpp
@@ -146,12 +146,12 @@ namespace dtor_access {
   struct S {
     void operator delete(S *p, std::destroying_delete_t);
   private:
-    ~S(); // expected-note {{here}}
+    ~S();
   };
 
-  // FIXME: PR47474: GCC accepts this, and it seems somewhat reasonable to
-  // allow, even though [expr.delete]p12 says this is ill-formed.
-  void f() { delete new S; } // expected-error {{calling a private destructor}}
+  // C++20 [expr.delete]p12 says this is ill-formed, but GCC accepts and we
+  // filed CWG2889 to resolve in the same way.
+  void f() { delete new S; }
 
   struct T {
     void operator delete(T *, std::destroying_delete_t);
@@ -165,7 +165,7 @@ namespace dtor_access {
     ~U() override;
   };
 
-  void g() { delete (T *)new U; } // expected-error {{calling a protected destructor}}
+  void g() { delete (T *)new U; } // expected-error {{calling a protected destructor of class 'T'}}
 }
 
 namespace delete_from_new {
diff --git a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp
index 4220486d3aed3..48061439941f2 100644
--- a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp
+++ b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp
@@ -233,7 +233,7 @@ void g() {
     A *ap;
     f(ap, ap); // expected-error{{no matching function for call to 'f'}} \
                // expected-note {{while checking constraint satisfaction}} \
-               // expected-note {{while substituting deduced template arguments}}
+               // expected-note {{in instantiation of function template specialization}}
 }
 
 }
diff --git a/clang/test/SemaCXX/lambda-unevaluated.cpp b/clang/test/SemaCXX/lambda-unevaluated.cpp
index d3f937281f201..a9bcab58464e2 100644
--- a/clang/test/SemaCXX/lambda-unevaluated.cpp
+++ b/clang/test/SemaCXX/lambda-unevaluated.cpp
@@ -174,7 +174,7 @@ int* func(T) requires requires { []() { T::foo(); }; }; // expected-error{{type
 double* func(...);
 
 static_assert(__is_same(decltype(func(0)), double*)); // expected-note {{while checking constraint satisfaction for template 'func' required here}}
-                                                      // expected-note@-1 {{while substituting deduced template arguments into function template 'func' [with T = int]}}
+                                                      // expected-note@-1 {{in instantiation of function template specialization 'lambda_in_constraints::func'}}
 static_assert(__is_same(decltype(func(WithFoo())), int*));
 
 template 
@@ -252,7 +252,7 @@ S s("a"); // #use
 // expected-note@#S-requires {{substituting template arguments into constraint expression here}}
 // expected-note@#S-requires {{in instantiation of requirement here}}
 // expected-note@#use {{checking constraint satisfaction for template 'S' required here}}
-// expected-note@#use {{while substituting deduced template arguments into function template 'S' [with value:auto = const char *]}}
+// expected-note@#use {{requested here}}
 // expected-note-re@#S 2{{candidate constructor {{.*}} not viable}}
 // expected-note@#S-ctor {{constraints not satisfied}}
 // expected-note-re@#S-requires {{because {{.*}} would be invalid}}
diff --git a/clang/test/SemaCXX/noexcept-destroying-delete.cpp b/clang/test/SemaCXX/noexcept-destroying-delete.cpp
index 92ccbc1fb3f96..6a745314b6204 100644
--- a/clang/test/SemaCXX/noexcept-destroying-delete.cpp
+++ b/clang/test/SemaCXX/noexcept-destroying-delete.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -fcxx-exceptions -Wno-unevaluated-expression -std=c++20 %s
-// expected-no-diagnostics
 
 namespace std {
   struct destroying_delete_t {
@@ -31,3 +30,19 @@ ThrowingDestroyingDelete *pn = nullptr;
 // noexcept should return false here because the destroying delete itself is a
 // potentially throwing function.
 static_assert(!noexcept(delete(pn)));
+
+
+struct A {
+  virtual ~A(); // implicitly noexcept
+};
+struct B : A {
+  void operator delete(B *p, std::destroying_delete_t) { throw "oh no"; } // expected-warning {{'operator delete' has a non-throwing exception specification but can still throw}} \
+                                                                             expected-note {{deallocator has a implicit non-throwing exception specification}}
+};
+A *p = new B;
+
+// Because the destructor for A is virtual, it is the only thing we consider
+// when determining whether the delete expression can throw or not, despite the
+// fact that the selected operator delete is a destroying delete. For virtual
+// destructors, it's the dynamic type that matters.
+static_assert(noexcept(delete p));
diff --git a/clang/test/SemaOpenACC/combined-construct-self-ast.cpp b/clang/test/SemaOpenACC/combined-construct-self-ast.cpp
index 3a6ba3ca6aea2..e504ea7f5a075 100644
--- a/clang/test/SemaOpenACC/combined-construct-self-ast.cpp
+++ b/clang/test/SemaOpenACC/combined-construct-self-ast.cpp
@@ -20,6 +20,7 @@ void TemplFunc() {
   for (unsigned i = 0; i < 5; ++i);
   // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop
   // CHECK-NEXT: self clause
+  // CHECK-NEXT: <<>
   // CHECK-NEXT: ForStmt
   // CHECK: NullStmt
 
@@ -65,6 +66,7 @@ void TemplFunc() {
   //
   // CHECK-NEXT: OpenACCCombinedConstruct{{.*}}serial loop
   // CHECK-NEXT: self clause
+  // CHECK-NEXT: <<>
   // CHECK-NEXT: ForStmt
   // CHECK: NullStmt
 
diff --git a/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp b/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp
index 69f65f4083ae7..58c12b828439d 100644
--- a/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp
+++ b/clang/test/SemaOpenACC/compute-construct-clause-ast.cpp
@@ -197,6 +197,7 @@ void TemplFunc() {
   while(true);
   // CHECK-NEXT: OpenACCComputeConstruct{{.*}}serial
   // CHECK-NEXT: self clause
+  // CHECK-NEXT: <<>
   // CHECK-NEXT: WhileStmt
   // CHECK-NEXT: CXXBoolLiteralExpr
   // CHECK-NEXT: NullStmt
@@ -393,6 +394,7 @@ void TemplFunc() {
 
   // CHECK-NEXT: OpenACCComputeConstruct{{.*}}serial
   // CHECK-NEXT: self clause
+  // CHECK-NEXT: <<>
   // CHECK-NEXT: WhileStmt
   // CHECK-NEXT: CXXBoolLiteralExpr
   // CHECK-NEXT: NullStmt
diff --git a/clang/test/SemaOpenACC/update-construct-ast.cpp b/clang/test/SemaOpenACC/update-construct-ast.cpp
index 114de654670d3..9048e8823f5f5 100644
--- a/clang/test/SemaOpenACC/update-construct-ast.cpp
+++ b/clang/test/SemaOpenACC/update-construct-ast.cpp
@@ -10,6 +10,10 @@
 int some_int();
 long some_long();
 
+int Global;
+short GlobalArray[5];
+
+
 void NormalFunc() {
   // CHECK-LABEL: NormalFunc
   // CHECK-NEXT: CompoundStmt
@@ -70,6 +74,21 @@ void NormalFunc() {
   // CHECK-NEXT: CallExpr{{.*}}'long'
   // CHECK-NEXT: ImplicitCastExpr
   // CHECK-NEXT: DeclRefExpr{{.*}}'some_long' 'long ()'
+
+#pragma acc update self(Global, GlobalArray, GlobalArray[0], GlobalArray[0:1])
+  // CHECK-NEXT: OpenACCUpdateConstruct{{.*}}update
+  // CHECK-NEXT: self clause
+  // CHECK-NEXT: DeclRefExpr{{.*}}'Global' 'int'
+  // CHECK-NEXT: DeclRefExpr{{.*}}'GlobalArray' 'short[5]'
+  // CHECK-NEXT: ArraySubscriptExpr{{.*}} 'short' lvalue
+  // CHECK-NEXT: ImplicitCastExpr
+  // CHECK-NEXT: DeclRefExpr{{.*}}'GlobalArray' 'short[5]'
+  // CHECK-NEXT: IntegerLiteral{{.*}} 0
+  // CHECK-NEXT: ArraySectionExpr
+  // CHECK-NEXT: ImplicitCastExpr
+  // CHECK-NEXT: DeclRefExpr{{.*}}'GlobalArray' 'short[5]'
+  // CHECK-NEXT: IntegerLiteral{{.*}} 0
+  // CHECK-NEXT: IntegerLiteral{{.*}} 1
 }
 
 template
@@ -124,6 +143,26 @@ void TemplFunc(T t) {
   // CHECK-NEXT: DependentScopeDeclRefExpr{{.*}}''
   // CHECK-NEXT: NestedNameSpecifier TypeSpec 'T'
 
+  decltype(T::value) Local = 0, LocalArray[5] = {};
+  // CHECK-NEXT: DeclStmt 
+  // CHECK-NEXT: VarDecl
+  // CHECK-NEXT: IntegerLiteral
+  // CHECK-NEXT: VarDecl
+  // CHECK-NEXT: InitListExpr
+
+#pragma acc update self(Local, LocalArray, LocalArray[0], LocalArray[0:1])
+  // CHECK-NEXT: OpenACCUpdateConstruct{{.*}}update
+  // CHECK-NEXT: self clause
+  // CHECK-NEXT: DeclRefExpr{{.*}} 'Local' 'decltype(T::value)'
+  // CHECK-NEXT: DeclRefExpr{{.*}} 'LocalArray' 'decltype(T::value)[5]'
+  // CHECK-NEXT: ArraySubscriptExpr
+  // CHECK-NEXT: DeclRefExpr{{.*}} 'LocalArray' 'decltype(T::value)[5]'
+  // CHECK-NEXT: IntegerLiteral{{.*}}0
+  // CHECK-NEXT: ArraySectionExpr
+  // CHECK-NEXT: DeclRefExpr{{.*}} 'LocalArray' 'decltype(T::value)[5]'
+  // CHECK-NEXT: IntegerLiteral{{.*}}0
+  // CHECK-NEXT: IntegerLiteral{{.*}}1
+
   // Instantiation:
   // CHECK-NEXT: FunctionDecl{{.*}} TemplFunc 'void (SomeStruct)' implicit_instantiation
   // CHECK-NEXT: TemplateArgument type 'SomeStruct'
@@ -194,6 +233,28 @@ void TemplFunc(T t) {
   // CHECK-NEXT: ImplicitCastExpr{{.*}}'unsigned int'
   // CHECK-NEXT: DeclRefExpr{{.*}}'value' 'const unsigned int'
   // CHECK-NEXT: NestedNameSpecifier TypeSpec 'SomeStruct'
+
+  // CHECK-NEXT: DeclStmt 
+  // CHECK-NEXT: VarDecl
+  // CHECK-NEXT: ImplicitCastExpr
+  // CHECK-NEXT: IntegerLiteral
+  // CHECK-NEXT: VarDecl
+  // CHECK-NEXT: InitListExpr
+  // CHECK-NEXT: array_filler
+
+  // CHECK-NEXT: OpenACCUpdateConstruct{{.*}}update
+  // CHECK-NEXT: self clause
+  // CHECK-NEXT: DeclRefExpr{{.*}} 'Local' 'decltype(SomeStruct::value)':'const unsigned int'
+  // CHECK-NEXT: DeclRefExpr{{.*}} 'LocalArray' 'decltype(SomeStruct::value)[5]'
+  // CHECK-NEXT: ArraySubscriptExpr
+  // CHECK-NEXT: ImplicitCastExpr
+  // CHECK-NEXT: DeclRefExpr{{.*}} 'LocalArray' 'decltype(SomeStruct::value)[5]'
+  // CHECK-NEXT: IntegerLiteral{{.*}}0
+  // CHECK-NEXT: ArraySectionExpr
+  // CHECK-NEXT: ImplicitCastExpr
+  // CHECK-NEXT: DeclRefExpr{{.*}} 'LocalArray' 'decltype(SomeStruct::value)[5]'
+  // CHECK-NEXT: IntegerLiteral{{.*}}0
+  // CHECK-NEXT: IntegerLiteral{{.*}}1
 }
 
 struct SomeStruct{
diff --git a/clang/test/SemaOpenACC/update-construct.cpp b/clang/test/SemaOpenACC/update-construct.cpp
index 04c0aaaab99ae..2abd7a30eda88 100644
--- a/clang/test/SemaOpenACC/update-construct.cpp
+++ b/clang/test/SemaOpenACC/update-construct.cpp
@@ -4,28 +4,20 @@ struct NotConvertible{} NC;
 int getI();
 void uses() {
   int Var;
-  // expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
 #pragma acc update async self(Var)
-  // expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
 #pragma acc update wait self(Var)
-  // expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
 #pragma acc update self(Var) device_type(I)
-  // expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
 #pragma acc update if(true) self(Var)
-  // expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
 #pragma acc update if_present self(Var)
-  // expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
 #pragma acc update self(Var)
   // expected-warning@+1{{OpenACC clause 'host' not yet implemented}}
 #pragma acc update host(Var)
   // expected-warning@+1{{OpenACC clause 'device' not yet implemented}}
 #pragma acc update device(Var)
 
-  // expected-warning@+3{{OpenACC clause 'self' not yet implemented}}
   // expected-error@+2{{OpenACC clause 'if' may not follow a 'device_type' clause in a 'update' construct}}
   // expected-note@+1{{previous clause is here}}
 #pragma acc update self(Var) device_type(I) if(true)
-  // expected-warning@+3{{OpenACC clause 'self' not yet implemented}}
   // expected-error@+2{{OpenACC clause 'if_present' may not follow a 'device_type' clause in a 'update' construct}}
   // expected-note@+1{{previous clause is here}}
 #pragma acc update self(Var) device_type(I) if_present
@@ -39,12 +31,9 @@ void uses() {
   // expected-note@+1{{previous clause is here}}
 #pragma acc update device_type(I) device(Var)
   // These 2 are OK.
-  // expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
 #pragma acc update self(Var) device_type(I) async
-  // expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
 #pragma acc update self(Var) device_type(I) wait
   // Unless otherwise specified, we assume 'device_type' can happen after itself.
-  // expected-warning@+1{{OpenACC clause 'self' not yet implemented}}
 #pragma acc update self(Var) device_type(I) device_type(I)
 
   // TODO: OpenACC: These should diagnose because there isn't at least 1 of
@@ -128,3 +117,51 @@ void uses() {
   // expected-error@+1{{OpenACC clause 'wait' requires expression of integer type ('struct NotConvertible' invalid)}}
 #pragma acc update wait(devnum:arr : queues: arr, NC, 5)
 }
+
+struct SomeS {
+  int Array[5];
+  int MemberOfComp;
+};
+
+template
+void varlist_restrictions_templ() {
+  I iArray[5];
+  T Single;
+  T Array[5];
+
+  // Members of a subarray of struct or class type may not appear, but others
+  // are permitted to.
+#pragma acc update self(iArray[0:1])
+
+#pragma acc update self(Array[0:1])
+
+  // expected-error@+1{{OpenACC sub-array is not allowed here}}
+#pragma acc update self(Array[0:1].MemberOfComp)
+}
+
+void varlist_restrictions() {
+  varlist_restrictions_templ();// expected-note{{in instantiation of}}
+  int iArray[5];
+  SomeS Single;
+  SomeS Array[5];
+
+  int LocalInt;
+  int *LocalPtr;
+
+#pragma acc update self(LocalInt, LocalPtr, Single)
+
+#pragma acc update self(Single.MemberOfComp)
+
+#pragma acc update self(Single.Array[0:1])
+
+
+  // Members of a subarray of struct or class type may not appear, but others
+  // are permitted to.
+#pragma acc update self(iArray[0:1])
+
+#pragma acc update self(Array[0:1])
+
+  // expected-error@+1{{OpenACC sub-array is not allowed here}}
+#pragma acc update self(Array[0:1].MemberOfComp)
+}
+
diff --git a/clang/test/SemaTemplate/concepts-recursive-inst.cpp b/clang/test/SemaTemplate/concepts-recursive-inst.cpp
index 30a410cef91ee..9330df8cdd039 100644
--- a/clang/test/SemaTemplate/concepts-recursive-inst.cpp
+++ b/clang/test/SemaTemplate/concepts-recursive-inst.cpp
@@ -76,7 +76,7 @@ auto it = begin(rng); // #BEGIN_CALL
 // expected-note@#INF_BEGIN {{while checking the satisfaction of concept 'Inf' requested here}}
 // expected-note@#INF_BEGIN {{while substituting template arguments into constraint expression here}}
 // expected-note@#BEGIN_CALL {{while checking constraint satisfaction for template 'begin' required here}}
-// expected-note@#BEGIN_CALL {{while substituting deduced template arguments into function template}}
+// expected-note@#BEGIN_CALL {{in instantiation of function template specialization}}
 
 // Fallout of the failure is failed lookup, which is necessary to stop odd
 // cascading errors.
@@ -103,7 +103,7 @@ namespace GH50891 {
   // expected-note@#OP_TO {{while checking the satisfaction of concept 'Numeric' requested here}}
   // expected-note@#OP_TO {{while substituting template arguments into constraint expression here}}
   // expected-note@#FOO_CALL {{while checking constraint satisfaction for template}}
-  // expected-note@#FOO_CALL {{while substituting deduced template arguments into function template}}
+  // expected-note@#FOO_CALL {{in instantiation of function template specialization}}
   // expected-note@#FOO_CALL {{in instantiation of requirement here}}
   // expected-note@#NUMERIC {{while substituting template arguments into constraint expression here}}
 
diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index 312469313fc53..f335ca3bd22bc 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1165,3 +1165,15 @@ concept C = invalid; // expected-error {{use of undeclared identifier 'invalid'}
 bool val2 = C;
 
 } // namespace GH109780
+
+namespace GH121980 {
+
+template 
+concept has_member_difference_type; // expected-error {{expected '='}}
+
+template  struct incrementable_traits; // expected-note {{declared here}}
+
+template 
+struct incrementable_traits; // expected-error {{not more specialized than the primary}}
+
+}
diff --git a/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp b/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp
index 5809ef684bbf3..f4403587a6259 100644
--- a/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp
+++ b/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp
@@ -34,7 +34,7 @@ namespace constant_evaluated {
      expected-note@-1{{candidate template ignored}}
   int a = (foo(), 0);
   // expected-note@-1 {{while checking}} expected-error@-1{{no matching function}} \
-     expected-note@-1 {{while substituting}}
+     expected-note@-1 {{in instantiation}}
   template void bar() requires requires { requires f; } { };
   // expected-note@-1{{in instantiation}} \
      expected-note@-1{{while substituting}} \
diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp
index 67d00bb49f77d..d03c783313dd7 100644
--- a/clang/test/SemaTemplate/deduction-guide.cpp
+++ b/clang/test/SemaTemplate/deduction-guide.cpp
@@ -234,6 +234,11 @@ F s(0);
 // CHECK: | `-CXXBoolLiteralExpr {{.*}} 'bool' false
 // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit  'auto (U) -> F<>'
 // CHECK: | `-ParmVarDecl {{.*}} 'U'
+// CHECK: `-CXXDeductionGuideDecl {{.*}} implicit  'auto (int) -> F<>'
+// CHECK:   |-TemplateArgument integral ''x''
+// CHECK:   |-TemplateArgument type 'int'
+// CHECK:   | `-BuiltinType {{.*}} 'int'
+// CHECK:   `-ParmVarDecl {{.*}} 'int'
 // CHECK: FunctionProtoType {{.*}} 'auto (U) -> F<>' dependent trailing_return cdecl
 // CHECK: |-InjectedClassNameType {{.*}} 'F<>' dependent
 // CHECK: | `-CXXRecord {{.*}} 'F'
diff --git a/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp b/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp
index 5c7a90273d0e0..af3e3358f6138 100644
--- a/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp
+++ b/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp
@@ -38,7 +38,7 @@ template
 concept True = true;
 
 template
-concept False = false; // #False
+concept False = false;
 
 template struct concepts {
     template struct B {
@@ -68,7 +68,7 @@ template struct nested_init_list {
         Y y;
     };
 
-    template  // #INIT_LIST_INNER_INVALID_HEADER
+    template
     struct concept_fail { // #INIT_LIST_INNER_INVALID
         X x;
         F f;
@@ -81,9 +81,7 @@ using NIL = nested_init_list::B;
 
 // expected-error@+1 {{no viable constructor or deduction guide for deduction of template arguments of 'nested_init_list::concept_fail'}}
 nested_init_list::concept_fail nil_invalid{1, ""};
-// expected-note@#INIT_LIST_INNER_INVALID {{candidate template ignored: constraints not satisfied [with F = const char *]}}
-// expected-note@#INIT_LIST_INNER_INVALID_HEADER {{because 'const char *' does not satisfy 'False'}}
-// expected-note@#False {{because 'false' evaluated to false}}
+// expected-note@#INIT_LIST_INNER_INVALID {{candidate template ignored: substitution failure [with F = const char *]: constraints not satisfied for class template 'concept_fail' [with F = const char *]}}
 // expected-note@#INIT_LIST_INNER_INVALID {{implicit deduction guide declared as 'template  concept_fail(int, F) -> concept_fail'}}
 // expected-note@#INIT_LIST_INNER_INVALID {{candidate function template not viable: requires 1 argument, but 2 were provided}}
 // expected-note@#INIT_LIST_INNER_INVALID {{implicit deduction guide declared as 'template  concept_fail(concept_fail) -> concept_fail'}}
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index bd36181fca3f3..709dc513be281 100644
--- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -913,7 +913,7 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
       return llvm::nulls();
 
     std::error_code EC;
-    FileOS.emplace(OutputFileName, EC);
+    FileOS.emplace(OutputFileName, EC, llvm::sys::fs::OF_Text);
     if (EC) {
       llvm::errs() << "Failed to open output file '" << OutputFileName
                    << "': " << llvm::errorCodeToError(EC) << '\n';
@@ -1003,9 +1003,9 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
           auto OSIter = OSs.find(MakeformatOutputPath);
           if (OSIter == OSs.end()) {
             std::error_code EC;
-            OSIter =
-                OSs.try_emplace(MakeformatOutputPath, MakeformatOutputPath, EC)
-                    .first;
+            OSIter = OSs.try_emplace(MakeformatOutputPath, MakeformatOutputPath,
+                                     EC, llvm::sys::fs::OF_Text)
+                         .first;
             if (EC)
               llvm::errs() << "Failed to open P1689 make format output file \""
                            << MakeformatOutputPath << "\" for " << EC.message()
diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp
index 12038de476ace..ffd157e60997c 100644
--- a/clang/tools/driver/driver.cpp
+++ b/clang/tools/driver/driver.cpp
@@ -355,10 +355,12 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
   if (!SetBackdoorDriverOutputsFromEnvVars(TheDriver))
     return 1;
 
+  auto ExecuteCC1WithContext =
+      [&ToolContext](SmallVectorImpl &ArgV) {
+        return ExecuteCC1Tool(ArgV, ToolContext);
+      };
   if (!UseNewCC1Process) {
-    TheDriver.CC1Main = [ToolContext](SmallVectorImpl &ArgV) {
-      return ExecuteCC1Tool(ArgV, ToolContext);
-    };
+    TheDriver.CC1Main = ExecuteCC1WithContext;
     // Ensure the CC1Command actually catches cc1 crashes
     llvm::CrashRecoveryContext::Enable();
   }
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 4114d9a37f1ec..5e51fc4e2f66c 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2839,8 +2839,13 @@ void OpenACCClauseEnqueue::VisitIfClause(const OpenACCIfClause &C) {
   Visitor.AddStmt(C.getConditionExpr());
 }
 void OpenACCClauseEnqueue::VisitSelfClause(const OpenACCSelfClause &C) {
-  if (C.hasConditionExpr())
-    Visitor.AddStmt(C.getConditionExpr());
+  if (C.isConditionExprClause()) {
+    if (C.hasConditionExpr())
+      Visitor.AddStmt(C.getConditionExpr());
+  } else {
+    for (Expr *Var : C.getVarList())
+      Visitor.AddStmt(Var);
+  }
 }
 void OpenACCClauseEnqueue::VisitNumWorkersClause(
     const OpenACCNumWorkersClause &C) {
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index f3d953454173c..92ec79d126575 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2253,6 +2253,21 @@ TEST_P(ASTMatchersTest, HasDependentName_DependentScopeDeclRefExpr) {
                       dependentScopeDeclRefExpr(hasDependentName("foo"))));
 }
 
+TEST_P(ASTMatchersTest, HasDependentName_DependentNameType) {
+  if (!GetParam().isCXX()) {
+    // FIXME: Fix this test to work with delayed template parsing.
+    return;
+  }
+
+  EXPECT_TRUE(matches(
+      R"(
+        template  struct declToImport {
+          typedef typename T::type dependent_name;
+        };
+      )",
+      dependentNameType(hasDependentName("type"))));
+}
+
 TEST(ASTMatchersTest, NamesMember_CXXDependentScopeMemberExpr) {
 
   // Member functions:
diff --git a/clang/unittests/Analysis/FlowSensitive/CachedConstAccessorsLatticeTest.cpp b/clang/unittests/Analysis/FlowSensitive/CachedConstAccessorsLatticeTest.cpp
index 6488833bd14cf..d27f6a6d27e71 100644
--- a/clang/unittests/Analysis/FlowSensitive/CachedConstAccessorsLatticeTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/CachedConstAccessorsLatticeTest.cpp
@@ -148,6 +148,35 @@ TEST_F(CachedConstAccessorsLatticeTest, SameLocBeforeClearOrDiffAfterClear) {
   EXPECT_NE(Loc3, Loc2);
 }
 
+TEST_F(CachedConstAccessorsLatticeTest,
+       SameLocBeforeClearOrDiffAfterClearWithCallee) {
+  CommonTestInputs Inputs;
+  auto *CE = Inputs.CallRef;
+  RecordStorageLocation Loc(Inputs.SType, RecordStorageLocation::FieldToLoc(),
+                            {});
+
+  LatticeT Lattice;
+  auto NopInit = [](StorageLocation &) {};
+  const FunctionDecl *Callee = CE->getDirectCallee();
+  ASSERT_NE(Callee, nullptr);
+  StorageLocation &Loc1 = Lattice.getOrCreateConstMethodReturnStorageLocation(
+      Loc, Callee, Env, NopInit);
+  auto NotCalled = [](StorageLocation &) {
+    ASSERT_TRUE(false) << "Not reached";
+  };
+  StorageLocation &Loc2 = Lattice.getOrCreateConstMethodReturnStorageLocation(
+      Loc, Callee, Env, NotCalled);
+
+  EXPECT_EQ(&Loc1, &Loc2);
+
+  Lattice.clearConstMethodReturnStorageLocations(Loc);
+  StorageLocation &Loc3 = Lattice.getOrCreateConstMethodReturnStorageLocation(
+      Loc, Callee, Env, NopInit);
+
+  EXPECT_NE(&Loc3, &Loc1);
+  EXPECT_NE(&Loc3, &Loc2);
+}
+
 TEST_F(CachedConstAccessorsLatticeTest,
        SameStructValBeforeClearOrDiffAfterClear) {
   TestAST AST(R"cpp(
diff --git a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
index de16f6be8eedb..19c3ff49eab27 100644
--- a/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/UncheckedOptionalAccessModelTest.cpp
@@ -3771,6 +3771,54 @@ TEST_P(UncheckedOptionalAccessTest, ConstPointerAccessorWithModInBetween) {
                        /*IgnoreSmartPointerDereference=*/false);
 }
 
+TEST_P(UncheckedOptionalAccessTest, SmartPointerAccessorMixed) {
+  ExpectDiagnosticsFor(R"cc(
+     #include "unchecked_optional_access_test.h"
+
+    struct A {
+      $ns::$optional x;
+    };
+
+    namespace absl {
+    template
+    class StatusOr {
+      public:
+      bool ok() const;
+
+      const T& operator*() const&;
+      T& operator*() &;
+
+      const T* operator->() const;
+      T* operator->();
+
+      const T& value() const;
+      T& value();
+    };
+    }
+
+    void target(absl::StatusOr &mut, const absl::StatusOr &imm) {
+      if (!mut.ok() || !imm.ok())
+        return;
+
+      if (mut->x.has_value()) {
+        mut->x.value();
+        ((*mut).x).value();
+        (mut.value().x).value();
+
+        // check flagged after modifying
+        mut = imm;
+        mut->x.value();  // [[unsafe]]
+      }
+      if (imm->x.has_value()) {
+        imm->x.value();
+        ((*imm).x).value();
+        (imm.value().x).value();
+      }
+    }
+  )cc",
+                       /*IgnoreSmartPointerDereference=*/false);
+}
+
 TEST_P(UncheckedOptionalAccessTest, ConstBoolAccessor) {
   ExpectDiagnosticsFor(R"cc(
     #include "unchecked_optional_access_test.h"
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 70f57a0c00a7f..f2716f1e4c653 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -14045,7 +14045,7 @@ 

C++ defect report implementation status

2369 CD6 Ordering between constraints and substitution - Partial + Unknown 2370 @@ -16464,11 +16464,7 @@

C++ defect report implementation status

2770 open Trailing requires-clause can refer to function parameters before they are substituted into - -
- Not resolved - Clang 20 implements 2023-07-14 resolution -
+ Not resolved 2771 diff --git a/compiler-rt/cmake/Modules/AddCompilerRT.cmake b/compiler-rt/cmake/Modules/AddCompilerRT.cmake index 3a6762320f447..c3e734f72392f 100644 --- a/compiler-rt/cmake/Modules/AddCompilerRT.cmake +++ b/compiler-rt/cmake/Modules/AddCompilerRT.cmake @@ -389,7 +389,8 @@ function(add_compiler_rt_runtime name type) set_target_properties(${libname} PROPERTIES IMPORT_PREFIX "") set_target_properties(${libname} PROPERTIES IMPORT_SUFFIX ".lib") endif() - if (APPLE AND NOT CMAKE_LINKER MATCHES ".*lld.*") + find_program(CODESIGN codesign) + if (APPLE AND NOT CMAKE_LINKER MATCHES ".*lld.*" AND CODESIGN) # Apple's linker signs the resulting dylib with an ad-hoc code signature in # most situations, except: # 1. Versions of ld64 prior to ld64-609 in Xcode 12 predate this behavior. @@ -404,7 +405,7 @@ function(add_compiler_rt_runtime name type) # argument and looking for `invalid argument "linker-signed"` in its output. # FIXME: Remove this once all supported toolchains support `-o linker-signed`. execute_process( - COMMAND sh -c "codesign -f -s - -o linker-signed this-does-not-exist 2>&1 | grep -q linker-signed" + COMMAND sh -c "${CODESIGN} -f -s - -o linker-signed this-does-not-exist 2>&1 | grep -q linker-signed" RESULT_VARIABLE CODESIGN_SUPPORTS_LINKER_SIGNED ) @@ -415,7 +416,7 @@ function(add_compiler_rt_runtime name type) add_custom_command(TARGET ${libname} POST_BUILD - COMMAND codesign --sign - ${EXTRA_CODESIGN_ARGUMENTS} $ + COMMAND ${CODESIGN} --sign - ${EXTRA_CODESIGN_ARGUMENTS} $ WORKING_DIRECTORY ${COMPILER_RT_OUTPUT_LIBRARY_DIR} COMMAND_EXPAND_LISTS ) diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp index 7ec0382b58566..6a5f4b91d11d7 100644 --- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp @@ -347,11 +347,33 @@ INTERCEPTOR(int, setvbuf, FILE *stream, char *buf, int mode, size_t size) { __rtsan_notify_intercepted_call("setvbuf"); return REAL(setvbuf)(stream, buf, mode, size); } + +#if SANITIZER_LINUX +INTERCEPTOR(void, setlinebuf, FILE *stream) { +#else +INTERCEPTOR(int, setlinebuf, FILE *stream) { +#endif + __rtsan_notify_intercepted_call("setlinebuf"); + return REAL(setlinebuf)(stream); +} + +#if SANITIZER_LINUX +INTERCEPTOR(void, setbuffer, FILE *stream, char *buf, size_t size) { +#else +INTERCEPTOR(void, setbuffer, FILE *stream, char *buf, int size) { +#endif + __rtsan_notify_intercepted_call("setbuffer"); + return REAL(setbuffer)(stream, buf, size); +} #define RTSAN_MAYBE_INTERCEPT_SETBUF INTERCEPT_FUNCTION(setbuf) #define RTSAN_MAYBE_INTERCEPT_SETVBUF INTERCEPT_FUNCTION(setvbuf) +#define RTSAN_MAYBE_INTERCEPT_SETLINEBUF INTERCEPT_FUNCTION(setlinebuf) +#define RTSAN_MAYBE_INTERCEPT_SETBUFFER INTERCEPT_FUNCTION(setbuffer) #else #define RTSAN_MAYBE_INTERCEPT_SETBUF #define RTSAN_MAYBE_INTERCEPT_SETVBUF +#define RTSAN_MAYBE_INTERCEPT_SETLINEBUF +#define RTSAN_MAYBE_INTERCEPT_SETBUFFER #endif INTERCEPTOR(int, puts, const char *s) { @@ -1018,6 +1040,8 @@ void __rtsan::InitializeInterceptors() { RTSAN_MAYBE_INTERCEPT_FMEMOPEN; RTSAN_MAYBE_INTERCEPT_SETBUF; RTSAN_MAYBE_INTERCEPT_SETVBUF; + RTSAN_MAYBE_INTERCEPT_SETLINEBUF; + RTSAN_MAYBE_INTERCEPT_SETBUFFER; INTERCEPT_FUNCTION(lseek); RTSAN_MAYBE_INTERCEPT_LSEEK64; INTERCEPT_FUNCTION(dup); diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp index db0ec951ad10c..5488d3c7e2056 100644 --- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp +++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp @@ -409,7 +409,7 @@ TEST_F(RtsanFileTest, SetbufDieWhenRealtime) { FILE *f = fopen(GetTemporaryFilePath(), "w"); EXPECT_THAT(f, Ne(nullptr)); - auto Func = [&f, &buffer]() { setbuf(f, buffer); }; + auto Func = [f, &buffer]() { setbuf(f, buffer); }; ExpectRealtimeDeath(Func, "setbuf"); ExpectNonRealtimeSurvival(Func); @@ -421,7 +421,7 @@ TEST_F(RtsanFileTest, SetvbufDieWhenRealtime) { FILE *f = fopen(GetTemporaryFilePath(), "w"); EXPECT_THAT(f, Ne(nullptr)); - auto Func = [&f, &buffer, &size]() { + auto Func = [f, &buffer, size]() { int r = setvbuf(f, buffer, _IOFBF, size); EXPECT_THAT(r, Eq(0)); }; @@ -429,6 +429,28 @@ TEST_F(RtsanFileTest, SetvbufDieWhenRealtime) { ExpectRealtimeDeath(Func, "setvbuf"); ExpectNonRealtimeSurvival(Func); } + +TEST_F(RtsanFileTest, SetlinebufDieWhenRealtime) { + FILE *f = fopen(GetTemporaryFilePath(), "w"); + EXPECT_THAT(f, Ne(nullptr)); + + auto Func = [f]() { setlinebuf(f); }; + + ExpectRealtimeDeath(Func, "setlinebuf"); + ExpectNonRealtimeSurvival(Func); +} + +TEST_F(RtsanFileTest, SetbufferDieWhenRealtime) { + char buffer[1024]; + size_t size = sizeof(buffer); + FILE *f = fopen(GetTemporaryFilePath(), "w"); + EXPECT_THAT(f, Ne(nullptr)); + + auto Func = [f, &buffer, size]() { setbuffer(f, buffer, size); }; + + ExpectRealtimeDeath(Func, "setbuffer"); + ExpectNonRealtimeSurvival(Func); +} #endif class RtsanOpenedFileTest : public RtsanFileTest { diff --git a/compiler-rt/lib/tysan/tysan.cpp b/compiler-rt/lib/tysan/tysan.cpp index 39d78e7c95e0c..9c87b4782671a 100644 --- a/compiler-rt/lib/tysan/tysan.cpp +++ b/compiler-rt/lib/tysan/tysan.cpp @@ -197,10 +197,14 @@ static void reportError(void *Addr, int Size, tysan_type_descriptor *TD, Printf("\n"); if (pc) { + uptr top = 0; + uptr bottom = 0; + if (flags().print_stacktrace) + GetThreadStackTopAndBottom(false, &top, &bottom); bool request_fast = StackTrace::WillUseFastUnwind(true); BufferedStackTrace ST; - ST.Unwind(kStackTraceMax, pc, bp, 0, 0, 0, request_fast); + ST.Unwind(kStackTraceMax, pc, bp, 0, top, bottom, request_fast); ST.Print(); } else { Printf("\n"); diff --git a/compiler-rt/lib/tysan/tysan_flags.inc b/compiler-rt/lib/tysan/tysan_flags.inc index 98b6591f844ef..be65c8e828794 100644 --- a/compiler-rt/lib/tysan/tysan_flags.inc +++ b/compiler-rt/lib/tysan/tysan_flags.inc @@ -15,3 +15,6 @@ // TYSAN_FLAG(Type, Name, DefaultValue, Description) // See COMMON_FLAG in sanitizer_flags.inc for more details. + +TYSAN_FLAG(bool, print_stacktrace, false, + "Include full stacktrace into an error report") diff --git a/compiler-rt/test/tysan/print_stacktrace.c b/compiler-rt/test/tysan/print_stacktrace.c new file mode 100644 index 0000000000000..3ffb6063377d9 --- /dev/null +++ b/compiler-rt/test/tysan/print_stacktrace.c @@ -0,0 +1,22 @@ +// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1 +// RUN: FileCheck --check-prefixes=CHECK,CHECK-SHORT %s < %t.out + +// RUN: %env_tysan_opts=print_stacktrace=1 %run %t >%t.out 2>&1 +// RUN: FileCheck --check-prefixes=CHECK,CHECK-LONG %s < %t.out + +float *P; +void zero_array() { + int i; + for (i = 0; i < 1; ++i) + P[i] = 0.0f; + // CHECK: ERROR: TypeSanitizer: type-aliasing-violation + // CHECK: WRITE of size 4 at {{.*}} with type float accesses an existing object of type p1 float + // CHECK: {{#0 0x.* in zero_array .*print_stacktrace.c:}}[[@LINE-3]] + // CHECK-SHORT-NOT: {{#1 0x.* in main .*print_stacktrace.c}} + // CHECK-LONG-NEXT: {{#1 0x.* in main .*print_stacktrace.c}} +} + +int main() { + P = (float *)&P; + zero_array(); +} diff --git a/compiler-rt/test/ubsan/TestCases/Pointer/nullptr-and-nonzero-offset-constants.cpp b/compiler-rt/test/ubsan/TestCases/Pointer/nullptr-and-nonzero-offset-constants.cpp index 6a374c4b79c5b..9e7ed376c5de4 100644 --- a/compiler-rt/test/ubsan/TestCases/Pointer/nullptr-and-nonzero-offset-constants.cpp +++ b/compiler-rt/test/ubsan/TestCases/Pointer/nullptr-and-nonzero-offset-constants.cpp @@ -1,12 +1,12 @@ -// RUN: %clang -x c -fsanitize=pointer-overflow -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-C --implicit-check-not="runtime error:" -// RUN: %clang -x c -fsanitize=pointer-overflow -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-C --implicit-check-not="runtime error:" -// RUN: %clang -x c -fsanitize=pointer-overflow -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-C --implicit-check-not="runtime error:" -// RUN: %clang -x c -fsanitize=pointer-overflow -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-C --implicit-check-not="runtime error:" +// RUN: %clang -x c -fsanitize=pointer-overflow -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" +// RUN: %clang -x c -fsanitize=pointer-overflow -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" +// RUN: %clang -x c -fsanitize=pointer-overflow -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" +// RUN: %clang -x c -fsanitize=pointer-overflow -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" -// RUN: %clangxx -fsanitize=pointer-overflow -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-CPP --implicit-check-not="runtime error:" -// RUN: %clangxx -fsanitize=pointer-overflow -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-CPP --implicit-check-not="runtime error:" -// RUN: %clangxx -fsanitize=pointer-overflow -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-CPP --implicit-check-not="runtime error:" -// RUN: %clangxx -fsanitize=pointer-overflow -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-CPP --implicit-check-not="runtime error:" +// RUN: %clangxx -fsanitize=pointer-overflow -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" +// RUN: %clangxx -fsanitize=pointer-overflow -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" +// RUN: %clangxx -fsanitize=pointer-overflow -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" +// RUN: %clangxx -fsanitize=pointer-overflow -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" #include @@ -15,8 +15,7 @@ int main(int argc, char *argv[]) { base = (char *)0; result = base + 0; - // CHECK-C: {{.*}}.cpp:[[@LINE-1]]:17: runtime error: applying zero offset to null pointer - // CHECK-CPP-NOT: runtime error: + // CHECK-NOT: runtime error: base = (char *)0; result = base + 1; diff --git a/compiler-rt/test/ubsan/TestCases/Pointer/nullptr-and-nonzero-offset-summary.cpp b/compiler-rt/test/ubsan/TestCases/Pointer/nullptr-and-nonzero-offset-summary.cpp index 9e1d93fceb504..c7bdf7cd8a5a2 100644 --- a/compiler-rt/test/ubsan/TestCases/Pointer/nullptr-and-nonzero-offset-summary.cpp +++ b/compiler-rt/test/ubsan/TestCases/Pointer/nullptr-and-nonzero-offset-summary.cpp @@ -1,10 +1,10 @@ // RUN: %clang -x c -fsanitize=pointer-overflow %s -o %t -// RUN: %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-NOTYPE,CHECK-NOTYPE-C -// RUN: %env_ubsan_opts=report_error_type=1 %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-TYPE,CHECK-TYPE-C +// RUN: %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-NOTYPE +// RUN: %env_ubsan_opts=report_error_type=1 %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-TYPE // RUN: %clangxx -fsanitize=pointer-overflow %s -o %t -// RUN: %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-NOTYPE,CHECK-NOTYPE-CPP -// RUN: %env_ubsan_opts=report_error_type=1 %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-TYPE,CHECK-TYPE-CPP +// RUN: %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-NOTYPE +// RUN: %env_ubsan_opts=report_error_type=1 %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK-TYPE #include @@ -13,10 +13,8 @@ int main(int argc, char *argv[]) { base = (char *)0; result = base + 0; - // CHECK-NOTYPE-C: SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior {{.*}}summary.cpp:[[@LINE-1]]:17 - // CHECK-TYPE-C: SUMMARY: UndefinedBehaviorSanitizer: nullptr-with-offset {{.*}}summary.cpp:[[@LINE-2]]:17 - // CHECK-NOTYPE-CPP-NOT: SUMMARY: - // CHECK-TYPE-CPP-NOT: SUMMARY: + // CHECK-NOTYPE-NOT: SUMMARY: + // CHECK-TYPE-NOT: SUMMARY: base = (char *)0; result = base + 1; diff --git a/compiler-rt/test/ubsan/TestCases/Pointer/nullptr-and-nonzero-offset-variable.cpp b/compiler-rt/test/ubsan/TestCases/Pointer/nullptr-and-nonzero-offset-variable.cpp index 5cbabf1849902..1eac1b2888cc7 100644 --- a/compiler-rt/test/ubsan/TestCases/Pointer/nullptr-and-nonzero-offset-variable.cpp +++ b/compiler-rt/test/ubsan/TestCases/Pointer/nullptr-and-nonzero-offset-variable.cpp @@ -1,7 +1,7 @@ -// RUN: %clang -x c -fsanitize=pointer-overflow -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" --check-prefix=CHECK-UB-C -// RUN: %clang -x c -fsanitize=pointer-overflow -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" --check-prefix=CHECK-UB-C -// RUN: %clang -x c -fsanitize=pointer-overflow -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" --check-prefix=CHECK-UB-C -// RUN: %clang -x c -fsanitize=pointer-overflow -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" --check-prefix=CHECK-UB-C +// RUN: %clang -x c -fsanitize=pointer-overflow -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" --check-prefix=CHECK +// RUN: %clang -x c -fsanitize=pointer-overflow -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" --check-prefix=CHECK +// RUN: %clang -x c -fsanitize=pointer-overflow -O2 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" --check-prefix=CHECK +// RUN: %clang -x c -fsanitize=pointer-overflow -O3 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" --check-prefix=CHECK // RUN: %clangxx -x c++ -fsanitize=pointer-overflow -O0 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" --check-prefix=CHECK // RUN: %clangxx -x c++ -fsanitize=pointer-overflow -O1 %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="runtime error:" --check-prefix=CHECK @@ -38,7 +38,6 @@ int main(int argc, char *argv[]) { offset = argc - 1; (void)getelementpointer_inbounds_v0(base, offset); // CHECK-UB: {{.*}}.cpp:[[@LINE-13]]:15: runtime error: applying non-zero offset 1 to null pointer - // CHECK-UB-C: {{.*}}.cpp:[[@LINE-14]]:15: runtime error: applying zero offset to null pointer return 0; } diff --git a/compiler-rt/test/ubsan_minimal/TestCases/nullptr-and-nonzero-offset.c b/compiler-rt/test/ubsan_minimal/TestCases/nullptr-and-nonzero-offset.c index 2077e7d47b4d3..bba9a38da0c73 100644 --- a/compiler-rt/test/ubsan_minimal/TestCases/nullptr-and-nonzero-offset.c +++ b/compiler-rt/test/ubsan_minimal/TestCases/nullptr-and-nonzero-offset.c @@ -1,5 +1,5 @@ -// RUN: %clang -fsanitize=pointer-overflow %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-C --implicit-check-not="pointer-overflow" -// RUN: %clangxx -x c++ -fsanitize=pointer-overflow %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-CPP --implicit-check-not="pointer-overflow" +// RUN: %clang -fsanitize=pointer-overflow %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="pointer-overflow" +// RUN: %clangxx -x c++ -fsanitize=pointer-overflow %s -o %t && %run %t 2>&1 | FileCheck %s --implicit-check-not="pointer-overflow" #include @@ -8,8 +8,7 @@ int main(int argc, char *argv[]) { base = (char *)0; result = base + 0; - // CHECK-C: pointer-overflow by 0x{{[[:xdigit:]]+$}} - // CHECK-CPP-NOT: pointer-overflow + // CHECK-NOT: pointer-overflow base = (char *)0; result = base + 1; diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md index 907f01204a387..f25f0d1e0ca39 100644 --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -410,6 +410,7 @@ end * A character length specifier in a component or entity declaration is accepted before an array specification (`ch*3(2)`) as well as afterwards. +* A zero field width is allowed for logical formatted output (`L0`). ### Extensions supported when enabled by options diff --git a/flang/include/flang/Common/format.h b/flang/include/flang/Common/format.h index de6967139c5ca..c5e9fb06e260f 100644 --- a/flang/include/flang/Common/format.h +++ b/flang/include/flang/Common/format.h @@ -463,10 +463,13 @@ template void FormatValidator::check_r(bool allowed) { template bool FormatValidator::check_w() { if (token_.kind() == TokenKind::UnsignedInteger) { wValue_ = integerValue_; - if (wValue_ == 0 && - (*argString_ == 'A' || *argString_ == 'L' || - stmt_ == IoStmtKind::Read)) { // C1306, 13.7.2.1p6 - ReportError("'%s' edit descriptor 'w' value must be positive"); + if (wValue_ == 0) { + if (*argString_ == 'A' || stmt_ == IoStmtKind::Read) { + // C1306, 13.7.2.1p6 + ReportError("'%s' edit descriptor 'w' value must be positive"); + } else if (*argString_ == 'L') { + ReportWarning("'%s' edit descriptor 'w' value should be positive"); + } } NextToken(); return true; diff --git a/flang/include/flang/Evaluate/call.h b/flang/include/flang/Evaluate/call.h index 7531d8a81e808..63277438128eb 100644 --- a/flang/include/flang/Evaluate/call.h +++ b/flang/include/flang/Evaluate/call.h @@ -250,6 +250,7 @@ class ProcedureRef { std::optional> LEN() const; int Rank() const; + static constexpr int Corank() { return 0; } // TODO bool IsElemental() const { return proc_.IsElemental(); } bool hasAlternateReturns() const { return hasAlternateReturns_; } diff --git a/flang/include/flang/Evaluate/characteristics.h b/flang/include/flang/Evaluate/characteristics.h index 11533a7259b05..357fc3e595243 100644 --- a/flang/include/flang/Evaluate/characteristics.h +++ b/flang/include/flang/Evaluate/characteristics.h @@ -102,6 +102,10 @@ class TypeAndShape { } if (auto type{x.GetType()}) { TypeAndShape result{*type, GetShape(context, x, invariantOnly)}; + result.corank_ = GetCorank(x); + if (result.corank_ > 0) { + result.attrs_.set(Attr::Coarray); + } if (type->category() == TypeCategory::Character) { if (const auto *chExpr{UnwrapExpr>(x)}) { if (auto length{chExpr->LEN()}) { diff --git a/flang/include/flang/Evaluate/constant.h b/flang/include/flang/Evaluate/constant.h index d9866a08889f3..61a814446bbfd 100644 --- a/flang/include/flang/Evaluate/constant.h +++ b/flang/include/flang/Evaluate/constant.h @@ -65,6 +65,7 @@ class ConstantBounds { ~ConstantBounds(); const ConstantSubscripts &shape() const { return shape_; } int Rank() const { return GetRank(shape_); } + static constexpr int Corank() { return 0; } Constant SHAPE() const; // It is possible in this representation for a constant array to have diff --git a/flang/include/flang/Evaluate/expression.h b/flang/include/flang/Evaluate/expression.h index 9ea037a2f7c42..04f4406fc8a2c 100644 --- a/flang/include/flang/Evaluate/expression.h +++ b/flang/include/flang/Evaluate/expression.h @@ -92,6 +92,7 @@ template class ExpressionBase { std::optional GetType() const; int Rank() const; + int Corank() const; std::string AsFortran() const; #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void dump() const; @@ -190,6 +191,7 @@ class Operation { return rank; } } + static constexpr int Corank() { return 0; } bool operator==(const Operation &that) const { return operand_ == that.operand_; @@ -395,6 +397,7 @@ struct ImpliedDoIndex { using Result = SubscriptInteger; bool operator==(const ImpliedDoIndex &) const; static constexpr int Rank() { return 0; } + static constexpr int Corank() { return 0; } parser::CharBlock name; // nested implied DOs must use distinct names }; @@ -441,6 +444,7 @@ template class ArrayConstructorValues { bool operator==(const ArrayConstructorValues &) const; static constexpr int Rank() { return 1; } + static constexpr int Corank() { return 0; } template common::NoLvalue Push(A &&x) { values_.emplace_back(std::move(x)); } @@ -680,6 +684,7 @@ template <> class Relational { int Rank() const { return common::visit([](const auto &x) { return x.Rank(); }, u); } + static constexpr int Corank() { return 0; } llvm::raw_ostream &AsFortran(llvm::raw_ostream &o) const; common::MapTemplate u; }; @@ -766,7 +771,8 @@ class StructureConstructor { std::optional> Find(const Symbol &) const; StructureConstructor &Add(const semantics::Symbol &, Expr &&); - int Rank() const { return 0; } + static constexpr int Rank() { return 0; } + static constexpr int Corank() { return 0; } DynamicType GetType() const; llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; @@ -820,7 +826,8 @@ using BOZLiteralConstant = typename LargestReal::Scalar::Word; // Null pointers without MOLD= arguments are typed by context. struct NullPointer { constexpr bool operator==(const NullPointer &) const { return true; } - constexpr int Rank() const { return 0; } + static constexpr int Rank() { return 0; } + static constexpr int Corank() { return 0; } }; // Procedure pointer targets are treated as if they were typeless. diff --git a/flang/include/flang/Evaluate/shape.h b/flang/include/flang/Evaluate/shape.h index e33044c0d34e5..e679a00123549 100644 --- a/flang/include/flang/Evaluate/shape.h +++ b/flang/include/flang/Evaluate/shape.h @@ -117,6 +117,14 @@ MaybeExtentExpr GetExtent(const Subscript &, const NamedEntity &, int dimension, MaybeExtentExpr GetExtent(FoldingContext &, const Subscript &, const NamedEntity &, int dimension, bool invariantOnly = true); +// Similar analyses for coarrays +MaybeExtentExpr GetLCOBOUND( + const Symbol &, int dimension, bool invariantOnly = true); +MaybeExtentExpr GetUCOBOUND( + const Symbol &, int dimension, bool invariantOnly = true); +Shape GetLCOBOUNDs(const Symbol &, bool invariantOnly = true); +Shape GetUCOBOUNDs(const Symbol &, bool invariantOnly = true); + // Compute an element count for a triplet or trip count for a DO. ExtentExpr CountTrips( ExtentExpr &&lower, ExtentExpr &&upper, ExtentExpr &&stride); diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h index f586c59d46e54..ec5fc7ab01485 100644 --- a/flang/include/flang/Evaluate/tools.h +++ b/flang/include/flang/Evaluate/tools.h @@ -102,22 +102,26 @@ template bool IsAssumedRank(const A *x) { return x && IsAssumedRank(*x); } -// Predicate: true when an expression is a coarray (corank > 0) -bool IsCoarray(const ActualArgument &); -bool IsCoarray(const Symbol &); -template bool IsCoarray(const A &) { return false; } -template bool IsCoarray(const Designator &designator) { - if (const auto *symbol{std::get_if(&designator.u)}) { - return IsCoarray(**symbol); - } - return false; +// Finds the corank of an entity, possibly packaged in various ways. +// Unlike rank, only data references have corank > 0. +int GetCorank(const ActualArgument &); +static inline int GetCorank(const Symbol &symbol) { return symbol.Corank(); } +template int GetCorank(const A &) { return 0; } +template int GetCorank(const Designator &designator) { + return designator.Corank(); } -template bool IsCoarray(const Expr &expr) { - return common::visit([](const auto &x) { return IsCoarray(x); }, expr.u); +template int GetCorank(const Expr &expr) { + return common::visit([](const auto &x) { return GetCorank(x); }, expr.u); } -template bool IsCoarray(const std::optional &x) { - return x && IsCoarray(*x); +template int GetCorank(const std::optional &x) { + return x ? GetCorank(*x) : 0; } +template int GetCorank(const A *x) { + return x ? GetCorank(*x) : 0; +} + +// Predicate: true when an expression is a coarray (corank > 0) +template bool IsCoarray(const A &x) { return GetCorank(x) > 0; } // Generalizing packagers: these take operations and expressions of more // specific types and wrap them in Expr<> containers of more abstract types. diff --git a/flang/include/flang/Evaluate/variable.h b/flang/include/flang/Evaluate/variable.h index 9565826dbfaea..b454d37d93e57 100644 --- a/flang/include/flang/Evaluate/variable.h +++ b/flang/include/flang/Evaluate/variable.h @@ -51,6 +51,7 @@ template struct Variable; struct BaseObject { EVALUATE_UNION_CLASS_BOILERPLATE(BaseObject) int Rank() const; + int Corank() const; std::optional> LEN() const; llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; const Symbol *symbol() const { @@ -84,6 +85,7 @@ class Component { SymbolRef &symbol() { return symbol_; } int Rank() const; + int Corank() const; const Symbol &GetFirstSymbol() const; const Symbol &GetLastSymbol() const { return symbol_; } std::optional> LEN() const; @@ -116,6 +118,7 @@ class NamedEntity { Component *UnwrapComponent(); int Rank() const; + int Corank() const; std::optional> LEN() const; bool operator==(const NamedEntity &) const; llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; @@ -147,6 +150,7 @@ class TypeParamInquiry { const Symbol ¶meter() const { return parameter_; } static constexpr int Rank() { return 0; } // always scalar + static constexpr int Corank() { return 0; } bool operator==(const TypeParamInquiry &) const; llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; @@ -224,6 +228,7 @@ class ArrayRef { } int Rank() const; + int Corank() const; const Symbol &GetFirstSymbol() const; const Symbol &GetLastSymbol() const; std::optional> LEN() const; @@ -271,6 +276,7 @@ class CoarrayRef { CoarrayRef &set_team(Expr &&, bool isTeamNumber = false); int Rank() const; + int Corank() const { return 0; } const Symbol &GetFirstSymbol() const; const Symbol &GetLastSymbol() const; NamedEntity GetBase() const; @@ -294,6 +300,7 @@ class CoarrayRef { struct DataRef { EVALUATE_UNION_CLASS_BOILERPLATE(DataRef) int Rank() const; + int Corank() const; const Symbol &GetFirstSymbol() const; const Symbol &GetLastSymbol() const; std::optional> LEN() const; @@ -331,6 +338,7 @@ class Substring { Parent &parent() { return parent_; } int Rank() const; + int Corank() const; template const A *GetParentIf() const { return std::get_if(&parent_); } @@ -361,6 +369,7 @@ class ComplexPart { const DataRef &complex() const { return complex_; } Part part() const { return part_; } int Rank() const; + int Corank() const; const Symbol &GetFirstSymbol() const { return complex_.GetFirstSymbol(); } const Symbol &GetLastSymbol() const { return complex_.GetLastSymbol(); } bool operator==(const ComplexPart &) const; @@ -396,6 +405,7 @@ template class Designator { std::optional GetType() const; int Rank() const; + int Corank() const; BaseObject GetBaseObject() const; const Symbol *GetLastSymbol() const; std::optional> LEN() const; @@ -421,6 +431,7 @@ class DescriptorInquiry { int dimension() const { return dimension_; } static constexpr int Rank() { return 0; } // always scalar + static constexpr int Corank() { return 0; } bool operator==(const DescriptorInquiry &) const; llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const; diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h index 6ee4370c99dca..c5d86e713f253 100644 --- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h +++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h @@ -769,6 +769,11 @@ mlir::Value genMaxWithZero(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value genCPtrOrCFunptrAddr(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value cPtr, mlir::Type ty); +/// The type(C_DEVPTR) is defined as the derived type with only one +/// component of C_PTR type. Get the C address from the C_PTR component. +mlir::Value genCDevPtrAddr(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value cDevPtr, mlir::Type ty); + /// Get the C address value. mlir::Value genCPtrOrCFunptrValue(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value cPtr); diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h index 3d0516555f761..18f84c7021e11 100644 --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -214,6 +214,7 @@ struct IntrinsicLibrary { llvm::ArrayRef); fir::ExtendedValue genCAssociatedCPtr(mlir::Type, llvm::ArrayRef); + fir::ExtendedValue genCDevLoc(mlir::Type, llvm::ArrayRef); mlir::Value genErfcScaled(mlir::Type resultType, llvm::ArrayRef args); void genCFPointer(llvm::ArrayRef); diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index 2f97efddf7f7b..bc6abccac1bb8 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -861,23 +861,7 @@ class Symbol { bool operator!=(const Symbol &that) const { return !(*this == that); } int Rank() const { return RankImpl(); } - - int Corank() const { - return common::visit( - common::visitors{ - [](const SubprogramDetails &sd) { - return sd.isFunction() ? sd.result().Corank() : 0; - }, - [](const GenericDetails &) { - return 0; /*TODO*/ - }, - [](const UseDetails &x) { return x.symbol().Corank(); }, - [](const HostAssocDetails &x) { return x.symbol().Corank(); }, - [](const ObjectEntityDetails &oed) { return oed.coshape().Rank(); }, - [](const auto &) { return 0; }, - }, - details_); - } + int Corank() const { return CorankImpl(); } // If there is a parent component, return a pointer to its derived type spec. // The Scope * argument defaults to this->scope_ but should be overridden @@ -955,6 +939,32 @@ class Symbol { }, details_); } + inline int CorankImpl(int depth = startRecursionDepth) const { + if (depth-- == 0) { + return 0; + } + return common::visit( + common::visitors{ + [&](const SubprogramDetails &sd) { + return sd.isFunction() ? sd.result().CorankImpl(depth) : 0; + }, + [](const GenericDetails &) { return 0; }, + [&](const ProcEntityDetails &ped) { + const Symbol *iface{ped.procInterface()}; + return iface ? iface->CorankImpl(depth) : 0; + }, + [&](const UseDetails &x) { return x.symbol().CorankImpl(depth); }, + [&](const HostAssocDetails &x) { + return x.symbol().CorankImpl(depth); + }, + [](const ObjectEntityDetails &oed) { return oed.coshape().Rank(); }, + [](const AssocEntityDetails &aed) { + return aed.expr() ? aed.expr()->Corank() : 0; + }, + [](const auto &) { return 0; }, + }, + details_); + } template friend class Symbols; template friend class std::array; }; diff --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp index 324d6b8dde73b..3912d1c4b4771 100644 --- a/flang/lib/Evaluate/characteristics.cpp +++ b/flang/lib/Evaluate/characteristics.cpp @@ -227,15 +227,14 @@ void TypeAndShape::AcquireAttrs(const semantics::Symbol &symbol) { } else if (semantics::IsAssumedSizeArray(symbol)) { attrs_.set(Attr::AssumedSize); } + if (int n{GetCorank(symbol)}) { + corank_ = n; + attrs_.set(Attr::Coarray); + } if (const auto *object{ - symbol.GetUltimate().detailsIf()}) { - corank_ = object->coshape().Rank(); - if (object->IsAssumedRank()) { - attrs_.set(Attr::AssumedRank); - } - if (object->IsCoarray()) { - attrs_.set(Attr::Coarray); - } + symbol.GetUltimate().detailsIf()}; + object && object->IsAssumedRank()) { + attrs_.set(Attr::AssumedRank); } } diff --git a/flang/lib/Evaluate/expression.cpp b/flang/lib/Evaluate/expression.cpp index 9514ac8e3f656..759fe5bc71b69 100644 --- a/flang/lib/Evaluate/expression.cpp +++ b/flang/lib/Evaluate/expression.cpp @@ -113,6 +113,18 @@ template int ExpressionBase::Rank() const { derived().u); } +template int ExpressionBase::Corank() const { + return common::visit( + [](const auto &x) { + if constexpr (common::HasMember) { + return 0; + } else { + return x.Corank(); + } + }, + derived().u); +} + DynamicType Parentheses::GetType() const { return left().GetType().value(); } diff --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp index 26ae33faffe1e..352dec4bb5ee2 100644 --- a/flang/lib/Evaluate/fold-integer.cpp +++ b/flang/lib/Evaluate/fold-integer.cpp @@ -71,6 +71,28 @@ static bool CheckDimArg(const std::optional &dimArg, return true; } +static bool CheckCoDimArg(const std::optional &dimArg, + const Symbol &symbol, parser::ContextualMessages &messages, + std::optional &dimVal) { + dimVal.reset(); + if (int corank{symbol.Corank()}; corank > 0) { + if (auto dim64{ToInt64(dimArg)}) { + if (*dim64 < 1) { + messages.Say("DIM=%jd dimension must be positive"_err_en_US, *dim64); + return false; + } else if (*dim64 > corank) { + messages.Say( + "DIM=%jd dimension is out of range for corank-%d coarray"_err_en_US, + *dim64, corank); + return false; + } else { + dimVal = static_cast(*dim64 - 1); // 1-based to 0-based + } + } + } + return true; +} + // Class to retrieve the constant bound of an expression which is an // array that devolves to a type of Constant class GetConstantArrayBoundHelper { @@ -264,6 +286,37 @@ Expr> UBOUND(FoldingContext &context, return Expr{std::move(funcRef)}; } +// LCOBOUND() & UCOBOUND() +template +Expr> COBOUND(FoldingContext &context, + FunctionRef> &&funcRef, bool isUCOBOUND) { + using T = Type; + ActualArguments &args{funcRef.arguments()}; + if (const Symbol * coarray{UnwrapWholeSymbolOrComponentDataRef(args[0])}) { + std::optional dim; + if (funcRef.Rank() == 0) { + // Optional DIM= argument is present: result is scalar. + if (!CheckCoDimArg(args[1], *coarray, context.messages(), dim)) { + return MakeInvalidIntrinsic(std::move(funcRef)); + } else if (!dim) { + // DIM= is present but not constant, or error + return Expr{std::move(funcRef)}; + } + } + if (dim) { + if (auto cb{isUCOBOUND ? GetUCOBOUND(*coarray, *dim) + : GetLCOBOUND(*coarray, *dim)}) { + return Fold(context, ConvertToType(std::move(*cb))); + } + } else if (auto cbs{ + AsExtentArrayExpr(isUCOBOUND ? GetUCOBOUNDs(*coarray) + : GetLCOBOUNDs(*coarray))}) { + return Fold(context, ConvertToType(Expr{std::move(*cbs)})); + } + } + return Expr{std::move(funcRef)}; +} + // COUNT() template class CountAccumulator { using MaskT = Type; @@ -1105,6 +1158,8 @@ Expr> FoldIntrinsicFunction( } } else if (name == "lbound") { return LBOUND(context, std::move(funcRef)); + } else if (name == "lcobound") { + return COBOUND(context, std::move(funcRef), /*isUCOBOUND=*/false); } else if (name == "leadz" || name == "trailz" || name == "poppar" || name == "popcnt") { if (auto *sn{UnwrapExpr>>(args[0])}) { @@ -1396,6 +1451,8 @@ Expr> FoldIntrinsicFunction( } } else if (name == "ubound") { return UBOUND(context, std::move(funcRef)); + } else if (name == "ucobound") { + return COBOUND(context, std::move(funcRef), /*isUCOBOUND=*/true); } else if (name == "__builtin_numeric_storage_size") { if (!context.moduleFileName()) { // Don't fold this reference until it appears in the module file diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index 28805efb177ee..0dc8e121ea165 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -958,7 +958,7 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ {{"coarray", AnyData, Rank::coarray}, RequiredDIM, OptionalTEAM}, DefaultInt, Rank::scalar, IntrinsicClass::transformationalFunction}, {"this_image", {{"coarray", AnyData, Rank::coarray}, OptionalTEAM}, - DefaultInt, Rank::scalar, IntrinsicClass::transformationalFunction}, + DefaultInt, Rank::vector, IntrinsicClass::transformationalFunction}, {"this_image", {OptionalTEAM}, DefaultInt, Rank::scalar, IntrinsicClass::transformationalFunction}, {"tiny", @@ -2663,6 +2663,8 @@ class IntrinsicProcTable::Implementation { ActualArguments &, FoldingContext &) const; std::optional HandleC_Loc( ActualArguments &, FoldingContext &) const; + std::optional HandleC_Devloc( + ActualArguments &, FoldingContext &) const; const std::string &ResolveAlias(const std::string &name) const { auto iter{aliases_.find(name)}; return iter == aliases_.end() ? name : iter->second; @@ -2690,7 +2692,8 @@ bool IntrinsicProcTable::Implementation::IsIntrinsicFunction( return true; } // special cases - return name == "__builtin_c_loc" || name == "null"; + return name == "__builtin_c_loc" || name == "__builtin_c_devloc" || + name == "null"; } bool IntrinsicProcTable::Implementation::IsIntrinsicSubroutine( const std::string &name0) const { @@ -3080,6 +3083,73 @@ std::optional IntrinsicProcTable::Implementation::HandleC_Loc( return std::nullopt; } +// CUDA Fortran C_DEVLOC(x) +std::optional IntrinsicProcTable::Implementation::HandleC_Devloc( + ActualArguments &arguments, FoldingContext &context) const { + static const char *const keywords[]{"cptr", nullptr}; + + if (CheckAndRearrangeArguments(arguments, context.messages(), keywords)) { + CHECK(arguments.size() == 1); + const auto *expr{arguments[0].value().UnwrapExpr()}; + if (auto typeAndShape{characteristics::TypeAndShape::Characterize( + arguments[0], context)}) { + if (expr && !IsContiguous(*expr, context).value_or(true)) { + context.messages().Say(arguments[0]->sourceLocation(), + "C_DEVLOC() argument must be contiguous"_err_en_US); + } + if (auto constExtents{AsConstantExtents(context, typeAndShape->shape())}; + constExtents && GetSize(*constExtents) == 0) { + context.messages().Say(arguments[0]->sourceLocation(), + "C_DEVLOC() argument may not be a zero-sized array"_err_en_US); + } + if (!(typeAndShape->type().category() != TypeCategory::Derived || + typeAndShape->type().IsAssumedType() || + (!typeAndShape->type().IsPolymorphic() && + CountNonConstantLenParameters( + typeAndShape->type().GetDerivedTypeSpec()) == 0))) { + context.messages().Say(arguments[0]->sourceLocation(), + "C_DEVLOC() argument must have an intrinsic type, assumed type, or non-polymorphic derived type with no non-constant length parameter"_err_en_US); + } else if (typeAndShape->type().knownLength().value_or(1) == 0) { + context.messages().Say(arguments[0]->sourceLocation(), + "C_DEVLOC() argument may not be zero-length character"_err_en_US); + } else if (typeAndShape->type().category() != TypeCategory::Derived && + !IsInteroperableIntrinsicType(typeAndShape->type()).value_or(true)) { + if (typeAndShape->type().category() == TypeCategory::Character && + typeAndShape->type().kind() == 1) { + // Default character kind, but length is not known to be 1 + if (context.languageFeatures().ShouldWarn( + common::UsageWarning::CharacterInteroperability)) { + context.messages().Say( + common::UsageWarning::CharacterInteroperability, + arguments[0]->sourceLocation(), + "C_DEVLOC() argument has non-interoperable character length"_warn_en_US); + } + } else if (context.languageFeatures().ShouldWarn( + common::UsageWarning::Interoperability)) { + context.messages().Say(common::UsageWarning::Interoperability, + arguments[0]->sourceLocation(), + "C_DEVLOC() argument has non-interoperable intrinsic type or kind"_warn_en_US); + } + } + + characteristics::DummyDataObject ddo{std::move(*typeAndShape)}; + ddo.intent = common::Intent::In; + return SpecificCall{ + SpecificIntrinsic{"__builtin_c_devloc"s, + characteristics::Procedure{ + characteristics::FunctionResult{ + DynamicType{GetBuiltinDerivedType( + builtinsScope_, "__builtin_c_devptr")}}, + characteristics::DummyArguments{ + characteristics::DummyArgument{"cptr"s, std::move(ddo)}}, + characteristics::Procedure::Attrs{ + characteristics::Procedure::Attr::Pure}}}, + std::move(arguments)}; + } + } + return std::nullopt; +} + static bool CheckForNonPositiveValues(FoldingContext &context, const ActualArgument &arg, const std::string &procName, const std::string &argName) { @@ -3119,27 +3189,6 @@ static bool CheckForNonPositiveValues(FoldingContext &context, return ok; } -static bool CheckDimAgainstCorank(SpecificCall &call, FoldingContext &context) { - bool ok{true}; - if (const auto &coarrayArg{call.arguments[0]}) { - if (const auto &dimArg{call.arguments[1]}) { - if (const auto *symbol{ - UnwrapWholeSymbolDataRef(coarrayArg->UnwrapExpr())}) { - const auto corank = symbol->Corank(); - if (const auto dimNum{ToInt64(dimArg->UnwrapExpr())}) { - if (dimNum < 1 || dimNum > corank) { - ok = false; - context.messages().Say(dimArg->sourceLocation(), - "DIM=%jd dimension is out of range for coarray with corank %d"_err_en_US, - static_cast(*dimNum), corank); - } - } - } - } - } - return ok; -} - static bool CheckAtomicDefineAndRef(FoldingContext &context, const std::optional &atomArg, const std::optional &valueArg, @@ -3207,8 +3256,6 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) { if (const auto &arg{call.arguments[0]}) { ok = CheckForNonPositiveValues(context, *arg, name, "image"); } - } else if (name == "lcobound") { - return CheckDimAgainstCorank(call, context); } else if (name == "loc") { const auto &arg{call.arguments[0]}; ok = @@ -3218,8 +3265,6 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) { arg ? arg->sourceLocation() : context.messages().at(), "Argument of LOC() must be an object or procedure"_err_en_US); } - } else if (name == "ucobound") { - return CheckDimAgainstCorank(call, context); } return ok; } @@ -3270,6 +3315,8 @@ std::optional IntrinsicProcTable::Implementation::Probe( } else { // function if (call.name == "__builtin_c_loc") { return HandleC_Loc(arguments, context); + } else if (call.name == "__builtin_c_devloc") { + return HandleC_Devloc(arguments, context); } else if (call.name == "null") { return HandleNull(arguments, context); } diff --git a/flang/lib/Evaluate/shape.cpp b/flang/lib/Evaluate/shape.cpp index c62d0cb0ff29d..c7b2156a3de17 100644 --- a/flang/lib/Evaluate/shape.cpp +++ b/flang/lib/Evaluate/shape.cpp @@ -723,6 +723,58 @@ Shape GetUBOUNDs(const NamedEntity &base, bool invariantOnly) { return GetUBOUNDs(nullptr, base, invariantOnly); } +MaybeExtentExpr GetLCOBOUND( + const Symbol &symbol0, int dimension, bool invariantOnly) { + const Symbol &symbol{ResolveAssociations(symbol0)}; + if (const auto *object{symbol.detailsIf()}) { + int corank{object->coshape().Rank()}; + if (dimension < corank) { + const semantics::ShapeSpec &shapeSpec{object->coshape()[dimension]}; + if (const auto &lcobound{shapeSpec.lbound().GetExplicit()}) { + if (!invariantOnly || IsScopeInvariantExpr(*lcobound)) { + return *lcobound; + } + } + } + } + return std::nullopt; +} + +MaybeExtentExpr GetUCOBOUND( + const Symbol &symbol0, int dimension, bool invariantOnly) { + const Symbol &symbol{ResolveAssociations(symbol0)}; + if (const auto *object{symbol.detailsIf()}) { + int corank{object->coshape().Rank()}; + if (dimension < corank - 1) { + const semantics::ShapeSpec &shapeSpec{object->coshape()[dimension]}; + if (const auto ucobound{shapeSpec.ubound().GetExplicit()}) { + if (!invariantOnly || IsScopeInvariantExpr(*ucobound)) { + return *ucobound; + } + } + } + } + return std::nullopt; +} + +Shape GetLCOBOUNDs(const Symbol &symbol, bool invariantOnly) { + Shape result; + int corank{symbol.Corank()}; + for (int dim{0}; dim < corank; ++dim) { + result.emplace_back(GetLCOBOUND(symbol, dim, invariantOnly)); + } + return result; +} + +Shape GetUCOBOUNDs(const Symbol &symbol, bool invariantOnly) { + Shape result; + int corank{symbol.Corank()}; + for (int dim{0}; dim < corank; ++dim) { + result.emplace_back(GetUCOBOUND(symbol, dim, invariantOnly)); + } + return result; +} + auto GetShapeHelper::operator()(const Symbol &symbol) const -> Result { return common::visit( common::visitors{ @@ -937,6 +989,10 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result { if (!call.arguments().empty()) { return (*this)(call.arguments()[0]); } + } else if (intrinsic->name == "lcobound" || intrinsic->name == "ucobound") { + if (call.arguments().size() == 3 && !call.arguments().at(1).has_value()) { + return Shape(1, ExtentExpr{GetCorank(call.arguments().at(0))}); + } } else if (intrinsic->name == "matmul") { if (call.arguments().size() == 2) { if (auto ashape{(*this)(call.arguments()[0])}) { @@ -1076,6 +1132,11 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result { } } } + } else if (intrinsic->name == "this_image") { + if (call.arguments().size() == 2) { + // THIS_IMAGE(coarray, no DIM, [TEAM]) + return Shape(1, ExtentExpr{GetCorank(call.arguments().at(0))}); + } } else if (intrinsic->name == "transpose") { if (call.arguments().size() >= 1) { if (auto shape{(*this)(call.arguments().at(0))}) { diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp index 6299084d729b2..6bd623a690e38 100644 --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -906,13 +906,9 @@ bool IsAssumedRank(const ActualArgument &arg) { } } -bool IsCoarray(const ActualArgument &arg) { +int GetCorank(const ActualArgument &arg) { const auto *expr{arg.UnwrapExpr()}; - return expr && IsCoarray(*expr); -} - -bool IsCoarray(const Symbol &symbol) { - return GetAssociationRoot(symbol).Corank() > 0; + return GetCorank(*expr); } bool IsProcedureDesignator(const Expr &expr) { diff --git a/flang/lib/Evaluate/variable.cpp b/flang/lib/Evaluate/variable.cpp index 707a2065ca30a..841d0f71ed0e2 100644 --- a/flang/lib/Evaluate/variable.cpp +++ b/flang/lib/Evaluate/variable.cpp @@ -465,6 +465,59 @@ template int Designator::Rank() const { u); } +// Corank() +int BaseObject::Corank() const { + return common::visit(common::visitors{ + [](SymbolRef symbol) { return symbol->Corank(); }, + [](const StaticDataObject::Pointer &) { return 0; }, + }, + u); +} + +int Component::Corank() const { + if (int corank{symbol_->Corank()}; corank > 0) { + return corank; + } + return base().Corank(); +} + +int NamedEntity::Corank() const { + return common::visit(common::visitors{ + [](const SymbolRef s) { return s->Corank(); }, + [](const Component &c) { return c.Corank(); }, + }, + u_); +} + +int ArrayRef::Corank() const { return base().Corank(); } + +int DataRef::Corank() const { + return common::visit(common::visitors{ + [](SymbolRef symbol) { return symbol->Corank(); }, + [](const auto &x) { return x.Corank(); }, + }, + u); +} + +int Substring::Corank() const { + return common::visit( + common::visitors{ + [](const DataRef &dataRef) { return dataRef.Corank(); }, + [](const StaticDataObject::Pointer &) { return 0; }, + }, + parent_); +} + +int ComplexPart::Corank() const { return complex_.Corank(); } + +template int Designator::Corank() const { + return common::visit(common::visitors{ + [](SymbolRef symbol) { return symbol->Corank(); }, + [](const auto &x) { return x.Corank(); }, + }, + u); +} + // GetBaseObject(), GetFirstSymbol(), GetLastSymbol(), &c. const Symbol &Component::GetFirstSymbol() const { return base_.value().GetFirstSymbol(); diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 79386c92d552c..340efb1c63a5e 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -766,6 +766,11 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, opts.features.Enable(Fortran::common::LanguageFeature::DefaultSave); } + // -fsave-main-program + if (args.hasArg(clang::driver::options::OPT_fsave_main_program)) { + opts.features.Enable(Fortran::common::LanguageFeature::SaveMainProgram); + } + if (args.hasArg( clang::driver::options::OPT_falternative_parameter_statement)) { opts.features.Enable(Fortran::common::LanguageFeature::OldStyleParameter); diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp index 041182bdf6178..9a555bc7cd23b 100644 --- a/flang/lib/Frontend/FrontendAction.cpp +++ b/flang/lib/Frontend/FrontendAction.cpp @@ -232,6 +232,19 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) { instance->getAllCookedSources()); return true; } + if (instance->getParsing().parseTree().has_value() && + !instance->getParsing().consumedWholeFile()) { + // Parsing failed without error. + const unsigned diagID = instance->getDiagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Error, message); + instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName(); + instance->getParsing().messages().Emit(llvm::errs(), + instance->getAllCookedSources()); + instance->getParsing().EmitMessage( + llvm::errs(), instance->getParsing().finalRestingPlace(), + "parser FAIL (final position)", "error: ", llvm::raw_ostream::RED); + return true; + } return false; } diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 603cb039d20b1..310cd650349c7 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -566,9 +566,11 @@ void DebugMeasureParseTreeAction::executeAction() { // Parse. In case of failure, report and return. ci.getParsing().Parse(llvm::outs()); - if (!ci.getParsing().messages().empty() && - (ci.getInvocation().getWarnAsErr() || - ci.getParsing().messages().AnyFatalError())) { + if ((ci.getParsing().parseTree().has_value() && + !ci.getParsing().consumedWholeFile()) || + (!ci.getParsing().messages().empty() && + (ci.getInvocation().getWarnAsErr() || + ci.getParsing().messages().AnyFatalError()))) { unsigned diagID = ci.getDiagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "Could not parse %0"); ci.getDiagnostics().Report(diagID) << getCurrentFileOrBufferName(); diff --git a/flang/lib/Optimizer/Builder/CMakeLists.txt b/flang/lib/Optimizer/Builder/CMakeLists.txt index a824d70fdb5c7..0960e858c4111 100644 --- a/flang/lib/Optimizer/Builder/CMakeLists.txt +++ b/flang/lib/Optimizer/Builder/CMakeLists.txt @@ -49,6 +49,7 @@ add_flang_library(FIRBuilder FIRDialect FIRDialectSupport FIRSupport + FortranEvaluate HLFIRDialect ${dialect_libs} ${extension_libs} diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp index 3a39c455015f9..d01becfe80093 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -1626,6 +1626,25 @@ mlir::Value fir::factory::genCPtrOrCFunptrAddr(fir::FirOpBuilder &builder, cPtr, addrFieldIndex); } +mlir::Value fir::factory::genCDevPtrAddr(fir::FirOpBuilder &builder, + mlir::Location loc, + mlir::Value cDevPtr, mlir::Type ty) { + auto recTy = mlir::cast(ty); + assert(recTy.getTypeList().size() == 1); + auto cptrFieldName = recTy.getTypeList()[0].first; + mlir::Type cptrFieldTy = recTy.getTypeList()[0].second; + auto fieldIndexType = fir::FieldType::get(ty.getContext()); + mlir::Value cptrFieldIndex = builder.create( + loc, fieldIndexType, cptrFieldName, recTy, + /*typeParams=*/mlir::ValueRange{}); + auto cptrCoord = builder.create( + loc, builder.getRefType(cptrFieldTy), cDevPtr, cptrFieldIndex); + auto [addrFieldIndex, addrFieldTy] = + genCPtrOrCFunptrFieldIndex(builder, loc, cptrFieldTy); + return builder.create(loc, builder.getRefType(addrFieldTy), + cptrCoord, addrFieldIndex); +} + mlir::Value fir::factory::genCPtrOrCFunptrValue(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value cPtr) { diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index 9a3777994a9df..cb0af392073f2 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -167,6 +167,7 @@ static constexpr IntrinsicHandler handlers[]{ &I::genCAssociatedCPtr, {{{"c_ptr_1", asAddr}, {"c_ptr_2", asAddr, handleDynamicOptional}}}, /*isElemental=*/false}, + {"c_devloc", &I::genCDevLoc, {{{"x", asBox}}}, /*isElemental=*/false}, {"c_f_pointer", &I::genCFPointer, {{{"cptr", asValue}, @@ -2867,11 +2868,14 @@ static mlir::Value getAddrFromBox(fir::FirOpBuilder &builder, static fir::ExtendedValue genCLocOrCFunLoc(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type resultType, llvm::ArrayRef args, - bool isFunc = false) { + bool isFunc = false, bool isDevLoc = false) { assert(args.size() == 1); mlir::Value res = builder.create(loc, resultType); - mlir::Value resAddr = - fir::factory::genCPtrOrCFunptrAddr(builder, loc, res, resultType); + mlir::Value resAddr; + if (isDevLoc) + resAddr = fir::factory::genCDevPtrAddr(builder, loc, res, resultType); + else + resAddr = fir::factory::genCPtrOrCFunptrAddr(builder, loc, res, resultType); assert(fir::isa_box_type(fir::getBase(args[0]).getType()) && "argument must have been lowered to box type"); mlir::Value argAddr = getAddrFromBox(builder, loc, args[0], isFunc); @@ -2928,6 +2932,14 @@ IntrinsicLibrary::genCAssociatedCPtr(mlir::Type resultType, return genCAssociated(builder, loc, resultType, args); } +// C_DEVLOC +fir::ExtendedValue +IntrinsicLibrary::genCDevLoc(mlir::Type resultType, + llvm::ArrayRef args) { + return genCLocOrCFunLoc(builder, loc, resultType, args, /*isFunc=*/false, + /*isDevLoc=*/true); +} + // C_F_POINTER void IntrinsicLibrary::genCFPointer(llvm::ArrayRef args) { assert(args.size() == 3); diff --git a/flang/lib/Parser/prescan.cpp b/flang/lib/Parser/prescan.cpp index b7462ebfb0900..703a02792a1c4 100644 --- a/flang/lib/Parser/prescan.cpp +++ b/flang/lib/Parser/prescan.cpp @@ -709,9 +709,22 @@ bool Prescanner::NextToken(TokenSequence &tokens) { QuotedCharacterLiteral(tokens, start); } else if (IsLetter(*at_) && !preventHollerith_ && parenthesisNesting_ > 0) { - // Handles FORMAT(3I9HHOLLERITH) by skipping over the first I so that - // we don't misrecognize I9HOLLERITH as an identifier in the next case. - EmitCharAndAdvance(tokens, *at_); + const char *p{at_}; + int digits{0}; + for (;; ++digits) { + ++p; + if (InFixedFormSource()) { + p = SkipWhiteSpace(p); + } + if (!IsDecimalDigit(*p)) { + break; + } + } + if (digits > 0 && (*p == 'h' || *p == 'H')) { + // Handles FORMAT(3I9HHOLLERITH) by skipping over the first I so that + // we don't misrecognize I9HOLLERITH as an identifier in the next case. + EmitCharAndAdvance(tokens, *at_); + } } preventHollerith_ = false; } else if (*at_ == '.') { diff --git a/flang/lib/Semantics/assignment.cpp b/flang/lib/Semantics/assignment.cpp index e69a73c7837ce..0b57197fb8db8 100644 --- a/flang/lib/Semantics/assignment.cpp +++ b/flang/lib/Semantics/assignment.cpp @@ -66,8 +66,13 @@ void AssignmentContext::Analyze(const parser::AssignmentStmt &stmt) { const SomeExpr &rhs{assignment->rhs}; auto lhsLoc{std::get(stmt.t).GetSource()}; const Scope &scope{context_.FindScope(lhsLoc)}; - if (auto whyNot{WhyNotDefinable(lhsLoc, scope, - DefinabilityFlags{DefinabilityFlag::VectorSubscriptIsOk}, lhs)}) { + DefinabilityFlags flags{DefinabilityFlag::VectorSubscriptIsOk}; + bool isDefinedAssignment{ + std::holds_alternative(assignment->u)}; + if (isDefinedAssignment) { + flags.set(DefinabilityFlag::AllowEventLockOrNotifyType); + } + if (auto whyNot{WhyNotDefinable(lhsLoc, scope, flags, lhs)}) { if (whyNot->IsFatal()) { if (auto *msg{Say(lhsLoc, "Left-hand side of assignment is not definable"_err_en_US)}) { @@ -79,9 +84,7 @@ void AssignmentContext::Analyze(const parser::AssignmentStmt &stmt) { } } auto rhsLoc{std::get(stmt.t).source}; - if (std::holds_alternative(assignment->u)) { - // it's a defined ASSIGNMENT(=) - } else { + if (!isDefinedAssignment) { CheckForPureContext(rhs, rhsLoc); } if (whereDepth_ > 0) { diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp index 597c280a6df8b..ba68a0f898d46 100644 --- a/flang/lib/Semantics/check-call.cpp +++ b/flang/lib/Semantics/check-call.cpp @@ -690,7 +690,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, } } if (actualLastObject && actualLastObject->IsCoarray() && - IsAllocatable(*actualLastSymbol) && dummy.intent == common::Intent::Out && + dummy.attrs.test(characteristics::DummyDataObject::Attr::Allocatable) && + dummy.intent == common::Intent::Out && !(intrinsic && evaluate::AcceptsIntentOutAllocatableCoarray( intrinsic->name))) { // C846 @@ -703,12 +704,14 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, // Problems with polymorphism are caught in the callee's definition. if (scope) { std::optional undefinableMessage; - if (dummy.intent == common::Intent::Out) { - undefinableMessage = - "Actual argument associated with INTENT(OUT) %s is not definable"_err_en_US; - } else if (dummy.intent == common::Intent::InOut) { + DefinabilityFlags flags{DefinabilityFlag::PolymorphicOkInPure}; + if (dummy.intent == common::Intent::InOut) { + flags.set(DefinabilityFlag::AllowEventLockOrNotifyType); undefinableMessage = "Actual argument associated with INTENT(IN OUT) %s is not definable"_err_en_US; + } else if (dummy.intent == common::Intent::Out) { + undefinableMessage = + "Actual argument associated with INTENT(OUT) %s is not definable"_err_en_US; } else if (context.ShouldWarn(common::LanguageFeature:: UndefinableAsynchronousOrVolatileActual)) { if (dummy.attrs.test( @@ -722,7 +725,6 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, } } if (undefinableMessage) { - DefinabilityFlags flags{DefinabilityFlag::PolymorphicOkInPure}; if (isElemental) { // 15.5.2.4(21) flags.set(DefinabilityFlag::VectorSubscriptIsOk); } @@ -1622,8 +1624,8 @@ static void CheckImage_Index(evaluate::ActualArguments &arguments, evaluate::GetShape(arguments[1]->UnwrapExpr())}) { if (const auto *coarrayArgSymbol{UnwrapWholeSymbolOrComponentDataRef( arguments[0]->UnwrapExpr())}) { - const auto coarrayArgCorank = coarrayArgSymbol->Corank(); - if (const auto subArrSize = evaluate::ToInt64(*subArrShape->front())) { + auto coarrayArgCorank{coarrayArgSymbol->Corank()}; + if (auto subArrSize{evaluate::ToInt64(*subArrShape->front())}) { if (subArrSize != coarrayArgCorank) { messages.Say(arguments[1]->sourceLocation(), "The size of 'SUB=' (%jd) for intrinsic 'image_index' must be equal to the corank of 'COARRAY=' (%d)"_err_en_US, diff --git a/flang/lib/Semantics/definable.cpp b/flang/lib/Semantics/definable.cpp index 88f9463e35c78..6d0155c24c31a 100644 --- a/flang/lib/Semantics/definable.cpp +++ b/flang/lib/Semantics/definable.cpp @@ -204,7 +204,8 @@ static std::optional WhyNotDefinableLast(parser::CharBlock at, } return std::nullopt; // pointer assignment - skip following checks } - if (IsOrContainsEventOrLockComponent(ultimate)) { + if (!flags.test(DefinabilityFlag::AllowEventLockOrNotifyType) && + IsOrContainsEventOrLockComponent(ultimate)) { return BlameSymbol(at, "'%s' is an entity with either an EVENT_TYPE or LOCK_TYPE"_en_US, original); diff --git a/flang/lib/Semantics/definable.h b/flang/lib/Semantics/definable.h index 709bbba494d10..902702dbccbf3 100644 --- a/flang/lib/Semantics/definable.h +++ b/flang/lib/Semantics/definable.h @@ -32,7 +32,8 @@ ENUM_CLASS(DefinabilityFlag, AcceptAllocatable, // treat allocatable as if it were a pointer SourcedAllocation, // ALLOCATE(a,SOURCE=) PolymorphicOkInPure, // don't check for polymorphic type in pure subprogram - DoNotNoteDefinition) // context does not imply definition + DoNotNoteDefinition, // context does not imply definition + AllowEventLockOrNotifyType) using DefinabilityFlags = common::EnumSet; diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index c2eb17c1ac8e5..3ec6f385ceb86 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -1506,9 +1506,9 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::CoindexedNamedObject &x) { if (cosubsOk && !reversed.empty()) { int numCosubscripts{static_cast(cosubscripts.size())}; const Symbol &symbol{reversed.front()}; - if (numCosubscripts != symbol.Corank()) { + if (numCosubscripts != GetCorank(symbol)) { Say("'%s' has corank %d, but coindexed reference has %d cosubscripts"_err_en_US, - symbol.name(), symbol.Corank(), numCosubscripts); + symbol.name(), GetCorank(symbol), numCosubscripts); } } for (const auto &imageSelSpec : @@ -2536,6 +2536,15 @@ static bool CheckCompatibleArgument(bool isElemental, return false; }, [&](const characteristics::DummyProcedure &dummy) { + if ((dummy.attrs.test( + characteristics::DummyProcedure::Attr::Optional) || + dummy.attrs.test( + characteristics::DummyProcedure::Attr::Pointer)) && + IsBareNullPointer(expr)) { + // NULL() is compatible with any dummy pointer + // or optional dummy procedure. + return true; + } if (!expr || !IsProcedurePointerTarget(*expr)) { return false; } diff --git a/flang/lib/Semantics/pointer-assignment.cpp b/flang/lib/Semantics/pointer-assignment.cpp index 2450ce39215ec..7f4548c7327e3 100644 --- a/flang/lib/Semantics/pointer-assignment.cpp +++ b/flang/lib/Semantics/pointer-assignment.cpp @@ -76,6 +76,7 @@ class PointerAssignmentChecker { const Procedure * = nullptr, const evaluate::SpecificIntrinsic *specific = nullptr); bool LhsOkForUnlimitedPoly() const; + std::optional CheckRanks(const TypeAndShape &rhs) const; template parser::Message *Say(A &&...); template parser::Message *Warn(FeatureOrUsageWarning, A &&...); @@ -278,10 +279,19 @@ bool PointerAssignmentChecker::Check(const evaluate::FunctionRef &f) { } else if (lhsType_) { const auto *frTypeAndShape{funcResult->GetTypeAndShape()}; CHECK(frTypeAndShape); - if (!lhsType_->IsCompatibleWith(foldingContext_.messages(), *frTypeAndShape, - "pointer", "function result", - /*omitShapeConformanceCheck=*/isBoundsRemapping_ || isAssumedRank_, - evaluate::CheckConformanceFlags::BothDeferredShape)) { + if (frTypeAndShape->type().IsUnlimitedPolymorphic() && + LhsOkForUnlimitedPoly()) { + // Special case exception to type checking (F'2023 C1017); + // still check rank compatibility. + if (auto msg{CheckRanks(*frTypeAndShape)}) { + Say(*msg); + return false; + } + } else if (!lhsType_->IsCompatibleWith(foldingContext_.messages(), + *frTypeAndShape, "pointer", "function result", + /*omitShapeConformanceCheck=*/isBoundsRemapping_ || + isAssumedRank_, + evaluate::CheckConformanceFlags::BothDeferredShape)) { return false; // IsCompatibleWith() emitted message } } @@ -324,27 +334,17 @@ bool PointerAssignmentChecker::Check(const evaluate::Designator &d) { msg = "Pointer must be VOLATILE when target is a" " VOLATILE coarray"_err_en_US; } + } else if (auto m{CheckRanks(*rhsType)}) { + msg = std::move(*m); } else if (rhsType->type().IsUnlimitedPolymorphic()) { if (!LhsOkForUnlimitedPoly()) { msg = "Pointer type must be unlimited polymorphic or non-extensible" " derived type when target is unlimited polymorphic"_err_en_US; } - } else { - if (!lhsType_->type().IsTkLenCompatibleWith(rhsType->type())) { - msg = MessageFormattedText{ - "Target type %s is not compatible with pointer type %s"_err_en_US, - rhsType->type().AsFortran(), lhsType_->type().AsFortran()}; - - } else if (!isBoundsRemapping_ && - !lhsType_->attrs().test(TypeAndShape::Attr::AssumedRank)) { - int lhsRank{lhsType_->Rank()}; - int rhsRank{rhsType->Rank()}; - if (lhsRank != rhsRank) { - msg = MessageFormattedText{ - "Pointer has rank %d but target has rank %d"_err_en_US, lhsRank, - rhsRank}; - } - } + } else if (!lhsType_->type().IsTkLenCompatibleWith(rhsType->type())) { + msg = MessageFormattedText{ + "Target type %s is not compatible with pointer type %s"_err_en_US, + rhsType->type().AsFortran(), lhsType_->type().AsFortran()}; } } if (msg) { @@ -434,6 +434,21 @@ bool PointerAssignmentChecker::LhsOkForUnlimitedPoly() const { } } +std::optional PointerAssignmentChecker::CheckRanks( + const TypeAndShape &rhs) const { + if (!isBoundsRemapping_ && + !lhsType_->attrs().test(TypeAndShape::Attr::AssumedRank)) { + int lhsRank{lhsType_->Rank()}; + int rhsRank{rhs.Rank()}; + if (lhsRank != rhsRank) { + return MessageFormattedText{ + "Pointer has rank %d but target has rank %d"_err_en_US, lhsRank, + rhsRank}; + } + } + return std::nullopt; +} + template parser::Message *PointerAssignmentChecker::Say(A &&...x) { auto *msg{foldingContext_.messages().Say(std::forward(x)...)}; diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 122c0a2ebb646..724f1b2807835 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -3162,6 +3162,10 @@ ModuleVisitor::SymbolRename ModuleVisitor::AddUse( // Convert it to a UseError with this additional location. static bool ConvertToUseError( Symbol &symbol, const SourceName &location, const Scope &module) { + if (auto *ued{symbol.detailsIf()}) { + ued->add_occurrence(location, module); + return true; + } const auto *useDetails{symbol.detailsIf()}; if (!useDetails) { if (auto *genericDetails{symbol.detailsIf()}) { @@ -3319,6 +3323,8 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName, combinedDerivedType = CreateLocalUseError(); } else { ConvertToUseError(*localSymbol, location, *useModuleScope_); + localDerivedType = nullptr; + localGeneric = nullptr; combinedDerivedType = localSymbol; } } diff --git a/flang/module/__fortran_builtins.f90 b/flang/module/__fortran_builtins.f90 index ef206dfd94310..4d134fa4b62b1 100644 --- a/flang/module/__fortran_builtins.f90 +++ b/flang/module/__fortran_builtins.f90 @@ -22,6 +22,9 @@ intrinsic :: __builtin_c_loc public :: __builtin_c_loc + intrinsic :: __builtin_c_devloc + public :: __builtin_c_devloc + intrinsic :: __builtin_c_f_pointer public :: __builtin_c_f_pointer @@ -40,15 +43,15 @@ end type type, public :: __builtin_event_type - integer(kind=int64), private :: __count + integer(kind=int64), private :: __count = -1 end type type, public :: __builtin_notify_type - integer(kind=int64), private :: __count + integer(kind=int64), private :: __count = -1 end type type, public :: __builtin_lock_type - integer(kind=int64), private :: __count + integer(kind=int64), private :: __count = -1 end type type, public :: __builtin_ieee_flag_type @@ -88,7 +91,7 @@ __builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_OTHER) type, public :: __builtin_team_type - integer(kind=int64), private :: __id + integer(kind=int64), private :: __id = -1 end type integer, parameter, public :: __builtin_atomic_int_kind = selected_int_kind(18) @@ -144,6 +147,7 @@ type :: __force_derived_type_instantiations type(__builtin_c_ptr) :: c_ptr + type(__builtin_c_devptr) :: c_devptr type(__builtin_c_funptr) :: c_funptr type(__builtin_event_type) :: event_type type(__builtin_lock_type) :: lock_type diff --git a/flang/module/__fortran_type_info.f90 b/flang/module/__fortran_type_info.f90 index 5f2273de1e3d1..b30a6bf697563 100644 --- a/flang/module/__fortran_type_info.f90 +++ b/flang/module/__fortran_type_info.f90 @@ -14,7 +14,7 @@ module __fortran_type_info use, intrinsic :: __fortran_builtins, & - only: __builtin_c_ptr, __builtin_c_funptr + only: __builtin_c_ptr, __builtin_c_devptr, __builtin_c_funptr implicit none ! Set PRIVATE by default to explicitly only export what is meant diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp index c714a85a336e7..317f0b676bd21 100644 --- a/flang/runtime/edit-input.cpp +++ b/flang/runtime/edit-input.cpp @@ -130,7 +130,7 @@ static RT_API_ATTRS bool EditBOZInput( shift = shift - 8; // misaligned octal } while (digits > 0) { - char32_t ch{*io.NextInField(remaining, edit)}; + char32_t ch{io.NextInField(remaining, edit).value_or(' ')}; int digit{0}; if (ch == ' ' || ch == '\t') { if (edit.modes.editingFlags & blankZero) { diff --git a/flang/test/Driver/fsave-main-program.f90 b/flang/test/Driver/fsave-main-program.f90 new file mode 100644 index 0000000000000..bffdfd97911e8 --- /dev/null +++ b/flang/test/Driver/fsave-main-program.f90 @@ -0,0 +1,5 @@ +! Check that the driver passes through -fsave-main-program: +! RUN: %flang -### -S -fsave-main-program %s -o - 2>&1 | FileCheck %s +! Check that the compiler accepts -fsave-main-program: +! RUN: %flang_fc1 -emit-hlfir -fsave-main-program %s -o - +! CHECK: "-fc1"{{.*}}"-fsave-main-program" diff --git a/flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90 b/flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90 index 3aa5d04246397..fe3a326702e52 100644 --- a/flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90 +++ b/flang/test/Integration/OpenMP/parallel-private-reduction-worstcase.f90 @@ -96,9 +96,12 @@ subroutine worst_case(a, b, c, d) ! CHECK: omp.region.cont13: ; preds = %omp.private.copy16 ! CHECK-NEXT: %{{.*}} = phi ptr +! CHECK-NEXT: br label %omp.par.region + +! CHECK: omp.par.region: ; preds = %omp.region.cont13 ! CHECK-NEXT: br label %omp.reduction.init -! CHECK: omp.reduction.init: ; preds = %omp.region.cont13 +! CHECK: omp.reduction.init: ; preds = %omp.par.region ! [deffered stores for results of reduction alloc regions] ! CHECK: br label %[[VAL_96:.*]] @@ -132,12 +135,9 @@ subroutine worst_case(a, b, c, d) ! CHECK: omp.region.cont21: ; preds = %omp.reduction.neutral25 ! CHECK-NEXT: %{{.*}} = phi ptr -! CHECK-NEXT: br label %omp.par.region - -! CHECK: omp.par.region: ; preds = %omp.region.cont21 ! CHECK-NEXT: br label %omp.par.region27 -! CHECK: omp.par.region27: ; preds = %omp.par.region +! CHECK: omp.par.region27: ; preds = %omp.region.cont21 ! [call SUM runtime function] ! [if (sum(a) == 1)] ! CHECK: br i1 %{{.*}}, label %omp.par.region28, label %omp.par.region29 diff --git a/flang/test/Integration/debug-local-var-2.f90 b/flang/test/Integration/debug-local-var-2.f90 index 5a675cbe1786d..fe4144a3dd46e 100644 --- a/flang/test/Integration/debug-local-var-2.f90 +++ b/flang/test/Integration/debug-local-var-2.f90 @@ -107,4 +107,4 @@ function fn2(a2, b2, c2) result (res2) end function end program -LINEONLY-NOT: DILocalVariable +! LINEONLY-NOT: DILocalVariable diff --git a/flang/test/Lower/CUDA/cuda-cdevloc.cuf b/flang/test/Lower/CUDA/cuda-cdevloc.cuf new file mode 100644 index 0000000000000..a71490207909a --- /dev/null +++ b/flang/test/Lower/CUDA/cuda-cdevloc.cuf @@ -0,0 +1,21 @@ +! RUN: bbc -emit-hlfir -fcuda %s -o - | FileCheck %s + +attributes(global) subroutine testcdevloc(a) + use __fortran_builtins, only: c_devloc => __builtin_c_devloc + integer, device :: a(10) + print*, c_devloc(a(1)) +end + +! CHECK-LABEL: func.func @_QPtestcdevloc( +! CHECK-SAME: %[[A_ARG:.*]]: !fir.ref> {cuf.data_attr = #cuf.cuda, fir.bindc_name = "a"}) attributes {cuf.proc_attr = #cuf.cuda_proc} +! CHECK: %[[A:.*]]:2 = hlfir.declare %[[A_ARG]](%{{.*}}) dummy_scope %{{.*}} {data_attr = #cuf.cuda, uniq_name = "_QFtestcdevlocEa"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[A1:.*]] = hlfir.designate %[[A]]#0 (%c1{{.*}}) : (!fir.ref>, index) -> !fir.ref +! CHECK: %[[BOX:.*]] = fir.embox %[[A1]] : (!fir.ref) -> !fir.box +! CHECK: %[[CDEVPTR:.*]] = fir.alloca !fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}> +! CHECK: %[[FIELD_CPTR:.*]] = fir.field_index cptr, !fir.type<_QM__fortran_builtinsT__builtin_c_devptr{cptr:!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>}> +! CHECK: %[[COORD_CPTR:.*]] = fir.coordinate_of %[[CDEVPTR]], %[[FIELD_CPTR]] : (!fir.ref}>>, !fir.field) -> !fir.ref> +! CHECK: %[[FIELD_ADDRESS:.*]] = fir.field_index __address, !fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}> +! CHECK: %[[COORD_ADDRESS:.*]] = fir.coordinate_of %[[COORD_CPTR]], %[[FIELD_ADDRESS]] : (!fir.ref>, !fir.field) -> !fir.ref +! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box) -> !fir.ref +! CHECK: %[[ADDRESS_A1:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.ref) -> i64 +! CHECK: fir.store %[[ADDRESS_A1]] to %[[COORD_ADDRESS]] : !fir.ref diff --git a/flang/test/Lower/OpenMP/parallel-reduction-mixed.f90 b/flang/test/Lower/OpenMP/parallel-reduction-mixed.f90 index 8e6f55abd5671..b3e25ae779561 100644 --- a/flang/test/Lower/OpenMP/parallel-reduction-mixed.f90 +++ b/flang/test/Lower/OpenMP/parallel-reduction-mixed.f90 @@ -27,11 +27,11 @@ end subroutine proc !CHECK: %[[F_priv:.*]] = alloca ptr !CHECK: %[[I_priv:.*]] = alloca i32 +!CHECK: omp.par.region: + !CHECK: omp.reduction.init: !CHECK: store ptr %{{.*}}, ptr %[[F_priv]] !CHECK: store i32 0, ptr %[[I_priv]] - -!CHECK: omp.par.region: !CHECK: br label %[[MALLOC_BB:.*]] !CHECK: [[MALLOC_BB]]: diff --git a/flang/test/Lower/fsave-main-program.f90 b/flang/test/Lower/fsave-main-program.f90 new file mode 100644 index 0000000000000..17fc1b02f5068 --- /dev/null +++ b/flang/test/Lower/fsave-main-program.f90 @@ -0,0 +1,10 @@ +! Test -fsave-main-program switch. +! RUN: %flang_fc1 -emit-hlfir -o - %s | FileCheck --check-prefix=CHECK-DEFAULT %s +! RUN: %flang_fc1 -fsave-main-program -emit-hlfir -o - %s | FileCheck --check-prefix=CHECK-SAVE %s +program test +integer :: i +call foo(i) +end + +!CHECK-DEFAULT-NOT: fir.global internal @_QFEi +!CHECK-SAVE: fir.global internal @_QFEi diff --git a/flang/test/Parser/at-process.f b/flang/test/Parser/at-process.f index 41b95044bfdc5..4f54c6b65638b 100644 --- a/flang/test/Parser/at-process.f +++ b/flang/test/Parser/at-process.f @@ -1,4 +1,4 @@ -! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s +! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s ! Test ignoring @PROCESS directive in fixed source form @@ -18,3 +18,5 @@ subroutine f() !CHECK: Character in fixed-form label field must be a digit @precoss + +!CHECK: at-process.f:14:1: error: parser FAIL (final position) diff --git a/flang/test/Parser/unparseable.f90 b/flang/test/Parser/unparseable.f90 new file mode 100644 index 0000000000000..9e7a890b67a34 --- /dev/null +++ b/flang/test/Parser/unparseable.f90 @@ -0,0 +1,5 @@ +! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s +! CHECK: unparseable.f90:5:1: error: parser FAIL (final position) +module m +end +select type (barf) diff --git a/flang/test/Preprocessing/bug129131.F b/flang/test/Preprocessing/bug129131.F new file mode 100644 index 0000000000000..5b1a914a2c9e3 --- /dev/null +++ b/flang/test/Preprocessing/bug129131.F @@ -0,0 +1,5 @@ +! RUN: %flang -fc1 -fdebug-unparse %s 2>&1 | FileCheck %s +! CHECK: PRINT *, 2_4 +#define a ,3 + print *, mod(5 a) + end diff --git a/flang/test/Semantics/assign16.f90 b/flang/test/Semantics/assign16.f90 new file mode 100644 index 0000000000000..2e65829ff990c --- /dev/null +++ b/flang/test/Semantics/assign16.f90 @@ -0,0 +1,46 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +! The RHS of a pointer assignment can be unlimited polymorphic +! if the LHS is a sequence type. +program main + type nonSeqType + integer j + end type + type seqType + sequence + integer j + end type + type(nonSeqType), target :: xNonSeq = nonSeqType(1) + type(nonSeqType), pointer :: pNonSeq + type(seqType), target :: xSeq = seqType(1), aSeq(1) + type(seqType), pointer :: pSeq, paSeq(:) + !ERROR: function result type 'CLASS(*)' is not compatible with pointer type 'nonseqtype' + pNonSeq => polyPtr(xNonSeq) + pSeq => polyPtr(xSeq) ! ok + !ERROR: Pointer has rank 1 but target has rank 0 + paSeq => polyPtr(xSeq) + !ERROR: Pointer has rank 0 but target has rank 1 + pSeq => polyPtrArr(aSeq) + contains + function polyPtr(target) + class(*), intent(in), target :: target + class(*), pointer :: polyPtr + polyPtr => target + end + function polyPtrArr(target) + class(*), intent(in), target :: target(:) + class(*), pointer :: polyPtrArr(:) + polyPtrArr => target + end + function err1(target) + class(*), intent(in), target :: target(:) + class(*), pointer :: err1 + !ERROR: Pointer has rank 0 but target has rank 1 + err1 => target + end + function err2(target) + class(*), intent(in), target :: target + class(*), pointer :: err2(:) + !ERROR: Pointer has rank 1 but target has rank 0 + err2 => target + end +end diff --git a/flang/test/Semantics/bug121718.f90 b/flang/test/Semantics/bug121718.f90 new file mode 100644 index 0000000000000..e99391f227d72 --- /dev/null +++ b/flang/test/Semantics/bug121718.f90 @@ -0,0 +1,31 @@ +! RUN: %flang_fc1 2>&1 | FileCheck %s --allow-empty +! CHECK-NOT: error +! Regression test simplified from LLVM bug 121718. +! Ensure no crash and no spurious error message. +module m1 + type foo + integer x + end type + contains + subroutine test + print *, foo(123) + end +end +module m2 + interface foo + procedure f + end interface + type foo + real x + end type + contains + complex function f(x) + complex, intent(in) :: x + f = x + end +end +program main + use m1 + use m2 + call test +end diff --git a/flang/test/Semantics/call04.f90 b/flang/test/Semantics/call04.f90 index 6877f9c9fa939..9be579fb696c0 100644 --- a/flang/test/Semantics/call04.f90 +++ b/flang/test/Semantics/call04.f90 @@ -21,10 +21,14 @@ module m subroutine s01a(x) real, allocatable, intent(out) :: x(:) end subroutine + subroutine s01c(x) + real, intent(out) :: x(:) + end subroutine subroutine s01b ! C846 - can only be caught at a call via explicit interface !ERROR: ALLOCATABLE coarray 'coarray' may not be associated with INTENT(OUT) dummy argument 'x=' !ERROR: ALLOCATABLE dummy argument 'x=' has corank 0 but actual argument has corank 1 call s01a(coarray) + call s01c(coarray) ! ok, dummy is not allocatable end subroutine subroutine s02(x) ! C846 diff --git a/flang/test/Semantics/definable01.f90 b/flang/test/Semantics/definable01.f90 index ff71b419fa971..d3b31ee38b2a3 100644 --- a/flang/test/Semantics/definable01.f90 +++ b/flang/test/Semantics/definable01.f90 @@ -109,7 +109,29 @@ pure function test6(lp) end pure subroutine test7(lp) type(list), pointer :: lp - !CHECK-NOT: error: - lp%next%next => null() + lp%next%next => null() ! ok end end module +program main + use iso_fortran_env, only: lock_type + type(lock_type) lock + interface + subroutine inlock(lock) + import lock_type + type(lock_type), intent(in) :: lock + end + subroutine outlock(lock) + import lock_type + !CHECK: error: An INTENT(OUT) dummy argument may not be, or contain, EVENT_TYPE or LOCK_TYPE + type(lock_type), intent(out) :: lock + end + subroutine inoutlock(lock) + import lock_type + type(lock_type), intent(in out) :: lock + end + end interface + call inlock(lock) ! ok + call inoutlock(lock) ! ok + !CHECK: error: Actual argument associated with INTENT(OUT) dummy argument 'lock=' is not definable + call outlock(lock) +end diff --git a/flang/test/Semantics/get_team.f90 b/flang/test/Semantics/get_team.f90 index 7e4886703d17c..a5b49a83f95f5 100644 --- a/flang/test/Semantics/get_team.f90 +++ b/flang/test/Semantics/get_team.f90 @@ -10,6 +10,8 @@ program get_team_test type(team_type) :: result_team logical wrong_result_type, non_integer + result_team = team_type() + !___ standard-conforming statement with no optional arguments present ___ result_team = get_team() diff --git a/flang/test/Semantics/io07.f90 b/flang/test/Semantics/io07.f90 index 64a32c9959287..a013849472f61 100644 --- a/flang/test/Semantics/io07.f90 +++ b/flang/test/Semantics/io07.f90 @@ -68,10 +68,10 @@ 6001 format(((I0, B0))) !ERROR: 'A' edit descriptor 'w' value must be positive - !ERROR: 'L' edit descriptor 'w' value must be positive + !WARNING: 'L' edit descriptor 'w' value should be positive 6101 format((A0), ((L0))) - !ERROR: 'L' edit descriptor 'w' value must be positive + !WARNING: 'L' edit descriptor 'w' value should be positive 6102 format((3(((L 0 0 0))))) 7001 format(17G8.1, 17G8.1e3) diff --git a/flang/test/Semantics/io08.f90 b/flang/test/Semantics/io08.f90 index f6038b471759f..517984fe3433d 100644 --- a/flang/test/Semantics/io08.f90 +++ b/flang/test/Semantics/io08.f90 @@ -192,8 +192,7 @@ !ERROR: 'A' edit descriptor 'w' value must be positive write(*,'(A0)') - !ERROR: 'L' edit descriptor 'w' value must be positive - write(*,'(L0)') + write(*,'(L0)') ! warning, not error !ERROR: Expected 'G' edit descriptor '.d' value write(*,'(G4)') diff --git a/flang/test/Semantics/lcobound.f90 b/flang/test/Semantics/lcobound.f90 index ce2f001ce2ea7..f03f2cae03ec4 100644 --- a/flang/test/Semantics/lcobound.f90 +++ b/flang/test/Semantics/lcobound.f90 @@ -11,6 +11,9 @@ program lcobound_tests logical non_integer, logical_coarray[3,*] logical, parameter :: const_non_integer = .true. integer, allocatable :: lcobounds(:) + real bounded[2:3,4:5,*] + + integer(kind=merge(kind(1),-1,all(lcobound(bounded)==[2,4,1]))) test_lcobound !___ standard-conforming statement with no optional arguments present ___ lcobounds = lcobound(scalar_coarray) @@ -50,28 +53,28 @@ program lcobound_tests !___ non-conforming statements ___ - !ERROR: DIM=0 dimension is out of range for coarray with corank 1 + !ERROR: DIM=0 dimension must be positive n = lcobound(scalar_coarray, dim=0) - !ERROR: DIM=0 dimension is out of range for coarray with corank 3 + !ERROR: DIM=0 dimension must be positive n = lcobound(coarray_corank3, dim=0) - !ERROR: DIM=-1 dimension is out of range for coarray with corank 1 + !ERROR: DIM=-1 dimension must be positive n = lcobound(scalar_coarray, dim=-1) - !ERROR: DIM=2 dimension is out of range for coarray with corank 1 + !ERROR: DIM=2 dimension is out of range for corank-1 coarray n = lcobound(array_coarray, dim=2) - !ERROR: DIM=2 dimension is out of range for coarray with corank 1 + !ERROR: DIM=2 dimension is out of range for corank-1 coarray n = lcobound(array_coarray, 2) - !ERROR: DIM=4 dimension is out of range for coarray with corank 3 + !ERROR: DIM=4 dimension is out of range for corank-3 coarray n = lcobound(coarray_corank3, dim=4) - !ERROR: DIM=4 dimension is out of range for coarray with corank 3 + !ERROR: DIM=4 dimension is out of range for corank-3 coarray n = lcobound(dim=4, coarray=coarray_corank3) - !ERROR: DIM=5 dimension is out of range for coarray with corank 3 + !ERROR: DIM=5 dimension is out of range for corank-3 coarray n = lcobound(coarray_corank3, const_out_of_range_dim) !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches scalar INTEGER(4) and rank 1 array of INTEGER(4) diff --git a/flang/test/Semantics/resolve94.f90 b/flang/test/Semantics/resolve94.f90 index e47ab4a433829..19c06ad0d1622 100644 --- a/flang/test/Semantics/resolve94.f90 +++ b/flang/test/Semantics/resolve94.f90 @@ -17,8 +17,15 @@ subroutine s1() intCoVar = 343 ! OK rVar1 = rCoarray[1,2,3] + associate (x => rCoarray) + rVar1 = x[1,2,3] ! also ok + end associate !ERROR: 'rcoarray' has corank 3, but coindexed reference has 2 cosubscripts rVar1 = rCoarray[1,2] + associate (x => rCoarray) + !ERROR: 'x' has corank 3, but coindexed reference has 2 cosubscripts + rVar1 = x[1,2] + end associate !ERROR: Must have INTEGER type, but is REAL(4) rVar1 = rCoarray[1,2,3.4] !ERROR: Must have INTEGER type, but is REAL(4) diff --git a/flang/test/Semantics/this_image01.f90 b/flang/test/Semantics/this_image01.f90 index 0e59aa3fa27c6..fdcccdaeed0e3 100644 --- a/flang/test/Semantics/this_image01.f90 +++ b/flang/test/Semantics/this_image01.f90 @@ -8,6 +8,8 @@ subroutine test type(team_type) :: coteam[*] integer :: coscalar[*], coarray(3)[*] save :: coteam, coscalar, coarray + real coarray1[*], coarray2[2,*], coarray3[2,3,*] + integer indices(3) ! correct calls, should produce no errors team = get_team() @@ -17,6 +19,10 @@ subroutine test print *, this_image(coarray, team) print *, this_image(coarray, 1) print *, this_image(coarray, 1, team) + print *, this_image(coarray(1)) + print *, this_image(coarray(1), team) + print *, this_image(coarray(1), 1) + print *, this_image(coarray(1), 1, team) print *, this_image(coscalar) print *, this_image(coscalar, team) print *, this_image(coscalar, 1) @@ -28,4 +34,14 @@ subroutine test print *, team_number() print *, team_number(team) + indices(1:1) = this_image(coarray1) ! ok + indices(1:2) = this_image(coarray2) ! ok + indices(1:3) = this_image(coarray3) ! ok + !ERROR: Dimension 1 of left-hand side has extent 2, but right-hand side has extent 1 + indices(1:2) = this_image(coarray1) + !ERROR: Dimension 1 of left-hand side has extent 3, but right-hand side has extent 2 + indices(1:3) = this_image(coarray2) + !ERROR: Dimension 1 of left-hand side has extent 1, but right-hand side has extent 3 + indices(1:1) = this_image(coarray3) + end subroutine diff --git a/flang/test/Semantics/ucobound.f90 b/flang/test/Semantics/ucobound.f90 index f9da11a03a6b0..d84c80cdd315c 100644 --- a/flang/test/Semantics/ucobound.f90 +++ b/flang/test/Semantics/ucobound.f90 @@ -11,6 +11,9 @@ program ucobound_tests logical non_integer, logical_coarray[3,*] logical, parameter :: const_non_integer = .true. integer, allocatable :: ucobounds(:) + real bounded[2:3,4:5,*] + + integer(kind=merge(kind(1),-1,ucobound(bounded,1)==3.and.ucobound(bounded,2)==5)) test_ucobound !___ standard-conforming statement with no optional arguments present ___ ucobounds = ucobound(scalar_coarray) @@ -50,28 +53,28 @@ program ucobound_tests !___ non-conforming statements ___ - !ERROR: DIM=0 dimension is out of range for coarray with corank 1 + !ERROR: DIM=0 dimension must be positive n = ucobound(scalar_coarray, dim=0) - !ERROR: DIM=0 dimension is out of range for coarray with corank 3 + !ERROR: DIM=0 dimension must be positive n = ucobound(coarray_corank3, dim=0) - !ERROR: DIM=-1 dimension is out of range for coarray with corank 1 + !ERROR: DIM=-1 dimension must be positive n = ucobound(scalar_coarray, dim=-1) - !ERROR: DIM=2 dimension is out of range for coarray with corank 1 + !ERROR: DIM=2 dimension is out of range for corank-1 coarray n = ucobound(array_coarray, dim=2) - !ERROR: DIM=2 dimension is out of range for coarray with corank 1 + !ERROR: DIM=2 dimension is out of range for corank-1 coarray n = ucobound(array_coarray, 2) - !ERROR: DIM=4 dimension is out of range for coarray with corank 3 + !ERROR: DIM=4 dimension is out of range for corank-3 coarray n = ucobound(coarray_corank3, dim=4) - !ERROR: DIM=4 dimension is out of range for coarray with corank 3 + !ERROR: DIM=4 dimension is out of range for corank-3 coarray n = ucobound(dim=4, coarray=coarray_corank3) - !ERROR: DIM=5 dimension is out of range for coarray with corank 3 + !ERROR: DIM=5 dimension is out of range for corank-3 coarray n = ucobound(coarray_corank3, const_out_of_range_dim) !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches scalar INTEGER(4) and rank 1 array of INTEGER(4) diff --git a/flang/unittests/Runtime/LogicalFormatTest.cpp b/flang/unittests/Runtime/LogicalFormatTest.cpp index c4fbfc81f06a4..26c9374be1338 100644 --- a/flang/unittests/Runtime/LogicalFormatTest.cpp +++ b/flang/unittests/Runtime/LogicalFormatTest.cpp @@ -23,7 +23,7 @@ TEST(IOApiTests, LogicalFormatTest) { char buffer[bufferSize]; // Create format for all types and values to be written - const char *format{"(L,L3,I3,L2,L2,I3,L2,A3,L2,L,F4.1,L2)"}; + const char *format{"(L0,L3,I3,L2,L2,I3,L2,A3,L2,L,F4.1,L2)"}; auto cookie{IONAME(BeginInternalFormattedOutput)( buffer, bufferSize, format, std::strlen(format))}; diff --git a/libc/cmake/modules/LLVMLibCHeaderRules.cmake b/libc/cmake/modules/LLVMLibCHeaderRules.cmake index a95c13389012f..288e4dade0b47 100644 --- a/libc/cmake/modules/LLVMLibCHeaderRules.cmake +++ b/libc/cmake/modules/LLVMLibCHeaderRules.cmake @@ -113,6 +113,7 @@ function(add_gen_header target_name) COMMAND ${Python3_EXECUTABLE} "${LIBC_SOURCE_DIR}/utils/hdrgen/main.py" --output ${out_file} --depfile ${dep_file} + --write-if-changed ${entry_points} ${yaml_file} DEPENDS ${yaml_file} ${fq_data_files} diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt index 5156b58ee11af..1674de1420152 100644 --- a/libc/hdr/types/CMakeLists.txt +++ b/libc/hdr/types/CMakeLists.txt @@ -85,6 +85,14 @@ add_proxy_header_library( libc.include.llvm-libc-types.struct_timespec ) +add_proxy_header_library( + struct_tm + HDRS + struct_tm.h + FULL_BUILD_DEPENDS + libc.include.llvm-libc-types.struct_tm +) + add_proxy_header_library( size_t HDRS diff --git a/libc/hdr/types/struct_tm.h b/libc/hdr/types/struct_tm.h new file mode 100644 index 0000000000000..96c23e2ce054a --- /dev/null +++ b/libc/hdr/types/struct_tm.h @@ -0,0 +1,21 @@ +//===-- Proxy for struct tm ----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_LIBC_HDR_TYPES_STRUCT_TM_H +#define LLVM_LIBC_HDR_TYPES_STRUCT_TM_H + +#ifdef LIBC_FULL_BUILD + +#include "include/llvm-libc-types/struct_tm.h" + +#else + +#include + +#endif // LIBC_FULL_BUILD + +#endif // LLVM_LIBC_HDR_TYPES_STRUCT_TM_H diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt index 4e90aad9a45b4..5090dc218cda4 100644 --- a/libc/src/__support/CMakeLists.txt +++ b/libc/src/__support/CMakeLists.txt @@ -267,7 +267,9 @@ add_header_library( HDRS fixedvector.h DEPENDS + .libc_assert libc.src.__support.CPP.array + libc.src.string.memory_utils.inline_memset ) add_header_library( diff --git a/libc/src/__support/File/file.cpp b/libc/src/__support/File/file.cpp index 972249fef96bc..528542cccf324 100644 --- a/libc/src/__support/File/file.cpp +++ b/libc/src/__support/File/file.cpp @@ -42,7 +42,7 @@ FileIOResult File::write_unlocked_nbf(const uint8_t *data, size_t len) { if (pos > 0) { // If the buffer is not empty // Flush the buffer const size_t write_size = pos; - auto write_result = platform_write(this, buf, write_size); + FileIOResult write_result = platform_write(this, buf, write_size); pos = 0; // Buffer is now empty so reset pos to the beginning. // If less bytes were written than expected, then an error occurred. if (write_result < write_size) { @@ -52,7 +52,7 @@ FileIOResult File::write_unlocked_nbf(const uint8_t *data, size_t len) { } } - auto write_result = platform_write(this, data, len); + FileIOResult write_result = platform_write(this, data, len); if (write_result < len) err = true; return write_result; @@ -99,7 +99,7 @@ FileIOResult File::write_unlocked_fbf(const uint8_t *data, size_t len) { // is full. const size_t write_size = pos; - auto buf_result = platform_write(this, buf, write_size); + FileIOResult buf_result = platform_write(this, buf, write_size); size_t bytes_written = buf_result.value; pos = 0; // Buffer is now empty so reset pos to the beginning. @@ -121,7 +121,8 @@ FileIOResult File::write_unlocked_fbf(const uint8_t *data, size_t len) { pos = remainder.size(); } else { - auto result = platform_write(this, remainder.data(), remainder.size()); + FileIOResult result = + platform_write(this, remainder.data(), remainder.size()); size_t bytes_written = buf_result.value; // If less bytes were written than expected, then an error occurred. Return @@ -190,6 +191,17 @@ FileIOResult File::read_unlocked(void *data, size_t len) { prev_op = FileOp::READ; + if (bufmode == _IONBF) { // unbuffered. + return read_unlocked_nbf(static_cast(data), len); + } else if (bufmode == _IOFBF) { // fully buffered + return read_unlocked_fbf(static_cast(data), len); + } else /*if (bufmode == _IOLBF) */ { // line buffered + // There is no line buffered mode for read. Use fully buffered instead. + return read_unlocked_fbf(static_cast(data), len); + } +} + +size_t File::copy_data_from_buf(uint8_t *data, size_t len) { cpp::span bufref(static_cast(buf), bufsize); cpp::span dataref(static_cast(data), len); @@ -209,32 +221,42 @@ FileIOResult File::read_unlocked(void *data, size_t len) { for (size_t i = 0; i < available_data; ++i) dataref[i] = bufref[i + pos]; read_limit = pos = 0; // Reset the pointers. + + return available_data; +} + +FileIOResult File::read_unlocked_fbf(uint8_t *data, size_t len) { + // Read data from the buffer first. + size_t available_data = copy_data_from_buf(data, len); + if (available_data == len) + return available_data; + // Update the dataref to reflect that fact that we have already // copied |available_data| into |data|. - dataref = cpp::span(dataref.data() + available_data, - dataref.size() - available_data); - size_t to_fetch = len - available_data; + cpp::span dataref(static_cast(data) + available_data, + to_fetch); + if (to_fetch > bufsize) { - auto result = platform_read(this, dataref.data(), to_fetch); + FileIOResult result = platform_read(this, dataref.data(), to_fetch); size_t fetched_size = result.value; if (result.has_error() || fetched_size < to_fetch) { if (!result.has_error()) eof = true; else err = true; - return {available_data + fetched_size, result.has_error()}; + return {available_data + fetched_size, result.error}; } return len; } // Fetch and buffer another buffer worth of data. - auto result = platform_read(this, buf, bufsize); + FileIOResult result = platform_read(this, buf, bufsize); size_t fetched_size = result.value; read_limit += fetched_size; size_t transfer_size = fetched_size >= to_fetch ? to_fetch : fetched_size; for (size_t i = 0; i < transfer_size; ++i) - dataref[i] = bufref[i]; + dataref[i] = buf[i]; pos += transfer_size; if (result.has_error() || fetched_size < to_fetch) { if (!result.has_error()) @@ -245,6 +267,26 @@ FileIOResult File::read_unlocked(void *data, size_t len) { return {transfer_size + available_data, result.error}; } +FileIOResult File::read_unlocked_nbf(uint8_t *data, size_t len) { + // Check whether there is a character in the ungetc buffer. + size_t available_data = copy_data_from_buf(data, len); + if (available_data == len) + return available_data; + + // Directly copy the data into |data|. + cpp::span dataref(static_cast(data) + available_data, + len - available_data); + FileIOResult result = platform_read(this, dataref.data(), dataref.size()); + + if (result.has_error() || result < dataref.size()) { + if (!result.has_error()) + eof = true; + else + err = true; + } + return {result + available_data, result.error}; +} + int File::ungetc_unlocked(int c) { // There is no meaning to unget if: // 1. You are trying to push back EOF. @@ -287,7 +329,7 @@ ErrorOr File::seek(off_t offset, int whence) { FileLock lock(this); if (prev_op == FileOp::WRITE && pos > 0) { - auto buf_result = platform_write(this, buf, pos); + FileIOResult buf_result = platform_write(this, buf, pos); if (buf_result.has_error() || buf_result.value < pos) { err = true; return Error(buf_result.error); @@ -325,7 +367,7 @@ ErrorOr File::tell() { int File::flush_unlocked() { if (prev_op == FileOp::WRITE && pos > 0) { - auto buf_result = platform_write(this, buf, pos); + FileIOResult buf_result = platform_write(this, buf, pos); if (buf_result.has_error() || buf_result.value < pos) { err = true; return buf_result.error; diff --git a/libc/src/__support/File/file.h b/libc/src/__support/File/file.h index 42e1d11b4ab1a..5c97a9c6419f0 100644 --- a/libc/src/__support/File/file.h +++ b/libc/src/__support/File/file.h @@ -280,6 +280,10 @@ class File { FileIOResult write_unlocked_fbf(const uint8_t *data, size_t len); FileIOResult write_unlocked_nbf(const uint8_t *data, size_t len); + FileIOResult read_unlocked_fbf(uint8_t *data, size_t len); + FileIOResult read_unlocked_nbf(uint8_t *data, size_t len); + size_t copy_data_from_buf(uint8_t *data, size_t len); + constexpr void adjust_buf() { if (read_allowed() && (buf == nullptr || bufsize == 0)) { // We should allow atleast one ungetc operation. diff --git a/libc/src/__support/fixedvector.h b/libc/src/__support/fixedvector.h index 7ac0c230f9c53..34601f86dc017 100644 --- a/libc/src/__support/fixedvector.h +++ b/libc/src/__support/fixedvector.h @@ -10,9 +10,10 @@ #define LLVM_LIBC_SRC___SUPPORT_FIXEDVECTOR_H #include "src/__support/CPP/array.h" - #include "src/__support/CPP/iterator.h" +#include "src/__support/libc_assert.h" #include "src/__support/macros/config.h" +#include "src/string/memory_utils/inline_memset.h" namespace LIBC_NAMESPACE_DECL { @@ -23,27 +24,32 @@ template class FixedVector { size_t item_count = 0; public: - constexpr FixedVector() = default; + LIBC_INLINE constexpr FixedVector() = default; using iterator = typename cpp::array::iterator; - constexpr FixedVector(iterator begin, iterator end) : store{}, item_count{} { + LIBC_INLINE constexpr FixedVector(iterator begin, iterator end) + : store{}, item_count{} { + LIBC_ASSERT(begin + CAPACITY >= end); for (; begin != end; ++begin) push_back(*begin); } using const_iterator = typename cpp::array::const_iterator; - constexpr FixedVector(const_iterator begin, const_iterator end) + LIBC_INLINE constexpr FixedVector(const_iterator begin, const_iterator end) : store{}, item_count{} { + LIBC_ASSERT(begin + CAPACITY >= end); for (; begin != end; ++begin) push_back(*begin); } - constexpr FixedVector(size_t count, const T &value) : store{}, item_count{} { + LIBC_INLINE constexpr FixedVector(size_t count, const T &value) + : store{}, item_count{} { + LIBC_ASSERT(count <= CAPACITY); for (size_t i = 0; i < count; ++i) push_back(value); } - constexpr bool push_back(const T &obj) { + LIBC_INLINE constexpr bool push_back(const T &obj) { if (item_count == CAPACITY) return false; store[item_count] = obj; @@ -51,27 +57,43 @@ template class FixedVector { return true; } - constexpr const T &back() const { return store[item_count - 1]; } + LIBC_INLINE constexpr const T &back() const { + LIBC_ASSERT(!empty()); + return store[item_count - 1]; + } - constexpr T &back() { return store[item_count - 1]; } + LIBC_INLINE constexpr T &back() { + LIBC_ASSERT(!empty()); + return store[item_count - 1]; + } - constexpr bool pop_back() { + LIBC_INLINE constexpr bool pop_back() { if (item_count == 0) return false; + inline_memset(&store[item_count - 1], 0, sizeof(T)); --item_count; return true; } - constexpr T &operator[](size_t idx) { return store[idx]; } + LIBC_INLINE constexpr T &operator[](size_t idx) { + LIBC_ASSERT(idx < item_count); + return store[idx]; + } - constexpr const T &operator[](size_t idx) const { return store[idx]; } + LIBC_INLINE constexpr const T &operator[](size_t idx) const { + LIBC_ASSERT(idx < item_count); + return store[idx]; + } - constexpr bool empty() const { return item_count == 0; } + LIBC_INLINE constexpr bool empty() const { return item_count == 0; } - constexpr size_t size() const { return item_count; } + LIBC_INLINE constexpr size_t size() const { return item_count; } // Empties the store for all practical purposes. - constexpr void reset() { item_count = 0; } + LIBC_INLINE constexpr void reset() { + inline_memset(store.data(), 0, sizeof(T) * item_count); + item_count = 0; + } // This static method does not free up the resources held by |store|, // say by calling `free` or something similar. It just does the equivalent @@ -81,7 +103,9 @@ template class FixedVector { // dynamically allocated storate. So, the `destroy` method like this // matches the `destroy` API of those other data structures so that users // can easily swap one data structure for the other. - static void destroy(FixedVector *store) { store->reset(); } + LIBC_INLINE static void destroy(FixedVector *store) { + store->reset(); + } using reverse_iterator = typename cpp::array::reverse_iterator; LIBC_INLINE constexpr reverse_iterator rbegin() { diff --git a/libc/src/__support/threads/thread.cpp b/libc/src/__support/threads/thread.cpp index dad4f75f092ed..6f6b75be5766d 100644 --- a/libc/src/__support/threads/thread.cpp +++ b/libc/src/__support/threads/thread.cpp @@ -117,7 +117,9 @@ class ThreadAtExitCallbackMgr { int add_callback(AtExitCallback *callback, void *obj) { cpp::lock_guard lock(mtx); - return callback_list.push_back({callback, obj}); + if (callback_list.push_back({callback, obj})) + return 0; + return -1; } void call() { diff --git a/libc/src/pthread/pthread_condattr_init.cpp b/libc/src/pthread/pthread_condattr_init.cpp index 12005b8a9d30f..b360804bb7bba 100644 --- a/libc/src/pthread/pthread_condattr_init.cpp +++ b/libc/src/pthread/pthread_condattr_init.cpp @@ -11,8 +11,8 @@ #include "src/__support/common.h" #include "src/__support/macros/config.h" -#include // pthread_condattr_t, PTHREAD_PROCESS_PRIVATE -#include // CLOCK_REALTIME +#include "hdr/time_macros.h" // CLOCK_REALTIME +#include // pthread_condattr_t, PTHREAD_PROCESS_PRIVATE namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/pthread/pthread_condattr_setclock.cpp b/libc/src/pthread/pthread_condattr_setclock.cpp index 37fbd6b27143d..5e825d5ecea69 100644 --- a/libc/src/pthread/pthread_condattr_setclock.cpp +++ b/libc/src/pthread/pthread_condattr_setclock.cpp @@ -12,9 +12,9 @@ #include "src/__support/macros/config.h" #include "src/errno/libc_errno.h" -#include // pthread_condattr_t -#include // clockid_t -#include // CLOCK_MONOTONIC, CLOCK_REALTIME +#include "hdr/time_macros.h" // CLOCK_MONOTONIC, CLOCK_REALTIME +#include // pthread_condattr_t +#include // clockid_t namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/stdlib/exit_handler.h b/libc/src/stdlib/exit_handler.h index 9720c5473940e..e9d163dfe9024 100644 --- a/libc/src/stdlib/exit_handler.h +++ b/libc/src/stdlib/exit_handler.h @@ -48,7 +48,7 @@ LIBC_INLINE void stdc_at_exit_func(void *payload) { LIBC_INLINE void call_exit_callbacks(ExitCallbackList &callbacks) { handler_list_mtx.lock(); while (!callbacks.empty()) { - AtExitUnit &unit = callbacks.back(); + AtExitUnit unit = callbacks.back(); callbacks.pop_back(); handler_list_mtx.unlock(); unit.callback(unit.payload); diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt index ae835dcc74274..ef9bfe57bc4ec 100644 --- a/libc/src/time/CMakeLists.txt +++ b/libc/src/time/CMakeLists.txt @@ -2,6 +2,17 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) endif() +add_header_library( + time_constants + HDRS + time_constants.h + DEPENDS + libc.include.time + libc.src.__support.CPP.array + libc.src.__support.CPP.string_view + libc.hdr.types.time_t +) + add_object_library( time_utils SRCS @@ -12,6 +23,10 @@ add_object_library( libc.include.time libc.src.__support.CPP.limits libc.src.errno.errno + .time_constants + libc.hdr.types.time_t + libc.hdr.types.size_t + libc.hdr.types.struct_tm ) add_entrypoint_object( @@ -22,7 +37,9 @@ add_entrypoint_object( asctime.h DEPENDS .time_utils + .time_constants libc.include.time + libc.hdr.types.struct_tm ) add_entrypoint_object( @@ -33,7 +50,9 @@ add_entrypoint_object( asctime_r.h DEPENDS .time_utils + .time_constants libc.include.time + libc.hdr.types.struct_tm ) add_entrypoint_object( @@ -44,6 +63,7 @@ add_entrypoint_object( ctime.h DEPENDS .time_utils + .time_constants libc.hdr.types.time_t libc.include.time ) @@ -56,6 +76,7 @@ add_entrypoint_object( ctime_r.h DEPENDS .time_utils + .time_constants libc.hdr.types.time_t libc.include.time ) @@ -68,6 +89,7 @@ add_entrypoint_object( difftime.h DEPENDS libc.include.time + libc.hdr.types.time_t ) add_entrypoint_object( @@ -79,6 +101,8 @@ add_entrypoint_object( DEPENDS .time_utils libc.include.time + libc.hdr.types.time_t + libc.hdr.types.struct_tm ) add_entrypoint_object( @@ -90,6 +114,8 @@ add_entrypoint_object( DEPENDS .time_utils libc.include.time + libc.hdr.types.time_t + libc.hdr.types.struct_tm ) add_entrypoint_object( @@ -100,8 +126,11 @@ add_entrypoint_object( mktime.h DEPENDS .time_utils + .time_constants libc.include.time libc.src.errno.errno + libc.hdr.types.time_t + libc.hdr.types.struct_tm ) add_entrypoint_object( @@ -115,6 +144,7 @@ add_entrypoint_object( libc.hdr.types.time_t libc.src.__support.time.clock_gettime libc.src.errno.errno + libc.hdr.types.struct_tm ) add_entrypoint_object( diff --git a/libc/src/time/asctime.cpp b/libc/src/time/asctime.cpp index d6fbe7316ced0..2b00c4136f906 100644 --- a/libc/src/time/asctime.cpp +++ b/libc/src/time/asctime.cpp @@ -9,15 +9,15 @@ #include "src/time/asctime.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" +#include "src/time/time_constants.h" #include "src/time/time_utils.h" namespace LIBC_NAMESPACE_DECL { -using LIBC_NAMESPACE::time_utils::TimeConstants; - LLVM_LIBC_FUNCTION(char *, asctime, (const struct tm *timeptr)) { - static char buffer[TimeConstants::ASCTIME_BUFFER_SIZE]; - return time_utils::asctime(timeptr, buffer, TimeConstants::ASCTIME_MAX_BYTES); + static char buffer[time_constants::ASCTIME_BUFFER_SIZE]; + return time_utils::asctime(timeptr, buffer, + time_constants::ASCTIME_MAX_BYTES); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/asctime.h b/libc/src/time/asctime.h index 623e6dff60c33..37325e75b829d 100644 --- a/libc/src/time/asctime.h +++ b/libc/src/time/asctime.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_SRC_TIME_ASCTIME_H #define LLVM_LIBC_SRC_TIME_ASCTIME_H +#include "hdr/types/struct_tm.h" #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/time/asctime_r.cpp b/libc/src/time/asctime_r.cpp index caa22f1cd7783..bf53bfdf2f8c2 100644 --- a/libc/src/time/asctime_r.cpp +++ b/libc/src/time/asctime_r.cpp @@ -9,15 +9,15 @@ #include "src/time/asctime_r.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" +#include "src/time/time_constants.h" #include "src/time/time_utils.h" namespace LIBC_NAMESPACE_DECL { -using LIBC_NAMESPACE::time_utils::TimeConstants; - LLVM_LIBC_FUNCTION(char *, asctime_r, (const struct tm *timeptr, char *buffer)) { - return time_utils::asctime(timeptr, buffer, TimeConstants::ASCTIME_MAX_BYTES); + return time_utils::asctime(timeptr, buffer, + time_constants::ASCTIME_MAX_BYTES); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/asctime_r.h b/libc/src/time/asctime_r.h index 328b7dff19c2e..65a6b84ca38f6 100644 --- a/libc/src/time/asctime_r.h +++ b/libc/src/time/asctime_r.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_SRC_TIME_ASCTIME_R_H #define LLVM_LIBC_SRC_TIME_ASCTIME_R_H +#include "hdr/types/struct_tm.h" #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/time/ctime.cpp b/libc/src/time/ctime.cpp index 8adae9be73809..ac0ffe5b32ae5 100644 --- a/libc/src/time/ctime.cpp +++ b/libc/src/time/ctime.cpp @@ -6,23 +6,22 @@ // //===----------------------------------------------------------------------===// -#include "ctime.h" +#include "src/time/ctime.h" #include "src/__support/CPP/limits.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" -#include "time_utils.h" +#include "src/time/time_constants.h" +#include "src/time/time_utils.h" namespace LIBC_NAMESPACE_DECL { -using LIBC_NAMESPACE::time_utils::TimeConstants; - LLVM_LIBC_FUNCTION(char *, ctime, (const time_t *t_ptr)) { if (t_ptr == nullptr || *t_ptr > cpp::numeric_limits::max()) { return nullptr; } - static char buffer[TimeConstants::ASCTIME_BUFFER_SIZE]; + static char buffer[time_constants::ASCTIME_BUFFER_SIZE]; return time_utils::asctime(time_utils::localtime(t_ptr), buffer, - TimeConstants::ASCTIME_MAX_BYTES); + time_constants::ASCTIME_MAX_BYTES); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/ctime_r.cpp b/libc/src/time/ctime_r.cpp index 63d93c4085f38..7224f7742f139 100644 --- a/libc/src/time/ctime_r.cpp +++ b/libc/src/time/ctime_r.cpp @@ -6,16 +6,15 @@ // //===----------------------------------------------------------------------===// -#include "ctime_r.h" +#include "src/time/ctime_r.h" #include "src/__support/CPP/limits.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" -#include "time_utils.h" +#include "src/time/time_constants.h" +#include "src/time/time_utils.h" namespace LIBC_NAMESPACE_DECL { -using LIBC_NAMESPACE::time_utils::TimeConstants; - LLVM_LIBC_FUNCTION(char *, ctime_r, (const time_t *t_ptr, char *buffer)) { if (t_ptr == nullptr || buffer == nullptr || *t_ptr > cpp::numeric_limits::max()) { @@ -23,7 +22,7 @@ LLVM_LIBC_FUNCTION(char *, ctime_r, (const time_t *t_ptr, char *buffer)) { } return time_utils::asctime(time_utils::localtime(t_ptr), buffer, - TimeConstants::ASCTIME_MAX_BYTES); + time_constants::ASCTIME_MAX_BYTES); } } // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/time/difftime.h b/libc/src/time/difftime.h index d5cd593cc5335..12de5678864c7 100644 --- a/libc/src/time/difftime.h +++ b/libc/src/time/difftime.h @@ -9,8 +9,8 @@ #ifndef LLVM_LIBC_SRC_TIME_DIFFTIME_H #define LLVM_LIBC_SRC_TIME_DIFFTIME_H +#include "hdr/types/time_t.h" #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/time/gmtime.h b/libc/src/time/gmtime.h index 3de3cebbfde2c..ac7f1be7bbce8 100644 --- a/libc/src/time/gmtime.h +++ b/libc/src/time/gmtime.h @@ -9,8 +9,9 @@ #ifndef LLVM_LIBC_SRC_TIME_GMTIME_H #define LLVM_LIBC_SRC_TIME_GMTIME_H +#include "hdr/types/struct_tm.h" +#include "hdr/types/time_t.h" #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/time/gmtime_r.h b/libc/src/time/gmtime_r.h index b4f387ef443bc..4c88b22faf4cf 100644 --- a/libc/src/time/gmtime_r.h +++ b/libc/src/time/gmtime_r.h @@ -9,8 +9,9 @@ #ifndef LLVM_LIBC_SRC_TIME_GMTIME_R_H #define LLVM_LIBC_SRC_TIME_GMTIME_R_H +#include "hdr/types/struct_tm.h" +#include "hdr/types/time_t.h" #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/time/mktime.cpp b/libc/src/time/mktime.cpp index b5d1da5fa8fba..3874cad02facb 100644 --- a/libc/src/time/mktime.cpp +++ b/libc/src/time/mktime.cpp @@ -9,15 +9,11 @@ #include "src/time/mktime.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" +#include "src/time/time_constants.h" #include "src/time/time_utils.h" namespace LIBC_NAMESPACE_DECL { -using LIBC_NAMESPACE::time_utils::TimeConstants; - -static constexpr int NON_LEAP_YEAR_DAYS_IN_MONTH[] = {31, 28, 31, 30, 31, 30, - 31, 31, 30, 31, 30, 31}; - // Returns number of years from (1, year). static constexpr int64_t get_num_of_leap_years_before(int64_t year) { return (year / 4) - (year / 100) + (year / 400); @@ -31,12 +27,12 @@ static constexpr bool is_leap_year(const int64_t year) { LLVM_LIBC_FUNCTION(time_t, mktime, (struct tm * tm_out)) { // Unlike most C Library functions, mktime doesn't just die on bad input. // TODO(rtenneti); Handle leap seconds. - int64_t tm_year_from_base = tm_out->tm_year + TimeConstants::TIME_YEAR_BASE; + int64_t tm_year_from_base = tm_out->tm_year + time_constants::TIME_YEAR_BASE; // 32-bit end-of-the-world is 03:14:07 UTC on 19 January 2038. if (sizeof(time_t) == 4 && - tm_year_from_base >= TimeConstants::END_OF32_BIT_EPOCH_YEAR) { - if (tm_year_from_base > TimeConstants::END_OF32_BIT_EPOCH_YEAR) + tm_year_from_base >= time_constants::END_OF32_BIT_EPOCH_YEAR) { + if (tm_year_from_base > time_constants::END_OF32_BIT_EPOCH_YEAR) return time_utils::out_of_range(); if (tm_out->tm_mon > 0) return time_utils::out_of_range(); @@ -64,7 +60,7 @@ LLVM_LIBC_FUNCTION(time_t, mktime, (struct tm * tm_out)) { // Calculate number of months and years from tm_mon. int64_t month = tm_out->tm_mon; - if (month < 0 || month >= TimeConstants::MONTHS_PER_YEAR - 1) { + if (month < 0 || month >= time_constants::MONTHS_PER_YEAR - 1) { int64_t years = month / 12; month %= 12; if (month < 0) { @@ -78,23 +74,23 @@ LLVM_LIBC_FUNCTION(time_t, mktime, (struct tm * tm_out)) { // Calculate total number of days based on the month and the day (tm_mday). int64_t total_days = tm_out->tm_mday - 1; for (int64_t i = 0; i < month; ++i) - total_days += NON_LEAP_YEAR_DAYS_IN_MONTH[i]; + total_days += time_constants::NON_LEAP_YEAR_DAYS_IN_MONTH[i]; // Add one day if it is a leap year and the month is after February. if (tm_year_is_leap && month > 1) total_days++; // Calculate total numbers of days based on the year. - total_days += (tm_year_from_base - TimeConstants::EPOCH_YEAR) * - TimeConstants::DAYS_PER_NON_LEAP_YEAR; - if (tm_year_from_base >= TimeConstants::EPOCH_YEAR) { + total_days += (tm_year_from_base - time_constants::EPOCH_YEAR) * + time_constants::DAYS_PER_NON_LEAP_YEAR; + if (tm_year_from_base >= time_constants::EPOCH_YEAR) { total_days += get_num_of_leap_years_before(tm_year_from_base - 1) - - get_num_of_leap_years_before(TimeConstants::EPOCH_YEAR); + get_num_of_leap_years_before(time_constants::EPOCH_YEAR); } else if (tm_year_from_base >= 1) { - total_days -= get_num_of_leap_years_before(TimeConstants::EPOCH_YEAR) - + total_days -= get_num_of_leap_years_before(time_constants::EPOCH_YEAR) - get_num_of_leap_years_before(tm_year_from_base - 1); } else { // Calculate number of leap years until 0th year. - total_days -= get_num_of_leap_years_before(TimeConstants::EPOCH_YEAR) - + total_days -= get_num_of_leap_years_before(time_constants::EPOCH_YEAR) - get_num_of_leap_years_before(0); if (tm_year_from_base <= 0) { total_days -= 1; // Subtract 1 for 0th year. @@ -109,9 +105,9 @@ LLVM_LIBC_FUNCTION(time_t, mktime, (struct tm * tm_out)) { // TODO: https://github.com/llvm/llvm-project/issues/121962 // Need to handle timezone and update of tm_isdst. int64_t seconds = tm_out->tm_sec + - tm_out->tm_min * TimeConstants::SECONDS_PER_MIN + - tm_out->tm_hour * TimeConstants::SECONDS_PER_HOUR + - total_days * TimeConstants::SECONDS_PER_DAY; + tm_out->tm_min * time_constants::SECONDS_PER_MIN + + tm_out->tm_hour * time_constants::SECONDS_PER_HOUR + + total_days * time_constants::SECONDS_PER_DAY; // Update the tm structure's year, month, day, etc. from seconds. if (time_utils::update_from_seconds(seconds, tm_out) < 0) diff --git a/libc/src/time/mktime.h b/libc/src/time/mktime.h index 2b4c67996555e..985c6293f9d51 100644 --- a/libc/src/time/mktime.h +++ b/libc/src/time/mktime.h @@ -9,8 +9,9 @@ #ifndef LLVM_LIBC_SRC_TIME_MKTIME_H #define LLVM_LIBC_SRC_TIME_MKTIME_H +#include "hdr/types/struct_tm.h" +#include "hdr/types/time_t.h" #include "src/__support/macros/config.h" -#include namespace LIBC_NAMESPACE_DECL { diff --git a/libc/src/time/time.cpp b/libc/src/time/time.cpp index 4a0b614a68ef5..860909af7488c 100644 --- a/libc/src/time/time.cpp +++ b/libc/src/time/time.cpp @@ -6,12 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "src/time/time_func.h" + #include "hdr/time_macros.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" #include "src/__support/time/clock_gettime.h" #include "src/errno/libc_errno.h" -#include "src/time/time_func.h" namespace LIBC_NAMESPACE_DECL { // avoid inconsitent clang-format behavior diff --git a/libc/src/time/time_constants.h b/libc/src/time/time_constants.h new file mode 100644 index 0000000000000..3e25f741745ab --- /dev/null +++ b/libc/src/time/time_constants.h @@ -0,0 +1,100 @@ +//===-- Collection of constants for time functions --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_TIME_TIME_CONSTANTS_H +#define LLVM_LIBC_SRC_TIME_TIME_CONSTANTS_H + +#include "hdr/types/time_t.h" +#include "src/__support/CPP/array.h" +#include "src/__support/CPP/string_view.h" +#include + +namespace LIBC_NAMESPACE_DECL { +namespace time_constants { + +enum Month : int { + JANUARY, + FEBRUARY, + MARCH, + APRIL, + MAY, + JUNE, + JULY, + AUGUST, + SEPTEMBER, + OCTOBER, + NOVEMBER, + DECEMBER +}; + +constexpr int SECONDS_PER_MIN = 60; +constexpr int MINUTES_PER_HOUR = 60; +constexpr int HOURS_PER_DAY = 24; +constexpr int DAYS_PER_WEEK = 7; +constexpr int MONTHS_PER_YEAR = 12; +constexpr int DAYS_PER_NON_LEAP_YEAR = 365; +constexpr int DAYS_PER_LEAP_YEAR = 366; + +constexpr int SECONDS_PER_HOUR = SECONDS_PER_MIN * MINUTES_PER_HOUR; +constexpr int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY; +constexpr int NUMBER_OF_SECONDS_IN_LEAP_YEAR = + DAYS_PER_LEAP_YEAR * SECONDS_PER_DAY; + +constexpr int TIME_YEAR_BASE = 1900; +constexpr int EPOCH_YEAR = 1970; +constexpr int EPOCH_WEEK_DAY = 4; + +// For asctime the behavior is undefined if struct tm's tm_wday or tm_mon are +// not within the normal ranges as defined in , or if struct tm's +// tm_year exceeds {INT_MAX}-1990, or if the below asctime_internal algorithm +// would attempt to generate more than 26 bytes of output (including the +// terminating null). +constexpr int ASCTIME_BUFFER_SIZE = 256; +constexpr int ASCTIME_MAX_BYTES = 26; + +/* 2000-03-01 (mod 400 year, immediately after feb29 */ +constexpr int64_t SECONDS_UNTIL2000_MARCH_FIRST = + (946684800LL + SECONDS_PER_DAY * (31 + 29)); +constexpr int WEEK_DAY_OF2000_MARCH_FIRST = 3; + +constexpr int DAYS_PER400_YEARS = + (DAYS_PER_NON_LEAP_YEAR * 400) + (400 / 4) - 3; +constexpr int DAYS_PER100_YEARS = + (DAYS_PER_NON_LEAP_YEAR * 100) + (100 / 4) - 1; +constexpr int DAYS_PER4_YEARS = (DAYS_PER_NON_LEAP_YEAR * 4) + 1; + +// The latest time that can be represented in this form is 03:14:07 UTC on +// Tuesday, 19 January 2038 (corresponding to 2,147,483,647 seconds since the +// start of the epoch). This means that systems using a 32-bit time_t type are +// susceptible to the Year 2038 problem. +constexpr int END_OF32_BIT_EPOCH_YEAR = 2038; + +constexpr time_t OUT_OF_RANGE_RETURN_VALUE = -1; + +constexpr cpp::array WEEK_DAY_NAMES = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + +constexpr cpp::array WEEK_DAY_FULL_NAMES = { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday"}; + +constexpr cpp::array MONTH_NAMES = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +constexpr cpp::array MONTH_FULL_NAMES = { + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"}; + +constexpr int NON_LEAP_YEAR_DAYS_IN_MONTH[] = {31, 28, 31, 30, 31, 30, + 31, 31, 30, 31, 30, 31}; + +} // namespace time_constants +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_TIME_TIME_CONSTANTS_H diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp index 509cad8146df8..abc93b8cb961e 100644 --- a/libc/src/time/time_utils.cpp +++ b/libc/src/time/time_utils.cpp @@ -10,12 +10,11 @@ #include "src/__support/CPP/limits.h" // INT_MIN, INT_MAX #include "src/__support/common.h" #include "src/__support/macros/config.h" +#include "src/time/time_constants.h" namespace LIBC_NAMESPACE_DECL { namespace time_utils { -using LIBC_NAMESPACE::time_utils::TimeConstants; - static int64_t computeRemainingYears(int64_t daysPerYears, int64_t quotientYears, int64_t *remainingDays) { @@ -52,36 +51,36 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) { (sizeof(time_t) == 4) ? INT_MIN : INT_MIN * static_cast( - TimeConstants::NUMBER_OF_SECONDS_IN_LEAP_YEAR); + time_constants::NUMBER_OF_SECONDS_IN_LEAP_YEAR); constexpr time_t time_max = (sizeof(time_t) == 4) ? INT_MAX : INT_MAX * static_cast( - TimeConstants::NUMBER_OF_SECONDS_IN_LEAP_YEAR); + time_constants::NUMBER_OF_SECONDS_IN_LEAP_YEAR); time_t ts = static_cast(total_seconds); if (ts < time_min || ts > time_max) return time_utils::out_of_range(); int64_t seconds = - total_seconds - TimeConstants::SECONDS_UNTIL2000_MARCH_FIRST; - int64_t days = seconds / TimeConstants::SECONDS_PER_DAY; - int64_t remainingSeconds = seconds % TimeConstants::SECONDS_PER_DAY; + total_seconds - time_constants::SECONDS_UNTIL2000_MARCH_FIRST; + int64_t days = seconds / time_constants::SECONDS_PER_DAY; + int64_t remainingSeconds = seconds % time_constants::SECONDS_PER_DAY; if (remainingSeconds < 0) { - remainingSeconds += TimeConstants::SECONDS_PER_DAY; + remainingSeconds += time_constants::SECONDS_PER_DAY; days--; } - int64_t wday = (TimeConstants::WEEK_DAY_OF2000_MARCH_FIRST + days) % - TimeConstants::DAYS_PER_WEEK; + int64_t wday = (time_constants::WEEK_DAY_OF2000_MARCH_FIRST + days) % + time_constants::DAYS_PER_WEEK; if (wday < 0) - wday += TimeConstants::DAYS_PER_WEEK; + wday += time_constants::DAYS_PER_WEEK; // Compute the number of 400 year cycles. - int64_t numOfFourHundredYearCycles = days / TimeConstants::DAYS_PER400_YEARS; - int64_t remainingDays = days % TimeConstants::DAYS_PER400_YEARS; + int64_t numOfFourHundredYearCycles = days / time_constants::DAYS_PER400_YEARS; + int64_t remainingDays = days % time_constants::DAYS_PER400_YEARS; if (remainingDays < 0) { - remainingDays += TimeConstants::DAYS_PER400_YEARS; + remainingDays += time_constants::DAYS_PER400_YEARS; numOfFourHundredYearCycles--; } @@ -89,17 +88,17 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) { // "four hundred year cycles" will be 4 hundred year cycles or less in 400 // years. int64_t numOfHundredYearCycles = computeRemainingYears( - TimeConstants::DAYS_PER100_YEARS, 4, &remainingDays); + time_constants::DAYS_PER100_YEARS, 4, &remainingDays); // The remaining number of years after computing the number of // "hundred year cycles" will be 25 four year cycles or less in 100 years. - int64_t numOfFourYearCycles = - computeRemainingYears(TimeConstants::DAYS_PER4_YEARS, 25, &remainingDays); + int64_t numOfFourYearCycles = computeRemainingYears( + time_constants::DAYS_PER4_YEARS, 25, &remainingDays); // The remaining number of years after computing the number of // "four year cycles" will be 4 one year cycles or less in 4 years. int64_t remainingYears = computeRemainingYears( - TimeConstants::DAYS_PER_NON_LEAP_YEAR, 4, &remainingDays); + time_constants::DAYS_PER_NON_LEAP_YEAR, 4, &remainingDays); // Calculate number of years from year 2000. int64_t years = remainingYears + 4 * numOfFourYearCycles + @@ -112,8 +111,8 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) { // We add 31 and 28 for the number of days in January and February, since our // starting point was March 1st. int64_t yday = remainingDays + 31 + 28 + leapDay; - if (yday >= TimeConstants::DAYS_PER_NON_LEAP_YEAR + leapDay) - yday -= TimeConstants::DAYS_PER_NON_LEAP_YEAR + leapDay; + if (yday >= time_constants::DAYS_PER_NON_LEAP_YEAR + leapDay) + yday -= time_constants::DAYS_PER_NON_LEAP_YEAR + leapDay; int64_t months = 0; while (daysInMonth[months] <= remainingDays) { @@ -121,8 +120,8 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) { months++; } - if (months >= TimeConstants::MONTHS_PER_YEAR - 2) { - months -= TimeConstants::MONTHS_PER_YEAR; + if (months >= time_constants::MONTHS_PER_YEAR - 2) { + months -= time_constants::MONTHS_PER_YEAR; years++; } @@ -131,19 +130,19 @@ int64_t update_from_seconds(int64_t total_seconds, struct tm *tm) { // All the data (years, month and remaining days) was calculated from // March, 2000. Thus adjust the data to be from January, 1900. - tm->tm_year = static_cast(years + 2000 - TimeConstants::TIME_YEAR_BASE); + tm->tm_year = static_cast(years + 2000 - time_constants::TIME_YEAR_BASE); tm->tm_mon = static_cast(months + 2); tm->tm_mday = static_cast(remainingDays + 1); tm->tm_wday = static_cast(wday); tm->tm_yday = static_cast(yday); tm->tm_hour = - static_cast(remainingSeconds / TimeConstants::SECONDS_PER_HOUR); + static_cast(remainingSeconds / time_constants::SECONDS_PER_HOUR); tm->tm_min = - static_cast(remainingSeconds / TimeConstants::SECONDS_PER_MIN % - TimeConstants::SECONDS_PER_MIN); + static_cast(remainingSeconds / time_constants::SECONDS_PER_MIN % + time_constants::SECONDS_PER_MIN); tm->tm_sec = - static_cast(remainingSeconds % TimeConstants::SECONDS_PER_MIN); + static_cast(remainingSeconds % time_constants::SECONDS_PER_MIN); // TODO(rtenneti): Need to handle timezone and update of tm_isdst. tm->tm_isdst = 0; diff --git a/libc/src/time/time_utils.h b/libc/src/time/time_utils.h index 552ea925c1c7d..5e0a692d4db04 100644 --- a/libc/src/time/time_utils.h +++ b/libc/src/time/time_utils.h @@ -9,79 +9,19 @@ #ifndef LLVM_LIBC_SRC_TIME_TIME_UTILS_H #define LLVM_LIBC_SRC_TIME_TIME_UTILS_H -#include // For size_t. - +#include "hdr/types/size_t.h" +#include "hdr/types/struct_tm.h" +#include "hdr/types/time_t.h" #include "src/__support/common.h" #include "src/__support/macros/config.h" #include "src/errno/libc_errno.h" -#include "src/time/mktime.h" +#include "time_constants.h" #include namespace LIBC_NAMESPACE_DECL { namespace time_utils { -enum Month : int { - JANUARY, - FEBRUARY, - MARCH, - APRIL, - MAY, - JUNE, - JULY, - AUGUST, - SEPTEMBER, - OCTOBER, - NOVEMBER, - DECEMBER -}; - -struct TimeConstants { - static constexpr int SECONDS_PER_MIN = 60; - static constexpr int MINUTES_PER_HOUR = 60; - static constexpr int HOURS_PER_DAY = 24; - static constexpr int DAYS_PER_WEEK = 7; - static constexpr int MONTHS_PER_YEAR = 12; - static constexpr int DAYS_PER_NON_LEAP_YEAR = 365; - static constexpr int DAYS_PER_LEAP_YEAR = 366; - - static constexpr int SECONDS_PER_HOUR = SECONDS_PER_MIN * MINUTES_PER_HOUR; - static constexpr int SECONDS_PER_DAY = SECONDS_PER_HOUR * HOURS_PER_DAY; - static constexpr int NUMBER_OF_SECONDS_IN_LEAP_YEAR = - DAYS_PER_LEAP_YEAR * SECONDS_PER_DAY; - - static constexpr int TIME_YEAR_BASE = 1900; - static constexpr int EPOCH_YEAR = 1970; - static constexpr int EPOCH_WEEK_DAY = 4; - - // For asctime the behavior is undefined if struct tm's tm_wday or tm_mon are - // not within the normal ranges as defined in , or if struct tm's - // tm_year exceeds {INT_MAX}-1990, or if the below asctime_internal algorithm - // would attempt to generate more than 26 bytes of output (including the - // terminating null). - static constexpr int ASCTIME_BUFFER_SIZE = 256; - static constexpr int ASCTIME_MAX_BYTES = 26; - - /* 2000-03-01 (mod 400 year, immediately after feb29 */ - static constexpr int64_t SECONDS_UNTIL2000_MARCH_FIRST = - (946684800LL + SECONDS_PER_DAY * (31 + 29)); - static constexpr int WEEK_DAY_OF2000_MARCH_FIRST = 3; - - static constexpr int DAYS_PER400_YEARS = - (DAYS_PER_NON_LEAP_YEAR * 400) + (400 / 4) - 3; - static constexpr int DAYS_PER100_YEARS = - (DAYS_PER_NON_LEAP_YEAR * 100) + (100 / 4) - 1; - static constexpr int DAYS_PER4_YEARS = (DAYS_PER_NON_LEAP_YEAR * 4) + 1; - - // The latest time that can be represented in this form is 03:14:07 UTC on - // Tuesday, 19 January 2038 (corresponding to 2,147,483,647 seconds since the - // start of the epoch). This means that systems using a 32-bit time_t type are - // susceptible to the Year 2038 problem. - static constexpr int END_OF32_BIT_EPOCH_YEAR = 2038; - - static constexpr time_t OUT_OF_RANGE_RETURN_VALUE = -1; -}; - // Update the "tm" structure's year, month, etc. members from seconds. // "total_seconds" is the number of seconds since January 1st, 1970. extern int64_t update_from_seconds(int64_t total_seconds, struct tm *tm); @@ -98,7 +38,7 @@ LIBC_INLINE time_t out_of_range() { // require it. libc_errno = EOVERFLOW; #endif - return TimeConstants::OUT_OF_RANGE_RETURN_VALUE; + return time_constants::OUT_OF_RANGE_RETURN_VALUE; } LIBC_INLINE void invalid_value() { libc_errno = EINVAL; } @@ -110,32 +50,23 @@ LIBC_INLINE char *asctime(const struct tm *timeptr, char *buffer, return nullptr; } if (timeptr->tm_wday < 0 || - timeptr->tm_wday > (TimeConstants::DAYS_PER_WEEK - 1)) { + timeptr->tm_wday > (time_constants::DAYS_PER_WEEK - 1)) { invalid_value(); return nullptr; } if (timeptr->tm_mon < 0 || - timeptr->tm_mon > (TimeConstants::MONTHS_PER_YEAR - 1)) { + timeptr->tm_mon > (time_constants::MONTHS_PER_YEAR - 1)) { invalid_value(); return nullptr; } - // TODO(rtenneti): i18n the following strings. - static const char *week_days_name[TimeConstants::DAYS_PER_WEEK] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; - - static const char *months_name[TimeConstants::MONTHS_PER_YEAR] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - - // TODO(michaelr): look into removing this call to __builtin_snprintf that may - // be emitted as a call to snprintf. Alternatively, look into using our - // internal printf machinery. + // TODO(michaelr): move this to use the strftime machinery int written_size = __builtin_snprintf( buffer, bufferLength, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n", - week_days_name[timeptr->tm_wday], months_name[timeptr->tm_mon], - timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, - TimeConstants::TIME_YEAR_BASE + timeptr->tm_year); + time_constants::WEEK_DAY_NAMES[timeptr->tm_wday].data(), + time_constants::MONTH_NAMES[timeptr->tm_mon].data(), timeptr->tm_mday, + timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, + time_constants::TIME_YEAR_BASE + timeptr->tm_year); if (written_size < 0) return nullptr; if (static_cast(written_size) >= bufferLength) { diff --git a/libc/test/src/time/CMakeLists.txt b/libc/test/src/time/CMakeLists.txt index da3903f3e0e49..12add224f386a 100644 --- a/libc/test/src/time/CMakeLists.txt +++ b/libc/test/src/time/CMakeLists.txt @@ -13,6 +13,8 @@ add_libc_unittest( 20 DEPENDS libc.src.time.asctime + libc.hdr.types.struct_tm + libc.src.time.time_constants ) add_libc_unittest( @@ -28,6 +30,8 @@ add_libc_unittest( 20 DEPENDS libc.src.time.asctime_r + libc.hdr.types.struct_tm + libc.src.time.time_constants ) add_libc_unittest( @@ -45,7 +49,8 @@ add_libc_unittest( libc.include.time libc.hdr.types.time_t libc.src.time.ctime - libc.src.time.time_utils + libc.src.time.time_constants + libc.hdr.types.struct_tm ) add_libc_unittest( @@ -63,7 +68,8 @@ add_libc_unittest( libc.include.time libc.hdr.types.time_t libc.src.time.ctime_r - libc.src.time.time_utils + libc.src.time.time_constants + libc.hdr.types.struct_tm ) add_libc_test( @@ -74,6 +80,9 @@ add_libc_test( clock_gettime_test.cpp DEPENDS libc.src.time.clock_gettime + libc.hdr.types.time_t + libc.hdr.types.struct_timespec + libc.hdr.time_macros ) add_libc_test( @@ -94,6 +103,8 @@ add_libc_unittest( difftime_test.cpp DEPENDS libc.src.time.difftime + libc.src.time.time_constants + libc.src.__support.FPUtil.fp_bits ) add_libc_unittest( @@ -105,6 +116,7 @@ add_libc_unittest( DEPENDS libc.include.time libc.src.time.gettimeofday + libc.hdr.types.struct_timeval ) add_libc_unittest( @@ -118,6 +130,8 @@ add_libc_unittest( DEPENDS libc.src.time.gmtime libc.src.__support.CPP.limits + libc.hdr.types.struct_tm + libc.src.time.time_constants ) add_libc_unittest( @@ -130,6 +144,8 @@ add_libc_unittest( TmMatcher.h DEPENDS libc.src.time.gmtime_r + libc.hdr.types.struct_tm + libc.src.time.time_constants ) add_libc_unittest( @@ -146,6 +162,8 @@ add_libc_unittest( DEPENDS libc.src.time.mktime libc.src.__support.CPP.limits + libc.hdr.types.struct_tm + libc.src.time.time_constants ) add_libc_test( @@ -158,6 +176,7 @@ add_libc_test( libc.include.time libc.src.time.nanosleep libc.src.errno.errno + libc.hdr.types.struct_timespec ) add_libc_unittest( @@ -180,6 +199,7 @@ add_libc_test( timespec_get_test.cpp DEPENDS libc.src.time.timespec_get + libc.hdr.types.struct_timespec ) add_libc_test( @@ -192,4 +212,5 @@ add_libc_test( libc.include.time libc.src.time.clock libc.src.errno.errno + libc.hdr.types.clock_t ) diff --git a/libc/test/src/time/TmHelper.h b/libc/test/src/time/TmHelper.h index 5ae258461099b..1582839ffaf2b 100644 --- a/libc/test/src/time/TmHelper.h +++ b/libc/test/src/time/TmHelper.h @@ -9,12 +9,9 @@ #ifndef LLVM_LIBC_TEST_SRC_TIME_TMHELPER_H #define LLVM_LIBC_TEST_SRC_TIME_TMHELPER_H -#include - +#include "hdr/types/struct_tm.h" #include "src/__support/macros/config.h" -#include "src/time/time_utils.h" - -using LIBC_NAMESPACE::time_utils::TimeConstants; +#include "src/time/time_constants.h" namespace LIBC_NAMESPACE_DECL { namespace tmhelper { @@ -30,7 +27,7 @@ static inline void initialize_tm_data(struct tm *tm_data, int year, int month, .tm_mday = mday, .tm_mon = month - 1, // tm_mon starts with 0 for Jan // years since 1900 - .tm_year = year - TimeConstants::TIME_YEAR_BASE, + .tm_year = year - time_constants::TIME_YEAR_BASE, .tm_wday = wday, .tm_yday = yday, .tm_isdst = 0}; diff --git a/libc/test/src/time/TmMatcher.h b/libc/test/src/time/TmMatcher.h index 630956b0f08d6..d39ee396057b8 100644 --- a/libc/test/src/time/TmMatcher.h +++ b/libc/test/src/time/TmMatcher.h @@ -9,8 +9,7 @@ #ifndef LLVM_LIBC_TEST_SRC_TIME_TM_MATCHER_H #define LLVM_LIBC_TEST_SRC_TIME_TM_MATCHER_H -#include - +#include "hdr/types/struct_tm.h" #include "src/__support/macros/config.h" #include "test/UnitTest/Test.h" diff --git a/libc/test/src/time/asctime_r_test.cpp b/libc/test/src/time/asctime_r_test.cpp index f3aadbb39de4d..b595cfe024866 100644 --- a/libc/test/src/time/asctime_r_test.cpp +++ b/libc/test/src/time/asctime_r_test.cpp @@ -8,12 +8,10 @@ #include "src/errno/libc_errno.h" #include "src/time/asctime_r.h" -#include "src/time/time_utils.h" +#include "src/time/time_constants.h" #include "test/UnitTest/Test.h" #include "test/src/time/TmHelper.h" -using LIBC_NAMESPACE::time_utils::TimeConstants; - static inline char *call_asctime_r(struct tm *tm_data, int year, int month, int mday, int hour, int min, int sec, int wday, int yday, char *buffer) { @@ -30,7 +28,7 @@ TEST(LlvmLibcAsctimeR, Nullptr) { ASSERT_ERRNO_EQ(EINVAL); ASSERT_STREQ(nullptr, result); - char buffer[TimeConstants::ASCTIME_BUFFER_SIZE]; + char buffer[LIBC_NAMESPACE::time_constants::ASCTIME_BUFFER_SIZE]; result = LIBC_NAMESPACE::asctime_r(nullptr, buffer); ASSERT_ERRNO_EQ(EINVAL); ASSERT_STREQ(nullptr, result); @@ -42,7 +40,7 @@ TEST(LlvmLibcAsctimeR, Nullptr) { } TEST(LlvmLibcAsctimeR, ValidDate) { - char buffer[TimeConstants::ASCTIME_BUFFER_SIZE]; + char buffer[LIBC_NAMESPACE::time_constants::ASCTIME_BUFFER_SIZE]; struct tm tm_data; char *result; // 1970-01-01 00:00:00. Test with a valid buffer size. diff --git a/libc/test/src/time/clock_gettime_test.cpp b/libc/test/src/time/clock_gettime_test.cpp index 43715c0265f1f..d3edcae00cdd0 100644 --- a/libc/test/src/time/clock_gettime_test.cpp +++ b/libc/test/src/time/clock_gettime_test.cpp @@ -6,12 +6,13 @@ // //===----------------------------------------------------------------------===// +#include "hdr/time_macros.h" +#include "hdr/types/struct_timespec.h" +#include "hdr/types/time_t.h" #include "src/__support/macros/properties/architectures.h" #include "src/time/clock_gettime.h" #include "test/UnitTest/Test.h" -#include - TEST(LlvmLibcClockGetTime, RealTime) { timespec tp; int result; diff --git a/libc/test/src/time/clock_test.cpp b/libc/test/src/time/clock_test.cpp index 05082aa233885..8d8d89d577a98 100644 --- a/libc/test/src/time/clock_test.cpp +++ b/libc/test/src/time/clock_test.cpp @@ -6,11 +6,10 @@ // //===----------------------------------------------------------------------===// +#include "hdr/types/clock_t.h" #include "src/time/clock.h" #include "test/UnitTest/Test.h" -#include - TEST(LlvmLibcClockTest, SmokeTest) { clock_t c1 = LIBC_NAMESPACE::clock(); ASSERT_GT(c1, clock_t(0)); diff --git a/libc/test/src/time/ctime_r_test.cpp b/libc/test/src/time/ctime_r_test.cpp index 9ce6f75f75484..27011b7e0fbd6 100644 --- a/libc/test/src/time/ctime_r_test.cpp +++ b/libc/test/src/time/ctime_r_test.cpp @@ -8,18 +8,16 @@ #include "src/errno/libc_errno.h" #include "src/time/ctime_r.h" -#include "src/time/time_utils.h" +#include "src/time/time_constants.h" #include "test/UnitTest/Test.h" #include "test/src/time/TmHelper.h" -using LIBC_NAMESPACE::time_utils::TimeConstants; - TEST(LlvmLibcCtimeR, Nullptr) { char *result; result = LIBC_NAMESPACE::ctime_r(nullptr, nullptr); ASSERT_STREQ(nullptr, result); - char buffer[TimeConstants::ASCTIME_BUFFER_SIZE]; + char buffer[LIBC_NAMESPACE::time_constants::ASCTIME_BUFFER_SIZE]; result = LIBC_NAMESPACE::ctime_r(nullptr, buffer); ASSERT_STREQ(nullptr, result); @@ -29,7 +27,7 @@ TEST(LlvmLibcCtimeR, Nullptr) { } TEST(LlvmLibcCtimeR, ValidUnixTimestamp0) { - char buffer[TimeConstants::ASCTIME_BUFFER_SIZE]; + char buffer[LIBC_NAMESPACE::time_constants::ASCTIME_BUFFER_SIZE]; time_t t; char *result; // 1970-01-01 00:00:00. Test with a valid buffer size. @@ -39,7 +37,7 @@ TEST(LlvmLibcCtimeR, ValidUnixTimestamp0) { } TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) { - char buffer[TimeConstants::ASCTIME_BUFFER_SIZE]; + char buffer[LIBC_NAMESPACE::time_constants::ASCTIME_BUFFER_SIZE]; time_t t; char *result; // 2038-01-19 03:14:07. Test with a valid buffer size. @@ -49,7 +47,7 @@ TEST(LlvmLibcCtime, ValidUnixTimestamp32Int) { } TEST(LlvmLibcCtimeR, InvalidArgument) { - char buffer[TimeConstants::ASCTIME_BUFFER_SIZE]; + char buffer[LIBC_NAMESPACE::time_constants::ASCTIME_BUFFER_SIZE]; time_t t; char *result; t = 2147483648; diff --git a/libc/test/src/time/difftime_test.cpp b/libc/test/src/time/difftime_test.cpp index 68ff4630e61ba..4dab1ac91104f 100644 --- a/libc/test/src/time/difftime_test.cpp +++ b/libc/test/src/time/difftime_test.cpp @@ -8,15 +8,12 @@ #include "src/__support/FPUtil/FPBits.h" #include "src/time/difftime.h" -#include "src/time/time_utils.h" +#include "src/time/time_constants.h" #include "test/UnitTest/ErrnoSetterMatcher.h" #include "test/UnitTest/Test.h" -using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; -using LIBC_NAMESPACE::time_utils::TimeConstants; - TEST(LlvmLibcDifftime, SmokeTest) { - time_t t1_seconds = TimeConstants::SECONDS_PER_HOUR; + time_t t1_seconds = LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR; time_t t2_seconds = 0; LIBC_NAMESPACE::fputil::FPBits expected_fp = diff --git a/libc/test/src/time/gettimeofday_test.cpp b/libc/test/src/time/gettimeofday_test.cpp index ee934b7f3a201..8f9f136164f57 100644 --- a/libc/test/src/time/gettimeofday_test.cpp +++ b/libc/test/src/time/gettimeofday_test.cpp @@ -6,8 +6,7 @@ // //===----------------------------------------------------------------------===// -#include - +#include "hdr/types/struct_timeval.h" #include "src/time/gettimeofday.h" #include "test/UnitTest/Test.h" diff --git a/libc/test/src/time/gmtime_r_test.cpp b/libc/test/src/time/gmtime_r_test.cpp index 2276b4803f192..9d466f444f97f 100644 --- a/libc/test/src/time/gmtime_r_test.cpp +++ b/libc/test/src/time/gmtime_r_test.cpp @@ -7,12 +7,10 @@ //===----------------------------------------------------------------------===// #include "src/time/gmtime_r.h" -#include "src/time/time_utils.h" +#include "src/time/time_constants.h" #include "test/UnitTest/Test.h" #include "test/src/time/TmMatcher.h" -using LIBC_NAMESPACE::time_utils::TimeConstants; - // gmtime and gmtime_r share the same code and thus didn't repeat all the tests // from gmtime. Added couple of validation tests. TEST(LlvmLibcGmTimeR, EndOf32BitEpochYear) { @@ -22,16 +20,17 @@ TEST(LlvmLibcGmTimeR, EndOf32BitEpochYear) { struct tm tm_data; struct tm *tm_data_ptr; tm_data_ptr = LIBC_NAMESPACE::gmtime_r(&seconds, &tm_data); - EXPECT_TM_EQ((tm{7, // sec - 14, // min - 3, // hr - 19, // day - 0, // tm_mon starts with 0 for Jan - 2038 - TimeConstants::TIME_YEAR_BASE, // year - 2, // wday - 7, // yday - 0}), - *tm_data_ptr); + EXPECT_TM_EQ( + (tm{7, // sec + 14, // min + 3, // hr + 19, // day + 0, // tm_mon starts with 0 for Jan + 2038 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 2, // wday + 7, // yday + 0}), + *tm_data_ptr); EXPECT_TM_EQ(*tm_data_ptr, tm_data); } @@ -43,15 +42,16 @@ TEST(LlvmLibcGmTimeR, Max64BitYear) { struct tm tm_data; struct tm *tm_data_ptr; tm_data_ptr = LIBC_NAMESPACE::gmtime_r(&seconds, &tm_data); - EXPECT_TM_EQ((tm{50, // sec - 50, // min - 12, // hr - 1, // day - 0, // tm_mon starts with 0 for Jan - 2147483647 - TimeConstants::TIME_YEAR_BASE, // year - 2, // wday - 50, // yday - 0}), - *tm_data_ptr); + EXPECT_TM_EQ( + (tm{50, // sec + 50, // min + 12, // hr + 1, // day + 0, // tm_mon starts with 0 for Jan + 2147483647 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 2, // wday + 50, // yday + 0}), + *tm_data_ptr); EXPECT_TM_EQ(*tm_data_ptr, tm_data); } diff --git a/libc/test/src/time/gmtime_test.cpp b/libc/test/src/time/gmtime_test.cpp index 433fbf6667057..6af5a18d36996 100644 --- a/libc/test/src/time/gmtime_test.cpp +++ b/libc/test/src/time/gmtime_test.cpp @@ -6,32 +6,36 @@ // //===----------------------------------------------------------------------===// +#include "hdr/types/struct_tm.h" #include "src/__support/CPP/limits.h" // INT_MAX, INT_MIN #include "src/errno/libc_errno.h" #include "src/time/gmtime.h" -#include "src/time/time_utils.h" +#include "src/time/time_constants.h" #include "test/UnitTest/ErrnoSetterMatcher.h" #include "test/UnitTest/Test.h" #include "test/src/time/TmMatcher.h" using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; -using LIBC_NAMESPACE::time_utils::TimeConstants; TEST(LlvmLibcGmTime, OutOfRange) { if (sizeof(time_t) < sizeof(int64_t)) return; time_t seconds = - 1 + INT_MAX * static_cast( - TimeConstants::NUMBER_OF_SECONDS_IN_LEAP_YEAR); + 1 + + INT_MAX * + static_cast( + LIBC_NAMESPACE::time_constants::NUMBER_OF_SECONDS_IN_LEAP_YEAR); struct tm *tm_data = LIBC_NAMESPACE::gmtime(&seconds); EXPECT_TRUE(tm_data == nullptr); ASSERT_ERRNO_EQ(EOVERFLOW); LIBC_NAMESPACE::libc_errno = 0; - seconds = INT_MIN * static_cast( - TimeConstants::NUMBER_OF_SECONDS_IN_LEAP_YEAR) - - 1; + seconds = + INT_MIN * + static_cast( + LIBC_NAMESPACE::time_constants::NUMBER_OF_SECONDS_IN_LEAP_YEAR) - + 1; tm_data = LIBC_NAMESPACE::gmtime(&seconds); EXPECT_TRUE(tm_data == nullptr); ASSERT_ERRNO_EQ(EOVERFLOW); @@ -43,201 +47,215 @@ TEST(LlvmLibcGmTime, InvalidSeconds) { // -1 second from 1970-01-01 00:00:00 returns 1969-12-31 23:59:59. seconds = -1; tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{59, // sec - 59, // min - 23, // hr - 31, // day - 12 - 1, // tm_mon starts with 0 for Jan - 1969 - TimeConstants::TIME_YEAR_BASE, // year - 3, // wday - 364, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{59, // sec + 59, // min + 23, // hr + 31, // day + 12 - 1, // tm_mon starts with 0 for Jan + 1969 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 3, // wday + 364, // yday + 0}), + *tm_data); // 60 seconds from 1970-01-01 00:00:00 returns 1970-01-01 00:01:00. seconds = 60; tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{0, // sec - 1, // min - 0, // hr - 1, // day - 0, // tm_mon starts with 0 for Jan - 1970 - TimeConstants::TIME_YEAR_BASE, // year - 4, // wday - 0, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{0, // sec + 1, // min + 0, // hr + 1, // day + 0, // tm_mon starts with 0 for Jan + 1970 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 4, // wday + 0, // yday + 0}), + *tm_data); } TEST(LlvmLibcGmTime, InvalidMinutes) { time_t seconds = 0; struct tm *tm_data = nullptr; // -1 minute from 1970-01-01 00:00:00 returns 1969-12-31 23:59:00. - seconds = -TimeConstants::SECONDS_PER_MIN; + seconds = -LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN; tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{0, // sec - 59, // min - 23, // hr - 31, // day - 11, // tm_mon starts with 0 for Jan - 1969 - TimeConstants::TIME_YEAR_BASE, // year - 3, // wday - 0, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{0, // sec + 59, // min + 23, // hr + 31, // day + 11, // tm_mon starts with 0 for Jan + 1969 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 3, // wday + 0, // yday + 0}), + *tm_data); // 60 minutes from 1970-01-01 00:00:00 returns 1970-01-01 01:00:00. - seconds = 60 * TimeConstants::SECONDS_PER_MIN; + seconds = 60 * LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN; tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{0, // sec - 0, // min - 1, // hr - 1, // day - 0, // tm_mon starts with 0 for Jan - 1970 - TimeConstants::TIME_YEAR_BASE, // year - 4, // wday - 0, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{0, // sec + 0, // min + 1, // hr + 1, // day + 0, // tm_mon starts with 0 for Jan + 1970 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 4, // wday + 0, // yday + 0}), + *tm_data); } TEST(LlvmLibcGmTime, InvalidHours) { time_t seconds = 0; struct tm *tm_data = nullptr; // -1 hour from 1970-01-01 00:00:00 returns 1969-12-31 23:00:00. - seconds = -TimeConstants::SECONDS_PER_HOUR; + seconds = -LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR; tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{0, // sec - 0, // min - 23, // hr - 31, // day - 11, // tm_mon starts with 0 for Jan - 1969 - TimeConstants::TIME_YEAR_BASE, // year - 3, // wday - 0, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{0, // sec + 0, // min + 23, // hr + 31, // day + 11, // tm_mon starts with 0 for Jan + 1969 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 3, // wday + 0, // yday + 0}), + *tm_data); // 24 hours from 1970-01-01 00:00:00 returns 1970-01-02 00:00:00. - seconds = 24 * TimeConstants::SECONDS_PER_HOUR; + seconds = 24 * LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR; tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{0, // sec - 0, // min - 0, // hr - 2, // day - 0, // tm_mon starts with 0 for Jan - 1970 - TimeConstants::TIME_YEAR_BASE, // year - 5, // wday - 0, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{0, // sec + 0, // min + 0, // hr + 2, // day + 0, // tm_mon starts with 0 for Jan + 1970 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 5, // wday + 0, // yday + 0}), + *tm_data); } TEST(LlvmLibcGmTime, InvalidYear) { // -1 year from 1970-01-01 00:00:00 returns 1969-01-01 00:00:00. - time_t seconds = - -TimeConstants::DAYS_PER_NON_LEAP_YEAR * TimeConstants::SECONDS_PER_DAY; + time_t seconds = -LIBC_NAMESPACE::time_constants::DAYS_PER_NON_LEAP_YEAR * + LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY; struct tm *tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{0, // sec - 0, // min - 0, // hr - 1, // day - 0, // tm_mon starts with 0 for Jan - 1969 - TimeConstants::TIME_YEAR_BASE, // year - 3, // wday - 0, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{0, // sec + 0, // min + 0, // hr + 1, // day + 0, // tm_mon starts with 0 for Jan + 1969 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 3, // wday + 0, // yday + 0}), + *tm_data); } TEST(LlvmLibcGmTime, InvalidMonths) { time_t seconds = 0; struct tm *tm_data = nullptr; // -1 month from 1970-01-01 00:00:00 returns 1969-12-01 00:00:00. - seconds = -31 * TimeConstants::SECONDS_PER_DAY; + seconds = -31 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY; tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{0, // sec - 0, // min - 0, // hr - 1, // day - 12 - 1, // tm_mon starts with 0 for Jan - 1969 - TimeConstants::TIME_YEAR_BASE, // year - 1, // wday - 0, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{0, // sec + 0, // min + 0, // hr + 1, // day + 12 - 1, // tm_mon starts with 0 for Jan + 1969 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 1, // wday + 0, // yday + 0}), + *tm_data); // 1970-13-01 00:00:00 returns 1971-01-01 00:00:00. - seconds = - TimeConstants::DAYS_PER_NON_LEAP_YEAR * TimeConstants::SECONDS_PER_DAY; + seconds = LIBC_NAMESPACE::time_constants::DAYS_PER_NON_LEAP_YEAR * + LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY; tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{0, // sec - 0, // min - 0, // hr - 1, // day - 0, // tm_mon starts with 0 for Jan - 1971 - TimeConstants::TIME_YEAR_BASE, // year - 5, // wday - 0, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{0, // sec + 0, // min + 0, // hr + 1, // day + 0, // tm_mon starts with 0 for Jan + 1971 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 5, // wday + 0, // yday + 0}), + *tm_data); } TEST(LlvmLibcGmTime, InvalidDays) { time_t seconds = 0; struct tm *tm_data = nullptr; // -1 day from 1970-01-01 00:00:00 returns 1969-12-31 00:00:00. - seconds = -1 * TimeConstants::SECONDS_PER_DAY; + seconds = -1 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY; tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{0, // sec - 0, // min - 0, // hr - 31, // day - 11, // tm_mon starts with 0 for Jan - 1969 - TimeConstants::TIME_YEAR_BASE, // year - 3, // wday - 0, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{0, // sec + 0, // min + 0, // hr + 31, // day + 11, // tm_mon starts with 0 for Jan + 1969 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 3, // wday + 0, // yday + 0}), + *tm_data); // 1970-01-32 00:00:00 returns 1970-02-01 00:00:00. - seconds = 31 * TimeConstants::SECONDS_PER_DAY; + seconds = 31 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY; tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{0, // sec - 0, // min - 0, // hr - 1, // day - 0, // tm_mon starts with 0 for Jan - 1970 - TimeConstants::TIME_YEAR_BASE, // year - 0, // wday - 0, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{0, // sec + 0, // min + 0, // hr + 1, // day + 0, // tm_mon starts with 0 for Jan + 1970 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 0, // wday + 0, // yday + 0}), + *tm_data); // 1970-02-29 00:00:00 returns 1970-03-01 00:00:00. - seconds = 59 * TimeConstants::SECONDS_PER_DAY; + seconds = 59 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY; tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{0, // sec - 0, // min - 0, // hr - 1, // day - 2, // tm_mon starts with 0 for Jan - 1970 - TimeConstants::TIME_YEAR_BASE, // year - 0, // wday - 0, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{0, // sec + 0, // min + 0, // hr + 1, // day + 2, // tm_mon starts with 0 for Jan + 1970 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 0, // wday + 0, // yday + 0}), + *tm_data); // 1972-02-30 00:00:00 returns 1972-03-01 00:00:00. - seconds = ((2 * TimeConstants::DAYS_PER_NON_LEAP_YEAR) + 60) * - TimeConstants::SECONDS_PER_DAY; + seconds = + ((2 * LIBC_NAMESPACE::time_constants::DAYS_PER_NON_LEAP_YEAR) + 60) * + LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY; tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{0, // sec - 0, // min - 0, // hr - 1, // day - 2, // tm_mon starts with 0 for Jan - 1972 - TimeConstants::TIME_YEAR_BASE, // year - 3, // wday - 0, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{0, // sec + 0, // min + 0, // hr + 1, // day + 2, // tm_mon starts with 0 for Jan + 1972 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 3, // wday + 0, // yday + 0}), + *tm_data); } TEST(LlvmLibcGmTime, EndOf32BitEpochYear) { @@ -245,16 +263,17 @@ TEST(LlvmLibcGmTime, EndOf32BitEpochYear) { // Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC. time_t seconds = 0x7FFFFFFF; struct tm *tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{7, // sec - 14, // min - 3, // hr - 19, // day - 0, // tm_mon starts with 0 for Jan - 2038 - TimeConstants::TIME_YEAR_BASE, // year - 2, // wday - 7, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{7, // sec + 14, // min + 3, // hr + 19, // day + 0, // tm_mon starts with 0 for Jan + 2038 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 2, // wday + 7, // yday + 0}), + *tm_data); } TEST(LlvmLibcGmTime, Max64BitYear) { @@ -263,28 +282,30 @@ TEST(LlvmLibcGmTime, Max64BitYear) { // Mon Jan 1 12:50:50 2170 (200 years from 1970), time_t seconds = 6311479850; struct tm *tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{50, // sec - 50, // min - 12, // hr - 1, // day - 0, // tm_mon starts with 0 for Jan - 2170 - TimeConstants::TIME_YEAR_BASE, // year - 1, // wday - 50, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{50, // sec + 50, // min + 12, // hr + 1, // day + 0, // tm_mon starts with 0 for Jan + 2170 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 1, // wday + 50, // yday + 0}), + *tm_data); // Test for Tue Jan 1 12:50:50 in 2,147,483,647th year. seconds = 67767976202043050; tm_data = LIBC_NAMESPACE::gmtime(&seconds); - EXPECT_TM_EQ((tm{50, // sec - 50, // min - 12, // hr - 1, // day - 0, // tm_mon starts with 0 for Jan - 2147483647 - TimeConstants::TIME_YEAR_BASE, // year - 2, // wday - 50, // yday - 0}), - *tm_data); + EXPECT_TM_EQ( + (tm{50, // sec + 50, // min + 12, // hr + 1, // day + 0, // tm_mon starts with 0 for Jan + 2147483647 - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE, // year + 2, // wday + 50, // yday + 0}), + *tm_data); } diff --git a/libc/test/src/time/mktime_test.cpp b/libc/test/src/time/mktime_test.cpp index 84e6c7eb2c42e..fe1116f7dd2ef 100644 --- a/libc/test/src/time/mktime_test.cpp +++ b/libc/test/src/time/mktime_test.cpp @@ -8,7 +8,7 @@ #include "src/__support/CPP/limits.h" // INT_MAX #include "src/time/mktime.h" -#include "src/time/time_utils.h" +#include "src/time/time_constants.h" #include "test/UnitTest/ErrnoSetterMatcher.h" #include "test/UnitTest/Test.h" #include "test/src/time/TmHelper.h" @@ -16,29 +16,37 @@ using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; -using LIBC_NAMESPACE::time_utils::Month; +using LIBC_NAMESPACE::time_constants::Month; static inline constexpr int tm_year(int year) { - return year - TimeConstants::TIME_YEAR_BASE; + return year - LIBC_NAMESPACE::time_constants::TIME_YEAR_BASE; } TEST(LlvmLibcMkTime, FailureSetsErrno) { - struct tm tm_data { - .tm_sec = INT_MAX, .tm_min = INT_MAX, .tm_hour = INT_MAX, - .tm_mday = INT_MAX, .tm_mon = INT_MAX - 1, .tm_year = tm_year(INT_MAX), - .tm_wday = 0, .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = INT_MAX, + .tm_min = INT_MAX, + .tm_hour = INT_MAX, + .tm_mday = INT_MAX, + .tm_mon = INT_MAX - 1, + .tm_year = tm_year(INT_MAX), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Fails(EOVERFLOW)); } TEST(LlvmLibcMkTime, InvalidSeconds) { { // -1 second from 1970-01-01 00:00:00 returns 1969-12-31 23:59:59. - struct tm tm_data { - .tm_sec = -1, .tm_min = 0, .tm_hour = 0, .tm_mday = 1, - .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = -1, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = 1, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(1970), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Succeeds(-1)); EXPECT_TM_EQ((tm{.tm_sec = 59, .tm_min = 59, @@ -54,11 +62,15 @@ TEST(LlvmLibcMkTime, InvalidSeconds) { { // 60 seconds from 1970-01-01 00:00:00 returns 1970-01-01 00:01:00. - struct tm tm_data { - .tm_sec = 60, .tm_min = 0, .tm_hour = 0, .tm_mday = 1, - .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 60, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = 1, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(1970), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Succeeds(60)); EXPECT_TM_EQ((tm{.tm_sec = 0, .tm_min = 1, @@ -76,13 +88,17 @@ TEST(LlvmLibcMkTime, InvalidSeconds) { TEST(LlvmLibcMkTime, InvalidMinutes) { { // -1 minute from 1970-01-01 00:00:00 returns 1969-12-31 23:59:00. - struct tm tm_data { - .tm_sec = 0, .tm_min = -1, .tm_hour = 0, .tm_mday = 1, - .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 0, + .tm_min = -1, + .tm_hour = 0, + .tm_mday = 1, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(1970), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), - Succeeds(-TimeConstants::SECONDS_PER_MIN)); + Succeeds(-LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN)); EXPECT_TM_EQ((tm{.tm_sec = 0, .tm_min = 59, .tm_hour = 23, @@ -97,13 +113,17 @@ TEST(LlvmLibcMkTime, InvalidMinutes) { { // 60 minutes from 1970-01-01 00:00:00 returns 1970-01-01 01:00:00. - struct tm tm_data { - .tm_sec = 0, .tm_min = 60, .tm_hour = 0, .tm_mday = 1, - .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 0, + .tm_min = 60, + .tm_hour = 0, + .tm_mday = 1, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(1970), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), - Succeeds(60 * TimeConstants::SECONDS_PER_MIN)); + Succeeds(60 * LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN)); EXPECT_TM_EQ((tm{.tm_sec = 0, .tm_min = 0, .tm_hour = 1, @@ -120,13 +140,17 @@ TEST(LlvmLibcMkTime, InvalidMinutes) { TEST(LlvmLibcMkTime, InvalidHours) { { // -1 hour from 1970-01-01 00:00:00 returns 1969-12-31 23:00:00. - struct tm tm_data { - .tm_sec = 0, .tm_min = 0, .tm_hour = -1, .tm_mday = 1, - .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 0, + .tm_min = 0, + .tm_hour = -1, + .tm_mday = 1, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(1970), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), - Succeeds(-TimeConstants::SECONDS_PER_HOUR)); + Succeeds(-LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR)); EXPECT_TM_EQ((tm{.tm_sec = 0, .tm_min = 0, .tm_hour = 23, @@ -141,13 +165,18 @@ TEST(LlvmLibcMkTime, InvalidHours) { { // 24 hours from 1970-01-01 00:00:00 returns 1970-01-02 00:00:00. - struct tm tm_data { - .tm_sec = 0, .tm_min = 0, .tm_hour = 24, .tm_mday = 1, - .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; - EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), - Succeeds(24 * TimeConstants::SECONDS_PER_HOUR)); + struct tm tm_data{.tm_sec = 0, + .tm_min = 0, + .tm_hour = 24, + .tm_mday = 1, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(1970), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; + EXPECT_THAT( + LIBC_NAMESPACE::mktime(&tm_data), + Succeeds(24 * LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR)); EXPECT_TM_EQ((tm{.tm_sec = 0, .tm_min = 0, .tm_hour = 0, @@ -163,14 +192,18 @@ TEST(LlvmLibcMkTime, InvalidHours) { TEST(LlvmLibcMkTime, InvalidYear) { // -1 year from 1970-01-01 00:00:00 returns 1969-01-01 00:00:00. - struct tm tm_data { - .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 1, - .tm_mon = Month::JANUARY, .tm_year = tm_year(1969), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 0, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = 1, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(1969), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), - Succeeds(-TimeConstants::DAYS_PER_NON_LEAP_YEAR * - TimeConstants::SECONDS_PER_DAY)); + Succeeds(-LIBC_NAMESPACE::time_constants::DAYS_PER_NON_LEAP_YEAR * + LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY)); EXPECT_TM_EQ((tm{.tm_sec = 0, .tm_min = 0, .tm_hour = 0, @@ -188,61 +221,85 @@ TEST(LlvmLibcMkTime, InvalidEndOf32BitEpochYear) { return; { // 2038-01-19 03:14:08 tests overflow of the second in 2038. - struct tm tm_data { - .tm_sec = 8, .tm_min = 14, .tm_hour = 3, .tm_mday = 19, - .tm_mon = Month::JANUARY, .tm_year = tm_year(2038), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 8, + .tm_min = 14, + .tm_hour = 3, + .tm_mday = 19, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(2038), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Fails(EOVERFLOW)); } { // 2038-01-19 03:15:07 tests overflow of the minute in 2038. - struct tm tm_data { - .tm_sec = 7, .tm_min = 15, .tm_hour = 3, .tm_mday = 19, - .tm_mon = Month::JANUARY, .tm_year = tm_year(2038), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 7, + .tm_min = 15, + .tm_hour = 3, + .tm_mday = 19, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(2038), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Fails(EOVERFLOW)); } { // 2038-01-19 04:14:07 tests overflow of the hour in 2038. - struct tm tm_data { - .tm_sec = 7, .tm_min = 14, .tm_hour = 4, .tm_mday = 19, - .tm_mon = Month::JANUARY, .tm_year = tm_year(2038), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 7, + .tm_min = 14, + .tm_hour = 4, + .tm_mday = 19, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(2038), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Fails(EOVERFLOW)); } { // 2038-01-20 03:14:07 tests overflow of the day in 2038. - struct tm tm_data { - .tm_sec = 7, .tm_min = 14, .tm_hour = 3, .tm_mday = 20, - .tm_mon = Month::JANUARY, .tm_year = tm_year(2038), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 7, + .tm_min = 14, + .tm_hour = 3, + .tm_mday = 20, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(2038), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Fails(EOVERFLOW)); } { // 2038-02-19 03:14:07 tests overflow of the month in 2038. - struct tm tm_data { - .tm_sec = 7, .tm_min = 14, .tm_hour = 3, .tm_mday = 19, - .tm_mon = Month::FEBRUARY, .tm_year = tm_year(2038), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 7, + .tm_min = 14, + .tm_hour = 3, + .tm_mday = 19, + .tm_mon = Month::FEBRUARY, + .tm_year = tm_year(2038), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Fails(EOVERFLOW)); } { // 2039-01-19 03:14:07 tests overflow of the year. - struct tm tm_data { - .tm_sec = 7, .tm_min = 14, .tm_hour = 3, .tm_mday = 19, - .tm_mon = Month::JANUARY, .tm_year = tm_year(2039), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 7, + .tm_min = 14, + .tm_hour = 3, + .tm_mday = 19, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(2039), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Fails(EOVERFLOW)); } } @@ -250,12 +307,18 @@ TEST(LlvmLibcMkTime, InvalidEndOf32BitEpochYear) { TEST(LlvmLibcMkTime, InvalidMonths) { { // -1 month from 1970-01-01 00:00:00 returns 1969-12-01 00:00:00. - struct tm tm_data { - .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 0, .tm_mon = -1, - .tm_year = tm_year(1970), .tm_wday = 0, .tm_yday = 0, .tm_isdst = 0 - }; - EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), - Succeeds(-32 * TimeConstants::SECONDS_PER_DAY)); + struct tm tm_data{.tm_sec = 0, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = 0, + .tm_mon = -1, + .tm_year = tm_year(1970), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; + EXPECT_THAT( + LIBC_NAMESPACE::mktime(&tm_data), + Succeeds(-32 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY)); EXPECT_TM_EQ((tm{.tm_sec = 0, .tm_min = 0, .tm_hour = 0, @@ -270,13 +333,19 @@ TEST(LlvmLibcMkTime, InvalidMonths) { { // 1970-13-01 00:00:00 returns 1971-01-01 00:00:00. - struct tm tm_data { - .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 1, .tm_mon = 12, - .tm_year = tm_year(1970), .tm_wday = 0, .tm_yday = 0, .tm_isdst = 0 - }; - EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), - Succeeds(TimeConstants::DAYS_PER_NON_LEAP_YEAR * - TimeConstants::SECONDS_PER_DAY)); + struct tm tm_data{.tm_sec = 0, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = 1, + .tm_mon = 12, + .tm_year = tm_year(1970), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; + EXPECT_THAT( + LIBC_NAMESPACE::mktime(&tm_data), + Succeeds(LIBC_NAMESPACE::time_constants::DAYS_PER_NON_LEAP_YEAR * + LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY)); EXPECT_TM_EQ((tm{.tm_sec = 0, .tm_min = 0, .tm_hour = 0, @@ -293,13 +362,17 @@ TEST(LlvmLibcMkTime, InvalidMonths) { TEST(LlvmLibcMkTime, InvalidDays) { { // -1 day from 1970-01-01 00:00:00 returns 1969-12-31 00:00:00. - struct tm tm_data { - .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = (1 - 1), - .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 0, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = (1 - 1), + .tm_mon = Month::JANUARY, + .tm_year = tm_year(1970), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), - Succeeds(-1 * TimeConstants::SECONDS_PER_DAY)); + Succeeds(-1 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY)); EXPECT_TM_EQ((tm{.tm_sec = 0, .tm_min = 0, .tm_hour = 0, @@ -314,13 +387,17 @@ TEST(LlvmLibcMkTime, InvalidDays) { { // 1970-01-32 00:00:00 returns 1970-02-01 00:00:00. - struct tm tm_data { - .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 32, - .tm_mon = Month::JANUARY, .tm_year = tm_year(1970), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 0, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = 32, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(1970), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), - Succeeds(31 * TimeConstants::SECONDS_PER_DAY)); + Succeeds(31 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY)); EXPECT_TM_EQ((tm{.tm_sec = 0, .tm_min = 0, .tm_hour = 0, @@ -335,13 +412,17 @@ TEST(LlvmLibcMkTime, InvalidDays) { { // 1970-02-29 00:00:00 returns 1970-03-01 00:00:00. - struct tm tm_data { - .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 29, - .tm_mon = Month::FEBRUARY, .tm_year = tm_year(1970), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 0, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = 29, + .tm_mon = Month::FEBRUARY, + .tm_year = tm_year(1970), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), - Succeeds(59 * TimeConstants::SECONDS_PER_DAY)); + Succeeds(59 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY)); EXPECT_TM_EQ((tm{.tm_sec = 0, .tm_min = 0, .tm_hour = 0, @@ -356,14 +437,20 @@ TEST(LlvmLibcMkTime, InvalidDays) { { // 1972-02-30 00:00:00 returns 1972-03-01 00:00:00. - struct tm tm_data { - .tm_sec = 0, .tm_min = 0, .tm_hour = 0, .tm_mday = 30, - .tm_mon = Month::FEBRUARY, .tm_year = tm_year(1972), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; - EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), - Succeeds(((2 * TimeConstants::DAYS_PER_NON_LEAP_YEAR) + 60) * - TimeConstants::SECONDS_PER_DAY)); + struct tm tm_data{.tm_sec = 0, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = 30, + .tm_mon = Month::FEBRUARY, + .tm_year = tm_year(1972), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; + EXPECT_THAT( + LIBC_NAMESPACE::mktime(&tm_data), + Succeeds(((2 * LIBC_NAMESPACE::time_constants::DAYS_PER_NON_LEAP_YEAR) + + 60) * + LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY)); EXPECT_TM_EQ((tm{.tm_sec = 0, .tm_min = 0, .tm_hour = 0, @@ -381,11 +468,15 @@ TEST(LlvmLibcMkTime, EndOf32BitEpochYear) { // Test for maximum value of a signed 32-bit integer. // Test implementation can encode time for Tue 19 January 2038 03:14:07 UTC. { - struct tm tm_data { - .tm_sec = 7, .tm_min = 14, .tm_hour = 3, .tm_mday = 19, - .tm_mon = Month::JANUARY, .tm_year = tm_year(2038), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 7, + .tm_min = 14, + .tm_hour = 3, + .tm_mday = 19, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(2038), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Succeeds(0x7FFFFFFF)); EXPECT_TM_EQ((tm{.tm_sec = 7, .tm_min = 14, @@ -403,11 +494,15 @@ TEST(LlvmLibcMkTime, EndOf32BitEpochYear) { { // 2038-01-19 03:13:59 tests that even a large seconds field is // accepted if the minutes field is smaller. - struct tm tm_data { - .tm_sec = 59, .tm_min = 13, .tm_hour = 3, .tm_mday = 19, - .tm_mon = Month::JANUARY, .tm_year = tm_year(2038), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 59, + .tm_min = 13, + .tm_hour = 3, + .tm_mday = 19, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(2038), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Succeeds(0x7FFFFFFF - 8)); EXPECT_TM_EQ((tm{.tm_sec = 59, .tm_min = 13, @@ -424,13 +519,18 @@ TEST(LlvmLibcMkTime, EndOf32BitEpochYear) { { // 2038-01-19 02:59:59 tests that large seconds and minutes are // accepted if the hours field is smaller. - struct tm tm_data { - .tm_sec = 59, .tm_min = 59, .tm_hour = 2, .tm_mday = 19, - .tm_mon = Month::JANUARY, .tm_year = tm_year(2038), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 59, + .tm_min = 59, + .tm_hour = 2, + .tm_mday = 19, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(2038), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), - Succeeds(0x7FFFFFFF - 8 - 14 * TimeConstants::SECONDS_PER_MIN)); + Succeeds(0x7FFFFFFF - 8 - + 14 * LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN)); EXPECT_TM_EQ((tm{.tm_sec = 59, .tm_min = 59, .tm_hour = 2, @@ -446,14 +546,19 @@ TEST(LlvmLibcMkTime, EndOf32BitEpochYear) { { // 2038-01-18 23:59:59 tests that large seconds, minutes and hours // are accepted if the days field is smaller. - struct tm tm_data { - .tm_sec = 59, .tm_min = 59, .tm_hour = 23, .tm_mday = 18, - .tm_mon = Month::JANUARY, .tm_year = tm_year(2038), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 59, + .tm_min = 59, + .tm_hour = 23, + .tm_mday = 18, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(2038), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), - Succeeds(0x7FFFFFFF - 8 - 14 * TimeConstants::SECONDS_PER_MIN - - 3 * TimeConstants::SECONDS_PER_HOUR)); + Succeeds(0x7FFFFFFF - 8 - + 14 * LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN - + 3 * LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR)); EXPECT_TM_EQ((tm{.tm_sec = 59, .tm_min = 59, .tm_hour = 23, @@ -469,15 +574,20 @@ TEST(LlvmLibcMkTime, EndOf32BitEpochYear) { { // 2038-01-18 23:59:59 tests that the final second of 2037 is // accepted. - struct tm tm_data { - .tm_sec = 59, .tm_min = 59, .tm_hour = 23, .tm_mday = 31, - .tm_mon = Month::DECEMBER, .tm_year = tm_year(2037), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 59, + .tm_min = 59, + .tm_hour = 23, + .tm_mday = 31, + .tm_mon = Month::DECEMBER, + .tm_year = tm_year(2037), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), - Succeeds(0x7FFFFFFF - 8 - 14 * TimeConstants::SECONDS_PER_MIN - - 3 * TimeConstants::SECONDS_PER_HOUR - - 18 * TimeConstants::SECONDS_PER_DAY)); + Succeeds(0x7FFFFFFF - 8 - + 14 * LIBC_NAMESPACE::time_constants::SECONDS_PER_MIN - + 3 * LIBC_NAMESPACE::time_constants::SECONDS_PER_HOUR - + 18 * LIBC_NAMESPACE::time_constants::SECONDS_PER_DAY)); EXPECT_TM_EQ((tm{.tm_sec = 59, .tm_min = 59, .tm_hour = 23, @@ -496,11 +606,15 @@ TEST(LlvmLibcMkTime, Max64BitYear) { return; { // Mon Jan 1 12:50:50 2170 (200 years from 1970), - struct tm tm_data { - .tm_sec = 50, .tm_min = 50, .tm_hour = 12, .tm_mday = 1, - .tm_mon = Month::JANUARY, .tm_year = tm_year(2170), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 50, + .tm_min = 50, + .tm_hour = 12, + .tm_mday = 1, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(2170), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Succeeds(6311479850)); EXPECT_TM_EQ((tm{.tm_sec = 50, .tm_min = 50, @@ -516,11 +630,15 @@ TEST(LlvmLibcMkTime, Max64BitYear) { { // Test for Tue Jan 1 12:50:50 in 2,147,483,647th year. - struct tm tm_data { - .tm_sec = 50, .tm_min = 50, .tm_hour = 12, .tm_mday = 1, - .tm_mon = Month::JANUARY, .tm_year = tm_year(2147483647), .tm_wday = 0, - .tm_yday = 0, .tm_isdst = 0 - }; + struct tm tm_data{.tm_sec = 50, + .tm_min = 50, + .tm_hour = 12, + .tm_mday = 1, + .tm_mon = Month::JANUARY, + .tm_year = tm_year(2147483647), + .tm_wday = 0, + .tm_yday = 0, + .tm_isdst = 0}; EXPECT_THAT(LIBC_NAMESPACE::mktime(&tm_data), Succeeds(67767976202043050)); EXPECT_TM_EQ((tm{.tm_sec = 50, .tm_min = 50, diff --git a/libc/test/src/time/nanosleep_test.cpp b/libc/test/src/time/nanosleep_test.cpp index 2a6eea4d5e161..d4f98e29bd980 100644 --- a/libc/test/src/time/nanosleep_test.cpp +++ b/libc/test/src/time/nanosleep_test.cpp @@ -6,8 +6,7 @@ // //===----------------------------------------------------------------------===// -#include - +#include "hdr/types/struct_timespec.h" #include "src/errno/libc_errno.h" #include "src/time/nanosleep.h" #include "test/UnitTest/ErrnoSetterMatcher.h" diff --git a/libc/utils/hdrgen/main.py b/libc/utils/hdrgen/main.py index 2bba1efa04e42..5dd392ab6662e 100755 --- a/libc/utils/hdrgen/main.py +++ b/libc/utils/hdrgen/main.py @@ -37,6 +37,12 @@ def main(): help="Path to write a depfile", type=Path, ) + parser.add_argument( + "--write-if-changed", + help="Write the output file only if its contents have changed", + action="store_true", + default=False, + ) parser.add_argument( "-e", "--entry-point", @@ -72,9 +78,13 @@ def write_depfile(): write_depfile() - args.output.parent.mkdir(parents=True, exist_ok=True) - with open(args.output, "w") as out: - out.write(contents) + if ( + not args.write_if_changed + or not args.output.exists() + or args.output.read_text() != contents + ): + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_text(contents) if __name__ == "__main__": diff --git a/libcxx/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst index c8a07fb8b7334..793b172a24af0 100644 --- a/libcxx/docs/ReleaseNotes/20.rst +++ b/libcxx/docs/ReleaseNotes/20.rst @@ -73,6 +73,39 @@ Improvements and New Features optimized, resulting in a performance improvement of up to 2x for trivial element types (e.g., `std::vector`), and up to 3.4x for non-trivial element types (e.g., `std::vector>`). +- On Windows, ````'s ``std::system_category`` is now distinct from ``std::generic_category``. The behavior + on other operating systems is unchanged. + + On Windows -- unlike on Unix systems -- the libc and system APIs use distinct error codes. The libc functions return + ``errno.h`` error codes via the ``errno`` global, while Win32 API functions return ``winerror.h`` error codes via + ``GetLastError()``. + + The C++ standard's ``std::error_code`` and ``std::error_category`` functionality was designed to support multiple + error domains, precisely in order to handle situations such as this. However, libc++ formerly treated + ``generic_category()`` and ``system_category()`` as equivalent, even on Windows. It now implements the intended split, + where ``system_category`` represents native ``winerror.h`` error codes, and ``generic_category`` represents libc error + codes (and, equivalently, ``std::errc::*`` errors). + + This change enables code like ``std::error_code(GetLastError(), std::system_category()) == + std::errc::invalid_argument`` to function as desired: constructing an ``error_code`` with the Windows error number in + the "system" category, and then mapping it to a generic code with ``error_condition``, for comparison with the + ``std::errc`` constant. + + This is an incompatible change: ``std::error_code(ENOSYS, std::system_category()) == + std::errc::function_not_supported`` would formerly have returned true, but now returns false on Windows. Code + providing a number from the ``errno.h`` domain should be migrated to construct a ``generic_category`` error_code, + instead. (E.g., use ``std::error_code(ENOSYS, std::generic_category())``). The new behavior matches MSVC. + +- On Windows, the ``std::filesystem`` library now returns the Win32 ``system_category`` error codes, where it's feasible + to do so. This allows interrogation and reporting of the original error code, which is useful if multiple Windows + errors map to a single generic error (such as with ``std::errc::no_such_file_or_directory``). + + This is also a slightly-incompatible API change: code inspecting the raw integer value from the returned error_code + expecting an integer from ``generic_category`` (e.g. ``err.value() == ENOTDIR``) will not work as desired. Instead, + such code should use the comparison operators which implicitly handle eror mappings, ``err == + std::errc::not_a_directory``, or use ``err.default_error_condition()`` to map to an ``error_condition``, and then test + its ``value()`` and ``category()``. + Deprecations and Removals ------------------------- @@ -92,9 +125,10 @@ Deprecations and Removals supported as an extension anymore, please migrate any code that uses e.g. ``std::vector`` to be standards conforming. -- Non-conforming member typedefs ``base``, ``iterator`` and ``const_iterator`` of ``std::bitset``, and member typedef - ``base`` of ``std::forward_list`` and ``std::list`` are removed. Previously, they were private but could cause - ambiguity in name lookup. Code that expects such ambiguity will possibly not compile in LLVM 20. +- Non-conforming member typedefs ``base``, ``iterator``, ``const_iterator``, and ``const_reference`` of ``std::bitset``, + and member typedef ``base`` of ``std::forward_list`` and ``std::list`` are removed. Previously, these member typedefs + (except ``const_reference``) were private but could cause ambiguity in name lookup. Code that expects such ambiguity + will possibly not compile in LLVM 20. - The function ``__libcpp_verbose_abort()`` is now ``noexcept``, to match ``std::terminate()``. (The combination of ``noexcept`` and ``[[noreturn]]`` has special significance for function effects analysis.) For backwards compatibility, diff --git a/libcxx/include/__algorithm/comp_ref_type.h b/libcxx/include/__algorithm/comp_ref_type.h index c367fbb91ac28..6a9d5cef26719 100644 --- a/libcxx/include/__algorithm/comp_ref_type.h +++ b/libcxx/include/__algorithm/comp_ref_type.h @@ -56,10 +56,10 @@ struct __debug_less { // Pass the comparator by lvalue reference. Or in the debug mode, using a debugging wrapper that stores a reference. #if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG template -using __comp_ref_type = __debug_less<_Comp>; +using __comp_ref_type _LIBCPP_NODEBUG = __debug_less<_Comp>; #else template -using __comp_ref_type = _Comp&; +using __comp_ref_type _LIBCPP_NODEBUG = _Comp&; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/copy.h b/libcxx/include/__algorithm/copy.h index 4f30b2050abba..962aa90059d57 100644 --- a/libcxx/include/__algorithm/copy.h +++ b/libcxx/include/__algorithm/copy.h @@ -47,7 +47,7 @@ struct __copy_impl { template struct _CopySegment { - using _Traits = __segmented_iterator_traits<_InIter>; + using _Traits _LIBCPP_NODEBUG = __segmented_iterator_traits<_InIter>; _OutIter& __result_; diff --git a/libcxx/include/__algorithm/iterator_operations.h b/libcxx/include/__algorithm/iterator_operations.h index 6cdb0aec9b2db..e5c89c1e67e3a 100644 --- a/libcxx/include/__algorithm/iterator_operations.h +++ b/libcxx/include/__algorithm/iterator_operations.h @@ -48,13 +48,13 @@ struct _RangeAlgPolicy {}; template <> struct _IterOps<_RangeAlgPolicy> { template - using __value_type = iter_value_t<_Iter>; + using __value_type _LIBCPP_NODEBUG = iter_value_t<_Iter>; template - using __iterator_category = ranges::__iterator_concept<_Iter>; + using __iterator_category _LIBCPP_NODEBUG = ranges::__iterator_concept<_Iter>; template - using __difference_type = iter_difference_t<_Iter>; + using __difference_type _LIBCPP_NODEBUG = iter_difference_t<_Iter>; static constexpr auto advance = ranges::advance; static constexpr auto distance = ranges::distance; @@ -72,13 +72,13 @@ struct _ClassicAlgPolicy {}; template <> struct _IterOps<_ClassicAlgPolicy> { template - using __value_type = typename iterator_traits<_Iter>::value_type; + using __value_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::value_type; template - using __iterator_category = typename iterator_traits<_Iter>::iterator_category; + using __iterator_category _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::iterator_category; template - using __difference_type = typename iterator_traits<_Iter>::difference_type; + using __difference_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::difference_type; // advance template @@ -94,10 +94,10 @@ struct _IterOps<_ClassicAlgPolicy> { } template - using __deref_t = decltype(*std::declval<_Iter&>()); + using __deref_t _LIBCPP_NODEBUG = decltype(*std::declval<_Iter&>()); template - using __move_t = decltype(std::move(*std::declval<_Iter&>())); + using __move_t _LIBCPP_NODEBUG = decltype(std::move(*std::declval<_Iter&>())); template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static void __validate_iter_reference() { @@ -217,7 +217,7 @@ struct _IterOps<_ClassicAlgPolicy> { }; template -using __policy_iter_diff_t = typename _IterOps<_AlgPolicy>::template __difference_type<_Iter>; +using __policy_iter_diff_t _LIBCPP_NODEBUG = typename _IterOps<_AlgPolicy>::template __difference_type<_Iter>; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/mismatch.h b/libcxx/include/__algorithm/mismatch.h index f5855379f6878..a6836792c0581 100644 --- a/libcxx/include/__algorithm/mismatch.h +++ b/libcxx/include/__algorithm/mismatch.h @@ -78,7 +78,7 @@ __mismatch_vectorized(_Iter __first1, _Iter __last1, _Iter __first2) { } for (size_t __i = 0; __i != __unroll_count; ++__i) { - if (auto __cmp_res = std::__as_mask(__lhs[__i] == __rhs[__i]); !std::__all_of(__cmp_res)) { + if (auto __cmp_res = __lhs[__i] == __rhs[__i]; !std::__all_of(__cmp_res)) { auto __offset = __i * __vec_size + std::__find_first_not_set(__cmp_res); return {__first1 + __offset, __first2 + __offset}; } @@ -90,7 +90,7 @@ __mismatch_vectorized(_Iter __first1, _Iter __last1, _Iter __first2) { // check the remaining 0-3 vectors while (static_cast(__last1 - __first1) >= __vec_size) { - if (auto __cmp_res = std::__as_mask(std::__load_vector<__vec>(__first1) == std::__load_vector<__vec>(__first2)); + if (auto __cmp_res = std::__load_vector<__vec>(__first1) == std::__load_vector<__vec>(__first2); !std::__all_of(__cmp_res)) { auto __offset = std::__find_first_not_set(__cmp_res); return {__first1 + __offset, __first2 + __offset}; @@ -107,8 +107,8 @@ __mismatch_vectorized(_Iter __first1, _Iter __last1, _Iter __first2) { if (static_cast(__first1 - __orig_first1) >= __vec_size) { __first1 = __last1 - __vec_size; __first2 = __last2 - __vec_size; - auto __offset = std::__find_first_not_set( - std::__as_mask(std::__load_vector<__vec>(__first1) == std::__load_vector<__vec>(__first2))); + auto __offset = + std::__find_first_not_set(std::__load_vector<__vec>(__first1) == std::__load_vector<__vec>(__first2)); return {__first1 + __offset, __first2 + __offset}; } // else loop over the elements individually } diff --git a/libcxx/include/__algorithm/move.h b/libcxx/include/__algorithm/move.h index 005099dcac06e..6f3b0eb5d2927 100644 --- a/libcxx/include/__algorithm/move.h +++ b/libcxx/include/__algorithm/move.h @@ -50,7 +50,7 @@ struct __move_impl { template struct _MoveSegment { - using _Traits = __segmented_iterator_traits<_InIter>; + using _Traits _LIBCPP_NODEBUG = __segmented_iterator_traits<_InIter>; _OutIter& __result_; diff --git a/libcxx/include/__algorithm/ranges_iterator_concept.h b/libcxx/include/__algorithm/ranges_iterator_concept.h index 2af891d3af005..58790e95aa803 100644 --- a/libcxx/include/__algorithm/ranges_iterator_concept.h +++ b/libcxx/include/__algorithm/ranges_iterator_concept.h @@ -44,7 +44,7 @@ consteval auto __get_iterator_concept() { } template -using __iterator_concept = decltype(__get_iterator_concept<_Iter>()); +using __iterator_concept _LIBCPP_NODEBUG = decltype(__get_iterator_concept<_Iter>()); } // namespace ranges _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__algorithm/ranges_unique_copy.h b/libcxx/include/__algorithm/ranges_unique_copy.h index 3b4a64e94ca1f..ee7f0a0187b73 100644 --- a/libcxx/include/__algorithm/ranges_unique_copy.h +++ b/libcxx/include/__algorithm/ranges_unique_copy.h @@ -60,7 +60,7 @@ struct __unique_copy { } template - using __algo_tag_t = decltype(__get_algo_tag<_InIter, _OutIter>()); + using __algo_tag_t _LIBCPP_NODEBUG = decltype(__get_algo_tag<_InIter, _OutIter>()); template _Sent, diff --git a/libcxx/include/__algorithm/simd_utils.h b/libcxx/include/__algorithm/simd_utils.h index 3ca79247bbd03..4e03723a32854 100644 --- a/libcxx/include/__algorithm/simd_utils.h +++ b/libcxx/include/__algorithm/simd_utils.h @@ -70,7 +70,7 @@ struct __get_as_integer_type_impl<8> { }; template -using __get_as_integer_type_t = typename __get_as_integer_type_impl::type; +using __get_as_integer_type_t _LIBCPP_NODEBUG = typename __get_as_integer_type_impl::type; // This isn't specialized for 64 byte vectors on purpose. They have the potential to significantly reduce performance // in mixed simd/non-simd workloads and don't provide any performance improvement for currently vectorized algorithms @@ -90,7 +90,7 @@ inline constexpr size_t __native_vector_size = 1; # endif template -using __simd_vector __attribute__((__ext_vector_type__(_Np))) = _ArithmeticT; +using __simd_vector __attribute__((__ext_vector_type__(_Np))) _LIBCPP_NODEBUG = _ArithmeticT; template inline constexpr size_t __simd_vector_size_v = []() -> size_t { @@ -106,7 +106,7 @@ _LIBCPP_HIDE_FROM_ABI _Tp __simd_vector_underlying_type_impl(__simd_vector<_Tp, } template -using __simd_vector_underlying_type_t = decltype(std::__simd_vector_underlying_type_impl(_VecT{})); +using __simd_vector_underlying_type_t _LIBCPP_NODEBUG = decltype(std::__simd_vector_underlying_type_impl(_VecT{})); // This isn't inlined without always_inline when loading chars. template @@ -116,65 +116,42 @@ template }(make_index_sequence<__simd_vector_size_v<_VecT>>{}); } -template -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector __vec) noexcept { - return __builtin_reduce_and(__vec); -} - template -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI auto __as_mask(__simd_vector<_Tp, _Np> __vec) noexcept { - static_assert(!is_same<_Tp, bool>::value, "vector type should not be a bool!"); - return __builtin_convertvector(__vec, __simd_vector); -} - -// This uses __builtin_convertvector around the __builtin_shufflevector to work around #107981. -template -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI __simd_vector -__extend_vector(__simd_vector __vec) noexcept { - using _VecT = __simd_vector; - if constexpr (_Np == 4) { - return __builtin_convertvector( - __builtin_shufflevector(__vec, _VecT{}, 0, 1, 2, 3, 4, 5, 6, 7), __simd_vector); - } else if constexpr (_Np == 2) { - return std::__extend_vector( - __builtin_convertvector(__builtin_shufflevector(__vec, _VecT{}, 0, 1, 2, 3), __simd_vector)); - } else if constexpr (_Np == 1) { - return std::__extend_vector( - __builtin_convertvector(__builtin_shufflevector(__vec, _VecT{}, 0, 1), __simd_vector)); - } else { - static_assert(sizeof(_VecT) == 0, "Unexpected vector size"); - } +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector<_Tp, _Np> __vec) noexcept { + return __builtin_reduce_and(__builtin_convertvector(__vec, __simd_vector)); } -template -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI auto __to_int_mask(__simd_vector __vec) { - if constexpr (_Np < 8) { - return std::__bit_cast(std::__extend_vector(__vec)); - } else if constexpr (_Np == 8) { - return std::__bit_cast(__vec); - } else if constexpr (_Np == 16) { - return std::__bit_cast(__vec); - } else if constexpr (_Np == 32) { - return std::__bit_cast(__vec); - } else if constexpr (_Np == 64) { - return std::__bit_cast(__vec); - } else { - static_assert(sizeof(__simd_vector) == 0, "Unexpected vector size"); - return 0; - } -} +template +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector<_Tp, _Np> __vec) noexcept { + using __mask_vec = __simd_vector; -template -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_set(__simd_vector __vec) noexcept { + // This has MSan disabled du to https://github.com/llvm/llvm-project/issues/85876 + auto __impl = [&](_MaskT) _LIBCPP_NO_SANITIZE("memory") noexcept { # if defined(_LIBCPP_BIG_ENDIAN) - return std::min(_Np, std::__countl_zero(std::__to_int_mask(__vec))); + return std::min( + _Np, std::__countl_zero(__builtin_bit_cast(_MaskT, __builtin_convertvector(__vec, __mask_vec)))); # else - return std::min(_Np, std::__countr_zero(std::__to_int_mask(__vec))); + return std::min( + _Np, std::__countr_zero(__builtin_bit_cast(_MaskT, __builtin_convertvector(__vec, __mask_vec)))); # endif + }; + + if constexpr (sizeof(__mask_vec) == sizeof(uint8_t)) { + return __impl(uint8_t{}); + } else if constexpr (sizeof(__mask_vec) == sizeof(uint16_t)) { + return __impl(uint16_t{}); + } else if constexpr (sizeof(__mask_vec) == sizeof(uint32_t)) { + return __impl(uint32_t{}); + } else if constexpr (sizeof(__mask_vec) == sizeof(uint64_t)) { + return __impl(uint64_t{}); + } else { + static_assert(sizeof(__mask_vec) == 0, "unexpected required size for mask integer type"); + return 0; + } } -template -[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_not_set(__simd_vector __vec) noexcept { +template +[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t __find_first_not_set(__simd_vector<_Tp, _Np> __vec) noexcept { return std::__find_first_set(~__vec); } diff --git a/libcxx/include/__algorithm/sort.h b/libcxx/include/__algorithm/sort.h index ed828b6d72314..5c60b23931cca 100644 --- a/libcxx/include/__algorithm/sort.h +++ b/libcxx/include/__algorithm/sort.h @@ -890,10 +890,10 @@ __sort_dispatch(_RandomAccessIterator __first, _RandomAccessIterator __last, _Co } template -using __is_any_of = _Or...>; +using __is_any_of _LIBCPP_NODEBUG = _Or...>; template -using __sort_is_specialized_in_library = __is_any_of< +using __sort_is_specialized_in_library _LIBCPP_NODEBUG = __is_any_of< _Type, char, #if _LIBCPP_HAS_WIDE_CHARACTERS diff --git a/libcxx/include/__algorithm/three_way_comp_ref_type.h b/libcxx/include/__algorithm/three_way_comp_ref_type.h index 5702a1fee0826..f6f76455e4664 100644 --- a/libcxx/include/__algorithm/three_way_comp_ref_type.h +++ b/libcxx/include/__algorithm/three_way_comp_ref_type.h @@ -61,10 +61,10 @@ struct __debug_three_way_comp { // Pass the comparator by lvalue reference. Or in the debug mode, using a debugging wrapper that stores a reference. # if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG template -using __three_way_comp_ref_type = __debug_three_way_comp<_Comp>; +using __three_way_comp_ref_type _LIBCPP_NODEBUG = __debug_three_way_comp<_Comp>; # else template -using __three_way_comp_ref_type = _Comp&; +using __three_way_comp_ref_type _LIBCPP_NODEBUG = _Comp&; # endif #endif // _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__algorithm/unwrap_iter.h b/libcxx/include/__algorithm/unwrap_iter.h index 8cc0d22d4fc21..b66a682e765fa 100644 --- a/libcxx/include/__algorithm/unwrap_iter.h +++ b/libcxx/include/__algorithm/unwrap_iter.h @@ -46,7 +46,7 @@ struct __unwrap_iter_impl { // It's a contiguous iterator, so we can use a raw pointer instead template struct __unwrap_iter_impl<_Iter, true> { - using _ToAddressT = decltype(std::__to_address(std::declval<_Iter>())); + using _ToAddressT _LIBCPP_NODEBUG = decltype(std::__to_address(std::declval<_Iter>())); static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Iter __rewrap(_Iter __orig_iter, _ToAddressT __unwrapped_iter) { return __orig_iter + (__unwrapped_iter - std::__to_address(__orig_iter)); diff --git a/libcxx/include/__atomic/aliases.h b/libcxx/include/__atomic/aliases.h index 37d11dd0aabf3..4fccebab25636 100644 --- a/libcxx/include/__atomic/aliases.h +++ b/libcxx/include/__atomic/aliases.h @@ -84,19 +84,19 @@ using atomic_uintmax_t = atomic; // C++20 atomic_{signed,unsigned}_lock_free: prefer the contention type most highly, then the largest lock-free type #if _LIBCPP_STD_VER >= 20 # if ATOMIC_LLONG_LOCK_FREE == 2 -using __largest_lock_free_type = long long; +using __largest_lock_free_type _LIBCPP_NODEBUG = long long; # elif ATOMIC_INT_LOCK_FREE == 2 -using __largest_lock_free_type = int; +using __largest_lock_free_type _LIBCPP_NODEBUG = int; # elif ATOMIC_SHORT_LOCK_FREE == 2 -using __largest_lock_free_type = short; +using __largest_lock_free_type _LIBCPP_NODEBUG = short; # elif ATOMIC_CHAR_LOCK_FREE == 2 -using __largest_lock_free_type = char; +using __largest_lock_free_type _LIBCPP_NODEBUG = char; # else # define _LIBCPP_NO_LOCK_FREE_TYPES // There are no lockfree types (this can happen on unusual platforms) # endif # ifndef _LIBCPP_NO_LOCK_FREE_TYPES -using __contention_t_or_largest = +using __contention_t_or_largest _LIBCPP_NODEBUG = __conditional_t<__libcpp_is_always_lock_free<__cxx_contention_t>::__value, __cxx_contention_t, __largest_lock_free_type>; diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h index 8029b52770d26..975a479e20400 100644 --- a/libcxx/include/__atomic/atomic.h +++ b/libcxx/include/__atomic/atomic.h @@ -143,7 +143,7 @@ struct __atomic_base // false template struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> { - using __base = __atomic_base<_Tp, false>; + using __base _LIBCPP_NODEBUG = __atomic_base<_Tp, false>; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __atomic_base() _NOEXCEPT = default; @@ -228,9 +228,9 @@ struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > { template struct atomic : public __atomic_base<_Tp> { - using __base = __atomic_base<_Tp>; - using value_type = _Tp; - using difference_type = value_type; + using __base _LIBCPP_NODEBUG = __atomic_base<_Tp>; + using value_type = _Tp; + using difference_type = value_type; #if _LIBCPP_STD_VER >= 20 _LIBCPP_HIDE_FROM_ABI atomic() = default; @@ -257,9 +257,9 @@ struct atomic : public __atomic_base<_Tp> { template struct atomic<_Tp*> : public __atomic_base<_Tp*> { - using __base = __atomic_base<_Tp*>; - using value_type = _Tp*; - using difference_type = ptrdiff_t; + using __base _LIBCPP_NODEBUG = __atomic_base<_Tp*>; + using value_type = _Tp*; + using difference_type = ptrdiff_t; _LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default; @@ -389,9 +389,9 @@ struct atomic<_Tp> : __atomic_base<_Tp> { } public: - using __base = __atomic_base<_Tp>; - using value_type = _Tp; - using difference_type = value_type; + using __base _LIBCPP_NODEBUG = __atomic_base<_Tp>; + using value_type = _Tp; + using difference_type = value_type; _LIBCPP_HIDE_FROM_ABI constexpr atomic() noexcept = default; _LIBCPP_HIDE_FROM_ABI constexpr atomic(_Tp __d) noexcept : __base(__d) {} diff --git a/libcxx/include/__atomic/atomic_ref.h b/libcxx/include/__atomic/atomic_ref.h index eef15983b9833..177ea646b6cd0 100644 --- a/libcxx/include/__atomic/atomic_ref.h +++ b/libcxx/include/__atomic/atomic_ref.h @@ -221,7 +221,7 @@ struct __atomic_ref_base { _LIBCPP_HIDE_FROM_ABI void notify_all() const noexcept { std::__atomic_notify_all(*this); } protected: - using _Aligned_Tp [[__gnu__::__aligned__(required_alignment)]] = _Tp; + using _Aligned_Tp [[__gnu__::__aligned__(required_alignment), __gnu__::__nodebug__]] = _Tp; _Aligned_Tp* __ptr_; _LIBCPP_HIDE_FROM_ABI __atomic_ref_base(_Tp& __obj) : __ptr_(std::addressof(__obj)) {} @@ -241,7 +241,7 @@ template struct atomic_ref : public __atomic_ref_base<_Tp> { static_assert(is_trivially_copyable_v<_Tp>, "std::atomic_ref requires that 'T' be a trivially copyable type"); - using __base = __atomic_ref_base<_Tp>; + using __base _LIBCPP_NODEBUG = __atomic_ref_base<_Tp>; _LIBCPP_HIDE_FROM_ABI explicit atomic_ref(_Tp& __obj) : __base(__obj) { _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( @@ -259,7 +259,7 @@ struct atomic_ref : public __atomic_ref_base<_Tp> { template requires(std::integral<_Tp> && !std::same_as) struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { - using __base = __atomic_ref_base<_Tp>; + using __base _LIBCPP_NODEBUG = __atomic_ref_base<_Tp>; using difference_type = __base::value_type; @@ -305,7 +305,7 @@ struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { template requires std::floating_point<_Tp> struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { - using __base = __atomic_ref_base<_Tp>; + using __base _LIBCPP_NODEBUG = __atomic_ref_base<_Tp>; using difference_type = __base::value_type; @@ -344,7 +344,7 @@ struct atomic_ref<_Tp> : public __atomic_ref_base<_Tp> { template struct atomic_ref<_Tp*> : public __atomic_ref_base<_Tp*> { - using __base = __atomic_ref_base<_Tp*>; + using __base _LIBCPP_NODEBUG = __atomic_ref_base<_Tp*>; using difference_type = ptrdiff_t; diff --git a/libcxx/include/__atomic/atomic_sync.h b/libcxx/include/__atomic/atomic_sync.h index 153001e7b62e3..ab9bc59fdcfe7 100644 --- a/libcxx/include/__atomic/atomic_sync.h +++ b/libcxx/include/__atomic/atomic_sync.h @@ -81,7 +81,7 @@ struct __atomic_wait_backoff_impl { _Poll __poll_; memory_order __order_; - using __waitable_traits = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >; + using __waitable_traits _LIBCPP_NODEBUG = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >; _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI bool diff --git a/libcxx/include/__atomic/contention_t.h b/libcxx/include/__atomic/contention_t.h index 6f2a073bc1a8e..5b42a0125f875 100644 --- a/libcxx/include/__atomic/contention_t.h +++ b/libcxx/include/__atomic/contention_t.h @@ -20,12 +20,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if defined(__linux__) || (defined(_AIX) && !defined(__64BIT__)) -using __cxx_contention_t = int32_t; +using __cxx_contention_t _LIBCPP_NODEBUG = int32_t; #else -using __cxx_contention_t = int64_t; +using __cxx_contention_t _LIBCPP_NODEBUG = int64_t; #endif // __linux__ || (_AIX && !__64BIT__) -using __cxx_atomic_contention_t = __cxx_atomic_impl<__cxx_contention_t>; +using __cxx_atomic_contention_t _LIBCPP_NODEBUG = __cxx_atomic_impl<__cxx_contention_t>; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__atomic/memory_order.h b/libcxx/include/__atomic/memory_order.h index 294121d1c4e7f..44790fe888b36 100644 --- a/libcxx/include/__atomic/memory_order.h +++ b/libcxx/include/__atomic/memory_order.h @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // to pin the underlying type in C++20. enum __legacy_memory_order { __mo_relaxed, __mo_consume, __mo_acquire, __mo_release, __mo_acq_rel, __mo_seq_cst }; -using __memory_order_underlying_t = underlying_type<__legacy_memory_order>::type; +using __memory_order_underlying_t _LIBCPP_NODEBUG = underlying_type<__legacy_memory_order>::type; #if _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__bit_reference b/libcxx/include/__bit_reference index 9fa24c98d493f..7e27090cc68a4 100644 --- a/libcxx/include/__bit_reference +++ b/libcxx/include/__bit_reference @@ -43,8 +43,8 @@ struct __has_storage_type { template ::value> class __bit_reference { - using __storage_type = typename _Cp::__storage_type; - using __storage_pointer = typename _Cp::__storage_pointer; + using __storage_type _LIBCPP_NODEBUG = typename _Cp::__storage_type; + using __storage_pointer _LIBCPP_NODEBUG = typename _Cp::__storage_pointer; __storage_pointer __seg_; __storage_type __mask_; @@ -55,7 +55,7 @@ class __bit_reference { friend class __bit_iterator<_Cp, false>; public: - using __container = typename _Cp::__self; + using __container _LIBCPP_NODEBUG = typename _Cp::__self; _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_reference(const __bit_reference&) = default; @@ -135,8 +135,8 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(bool& __x, template class __bit_const_reference { - using __storage_type = typename _Cp::__storage_type; - using __storage_pointer = typename _Cp::__const_storage_pointer; + using __storage_type _LIBCPP_NODEBUG = typename _Cp::__storage_type; + using __storage_pointer _LIBCPP_NODEBUG = typename _Cp::__const_storage_pointer; __storage_pointer __seg_; __storage_type __mask_; @@ -145,7 +145,7 @@ class __bit_const_reference { friend class __bit_iterator<_Cp, true>; public: - using __container = typename _Cp::__self; + using __container _LIBCPP_NODEBUG = typename _Cp::__self; _LIBCPP_HIDE_FROM_ABI __bit_const_reference(const __bit_const_reference&) = default; __bit_const_reference& operator=(const __bit_const_reference&) = delete; @@ -587,10 +587,10 @@ inline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> swap_ranges( template struct __bit_array { - using difference_type = typename _Cp::difference_type; - using __storage_type = typename _Cp::__storage_type; - using __storage_pointer = typename _Cp::__storage_pointer; - using iterator = typename _Cp::iterator; + using difference_type _LIBCPP_NODEBUG = typename _Cp::difference_type; + using __storage_type _LIBCPP_NODEBUG = typename _Cp::__storage_type; + using __storage_pointer _LIBCPP_NODEBUG = typename _Cp::__storage_pointer; + using iterator _LIBCPP_NODEBUG = typename _Cp::iterator; static const unsigned __bits_per_word = _Cp::__bits_per_word; static const unsigned _Np = 4; @@ -790,8 +790,8 @@ public: using iterator_category = random_access_iterator_tag; private: - using __storage_type = typename _Cp::__storage_type; - using __storage_pointer = + using __storage_type _LIBCPP_NODEBUG = typename _Cp::__storage_type; + using __storage_pointer _LIBCPP_NODEBUG = __conditional_t<_IsConst, typename _Cp::__const_storage_pointer, typename _Cp::__storage_pointer>; static const unsigned __bits_per_word = _Cp::__bits_per_word; diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h index 3671e6aa52b49..1086dde381955 100644 --- a/libcxx/include/__chrono/formatter.h +++ b/libcxx/include/__chrono/formatter.h @@ -711,7 +711,7 @@ struct _LIBCPP_TEMPLATE_VIS __formatter_chrono { template struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -722,7 +722,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : pub template struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -733,7 +733,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : pu template struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -745,7 +745,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : p template struct formatter, _CharT> : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -767,7 +767,7 @@ struct formatter, _CharT> : public __formatter_c template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -778,7 +778,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_ template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -789,7 +789,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __formatte template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -800,7 +800,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -811,7 +811,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __format template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -822,7 +822,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -833,7 +833,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __f template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -844,7 +844,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __form template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -855,7 +855,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public _ template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -866,7 +866,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __ template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -877,7 +877,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : publ template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -888,7 +888,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __for template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -899,7 +899,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public _ template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -910,7 +910,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : pub template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -921,7 +921,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : publ template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -932,7 +932,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : template struct formatter, _CharT> : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -944,7 +944,7 @@ struct formatter, _CharT> : public __formatter_chron template <__fmt_char_type _CharT> struct formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -955,7 +955,7 @@ struct formatter : public __formatter_chrono<_CharT> { template <__fmt_char_type _CharT> struct formatter : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { @@ -968,7 +968,7 @@ struct formatter : public __formatter_chrono<_CharT> template struct formatter, _CharT> : public __formatter_chrono<_CharT> { public: - using _Base = __formatter_chrono<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>; template _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { diff --git a/libcxx/include/__chrono/hh_mm_ss.h b/libcxx/include/__chrono/hh_mm_ss.h index c460b11305085..6ea8a28ee0938 100644 --- a/libcxx/include/__chrono/hh_mm_ss.h +++ b/libcxx/include/__chrono/hh_mm_ss.h @@ -30,7 +30,7 @@ template class hh_mm_ss { private: static_assert(__is_duration_v<_Duration>, "template parameter of hh_mm_ss must be a std::chrono::duration"); - using __CommonType = common_type_t<_Duration, chrono::seconds>; + using __CommonType _LIBCPP_NODEBUG = common_type_t<_Duration, chrono::seconds>; _LIBCPP_HIDE_FROM_ABI static constexpr uint64_t __pow10(unsigned __exp) { uint64_t __ret = 1; diff --git a/libcxx/include/__chrono/parser_std_format_spec.h b/libcxx/include/__chrono/parser_std_format_spec.h index 3976864c12b98..4df8e603c6bcf 100644 --- a/libcxx/include/__chrono/parser_std_format_spec.h +++ b/libcxx/include/__chrono/parser_std_format_spec.h @@ -140,7 +140,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __validate_time_zone(__flags __flags) { template class _LIBCPP_TEMPLATE_VIS __parser_chrono { - using _ConstIterator = typename basic_format_parse_context<_CharT>::const_iterator; + using _ConstIterator _LIBCPP_NODEBUG = typename basic_format_parse_context<_CharT>::const_iterator; public: template diff --git a/libcxx/include/__chrono/zoned_time.h b/libcxx/include/__chrono/zoned_time.h index f57e65c90a624..1deba10d96ae8 100644 --- a/libcxx/include/__chrono/zoned_time.h +++ b/libcxx/include/__chrono/zoned_time.h @@ -66,7 +66,7 @@ class zoned_time { // Using these constraints in the code causes the compiler to give an // error that the constraint depends on itself. To avoid that issue use // the fact it is possible to create this object from a _TimeZonePtr. - using __traits = zoned_traits<_TimeZonePtr>; + using __traits _LIBCPP_NODEBUG = zoned_traits<_TimeZonePtr>; public: using duration = common_type_t<_Duration, seconds>; @@ -186,7 +186,7 @@ template zoned_time(sys_time<_Duration>) -> zoned_time>; template -using __time_zone_representation = +using __time_zone_representation _LIBCPP_NODEBUG = conditional_t, const time_zone*, remove_cvref_t<_TimeZonePtrOrName>>; diff --git a/libcxx/include/__compare/ordering.h b/libcxx/include/__compare/ordering.h index 297218e6f29e5..902ef5329dd43 100644 --- a/libcxx/include/__compare/ordering.h +++ b/libcxx/include/__compare/ordering.h @@ -120,7 +120,7 @@ inline constexpr partial_ordering partial_ordering::greater(_PartialOrdResult::_ inline constexpr partial_ordering partial_ordering::unordered(_PartialOrdResult::__unordered); class weak_ordering { - using _ValueT = signed char; + using _ValueT _LIBCPP_NODEBUG = signed char; _LIBCPP_HIDE_FROM_ABI explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} @@ -190,7 +190,7 @@ inline constexpr weak_ordering weak_ordering::equivalent(_OrdResult::__equiv); inline constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater); class strong_ordering { - using _ValueT = signed char; + using _ValueT _LIBCPP_NODEBUG = signed char; _LIBCPP_HIDE_FROM_ABI explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} diff --git a/libcxx/include/__compare/synth_three_way.h b/libcxx/include/__compare/synth_three_way.h index e48ce49799836..63bf56d0cf42b 100644 --- a/libcxx/include/__compare/synth_three_way.h +++ b/libcxx/include/__compare/synth_three_way.h @@ -43,7 +43,8 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr auto __synth_three_way = [] -using __synth_three_way_result = decltype(std::__synth_three_way(std::declval<_Tp&>(), std::declval<_Up&>())); +using __synth_three_way_result _LIBCPP_NODEBUG = + decltype(std::__synth_three_way(std::declval<_Tp&>(), std::declval<_Up&>())); #endif // _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h index 7df46a0e94dce..6257e6f729bf3 100644 --- a/libcxx/include/__exception/exception_ptr.h +++ b/libcxx/include/__exception/exception_ptr.h @@ -66,7 +66,7 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { public: // exception_ptr is basically a COW string. - using __trivially_relocatable = exception_ptr; + using __trivially_relocatable _LIBCPP_NODEBUG = exception_ptr; _LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {} _LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h index 3d3f11967ee74..03bbd1623ed5c 100644 --- a/libcxx/include/__expected/expected.h +++ b/libcxx/include/__expected/expected.h @@ -459,14 +459,14 @@ class expected : private __expected_base<_Tp, _Err> { template friend class expected; - using __base = __expected_base<_Tp, _Err>; + using __base _LIBCPP_NODEBUG = __expected_base<_Tp, _Err>; public: using value_type = _Tp; using error_type = _Err; using unexpected_type = unexpected<_Err>; - using __trivially_relocatable = + using __trivially_relocatable _LIBCPP_NODEBUG = __conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value && __libcpp_is_trivially_relocatable<_Err>::value, expected, void>; @@ -505,7 +505,7 @@ class expected : private __expected_base<_Tp, _Err> { private: template - using __can_convert = _And< + using __can_convert _LIBCPP_NODEBUG = _And< is_constructible<_Tp, _UfQual>, is_constructible<_Err, _OtherErrQual>, _If<_Not, bool>>::value, @@ -1363,7 +1363,7 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> { friend class expected; template - using __can_convert = + using __can_convert _LIBCPP_NODEBUG = _And< is_void<_Up>, is_constructible<_Err, _OtherErrQual>, _Not, expected<_Up, _OtherErr>&>>, @@ -1371,7 +1371,7 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> { _Not, const expected<_Up, _OtherErr>&>>, _Not, const expected<_Up, _OtherErr>>>>; - using __base = __expected_void_base<_Err>; + using __base _LIBCPP_NODEBUG = __expected_void_base<_Err>; public: using value_type = _Tp; diff --git a/libcxx/include/__expected/unexpected.h b/libcxx/include/__expected/unexpected.h index cf110bcf69a82..6904889b8c6b1 100644 --- a/libcxx/include/__expected/unexpected.h +++ b/libcxx/include/__expected/unexpected.h @@ -48,12 +48,12 @@ template struct __is_std_unexpected> : true_type {}; template -using __valid_std_unexpected = _BoolConstant< // - is_object_v<_Tp> && // - !is_array_v<_Tp> && // - !__is_std_unexpected<_Tp>::value && // - !is_const_v<_Tp> && // - !is_volatile_v<_Tp> // +using __valid_std_unexpected _LIBCPP_NODEBUG = _BoolConstant< // + is_object_v<_Tp> && // + !is_array_v<_Tp> && // + !__is_std_unexpected<_Tp>::value && // + !is_const_v<_Tp> && // + !is_volatile_v<_Tp> // >; template diff --git a/libcxx/include/__filesystem/directory_entry.h b/libcxx/include/__filesystem/directory_entry.h index 7d0c01b98def6..11e07acdbe00c 100644 --- a/libcxx/include/__filesystem/directory_entry.h +++ b/libcxx/include/__filesystem/directory_entry.h @@ -22,7 +22,9 @@ #include <__filesystem/perms.h> #include <__fwd/ostream.h> #include <__system_error/errc.h> +#include <__system_error/error_category.h> #include <__system_error/error_code.h> +#include <__system_error/error_condition.h> #include <__utility/move.h> #include <__utility/unreachable.h> #include @@ -274,15 +276,7 @@ class directory_entry { _LIBCPP_EXPORTED_FROM_ABI error_code __do_refresh() noexcept; _LIBCPP_HIDE_FROM_ABI static bool __is_dne_error(error_code const& __ec) { - if (!__ec) - return true; - switch (static_cast(__ec.value())) { - case errc::no_such_file_or_directory: - case errc::not_a_directory: - return true; - default: - return false; - } + return !__ec || __ec == errc::no_such_file_or_directory || __ec == errc::not_a_directory; } _LIBCPP_HIDE_FROM_ABI void diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h index 509d1cc8052f0..0a751ba32954f 100644 --- a/libcxx/include/__filesystem/path.h +++ b/libcxx/include/__filesystem/path.h @@ -51,30 +51,30 @@ template struct __can_convert_char : public __can_convert_char<_Tp> {}; template <> struct __can_convert_char { - static const bool value = true; - using __char_type = char; + static const bool value = true; + using __char_type _LIBCPP_NODEBUG = char; }; template <> struct __can_convert_char { - static const bool value = true; - using __char_type = wchar_t; + static const bool value = true; + using __char_type _LIBCPP_NODEBUG = wchar_t; }; # if _LIBCPP_HAS_CHAR8_T template <> struct __can_convert_char { - static const bool value = true; - using __char_type = char8_t; + static const bool value = true; + using __char_type _LIBCPP_NODEBUG = char8_t; }; # endif template <> struct __can_convert_char { - static const bool value = true; - using __char_type = char16_t; + static const bool value = true; + using __char_type _LIBCPP_NODEBUG = char16_t; }; template <> struct __can_convert_char { - static const bool value = true; - using __char_type = char32_t; + static const bool value = true; + using __char_type _LIBCPP_NODEBUG = char32_t; }; template ::value, int> = 0> @@ -95,7 +95,7 @@ typedef string __u8_string; struct _NullSentinel {}; template -using _Void = void; +using _Void _LIBCPP_NODEBUG = void; template struct __is_pathable_string : public false_type {}; @@ -104,7 +104,7 @@ template struct __is_pathable_string< basic_string<_ECharT, _Traits, _Alloc>, _Void::__char_type> > : public __can_convert_char<_ECharT> { - using _Str = basic_string<_ECharT, _Traits, _Alloc>; + using _Str _LIBCPP_NODEBUG = basic_string<_ECharT, _Traits, _Alloc>; _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } @@ -117,7 +117,7 @@ template struct __is_pathable_string< basic_string_view<_ECharT, _Traits>, _Void::__char_type> > : public __can_convert_char<_ECharT> { - using _Str = basic_string_view<_ECharT, _Traits>; + using _Str _LIBCPP_NODEBUG = basic_string_view<_ECharT, _Traits>; _LIBCPP_HIDE_FROM_ABI static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } @@ -157,7 +157,7 @@ struct __is_pathable_iter< true, _Void::value_type>::__char_type> > : __can_convert_char::value_type> { - using _ECharT = typename iterator_traits<_Iter>::value_type; + using _ECharT _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::value_type; _LIBCPP_HIDE_FROM_ABI static _Iter __range_begin(_Iter __b) { return __b; } @@ -380,13 +380,13 @@ struct _PathExport { class _LIBCPP_EXPORTED_FROM_ABI path { template - using _EnableIfPathable = __enable_if_t<__is_pathable<_SourceOrIter>::value, _Tp>; + using _EnableIfPathable _LIBCPP_NODEBUG = __enable_if_t<__is_pathable<_SourceOrIter>::value, _Tp>; template - using _SourceChar = typename __is_pathable<_Tp>::__char_type; + using _SourceChar _LIBCPP_NODEBUG = typename __is_pathable<_Tp>::__char_type; template - using _SourceCVT = _PathCVT<_SourceChar<_Tp> >; + using _SourceCVT _LIBCPP_NODEBUG = _PathCVT<_SourceChar<_Tp> >; public: # if defined(_LIBCPP_WIN32API) diff --git a/libcxx/include/__flat_map/flat_map.h b/libcxx/include/__flat_map/flat_map.h index b66bc1cb66fc1..9fe84250b1204 100644 --- a/libcxx/include/__flat_map/flat_map.h +++ b/libcxx/include/__flat_map/flat_map.h @@ -90,7 +90,7 @@ class flat_map { static_assert(!is_same_v<_MappedContainer, std::vector>, "vector is not a sequence container"); template - using __iterator = __key_value_iterator; + using __iterator _LIBCPP_NODEBUG = __key_value_iterator; public: // types diff --git a/libcxx/include/__flat_map/key_value_iterator.h b/libcxx/include/__flat_map/key_value_iterator.h index 987ac677a4130..06a23f3429974 100644 --- a/libcxx/include/__flat_map/key_value_iterator.h +++ b/libcxx/include/__flat_map/key_value_iterator.h @@ -41,9 +41,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template struct __key_value_iterator { private: - using __key_iterator = ranges::iterator_t; - using __mapped_iterator = ranges::iterator_t<__maybe_const<_Const, _MappedContainer>>; - using __reference = _If<_Const, typename _Owner::const_reference, typename _Owner::reference>; + using __key_iterator _LIBCPP_NODEBUG = ranges::iterator_t; + using __mapped_iterator _LIBCPP_NODEBUG = ranges::iterator_t<__maybe_const<_Const, _MappedContainer>>; + using __reference _LIBCPP_NODEBUG = _If<_Const, typename _Owner::const_reference, typename _Owner::reference>; struct __arrow_proxy { __reference __ref_; diff --git a/libcxx/include/__format/buffer.h b/libcxx/include/__format/buffer.h index 618b8ef025643..9509f19e16724 100644 --- a/libcxx/include/__format/buffer.h +++ b/libcxx/include/__format/buffer.h @@ -322,7 +322,7 @@ struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container class _LIBCPP_TEMPLATE_VIS __writer_container { public: - using _CharT = typename _Container::value_type; + using _CharT _LIBCPP_NODEBUG = typename _Container::value_type; _LIBCPP_HIDE_FROM_ABI explicit __writer_container(back_insert_iterator<_Container> __out_it) : __container_{__out_it.__get_container()} {} @@ -340,7 +340,7 @@ class _LIBCPP_TEMPLATE_VIS __writer_container { /// Selects the type of the writer used for the output iterator. template class _LIBCPP_TEMPLATE_VIS __writer_selector { - using _Container = typename __back_insert_iterator_container<_OutIt>::type; + using _Container _LIBCPP_NODEBUG = typename __back_insert_iterator_container<_OutIt>::type; public: using type = @@ -355,7 +355,7 @@ class _LIBCPP_TEMPLATE_VIS __writer_selector { template requires(output_iterator<_OutIt, const _CharT&>) class _LIBCPP_TEMPLATE_VIS __format_buffer { - using _Storage = + using _Storage _LIBCPP_NODEBUG = conditional_t<__enable_direct_output<_OutIt, _CharT>, __direct_storage<_CharT>, __internal_storage<_CharT>>; public: @@ -408,7 +408,7 @@ class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer { template requires(output_iterator<_OutIt, const _CharT&>) struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base { - using _Size = iter_difference_t<_OutIt>; + using _Size _LIBCPP_NODEBUG = iter_difference_t<_OutIt>; public: _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size) @@ -438,7 +438,7 @@ struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base { template requires(output_iterator<_OutIt, const _CharT&>) class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer_base<_OutIt, _CharT, true> { - using _Size = iter_difference_t<_OutIt>; + using _Size _LIBCPP_NODEBUG = iter_difference_t<_OutIt>; public: _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer_base(_OutIt __out_it, _Size __max_size) @@ -489,8 +489,8 @@ template requires(output_iterator<_OutIt, const _CharT&>) struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer final : public __format_to_n_buffer_base< _OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>> { - using _Base = __format_to_n_buffer_base<_OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>>; - using _Size = iter_difference_t<_OutIt>; + using _Base _LIBCPP_NODEBUG = __format_to_n_buffer_base<_OutIt, _CharT, __enable_direct_output<_OutIt, _CharT>>; + using _Size _LIBCPP_NODEBUG = iter_difference_t<_OutIt>; public: _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer(_OutIt __out_it, _Size __max_size) @@ -523,7 +523,7 @@ struct _LIBCPP_TEMPLATE_VIS __format_to_n_buffer final // would lead to a circular include with formatter for vector. template <__fmt_char_type _CharT> class _LIBCPP_TEMPLATE_VIS __retarget_buffer { - using _Alloc = allocator<_CharT>; + using _Alloc _LIBCPP_NODEBUG = allocator<_CharT>; public: using value_type = _CharT; diff --git a/libcxx/include/__format/concepts.h b/libcxx/include/__format/concepts.h index 2c40e3e314917..28297c612db77 100644 --- a/libcxx/include/__format/concepts.h +++ b/libcxx/include/__format/concepts.h @@ -44,7 +44,7 @@ concept __fmt_char_type = // (Note testing for (w)format_context would be a valid choice, but requires // selecting the proper one depending on the type of _CharT.) template -using __fmt_iter_for = _CharT*; +using __fmt_iter_for _LIBCPP_NODEBUG = _CharT*; template >> concept __formattable_with = diff --git a/libcxx/include/__format/container_adaptor.h b/libcxx/include/__format/container_adaptor.h index d3be2e1895604..48d42ee7d901b 100644 --- a/libcxx/include/__format/container_adaptor.h +++ b/libcxx/include/__format/container_adaptor.h @@ -37,8 +37,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD template struct _LIBCPP_TEMPLATE_VIS __formatter_container_adaptor { private: - using __maybe_const_container = __fmt_maybe_const; - using __maybe_const_adaptor = __maybe_const, _Adaptor>; + using __maybe_const_container _LIBCPP_NODEBUG = __fmt_maybe_const; + using __maybe_const_adaptor _LIBCPP_NODEBUG = __maybe_const, _Adaptor>; formatter, _CharT> __underlying_; public: diff --git a/libcxx/include/__format/format_arg.h b/libcxx/include/__format/format_arg.h index a973ccd43c420..1c530fd5a5d03 100644 --- a/libcxx/include/__format/format_arg.h +++ b/libcxx/include/__format/format_arg.h @@ -208,7 +208,7 @@ _LIBCPP_HIDE_FROM_ABI _Rp __visit_format_arg(_Visitor&& __vis, basic_format_arg< /// separate arrays. template class __basic_format_arg_value { - using _CharT = typename _Context::char_type; + using _CharT _LIBCPP_NODEBUG = typename _Context::char_type; public: /// Contains the implementation for basic_format_arg::handle. diff --git a/libcxx/include/__format/format_arg_store.h b/libcxx/include/__format/format_arg_store.h index 8b2c95c657c9b..4c5ee9e9e4fd3 100644 --- a/libcxx/include/__format/format_arg_store.h +++ b/libcxx/include/__format/format_arg_store.h @@ -257,7 +257,7 @@ struct _LIBCPP_TEMPLATE_VIS __format_arg_store { } } - using _Storage = + using _Storage _LIBCPP_NODEBUG = conditional_t<__format::__use_packed_format_arg_store(sizeof...(_Args)), __format::__packed_format_arg_store<_Context, sizeof...(_Args)>, __format::__unpacked_format_arg_store<_Context, sizeof...(_Args)>>; diff --git a/libcxx/include/__format/format_functions.h b/libcxx/include/__format/format_functions.h index 3991363c0124e..b920be5acbe86 100644 --- a/libcxx/include/__format/format_functions.h +++ b/libcxx/include/__format/format_functions.h @@ -379,7 +379,7 @@ struct _LIBCPP_TEMPLATE_VIS basic_format_string { private: basic_string_view<_CharT> __str_; - using _Context = __format::__compile_time_basic_format_context<_CharT>; + using _Context _LIBCPP_NODEBUG = __format::__compile_time_basic_format_context<_CharT>; static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{ __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...}; diff --git a/libcxx/include/__format/formatter_floating_point.h b/libcxx/include/__format/formatter_floating_point.h index e04fffb683c3a..ac4be9b619355 100644 --- a/libcxx/include/__format/formatter_floating_point.h +++ b/libcxx/include/__format/formatter_floating_point.h @@ -141,7 +141,7 @@ struct __traits { /// on the stack or the heap. template class _LIBCPP_TEMPLATE_VIS __float_buffer { - using _Traits = __traits<_Fp>; + using _Traits _LIBCPP_NODEBUG = __traits<_Fp>; public: // TODO FMT Improve this constructor to do a better estimate. diff --git a/libcxx/include/__format/formatter_string.h b/libcxx/include/__format/formatter_string.h index 826d6421c8631..30084e582214d 100644 --- a/libcxx/include/__format/formatter_string.h +++ b/libcxx/include/__format/formatter_string.h @@ -59,7 +59,7 @@ struct _LIBCPP_TEMPLATE_VIS __formatter_string { // Formatter const char*. template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter : public __formatter_string<_CharT> { - using _Base = __formatter_string<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const _CharT* __str, _FormatContext& __ctx) const { @@ -78,7 +78,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter : public __formatte // Formatter char*. template <__fmt_char_type _CharT> struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT> : public formatter { - using _Base = formatter; + using _Base _LIBCPP_NODEBUG = formatter; template _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_CharT* __str, _FormatContext& __ctx) const { @@ -89,7 +89,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT> : public formatter struct _LIBCPP_TEMPLATE_VIS formatter<_CharT[_Size], _CharT> : public __formatter_string<_CharT> { - using _Base = __formatter_string<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator @@ -102,7 +102,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter<_CharT[_Size], _CharT> : public __formatte template <__fmt_char_type _CharT, class _Traits, class _Allocator> struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_string<_CharT> { - using _Base = __formatter_string<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator @@ -115,7 +115,7 @@ struct _LIBCPP_TEMPLATE_VIS formatter, // Formatter std::string_view. template <__fmt_char_type _CharT, class _Traits> struct _LIBCPP_TEMPLATE_VIS formatter, _CharT> : public __formatter_string<_CharT> { - using _Base = __formatter_string<_CharT>; + using _Base _LIBCPP_NODEBUG = __formatter_string<_CharT>; template _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator diff --git a/libcxx/include/__format/range_default_formatter.h b/libcxx/include/__format/range_default_formatter.h index fb21b0f8beb3a..bb4c520f5ea11 100644 --- a/libcxx/include/__format/range_default_formatter.h +++ b/libcxx/include/__format/range_default_formatter.h @@ -40,7 +40,7 @@ concept __const_formattable_range = ranges::input_range && formattable, _CharT>; template -using __fmt_maybe_const = conditional_t<__const_formattable_range<_Rp, _CharT>, const _Rp, _Rp>; +using __fmt_maybe_const _LIBCPP_NODEBUG = conditional_t<__const_formattable_range<_Rp, _CharT>, const _Rp, _Rp>; _LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wshadow") @@ -95,7 +95,7 @@ struct _LIBCPP_TEMPLATE_VIS __range_default_formatter; template struct _LIBCPP_TEMPLATE_VIS __range_default_formatter { private: - using __maybe_const_r = __fmt_maybe_const<_Rp, _CharT>; + using __maybe_const_r _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; range_formatter>, _CharT> __underlying_; public: @@ -122,8 +122,8 @@ struct _LIBCPP_TEMPLATE_VIS __range_default_formatter struct _LIBCPP_TEMPLATE_VIS __range_default_formatter { private: - using __maybe_const_map = __fmt_maybe_const<_Rp, _CharT>; - using __element_type = remove_cvref_t>; + using __maybe_const_map _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; + using __element_type _LIBCPP_NODEBUG = remove_cvref_t>; range_formatter<__element_type, _CharT> __underlying_; public: @@ -150,8 +150,8 @@ struct _LIBCPP_TEMPLATE_VIS __range_default_formatter struct _LIBCPP_TEMPLATE_VIS __range_default_formatter { private: - using __maybe_const_set = __fmt_maybe_const<_Rp, _CharT>; - using __element_type = remove_cvref_t>; + using __maybe_const_set _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; + using __element_type _LIBCPP_NODEBUG = remove_cvref_t>; range_formatter<__element_type, _CharT> __underlying_; public: diff --git a/libcxx/include/__format/unicode.h b/libcxx/include/__format/unicode.h index b4f22c739d6a1..46096fda1e8ae 100644 --- a/libcxx/include/__format/unicode.h +++ b/libcxx/include/__format/unicode.h @@ -123,7 +123,7 @@ class __code_point_view; /// UTF-8 specialization. template <> class __code_point_view { - using _Iterator = basic_string_view::const_iterator; + using _Iterator _LIBCPP_NODEBUG = basic_string_view::const_iterator; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) @@ -249,7 +249,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __is_surrogate_pair_low(wchar_t __value) { /// - 4 UTF-32 (for example Linux) template <> class __code_point_view { - using _Iterator = typename basic_string_view::const_iterator; + using _Iterator _LIBCPP_NODEBUG = typename basic_string_view::const_iterator; public: static_assert(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4, "sizeof(wchar_t) has a not implemented value"); @@ -300,8 +300,8 @@ class __code_point_view { // This implements the extended rules see // https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries class __extended_grapheme_cluster_break { - using __EGC_property = __extended_grapheme_custer_property_boundary::__property; - using __inCB_property = __indic_conjunct_break::__property; + using __EGC_property _LIBCPP_NODEBUG = __extended_grapheme_custer_property_boundary::__property; + using __inCB_property _LIBCPP_NODEBUG = __indic_conjunct_break::__property; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_break(char32_t __first_code_point) @@ -527,7 +527,7 @@ class __extended_grapheme_cluster_break { /// Therefore only this code point is extracted. template class __extended_grapheme_cluster_view { - using _Iterator = typename basic_string_view<_CharT>::const_iterator; + using _Iterator _LIBCPP_NODEBUG = typename basic_string_view<_CharT>::const_iterator; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit __extended_grapheme_cluster_view(_Iterator __first, _Iterator __last) @@ -572,7 +572,7 @@ __extended_grapheme_cluster_view(_Iterator, _Iterator) -> __extended_grapheme_cl // This makes it easier to write code agnostic of the _LIBCPP_HAS_UNICODE define. template class __code_point_view { - using _Iterator = typename basic_string_view<_CharT>::const_iterator; + using _Iterator _LIBCPP_NODEBUG = typename basic_string_view<_CharT>::const_iterator; public: _LIBCPP_HIDE_FROM_ABI constexpr explicit __code_point_view(_Iterator __first, _Iterator __last) diff --git a/libcxx/include/__functional/binary_function.h b/libcxx/include/__functional/binary_function.h index ddee3b170311f..bde8b03ef8281 100644 --- a/libcxx/include/__functional/binary_function.h +++ b/libcxx/include/__functional/binary_function.h @@ -42,11 +42,11 @@ struct __binary_function_keep_layout_base { _LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated-declarations") template -using __binary_function = binary_function<_Arg1, _Arg2, _Result>; +using __binary_function _LIBCPP_NODEBUG = binary_function<_Arg1, _Arg2, _Result>; _LIBCPP_DIAGNOSTIC_POP #else template -using __binary_function = __binary_function_keep_layout_base<_Arg1, _Arg2, _Result>; +using __binary_function _LIBCPP_NODEBUG = __binary_function_keep_layout_base<_Arg1, _Arg2, _Result>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__functional/bind.h b/libcxx/include/__functional/bind.h index f82c1517249b1..e31ad29790355 100644 --- a/libcxx/include/__functional/bind.h +++ b/libcxx/include/__functional/bind.h @@ -198,7 +198,7 @@ __apply_functor(_Fp& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>, _ template class __bind : public __weak_result_type<__decay_t<_Fp> > { protected: - using _Fd = __decay_t<_Fp>; + using _Fd _LIBCPP_NODEBUG = __decay_t<_Fp>; typedef tuple<__decay_t<_BoundArgs>...> _Td; private: diff --git a/libcxx/include/__functional/boyer_moore_searcher.h b/libcxx/include/__functional/boyer_moore_searcher.h index 52a58d57a8d40..1e49cc5464be5 100644 --- a/libcxx/include/__functional/boyer_moore_searcher.h +++ b/libcxx/include/__functional/boyer_moore_searcher.h @@ -92,7 +92,7 @@ class _LIBCPP_TEMPLATE_VIS boyer_moore_searcher { private: using difference_type = typename std::iterator_traits<_RandomAccessIterator1>::difference_type; using value_type = typename std::iterator_traits<_RandomAccessIterator1>::value_type; - using __skip_table_type = + using __skip_table_type _LIBCPP_NODEBUG = _BMSkipTable::difference_type; using value_type = typename iterator_traits<_RandomAccessIterator1>::value_type; - using __skip_table_type = + using __skip_table_type _LIBCPP_NODEBUG = _BMSkipTable -using __fast_forward = __conditional_t::value, _Tp, _Tp&&>; +using __fast_forward _LIBCPP_NODEBUG = __conditional_t::value, _Tp, _Tp&&>; // __policy_invoker calls an instance of __alloc_func held in __policy_storage. @@ -847,7 +847,7 @@ class _LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)> }; template - using _EnableIfLValueCallable = __enable_if_t<__callable<_Fp&>::value>; + using _EnableIfLValueCallable _LIBCPP_NODEBUG = __enable_if_t<__callable<_Fp&>::value>; public: typedef _Rp result_type; diff --git a/libcxx/include/__functional/perfect_forward.h b/libcxx/include/__functional/perfect_forward.h index 8fd68db3d6eb8..37c3d15b4bec0 100644 --- a/libcxx/include/__functional/perfect_forward.h +++ b/libcxx/include/__functional/perfect_forward.h @@ -94,7 +94,7 @@ struct __perfect_forward_impl<_Op, index_sequence<_Idx...>, _BoundArgs...> { // __perfect_forward implements a perfect-forwarding call wrapper as explained in [func.require]. template -using __perfect_forward = __perfect_forward_impl<_Op, index_sequence_for<_Args...>, _Args...>; +using __perfect_forward _LIBCPP_NODEBUG = __perfect_forward_impl<_Op, index_sequence_for<_Args...>, _Args...>; #endif // _LIBCPP_STD_VER >= 17 diff --git a/libcxx/include/__functional/unary_function.h b/libcxx/include/__functional/unary_function.h index 69b1bc94220ae..769ffc9893a72 100644 --- a/libcxx/include/__functional/unary_function.h +++ b/libcxx/include/__functional/unary_function.h @@ -39,11 +39,11 @@ struct __unary_function_keep_layout_base { _LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wdeprecated-declarations") template -using __unary_function = unary_function<_Arg, _Result>; +using __unary_function _LIBCPP_NODEBUG = unary_function<_Arg, _Result>; _LIBCPP_DIAGNOSTIC_POP #else template -using __unary_function = __unary_function_keep_layout_base<_Arg, _Result>; +using __unary_function _LIBCPP_NODEBUG = __unary_function_keep_layout_base<_Arg, _Result>; #endif _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index 9c821ea690813..7788f687746f0 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -111,8 +111,8 @@ struct __hash_node_base { template struct __hash_node : public __hash_node_base< __rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > > { typedef _Tp __node_value_type; - using _Base = __hash_node_base<__rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > >; - using __next_pointer = typename _Base::__next_pointer; + using _Base _LIBCPP_NODEBUG = __hash_node_base<__rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > >; + using __next_pointer _LIBCPP_NODEBUG = typename _Base::__next_pointer; size_t __hash_; diff --git a/libcxx/include/__iterator/aliasing_iterator.h b/libcxx/include/__iterator/aliasing_iterator.h index aeb5b4a88ec37..e01127142ae98 100644 --- a/libcxx/include/__iterator/aliasing_iterator.h +++ b/libcxx/include/__iterator/aliasing_iterator.h @@ -31,8 +31,8 @@ struct __aliasing_iterator_wrapper { class __iterator { _BaseIter __base_ = nullptr; - using __iter_traits = iterator_traits<_BaseIter>; - using __base_value_type = typename __iter_traits::value_type; + using __iter_traits _LIBCPP_NODEBUG = iterator_traits<_BaseIter>; + using __base_value_type _LIBCPP_NODEBUG = typename __iter_traits::value_type; static_assert(__has_random_access_iterator_category<_BaseIter>::value, "The base iterator has to be a random access iterator!"); @@ -120,7 +120,7 @@ struct __aliasing_iterator_wrapper { // This is required to avoid ADL instantiations on _BaseT template -using __aliasing_iterator = typename __aliasing_iterator_wrapper<_BaseT, _Alias>::__iterator; +using __aliasing_iterator _LIBCPP_NODEBUG = typename __aliasing_iterator_wrapper<_BaseT, _Alias>::__iterator; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__iterator/concepts.h b/libcxx/include/__iterator/concepts.h index 1c227933a482a..6e5ac1d3af37b 100644 --- a/libcxx/include/__iterator/concepts.h +++ b/libcxx/include/__iterator/concepts.h @@ -67,10 +67,10 @@ template concept indirectly_readable = __indirectly_readable_impl>; template -using __projected_iterator_t = typename _Tp::__projected_iterator; +using __projected_iterator_t _LIBCPP_NODEBUG = typename _Tp::__projected_iterator; template -using __projected_projection_t = typename _Tp::__projected_projection; +using __projected_projection_t _LIBCPP_NODEBUG = typename _Tp::__projected_projection; template concept __specialization_of_projected = requires { @@ -89,7 +89,7 @@ struct __indirect_value_t_impl<_Tp> { }; template -using __indirect_value_t = typename __indirect_value_t_impl<_Tp>::type; +using __indirect_value_t _LIBCPP_NODEBUG = typename __indirect_value_t_impl<_Tp>::type; template using iter_common_reference_t = common_reference_t, __indirect_value_t<_Tp>>; @@ -274,7 +274,7 @@ concept indirectly_copyable_storable = #endif // _LIBCPP_STD_VER >= 20 template -using __has_random_access_iterator_category_or_concept +using __has_random_access_iterator_category_or_concept _LIBCPP_NODEBUG #if _LIBCPP_STD_VER >= 20 = integral_constant>; #else // _LIBCPP_STD_VER < 20 diff --git a/libcxx/include/__iterator/insert_iterator.h b/libcxx/include/__iterator/insert_iterator.h index b3311042014f8..e0ee0ce035e2a 100644 --- a/libcxx/include/__iterator/insert_iterator.h +++ b/libcxx/include/__iterator/insert_iterator.h @@ -29,10 +29,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template -using __insert_iterator_iter_t = ranges::iterator_t<_Container>; +using __insert_iterator_iter_t _LIBCPP_NODEBUG = ranges::iterator_t<_Container>; #else template -using __insert_iterator_iter_t = typename _Container::iterator; +using __insert_iterator_iter_t _LIBCPP_NODEBUG = typename _Container::iterator; #endif _LIBCPP_SUPPRESS_DEPRECATED_PUSH diff --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h index eb6ba8b62fb30..db68dd2c377ac 100644 --- a/libcxx/include/__iterator/iterator_traits.h +++ b/libcxx/include/__iterator/iterator_traits.h @@ -47,7 +47,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template -using __with_reference = _Tp&; +using __with_reference _LIBCPP_NODEBUG = _Tp&; template concept __can_reference = requires { typename __with_reference<_Tp>; }; @@ -80,19 +80,20 @@ struct __iter_traits_cache { using type = _If< __is_primary_template >::value, _Iter, iterator_traits<_Iter> >; }; template -using _ITER_TRAITS = typename __iter_traits_cache<_Iter>::type; +using _ITER_TRAITS _LIBCPP_NODEBUG = typename __iter_traits_cache<_Iter>::type; struct __iter_concept_concept_test { template - using _Apply = typename _ITER_TRAITS<_Iter>::iterator_concept; + using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_concept; }; struct __iter_concept_category_test { template - using _Apply = typename _ITER_TRAITS<_Iter>::iterator_category; + using _Apply _LIBCPP_NODEBUG = typename _ITER_TRAITS<_Iter>::iterator_category; }; struct __iter_concept_random_fallback { template - using _Apply = __enable_if_t< __is_primary_template >::value, random_access_iterator_tag >; + using _Apply _LIBCPP_NODEBUG = + __enable_if_t<__is_primary_template >::value, random_access_iterator_tag>; }; template @@ -106,7 +107,7 @@ struct __iter_concept_cache { }; template -using _ITER_CONCEPT = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>; +using _ITER_CONCEPT _LIBCPP_NODEBUG = typename __iter_concept_cache<_Iter>::type::template _Apply<_Iter>; template struct __has_iterator_typedefs { @@ -364,7 +365,7 @@ struct __iterator_traits<_Ip> { template struct iterator_traits : __iterator_traits<_Ip> { - using __primary_template = iterator_traits; + using __primary_template _LIBCPP_NODEBUG = iterator_traits; }; #else // _LIBCPP_STD_VER >= 20 @@ -397,7 +398,7 @@ struct __iterator_traits<_Iter, true> template struct _LIBCPP_TEMPLATE_VIS iterator_traits : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> { - using __primary_template = iterator_traits; + using __primary_template _LIBCPP_NODEBUG = iterator_traits; }; #endif // _LIBCPP_STD_VER >= 20 @@ -430,16 +431,19 @@ template struct __has_iterator_concept_convertible_to<_Tp, _Up, false> : false_type {}; template -using __has_input_iterator_category = __has_iterator_category_convertible_to<_Tp, input_iterator_tag>; +using __has_input_iterator_category _LIBCPP_NODEBUG = __has_iterator_category_convertible_to<_Tp, input_iterator_tag>; template -using __has_forward_iterator_category = __has_iterator_category_convertible_to<_Tp, forward_iterator_tag>; +using __has_forward_iterator_category _LIBCPP_NODEBUG = + __has_iterator_category_convertible_to<_Tp, forward_iterator_tag>; template -using __has_bidirectional_iterator_category = __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>; +using __has_bidirectional_iterator_category _LIBCPP_NODEBUG = + __has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>; template -using __has_random_access_iterator_category = __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>; +using __has_random_access_iterator_category _LIBCPP_NODEBUG = + __has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>; // __libcpp_is_contiguous_iterator determines if an iterator is known by // libc++ to be contiguous, either because it advertises itself as such @@ -466,48 +470,49 @@ template class __wrap_iter; template -using __has_exactly_input_iterator_category = +using __has_exactly_input_iterator_category _LIBCPP_NODEBUG = integral_constant::value && !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value>; template -using __has_exactly_forward_iterator_category = +using __has_exactly_forward_iterator_category _LIBCPP_NODEBUG = integral_constant::value && !__has_iterator_category_convertible_to<_Tp, bidirectional_iterator_tag>::value>; template -using __has_exactly_bidirectional_iterator_category = +using __has_exactly_bidirectional_iterator_category _LIBCPP_NODEBUG = integral_constant::value && !__has_iterator_category_convertible_to<_Tp, random_access_iterator_tag>::value>; template -using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; +using __iter_value_type _LIBCPP_NODEBUG = typename iterator_traits<_InputIterator>::value_type; template -using __iter_key_type = __remove_const_t::value_type::first_type>; +using __iter_key_type _LIBCPP_NODEBUG = + __remove_const_t::value_type::first_type>; template -using __iter_mapped_type = typename iterator_traits<_InputIterator>::value_type::second_type; +using __iter_mapped_type _LIBCPP_NODEBUG = typename iterator_traits<_InputIterator>::value_type::second_type; template -using __iter_to_alloc_type = +using __iter_to_alloc_type _LIBCPP_NODEBUG = pair::value_type::first_type, typename iterator_traits<_InputIterator>::value_type::second_type>; template -using __iterator_category_type = typename iterator_traits<_Iter>::iterator_category; +using __iterator_category_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::iterator_category; template -using __iterator_pointer_type = typename iterator_traits<_Iter>::pointer; +using __iterator_pointer_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::pointer; template -using __iter_diff_t = typename iterator_traits<_Iter>::difference_type; +using __iter_diff_t _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::difference_type; template -using __iter_reference = typename iterator_traits<_Iter>::reference; +using __iter_reference _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::reference; #if _LIBCPP_STD_VER >= 20 diff --git a/libcxx/include/__iterator/projected.h b/libcxx/include/__iterator/projected.h index 1c560ec055001..d12f0167de1df 100644 --- a/libcxx/include/__iterator/projected.h +++ b/libcxx/include/__iterator/projected.h @@ -26,9 +26,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD template struct __projected_impl { struct __type { - using __primary_template = __type; - using __projected_iterator = _It; - using __projected_projection = _Proj; + using __primary_template _LIBCPP_NODEBUG = __type; + using __projected_iterator _LIBCPP_NODEBUG = _It; + using __projected_projection _LIBCPP_NODEBUG = _Proj; using value_type = remove_cvref_t>; indirect_result_t<_Proj&, _It> operator*() const; // not defined @@ -38,9 +38,9 @@ struct __projected_impl { template struct __projected_impl<_It, _Proj> { struct __type { - using __primary_template = __type; - using __projected_iterator = _It; - using __projected_projection = _Proj; + using __primary_template _LIBCPP_NODEBUG = __type; + using __projected_iterator _LIBCPP_NODEBUG = _It; + using __projected_projection _LIBCPP_NODEBUG = _Proj; using value_type = remove_cvref_t>; using difference_type = iter_difference_t<_It>; diff --git a/libcxx/include/__iterator/ranges_iterator_traits.h b/libcxx/include/__iterator/ranges_iterator_traits.h index 859e7082048ac..9a31b651eb5da 100644 --- a/libcxx/include/__iterator/ranges_iterator_traits.h +++ b/libcxx/include/__iterator/ranges_iterator_traits.h @@ -24,13 +24,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 23 template -using __range_key_type = __remove_const_t::first_type>; +using __range_key_type _LIBCPP_NODEBUG = __remove_const_t::first_type>; template -using __range_mapped_type = typename ranges::range_value_t<_Range>::second_type; +using __range_mapped_type _LIBCPP_NODEBUG = typename ranges::range_value_t<_Range>::second_type; template -using __range_to_alloc_type = +using __range_to_alloc_type _LIBCPP_NODEBUG = pair::first_type, typename ranges::range_value_t<_Range>::second_type>; #endif diff --git a/libcxx/include/__iterator/reverse_iterator.h b/libcxx/include/__iterator/reverse_iterator.h index 5e88d86ad5e9b..5bd1f868d3ff3 100644 --- a/libcxx/include/__iterator/reverse_iterator.h +++ b/libcxx/include/__iterator/reverse_iterator.h @@ -329,8 +329,8 @@ __reverse_range(_Range&& __range) { template struct __unwrap_iter_impl >, __b> { - using _UnwrappedIter = decltype(__unwrap_iter_impl<_Iter>::__unwrap(std::declval<_Iter>())); - using _ReverseWrapper = reverse_iterator >; + using _UnwrappedIter _LIBCPP_NODEBUG = decltype(__unwrap_iter_impl<_Iter>::__unwrap(std::declval<_Iter>())); + using _ReverseWrapper _LIBCPP_NODEBUG = reverse_iterator >; static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ReverseWrapper __rewrap(_ReverseWrapper __orig_iter, _UnwrappedIter __unwrapped_iter) { diff --git a/libcxx/include/__iterator/segmented_iterator.h b/libcxx/include/__iterator/segmented_iterator.h index 8cb54a35a7f5e..7a8e1addeacd9 100644 --- a/libcxx/include/__iterator/segmented_iterator.h +++ b/libcxx/include/__iterator/segmented_iterator.h @@ -72,7 +72,7 @@ template struct __has_specialization<_Tp, sizeof(_Tp) * 0> : true_type {}; template -using __is_segmented_iterator = __has_specialization<__segmented_iterator_traits<_Iterator> >; +using __is_segmented_iterator _LIBCPP_NODEBUG = __has_specialization<__segmented_iterator_traits<_Iterator> >; _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/__locale b/libcxx/include/__locale index b675e01bac81e..94dc8a08437bf 100644 --- a/libcxx/include/__locale +++ b/libcxx/include/__locale @@ -50,7 +50,7 @@ _LIBCPP_HIDE_FROM_ABI const _Facet& use_facet(const locale&); class _LIBCPP_EXPORTED_FROM_ABI locale { public: // locale is essentially a shared_ptr that doesn't support weak_ptrs and never got a move constructor. - using __trivially_relocatable = locale; + using __trivially_relocatable _LIBCPP_NODEBUG = locale; // types: class _LIBCPP_EXPORTED_FROM_ABI facet; diff --git a/libcxx/include/__locale_dir/locale_base_api.h b/libcxx/include/__locale_dir/locale_base_api.h index c8097beb9052d..cda6033b03db7 100644 --- a/libcxx/include/__locale_dir/locale_base_api.h +++ b/libcxx/include/__locale_dir/locale_base_api.h @@ -56,6 +56,7 @@ // int __strcoll(const char*, const char*, __locale_t); // size_t __strxfrm(char*, const char*, size_t, __locale_t); // +// int __iswctype(wint_t, wctype_t, __locale_t); // int __iswspace(wint_t, __locale_t); // int __iswprint(wint_t, __locale_t); // int __iswcntrl(wint_t, __locale_t); @@ -135,7 +136,7 @@ namespace __locale { // // Locale management // -using __locale_t = locale_t; +using __locale_t _LIBCPP_NODEBUG = locale_t; inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __name, __locale_t __loc) { return newlocale(__category_mask, __name, __loc); @@ -192,6 +193,9 @@ inline _LIBCPP_HIDE_FROM_ABI int __wcscoll(const wchar_t* __s1, const wchar_t* _ inline _LIBCPP_HIDE_FROM_ABI size_t __wcsxfrm(wchar_t* __dest, const wchar_t* __src, size_t __n, __locale_t __loc) { return wcsxfrm_l(__dest, __src, __n, __loc); } +inline _LIBCPP_HIDE_FROM_ABI int __iswctype(wint_t __ch, wctype_t __type, __locale_t __loc) { + return iswctype_l(__ch, __type, __loc); +} inline _LIBCPP_HIDE_FROM_ABI int __iswspace(wint_t __ch, __locale_t __loc) { return iswspace_l(__ch, __loc); } inline _LIBCPP_HIDE_FROM_ABI int __iswprint(wint_t __ch, __locale_t __loc) { return iswprint_l(__ch, __loc); } inline _LIBCPP_HIDE_FROM_ABI int __iswcntrl(wint_t __ch, __locale_t __loc) { return iswcntrl_l(__ch, __loc); } diff --git a/libcxx/include/__locale_dir/support/bsd_like.h b/libcxx/include/__locale_dir/support/bsd_like.h index da31aeaf3c58e..b3933c71c6b26 100644 --- a/libcxx/include/__locale_dir/support/bsd_like.h +++ b/libcxx/include/__locale_dir/support/bsd_like.h @@ -94,6 +94,10 @@ inline _LIBCPP_HIDE_FROM_ABI size_t __strxfrm(char* __dest, const char* __src, s } #if _LIBCPP_HAS_WIDE_CHARACTERS +inline _LIBCPP_HIDE_FROM_ABI int __iswctype(wint_t __c, wctype_t __type, __locale_t __loc) { + return ::iswctype_l(__c, __type, __loc); +} + inline _LIBCPP_HIDE_FROM_ABI int __iswspace(wint_t __c, __locale_t __loc) { return ::iswspace_l(__c, __loc); } inline _LIBCPP_HIDE_FROM_ABI int __iswprint(wint_t __c, __locale_t __loc) { return ::iswprint_l(__c, __loc); } diff --git a/libcxx/include/__locale_dir/support/windows.h b/libcxx/include/__locale_dir/support/windows.h index 03d05a410fdc3..eca0e17d94c85 100644 --- a/libcxx/include/__locale_dir/support/windows.h +++ b/libcxx/include/__locale_dir/support/windows.h @@ -206,6 +206,9 @@ inline _LIBCPP_HIDE_FROM_ABI size_t __strxfrm(char* __dest, const char* __src, s } #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +inline _LIBCPP_HIDE_FROM_ABI int __iswctype(wint_t __c, wctype_t __type, __locale_t __loc) { + return ::_iswctype_l(__c, __type, __loc); +} inline _LIBCPP_HIDE_FROM_ABI int __iswspace(wint_t __c, __locale_t __loc) { return ::_iswspace_l(__c, __loc); } inline _LIBCPP_HIDE_FROM_ABI int __iswprint(wint_t __c, __locale_t __loc) { return ::_iswprint_l(__c, __loc); } inline _LIBCPP_HIDE_FROM_ABI int __iswcntrl(wint_t __c, __locale_t __loc) { return ::_iswcntrl_l(__c, __loc); } diff --git a/libcxx/include/__mdspan/extents.h b/libcxx/include/__mdspan/extents.h index edbc30a7a40e4..65a697769bdaa 100644 --- a/libcxx/include/__mdspan/extents.h +++ b/libcxx/include/__mdspan/extents.h @@ -129,14 +129,14 @@ struct __maybe_static_array { // Static values member static constexpr size_t __size_ = sizeof...(_Values); static constexpr size_t __size_dynamic_ = ((_Values == _DynTag) + ... + 0); - using _StaticValues = __static_array<_TStatic, _Values...>; - using _DynamicValues = __possibly_empty_array<_TDynamic, __size_dynamic_>; + using _StaticValues _LIBCPP_NODEBUG = __static_array<_TStatic, _Values...>; + using _DynamicValues _LIBCPP_NODEBUG = __possibly_empty_array<_TDynamic, __size_dynamic_>; // Dynamic values member _LIBCPP_NO_UNIQUE_ADDRESS _DynamicValues __dyn_vals_; // static mapping of indices to the position in the dynamic values array - using _DynamicIdxMap = __static_partial_sums(_Values == _DynTag)...>; + using _DynamicIdxMap _LIBCPP_NODEBUG = __static_partial_sums(_Values == _DynTag)...>; template _LIBCPP_HIDE_FROM_ABI static constexpr _DynamicValues __zeros(index_sequence<_Indices...>) noexcept { @@ -292,7 +292,8 @@ class extents { static constexpr rank_type __rank_dynamic_ = ((_Extents == dynamic_extent) + ... + 0); // internal storage type using __maybe_static_array - using _Values = __mdspan_detail::__maybe_static_array<_IndexType, size_t, dynamic_extent, _Extents...>; + using _Values _LIBCPP_NODEBUG = + __mdspan_detail::__maybe_static_array<_IndexType, size_t, dynamic_extent, _Extents...>; [[no_unique_address]] _Values __vals_; public: diff --git a/libcxx/include/__memory/allocation_guard.h b/libcxx/include/__memory/allocation_guard.h index 66d6a5002c299..66edcd92ed618 100644 --- a/libcxx/include/__memory/allocation_guard.h +++ b/libcxx/include/__memory/allocation_guard.h @@ -45,8 +45,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD // custom allocator. template struct __allocation_guard { - using _Pointer = typename allocator_traits<_Alloc>::pointer; - using _Size = typename allocator_traits<_Alloc>::size_type; + using _Pointer _LIBCPP_NODEBUG = typename allocator_traits<_Alloc>::pointer; + using _Size _LIBCPP_NODEBUG = typename allocator_traits<_Alloc>::size_type; template // we perform the allocator conversion inside the constructor _LIBCPP_HIDE_FROM_ABI explicit __allocation_guard(_AllocT __alloc, _Size __n) diff --git a/libcxx/include/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h index e35cfb7c3b878..afe3d1bf8a2de 100644 --- a/libcxx/include/__memory/pointer_traits.h +++ b/libcxx/include/__memory/pointer_traits.h @@ -176,10 +176,10 @@ struct _LIBCPP_TEMPLATE_VIS pointer_traits<_Tp*> { #ifndef _LIBCPP_CXX03_LANG template -using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>; +using __rebind_pointer_t _LIBCPP_NODEBUG = typename pointer_traits<_From>::template rebind<_To>; #else template -using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>::other; +using __rebind_pointer_t _LIBCPP_NODEBUG = typename pointer_traits<_From>::template rebind<_To>::other; #endif // to_address @@ -276,7 +276,7 @@ struct __pointer_of<_Tp> { }; template -using __pointer_of_t = typename __pointer_of<_Tp>::type; +using __pointer_of_t _LIBCPP_NODEBUG = typename __pointer_of<_Tp>::type; template struct __pointer_of_or { @@ -290,7 +290,7 @@ struct __pointer_of_or<_Tp, _Up> { }; template -using __pointer_of_or_t = typename __pointer_of_or<_Tp, _Up>::type; +using __pointer_of_or_t _LIBCPP_NODEBUG = typename __pointer_of_or<_Tp, _Up>::type; template concept __resettable_smart_pointer = requires(_Smart __s) { __s.reset(); }; diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h index 97e4031499ed5..06b1fc488cf51 100644 --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -141,7 +141,7 @@ struct __for_overwrite_tag {}; template struct __shared_ptr_emplace : __shared_weak_count { - using __value_type = __remove_cv_t<_Tp>; + using __value_type _LIBCPP_NODEBUG = __remove_cv_t<_Tp>; template -using __shared_ptr_nullptr_deleter_ctor_reqs = _And, __well_formed_deleter<_Dp, nullptr_t> >; +using __shared_ptr_nullptr_deleter_ctor_reqs _LIBCPP_NODEBUG = + _And, __well_formed_deleter<_Dp, nullptr_t> >; #if defined(_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI) # define _LIBCPP_SHARED_PTR_TRIVIAL_ABI __attribute__((__trivial_abi__)) @@ -315,7 +316,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr { // A shared_ptr contains only two raw pointers which point to the heap and move constructing already doesn't require // any bookkeeping, so it's always trivially relocatable. - using __trivially_relocatable = shared_ptr; + using __trivially_relocatable _LIBCPP_NODEBUG = shared_ptr; private: element_type* __ptr_; @@ -1210,7 +1211,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr { // A weak_ptr contains only two raw pointers which point to the heap and move constructing already doesn't require // any bookkeeping, so it's always trivially relocatable. - using __trivially_relocatable = weak_ptr; + using __trivially_relocatable _LIBCPP_NODEBUG = weak_ptr; private: element_type* __ptr_; diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h index 2368f7b03e005..29d391fc80fe4 100644 --- a/libcxx/include/__memory/unique_ptr.h +++ b/libcxx/include/__memory/unique_ptr.h @@ -153,7 +153,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr { // // This unique_ptr implementation only contains a pointer to the unique object and a deleter, so there are no // references to itself. This means that the entire structure is trivially relocatable if its members are. - using __trivially_relocatable = __conditional_t< + using __trivially_relocatable _LIBCPP_NODEBUG = __conditional_t< __libcpp_is_trivially_relocatable::value && __libcpp_is_trivially_relocatable::value, unique_ptr, void>; @@ -189,7 +189,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr { (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) >; template - using _EnableIfDeleterAssignable = __enable_if_t< is_assignable<_Dp&, _UDel&&>::value >; + using _EnableIfDeleterAssignable _LIBCPP_NODEBUG = __enable_if_t< is_assignable<_Dp&, _UDel&&>::value >; public: template > @@ -419,7 +419,7 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> // // This unique_ptr implementation only contains a pointer to the unique object and a deleter, so there are no // references to itself. This means that the entire structure is trivially relocatable if its members are. - using __trivially_relocatable = __conditional_t< + using __trivially_relocatable _LIBCPP_NODEBUG = __conditional_t< __libcpp_is_trivially_relocatable::value && __libcpp_is_trivially_relocatable::value, unique_ptr, void>; @@ -430,9 +430,9 @@ class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> _LIBCPP_COMPRESSED_PAIR(pointer, __ptr_, deleter_type, __deleter_); #ifdef _LIBCPP_ABI_BOUNDED_UNIQUE_PTR - using _BoundsChecker = __unique_ptr_array_bounds_stored; + using _BoundsChecker _LIBCPP_NODEBUG = __unique_ptr_array_bounds_stored; #else - using _BoundsChecker = __unique_ptr_array_bounds_stateless; + using _BoundsChecker _LIBCPP_NODEBUG = __unique_ptr_array_bounds_stateless; #endif _LIBCPP_NO_UNIQUE_ADDRESS _BoundsChecker __checker_; diff --git a/libcxx/include/__memory/unique_temporary_buffer.h b/libcxx/include/__memory/unique_temporary_buffer.h index ca6292338c005..dea7fa8e18728 100644 --- a/libcxx/include/__memory/unique_temporary_buffer.h +++ b/libcxx/include/__memory/unique_temporary_buffer.h @@ -45,7 +45,7 @@ struct __temporary_buffer_deleter { }; template -using __unique_temporary_buffer = unique_ptr<_Tp, __temporary_buffer_deleter<_Tp> >; +using __unique_temporary_buffer _LIBCPP_NODEBUG = unique_ptr<_Tp, __temporary_buffer_deleter<_Tp> >; template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _LIBCPP_CONSTEXPR_SINCE_CXX23 __unique_temporary_buffer<_Tp> diff --git a/libcxx/include/__node_handle b/libcxx/include/__node_handle index d0b35bfd19340..8f32f2de83391 100644 --- a/libcxx/include/__node_handle +++ b/libcxx/include/__node_handle @@ -188,10 +188,10 @@ struct __map_node_handle_specifics { }; template -using __set_node_handle = __basic_node_handle< _NodeType, _Alloc, __set_node_handle_specifics>; +using __set_node_handle _LIBCPP_NODEBUG = __basic_node_handle< _NodeType, _Alloc, __set_node_handle_specifics>; template -using __map_node_handle = __basic_node_handle< _NodeType, _Alloc, __map_node_handle_specifics>; +using __map_node_handle _LIBCPP_NODEBUG = __basic_node_handle< _NodeType, _Alloc, __map_node_handle_specifics>; template struct _LIBCPP_TEMPLATE_VIS __insert_return_type { diff --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h index 2132e8dbceb3a..a7d53b6a1c989 100644 --- a/libcxx/include/__pstl/backend_fwd.h +++ b/libcxx/include/__pstl/backend_fwd.h @@ -53,11 +53,13 @@ struct __serial_backend_tag; struct __std_thread_backend_tag; # if defined(_LIBCPP_PSTL_BACKEND_SERIAL) -using __current_configuration = __backend_configuration<__serial_backend_tag, __default_backend_tag>; +using __current_configuration _LIBCPP_NODEBUG = __backend_configuration<__serial_backend_tag, __default_backend_tag>; # elif defined(_LIBCPP_PSTL_BACKEND_STD_THREAD) -using __current_configuration = __backend_configuration<__std_thread_backend_tag, __default_backend_tag>; +using __current_configuration _LIBCPP_NODEBUG = + __backend_configuration<__std_thread_backend_tag, __default_backend_tag>; # elif defined(_LIBCPP_PSTL_BACKEND_LIBDISPATCH) -using __current_configuration = __backend_configuration<__libdispatch_backend_tag, __default_backend_tag>; +using __current_configuration _LIBCPP_NODEBUG = + __backend_configuration<__libdispatch_backend_tag, __default_backend_tag>; # else // ...New vendors can add parallel backends here... diff --git a/libcxx/include/__pstl/dispatch.h b/libcxx/include/__pstl/dispatch.h index ea40fa79eb949..828842368e339 100644 --- a/libcxx/include/__pstl/dispatch.h +++ b/libcxx/include/__pstl/dispatch.h @@ -58,7 +58,8 @@ struct __find_first_implemented<_Algorithm, __backend_configuration<_B1, _Bn...> __find_first_implemented<_Algorithm, __backend_configuration<_Bn...>, _ExecutionPolicy> > {}; template