diff --git a/.ci/monolithic-linux.sh b/.ci/monolithic-linux.sh index 1e7b2d2a36c2453d8dce7bc08ee53a152b9f2cfc..9e670c447fbaddc82106905b60927fc2c5c883db 100755 --- a/.ci/monolithic-linux.sh +++ b/.ci/monolithic-linux.sh @@ -54,4 +54,4 @@ cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ echo "--- ninja" # Targets are not escaped as they are passed as separate arguments. -ninja -C "${BUILD_DIR}" ${targets} +ninja -C "${BUILD_DIR}" -k 0 ${targets} diff --git a/.ci/monolithic-windows.sh b/.ci/monolithic-windows.sh index 9561bf668a90cb87e44b26195bb86c2c0400c212..52ba13036f915983e97ad1149ffc40ee51a4c24e 100755 --- a/.ci/monolithic-windows.sh +++ b/.ci/monolithic-windows.sh @@ -62,4 +62,4 @@ cmake -S ${MONOREPO_ROOT}/llvm -B ${BUILD_DIR} \ echo "--- ninja" # Targets are not escaped as they are passed as separate arguments. -ninja -C "${BUILD_DIR}" ${targets} +ninja -C "${BUILD_DIR}" -k 0 ${targets} diff --git a/.clang-tidy b/.clang-tidy index 4e1cb114f43b2cbb5c9cadd3173271cebf3ade5d..9cece0de812b8e5370d70a12b1bad9f53d52d325 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,4 +1,4 @@ -Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,-misc-const-correctness,-misc-unused-parameters,-misc-non-private-member-variables-in-classes,-misc-no-recursion,-misc-use-anonymous-namespace,readability-identifier-naming' +Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,-misc-const-correctness,-misc-unused-parameters,-misc-non-private-member-variables-in-classes,-misc-no-recursion,-misc-use-anonymous-namespace,readability-identifier-naming,-misc-include-cleaner' CheckOptions: - key: readability-identifier-naming.ClassCase value: CamelCase diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3fe0cbbcb84d2900d2a16af83b05fe0c462d707e..85850848b220c4e61b447dc022657065bb914ab1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -27,6 +27,7 @@ /llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp @nikic /llvm/lib/Transforms/InstCombine/ @nikic +/clang/include/clang/Sema/Sema.h @Endilll /clang/test/CXX/drs/ @Endilll /clang/www/cxx_dr_status.html @Endilll /clang/www/make_cxx_dr_status @Endilll diff --git a/.github/workflows/containers/github-action-ci/stage2.Dockerfile b/.github/workflows/containers/github-action-ci/stage2.Dockerfile index e1a06cb68a589e38ae0b27014f63a729cf0ea791..0ca0da87734c4cb880113472dc474dff5345f7db 100644 --- a/.github/workflows/containers/github-action-ci/stage2.Dockerfile +++ b/.github/workflows/containers/github-action-ci/stage2.Dockerfile @@ -12,11 +12,13 @@ COPY --from=stage2-toolchain $LLVM_SYSROOT $LLVM_SYSROOT # Need to install curl for hendrikmuhs/ccache-action # Need nodejs for some of the GitHub actions. # Need perl-modules for clang analyzer tests. +# Need git for SPIRV-Tools tests. RUN apt-get update && \ apt-get install -y \ binutils \ cmake \ curl \ + git \ libstdc++-11-dev \ ninja-build \ nodejs \ diff --git a/.github/workflows/issue-release-workflow.yml b/.github/workflows/issue-release-workflow.yml index 448c1c56f897f5ef99aa9877fb30dd8c5603a3f9..eb88ec6e43c57409b6656c9b3e21bdc7cf76fede 100644 --- a/.github/workflows/issue-release-workflow.yml +++ b/.github/workflows/issue-release-workflow.yml @@ -65,5 +65,5 @@ jobs: release-workflow \ --branch-repo-token ${{ secrets.RELEASE_WORKFLOW_PUSH_SECRET }} \ --issue-number ${{ github.event.issue.number }} \ - --requested-by ${{ github.event.issue.user.login }} \ + --requested-by ${{ (github.event.action == 'opened' && github.event.issue.user.login) || github.event.comment.user.login }} \ auto diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml index ebf6fa41898dc40d85018496faaabf6ae2193da5..131ad3004f457743403fbc07a64193cf53262c6a 100644 --- a/.github/workflows/release-binaries.yml +++ b/.github/workflows/release-binaries.yml @@ -35,6 +35,7 @@ jobs: prepare: name: Prepare to build binaries runs-on: ubuntu-22.04 + if: github.repository == 'llvm/llvm-project' outputs: release-version: ${{ steps.vars.outputs.release-version }} flags: ${{ steps.vars.outputs.flags }} @@ -47,11 +48,16 @@ jobs: - name: Checkout LLVM uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Install Dependencies + run: | + pip install -r ./llvm/utils/git/requirements.txt + - name: Check Permissions env: GITHUB_TOKEN: ${{ github.token }} + USER_TOKEN: ${{ secrets.RELEASE_TASKS_USER_TOKEN }} run: | - ./llvm/utils/release/./github-upload-release.py --token "$GITHUB_TOKEN" --user ${{ github.actor }} check-permissions + ./llvm/utils/release/./github-upload-release.py --token "$GITHUB_TOKEN" --user ${{ github.actor }} --user-token "$USER_TOKEN" check-permissions - name: Collect Variables id: vars @@ -65,8 +71,8 @@ jobs: # | X.Y.Z | -final run: | tag="${{ github.ref_name }}" - trimmed=$(echo ${{ inputs.tag }} | xargs) - [[ "$trimmed" != "" ]] && tag="$trimmed" + trimmed=$(echo ${{ inputs.release-version }} | xargs) + [[ "$trimmed" != "" ]] && tag="llvmorg-$trimmed" if [ "$tag" = "main" ]; then # If tag is main, then we've been triggered by a scheduled so pass so # use the head commit as the tag. @@ -85,6 +91,7 @@ jobs: name: "Fill Cache ${{ matrix.os }}" needs: prepare runs-on: ${{ matrix.os }} + if: github.repository == 'llvm/llvm-project' strategy: matrix: os: @@ -119,6 +126,7 @@ jobs: - prepare - fill-cache runs-on: ${{ matrix.target.runs-on }} + if: github.repository == 'llvm/llvm-project' strategy: fail-fast: false matrix: diff --git a/bolt/include/bolt/Core/ParallelUtilities.h b/bolt/include/bolt/Core/ParallelUtilities.h index e510525bc51d0040ba8347af4cfed759708d5d94..e7b35a79acc78cc5f88d4baa66c76ff3507d568f 100644 --- a/bolt/include/bolt/Core/ParallelUtilities.h +++ b/bolt/include/bolt/Core/ParallelUtilities.h @@ -49,8 +49,8 @@ enum SchedulingPolicy { SP_BB_QUADRATIC, /// cost is estimated by the square of the BB count }; -/// Return the managed thread pool and initialize it if not initiliazed. -ThreadPool &getThreadPool(); +/// Return the managed thread pool and initialize it if not initialized. +ThreadPoolInterface &getThreadPool(); /// Perform the work on each BinaryFunction except those that are accepted /// by SkipPredicate, scheduling heuristic is based on SchedPolicy. diff --git a/bolt/lib/Core/DebugNames.cpp b/bolt/lib/Core/DebugNames.cpp index 1a7792afbbd941fa962b98f04205939b9f60806e..384e63695dfdc563ceda2a97eb2f48692615ec7a 100644 --- a/bolt/lib/Core/DebugNames.cpp +++ b/bolt/lib/Core/DebugNames.cpp @@ -345,8 +345,13 @@ void DWARF5AcceleratorTable::finalize() { std::optional DWARF5AcceleratorTable::getIndexForEntry( const BOLTDWARF5AccelTableData &Value) const { + // The foreign TU list immediately follows the local TU list and they both + // use the same index, so that if there are N local TU entries, the index for + // the first foreign TU is N. if (Value.isTU()) - return {{Value.getUnitID(), {dwarf::DW_IDX_type_unit, TUIndexForm}}}; + return {{(Value.getSecondUnitID() ? (unsigned)LocalTUList.size() : 0) + + Value.getUnitID(), + {dwarf::DW_IDX_type_unit, TUIndexForm}}}; if (CUList.size() > 1) return {{Value.getUnitID(), {dwarf::DW_IDX_compile_unit, CUIndexForm}}}; return std::nullopt; diff --git a/bolt/lib/Core/ParallelUtilities.cpp b/bolt/lib/Core/ParallelUtilities.cpp index 1a28bc4346ecd565cad6c645f5673f4279d044e1..5f5e96e0e7881c56eedd33db06782f9ad9bdf301 100644 --- a/bolt/lib/Core/ParallelUtilities.cpp +++ b/bolt/lib/Core/ParallelUtilities.cpp @@ -49,7 +49,7 @@ namespace ParallelUtilities { namespace { /// A single thread pool that is used to run parallel tasks -std::unique_ptr ThreadPoolPtr; +std::unique_ptr ThreadPoolPtr; unsigned computeCostFor(const BinaryFunction &BF, const PredicateTy &SkipPredicate, @@ -102,11 +102,11 @@ inline unsigned estimateTotalCost(const BinaryContext &BC, } // namespace -ThreadPool &getThreadPool() { +ThreadPoolInterface &getThreadPool() { if (ThreadPoolPtr.get()) return *ThreadPoolPtr; - ThreadPoolPtr = std::make_unique( + ThreadPoolPtr = std::make_unique( llvm::hardware_concurrency(opts::ThreadCount)); return *ThreadPoolPtr; } @@ -145,7 +145,7 @@ void runOnEachFunction(BinaryContext &BC, SchedulingPolicy SchedPolicy, TotalCost > BlocksCount ? TotalCost / BlocksCount : 1; // Divide work into blocks of equal cost - ThreadPool &Pool = getThreadPool(); + ThreadPoolInterface &Pool = getThreadPool(); auto BlockBegin = BC.getBinaryFunctions().begin(); unsigned CurrentCost = 0; @@ -202,7 +202,7 @@ void runOnEachFunctionWithUniqueAllocId( TotalCost > BlocksCount ? TotalCost / BlocksCount : 1; // Divide work into blocks of equal cost - ThreadPool &Pool = getThreadPool(); + ThreadPoolInterface &Pool = getThreadPool(); auto BlockBegin = BC.getBinaryFunctions().begin(); unsigned CurrentCost = 0; unsigned AllocId = 1; diff --git a/bolt/lib/Passes/IdenticalCodeFolding.cpp b/bolt/lib/Passes/IdenticalCodeFolding.cpp index 9f8d82b05ccf48522197ed6884def81dc2dddee1..87eba10354a37b1d26a70dc481b67e8b4db947f7 100644 --- a/bolt/lib/Passes/IdenticalCodeFolding.cpp +++ b/bolt/lib/Passes/IdenticalCodeFolding.cpp @@ -397,7 +397,7 @@ Error IdenticalCodeFolding::runOnFunctions(BinaryContext &BC) { Timer SinglePass("single fold pass", "single fold pass"); LLVM_DEBUG(SinglePass.startTimer()); - ThreadPool *ThPool; + ThreadPoolInterface *ThPool; if (!opts::NoThreads) ThPool = &ParallelUtilities::getThreadPool(); diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp index ca9d24245ceb1d0d8f12fe3aeb7f465153b19c07..85c2397dcc5b25ad18d4de453e21a3f4ce9e991d 100644 --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -784,7 +784,7 @@ void DWARFRewriter::updateDebugInfo() { } } else { // Update unit debug info in parallel - ThreadPool &ThreadPool = ParallelUtilities::getThreadPool(); + ThreadPoolInterface &ThreadPool = ParallelUtilities::getThreadPool(); for (std::unique_ptr &CU : BC.DwCtx->compile_units()) ThreadPool.async(processUnitDIE, CU.get(), &DIEBlder); ThreadPool.wait(); diff --git a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp index 0d7dc1070ce75e4d5adf5d3f21c9353b5bfd0fd2..331a61e7c3c2cdc0f344adc12f10be5fed6cea29 100644 --- a/bolt/lib/Rewrite/LinuxKernelRewriter.cpp +++ b/bolt/lib/Rewrite/LinuxKernelRewriter.cpp @@ -14,6 +14,7 @@ #include "bolt/Rewrite/MetadataRewriter.h" #include "bolt/Rewrite/MetadataRewriters.h" #include "bolt/Utils/CommandLineOpts.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -27,19 +28,43 @@ using namespace bolt; namespace opts { static cl::opt - PrintORC("print-orc", - cl::desc("print ORC unwind information for instructions"), - cl::init(true), cl::Hidden, cl::cat(BoltCategory)); + AltInstHasPadLen("alt-inst-has-padlen", + cl::desc("specify that .altinstructions has padlen field"), + cl::init(false), cl::Hidden, cl::cat(BoltCategory)); + +static cl::opt + AltInstFeatureSize("alt-inst-feature-size", + cl::desc("size of feature field in .altinstructions"), + cl::init(2), cl::Hidden, cl::cat(BoltCategory)); + +static cl::opt + DumpAltInstructions("dump-alt-instructions", + cl::desc("dump Linux alternative instructions info"), + cl::init(false), cl::Hidden, cl::cat(BoltCategory)); + +static cl::opt + DumpExceptions("dump-linux-exceptions", + cl::desc("dump Linux kernel exception table"), + cl::init(false), cl::Hidden, cl::cat(BoltCategory)); static cl::opt DumpORC("dump-orc", cl::desc("dump raw ORC unwind information (sorted)"), cl::init(false), cl::Hidden, cl::cat(BoltCategory)); +static cl::opt DumpParavirtualPatchSites( + "dump-para-sites", cl::desc("dump Linux kernel paravitual patch sites"), + cl::init(false), cl::Hidden, cl::cat(BoltCategory)); + static cl::opt DumpStaticCalls("dump-static-calls", cl::desc("dump Linux kernel static calls"), cl::init(false), cl::Hidden, cl::cat(BoltCategory)); +static cl::opt + PrintORC("print-orc", + cl::desc("print ORC unwind information for instructions"), + cl::init(true), cl::Hidden, cl::cat(BoltCategory)); + } // namespace opts /// Linux Kernel supports stack unwinding using ORC (oops rewind capability). @@ -134,6 +159,28 @@ class LinuxKernelRewriter final : public MetadataRewriter { using StaticCallListType = std::vector; StaticCallListType StaticCallEntries; + /// Section containing the Linux exception table. + ErrorOr ExceptionsSection = std::errc::bad_address; + static constexpr size_t EXCEPTION_TABLE_ENTRY_SIZE = 12; + + /// Functions with exception handling code. + DenseSet FunctionsWithExceptions; + + /// Section with paravirtual patch sites. + ErrorOr ParavirtualPatchSection = std::errc::bad_address; + + /// Alignment of paravirtual patch structures. + static constexpr size_t PARA_PATCH_ALIGN = 8; + + /// .altinstructions section. + ErrorOr AltInstrSection = std::errc::bad_address; + + /// Section containing Linux bug table. + ErrorOr BugTableSection = std::errc::bad_address; + + /// Size of bug_entry struct. + static constexpr size_t BUG_TABLE_ENTRY_SIZE = 12; + /// Insert an LKMarker for a given code pointer \p PC from a non-code section /// \p SectionName. void insertLKMarker(uint64_t PC, uint64_t SectionOffset, @@ -143,18 +190,12 @@ class LinuxKernelRewriter final : public MetadataRewriter { /// Process linux kernel special sections and their relocations. void processLKSections(); - /// Process special linux kernel section, __ex_table. - void processLKExTable(); - /// Process special linux kernel section, .pci_fixup. void processLKPCIFixup(); /// Process __ksymtab and __ksymtab_gpl. void processLKKSymtab(bool IsGPL = false); - /// Process special linux kernel section, __bug_table. - void processLKBugTable(); - /// Process special linux kernel section, .smp_locks. void processLKSMPLocks(); @@ -174,6 +215,17 @@ class LinuxKernelRewriter final : public MetadataRewriter { Error readStaticCalls(); Error rewriteStaticCalls(); + Error readExceptionTable(); + Error rewriteExceptionTable(); + + /// Paravirtual instruction patch sites. + Error readParaInstructions(); + + Error readBugTable(); + + /// Read alternative instruction info from .altinstructions. + Error readAltInstructions(); + /// Mark instructions referenced by kernel metadata. Error markInstructions(); @@ -192,6 +244,18 @@ public: if (Error E = readStaticCalls()) return E; + if (Error E = readExceptionTable()) + return E; + + if (Error E = readParaInstructions()) + return E; + + if (Error E = readBugTable()) + return E; + + if (Error E = readAltInstructions()) + return E; + return Error::success(); } @@ -203,6 +267,11 @@ public: } Error preEmitFinalizer() override { + // Since rewriteExceptionTable() can mark functions as non-simple, run it + // before other rewriters that depend on simple/emit status. + if (Error E = rewriteExceptionTable()) + return E; + if (Error E = rewriteORCTables()) return E; @@ -249,77 +318,12 @@ void LinuxKernelRewriter::insertLKMarker(uint64_t PC, uint64_t SectionOffset, } void LinuxKernelRewriter::processLKSections() { - processLKExTable(); processLKPCIFixup(); processLKKSymtab(); processLKKSymtab(true); - processLKBugTable(); processLKSMPLocks(); } -/// Process __ex_table section of Linux Kernel. -/// This section contains information regarding kernel level exception -/// handling (https://www.kernel.org/doc/html/latest/x86/exception-tables.html). -/// More documentation is in arch/x86/include/asm/extable.h. -/// -/// The section is the list of the following structures: -/// -/// struct exception_table_entry { -/// int insn; -/// int fixup; -/// int handler; -/// }; -/// -void LinuxKernelRewriter::processLKExTable() { - ErrorOr SectionOrError = - BC.getUniqueSectionByName("__ex_table"); - if (!SectionOrError) - return; - - const uint64_t SectionSize = SectionOrError->getSize(); - const uint64_t SectionAddress = SectionOrError->getAddress(); - assert((SectionSize % 12) == 0 && - "The size of the __ex_table section should be a multiple of 12"); - for (uint64_t I = 0; I < SectionSize; I += 4) { - const uint64_t EntryAddress = SectionAddress + I; - ErrorOr Offset = BC.getSignedValueAtAddress(EntryAddress, 4); - assert(Offset && "failed reading PC-relative offset for __ex_table"); - int32_t SignedOffset = *Offset; - const uint64_t RefAddress = EntryAddress + SignedOffset; - - BinaryFunction *ContainingBF = - BC.getBinaryFunctionContainingAddress(RefAddress); - if (!ContainingBF) - continue; - - MCSymbol *ReferencedSymbol = ContainingBF->getSymbol(); - const uint64_t FunctionOffset = RefAddress - ContainingBF->getAddress(); - switch (I % 12) { - default: - llvm_unreachable("bad alignment of __ex_table"); - break; - case 0: - // insn - insertLKMarker(RefAddress, I, SignedOffset, true, "__ex_table"); - break; - case 4: - // fixup - if (FunctionOffset) - ReferencedSymbol = ContainingBF->addEntryPointAtOffset(FunctionOffset); - BC.addRelocation(EntryAddress, ReferencedSymbol, Relocation::getPC32(), 0, - *Offset); - break; - case 8: - // handler - assert(!FunctionOffset && - "__ex_table handler entry should point to function start"); - BC.addRelocation(EntryAddress, ReferencedSymbol, Relocation::getPC32(), 0, - *Offset); - break; - } - } -} - /// Process .pci_fixup section of Linux Kernel. /// This section contains a list of entries for different PCI devices and their /// corresponding hook handler (code pointer where the fixup @@ -383,37 +387,6 @@ void LinuxKernelRewriter::processLKKSymtab(bool IsGPL) { } } -/// Process __bug_table section. -/// This section contains information useful for kernel debugging. -/// Each entry in the section is a struct bug_entry that contains a pointer to -/// the ud2 instruction corresponding to the bug, corresponding file name (both -/// pointers use PC relative offset addressing), line number, and flags. -/// The definition of the struct bug_entry can be found in -/// `include/asm-generic/bug.h` -void LinuxKernelRewriter::processLKBugTable() { - ErrorOr SectionOrError = - BC.getUniqueSectionByName("__bug_table"); - if (!SectionOrError) - return; - - const uint64_t SectionSize = SectionOrError->getSize(); - const uint64_t SectionAddress = SectionOrError->getAddress(); - assert((SectionSize % 12) == 0 && - "The size of the __bug_table section should be a multiple of 12"); - for (uint64_t I = 0; I < SectionSize; I += 12) { - const uint64_t EntryAddress = SectionAddress + I; - ErrorOr Offset = BC.getSignedValueAtAddress(EntryAddress, 4); - assert(Offset && - "Reading valid PC-relative offset for a __bug_table entry"); - const int32_t SignedOffset = *Offset; - const uint64_t RefAddress = EntryAddress + SignedOffset; - assert(BC.getBinaryFunctionContainingAddress(RefAddress) && - "__bug_table entries should point to a function"); - - insertLKMarker(RefAddress, I, SignedOffset, true, "__bug_table"); - } -} - /// .smp_locks section contains PC-relative references to instructions with LOCK /// prefix. The prefix can be converted to NOP at boot time on non-SMP systems. void LinuxKernelRewriter::processLKSMPLocks() { @@ -527,7 +500,8 @@ Error LinuxKernelRewriter::readORCTables() { // Consume the status of the cursor. if (!IPCursor) return createStringError(errc::executable_format_error, - "out of bounds while reading ORC IP table"); + "out of bounds while reading ORC IP table: %s", + toString(IPCursor.takeError()).c_str()); if (IP < PrevIP && opts::Verbosity) BC.errs() << "BOLT-WARNING: out of order IP 0x" << Twine::utohexstr(IP) @@ -549,7 +523,8 @@ Error LinuxKernelRewriter::readORCTables() { // Consume the status of the cursor. if (!ORCCursor) return createStringError(errc::executable_format_error, - "out of bounds while reading ORC"); + "out of bounds while reading ORC: %s", + toString(ORCCursor.takeError()).c_str()); if (Entry.ORC == NullORC) continue; @@ -870,7 +845,8 @@ Error LinuxKernelRewriter::readStaticCalls() { // Consume the status of the cursor. if (!Cursor) return createStringError(errc::executable_format_error, - "out of bounds while reading static calls"); + "out of bounds while reading static calls: %s", + toString(Cursor.takeError()).c_str()); ++EntryID; @@ -943,6 +919,370 @@ Error LinuxKernelRewriter::rewriteStaticCalls() { return Error::success(); } +/// Instructions that access user-space memory can cause page faults. These +/// faults will be handled by the kernel and execution will resume at the fixup +/// code location if the address was invalid. The kernel uses the exception +/// table to match the faulting instruction to its fixup. The table consists of +/// the following entries: +/// +/// struct exception_table_entry { +/// int insn; +/// int fixup; +/// int data; +/// }; +/// +/// More info at: +/// https://www.kernel.org/doc/Documentation/x86/exception-tables.txt +Error LinuxKernelRewriter::readExceptionTable() { + ExceptionsSection = BC.getUniqueSectionByName("__ex_table"); + if (!ExceptionsSection) + return Error::success(); + + if (ExceptionsSection->getSize() % EXCEPTION_TABLE_ENTRY_SIZE) + return createStringError(errc::executable_format_error, + "exception table size error"); + + const uint64_t SectionAddress = ExceptionsSection->getAddress(); + DataExtractor DE(ExceptionsSection->getContents(), + BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + DataExtractor::Cursor Cursor(0); + uint32_t EntryID = 0; + while (Cursor && Cursor.tell() < ExceptionsSection->getSize()) { + const uint64_t InstAddress = + SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor); + const uint64_t FixupAddress = + SectionAddress + Cursor.tell() + (int32_t)DE.getU32(Cursor); + const uint64_t Data = DE.getU32(Cursor); + + // Consume the status of the cursor. + if (!Cursor) + return createStringError( + errc::executable_format_error, + "out of bounds while reading exception table: %s", + toString(Cursor.takeError()).c_str()); + + ++EntryID; + + if (opts::DumpExceptions) { + BC.outs() << "Exception Entry: " << EntryID << '\n'; + BC.outs() << "\tInsn: 0x" << Twine::utohexstr(InstAddress) << '\n' + << "\tFixup: 0x" << Twine::utohexstr(FixupAddress) << '\n' + << "\tData: 0x" << Twine::utohexstr(Data) << '\n'; + } + + MCInst *Inst = nullptr; + MCSymbol *FixupLabel = nullptr; + + BinaryFunction *InstBF = BC.getBinaryFunctionContainingAddress(InstAddress); + if (InstBF && BC.shouldEmit(*InstBF)) { + Inst = InstBF->getInstructionAtOffset(InstAddress - InstBF->getAddress()); + if (!Inst) + return createStringError(errc::executable_format_error, + "no instruction at address 0x%" PRIx64 + " in exception table", + InstAddress); + BC.MIB->addAnnotation(*Inst, "ExceptionEntry", EntryID); + FunctionsWithExceptions.insert(InstBF); + } + + if (!InstBF && opts::Verbosity) { + BC.outs() << "BOLT-INFO: no function matches instruction at 0x" + << Twine::utohexstr(InstAddress) + << " referenced by Linux exception table\n"; + } + + BinaryFunction *FixupBF = + BC.getBinaryFunctionContainingAddress(FixupAddress); + if (FixupBF && BC.shouldEmit(*FixupBF)) { + const uint64_t Offset = FixupAddress - FixupBF->getAddress(); + if (!FixupBF->getInstructionAtOffset(Offset)) + return createStringError(errc::executable_format_error, + "no instruction at fixup address 0x%" PRIx64 + " in exception table", + FixupAddress); + FixupLabel = Offset ? FixupBF->addEntryPointAtOffset(Offset) + : FixupBF->getSymbol(); + if (Inst) + BC.MIB->addAnnotation(*Inst, "Fixup", FixupLabel->getName()); + FunctionsWithExceptions.insert(FixupBF); + } + + if (!FixupBF && opts::Verbosity) { + BC.outs() << "BOLT-INFO: no function matches fixup code at 0x" + << Twine::utohexstr(FixupAddress) + << " referenced by Linux exception table\n"; + } + } + + BC.outs() << "BOLT-INFO: parsed " + << ExceptionsSection->getSize() / EXCEPTION_TABLE_ENTRY_SIZE + << " exception table entries\n"; + + return Error::success(); +} + +/// Depending on the value of CONFIG_BUILDTIME_TABLE_SORT, the kernel expects +/// the exception table to be sorted. Hence we have to sort it after code +/// reordering. +Error LinuxKernelRewriter::rewriteExceptionTable() { + // Disable output of functions with exceptions before rewrite support is + // added. + for (BinaryFunction *BF : FunctionsWithExceptions) + BF->setSimple(false); + + return Error::success(); +} + +/// .parainsrtuctions section contains information for patching parvirtual call +/// instructions during runtime. The entries in the section are in the form: +/// +/// struct paravirt_patch_site { +/// u8 *instr; /* original instructions */ +/// u8 type; /* type of this instruction */ +/// u8 len; /* length of original instruction */ +/// }; +/// +/// Note that the structures are aligned at 8-byte boundary. +Error LinuxKernelRewriter::readParaInstructions() { + ParavirtualPatchSection = BC.getUniqueSectionByName(".parainstructions"); + if (!ParavirtualPatchSection) + return Error::success(); + + DataExtractor DE = DataExtractor(ParavirtualPatchSection->getContents(), + BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + uint32_t EntryID = 0; + DataExtractor::Cursor Cursor(0); + while (Cursor && !DE.eof(Cursor)) { + const uint64_t NextOffset = alignTo(Cursor.tell(), Align(PARA_PATCH_ALIGN)); + if (!DE.isValidOffset(NextOffset)) + break; + + Cursor.seek(NextOffset); + + const uint64_t InstrLocation = DE.getU64(Cursor); + const uint8_t Type = DE.getU8(Cursor); + const uint8_t Len = DE.getU8(Cursor); + + if (!Cursor) + return createStringError( + errc::executable_format_error, + "out of bounds while reading .parainstructions: %s", + toString(Cursor.takeError()).c_str()); + + ++EntryID; + + if (opts::DumpParavirtualPatchSites) { + BC.outs() << "Paravirtual patch site: " << EntryID << '\n'; + BC.outs() << "\tInstr: 0x" << Twine::utohexstr(InstrLocation) + << "\n\tType: 0x" << Twine::utohexstr(Type) << "\n\tLen: 0x" + << Twine::utohexstr(Len) << '\n'; + } + + BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(InstrLocation); + if (!BF && opts::Verbosity) { + BC.outs() << "BOLT-INFO: no function matches address 0x" + << Twine::utohexstr(InstrLocation) + << " referenced by paravirutal patch site\n"; + } + + if (BF && BC.shouldEmit(*BF)) { + MCInst *Inst = + BF->getInstructionAtOffset(InstrLocation - BF->getAddress()); + if (!Inst) + return createStringError(errc::executable_format_error, + "no instruction at address 0x%" PRIx64 + " in paravirtual call site %d", + InstrLocation, EntryID); + BC.MIB->addAnnotation(*Inst, "ParaSite", EntryID); + } + } + + BC.outs() << "BOLT-INFO: parsed " << EntryID << " paravirtual patch sites\n"; + + return Error::success(); +} + +/// Process __bug_table section. +/// This section contains information useful for kernel debugging. +/// Each entry in the section is a struct bug_entry that contains a pointer to +/// the ud2 instruction corresponding to the bug, corresponding file name (both +/// pointers use PC relative offset addressing), line number, and flags. +/// The definition of the struct bug_entry can be found in +/// `include/asm-generic/bug.h` +/// +/// NB: find_bug() uses linear search to match an address to an entry in the bug +/// table. Hence there is no need to sort entries when rewriting the table. +Error LinuxKernelRewriter::readBugTable() { + BugTableSection = BC.getUniqueSectionByName("__bug_table"); + if (!BugTableSection) + return Error::success(); + + if (BugTableSection->getSize() % BUG_TABLE_ENTRY_SIZE) + return createStringError(errc::executable_format_error, + "bug table size error"); + + const uint64_t SectionAddress = BugTableSection->getAddress(); + DataExtractor DE(BugTableSection->getContents(), BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + DataExtractor::Cursor Cursor(0); + uint32_t EntryID = 0; + while (Cursor && Cursor.tell() < BugTableSection->getSize()) { + const uint64_t Pos = Cursor.tell(); + const uint64_t InstAddress = + SectionAddress + Pos + (int32_t)DE.getU32(Cursor); + Cursor.seek(Pos + BUG_TABLE_ENTRY_SIZE); + + if (!Cursor) + return createStringError(errc::executable_format_error, + "out of bounds while reading __bug_table: %s", + toString(Cursor.takeError()).c_str()); + + ++EntryID; + + BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(InstAddress); + if (!BF && opts::Verbosity) { + BC.outs() << "BOLT-INFO: no function matches address 0x" + << Twine::utohexstr(InstAddress) + << " referenced by bug table\n"; + } + + if (BF && BC.shouldEmit(*BF)) { + MCInst *Inst = BF->getInstructionAtOffset(InstAddress - BF->getAddress()); + if (!Inst) + return createStringError(errc::executable_format_error, + "no instruction at address 0x%" PRIx64 + " referenced by bug table entry %d", + InstAddress, EntryID); + BC.MIB->addAnnotation(*Inst, "BugEntry", EntryID); + } + } + + BC.outs() << "BOLT-INFO: parsed " << EntryID << " bug table entries\n"; + + return Error::success(); +} + +/// The kernel can replace certain instruction sequences depending on hardware +/// it is running on and features specified during boot time. The information +/// about alternative instruction sequences is stored in .altinstructions +/// section. The format of entries in this section is defined in +/// arch/x86/include/asm/alternative.h: +/// +/// struct alt_instr { +/// s32 instr_offset; +/// s32 repl_offset; +/// uXX feature; +/// u8 instrlen; +/// u8 replacementlen; +/// u8 padlen; // present in older kernels +/// } __packed; +/// +/// Note the structures is packed. +Error LinuxKernelRewriter::readAltInstructions() { + AltInstrSection = BC.getUniqueSectionByName(".altinstructions"); + if (!AltInstrSection) + return Error::success(); + + const uint64_t Address = AltInstrSection->getAddress(); + DataExtractor DE = DataExtractor(AltInstrSection->getContents(), + BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + uint64_t EntryID = 0; + DataExtractor::Cursor Cursor(0); + while (Cursor && !DE.eof(Cursor)) { + const uint64_t OrgInstAddress = + Address + Cursor.tell() + (int32_t)DE.getU32(Cursor); + const uint64_t AltInstAddress = + Address + Cursor.tell() + (int32_t)DE.getU32(Cursor); + const uint64_t Feature = DE.getUnsigned(Cursor, opts::AltInstFeatureSize); + const uint8_t OrgSize = DE.getU8(Cursor); + const uint8_t AltSize = DE.getU8(Cursor); + + // Older kernels may have the padlen field. + const uint8_t PadLen = opts::AltInstHasPadLen ? DE.getU8(Cursor) : 0; + + if (!Cursor) + return createStringError( + errc::executable_format_error, + "out of bounds while reading .altinstructions: %s", + toString(Cursor.takeError()).c_str()); + + ++EntryID; + + if (opts::DumpAltInstructions) { + BC.outs() << "Alternative instruction entry: " << EntryID + << "\n\tOrg: 0x" << Twine::utohexstr(OrgInstAddress) + << "\n\tAlt: 0x" << Twine::utohexstr(AltInstAddress) + << "\n\tFeature: 0x" << Twine::utohexstr(Feature) + << "\n\tOrgSize: " << (int)OrgSize + << "\n\tAltSize: " << (int)AltSize << '\n'; + if (opts::AltInstHasPadLen) + BC.outs() << "\tPadLen: " << (int)PadLen << '\n'; + } + + if (AltSize > OrgSize) + return createStringError(errc::executable_format_error, + "error reading .altinstructions"); + + BinaryFunction *BF = BC.getBinaryFunctionContainingAddress(OrgInstAddress); + if (!BF && opts::Verbosity) { + BC.outs() << "BOLT-INFO: no function matches address 0x" + << Twine::utohexstr(OrgInstAddress) + << " of instruction from .altinstructions\n"; + } + + BinaryFunction *AltBF = + BC.getBinaryFunctionContainingAddress(AltInstAddress); + if (AltBF && BC.shouldEmit(*AltBF)) { + BC.errs() + << "BOLT-WARNING: alternative instruction sequence found in function " + << *AltBF << '\n'; + AltBF->setIgnored(); + } + + if (!BF || !BC.shouldEmit(*BF)) + continue; + + if (OrgInstAddress + OrgSize > BF->getAddress() + BF->getSize()) + return createStringError(errc::executable_format_error, + "error reading .altinstructions"); + + MCInst *Inst = + BF->getInstructionAtOffset(OrgInstAddress - BF->getAddress()); + if (!Inst) + return createStringError(errc::executable_format_error, + "no instruction at address 0x%" PRIx64 + " referenced by .altinstructions entry %d", + OrgInstAddress, EntryID); + + // There could be more than one alternative instruction sequences for the + // same original instruction. Annotate each alternative separately. + std::string AnnotationName = "AltInst"; + unsigned N = 2; + while (BC.MIB->hasAnnotation(*Inst, AnnotationName)) + AnnotationName = "AltInst" + std::to_string(N++); + + BC.MIB->addAnnotation(*Inst, AnnotationName, EntryID); + + // Annotate all instructions from the original sequence. Note that it's not + // the most efficient way to look for instructions in the address range, + // but since alternative instructions are uncommon, it will do for now. + for (uint32_t Offset = 1; Offset < OrgSize; ++Offset) { + Inst = BF->getInstructionAtOffset(OrgInstAddress + Offset - + BF->getAddress()); + if (Inst) + BC.MIB->addAnnotation(*Inst, AnnotationName, EntryID); + } + } + + BC.outs() << "BOLT-INFO: parsed " << EntryID + << " alternative instruction entries\n"; + + return Error::success(); +} + } // namespace std::unique_ptr diff --git a/bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper.s b/bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper.s new file mode 100644 index 0000000000000000000000000000000000000000..68eee45ec98330557edc8f54e232e10e4b66c885 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper.s @@ -0,0 +1,314 @@ +# struct AMono { +# int x; +# }; +# +# AMono globalMono; +# # clang++ -g2 -gdwarf-5 -gpubnames -S -fdebug-types-section -o + + .text + .file "helper.cpp" + .file 0 "/home" "helper.cpp" md5 0x3c0ac73d7b074961c6e8202230a76228 + .section .debug_info,"G",@progbits,6412503741467814911,comdat +.Ltu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 6412503741467814911 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x20 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0x10 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 6 # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member + .byte 4 # DW_AT_name + .long 51 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x33:0x4 DW_TAG_base_type + .byte 5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .type globalMono,@object # @globalMono + .bss + .globl globalMono + .p2align 2, 0x0 +globalMono: + .zero 4 + .size globalMono, 4 + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 5 # Abbrev [5] 0xc:0x27 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 6 # Abbrev [6] 0x1e:0xb DW_TAG_variable + .byte 3 # DW_AT_name + .long 41 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 7 # Abbrev [7] 0x29:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 6412503741467814911 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_str_offsets,"",@progbits + .long 32 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" # string offset=0 +.Linfo_string1: + .asciz "helper.cpp" # string offset=104 +.Linfo_string2: + .asciz "/home" # string offset=115 +.Linfo_string3: + .asciz "globalMono" # string offset=153 +.Linfo_string4: + .asciz "AMono" # string offset=164 +.Linfo_string5: + .asciz "x" # string offset=170 +.Linfo_string6: + .asciz "int" # string offset=172 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string4 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad globalMono +.Ldebug_addr_end0: + .section .debug_names,"",@progbits + .long .Lnames_end0-.Lnames_start0 # Header: unit length +.Lnames_start0: + .short 5 # Header: version + .short 0 # Header: padding + .long 1 # Header: compilation unit count + .long 1 # Header: local type unit count + .long 0 # Header: foreign type unit count + .long 3 # Header: bucket count + .long 3 # Header: name count + .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size + .long 8 # Header: augmentation string size + .ascii "LLVM0700" # Header: augmentation string + .long .Lcu_begin0 # Compilation unit 0 + .long .Ltu_begin0 # Type unit 0 + .long 0 # Bucket 0 + .long 0 # Bucket 1 + .long 1 # Bucket 2 + .long 193495088 # Hash in Bucket 2 + .long 253228319 # Hash in Bucket 2 + .long -857151761 # Hash in Bucket 2 + .long .Linfo_string6 # String in Bucket 2: int + .long .Linfo_string4 # String in Bucket 2: AMono + .long .Linfo_string3 # String in Bucket 2: globalMono + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2 +.Lnames_abbrev_start0: + .byte 1 # Abbrev code + .byte 36 # DW_TAG_base_type + .byte 2 # DW_IDX_type_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 2 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 2 # DW_IDX_type_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 3 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 4 # Abbrev code + .byte 52 # DW_TAG_variable + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames1: +.L1: + .byte 1 # Abbreviation code + .byte 0 # DW_IDX_type_unit + .long 51 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: int +.Lnames0: +.L2: + .byte 2 # Abbreviation code + .byte 0 # DW_IDX_type_unit + .long 35 # DW_IDX_die_offset +.L3: # DW_IDX_parent + .byte 3 # Abbreviation code + .long 41 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: AMono +.Lnames2: +.L0: + .byte 4 # Abbreviation code + .long 30 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: globalMono + .p2align 2, 0x0 +.Lnames_end0: + .ident "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper1.s b/bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper1.s new file mode 100644 index 0000000000000000000000000000000000000000..8b28c19dc87de8456314d4eb767d1cd90936e524 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper1.s @@ -0,0 +1,315 @@ +# struct BMono { +# int x; +# }; +# +# BMono globalMono1; +# clang++ -g2 -gdwarf-5 -gpubnames -S -fdebug-types-section -o + + + .text + .file "helper1.cpp" + .file 0 "/home" "helper1.cpp" md5 0x1fdaf911330b73495aed962bc02cfb3a + .section .debug_info,"G",@progbits,5884764266900841573,comdat +.Ltu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 5884764266900841573 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x20 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0x10 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 6 # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member + .byte 4 # DW_AT_name + .long 51 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x33:0x4 DW_TAG_base_type + .byte 5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .type globalMono1,@object # @globalMono1 + .bss + .globl globalMono1 + .p2align 2, 0x0 +globalMono1: + .zero 4 + .size globalMono1, 4 + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 5 # Abbrev [5] 0xc:0x27 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 6 # Abbrev [6] 0x1e:0xb DW_TAG_variable + .byte 3 # DW_AT_name + .long 41 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 7 # Abbrev [7] 0x29:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 5884764266900841573 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_str_offsets,"",@progbits + .long 32 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" # string offset=0 +.Linfo_string1: + .asciz "helper1.cpp" # string offset=104 +.Linfo_string2: + .asciz "/home" # string offset=116 +.Linfo_string3: + .asciz "globalMono1" # string offset=154 +.Linfo_string4: + .asciz "BMono" # string offset=166 +.Linfo_string5: + .asciz "x" # string offset=172 +.Linfo_string6: + .asciz "int" # string offset=174 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string4 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad globalMono1 +.Ldebug_addr_end0: + .section .debug_names,"",@progbits + .long .Lnames_end0-.Lnames_start0 # Header: unit length +.Lnames_start0: + .short 5 # Header: version + .short 0 # Header: padding + .long 1 # Header: compilation unit count + .long 1 # Header: local type unit count + .long 0 # Header: foreign type unit count + .long 3 # Header: bucket count + .long 3 # Header: name count + .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size + .long 8 # Header: augmentation string size + .ascii "LLVM0700" # Header: augmentation string + .long .Lcu_begin0 # Compilation unit 0 + .long .Ltu_begin0 # Type unit 0 + .long 0 # Bucket 0 + .long 0 # Bucket 1 + .long 1 # Bucket 2 + .long 193495088 # Hash in Bucket 2 + .long 254414240 # Hash in Bucket 2 + .long 1778763008 # Hash in Bucket 2 + .long .Linfo_string6 # String in Bucket 2: int + .long .Linfo_string4 # String in Bucket 2: BMono + .long .Linfo_string3 # String in Bucket 2: globalMono1 + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2 +.Lnames_abbrev_start0: + .byte 1 # Abbrev code + .byte 36 # DW_TAG_base_type + .byte 2 # DW_IDX_type_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 2 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 2 # DW_IDX_type_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 3 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 4 # Abbrev code + .byte 52 # DW_TAG_variable + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames1: +.L1: + .byte 1 # Abbreviation code + .byte 0 # DW_IDX_type_unit + .long 51 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: int +.Lnames0: +.L2: + .byte 2 # Abbreviation code + .byte 0 # DW_IDX_type_unit + .long 35 # DW_IDX_die_offset +.L3: # DW_IDX_parent + .byte 3 # Abbreviation code + .long 41 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: BMono +.Lnames2: +.L0: + .byte 4 # Abbreviation code + .long 30 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: globalMono1 + .p2align 2, 0x0 +.Lnames_end0: + .ident "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf5-df-debug-names-ftu-ltu-mix-main.s b/bolt/test/X86/Inputs/dwarf5-df-debug-names-ftu-ltu-mix-main.s new file mode 100644 index 0000000000000000000000000000000000000000..69f6c5a5376a027615ecdf67a743a431fe542430 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-df-debug-names-ftu-ltu-mix-main.s @@ -0,0 +1,505 @@ +# struct ASplit { +# int x; +# }; +# +# ASplit globalSplit; +# int main() { +# return 0; +# } +# clang++ -g2 -gdwarf-5 -gpubnames -S -fdebug-types-section -gsplit-dwarf -fdebug-compilation-dir='.' + + .text + .file "main.cpp" + .file 0 "." "main.cpp" md5 0xbb74a3c2960dafa324547ebbd87d13ea + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 5 # DWARF version number + .byte 6 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad -8602855756067469281 # Type Signature + .long 33 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x1e DW_TAG_type_unit + .short 33 # DW_AT_language + .byte 1 # DW_AT_comp_dir + .byte 2 # DW_AT_dwo_name + .long 0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x21:0x10 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 5 # DW_AT_name + .byte 4 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x27:0x9 DW_TAG_member + .byte 3 # DW_AT_name + .long 49 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x31:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end0: + .text + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .loc 0 6 0 # main.cpp:6:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movl $0, -4(%rbp) +.Ltmp0: + .loc 0 7 3 prologue_end # main.cpp:7:3 + xorl %eax, %eax + .loc 0 7 3 epilogue_begin is_stmt 0 # main.cpp:7:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .type globalSplit,@object # @globalSplit + .bss + .globl globalSplit + .p2align 2, 0x0 +globalSplit: + .zero 4 + .size globalSplit, 4 + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 74 # DW_TAG_skeleton_unit + .byte 0 # DW_CHILDREN_no + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 4 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 5806847994123082226 + .byte 1 # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 0 # DW_AT_comp_dir + .byte 1 # DW_AT_dwo_name + .byte 1 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 12 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Lskel_string0: + .asciz "." # string offset=0 +.Lskel_string1: + .asciz "ASplit" # string offset=2 +.Lskel_string2: + .asciz "int" # string offset=9 +.Lskel_string3: + .asciz "globalSplit" # string offset=13 +.Lskel_string4: + .asciz "main" # string offset=25 +.Lskel_string5: + .asciz "main.dwo" # string offset=30 + .section .debug_str_offsets,"",@progbits + .long .Lskel_string0 + .long .Lskel_string5 + .section .debug_str_offsets.dwo,"e",@progbits + .long 40 # Length of String Offsets Set + .short 5 + .short 0 + .section .debug_str.dwo,"eMS",@progbits,1 +.Linfo_string0: + .asciz "globalSplit" # string offset=0 +.Linfo_string1: + .asciz "." # string offset=12 +.Linfo_string2: + .asciz "main.dwo" # string offset=14 +.Linfo_string3: + .asciz "x" # string offset=23 +.Linfo_string4: + .asciz "int" # string offset=25 +.Linfo_string5: + .asciz "ASplit" # string offset=29 +.Linfo_string6: + .asciz "main" # string offset=36 +.Linfo_string7: + .asciz "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" # string offset=41 +.Linfo_string8: + .asciz "main.cpp" # string offset=145 + .section .debug_str_offsets.dwo,"e",@progbits + .long 0 + .long 12 + .long 14 + .long 23 + .long 25 + .long 29 + .long 36 + .long 41 + .long 145 + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit +.Ldebug_info_dwo_start1: + .short 5 # DWARF version number + .byte 5 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad 5806847994123082226 + .byte 5 # Abbrev [5] 0x14:0x2e DW_TAG_compile_unit + .byte 7 # DW_AT_producer + .short 33 # DW_AT_language + .byte 8 # DW_AT_name + .byte 2 # DW_AT_dwo_name + .byte 6 # Abbrev [6] 0x1a:0xb DW_TAG_variable + .byte 0 # DW_AT_name + .long 37 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 7 # Abbrev [7] 0x25:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad -8602855756067469281 # DW_AT_signature + .byte 8 # Abbrev [8] 0x2e:0xf DW_TAG_subprogram + .byte 1 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 6 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 61 # DW_AT_type + # DW_AT_external + .byte 4 # Abbrev [4] 0x3d:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end1: + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_line.dwo,"e",@progbits +.Ltmp2: + .long .Ldebug_line_end0-.Ldebug_line_start0 # unit length +.Ldebug_line_start0: + .short 5 + .byte 8 + .byte 0 + .long .Lprologue_end0-.Lprologue_start0 +.Lprologue_start0: + .byte 1 + .byte 1 + .byte 1 + .byte -5 + .byte 14 + .byte 1 + .byte 1 + .byte 1 + .byte 8 + .byte 1 + .byte 46 + .byte 0 + .byte 3 + .byte 1 + .byte 8 + .byte 2 + .byte 15 + .byte 5 + .byte 30 + .byte 1 + .ascii "main.cpp" + .byte 0 + .byte 0 + .byte 0xbb, 0x74, 0xa3, 0xc2 + .byte 0x96, 0x0d, 0xaf, 0xa3 + .byte 0x24, 0x54, 0x7e, 0xbb + .byte 0xd8, 0x7d, 0x13, 0xea +.Lprologue_end0: +.Ldebug_line_end0: + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad globalSplit + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + .section .debug_names,"",@progbits + .long .Lnames_end0-.Lnames_start0 # Header: unit length +.Lnames_start0: + .short 5 # Header: version + .short 0 # Header: padding + .long 1 # Header: compilation unit count + .long 0 # Header: local type unit count + .long 1 # Header: foreign type unit count + .long 4 # Header: bucket count + .long 4 # Header: name count + .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size + .long 8 # Header: augmentation string size + .ascii "LLVM0700" # Header: augmentation string + .long .Lcu_begin0 # Compilation unit 0 + .quad -8602855756067469281 # Type unit 0 + .long 1 # Bucket 0 + .long 0 # Bucket 1 + .long 2 # Bucket 2 + .long 0 # Bucket 3 + .long 193495088 # Hash in Bucket 0 + .long 1785912162 # Hash in Bucket 2 + .long 2090499946 # Hash in Bucket 2 + .long -226250862 # Hash in Bucket 2 + .long .Lskel_string2 # String in Bucket 0: int + .long .Lskel_string3 # String in Bucket 2: globalSplit + .long .Lskel_string4 # String in Bucket 2: main + .long .Lskel_string1 # String in Bucket 2: ASplit + .long .Lnames1-.Lnames_entries0 # Offset in Bucket 0 + .long .Lnames2-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames3-.Lnames_entries0 # Offset in Bucket 2 + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 2 +.Lnames_abbrev_start0: + .byte 1 # Abbrev code + .byte 36 # DW_TAG_base_type + .byte 2 # DW_IDX_type_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 2 # Abbrev code + .byte 36 # DW_TAG_base_type + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 3 # Abbrev code + .byte 52 # DW_TAG_variable + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 4 # Abbrev code + .byte 46 # DW_TAG_subprogram + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 5 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 2 # DW_IDX_type_unit + .byte 11 # DW_FORM_data1 + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 6 # Abbrev code + .byte 19 # DW_TAG_structure_type + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 4 # DW_IDX_parent + .byte 25 # DW_FORM_flag_present + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames1: +.L5: + .byte 1 # Abbreviation code + .byte 0 # DW_IDX_type_unit + .long 49 # DW_IDX_die_offset +.L1: # DW_IDX_parent + .byte 2 # Abbreviation code + .long 61 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: int +.Lnames2: +.L0: + .byte 3 # Abbreviation code + .long 26 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: globalSplit +.Lnames3: +.L2: + .byte 4 # Abbreviation code + .long 46 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: main +.Lnames0: +.L4: + .byte 5 # Abbreviation code + .byte 0 # DW_IDX_type_unit + .long 33 # DW_IDX_die_offset +.L3: # DW_IDX_parent + .byte 6 # Abbreviation code + .long 37 # DW_IDX_die_offset + .byte 0 # DW_IDX_parent + # End of list: ASplit + .p2align 2, 0x0 +.Lnames_end0: + .ident "clang version 19.0.0git (git@github.com:llvm/llvm-project.git ced1fac8a32e35b63733bda27c7f5b9a2b635403)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/dwarf5-df-main-debug-names-ftu-ltu-mix.test b/bolt/test/X86/dwarf5-df-main-debug-names-ftu-ltu-mix.test new file mode 100644 index 0000000000000000000000000000000000000000..8a8a4b118b8c031c3ae96ed05d4a4c124543b2e5 --- /dev/null +++ b/bolt/test/X86/dwarf5-df-main-debug-names-ftu-ltu-mix.test @@ -0,0 +1,56 @@ +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-debug-names-ftu-ltu-mix-main.s \ +; RUN: -split-dwarf-file=main.dwo -o main.o +; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper.s -o helper.o +; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-debug-names-ftu-ltu-mix-helper1.s -o helper1.o +; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o helper.o helper1.o -o main.exe -fno-pic -no-pie +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections --create-debug-names-section=true +; RUN: llvm-dwarfdump --debug-names main.exe.bolt | FileCheck -check-prefix=BOLT %s + +;; Tests BOLT correctly sets foreign TU Index when there are local TUs. + +; BOLT: Compilation Unit offsets [ +; BOLT-NEXT: CU[0]: {{.+}} +; BOLT-NEXT: CU[1]: {{.+}} +; BOLT-NEXT: CU[2]: {{.+}} +; BOLT-NEXT: ] +; BOLT-NEXT: Local Type Unit offsets [ +; BOLT-NEXT: LocalTU[0]: {{.+}} +; BOLT-NEXT: LocalTU[1]: {{.+}} +; BOLT-NEXT: ] +; BOLT-NEXT: Foreign Type Unit signatures [ +; BOLT-NEXT: ForeignTU[0]: 0x889c84450dac881f +; BOLT-NEXT: ] +; BOLT: Name 3 { +; BOLT-NEXT: Hash: 0x6A05C500 +; BOLT-NEXT: String: {{.+}} "globalMono1" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: 0x5 +; BOLT-NEXT: Tag: DW_TAG_variable +; BOLT-NEXT: DW_IDX_compile_unit: 0x02 +; BOLT-NEXT: DW_IDX_die_offset: 0x0000001e +; BOLT-NEXT: } +; BOLT-NEXT: } +; BOLT: Name 6 { +; BOLT-NEXT: Hash: 0xF283AF92 +; BOLT-NEXT: String: {{.+}} "ASplit" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: 0x7 +; BOLT-NEXT: Tag: DW_TAG_structure_type +; BOLT-NEXT: DW_IDX_type_unit: 0x02 +; BOLT-NEXT: DW_IDX_compile_unit: 0x00 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000021 +; BOLT-NEXT: } +; BOLT-NEXT: } +; BOLT: Name 7 { +; BOLT-NEXT: Hash: 0xF17F51F +; BOLT-NEXT: String: {{.+}} "AMono" +; BOLT-NEXT: Entry @ {{.+}} { +; BOLT-NEXT: Abbrev: 0x4 +; BOLT-NEXT: Tag: DW_TAG_structure_type +; BOLT-NEXT: DW_IDX_type_unit: 0x00 +; BOLT-NEXT: DW_IDX_die_offset: 0x00000023 +; BOLT-NEXT: } +; BOLT-NEXT: } diff --git a/bolt/test/X86/gotpcrelx.s b/bolt/test/X86/gotpcrelx.s index ddac5ebda0caf0cd849465865cd6c0e8a97e6f49..6dec125c6a72bdf24638bf0b3beb057be24cbc99 100644 --- a/bolt/test/X86/gotpcrelx.s +++ b/bolt/test/X86/gotpcrelx.s @@ -5,8 +5,7 @@ ## kinds of handling of the relocation by the linker (no relaxation, pic, and ## non-pic). -# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux \ -# RUN: -relax-relocations %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t.o # RUN: ld.lld %t.o -o %t.exe -q # RUN: ld.lld %t.o -o %t.pie.exe -q -pie # RUN: ld.lld %t.o -o %t.no-relax.exe -q --no-relax diff --git a/bolt/test/X86/linux-alt-instruction.s b/bolt/test/X86/linux-alt-instruction.s new file mode 100644 index 0000000000000000000000000000000000000000..5dcc6fe3ab0c81f178bd447be064529d79f11593 --- /dev/null +++ b/bolt/test/X86/linux-alt-instruction.s @@ -0,0 +1,97 @@ +# REQUIRES: system-linux + +## Check that BOLT correctly parses the Linux kernel .altinstructions section +## and annotates alternative instructions. + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ +# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie +# RUN: llvm-bolt %t.exe --print-normalized --keep-nops -o %t.out \ +# RUN: --alt-inst-feature-size=2 | FileCheck %s + +## Older kernels used to have padlen field in alt_instr. Check compatibility. + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown --defsym PADLEN=1 \ +# RUN: %s -o %t.o +# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ +# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie +# RUN: llvm-bolt %t.exe --print-normalized --keep-nops --alt-inst-has-padlen \ +# RUN: -o %t.out | FileCheck %s + +## Check with a larger size of "feature" field in alt_instr. + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown \ +# RUN: --defsym FEATURE_SIZE_4=1 %s -o %t.o +# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ +# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie +# RUN: llvm-bolt %t.exe --print-normalized --keep-nops \ +# RUN: --alt-inst-feature-size=4 -o %t.out | FileCheck %s + +## Check that out-of-bounds read is handled properly. + +# RUN: not llvm-bolt %t.exe --print-normalized --keep-nops \ +# RUN: --alt-inst-feature-size=2 -o %t.out + +# CHECK: BOLT-INFO: Linux kernel binary detected +# CHECK: BOLT-INFO: parsed 2 alternative instruction entries + + .text + .globl _start + .type _start, %function +_start: +# CHECK: Binary Function "_start" +.L0: + rdtsc +# CHECK: rdtsc +# CHECK-SAME: AltInst: 1 +# CHECK-SAME: AltInst2: 2 + nop +# CHECK-NEXT: nop +# CHECK-SAME: AltInst: 1 +# CHECK-SAME: AltInst2: 2 + nop + nop +.L1: + ret + .size _start, .-_start + + .section .altinstr_replacement,"ax",@progbits +.A0: + lfence + rdtsc +.A1: + rdtscp +.Ae: + +## Alternative instruction info. + .section .altinstructions,"a",@progbits + + .long .L0 - . # org instruction + .long .A0 - . # alt instruction +.ifdef FEATURE_SIZE_4 + .long 0x72 # feature flags +.else + .word 0x72 # feature flags +.endif + .byte .L1 - .L0 # org size + .byte .A1 - .A0 # alt size +.ifdef PADLEN + .byte 0 +.endif + + .long .L0 - . # org instruction + .long .A1 - . # alt instruction +.ifdef FEATURE_SIZE_4 + .long 0x3b # feature flags +.else + .word 0x3b # feature flags +.endif + .byte .L1 - .L0 # org size + .byte .Ae - .A1 # alt size +.ifdef PADLEN + .byte 0 +.endif + +## Fake Linux Kernel sections. + .section __ksymtab,"a",@progbits + .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/test/X86/linux-bug-table.s b/bolt/test/X86/linux-bug-table.s new file mode 100644 index 0000000000000000000000000000000000000000..e8de2fb6cba79ddab8061705700f263200c0701e --- /dev/null +++ b/bolt/test/X86/linux-bug-table.s @@ -0,0 +1,46 @@ +# REQUIRES: system-linux + +## Check that BOLT correctly parses the Linux kernel __bug_table section. + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ +# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie + +## Verify bug entry bindings to instructions. + +# RUN: llvm-bolt %t.exe --print-normalized -o %t.out | FileCheck %s + +# CHECK: BOLT-INFO: Linux kernel binary detected +# CHECK: BOLT-INFO: parsed 2 bug table entries + + .text + .globl _start + .type _start, %function +_start: +# CHECK: Binary Function "_start" + nop +.L0: + ud2 +# CHECK: ud2 +# CHECK-SAME: BugEntry: 1 + nop +.L1: + ud2 +# CHECK: ud2 +# CHECK-SAME: BugEntry: 2 + ret + .size _start, .-_start + + +## Bug table. + .section __bug_table,"a",@progbits +1: + .long .L0 - . # instruction + .org 1b + 12 +2: + .long .L1 - . # instruction + .org 2b + 12 + +## Fake Linux Kernel sections. + .section __ksymtab,"a",@progbits + .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/test/X86/linux-exceptions.s b/bolt/test/X86/linux-exceptions.s new file mode 100644 index 0000000000000000000000000000000000000000..20b8c965f853a97cf782307e9f4dc3881489e793 --- /dev/null +++ b/bolt/test/X86/linux-exceptions.s @@ -0,0 +1,64 @@ +# REQUIRES: system-linux + +## Check that BOLT correctly parses the Linux kernel exception table. + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ +# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr + +## Verify exception bindings to instructions. + +# RUN: llvm-bolt %t.exe --print-normalized -o %t.out --keep-nops=0 \ +# RUN: --bolt-info=0 | FileCheck %s + +## Verify the bindings again on the rewritten binary with nops removed. + +# RUN: llvm-bolt %t.out -o %t.out.1 --print-normalized | FileCheck %s + +# CHECK: BOLT-INFO: Linux kernel binary detected +# CHECK: BOLT-INFO: parsed 2 exception table entries + + .text + .globl _start + .type _start, %function +_start: +# CHECK: Binary Function "_start" + nop +.L0: + mov (%rdi), %rax +# CHECK: mov +# CHECK-SAME: ExceptionEntry: 1 # Fixup: [[FIXUP:[a-zA-Z0-9_]+]] + nop +.L1: + mov (%rsi), %rax +# CHECK: mov +# CHECK-SAME: ExceptionEntry: 2 # Fixup: [[FIXUP]] + nop + ret +.LF0: +# CHECK: Secondary Entry Point: [[FIXUP]] + jmp foo + .size _start, .-_start + + .globl foo + .type foo, %function +foo: + ret + .size foo, .-foo + + +## Exception table. + .section __ex_table,"a",@progbits + .align 4 + + .long .L0 - . # instruction + .long .LF0 - . # fixup + .long 0 # data + + .long .L1 - . # instruction + .long .LF0 - . # fixup + .long 0 # data + +## Fake Linux Kernel sections. + .section __ksymtab,"a",@progbits + .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/test/X86/linux-parainstructions.s b/bolt/test/X86/linux-parainstructions.s new file mode 100644 index 0000000000000000000000000000000000000000..4bdfde5fb7f24bf505ae4537b988fa8321d6db20 --- /dev/null +++ b/bolt/test/X86/linux-parainstructions.s @@ -0,0 +1,54 @@ +# REQUIRES: system-linux + +## Check that BOLT correctly parses the Linux kernel .parainstructions section. + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: %clang %cflags -nostdlib %t.o -o %t.exe \ +# RUN: -Wl,--image-base=0xffffffff80000000,--no-dynamic-linker,--no-eh-frame-hdr,--no-pie + +## Verify paravirtual bindings to instructions. + +# RUN: llvm-bolt %t.exe --print-normalized -o %t.out | FileCheck %s + +# CHECK: BOLT-INFO: Linux kernel binary detected +# CHECK: BOLT-INFO: parsed 2 paravirtual patch sites + + .rodata +fptr: + .quad 0 + + .text + .globl _start + .type _start, %function +_start: +# CHECK: Binary Function "_start" + nop +.L1: + call *fptr(%rip) +# CHECK: call +# CHECK-SAME: ParaSite: 1 + nop +.L2: + call *fptr(%rip) +# CHECK: call +# CHECK-SAME: ParaSite: 2 + ret + .size _start, .-_start + + +## Paravirtual patch sites. + .section .parainstructions,"a",@progbits + + .balign 8 + .quad .L1 # instruction + .byte 1 # type + .byte 7 # length + + .balign 8 + .quad .L2 # instruction + .byte 1 # type + .byte 7 # length + +## Fake Linux Kernel sections. + .section __ksymtab,"a",@progbits + .section __ksymtab_gpl,"a",@progbits diff --git a/bolt/test/X86/pt_gnu_relro.s b/bolt/test/X86/pt_gnu_relro.s index ad8d475c83724b6281e2e9ea58e8b3618b0d67f5..fa4af8287494fcb47cb614f836aad011a24595f5 100644 --- a/bolt/test/X86/pt_gnu_relro.s +++ b/bolt/test/X86/pt_gnu_relro.s @@ -3,7 +3,7 @@ # Check that BOLT recognizes PT_GNU_RELRO segment and marks respective sections # accordingly. -# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t.o -relax-relocations +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t.o # RUN: ld.lld %t.o -o %t.exe -q --no-relax # RUN: llvm-readelf -We %t.exe | FileCheck --check-prefix=READELF %s # Unfortunately there's no direct way to extract a segment to section mapping diff --git a/bolt/tools/merge-fdata/merge-fdata.cpp b/bolt/tools/merge-fdata/merge-fdata.cpp index c6dfd3cfdc56deaf6fbd676574cf8c5f5adf0839..f2ac5ad4492ee526a09e3911fa54917285ad9d8a 100644 --- a/bolt/tools/merge-fdata/merge-fdata.cpp +++ b/bolt/tools/merge-fdata/merge-fdata.cpp @@ -316,7 +316,7 @@ void mergeLegacyProfiles(const SmallVectorImpl &Filenames) { // least 4 tasks. ThreadPoolStrategy S = optimal_concurrency( std::max(Filenames.size() / 4, static_cast(1))); - ThreadPool Pool(S); + DefaultThreadPool Pool(S); DenseMap ParsedProfiles( Pool.getMaxConcurrency()); for (const auto &Filename : Filenames) diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp index 22bdb5de22d87107055b472d0490577e35c45ce8..21b581fa6df2e1e59f172a393f4410c882d7becd 100644 --- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -238,7 +238,7 @@ Example usage for a project using a compile commands database: Error = false; llvm::sys::Mutex IndexMutex; // ExecutorConcurrency is a flag exposed by AllTUsExecution.h - llvm::ThreadPool Pool(llvm::hardware_concurrency(ExecutorConcurrency)); + llvm::DefaultThreadPool Pool(llvm::hardware_concurrency(ExecutorConcurrency)); for (auto &Group : USRToBitcode) { Pool.async([&]() { std::vector> Infos; diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp index b2d0efecc206922dbe113fd1f4afd4c9d0768230..298b02e77cb0aa36cb50e8e8169a9878678ed848 100644 --- a/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp +++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp @@ -89,7 +89,7 @@ bool Merge(llvm::StringRef MergeDir, llvm::StringRef OutputFile) { // Load all symbol files in MergeDir. { - llvm::ThreadPool Pool; + llvm::DefaultThreadPool Pool; for (llvm::sys::fs::directory_iterator Dir(MergeDir, EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { // Parse YAML files in parallel. diff --git a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp index 43bedd4f73ef44736effccd6be21b17d395fea41..c650aae4fa03c088c24d44d872edb37da105dfd1 100644 --- a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp @@ -60,16 +60,26 @@ AST_MATCHER_P2(Expr, hasSideEffect, bool, CheckFunctionCalls, } if (const auto *CExpr = dyn_cast(E)) { - bool Result = CheckFunctionCalls; + if (!CheckFunctionCalls) + return false; if (const auto *FuncDecl = CExpr->getDirectCallee()) { if (FuncDecl->getDeclName().isIdentifier() && IgnoredFunctionsMatcher.matches(*FuncDecl, Finder, Builder)) // exceptions come here - Result = false; - else if (const auto *MethodDecl = dyn_cast(FuncDecl)) - Result &= !MethodDecl->isConst(); + return false; + for (size_t I = 0; I < FuncDecl->getNumParams(); I++) { + const ParmVarDecl *P = FuncDecl->getParamDecl(I); + const Expr *ArgExpr = + I < CExpr->getNumArgs() ? CExpr->getArg(I) : nullptr; + const QualType PT = P->getType().getCanonicalType(); + if (ArgExpr && !ArgExpr->isXValue() && PT->isReferenceType() && + !PT.getNonReferenceType().isConstQualified()) + return true; + } + if (const auto *MethodDecl = dyn_cast(FuncDecl)) + return !MethodDecl->isConst(); } - return Result; + return true; } return isa(E) || isa(E) || isa(E); diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp index a8a23b045f80bb83c0dbf3d9ea1f6dbdf476a008..e518a64abc52eb30a60d127fdd2cf4da77a26077 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp @@ -20,6 +20,7 @@ #include "ChainedComparisonCheck.h" #include "ComparePointerToMemberVirtualFunctionCheck.h" #include "CopyConstructorInitCheck.h" +#include "CrtpConstructorAccessibilityCheck.h" #include "DanglingHandleCheck.h" #include "DynamicStaticInitializersCheck.h" #include "EasilySwappableParametersCheck.h" @@ -237,6 +238,8 @@ public: "bugprone-unhandled-exception-at-new"); CheckFactories.registerCheck( "bugprone-unique-ptr-array-mismatch"); + CheckFactories.registerCheck( + "bugprone-crtp-constructor-accessibility"); CheckFactories.registerCheck( "bugprone-unsafe-functions"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt index 1cd6fb207d7625ac1124c1490008456182f49b86..638fba03a4358795cb1fb75384d250f2f527c239 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -79,6 +79,7 @@ add_clang_library(clangTidyBugproneModule UnhandledExceptionAtNewCheck.cpp UnhandledSelfAssignmentCheck.cpp UniquePtrArrayMismatchCheck.cpp + CrtpConstructorAccessibilityCheck.cpp UnsafeFunctionsCheck.cpp UnusedLocalNonTrivialVariableCheck.cpp UnusedRaiiCheck.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6175fcdfd229c3a1409217786a95e44dc539034a --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp @@ -0,0 +1,181 @@ +//===--- CrtpConstructorAccessibilityCheck.cpp - clang-tidy ---------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "CrtpConstructorAccessibilityCheck.h" +#include "../utils/LexerUtils.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::bugprone { + +static bool hasPrivateConstructor(const CXXRecordDecl *RD) { + return llvm::any_of(RD->ctors(), [](const CXXConstructorDecl *Ctor) { + return Ctor->getAccess() == AS_private; + }); +} + +static bool isDerivedParameterBefriended(const CXXRecordDecl *CRTP, + const NamedDecl *Param) { + return llvm::any_of(CRTP->friends(), [&](const FriendDecl *Friend) { + const TypeSourceInfo *const FriendType = Friend->getFriendType(); + if (!FriendType) { + return false; + } + + const auto *const TTPT = + dyn_cast(FriendType->getType()); + + return TTPT && TTPT->getDecl() == Param; + }); +} + +static bool isDerivedClassBefriended(const CXXRecordDecl *CRTP, + const CXXRecordDecl *Derived) { + return llvm::any_of(CRTP->friends(), [&](const FriendDecl *Friend) { + const TypeSourceInfo *const FriendType = Friend->getFriendType(); + if (!FriendType) { + return false; + } + + return FriendType->getType()->getAsCXXRecordDecl() == Derived; + }); +} + +static const NamedDecl * +getDerivedParameter(const ClassTemplateSpecializationDecl *CRTP, + const CXXRecordDecl *Derived) { + size_t Idx = 0; + const bool AnyOf = llvm::any_of( + CRTP->getTemplateArgs().asArray(), [&](const TemplateArgument &Arg) { + ++Idx; + return Arg.getKind() == TemplateArgument::Type && + Arg.getAsType()->getAsCXXRecordDecl() == Derived; + }); + + return AnyOf ? CRTP->getSpecializedTemplate() + ->getTemplateParameters() + ->getParam(Idx - 1) + : nullptr; +} + +static std::vector +hintMakeCtorPrivate(const CXXConstructorDecl *Ctor, + const std::string &OriginalAccess) { + std::vector Hints; + + Hints.emplace_back(FixItHint::CreateInsertion( + Ctor->getBeginLoc().getLocWithOffset(-1), "private:\n")); + + const ASTContext &ASTCtx = Ctor->getASTContext(); + const SourceLocation CtorEndLoc = + Ctor->isExplicitlyDefaulted() + ? utils::lexer::findNextTerminator(Ctor->getEndLoc(), + ASTCtx.getSourceManager(), + ASTCtx.getLangOpts()) + : Ctor->getEndLoc(); + Hints.emplace_back(FixItHint::CreateInsertion( + CtorEndLoc.getLocWithOffset(1), '\n' + OriginalAccess + ':' + '\n')); + + return Hints; +} + +void CrtpConstructorAccessibilityCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + classTemplateSpecializationDecl( + decl().bind("crtp"), + hasAnyTemplateArgument(refersToType(recordType(hasDeclaration( + cxxRecordDecl( + isDerivedFrom(cxxRecordDecl(equalsBoundNode("crtp")))) + .bind("derived")))))), + this); +} + +void CrtpConstructorAccessibilityCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *CRTPInstantiation = + Result.Nodes.getNodeAs("crtp"); + const auto *DerivedRecord = Result.Nodes.getNodeAs("derived"); + const CXXRecordDecl *CRTPDeclaration = + CRTPInstantiation->getSpecializedTemplate()->getTemplatedDecl(); + + if (!CRTPDeclaration->hasDefinition()) { + return; + } + + const auto *DerivedTemplateParameter = + getDerivedParameter(CRTPInstantiation, DerivedRecord); + + assert(DerivedTemplateParameter && + "No template parameter corresponds to the derived class of the CRTP."); + + bool NeedsFriend = !isDerivedParameterBefriended(CRTPDeclaration, + DerivedTemplateParameter) && + !isDerivedClassBefriended(CRTPDeclaration, DerivedRecord); + + const FixItHint HintFriend = FixItHint::CreateInsertion( + CRTPDeclaration->getBraceRange().getEnd(), + "friend " + DerivedTemplateParameter->getNameAsString() + ';' + '\n'); + + if (hasPrivateConstructor(CRTPDeclaration) && NeedsFriend) { + diag(CRTPDeclaration->getLocation(), + "the CRTP cannot be constructed from the derived class; consider " + "declaring the derived class as friend") + << HintFriend; + } + + auto WithFriendHintIfNeeded = + [&](const DiagnosticBuilder &Diag, + bool NeedsFriend) -> const DiagnosticBuilder & { + if (NeedsFriend) + Diag << HintFriend; + + return Diag; + }; + + if (!CRTPDeclaration->hasUserDeclaredConstructor()) { + const bool IsStruct = CRTPDeclaration->isStruct(); + + WithFriendHintIfNeeded( + diag(CRTPDeclaration->getLocation(), + "the implicit default constructor of the CRTP is publicly " + "accessible; consider making it private%select{| and declaring " + "the derived class as friend}0") + << NeedsFriend + << FixItHint::CreateInsertion( + CRTPDeclaration->getBraceRange().getBegin().getLocWithOffset( + 1), + (IsStruct ? "\nprivate:\n" : "\n") + + CRTPDeclaration->getNameAsString() + "() = default;\n" + + (IsStruct ? "public:\n" : "")), + NeedsFriend); + } + + for (auto &&Ctor : CRTPDeclaration->ctors()) { + if (Ctor->getAccess() == AS_private) + continue; + + const bool IsPublic = Ctor->getAccess() == AS_public; + const std::string Access = IsPublic ? "public" : "protected"; + + WithFriendHintIfNeeded( + diag(Ctor->getLocation(), + "%0 contructor allows the CRTP to be %select{inherited " + "from|constructed}1 as a regular template class; consider making " + "it private%select{| and declaring the derived class as friend}2") + << Access << IsPublic << NeedsFriend + << hintMakeCtorPrivate(Ctor, Access), + NeedsFriend); + } +} + +bool CrtpConstructorAccessibilityCheck::isLanguageVersionSupported( + const LangOptions &LangOpts) const { + return LangOpts.CPlusPlus11; +} +} // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.h b/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.h new file mode 100644 index 0000000000000000000000000000000000000000..785116218f468994c74c6472230a6aa1484aedea --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.h @@ -0,0 +1,32 @@ +//===--- CrtpConstructorAccessibilityCheck.h - clang-tidy -------*- 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_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_CRTPCONSTRUCTORACCESSIBILITYCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_CRTPCONSTRUCTORACCESSIBILITYCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::bugprone { + +/// Detects error-prone Curiously Recurring Template Pattern usage, when the +/// CRTP can be constructed outside itself and the derived class. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/crtp-constructor-accessibility.html +class CrtpConstructorAccessibilityCheck : public ClangTidyCheck { +public: + CrtpConstructorAccessibilityCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override; +}; + +} // namespace clang::tidy::bugprone + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_CRTPCONSTRUCTORACCESSIBILITYCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp index 05012c7df6a97585762f1777f319bfd1f762aa27..243fe47c2036b6c3104c8e419c070a591b8fcc7f 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp @@ -11,6 +11,8 @@ #include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Basic/OperatorKinds.h" using namespace clang::ast_matchers; using namespace clang::ast_matchers::internal; @@ -28,145 +30,156 @@ AST_MATCHER_P(FunctionDecl, isInstantiatedFrom, Matcher, return InnerMatcher.matches(InstantiatedFrom ? *InstantiatedFrom : Node, Finder, Builder); } + +AST_MATCHER_P(CXXMethodDecl, isOperatorOverloading, + llvm::SmallVector, Kinds) { + return llvm::is_contained(Kinds, Node.getOverloadedOperator()); +} } // namespace UnusedReturnValueCheck::UnusedReturnValueCheck(llvm::StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - CheckedFunctions(Options.get("CheckedFunctions", - "::std::async;" - "::std::launder;" - "::std::remove;" - "::std::remove_if;" - "::std::unique;" - "::std::unique_ptr::release;" - "::std::basic_string::empty;" - "::std::vector::empty;" - "::std::back_inserter;" - "::std::distance;" - "::std::find;" - "::std::find_if;" - "::std::inserter;" - "::std::lower_bound;" - "::std::make_pair;" - "::std::map::count;" - "::std::map::find;" - "::std::map::lower_bound;" - "::std::multimap::equal_range;" - "::std::multimap::upper_bound;" - "::std::set::count;" - "::std::set::find;" - "::std::setfill;" - "::std::setprecision;" - "::std::setw;" - "::std::upper_bound;" - "::std::vector::at;" - // C standard library - "::bsearch;" - "::ferror;" - "::feof;" - "::isalnum;" - "::isalpha;" - "::isblank;" - "::iscntrl;" - "::isdigit;" - "::isgraph;" - "::islower;" - "::isprint;" - "::ispunct;" - "::isspace;" - "::isupper;" - "::iswalnum;" - "::iswprint;" - "::iswspace;" - "::isxdigit;" - "::memchr;" - "::memcmp;" - "::strcmp;" - "::strcoll;" - "::strncmp;" - "::strpbrk;" - "::strrchr;" - "::strspn;" - "::strstr;" - "::wcscmp;" - // POSIX - "::access;" - "::bind;" - "::connect;" - "::difftime;" - "::dlsym;" - "::fnmatch;" - "::getaddrinfo;" - "::getopt;" - "::htonl;" - "::htons;" - "::iconv_open;" - "::inet_addr;" - "::isascii;" - "::isatty;" - "::mmap;" - "::newlocale;" - "::openat;" - "::pathconf;" - "::pthread_equal;" - "::pthread_getspecific;" - "::pthread_mutex_trylock;" - "::readdir;" - "::readlink;" - "::recvmsg;" - "::regexec;" - "::scandir;" - "::semget;" - "::setjmp;" - "::shm_open;" - "::shmget;" - "::sigismember;" - "::strcasecmp;" - "::strsignal;" - "::ttyname")), + CheckedFunctions(utils::options::parseStringList( + Options.get("CheckedFunctions", "::std::async$;" + "::std::launder$;" + "::std::remove$;" + "::std::remove_if$;" + "::std::unique$;" + "::std::unique_ptr::release$;" + "::std::basic_string::empty$;" + "::std::vector::empty$;" + "::std::back_inserter$;" + "::std::distance$;" + "::std::find$;" + "::std::find_if$;" + "::std::inserter$;" + "::std::lower_bound$;" + "::std::make_pair$;" + "::std::map::count$;" + "::std::map::find$;" + "::std::map::lower_bound$;" + "::std::multimap::equal_range$;" + "::std::multimap::upper_bound$;" + "::std::set::count$;" + "::std::set::find$;" + "::std::setfill$;" + "::std::setprecision$;" + "::std::setw$;" + "::std::upper_bound$;" + "::std::vector::at$;" + // C standard library + "::bsearch$;" + "::ferror$;" + "::feof$;" + "::isalnum$;" + "::isalpha$;" + "::isblank$;" + "::iscntrl$;" + "::isdigit$;" + "::isgraph$;" + "::islower$;" + "::isprint$;" + "::ispunct$;" + "::isspace$;" + "::isupper$;" + "::iswalnum$;" + "::iswprint$;" + "::iswspace$;" + "::isxdigit$;" + "::memchr$;" + "::memcmp$;" + "::strcmp$;" + "::strcoll$;" + "::strncmp$;" + "::strpbrk$;" + "::strrchr$;" + "::strspn$;" + "::strstr$;" + "::wcscmp$;" + // POSIX + "::access$;" + "::bind$;" + "::connect$;" + "::difftime$;" + "::dlsym$;" + "::fnmatch$;" + "::getaddrinfo$;" + "::getopt$;" + "::htonl$;" + "::htons$;" + "::iconv_open$;" + "::inet_addr$;" + "::isascii$;" + "::isatty$;" + "::mmap$;" + "::newlocale$;" + "::openat$;" + "::pathconf$;" + "::pthread_equal$;" + "::pthread_getspecific$;" + "::pthread_mutex_trylock$;" + "::readdir$;" + "::readlink$;" + "::recvmsg$;" + "::regexec$;" + "::scandir$;" + "::semget$;" + "::setjmp$;" + "::shm_open$;" + "::shmget$;" + "::sigismember$;" + "::strcasecmp$;" + "::strsignal$;" + "::ttyname"))), CheckedReturnTypes(utils::options::parseStringList( - Options.get("CheckedReturnTypes", "::std::error_code;" - "::std::error_condition;" - "::std::errc;" - "::std::expected;" + Options.get("CheckedReturnTypes", "::std::error_code$;" + "::std::error_condition$;" + "::std::errc$;" + "::std::expected$;" "::boost::system::error_code"))), AllowCastToVoid(Options.get("AllowCastToVoid", false)) {} -UnusedReturnValueCheck::UnusedReturnValueCheck(llvm::StringRef Name, - ClangTidyContext *Context, - std::string CheckedFunctions) +UnusedReturnValueCheck::UnusedReturnValueCheck( + llvm::StringRef Name, ClangTidyContext *Context, + std::vector CheckedFunctions) : UnusedReturnValueCheck(Name, Context, std::move(CheckedFunctions), {}, false) {} UnusedReturnValueCheck::UnusedReturnValueCheck( llvm::StringRef Name, ClangTidyContext *Context, - std::string CheckedFunctions, std::vector CheckedReturnTypes, - bool AllowCastToVoid) + std::vector CheckedFunctions, + std::vector CheckedReturnTypes, bool AllowCastToVoid) : ClangTidyCheck(Name, Context), CheckedFunctions(std::move(CheckedFunctions)), CheckedReturnTypes(std::move(CheckedReturnTypes)), AllowCastToVoid(AllowCastToVoid) {} void UnusedReturnValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "CheckedFunctions", CheckedFunctions); + Options.store(Opts, "CheckedFunctions", + utils::options::serializeStringList(CheckedFunctions)); Options.store(Opts, "CheckedReturnTypes", utils::options::serializeStringList(CheckedReturnTypes)); Options.store(Opts, "AllowCastToVoid", AllowCastToVoid); } void UnusedReturnValueCheck::registerMatchers(MatchFinder *Finder) { - auto FunVec = utils::options::parseStringList(CheckedFunctions); - - auto MatchedDirectCallExpr = - expr(callExpr(callee(functionDecl( - // Don't match void overloads of checked functions. - unless(returns(voidType())), - anyOf(isInstantiatedFrom(hasAnyName(FunVec)), - returns(hasCanonicalType(hasDeclaration( - namedDecl(matchers::matchesAnyListedName( - CheckedReturnTypes))))))))) - .bind("match")); + auto MatchedDirectCallExpr = expr( + callExpr( + callee(functionDecl( + // Don't match void overloads of checked functions. + unless(returns(voidType())), + // Don't match copy or move assignment operator. + unless(cxxMethodDecl(isOperatorOverloading( + {OO_Equal, OO_PlusEqual, OO_MinusEqual, OO_StarEqual, + OO_SlashEqual, OO_PercentEqual, OO_CaretEqual, OO_AmpEqual, + OO_PipeEqual, OO_LessLessEqual, OO_GreaterGreaterEqual}))), + anyOf( + isInstantiatedFrom( + matchers::matchesAnyListedName(CheckedFunctions)), + returns(hasCanonicalType(hasDeclaration(namedDecl( + matchers::matchesAnyListedName(CheckedReturnTypes))))))))) + .bind("match")); auto CheckCastToVoid = AllowCastToVoid ? castExpr(unless(hasCastKind(CK_ToVoid))) : castExpr(); diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h index ab2cc691b894f7b08442d9d3d6410f0b3a70502a..d65a567e1c468a713a2149c8d0230d606913101b 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h @@ -29,14 +29,14 @@ public: } private: - std::string CheckedFunctions; + const std::vector CheckedFunctions; const std::vector CheckedReturnTypes; protected: UnusedReturnValueCheck(StringRef Name, ClangTidyContext *Context, - std::string CheckedFunctions); + std::vector CheckedFunctions); UnusedReturnValueCheck(StringRef Name, ClangTidyContext *Context, - std::string CheckedFunctions, + std::vector CheckedFunctions, std::vector CheckedReturnTypes, bool AllowCastToVoid); bool AllowCastToVoid; diff --git a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp index c5b6b541096ca9805e04c31c2b42d901abfffdab..b91ad0f18229550dfd0b552c98336f1a2fc911e4 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp @@ -330,7 +330,8 @@ void UseAfterMoveFinder::getReinits( traverse(TK_AsIs, DeclRefMatcher), unless(parmVarDecl(hasType( references(qualType(isConstQualified())))))), - unless(callee(functionDecl(hasName("::std::move"))))))) + unless(callee(functionDecl( + hasAnyName("::std::move", "::std::forward"))))))) .bind("reinit"); Stmts->clear(); @@ -359,24 +360,46 @@ void UseAfterMoveFinder::getReinits( } } +enum class MoveType { + Move, // std::move + Forward, // std::forward +}; + +static MoveType determineMoveType(const FunctionDecl *FuncDecl) { + if (FuncDecl->getName() == "move") + return MoveType::Move; + if (FuncDecl->getName() == "forward") + return MoveType::Forward; + + llvm_unreachable("Invalid move type"); +} + static void emitDiagnostic(const Expr *MovingCall, const DeclRefExpr *MoveArg, const UseAfterMove &Use, ClangTidyCheck *Check, - ASTContext *Context) { - SourceLocation UseLoc = Use.DeclRef->getExprLoc(); - SourceLocation MoveLoc = MovingCall->getExprLoc(); + ASTContext *Context, MoveType Type) { + const SourceLocation UseLoc = Use.DeclRef->getExprLoc(); + const SourceLocation MoveLoc = MovingCall->getExprLoc(); + + const bool IsMove = (Type == MoveType::Move); - Check->diag(UseLoc, "'%0' used after it was moved") - << MoveArg->getDecl()->getName(); - Check->diag(MoveLoc, "move occurred here", DiagnosticIDs::Note); + Check->diag(UseLoc, "'%0' used after it was %select{forwarded|moved}1") + << MoveArg->getDecl()->getName() << IsMove; + Check->diag(MoveLoc, "%select{forward|move}0 occurred here", + DiagnosticIDs::Note) + << IsMove; if (Use.EvaluationOrderUndefined) { - Check->diag(UseLoc, - "the use and move are unsequenced, i.e. there is no guarantee " - "about the order in which they are evaluated", - DiagnosticIDs::Note); + Check->diag( + UseLoc, + "the use and %select{forward|move}0 are unsequenced, i.e. " + "there is no guarantee about the order in which they are evaluated", + DiagnosticIDs::Note) + << IsMove; } else if (UseLoc < MoveLoc || Use.DeclRef == MoveArg) { Check->diag(UseLoc, - "the use happens in a later loop iteration than the move", - DiagnosticIDs::Note); + "the use happens in a later loop iteration than the " + "%select{forward|move}0", + DiagnosticIDs::Note) + << IsMove; } } @@ -388,7 +411,9 @@ void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) { auto TryEmplaceMatcher = cxxMemberCallExpr(callee(cxxMethodDecl(hasName("try_emplace")))); auto CallMoveMatcher = - callExpr(argumentCountIs(1), callee(functionDecl(hasName("::std::move"))), + callExpr(argumentCountIs(1), + callee(functionDecl(hasAnyName("::std::move", "::std::forward")) + .bind("move-decl")), hasArgument(0, declRefExpr().bind("arg")), unless(inDecltypeOrTemplateArg()), unless(hasParent(TryEmplaceMatcher)), expr().bind("call-move"), @@ -436,6 +461,7 @@ void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) { const auto *CallMove = Result.Nodes.getNodeAs("call-move"); const auto *MovingCall = Result.Nodes.getNodeAs("moving-call"); const auto *Arg = Result.Nodes.getNodeAs("arg"); + const auto *MoveDecl = Result.Nodes.getNodeAs("move-decl"); if (!MovingCall || !MovingCall->getExprLoc().isValid()) MovingCall = CallMove; @@ -470,7 +496,8 @@ void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) { UseAfterMoveFinder Finder(Result.Context); UseAfterMove Use; if (Finder.find(CodeBlock, MovingCall, Arg->getDecl(), &Use)) - emitDiagnostic(MovingCall, Arg, Use, this, Result.Context); + emitDiagnostic(MovingCall, Arg, Use, this, Result.Context, + determineMoveType(MoveDecl)); } } diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp index c633683570f748045ab3a67f4fa861f6b7df063c..87fd8adf997082593a28d680478c06f06fcfd9fc 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp @@ -112,10 +112,12 @@ void MissingStdForwardCheck::registerMatchers(MatchFinder *Finder) { auto ForwardCallMatcher = callExpr( callExpr().bind("call"), argumentCountIs(1), - hasArgument( - 0, declRefExpr(to( - varDecl(optionally(equalsBoundNode("param"))).bind("var")))), - forCallable(anyOf(equalsBoundNode("func"), CapturedInLambda)), + hasArgument(0, declRefExpr(to(varDecl().bind("var")))), + forCallable( + anyOf(allOf(equalsBoundNode("func"), + functionDecl(hasAnyParameter(parmVarDecl(allOf( + equalsBoundNode("param"), equalsBoundNode("var")))))), + CapturedInLambda)), callee(unresolvedLookupExpr(hasAnyDeclaration( namedDecl(hasUnderlyingDecl(hasName("::std::forward")))))), diff --git a/clang-tools-extra/clang-tidy/hicpp/IgnoredRemoveResultCheck.cpp b/clang-tools-extra/clang-tidy/hicpp/IgnoredRemoveResultCheck.cpp index 3410559d435f6385633d5394dad0ec19c5484212..8020f8cd062510b5ac677cf1d73de8d8c38800f1 100644 --- a/clang-tools-extra/clang-tidy/hicpp/IgnoredRemoveResultCheck.cpp +++ b/clang-tools-extra/clang-tidy/hicpp/IgnoredRemoveResultCheck.cpp @@ -13,9 +13,11 @@ namespace clang::tidy::hicpp { IgnoredRemoveResultCheck::IgnoredRemoveResultCheck(llvm::StringRef Name, ClangTidyContext *Context) : UnusedReturnValueCheck(Name, Context, - "::std::remove;" - "::std::remove_if;" - "::std::unique") { + { + "::std::remove", + "::std::remove_if", + "::std::unique", + }) { // The constructor for ClangTidyCheck needs to have been called // before we can access options via Options.get(). AllowCastToVoid = Options.get("AllowCastToVoid", true); diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index 335c3de25b861b74dcda9c8cf5f53fe52e2ab4cb..dc30531ebda0e98fe18e2f325111ba8d303598b4 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -888,8 +888,14 @@ bool IdentifierNamingCheck::matchesStyle( return false; if (IdentifierNamingCheck::HungarianPrefixType::HPT_Off != Style.HPType) { std::string HNPrefix = HungarianNotation.getPrefix(Decl, HNOption); - if (!Name.consume_front(HNPrefix)) - return false; + if (!HNPrefix.empty()) { + if (!Name.consume_front(HNPrefix)) + return false; + if (Style.HPType == + IdentifierNamingCheck::HungarianPrefixType::HPT_LowerCase && + !Name.consume_front("_")) + return false; + } } // Ensure the name doesn't have any extra underscores beyond those specified diff --git a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp index f0ffa517047b274eca2e3de61daf3911a3b9626c..a48e45e13568134d44a5a080757c5838407823a6 100644 --- a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp +++ b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp @@ -155,15 +155,16 @@ AST_MATCHER_P(DeclRefExpr, doesNotMutateObject, int, Indirections) { if (const auto *const Member = dyn_cast(P)) { if (const auto *const Method = dyn_cast(Member->getMemberDecl())) { - if (!Method->isConst()) { - // The method can mutate our variable. - return false; + if (Method->isConst() || Method->isStatic()) { + // The method call cannot mutate our variable. + continue; } - continue; + return false; } Stack.emplace_back(Member, 0); continue; } + if (const auto *const Op = dyn_cast(P)) { switch (Op->getOpcode()) { case UO_AddrOf: diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index 3f9fd0128194284eec042cfda390ddfcbc4c79b7..5790273d625ef14f7ae06ff608b88cd65926e808 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -523,7 +523,7 @@ void ClangdServer::formatFile(PathRef File, std::optional Rng, auto Action = [File = File.str(), Code = std::move(*Code), Ranges = std::vector{RequestedRange}, CB = std::move(CB), this]() mutable { - format::FormatStyle Style = getFormatStyleForFile(File, Code, TFS); + format::FormatStyle Style = getFormatStyleForFile(File, Code, TFS, true); tooling::Replacements IncludeReplaces = format::sortIncludes(Style, Code, Ranges, File); auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces); @@ -551,15 +551,10 @@ void ClangdServer::formatOnType(PathRef File, Position Pos, auto Action = [File = File.str(), Code = std::move(*Code), TriggerText = TriggerText.str(), CursorPos = *CursorPos, CB = std::move(CB), this]() mutable { - auto Style = format::getStyle(format::DefaultFormatStyle, File, - format::DefaultFallbackStyle, Code, - TFS.view(/*CWD=*/std::nullopt).get()); - if (!Style) - return CB(Style.takeError()); - + auto Style = getFormatStyleForFile(File, Code, TFS, false); std::vector Result; for (const tooling::Replacement &R : - formatIncremental(Code, CursorPos, TriggerText, *Style)) + formatIncremental(Code, CursorPos, TriggerText, Style)) Result.push_back(replacementToEdit(Code, R)); return CB(Result); }; @@ -610,7 +605,7 @@ void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName, if (Opts.WantFormat) { auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents, - *InpAST->Inputs.TFS); + *InpAST->Inputs.TFS, false); llvm::Error Err = llvm::Error::success(); for (auto &E : R->GlobalChanges) Err = @@ -767,7 +762,7 @@ void ClangdServer::applyTweak(PathRef File, Range Sel, StringRef TweakID, for (auto &It : (*Effect)->ApplyEdits) { Edit &E = It.second; format::FormatStyle Style = - getFormatStyleForFile(File, E.InitialCode, TFS); + getFormatStyleForFile(File, E.InitialCode, TFS, false); if (llvm::Error Err = reformatEdit(E, Style)) elog("Failed to format {0}: {1}", It.first(), std::move(Err)); } @@ -830,7 +825,7 @@ void ClangdServer::findHover(PathRef File, Position Pos, if (!InpAST) return CB(InpAST.takeError()); format::FormatStyle Style = getFormatStyleForFile( - File, InpAST->Inputs.Contents, *InpAST->Inputs.TFS); + File, InpAST->Inputs.Contents, *InpAST->Inputs.TFS, false); CB(clangd::getHover(InpAST->AST, Pos, std::move(Style), Index)); }; diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp index 0e5f08cec440cefc0a7169ba00d66c88726d0ab6..036eb9808ea082be28229e849382927522b47fbd 100644 --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -1628,7 +1628,7 @@ public: IsUsingDeclaration = Recorder->CCContext.isUsingDeclaration(); auto Style = getFormatStyleForFile(SemaCCInput.FileName, SemaCCInput.ParseInput.Contents, - *SemaCCInput.ParseInput.TFS); + *SemaCCInput.ParseInput.TFS, false); const auto NextToken = findTokenAfterCompletionPoint( Recorder->CCSema->getPreprocessor().getCodeCompletionLoc(), Recorder->CCSema->getSourceManager(), Recorder->CCSema->LangOpts); @@ -1719,7 +1719,7 @@ public: ProxSources[FileName].Cost = 0; FileProximity.emplace(ProxSources); - auto Style = getFormatStyleForFile(FileName, Content, TFS); + auto Style = getFormatStyleForFile(FileName, Content, TFS, false); // This will only insert verbatim headers. Inserter.emplace(FileName, Content, Style, /*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr); diff --git a/clang-tools-extra/clangd/FindSymbols.cpp b/clang-tools-extra/clangd/FindSymbols.cpp index 5b3e46a7b4dc167604a620540dae04f052487b78..5244a4e893769ed373e310ff1795ecf4419df7e1 100644 --- a/clang-tools-extra/clangd/FindSymbols.cpp +++ b/clang-tools-extra/clangd/FindSymbols.cpp @@ -223,8 +223,8 @@ std::string getSymbolDetail(ASTContext &Ctx, const NamedDecl &ND) { std::optional declToSym(ASTContext &Ctx, const NamedDecl &ND) { auto &SM = Ctx.getSourceManager(); - SourceLocation BeginLoc = SM.getFileLoc(ND.getBeginLoc()); - SourceLocation EndLoc = SM.getFileLoc(ND.getEndLoc()); + SourceLocation BeginLoc = ND.getBeginLoc(); + SourceLocation EndLoc = ND.getEndLoc(); const auto SymbolRange = toHalfOpenFileRange(SM, Ctx.getLangOpts(), {BeginLoc, EndLoc}); if (!SymbolRange) diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp b/clang-tools-extra/clangd/IncludeCleaner.cpp index f86a121340f7fbe3c76bba1a81bdcd0f3880484c..8e48f546d94e7799ca727a5e3de0895c90fd69cd 100644 --- a/clang-tools-extra/clangd/IncludeCleaner.cpp +++ b/clang-tools-extra/clangd/IncludeCleaner.cpp @@ -111,21 +111,15 @@ bool mayConsiderUnused(const Inclusion &Inc, ParsedAST &AST, std::vector generateMissingIncludeDiagnostics( ParsedAST &AST, llvm::ArrayRef MissingIncludes, - llvm::StringRef Code, HeaderFilter IgnoreHeaders) { + llvm::StringRef Code, HeaderFilter IgnoreHeaders, const ThreadsafeFS &TFS) { std::vector Result; const SourceManager &SM = AST.getSourceManager(); const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID()); - auto FileStyle = format::getStyle( - format::DefaultFormatStyle, AST.tuPath(), format::DefaultFallbackStyle, - Code, &SM.getFileManager().getVirtualFileSystem()); - if (!FileStyle) { - elog("Couldn't infer style", FileStyle.takeError()); - FileStyle = format::getLLVMStyle(); - } + auto FileStyle = getFormatStyleForFile(AST.tuPath(), Code, TFS, false); tooling::HeaderIncludes HeaderIncludes(AST.tuPath(), Code, - FileStyle->IncludeStyle); + FileStyle.IncludeStyle); for (const auto &SymbolWithMissingInclude : MissingIncludes) { llvm::StringRef ResolvedPath = SymbolWithMissingInclude.Providers.front().resolvedPath(); @@ -459,6 +453,7 @@ bool isPreferredProvider(const Inclusion &Inc, std::vector issueIncludeCleanerDiagnostics(ParsedAST &AST, llvm::StringRef Code, const IncludeCleanerFindings &Findings, + const ThreadsafeFS &TFS, HeaderFilter IgnoreHeaders) { trace::Span Tracer("IncludeCleaner::issueIncludeCleanerDiagnostics"); std::vector UnusedIncludes = generateUnusedIncludeDiagnostics( @@ -466,7 +461,7 @@ issueIncludeCleanerDiagnostics(ParsedAST &AST, llvm::StringRef Code, std::optional RemoveAllUnused = removeAllUnusedIncludes(UnusedIncludes); std::vector MissingIncludeDiags = generateMissingIncludeDiagnostics( - AST, Findings.MissingIncludes, Code, IgnoreHeaders); + AST, Findings.MissingIncludes, Code, IgnoreHeaders, TFS); std::optional AddAllMissing = addAllMissingIncludes(MissingIncludeDiags); std::optional FixAll; diff --git a/clang-tools-extra/clangd/IncludeCleaner.h b/clang-tools-extra/clangd/IncludeCleaner.h index b3ba3a716083e886160c377ecf66ec27c669aa6c..387763de340767be7e3cf8598db2b1a6c7076fd5 100644 --- a/clang-tools-extra/clangd/IncludeCleaner.h +++ b/clang-tools-extra/clangd/IncludeCleaner.h @@ -59,6 +59,7 @@ using HeaderFilter = llvm::ArrayRef>; std::vector issueIncludeCleanerDiagnostics(ParsedAST &AST, llvm::StringRef Code, const IncludeCleanerFindings &Findings, + const ThreadsafeFS &TFS, HeaderFilter IgnoreHeader = {}); /// Affects whether standard library includes should be considered for diff --git a/clang-tools-extra/clangd/JSONTransport.cpp b/clang-tools-extra/clangd/JSONTransport.cpp index 346c7dfb66a1dbb01709e31ed6386470f42749b4..3c0e198433f36004056bdd995081dc3d30ca6de4 100644 --- a/clang-tools-extra/clangd/JSONTransport.cpp +++ b/clang-tools-extra/clangd/JSONTransport.cpp @@ -107,8 +107,7 @@ public: return error(std::make_error_code(std::errc::operation_canceled), "Got signal, shutting down"); if (ferror(In)) - return llvm::errorCodeToError( - std::error_code(errno, std::system_category())); + return llvm::errorCodeToError(llvm::errnoAsErrorCode()); if (readRawMessage(JSON)) { ThreadCrashReporter ScopedReporter([&JSON]() { auto &OS = llvm::errs(); diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp index bbb0e2c77b3f318c9afeca83b111e93c6b7b5423..3ff759415f7c8b24fab5a3a538c13755dd14544f 100644 --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -360,7 +360,8 @@ void applyWarningOptions(llvm::ArrayRef ExtraArgs, } } -std::vector getIncludeCleanerDiags(ParsedAST &AST, llvm::StringRef Code) { +std::vector getIncludeCleanerDiags(ParsedAST &AST, llvm::StringRef Code, + const ThreadsafeFS &TFS) { auto &Cfg = Config::current(); if (Cfg.Diagnostics.SuppressAll) return {}; @@ -377,7 +378,7 @@ std::vector getIncludeCleanerDiags(ParsedAST &AST, llvm::StringRef Code) { Findings.MissingIncludes.clear(); if (SuppressUnused) Findings.UnusedIncludes.clear(); - return issueIncludeCleanerDiagnostics(AST, Code, Findings, + return issueIncludeCleanerDiagnostics(AST, Code, Findings, TFS, Cfg.Diagnostics.Includes.IgnoreHeader); } @@ -625,7 +626,7 @@ ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs, // (e.g. incomplete type) and attach include insertion fixes to diagnostics. if (Inputs.Index && !BuildDir.getError()) { auto Style = - getFormatStyleForFile(Filename, Inputs.Contents, *Inputs.TFS); + getFormatStyleForFile(Filename, Inputs.Contents, *Inputs.TFS, false); auto Inserter = std::make_shared( Filename, Inputs.Contents, Style, BuildDir.get(), &Clang->getPreprocessor().getHeaderSearchInfo()); @@ -741,7 +742,7 @@ ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs, std::move(Clang), std::move(Action), std::move(Tokens), std::move(Macros), std::move(Marks), std::move(ParsedDecls), std::move(Diags), std::move(Includes), std::move(PI)); - llvm::move(getIncludeCleanerDiags(Result, Inputs.Contents), + llvm::move(getIncludeCleanerDiags(Result, Inputs.Contents, *Inputs.TFS), std::back_inserter(Result.Diags)); return std::move(Result); } diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index 8aa18bb0058abe35b469e8321fc806325cad7f45..c6553e00dcae28209da96ff0eb6a7dd2288d008f 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -1412,7 +1412,7 @@ bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R, } llvm::json::Value toJSON(SymbolTag Tag) { - return llvm::json::Value{static_cast(Tag)}; + return llvm::json::Value(static_cast(Tag)); } llvm::json::Value toJSON(const CallHierarchyItem &I) { diff --git a/clang-tools-extra/clangd/SourceCode.cpp b/clang-tools-extra/clangd/SourceCode.cpp index 3e741f6e0b536ba44bafc8245fa01e4a219fa2d6..3af99b9db056da5780dad816be27dc7a0c1c4b25 100644 --- a/clang-tools-extra/clangd/SourceCode.cpp +++ b/clang-tools-extra/clangd/SourceCode.cpp @@ -582,7 +582,21 @@ std::optional digestFile(const SourceManager &SM, FileID FID) { format::FormatStyle getFormatStyleForFile(llvm::StringRef File, llvm::StringRef Content, - const ThreadsafeFS &TFS) { + const ThreadsafeFS &TFS, + bool FormatFile) { + // Unless we're formatting a substantial amount of code (the entire file + // or an arbitrarily large range), skip libFormat's heuristic check for + // .h files that tries to determine whether the file contains objective-c + // code. (This is accomplished by passing empty code contents to getStyle(). + // The heuristic is the only thing that looks at the contents.) + // This is a workaround for PR60151, a known issue in libFormat where this + // heuristic can OOM on large files. If we *are* formatting the entire file, + // there's no point in doing this because the actual format::reformat() call + // will run into the same OOM; we'd just be risking inconsistencies between + // clangd and clang-format on smaller .h files where they disagree on what + // language is detected. + if (!FormatFile) + Content = {}; auto Style = format::getStyle(format::DefaultFormatStyle, File, format::DefaultFallbackStyle, Content, TFS.view(/*CWD=*/std::nullopt).get()); diff --git a/clang-tools-extra/clangd/SourceCode.h b/clang-tools-extra/clangd/SourceCode.h index a1bb44c176120210aca1fa5f73ee2d5fc47d21e9..028549f659d60aad310db71ac12a1ec95467f654 100644 --- a/clang-tools-extra/clangd/SourceCode.h +++ b/clang-tools-extra/clangd/SourceCode.h @@ -171,9 +171,13 @@ std::optional getCanonicalPath(const FileEntryRef F, /// FIXME: should we be caching the .clang-format file search? /// This uses format::DefaultFormatStyle and format::DefaultFallbackStyle, /// though the latter may have been overridden in main()! +/// \p FormatFile indicates whether the returned FormatStyle is used +/// to format the entire main file (or a range selected by the user +/// which can be arbitrarily long). format::FormatStyle getFormatStyleForFile(llvm::StringRef File, llvm::StringRef Content, - const ThreadsafeFS &TFS); + const ThreadsafeFS &TFS, + bool FormatFile); /// Cleanup and format the given replacements. llvm::Expected diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp index 4e135801f6853d637e6883f609e5842196be01a9..75b30e66d63761fd4bcbc007c97a1f299d947409 100644 --- a/clang-tools-extra/clangd/refactor/Rename.cpp +++ b/clang-tools-extra/clangd/refactor/Rename.cpp @@ -1062,6 +1062,10 @@ llvm::Expected rename(const RenameInputs &RInputs) { return makeError(ReasonToReject::AmbiguousSymbol); const auto &RenameDecl = **DeclsUnderCursor.begin(); + static constexpr trace::Metric RenameTriggerCounter( + "rename_trigger_count", trace::Metric::Counter, "decl_kind"); + RenameTriggerCounter.record(1, RenameDecl.getDeclKindName()); + std::string Placeholder = getName(RenameDecl); auto Invalid = checkName(RenameDecl, RInputs.NewName, Placeholder); if (Invalid) diff --git a/clang-tools-extra/clangd/tool/Check.cpp b/clang-tools-extra/clangd/tool/Check.cpp index b5c4d145619df33a5da26c5704f79776d6d4c3d6..45e2e1e278deafa4843d8f7945472b961f7519a4 100644 --- a/clang-tools-extra/clangd/tool/Check.cpp +++ b/clang-tools-extra/clangd/tool/Check.cpp @@ -226,7 +226,7 @@ public: // FIXME: Check that resource-dir/built-in-headers exist? - Style = getFormatStyleForFile(File, Inputs.Contents, TFS); + Style = getFormatStyleForFile(File, Inputs.Contents, TFS, false); return true; } diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 6d387fec9b3851d10bda8b4164223b453242315e..5721feecd58ea89219e193aa18c9be15321cb8e4 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1462,6 +1462,23 @@ TEST(SignatureHelpTest, FunctionPointers) { typedef void (__stdcall *fn)(int x, int y); fn foo; int main() { foo(^); } + )cpp", + // Field of function pointer type + R"cpp( + struct S { + void (*foo)(int x, int y); + }; + S s; + int main() { s.foo(^); } + )cpp", + // Field of function pointer typedef type + R"cpp( + typedef void (*fn)(int x, int y); + struct S { + fn foo; + }; + S s; + int main() { s.foo(^); } )cpp"}; for (auto Test : Tests) EXPECT_THAT(signatures(Test).signatures, diff --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp index 2f6dd0611b6621bf5dca556b3b44ebe360a1a1e4..25d2f03e0b366b0d627bdbdd09d4e5beef4ed270 100644 --- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp +++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp @@ -544,7 +544,7 @@ TEST(DiagnosticTest, RespectsDiagnosticConfig) { Diag(Main.range("ret"), "void function 'x' should not return a value"))); Config Cfg; - Cfg.Diagnostics.Suppress.insert("return-type"); + Cfg.Diagnostics.Suppress.insert("return-mismatch"); WithContextValue WithCfg(Config::Key, std::move(Cfg)); EXPECT_THAT(TU.build().getDiagnostics(), ElementsAre(Diag(Main.range(), diff --git a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp index b1b8b4ccd184c2bc42ac8ac4b182420dffc6c69e..4276a44275f53522dc36c819cf248f68e8c6d1b2 100644 --- a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp @@ -750,6 +750,9 @@ TEST(DocumentSymbols, RangeFromMacro) { $fullDef[[FF3() { int var = 42; }]] + + #define FF4(name) int name = 0 + $FooRange[[FF4($FooSelectionRange[[foo]])]]; )"); TU.Code = Main.code().str(); EXPECT_THAT( @@ -766,7 +769,11 @@ TEST(DocumentSymbols, RangeFromMacro) { AllOf(withName("FF3"), withDetail("()"), symRange(Main.range("fullDef")), children(AllOf(withName("waldo"), withDetail("void ()"), - symRange(Main.range("fullDef"))))))); + symRange(Main.range("fullDef"))))), + AllOf( + withName("FF4"), withDetail("(foo)"), + children(AllOf(withName("foo"), symRange(Main.range("FooRange")), + symNameRange(Main.range("FooSelectionRange"))))))); } TEST(DocumentSymbols, FuncTemplates) { diff --git a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp index 7ed4a9103e1f248df5cffac789c7e493cc680106..142310837bd9ce276d92b6ab1f1e9bb4b20e35f2 100644 --- a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp +++ b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp @@ -252,7 +252,7 @@ $insert_f[[]]$insert_vector[[]] auto Findings = computeIncludeCleanerFindings(AST); Findings.UnusedIncludes.clear(); std::vector Diags = issueIncludeCleanerDiagnostics( - AST, TU.Code, Findings, + AST, TU.Code, Findings, MockFS(), {[](llvm::StringRef Header) { return Header.ends_with("buzz.h"); }}); EXPECT_THAT( Diags, @@ -505,8 +505,8 @@ TEST(IncludeCleaner, BatchFix) { )cpp"; auto AST = TU.build(); EXPECT_THAT( - issueIncludeCleanerDiagnostics(AST, TU.Code, - computeIncludeCleanerFindings(AST)), + issueIncludeCleanerDiagnostics( + AST, TU.Code, computeIncludeCleanerFindings(AST), MockFS()), UnorderedElementsAre(withFix({FixMessage("#include \"foo.h\""), FixMessage("fix all includes")}), withFix({FixMessage("remove #include directive"), @@ -520,8 +520,8 @@ TEST(IncludeCleaner, BatchFix) { )cpp"; AST = TU.build(); EXPECT_THAT( - issueIncludeCleanerDiagnostics(AST, TU.Code, - computeIncludeCleanerFindings(AST)), + issueIncludeCleanerDiagnostics( + AST, TU.Code, computeIncludeCleanerFindings(AST), MockFS()), UnorderedElementsAre(withFix({FixMessage("#include \"foo.h\""), FixMessage("fix all includes")}), withFix({FixMessage("remove #include directive"), @@ -539,8 +539,8 @@ TEST(IncludeCleaner, BatchFix) { )cpp"; AST = TU.build(); EXPECT_THAT( - issueIncludeCleanerDiagnostics(AST, TU.Code, - computeIncludeCleanerFindings(AST)), + issueIncludeCleanerDiagnostics( + AST, TU.Code, computeIncludeCleanerFindings(AST), MockFS()), UnorderedElementsAre(withFix({FixMessage("#include \"foo.h\""), FixMessage("add all missing includes"), FixMessage("fix all includes")}), diff --git a/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp b/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp index 1be5b7f6a8dbbadab21c00c58bb57f9ef7571fb2..801d535c1b9d0dc438415cba163821b413677912 100644 --- a/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp +++ b/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp @@ -1090,6 +1090,44 @@ TEST(ApplyEditsTest, EndLineOutOfRange) { FailedWithMessage("Line value is out of range (100)")); } +TEST(FormatStyleForFile, LanguageGuessingHeuristic) { + StringRef ObjCContent = "@interface Foo\n@end\n"; + StringRef CppContent = "class Foo {};\n"; + using LK = format::FormatStyle::LanguageKind; + struct TestCase { + llvm::StringRef Filename; + llvm::StringRef Contents; + bool FormatFile; + LK ExpectedLanguage; + } TestCases[] = { + // If the file extension identifies the file as ObjC, the guessed + // language should be ObjC regardless of content or FormatFile flag. + {"foo.mm", ObjCContent, true, LK::LK_ObjC}, + {"foo.mm", ObjCContent, false, LK::LK_ObjC}, + {"foo.mm", CppContent, true, LK::LK_ObjC}, + {"foo.mm", CppContent, false, LK::LK_ObjC}, + + // If the file extension is ambiguous like .h, FormatFile=true should + // result in using libFormat's heuristic to guess the language based + // on the file contents. + {"foo.h", ObjCContent, true, LK::LK_ObjC}, + {"foo.h", CppContent, true, LK::LK_Cpp}, + + // With FomatFile=false, the language guessing heuristic should be + // bypassed + {"foo.h", ObjCContent, false, LK::LK_Cpp}, + {"foo.h", CppContent, false, LK::LK_Cpp}, + }; + + MockFS FS; + for (const auto &[Filename, Contents, FormatFile, ExpectedLanguage] : + TestCases) { + EXPECT_EQ( + getFormatStyleForFile(Filename, Contents, FS, FormatFile).Language, + ExpectedLanguage); + } +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 0d2467210fc6640134cdf6f59203217b8342f447..44680f79de6f543e84cc05fb39c2c97a5e1a5dfa 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -104,6 +104,12 @@ Improvements to clang-tidy New checks ^^^^^^^^^^ +- New :doc:`bugprone-crtp-constructor-accessibility + ` check. + + Detects error-prone Curiously Recurring Template Pattern usage, when the CRTP + can be constructed outside itself and the derived class. + - New :doc:`modernize-use-designated-initializers ` check. @@ -122,6 +128,10 @@ New check aliases Changes in existing checks ^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Improved :doc:`bugprone-assert-side-effect + ` check by detecting side + effect from calling a method with non-const reference parameters. + - Improved :doc:`bugprone-non-zero-enum-to-bool-conversion ` check by eliminating false positives resulting from direct usage of bitwise operators @@ -140,9 +150,20 @@ Changes in existing checks ` check by ignoring local variable with ``[maybe_unused]`` attribute. +- Improved :doc:`bugprone-unused-return-value + ` check by updating the + parameter `CheckedFunctions` to support regexp, avoiding false positive for + function with the same prefix as the default argument, e.g. ``std::unique_ptr`` + and ``std::unique``, avoiding false positive for assignment operator overloading. + +- Improved :doc:`bugprone-use-after-move + ` check to also handle + calls to ``std::forward``. + - Improved :doc:`cppcoreguidelines-missing-std-forward ` check by no longer - giving false positives for deleted functions. + giving false positives for deleted functions and fix false negative when some + parameters are forwarded, but other aren't. - Cleaned up :doc:`cppcoreguidelines-prefer-member-initializer ` @@ -214,7 +235,8 @@ Changes in existing checks - Improved :doc:`readability-identifier-naming ` check in `GetConfigPerFile` - mode by resolving symbolic links to header files. + mode by resolving symbolic links to header files. Fixed handling of Hungarian + Prefix when configured to `LowerCase`. Removed checks ^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/crtp-constructor-accessibility.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/crtp-constructor-accessibility.rst new file mode 100644 index 0000000000000000000000000000000000000000..afd88764b5967302d3516453e3f4639b6c5268c4 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/crtp-constructor-accessibility.rst @@ -0,0 +1,98 @@ +.. title:: clang-tidy - bugprone-crtp-constructor-accessibility + +bugprone-crtp-constructor-accessibility +======================================= + +Detects error-prone Curiously Recurring Template Pattern usage, when the CRTP +can be constructed outside itself and the derived class. + +The CRTP is an idiom, in which a class derives from a template class, where +itself is the template argument. It should be ensured that if a class is +intended to be a base class in this idiom, it can only be instantiated if +the derived class is it's template argument. + +Example: + +.. code-block:: c++ + + template class CRTP { + private: + CRTP() = default; + friend T; + }; + + class Derived : CRTP {}; + +Below can be seen some common mistakes that will allow the breaking of the +idiom. + +If the constructor of a class intended to be used in a CRTP is public, then +it allows users to construct that class on its own. + +Example: + +.. code-block:: c++ + + template class CRTP { + public: + CRTP() = default; + }; + + class Good : CRTP {}; + Good GoodInstance; + + CRTP BadInstance; + +If the constructor is protected, the possibility of an accidental instantiation +is prevented, however it can fade an error, when a different class is used as +the template parameter instead of the derived one. + +Example: + +.. code-block:: c++ + + template class CRTP { + protected: + CRTP() = default; + }; + + class Good : CRTP {}; + Good GoodInstance; + + class Bad : CRTP {}; + Bad BadInstance; + +To ensure that no accidental instantiation happens, the best practice is to +make the constructor private and declare the derived class as friend. Note +that as a tradeoff, this also gives the derived class access to every other +private members of the CRTP. + +Example: + +.. code-block:: c++ + + template class CRTP { + CRTP() = default; + friend T; + }; + + class Good : CRTP {}; + Good GoodInstance; + + class Bad : CRTP {}; + Bad CompileTimeError; + + CRTP AlsoCompileTimeError; + +Limitations: + +* The check is not supported below C++11 + +* The check does not handle when the derived class is passed as a variadic + template argument + +* Accessible functions that can construct the CRTP, like factory functions + are not checked + +The check also suggests a fix-its in some cases. + diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-return-value.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-return-value.rst index 1e3c8a3268222edf3d33b0dc99412b2aa844c4cf..9205ba98729c4b9a0b441a90d50c34f6138a06e6 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-return-value.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-return-value.rst @@ -5,30 +5,34 @@ bugprone-unused-return-value Warns on unused function return values. The checked functions can be configured. +Operator overloading with assignment semantics are ignored. + Options ------- .. option:: CheckedFunctions - Semicolon-separated list of functions to check. The function is checked if - the name and scope matches, with any arguments. + Semicolon-separated list of functions to check. + This parameter supports regexp. The function is checked if the name + and scope matches, with any arguments. By default the following functions are checked: - ``std::async, std::launder, std::remove, std::remove_if, std::unique, - std::unique_ptr::release, std::basic_string::empty, std::vector::empty, - std::back_inserter, std::distance, std::find, std::find_if, std::inserter, - std::lower_bound, std::make_pair, std::map::count, std::map::find, - std::map::lower_bound, std::multimap::equal_range, - std::multimap::upper_bound, std::set::count, std::set::find, std::setfill, - std::setprecision, std::setw, std::upper_bound, std::vector::at, - bsearch, ferror, feof, isalnum, isalpha, isblank, iscntrl, isdigit, isgraph, - islower, isprint, ispunct, isspace, isupper, iswalnum, iswprint, iswspace, - isxdigit, memchr, memcmp, strcmp, strcoll, strncmp, strpbrk, strrchr, - strspn, strstr, wcscmp, access, bind, connect, difftime, dlsym, fnmatch, - getaddrinfo, getopt, htonl, htons, iconv_open, inet_addr, isascii, isatty, - mmap, newlocale, openat, pathconf, pthread_equal, pthread_getspecific, - pthread_mutex_trylock, readdir, readlink, recvmsg, regexec, scandir, - semget, setjmp, shm_open, shmget, sigismember, strcasecmp, strsignal, - ttyname`` + ``::std::async$, ::std::launder$, ::std::remove$, ::std::remove_if$, ::std::unique$, + ::std::unique_ptr::release$, ::std::basic_string::empty$, ::std::vector::empty$, + ::std::back_inserter$, ::std::distance$, ::std::find$, ::std::find_if$, ::std::inserter$, + ::std::lower_bound$, ::std::make_pair$, ::std::map::count$, ::std::map::find$, + ::std::map::lower_bound$, ::std::multimap::equal_range$, ::std::multimap::upper_bound$, + ::std::set::count$, ::std::set::find$, ::std::setfill$, ::std::setprecision$, + ::std::setw$, ::std::upper_bound$, ::std::vector::at$, ::bsearch$, ::ferror$, + ::feof$, ::isalnum$, ::isalpha$, ::isblank$, ::iscntrl$, ::isdigit$, ::isgraph$, + ::islower$, ::isprint$, ::ispunct$, ::isspace$, ::isupper$, ::iswalnum$, ::iswprint$, + ::iswspace$, ::isxdigit$, ::memchr$, ::memcmp$, ::strcmp$, ::strcoll$, ::strncmp$, + ::strpbrk$, ::strrchr$, ::strspn$, ::strstr$, ::wcscmp$, ::access$, ::bind$, + ::connect$, ::difftime$, ::dlsym$, ::fnmatch$, ::getaddrinfo$, ::getopt$, + ::htonl$, ::htons$, ::iconv_open$, ::inet_addr$, isascii$, isatty$, ::mmap$, + ::newlocale$, ::openat$, ::pathconf$, ::pthread_equal$, ::pthread_getspecific$, + ::pthread_mutex_trylock$, ::readdir$, ::readlink$, ::recvmsg$, ::regexec$, ::scandir$, + ::semget$, ::setjmp$, ::shm_open$, ::shmget$, ::sigismember$, ::strcasecmp$, ::strsignal$, + ::ttyname$`` - ``std::async()``. Not using the return value makes the call synchronous. - ``std::launder()``. Not using the return value usually means that the diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst index 8509292eff9947723ba6227bcc0d430278805dd6..08bb5374bab1f4e74d4608009728229c9a06174f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst @@ -177,6 +177,18 @@ When analyzing the order in which moves, uses and reinitializations happen (see section `Unsequenced moves, uses, and reinitializations`_), the move is assumed to occur in whichever function the result of the ``std::move`` is passed to. +The check also handles perfect-forwarding with ``std::forward`` so the +following code will also trigger a use-after-move warning. + +.. code-block:: c++ + + void consume(int); + + void f(int&& i) { + consume(std::forward(i)); + consume(std::forward(i)); // use-after-move + } + Use --- diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 5e57bc0ee483fecda223cc94e9e745649f41ca4f..d03e7af688f007aead351335a5af647e9c2b386b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -86,6 +86,7 @@ Clang-Tidy Checks :doc:`bugprone-chained-comparison `, :doc:`bugprone-compare-pointer-to-member-virtual-function `, :doc:`bugprone-copy-constructor-init `, "Yes" + :doc:`bugprone-crtp-constructor-accessibility `, "Yes" :doc:`bugprone-dangling-handle `, :doc:`bugprone-dynamic-static-initializers `, :doc:`bugprone-easily-swappable-parameters `, diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst index 2affb55cfa9ad7393491cf4b7ba21bdf51b185c2..8a54687a25704c99edbde935e01d8a37f5ae1d8d 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst @@ -11,14 +11,14 @@ another if a mismatch is detected Casing types include: - - ``lower_case``, - - ``UPPER_CASE``, - - ``camelBack``, - - ``CamelCase``, - - ``camel_Snake_Back``, - - ``Camel_Snake_Case``, - - ``aNy_CasE``, - - ``Leading_upper_snake_case``. + - ``lower_case`` + - ``UPPER_CASE`` + - ``camelBack`` + - ``CamelCase`` + - ``camel_Snake_Back`` + - ``Camel_Snake_Case`` + - ``aNy_CasE`` + - ``Leading_upper_snake_case`` It also supports a fixed prefix and suffix that will be prepended or appended to the identifiers, regardless of the casing. @@ -32,8 +32,16 @@ but not where they are overridden, as it can't be fixed locally there. This also applies for pseudo-override patterns like CRTP. ``Leading_upper_snake_case`` is a naming convention where the first word is capitalized -followed by lower case word(s) seperated by underscore(s) '_'. Examples include: -Cap_snake_case, Cobra_case, Foo_bar_baz, and Master_copy_8gb. +followed by lower case word(s) separated by underscore(s) '_'. Examples include: +`Cap_snake_case`, `Cobra_case`, `Foo_bar_baz`, and `Master_copy_8gb`. + +Hungarian notation can be customized using different *HungarianPrefix* settings. +The options and their corresponding values are: + + - ``Off`` - the default setting + - ``On`` - example: ``int iVariable`` + - ``LowerCase`` - example: ``int i_Variable`` + - ``CamelCase`` - example: ``int IVariable`` Options ------- diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/assert-side-effect.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/assert-side-effect.cpp index c11638aa823aaebe5e39b225c68cbe89a446c20b..5cdc1afb3d90991559f33d33860dbc55822fc039 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/assert-side-effect.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/assert-side-effect.cpp @@ -108,3 +108,27 @@ int main() { return 0; } + +namespace parameter_anaylysis { + +struct S { + bool value(int) const; + bool leftValueRef(int &) const; + bool constRef(int const &) const; + bool rightValueRef(int &&) const; +}; + +void foo() { + S s{}; + int i = 0; + assert(s.value(0)); + assert(s.value(i)); + assert(s.leftValueRef(i)); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: side effect in assert() condition discarded in release builds + assert(s.constRef(0)); + assert(s.constRef(i)); + assert(s.rightValueRef(0)); + assert(s.rightValueRef(static_cast(i))); +} + +} // namespace parameter_anaylysis diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/crtp-constructor-accessibility.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/crtp-constructor-accessibility.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb41923df157cf83a0c6d2539fab5cb57c787988 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/crtp-constructor-accessibility.cpp @@ -0,0 +1,255 @@ +// RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-crtp-constructor-accessibility %t -- -- -fno-delayed-template-parsing + +namespace class_implicit_ctor { +template +class CRTP {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] +// CHECK-FIXES: CRTP() = default; +// CHECK-FIXES: friend T; + +class A : CRTP {}; +} // namespace class_implicit_ctor + +namespace class_unconstructible { +template +class CRTP { +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] +// CHECK-FIXES: friend T; + CRTP() = default; +}; + +class A : CRTP {}; +} // namespace class_unconstructible + +namespace class_public_default_ctor { +template +class CRTP { +public: + CRTP() = default; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] + // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: + // CHECK-FIXES: friend T; +}; + +class A : CRTP {}; +} // namespace class_public_default_ctor + +namespace class_public_user_provided_ctor { +template +class CRTP { +public: + CRTP(int) {} + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] + // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}public: + // CHECK-FIXES: friend T; +}; + +class A : CRTP {}; +} // namespace class_public_user_provided_ctor + +namespace class_public_multiple_user_provided_ctors { +template +class CRTP { +public: + CRTP(int) {} + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] + // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}public: + CRTP(float) {} + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] + // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(float) {}{{[[:space:]]*}}public: + + // CHECK-FIXES: friend T; + // CHECK-FIXES: friend T; +}; + +class A : CRTP {}; +} // namespace class_public_multiple_user_provided_ctors + +namespace class_protected_ctors { +template +class CRTP { +protected: + CRTP(int) {} + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected contructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] + // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}protected: + CRTP() = default; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected contructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] + // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}protected: + CRTP(float) {} + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected contructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] + // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(float) {}{{[[:space:]]*}}protected: + + // CHECK-FIXES: friend T; + // CHECK-FIXES: friend T; + // CHECK-FIXES: friend T; +}; + +class A : CRTP {}; +} // namespace class_protected_ctors + +namespace struct_implicit_ctor { +template +struct CRTP {}; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] +// CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: +// CHECK-FIXES: friend T; + +class A : CRTP {}; +} // namespace struct_implicit_ctor + +namespace struct_default_ctor { +template +struct CRTP { + CRTP() = default; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public contructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] + // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: + // CHECK-FIXES: friend T; +}; + +class A : CRTP {}; +} // namespace struct_default_ctor + +namespace same_class_multiple_crtps { +template +struct CRTP {}; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] +// CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: +// CHECK-FIXES: friend T; + +template +struct CRTP2 {}; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] +// CHECK-FIXES: private:{{[[:space:]]*}}CRTP2() = default;{{[[:space:]]*}}public: +// CHECK-FIXES: friend T; + +class A : CRTP, CRTP2 {}; +} // namespace same_class_multiple_crtps + +namespace same_crtp_multiple_classes { +template +class CRTP { +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] +// CHECK-FIXES: friend T; + CRTP() = default; +}; + +class A : CRTP {}; +class B : CRTP {}; +} // namespace same_crtp_multiple_classes + +namespace crtp_template { +template +class CRTP { +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] +// CHECK-FIXES: friend U; + CRTP() = default; +}; + +class A : CRTP {}; +} // namespace crtp_template + +namespace crtp_template2 { +template +class CRTP { +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] +// CHECK-FIXES: friend T; + CRTP() = default; +}; + +class A : CRTP {}; +} // namespace crtp_template2 + +namespace template_derived { +template +class CRTP {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] +// CHECK-FIXES: CRTP() = default; +// CHECK-FIXES: friend T; + +template +class A : CRTP> {}; + +// FIXME: Ideally the warning should be triggered without instantiation. +void foo() { + A A; + (void) A; +} +} // namespace template_derived + +namespace template_derived_explicit_specialization { +template +class CRTP {}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] +// CHECK-FIXES: CRTP() = default; +// CHECK-FIXES: friend T; + +template +class A : CRTP> {}; + +template<> +class A : CRTP> {}; +} // namespace template_derived_explicit_specialization + +namespace explicit_derived_friend { +class A; + +template +class CRTP { + CRTP() = default; + friend A; +}; + +class A : CRTP {}; +} // namespace explicit_derived_friend + +namespace explicit_derived_friend_multiple { +class A; + +template +class CRTP { +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] +// CHECK-FIXES: friend T; + CRTP() = default; + friend A; +}; + +class A : CRTP {}; +class B : CRTP {}; +} // namespace explicit_derived_friend_multiple + +namespace no_need_for_friend { +class A; + +template +class CRTP { +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private [bugprone-crtp-constructor-accessibility] +// CHECK-FIXES: CRTP() = default; + friend A; +}; + +class A : CRTP {}; +} // namespace no_need_for_friend + +namespace no_warning { +template +class CRTP +{ + CRTP() = default; + friend T; +}; + +class A : CRTP {}; +} // namespace no_warning + +namespace no_warning_unsupported { +template +class CRTP +{}; + +class A : CRTP {}; + +void foo() { + A A; + (void) A; +} +} // namespace no_warning_unsupported diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b4a41004adf8949ef6145d7f5cbb86b447122dfb --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-avoid-assignment.cpp @@ -0,0 +1,30 @@ +// RUN: %check_clang_tidy %s bugprone-unused-return-value %t \ +// RUN: -config='{CheckOptions: \ +// RUN: {bugprone-unused-return-value.CheckedFunctions: "::*"}}' \ +// RUN: -- + +struct S { + S(){}; + S(S const &); + S(S &&); + S &operator=(S const &); + S &operator=(S &&); + S &operator+=(S); +}; + +S returnValue(); +S const &returnRef(); + +void bar() { + returnValue(); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: the value returned by this function should not be disregarded; neglecting it may lead to errors + + S a{}; + a = returnValue(); + a.operator=(returnValue()); + + a = returnRef(); + a.operator=(returnRef()); + + a += returnRef(); +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-custom.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-custom.cpp index d3650b210ab02b5afddab2a7a9c2c7da1fcae42f..3035183573ccd7f2f819806bef9f792e54235c60 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-custom.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-custom.cpp @@ -1,7 +1,7 @@ // RUN: %check_clang_tidy %s bugprone-unused-return-value %t \ // RUN: -config='{CheckOptions: \ // RUN: {bugprone-unused-return-value.CheckedFunctions: \ -// RUN: "::fun;::ns::Outer::Inner::memFun;::ns::Type::staticFun;::ns::ClassTemplate::memFun;::ns::ClassTemplate::staticFun"}}' \ +// RUN: "::fun;::ns::Outer::Inner::memFun;::ns::Type::staticFun;::ns::ClassTemplate::(mem|static)Fun"}}' \ // RUN: -- namespace std { diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value.cpp index 5c6ce1e4bf1fd217a9aaea8f9d77eb2c9e85d354..e784c9b85172cf911965c620d0f9a29304fbf1de 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value.cpp @@ -30,6 +30,11 @@ struct default_delete; template > struct unique_ptr { + unique_ptr(); + unique_ptr(unique_ptr const&); + unique_ptr(unique_ptr &&); + unique_ptr& operator=(unique_ptr const&); + unique_ptr& operator=(unique_ptr &&); T *release() noexcept; }; @@ -254,3 +259,12 @@ void noWarning() { ({ std::async(increment, 42); }); auto StmtExprRetval = ({ std::async(increment, 42); }); } + +namespace gh84314 { + +extern std::unique_ptr alloc(); +void f1(std::unique_ptr &foo) { + foo = alloc(); +} + +} // namespace gh84314 \ No newline at end of file diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp index 00b1da1e727e4f11ec5a5ccebb98e66da9632339..7d9f63479a1b4e29ff5ee179ad29e5879d9c99be 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp @@ -111,6 +111,18 @@ constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) noexcept { return static_cast::type &&>(__t); } +template +constexpr _Tp&& +forward(typename std::remove_reference<_Tp>::type& __t) noexcept { + return static_cast<_Tp&&>(__t); +} + +template +constexpr _Tp&& +forward(typename std::remove_reference<_Tp>::type&& __t) noexcept { + return static_cast<_Tp&&>(__t); +} + } // namespace std class A { @@ -1525,3 +1537,28 @@ public: private: std::string val_; }; + +namespace issue82023 +{ + +struct S { + S(); + S(S&&); +}; + +void consume(S s); + +template +void forward(T&& t) { + consume(std::forward(t)); + consume(std::forward(t)); + // CHECK-NOTES: [[@LINE-1]]:27: warning: 't' used after it was forwarded + // CHECK-NOTES: [[@LINE-3]]:11: note: forward occurred here +} + +void create() { + S s; + forward(std::move(s)); +} + +} // namespace issue82023 diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp index 20e43f04180ff3a64ca746830dc5479f53cade85..9a50eabf619bd57a8f18091b48796e2ef7a479f1 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp @@ -95,6 +95,16 @@ void lambda_value_capture_copy(T&& t) { [&,t]() { T other = std::forward(t); }; } +template +void use(const X &x) {} + +template +void foo(X &&x, Y &&y) { + // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: forwarding reference parameter 'y' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward] + use(std::forward(x)); + use(y); +} + } // namespace positive_cases namespace negative_cases { diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/identifier-naming/hungarian-notation3/.clang-tidy b/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/identifier-naming/hungarian-notation3/.clang-tidy new file mode 100644 index 0000000000000000000000000000000000000000..45b4cd46c249c05ab9ab45cd72a3d83cb7c26d92 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/identifier-naming/hungarian-notation3/.clang-tidy @@ -0,0 +1,60 @@ +Checks: readability-identifier-naming +CheckOptions: + readability-identifier-naming.AbstractClassCase: CamelCase + readability-identifier-naming.StructCase: CamelCase + readability-identifier-naming.UnionCase: camelBack + readability-identifier-naming.ClassCase: CamelCase + readability-identifier-naming.ClassConstantCase: CamelCase + readability-identifier-naming.ClassMemberCase: CamelCase + readability-identifier-naming.ConstantCase: CamelCase + readability-identifier-naming.ConstantMemberCase: CamelCase + readability-identifier-naming.ConstantParameterCase: CamelCase + readability-identifier-naming.ConstantPointerParameterCase: CamelCase + readability-identifier-naming.ConstexprVariableCase: CamelCase + readability-identifier-naming.EnumConstantCase: CamelCase + readability-identifier-naming.GlobalConstantCase: CamelCase + readability-identifier-naming.GlobalConstantPointerCase: CamelCase + readability-identifier-naming.GlobalPointerCase: CamelCase + readability-identifier-naming.GlobalVariableCase: CamelCase + readability-identifier-naming.LocalConstantCase: CamelCase + readability-identifier-naming.LocalConstantPointerCase: CamelCase + readability-identifier-naming.LocalPointerCase: CamelCase + readability-identifier-naming.LocalVariableCase: CamelCase + readability-identifier-naming.MemberCase: CamelCase + readability-identifier-naming.ParameterCase: CamelCase + readability-identifier-naming.PointerParameterCase: CamelCase + readability-identifier-naming.PrivateMemberCase: CamelCase + readability-identifier-naming.ProtectedMemberCase: CamelCase + readability-identifier-naming.PublicMemberCase: CamelCase + readability-identifier-naming.ScopedEnumConstantCase: CamelCase + readability-identifier-naming.StaticConstantCase: CamelCase + readability-identifier-naming.StaticVariableCase: CamelCase + readability-identifier-naming.VariableCase: CamelCase + readability-identifier-naming.AbstractClassHungarianPrefix: LowerCase + readability-identifier-naming.ClassHungarianPrefix: LowerCase + readability-identifier-naming.ClassConstantHungarianPrefix: LowerCase + readability-identifier-naming.ClassMemberHungarianPrefix: LowerCase + readability-identifier-naming.ConstantHungarianPrefix: LowerCase + readability-identifier-naming.ConstantMemberHungarianPrefix: LowerCase + readability-identifier-naming.ConstantParameterHungarianPrefix: LowerCase + readability-identifier-naming.ConstantPointerParameterHungarianPrefix: LowerCase + readability-identifier-naming.ConstexprVariableHungarianPrefix: LowerCase + readability-identifier-naming.EnumConstantHungarianPrefix: LowerCase + readability-identifier-naming.GlobalConstantHungarianPrefix: LowerCase + readability-identifier-naming.GlobalConstantPointerHungarianPrefix: LowerCase + readability-identifier-naming.GlobalPointerHungarianPrefix: LowerCase + readability-identifier-naming.GlobalVariableHungarianPrefix: LowerCase + readability-identifier-naming.LocalConstantHungarianPrefix: LowerCase + readability-identifier-naming.LocalConstantPointerHungarianPrefix: LowerCase + readability-identifier-naming.LocalPointerHungarianPrefix: LowerCase + readability-identifier-naming.LocalVariableHungarianPrefix: LowerCase + readability-identifier-naming.MemberHungarianPrefix: LowerCase + readability-identifier-naming.ParameterHungarianPrefix: LowerCase + readability-identifier-naming.PointerParameterHungarianPrefix: LowerCase + readability-identifier-naming.PrivateMemberHungarianPrefix: LowerCase + readability-identifier-naming.ProtectedMemberHungarianPrefix: LowerCase + readability-identifier-naming.PublicMemberHungarianPrefix: LowerCase + readability-identifier-naming.ScopedEnumConstantHungarianPrefix: LowerCase + readability-identifier-naming.StaticConstantHungarianPrefix: LowerCase + readability-identifier-naming.StaticVariableHungarianPrefix: LowerCase + readability-identifier-naming.VariableHungarianPrefix: LowerCase diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-hungarian-notation-lower-case-prefix.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-hungarian-notation-lower-case-prefix.cpp new file mode 100644 index 0000000000000000000000000000000000000000..65aee7e9f6ced24ed194bd1e5b94f93e148e04a8 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-hungarian-notation-lower-case-prefix.cpp @@ -0,0 +1,678 @@ +// RUN: %check_clang_tidy %s readability-identifier-naming %t -- \ +// RUN: --config-file=%S/Inputs/identifier-naming/hungarian-notation3/.clang-tidy -- -I %S + +#include "identifier-naming-standard-types.h" + +// clang-format off +//===----------------------------------------------------------------------===// +// Cases to CheckOptions +//===----------------------------------------------------------------------===// +class C_MyClass1 { +public: + static int ClassMemberCase; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: invalid case style for class member 'ClassMemberCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} static int i_ClassMemberCase; + + char const ConstantMemberCase = 0; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: invalid case style for constant member 'ConstantMemberCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} char const c_ConstantMemberCase = 0; + + void MyFunc1(const int ConstantParameterCase); + // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: invalid case style for constant parameter 'ConstantParameterCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} void MyFunc1(const int i_ConstantParameterCase); + + void MyFunc2(const int* ConstantPointerParameterCase); + // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: invalid case style for pointer parameter 'ConstantPointerParameterCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} void MyFunc2(const int* pi_ConstantPointerParameterCase); + + static constexpr int ConstexprVariableCase = 123; + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: invalid case style for constexpr variable 'ConstexprVariableCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} static constexpr int i_ConstexprVariableCase = 123; +}; + +const int GlobalConstantCase = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: invalid case style for global constant 'GlobalConstantCase' [readability-identifier-naming] +// CHECK-FIXES: {{^}}const int i_GlobalConstantCase = 0; + +const int* GlobalConstantPointerCase = nullptr; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: invalid case style for global pointer 'GlobalConstantPointerCase' [readability-identifier-naming] +// CHECK-FIXES: {{^}}const int* pi_GlobalConstantPointerCase = nullptr; + +int* GlobalPointerCase = nullptr; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global pointer 'GlobalPointerCase' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int* pi_GlobalPointerCase = nullptr; + +int GlobalVariableCase = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'GlobalVariableCase' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_GlobalVariableCase = 0; + +void Func1(){ + int const LocalConstantCase = 3; + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: invalid case style for local constant 'LocalConstantCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} int const i_LocalConstantCase = 3; + + unsigned const ConstantCase = 1; + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: invalid case style for local constant 'ConstantCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} unsigned const u_ConstantCase = 1; + + int* const LocalConstantPointerCase = nullptr; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: invalid case style for local constant pointer 'LocalConstantPointerCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} int* const pi_LocalConstantPointerCase = nullptr; + + int *LocalPointerCase = nullptr; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for local pointer 'LocalPointerCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} int *pi_LocalPointerCase = nullptr; + + int LocalVariableCase = 0; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for local variable 'LocalVariableCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} int i_LocalVariableCase = 0; +} + +class C_MyClass2 { + char MemberCase; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for private member 'MemberCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} char c_MemberCase; + + void Func1(int ParameterCase); + // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: invalid case style for parameter 'ParameterCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} void Func1(int i_ParameterCase); + + void Func2(const int ParameterCase); + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: invalid case style for constant parameter 'ParameterCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} void Func2(const int i_ParameterCase); + + void Func3(const int *PointerParameterCase); + // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: invalid case style for pointer parameter 'PointerParameterCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} void Func3(const int *pi_PointerParameterCase); +}; + +class C_MyClass3 { +private: + char PrivateMemberCase; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for private member 'PrivateMemberCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} char c_PrivateMemberCase; + +protected: + char ProtectedMemberCase; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for protected member 'ProtectedMemberCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} char c_ProtectedMemberCase; + +public: + char PublicMemberCase; + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for public member 'PublicMemberCase' [readability-identifier-naming] + // CHECK-FIXES: {{^}} char c_PublicMemberCase; +}; + +static const int StaticConstantCase = 3; +// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: invalid case style for global constant 'StaticConstantCase' [readability-identifier-naming] +// CHECK-FIXES: {{^}}static const int i_StaticConstantCase = 3; + +static int StaticVariableCase = 3; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: invalid case style for global variable 'StaticVariableCase' [readability-identifier-naming] +// CHECK-FIXES: {{^}}static int i_StaticVariableCase = 3; + +struct MyStruct { int StructCase; }; +// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: invalid case style for public member 'StructCase' [readability-identifier-naming] +// CHECK-FIXES: {{^}}struct MyStruct { int i_StructCase; }; + +struct shouldBeCamelCaseStruct { int i_Field; }; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for struct 'shouldBeCamelCaseStruct' [readability-identifier-naming] +// CHECK-FIXES: {{^}}struct ShouldBeCamelCaseStruct { int i_Field; }; + +union MyUnion { int UnionCase; long l_UnionCase; }; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for union 'MyUnion' [readability-identifier-naming] +// CHECK-MESSAGES: :[[@LINE-2]]:21: warning: invalid case style for public member 'UnionCase' [readability-identifier-naming] +// CHECK-FIXES: {{^}}union myUnion { int i_UnionCase; long l_UnionCase; }; + +//===----------------------------------------------------------------------===// +// C string +//===----------------------------------------------------------------------===// +const char *NamePtr = "Name"; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: invalid case style for global pointer 'NamePtr' [readability-identifier-naming] +// CHECK-FIXES: {{^}}const char *sz_NamePtr = "Name"; + +const char NameArray[] = "Name"; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: invalid case style for global constant 'NameArray' [readability-identifier-naming] +// CHECK-FIXES: {{^}}const char sz_NameArray[] = "Name"; + +const char *NamePtrArray[] = {"AA", "BB"}; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: invalid case style for global variable 'NamePtrArray' [readability-identifier-naming] +// CHECK-FIXES: {{^}}const char *psz_NamePtrArray[] = {"AA", "BB"}; + +const wchar_t *WideNamePtr = L"Name"; +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: invalid case style for global pointer 'WideNamePtr' [readability-identifier-naming] +// CHECK-FIXES: {{^}}const wchar_t *wsz_WideNamePtr = L"Name"; + +const wchar_t WideNameArray[] = L"Name"; +// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for global constant 'WideNameArray' [readability-identifier-naming] +// CHECK-FIXES: {{^}}const wchar_t wsz_WideNameArray[] = L"Name"; + +const wchar_t *WideNamePtrArray[] = {L"AA", L"BB"}; +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: invalid case style for global variable 'WideNamePtrArray' [readability-identifier-naming] +// CHECK-FIXES: {{^}}const wchar_t *pwsz_WideNamePtrArray[] = {L"AA", L"BB"}; + +class C_MyClass4 { +private: + char *Name = "Text"; + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for private member 'Name' [readability-identifier-naming] + // CHECK-FIXES: {{^}} char *sz_Name = "Text"; + + const char *ConstName = "Text"; + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for private member 'ConstName' [readability-identifier-naming] + // CHECK-FIXES: {{^}} const char *sz_ConstName = "Text"; + +public: + const char* DuplicateString(const char* Input, size_t n_RequiredSize); + // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: invalid case style for pointer parameter 'Input' [readability-identifier-naming] + // CHECK-FIXES: {{^}} const char* DuplicateString(const char* sz_Input, size_t n_RequiredSize); + + size_t UpdateText(const char* Buffer, size_t n_BufferSize); + // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: invalid case style for pointer parameter 'Buffer' [readability-identifier-naming] + // CHECK-FIXES: {{^}} size_t UpdateText(const char* sz_Buffer, size_t n_BufferSize); +}; + + +//===----------------------------------------------------------------------===// +// Microsoft Windows data types +//===----------------------------------------------------------------------===// +DWORD MsDword = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'MsDword' [readability-identifier-naming] +// CHECK-FIXES: {{^}}DWORD dw_MsDword = 0; + +BYTE MsByte = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global variable 'MsByte' [readability-identifier-naming] +// CHECK-FIXES: {{^}}BYTE by_MsByte = 0; + +WORD MsWord = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global variable 'MsWord' [readability-identifier-naming] +// CHECK-FIXES: {{^}}WORD w_MsWord = 0; + +BOOL MsBool = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global variable 'MsBool' [readability-identifier-naming] +// CHECK-FIXES: {{^}}BOOL b_MsBool = 0; + +BOOLEAN MsBoolean = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for global variable 'MsBoolean' [readability-identifier-naming] +// CHECK-FIXES: {{^}}BOOLEAN b_MsBoolean = 0; + +CHAR MsValueChar = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global variable 'MsValueChar' [readability-identifier-naming] +// CHECK-FIXES: {{^}}CHAR c_MsValueChar = 0; + +UCHAR MsValueUchar = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'MsValueUchar' [readability-identifier-naming] +// CHECK-FIXES: {{^}}UCHAR uc_MsValueUchar = 0; + +SHORT MsValueShort = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'MsValueShort' [readability-identifier-naming] +// CHECK-FIXES: {{^}}SHORT s_MsValueShort = 0; + +USHORT MsValueUshort = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for global variable 'MsValueUshort' [readability-identifier-naming] +// CHECK-FIXES: {{^}}USHORT us_MsValueUshort = 0; + +WORD MsValueWord = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global variable 'MsValueWord' [readability-identifier-naming] +// CHECK-FIXES: {{^}}WORD w_MsValueWord = 0; + +DWORD MsValueDword = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'MsValueDword' [readability-identifier-naming] +// CHECK-FIXES: {{^}}DWORD dw_MsValueDword = 0; + +DWORD32 MsValueDword32 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for global variable 'MsValueDword32' [readability-identifier-naming] +// CHECK-FIXES: {{^}}DWORD32 dw32_MsValueDword32 = 0; + +DWORD64 MsValueDword64 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for global variable 'MsValueDword64' [readability-identifier-naming] +// CHECK-FIXES: {{^}}DWORD64 dw64_MsValueDword64 = 0; + +LONG MsValueLong = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global variable 'MsValueLong' [readability-identifier-naming] +// CHECK-FIXES: {{^}}LONG l_MsValueLong = 0; + +ULONG MsValueUlong = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'MsValueUlong' [readability-identifier-naming] +// CHECK-FIXES: {{^}}ULONG ul_MsValueUlong = 0; + +ULONG32 MsValueUlong32 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for global variable 'MsValueUlong32' [readability-identifier-naming] +// CHECK-FIXES: {{^}}ULONG32 ul32_MsValueUlong32 = 0; + +ULONG64 MsValueUlong64 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for global variable 'MsValueUlong64' [readability-identifier-naming] +// CHECK-FIXES: {{^}}ULONG64 ul64_MsValueUlong64 = 0; + +ULONGLONG MsValueUlongLong = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: invalid case style for global variable 'MsValueUlongLong' [readability-identifier-naming] +// CHECK-FIXES: {{^}}ULONGLONG ull_MsValueUlongLong = 0; + +HANDLE MsValueHandle = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for global pointer 'MsValueHandle' [readability-identifier-naming] +// CHECK-FIXES: {{^}}HANDLE h_MsValueHandle = 0; + +INT MsValueInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'MsValueInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}INT i_MsValueInt = 0; + +INT8 MsValueInt8 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global variable 'MsValueInt8' [readability-identifier-naming] +// CHECK-FIXES: {{^}}INT8 i8_MsValueInt8 = 0; + +INT16 MsValueInt16 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'MsValueInt16' [readability-identifier-naming] +// CHECK-FIXES: {{^}}INT16 i16_MsValueInt16 = 0; + +INT32 MsValueInt32 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'MsValueInt32' [readability-identifier-naming] +// CHECK-FIXES: {{^}}INT32 i32_MsValueInt32 = 0; + +INT64 MsValueINt64 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'MsValueINt64' [readability-identifier-naming] +// CHECK-FIXES: {{^}}INT64 i64_MsValueINt64 = 0; + +UINT MsValueUint = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global variable 'MsValueUint' [readability-identifier-naming] +// CHECK-FIXES: {{^}}UINT ui_MsValueUint = 0; + +UINT8 MsValueUint8 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'MsValueUint8' [readability-identifier-naming] +// CHECK-FIXES: {{^}}UINT8 u8_MsValueUint8 = 0; + +UINT16 MsValueUint16 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for global variable 'MsValueUint16' [readability-identifier-naming] +// CHECK-FIXES: {{^}}UINT16 u16_MsValueUint16 = 0; + +UINT32 MsValueUint32 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for global variable 'MsValueUint32' [readability-identifier-naming] +// CHECK-FIXES: {{^}}UINT32 u32_MsValueUint32 = 0; + +UINT64 MsValueUint64 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for global variable 'MsValueUint64' [readability-identifier-naming] +// CHECK-FIXES: {{^}}UINT64 u64_MsValueUint64 = 0; + +PVOID MsValuePvoid = NULL; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global pointer 'MsValuePvoid' [readability-identifier-naming] +// CHECK-FIXES: {{^}}PVOID p_MsValuePvoid = NULL; + + +//===----------------------------------------------------------------------===// +// Array +//===----------------------------------------------------------------------===// +unsigned GlobalUnsignedArray[] = {1, 2, 3}; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for global variable 'GlobalUnsignedArray' [readability-identifier-naming] +// CHECK-FIXES: {{^}}unsigned a_GlobalUnsignedArray[] = {1, 2, 3}; + +int GlobalIntArray[] = {1, 2, 3}; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'GlobalIntArray' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int a_GlobalIntArray[] = {1, 2, 3}; + +int DataInt[1] = {0}; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'DataInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int a_DataInt[1] = {0}; + +int DataArray[2] = {0}; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'DataArray' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int a_DataArray[2] = {0}; + + +//===----------------------------------------------------------------------===// +// Pointer +//===----------------------------------------------------------------------===// +int *DataIntPtr[1] = {0}; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global variable 'DataIntPtr' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int *pa_DataIntPtr[1] = {0}; + +void *BufferPtr1; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global pointer 'BufferPtr1' [readability-identifier-naming] +// CHECK-FIXES: {{^}}void *p_BufferPtr1; + +void **BufferPtr2; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for global pointer 'BufferPtr2' [readability-identifier-naming] +// CHECK-FIXES: {{^}}void **pp_BufferPtr2; + +void **pBufferPtr3; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for global pointer 'pBufferPtr3' [readability-identifier-naming] +// CHECK-FIXES: {{^}}void **pp_BufferPtr3; + +int *pBufferPtr4; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global pointer 'pBufferPtr4' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int *pi_BufferPtr4; + +typedef void (*FUNC_PTR_HELLO)(); +FUNC_PTR_HELLO Hello = NULL; +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: invalid case style for global pointer 'Hello' [readability-identifier-naming] +// CHECK-FIXES: {{^}}FUNC_PTR_HELLO fn_Hello = NULL; + +void *ValueVoidPtr = NULL; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global pointer 'ValueVoidPtr' [readability-identifier-naming] +// CHECK-FIXES: {{^}}void *p_ValueVoidPtr = NULL; + +ptrdiff_t PtrDiff = NULL; +// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: invalid case style for global variable 'PtrDiff' [readability-identifier-naming] +// CHECK-FIXES: {{^}}ptrdiff_t p_PtrDiff = NULL; + +int8_t *ValueI8Ptr; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for global pointer 'ValueI8Ptr' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int8_t *pi8_ValueI8Ptr; + +uint8_t *ValueU8Ptr; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for global pointer 'ValueU8Ptr' [readability-identifier-naming] +// CHECK-FIXES: {{^}}uint8_t *pu8_ValueU8Ptr; + +unsigned char *ValueUcPtr; +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: invalid case style for global pointer 'ValueUcPtr' [readability-identifier-naming] +// CHECK-FIXES: {{^}}unsigned char *puc_ValueUcPtr; + +unsigned char **ValueUcPtr2; +// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: invalid case style for global pointer 'ValueUcPtr2' [readability-identifier-naming] +// CHECK-FIXES: {{^}}unsigned char **ppuc_ValueUcPtr2; + +void MyFunc2(void* Val){} +// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: invalid case style for pointer parameter 'Val' [readability-identifier-naming] +// CHECK-FIXES: {{^}}void MyFunc2(void* p_Val){} + + +//===----------------------------------------------------------------------===// +// Reference +//===----------------------------------------------------------------------===// +int i_ValueIndex = 1; +int &RefValueIndex = i_ValueIndex; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global variable 'RefValueIndex' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int &i_RefValueIndex = i_ValueIndex; + +const int &ConstRefValue = i_ValueIndex; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: invalid case style for global variable 'ConstRefValue' [readability-identifier-naming] +// CHECK-FIXES: {{^}}const int &i_ConstRefValue = i_ValueIndex; + +long long ll_ValueLongLong = 2; +long long &RefValueLongLong = ll_ValueLongLong; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: invalid case style for global variable 'RefValueLongLong' [readability-identifier-naming] +// CHECK-FIXES: {{^}}long long &ll_RefValueLongLong = ll_ValueLongLong; + + +//===----------------------------------------------------------------------===// +// Various types +//===----------------------------------------------------------------------===// +int8_t ValueI8; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for global variable 'ValueI8' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int8_t i8_ValueI8; + +int16_t ValueI16 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for global variable 'ValueI16' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int16_t i16_ValueI16 = 0; + +int32_t ValueI32 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for global variable 'ValueI32' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int32_t i32_ValueI32 = 0; + +int64_t ValueI64 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for global variable 'ValueI64' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int64_t i64_ValueI64 = 0; + +uint8_t ValueU8 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for global variable 'ValueU8' [readability-identifier-naming] +// CHECK-FIXES: {{^}}uint8_t u8_ValueU8 = 0; + +uint16_t ValueU16 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for global variable 'ValueU16' [readability-identifier-naming] +// CHECK-FIXES: {{^}}uint16_t u16_ValueU16 = 0; + +uint32_t ValueU32 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for global variable 'ValueU32' [readability-identifier-naming] +// CHECK-FIXES: {{^}}uint32_t u32_ValueU32 = 0; + +uint64_t ValueU64 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for global variable 'ValueU64' [readability-identifier-naming] +// CHECK-FIXES: {{^}}uint64_t u64_ValueU64 = 0; + +float ValueFloat = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'ValueFloat' [readability-identifier-naming] +// CHECK-FIXES: {{^}}float f_ValueFloat = 0; + +double ValueDouble = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for global variable 'ValueDouble' [readability-identifier-naming] +// CHECK-FIXES: {{^}}double d_ValueDouble = 0; + +char ValueChar = 'c'; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global variable 'ValueChar' [readability-identifier-naming] +// CHECK-FIXES: {{^}}char c_ValueChar = 'c'; + +bool ValueBool = true; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global variable 'ValueBool' [readability-identifier-naming] +// CHECK-FIXES: {{^}}bool b_ValueBool = true; + +int ValueInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'ValueInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_ValueInt = 0; + +size_t ValueSize = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for global variable 'ValueSize' [readability-identifier-naming] +// CHECK-FIXES: {{^}}size_t n_ValueSize = 0; + +wchar_t ValueWchar = 'w'; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for global variable 'ValueWchar' [readability-identifier-naming] +// CHECK-FIXES: {{^}}wchar_t wc_ValueWchar = 'w'; + +short ValueShort = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'ValueShort' [readability-identifier-naming] +// CHECK-FIXES: {{^}}short s_ValueShort = 0; + +unsigned ValueUnsigned = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for global variable 'ValueUnsigned' [readability-identifier-naming] +// CHECK-FIXES: {{^}}unsigned u_ValueUnsigned = 0; + +signed ValueSigned = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for global variable 'ValueSigned' [readability-identifier-naming] +// CHECK-FIXES: {{^}}signed s_ValueSigned = 0; + +long ValueLong = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: invalid case style for global variable 'ValueLong' [readability-identifier-naming] +// CHECK-FIXES: {{^}}long l_ValueLong = 0; + +long long ValueLongLong = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: invalid case style for global variable 'ValueLongLong' [readability-identifier-naming] +// CHECK-FIXES: {{^}}long long ll_ValueLongLong = 0; + +long long int ValueLongLongInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for global variable 'ValueLongLongInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}long long int lli_ValueLongLongInt = 0; + +long double ValueLongDouble = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: invalid case style for global variable 'ValueLongDouble' [readability-identifier-naming] +// CHECK-FIXES: {{^}}long double ld_ValueLongDouble = 0; + +signed int ValueSignedInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: invalid case style for global variable 'ValueSignedInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}signed int si_ValueSignedInt = 0; + +signed short ValueSignedShort = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: invalid case style for global variable 'ValueSignedShort' [readability-identifier-naming] +// CHECK-FIXES: {{^}}signed short ss_ValueSignedShort = 0; + +signed short int ValueSignedShortInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: invalid case style for global variable 'ValueSignedShortInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}signed short int ssi_ValueSignedShortInt = 0; + +signed long long ValueSignedLongLong = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: invalid case style for global variable 'ValueSignedLongLong' [readability-identifier-naming] +// CHECK-FIXES: {{^}}signed long long sll_ValueSignedLongLong = 0; + +signed long int ValueSignedLongInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: invalid case style for global variable 'ValueSignedLongInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}signed long int sli_ValueSignedLongInt = 0; + +signed long ValueSignedLong = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: invalid case style for global variable 'ValueSignedLong' [readability-identifier-naming] +// CHECK-FIXES: {{^}}signed long sl_ValueSignedLong = 0; + +unsigned long long int ValueUnsignedLongLongInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: invalid case style for global variable 'ValueUnsignedLongLongInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}unsigned long long int ulli_ValueUnsignedLongLongInt = 0; + +unsigned long long ValueUnsignedLongLong = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: invalid case style for global variable 'ValueUnsignedLongLong' [readability-identifier-naming] +// CHECK-FIXES: {{^}}unsigned long long ull_ValueUnsignedLongLong = 0; + +unsigned long int ValueUnsignedLongInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: invalid case style for global variable 'ValueUnsignedLongInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}unsigned long int uli_ValueUnsignedLongInt = 0; + +unsigned long ValueUnsignedLong = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for global variable 'ValueUnsignedLong' [readability-identifier-naming] +// CHECK-FIXES: {{^}}unsigned long ul_ValueUnsignedLong = 0; + +unsigned short int ValueUnsignedShortInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: invalid case style for global variable 'ValueUnsignedShortInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}unsigned short int usi_ValueUnsignedShortInt = 0; + +unsigned short ValueUnsignedShort = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: invalid case style for global variable 'ValueUnsignedShort' [readability-identifier-naming] +// CHECK-FIXES: {{^}}unsigned short us_ValueUnsignedShort = 0; + +unsigned int ValueUnsignedInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: invalid case style for global variable 'ValueUnsignedInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}unsigned int ui_ValueUnsignedInt = 0; + +unsigned char ValueUnsignedChar = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for global variable 'ValueUnsignedChar' [readability-identifier-naming] +// CHECK-FIXES: {{^}}unsigned char uc_ValueUnsignedChar = 0; + +long int ValueLongInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for global variable 'ValueLongInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}long int li_ValueLongInt = 0; + + +//===----------------------------------------------------------------------===// +// Specifier, Qualifier, Other keywords +//===----------------------------------------------------------------------===// +volatile int VolatileInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: invalid case style for global variable 'VolatileInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}volatile int i_VolatileInt = 0; + +thread_local int ThreadLocalValueInt = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: invalid case style for global variable 'ThreadLocalValueInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}thread_local int i_ThreadLocalValueInt = 0; + +extern int ExternValueInt; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: invalid case style for global variable 'ExternValueInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}extern int i_ExternValueInt; + +struct DataBuffer { + mutable size_t Size; +}; +// CHECK-MESSAGES: :[[@LINE-2]]:20: warning: invalid case style for public member 'Size' [readability-identifier-naming] +// CHECK-FIXES: {{^}} mutable size_t n_Size; + +static constexpr int const &ConstExprInt = 42; +// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: invalid case style for constexpr variable 'ConstExprInt' [readability-identifier-naming] +// CHECK-FIXES: {{^}}static constexpr int const &i_ConstExprInt = 42; + + +//===----------------------------------------------------------------------===// +// Redefined types +//===----------------------------------------------------------------------===// +typedef int INDEX; +INDEX iIndex = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'iIndex' [readability-identifier-naming] +// CHECK-FIXES: {{^}}INDEX Index = 0; + + +//===----------------------------------------------------------------------===// +// Class +//===----------------------------------------------------------------------===// +class ClassCase { int Func(); }; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for class 'ClassCase' [readability-identifier-naming] +// CHECK-FIXES: {{^}}class C_ClassCase { int Func(); }; + +class AbstractClassCase { virtual int Func() = 0; }; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for abstract class 'AbstractClassCase' [readability-identifier-naming] +// CHECK-FIXES: {{^}}class I_AbstractClassCase { virtual int Func() = 0; }; + +class AbstractClassCase1 { virtual int Func1() = 0; int Func2(); }; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for abstract class 'AbstractClassCase1' [readability-identifier-naming] +// CHECK-FIXES: {{^}}class I_AbstractClassCase1 { virtual int Func1() = 0; int Func2(); }; + +class ClassConstantCase { public: static const int i_ConstantCase; }; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for class 'ClassConstantCase' [readability-identifier-naming] +// CHECK-FIXES: {{^}}class C_ClassConstantCase { public: static const int i_ConstantCase; }; + +//===----------------------------------------------------------------------===// +// Other Cases +//===----------------------------------------------------------------------===// +int lower_case = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'lower_case' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_LowerCase = 0; + +int lower_case1 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'lower_case1' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_LowerCase1 = 0; + +int lower_case_2 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'lower_case_2' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_LowerCase2 = 0; + +int UPPER_CASE = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'UPPER_CASE' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_UpperCase = 0; + +int UPPER_CASE_1 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'UPPER_CASE_1' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_UpperCase1 = 0; + +int camelBack = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'camelBack' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_CamelBack = 0; + +int camelBack_1 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'camelBack_1' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_CamelBack1 = 0; + +int camelBack2 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'camelBack2' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_CamelBack2 = 0; + +int CamelCase = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'CamelCase' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_CamelCase = 0; + +int CamelCase_1 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'CamelCase_1' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_CamelCase1 = 0; + +int CamelCase2 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'CamelCase2' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_CamelCase2 = 0; + +int camel_Snake_Back = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'camel_Snake_Back' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_CamelSnakeBack = 0; + +int camel_Snake_Back_1 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'camel_Snake_Back_1' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_CamelSnakeBack1 = 0; + +int Camel_Snake_Case = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'Camel_Snake_Case' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_CamelSnakeCase = 0; + +int Camel_Snake_Case_1 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for global variable 'Camel_Snake_Case_1' [readability-identifier-naming] +// CHECK-FIXES: {{^}}int i_CamelSnakeCase1 = 0; + +//===----------------------------------------------------------------------===// +// Enum +//===----------------------------------------------------------------------===// +enum REV_TYPE { RevValid }; +// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: invalid case style for enum constant 'RevValid' [readability-identifier-naming] +// CHECK-FIXES: {{^}}enum REV_TYPE { rt_RevValid }; + +enum EnumConstantCase { OneByte, TwoByte }; +// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: invalid case style for enum constant 'OneByte' [readability-identifier-naming] +// CHECK-MESSAGES: :[[@LINE-2]]:34: warning: invalid case style for enum constant 'TwoByte' [readability-identifier-naming] +// CHECK-FIXES: {{^}}enum EnumConstantCase { ecc_OneByte, ecc_TwoByte }; + +enum class ScopedEnumConstantCase { Case1 }; +// CHECK-MESSAGES: :[[@LINE-1]]:37: warning: invalid case style for scoped enum constant 'Case1' [readability-identifier-naming] +// CHECK-FIXES: {{^}}enum class ScopedEnumConstantCase { secc_Case1 }; +// clang-format on diff --git a/clang-tools-extra/unittests/clang-tidy/DeclRefExprUtilsTest.cpp b/clang-tools-extra/unittests/clang-tidy/DeclRefExprUtilsTest.cpp index 4c9e81ea0f61ac3d2ed277c2b9d1add5616cf736..3d9f51e2e17b0945bec574145a46a3437f9402df 100644 --- a/clang-tools-extra/unittests/clang-tidy/DeclRefExprUtilsTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/DeclRefExprUtilsTest.cpp @@ -51,6 +51,8 @@ template void RunTest(StringRef Snippet) { void constMethod() const; void nonConstMethod(); + static void staticMethod(); + void operator()(ConstTag) const; void operator()(NonConstTag); @@ -109,10 +111,12 @@ TEST(ConstReferenceDeclRefExprsTest, ConstValueVar) { useConstPtr(&/*const*/target); useConstPtrConstRef(&/*const*/target); /*const*/target.constMethod(); + /*const*/target.staticMethod(); /*const*/target(ConstTag{}); /*const*/target[42]; useConstRef((/*const*/target)); (/*const*/target).constMethod(); + /*const*/target.staticMethod(); (void)(/*const*/target == /*const*/target); (void)/*const*/target; (void)&/*const*/target; @@ -140,6 +144,7 @@ TEST(ConstReferenceDeclRefExprsTest, ConstRefVar) { useConstPtr(&/*const*/target); useConstPtrConstRef(&/*const*/target); /*const*/target.constMethod(); + /*const*/target.staticMethod(); /*const*/target(ConstTag{}); /*const*/target[42]; useConstRef((/*const*/target)); @@ -179,6 +184,7 @@ TEST(ConstReferenceDeclRefExprsTest, ValueVar) { useConstPtr(&/*const*/target); useConstPtrConstRef(&/*const*/target); /*const*/target.constMethod(); + /*const*/target.staticMethod(); target.nonConstMethod(); /*const*/target(ConstTag{}); target[42]; @@ -218,6 +224,7 @@ TEST(ConstReferenceDeclRefExprsTest, RefVar) { useConstPtr(&/*const*/target); useConstPtrConstRef(&/*const*/target); /*const*/target.constMethod(); + /*const*/target.staticMethod(); target.nonConstMethod(); /*const*/target(ConstTag{}); target[42]; @@ -256,6 +263,7 @@ TEST(ConstReferenceDeclRefExprsTest, PtrVar) { useConstPtrConstRef(/*const*/target); usePtrConstPtr(&target); /*const*/target->constMethod(); + /*const*/target->staticMethod(); target->nonConstMethod(); (*/*const*/target)(ConstTag{}); (*target)[42]; @@ -292,6 +300,7 @@ TEST(ConstReferenceDeclRefExprsTest, ConstPtrVar) { useConstPtrConstPtr(&/*const*/target); useConstPtrConstRef(/*const*/target); /*const*/target->constMethod(); + /*const*/target->staticMethod(); (*/*const*/target)(ConstTag{}); (*/*const*/target)[42]; /*const*/target->operator[](42); diff --git a/clang/CodeOwners.rst b/clang/CodeOwners.rst index 995a2f50226a169ede3ad3133ced72b05129ed7b..2ae04c129eb765425ed1716adbc6bea11acf4d66 100644 --- a/clang/CodeOwners.rst +++ b/clang/CodeOwners.rst @@ -60,7 +60,7 @@ Analysis & CFG Experimental new constant interpreter ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | Timm Bäder -| tbaeder@redhat.com (email), tbaeder (Phabricator), tbaederr (GitHub) +| tbaeder\@redhat.com (email), tbaeder (Phabricator), tbaederr (GitHub), tbaeder (Discourse), tbaeder (Discord) Modules & serialization diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake b/clang/cmake/caches/Fuchsia-stage2.cmake index eee37c5e7901fae1cbc53ce28aee8fb7be7f7c89..db7430b3344c3e76c15b0038ad9011a0c8e2fecb 100644 --- a/clang/cmake/caches/Fuchsia-stage2.cmake +++ b/clang/cmake/caches/Fuchsia-stage2.cmake @@ -300,6 +300,39 @@ if(FUCHSIA_SDK) set(LLVM_RUNTIME_MULTILIB_hwasan+noexcept_TARGETS "aarch64-unknown-fuchsia;riscv64-unknown-fuchsia" CACHE STRING "") endif() +foreach(target armv6m-unknown-eabi) + list(APPEND BUILTIN_TARGETS "${target}") + set(BUILTINS_${target}_CMAKE_SYSTEM_NAME Generic CACHE STRING "") + set(BUILTINS_${target}_CMAKE_SYSTEM_PROCESSOR arm CACHE STRING "") + set(BUILTINS_${target}_CMAKE_SYSROOT "" CACHE STRING "") + set(BUILTINS_${target}_CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "") + foreach(lang C;CXX;ASM) + set(BUILTINS_${target}_CMAKE_${lang}_FLAGS "--target=${target} -mcpu=cortex-m0plus -mthumb" CACHE STRING "") + endforeach() + foreach(type SHARED;MODULE;EXE) + set(BUILTINS_${target}_CMAKE_${type}_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "") + endforeach() + set(BUILTINS_${target}_COMPILER_RT_BAREMETAL_BUILD ON CACHE BOOL "") + + list(APPEND RUNTIME_TARGETS "${target}") + set(RUNTIMES_${target}_CMAKE_SYSTEM_NAME Generic CACHE STRING "") + set(RUNTIMES_${target}_CMAKE_SYSTEM_PROCESSOR arm CACHE STRING "") + set(RUNTIMES_${target}_CMAKE_SYSROOT "" CACHE STRING "") + set(RUNTIMES_${target}_CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "") + set(RUNTIMES_${target}_CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY CACHE STRING "") + foreach(lang C;CXX;ASM) + set(RUNTIMES_${target}_CMAKE_${lang}_FLAGS "--target=${target} -mcpu=cortex-m0plus -mthumb" CACHE STRING "") + endforeach() + foreach(type SHARED;MODULE;EXE) + set(RUNTIMES_${target}_CMAKE_${type}_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "") + endforeach() + set(RUNTIMES_${target}_LLVM_LIBC_FULL_BUILD ON CACHE BOOL "") + set(RUNTIMES_${target}_LIBC_ENABLE_USE_BY_CLANG ON CACHE BOOL "") + set(RUNTIMES_${target}_LLVM_INCLUDE_TESTS OFF CACHE BOOL "") + set(RUNTIMES_${target}_LLVM_ENABLE_ASSERTIONS OFF CACHE BOOL "") + set(RUNTIMES_${target}_LLVM_ENABLE_RUNTIMES "libc" CACHE STRING "") +endforeach() + foreach(target riscv32-unknown-elf) list(APPEND BUILTIN_TARGETS "${target}") set(BUILTINS_${target}_CMAKE_SYSTEM_NAME Generic CACHE STRING "") diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index df399a229d8d4f3bbefc48b6419faf61a191725e..5b00a8f4c00fb81ebb95d9be945db223b2561803 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -318,9 +318,9 @@ the configuration (without a prefix: ``Auto``). .. code-block:: c++ - AlignConsecutiveMacros: AcrossEmptyLines + AlignConsecutiveAssignments: AcrossEmptyLines - AlignConsecutiveMacros: + AlignConsecutiveAssignments: Enabled: true AcrossEmptyLines: true AcrossComments: false @@ -460,9 +460,9 @@ the configuration (without a prefix: ``Auto``). .. code-block:: c++ - AlignConsecutiveMacros: AcrossEmptyLines + AlignConsecutiveBitFields: AcrossEmptyLines - AlignConsecutiveMacros: + AlignConsecutiveBitFields: Enabled: true AcrossEmptyLines: true AcrossComments: false @@ -602,9 +602,9 @@ the configuration (without a prefix: ``Auto``). .. code-block:: c++ - AlignConsecutiveMacros: AcrossEmptyLines + AlignConsecutiveDeclarations: AcrossEmptyLines - AlignConsecutiveMacros: + AlignConsecutiveDeclarations: Enabled: true AcrossEmptyLines: true AcrossComments: false @@ -983,9 +983,9 @@ the configuration (without a prefix: ``Auto``). .. code-block:: c++ - AlignConsecutiveMacros: AcrossEmptyLines + AlignConsecutiveTableGenCondOperatorColons: AcrossEmptyLines - AlignConsecutiveMacros: + AlignConsecutiveTableGenCondOperatorColons: Enabled: true AcrossEmptyLines: true AcrossComments: false @@ -1123,9 +1123,9 @@ the configuration (without a prefix: ``Auto``). .. code-block:: c++ - AlignConsecutiveMacros: AcrossEmptyLines + AlignConsecutiveTableGenDefinitionColons: AcrossEmptyLines - AlignConsecutiveMacros: + AlignConsecutiveTableGenDefinitionColons: Enabled: true AcrossEmptyLines: true AcrossComments: false diff --git a/clang/docs/DataFlowSanitizer.rst b/clang/docs/DataFlowSanitizer.rst index a18b8ed1948f33cc3f02daafcf434272e5cf3986..5ff50b85dcdcf9304e607a27cb649f09372b6d77 100644 --- a/clang/docs/DataFlowSanitizer.rst +++ b/clang/docs/DataFlowSanitizer.rst @@ -233,6 +233,28 @@ labels of just ``v1`` and ``v2``. or, and can be accessed using ``dfsan_label dfsan_get_labels_in_signal_conditional();``. +* ``-dfsan-reaches-function-callbacks`` -- An experimental feature that inserts + callbacks for data entering a function. + + In addition to this compilation flag, a callback handler must be registered + using ``dfsan_set_reaches_function_callback(my_callback);``, where my_callback is + a function with a signature matching + ``void my_callback(dfsan_label label, dfsan_origin origin, const char *file, unsigned int line, const char *function);`` + This signature is the same when origin tracking is disabled - in this case + the dfsan_origin passed in it will always be 0. + + The callback will be called when a tained value reach stack/registers + in the context of a function. Tainted values can reach a function: + * via the arguments of the function + * via the return value of a call that occurs in the function + * via the loaded value of a load that occurs in the function + + The callback will be skipped for conditional expressions inside signal + handlers, as this is prone to deadlock. Tainted values reaching functions + inside signal handlers will instead be aggregated via bitwise or, and can + be accessed using + ``dfsan_label dfsan_get_labels_in_signal_reaches_function()``. + * ``-dfsan-track-origins`` -- Controls how to track origins. When its value is 0, the runtime does not track origins. When its value is 1, the runtime tracks origins at memory store operations. When its value is 2, the runtime tracks diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index bcd69198eafdbec3f1097c1fae4bd88dddc99cb6..06af93fd3c15ca8ce3da56190a024f3ee3ffb5e4 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -2799,6 +2799,34 @@ counter's true frequency will need to be provided by the user. Query for this feature with ``__has_builtin(__builtin_readsteadycounter)``. +``__builtin_cpu_supports`` +-------------------------- + +**Syntax**: + +.. code-block:: c++ + + int __builtin_cpu_supports(const char *features); + +**Example of Use:**: + +.. code-block:: c++ + + if (__builtin_cpu_supports("sve")) + sve_code(); + +**Description**: + +The ``__builtin_cpu_supports`` function detects if the run-time CPU supports +features specified in string argument. It returns a positive integer if all +features are supported and 0 otherwise. Feature names are target specific. On +AArch64 features are combined using ``+`` like this +``__builtin_cpu_supports("flagm+sha3+lse+rcpc2+fcma+memtag+bti+sme2")``. +If a feature name is not supported, Clang will issue a warning and replace +builtin by the constant 0. + +Query for this feature with ``__has_builtin(__builtin_cpu_supports)``. + ``__builtin_dump_struct`` ------------------------- @@ -5350,6 +5378,7 @@ The following builtin intrinsics can be used in constant expressions: * ``__builtin_popcount`` * ``__builtin_popcountl`` * ``__builtin_popcountll`` +* ``__builtin_popcountg`` * ``__builtin_rotateleft8`` * ``__builtin_rotateleft16`` * ``__builtin_rotateleft32`` diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 8a06084955aa6b8d8fb1399d22800503aba66793..bb1b68f6671b1a7a3058968ce28671dc58c9eeaa 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -3546,6 +3546,21 @@ cxxMethodDecl(isConst()) matches A::foo() but not A::bar() +Matcher<CXXMethodDecl>isExplicitObjectMemberFunction +
Matches if the given method declaration declares a member function with an explicit object parameter.
+
+Given
+struct A {
+  int operator-(this A, int);
+  void fun(this A &&self);
+  static int operator()(int);
+  int operator+(int);
+};
+
+cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two methods but not the last two.
+
+ + Matcher<CXXMethodDecl>isCopyAssignmentOperator
Matches if the given method declaration declares a copy assignment
 operator.
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c381da7e354c709b7525b96b5bcfa950d084a88d..6c30af304d981df545c34262d4b4dcd126f5d9a3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -86,11 +86,23 @@ C++20 Feature Support
 - Implemented the `__is_layout_compatible` intrinsic to support
   `P0466R5: Layout-compatibility and Pointer-interconvertibility Traits `_.
 
+- Clang now implements [module.import]p7 fully. Clang now will import module
+  units transitively for the module units coming from the same module of the
+  current module units.
+  Fixes `#84002 `_.
+
+- Initial support for class template argument deduction (CTAD) for type alias
+  templates (`P1814R0 `_).
+  (#GH54051).
+
 C++23 Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 
 - Implemented `P2718R0: Lifetime extension in range-based for loops `_. Also
   materialize temporary object which is a prvalue in discarded-value expression.
+- Implemented `P1774R8: Portable assumptions `_.
+
+- Implemented `P2448R2: Relaxing some constexpr restrictions `_.
 
 C++2c Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
@@ -108,6 +120,10 @@ Resolutions to C++ Defect Reports
   of two types.
   (`CWG1719: Layout compatibility and cv-qualification revisited `_).
 
+- Alignment of members is now respected when evaluating layout compatibility
+  of structs.
+  (`CWG2583: Common initial sequence should consider over-alignment `_).
+
 - ``[[no_unique_address]]`` is now respected when evaluating layout
   compatibility of two types.
   (`CWG2759: [[no_unique_address] and common initial sequence  `_).
@@ -138,6 +154,9 @@ C23 Feature Support
   macros typically exposed from ````, such as ``PRIb8``.
   (`#81896: `_).
 
+- Clang now supports `N3018 The constexpr specifier for object definitions`
+  `_.
+
 Non-comprehensive list of changes in this release
 -------------------------------------------------
 
@@ -147,14 +166,26 @@ Non-comprehensive list of changes in this release
 - ``__builtin_addc``, ``__builtin_subc``, and the other sizes of those
   builtins are now constexpr and may be used in constant expressions.
 
+- Added ``__builtin_popcountg`` as a type-generic alternative to
+  ``__builtin_popcount{,l,ll}`` with support for any unsigned integer type. Like
+  the previous builtins, this new builtin is constexpr and may be used in
+  constant expressions.
+
 New Compiler Flags
 ------------------
 
+- ``-Wmissing-designated-field-initializers``, grouped under ``-Wmissing-field-initializers``.
+  This diagnostic can be disabled to make ``-Wmissing-field-initializers`` behave
+  like it did before Clang 18.x. Fixes (`#56628 `_)
+
 Deprecated Compiler Flags
 -------------------------
 
 Modified Compiler Flags
 -----------------------
+- Added a new diagnostic flag ``-Wreturn-mismatch`` which is grouped under
+  ``-Wreturn-type``, and moved some of the diagnostics previously controlled by
+  ``-Wreturn-type`` under this new flag. Fixes #GH72116.
 
 Removed Compiler Flags
 -------------------------
@@ -177,6 +208,9 @@ Improvements to Clang's diagnostics
 - The ``-Wshorten-64-to-32`` diagnostic is now grouped under ``-Wimplicit-int-conversion`` instead
    of ``-Wconversion``. Fixes #GH69444.
 
+- Clang now uses thousand separators when printing large numbers in integer overflow diagnostics.
+  Fixes #GH80939.
+
 - Clang now diagnoses friend declarations with an ``enum`` elaborated-type-specifier in language modes after C++98.
 
 - Added diagnostics for C11 keywords being incompatible with language standards
@@ -220,10 +254,20 @@ Bug Fixes in This Version
   for logical operators in C23.
   Fixes (#GH64356).
 
+- ``__is_trivially_relocatable`` no longer returns ``false`` for volatile-qualified types.
+  Fixes (#GH77091).
+
 - Clang no longer produces a false-positive `-Wunused-variable` warning
   for variables created through copy initialization having side-effects in C++17 and later.
   Fixes (#GH64356) (#GH79518).
 
+- Clang now emits errors for explicit specializations/instatiations of lambda call
+  operator.
+  Fixes (#GH83267).
+
+- Clang now correctly generates overloads for bit-precise integer types for
+  builtin operators in C++. Fixes #GH82998.
+
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -265,6 +309,8 @@ Bug Fixes to C++ Support
 - Fix a crash when trying to call a varargs function that also has an explicit object parameter. (#GH80971)
 - Fixed a bug where abbreviated function templates would append their invented template parameters to
   an empty template parameter lists.
+- Fix parsing of abominable function types inside type traits.
+  Fixes (`#77585 `_)
 - Clang now classifies aggregate initialization in C++17 and newer as constant
   or non-constant more accurately. Previously, only a subset of the initializer
   elements were considered, misclassifying some initializers as constant. Partially fixes
@@ -295,7 +341,19 @@ Bug Fixes to C++ Support
   of templates. Previously we were diagnosing on any non-function template
   instead of only on class, alias, and variable templates, as last updated by
   CWG2032. Fixes (#GH83461)
-
+- Fixed an issue where an attribute on a declarator would cause the attribute to
+  be destructed prematurely. This fixes a pair of Chromium that were brought to
+  our attention by an attempt to fix in (#GH77703). Fixes (#GH83385).
+- Fix evaluation of some immediate calls in default arguments.
+  Fixes (#GH80630)
+- Fixed an issue where the ``RequiresExprBody`` was involved in the lambda dependency
+  calculation. (#GH56556), (#GH82849).
+- Fix a bug where overload resolution falsely reported an ambiguity when it was comparing
+  a member-function against a non member function or a member-function with an
+  explicit object parameter against a member function with no explicit object parameter
+  when one of the function had more specialized templates.
+  Fixes (`#82509 `_)
+  and (`#74494 `_)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -340,6 +398,8 @@ Arm and AArch64 Support
   instructions (rdm). The identifier is available on the command line as
   a feature modifier for -march and -mcpu as well as via target attributes
   like ``target_version`` or ``target_clones``.
+- Support has been added for the following processors (-mcpu identifiers in parenthesis):
+    * Arm Cortex-A78AE (cortex-a78ae).
 
 Android Support
 ^^^^^^^^^^^^^^^
@@ -358,6 +418,9 @@ RISC-V Support
 CUDA/HIP Language Changes
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
+- PTX is no longer included by default when compiling for CUDA. Using
+  ``--cuda-include-ptx=all`` will return the old behavior.
+
 CUDA Support
 ^^^^^^^^^^^^
 
@@ -386,6 +449,7 @@ AST Matchers
 ------------
 
 - ``isInStdNamespace`` now supports Decl declared with ``extern "C++"``.
+- Add ``isExplicitObjectMemberFunction``.
 
 clang-format
 ------------
@@ -436,6 +500,11 @@ Python Binding Changes
 
 - Exposed `CXRewriter` API as `class Rewriter`.
 
+OpenMP Support
+--------------
+
+- Added support for the `[[omp::assume]]` attribute.
+
 Additional Information
 ======================
 
diff --git a/clang/docs/tools/dump_format_style.py b/clang/docs/tools/dump_format_style.py
index af0124b94ecaf1367616908460412640bfe8f193..af0e658fcdc55d0f305d2e2c6c92a11fdbab7bf0 100755
--- a/clang/docs/tools/dump_format_style.py
+++ b/clang/docs/tools/dump_format_style.py
@@ -129,6 +129,7 @@ class Option(object):
             s += indent(
                 "\n\nNested configuration flags:\n\n%s\n" % self.nested_struct, 2
             )
+            s = s.replace("", self.name)
         return s
 
 
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 61117cc5ce71f9f4422e11a155e945acfd4d56f1..a5879591f4c65965b4ebd4b391c26f8e7fd6224c 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -4419,7 +4419,7 @@ public:
 ///
 /// \note This is used in libInterpreter, clang -cc1 -fincremental-extensions
 /// and in tools such as clang-repl.
-class TopLevelStmtDecl : public Decl {
+class TopLevelStmtDecl : public Decl, public DeclContext {
   friend class ASTDeclReader;
   friend class ASTDeclWriter;
 
@@ -4427,7 +4427,7 @@ class TopLevelStmtDecl : public Decl {
   bool IsSemiMissing = false;
 
   TopLevelStmtDecl(DeclContext *DC, SourceLocation L, Stmt *S)
-      : Decl(TopLevelStmt, DC, L), Statement(S) {}
+      : Decl(TopLevelStmt, DC, L), DeclContext(TopLevelStmt), Statement(S) {}
 
   virtual void anchor();
 
@@ -4438,15 +4438,19 @@ public:
   SourceRange getSourceRange() const override LLVM_READONLY;
   Stmt *getStmt() { return Statement; }
   const Stmt *getStmt() const { return Statement; }
-  void setStmt(Stmt *S) {
-    assert(IsSemiMissing && "Operation supported for printing values only!");
-    Statement = S;
-  }
+  void setStmt(Stmt *S);
   bool isSemiMissing() const { return IsSemiMissing; }
   void setSemiMissing(bool Missing = true) { IsSemiMissing = Missing; }
 
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) { return K == TopLevelStmt; }
+
+  static DeclContext *castToDeclContext(const TopLevelStmtDecl *D) {
+    return static_cast(const_cast(D));
+  }
+  static TopLevelStmtDecl *castFromDeclContext(const DeclContext *DC) {
+    return static_cast(const_cast(DC));
+  }
 };
 
 /// Represents a block literal declaration, which is like an
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 9a4736019d1b1b9d90a6aa8d5f9afa46003d7750..47ed6d0d1db0df804f55cdfca4c5c0ddd4868bb9 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -673,6 +673,16 @@ public:
   /// fragment. See [module.global.frag]p3,4 for details.
   bool isDiscardedInGlobalModuleFragment() const { return false; }
 
+  /// Check if we should skip checking ODRHash for declaration \param D.
+  ///
+  /// The existing ODRHash mechanism seems to be not stable enough and
+  /// the false positive ODR violation reports are annoying and we rarely see
+  /// true ODR violation reports. Also we learned that MSVC disabled ODR checks
+  /// for declarations in GMF. So we try to disable ODR checks in the GMF to
+  /// get better user experiences before we make the ODR violation checks stable
+  /// enough.
+  bool shouldSkipCheckingODR() const;
+
   /// Return true if this declaration has an attribute which acts as
   /// definition of the entity, such as 'alias' or 'ifunc'.
   bool hasDefiningAttr() const;
@@ -2120,6 +2130,7 @@ public:
     case Decl::Block:
     case Decl::Captured:
     case Decl::ObjCMethod:
+    case Decl::TopLevelStmt:
       return true;
     default:
       return getDeclKind() >= Decl::firstFunction &&
diff --git a/clang/include/clang/AST/DeclOpenMP.h b/clang/include/clang/AST/DeclOpenMP.h
index 73725e6e85666a04398409fbd44d6e57e504691a..8fdfddb6c1fd74bf2ddc3b852b0e28679b286926 100644
--- a/clang/include/clang/AST/DeclOpenMP.h
+++ b/clang/include/clang/AST/DeclOpenMP.h
@@ -1,4 +1,4 @@
-//===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-===//
+//===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-==//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index bf0622bdeca30e2240651f7ad9478bfbd16e54a5..446bec4081e86908b337ae17bdaf0c9ac6340815 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -1875,6 +1875,17 @@ public:
     llvm_unreachable("Unsupported character width!");
   }
 
+  // Get code unit but preserve sign info.
+  int64_t getCodeUnitS(size_t I, uint64_t BitWidth) const {
+    int64_t V = getCodeUnit(I);
+    if (isOrdinary() || isWide()) {
+      unsigned Width = getCharByteWidth() * BitWidth;
+      llvm::APInt AInt(Width, (uint64_t)V);
+      V = AInt.getSExtValue();
+    }
+    return V;
+  }
+
   unsigned getByteLength() const { return getCharByteWidth() * getLength(); }
   unsigned getLength() const { return *getTrailingObjects(); }
   unsigned getCharByteWidth() const { return StringLiteralBits.CharByteWidth; }
@@ -5832,7 +5843,7 @@ class GenericSelectionExpr final
         std::conditional_t;
     using TSIPtrPtrTy = std::conditional_t;
-    StmtPtrPtrTy E; // = nullptr; FIXME: Once support for gcc 4.8 is dropped.
+    StmtPtrPtrTy E = nullptr;
     TSIPtrPtrTy TSI; // Kept in sync with E.
     unsigned Offset = 0, SelectedOffset = 0;
     AssociationIteratorTy(StmtPtrPtrTy E, TSIPtrPtrTy TSI, unsigned Offset,
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index a0e467b35778c5c5f2b7a358ebb95c243ce9f86a..6003b866c9f564519006077b3618fc324bd09bef 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -5038,6 +5038,9 @@ class CoroutineSuspendExpr : public Expr {
   OpaqueValueExpr *OpaqueValue = nullptr;
 
 public:
+  // These types correspond to the three C++ 'await_suspend' return variants
+  enum class SuspendReturnType { SuspendVoid, SuspendBool, SuspendHandle };
+
   CoroutineSuspendExpr(StmtClass SC, SourceLocation KeywordLoc, Expr *Operand,
                        Expr *Common, Expr *Ready, Expr *Suspend, Expr *Resume,
                        OpaqueValueExpr *OpaqueValue)
@@ -5097,6 +5100,24 @@ public:
     return static_cast(SubExprs[SubExpr::Operand]);
   }
 
+  SuspendReturnType getSuspendReturnType() const {
+    auto *SuspendExpr = getSuspendExpr();
+    assert(SuspendExpr);
+
+    auto SuspendType = SuspendExpr->getType();
+
+    if (SuspendType->isVoidType())
+      return SuspendReturnType::SuspendVoid;
+    if (SuspendType->isBooleanType())
+      return SuspendReturnType::SuspendBool;
+
+    // Void pointer is the type of handle.address(), which is returned
+    // from the await suspend wrapper so that the temporary coroutine handle
+    // value won't go to the frame by mistake
+    assert(SuspendType->isVoidPointerType());
+    return SuspendReturnType::SuspendHandle;
+  }
+
   SourceLocation getKeywordLoc() const { return KeywordLoc; }
 
   SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; }
diff --git a/clang/include/clang/AST/ParentMapContext.h b/clang/include/clang/AST/ParentMapContext.h
index d3b2e3986a993554327c1cab5302983d0a86dbf0..6f79038627d9e1704a4d77a13d934beab1de5138 100644
--- a/clang/include/clang/AST/ParentMapContext.h
+++ b/clang/include/clang/AST/ParentMapContext.h
@@ -1,4 +1,4 @@
-//===- ParentMapContext.h - Map of parents using DynTypedNode -------*- C++ -*-===//
+//===- ParentMapContext.h - Map of parents using DynTypedNode ---*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index ced89ff127ab3ec25ff512c428ac74d4473bc944..96dbcdc344e131acadb629276434854a011d92df 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -6366,6 +6366,25 @@ AST_MATCHER(CXXMethodDecl, isConst) {
   return Node.isConst();
 }
 
+/// Matches if the given method declaration declares a member function with an
+/// explicit object parameter.
+///
+/// Given
+/// \code
+/// struct A {
+///  int operator-(this A, int);
+///  void fun(this A &&self);
+///  static int operator()(int);
+///  int operator+(int);
+/// };
+/// \endcode
+///
+/// cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two
+/// methods but not the last two.
+AST_MATCHER(CXXMethodDecl, isExplicitObjectMemberFunction) {
+  return Node.isExplicitObjectMemberFunction();
+}
+
 /// Matches if the given method declaration declares a copy assignment
 /// operator.
 ///
diff --git a/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h b/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h
index 405e93287a05d38357891438f3eab01323968f0c..9a0a00f3c0134303d1b30e5a703db15204f03817 100644
--- a/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h
+++ b/clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h
@@ -58,19 +58,36 @@ public:
     return BlockReachable[B.getBlockID()];
   }
 
+  /// Returns whether `B` contains an expression that is consumed in a
+  /// different block than `B` (i.e. the parent of the expression is in a
+  /// different block).
+  /// This happens if there is control flow within a full-expression (triggered
+  /// by `&&`, `||`, or the conditional operator). Note that the operands of
+  /// these operators are not the only expressions that can be consumed in a
+  /// different block. For example, in the function call
+  /// `f(&i, cond() ? 1 : 0)`, `&i` is in a different block than the `CallExpr`.
+  bool containsExprConsumedInDifferentBlock(const CFGBlock &B) const {
+    return ContainsExprConsumedInDifferentBlock.contains(&B);
+  }
+
 private:
-  ControlFlowContext(const Decl &D, std::unique_ptr Cfg,
-                     llvm::DenseMap StmtToBlock,
-                     llvm::BitVector BlockReachable)
+  ControlFlowContext(
+      const Decl &D, std::unique_ptr Cfg,
+      llvm::DenseMap StmtToBlock,
+      llvm::BitVector BlockReachable,
+      llvm::DenseSet ContainsExprConsumedInDifferentBlock)
       : ContainingDecl(D), Cfg(std::move(Cfg)),
         StmtToBlock(std::move(StmtToBlock)),
-        BlockReachable(std::move(BlockReachable)) {}
+        BlockReachable(std::move(BlockReachable)),
+        ContainsExprConsumedInDifferentBlock(
+            std::move(ContainsExprConsumedInDifferentBlock)) {}
 
   /// The `Decl` containing the statement used to construct the CFG.
   const Decl &ContainingDecl;
   std::unique_ptr Cfg;
   llvm::DenseMap StmtToBlock;
   llvm::BitVector BlockReachable;
+  llvm::DenseSet ContainsExprConsumedInDifferentBlock;
 };
 
 } // namespace dataflow
diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index 62e7af7ac219bc2e5a7ddd19504f57dfd3ad1b8b..2330697299fdd7aaffe728dae049c33cb5efdf9f 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -210,6 +210,14 @@ public:
   bool equivalentTo(const Environment &Other,
                     Environment::ValueModel &Model) const;
 
+  /// How to treat expression state (`ExprToLoc` and `ExprToVal`) in a join.
+  /// If the join happens within a full expression, expression state should be
+  /// kept; otherwise, we can discard it.
+  enum ExprJoinBehavior {
+    DiscardExprState,
+    KeepExprState,
+  };
+
   /// Joins two environments by taking the intersection of storage locations and
   /// values that are stored in them. Distinct values that are assigned to the
   /// same storage locations in `EnvA` and `EnvB` are merged using `Model`.
@@ -218,7 +226,8 @@ public:
   ///
   ///  `EnvA` and `EnvB` must use the same `DataflowAnalysisContext`.
   static Environment join(const Environment &EnvA, const Environment &EnvB,
-                          Environment::ValueModel &Model);
+                          Environment::ValueModel &Model,
+                          ExprJoinBehavior ExprBehavior);
 
   /// Widens the environment point-wise, using `PrevEnv` as needed to inform the
   /// approximation.
@@ -436,6 +445,11 @@ public:
     return createObjectInternal(&D, D.getType(), InitExpr);
   }
 
+  /// Initializes the fields (including synthetic fields) of `Loc` with values,
+  /// unless values of the field type are not supported or we hit one of the
+  /// limits at which we stop producing values.
+  void initializeFieldsWithValues(RecordStorageLocation &Loc);
+
   /// Assigns `Val` as the value of `Loc` in the environment.
   void setValue(const StorageLocation &Loc, Value &Val);
 
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index fa191c7378dba4445265402ee8988645d47da86d..080340669b60a04bbb38d33671a7e8d18594c57b 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -983,6 +983,8 @@ def Availability : InheritableAttr {
              .Case("watchos_app_extension", "watchOS (App Extension)")
              .Case("maccatalyst", "macCatalyst")
              .Case("maccatalyst_app_extension", "macCatalyst (App Extension)")
+             .Case("xros", "visionOS")
+             .Case("xros_app_extension", "visionOS (App Extension)")
              .Case("swift", "Swift")
              .Case("shadermodel", "HLSL ShaderModel")
              .Case("ohos", "OpenHarmony OS")
@@ -1000,6 +1002,8 @@ static llvm::StringRef getPlatformNameSourceSpelling(llvm::StringRef Platform) {
              .Case("watchos_app_extension", "watchOSApplicationExtension")
              .Case("maccatalyst", "macCatalyst")
              .Case("maccatalyst_app_extension", "macCatalystApplicationExtension")
+             .Case("xros", "visionOS")
+             .Case("xros_app_extension", "visionOSApplicationExtension")
              .Case("zos", "z/OS")
              .Case("shadermodel", "ShaderModel")
              .Default(Platform);
@@ -1016,6 +1020,10 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) {
              .Case("watchOSApplicationExtension", "watchos_app_extension")
              .Case("macCatalyst", "maccatalyst")
              .Case("macCatalystApplicationExtension", "maccatalyst_app_extension")
+             .Case("visionOS", "xros")
+             .Case("visionOSApplicationExtension", "xros_app_extension")
+             .Case("visionos", "xros")
+             .Case("visionos_app_extension", "xros_app_extension")
              .Case("ShaderModel", "shadermodel")
              .Default(Platform);
 } }];
@@ -1572,6 +1580,13 @@ def Unlikely : StmtAttr {
 }
 def : MutualExclusions<[Likely, Unlikely]>;
 
+def CXXAssume : StmtAttr {
+  let Spellings = [CXX11<"", "assume", 202207>];
+  let Subjects = SubjectList<[NullStmt], ErrorDiag, "empty statements">;
+  let Args = [ExprArgument<"Assumption">];
+  let Documentation = [CXXAssumeDocs];
+}
+
 def NoMerge : DeclOrStmtAttr {
   let Spellings = [Clang<"nomerge">];
   let Documentation = [NoMergeDocs];
@@ -4143,11 +4158,11 @@ def OMPDeclareVariant : InheritableAttr {
   }];
 }
 
-def Assumption : InheritableAttr {
-  let Spellings = [Clang<"assume">];
+def OMPAssume : InheritableAttr {
+  let Spellings = [Clang<"assume">, CXX11<"omp", "assume">];
   let Subjects = SubjectList<[Function, ObjCMethod]>;
   let InheritEvenIfAlreadyPresent = 1;
-  let Documentation = [AssumptionDocs];
+  let Documentation = [OMPAssumeDocs];
   let Args = [StringArgument<"Assumption">];
 }
 
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index b96fbddd51154ca7c7b87390a0ea27911e0df3d6..2c07cd09b0d5b71727d4fd6f3bc421ef6cbe6256 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -1996,6 +1996,34 @@ Here is an example:
   }];
 }
 
+def CXXAssumeDocs : Documentation {
+  let Category = DocCatStmt;
+  let Heading = "assume";
+  let Content = [{
+The ``assume`` attribute is used to indicate to the optimizer that a
+certain condition is assumed to be true at a certain point in the
+program. If this condition is violated at runtime, the behavior is
+undefined. ``assume`` can only be applied to a null statement.
+
+Different optimisers are likely to react differently to the presence of
+this attribute; in some cases, adding ``assume`` may affect performance
+negatively. It should be used with parsimony and care.
+
+Note that `clang::assume` is a different attribute. Always write ``assume``
+without a namespace if you intend to use the standard C++ attribute.
+
+Example:
+
+.. code-block:: c++
+
+  int f(int x, int y) {
+    [[assume(x == 27)]];
+    [[assume(x == y)]];
+    return y + 1; // May be optimised to `return 28`.
+  }
+  }];
+}
+
 def LikelihoodDocs : Documentation {
   let Category = DocCatStmt;
   let Heading = "likely and unlikely";
@@ -4629,7 +4657,7 @@ For more information see
 }];
 }
 
-def AssumptionDocs : Documentation {
+def OMPAssumeDocs : Documentation {
   let Category = DocCatFunction;
   let Heading = "assume";
   let Content = [{
diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
deleted file mode 100644
index f356f881d5ef9bc2e2a13f806d40e0ab8a93c283..0000000000000000000000000000000000000000
--- a/clang/include/clang/Basic/Builtins.def
+++ /dev/null
@@ -1,102 +0,0 @@
-//===--- Builtins.def - Builtin function info database ----------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-// This is only documentation for the database layout. This will be removed once
-// all builtin databases are converted to tablegen files
-
-// The second value provided to the macro specifies the type of the function
-// (result value, then each argument) as follows:
-//  v -> void
-//  b -> boolean
-//  c -> char
-//  s -> short
-//  i -> int
-//  h -> half (__fp16, OpenCL)
-//  x -> half (_Float16)
-//  y -> half (__bf16)
-//  f -> float
-//  d -> double
-//  z -> size_t
-//  w -> wchar_t
-//  F -> constant CFString
-//  G -> id
-//  H -> SEL
-//  M -> struct objc_super
-//  a -> __builtin_va_list
-//  A -> "reference" to __builtin_va_list
-//  V -> Vector, followed by the number of elements and the base type.
-//  q -> Scalable vector, followed by the number of elements and the base type.
-//  Q -> target builtin type, followed by a character to distinguish the builtin type
-//    Qa -> AArch64 svcount_t builtin type.
-//  E -> ext_vector, followed by the number of elements and the base type.
-//  X -> _Complex, followed by the base type.
-//  Y -> ptrdiff_t
-//  P -> FILE
-//  J -> jmp_buf
-//  SJ -> sigjmp_buf
-//  K -> ucontext_t
-//  p -> pid_t
-//  . -> "...".  This may only occur at the end of the function list.
-//
-// Types may be prefixed with the following modifiers:
-//  L   -> long (e.g. Li for 'long int', Ld for 'long double')
-//  LL  -> long long (e.g. LLi for 'long long int', LLd for __float128)
-//  LLL -> __int128_t (e.g. LLLi)
-//  Z   -> int32_t (require a native 32-bit integer type on the target)
-//  W   -> int64_t (require a native 64-bit integer type on the target)
-//  N   -> 'int' size if target is LP64, 'L' otherwise.
-//  O   -> long for OpenCL targets, long long otherwise.
-//  S   -> signed
-//  U   -> unsigned
-//  I   -> Required to constant fold to an integer constant expression.
-//
-// Types may be postfixed with the following modifiers:
-// * -> pointer (optionally followed by an address space number, if no address
-//               space is specified than any address space will be accepted)
-// & -> reference (optionally followed by an address space number)
-// C -> const
-// D -> volatile
-// R -> restrict
-
-// The third value provided to the macro specifies information about attributes
-// of the function.  These must be kept in sync with the predicates in the
-// Builtin::Context class.  Currently we have:
-//  n -> nothrow
-//  r -> noreturn
-//  U -> pure
-//  c -> const
-//  t -> signature is meaningless, use custom typechecking
-//  T -> type is not important to semantic analysis and codegen; recognize as
-//       builtin even if type doesn't match signature, and don't warn if we
-//       can't be sure the type is right
-//  F -> this is a libc/libm function with a '__builtin_' prefix added.
-//  f -> this is a libc/libm function without a '__builtin_' prefix, or with
-//       'z', a C++ standard library function in namespace std::. This builtin
-//       is disableable by '-fno-builtin-foo' / '-fno-builtin-std-foo'.
-//  h -> this function requires a specific header or an explicit declaration.
-//  i -> this is a runtime library implemented function without the
-//       '__builtin_' prefix. It will be implemented in compiler-rt or libgcc.
-//  p:N: -> this is a printf-like function whose Nth argument is the format
-//          string.
-//  P:N: -> similar to the p:N: attribute, but the function is like vprintf
-//          in that it accepts its arguments as a va_list rather than
-//          through an ellipsis
-//  s:N: -> this is a scanf-like function whose Nth argument is the format
-//          string.
-//  S:N: -> similar to the s:N: attribute, but the function is like vscanf
-//          in that it accepts its arguments as a va_list rather than
-//          through an ellipsis
-//  e -> const, but only when -fno-math-errno and FP exceptions are ignored
-//  g -> const when FP exceptions are ignored
-//  j -> returns_twice (like setjmp)
-//  u -> arguments are not evaluated for their side-effects
-//  V:N: -> requires vectors of at least N bits to be legal
-//  C -> callback behavior: argument N is called with argument
-//                      M_0, ..., M_k as payload
-//  z -> this is a function in (possibly-versioned) namespace std
-//  E -> this function can be constant evaluated by Clang frontend
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 2c83dca248fb7d52d2021de31fd6d010ac8551f6..9c703377ca8d3e8d5bf47a6dd4ee3ad7fe4e7d97 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -12,13 +12,17 @@ class FPMathTemplate : Template<["float", "double", "long double"],
                                 ["f",     "",       "l"]>;
 
 class FPMathWithF16Template :
-    Template<["float", "double", "long double", "__fp16", "__float128"],
-             ["f",     "",       "l",           "f16",    "f128"]>;
+    Template<["float", "double", "long double", "__fp16"],
+             ["f",     "",       "l",           "f16"]>;
 
 class FPMathWithF16F128Template :
     Template<["float", "double", "long double", "__fp16", "__float128"],
              ["f",     "",       "l",           "f16",    "f128"]>;
 
+class FPMathWithF128Template :
+    Template<["float", "double", "long double", "__float128"],
+             ["f",     "",       "l",           "f128"]>;
+
 class F16F128MathTemplate : Template<["__fp16", "__float128"],
                                      ["f16",    "f128"]>;
 
@@ -253,18 +257,30 @@ def FrexpF16F128 : F16F128MathTemplate, Builtin {
   let Prototype = "T(T, int*)";
 }
 
-def HugeVal : Builtin, FPMathWithF16F128Template {
+def HugeVal : Builtin, FPMathWithF128Template {
   let Spellings = ["__builtin_huge_val"];
   let Attributes = [NoThrow, Const, Constexpr];
   let Prototype = "T()";
 }
 
-def Inf : Builtin, FPMathWithF16F128Template {
+def HugeValF16 : Builtin {
+       let Spellings = ["__builtin_huge_valf16"];
+  let Attributes = [NoThrow, Const, Constexpr];
+  let Prototype = "_Float16()";
+}
+
+def Inf : Builtin, FPMathWithF128Template {
   let Spellings = ["__builtin_inf"];
   let Attributes = [NoThrow, Const, Constexpr];
   let Prototype = "T()";
 }
 
+def InfF16 : Builtin {
+  let Spellings = ["__builtin_inff16"];
+  let Attributes = [NoThrow, Const, Constexpr];
+  let Prototype = "_Float16()";
+}
+
 def LdexpF16F128 : F16F128MathTemplate, Builtin {
   let Spellings = ["__builtin_ldexp"];
   let Attributes = [FunctionWithBuiltinPrefix, NoThrow, ConstIgnoringErrnoAndExceptions];
@@ -690,7 +706,7 @@ def Popcount : Builtin, BitInt_Long_LongLongTemplate {
 
 def Popcountg : Builtin {
   let Spellings = ["__builtin_popcountg"];
-  let Attributes = [NoThrow, Const, CustomTypeChecking];
+  let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
   let Prototype = "int(...)";
 }
 
@@ -1550,7 +1566,7 @@ def SyncBoolCompareAndSwap : Builtin {
 def SyncBoolCompareAndSwapN : Builtin, SyncBuiltinsTemplate {
   let Spellings = ["__sync_bool_compare_and_swap_"];
   let Attributes = [CustomTypeChecking, NoThrow];
-  let Prototype = "T(T volatile*, T, ...)";
+  let Prototype = "bool(T volatile*, T, T, ...)";
 }
 
 def SyncValCompareAndSwap : Builtin {
@@ -1562,7 +1578,7 @@ def SyncValCompareAndSwap : Builtin {
 def SynLockValCompareAndSwapN : Builtin, SyncBuiltinsTemplate {
   let Spellings = ["__sync_val_compare_and_swap_"];
   let Attributes = [CustomTypeChecking, NoThrow];
-  let Prototype = "T(T volatile*, T, ...)";
+  let Prototype = "T(T volatile*, T, T, ...)";
 }
 
 def SyncLockTestAndSet : Builtin {
@@ -1577,16 +1593,16 @@ def SynLockLockTestAndSetN : Builtin, SyncBuiltinsTemplate {
   let Prototype = "T(T volatile*, T, ...)";
 }
 
-def SyncLockReleaseN : Builtin {
+def SyncLockRelease : Builtin {
   let Spellings = ["__sync_lock_release"];
   let Attributes = [CustomTypeChecking];
   let Prototype = "void(...)";
 }
 
-def SynLockReleaseN : Builtin, SyncBuiltinsTemplate {
+def SyncLockReleaseN : Builtin, SyncBuiltinsTemplate {
   let Spellings = ["__sync_lock_release_"];
   let Attributes = [CustomTypeChecking, NoThrow];
-  let Prototype = "T(T volatile*, T, ...)";
+  let Prototype = "void(T volatile*, ...)";
 }
 
 def SyncSwap : Builtin {
@@ -2569,6 +2585,13 @@ def Abort : LibBuiltin<"stdlib.h"> {
   let AddBuiltinPrefixedAlias = 1;
 }
 
+def Abs : IntMathTemplate, LibBuiltin<"stdlib.h"> {
+  let Spellings = ["abs"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "T(T)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
 def Calloc : LibBuiltin<"stdlib.h"> {
   let Spellings = ["calloc"];
   let Prototype = "void*(size_t, size_t)";
@@ -3085,38 +3108,38 @@ def MemAlign : GNULibBuiltin<"malloc.h"> {
 
 // POSIX string.h
 
-def MemcCpy : GNULibBuiltin<"stdlib.h"> {
+def MemcCpy : GNULibBuiltin<"string.h"> {
   let Spellings = ["memccpy"];
   let Prototype = "void*(void*, void const*, int, size_t)";
 }
 
-def MempCpy : GNULibBuiltin<"stdlib.h"> {
+def MempCpy : GNULibBuiltin<"string.h"> {
   let Spellings = ["mempcpy"];
   let Prototype = "void*(void*, void const*, size_t)";
 }
 
-def StpCpy : GNULibBuiltin<"stdlib.h"> {
+def StpCpy : GNULibBuiltin<"string.h"> {
   let Spellings = ["stpcpy"];
   let Attributes = [NoThrow];
   let Prototype = "char*(char*, char const*)";
   let AddBuiltinPrefixedAlias = 1;
 }
 
-def StpnCpy : GNULibBuiltin<"stdlib.h"> {
+def StpnCpy : GNULibBuiltin<"string.h"> {
   let Spellings = ["stpncpy"];
   let Attributes = [NoThrow];
   let Prototype = "char*(char*, char const*, size_t)";
   let AddBuiltinPrefixedAlias = 1;
 }
 
-def StrDup : GNULibBuiltin<"stdlib.h"> {
+def StrDup : GNULibBuiltin<"string.h"> {
   let Spellings = ["strdup"];
   let Attributes = [NoThrow];
   let Prototype = "char*(char const*)";
   let AddBuiltinPrefixedAlias = 1;
 }
 
-def StrnDup : GNULibBuiltin<"stdlib.h"> {
+def StrnDup : GNULibBuiltin<"string.h"> {
   let Spellings = ["strndup"];
   let Attributes = [NoThrow];
   let Prototype = "char*(char const*, size_t)";
@@ -3286,22 +3309,22 @@ def ObjcEnumerationMutation : ObjCLibBuiltin<"objc/runtime.h"> {
   let Prototype = "void(id)";
 }
 
-def ObjcReadWeak : ObjCLibBuiltin<"objc/message.h"> {
+def ObjcReadWeak : ObjCLibBuiltin<"objc/objc-auto.h"> {
   let Spellings = ["objc_read_weak"];
   let Prototype = "id(id*)";
 }
 
-def ObjcAssignWeak : ObjCLibBuiltin<"objc/message.h"> {
+def ObjcAssignWeak : ObjCLibBuiltin<"objc/objc-auto.h"> {
   let Spellings = ["objc_assign_weak"];
   let Prototype = "id(id, id*)";
 }
 
-def ObjcAssignIvar : ObjCLibBuiltin<"objc/message.h"> {
+def ObjcAssignIvar : ObjCLibBuiltin<"objc/objc-auto.h"> {
   let Spellings = ["objc_assign_ivar"];
   let Prototype = "id(id, id, ptrdiff_t)";
 }
 
-def ObjcAssignGlobal : ObjCLibBuiltin<"objc/message.h"> {
+def ObjcAssignGlobal : ObjCLibBuiltin<"objc/objc-auto.h"> {
   let Spellings = ["objc_assign_global"];
   let Prototype = "id(id, id*)";
 }
@@ -3371,13 +3394,6 @@ def Atan2 : FPMathTemplate, LibBuiltin<"math.h"> {
   let AddBuiltinPrefixedAlias = 1;
 }
 
-def Abs : IntMathTemplate, LibBuiltin<"math.h"> {
-  let Spellings = ["abs"];
-  let Attributes = [NoThrow, Const];
-  let Prototype = "T(T)";
-  let AddBuiltinPrefixedAlias = 1;
-}
-
 def Copysign : FPMathTemplate, LibBuiltin<"math.h"> {
   let Spellings = ["copysign"];
   let Attributes = [NoThrow, Const];
@@ -3996,8 +4012,16 @@ def BlockObjectDispose : LibBuiltin<"blocks.h"> {
 }
 // FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock.
 
+def __Addressof : LangBuiltin<"CXX_LANG"> {
+  let Spellings = ["__addressof"];
+  let Attributes = [FunctionWithoutBuiltinPrefix, NoThrow, Const,
+                    IgnoreSignature, Constexpr];
+  let Prototype = "void*(void&)";
+  let Namespace = "std";
+}
+
 def Addressof : CxxLibBuiltin<"memory"> {
-  let Spellings = ["addressof", "__addressof"];
+  let Spellings = ["addressof"];
   let Attributes = [NoThrow, Const, IgnoreSignature, RequireDeclaration,
                     Constexpr];
   let Prototype = "void*(void&)";
@@ -4036,7 +4060,7 @@ def Move : CxxLibBuiltin<"utility"> {
   let Namespace = "std";
 }
 
-def MoveIfNsoexcept : CxxLibBuiltin<"memory"> {
+def MoveIfNsoexcept : CxxLibBuiltin<"utility"> {
   let Spellings = ["move_if_noexcept"];
   let Attributes = [NoThrow, Const, IgnoreSignature, RequireDeclaration,
                     Constexpr];
@@ -4518,6 +4542,12 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> {
 }
 
 // HLSL
+def HLSLAny : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_any"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(...)";
+}
+
 def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
   let Attributes = [NoThrow, Const];
@@ -4548,6 +4578,18 @@ def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLMad : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_mad"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
+def HLSLRcp : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_rcp"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 // Builtins for XRay.
 def XRayCustomEvent : Builtin {
   let Spellings = ["__xray_customevent"];
diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def
index 213311b96df74f0872ad1e3bf2224906cdca8582..61ec8b79bf054daa03e02fddca3c4edb2da75088 100644
--- a/clang/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def
@@ -256,10 +256,10 @@ TARGET_BUILTIN(__builtin_amdgcn_sudot4, "iIbiIbiiIb", "nc", "dot8-insts")
 TARGET_BUILTIN(__builtin_amdgcn_sdot8, "SiSiSiSiIb", "nc", "dot1-insts")
 TARGET_BUILTIN(__builtin_amdgcn_udot8, "UiUiUiUiIb", "nc", "dot7-insts")
 TARGET_BUILTIN(__builtin_amdgcn_sudot8, "iIbiIbiiIb", "nc", "dot8-insts")
-TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_fp8_bf8, "fUiUif", "nc", "gfx12-insts")
-TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_bf8_fp8, "fUiUif", "nc", "gfx12-insts")
-TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_fp8_fp8, "fUiUif", "nc", "gfx12-insts")
-TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_bf8_bf8, "fUiUif", "nc", "gfx12-insts")
+TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_fp8_bf8, "fUiUif", "nc", "dot11-insts")
+TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_bf8_fp8, "fUiUif", "nc", "dot11-insts")
+TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_fp8_fp8, "fUiUif", "nc", "dot11-insts")
+TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_bf8_bf8, "fUiUif", "nc", "dot11-insts")
 
 //===----------------------------------------------------------------------===//
 // GFX10+ only builtins.
@@ -325,6 +325,9 @@ BUILTIN(__builtin_amdgcn_read_exec_hi, "Ui", "nc")
 
 BUILTIN(__builtin_amdgcn_endpgm, "v", "nr")
 
+BUILTIN(__builtin_amdgcn_get_fpenv, "WUi", "n")
+BUILTIN(__builtin_amdgcn_set_fpenv, "vWUi", "n")
+
 //===----------------------------------------------------------------------===//
 // R600-NI only builtins.
 //===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/Basic/BuiltinsBase.td b/clang/include/clang/Basic/BuiltinsBase.td
index bfccff5600ddb378347a0f07de23b812a36e8a2e..724747ec76d732e6e0b1be86e070bcebb964c664 100644
--- a/clang/include/clang/Basic/BuiltinsBase.td
+++ b/clang/include/clang/Basic/BuiltinsBase.td
@@ -49,6 +49,8 @@ def UnevaluatedArguments : Attribute<"u">;
 // is required for a builtin.
 def FunctionWithBuiltinPrefix : Attribute<"F">;
 
+def FunctionWithoutBuiltinPrefix : Attribute<"f">;
+
 // const, but only when -fno-math-errno and FP exceptions are ignored.
 def ConstIgnoringErrnoAndExceptions : Attribute<"e">;
 
diff --git a/clang/include/clang/Basic/BuiltinsX86.def b/clang/include/clang/Basic/BuiltinsX86.def
index 207cde0414b54e41ba88a20f82c879e8bcbae315..eafcc219c10966b8789182c486fb950c426c9e1d 100644
--- a/clang/include/clang/Basic/BuiltinsX86.def
+++ b/clang/include/clang/Basic/BuiltinsX86.def
@@ -226,6 +226,8 @@ TARGET_BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "ncV:128:", "sse")
 TARGET_BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "ncV:128:", "sse")
 TARGET_BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "ncV:128:", "sse")
 TARGET_BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "ncV:128:", "sse")
+TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "ncV:128:", "sse")
 
 TARGET_BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "ncV:128:", "sse2")
 TARGET_BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "ncV:128:", "sse2")
@@ -243,6 +245,8 @@ TARGET_BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "ncV:128:", "sse2")
 TARGET_BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "ncV:128:", "sse2")
 TARGET_BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "ncV:128:", "sse2")
 TARGET_BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "ncV:128:", "sse2")
+TARGET_BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "ncV:128:", "sse2")
 TARGET_BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "ncV:128:", "sse2")
 TARGET_BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "ncV:128:", "sse2")
 TARGET_BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "ncV:128:", "sse2")
@@ -462,12 +466,8 @@ TARGET_BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "ncV:256:", "avx")
 TARGET_BUILTIN(__builtin_ia32_shufpd256, "V4dV4dV4dIi", "ncV:256:", "avx")
 TARGET_BUILTIN(__builtin_ia32_shufps256, "V8fV8fV8fIi", "ncV:256:", "avx")
 TARGET_BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "ncV:256:", "avx")
-TARGET_BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "ncV:128:", "avx")
 TARGET_BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "ncV:256:", "avx")
-TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "ncV:128:", "avx")
 TARGET_BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "ncV:256:", "avx")
-TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "ncV:128:", "avx")
-TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "ncV:128:", "avx")
 TARGET_BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dIi", "ncV:256:", "avx")
 TARGET_BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fIi", "ncV:256:", "avx")
 TARGET_BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8iIi", "ncV:256:", "avx")
diff --git a/clang/include/clang/Basic/Cuda.h b/clang/include/clang/Basic/Cuda.h
index 916cb4b7ef34a7eeb65286c35c5c0f34d51f2091..3e77a74c7c0092239c2f9235de9c43b532423ab3 100644
--- a/clang/include/clang/Basic/Cuda.h
+++ b/clang/include/clang/Basic/Cuda.h
@@ -123,7 +123,7 @@ enum class CudaArch {
   LAST,
 
   CudaDefault = CudaArch::SM_52,
-  HIPDefault = CudaArch::GFX803,
+  HIPDefault = CudaArch::GFX906,
 };
 
 static inline bool IsNVIDIAGpuArch(CudaArch A) {
diff --git a/clang/include/clang/Basic/DarwinSDKInfo.h b/clang/include/clang/Basic/DarwinSDKInfo.h
index dedfbd934a7b63725ed1beb66a87b0704eda53fb..db20b968a898ea13167008cc891c338477726c97 100644
--- a/clang/include/clang/Basic/DarwinSDKInfo.h
+++ b/clang/include/clang/Basic/DarwinSDKInfo.h
@@ -105,6 +105,30 @@ public:
     map(const VersionTuple &Key, const VersionTuple &MinimumValue,
         std::optional MaximumValue) const;
 
+    /// Remap the 'introduced' availability version.
+    /// If None is returned, the 'unavailable' availability should be used
+    /// instead.
+    std::optional
+    mapIntroducedAvailabilityVersion(const VersionTuple &Key) const {
+      // API_TO_BE_DEPRECATED is 100000.
+      if (Key.getMajor() == 100000)
+        return VersionTuple(100000);
+      // Use None for maximum to force unavailable behavior for
+      return map(Key, MinimumValue, std::nullopt);
+    }
+
+    /// Remap the 'deprecated' and 'obsoleted' availability version.
+    /// If None is returned for 'obsoleted', the 'unavailable' availability
+    /// should be used instead. If None is returned for 'deprecated', the
+    /// 'deprecated' version should be dropped.
+    std::optional
+    mapDeprecatedObsoletedAvailabilityVersion(const VersionTuple &Key) const {
+      // API_TO_BE_DEPRECATED is 100000.
+      if (Key.getMajor() == 100000)
+        return VersionTuple(100000);
+      return map(Key, MinimumValue, MaximumValue);
+    }
+
     static std::optional
     parseJSON(const llvm::json::Object &Obj,
               VersionTuple MaximumDeploymentTarget);
diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td
index 8b1f415dd5fe2cbda4ed5c8cb598b1d301f0f4bb..48396e85c5adac331f5d270d8d0a8b0daca371bd 100644
--- a/clang/include/clang/Basic/DeclNodes.td
+++ b/clang/include/clang/Basic/DeclNodes.td
@@ -95,7 +95,7 @@ def LinkageSpec : DeclNode, DeclContext;
 def Export : DeclNode, DeclContext;
 def ObjCPropertyImpl : DeclNode;
 def FileScopeAsm : DeclNode;
-def TopLevelStmt : DeclNode;
+def TopLevelStmt : DeclNode, DeclContext;
 def AccessSpec : DeclNode;
 def Friend : DeclNode;
 def FriendTemplate : DeclNode;
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td
index c81d17ed641084a8189d5f2147354b505b40bdd5..a024f9b2a9f8c0dea9fcb0a654e5027d24508632 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -399,6 +399,8 @@ def note_constexpr_unsupported_flexible_array : Note<
   "flexible array initialization is not yet supported">;
 def note_constexpr_non_const_vectorelements : Note<
   "cannot determine number of elements for sizeless vectors in a constant expression">;
+def note_constexpr_assumption_failed : Note<
+  "assumption evaluated to false">;
 def err_experimental_clang_interp_failed : Error<
   "the experimental clang interpreter failed to evaluate an expression">;
 
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index e8b4139d7893ce8e47fab9ab17aac86277add964..3f14167d6b84693a630622abc4bef061f7870b61 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -517,7 +517,15 @@ def MethodSignatures : DiagGroup<"method-signatures">;
 def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">;
 def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
 def MismatchedTags : DiagGroup<"mismatched-tags">;
-def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def MissingDesignatedFieldInitializers : DiagGroup<"missing-designated-field-initializers">{
+  code Documentation = [{
+Warn about designated initializers with some fields missing (only in C++).
+  }];
+}
+// Default -Wmissing-field-initializers matches gcc behavior,
+// but missing-designated-field-initializers can be turned off to match old clang behavior.
+def MissingFieldInitializers : DiagGroup<"missing-field-initializers",
+                                         [MissingDesignatedFieldInitializers]>;
 def ModuleLock : DiagGroup<"module-lock">;
 def ModuleBuild : DiagGroup<"module-build">;
 def ModuleImport : DiagGroup<"module-import">;
@@ -609,7 +617,9 @@ def GNURedeclaredEnum : DiagGroup<"gnu-redeclared-enum">;
 def RedundantMove : DiagGroup<"redundant-move">;
 def Register : DiagGroup<"register", [DeprecatedRegister]>;
 def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">;
-def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>;
+def ReturnMismatch : DiagGroup<"return-mismatch">;
+def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage, ReturnMismatch]>;
+
 def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy",
                                     [CXX98CompatBindToTemporaryCopy]>;
 def SelfAssignmentField : DiagGroup<"self-assign-field">;
@@ -1125,9 +1135,11 @@ def NonGCC : DiagGroup<"non-gcc",
 def CXX14Attrs : DiagGroup<"c++14-attribute-extensions">;
 def CXX17Attrs : DiagGroup<"c++17-attribute-extensions">;
 def CXX20Attrs : DiagGroup<"c++20-attribute-extensions">;
+def CXX23Attrs : DiagGroup<"c++23-attribute-extensions">;
 def FutureAttrs : DiagGroup<"future-attribute-extensions", [CXX14Attrs,
                                                             CXX17Attrs,
-                                                            CXX20Attrs]>;
+                                                            CXX20Attrs,
+                                                            CXX23Attrs]>;
 
 def CXX23AttrsOnLambda : DiagGroup<"c++23-lambda-attributes">;
 
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index c0dbc25a0c3265f121f297c0a3b2e8602f1826ba..816c3ff5f8b2aa5cb6c16118f7e6522f908423e9 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -786,6 +786,9 @@ def err_ms_property_expected_comma_or_rparen : Error<
 def err_ms_property_initializer : Error<
   "property declaration cannot have a default member initializer">;
 
+def err_assume_attr_expects_cond_expr : Error<
+  "use of this expression in an %0 attribute requires parentheses">;
+
 def warn_cxx20_compat_explicit_bool : Warning<
   "this expression will be parsed as explicit(bool) in C++20">,
   InGroup, DefaultIgnore;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8ea194ceadb5d1d920b93e17a5e963191adfde79..c54105507753eb4ab3c4c99542af02123ca6617c 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -855,10 +855,10 @@ def note_strncat_wrong_size : Note<
 def warn_assume_side_effects : Warning<
   "the argument to %0 has side effects that will be discarded">,
   InGroup>;
-def warn_assume_attribute_string_unknown : Warning<
+def warn_omp_assume_attribute_string_unknown : Warning<
   "unknown assumption string '%0'; attribute is potentially ignored">,
   InGroup;
-def warn_assume_attribute_string_unknown_suggested : Warning<
+def warn_omp_assume_attribute_string_unknown_suggested : Warning<
   "unknown assumption string '%0' may be misspelled; attribute is potentially "
   "ignored, did you mean '%1'?">,
   InGroup;
@@ -2515,10 +2515,11 @@ def err_deduced_class_template_compound_type : Error<
   "cannot %select{form pointer to|form reference to|form array of|"
   "form function returning|use parentheses when declaring variable with}0 "
   "deduced class template specialization type">;
-def err_deduced_non_class_template_specialization_type : Error<
+def err_deduced_non_class_or_alias_template_specialization_type : Error<
   "%select{|function template|variable template|alias template|"
   "template template parameter|concept|template}0 %1 requires template "
-  "arguments; argument deduction only allowed for class templates">;
+  "arguments; argument deduction only allowed for class templates or alias "
+  "templates">;
 def err_deduced_class_template_ctor_ambiguous : Error<
   "ambiguous deduction for template arguments of %0">;
 def err_deduced_class_template_ctor_no_viable : Error<
@@ -2946,6 +2947,18 @@ def warn_private_extern : Warning<
 def note_private_extern : Note<
   "use __attribute__((visibility(\"hidden\"))) attribute instead">;
 
+// C23 constexpr
+def err_c23_constexpr_not_variable : Error<
+  "'constexpr' can only be used in variable declarations">;
+def err_c23_constexpr_invalid_type : Error<
+  "constexpr variable cannot have type %0">;
+def err_c23_constexpr_init_not_representable : Error<
+  "constexpr initializer evaluates to %0 which is not exactly representable in type %1">;
+def err_c23_constexpr_init_type_mismatch : Error<
+  "constexpr initializer for type %0 is of type %1">;
+def err_c23_constexpr_pointer_not_null : Error<
+  "constexpr pointer initializer is not null">;
+
 // C++ Concepts
 def err_concept_decls_may_only_appear_in_global_namespace_scope : Error<
   "concept declarations may only appear in global or namespace scope">;
@@ -6170,6 +6183,10 @@ def ext_initializer_string_for_char_array_too_long : ExtWarn<
 def warn_missing_field_initializers : Warning<
   "missing field %0 initializer">,
   InGroup, DefaultIgnore;
+// The same warning, but another group is needed to disable it separately.
+def warn_missing_designated_field_initializers : Warning<
+  warn_missing_field_initializers.Summary>,
+  InGroup, DefaultIgnore;
 def warn_braces_around_init : Warning<
   "braces around %select{scalar |}0initializer">,
   InGroup>;
@@ -8154,6 +8171,8 @@ let CategoryName = "Lambda Issue" in {
   def warn_cxx11_compat_generic_lambda : Warning<
     "generic lambdas are incompatible with C++11">,
     InGroup, DefaultIgnore;
+  def err_lambda_explicit_spec : Error<
+    "lambda call operator should not be explicitly specialized or instantiated">;
 
   // C++17 '*this' captures.
   def warn_cxx14_compat_star_this_lambda_capture : Warning<
@@ -8183,6 +8202,11 @@ let CategoryName = "Lambda Issue" in {
   def warn_cxx17_compat_lambda_def_ctor_assign : Warning<
     "%select{default construction|assignment}0 of lambda is incompatible with "
     "C++ standards before C++20">, InGroup, DefaultIgnore;
+
+  // C++20 class template argument deduction for alias templates.
+  def warn_cxx17_compat_ctad_for_alias_templates : Warning<
+  "class template argument deduction for alias templates is incompatible with "
+  "C++ standards before C++20">, InGroup, DefaultIgnore;
 }
 
 def err_return_in_captured_stmt : Error<
@@ -9091,6 +9115,8 @@ def ext_cxx17_attr : Extension<
   "use of the %0 attribute is a C++17 extension">, InGroup;
 def ext_cxx20_attr : Extension<
   "use of the %0 attribute is a C++20 extension">, InGroup;
+def ext_cxx23_attr : Extension<
+  "use of the %0 attribute is a C++23 extension">, InGroup;
 
 def warn_unused_comparison : Warning<
   "%select{equality|inequality|relational|three-way}0 comparison result unused">,
@@ -9591,13 +9617,10 @@ def err_defaulted_copy_assign_not_ref : Error<
   "the parameter for an explicitly-defaulted copy assignment operator must be an "
   "lvalue reference type">;
 def err_incorrect_defaulted_constexpr : Error<
-  "defaulted definition of %sub{select_special_member_kind}0 "
-  "is not constexpr">;
+  "defaulted definition of %sub{select_special_member_kind}0 cannot be marked %select{constexpr|consteval}1 "
+  "before C++23">;
 def err_incorrect_defaulted_constexpr_with_vb: Error<
   "%sub{select_special_member_kind}0 cannot be 'constexpr' in a class with virtual base class">;
-def err_incorrect_defaulted_consteval : Error<
-  "defaulted declaration of %sub{select_special_member_kind}0 "
-  "cannot be consteval because implicit definition is not constexpr">;
 def warn_defaulted_method_deleted : Warning<
   "explicitly defaulted %sub{select_special_member_kind}0 is implicitly "
   "deleted">, InGroup;
@@ -9708,21 +9731,12 @@ def note_defaulted_comparison_cannot_deduce_undeduced_auto : Note<
   "%select{|member|base class}0 %1 declared here">;
 def note_defaulted_comparison_cannot_deduce_callee : Note<
   "selected 'operator<=>' for %select{|member|base class}0 %1 declared here">;
-def ext_defaulted_comparison_constexpr_mismatch : Extension<
-  "defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|"
-  "three-way comparison operator}0 that is "
-  "declared %select{constexpr|consteval}2 but"
-  "%select{|for which the corresponding implicit 'operator==' }0 "
-  "invokes a non-constexpr comparison function is a C++23 extension">,
-  InGroup>;
-def warn_cxx23_compat_defaulted_comparison_constexpr_mismatch : Warning<
+def err_defaulted_comparison_constexpr_mismatch : Error<
   "defaulted definition of %select{%sub{select_defaulted_comparison_kind}1|"
-  "three-way comparison operator}0 that is "
-  "declared %select{constexpr|consteval}2 but"
-  "%select{|for which the corresponding implicit 'operator==' }0 "
-  "invokes a non-constexpr comparison function is incompatible with C++ "
-  "standards before C++23">,
-  InGroup, DefaultIgnore;
+  "three-way comparison operator}0 cannot be "
+  "declared %select{constexpr|consteval}2 because "
+  "%select{it|for which the corresponding implicit 'operator==' }0 "
+  "invokes a non-constexpr comparison function ">;
 def note_defaulted_comparison_not_constexpr : Note<
   "non-constexpr comparison function would be used to compare "
   "%select{|member %1|base class %1}0">;
@@ -9901,7 +9915,7 @@ def err_lifetimebound_ctor_dtor : Error<
 // CHECK: returning address/reference of stack memory
 def warn_ret_stack_addr_ref : Warning<
   "%select{address of|reference to}0 stack memory associated with "
-  "%select{local variable|parameter}2 %1 returned">,
+  "%select{local variable|parameter|compound literal}2 %1 returned">,
   InGroup;
 def warn_ret_local_temp_addr_ref : Warning<
   "returning %select{address of|reference to}0 local temporary object">,
@@ -10157,6 +10171,9 @@ def err_fallthrough_attr_outside_switch : Error<
 def err_fallthrough_attr_invalid_placement : Error<
   "fallthrough annotation does not directly precede switch label">;
 
+def err_assume_attr_args : Error<
+  "attribute '%0' requires a single expression argument">;
+
 def warn_unreachable_default : Warning<
   "default label in switch which covers all enumeration values">,
   InGroup, DefaultIgnore;
@@ -10231,14 +10248,14 @@ def warn_second_parameter_to_va_arg_never_compatible : Warning<
 
 def warn_return_missing_expr : Warning<
   "non-void %select{function|method}1 %0 should return a value">, DefaultError,
-  InGroup;
+  InGroup;
 def ext_return_missing_expr : ExtWarn<
   "non-void %select{function|method}1 %0 should return a value">, DefaultError,
-  InGroup;
+  InGroup;
 def ext_return_has_expr : ExtWarn<
   "%select{void function|void method|constructor|destructor}1 %0 "
   "should not return a value">,
-  DefaultError, InGroup;
+  DefaultError, InGroup;
 def ext_return_has_void_expr : Extension<
   "void %select{function|method|block}1 %0 should not return void expression">;
 def err_return_init_list : Error<
@@ -11336,6 +11353,8 @@ def err_omp_device_type_mismatch : Error<
 def err_omp_wrong_device_function_call : Error<
   "function with 'device_type(%0)' is not available on %select{device|host}1">;
 def note_omp_marked_device_type_here : Note<"marked as 'device_type(%0)' here">;
+def err_omp_declare_target_has_local_vars : Error<
+  "local variable '%0' should not be used in 'declare target' directive; ">;
 def warn_omp_declare_target_after_first_use : Warning<
   "declaration marked as declare target after first use, it may lead to incorrect results">,
   InGroup;
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 2b42b521a30363367a1620f753188bf668a1f9d9..472fd9f093a718a42ba6984308e41f4db255f27c 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -450,6 +450,8 @@ LANGOPT(RegCall4, 1, 0, "Set __regcall4 as a default calling convention to respe
 
 LANGOPT(MatrixTypes, 1, 0, "Enable or disable the builtin matrix type")
 
+LANGOPT(CXXAssumptions, 1, 1, "Enable or disable codegen and compile-time checks for C++23's [[assume]] attribute")
+
 ENUM_LANGOPT(StrictFlexArraysLevel, StrictFlexArraysLevelKind, 2,
              StrictFlexArraysLevelKind::Default,
              "Rely on strict definition of flexible arrays")
diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h
index 30ec9c99315092965b0997eb9b6b41c3e52fb6e1..9f62c058ca0da068ac21f988c40c3995e3d99d8f 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -598,6 +598,11 @@ public:
            Kind == ModulePartitionImplementation;
   }
 
+  /// Is this a module partition implementation unit.
+  bool isModulePartitionImplementation() const {
+    return Kind == ModulePartitionImplementation;
+  }
+
   /// Is this a module implementation.
   bool isModuleImplementation() const {
     return Kind == ModuleImplementationUnit;
@@ -853,12 +858,6 @@ public:
                   VisibleCallback Vis = [](Module *) {},
                   ConflictCallback Cb = [](ArrayRef, Module *,
                                            StringRef) {});
-
-  /// Make transitive imports visible for [module.import]/7.
-  void makeTransitiveImportsVisible(
-      Module *M, SourceLocation Loc, VisibleCallback Vis = [](Module *) {},
-      ConflictCallback Cb = [](ArrayRef, Module *, StringRef) {});
-
 private:
   /// Import locations for each visible module. Indexed by the module's
   /// VisibilityID.
diff --git a/clang/include/clang/Basic/OpenCLExtensionTypes.def b/clang/include/clang/Basic/OpenCLExtensionTypes.def
index 17c72d69a020655736bb1c52ba281b2d5f0b20b8..50ea826c18a77caa7ac8d12f2b4798cd8cd717d4 100644
--- a/clang/include/clang/Basic/OpenCLExtensionTypes.def
+++ b/clang/include/clang/Basic/OpenCLExtensionTypes.def
@@ -1,4 +1,4 @@
-//===-- OpenCLExtensionTypes.def - Metadata about BuiltinTypes ------*- C++ -*-===//
+//===-- OpenCLExtensionTypes.def - Metadata about BuiltinTypes --*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/include/clang/Basic/RISCVVTypes.def b/clang/include/clang/Basic/RISCVVTypes.def
index 6620de8ad50e01e1f65df99e0428c5b9a1e117e0..ccb8cb39068e2ba12b01c874088c400ba1eea86d 100644
--- a/clang/include/clang/Basic/RISCVVTypes.def
+++ b/clang/include/clang/Basic/RISCVVTypes.def
@@ -383,7 +383,7 @@ RVV_VECTOR_TYPE_INT("__rvv_uint64m2x4_t", RvvUint64m2x4, RvvUint64m2x4Ty, 2, 64,
 
 RVV_VECTOR_TYPE_INT("__rvv_uint64m4x2_t", RvvUint64m4x2, RvvUint64m4x2Ty, 4, 64, 2, false)
 
-//===- Float16 tuple types --------------------------------------------------===//
+//===- Float16 tuple types ------------------------------------------------===//
 RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf4x2_t", RvvFloat16mf4x2, RvvFloat16mf4x2Ty, 1, 16, 2)
 RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf4x3_t", RvvFloat16mf4x3, RvvFloat16mf4x3Ty, 1, 16, 3)
 RVV_VECTOR_TYPE_FLOAT("__rvv_float16mf4x4_t", RvvFloat16mf4x4, RvvFloat16mf4x4Ty, 1, 16, 4)
@@ -414,7 +414,7 @@ RVV_VECTOR_TYPE_FLOAT("__rvv_float16m2x4_t", RvvFloat16m2x4, RvvFloat16m2x4Ty, 8
 
 RVV_VECTOR_TYPE_FLOAT("__rvv_float16m4x2_t", RvvFloat16m4x2, RvvFloat16m4x2Ty, 16, 16, 2)
 
-//===- Float32 tuple types --------------------------------------------------===//
+//===- Float32 tuple types ------------------------------------------------===//
 RVV_VECTOR_TYPE_FLOAT("__rvv_float32mf2x2_t", RvvFloat32mf2x2, RvvFloat32mf2x2Ty, 1, 32, 2)
 RVV_VECTOR_TYPE_FLOAT("__rvv_float32mf2x3_t", RvvFloat32mf2x3, RvvFloat32mf2x3Ty, 1, 32, 3)
 RVV_VECTOR_TYPE_FLOAT("__rvv_float32mf2x4_t", RvvFloat32mf2x4, RvvFloat32mf2x4Ty, 1, 32, 4)
@@ -437,7 +437,7 @@ RVV_VECTOR_TYPE_FLOAT("__rvv_float32m2x4_t", RvvFloat32m2x4, RvvFloat32m2x4Ty, 4
 
 RVV_VECTOR_TYPE_FLOAT("__rvv_float32m4x2_t", RvvFloat32m4x2, RvvFloat32m4x2Ty, 8, 32, 2)
 
-//===- Float64 tuple types -------------------------------------------------===//
+//===- Float64 tuple types ------------------------------------------------===//
 RVV_VECTOR_TYPE_FLOAT("__rvv_float64m1x2_t", RvvFloat64m1x2, RvvFloat64m1x2Ty, 1, 64, 2)
 RVV_VECTOR_TYPE_FLOAT("__rvv_float64m1x3_t", RvvFloat64m1x3, RvvFloat64m1x3Ty, 1, 64, 3)
 RVV_VECTOR_TYPE_FLOAT("__rvv_float64m1x4_t", RvvFloat64m1x4, RvvFloat64m1x4Ty, 1, 64, 4)
@@ -452,7 +452,7 @@ RVV_VECTOR_TYPE_FLOAT("__rvv_float64m2x4_t", RvvFloat64m2x4, RvvFloat64m2x4Ty, 2
 
 RVV_VECTOR_TYPE_FLOAT("__rvv_float64m4x2_t", RvvFloat64m4x2, RvvFloat64m4x2Ty, 4, 64, 2)
 
-//===- BFloat16 tuple types -------------------------------------------------===//
+//===- BFloat16 tuple types -----------------------------------------------===//
 RVV_VECTOR_TYPE_BFLOAT("__rvv_bfloat16mf4x2_t", RvvBFloat16mf4x2, RvvBFloat16mf4x2Ty,
                        1, 16, 2)
 RVV_VECTOR_TYPE_BFLOAT("__rvv_bfloat16mf4x3_t", RvvBFloat16mf4x3, RvvBFloat16mf4x3Ty,
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 1d16e4843615d99d986500b63feee54f05adf746..3a96f8a4d22bd14b843a9fb3a3750676255726c1 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -393,7 +393,7 @@ CXX11_KEYWORD(alignas               , KEYC23)
 CXX11_UNARY_EXPR_OR_TYPE_TRAIT(alignof, AlignOf, KEYC23)
 CXX11_KEYWORD(char16_t              , KEYNOMS18)
 CXX11_KEYWORD(char32_t              , KEYNOMS18)
-CXX11_KEYWORD(constexpr             , 0)
+CXX11_KEYWORD(constexpr             , KEYC23)
 CXX11_KEYWORD(decltype              , 0)
 CXX11_KEYWORD(noexcept              , 0)
 CXX11_KEYWORD(nullptr               , KEYC23)
diff --git a/clang/include/clang/Basic/arm_neon_incl.td b/clang/include/clang/Basic/arm_neon_incl.td
index 4f969ac1c78a0262085569806516bb8feca62dd2..b8155c187d1bccac62e245b75114355978d0ab53 100644
--- a/clang/include/clang/Basic/arm_neon_incl.td
+++ b/clang/include/clang/Basic/arm_neon_incl.td
@@ -1,4 +1,4 @@
-//===--- arm_neon_incl.td - ARM NEON compiler interface ------------------------===//
+//===--- arm_neon_incl.td - ARM NEON compiler interface -------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td
index 6da30e08e7521e767e25ac6d9587f5f36518fdb5..6cc249837d3f3d42414331ee5a0bf3f0e9c36bee 100644
--- a/clang/include/clang/Basic/arm_sve.td
+++ b/clang/include/clang/Basic/arm_sve.td
@@ -2215,6 +2215,15 @@ let TargetGuard = "sve2p1" in {
   def SVTBXQ : SInst<"svtbxq[_{d}]", "dddu", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_tbxq">;
   // EXTQ
   def EXTQ : SInst<"svextq[_{d}]", "dddk", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_extq", [], [ImmCheck<2, ImmCheck0_15>]>;
+  // DUPQ
+  def SVDUP_LANEQ_B  : SInst<"svdup_laneq[_{d}]", "ddi",  "cUc", MergeNone, "aarch64_sve_dup_laneq", [IsStreamingCompatible], [ImmCheck<1, ImmCheck0_15>]>;
+  def SVDUP_LANEQ_H  : SInst<"svdup_laneq[_{d}]", "ddi",  "sUsh", MergeNone, "aarch64_sve_dup_laneq", [IsStreamingCompatible], [ImmCheck<1, ImmCheck0_7>]>;
+  def SVDUP_LANEQ_S  : SInst<"svdup_laneq[_{d}]", "ddi",  "iUif", MergeNone, "aarch64_sve_dup_laneq", [IsStreamingCompatible], [ImmCheck<1, ImmCheck0_3>]>;
+  def SVDUP_LANEQ_D  : SInst<"svdup_laneq[_{d}]", "ddi",  "lUld", MergeNone, "aarch64_sve_dup_laneq", [IsStreamingCompatible], [ImmCheck<1, ImmCheck0_1>]>;
+
+  let TargetGuard = "bf16" in {
+    def SVDUP_LANEQ_BF16  : SInst<"svdup_laneq[_{d}]", "ddi",  "b", MergeNone, "aarch64_sve_dup_laneq", [IsStreamingCompatible], [ImmCheck<1, ImmCheck0_7>]>;
+  }
   // PMOV
   // Move to Pred
   multiclass PMOV_TO_PRED flags=[], ImmCheckType immCh > {
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index bcf8c1295f2ddfc53b49809f2d8e148b13b404f0..c4cab360bab3bb3b31b117eb8ce2db5644b653fa 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -615,16 +615,6 @@ public:
   // FIXME: This should be in CompilationInfo.
   std::string GetProgramPath(StringRef Name, const ToolChain &TC) const;
 
-  /// Lookup the path to the Standard library module manifest.
-  ///
-  /// \param C - The compilation.
-  /// \param TC - The tool chain for additional information on
-  /// directories to search.
-  //
-  // FIXME: This should be in CompilationInfo.
-  std::string GetStdModuleManifestPath(const Compilation &C,
-                                       const ToolChain &TC) const;
-
   /// HandleAutocompletions - Handle --autocomplete by searching and printing
   /// possible flags, descriptions, and its arguments.
   void HandleAutocompletions(StringRef PassedFlags) const;
diff --git a/clang/include/clang/Driver/OffloadBundler.h b/clang/include/clang/Driver/OffloadBundler.h
index 84349abe185fa4d778585f5832930e650c1b3fb0..65d33bfbd2825f907c580b70684a36d41d1abd4e 100644
--- a/clang/include/clang/Driver/OffloadBundler.h
+++ b/clang/include/clang/Driver/OffloadBundler.h
@@ -17,6 +17,7 @@
 #ifndef LLVM_CLANG_DRIVER_OFFLOADBUNDLER_H
 #define LLVM_CLANG_DRIVER_OFFLOADBUNDLER_H
 
+#include "llvm/Support/Compression.h"
 #include "llvm/Support/Error.h"
 #include "llvm/TargetParser/Triple.h"
 #include 
@@ -36,6 +37,8 @@ public:
   bool HipOpenmpCompatible = false;
   bool Compress = false;
   bool Verbose = false;
+  llvm::compression::Format CompressionFormat;
+  int CompressionLevel;
 
   unsigned BundleAlignment = 1;
   unsigned HostInputIndex = ~0u;
@@ -116,7 +119,8 @@ private:
 
 public:
   static llvm::Expected>
-  compress(const llvm::MemoryBuffer &Input, bool Verbose = false);
+  compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input,
+           bool Verbose = false);
   static llvm::Expected>
   decompress(const llvm::MemoryBuffer &Input, bool Verbose = false);
 };
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 3e857f4e6faf8723b9c583579f49f962be243923..aca8c9b0d5487a8fe8b95761849262639a6df314 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1264,6 +1264,10 @@ def fno_gpu_sanitize : Flag<["-"], "fno-gpu-sanitize">, Group;
 def offload_compress : Flag<["--"], "offload-compress">,
   HelpText<"Compress offload device binaries (HIP only)">;
 def no_offload_compress : Flag<["--"], "no-offload-compress">;
+
+def offload_compression_level_EQ : Joined<["--"], "offload-compression-level=">,
+  Flags<[HelpHidden]>,
+  HelpText<"Compression level for offload device binaries (HIP only)">;
 }
 
 // CUDA options
@@ -3789,6 +3793,12 @@ def foptimization_record_passes_EQ : Joined<["-"], "foptimization-record-passes=
   HelpText<"Only include passes which match a specified regular expression in the generated optimization record (by default, include all passes)">,
   MetaVarName<"">;
 
+defm assumptions : BoolFOption<"assumptions",
+  LangOpts<"CXXAssumptions">, DefaultTrue,
+  NegFlag,
+  PosFlag>;
+
 def fvectorize : Flag<["-"], "fvectorize">, Group,
   HelpText<"Enable the loop vectorization passes">;
 def fno_vectorize : Flag<["-"], "fno-vectorize">, Group;
@@ -5364,9 +5374,6 @@ def print_resource_dir : Flag<["-", "--"], "print-resource-dir">,
 def print_search_dirs : Flag<["-", "--"], "print-search-dirs">,
   HelpText<"Print the paths used for finding libraries and programs">,
   Visibility<[ClangOption, CLOption]>;
-def print_std_module_manifest_path : Flag<["-", "--"], "print-library-module-manifest-path">,
-  HelpText<"Print the path for the C++ Standard library module manifest">,
-  Visibility<[ClangOption, CLOption]>;
 def print_targets : Flag<["-", "--"], "print-targets">,
   HelpText<"Print the registered targets">,
   Visibility<[ClangOption, CLOption]>;
@@ -7417,7 +7424,9 @@ def ast_view : Flag<["-"], "ast-view">,
 def emit_module : Flag<["-"], "emit-module">,
   HelpText<"Generate pre-compiled module file from a module map">;
 def emit_module_interface : Flag<["-"], "emit-module-interface">,
-  HelpText<"Generate pre-compiled module file from a C++ module interface">;
+  HelpText<"Generate pre-compiled module file from a standard C++ module interface unit">;
+def emit_reduced_module_interface : Flag<["-"], "emit-reduced-module-interface">,
+  HelpText<"Generate reduced prebuilt module interface from a standard C++ module interface unit">;
 def emit_header_unit : Flag<["-"], "emit-header-unit">,
   HelpText<"Generate C++20 header units from header files">;
 def emit_pch : Flag<["-"], "emit-pch">,
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 613f1fd168465d27dcd5885179d6ccfb8cba18ab..590297fd89a398a8284f038d7a06c3c071c40ac4 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -154,9 +154,9 @@ struct FormatStyle {
   /// For example, to align across empty lines and not across comments, either
   /// of these work.
   /// \code
-  ///   AlignConsecutiveMacros: AcrossEmptyLines
+  ///   : AcrossEmptyLines
   ///
-  ///   AlignConsecutiveMacros:
+  ///   :
   ///     Enabled: true
   ///     AcrossEmptyLines: true
   ///     AcrossComments: false
diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h
index fcce31ac0590ff678adec7999a7cb5d0c3552cfd..8441af2ee3e718603ac9dd2898dcee4b14b38d01 100644
--- a/clang/include/clang/Frontend/FrontendActions.h
+++ b/clang/include/clang/Frontend/FrontendActions.h
@@ -118,6 +118,9 @@ class GenerateModuleAction : public ASTFrontendAction {
   CreateOutputFile(CompilerInstance &CI, StringRef InFile) = 0;
 
 protected:
+  std::vector>
+  CreateMultiplexConsumer(CompilerInstance &CI, StringRef InFile);
+
   std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
                                                  StringRef InFile) override;
 
@@ -147,8 +150,10 @@ private:
   CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
 };
 
+/// Generates full BMI (which contains full information to generate the object
+/// files) for C++20 Named Modules.
 class GenerateModuleInterfaceAction : public GenerateModuleAction {
-private:
+protected:
   bool BeginSourceFileAction(CompilerInstance &CI) override;
 
   std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
@@ -158,6 +163,14 @@ private:
   CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
 };
 
+/// Only generates the reduced BMI. This action is mainly used by tests.
+class GenerateReducedModuleInterfaceAction
+    : public GenerateModuleInterfaceAction {
+private:
+  std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
+                                                 StringRef InFile) override;
+};
+
 class GenerateHeaderUnitAction : public GenerateModuleAction {
 
 private:
diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h
index 53a8681cfdbba04a667e80677a95a00d6baa948c..8085dbcbf671a6e858df6870fc121055f51f60df 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -85,9 +85,13 @@ enum ActionKind {
   /// Generate pre-compiled module from a module map.
   GenerateModule,
 
-  /// Generate pre-compiled module from a C++ module interface file.
+  /// Generate pre-compiled module from a standard C++ module interface unit.
   GenerateModuleInterface,
 
+  /// Generate reduced module interface for a standard C++ module interface
+  /// unit.
+  GenerateReducedModuleInterface,
+
   /// Generate a C++20 header unit module from a header file.
   GenerateHeaderUnit,
 
diff --git a/clang/include/clang/InstallAPI/Frontend.h b/clang/include/clang/InstallAPI/Frontend.h
index d72b4680fde400ad2b567fd65dda3e942a9768bd..cbc2b159ebd17a3b92c27c5ea391c96120ad9f8c 100644
--- a/clang/include/clang/InstallAPI/Frontend.h
+++ b/clang/include/clang/InstallAPI/Frontend.h
@@ -28,7 +28,10 @@ namespace installapi {
 using SymbolFlags = llvm::MachO::SymbolFlags;
 using RecordLinkage = llvm::MachO::RecordLinkage;
 using GlobalRecord = llvm::MachO::GlobalRecord;
+using ObjCContainerRecord = llvm::MachO::ObjCContainerRecord;
 using ObjCInterfaceRecord = llvm::MachO::ObjCInterfaceRecord;
+using ObjCCategoryRecord = llvm::MachO::ObjCCategoryRecord;
+using ObjCIVarRecord = llvm::MachO::ObjCIVarRecord;
 
 // Represents a collection of frontend records for a library that are tied to a
 // darwin target triple.
@@ -47,12 +50,15 @@ public:
   /// \param D The pointer to the declaration from traversing AST.
   /// \param Access The intended access level of symbol.
   /// \param Flags The flags that describe attributes of the symbol.
+  /// \param Inlined Whether declaration is inlined, only applicable to
+  /// functions.
   /// \return The non-owning pointer to added record in slice.
   GlobalRecord *addGlobal(StringRef Name, RecordLinkage Linkage,
                           GlobalRecord::Kind GV,
                           const clang::AvailabilityInfo Avail, const Decl *D,
                           const HeaderType Access,
-                          SymbolFlags Flags = SymbolFlags::None);
+                          SymbolFlags Flags = SymbolFlags::None,
+                          bool Inlined = false);
 
   /// Add ObjC Class record with attributes from AST.
   ///
@@ -69,6 +75,38 @@ public:
                                         const Decl *D, HeaderType Access,
                                         bool IsEHType);
 
+  /// Add ObjC Category record with attributes from AST.
+  ///
+  /// \param ClassToExtend The name of class that is extended by category, not
+  /// symbol.
+  /// \param CategoryName The name of category, not symbol.
+  /// \param Avail The availability information tied
+  /// to the active target triple.
+  /// \param D The pointer to the declaration from traversing AST.
+  /// \param Access The intended access level of symbol.
+  /// \return The non-owning pointer to added record in slice.
+  ObjCCategoryRecord *addObjCCategory(StringRef ClassToExtend,
+                                      StringRef CategoryName,
+                                      const clang::AvailabilityInfo Avail,
+                                      const Decl *D, HeaderType Access);
+
+  /// Add ObjC IVar record with attributes from AST.
+  ///
+  /// \param Container The owning pointer for instance variable.
+  /// \param Name The name of ivar, not symbol.
+  /// \param Linkage The linkage of symbol.
+  /// \param Avail The availability information tied to the active target
+  /// triple.
+  /// \param D The pointer to the declaration from traversing AST.
+  /// \param Access The intended access level of symbol.
+  /// \param AC The access control tied to the ivar declaration.
+  /// \return The non-owning pointer to added record in slice.
+  ObjCIVarRecord *addObjCIVar(ObjCContainerRecord *Container,
+                              StringRef IvarName, RecordLinkage Linkage,
+                              const clang::AvailabilityInfo Avail,
+                              const Decl *D, HeaderType Access,
+                              const clang::ObjCIvarDecl::AccessControl AC);
+
 private:
   /// Frontend information captured about records.
   struct FrontendAttrs {
diff --git a/clang/include/clang/InstallAPI/Visitor.h b/clang/include/clang/InstallAPI/Visitor.h
index 60a05005df841a97d26e2839ac0bd256528fc6c6..9ac948ded3e332d62401132650f288c0a0805c99 100644
--- a/clang/include/clang/InstallAPI/Visitor.h
+++ b/clang/include/clang/InstallAPI/Visitor.h
@@ -21,6 +21,7 @@
 #include "llvm/ADT/Twine.h"
 
 namespace clang {
+struct AvailabilityInfo;
 namespace installapi {
 
 /// ASTVisitor for collecting declarations that represent global symbols.
@@ -33,19 +34,47 @@ public:
         MC(ItaniumMangleContext::create(ASTCtx, ASTCtx.getDiagnostics())),
         Layout(ASTCtx.getTargetInfo().getDataLayoutString()) {}
   void HandleTranslationUnit(ASTContext &ASTCtx) override;
+  bool shouldVisitTemplateInstantiations() const { return true; }
 
   /// Collect global variables.
   bool VisitVarDecl(const VarDecl *D);
 
+  /// Collect global functions.
+  bool VisitFunctionDecl(const FunctionDecl *D);
+
   /// Collect Objective-C Interface declarations.
   /// Every Objective-C class has an interface declaration that lists all the
   /// ivars, properties, and methods of the class.
   bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D);
 
+  /// Collect Objective-C Category/Extension declarations.
+  ///
+  /// The class that is being extended might come from a different library and
+  /// is therefore itself not collected.
+  bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D);
+
+  /// Collect global c++ declarations.
+  bool VisitCXXRecordDecl(const CXXRecordDecl *D);
+
 private:
   std::string getMangledName(const NamedDecl *D) const;
   std::string getBackendMangledName(llvm::Twine Name) const;
+  std::string getMangledCXXVTableName(const CXXRecordDecl *D) const;
+  std::string getMangledCXXThunk(const GlobalDecl &D,
+                                 const ThunkInfo &Thunk) const;
+  std::string getMangledCXXRTTI(const CXXRecordDecl *D) const;
+  std::string getMangledCXXRTTIName(const CXXRecordDecl *D) const;
+  std::string getMangledCtorDtor(const CXXMethodDecl *D, int Type) const;
+
   std::optional getAccessForDecl(const NamedDecl *D) const;
+  void recordObjCInstanceVariables(
+      const ASTContext &ASTCtx, llvm::MachO::ObjCContainerRecord *Record,
+      StringRef SuperClass,
+      const llvm::iterator_range<
+          DeclContext::specific_decl_iterator>
+          Ivars);
+  void emitVTableSymbols(const CXXRecordDecl *D, const AvailabilityInfo &Avail,
+                         const HeaderType Access, bool EmittedVTable = false);
 
   InstallAPIContext &Ctx;
   SourceManager &SrcMgr;
diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h
index 292fa566ae703795ec4fce7716026b3d733fd71d..1dcba1ef967980b7aa6297316b78912b3dbdb21d 100644
--- a/clang/include/clang/Interpreter/Interpreter.h
+++ b/clang/include/clang/Interpreter/Interpreter.h
@@ -18,6 +18,7 @@
 #include "clang/AST/GlobalDecl.h"
 #include "clang/Interpreter/PartialTranslationUnit.h"
 #include "clang/Interpreter/Value.h"
+#include "clang/Sema/Ownership.h"
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ExecutionEngine/JITSymbol.h"
@@ -48,6 +49,8 @@ public:
     UserArgs = Args;
   }
 
+  void SetTargetTriple(std::string TT) { TargetTriple = TT; }
+
   // General C++
   llvm::Expected> CreateCpp();
 
@@ -62,28 +65,37 @@ public:
 
 private:
   static llvm::Expected>
-  create(std::vector &ClangArgv);
+  create(std::string TT, std::vector &ClangArgv);
 
   llvm::Expected> createCuda(bool device);
 
   std::vector UserArgs;
+  std::optional TargetTriple;
 
   llvm::StringRef OffloadArch;
   llvm::StringRef CudaSDKPath;
 };
 
+/// Generate glue code between the Interpreter's built-in runtime and user code.
+class RuntimeInterfaceBuilder {
+public:
+  virtual ~RuntimeInterfaceBuilder() = default;
+
+  using TransformExprFunction = ExprResult(RuntimeInterfaceBuilder *Builder,
+                                           Expr *, ArrayRef);
+  virtual TransformExprFunction *getPrintValueTransformer() = 0;
+};
+
 /// Provides top-level interfaces for incremental compilation and execution.
 class Interpreter {
   std::unique_ptr TSCtx;
   std::unique_ptr IncrParser;
   std::unique_ptr IncrExecutor;
+  std::unique_ptr RuntimeIB;
 
   // An optional parser for CUDA offloading
   std::unique_ptr DeviceParser;
 
-  Interpreter(std::unique_ptr CI, llvm::Error &Err);
-
-  llvm::Error CreateExecutor();
   unsigned InitPTUSize = 0;
 
   // This member holds the last result of the value printing. It's a class
@@ -91,8 +103,33 @@ class Interpreter {
   // printing happens, it's in an invalid state.
   Value LastValue;
 
+  // Add a call to an Expr to report its result. We query the function from
+  // RuntimeInterfaceBuilder once and store it as a function pointer to avoid
+  // frequent virtual function calls.
+  RuntimeInterfaceBuilder::TransformExprFunction *AddPrintValueCall = nullptr;
+
+protected:
+  // Derived classes can make use an extended interface of the Interpreter.
+  // That's useful for testing and out-of-tree clients.
+  Interpreter(std::unique_ptr CI, llvm::Error &Err);
+
+  // Create the internal IncrementalExecutor, or re-create it after calling
+  // ResetExecutor().
+  llvm::Error CreateExecutor();
+
+  // Delete the internal IncrementalExecutor. This causes a hard shutdown of the
+  // JIT engine. In particular, it doesn't run cleanup or destructors.
+  void ResetExecutor();
+
+  // Lazily construct the RuntimeInterfaceBuilder. The provided instance will be
+  // used for the entire lifetime of the interpreter. The default implementation
+  // targets the in-process __clang_Interpreter runtime. Override this to use a
+  // custom runtime.
+  virtual std::unique_ptr FindRuntimeInterface();
+
 public:
-  ~Interpreter();
+  virtual ~Interpreter();
+
   static llvm::Expected>
   create(std::unique_ptr CI);
   static llvm::Expected>
@@ -139,8 +176,7 @@ public:
 
 private:
   size_t getEffectivePTUSize() const;
-
-  bool FindRuntimeInterface();
+  void markUserCodeStart();
 
   llvm::DenseMap Dtors;
 
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 071520f535bc95742b5b9da4e27d479fb76f2f21..64e031d5094c74cd0dbef96df55e479661b033b2 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1803,6 +1803,7 @@ public:
   ExprResult ParseConstraintLogicalOrExpression(bool IsTrailingRequiresClause);
   // Expr that doesn't include commas.
   ExprResult ParseAssignmentExpression(TypeCastState isTypeCast = NotTypeCast);
+  ExprResult ParseConditionalExpression();
 
   ExprResult ParseMSAsmIdentifier(llvm::SmallVectorImpl &LineToks,
                                   unsigned &NumLineToksConsumed,
@@ -2955,6 +2956,12 @@ private:
                                SourceLocation ScopeLoc,
                                CachedTokens &OpenMPTokens);
 
+  /// Parse a C++23 assume() attribute. Returns true on error.
+  bool ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs,
+                                  IdentifierInfo *AttrName,
+                                  SourceLocation AttrNameLoc,
+                                  SourceLocation *EndLoc);
+
   IdentifierInfo *TryParseCXX11AttributeIdentifier(
       SourceLocation &Loc,
       Sema::AttributeCompletion Completion = Sema::AttributeCompletion::None,
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 316e8071169a3a340f0673b262a736a6bbba3b89..a176159707486c61f618ec55e78d100b1a4a9d0a 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -2359,11 +2359,27 @@ public:
       SetRangeEnd(EndLoc);
   }
 
+  /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
+  /// EndLoc, which should be the last token of the chunk. This overload is for
+  /// copying a 'chunk' from another declarator, so it takes the pool that the
+  /// other Declarator owns so that it can 'take' the attributes from it.
+  void AddTypeInfo(const DeclaratorChunk &TI, AttributePool &OtherPool,
+                   SourceLocation EndLoc) {
+    DeclTypeInfo.push_back(TI);
+    getAttributePool().takeFrom(DeclTypeInfo.back().getAttrs(), OtherPool);
+
+    if (!EndLoc.isInvalid())
+      SetRangeEnd(EndLoc);
+  }
+
   /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
   /// EndLoc, which should be the last token of the chunk.
   void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) {
     DeclTypeInfo.push_back(TI);
 
+    assert(TI.AttrList.empty() &&
+           "Cannot add a declarator chunk with attributes with this overload");
+
     if (!EndLoc.isInvalid())
       SetRangeEnd(EndLoc);
   }
diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h
index 8c3ba39031aad868c5986a01cf6ced0e7f3eb880..e3857b2f07d9e06978815721228c25fa5037e9e8 100644
--- a/clang/include/clang/Sema/ParsedAttr.h
+++ b/clang/include/clang/Sema/ParsedAttr.h
@@ -680,6 +680,7 @@ public:
   ~AttributeFactory();
 };
 
+class ParsedAttributesView;
 class AttributePool {
   friend class AttributeFactory;
   friend class ParsedAttributes;
@@ -734,6 +735,10 @@ public:
     pool.Attrs.clear();
   }
 
+  /// Removes the attributes from \c List, which are owned by \c Pool, and adds
+  /// them at the end of this \c AttributePool.
+  void takeFrom(ParsedAttributesView &List, AttributePool &Pool);
+
   ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange,
                      IdentifierInfo *scopeName, SourceLocation scopeLoc,
                      ArgsUnion *args, unsigned numArgs, ParsedAttr::Form form,
@@ -816,6 +821,7 @@ public:
 };
 
 class ParsedAttributesView {
+  friend class AttributePool;
   using VecTy = llvm::SmallVector;
   using SizeType = decltype(std::declval().size());
 
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 29baf542f6cbf50e5fb1645f403d12dc8a229463..267c79cc057cbae140f349eac955d6a9655c677b 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -76,168 +76,168 @@
 #include 
 
 namespace llvm {
-  class APSInt;
-  template  class DenseSet;
-  class SmallBitVector;
-  struct InlineAsmIdentifierInfo;
-}
+class APSInt;
+template  class DenseSet;
+class SmallBitVector;
+struct InlineAsmIdentifierInfo;
+} // namespace llvm
 
 namespace clang {
-  class ADLResult;
-  class ASTConsumer;
-  class ASTContext;
-  class ASTMutationListener;
-  class ASTReader;
-  class ASTWriter;
-  class ArrayType;
-  class ParsedAttr;
-  class BindingDecl;
-  class BlockDecl;
-  class CapturedDecl;
-  class CXXBasePath;
-  class CXXBasePaths;
-  class CXXBindTemporaryExpr;
-  typedef SmallVector CXXCastPath;
-  class CXXConstructorDecl;
-  class CXXConversionDecl;
-  class CXXDeleteExpr;
-  class CXXDestructorDecl;
-  class CXXFieldCollector;
-  class CXXMemberCallExpr;
-  class CXXMethodDecl;
-  class CXXScopeSpec;
-  class CXXTemporary;
-  class CXXTryStmt;
-  class CallExpr;
-  class ClassTemplateDecl;
-  class ClassTemplatePartialSpecializationDecl;
-  class ClassTemplateSpecializationDecl;
-  class VarTemplatePartialSpecializationDecl;
-  class CodeCompleteConsumer;
-  class CodeCompletionAllocator;
-  class CodeCompletionTUInfo;
-  class CodeCompletionResult;
-  class CoroutineBodyStmt;
-  class Decl;
-  class DeclAccessPair;
-  class DeclContext;
-  class DeclRefExpr;
-  class DeclaratorDecl;
-  class DeducedTemplateArgument;
-  class DependentDiagnostic;
-  class DesignatedInitExpr;
-  class Designation;
-  class EnableIfAttr;
-  class EnumConstantDecl;
-  class Expr;
-  class ExtVectorType;
-  class FormatAttr;
-  class FriendDecl;
-  class FunctionDecl;
-  class FunctionProtoType;
-  class FunctionTemplateDecl;
-  class ImplicitConversionSequence;
-  typedef MutableArrayRef ConversionSequenceList;
-  class InitListExpr;
-  class InitializationKind;
-  class InitializationSequence;
-  class InitializedEntity;
-  class IntegerLiteral;
-  class LabelStmt;
-  class LambdaExpr;
-  class LangOptions;
-  class LocalInstantiationScope;
-  class LookupResult;
-  class MacroInfo;
-  typedef ArrayRef> ModuleIdPath;
-  class ModuleLoader;
-  class MultiLevelTemplateArgumentList;
-  class NamedDecl;
-  class ObjCCategoryDecl;
-  class ObjCCategoryImplDecl;
-  class ObjCCompatibleAliasDecl;
-  class ObjCContainerDecl;
-  class ObjCImplDecl;
-  class ObjCImplementationDecl;
-  class ObjCInterfaceDecl;
-  class ObjCIvarDecl;
-  template  class ObjCList;
-  class ObjCMessageExpr;
-  class ObjCMethodDecl;
-  class ObjCPropertyDecl;
-  class ObjCProtocolDecl;
-  class OMPThreadPrivateDecl;
-  class OMPRequiresDecl;
-  class OMPDeclareReductionDecl;
-  class OMPDeclareSimdDecl;
-  class OMPClause;
-  struct OMPVarListLocTy;
-  struct OverloadCandidate;
-  enum class OverloadCandidateParamOrder : char;
-  enum OverloadCandidateRewriteKind : unsigned;
-  class OverloadCandidateSet;
-  class OverloadExpr;
-  class ParenListExpr;
-  class ParmVarDecl;
-  class Preprocessor;
-  class PseudoDestructorTypeStorage;
-  class PseudoObjectExpr;
-  class QualType;
-  class StandardConversionSequence;
-  class Stmt;
-  class StringLiteral;
-  class SwitchStmt;
-  class TemplateArgument;
-  class TemplateArgumentList;
-  class TemplateArgumentLoc;
-  class TemplateDecl;
-  class TemplateInstantiationCallback;
-  class TemplateParameterList;
-  class TemplatePartialOrderingContext;
-  class TemplateTemplateParmDecl;
-  class Token;
-  class TypeAliasDecl;
-  class TypedefDecl;
-  class TypedefNameDecl;
-  class TypeLoc;
-  class TypoCorrectionConsumer;
-  class UnqualifiedId;
-  class UnresolvedLookupExpr;
-  class UnresolvedMemberExpr;
-  class UnresolvedSetImpl;
-  class UnresolvedSetIterator;
-  class UsingDecl;
-  class UsingShadowDecl;
-  class ValueDecl;
-  class VarDecl;
-  class VarTemplateSpecializationDecl;
-  class VisibilityAttr;
-  class VisibleDeclConsumer;
-  class IndirectFieldDecl;
-  struct DeductionFailureInfo;
-  class TemplateSpecCandidateSet;
+class ADLResult;
+class ASTConsumer;
+class ASTContext;
+class ASTMutationListener;
+class ASTReader;
+class ASTWriter;
+class ArrayType;
+class ParsedAttr;
+class BindingDecl;
+class BlockDecl;
+class CapturedDecl;
+class CXXBasePath;
+class CXXBasePaths;
+class CXXBindTemporaryExpr;
+typedef SmallVector CXXCastPath;
+class CXXConstructorDecl;
+class CXXConversionDecl;
+class CXXDeleteExpr;
+class CXXDestructorDecl;
+class CXXFieldCollector;
+class CXXMemberCallExpr;
+class CXXMethodDecl;
+class CXXScopeSpec;
+class CXXTemporary;
+class CXXTryStmt;
+class CallExpr;
+class ClassTemplateDecl;
+class ClassTemplatePartialSpecializationDecl;
+class ClassTemplateSpecializationDecl;
+class VarTemplatePartialSpecializationDecl;
+class CodeCompleteConsumer;
+class CodeCompletionAllocator;
+class CodeCompletionTUInfo;
+class CodeCompletionResult;
+class CoroutineBodyStmt;
+class Decl;
+class DeclAccessPair;
+class DeclContext;
+class DeclRefExpr;
+class DeclaratorDecl;
+class DeducedTemplateArgument;
+class DependentDiagnostic;
+class DesignatedInitExpr;
+class Designation;
+class EnableIfAttr;
+class EnumConstantDecl;
+class Expr;
+class ExtVectorType;
+class FormatAttr;
+class FriendDecl;
+class FunctionDecl;
+class FunctionProtoType;
+class FunctionTemplateDecl;
+class ImplicitConversionSequence;
+typedef MutableArrayRef ConversionSequenceList;
+class InitListExpr;
+class InitializationKind;
+class InitializationSequence;
+class InitializedEntity;
+class IntegerLiteral;
+class LabelStmt;
+class LambdaExpr;
+class LangOptions;
+class LocalInstantiationScope;
+class LookupResult;
+class MacroInfo;
+typedef ArrayRef> ModuleIdPath;
+class ModuleLoader;
+class MultiLevelTemplateArgumentList;
+class NamedDecl;
+class ObjCCategoryDecl;
+class ObjCCategoryImplDecl;
+class ObjCCompatibleAliasDecl;
+class ObjCContainerDecl;
+class ObjCImplDecl;
+class ObjCImplementationDecl;
+class ObjCInterfaceDecl;
+class ObjCIvarDecl;
+template  class ObjCList;
+class ObjCMessageExpr;
+class ObjCMethodDecl;
+class ObjCPropertyDecl;
+class ObjCProtocolDecl;
+class OMPThreadPrivateDecl;
+class OMPRequiresDecl;
+class OMPDeclareReductionDecl;
+class OMPDeclareSimdDecl;
+class OMPClause;
+struct OMPVarListLocTy;
+struct OverloadCandidate;
+enum class OverloadCandidateParamOrder : char;
+enum OverloadCandidateRewriteKind : unsigned;
+class OverloadCandidateSet;
+class OverloadExpr;
+class ParenListExpr;
+class ParmVarDecl;
+class Preprocessor;
+class PseudoDestructorTypeStorage;
+class PseudoObjectExpr;
+class QualType;
+class StandardConversionSequence;
+class Stmt;
+class StringLiteral;
+class SwitchStmt;
+class TemplateArgument;
+class TemplateArgumentList;
+class TemplateArgumentLoc;
+class TemplateDecl;
+class TemplateInstantiationCallback;
+class TemplateParameterList;
+class TemplatePartialOrderingContext;
+class TemplateTemplateParmDecl;
+class Token;
+class TypeAliasDecl;
+class TypedefDecl;
+class TypedefNameDecl;
+class TypeLoc;
+class TypoCorrectionConsumer;
+class UnqualifiedId;
+class UnresolvedLookupExpr;
+class UnresolvedMemberExpr;
+class UnresolvedSetImpl;
+class UnresolvedSetIterator;
+class UsingDecl;
+class UsingShadowDecl;
+class ValueDecl;
+class VarDecl;
+class VarTemplateSpecializationDecl;
+class VisibilityAttr;
+class VisibleDeclConsumer;
+class IndirectFieldDecl;
+struct DeductionFailureInfo;
+class TemplateSpecCandidateSet;
 
 namespace sema {
-  class AccessedEntity;
-  class BlockScopeInfo;
-  class Capture;
-  class CapturedRegionScopeInfo;
-  class CapturingScopeInfo;
-  class CompoundScopeInfo;
-  class DelayedDiagnostic;
-  class DelayedDiagnosticPool;
-  class FunctionScopeInfo;
-  class LambdaScopeInfo;
-  class PossiblyUnreachableDiag;
-  class RISCVIntrinsicManager;
-  class SemaPPCallbacks;
-  class TemplateDeductionInfo;
-}
+class AccessedEntity;
+class BlockScopeInfo;
+class Capture;
+class CapturedRegionScopeInfo;
+class CapturingScopeInfo;
+class CompoundScopeInfo;
+class DelayedDiagnostic;
+class DelayedDiagnosticPool;
+class FunctionScopeInfo;
+class LambdaScopeInfo;
+class PossiblyUnreachableDiag;
+class RISCVIntrinsicManager;
+class SemaPPCallbacks;
+class TemplateDeductionInfo;
+} // namespace sema
 
 namespace threadSafety {
-  class BeforeSet;
-  void threadSafetyCleanup(BeforeSet* Cache);
-}
+class BeforeSet;
+void threadSafetyCleanup(BeforeSet *Cache);
+} // namespace threadSafety
 
 // FIXME: No way to easily map from TemplateTypeParmTypes to
 // TemplateTypeParmDecls, so we have this horrible PointerUnion.
@@ -422,591 +422,652 @@ enum class TemplateDeductionResult {
 };
 
 /// Sema - This implements semantic analysis and AST building for C.
+/// \nosubgrouping
 class Sema final {
-  Sema(const Sema &) = delete;
-  void operator=(const Sema &) = delete;
-
-  ///Source of additional semantic information.
-  IntrusiveRefCntPtr ExternalSource;
-
-  static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD);
-
-  /// Determine whether two declarations should be linked together, given that
-  /// the old declaration might not be visible and the new declaration might
-  /// not have external linkage.
-  bool shouldLinkPossiblyHiddenDecl(const NamedDecl *Old,
-                                    const NamedDecl *New) {
-    if (isVisible(Old))
-     return true;
-    // See comment in below overload for why it's safe to compute the linkage
-    // of the new declaration here.
-    if (New->isExternallyDeclarable()) {
-      assert(Old->isExternallyDeclarable() &&
-             "should not have found a non-externally-declarable previous decl");
-      return true;
-    }
-    return false;
-  }
-  bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New);
-
-  void setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem,
-                                      QualType ResultTy,
-                                      ArrayRef Args);
+  // Table of Contents
+  // -----------------
+  // 1. Semantic Analysis (Sema.cpp)
+  // 2. C++ Access Control (SemaAccess.cpp)
+  // 3. Attributes (SemaAttr.cpp)
+  // 4. Availability Attribute Handling (SemaAvailability.cpp)
+  // 5. Casts (SemaCast.cpp)
+  // 6. Extra Semantic Checking (SemaChecking.cpp)
+  // 7. C++ Coroutines (SemaCoroutine.cpp)
+  // 8. C++ Scope Specifiers (SemaCXXScopeSpec.cpp)
+  // 9. Declarations (SemaDecl.cpp)
+  // 10. Declaration Attribute Handling (SemaDeclAttr.cpp)
+  // 11. C++ Declarations (SemaDeclCXX.cpp)
+  // 12. C++ Exception Specifications (SemaExceptionSpec.cpp)
+  // 13. Expressions (SemaExpr.cpp)
+  // 14. C++ Expressions (SemaExprCXX.cpp)
+  // 15. Member Access Expressions (SemaExprMember.cpp)
+  // 16. Initializers (SemaInit.cpp)
+  // 17. C++ Lambda Expressions (SemaLambda.cpp)
+  // 18. Name Lookup (SemaLookup.cpp)
+  // 19. Modules (SemaModule.cpp)
+  // 20. C++ Overloading (SemaOverload.cpp)
+  // 21. Pseudo-Object (SemaPseudoObject.cpp)
+  // 22. Statements (SemaStmt.cpp)
+  // 23. `inline asm` Statement (SemaStmtAsm.cpp)
+  // 24. Statement Attribute Handling (SemaStmtAttr.cpp)
+  // 25. C++ Templates (SemaTemplate.cpp)
+  // 26. C++ Template Argument Deduction (SemaTemplateDeduction.cpp)
+  // 27. C++ Template Instantiation (SemaTemplateInstantiate.cpp)
+  // 28. C++ Template Declaration Instantiation
+  //     (SemaTemplateInstantiateDecl.cpp)
+  // 29. C++ Variadic Templates (SemaTemplateVariadic.cpp)
+  // 30. Constraints and Concepts (SemaConcept.cpp)
+  // 31. Types (SemaType.cpp)
+  // 32. ObjC Declarations (SemaDeclObjC.cpp)
+  // 33. ObjC Expressions (SemaExprObjC.cpp)
+  // 34. ObjC @property and @synthesize (SemaObjCProperty.cpp)
+  // 35. Code Completion (SemaCodeComplete.cpp)
+  // 36. FixIt Helpers (SemaFixItUtils.cpp)
+  // 37. Name Lookup for RISC-V Vector Intrinsic (SemaRISCVVectorLookup.cpp)
+  // 38. CUDA (SemaCUDA.cpp)
+  // 39. HLSL Constructs (SemaHLSL.cpp)
+  // 40. OpenACC Constructs (SemaOpenACC.cpp)
+  // 41. OpenMP Directives and Clauses (SemaOpenMP.cpp)
+  // 42. SYCL Constructs (SemaSYCL.cpp)
+
+  /// \name Semantic Analysis
+  /// Implementations are in Sema.cpp
+  ///@{
 
 public:
-  /// The maximum alignment, same as in llvm::Value. We duplicate them here
-  /// because that allows us not to duplicate the constants in clang code,
-  /// which we must to since we can't directly use the llvm constants.
-  /// The value is verified against llvm here: lib/CodeGen/CGDecl.cpp
-  ///
-  /// This is the greatest alignment value supported by load, store, and alloca
-  /// instructions, and global values.
-  static const unsigned MaxAlignmentExponent = 32;
-  static const uint64_t MaximumAlignment = 1ull << MaxAlignmentExponent;
-
-  typedef OpaquePtr DeclGroupPtrTy;
-  typedef OpaquePtr TemplateTy;
-  typedef OpaquePtr TypeTy;
-
-  OpenCLOptions OpenCLFeatures;
-  FPOptions CurFPFeatures;
-
-  const LangOptions &LangOpts;
-  Preprocessor &PP;
-  ASTContext &Context;
-  ASTConsumer &Consumer;
-  DiagnosticsEngine &Diags;
-  SourceManager &SourceMgr;
-  api_notes::APINotesManager APINotes;
-
-  /// Flag indicating whether or not to collect detailed statistics.
-  bool CollectStats;
-
-  /// Code-completion consumer.
-  CodeCompleteConsumer *CodeCompleter;
+  Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
+       TranslationUnitKind TUKind = TU_Complete,
+       CodeCompleteConsumer *CompletionConsumer = nullptr);
+  ~Sema();
 
-  /// CurContext - This is the current declaration context of parsing.
-  DeclContext *CurContext;
+  /// Perform initialization that occurs after the parser has been
+  /// initialized but before it parses anything.
+  void Initialize();
 
-  /// Generally null except when we temporarily switch decl contexts,
-  /// like in \see ActOnObjCTemporaryExitContainerContext.
-  DeclContext *OriginalLexicalContext;
+  /// This virtual key function only exists to limit the emission of debug info
+  /// describing the Sema class. GCC and Clang only emit debug info for a class
+  /// with a vtable when the vtable is emitted. Sema is final and not
+  /// polymorphic, but the debug info size savings are so significant that it is
+  /// worth adding a vtable just to take advantage of this optimization.
+  virtual void anchor();
 
-  /// VAListTagName - The declaration name corresponding to __va_list_tag.
-  /// This is used as part of a hack to omit that class from ADL results.
-  DeclarationName VAListTagName;
+  const LangOptions &getLangOpts() const { return LangOpts; }
+  OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; }
+  FPOptions &getCurFPFeatures() { return CurFPFeatures; }
 
-  bool MSStructPragmaOn; // True when \#pragma ms_struct on
+  DiagnosticsEngine &getDiagnostics() const { return Diags; }
+  SourceManager &getSourceManager() const { return SourceMgr; }
+  Preprocessor &getPreprocessor() const { return PP; }
+  ASTContext &getASTContext() const { return Context; }
+  ASTConsumer &getASTConsumer() const { return Consumer; }
+  ASTMutationListener *getASTMutationListener() const;
+  ExternalSemaSource *getExternalSource() const { return ExternalSource.get(); }
 
-  /// Controls member pointer representation format under the MS ABI.
-  LangOptions::PragmaMSPointersToMembersKind
-      MSPointerToMemberRepresentationMethod;
+  DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc,
+                                                         StringRef Platform);
+  DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking();
 
-  /// Stack of active SEH __finally scopes.  Can be empty.
-  SmallVector CurrentSEHFinally;
+  /// Registers an external source. If an external source already exists,
+  ///  creates a multiplex external source and appends to it.
+  ///
+  ///\param[in] E - A non-null external sema source.
+  ///
+  void addExternalSource(ExternalSemaSource *E);
 
-  /// Source location for newly created implicit MSInheritanceAttrs
-  SourceLocation ImplicitMSInheritanceAttrLoc;
+  /// Helper class that creates diagnostics with optional
+  /// template instantiation stacks.
+  ///
+  /// This class provides a wrapper around the basic DiagnosticBuilder
+  /// class that emits diagnostics. ImmediateDiagBuilder is
+  /// responsible for emitting the diagnostic (as DiagnosticBuilder
+  /// does) and, if the diagnostic comes from inside a template
+  /// instantiation, printing the template instantiation stack as
+  /// well.
+  class ImmediateDiagBuilder : public DiagnosticBuilder {
+    Sema &SemaRef;
+    unsigned DiagID;
 
-  /// Holds TypoExprs that are created from `createDelayedTypo`. This is used by
-  /// `TransformTypos` in order to keep track of any TypoExprs that are created
-  /// recursively during typo correction and wipe them away if the correction
-  /// fails.
-  llvm::SmallVector TypoExprs;
+  public:
+    ImmediateDiagBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID)
+        : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) {}
+    ImmediateDiagBuilder(DiagnosticBuilder &&DB, Sema &SemaRef, unsigned DiagID)
+        : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) {}
 
-  /// pragma clang section kind
-  enum PragmaClangSectionKind {
-    PCSK_Invalid      = 0,
-    PCSK_BSS          = 1,
-    PCSK_Data         = 2,
-    PCSK_Rodata       = 3,
-    PCSK_Text         = 4,
-    PCSK_Relro        = 5
-   };
+    // This is a cunning lie. DiagnosticBuilder actually performs move
+    // construction in its copy constructor (but due to varied uses, it's not
+    // possible to conveniently express this as actual move construction). So
+    // the default copy ctor here is fine, because the base class disables the
+    // source anyway, so the user-defined ~ImmediateDiagBuilder is a safe no-op
+    // in that case anwyay.
+    ImmediateDiagBuilder(const ImmediateDiagBuilder &) = default;
 
-  enum PragmaClangSectionAction {
-    PCSA_Set     = 0,
-    PCSA_Clear   = 1
-  };
+    ~ImmediateDiagBuilder() {
+      // If we aren't active, there is nothing to do.
+      if (!isActive())
+        return;
 
-  struct PragmaClangSection {
-    std::string SectionName;
-    bool Valid = false;
-    SourceLocation PragmaLocation;
-  };
+      // Otherwise, we need to emit the diagnostic. First clear the diagnostic
+      // builder itself so it won't emit the diagnostic in its own destructor.
+      //
+      // This seems wasteful, in that as written the DiagnosticBuilder dtor will
+      // do its own needless checks to see if the diagnostic needs to be
+      // emitted. However, because we take care to ensure that the builder
+      // objects never escape, a sufficiently smart compiler will be able to
+      // eliminate that code.
+      Clear();
 
-   PragmaClangSection PragmaClangBSSSection;
-   PragmaClangSection PragmaClangDataSection;
-   PragmaClangSection PragmaClangRodataSection;
-   PragmaClangSection PragmaClangRelroSection;
-   PragmaClangSection PragmaClangTextSection;
+      // Dispatch to Sema to emit the diagnostic.
+      SemaRef.EmitCurrentDiagnostic(DiagID);
+    }
 
-  enum PragmaMsStackAction {
-    PSK_Reset     = 0x0,                // #pragma ()
-    PSK_Set       = 0x1,                // #pragma (value)
-    PSK_Push      = 0x2,                // #pragma (push[, id])
-    PSK_Pop       = 0x4,                // #pragma (pop[, id])
-    PSK_Show      = 0x8,                // #pragma (show) -- only for "pack"!
-    PSK_Push_Set  = PSK_Push | PSK_Set, // #pragma (push[, id], value)
-    PSK_Pop_Set   = PSK_Pop | PSK_Set,  // #pragma (pop[, id], value)
-  };
+    /// Teach operator<< to produce an object of the correct type.
+    template 
+    friend const ImmediateDiagBuilder &
+    operator<<(const ImmediateDiagBuilder &Diag, const T &Value) {
+      const DiagnosticBuilder &BaseDiag = Diag;
+      BaseDiag << Value;
+      return Diag;
+    }
 
-  struct PragmaPackInfo {
-    PragmaMsStackAction Action;
-    StringRef SlotLabel;
-    Token Alignment;
+    // It is necessary to limit this to rvalue reference to avoid calling this
+    // function with a bitfield lvalue argument since non-const reference to
+    // bitfield is not allowed.
+    template ::value>>
+    const ImmediateDiagBuilder &operator<<(T &&V) const {
+      const DiagnosticBuilder &BaseDiag = *this;
+      BaseDiag << std::move(V);
+      return *this;
+    }
   };
 
-  // #pragma pack and align.
-  class AlignPackInfo {
+  /// A generic diagnostic builder for errors which may or may not be deferred.
+  ///
+  /// In CUDA, there exist constructs (e.g. variable-length arrays, try/catch)
+  /// which are not allowed to appear inside __device__ functions and are
+  /// allowed to appear in __host__ __device__ functions only if the host+device
+  /// function is never codegen'ed.
+  ///
+  /// To handle this, we use the notion of "deferred diagnostics", where we
+  /// attach a diagnostic to a FunctionDecl that's emitted iff it's codegen'ed.
+  ///
+  /// This class lets you emit either a regular diagnostic, a deferred
+  /// diagnostic, or no diagnostic at all, according to an argument you pass to
+  /// its constructor, thus simplifying the process of creating these "maybe
+  /// deferred" diagnostics.
+  class SemaDiagnosticBuilder {
   public:
-    // `Native` represents default align mode, which may vary based on the
-    // platform.
-    enum Mode : unsigned char { Native, Natural, Packed, Mac68k };
-
-    // #pragma pack info constructor
-    AlignPackInfo(AlignPackInfo::Mode M, unsigned Num, bool IsXL)
-        : PackAttr(true), AlignMode(M), PackNumber(Num), XLStack(IsXL) {
-      assert(Num == PackNumber && "The pack number has been truncated.");
-    }
-
-    // #pragma align info constructor
-    AlignPackInfo(AlignPackInfo::Mode M, bool IsXL)
-        : PackAttr(false), AlignMode(M),
-          PackNumber(M == Packed ? 1 : UninitPackVal), XLStack(IsXL) {}
+    enum Kind {
+      /// Emit no diagnostics.
+      K_Nop,
+      /// Emit the diagnostic immediately (i.e., behave like Sema::Diag()).
+      K_Immediate,
+      /// Emit the diagnostic immediately, and, if it's a warning or error, also
+      /// emit a call stack showing how this function can be reached by an a
+      /// priori known-emitted function.
+      K_ImmediateWithCallStack,
+      /// Create a deferred diagnostic, which is emitted only if the function
+      /// it's attached to is codegen'ed.  Also emit a call stack as with
+      /// K_ImmediateWithCallStack.
+      K_Deferred
+    };
 
-    explicit AlignPackInfo(bool IsXL) : AlignPackInfo(Native, IsXL) {}
+    SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID,
+                          const FunctionDecl *Fn, Sema &S);
+    SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D);
+    SemaDiagnosticBuilder(const SemaDiagnosticBuilder &) = default;
 
-    AlignPackInfo() : AlignPackInfo(Native, false) {}
+    // The copy and move assignment operator is defined as deleted pending
+    // further motivation.
+    SemaDiagnosticBuilder &operator=(const SemaDiagnosticBuilder &) = delete;
+    SemaDiagnosticBuilder &operator=(SemaDiagnosticBuilder &&) = delete;
 
-    // When a AlignPackInfo itself cannot be used, this returns an 32-bit
-    // integer encoding for it. This should only be passed to
-    // AlignPackInfo::getFromRawEncoding, it should not be inspected directly.
-    static uint32_t getRawEncoding(const AlignPackInfo &Info) {
-      std::uint32_t Encoding{};
-      if (Info.IsXLStack())
-        Encoding |= IsXLMask;
+    ~SemaDiagnosticBuilder();
 
-      Encoding |= static_cast(Info.getAlignMode()) << 1;
+    bool isImmediate() const { return ImmediateDiag.has_value(); }
 
-      if (Info.IsPackAttr())
-        Encoding |= PackAttrMask;
+    /// Convertible to bool: True if we immediately emitted an error, false if
+    /// we didn't emit an error or we created a deferred error.
+    ///
+    /// Example usage:
+    ///
+    ///   if (SemaDiagnosticBuilder(...) << foo << bar)
+    ///     return ExprError();
+    ///
+    /// But see CUDADiagIfDeviceCode() and CUDADiagIfHostCode() -- you probably
+    /// want to use these instead of creating a SemaDiagnosticBuilder yourself.
+    operator bool() const { return isImmediate(); }
 
-      Encoding |= static_cast(Info.getPackNumber()) << 4;
-
-      return Encoding;
+    template 
+    friend const SemaDiagnosticBuilder &
+    operator<<(const SemaDiagnosticBuilder &Diag, const T &Value) {
+      if (Diag.ImmediateDiag)
+        *Diag.ImmediateDiag << Value;
+      else if (Diag.PartialDiagId)
+        Diag.S.DeviceDeferredDiags[Diag.Fn][*Diag.PartialDiagId].second
+            << Value;
+      return Diag;
     }
 
-    static AlignPackInfo getFromRawEncoding(unsigned Encoding) {
-      bool IsXL = static_cast(Encoding & IsXLMask);
-      AlignPackInfo::Mode M =
-          static_cast((Encoding & AlignModeMask) >> 1);
-      int PackNumber = (Encoding & PackNumMask) >> 4;
+    // It is necessary to limit this to rvalue reference to avoid calling this
+    // function with a bitfield lvalue argument since non-const reference to
+    // bitfield is not allowed.
+    template ::value>>
+    const SemaDiagnosticBuilder &operator<<(T &&V) const {
+      if (ImmediateDiag)
+        *ImmediateDiag << std::move(V);
+      else if (PartialDiagId)
+        S.DeviceDeferredDiags[Fn][*PartialDiagId].second << std::move(V);
+      return *this;
+    }
 
-      if (Encoding & PackAttrMask)
-        return AlignPackInfo(M, PackNumber, IsXL);
+    friend const SemaDiagnosticBuilder &
+    operator<<(const SemaDiagnosticBuilder &Diag, const PartialDiagnostic &PD) {
+      if (Diag.ImmediateDiag)
+        PD.Emit(*Diag.ImmediateDiag);
+      else if (Diag.PartialDiagId)
+        Diag.S.DeviceDeferredDiags[Diag.Fn][*Diag.PartialDiagId].second = PD;
+      return Diag;
+    }
 
-      return AlignPackInfo(M, IsXL);
+    void AddFixItHint(const FixItHint &Hint) const {
+      if (ImmediateDiag)
+        ImmediateDiag->AddFixItHint(Hint);
+      else if (PartialDiagId)
+        S.DeviceDeferredDiags[Fn][*PartialDiagId].second.AddFixItHint(Hint);
     }
 
-    bool IsPackAttr() const { return PackAttr; }
+    friend ExprResult ExprError(const SemaDiagnosticBuilder &) {
+      return ExprError();
+    }
+    friend StmtResult StmtError(const SemaDiagnosticBuilder &) {
+      return StmtError();
+    }
+    operator ExprResult() const { return ExprError(); }
+    operator StmtResult() const { return StmtError(); }
+    operator TypeResult() const { return TypeError(); }
+    operator DeclResult() const { return DeclResult(true); }
+    operator MemInitResult() const { return MemInitResult(true); }
 
-    bool IsAlignAttr() const { return !PackAttr; }
+  private:
+    Sema &S;
+    SourceLocation Loc;
+    unsigned DiagID;
+    const FunctionDecl *Fn;
+    bool ShowCallStack;
 
-    Mode getAlignMode() const { return AlignMode; }
+    // Invariant: At most one of these Optionals has a value.
+    // FIXME: Switch these to a Variant once that exists.
+    std::optional ImmediateDiag;
+    std::optional PartialDiagId;
+  };
 
-    unsigned getPackNumber() const { return PackNumber; }
+  void PrintStats() const;
 
-    bool IsPackSet() const {
-      // #pragma align, #pragma pack(), and #pragma pack(0) do not set the pack
-      // attriute on a decl.
-      return PackNumber != UninitPackVal && PackNumber != 0;
-    }
+  /// Warn that the stack is nearly exhausted.
+  void warnStackExhausted(SourceLocation Loc);
 
-    bool IsXLStack() const { return XLStack; }
+  /// Run some code with "sufficient" stack space. (Currently, at least 256K is
+  /// guaranteed). Produces a warning if we're low on stack space and allocates
+  /// more in that case. Use this in code that may recurse deeply (for example,
+  /// in template instantiation) to avoid stack overflow.
+  void runWithSufficientStackSpace(SourceLocation Loc,
+                                   llvm::function_ref Fn);
 
-    bool operator==(const AlignPackInfo &Info) const {
-      return std::tie(AlignMode, PackNumber, PackAttr, XLStack) ==
-             std::tie(Info.AlignMode, Info.PackNumber, Info.PackAttr,
-                      Info.XLStack);
-    }
+  /// Returns default addr space for method qualifiers.
+  LangAS getDefaultCXXMethodAddrSpace() const;
 
-    bool operator!=(const AlignPackInfo &Info) const {
-      return !(*this == Info);
-    }
+  /// Load weak undeclared identifiers from the external source.
+  void LoadExternalWeakUndeclaredIdentifiers();
 
-  private:
-    /// \brief True if this is a pragma pack attribute,
-    ///         not a pragma align attribute.
-    bool PackAttr;
+  /// Determine if VD, which must be a variable or function, is an external
+  /// symbol that nonetheless can't be referenced from outside this translation
+  /// unit because its type has no linkage and it's not extern "C".
+  bool isExternalWithNoLinkageType(const ValueDecl *VD) const;
 
-    /// \brief The alignment mode that is in effect.
-    Mode AlignMode;
+  /// Obtain a sorted list of functions that are undefined but ODR-used.
+  void getUndefinedButUsed(
+      SmallVectorImpl> &Undefined);
 
-    /// \brief The pack number of the stack.
-    unsigned char PackNumber;
+  typedef std::pair DeleteExprLoc;
+  typedef llvm::SmallVector DeleteLocs;
+  /// Retrieves list of suspicious delete-expressions that will be checked at
+  /// the end of translation unit.
+  const llvm::MapVector &
+  getMismatchingDeleteExpressions() const;
 
-    /// \brief True if it is a XL #pragma align/pack stack.
-    bool XLStack;
+  /// Cause the active diagnostic on the DiagosticsEngine to be
+  /// emitted. This is closely coupled to the SemaDiagnosticBuilder class and
+  /// should not be used elsewhere.
+  void EmitCurrentDiagnostic(unsigned DiagID);
 
-    /// \brief Uninitialized pack value.
-    static constexpr unsigned char UninitPackVal = -1;
+  void addImplicitTypedef(StringRef Name, QualType T);
 
-    // Masks to encode and decode an AlignPackInfo.
-    static constexpr uint32_t IsXLMask{0x0000'0001};
-    static constexpr uint32_t AlignModeMask{0x0000'0006};
-    static constexpr uint32_t PackAttrMask{0x00000'0008};
-    static constexpr uint32_t PackNumMask{0x0000'01F0};
-  };
+  /// Emit a diagnostic.
+  SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID,
+                             bool DeferHint = false);
 
-  template
-  struct PragmaStack {
-    struct Slot {
-      llvm::StringRef StackSlotLabel;
-      ValueType Value;
-      SourceLocation PragmaLocation;
-      SourceLocation PragmaPushLocation;
-      Slot(llvm::StringRef StackSlotLabel, ValueType Value,
-           SourceLocation PragmaLocation, SourceLocation PragmaPushLocation)
-          : StackSlotLabel(StackSlotLabel), Value(Value),
-            PragmaLocation(PragmaLocation),
-            PragmaPushLocation(PragmaPushLocation) {}
-    };
+  /// Emit a partial diagnostic.
+  SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic &PD,
+                             bool DeferHint = false);
 
-    void Act(SourceLocation PragmaLocation, PragmaMsStackAction Action,
-             llvm::StringRef StackSlotLabel, ValueType Value) {
-      if (Action == PSK_Reset) {
-        CurrentValue = DefaultValue;
-        CurrentPragmaLocation = PragmaLocation;
-        return;
-      }
-      if (Action & PSK_Push)
-        Stack.emplace_back(StackSlotLabel, CurrentValue, CurrentPragmaLocation,
-                           PragmaLocation);
-      else if (Action & PSK_Pop) {
-        if (!StackSlotLabel.empty()) {
-          // If we've got a label, try to find it and jump there.
-          auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) {
-            return x.StackSlotLabel == StackSlotLabel;
-          });
-          // If we found the label so pop from there.
-          if (I != Stack.rend()) {
-            CurrentValue = I->Value;
-            CurrentPragmaLocation = I->PragmaLocation;
-            Stack.erase(std::prev(I.base()), Stack.end());
-          }
-        } else if (!Stack.empty()) {
-          // We do not have a label, just pop the last entry.
-          CurrentValue = Stack.back().Value;
-          CurrentPragmaLocation = Stack.back().PragmaLocation;
-          Stack.pop_back();
-        }
-      }
-      if (Action & PSK_Set) {
-        CurrentValue = Value;
-        CurrentPragmaLocation = PragmaLocation;
-      }
-    }
+  /// Whether uncompilable error has occurred. This includes error happens
+  /// in deferred diagnostics.
+  bool hasUncompilableErrorOccurred() const;
 
-    // MSVC seems to add artificial slots to #pragma stacks on entering a C++
-    // method body to restore the stacks on exit, so it works like this:
-    //
-    //   struct S {
-    //     #pragma (push, InternalPragmaSlot, )
-    //     void Method {}
-    //     #pragma (pop, InternalPragmaSlot)
-    //   };
-    //
-    // It works even with #pragma vtordisp, although MSVC doesn't support
-    //   #pragma vtordisp(push [, id], n)
-    // syntax.
-    //
-    // Push / pop a named sentinel slot.
-    void SentinelAction(PragmaMsStackAction Action, StringRef Label) {
-      assert((Action == PSK_Push || Action == PSK_Pop) &&
-             "Can only push / pop #pragma stack sentinels!");
-      Act(CurrentPragmaLocation, Action, Label, CurrentValue);
-    }
+  bool findMacroSpelling(SourceLocation &loc, StringRef name);
 
-    // Constructors.
-    explicit PragmaStack(const ValueType &Default)
-        : DefaultValue(Default), CurrentValue(Default) {}
+  /// Calls \c Lexer::getLocForEndOfToken()
+  SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0);
 
-    bool hasValue() const { return CurrentValue != DefaultValue; }
+  /// Retrieve the module loader associated with the preprocessor.
+  ModuleLoader &getModuleLoader() const;
 
-    SmallVector Stack;
-    ValueType DefaultValue; // Value used for PSK_Reset action.
-    ValueType CurrentValue;
-    SourceLocation CurrentPragmaLocation;
-  };
-  // FIXME: We should serialize / deserialize these if they occur in a PCH (but
-  // we shouldn't do so if they're in a module).
+  /// Invent a new identifier for parameters of abbreviated templates.
+  IdentifierInfo *
+  InventAbbreviatedTemplateParameterTypeName(IdentifierInfo *ParamName,
+                                             unsigned Index);
 
-  /// Whether to insert vtordisps prior to virtual bases in the Microsoft
-  /// C++ ABI.  Possible values are 0, 1, and 2, which mean:
-  ///
-  /// 0: Suppress all vtordisps
-  /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial
-  ///    structors
-  /// 2: Always insert vtordisps to support RTTI on partially constructed
-  ///    objects
-  PragmaStack VtorDispStack;
-  PragmaStack AlignPackStack;
-  // The current #pragma align/pack values and locations at each #include.
-  struct AlignPackIncludeState {
-    AlignPackInfo CurrentValue;
-    SourceLocation CurrentPragmaLocation;
-    bool HasNonDefaultValue, ShouldWarnOnInclude;
-  };
-  SmallVector AlignPackIncludeStack;
-  // Segment #pragmas.
-  PragmaStack DataSegStack;
-  PragmaStack BSSSegStack;
-  PragmaStack ConstSegStack;
-  PragmaStack CodeSegStack;
+  void emitAndClearUnusedLocalTypedefWarnings();
 
-  // #pragma strict_gs_check.
-  PragmaStack StrictGuardStackCheckStack;
+  // Emit all deferred diagnostics.
+  void emitDeferredDiags();
 
-  // This stack tracks the current state of Sema.CurFPFeatures.
-  PragmaStack FpPragmaStack;
-  FPOptionsOverride CurFPFeatureOverrides() {
-    FPOptionsOverride result;
-    if (!FpPragmaStack.hasValue()) {
-      result = FPOptionsOverride();
-    } else {
-      result = FpPragmaStack.CurrentValue;
-    }
-    return result;
-  }
-
-  // Saves the current floating-point pragma stack and clear it in this Sema.
-  class FpPragmaStackSaveRAII {
-  public:
-    FpPragmaStackSaveRAII(Sema &S)
-        : S(S), SavedStack(std::move(S.FpPragmaStack)) {
-      S.FpPragmaStack.Stack.clear();
-    }
-    ~FpPragmaStackSaveRAII() { S.FpPragmaStack = std::move(SavedStack); }
-
-  private:
-    Sema &S;
-    PragmaStack SavedStack;
+  enum TUFragmentKind {
+    /// The global module fragment, between 'module;' and a module-declaration.
+    Global,
+    /// A normal translation unit fragment. For a non-module unit, this is the
+    /// entire translation unit. Otherwise, it runs from the module-declaration
+    /// to the private-module-fragment (if any) or the end of the TU (if not).
+    Normal,
+    /// The private module fragment, between 'module :private;' and the end of
+    /// the translation unit.
+    Private
   };
 
-  void resetFPOptions(FPOptions FPO) {
-    CurFPFeatures = FPO;
-    FpPragmaStack.CurrentValue = FPO.getChangesFrom(FPOptions(LangOpts));
-  }
-
-  // RAII object to push / pop sentinel slots for all MS #pragma stacks.
-  // Actions should be performed only if we enter / exit a C++ method body.
-  class PragmaStackSentinelRAII {
-  public:
-    PragmaStackSentinelRAII(Sema &S, StringRef SlotLabel, bool ShouldAct);
-    ~PragmaStackSentinelRAII();
+  void ActOnStartOfTranslationUnit();
+  void ActOnEndOfTranslationUnit();
+  void ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind);
 
-  private:
-    Sema &S;
-    StringRef SlotLabel;
-    bool ShouldAct;
-  };
+  Scope *getScopeForContext(DeclContext *Ctx);
 
-  /// A mapping that describes the nullability we've seen in each header file.
-  FileNullabilityMap NullabilityMap;
+  void PushFunctionScope();
+  void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
+  sema::LambdaScopeInfo *PushLambdaScope();
 
-  /// Last section used with #pragma init_seg.
-  StringLiteral *CurInitSeg;
-  SourceLocation CurInitSegLoc;
+  /// This is used to inform Sema what the current TemplateParameterDepth
+  /// is during Parsing.  Currently it is used to pass on the depth
+  /// when parsing generic lambda 'auto' parameters.
+  void RecordParsingTemplateParameterDepth(unsigned Depth);
 
-  /// Sections used with #pragma alloc_text.
-  llvm::StringMap> FunctionToSectionMap;
+  void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
+                               RecordDecl *RD, CapturedRegionKind K,
+                               unsigned OpenMPCaptureLevel = 0);
 
-  /// VisContext - Manages the stack for \#pragma GCC visibility.
-  void *VisContext; // Really a "PragmaVisStack*"
+  /// Custom deleter to allow FunctionScopeInfos to be kept alive for a short
+  /// time after they've been popped.
+  class PoppedFunctionScopeDeleter {
+    Sema *Self;
 
-  /// This an attribute introduced by \#pragma clang attribute.
-  struct PragmaAttributeEntry {
-    SourceLocation Loc;
-    ParsedAttr *Attribute;
-    SmallVector MatchRules;
-    bool IsUsed;
+  public:
+    explicit PoppedFunctionScopeDeleter(Sema *Self) : Self(Self) {}
+    void operator()(sema::FunctionScopeInfo *Scope) const;
   };
 
-  /// A push'd group of PragmaAttributeEntries.
-  struct PragmaAttributeGroup {
-    /// The location of the push attribute.
-    SourceLocation Loc;
-    /// The namespace of this push group.
-    const IdentifierInfo *Namespace;
-    SmallVector Entries;
-  };
+  using PoppedFunctionScopePtr =
+      std::unique_ptr;
 
-  SmallVector PragmaAttributeStack;
+  PoppedFunctionScopePtr
+  PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP = nullptr,
+                       const Decl *D = nullptr,
+                       QualType BlockType = QualType());
 
-  /// The declaration that is currently receiving an attribute from the
-  /// #pragma attribute stack.
-  const Decl *PragmaAttributeCurrentTargetDecl;
+  sema::FunctionScopeInfo *getEnclosingFunction() const;
 
-  /// This represents the last location of a "#pragma clang optimize off"
-  /// directive if such a directive has not been closed by an "on" yet. If
-  /// optimizations are currently "on", this is set to an invalid location.
-  SourceLocation OptimizeOffPragmaLocation;
+  void setFunctionHasBranchIntoScope();
+  void setFunctionHasBranchProtectedScope();
+  void setFunctionHasIndirectGoto();
+  void setFunctionHasMustTail();
 
-  /// The "on" or "off" argument passed by \#pragma optimize, that denotes
-  /// whether the optimizations in the list passed to the pragma should be
-  /// turned off or on. This boolean is true by default because command line
-  /// options are honored when `#pragma optimize("", on)`.
-  /// (i.e. `ModifyFnAttributeMSPragmaOptimze()` does nothing)
-  bool MSPragmaOptimizeIsOn = true;
+  void PushCompoundScope(bool IsStmtExpr);
+  void PopCompoundScope();
 
-  /// Set of no-builtin functions listed by \#pragma function.
-  llvm::SmallSetVector MSFunctionNoBuiltins;
+  bool hasAnyUnrecoverableErrorsInThisFunction() const;
 
-  /// Flag indicating if Sema is building a recovery call expression.
-  ///
-  /// This flag is used to avoid building recovery call expressions
-  /// if Sema is already doing so, which would cause infinite recursions.
-  bool IsBuildingRecoveryCallExpr;
+  /// Retrieve the current block, if any.
+  sema::BlockScopeInfo *getCurBlock();
 
-  /// Used to control the generation of ExprWithCleanups.
-  CleanupInfo Cleanup;
+  /// Get the innermost lambda enclosing the current location, if any. This
+  /// looks through intervening non-lambda scopes such as local functions and
+  /// blocks.
+  sema::LambdaScopeInfo *getEnclosingLambda() const;
 
-  /// ExprCleanupObjects - This is the stack of objects requiring
-  /// cleanup that are created by the current full expression.
-  SmallVector ExprCleanupObjects;
+  /// Retrieve the current lambda scope info, if any.
+  /// \param IgnoreNonLambdaCapturingScope true if should find the top-most
+  /// lambda scope info ignoring all inner capturing scopes that are not
+  /// lambda scopes.
+  sema::LambdaScopeInfo *
+  getCurLambda(bool IgnoreNonLambdaCapturingScope = false);
 
-  /// Store a set of either DeclRefExprs or MemberExprs that contain a reference
-  /// to a variable (constant) that may or may not be odr-used in this Expr, and
-  /// we won't know until all lvalue-to-rvalue and discarded value conversions
-  /// have been applied to all subexpressions of the enclosing full expression.
-  /// This is cleared at the end of each full expression.
-  using MaybeODRUseExprSet = llvm::SmallSetVector;
-  MaybeODRUseExprSet MaybeODRUseExprs;
+  /// Retrieve the current generic lambda info, if any.
+  sema::LambdaScopeInfo *getCurGenericLambda();
 
-  std::unique_ptr CachedFunctionScope;
+  /// Retrieve the current captured region, if any.
+  sema::CapturedRegionScopeInfo *getCurCapturedRegion();
 
-  /// Stack containing information about each of the nested
-  /// function, block, and method scopes that are currently active.
-  SmallVector FunctionScopes;
+  void ActOnComment(SourceRange Comment);
 
-  /// The index of the first FunctionScope that corresponds to the current
-  /// context.
-  unsigned FunctionScopesStart = 0;
+  /// Retrieve the parser's current scope.
+  ///
+  /// This routine must only be used when it is certain that semantic analysis
+  /// and the parser are in precisely the same context, which is not the case
+  /// when, e.g., we are performing any kind of template instantiation.
+  /// Therefore, the only safe places to use this scope are in the parser
+  /// itself and in routines directly invoked from the parser and *never* from
+  /// template substitution or instantiation.
+  Scope *getCurScope() const { return CurScope; }
 
-  /// Track the number of currently active capturing scopes.
-  unsigned CapturingFunctionScopes = 0;
+  IdentifierInfo *getSuperIdentifier() const;
 
-  ArrayRef getFunctionScopes() const {
-    return llvm::ArrayRef(FunctionScopes.begin() + FunctionScopesStart,
-                          FunctionScopes.end());
+  DeclContext *getCurLexicalContext() const {
+    return OriginalLexicalContext ? OriginalLexicalContext : CurContext;
   }
 
-  /// Stack containing information needed when in C++2a an 'auto' is encountered
-  /// in a function declaration parameter type specifier in order to invent a
-  /// corresponding template parameter in the enclosing abbreviated function
-  /// template. This information is also present in LambdaScopeInfo, stored in
-  /// the FunctionScopes stack.
-  SmallVector InventedParameterInfos;
+  SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID,
+                                   const FunctionDecl *FD = nullptr);
+  SemaDiagnosticBuilder targetDiag(SourceLocation Loc,
+                                   const PartialDiagnostic &PD,
+                                   const FunctionDecl *FD = nullptr) {
+    return targetDiag(Loc, PD.getDiagID(), FD) << PD;
+  }
 
-  /// The index of the first InventedParameterInfo that refers to the current
-  /// context.
-  unsigned InventedParameterInfosStart = 0;
+  /// Check if the type is allowed to be used for the current target.
+  void checkTypeSupport(QualType Ty, SourceLocation Loc,
+                        ValueDecl *D = nullptr);
 
-  ArrayRef getInventedParameterInfos() const {
-    return llvm::ArrayRef(InventedParameterInfos.begin() +
-                              InventedParameterInfosStart,
-                          InventedParameterInfos.end());
-  }
+  /// The kind of conversion being performed.
+  enum CheckedConversionKind {
+    /// An implicit conversion.
+    CCK_ImplicitConversion,
+    /// A C-style cast.
+    CCK_CStyleCast,
+    /// A functional-style cast.
+    CCK_FunctionalCast,
+    /// A cast other than a C-style cast.
+    CCK_OtherCast,
+    /// A conversion for an operand of a builtin overloaded operator.
+    CCK_ForBuiltinOverloadedOp
+  };
 
-  typedef LazyVector
-    ExtVectorDeclsType;
+  /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit
+  /// cast.  If there is already an implicit cast, merge into the existing one.
+  /// If isLvalue, the result of the cast is an lvalue.
+  ExprResult
+  ImpCastExprToType(Expr *E, QualType Type, CastKind CK,
+                    ExprValueKind VK = VK_PRValue,
+                    const CXXCastPath *BasePath = nullptr,
+                    CheckedConversionKind CCK = CCK_ImplicitConversion);
 
-  /// ExtVectorDecls - This is a list all the extended vector types. This allows
-  /// us to associate a raw vector type with one of the ext_vector type names.
-  /// This is only necessary for issuing pretty diagnostics.
-  ExtVectorDeclsType ExtVectorDecls;
+  /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
+  /// to the conversion from scalar type ScalarTy to the Boolean type.
+  static CastKind ScalarTypeToBooleanCastKind(QualType ScalarTy);
 
-  /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
-  std::unique_ptr FieldCollector;
+  /// If \p AllowLambda is true, treat lambda as function.
+  DeclContext *getFunctionLevelDeclContext(bool AllowLambda = false) const;
 
-  typedef llvm::SmallSetVector NamedDeclSetType;
+  /// Returns a pointer to the innermost enclosing function, or nullptr if the
+  /// current context is not inside a function. If \p AllowLambda is true,
+  /// this can return the call operator of an enclosing lambda, otherwise
+  /// lambdas are skipped when looking for an enclosing function.
+  FunctionDecl *getCurFunctionDecl(bool AllowLambda = false) const;
 
-  /// Set containing all declared private fields that are not used.
-  NamedDeclSetType UnusedPrivateFields;
+  /// getCurMethodDecl - If inside of a method body, this returns a pointer to
+  /// the method decl for the method being parsed.  If we're currently
+  /// in a 'block', this returns the containing context.
+  ObjCMethodDecl *getCurMethodDecl();
 
-  /// Set containing all typedefs that are likely unused.
-  llvm::SmallSetVector
-      UnusedLocalTypedefNameCandidates;
+  /// getCurFunctionOrMethodDecl - Return the Decl for the current ObjC method
+  /// or C function we're in, otherwise return null.  If we're currently
+  /// in a 'block', this returns the containing context.
+  NamedDecl *getCurFunctionOrMethodDecl() const;
 
-  /// Delete-expressions to be analyzed at the end of translation unit
+  /// Warn if we're implicitly casting from a _Nullable pointer type to a
+  /// _Nonnull one.
+  void diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType,
+                                           SourceLocation Loc);
+
+  /// Warn when implicitly casting 0 to nullptr.
+  void diagnoseZeroToNullptrConversion(CastKind Kind, const Expr *E);
+
+  bool makeUnavailableInSystemHeader(SourceLocation loc,
+                                     UnavailableAttr::ImplicitReason reason);
+
+  /// Retrieve a suitable printing policy for diagnostics.
+  PrintingPolicy getPrintingPolicy() const {
+    return getPrintingPolicy(Context, PP);
+  }
+
+  /// Retrieve a suitable printing policy for diagnostics.
+  static PrintingPolicy getPrintingPolicy(const ASTContext &Ctx,
+                                          const Preprocessor &PP);
+
+  /// Scope actions.
+  void ActOnTranslationUnitScope(Scope *S);
+
+  /// Determine whether \param D is function like (function or function
+  /// template) for parsing.
+  bool isDeclaratorFunctionLike(Declarator &D);
+
+  /// The maximum alignment, same as in llvm::Value. We duplicate them here
+  /// because that allows us not to duplicate the constants in clang code,
+  /// which we must to since we can't directly use the llvm constants.
+  /// The value is verified against llvm here: lib/CodeGen/CGDecl.cpp
   ///
-  /// This list contains class members, and locations of delete-expressions
-  /// that could not be proven as to whether they mismatch with new-expression
-  /// used in initializer of the field.
-  typedef std::pair DeleteExprLoc;
-  typedef llvm::SmallVector DeleteLocs;
-  llvm::MapVector DeleteExprs;
+  /// This is the greatest alignment value supported by load, store, and alloca
+  /// instructions, and global values.
+  static const unsigned MaxAlignmentExponent = 32;
+  static const uint64_t MaximumAlignment = 1ull << MaxAlignmentExponent;
 
-  typedef llvm::SmallPtrSet RecordDeclSetTy;
+  /// Flag indicating whether or not to collect detailed statistics.
+  bool CollectStats;
 
-  /// PureVirtualClassDiagSet - a set of class declarations which we have
-  /// emitted a list of pure virtual functions. Used to prevent emitting the
-  /// same list more than once.
-  std::unique_ptr PureVirtualClassDiagSet;
+  std::unique_ptr CachedFunctionScope;
 
-  /// ParsingInitForAutoVars - a set of declarations with auto types for which
-  /// we are currently parsing the initializer.
-  llvm::SmallPtrSet ParsingInitForAutoVars;
+  /// Stack containing information about each of the nested
+  /// function, block, and method scopes that are currently active.
+  SmallVector FunctionScopes;
 
-  /// Look for a locally scoped extern "C" declaration by the given name.
-  NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name);
+  /// The index of the first FunctionScope that corresponds to the current
+  /// context.
+  unsigned FunctionScopesStart = 0;
 
-  typedef LazyVector
-    TentativeDefinitionsType;
+  /// Track the number of currently active capturing scopes.
+  unsigned CapturingFunctionScopes = 0;
 
-  /// All the tentative definitions encountered in the TU.
-  TentativeDefinitionsType TentativeDefinitions;
+  llvm::BumpPtrAllocator BumpAlloc;
 
-  /// All the external declarations encoutered and used in the TU.
-  SmallVector ExternalDeclarations;
+  /// The kind of translation unit we are processing.
+  ///
+  /// When we're processing a complete translation unit, Sema will perform
+  /// end-of-translation-unit semantic tasks (such as creating
+  /// initializers for tentative definitions in C) once parsing has
+  /// completed. Modules and precompiled headers perform different kinds of
+  /// checks.
+  const TranslationUnitKind TUKind;
 
-  typedef LazyVector
-    UnusedFileScopedDeclsType;
+  /// Translation Unit Scope - useful to Objective-C actions that need
+  /// to lookup file scope declarations in the "ordinary" C decl namespace.
+  /// For example, user-defined classes, built-in "id" type, etc.
+  Scope *TUScope;
 
-  /// The set of file scoped decls seen so far that have not been used
-  /// and must warn if not used. Only contains the first declaration.
-  UnusedFileScopedDeclsType UnusedFileScopedDecls;
+  bool WarnedStackExhausted = false;
 
-  typedef LazyVector
-    DelegatingCtorDeclsType;
+  void incrementMSManglingNumber() const {
+    return CurScope->incrementMSManglingNumber();
+  }
 
-  /// All the delegating constructors seen so far in the file, used for
-  /// cycle detection at the end of the TU.
-  DelegatingCtorDeclsType DelegatingCtorDecls;
+  /// Try to recover by turning the given expression into a
+  /// call.  Returns true if recovery was attempted or an error was
+  /// emitted; this may also leave the ExprResult invalid.
+  bool tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
+                            bool ForceComplain = false,
+                            bool (*IsPlausibleResult)(QualType) = nullptr);
 
-  /// All the overriding functions seen during a class definition
-  /// that had their exception spec checks delayed, plus the overridden
-  /// function.
-  SmallVector, 2>
-    DelayedOverridingExceptionSpecChecks;
+  /// Figure out if an expression could be turned into a call.
+  bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
+                     UnresolvedSetImpl &NonTemplateOverloads);
 
-  /// All the function redeclarations seen during a class definition that had
-  /// their exception spec checks delayed, plus the prior declaration they
-  /// should be checked against. Except during error recovery, the new decl
-  /// should always be a friend declaration, as that's the only valid way to
-  /// redeclare a special member before its class is complete.
-  SmallVector, 2>
-    DelayedEquivalentExceptionSpecChecks;
+  typedef OpaquePtr DeclGroupPtrTy;
+  typedef OpaquePtr TemplateTy;
+  typedef OpaquePtr TypeTy;
 
-  typedef llvm::MapVector>
-      LateParsedTemplateMapT;
-  LateParsedTemplateMapT LateParsedTemplateMap;
+  OpenCLOptions OpenCLFeatures;
+  FPOptions CurFPFeatures;
+
+  const LangOptions &LangOpts;
+  Preprocessor &PP;
+  ASTContext &Context;
+  ASTConsumer &Consumer;
+  DiagnosticsEngine &Diags;
+  SourceManager &SourceMgr;
+  api_notes::APINotesManager APINotes;
+
+  /// A RAII object to enter scope of a compound statement.
+  class CompoundScopeRAII {
+  public:
+    CompoundScopeRAII(Sema &S, bool IsStmtExpr = false) : S(S) {
+      S.ActOnStartOfCompoundStmt(IsStmtExpr);
+    }
+
+    ~CompoundScopeRAII() { S.ActOnFinishOfCompoundStmt(); }
+
+  private:
+    Sema &S;
+  };
+
+  /// An RAII helper that pops function a function scope on exit.
+  struct FunctionScopeRAII {
+    Sema &S;
+    bool Active;
+    FunctionScopeRAII(Sema &S) : S(S), Active(true) {}
+    ~FunctionScopeRAII() {
+      if (Active)
+        S.PopFunctionScopeInfo();
+    }
+    void disable() { Active = false; }
+  };
+
+  /// Build a partial diagnostic.
+  PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h
+
+  sema::FunctionScopeInfo *getCurFunction() const {
+    return FunctionScopes.empty() ? nullptr : FunctionScopes.back();
+  }
+
+  /// Worker object for performing CFG-based warnings.
+  sema::AnalysisBasedWarnings AnalysisWarnings;
+  threadSafety::BeforeSet *ThreadSafetyDeclCache;
 
   /// Callback to the parser to parse templated functions when needed.
   typedef void LateTemplateParserCB(void *P, LateParsedTemplate &LPT);
@@ -1016,8 +1077,7 @@ public:
   void *OpaqueParser;
 
   void SetLateTemplateParser(LateTemplateParserCB *LTP,
-                             LateTemplateParserCleanupCB *LTPCleanup,
-                             void *P) {
+                             LateTemplateParserCleanupCB *LTPCleanup, void *P) {
     LateTemplateParser = LTP;
     LateTemplateParserCleanup = LTPCleanup;
     OpaqueParser = P;
@@ -1027,6 +1087,14 @@ public:
   std::function
       ParseTypeFromStringCallback;
 
+  /// VAListTagName - The declaration name corresponding to __va_list_tag.
+  /// This is used as part of a hack to omit that class from ADL results.
+  DeclarationName VAListTagName;
+
+  /// Is the last error level diagnostic immediate. This is used to determined
+  /// whether the next info diagnostic should be immediate.
+  bool IsLastErrorImmediate = true;
+
   class DelayedDiagnostics;
 
   class DelayedDiagnosticsState {
@@ -1053,9 +1121,7 @@ public:
     bool shouldDelayDiagnostics() { return CurPool != nullptr; }
 
     /// Returns the current delayed-diagnostics pool.
-    sema::DelayedDiagnosticPool *getCurrentPool() const {
-      return CurPool;
-    }
+    sema::DelayedDiagnosticPool *getCurrentPool() const { return CurPool; }
 
     /// Enter a new scope.  Access and deprecation diagnostics will be
     /// collected in this pool.
@@ -1089,1657 +1155,1626 @@ public:
     }
   } DelayedDiagnostics;
 
-  enum CUDAFunctionTarget {
-    CFT_Device,
-    CFT_Global,
-    CFT_Host,
-    CFT_HostDevice,
-    CFT_InvalidTarget
-  };
+  ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) {
+    return DelayedDiagnostics.push(pool);
+  }
 
-  /// A RAII object to temporarily push a declaration context.
-  class ContextRAII {
-  private:
-    Sema &S;
-    DeclContext *SavedContext;
-    ProcessingContextState SavedContextState;
-    QualType SavedCXXThisTypeOverride;
-    unsigned SavedFunctionScopesStart;
-    unsigned SavedInventedParameterInfosStart;
+  /// CurContext - This is the current declaration context of parsing.
+  DeclContext *CurContext;
 
-  public:
-    ContextRAII(Sema &S, DeclContext *ContextToPush, bool NewThisContext = true)
-      : S(S), SavedContext(S.CurContext),
-        SavedContextState(S.DelayedDiagnostics.pushUndelayed()),
-        SavedCXXThisTypeOverride(S.CXXThisTypeOverride),
-        SavedFunctionScopesStart(S.FunctionScopesStart),
-        SavedInventedParameterInfosStart(S.InventedParameterInfosStart)
-    {
-      assert(ContextToPush && "pushing null context");
-      S.CurContext = ContextToPush;
-      if (NewThisContext)
-        S.CXXThisTypeOverride = QualType();
-      // Any saved FunctionScopes do not refer to this context.
-      S.FunctionScopesStart = S.FunctionScopes.size();
-      S.InventedParameterInfosStart = S.InventedParameterInfos.size();
-    }
+protected:
+  friend class Parser;
+  friend class InitializationSequence;
+  friend class ASTReader;
+  friend class ASTDeclReader;
+  friend class ASTWriter;
 
-    void pop() {
-      if (!SavedContext) return;
-      S.CurContext = SavedContext;
-      S.DelayedDiagnostics.popUndelayed(SavedContextState);
-      S.CXXThisTypeOverride = SavedCXXThisTypeOverride;
-      S.FunctionScopesStart = SavedFunctionScopesStart;
-      S.InventedParameterInfosStart = SavedInventedParameterInfosStart;
-      SavedContext = nullptr;
-    }
+private:
+  std::optional> CachedDarwinSDKInfo;
+  bool WarnedDarwinSDKInfoMissing = false;
 
-    ~ContextRAII() {
-      pop();
-    }
-  };
+  Sema(const Sema &) = delete;
+  void operator=(const Sema &) = delete;
 
-  /// RAII object to handle the state changes required to synthesize
-  /// a function body.
-  class SynthesizedFunctionScope {
-    Sema &S;
-    Sema::ContextRAII SavedContext;
-    bool PushedCodeSynthesisContext = false;
+  /// Source of additional semantic information.
+  IntrusiveRefCntPtr ExternalSource;
 
-  public:
-    SynthesizedFunctionScope(Sema &S, DeclContext *DC)
-        : S(S), SavedContext(S, DC) {
-      auto *FD = dyn_cast(DC);
-      S.PushFunctionScope();
-      S.PushExpressionEvaluationContext(
-          (FD && FD->isConsteval())
-              ? ExpressionEvaluationContext::ImmediateFunctionContext
-              : ExpressionEvaluationContext::PotentiallyEvaluated);
-      if (FD) {
-        FD->setWillHaveBody(true);
-        S.ExprEvalContexts.back().InImmediateFunctionContext =
-            FD->isImmediateFunction() ||
-            S.ExprEvalContexts[S.ExprEvalContexts.size() - 2]
-                .isConstantEvaluated();
-        S.ExprEvalContexts.back().InImmediateEscalatingFunctionContext =
-            S.getLangOpts().CPlusPlus20 && FD->isImmediateEscalating();
-      } else
-        assert(isa(DC));
-    }
+  /// The handler for the FileChanged preprocessor events.
+  ///
+  /// Used for diagnostics that implement custom semantic analysis for #include
+  /// directives, like -Wpragma-pack.
+  sema::SemaPPCallbacks *SemaPPCallbackHandler;
 
-    void addContextNote(SourceLocation UseLoc) {
-      assert(!PushedCodeSynthesisContext);
+  /// The parser's current scope.
+  ///
+  /// The parser maintains this state here.
+  Scope *CurScope;
 
-      Sema::CodeSynthesisContext Ctx;
-      Ctx.Kind = Sema::CodeSynthesisContext::DefiningSynthesizedFunction;
-      Ctx.PointOfInstantiation = UseLoc;
-      Ctx.Entity = cast(S.CurContext);
-      S.pushCodeSynthesisContext(Ctx);
+  mutable IdentifierInfo *Ident_super;
 
-      PushedCodeSynthesisContext = true;
-    }
+  ///@}
 
-    ~SynthesizedFunctionScope() {
-      if (PushedCodeSynthesisContext)
-        S.popCodeSynthesisContext();
-      if (auto *FD = dyn_cast(S.CurContext)) {
-        FD->setWillHaveBody(false);
-        S.CheckImmediateEscalatingFunctionDefinition(FD, S.getCurFunction());
-      }
-      S.PopExpressionEvaluationContext();
-      S.PopFunctionScopeInfo();
-    }
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \name C++ Access Control
+  /// Implementations are in SemaAccess.cpp
+  ///@{
+
+public:
+  enum AccessResult {
+    AR_accessible,
+    AR_inaccessible,
+    AR_dependent,
+    AR_delayed
   };
 
-  /// WeakUndeclaredIdentifiers - Identifiers contained in \#pragma weak before
-  /// declared. Rare. May alias another identifier, declared or undeclared.
-  ///
-  /// For aliases, the target identifier is used as a key for eventual
-  /// processing when the target is declared. For the single-identifier form,
-  /// the sole identifier is used as the key. Each entry is a `SetVector`
-  /// (ordered by parse order) of aliases (identified by the alias name) in case
-  /// of multiple aliases to the same undeclared identifier.
-  llvm::MapVector<
-      IdentifierInfo *,
-      llvm::SetVector<
-          WeakInfo, llvm::SmallVector,
-          llvm::SmallDenseSet>>
-      WeakUndeclaredIdentifiers;
+  bool SetMemberAccessSpecifier(NamedDecl *MemberDecl,
+                                NamedDecl *PrevMemberDecl,
+                                AccessSpecifier LexicalAS);
 
-  /// ExtnameUndeclaredIdentifiers - Identifiers contained in
-  /// \#pragma redefine_extname before declared.  Used in Solaris system headers
-  /// to define functions that occur in multiple standards to call the version
-  /// in the currently selected standard.
-  llvm::DenseMap ExtnameUndeclaredIdentifiers;
+  AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
+                                           DeclAccessPair FoundDecl);
+  AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
+                                           DeclAccessPair FoundDecl);
+  AccessResult CheckAllocationAccess(SourceLocation OperatorLoc,
+                                     SourceRange PlacementRange,
+                                     CXXRecordDecl *NamingClass,
+                                     DeclAccessPair FoundDecl,
+                                     bool Diagnose = true);
+  AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D,
+                                      DeclAccessPair FoundDecl,
+                                      const InitializedEntity &Entity,
+                                      bool IsCopyBindingRefToTemp = false);
+  AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D,
+                                      DeclAccessPair FoundDecl,
+                                      const InitializedEntity &Entity,
+                                      const PartialDiagnostic &PDiag);
+  AccessResult CheckDestructorAccess(SourceLocation Loc,
+                                     CXXDestructorDecl *Dtor,
+                                     const PartialDiagnostic &PDiag,
+                                     QualType objectType = QualType());
+  AccessResult CheckFriendAccess(NamedDecl *D);
+  AccessResult CheckMemberAccess(SourceLocation UseLoc,
+                                 CXXRecordDecl *NamingClass,
+                                 DeclAccessPair Found);
+  AccessResult
+  CheckStructuredBindingMemberAccess(SourceLocation UseLoc,
+                                     CXXRecordDecl *DecomposedClass,
+                                     DeclAccessPair Field);
+  AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr,
+                                         const SourceRange &,
+                                         DeclAccessPair FoundDecl);
+  AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr,
+                                         Expr *ArgExpr,
+                                         DeclAccessPair FoundDecl);
+  AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr,
+                                         ArrayRef ArgExprs,
+                                         DeclAccessPair FoundDecl);
+  AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr,
+                                          DeclAccessPair FoundDecl);
+  AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, QualType Base,
+                                    QualType Derived, const CXXBasePath &Path,
+                                    unsigned DiagID, bool ForceCheck = false,
+                                    bool ForceUnprivileged = false);
+  void CheckLookupAccess(const LookupResult &R);
+  bool IsSimplyAccessible(NamedDecl *Decl, CXXRecordDecl *NamingClass,
+                          QualType BaseType);
+  bool isMemberAccessibleForDeletion(CXXRecordDecl *NamingClass,
+                                     DeclAccessPair Found, QualType ObjectType,
+                                     SourceLocation Loc,
+                                     const PartialDiagnostic &Diag);
+  bool isMemberAccessibleForDeletion(CXXRecordDecl *NamingClass,
+                                     DeclAccessPair Found,
+                                     QualType ObjectType) {
+    return isMemberAccessibleForDeletion(NamingClass, Found, ObjectType,
+                                         SourceLocation(), PDiag());
+  }
 
+  void HandleDependentAccessCheck(
+      const DependentDiagnostic &DD,
+      const MultiLevelTemplateArgumentList &TemplateArgs);
+  void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
 
-  /// Load weak undeclared identifiers from the external source.
-  void LoadExternalWeakUndeclaredIdentifiers();
+  ///@}
 
-  /// WeakTopLevelDecl - Translation-unit scoped declarations generated by
-  /// \#pragma weak during processing of other Decls.
-  /// I couldn't figure out a clean way to generate these in-line, so
-  /// we store them here and handle separately -- which is a hack.
-  /// It would be best to refactor this.
-  SmallVector WeakTopLevelDecl;
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  IdentifierResolver IdResolver;
+  /// \name Attributes
+  /// Implementations are in SemaAttr.cpp
+  ///@{
 
-  /// Translation Unit Scope - useful to Objective-C actions that need
-  /// to lookup file scope declarations in the "ordinary" C decl namespace.
-  /// For example, user-defined classes, built-in "id" type, etc.
-  Scope *TUScope;
+public:
+  /// Controls member pointer representation format under the MS ABI.
+  LangOptions::PragmaMSPointersToMembersKind
+      MSPointerToMemberRepresentationMethod;
 
-  /// The C++ "std" namespace, where the standard library resides.
-  LazyDeclPtr StdNamespace;
+  bool MSStructPragmaOn; // True when \#pragma ms_struct on
 
-  /// The C++ "std::bad_alloc" class, which is defined by the C++
-  /// standard library.
-  LazyDeclPtr StdBadAlloc;
+  /// Source location for newly created implicit MSInheritanceAttrs
+  SourceLocation ImplicitMSInheritanceAttrLoc;
 
-  /// The C++ "std::align_val_t" enum class, which is defined by the C++
-  /// standard library.
-  LazyDeclPtr StdAlignValT;
+  /// pragma clang section kind
+  enum PragmaClangSectionKind {
+    PCSK_Invalid = 0,
+    PCSK_BSS = 1,
+    PCSK_Data = 2,
+    PCSK_Rodata = 3,
+    PCSK_Text = 4,
+    PCSK_Relro = 5
+  };
 
-  /// The C++ "std::initializer_list" template, which is defined in
-  /// \.
-  ClassTemplateDecl *StdInitializerList;
+  enum PragmaClangSectionAction { PCSA_Set = 0, PCSA_Clear = 1 };
 
-  /// The C++ "std::coroutine_traits" template, which is defined in
-  /// \
-  ClassTemplateDecl *StdCoroutineTraitsCache;
+  struct PragmaClangSection {
+    std::string SectionName;
+    bool Valid = false;
+    SourceLocation PragmaLocation;
+  };
 
-  /// The C++ "type_info" declaration, which is defined in \.
-  RecordDecl *CXXTypeInfoDecl;
+  PragmaClangSection PragmaClangBSSSection;
+  PragmaClangSection PragmaClangDataSection;
+  PragmaClangSection PragmaClangRodataSection;
+  PragmaClangSection PragmaClangRelroSection;
+  PragmaClangSection PragmaClangTextSection;
 
-  /// The C++ "std::source_location::__impl" struct, defined in
-  /// \.
-  RecordDecl *StdSourceLocationImplDecl;
+  enum PragmaMsStackAction {
+    PSK_Reset = 0x0,                   // #pragma ()
+    PSK_Set = 0x1,                     // #pragma (value)
+    PSK_Push = 0x2,                    // #pragma (push[, id])
+    PSK_Pop = 0x4,                     // #pragma (pop[, id])
+    PSK_Show = 0x8,                    // #pragma (show) -- only for "pack"!
+    PSK_Push_Set = PSK_Push | PSK_Set, // #pragma (push[, id], value)
+    PSK_Pop_Set = PSK_Pop | PSK_Set,   // #pragma (pop[, id], value)
+  };
 
-  /// Caches identifiers/selectors for NSFoundation APIs.
-  std::unique_ptr NSAPIObj;
+  struct PragmaPackInfo {
+    PragmaMsStackAction Action;
+    StringRef SlotLabel;
+    Token Alignment;
+  };
 
-  /// The declaration of the Objective-C NSNumber class.
-  ObjCInterfaceDecl *NSNumberDecl;
+  // #pragma pack and align.
+  class AlignPackInfo {
+  public:
+    // `Native` represents default align mode, which may vary based on the
+    // platform.
+    enum Mode : unsigned char { Native, Natural, Packed, Mac68k };
 
-  /// The declaration of the Objective-C NSValue class.
-  ObjCInterfaceDecl *NSValueDecl;
+    // #pragma pack info constructor
+    AlignPackInfo(AlignPackInfo::Mode M, unsigned Num, bool IsXL)
+        : PackAttr(true), AlignMode(M), PackNumber(Num), XLStack(IsXL) {
+      assert(Num == PackNumber && "The pack number has been truncated.");
+    }
 
-  /// Pointer to NSNumber type (NSNumber *).
-  QualType NSNumberPointer;
+    // #pragma align info constructor
+    AlignPackInfo(AlignPackInfo::Mode M, bool IsXL)
+        : PackAttr(false), AlignMode(M),
+          PackNumber(M == Packed ? 1 : UninitPackVal), XLStack(IsXL) {}
 
-  /// Pointer to NSValue type (NSValue *).
-  QualType NSValuePointer;
+    explicit AlignPackInfo(bool IsXL) : AlignPackInfo(Native, IsXL) {}
 
-  /// The Objective-C NSNumber methods used to create NSNumber literals.
-  ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods];
+    AlignPackInfo() : AlignPackInfo(Native, false) {}
 
-  /// The declaration of the Objective-C NSString class.
-  ObjCInterfaceDecl *NSStringDecl;
+    // When a AlignPackInfo itself cannot be used, this returns an 32-bit
+    // integer encoding for it. This should only be passed to
+    // AlignPackInfo::getFromRawEncoding, it should not be inspected directly.
+    static uint32_t getRawEncoding(const AlignPackInfo &Info) {
+      std::uint32_t Encoding{};
+      if (Info.IsXLStack())
+        Encoding |= IsXLMask;
 
-  /// Pointer to NSString type (NSString *).
-  QualType NSStringPointer;
+      Encoding |= static_cast(Info.getAlignMode()) << 1;
 
-  /// The declaration of the stringWithUTF8String: method.
-  ObjCMethodDecl *StringWithUTF8StringMethod;
+      if (Info.IsPackAttr())
+        Encoding |= PackAttrMask;
 
-  /// The declaration of the valueWithBytes:objCType: method.
-  ObjCMethodDecl *ValueWithBytesObjCTypeMethod;
+      Encoding |= static_cast(Info.getPackNumber()) << 4;
 
-  /// The declaration of the Objective-C NSArray class.
-  ObjCInterfaceDecl *NSArrayDecl;
+      return Encoding;
+    }
 
-  /// The declaration of the arrayWithObjects:count: method.
-  ObjCMethodDecl *ArrayWithObjectsMethod;
+    static AlignPackInfo getFromRawEncoding(unsigned Encoding) {
+      bool IsXL = static_cast(Encoding & IsXLMask);
+      AlignPackInfo::Mode M =
+          static_cast((Encoding & AlignModeMask) >> 1);
+      int PackNumber = (Encoding & PackNumMask) >> 4;
 
-  /// The declaration of the Objective-C NSDictionary class.
-  ObjCInterfaceDecl *NSDictionaryDecl;
+      if (Encoding & PackAttrMask)
+        return AlignPackInfo(M, PackNumber, IsXL);
 
-  /// The declaration of the dictionaryWithObjects:forKeys:count: method.
-  ObjCMethodDecl *DictionaryWithObjectsMethod;
+      return AlignPackInfo(M, IsXL);
+    }
 
-  /// id type.
-  QualType QIDNSCopying;
+    bool IsPackAttr() const { return PackAttr; }
 
-  /// will hold 'respondsToSelector:'
-  Selector RespondsToSelectorSel;
+    bool IsAlignAttr() const { return !PackAttr; }
 
-  /// A flag to remember whether the implicit forms of operator new and delete
-  /// have been declared.
-  bool GlobalNewDeleteDeclared;
+    Mode getAlignMode() const { return AlignMode; }
 
-  /// Describes how the expressions currently being parsed are
-  /// evaluated at run-time, if at all.
-  enum class ExpressionEvaluationContext {
-    /// The current expression and its subexpressions occur within an
-    /// unevaluated operand (C++11 [expr]p7), such as the subexpression of
-    /// \c sizeof, where the type of the expression may be significant but
-    /// no code will be generated to evaluate the value of the expression at
-    /// run time.
-    Unevaluated,
+    unsigned getPackNumber() const { return PackNumber; }
 
-    /// The current expression occurs within a braced-init-list within
-    /// an unevaluated operand. This is mostly like a regular unevaluated
-    /// context, except that we still instantiate constexpr functions that are
-    /// referenced here so that we can perform narrowing checks correctly.
-    UnevaluatedList,
-
-    /// The current expression occurs within a discarded statement.
-    /// This behaves largely similarly to an unevaluated operand in preventing
-    /// definitions from being required, but not in other ways.
-    DiscardedStatement,
+    bool IsPackSet() const {
+      // #pragma align, #pragma pack(), and #pragma pack(0) do not set the pack
+      // attriute on a decl.
+      return PackNumber != UninitPackVal && PackNumber != 0;
+    }
 
-    /// The current expression occurs within an unevaluated
-    /// operand that unconditionally permits abstract references to
-    /// fields, such as a SIZE operator in MS-style inline assembly.
-    UnevaluatedAbstract,
+    bool IsXLStack() const { return XLStack; }
 
-    /// The current context is "potentially evaluated" in C++11 terms,
-    /// but the expression is evaluated at compile-time (like the values of
-    /// cases in a switch statement).
-    ConstantEvaluated,
+    bool operator==(const AlignPackInfo &Info) const {
+      return std::tie(AlignMode, PackNumber, PackAttr, XLStack) ==
+             std::tie(Info.AlignMode, Info.PackNumber, Info.PackAttr,
+                      Info.XLStack);
+    }
 
-    /// In addition of being constant evaluated, the current expression
-    /// occurs in an immediate function context - either a consteval function
-    /// or a consteval if statement.
-    ImmediateFunctionContext,
+    bool operator!=(const AlignPackInfo &Info) const {
+      return !(*this == Info);
+    }
 
-    /// The current expression is potentially evaluated at run time,
-    /// which means that code may be generated to evaluate the value of the
-    /// expression at run time.
-    PotentiallyEvaluated,
+  private:
+    /// \brief True if this is a pragma pack attribute,
+    ///         not a pragma align attribute.
+    bool PackAttr;
 
-    /// The current expression is potentially evaluated, but any
-    /// declarations referenced inside that expression are only used if
-    /// in fact the current expression is used.
-    ///
-    /// This value is used when parsing default function arguments, for which
-    /// we would like to provide diagnostics (e.g., passing non-POD arguments
-    /// through varargs) but do not want to mark declarations as "referenced"
-    /// until the default argument is used.
-    PotentiallyEvaluatedIfUsed
-  };
+    /// \brief The alignment mode that is in effect.
+    Mode AlignMode;
 
-  using ImmediateInvocationCandidate = llvm::PointerIntPair;
+    /// \brief The pack number of the stack.
+    unsigned char PackNumber;
 
-  /// Data structure used to record current or nested
-  /// expression evaluation contexts.
-  struct ExpressionEvaluationContextRecord {
-    /// The expression evaluation context.
-    ExpressionEvaluationContext Context;
+    /// \brief True if it is a XL #pragma align/pack stack.
+    bool XLStack;
 
-    /// Whether the enclosing context needed a cleanup.
-    CleanupInfo ParentCleanup;
+    /// \brief Uninitialized pack value.
+    static constexpr unsigned char UninitPackVal = -1;
 
-    /// The number of active cleanup objects when we entered
-    /// this expression evaluation context.
-    unsigned NumCleanupObjects;
+    // Masks to encode and decode an AlignPackInfo.
+    static constexpr uint32_t IsXLMask{0x0000'0001};
+    static constexpr uint32_t AlignModeMask{0x0000'0006};
+    static constexpr uint32_t PackAttrMask{0x00000'0008};
+    static constexpr uint32_t PackNumMask{0x0000'01F0};
+  };
 
-    /// The number of typos encountered during this expression evaluation
-    /// context (i.e. the number of TypoExprs created).
-    unsigned NumTypos;
+  template  struct PragmaStack {
+    struct Slot {
+      llvm::StringRef StackSlotLabel;
+      ValueType Value;
+      SourceLocation PragmaLocation;
+      SourceLocation PragmaPushLocation;
+      Slot(llvm::StringRef StackSlotLabel, ValueType Value,
+           SourceLocation PragmaLocation, SourceLocation PragmaPushLocation)
+          : StackSlotLabel(StackSlotLabel), Value(Value),
+            PragmaLocation(PragmaLocation),
+            PragmaPushLocation(PragmaPushLocation) {}
+    };
 
-    MaybeODRUseExprSet SavedMaybeODRUseExprs;
+    void Act(SourceLocation PragmaLocation, PragmaMsStackAction Action,
+             llvm::StringRef StackSlotLabel, ValueType Value) {
+      if (Action == PSK_Reset) {
+        CurrentValue = DefaultValue;
+        CurrentPragmaLocation = PragmaLocation;
+        return;
+      }
+      if (Action & PSK_Push)
+        Stack.emplace_back(StackSlotLabel, CurrentValue, CurrentPragmaLocation,
+                           PragmaLocation);
+      else if (Action & PSK_Pop) {
+        if (!StackSlotLabel.empty()) {
+          // If we've got a label, try to find it and jump there.
+          auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) {
+            return x.StackSlotLabel == StackSlotLabel;
+          });
+          // If we found the label so pop from there.
+          if (I != Stack.rend()) {
+            CurrentValue = I->Value;
+            CurrentPragmaLocation = I->PragmaLocation;
+            Stack.erase(std::prev(I.base()), Stack.end());
+          }
+        } else if (!Stack.empty()) {
+          // We do not have a label, just pop the last entry.
+          CurrentValue = Stack.back().Value;
+          CurrentPragmaLocation = Stack.back().PragmaLocation;
+          Stack.pop_back();
+        }
+      }
+      if (Action & PSK_Set) {
+        CurrentValue = Value;
+        CurrentPragmaLocation = PragmaLocation;
+      }
+    }
 
-    /// The lambdas that are present within this context, if it
-    /// is indeed an unevaluated context.
-    SmallVector Lambdas;
+    // MSVC seems to add artificial slots to #pragma stacks on entering a C++
+    // method body to restore the stacks on exit, so it works like this:
+    //
+    //   struct S {
+    //     #pragma (push, InternalPragmaSlot, )
+    //     void Method {}
+    //     #pragma (pop, InternalPragmaSlot)
+    //   };
+    //
+    // It works even with #pragma vtordisp, although MSVC doesn't support
+    //   #pragma vtordisp(push [, id], n)
+    // syntax.
+    //
+    // Push / pop a named sentinel slot.
+    void SentinelAction(PragmaMsStackAction Action, StringRef Label) {
+      assert((Action == PSK_Push || Action == PSK_Pop) &&
+             "Can only push / pop #pragma stack sentinels!");
+      Act(CurrentPragmaLocation, Action, Label, CurrentValue);
+    }
 
-    /// The declaration that provides context for lambda expressions
-    /// and block literals if the normal declaration context does not
-    /// suffice, e.g., in a default function argument.
-    Decl *ManglingContextDecl;
+    // Constructors.
+    explicit PragmaStack(const ValueType &Default)
+        : DefaultValue(Default), CurrentValue(Default) {}
 
-    /// If we are processing a decltype type, a set of call expressions
-    /// for which we have deferred checking the completeness of the return type.
-    SmallVector DelayedDecltypeCalls;
+    bool hasValue() const { return CurrentValue != DefaultValue; }
 
-    /// If we are processing a decltype type, a set of temporary binding
-    /// expressions for which we have deferred checking the destructor.
-    SmallVector DelayedDecltypeBinds;
+    SmallVector Stack;
+    ValueType DefaultValue; // Value used for PSK_Reset action.
+    ValueType CurrentValue;
+    SourceLocation CurrentPragmaLocation;
+  };
+  // FIXME: We should serialize / deserialize these if they occur in a PCH (but
+  // we shouldn't do so if they're in a module).
 
-    llvm::SmallPtrSet PossibleDerefs;
+  /// Whether to insert vtordisps prior to virtual bases in the Microsoft
+  /// C++ ABI.  Possible values are 0, 1, and 2, which mean:
+  ///
+  /// 0: Suppress all vtordisps
+  /// 1: Insert vtordisps in the presence of vbase overrides and non-trivial
+  ///    structors
+  /// 2: Always insert vtordisps to support RTTI on partially constructed
+  ///    objects
+  PragmaStack VtorDispStack;
+  PragmaStack AlignPackStack;
+  // The current #pragma align/pack values and locations at each #include.
+  struct AlignPackIncludeState {
+    AlignPackInfo CurrentValue;
+    SourceLocation CurrentPragmaLocation;
+    bool HasNonDefaultValue, ShouldWarnOnInclude;
+  };
+  SmallVector AlignPackIncludeStack;
+  // Segment #pragmas.
+  PragmaStack DataSegStack;
+  PragmaStack BSSSegStack;
+  PragmaStack ConstSegStack;
+  PragmaStack CodeSegStack;
 
-    /// Expressions appearing as the LHS of a volatile assignment in this
-    /// context. We produce a warning for these when popping the context if
-    /// they are not discarded-value expressions nor unevaluated operands.
-    SmallVector VolatileAssignmentLHSs;
+  // #pragma strict_gs_check.
+  PragmaStack StrictGuardStackCheckStack;
 
-    /// Set of candidates for starting an immediate invocation.
-    llvm::SmallVector ImmediateInvocationCandidates;
+  // This stack tracks the current state of Sema.CurFPFeatures.
+  PragmaStack FpPragmaStack;
+  FPOptionsOverride CurFPFeatureOverrides() {
+    FPOptionsOverride result;
+    if (!FpPragmaStack.hasValue()) {
+      result = FPOptionsOverride();
+    } else {
+      result = FpPragmaStack.CurrentValue;
+    }
+    return result;
+  }
 
-    /// Set of DeclRefExprs referencing a consteval function when used in a
-    /// context not already known to be immediately invoked.
-    llvm::SmallPtrSet ReferenceToConsteval;
+  enum PragmaSectionKind {
+    PSK_DataSeg,
+    PSK_BSSSeg,
+    PSK_ConstSeg,
+    PSK_CodeSeg,
+  };
 
-    /// P2718R0 - Lifetime extension in range-based for loops.
-    /// MaterializeTemporaryExprs in for-range-init expressions which need to
-    /// extend lifetime. Add MaterializeTemporaryExpr* if the value of
-    /// InLifetimeExtendingContext is true.
-    SmallVector ForRangeLifetimeExtendTemps;
+  // RAII object to push / pop sentinel slots for all MS #pragma stacks.
+  // Actions should be performed only if we enter / exit a C++ method body.
+  class PragmaStackSentinelRAII {
+  public:
+    PragmaStackSentinelRAII(Sema &S, StringRef SlotLabel, bool ShouldAct);
+    ~PragmaStackSentinelRAII();
 
-    /// \brief Describes whether we are in an expression constext which we have
-    /// to handle differently.
-    enum ExpressionKind {
-      EK_Decltype, EK_TemplateArgument, EK_Other
-    } ExprContext;
+  private:
+    Sema &S;
+    StringRef SlotLabel;
+    bool ShouldAct;
+  };
 
-    // A context can be nested in both a discarded statement context and
-    // an immediate function context, so they need to be tracked independently.
-    bool InDiscardedStatement;
-    bool InImmediateFunctionContext;
-    bool InImmediateEscalatingFunctionContext;
+  /// Last section used with #pragma init_seg.
+  StringLiteral *CurInitSeg;
+  SourceLocation CurInitSegLoc;
 
-    bool IsCurrentlyCheckingDefaultArgumentOrInitializer = false;
+  /// Sections used with #pragma alloc_text.
+  llvm::StringMap> FunctionToSectionMap;
 
-    // We are in a constant context, but we also allow
-    // non constant expressions, for example for array bounds (which may be
-    // VLAs).
-    bool InConditionallyConstantEvaluateContext = false;
+  /// VisContext - Manages the stack for \#pragma GCC visibility.
+  void *VisContext; // Really a "PragmaVisStack*"
 
-    /// Whether we are currently in a context in which all temporaries must be
-    /// lifetime-extended, even if they're not bound to a reference (for
-    /// example, in a for-range initializer).
-    bool InLifetimeExtendingContext = false;
+  /// This an attribute introduced by \#pragma clang attribute.
+  struct PragmaAttributeEntry {
+    SourceLocation Loc;
+    ParsedAttr *Attribute;
+    SmallVector MatchRules;
+    bool IsUsed;
+  };
 
-    /// Whether we are currently in a context in which all temporaries must be
-    /// materialized.
-    ///
-    /// [class.temporary]/p2:
-    /// The materialization of a temporary object is generally delayed as long
-    /// as possible in order to avoid creating unnecessary temporary objects.
-    ///
-    /// Temporary objects are materialized:
-    ///   (2.1) when binding a reference to a prvalue ([dcl.init.ref],
-    ///   [expr.type.conv], [expr.dynamic.cast], [expr.static.cast],
-    ///   [expr.const.cast], [expr.cast]),
-    ///
-    ///   (2.2) when performing member access on a class prvalue ([expr.ref],
-    ///   [expr.mptr.oper]),
-    ///
-    ///   (2.3) when performing an array-to-pointer conversion or subscripting
-    ///   on an array prvalue ([conv.array], [expr.sub]),
-    ///
-    ///   (2.4) when initializing an object of type
-    ///   std​::​initializer_list from a braced-init-list
-    ///   ([dcl.init.list]),
-    ///
-    ///   (2.5) for certain unevaluated operands ([expr.typeid], [expr.sizeof])
-    ///
-    ///   (2.6) when a prvalue that has type other than cv void appears as a
-    ///   discarded-value expression ([expr.context]).
-    bool InMaterializeTemporaryObjectContext = false;
+  /// A push'd group of PragmaAttributeEntries.
+  struct PragmaAttributeGroup {
+    /// The location of the push attribute.
+    SourceLocation Loc;
+    /// The namespace of this push group.
+    const IdentifierInfo *Namespace;
+    SmallVector Entries;
+  };
 
-    // When evaluating immediate functions in the initializer of a default
-    // argument or default member initializer, this is the declaration whose
-    // default initializer is being evaluated and the location of the call
-    // or constructor definition.
-    struct InitializationContext {
-      InitializationContext(SourceLocation Loc, ValueDecl *Decl,
-                            DeclContext *Context)
-          : Loc(Loc), Decl(Decl), Context(Context) {
-        assert(Decl && Context && "invalid initialization context");
-      }
+  SmallVector PragmaAttributeStack;
 
-      SourceLocation Loc;
-      ValueDecl *Decl = nullptr;
-      DeclContext *Context = nullptr;
-    };
-    std::optional DelayedDefaultInitializationContext;
+  /// The declaration that is currently receiving an attribute from the
+  /// #pragma attribute stack.
+  const Decl *PragmaAttributeCurrentTargetDecl;
 
-    ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
-                                      unsigned NumCleanupObjects,
-                                      CleanupInfo ParentCleanup,
-                                      Decl *ManglingContextDecl,
-                                      ExpressionKind ExprContext)
-        : Context(Context), ParentCleanup(ParentCleanup),
-          NumCleanupObjects(NumCleanupObjects), NumTypos(0),
-          ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext),
-          InDiscardedStatement(false), InImmediateFunctionContext(false),
-          InImmediateEscalatingFunctionContext(false) {}
+  /// This represents the last location of a "#pragma clang optimize off"
+  /// directive if such a directive has not been closed by an "on" yet. If
+  /// optimizations are currently "on", this is set to an invalid location.
+  SourceLocation OptimizeOffPragmaLocation;
 
-    bool isUnevaluated() const {
-      return Context == ExpressionEvaluationContext::Unevaluated ||
-             Context == ExpressionEvaluationContext::UnevaluatedAbstract ||
-             Context == ExpressionEvaluationContext::UnevaluatedList;
-    }
+  /// Get the location for the currently active "\#pragma clang optimize
+  /// off". If this location is invalid, then the state of the pragma is "on".
+  SourceLocation getOptimizeOffPragmaLocation() const {
+    return OptimizeOffPragmaLocation;
+  }
 
-    bool isConstantEvaluated() const {
-      return Context == ExpressionEvaluationContext::ConstantEvaluated ||
-             Context == ExpressionEvaluationContext::ImmediateFunctionContext;
-    }
+  /// The "on" or "off" argument passed by \#pragma optimize, that denotes
+  /// whether the optimizations in the list passed to the pragma should be
+  /// turned off or on. This boolean is true by default because command line
+  /// options are honored when `#pragma optimize("", on)`.
+  /// (i.e. `ModifyFnAttributeMSPragmaOptimze()` does nothing)
+  bool MSPragmaOptimizeIsOn = true;
 
-    bool isImmediateFunctionContext() const {
-      return Context == ExpressionEvaluationContext::ImmediateFunctionContext ||
-             (Context == ExpressionEvaluationContext::DiscardedStatement &&
-              InImmediateFunctionContext) ||
-             // C++23 [expr.const]p14:
-             // An expression or conversion is in an immediate function
-             // context if it is potentially evaluated and either:
-             //   * its innermost enclosing non-block scope is a function
-             //     parameter scope of an immediate function, or
-             //   * its enclosing statement is enclosed by the compound-
-             //     statement of a consteval if statement.
-             (Context == ExpressionEvaluationContext::PotentiallyEvaluated &&
-              InImmediateFunctionContext);
-    }
+  /// Set of no-builtin functions listed by \#pragma function.
+  llvm::SmallSetVector MSFunctionNoBuiltins;
 
-    bool isDiscardedStatementContext() const {
-      return Context == ExpressionEvaluationContext::DiscardedStatement ||
-             (Context ==
-                  ExpressionEvaluationContext::ImmediateFunctionContext &&
-              InDiscardedStatement);
-    }
-  };
+  /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
+  /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'.
+  void AddAlignmentAttributesForRecord(RecordDecl *RD);
 
-  /// A stack of expression evaluation contexts.
-  SmallVector ExprEvalContexts;
+  /// AddMsStructLayoutForRecord - Adds ms_struct layout attribute to record.
+  void AddMsStructLayoutForRecord(RecordDecl *RD);
 
-  // Set of failed immediate invocations to avoid double diagnosing.
-  llvm::SmallPtrSet FailedImmediateInvocations;
+  /// Add gsl::Pointer attribute to std::container::iterator
+  /// \param ND The declaration that introduces the name
+  /// std::container::iterator. \param UnderlyingRecord The record named by ND.
+  void inferGslPointerAttribute(NamedDecl *ND, CXXRecordDecl *UnderlyingRecord);
 
-  /// Emit a warning for all pending noderef expressions that we recorded.
-  void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec);
+  /// Add [[gsl::Owner]] and [[gsl::Pointer]] attributes for std:: types.
+  void inferGslOwnerPointerAttribute(CXXRecordDecl *Record);
 
-  /// Compute the mangling number context for a lambda expression or
-  /// block literal. Also return the extra mangling decl if any.
-  ///
-  /// \param DC - The DeclContext containing the lambda expression or
-  /// block literal.
-  std::tuple
-  getCurrentMangleNumberContext(const DeclContext *DC);
+  /// Add [[gsl::Pointer]] attributes for std:: types.
+  void inferGslPointerAttribute(TypedefNameDecl *TD);
 
+  enum PragmaOptionsAlignKind {
+    POAK_Native,  // #pragma options align=native
+    POAK_Natural, // #pragma options align=natural
+    POAK_Packed,  // #pragma options align=packed
+    POAK_Power,   // #pragma options align=power
+    POAK_Mac68k,  // #pragma options align=mac68k
+    POAK_Reset    // #pragma options align=reset
+  };
 
-  /// SpecialMemberOverloadResult - The overloading result for a special member
-  /// function.
-  ///
-  /// This is basically a wrapper around PointerIntPair. The lowest bits of the
-  /// integer are used to determine whether overload resolution succeeded.
-  class SpecialMemberOverloadResult {
-  public:
-    enum Kind {
-      NoMemberOrDeleted,
-      Ambiguous,
-      Success
-    };
+  /// ActOnPragmaClangSection - Called on well formed \#pragma clang section
+  void ActOnPragmaClangSection(SourceLocation PragmaLoc,
+                               PragmaClangSectionAction Action,
+                               PragmaClangSectionKind SecKind,
+                               StringRef SecName);
 
-  private:
-    llvm::PointerIntPair Pair;
+  /// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align.
+  void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
+                               SourceLocation PragmaLoc);
 
-  public:
-    SpecialMemberOverloadResult() {}
-    SpecialMemberOverloadResult(CXXMethodDecl *MD)
-        : Pair(MD, MD->isDeleted() ? NoMemberOrDeleted : Success) {}
+  /// ActOnPragmaPack - Called on well formed \#pragma pack(...).
+  void ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
+                       StringRef SlotLabel, Expr *Alignment);
 
-    CXXMethodDecl *getMethod() const { return Pair.getPointer(); }
-    void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); }
+  /// ConstantFoldAttrArgs - Folds attribute arguments into ConstantExprs
+  /// (unless they are value dependent or type dependent). Returns false
+  /// and emits a diagnostic if one or more of the arguments could not be
+  /// folded into a constant.
+  bool ConstantFoldAttrArgs(const AttributeCommonInfo &CI,
+                            MutableArrayRef Args);
 
-    Kind getKind() const { return static_cast(Pair.getInt()); }
-    void setKind(Kind K) { Pair.setInt(K); }
+  enum class PragmaAlignPackDiagnoseKind {
+    NonDefaultStateAtInclude,
+    ChangedStateAtExit
   };
 
-  class SpecialMemberOverloadResultEntry
-      : public llvm::FastFoldingSetNode,
-        public SpecialMemberOverloadResult {
-  public:
-    SpecialMemberOverloadResultEntry(const llvm::FoldingSetNodeID &ID)
-      : FastFoldingSetNode(ID)
-    {}
-  };
+  void DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind,
+                                         SourceLocation IncludeLoc);
+  void DiagnoseUnterminatedPragmaAlignPack();
 
-  /// A cache of special member function overload resolution results
-  /// for C++ records.
-  llvm::FoldingSet SpecialMemberCache;
+  /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off].
+  void ActOnPragmaMSStruct(PragmaMSStructKind Kind);
 
-  /// A cache of the flags available in enumerations with the flag_bits
-  /// attribute.
-  mutable llvm::DenseMap FlagBitsCache;
+  /// ActOnPragmaMSComment - Called on well formed
+  /// \#pragma comment(kind, "arg").
+  void ActOnPragmaMSComment(SourceLocation CommentLoc, PragmaMSCommentKind Kind,
+                            StringRef Arg);
 
-  /// The kind of translation unit we are processing.
-  ///
-  /// When we're processing a complete translation unit, Sema will perform
-  /// end-of-translation-unit semantic tasks (such as creating
-  /// initializers for tentative definitions in C) once parsing has
-  /// completed. Modules and precompiled headers perform different kinds of
-  /// checks.
-  const TranslationUnitKind TUKind;
+  /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
+  void ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
+                                 StringRef Value);
 
-  llvm::BumpPtrAllocator BumpAlloc;
+  /// Are precise floating point semantics currently enabled?
+  bool isPreciseFPEnabled() {
+    return !CurFPFeatures.getAllowFPReassociate() &&
+           !CurFPFeatures.getNoSignedZero() &&
+           !CurFPFeatures.getAllowReciprocal() &&
+           !CurFPFeatures.getAllowApproxFunc();
+  }
 
-  /// The number of SFINAE diagnostics that have been trapped.
-  unsigned NumSFINAEErrors;
+  void ActOnPragmaFPEvalMethod(SourceLocation Loc,
+                               LangOptions::FPEvalMethodKind Value);
 
-  typedef llvm::DenseMap>
-    UnparsedDefaultArgInstantiationsMap;
+  /// ActOnPragmaFloatControl - Call on well-formed \#pragma float_control
+  void ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action,
+                               PragmaFloatControlKind Value);
 
-  /// A mapping from parameters with unparsed default arguments to the
-  /// set of instantiations of each parameter.
-  ///
-  /// This mapping is a temporary data structure used when parsing
-  /// nested class templates or nested classes of class templates,
-  /// where we might end up instantiating an inner class before the
-  /// default arguments of its methods have been parsed.
-  UnparsedDefaultArgInstantiationsMap UnparsedDefaultArgInstantiations;
+  /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma
+  /// pointers_to_members(representation method[, general purpose
+  /// representation]).
+  void ActOnPragmaMSPointersToMembers(
+      LangOptions::PragmaMSPointersToMembersKind Kind,
+      SourceLocation PragmaLoc);
 
-  // Contains the locations of the beginning of unparsed default
-  // argument locations.
-  llvm::DenseMap UnparsedDefaultArgLocs;
+  /// Called on well formed \#pragma vtordisp().
+  void ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
+                             SourceLocation PragmaLoc, MSVtorDispMode Value);
 
-  /// UndefinedInternals - all the used, undefined objects which require a
-  /// definition in this translation unit.
-  llvm::MapVector UndefinedButUsed;
-
-  /// Determine if VD, which must be a variable or function, is an external
-  /// symbol that nonetheless can't be referenced from outside this translation
-  /// unit because its type has no linkage and it's not extern "C".
-  bool isExternalWithNoLinkageType(const ValueDecl *VD) const;
+  bool UnifySection(StringRef SectionName, int SectionFlags,
+                    NamedDecl *TheDecl);
+  bool UnifySection(StringRef SectionName, int SectionFlags,
+                    SourceLocation PragmaSectionLocation);
 
-  /// Obtain a sorted list of functions that are undefined but ODR-used.
-  void getUndefinedButUsed(
-      SmallVectorImpl > &Undefined);
+  /// Called on well formed \#pragma bss_seg/data_seg/const_seg/code_seg.
+  void ActOnPragmaMSSeg(SourceLocation PragmaLocation,
+                        PragmaMsStackAction Action,
+                        llvm::StringRef StackSlotLabel,
+                        StringLiteral *SegmentName, llvm::StringRef PragmaName);
 
-  /// Retrieves list of suspicious delete-expressions that will be checked at
-  /// the end of translation unit.
-  const llvm::MapVector &
-  getMismatchingDeleteExpressions() const;
+  /// Called on well formed \#pragma section().
+  void ActOnPragmaMSSection(SourceLocation PragmaLocation, int SectionFlags,
+                            StringLiteral *SegmentName);
 
-  class GlobalMethodPool {
-  public:
-    using Lists = std::pair;
-    using iterator = llvm::DenseMap::iterator;
-    iterator begin() { return Methods.begin(); }
-    iterator end() { return Methods.end(); }
-    iterator find(Selector Sel) { return Methods.find(Sel); }
-    std::pair insert(std::pair &&Val) {
-      return Methods.insert(Val);
-    }
-    int count(Selector Sel) const { return Methods.count(Sel); }
-    bool empty() const { return Methods.empty(); }
+  /// Called on well-formed \#pragma init_seg().
+  void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
+                            StringLiteral *SegmentName);
 
-  private:
-    llvm::DenseMap Methods;
-  };
+  /// Called on well-formed \#pragma alloc_text().
+  void ActOnPragmaMSAllocText(
+      SourceLocation PragmaLocation, StringRef Section,
+      const SmallVector>
+          &Functions);
 
-  /// Method Pool - allows efficient lookup when typechecking messages to "id".
-  /// We need to maintain a list, since selectors can have differing signatures
-  /// across classes. In Cocoa, this happens to be extremely uncommon (only 1%
-  /// of selectors are "overloaded").
-  /// At the head of the list it is recorded whether there were 0, 1, or >= 2
-  /// methods inside categories with a particular selector.
-  GlobalMethodPool MethodPool;
+  /// ActOnPragmaMSStrictGuardStackCheck - Called on well formed \#pragma
+  /// strict_gs_check.
+  void ActOnPragmaMSStrictGuardStackCheck(SourceLocation PragmaLocation,
+                                          PragmaMsStackAction Action,
+                                          bool Value);
 
-  /// Method selectors used in a \@selector expression. Used for implementation
-  /// of -Wselector.
-  llvm::MapVector ReferencedSelectors;
+  /// ActOnPragmaUnused - Called on well-formed '\#pragma unused'.
+  void ActOnPragmaUnused(const Token &Identifier, Scope *curScope,
+                         SourceLocation PragmaLoc);
 
-  /// List of SourceLocations where 'self' is implicitly retained inside a
-  /// block.
-  llvm::SmallVector, 1>
-      ImplicitlyRetainedSelfLocs;
+  /// AddCFAuditedAttribute - Check whether we're currently within
+  /// '\#pragma clang arc_cf_code_audited' and, if so, consider adding
+  /// the appropriate attribute.
+  void AddCFAuditedAttribute(Decl *D);
 
-  /// Kinds of C++ special members.
-  enum CXXSpecialMember {
-    CXXDefaultConstructor,
-    CXXCopyConstructor,
-    CXXMoveConstructor,
-    CXXCopyAssignment,
-    CXXMoveAssignment,
-    CXXDestructor,
-    CXXInvalid
-  };
+  void ActOnPragmaAttributeAttribute(ParsedAttr &Attribute,
+                                     SourceLocation PragmaLoc,
+                                     attr::ParsedSubjectMatchRuleSet Rules);
+  void ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc,
+                                     const IdentifierInfo *Namespace);
 
-  typedef llvm::PointerIntPair
-      SpecialMemberDecl;
+  /// Called on well-formed '\#pragma clang attribute pop'.
+  void ActOnPragmaAttributePop(SourceLocation PragmaLoc,
+                               const IdentifierInfo *Namespace);
 
-  /// The C++ special members which we are currently in the process of
-  /// declaring. If this process recursively triggers the declaration of the
-  /// same special member, we should act as if it is not yet declared.
-  llvm::SmallPtrSet SpecialMembersBeingDeclared;
+  /// Adds the attributes that have been specified using the
+  /// '\#pragma clang attribute push' directives to the given declaration.
+  void AddPragmaAttributes(Scope *S, Decl *D);
 
-  /// Kinds of defaulted comparison operator functions.
-  enum class DefaultedComparisonKind : unsigned char {
-    /// This is not a defaultable comparison operator.
-    None,
-    /// This is an operator== that should be implemented as a series of
-    /// subobject comparisons.
-    Equal,
-    /// This is an operator<=> that should be implemented as a series of
-    /// subobject comparisons.
-    ThreeWay,
-    /// This is an operator!= that should be implemented as a rewrite in terms
-    /// of a == comparison.
-    NotEqual,
-    /// This is an <, <=, >, or >= that should be implemented as a rewrite in
-    /// terms of a <=> comparison.
-    Relational,
-  };
+  void PrintPragmaAttributeInstantiationPoint();
 
-  /// The function definitions which were renamed as part of typo-correction
-  /// to match their respective declarations. We want to keep track of them
-  /// to ensure that we don't emit a "redefinition" error if we encounter a
-  /// correctly named definition after the renamed definition.
-  llvm::SmallPtrSet TypoCorrectedFunctionDefinitions;
+  void DiagnoseUnterminatedPragmaAttribute();
 
-  /// Stack of types that correspond to the parameter entities that are
-  /// currently being copy-initialized. Can be empty.
-  llvm::SmallVector CurrentParameterCopyTypes;
+  /// Called on well formed \#pragma clang optimize.
+  void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc);
 
-  void ReadMethodPool(Selector Sel);
-  void updateOutOfDateSelector(Selector Sel);
+  /// #pragma optimize("[optimization-list]", on | off).
+  void ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn);
 
-  /// Private Helper predicate to check for 'self'.
-  bool isSelfExpr(Expr *RExpr);
-  bool isSelfExpr(Expr *RExpr, const ObjCMethodDecl *Method);
+  /// Call on well formed \#pragma function.
+  void
+  ActOnPragmaMSFunction(SourceLocation Loc,
+                        const llvm::SmallVectorImpl &NoBuiltins);
 
-  /// Cause the active diagnostic on the DiagosticsEngine to be
-  /// emitted. This is closely coupled to the SemaDiagnosticBuilder class and
-  /// should not be used elsewhere.
-  void EmitCurrentDiagnostic(unsigned DiagID);
+  /// Only called on function definitions; if there is a pragma in scope
+  /// with the effect of a range-based optnone, consider marking the function
+  /// with attribute optnone.
+  void AddRangeBasedOptnone(FunctionDecl *FD);
 
-  /// Records and restores the CurFPFeatures state on entry/exit of compound
-  /// statements.
-  class FPFeaturesStateRAII {
-  public:
-    FPFeaturesStateRAII(Sema &S);
-    ~FPFeaturesStateRAII();
-    FPOptionsOverride getOverrides() { return OldOverrides; }
+  /// Only called on function definitions; if there is a `#pragma alloc_text`
+  /// that decides which code section the function should be in, add
+  /// attribute section to the function.
+  void AddSectionMSAllocText(FunctionDecl *FD);
 
-  private:
-    Sema& S;
-    FPOptions OldFPFeaturesState;
-    FPOptionsOverride OldOverrides;
-    LangOptions::FPEvalMethodKind OldEvalMethod;
-    SourceLocation OldFPPragmaLocation;
-  };
+  /// Adds the 'optnone' attribute to the function declaration if there
+  /// are no conflicts; Loc represents the location causing the 'optnone'
+  /// attribute to be added (usually because of a pragma).
+  void AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc);
 
-  void addImplicitTypedef(StringRef Name, QualType T);
+  /// Only called on function definitions; if there is a MSVC #pragma optimize
+  /// in scope, consider changing the function's attributes based on the
+  /// optimization list passed to the pragma.
+  void ModifyFnAttributesMSPragmaOptimize(FunctionDecl *FD);
 
-  bool WarnedStackExhausted = false;
+  /// Only called on function definitions; if there is a pragma in scope
+  /// with the effect of a range-based no_builtin, consider marking the function
+  /// with attribute no_builtin.
+  void AddImplicitMSFunctionNoBuiltinAttr(FunctionDecl *FD);
 
-  /// Increment when we find a reference; decrement when we find an ignored
-  /// assignment.  Ultimately the value is 0 if every reference is an ignored
-  /// assignment.
-  llvm::DenseMap RefsMinusAssignments;
+  /// AddPushedVisibilityAttribute - If '\#pragma GCC visibility' was used,
+  /// add an appropriate visibility attribute.
+  void AddPushedVisibilityAttribute(Decl *RD);
 
-  /// Indicate RISC-V vector builtin functions enabled or not.
-  bool DeclareRISCVVBuiltins = false;
+  /// FreeVisContext - Deallocate and null out VisContext.
+  void FreeVisContext();
 
-  /// Indicate RISC-V SiFive vector builtin functions enabled or not.
-  bool DeclareRISCVSiFiveVectorBuiltins = false;
+  /// ActOnPragmaVisibility - Called on well formed \#pragma GCC visibility... .
+  void ActOnPragmaVisibility(const IdentifierInfo *VisType,
+                             SourceLocation PragmaLoc);
 
-private:
-  std::unique_ptr RVIntrinsicManager;
+  /// ActOnPragmaFPContract - Called on well formed
+  /// \#pragma {STDC,OPENCL} FP_CONTRACT and
+  /// \#pragma clang fp contract
+  void ActOnPragmaFPContract(SourceLocation Loc, LangOptions::FPModeKind FPC);
 
-  std::optional> CachedDarwinSDKInfo;
+  /// Called on well formed
+  /// \#pragma clang fp reassociate
+  /// or
+  /// \#pragma clang fp reciprocal
+  void ActOnPragmaFPValueChangingOption(SourceLocation Loc, PragmaFPKind Kind,
+                                        bool IsEnabled);
 
-  bool WarnedDarwinSDKInfoMissing = false;
+  /// ActOnPragmaFenvAccess - Called on well formed
+  /// \#pragma STDC FENV_ACCESS
+  void ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled);
 
-public:
-  Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
-       TranslationUnitKind TUKind = TU_Complete,
-       CodeCompleteConsumer *CompletionConsumer = nullptr);
-  ~Sema();
+  /// ActOnPragmaCXLimitedRange - Called on well formed
+  /// \#pragma STDC CX_LIMITED_RANGE
+  void ActOnPragmaCXLimitedRange(SourceLocation Loc,
+                                 LangOptions::ComplexRangeKind Range);
 
-  /// Perform initialization that occurs after the parser has been
-  /// initialized but before it parses anything.
-  void Initialize();
+  /// Called on well formed '\#pragma clang fp' that has option 'exceptions'.
+  void ActOnPragmaFPExceptions(SourceLocation Loc,
+                               LangOptions::FPExceptionModeKind);
 
-  /// This virtual key function only exists to limit the emission of debug info
-  /// describing the Sema class. GCC and Clang only emit debug info for a class
-  /// with a vtable when the vtable is emitted. Sema is final and not
-  /// polymorphic, but the debug info size savings are so significant that it is
-  /// worth adding a vtable just to take advantage of this optimization.
-  virtual void anchor();
+  /// Called to set constant rounding mode for floating point operations.
+  void ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode);
 
-  const LangOptions &getLangOpts() const { return LangOpts; }
-  OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; }
-  FPOptions     &getCurFPFeatures() { return CurFPFeatures; }
+  /// Called to set exception behavior for floating point operations.
+  void setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind);
 
-  DiagnosticsEngine &getDiagnostics() const { return Diags; }
-  SourceManager &getSourceManager() const { return SourceMgr; }
-  Preprocessor &getPreprocessor() const { return PP; }
-  ASTContext &getASTContext() const { return Context; }
-  ASTConsumer &getASTConsumer() const { return Consumer; }
-  ASTMutationListener *getASTMutationListener() const;
-  ExternalSemaSource *getExternalSource() const { return ExternalSource.get(); }
+  /// PushNamespaceVisibilityAttr - Note that we've entered a
+  /// namespace with a visibility attribute.
+  void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
+                                   SourceLocation Loc);
 
-  DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc,
-                                                         StringRef Platform);
-  DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking();
+  /// PopPragmaVisibility - Pop the top element of the visibility stack; used
+  /// for '\#pragma GCC visibility' and visibility attributes on namespaces.
+  void PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc);
 
-  ///Registers an external source. If an external source already exists,
-  /// creates a multiplex external source and appends to it.
-  ///
-  ///\param[in] E - A non-null external sema source.
-  ///
-  void addExternalSource(ExternalSemaSource *E);
+  /// Handles semantic checking for features that are common to all attributes,
+  /// such as checking whether a parameter was properly specified, or the
+  /// correct number of arguments were passed, etc. Returns true if the
+  /// attribute has been diagnosed.
+  bool checkCommonAttributeFeatures(const Decl *D, const ParsedAttr &A,
+                                    bool SkipArgCountCheck = false);
+  bool checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A,
+                                    bool SkipArgCountCheck = false);
 
-  void PrintStats() const;
+  ///@}
 
-  /// Warn that the stack is nearly exhausted.
-  void warnStackExhausted(SourceLocation Loc);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Run some code with "sufficient" stack space. (Currently, at least 256K is
-  /// guaranteed). Produces a warning if we're low on stack space and allocates
-  /// more in that case. Use this in code that may recurse deeply (for example,
-  /// in template instantiation) to avoid stack overflow.
-  void runWithSufficientStackSpace(SourceLocation Loc,
-                                   llvm::function_ref Fn);
+  /// \name Availability Attribute Handling
+  /// Implementations are in SemaAvailability.cpp
+  ///@{
 
-  /// Helper class that creates diagnostics with optional
-  /// template instantiation stacks.
-  ///
-  /// This class provides a wrapper around the basic DiagnosticBuilder
-  /// class that emits diagnostics. ImmediateDiagBuilder is
-  /// responsible for emitting the diagnostic (as DiagnosticBuilder
-  /// does) and, if the diagnostic comes from inside a template
-  /// instantiation, printing the template instantiation stack as
-  /// well.
-  class ImmediateDiagBuilder : public DiagnosticBuilder {
-    Sema &SemaRef;
-    unsigned DiagID;
+public:
+  /// Issue any -Wunguarded-availability warnings in \c FD
+  void DiagnoseUnguardedAvailabilityViolations(Decl *FD);
 
-  public:
-    ImmediateDiagBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID)
-        : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) {}
-    ImmediateDiagBuilder(DiagnosticBuilder &&DB, Sema &SemaRef, unsigned DiagID)
-        : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) {}
+  void handleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
 
-    // This is a cunning lie. DiagnosticBuilder actually performs move
-    // construction in its copy constructor (but due to varied uses, it's not
-    // possible to conveniently express this as actual move construction). So
-    // the default copy ctor here is fine, because the base class disables the
-    // source anyway, so the user-defined ~ImmediateDiagBuilder is a safe no-op
-    // in that case anwyay.
-    ImmediateDiagBuilder(const ImmediateDiagBuilder &) = default;
+  /// Retrieve the current function, if any, that should be analyzed for
+  /// potential availability violations.
+  sema::FunctionScopeInfo *getCurFunctionAvailabilityContext();
 
-    ~ImmediateDiagBuilder() {
-      // If we aren't active, there is nothing to do.
-      if (!isActive()) return;
+  void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef Locs,
+                                  const ObjCInterfaceDecl *UnknownObjCClass,
+                                  bool ObjCPropertyAccess,
+                                  bool AvoidPartialAvailabilityChecks = false,
+                                  ObjCInterfaceDecl *ClassReceiver = nullptr);
 
-      // Otherwise, we need to emit the diagnostic. First clear the diagnostic
-      // builder itself so it won't emit the diagnostic in its own destructor.
-      //
-      // This seems wasteful, in that as written the DiagnosticBuilder dtor will
-      // do its own needless checks to see if the diagnostic needs to be
-      // emitted. However, because we take care to ensure that the builder
-      // objects never escape, a sufficiently smart compiler will be able to
-      // eliminate that code.
-      Clear();
+  ///@}
 
-      // Dispatch to Sema to emit the diagnostic.
-      SemaRef.EmitCurrentDiagnostic(DiagID);
-    }
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-    /// Teach operator<< to produce an object of the correct type.
-    template 
-    friend const ImmediateDiagBuilder &
-    operator<<(const ImmediateDiagBuilder &Diag, const T &Value) {
-      const DiagnosticBuilder &BaseDiag = Diag;
-      BaseDiag << Value;
-      return Diag;
-    }
+  /// \name Casts
+  /// Implementations are in SemaCast.cpp
+  ///@{
 
-    // It is necessary to limit this to rvalue reference to avoid calling this
-    // function with a bitfield lvalue argument since non-const reference to
-    // bitfield is not allowed.
-    template ::value>>
-    const ImmediateDiagBuilder &operator<<(T &&V) const {
-      const DiagnosticBuilder &BaseDiag = *this;
-      BaseDiag << std::move(V);
-      return *this;
-    }
-  };
+public:
+  static bool isCast(CheckedConversionKind CCK) {
+    return CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast ||
+           CCK == CCK_OtherCast;
+  }
 
-  /// A generic diagnostic builder for errors which may or may not be deferred.
-  ///
-  /// In CUDA, there exist constructs (e.g. variable-length arrays, try/catch)
-  /// which are not allowed to appear inside __device__ functions and are
-  /// allowed to appear in __host__ __device__ functions only if the host+device
-  /// function is never codegen'ed.
-  ///
-  /// To handle this, we use the notion of "deferred diagnostics", where we
-  /// attach a diagnostic to a FunctionDecl that's emitted iff it's codegen'ed.
-  ///
-  /// This class lets you emit either a regular diagnostic, a deferred
-  /// diagnostic, or no diagnostic at all, according to an argument you pass to
-  /// its constructor, thus simplifying the process of creating these "maybe
-  /// deferred" diagnostics.
-  class SemaDiagnosticBuilder {
-  public:
-    enum Kind {
-      /// Emit no diagnostics.
-      K_Nop,
-      /// Emit the diagnostic immediately (i.e., behave like Sema::Diag()).
-      K_Immediate,
-      /// Emit the diagnostic immediately, and, if it's a warning or error, also
-      /// emit a call stack showing how this function can be reached by an a
-      /// priori known-emitted function.
-      K_ImmediateWithCallStack,
-      /// Create a deferred diagnostic, which is emitted only if the function
-      /// it's attached to is codegen'ed.  Also emit a call stack as with
-      /// K_ImmediateWithCallStack.
-      K_Deferred
-    };
+  /// ActOnCXXNamedCast - Parse
+  /// {dynamic,static,reinterpret,const,addrspace}_cast's.
+  ExprResult ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+                               SourceLocation LAngleBracketLoc, Declarator &D,
+                               SourceLocation RAngleBracketLoc,
+                               SourceLocation LParenLoc, Expr *E,
+                               SourceLocation RParenLoc);
 
-    SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID,
-                          const FunctionDecl *Fn, Sema &S);
-    SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D);
-    SemaDiagnosticBuilder(const SemaDiagnosticBuilder &) = default;
+  ExprResult BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+                               TypeSourceInfo *Ty, Expr *E,
+                               SourceRange AngleBrackets, SourceRange Parens);
 
-    // The copy and move assignment operator is defined as deleted pending
-    // further motivation.
-    SemaDiagnosticBuilder &operator=(const SemaDiagnosticBuilder &) = delete;
-    SemaDiagnosticBuilder &operator=(SemaDiagnosticBuilder &&) = delete;
+  ExprResult ActOnBuiltinBitCastExpr(SourceLocation KWLoc, Declarator &Dcl,
+                                     ExprResult Operand,
+                                     SourceLocation RParenLoc);
 
-    ~SemaDiagnosticBuilder();
+  ExprResult BuildBuiltinBitCastExpr(SourceLocation KWLoc, TypeSourceInfo *TSI,
+                                     Expr *Operand, SourceLocation RParenLoc);
 
-    bool isImmediate() const { return ImmediateDiag.has_value(); }
+  // Checks that reinterpret casts don't have undefined behavior.
+  void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
+                                      bool IsDereference, SourceRange Range);
 
-    /// Convertible to bool: True if we immediately emitted an error, false if
-    /// we didn't emit an error or we created a deferred error.
-    ///
-    /// Example usage:
-    ///
-    ///   if (SemaDiagnosticBuilder(...) << foo << bar)
-    ///     return ExprError();
-    ///
-    /// But see CUDADiagIfDeviceCode() and CUDADiagIfHostCode() -- you probably
-    /// want to use these instead of creating a SemaDiagnosticBuilder yourself.
-    operator bool() const { return isImmediate(); }
+  // Checks that the vector type should be initialized from a scalar
+  // by splatting the value rather than populating a single element.
+  // This is the case for AltiVecVector types as well as with
+  // AltiVecPixel and AltiVecBool when -faltivec-src-compat=xl is specified.
+  bool ShouldSplatAltivecScalarInCast(const VectorType *VecTy);
 
-    template 
-    friend const SemaDiagnosticBuilder &
-    operator<<(const SemaDiagnosticBuilder &Diag, const T &Value) {
-      if (Diag.ImmediateDiag)
-        *Diag.ImmediateDiag << Value;
-      else if (Diag.PartialDiagId)
-        Diag.S.DeviceDeferredDiags[Diag.Fn][*Diag.PartialDiagId].second
-            << Value;
-      return Diag;
-    }
+  // Checks if the -faltivec-src-compat=gcc option is specified.
+  // If so, AltiVecVector, AltiVecBool and AltiVecPixel types are
+  // treated the same way as they are when trying to initialize
+  // these vectors on gcc (an error is emitted).
+  bool CheckAltivecInitFromScalar(SourceRange R, QualType VecTy,
+                                  QualType SrcTy);
 
-    // It is necessary to limit this to rvalue reference to avoid calling this
-    // function with a bitfield lvalue argument since non-const reference to
-    // bitfield is not allowed.
-    template ::value>>
-    const SemaDiagnosticBuilder &operator<<(T &&V) const {
-      if (ImmediateDiag)
-        *ImmediateDiag << std::move(V);
-      else if (PartialDiagId)
-        S.DeviceDeferredDiags[Fn][*PartialDiagId].second << std::move(V);
-      return *this;
-    }
+  ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
+                                 SourceLocation RParenLoc, Expr *Op);
 
-    friend const SemaDiagnosticBuilder &
-    operator<<(const SemaDiagnosticBuilder &Diag, const PartialDiagnostic &PD) {
-      if (Diag.ImmediateDiag)
-        PD.Emit(*Diag.ImmediateDiag);
-      else if (Diag.PartialDiagId)
-        Diag.S.DeviceDeferredDiags[Diag.Fn][*Diag.PartialDiagId].second = PD;
-      return Diag;
-    }
+  ExprResult BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo, QualType Type,
+                                        SourceLocation LParenLoc,
+                                        Expr *CastExpr,
+                                        SourceLocation RParenLoc);
 
-    void AddFixItHint(const FixItHint &Hint) const {
-      if (ImmediateDiag)
-        ImmediateDiag->AddFixItHint(Hint);
-      else if (PartialDiagId)
-        S.DeviceDeferredDiags[Fn][*PartialDiagId].second.AddFixItHint(Hint);
-    }
+  ///@}
 
-    friend ExprResult ExprError(const SemaDiagnosticBuilder &) {
-      return ExprError();
-    }
-    friend StmtResult StmtError(const SemaDiagnosticBuilder &) {
-      return StmtError();
-    }
-    operator ExprResult() const { return ExprError(); }
-    operator StmtResult() const { return StmtError(); }
-    operator TypeResult() const { return TypeError(); }
-    operator DeclResult() const { return DeclResult(true); }
-    operator MemInitResult() const { return MemInitResult(true); }
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  private:
-    Sema &S;
-    SourceLocation Loc;
-    unsigned DiagID;
-    const FunctionDecl *Fn;
-    bool ShowCallStack;
+  /// \name Extra Semantic Checking
+  /// Implementations are in SemaChecking.cpp
+  ///@{
 
-    // Invariant: At most one of these Optionals has a value.
-    // FIXME: Switch these to a Variant once that exists.
-    std::optional ImmediateDiag;
-    std::optional PartialDiagId;
-  };
+public:
+  /// Used to change context to isConstantEvaluated without pushing a heavy
+  /// ExpressionEvaluationContextRecord object.
+  bool isConstantEvaluatedOverride = false;
 
-  /// Is the last error level diagnostic immediate. This is used to determined
-  /// whether the next info diagnostic should be immediate.
-  bool IsLastErrorImmediate = true;
+  bool isConstantEvaluatedContext() const {
+    return currentEvaluationContext().isConstantEvaluated() ||
+           isConstantEvaluatedOverride;
+  }
 
-  /// Emit a diagnostic.
-  SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID,
-                             bool DeferHint = false);
+  SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
+                                                unsigned ByteNo) const;
 
-  /// Emit a partial diagnostic.
-  SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic &PD,
-                             bool DeferHint = false);
+  enum FormatArgumentPassingKind {
+    FAPK_Fixed,    // values to format are fixed (no C-style variadic arguments)
+    FAPK_Variadic, // values to format are passed as variadic arguments
+    FAPK_VAList,   // values to format are passed in a va_list
+  };
 
-  /// Build a partial diagnostic.
-  PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h
+  // Used to grab the relevant information from a FormatAttr and a
+  // FunctionDeclaration.
+  struct FormatStringInfo {
+    unsigned FormatIdx;
+    unsigned FirstDataArg;
+    FormatArgumentPassingKind ArgPassingKind;
+  };
 
-  /// Whether deferrable diagnostics should be deferred.
-  bool DeferDiags = false;
+  static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
+                                  bool IsVariadic, FormatStringInfo *FSI);
 
-  /// RAII class to control scope of DeferDiags.
-  class DeferDiagsRAII {
-    Sema &S;
-    bool SavedDeferDiags = false;
+  // Used by C++ template instantiation.
+  ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
+  ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
+                                   SourceLocation BuiltinLoc,
+                                   SourceLocation RParenLoc);
 
-  public:
-    DeferDiagsRAII(Sema &S, bool DeferDiags)
-        : S(S), SavedDeferDiags(S.DeferDiags) {
-      S.DeferDiags = DeferDiags;
-    }
-    ~DeferDiagsRAII() { S.DeferDiags = SavedDeferDiags; }
+  enum FormatStringType {
+    FST_Scanf,
+    FST_Printf,
+    FST_NSString,
+    FST_Strftime,
+    FST_Strfmon,
+    FST_Kprintf,
+    FST_FreeBSDKPrintf,
+    FST_OSTrace,
+    FST_OSLog,
+    FST_Unknown
   };
+  static FormatStringType GetFormatStringType(const FormatAttr *Format);
 
-  /// Whether uncompilable error has occurred. This includes error happens
-  /// in deferred diagnostics.
-  bool hasUncompilableErrorOccurred() const;
+  bool FormatStringHasSArg(const StringLiteral *FExpr);
 
-  bool findMacroSpelling(SourceLocation &loc, StringRef name);
+  static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);
 
-  /// Get a string to suggest for zero-initialization of a type.
-  std::string
-  getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const;
-  std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const;
+  void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
+                            BinaryOperatorKind Opcode);
 
-  /// Calls \c Lexer::getLocForEndOfToken()
-  SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0);
+  /// Register a magic integral constant to be used as a type tag.
+  void RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind,
+                                  uint64_t MagicValue, QualType Type,
+                                  bool LayoutCompatible, bool MustBeNull);
 
-  /// Retrieve the module loader associated with the preprocessor.
-  ModuleLoader &getModuleLoader() const;
+  struct TypeTagData {
+    TypeTagData() {}
 
-  /// Invent a new identifier for parameters of abbreviated templates.
-  IdentifierInfo *
-  InventAbbreviatedTemplateParameterTypeName(IdentifierInfo *ParamName,
-                                             unsigned Index);
+    TypeTagData(QualType Type, bool LayoutCompatible, bool MustBeNull)
+        : Type(Type), LayoutCompatible(LayoutCompatible),
+          MustBeNull(MustBeNull) {}
 
-  void emitAndClearUnusedLocalTypedefWarnings();
+    QualType Type;
 
-  private:
-    /// Function or variable declarations to be checked for whether the deferred
-    /// diagnostics should be emitted.
-    llvm::SmallSetVector DeclsToCheckForDeferredDiags;
+    /// If true, \c Type should be compared with other expression's types for
+    /// layout-compatibility.
+    LLVM_PREFERRED_TYPE(bool)
+    unsigned LayoutCompatible : 1;
+    LLVM_PREFERRED_TYPE(bool)
+    unsigned MustBeNull : 1;
+  };
 
-  public:
-  // Emit all deferred diagnostics.
-  void emitDeferredDiags();
+  /// A pair of ArgumentKind identifier and magic value.  This uniquely
+  /// identifies the magic value.
+  typedef std::pair TypeTagMagicValue;
 
-  enum TUFragmentKind {
-    /// The global module fragment, between 'module;' and a module-declaration.
-    Global,
-    /// A normal translation unit fragment. For a non-module unit, this is the
-    /// entire translation unit. Otherwise, it runs from the module-declaration
-    /// to the private-module-fragment (if any) or the end of the TU (if not).
-    Normal,
-    /// The private module fragment, between 'module :private;' and the end of
-    /// the translation unit.
-    Private
-  };
+  /// Diagnoses the current set of gathered accesses. This typically
+  /// happens at full expression level. The set is cleared after emitting the
+  /// diagnostics.
+  void DiagnoseMisalignedMembers();
 
-  void ActOnStartOfTranslationUnit();
-  void ActOnEndOfTranslationUnit();
-  void ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind);
+  /// This function checks if the expression is in the sef of potentially
+  /// misaligned members and it is converted to some pointer type T with lower
+  /// or equal alignment requirements. If so it removes it. This is used when
+  /// we do not want to diagnose such misaligned access (e.g. in conversions to
+  /// void*).
+  void DiscardMisalignedMemberAddress(const Type *T, Expr *E);
 
-  void CheckDelegatingCtorCycles();
+  /// This function calls Action when it determines that E designates a
+  /// misaligned member due to the packed attribute. This is used to emit
+  /// local diagnostics like in reference binding.
+  void RefersToMemberWithReducedAlignment(
+      Expr *E,
+      llvm::function_ref
+          Action);
 
-  Scope *getScopeForContext(DeclContext *Ctx);
+  enum class AtomicArgumentOrder { API, AST };
+  ExprResult
+  BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
+                  SourceLocation RParenLoc, MultiExprArg Args,
+                  AtomicExpr::AtomicOp Op,
+                  AtomicArgumentOrder ArgOrder = AtomicArgumentOrder::API);
 
-  void PushFunctionScope();
-  void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
-  sema::LambdaScopeInfo *PushLambdaScope();
+  /// Check to see if a given expression could have '.c_str()' called on it.
+  bool hasCStrMethod(const Expr *E);
 
-  /// This is used to inform Sema what the current TemplateParameterDepth
-  /// is during Parsing.  Currently it is used to pass on the depth
-  /// when parsing generic lambda 'auto' parameters.
-  void RecordParsingTemplateParameterDepth(unsigned Depth);
+  void DiagnoseAlwaysNonNullPointer(Expr *E,
+                                    Expr::NullPointerConstantKind NullType,
+                                    bool IsEqual, SourceRange Range);
 
-  void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
-                               RecordDecl *RD, CapturedRegionKind K,
-                               unsigned OpenMPCaptureLevel = 0);
+  bool CheckParmsForFunctionDef(ArrayRef Parameters,
+                                bool CheckParameterNames);
 
-  /// Custom deleter to allow FunctionScopeInfos to be kept alive for a short
-  /// time after they've been popped.
-  class PoppedFunctionScopeDeleter {
-    Sema *Self;
+  void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange);
 
-  public:
-    explicit PoppedFunctionScopeDeleter(Sema *Self) : Self(Self) {}
-    void operator()(sema::FunctionScopeInfo *Scope) const;
-  };
+  /// checkRetainCycles - Check whether an Objective-C message send
+  /// might create an obvious retain cycle.
+  void checkRetainCycles(ObjCMessageExpr *msg);
+  void checkRetainCycles(Expr *receiver, Expr *argument);
+  void checkRetainCycles(VarDecl *Var, Expr *Init);
 
-  using PoppedFunctionScopePtr =
-      std::unique_ptr;
+  /// checkUnsafeAssigns - Check whether +1 expr is being assigned
+  /// to weak/__unsafe_unretained type.
+  bool checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS);
 
-  PoppedFunctionScopePtr
-  PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP = nullptr,
-                       const Decl *D = nullptr,
-                       QualType BlockType = QualType());
+  /// checkUnsafeExprAssigns - Check whether +1 expr is being assigned
+  /// to weak/__unsafe_unretained expression.
+  void checkUnsafeExprAssigns(SourceLocation Loc, Expr *LHS, Expr *RHS);
 
-  sema::FunctionScopeInfo *getCurFunction() const {
-    return FunctionScopes.empty() ? nullptr : FunctionScopes.back();
-  }
+  /// Emit \p DiagID if statement located on \p StmtLoc has a suspicious null
+  /// statement as a \p Body, and it is located on the same line.
+  ///
+  /// This helps prevent bugs due to typos, such as:
+  ///     if (condition);
+  ///       do_stuff();
+  void DiagnoseEmptyStmtBody(SourceLocation StmtLoc, const Stmt *Body,
+                             unsigned DiagID);
 
-  sema::FunctionScopeInfo *getEnclosingFunction() const;
+  /// Warn if a for/while loop statement \p S, which is followed by
+  /// \p PossibleBody, has a suspicious null statement as a body.
+  void DiagnoseEmptyLoopBody(const Stmt *S, const Stmt *PossibleBody);
 
-  void setFunctionHasBranchIntoScope();
-  void setFunctionHasBranchProtectedScope();
-  void setFunctionHasIndirectGoto();
-  void setFunctionHasMustTail();
+  /// Warn if a value is moved to itself.
+  void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
+                        SourceLocation OpLoc);
 
-  void PushCompoundScope(bool IsStmtExpr);
-  void PopCompoundScope();
+  // Used for emitting the right warning by DefaultVariadicArgumentPromotion
+  enum VariadicCallType {
+    VariadicFunction,
+    VariadicBlock,
+    VariadicMethod,
+    VariadicConstructor,
+    VariadicDoesNotApply
+  };
 
-  sema::CompoundScopeInfo &getCurCompoundScope() const;
+  bool IsLayoutCompatible(QualType T1, QualType T2) const;
 
-  bool hasAnyUnrecoverableErrorsInThisFunction() const;
+private:
+  void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
+                        const ArraySubscriptExpr *ASE = nullptr,
+                        bool AllowOnePastEnd = true, bool IndexNegated = false);
+  void CheckArrayAccess(const Expr *E);
 
-  /// Retrieve the current block, if any.
-  sema::BlockScopeInfo *getCurBlock();
+  bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
+                         const FunctionProtoType *Proto);
+  bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc,
+                           ArrayRef Args);
+  bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
+                        const FunctionProtoType *Proto);
+  bool CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto);
+  void CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType,
+                            ArrayRef Args,
+                            const FunctionProtoType *Proto, SourceLocation Loc);
 
-  /// Get the innermost lambda enclosing the current location, if any. This
-  /// looks through intervening non-lambda scopes such as local functions and
-  /// blocks.
-  sema::LambdaScopeInfo *getEnclosingLambda() const;
+  void checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg);
 
-  /// Retrieve the current lambda scope info, if any.
-  /// \param IgnoreNonLambdaCapturingScope true if should find the top-most
-  /// lambda scope info ignoring all inner capturing scopes that are not
-  /// lambda scopes.
-  sema::LambdaScopeInfo *
-  getCurLambda(bool IgnoreNonLambdaCapturingScope = false);
+  void CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl,
+                         StringRef ParamName, QualType ArgTy, QualType ParamTy);
 
-  /// Retrieve the current generic lambda info, if any.
-  sema::LambdaScopeInfo *getCurGenericLambda();
+  void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
+                 const Expr *ThisArg, ArrayRef Args,
+                 bool IsMemberFunction, SourceLocation Loc, SourceRange Range,
+                 VariadicCallType CallType);
 
-  /// Retrieve the current captured region, if any.
-  sema::CapturedRegionScopeInfo *getCurCapturedRegion();
+  bool CheckObjCString(Expr *Arg);
+  ExprResult CheckOSLogFormatStringArg(Expr *Arg);
 
-  /// Retrieve the current function, if any, that should be analyzed for
-  /// potential availability violations.
-  sema::FunctionScopeInfo *getCurFunctionAvailabilityContext();
+  ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
+                                      CallExpr *TheCall);
 
-  /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
-  SmallVectorImpl &WeakTopLevelDecls() { return WeakTopLevelDecl; }
+  bool CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
+                                  CallExpr *TheCall);
 
-  /// Called before parsing a function declarator belonging to a function
-  /// declaration.
-  void ActOnStartFunctionDeclarationDeclarator(Declarator &D,
-                                               unsigned TemplateParameterDepth);
+  void checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, CallExpr *TheCall);
 
-  /// Called after parsing a function declarator belonging to a function
-  /// declaration.
-  void ActOnFinishFunctionDeclarationDeclarator(Declarator &D);
-
-  void ActOnComment(SourceRange Comment);
+  bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
+                                    unsigned MaxWidth);
+  bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
+                                    CallExpr *TheCall);
+  bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+  bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+  bool ParseSVEImmChecks(CallExpr *TheCall,
+                         SmallVector, 3> &ImmChecks);
+  bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+  bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
+                                   CallExpr *TheCall);
+  bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg,
+                                    bool WantCDE);
+  bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
+                                   CallExpr *TheCall);
 
-  //===--------------------------------------------------------------------===//
-  // Type Analysis / Processing: SemaType.cpp.
-  //
+  bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
+                                       CallExpr *TheCall);
+  bool CheckBPFBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+  bool CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+  bool CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
+  bool CheckMipsBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
+                                    CallExpr *TheCall);
+  bool CheckMipsBuiltinCpu(const TargetInfo &TI, unsigned BuiltinID,
+                           CallExpr *TheCall);
+  bool CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
+  bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+  bool CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall);
+  bool CheckX86BuiltinGatherScatterScale(unsigned BuiltinID, CallExpr *TheCall);
+  bool CheckX86BuiltinTileArguments(unsigned BuiltinID, CallExpr *TheCall);
+  bool CheckX86BuiltinTileArgumentsRange(CallExpr *TheCall,
+                                         ArrayRef ArgNums);
+  bool CheckX86BuiltinTileDuplicate(CallExpr *TheCall, ArrayRef ArgNums);
+  bool CheckX86BuiltinTileRangeAndDuplicate(CallExpr *TheCall,
+                                            ArrayRef ArgNums);
+  bool CheckX86BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
+                                   CallExpr *TheCall);
+  bool CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
+                                   CallExpr *TheCall);
+  bool CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+  bool CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum);
+  bool CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
+                                     CallExpr *TheCall);
+  void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D);
+  bool CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI,
+                                         unsigned BuiltinID, CallExpr *TheCall);
+  bool CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI,
+                                           unsigned BuiltinID,
+                                           CallExpr *TheCall);
+  bool CheckNVPTXBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
+                                     CallExpr *TheCall);
 
-  QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs,
-                              const DeclSpec *DS = nullptr);
-  QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVRA,
-                              const DeclSpec *DS = nullptr);
-  QualType BuildPointerType(QualType T,
-                            SourceLocation Loc, DeclarationName Entity);
-  QualType BuildReferenceType(QualType T, bool LValueRef,
-                              SourceLocation Loc, DeclarationName Entity);
-  QualType BuildArrayType(QualType T, ArraySizeModifier ASM, Expr *ArraySize,
-                          unsigned Quals, SourceRange Brackets,
-                          DeclarationName Entity);
-  QualType BuildVectorType(QualType T, Expr *VecSize, SourceLocation AttrLoc);
-  QualType BuildExtVectorType(QualType T, Expr *ArraySize,
-                              SourceLocation AttrLoc);
-  QualType BuildMatrixType(QualType T, Expr *NumRows, Expr *NumColumns,
-                           SourceLocation AttrLoc);
+  bool SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall);
+  bool SemaBuiltinVAStartARMMicrosoft(CallExpr *Call);
+  bool SemaBuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID);
+  bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs,
+                                   unsigned BuiltinID);
+  bool SemaBuiltinComplex(CallExpr *TheCall);
+  bool SemaBuiltinVSX(CallExpr *TheCall);
+  bool SemaBuiltinOSLogFormat(CallExpr *TheCall);
+  bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
-  QualType BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace,
-                                 SourceLocation AttrLoc);
+  bool SemaBuiltinPrefetch(CallExpr *TheCall);
+  bool SemaBuiltinAllocaWithAlign(CallExpr *TheCall);
+  bool SemaBuiltinArithmeticFence(CallExpr *TheCall);
+  bool SemaBuiltinAssume(CallExpr *TheCall);
+  bool SemaBuiltinAssumeAligned(CallExpr *TheCall);
+  bool SemaBuiltinLongjmp(CallExpr *TheCall);
+  bool SemaBuiltinSetjmp(CallExpr *TheCall);
+  ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult);
+  ExprResult SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult);
+  ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult,
+                                     AtomicExpr::AtomicOp Op);
+  bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
+                              llvm::APSInt &Result);
+  bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low,
+                                   int High, bool RangeIsError = true);
+  bool SemaBuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum,
+                                      unsigned Multiple);
+  bool SemaBuiltinConstantArgPower2(CallExpr *TheCall, int ArgNum);
+  bool SemaBuiltinConstantArgShiftedByte(CallExpr *TheCall, int ArgNum,
+                                         unsigned ArgBits);
+  bool SemaBuiltinConstantArgShiftedByteOrXXFF(CallExpr *TheCall, int ArgNum,
+                                               unsigned ArgBits);
+  bool SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
+                                int ArgNum, unsigned ExpectedFieldNum,
+                                bool AllowName);
+  bool SemaBuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall);
+  bool SemaBuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID,
+                             const char *TypeDesc);
 
-  /// Same as above, but constructs the AddressSpace index if not provided.
-  QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
-                                 SourceLocation AttrLoc);
+  bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc);
 
-  CodeAlignAttr *BuildCodeAlignAttr(const AttributeCommonInfo &CI, Expr *E);
-  bool CheckRebuiltStmtAttributes(ArrayRef Attrs);
+  bool SemaBuiltinElementwiseMath(CallExpr *TheCall);
+  bool SemaBuiltinElementwiseTernaryMath(CallExpr *TheCall,
+                                         bool CheckForFloatArgs = true);
+  bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall);
+  bool PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall);
 
-  bool CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc);
+  bool SemaBuiltinNonDeterministicValue(CallExpr *TheCall);
 
-  bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
+  // Matrix builtin handling.
+  ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall,
+                                        ExprResult CallResult);
+  ExprResult SemaBuiltinMatrixColumnMajorLoad(CallExpr *TheCall,
+                                              ExprResult CallResult);
+  ExprResult SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall,
+                                               ExprResult CallResult);
 
-  /// Check an argument list for placeholders that we won't try to
-  /// handle later.
-  bool CheckArgsForPlaceholders(MultiExprArg args);
+  // WebAssembly builtin handling.
+  bool BuiltinWasmRefNullExtern(CallExpr *TheCall);
+  bool BuiltinWasmRefNullFunc(CallExpr *TheCall);
+  bool BuiltinWasmTableGet(CallExpr *TheCall);
+  bool BuiltinWasmTableSet(CallExpr *TheCall);
+  bool BuiltinWasmTableSize(CallExpr *TheCall);
+  bool BuiltinWasmTableGrow(CallExpr *TheCall);
+  bool BuiltinWasmTableFill(CallExpr *TheCall);
+  bool BuiltinWasmTableCopy(CallExpr *TheCall);
 
-  /// Build a function type.
-  ///
-  /// This routine checks the function type according to C++ rules and
-  /// under the assumption that the result type and parameter types have
-  /// just been instantiated from a template. It therefore duplicates
-  /// some of the behavior of GetTypeForDeclarator, but in a much
-  /// simpler form that is only suitable for this narrow use case.
-  ///
-  /// \param T The return type of the function.
-  ///
-  /// \param ParamTypes The parameter types of the function. This array
-  /// will be modified to account for adjustments to the types of the
-  /// function parameters.
-  ///
-  /// \param Loc The location of the entity whose type involves this
-  /// function type or, if there is no such entity, the location of the
-  /// type that will have function type.
-  ///
-  /// \param Entity The name of the entity that involves the function
-  /// type, if known.
-  ///
-  /// \param EPI Extra information about the function type. Usually this will
-  /// be taken from an existing function with the same prototype.
-  ///
-  /// \returns A suitable function type, if there are no errors. The
-  /// unqualified type will always be a FunctionProtoType.
-  /// Otherwise, returns a NULL type.
-  QualType BuildFunctionType(QualType T,
-                             MutableArrayRef ParamTypes,
-                             SourceLocation Loc, DeclarationName Entity,
-                             const FunctionProtoType::ExtProtoInfo &EPI);
+  bool CheckFormatArguments(const FormatAttr *Format,
+                            ArrayRef Args, bool IsCXXMember,
+                            VariadicCallType CallType, SourceLocation Loc,
+                            SourceRange Range,
+                            llvm::SmallBitVector &CheckedVarArgs);
+  bool CheckFormatArguments(ArrayRef Args,
+                            FormatArgumentPassingKind FAPK, unsigned format_idx,
+                            unsigned firstDataArg, FormatStringType Type,
+                            VariadicCallType CallType, SourceLocation Loc,
+                            SourceRange range,
+                            llvm::SmallBitVector &CheckedVarArgs);
 
-  QualType BuildMemberPointerType(QualType T, QualType Class,
-                                  SourceLocation Loc,
-                                  DeclarationName Entity);
-  QualType BuildBlockPointerType(QualType T,
-                                 SourceLocation Loc, DeclarationName Entity);
-  QualType BuildParenType(QualType T);
-  QualType BuildAtomicType(QualType T, SourceLocation Loc);
-  QualType BuildReadPipeType(QualType T,
-                         SourceLocation Loc);
-  QualType BuildWritePipeType(QualType T,
-                         SourceLocation Loc);
-  QualType BuildBitIntType(bool IsUnsigned, Expr *BitWidth, SourceLocation Loc);
+  void CheckInfNaNFunction(const CallExpr *Call, const FunctionDecl *FDecl);
 
-  TypeSourceInfo *GetTypeForDeclarator(Declarator &D);
-  TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
+  void CheckAbsoluteValueFunction(const CallExpr *Call,
+                                  const FunctionDecl *FDecl);
 
-  /// Package the given type and TSI into a ParsedType.
-  ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo);
-  DeclarationNameInfo GetNameForDeclarator(Declarator &D);
-  DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name);
-  static QualType GetTypeFromParser(ParsedType Ty,
-                                    TypeSourceInfo **TInfo = nullptr);
-  CanThrowResult canThrow(const Stmt *E);
-  /// Determine whether the callee of a particular function call can throw.
-  /// E, D and Loc are all optional.
-  static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D,
-                                       SourceLocation Loc = SourceLocation());
-  const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc,
-                                                const FunctionProtoType *FPT);
-  void UpdateExceptionSpec(FunctionDecl *FD,
-                           const FunctionProtoType::ExceptionSpecInfo &ESI);
-  bool CheckSpecifiedExceptionType(QualType &T, SourceRange Range);
-  bool CheckDistantExceptionSpec(QualType T);
-  bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New);
-  bool CheckEquivalentExceptionSpec(
-      const FunctionProtoType *Old, SourceLocation OldLoc,
-      const FunctionProtoType *New, SourceLocation NewLoc);
-  bool CheckEquivalentExceptionSpec(
-      const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
-      const FunctionProtoType *Old, SourceLocation OldLoc,
-      const FunctionProtoType *New, SourceLocation NewLoc);
-  bool handlerCanCatch(QualType HandlerType, QualType ExceptionType);
-  bool CheckExceptionSpecSubset(
-      const PartialDiagnostic &DiagID, const PartialDiagnostic &NestedDiagID,
-      const PartialDiagnostic &NoteID, const PartialDiagnostic &NoThrowDiagID,
-      const FunctionProtoType *Superset, bool SkipSupersetFirstParameter,
-      SourceLocation SuperLoc, const FunctionProtoType *Subset,
-      bool SkipSubsetFirstParameter, SourceLocation SubLoc);
-  bool CheckParamExceptionSpec(
-      const PartialDiagnostic &NestedDiagID, const PartialDiagnostic &NoteID,
-      const FunctionProtoType *Target, bool SkipTargetFirstParameter,
-      SourceLocation TargetLoc, const FunctionProtoType *Source,
-      bool SkipSourceFirstParameter, SourceLocation SourceLoc);
+  void CheckMaxUnsignedZero(const CallExpr *Call, const FunctionDecl *FDecl);
 
-  TypeResult ActOnTypeName(Declarator &D);
+  void CheckMemaccessArguments(const CallExpr *Call, unsigned BId,
+                               IdentifierInfo *FnName);
 
-  /// The parser has parsed the context-sensitive type 'instancetype'
-  /// in an Objective-C message declaration. Return the appropriate type.
-  ParsedType ActOnObjCInstanceType(SourceLocation Loc);
+  void CheckStrlcpycatArguments(const CallExpr *Call, IdentifierInfo *FnName);
 
-  /// Abstract class used to diagnose incomplete types.
-  struct TypeDiagnoser {
-    TypeDiagnoser() {}
+  void CheckStrncatArguments(const CallExpr *Call, IdentifierInfo *FnName);
 
-    virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0;
-    virtual ~TypeDiagnoser() {}
-  };
+  void CheckFreeArguments(const CallExpr *E);
 
-  static int getPrintable(int I) { return I; }
-  static unsigned getPrintable(unsigned I) { return I; }
-  static bool getPrintable(bool B) { return B; }
-  static const char * getPrintable(const char *S) { return S; }
-  static StringRef getPrintable(StringRef S) { return S; }
-  static const std::string &getPrintable(const std::string &S) { return S; }
-  static const IdentifierInfo *getPrintable(const IdentifierInfo *II) {
-    return II;
-  }
-  static DeclarationName getPrintable(DeclarationName N) { return N; }
-  static QualType getPrintable(QualType T) { return T; }
-  static SourceRange getPrintable(SourceRange R) { return R; }
-  static SourceRange getPrintable(SourceLocation L) { return L; }
-  static SourceRange getPrintable(const Expr *E) { return E->getSourceRange(); }
-  static SourceRange getPrintable(TypeLoc TL) { return TL.getSourceRange();}
+  void CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
+                          SourceLocation ReturnLoc, bool isObjCMethod = false,
+                          const AttrVec *Attrs = nullptr,
+                          const FunctionDecl *FD = nullptr);
 
-  template  class BoundTypeDiagnoser : public TypeDiagnoser {
-  protected:
-    unsigned DiagID;
-    std::tuple Args;
+  void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
+  void CheckBoolLikeConversion(Expr *E, SourceLocation CC);
+  void CheckForIntOverflow(const Expr *E);
+  void CheckUnsequencedOperations(const Expr *E);
 
-    template 
-    void emit(const SemaDiagnosticBuilder &DB,
-              std::index_sequence) const {
-      // Apply all tuple elements to the builder in order.
-      bool Dummy[] = {false, (DB << getPrintable(std::get(Args)))...};
-      (void)Dummy;
-    }
+  /// Perform semantic checks on a completed expression. This will either
+  /// be a full-expression or a default argument expression.
+  void CheckCompletedExpr(Expr *E, SourceLocation CheckLoc = SourceLocation(),
+                          bool IsConstexpr = false);
 
-  public:
-    BoundTypeDiagnoser(unsigned DiagID, const Ts &...Args)
-        : TypeDiagnoser(), DiagID(DiagID), Args(Args...) {
-      assert(DiagID != 0 && "no diagnostic for type diagnoser");
-    }
+  void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field,
+                                   Expr *Init);
+  /// Check whether receiver is mutable ObjC container which
+  /// attempts to add itself into the container
+  void CheckObjCCircularContainer(ObjCMessageExpr *Message);
 
-    void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
-      const SemaDiagnosticBuilder &DB = S.Diag(Loc, DiagID);
-      emit(DB, std::index_sequence_for());
-      DB << T;
-    }
-  };
+  void CheckTCBEnforcement(const SourceLocation CallExprLoc,
+                           const NamedDecl *Callee);
 
-  /// Do a check to make sure \p Name looks like a legal argument for the
-  /// swift_name attribute applied to decl \p D.  Raise a diagnostic if the name
-  /// is invalid for the given declaration.
-  ///
-  /// \p AL is used to provide caret diagnostics in case of a malformed name.
-  ///
-  /// \returns true if the name is a valid swift name for \p D, false otherwise.
-  bool DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc,
-                         const ParsedAttr &AL, bool IsAsync);
+  /// A map from magic value to type information.
+  std::unique_ptr>
+      TypeTagForDatatypeMagicValues;
 
-  /// A derivative of BoundTypeDiagnoser for which the diagnostic's type
-  /// parameter is preceded by a 0/1 enum that is 1 if the type is sizeless.
-  /// For example, a diagnostic with no other parameters would generally have
-  /// the form "...%select{incomplete|sizeless}0 type %1...".
-  template 
-  class SizelessTypeDiagnoser : public BoundTypeDiagnoser {
-  public:
-    SizelessTypeDiagnoser(unsigned DiagID, const Ts &... Args)
-        : BoundTypeDiagnoser(DiagID, Args...) {}
+  /// Peform checks on a call of a function with argument_with_type_tag
+  /// or pointer_with_type_tag attributes.
+  void CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
+                                const ArrayRef ExprArgs,
+                                SourceLocation CallSiteLoc);
 
-    void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
-      const SemaDiagnosticBuilder &DB = S.Diag(Loc, this->DiagID);
-      this->emit(DB, std::index_sequence_for());
-      DB << T->isSizelessType() << T;
-    }
-  };
+  /// Check if we are taking the address of a packed field
+  /// as this may be a problem if the pointer value is dereferenced.
+  void CheckAddressOfPackedMember(Expr *rhs);
 
-  enum class CompleteTypeKind {
-    /// Apply the normal rules for complete types.  In particular,
-    /// treat all sizeless types as incomplete.
-    Normal,
+  /// Helper class that collects misaligned member designations and
+  /// their location info for delayed diagnostics.
+  struct MisalignedMember {
+    Expr *E;
+    RecordDecl *RD;
+    ValueDecl *MD;
+    CharUnits Alignment;
 
-    /// Relax the normal rules for complete types so that they include
-    /// sizeless built-in types.
-    AcceptSizeless,
+    MisalignedMember() : E(), RD(), MD() {}
+    MisalignedMember(Expr *E, RecordDecl *RD, ValueDecl *MD,
+                     CharUnits Alignment)
+        : E(E), RD(RD), MD(MD), Alignment(Alignment) {}
+    explicit MisalignedMember(Expr *E)
+        : MisalignedMember(E, nullptr, nullptr, CharUnits()) {}
 
-    // FIXME: Eventually we should flip the default to Normal and opt in
-    // to AcceptSizeless rather than opt out of it.
-    Default = AcceptSizeless
+    bool operator==(const MisalignedMember &m) { return this->E == m.E; }
   };
+  /// Small set of gathered accesses to potentially misaligned members
+  /// due to the packed attribute.
+  SmallVector MisalignedMembers;
 
-  enum class AcceptableKind { Visible, Reachable };
-
-private:
-  /// Methods for marking which expressions involve dereferencing a pointer
-  /// marked with the 'noderef' attribute. Expressions are checked bottom up as
-  /// they are parsed, meaning that a noderef pointer may not be accessed. For
-  /// example, in `&*p` where `p` is a noderef pointer, we will first parse the
-  /// `*p`, but need to check that `address of` is called on it. This requires
-  /// keeping a container of all pending expressions and checking if the address
-  /// of them are eventually taken.
-  void CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E);
-  void CheckAddressOfNoDeref(const Expr *E);
-  void CheckMemberAccessOfNoDeref(const MemberExpr *E);
+  /// Adds an expression to the set of gathered misaligned members.
+  void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,
+                                     CharUnits Alignment);
+  ///@}
 
-  bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
-                               CompleteTypeKind Kind, TypeDiagnoser *Diagnoser);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  struct ModuleScope {
-    SourceLocation BeginLoc;
-    clang::Module *Module = nullptr;
-    VisibleModuleSet OuterVisibleModules;
-  };
-  /// The modules we're currently parsing.
-  llvm::SmallVector ModuleScopes;
+  /// \name C++ Coroutines
+  /// Implementations are in SemaCoroutine.cpp
+  ///@{
 
-  /// For an interface unit, this is the implicitly imported interface unit.
-  clang::Module *ThePrimaryInterface = nullptr;
+public:
+  /// The C++ "std::coroutine_traits" template, which is defined in
+  /// \
+  ClassTemplateDecl *StdCoroutineTraitsCache;
 
-  /// The explicit global module fragment of the current translation unit.
-  /// The explicit Global Module Fragment, as specified in C++
-  /// [module.global.frag].
-  clang::Module *TheGlobalModuleFragment = nullptr;
+  bool ActOnCoroutineBodyStart(Scope *S, SourceLocation KwLoc,
+                               StringRef Keyword);
+  ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E);
+  ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E);
+  StmtResult ActOnCoreturnStmt(Scope *S, SourceLocation KwLoc, Expr *E);
 
-  /// The implicit global module fragments of the current translation unit.
-  ///
-  /// The contents in the implicit global module fragment can't be discarded.
-  clang::Module *TheImplicitGlobalModuleFragment = nullptr;
+  ExprResult BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc);
+  ExprResult BuildOperatorCoawaitCall(SourceLocation Loc, Expr *E,
+                                      UnresolvedLookupExpr *Lookup);
+  ExprResult BuildResolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand,
+                                      Expr *Awaiter, bool IsImplicit = false);
+  ExprResult BuildUnresolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand,
+                                        UnresolvedLookupExpr *Lookup);
+  ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E);
+  StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E,
+                               bool IsImplicit = false);
+  StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs);
+  bool buildCoroutineParameterMoves(SourceLocation Loc);
+  VarDecl *buildCoroutinePromise(SourceLocation Loc);
+  void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body);
 
-  /// Namespace definitions that we will export when they finish.
-  llvm::SmallPtrSet DeferredExportedNamespaces;
+  // As a clang extension, enforces that a non-coroutine function must be marked
+  // with [[clang::coro_wrapper]] if it returns a type marked with
+  // [[clang::coro_return_type]].
+  // Expects that FD is not a coroutine.
+  void CheckCoroutineWrapper(FunctionDecl *FD);
+  /// Lookup 'coroutine_traits' in std namespace and std::experimental
+  /// namespace. The namespace found is recorded in Namespace.
+  ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc,
+                                           SourceLocation FuncLoc);
+  /// Check that the expression co_await promise.final_suspend() shall not be
+  /// potentially-throwing.
+  bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend);
 
-  /// In a C++ standard module, inline declarations require a definition to be
-  /// present at the end of a definition domain.  This set holds the decls to
-  /// be checked at the end of the TU.
-  llvm::SmallPtrSet PendingInlineFuncDecls;
+  ///@}
 
-  /// Helper function to judge if we are in module purview.
-  /// Return false if we are not in a module.
-  bool isCurrentModulePurview() const;
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Enter the scope of the explicit global module fragment.
-  Module *PushGlobalModuleFragment(SourceLocation BeginLoc);
-  /// Leave the scope of the explicit global module fragment.
-  void PopGlobalModuleFragment();
+  /// \name C++ Scope Specifiers
+  /// Implementations are in SemaCXXScopeSpec.cpp
+  ///@{
 
-  /// Enter the scope of an implicit global module fragment.
-  Module *PushImplicitGlobalModuleFragment(SourceLocation BeginLoc);
-  /// Leave the scope of an implicit global module fragment.
-  void PopImplicitGlobalModuleFragment();
+public:
+  // Marks SS invalid if it represents an incomplete type.
+  bool RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC);
+  // Complete an enum decl, maybe without a scope spec.
+  bool RequireCompleteEnumDecl(EnumDecl *D, SourceLocation L,
+                               CXXScopeSpec *SS = nullptr);
 
-  VisibleModuleSet VisibleModules;
+  DeclContext *computeDeclContext(QualType T);
+  DeclContext *computeDeclContext(const CXXScopeSpec &SS,
+                                  bool EnteringContext = false);
+  bool isDependentScopeSpecifier(const CXXScopeSpec &SS);
+  CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
 
-  /// Cache for module units which is usable for current module.
-  llvm::DenseSet UsableModuleUnitsCache;
+  /// The parser has parsed a global nested-name-specifier '::'.
+  ///
+  /// \param CCLoc The location of the '::'.
+  ///
+  /// \param SS The nested-name-specifier, which will be updated in-place
+  /// to reflect the parsed nested-name-specifier.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool ActOnCXXGlobalScopeSpecifier(SourceLocation CCLoc, CXXScopeSpec &SS);
 
-  bool isUsableModule(const Module *M);
+  /// The parser has parsed a '__super' nested-name-specifier.
+  ///
+  /// \param SuperLoc The location of the '__super' keyword.
+  ///
+  /// \param ColonColonLoc The location of the '::'.
+  ///
+  /// \param SS The nested-name-specifier, which will be updated in-place
+  /// to reflect the parsed nested-name-specifier.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool ActOnSuperScopeSpecifier(SourceLocation SuperLoc,
+                                SourceLocation ColonColonLoc, CXXScopeSpec &SS);
 
-  bool isAcceptableSlow(const NamedDecl *D, AcceptableKind Kind);
+  bool isAcceptableNestedNameSpecifier(const NamedDecl *SD,
+                                       bool *CanCorrect = nullptr);
+  NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
 
-public:
-  /// Get the module unit whose scope we are currently within.
-  Module *getCurrentModule() const {
-    return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
-  }
+  /// Keeps information about an identifier in a nested-name-spec.
+  ///
+  struct NestedNameSpecInfo {
+    /// The type of the object, if we're parsing nested-name-specifier in
+    /// a member access expression.
+    ParsedType ObjectType;
 
-  /// Is the module scope we are an implementation unit?
-  bool currentModuleIsImplementation() const {
-    return ModuleScopes.empty()
-               ? false
-               : ModuleScopes.back().Module->isModuleImplementation();
-  }
+    /// The identifier preceding the '::'.
+    IdentifierInfo *Identifier;
 
-  /// Is the module scope we are in a C++ Header Unit?
-  bool currentModuleIsHeaderUnit() const {
-    return ModuleScopes.empty() ? false
-                                : ModuleScopes.back().Module->isHeaderUnit();
-  }
+    /// The location of the identifier.
+    SourceLocation IdentifierLoc;
 
-  /// Get the module owning an entity.
-  Module *getOwningModule(const Decl *Entity) {
-    return Entity->getOwningModule();
-  }
+    /// The location of the '::'.
+    SourceLocation CCLoc;
 
-  /// Make a merged definition of an existing hidden definition \p ND
-  /// visible at the specified location.
-  void makeMergedDefinitionVisible(NamedDecl *ND);
-
-  bool isModuleVisible(const Module *M, bool ModulePrivate = false);
+    /// Creates info object for the most typical case.
+    NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc,
+                       SourceLocation ColonColonLoc,
+                       ParsedType ObjectType = ParsedType())
+        : ObjectType(ObjectType), Identifier(II), IdentifierLoc(IdLoc),
+          CCLoc(ColonColonLoc) {}
 
-  // When loading a non-modular PCH files, this is used to restore module
-  // visibility.
-  void makeModuleVisible(Module *Mod, SourceLocation ImportLoc) {
-    VisibleModules.setVisible(Mod, ImportLoc);
-  }
+    NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc,
+                       SourceLocation ColonColonLoc, QualType ObjectType)
+        : ObjectType(ParsedType::make(ObjectType)), Identifier(II),
+          IdentifierLoc(IdLoc), CCLoc(ColonColonLoc) {}
+  };
 
-  /// Determine whether a declaration is visible to name lookup.
-  bool isVisible(const NamedDecl *D) {
-    return D->isUnconditionallyVisible() ||
-           isAcceptableSlow(D, AcceptableKind::Visible);
-  }
+  bool BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
+                                   bool EnteringContext, CXXScopeSpec &SS,
+                                   NamedDecl *ScopeLookupResult,
+                                   bool ErrorRecoveryLookup,
+                                   bool *IsCorrectedToColon = nullptr,
+                                   bool OnlyNamespace = false);
 
-  /// Determine whether a declaration is reachable.
-  bool isReachable(const NamedDecl *D) {
-    // All visible declarations are reachable.
-    return D->isUnconditionallyVisible() ||
-           isAcceptableSlow(D, AcceptableKind::Reachable);
-  }
+  /// The parser has parsed a nested-name-specifier 'identifier::'.
+  ///
+  /// \param S The scope in which this nested-name-specifier occurs.
+  ///
+  /// \param IdInfo Parser information about an identifier in the
+  /// nested-name-spec.
+  ///
+  /// \param EnteringContext Whether we're entering the context nominated by
+  /// this nested-name-specifier.
+  ///
+  /// \param SS The nested-name-specifier, which is both an input
+  /// parameter (the nested-name-specifier before this type) and an
+  /// output parameter (containing the full nested-name-specifier,
+  /// including this new type).
+  ///
+  /// \param IsCorrectedToColon If not null, suggestions to replace '::' -> ':'
+  /// are allowed.  The bool value pointed by this parameter is set to 'true'
+  /// if the identifier is treated as if it was followed by ':', not '::'.
+  ///
+  /// \param OnlyNamespace If true, only considers namespaces in lookup.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool ActOnCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
+                                   bool EnteringContext, CXXScopeSpec &SS,
+                                   bool *IsCorrectedToColon = nullptr,
+                                   bool OnlyNamespace = false);
 
-  /// Determine whether a declaration is acceptable (visible/reachable).
-  bool isAcceptable(const NamedDecl *D, AcceptableKind Kind) {
-    return Kind == AcceptableKind::Visible ? isVisible(D) : isReachable(D);
-  }
+  /// The parser has parsed a nested-name-specifier
+  /// 'template[opt] template-name < template-args >::'.
+  ///
+  /// \param S The scope in which this nested-name-specifier occurs.
+  ///
+  /// \param SS The nested-name-specifier, which is both an input
+  /// parameter (the nested-name-specifier before this type) and an
+  /// output parameter (containing the full nested-name-specifier,
+  /// including this new type).
+  ///
+  /// \param TemplateKWLoc the location of the 'template' keyword, if any.
+  /// \param TemplateName the template name.
+  /// \param TemplateNameLoc The location of the template name.
+  /// \param LAngleLoc The location of the opening angle bracket  ('<').
+  /// \param TemplateArgs The template arguments.
+  /// \param RAngleLoc The location of the closing angle bracket  ('>').
+  /// \param CCLoc The location of the '::'.
+  ///
+  /// \param EnteringContext Whether we're entering the context of the
+  /// nested-name-specifier.
+  ///
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool ActOnCXXNestedNameSpecifier(
+      Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+      TemplateTy TemplateName, SourceLocation TemplateNameLoc,
+      SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs,
+      SourceLocation RAngleLoc, SourceLocation CCLoc, bool EnteringContext);
 
-  /// Determine whether any declaration of an entity is visible.
-  bool
-  hasVisibleDeclaration(const NamedDecl *D,
-                        llvm::SmallVectorImpl *Modules = nullptr) {
-    return isVisible(D) || hasVisibleDeclarationSlow(D, Modules);
-  }
+  bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, const DeclSpec &DS,
+                                           SourceLocation ColonColonLoc);
 
-  bool hasVisibleDeclarationSlow(const NamedDecl *D,
-                                 llvm::SmallVectorImpl *Modules);
-  /// Determine whether any declaration of an entity is reachable.
-  bool
-  hasReachableDeclaration(const NamedDecl *D,
-                          llvm::SmallVectorImpl *Modules = nullptr) {
-    return isReachable(D) || hasReachableDeclarationSlow(D, Modules);
-  }
-  bool hasReachableDeclarationSlow(
-      const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr);
+  bool ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS,
+                                              const DeclSpec &DS,
+                                              SourceLocation ColonColonLoc,
+                                              QualType Type);
 
-  bool hasVisibleMergedDefinition(const NamedDecl *Def);
-  bool hasMergedDefinitionInCurrentModule(const NamedDecl *Def);
+  bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
+                                 NestedNameSpecInfo &IdInfo,
+                                 bool EnteringContext);
 
-  /// Determine if \p D and \p Suggested have a structurally compatible
-  /// layout as described in C11 6.2.7/1.
-  bool hasStructuralCompatLayout(Decl *D, Decl *Suggested);
+  /// Given a C++ nested-name-specifier, produce an annotation value
+  /// that the parser can use later to reconstruct the given
+  /// nested-name-specifier.
+  ///
+  /// \param SS A nested-name-specifier.
+  ///
+  /// \returns A pointer containing all of the information in the
+  /// nested-name-specifier \p SS.
+  void *SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS);
 
-  /// Determine if \p D has a visible definition. If not, suggest a declaration
-  /// that should be made visible to expose the definition.
-  bool hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
-                            bool OnlyNeedComplete = false);
-  bool hasVisibleDefinition(const NamedDecl *D) {
-    NamedDecl *Hidden;
-    return hasVisibleDefinition(const_cast(D), &Hidden);
-  }
+  /// Given an annotation pointer for a nested-name-specifier, restore
+  /// the nested-name-specifier structure.
+  ///
+  /// \param Annotation The annotation pointer, produced by
+  /// \c SaveNestedNameSpecifierAnnotation().
+  ///
+  /// \param AnnotationRange The source range corresponding to the annotation.
+  ///
+  /// \param SS The nested-name-specifier that will be updated with the contents
+  /// of the annotation pointer.
+  void RestoreNestedNameSpecifierAnnotation(void *Annotation,
+                                            SourceRange AnnotationRange,
+                                            CXXScopeSpec &SS);
 
-  /// Determine if \p D has a reachable definition. If not, suggest a
-  /// declaration that should be made reachable to expose the definition.
-  bool hasReachableDefinition(NamedDecl *D, NamedDecl **Suggested,
-                              bool OnlyNeedComplete = false);
-  bool hasReachableDefinition(NamedDecl *D) {
-    NamedDecl *Hidden;
-    return hasReachableDefinition(D, &Hidden);
-  }
+  bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
 
-  bool hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested,
-                               AcceptableKind Kind,
-                               bool OnlyNeedComplete = false);
-  bool hasAcceptableDefinition(NamedDecl *D, AcceptableKind Kind) {
-    NamedDecl *Hidden;
-    return hasAcceptableDefinition(D, &Hidden, Kind);
-  }
+  /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
+  /// scope or nested-name-specifier) is parsed, part of a declarator-id.
+  /// After this method is called, according to [C++ 3.4.3p3], names should be
+  /// looked up in the declarator-id's scope, until the declarator is parsed and
+  /// ActOnCXXExitDeclaratorScope is called.
+  /// The 'SS' should be a non-empty valid CXXScopeSpec.
+  bool ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS);
 
-  /// Determine if the template parameter \p D has a visible default argument.
-  bool
-  hasVisibleDefaultArgument(const NamedDecl *D,
-                            llvm::SmallVectorImpl *Modules = nullptr);
-  /// Determine if the template parameter \p D has a reachable default argument.
-  bool hasReachableDefaultArgument(
-      const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr);
-  /// Determine if the template parameter \p D has a reachable default argument.
-  bool hasAcceptableDefaultArgument(const NamedDecl *D,
-                                    llvm::SmallVectorImpl *Modules,
-                                    Sema::AcceptableKind Kind);
+  /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
+  /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same
+  /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well.
+  /// Used to indicate that names should revert to being looked up in the
+  /// defining scope.
+  void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
 
-  /// Determine if there is a visible declaration of \p D that is an explicit
-  /// specialization declaration for a specialization of a template. (For a
-  /// member specialization, use hasVisibleMemberSpecialization.)
-  bool hasVisibleExplicitSpecialization(
-      const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr);
-  /// Determine if there is a reachable declaration of \p D that is an explicit
-  /// specialization declaration for a specialization of a template. (For a
-  /// member specialization, use hasReachableMemberSpecialization.)
-  bool hasReachableExplicitSpecialization(
-      const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr);
+  ///@}
 
-  /// Determine if there is a visible declaration of \p D that is a member
-  /// specialization declaration (as opposed to an instantiated declaration).
-  bool hasVisibleMemberSpecialization(
-      const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr);
-  /// Determine if there is a reachable declaration of \p D that is a member
-  /// specialization declaration (as opposed to an instantiated declaration).
-  bool hasReachableMemberSpecialization(
-      const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Determine if \p A and \p B are equivalent internal linkage declarations
-  /// from different modules, and thus an ambiguity error can be downgraded to
-  /// an extension warning.
-  bool isEquivalentInternalLinkageDeclaration(const NamedDecl *A,
-                                              const NamedDecl *B);
-  void diagnoseEquivalentInternalLinkageDeclarations(
-      SourceLocation Loc, const NamedDecl *D,
-      ArrayRef Equiv);
+  /// \name Declarations
+  /// Implementations are in SemaDecl.cpp
+  ///@{
 
-  bool isUsualDeallocationFunction(const CXXMethodDecl *FD);
+public:
+  IdentifierResolver IdResolver;
 
-  // Check whether the size of array element of type \p EltTy is a multiple of
-  // its alignment and return false if it isn't.
-  bool checkArrayElementAlignment(QualType EltTy, SourceLocation Loc);
+  /// The index of the first InventedParameterInfo that refers to the current
+  /// context.
+  unsigned InventedParameterInfosStart = 0;
 
-  bool isCompleteType(SourceLocation Loc, QualType T,
-                      CompleteTypeKind Kind = CompleteTypeKind::Default) {
-    return !RequireCompleteTypeImpl(Loc, T, Kind, nullptr);
-  }
-  bool RequireCompleteType(SourceLocation Loc, QualType T,
-                           CompleteTypeKind Kind, TypeDiagnoser &Diagnoser);
-  bool RequireCompleteType(SourceLocation Loc, QualType T,
-                           CompleteTypeKind Kind, unsigned DiagID);
+  /// A RAII object to temporarily push a declaration context.
+  class ContextRAII {
+  private:
+    Sema &S;
+    DeclContext *SavedContext;
+    ProcessingContextState SavedContextState;
+    QualType SavedCXXThisTypeOverride;
+    unsigned SavedFunctionScopesStart;
+    unsigned SavedInventedParameterInfosStart;
 
-  bool RequireCompleteType(SourceLocation Loc, QualType T,
-                           TypeDiagnoser &Diagnoser) {
-    return RequireCompleteType(Loc, T, CompleteTypeKind::Default, Diagnoser);
-  }
-  bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID) {
-    return RequireCompleteType(Loc, T, CompleteTypeKind::Default, DiagID);
-  }
+  public:
+    ContextRAII(Sema &S, DeclContext *ContextToPush, bool NewThisContext = true)
+        : S(S), SavedContext(S.CurContext),
+          SavedContextState(S.DelayedDiagnostics.pushUndelayed()),
+          SavedCXXThisTypeOverride(S.CXXThisTypeOverride),
+          SavedFunctionScopesStart(S.FunctionScopesStart),
+          SavedInventedParameterInfosStart(S.InventedParameterInfosStart) {
+      assert(ContextToPush && "pushing null context");
+      S.CurContext = ContextToPush;
+      if (NewThisContext)
+        S.CXXThisTypeOverride = QualType();
+      // Any saved FunctionScopes do not refer to this context.
+      S.FunctionScopesStart = S.FunctionScopes.size();
+      S.InventedParameterInfosStart = S.InventedParameterInfos.size();
+    }
 
-  template 
-  bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID,
-                           const Ts &...Args) {
-    BoundTypeDiagnoser Diagnoser(DiagID, Args...);
-    return RequireCompleteType(Loc, T, Diagnoser);
-  }
+    void pop() {
+      if (!SavedContext)
+        return;
+      S.CurContext = SavedContext;
+      S.DelayedDiagnostics.popUndelayed(SavedContextState);
+      S.CXXThisTypeOverride = SavedCXXThisTypeOverride;
+      S.FunctionScopesStart = SavedFunctionScopesStart;
+      S.InventedParameterInfosStart = SavedInventedParameterInfosStart;
+      SavedContext = nullptr;
+    }
 
-  template 
-  bool RequireCompleteSizedType(SourceLocation Loc, QualType T, unsigned DiagID,
-                                const Ts &... Args) {
-    SizelessTypeDiagnoser Diagnoser(DiagID, Args...);
-    return RequireCompleteType(Loc, T, CompleteTypeKind::Normal, Diagnoser);
-  }
+    ~ContextRAII() { pop(); }
+  };
 
-  /// Get the type of expression E, triggering instantiation to complete the
-  /// type if necessary -- that is, if the expression refers to a templated
-  /// static data member of incomplete array type.
-  ///
-  /// May still return an incomplete type if instantiation was not possible or
-  /// if the type is incomplete for a different reason. Use
-  /// RequireCompleteExprType instead if a diagnostic is expected for an
-  /// incomplete expression type.
-  QualType getCompletedType(Expr *E);
+  void DiagnoseInvalidJumps(Stmt *Body);
 
-  void completeExprArrayBound(Expr *E);
-  bool RequireCompleteExprType(Expr *E, CompleteTypeKind Kind,
-                               TypeDiagnoser &Diagnoser);
-  bool RequireCompleteExprType(Expr *E, unsigned DiagID);
+  /// The function definitions which were renamed as part of typo-correction
+  /// to match their respective declarations. We want to keep track of them
+  /// to ensure that we don't emit a "redefinition" error if we encounter a
+  /// correctly named definition after the renamed definition.
+  llvm::SmallPtrSet TypoCorrectedFunctionDefinitions;
 
-  template 
-  bool RequireCompleteExprType(Expr *E, unsigned DiagID, const Ts &...Args) {
-    BoundTypeDiagnoser Diagnoser(DiagID, Args...);
-    return RequireCompleteExprType(E, CompleteTypeKind::Default, Diagnoser);
-  }
+  /// A cache of the flags available in enumerations with the flag_bits
+  /// attribute.
+  mutable llvm::DenseMap FlagBitsCache;
 
-  template 
-  bool RequireCompleteSizedExprType(Expr *E, unsigned DiagID,
-                                    const Ts &... Args) {
-    SizelessTypeDiagnoser Diagnoser(DiagID, Args...);
-    return RequireCompleteExprType(E, CompleteTypeKind::Normal, Diagnoser);
-  }
+  /// WeakUndeclaredIdentifiers - Identifiers contained in \#pragma weak before
+  /// declared. Rare. May alias another identifier, declared or undeclared.
+  ///
+  /// For aliases, the target identifier is used as a key for eventual
+  /// processing when the target is declared. For the single-identifier form,
+  /// the sole identifier is used as the key. Each entry is a `SetVector`
+  /// (ordered by parse order) of aliases (identified by the alias name) in case
+  /// of multiple aliases to the same undeclared identifier.
+  llvm::MapVector<
+      IdentifierInfo *,
+      llvm::SetVector<
+          WeakInfo, llvm::SmallVector,
+          llvm::SmallDenseSet>>
+      WeakUndeclaredIdentifiers;
 
-  bool RequireLiteralType(SourceLocation Loc, QualType T,
-                          TypeDiagnoser &Diagnoser);
-  bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID);
+  /// ExtnameUndeclaredIdentifiers - Identifiers contained in
+  /// \#pragma redefine_extname before declared.  Used in Solaris system headers
+  /// to define functions that occur in multiple standards to call the version
+  /// in the currently selected standard.
+  llvm::DenseMap ExtnameUndeclaredIdentifiers;
 
-  template 
-  bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID,
-                          const Ts &...Args) {
-    BoundTypeDiagnoser Diagnoser(DiagID, Args...);
-    return RequireLiteralType(Loc, T, Diagnoser);
-  }
+  /// Set containing all typedefs that are likely unused.
+  llvm::SmallSetVector
+      UnusedLocalTypedefNameCandidates;
 
-  QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
-                             const CXXScopeSpec &SS, QualType T,
-                             TagDecl *OwnedTagDecl = nullptr);
+  typedef LazyVector
+      UnusedFileScopedDeclsType;
 
-  // Returns the underlying type of a decltype with the given expression.
-  QualType getDecltypeForExpr(Expr *E);
+  /// The set of file scoped decls seen so far that have not been used
+  /// and must warn if not used. Only contains the first declaration.
+  UnusedFileScopedDeclsType UnusedFileScopedDecls;
 
-  QualType BuildTypeofExprType(Expr *E, TypeOfKind Kind);
-  /// If AsUnevaluated is false, E is treated as though it were an evaluated
-  /// context, such as when building a type for decltype(auto).
-  QualType BuildDecltypeType(Expr *E, bool AsUnevaluated = true);
+  typedef LazyVector
+      TentativeDefinitionsType;
 
-  QualType ActOnPackIndexingType(QualType Pattern, Expr *IndexExpr,
-                                 SourceLocation Loc,
-                                 SourceLocation EllipsisLoc);
-  QualType BuildPackIndexingType(QualType Pattern, Expr *IndexExpr,
-                                 SourceLocation Loc, SourceLocation EllipsisLoc,
-                                 bool FullySubstituted = false,
-                                 ArrayRef Expansions = {});
+  /// All the tentative definitions encountered in the TU.
+  TentativeDefinitionsType TentativeDefinitions;
 
-  using UTTKind = UnaryTransformType::UTTKind;
-  QualType BuildUnaryTransformType(QualType BaseType, UTTKind UKind,
-                                   SourceLocation Loc);
-  QualType BuiltinEnumUnderlyingType(QualType BaseType, SourceLocation Loc);
-  QualType BuiltinAddPointer(QualType BaseType, SourceLocation Loc);
-  QualType BuiltinRemovePointer(QualType BaseType, SourceLocation Loc);
-  QualType BuiltinDecay(QualType BaseType, SourceLocation Loc);
-  QualType BuiltinAddReference(QualType BaseType, UTTKind UKind,
-                               SourceLocation Loc);
-  QualType BuiltinRemoveExtent(QualType BaseType, UTTKind UKind,
-                               SourceLocation Loc);
-  QualType BuiltinRemoveReference(QualType BaseType, UTTKind UKind,
-                                  SourceLocation Loc);
-  QualType BuiltinChangeCVRQualifiers(QualType BaseType, UTTKind UKind,
-                                      SourceLocation Loc);
-  QualType BuiltinChangeSignedness(QualType BaseType, UTTKind UKind,
-                                   SourceLocation Loc);
+  /// All the external declarations encoutered and used in the TU.
+  SmallVector ExternalDeclarations;
 
-  //===--------------------------------------------------------------------===//
-  // Symbol table / Decl tracking callbacks: SemaDecl.cpp.
-  //
+  /// Generally null except when we temporarily switch decl contexts,
+  /// like in \see ActOnObjCTemporaryExitContainerContext.
+  DeclContext *OriginalLexicalContext;
+
+  /// Is the module scope we are in a C++ Header Unit?
+  bool currentModuleIsHeaderUnit() const {
+    return ModuleScopes.empty() ? false
+                                : ModuleScopes.back().Module->isHeaderUnit();
+  }
+
+  /// Get the module owning an entity.
+  Module *getOwningModule(const Decl *Entity) {
+    return Entity->getOwningModule();
+  }
 
   struct SkipBodyInfo {
     SkipBodyInfo() = default;
@@ -2751,8 +2786,6 @@ public:
 
   DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr);
 
-  void DiagnoseUseOfUnimplementedSelectors();
-
   ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
                          Scope *S, CXXScopeSpec *SS = nullptr,
                          bool isClassName = false, bool HasTrailingDot = false,
@@ -2765,10 +2798,8 @@ public:
                          IdentifierInfo **CorrectedII = nullptr);
   TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
   bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S);
-  void DiagnoseUnknownTypeName(IdentifierInfo *&II,
-                               SourceLocation IILoc,
-                               Scope *S,
-                               CXXScopeSpec *SS,
+  void DiagnoseUnknownTypeName(IdentifierInfo *&II, SourceLocation IILoc,
+                               Scope *S, CXXScopeSpec *SS,
                                ParsedType &SuggestedType,
                                bool IsTemplateName = false);
 
@@ -2837,9 +2868,7 @@ public:
 
     NameClassification(const IdentifierInfo *Keyword) : Kind(NC_Keyword) {}
 
-    static NameClassification Error() {
-      return NameClassification(NC_Error);
-    }
+    static NameClassification Error() { return NameClassification(NC_Error); }
 
     static NameClassification Unknown() {
       return NameClassification(NC_Unknown);
@@ -3013,9 +3042,6 @@ public:
     // diagnoseExprIntendedAsTemplateName.
     return false;
   }
-  void diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,
-                                          SourceLocation Less,
-                                          SourceLocation Greater);
 
   void warnOnReservedIdentifier(const NamedDecl *D);
 
@@ -3023,8 +3049,8 @@ public:
 
   NamedDecl *HandleDeclarator(Scope *S, Declarator &D,
                               MultiTemplateParamsArg TemplateParameterLists);
-  bool tryToFixVariablyModifiedVarType(TypeSourceInfo *&TInfo,
-                                       QualType &T, SourceLocation Loc,
+  bool tryToFixVariablyModifiedVarType(TypeSourceInfo *&TInfo, QualType &T,
+                                       SourceLocation Loc,
                                        unsigned FailedFoldDiagID);
   void RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S);
   bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info);
@@ -3032,16 +3058,7 @@ public:
                                     DeclarationName Name, SourceLocation Loc,
                                     TemplateIdAnnotation *TemplateId,
                                     bool IsMemberSpecialization);
-  void
-  diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
-                            SourceLocation FallbackLoc,
-                            SourceLocation ConstQualLoc = SourceLocation(),
-                            SourceLocation VolatileQualLoc = SourceLocation(),
-                            SourceLocation RestrictQualLoc = SourceLocation(),
-                            SourceLocation AtomicQualLoc = SourceLocation(),
-                            SourceLocation UnalignedQualLoc = SourceLocation());
 
-  static bool adjustContextForLocalExternDecl(DeclContext *&DC);
   void DiagnoseFunctionSpecifiers(const DeclSpec &DS);
   NamedDecl *getShadowedDeclaration(const TypedefNameDecl *D,
                                     const LookupResult &R);
@@ -3058,68 +3075,35 @@ public:
 
   void DiagnoseShadowingLambdaDecls(const sema::LambdaScopeInfo *LSI);
 
-private:
-  /// Map of current shadowing declarations to shadowed declarations. Warn if
-  /// it looks like the user is trying to modify the shadowing declaration.
-  llvm::DenseMap ShadowingDecls;
-
-public:
-  void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange);
   void handleTagNumbering(const TagDecl *Tag, Scope *TagScope);
   void setTagNameForLinkagePurposes(TagDecl *TagFromDeclSpec,
                                     TypedefNameDecl *NewTD);
   void CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *D);
-  NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+  NamedDecl *ActOnTypedefDeclarator(Scope *S, Declarator &D, DeclContext *DC,
                                     TypeSourceInfo *TInfo,
                                     LookupResult &Previous);
-  NamedDecl* ActOnTypedefNameDecl(Scope* S, DeclContext* DC, TypedefNameDecl *D,
+  NamedDecl *ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *D,
                                   LookupResult &Previous, bool &Redeclaration);
   NamedDecl *ActOnVariableDeclarator(
       Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo,
       LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists,
       bool &AddToScope, ArrayRef Bindings = std::nullopt);
-  NamedDecl *
-  ActOnDecompositionDeclarator(Scope *S, Declarator &D,
-                               MultiTemplateParamsArg TemplateParamLists);
-  void DiagPlaceholderVariableDefinition(SourceLocation Loc);
-  bool DiagRedefinedPlaceholderFieldDecl(SourceLocation Loc,
-                                         RecordDecl *ClassDecl,
-                                         const IdentifierInfo *Name);
+
   // Returns true if the variable declaration is a redeclaration
   bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous);
   void CheckVariableDeclarationType(VarDecl *NewVD);
-  bool DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit,
-                                     Expr *Init);
   void CheckCompleteVariableDeclaration(VarDecl *VD);
-  void CheckCompleteDecompositionDeclaration(DecompositionDecl *DD);
-  void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D);
 
-  NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
+  NamedDecl *ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
                                      TypeSourceInfo *TInfo,
                                      LookupResult &Previous,
                                      MultiTemplateParamsArg TemplateParamLists,
                                      bool &AddToScope);
   bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
 
-  enum class CheckConstexprKind {
-    /// Diagnose issues that are non-constant or that are extensions.
-    Diagnose,
-    /// Identify whether this function satisfies the formal rules for constexpr
-    /// functions in the current lanugage mode (with no extensions).
-    CheckValid
-  };
-
-  bool CheckConstexprFunctionDefinition(const FunctionDecl *FD,
-                                        CheckConstexprKind Kind);
-
-  void DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD);
-  void FindHiddenVirtualMethods(CXXMethodDecl *MD,
-                          SmallVectorImpl &OverloadedMethods);
-  void NoteHiddenVirtualMethods(CXXMethodDecl *MD,
-                          SmallVectorImpl &OverloadedMethods);
   // Returns true if the function declaration is a redeclaration
-  bool CheckFunctionDeclaration(Scope *S,
-                                FunctionDecl *NewFD, LookupResult &Previous,
+  bool CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
+                                LookupResult &Previous,
                                 bool IsMemberSpecialization, bool DeclIsDefn);
   bool shouldLinkDependentDeclWithPrevious(Decl *D, Decl *OldDecl);
   bool canFullyTypeCheckRedeclaration(ValueDecl *NewD, ValueDecl *OldD,
@@ -3138,8 +3122,7 @@ public:
   void CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D);
   Decl *ActOnParamDeclarator(Scope *S, Declarator &D,
                              SourceLocation ExplicitThisLoc = {});
-  ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC,
-                                          SourceLocation Loc,
+  ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc,
                                           QualType T);
   QualType AdjustParameterTypeForObjCAutoRefCount(QualType T,
                                                   SourceLocation NameLoc,
@@ -3148,17 +3131,6 @@ public:
                               SourceLocation NameLoc, IdentifierInfo *Name,
                               QualType T, TypeSourceInfo *TSInfo,
                               StorageClass SC);
-  void ActOnParamDefaultArgument(Decl *param,
-                                 SourceLocation EqualLoc,
-                                 Expr *defarg);
-  void ActOnParamUnparsedDefaultArgument(Decl *param, SourceLocation EqualLoc,
-                                         SourceLocation ArgLoc);
-  void ActOnParamDefaultArgumentError(Decl *param, SourceLocation EqualLoc,
-                                      Expr* DefaultArg);
-  ExprResult ConvertParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
-                                         SourceLocation EqualLoc);
-  void SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
-                               SourceLocation EqualLoc);
 
   // Contexts where using non-trivial C union types can be disallowed. This is
   // passed to err_non_trivial_c_union_in_invalid_context.
@@ -3206,13 +3178,11 @@ public:
   void ActOnUninitializedDecl(Decl *dcl);
   void ActOnInitializerError(Decl *Dcl);
 
-  void ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc);
   void ActOnCXXForRangeDecl(Decl *D);
   StmtResult ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
                                         IdentifierInfo *Ident,
                                         ParsedAttributes &Attrs);
-  void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
-  void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc);
+
   void CheckStaticLocalForDllExport(VarDecl *VD);
   void CheckThreadLocalForLargeAlignment(VarDecl *VD);
   void FinalizeDeclaration(Decl *D);
@@ -3249,14 +3219,6 @@ public:
   Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D,
                                 SkipBodyInfo *SkipBody = nullptr,
                                 FnBodyKind BodyKind = FnBodyKind::Other);
-  void SetFunctionBodyKind(Decl *D, SourceLocation Loc, FnBodyKind BodyKind);
-  void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D);
-  ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr);
-  ExprResult ActOnRequiresClause(ExprResult ConstraintExpr);
-  void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
-  bool isObjCMethodDecl(Decl *D) {
-    return D && isa(D);
-  }
 
   /// Determine whether we can delay parsing the body of a function or
   /// function template until it is used, assuming we don't care about emitting
@@ -3277,10 +3239,6 @@ public:
   /// \c constexpr in C++11 or has an 'auto' return type in C++14).
   bool canSkipFunctionBody(Decl *D);
 
-  /// Determine whether \param D is function like (function or function
-  /// template) for parsing.
-  bool isDeclaratorFunctionLike(Declarator &D);
-
   void computeNRVO(Stmt *Body, sema::FunctionScopeInfo *Scope);
   Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body);
   Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation);
@@ -3302,159 +3260,30 @@ public:
   DiagnoseSizeOfParametersAndReturnValue(ArrayRef Parameters,
                                          QualType ReturnTy, NamedDecl *D);
 
-  void DiagnoseInvalidJumps(Stmt *Body);
-  Decl *ActOnFileScopeAsmDecl(Expr *expr,
-                              SourceLocation AsmLoc,
+  Decl *ActOnFileScopeAsmDecl(Expr *expr, SourceLocation AsmLoc,
                               SourceLocation RParenLoc);
 
-  Decl *ActOnTopLevelStmtDecl(Stmt *Statement);
+  TopLevelStmtDecl *ActOnStartTopLevelStmtDecl(Scope *S);
+  void ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl *D, Stmt *Statement);
 
-  /// Handle a C++11 empty-declaration and attribute-declaration.
-  Decl *ActOnEmptyDeclaration(Scope *S, const ParsedAttributesView &AttrList,
-                              SourceLocation SemiLoc);
+  void ActOnPopScope(SourceLocation Loc, Scope *S);
 
-  enum class ModuleDeclKind {
-    Interface,               ///< 'export module X;'
-    Implementation,          ///< 'module X;'
-    PartitionInterface,      ///< 'export module X:Y;'
-    PartitionImplementation, ///< 'module X:Y;'
-  };
+  Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
+                                   const ParsedAttributesView &DeclAttrs,
+                                   RecordDecl *&AnonRecord);
+  Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
+                                   const ParsedAttributesView &DeclAttrs,
+                                   MultiTemplateParamsArg TemplateParams,
+                                   bool IsExplicitInstantiation,
+                                   RecordDecl *&AnonRecord);
 
-  /// An enumeration to represent the transition of states in parsing module
-  /// fragments and imports.  If we are not parsing a C++20 TU, or we find
-  /// an error in state transition, the state is set to NotACXX20Module.
-  enum class ModuleImportState {
-    FirstDecl,      ///< Parsing the first decl in a TU.
-    GlobalFragment, ///< after 'module;' but before 'module X;'
-    ImportAllowed,  ///< after 'module X;' but before any non-import decl.
-    ImportFinished, ///< after any non-import decl.
-    PrivateFragmentImportAllowed,  ///< after 'module :private;' but before any
-                                   ///< non-import decl.
-    PrivateFragmentImportFinished, ///< after 'module :private;' but a
-                                   ///< non-import decl has already been seen.
-    NotACXX20Module ///< Not a C++20 TU, or an invalid state was found.
-  };
+  Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, AccessSpecifier AS,
+                                    RecordDecl *Record,
+                                    const PrintingPolicy &Policy);
 
-private:
-  /// The parser has begun a translation unit to be compiled as a C++20
-  /// Header Unit, helper for ActOnStartOfTranslationUnit() only.
-  void HandleStartOfHeaderUnit();
-
-public:
-  /// The parser has processed a module-declaration that begins the definition
-  /// of a module interface or implementation.
-  DeclGroupPtrTy ActOnModuleDecl(SourceLocation StartLoc,
-                                 SourceLocation ModuleLoc, ModuleDeclKind MDK,
-                                 ModuleIdPath Path, ModuleIdPath Partition,
-                                 ModuleImportState &ImportState);
-
-  /// The parser has processed a global-module-fragment declaration that begins
-  /// the definition of the global module fragment of the current module unit.
-  /// \param ModuleLoc The location of the 'module' keyword.
-  DeclGroupPtrTy ActOnGlobalModuleFragmentDecl(SourceLocation ModuleLoc);
-
-  /// The parser has processed a private-module-fragment declaration that begins
-  /// the definition of the private module fragment of the current module unit.
-  /// \param ModuleLoc The location of the 'module' keyword.
-  /// \param PrivateLoc The location of the 'private' keyword.
-  DeclGroupPtrTy ActOnPrivateModuleFragmentDecl(SourceLocation ModuleLoc,
-                                                SourceLocation PrivateLoc);
-
-  /// The parser has processed a module import declaration.
-  ///
-  /// \param StartLoc The location of the first token in the declaration. This
-  ///        could be the location of an '@', 'export', or 'import'.
-  /// \param ExportLoc The location of the 'export' keyword, if any.
-  /// \param ImportLoc The location of the 'import' keyword.
-  /// \param Path The module toplevel name as an access path.
-  /// \param IsPartition If the name is for a partition.
-  DeclResult ActOnModuleImport(SourceLocation StartLoc,
-                               SourceLocation ExportLoc,
-                               SourceLocation ImportLoc, ModuleIdPath Path,
-                               bool IsPartition = false);
-  DeclResult ActOnModuleImport(SourceLocation StartLoc,
-                               SourceLocation ExportLoc,
-                               SourceLocation ImportLoc, Module *M,
-                               ModuleIdPath Path = {});
-
-  /// The parser has processed a module import translated from a
-  /// #include or similar preprocessing directive.
-  void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
-  void BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
-
-  /// The parsed has entered a submodule.
-  void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod);
-  /// The parser has left a submodule.
-  void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod);
-
-  /// Create an implicit import of the given module at the given
-  /// source location, for error recovery, if possible.
-  ///
-  /// This routine is typically used when an entity found by name lookup
-  /// is actually hidden within a module that we know about but the user
-  /// has forgotten to import.
-  void createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
-                                                  Module *Mod);
-
-  /// Kinds of missing import. Note, the values of these enumerators correspond
-  /// to %select values in diagnostics.
-  enum class MissingImportKind {
-    Declaration,
-    Definition,
-    DefaultArgument,
-    ExplicitSpecialization,
-    PartialSpecialization
-  };
-
-  /// Diagnose that the specified declaration needs to be visible but
-  /// isn't, and suggest a module import that would resolve the problem.
-  void diagnoseMissingImport(SourceLocation Loc, const NamedDecl *Decl,
-                             MissingImportKind MIK, bool Recover = true);
-  void diagnoseMissingImport(SourceLocation Loc, const NamedDecl *Decl,
-                             SourceLocation DeclLoc, ArrayRef Modules,
-                             MissingImportKind MIK, bool Recover);
-
-  Decl *ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc,
-                             SourceLocation LBraceLoc);
-  Decl *ActOnFinishExportDecl(Scope *S, Decl *ExportDecl,
-                              SourceLocation RBraceLoc);
-
-  /// We've found a use of a templated declaration that would trigger an
-  /// implicit instantiation. Check that any relevant explicit specializations
-  /// and partial specializations are visible/reachable, and diagnose if not.
-  void checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec);
-  void checkSpecializationReachability(SourceLocation Loc, NamedDecl *Spec);
-
-  /// Retrieve a suitable printing policy for diagnostics.
-  PrintingPolicy getPrintingPolicy() const {
-    return getPrintingPolicy(Context, PP);
-  }
-
-  /// Retrieve a suitable printing policy for diagnostics.
-  static PrintingPolicy getPrintingPolicy(const ASTContext &Ctx,
-                                          const Preprocessor &PP);
-
-  /// Scope actions.
-  void ActOnPopScope(SourceLocation Loc, Scope *S);
-  void ActOnTranslationUnitScope(Scope *S);
-
-  Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
-                                   const ParsedAttributesView &DeclAttrs,
-                                   RecordDecl *&AnonRecord);
-  Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
-                                   const ParsedAttributesView &DeclAttrs,
-                                   MultiTemplateParamsArg TemplateParams,
-                                   bool IsExplicitInstantiation,
-                                   RecordDecl *&AnonRecord);
-
-  Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
-                                    AccessSpecifier AS,
-                                    RecordDecl *Record,
-                                    const PrintingPolicy &Policy);
-
-  /// Called once it is known whether
-  /// a tag declaration is an anonymous union or struct.
-  void ActOnDefinedDeclarationSpecifier(Decl *D);
+  /// Called once it is known whether
+  /// a tag declaration is an anonymous union or struct.
+  void ActOnDefinedDeclarationSpecifier(Decl *D);
 
   void DiagPlaceholderFieldDeclDefinitions(RecordDecl *Record);
 
@@ -3479,9 +3308,8 @@ public:
   /// what kind of non-tag type this is.
   NonTagKind getNonTagTypeDeclKind(const Decl *D, TagTypeKind TTK);
 
-  bool isAcceptableTagRedeclaration(const TagDecl *Previous,
-                                    TagTypeKind NewTag, bool isDefinition,
-                                    SourceLocation NewTagLoc,
+  bool isAcceptableTagRedeclaration(const TagDecl *Previous, TagTypeKind NewTag,
+                                    bool isDefinition, SourceLocation NewTagLoc,
                                     const IdentifierInfo *Name);
 
   enum TagUseKind {
@@ -3513,106 +3341,21 @@ public:
                       bool IsTypeSpecifier, bool IsTemplateParamOrArg,
                       OffsetOfKind OOK, SkipBodyInfo *SkipBody = nullptr);
 
-  DeclResult ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
-                                     unsigned TagSpec, SourceLocation TagLoc,
-                                     CXXScopeSpec &SS, IdentifierInfo *Name,
-                                     SourceLocation NameLoc,
-                                     const ParsedAttributesView &Attr,
-                                     MultiTemplateParamsArg TempParamLists);
-
-  TypeResult ActOnDependentTag(Scope *S,
-                               unsigned TagSpec,
-                               TagUseKind TUK,
-                               const CXXScopeSpec &SS,
-                               IdentifierInfo *Name,
-                               SourceLocation TagLoc,
-                               SourceLocation NameLoc);
-
-  void ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
-                 IdentifierInfo *ClassName,
-                 SmallVectorImpl &Decls);
   Decl *ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart,
                    Declarator &D, Expr *BitfieldWidth);
 
   FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart,
                          Declarator &D, Expr *BitfieldWidth,
-                         InClassInitStyle InitStyle,
-                         AccessSpecifier AS);
-  MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD,
-                                   SourceLocation DeclStart, Declarator &D,
-                                   Expr *BitfieldWidth,
-                                   InClassInitStyle InitStyle,
-                                   AccessSpecifier AS,
-                                   const ParsedAttr &MSPropertyAttr);
+                         InClassInitStyle InitStyle, AccessSpecifier AS);
 
   FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T,
-                            TypeSourceInfo *TInfo,
-                            RecordDecl *Record, SourceLocation Loc,
-                            bool Mutable, Expr *BitfieldWidth,
-                            InClassInitStyle InitStyle,
-                            SourceLocation TSSL,
-                            AccessSpecifier AS, NamedDecl *PrevDecl,
-                            Declarator *D = nullptr);
+                            TypeSourceInfo *TInfo, RecordDecl *Record,
+                            SourceLocation Loc, bool Mutable,
+                            Expr *BitfieldWidth, InClassInitStyle InitStyle,
+                            SourceLocation TSSL, AccessSpecifier AS,
+                            NamedDecl *PrevDecl, Declarator *D = nullptr);
 
   bool CheckNontrivialField(FieldDecl *FD);
-  void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM);
-
-  enum TrivialABIHandling {
-    /// The triviality of a method unaffected by "trivial_abi".
-    TAH_IgnoreTrivialABI,
-
-    /// The triviality of a method affected by "trivial_abi".
-    TAH_ConsiderTrivialABI
-  };
-
-  bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
-                              TrivialABIHandling TAH = TAH_IgnoreTrivialABI,
-                              bool Diagnose = false);
-
-  /// For a defaulted function, the kind of defaulted function that it is.
-  class DefaultedFunctionKind {
-    unsigned SpecialMember : 8;
-    unsigned Comparison : 8;
-
-  public:
-    DefaultedFunctionKind()
-        : SpecialMember(CXXInvalid), Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {
-    }
-    DefaultedFunctionKind(CXXSpecialMember CSM)
-        : SpecialMember(CSM), Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {}
-    DefaultedFunctionKind(DefaultedComparisonKind Comp)
-        : SpecialMember(CXXInvalid), Comparison(llvm::to_underlying(Comp)) {}
-
-    bool isSpecialMember() const { return SpecialMember != CXXInvalid; }
-    bool isComparison() const {
-      return static_cast(Comparison) != DefaultedComparisonKind::None;
-    }
-
-    explicit operator bool() const {
-      return isSpecialMember() || isComparison();
-    }
-
-    CXXSpecialMember asSpecialMember() const { return static_cast(SpecialMember); }
-    DefaultedComparisonKind asComparison() const { return static_cast(Comparison); }
-
-    /// Get the index of this function kind for use in diagnostics.
-    unsigned getDiagnosticIndex() const {
-      static_assert(CXXInvalid > CXXDestructor,
-                    "invalid should have highest index");
-      static_assert((unsigned)DefaultedComparisonKind::None == 0,
-                    "none should be equal to zero");
-      return SpecialMember + Comparison;
-    }
-  };
-
-  DefaultedFunctionKind getDefaultedFunctionKind(const FunctionDecl *FD);
-
-  CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD) {
-    return getDefaultedFunctionKind(MD).asSpecialMember();
-  }
-  DefaultedComparisonKind getDefaultedComparisonKind(const FunctionDecl *FD) {
-    return getDefaultedFunctionKind(FD).asComparison();
-  }
 
   void ActOnLastBitfield(SourceLocation DeclStart,
                          SmallVectorImpl &AllIvarDecls);
@@ -3634,20 +3377,6 @@ public:
   /// in case of a structural mismatch.
   bool ActOnDuplicateDefinition(Decl *Prev, SkipBodyInfo &SkipBody);
 
-  /// Check ODR hashes for C/ObjC when merging types from modules.
-  /// Differently from C++, actually parse the body and reject in case
-  /// of a mismatch.
-  template ::value>>
-  bool ActOnDuplicateODRHashDefinition(T *Duplicate, T *Previous) {
-    if (Duplicate->getODRHash() != Previous->getODRHash())
-      return false;
-
-    // Make the previous decl visible.
-    makeMergedDefinitionVisible(Previous);
-    return true;
-  }
-
   typedef void *SkippedDefinitionContext;
 
   /// Invoked when we enter a tag definition that we're skipping.
@@ -3686,8 +3415,7 @@ public:
 
   EnumConstantDecl *CheckEnumConstant(EnumDecl *Enum,
                                       EnumConstantDecl *LastEnumConst,
-                                      SourceLocation IdLoc,
-                                      IdentifierInfo *Id,
+                                      SourceLocation IdLoc, IdentifierInfo *Id,
                                       Expr *val);
   bool CheckEnumUnderlyingType(TypeSourceInfo *TI);
   bool CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
@@ -3716,34 +3444,15 @@ public:
   void EnterDeclaratorContext(Scope *S, DeclContext *DC);
   void ExitDeclaratorContext(Scope *S);
 
-  /// Enter a template parameter scope, after it's been associated with a particular
-  /// DeclContext. Causes lookup within the scope to chain through enclosing contexts
-  /// in the correct order.
+  /// Enter a template parameter scope, after it's been associated with a
+  /// particular DeclContext. Causes lookup within the scope to chain through
+  /// enclosing contexts in the correct order.
   void EnterTemplatedContext(Scope *S, DeclContext *DC);
 
   /// Push the parameters of D, which must be a function, into scope.
-  void ActOnReenterFunctionContext(Scope* S, Decl* D);
+  void ActOnReenterFunctionContext(Scope *S, Decl *D);
   void ActOnExitFunctionContext();
 
-  /// If \p AllowLambda is true, treat lambda as function.
-  DeclContext *getFunctionLevelDeclContext(bool AllowLambda = false) const;
-
-  /// Returns a pointer to the innermost enclosing function, or nullptr if the
-  /// current context is not inside a function. If \p AllowLambda is true,
-  /// this can return the call operator of an enclosing lambda, otherwise
-  /// lambdas are skipped when looking for an enclosing function.
-  FunctionDecl *getCurFunctionDecl(bool AllowLambda = false) const;
-
-  /// getCurMethodDecl - If inside of a method body, this returns a pointer to
-  /// the method decl for the method being parsed.  If we're currently
-  /// in a 'block', this returns the containing context.
-  ObjCMethodDecl *getCurMethodDecl();
-
-  /// getCurFunctionOrMethodDecl - Return the Decl for the current ObjC method
-  /// or C function we're in, otherwise return null.  If we're currently
-  /// in a 'block', this returns the containing context.
-  NamedDecl *getCurFunctionOrMethodDecl() const;
-
   /// Add this decl to the scope shadowed decl chains.
   void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true);
 
@@ -3785,9516 +3494,9131 @@ public:
     AMK_OptionalProtocolImplementation
   };
 
-  /// Describes the kind of priority given to an availability attribute.
-  ///
-  /// The sum of priorities deteremines the final priority of the attribute.
-  /// The final priority determines how the attribute will be merged.
-  /// An attribute with a lower priority will always remove higher priority
-  /// attributes for the specified platform when it is being applied. An
-  /// attribute with a higher priority will not be applied if the declaration
-  /// already has an availability attribute with a lower priority for the
-  /// specified platform. The final prirority values are not expected to match
-  /// the values in this enumeration, but instead should be treated as a plain
-  /// integer value. This enumeration just names the priority weights that are
-  /// used to calculate that final vaue.
-  enum AvailabilityPriority : int {
-    /// The availability attribute was specified explicitly next to the
-    /// declaration.
-    AP_Explicit = 0,
+  void mergeDeclAttributes(NamedDecl *New, Decl *Old,
+                           AvailabilityMergeKind AMK = AMK_Redeclaration);
+  void MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,
+                            LookupResult &OldDecls);
+  bool MergeFunctionDecl(FunctionDecl *New, NamedDecl *&Old, Scope *S,
+                         bool MergeTypeWithOld, bool NewDeclIsDefn);
+  bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
+                                    Scope *S, bool MergeTypeWithOld);
+  void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old);
+  void MergeVarDecl(VarDecl *New, LookupResult &Previous);
+  void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld);
+  bool checkVarDeclRedefinition(VarDecl *OldDefn, VarDecl *NewDefn);
+  void notePreviousDefinition(const NamedDecl *Old, SourceLocation New);
 
-    /// The availability attribute was applied using '#pragma clang attribute'.
-    AP_PragmaClangAttribute = 1,
+  void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
+                            bool ConsiderLinkage, bool AllowInlineNamespace);
 
-    /// The availability attribute for a specific platform was inferred from
-    /// an availability attribute for another platform.
-    AP_InferredFromOtherPlatform = 2
-  };
+  bool CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old);
+  bool CheckRedeclarationExported(NamedDecl *New, NamedDecl *Old);
+  bool CheckRedeclarationInModule(NamedDecl *New, NamedDecl *Old);
+  bool IsRedefinitionInModule(const NamedDecl *New, const NamedDecl *Old) const;
 
-  /// Attribute merging methods. Return true if a new attribute was added.
-  AvailabilityAttr *
-  mergeAvailabilityAttr(NamedDecl *D, const AttributeCommonInfo &CI,
-                        IdentifierInfo *Platform, bool Implicit,
-                        VersionTuple Introduced, VersionTuple Deprecated,
-                        VersionTuple Obsoleted, bool IsUnavailable,
-                        StringRef Message, bool IsStrict, StringRef Replacement,
-                        AvailabilityMergeKind AMK, int Priority);
-  TypeVisibilityAttr *
-  mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI,
-                          TypeVisibilityAttr::VisibilityType Vis);
-  VisibilityAttr *mergeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI,
-                                      VisibilityAttr::VisibilityType Vis);
-  UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
-                          StringRef UuidAsWritten, MSGuidDecl *GuidDecl);
-  DLLImportAttr *mergeDLLImportAttr(Decl *D, const AttributeCommonInfo &CI);
-  DLLExportAttr *mergeDLLExportAttr(Decl *D, const AttributeCommonInfo &CI);
-  MSInheritanceAttr *mergeMSInheritanceAttr(Decl *D,
-                                            const AttributeCommonInfo &CI,
-                                            bool BestCase,
-                                            MSInheritanceModel Model);
-  ErrorAttr *mergeErrorAttr(Decl *D, const AttributeCommonInfo &CI,
-                            StringRef NewUserDiagnostic);
-  FormatAttr *mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI,
-                              IdentifierInfo *Format, int FormatIdx,
-                              int FirstArg);
-  SectionAttr *mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI,
-                                StringRef Name);
-  CodeSegAttr *mergeCodeSegAttr(Decl *D, const AttributeCommonInfo &CI,
-                                StringRef Name);
-  AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D,
-                                          const AttributeCommonInfo &CI,
-                                          const IdentifierInfo *Ident);
-  MinSizeAttr *mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI);
-  SwiftNameAttr *mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA,
-                                    StringRef Name);
-  OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D,
-                                          const AttributeCommonInfo &CI);
-  InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL);
-  InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D,
-                                                const InternalLinkageAttr &AL);
-  WebAssemblyImportNameAttr *mergeImportNameAttr(
-      Decl *D, const WebAssemblyImportNameAttr &AL);
-  WebAssemblyImportModuleAttr *mergeImportModuleAttr(
-      Decl *D, const WebAssemblyImportModuleAttr &AL);
-  EnforceTCBAttr *mergeEnforceTCBAttr(Decl *D, const EnforceTCBAttr &AL);
-  EnforceTCBLeafAttr *mergeEnforceTCBLeafAttr(Decl *D,
-                                              const EnforceTCBLeafAttr &AL);
-  BTFDeclTagAttr *mergeBTFDeclTagAttr(Decl *D, const BTFDeclTagAttr &AL);
-  HLSLNumThreadsAttr *mergeHLSLNumThreadsAttr(Decl *D,
-                                              const AttributeCommonInfo &AL,
-                                              int X, int Y, int Z);
-  HLSLShaderAttr *mergeHLSLShaderAttr(Decl *D, const AttributeCommonInfo &AL,
-                                      HLSLShaderAttr::ShaderType ShaderType);
-  HLSLParamModifierAttr *
-  mergeHLSLParamModifierAttr(Decl *D, const AttributeCommonInfo &AL,
-                             HLSLParamModifierAttr::Spelling Spelling);
-
-  void mergeDeclAttributes(NamedDecl *New, Decl *Old,
-                           AvailabilityMergeKind AMK = AMK_Redeclaration);
-  void MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New,
-                            LookupResult &OldDecls);
-  bool MergeFunctionDecl(FunctionDecl *New, NamedDecl *&Old, Scope *S,
-                         bool MergeTypeWithOld, bool NewDeclIsDefn);
-  bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
-                                    Scope *S, bool MergeTypeWithOld);
-  void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old);
-  void MergeVarDecl(VarDecl *New, LookupResult &Previous);
-  void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld);
-  void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old);
-  bool checkVarDeclRedefinition(VarDecl *OldDefn, VarDecl *NewDefn);
-  void notePreviousDefinition(const NamedDecl *Old, SourceLocation New);
-  bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S);
+  bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const;
 
-  // AssignmentAction - This is used by all the assignment diagnostic functions
-  // to represent what is actually causing the operation
-  enum AssignmentAction {
-    AA_Assigning,
-    AA_Passing,
-    AA_Returning,
-    AA_Converting,
-    AA_Initializing,
-    AA_Sending,
-    AA_Casting,
-    AA_Passing_CFAudited
-  };
+  /// If it's a file scoped decl that must warn if not used, keep track
+  /// of it.
+  void MarkUnusedFileScopedDecl(const DeclaratorDecl *D);
 
-  /// C++ Overloading.
-  enum OverloadKind {
-    /// This is a legitimate overload: the existing declarations are
-    /// functions or function templates with different signatures.
-    Ovl_Overload,
+  typedef llvm::function_ref
+      DiagReceiverTy;
 
-    /// This is not an overload because the signature exactly matches
-    /// an existing declaration.
-    Ovl_Match,
+  void DiagnoseUnusedNestedTypedefs(const RecordDecl *D);
+  void DiagnoseUnusedNestedTypedefs(const RecordDecl *D,
+                                    DiagReceiverTy DiagReceiver);
+  void DiagnoseUnusedDecl(const NamedDecl *ND);
+  void DiagnoseUnusedDecl(const NamedDecl *ND, DiagReceiverTy DiagReceiver);
 
-    /// This is not an overload because the lookup results contain a
-    /// non-function.
-    Ovl_NonFunction
-  };
-  OverloadKind CheckOverload(Scope *S,
-                             FunctionDecl *New,
-                             const LookupResult &OldDecls,
-                             NamedDecl *&OldDecl,
-                             bool UseMemberUsingDeclRules);
-  bool IsOverload(FunctionDecl *New, FunctionDecl *Old,
-                  bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs = true);
+  /// If VD is set but not otherwise used, diagnose, for a parameter or a
+  /// variable.
+  void DiagnoseUnusedButSetDecl(const VarDecl *VD, DiagReceiverTy DiagReceiver);
 
-  // Checks whether MD constitutes an override the base class method BaseMD.
-  // When checking for overrides, the object object members are ignored.
-  bool IsOverride(FunctionDecl *MD, FunctionDecl *BaseMD,
-                  bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs = true);
+  ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id,
+                                          SourceLocation IdLoc,
+                                          bool TypoCorrection = false);
 
-  // Calculates whether the expression Constraint depends on an enclosing
-  // template, for the purposes of [temp.friend] p9.
-  // TemplateDepth is the 'depth' of the friend function, which is used to
-  // compare whether a declaration reference is referring to a containing
-  // template, or just the current friend function. A 'lower' TemplateDepth in
-  // the AST refers to a 'containing' template. As the constraint is
-  // uninstantiated, this is relative to the 'top' of the TU.
-  bool
-  ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend,
-                                                 unsigned TemplateDepth,
-                                                 const Expr *Constraint);
+  Scope *getNonFieldDeclScope(Scope *S);
 
-  // Calculates whether the friend function depends on an enclosing template for
-  // the purposes of [temp.friend] p9.
-  bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD);
+  FunctionDecl *CreateBuiltin(IdentifierInfo *II, QualType Type, unsigned ID,
+                              SourceLocation Loc);
+  NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S,
+                                 bool ForRedeclaration, SourceLocation Loc);
 
-  enum class AllowedExplicit {
-    /// Allow no explicit functions to be used.
-    None,
-    /// Allow explicit conversion functions but not explicit constructors.
-    Conversions,
-    /// Allow both explicit conversion functions and explicit constructors.
-    All
-  };
+  /// Get the outermost AttributedType node that sets a calling convention.
+  /// Valid types should not have multiple attributes with different CCs.
+  const AttributedType *getCallingConvAttributedType(QualType T) const;
 
-  ImplicitConversionSequence
-  TryImplicitConversion(Expr *From, QualType ToType,
-                        bool SuppressUserConversions,
-                        AllowedExplicit AllowExplicit,
-                        bool InOverloadResolution,
-                        bool CStyle,
-                        bool AllowObjCWritebackConversion);
+  DeclarationNameInfo GetNameForDeclarator(Declarator &D);
+  DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name);
 
-  bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType);
-  bool IsFloatingPointPromotion(QualType FromType, QualType ToType);
-  bool IsComplexPromotion(QualType FromType, QualType ToType);
-  bool IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
-                           bool InOverloadResolution,
-                           QualType& ConvertedType, bool &IncompatibleObjC);
-  bool isObjCPointerConversion(QualType FromType, QualType ToType,
-                               QualType& ConvertedType, bool &IncompatibleObjC);
-  bool isObjCWritebackConversion(QualType FromType, QualType ToType,
-                                 QualType &ConvertedType);
-  bool IsBlockPointerConversion(QualType FromType, QualType ToType,
-                                QualType& ConvertedType);
+  /// ParsingInitForAutoVars - a set of declarations with auto types for which
+  /// we are currently parsing the initializer.
+  llvm::SmallPtrSet ParsingInitForAutoVars;
 
-  bool FunctionParamTypesAreEqual(ArrayRef Old,
-                                  ArrayRef New,
-                                  unsigned *ArgPos = nullptr,
-                                  bool Reversed = false);
+  /// Look for a locally scoped extern "C" declaration by the given name.
+  NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name);
 
-  bool FunctionParamTypesAreEqual(const FunctionProtoType *OldType,
-                                  const FunctionProtoType *NewType,
-                                  unsigned *ArgPos = nullptr,
-                                  bool Reversed = false);
+  bool inferObjCARCLifetime(ValueDecl *decl);
 
-  bool FunctionNonObjectParamTypesAreEqual(const FunctionDecl *OldFunction,
-                                           const FunctionDecl *NewFunction,
-                                           unsigned *ArgPos = nullptr,
-                                           bool Reversed = false);
+  void deduceOpenCLAddressSpace(ValueDecl *decl);
 
-  void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
-                                  QualType FromType, QualType ToType);
+  static bool adjustContextForLocalExternDecl(DeclContext *&DC);
 
-  void maybeExtendBlockObject(ExprResult &E);
-  CastKind PrepareCastToObjCObjectPointer(ExprResult &E);
-  bool CheckPointerConversion(Expr *From, QualType ToType,
-                              CastKind &Kind,
-                              CXXCastPath& BasePath,
-                              bool IgnoreBaseAccess,
-                              bool Diagnose = true);
-  bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType,
-                                 bool InOverloadResolution,
-                                 QualType &ConvertedType);
-  bool CheckMemberPointerConversion(Expr *From, QualType ToType,
-                                    CastKind &Kind,
-                                    CXXCastPath &BasePath,
-                                    bool IgnoreBaseAccess);
-  bool IsQualificationConversion(QualType FromType, QualType ToType,
-                                 bool CStyle, bool &ObjCLifetimeConversion);
-  bool IsFunctionConversion(QualType FromType, QualType ToType,
-                            QualType &ResultTy);
-  bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
-  bool isSameOrCompatibleFunctionType(QualType Param, QualType Arg);
+  void MarkTypoCorrectedFunctionDefinition(const NamedDecl *F);
 
-  bool CanPerformAggregateInitializationForOverloadResolution(
-      const InitializedEntity &Entity, InitListExpr *From);
+  /// Checks if the variant/multiversion functions are compatible.
+  bool areMultiversionVariantFunctionsCompatible(
+      const FunctionDecl *OldFD, const FunctionDecl *NewFD,
+      const PartialDiagnostic &NoProtoDiagID,
+      const PartialDiagnosticAt &NoteCausedDiagIDAt,
+      const PartialDiagnosticAt &NoSupportDiagIDAt,
+      const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported,
+      bool ConstexprSupported, bool CLinkageMayDiffer);
 
-  bool IsStringInit(Expr *Init, const ArrayType *AT);
+  /// type checking declaration initializers (C99 6.7.8)
+  bool CheckForConstantInitializer(Expr *e, QualType t);
 
-  bool CanPerformCopyInitialization(const InitializedEntity &Entity,
-                                    ExprResult Init);
-  ExprResult PerformCopyInitialization(const InitializedEntity &Entity,
-                                       SourceLocation EqualLoc,
-                                       ExprResult Init,
-                                       bool TopLevelOfInitList = false,
-                                       bool AllowExplicit = false);
-  ExprResult InitializeExplicitObjectArgument(Sema &S, Expr *Obj,
-                                              FunctionDecl *Fun);
-  ExprResult PerformImplicitObjectArgumentInitialization(
-      Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl,
-      CXXMethodDecl *Method);
+  QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name,
+                                        QualType Type, TypeSourceInfo *TSI,
+                                        SourceRange Range, bool DirectInit,
+                                        Expr *Init);
 
-  /// Check that the lifetime of the initializer (and its subobjects) is
-  /// sufficient for initializing the entity, and perform lifetime extension
-  /// (when permitted) if not.
-  void checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init);
+  bool DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit,
+                                     Expr *Init);
 
-  ExprResult PerformContextuallyConvertToBool(Expr *From);
-  ExprResult PerformContextuallyConvertToObjCPointer(Expr *From);
+  sema::LambdaScopeInfo *RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator);
 
-  /// Contexts in which a converted constant expression is required.
-  enum CCEKind {
-    CCEK_CaseValue,    ///< Expression in a case label.
-    CCEK_Enumerator,   ///< Enumerator value with fixed underlying type.
-    CCEK_TemplateArg,  ///< Value of a non-type template parameter.
-    CCEK_ArrayBound,   ///< Array bound in array declarator or new-expression.
-    CCEK_ExplicitBool, ///< Condition in an explicit(bool) specifier.
-    CCEK_Noexcept,     ///< Condition in a noexcept(bool) specifier.
-    CCEK_StaticAssertMessageSize, ///< Call to size() in a static assert
-                                  ///< message.
-    CCEK_StaticAssertMessageData, ///< Call to data() in a static assert
-                                  ///< message.
-  };
+  /// The declarator \p D defines a function in the scope \p S which is nested
+  /// in an `omp begin/end declare variant` scope. In this method we create a
+  /// declaration for \p D and rename \p D according to the OpenMP context
+  /// selector of the surrounding scope. Return all base functions in \p Bases.
+  void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
+      Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists,
+      SmallVectorImpl &Bases);
 
-  ExprResult BuildConvertedConstantExpression(Expr *From, QualType T,
-                                              CCEKind CCE,
-                                              NamedDecl *Dest = nullptr);
+  // Heuristically tells if the function is `get_return_object` member of a
+  // coroutine promise_type by matching the function name.
+  static bool CanBeGetReturnObject(const FunctionDecl *FD);
+  static bool CanBeGetReturnTypeOnAllocFailure(const FunctionDecl *FD);
 
-  ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
-                                              llvm::APSInt &Value, CCEKind CCE);
-  ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
-                                              APValue &Value, CCEKind CCE,
-                                              NamedDecl *Dest = nullptr);
+  NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
+                                      Scope *S);
+  void AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(
+      FunctionDecl *FD);
+  void AddKnownFunctionAttributes(FunctionDecl *FD);
 
-  ExprResult
-  EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value,
-                                      CCEKind CCE, bool RequireInt,
-                                      const APValue &PreNarrowingValue);
+  /// VerifyBitField - verifies that a bit field expression is an ICE and has
+  /// the correct width, and that the field type is valid.
+  /// Returns false on success.
+  ExprResult VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
+                            QualType FieldTy, bool IsMsStruct, Expr *BitWidth);
 
-  /// Abstract base class used to perform a contextual implicit
-  /// conversion from an expression to any type passing a filter.
-  class ContextualImplicitConverter {
-  public:
-    bool Suppress;
-    bool SuppressConversion;
+  /// IsValueInFlagEnum - Determine if a value is allowed as part of a flag
+  /// enum. If AllowMask is true, then we also allow the complement of a valid
+  /// value, to be used as a mask.
+  bool IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
+                         bool AllowMask) const;
 
-    ContextualImplicitConverter(bool Suppress = false,
-                                bool SuppressConversion = false)
-        : Suppress(Suppress), SuppressConversion(SuppressConversion) {}
+  /// ActOnPragmaWeakID - Called on well formed \#pragma weak ident.
+  void ActOnPragmaWeakID(IdentifierInfo *WeakName, SourceLocation PragmaLoc,
+                         SourceLocation WeakNameLoc);
 
-    /// Determine whether the specified type is a valid destination type
-    /// for this conversion.
-    virtual bool match(QualType T) = 0;
+  /// ActOnPragmaRedefineExtname - Called on well formed
+  /// \#pragma redefine_extname oldname newname.
+  void ActOnPragmaRedefineExtname(IdentifierInfo *WeakName,
+                                  IdentifierInfo *AliasName,
+                                  SourceLocation PragmaLoc,
+                                  SourceLocation WeakNameLoc,
+                                  SourceLocation AliasNameLoc);
 
-    /// Emits a diagnostic complaining that the expression does not have
-    /// integral or enumeration type.
-    virtual SemaDiagnosticBuilder
-    diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) = 0;
+  /// ActOnPragmaWeakAlias - Called on well formed \#pragma weak ident = ident.
+  void ActOnPragmaWeakAlias(IdentifierInfo *WeakName, IdentifierInfo *AliasName,
+                            SourceLocation PragmaLoc,
+                            SourceLocation WeakNameLoc,
+                            SourceLocation AliasNameLoc);
 
-    /// Emits a diagnostic when the expression has incomplete class type.
-    virtual SemaDiagnosticBuilder
-    diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) = 0;
+  ObjCContainerDecl *getObjCDeclContext() const;
 
-    /// Emits a diagnostic when the only matching conversion function
-    /// is explicit.
-    virtual SemaDiagnosticBuilder diagnoseExplicitConv(
-        Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;
+  /// Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
+  enum class FunctionEmissionStatus {
+    Emitted,
+    CUDADiscarded,     // Discarded due to CUDA/HIP hostness
+    OMPDiscarded,      // Discarded due to OpenMP hostness
+    TemplateDiscarded, // Discarded due to uninstantiated templates
+    Unknown,
+  };
+  FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl,
+                                           bool Final = false);
 
-    /// Emits a note for the explicit conversion function.
-    virtual SemaDiagnosticBuilder
-    noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
+  // Whether the callee should be ignored in CUDA/HIP/OpenMP host/device check.
+  bool shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee);
 
-    /// Emits a diagnostic when there are multiple possible conversion
-    /// functions.
-    virtual SemaDiagnosticBuilder
-    diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) = 0;
+private:
+  /// Function or variable declarations to be checked for whether the deferred
+  /// diagnostics should be emitted.
+  llvm::SmallSetVector DeclsToCheckForDeferredDiags;
 
-    /// Emits a note for one of the candidate conversions.
-    virtual SemaDiagnosticBuilder
-    noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
+  /// Map of current shadowing declarations to shadowed declarations. Warn if
+  /// it looks like the user is trying to modify the shadowing declaration.
+  llvm::DenseMap ShadowingDecls;
 
-    /// Emits a diagnostic when we picked a conversion function
-    /// (for cases when we are not allowed to pick a conversion function).
-    virtual SemaDiagnosticBuilder diagnoseConversion(
-        Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0;
+  static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD);
 
-    virtual ~ContextualImplicitConverter() {}
-  };
+  ///@}
 
-  class ICEConvertDiagnoser : public ContextualImplicitConverter {
-    bool AllowScopedEnumerations;
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  public:
-    ICEConvertDiagnoser(bool AllowScopedEnumerations,
-                        bool Suppress, bool SuppressConversion)
-        : ContextualImplicitConverter(Suppress, SuppressConversion),
-          AllowScopedEnumerations(AllowScopedEnumerations) {}
+  /// \name Declaration Attribute Handling
+  /// Implementations are in SemaDeclAttr.cpp
+  ///@{
 
-    /// Match an integral or (possibly scoped) enumeration type.
-    bool match(QualType T) override;
+public:
+  /// Describes the kind of priority given to an availability attribute.
+  ///
+  /// The sum of priorities deteremines the final priority of the attribute.
+  /// The final priority determines how the attribute will be merged.
+  /// An attribute with a lower priority will always remove higher priority
+  /// attributes for the specified platform when it is being applied. An
+  /// attribute with a higher priority will not be applied if the declaration
+  /// already has an availability attribute with a lower priority for the
+  /// specified platform. The final prirority values are not expected to match
+  /// the values in this enumeration, but instead should be treated as a plain
+  /// integer value. This enumeration just names the priority weights that are
+  /// used to calculate that final vaue.
+  enum AvailabilityPriority : int {
+    /// The availability attribute was specified explicitly next to the
+    /// declaration.
+    AP_Explicit = 0,
 
-    SemaDiagnosticBuilder
-    diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) override {
-      return diagnoseNotInt(S, Loc, T);
-    }
+    /// The availability attribute was applied using '#pragma clang attribute'.
+    AP_PragmaClangAttribute = 1,
 
-    /// Emits a diagnostic complaining that the expression does not have
-    /// integral or enumeration type.
-    virtual SemaDiagnosticBuilder
-    diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) = 0;
+    /// The availability attribute for a specific platform was inferred from
+    /// an availability attribute for another platform.
+    AP_InferredFromOtherPlatform = 2
   };
 
-  /// Perform a contextual implicit conversion.
-  ExprResult PerformContextualImplicitConversion(
-      SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter);
-
-
-  enum ObjCSubscriptKind {
-    OS_Array,
-    OS_Dictionary,
-    OS_Error
+  /// Describes the reason a calling convention specification was ignored, used
+  /// for diagnostics.
+  enum class CallingConventionIgnoredReason {
+    ForThisTarget = 0,
+    VariadicFunction,
+    ConstructorDestructor,
+    BuiltinFunction
   };
-  ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE);
 
-  // Note that LK_String is intentionally after the other literals, as
-  // this is used for diagnostics logic.
-  enum ObjCLiteralKind {
-    LK_Array,
-    LK_Dictionary,
-    LK_Numeric,
-    LK_Boxed,
-    LK_String,
-    LK_Block,
-    LK_None
-  };
-  ObjCLiteralKind CheckLiteralKind(Expr *FromE);
+  /// WeakTopLevelDecl - Translation-unit scoped declarations generated by
+  /// \#pragma weak during processing of other Decls.
+  /// I couldn't figure out a clean way to generate these in-line, so
+  /// we store them here and handle separately -- which is a hack.
+  /// It would be best to refactor this.
+  SmallVector WeakTopLevelDecl;
 
-  ExprResult PerformObjectMemberConversion(Expr *From,
-                                           NestedNameSpecifier *Qualifier,
-                                           NamedDecl *FoundDecl,
-                                           NamedDecl *Member);
+  /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
+  SmallVectorImpl &WeakTopLevelDecls() { return WeakTopLevelDecl; }
 
-  // Members have to be NamespaceDecl* or TranslationUnitDecl*.
-  // TODO: make this is a typesafe union.
-  typedef llvm::SmallSetVector AssociatedNamespaceSet;
-  typedef llvm::SmallSetVector AssociatedClassSet;
+  typedef LazyVector
+      ExtVectorDeclsType;
 
-  using ADLCallKind = CallExpr::ADLCallKind;
+  /// ExtVectorDecls - This is a list all the extended vector types. This allows
+  /// us to associate a raw vector type with one of the ext_vector type names.
+  /// This is only necessary for issuing pretty diagnostics.
+  ExtVectorDeclsType ExtVectorDecls;
 
-  void AddOverloadCandidate(
-      FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef Args,
-      OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
-      bool PartialOverloading = false, bool AllowExplicit = true,
-      bool AllowExplicitConversion = false,
-      ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
-      ConversionSequenceList EarlyConversions = std::nullopt,
-      OverloadCandidateParamOrder PO = {},
-      bool AggregateCandidateDeduction = false);
-  void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
-                      ArrayRef Args,
-                      OverloadCandidateSet &CandidateSet,
-                      TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
-                      bool SuppressUserConversions = false,
-                      bool PartialOverloading = false,
-                      bool FirstArgumentIsBase = false);
-  void AddMethodCandidate(DeclAccessPair FoundDecl,
-                          QualType ObjectType,
-                          Expr::Classification ObjectClassification,
-                          ArrayRef Args,
-                          OverloadCandidateSet& CandidateSet,
-                          bool SuppressUserConversion = false,
-                          OverloadCandidateParamOrder PO = {});
-  void
-  AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
-                     CXXRecordDecl *ActingContext, QualType ObjectType,
-                     Expr::Classification ObjectClassification,
-                     ArrayRef Args, OverloadCandidateSet &CandidateSet,
-                     bool SuppressUserConversions = false,
-                     bool PartialOverloading = false,
-                     ConversionSequenceList EarlyConversions = std::nullopt,
-                     OverloadCandidateParamOrder PO = {});
-  void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
-                                  DeclAccessPair FoundDecl,
-                                  CXXRecordDecl *ActingContext,
-                                 TemplateArgumentListInfo *ExplicitTemplateArgs,
-                                  QualType ObjectType,
-                                  Expr::Classification ObjectClassification,
-                                  ArrayRef Args,
-                                  OverloadCandidateSet& CandidateSet,
-                                  bool SuppressUserConversions = false,
-                                  bool PartialOverloading = false,
-                                  OverloadCandidateParamOrder PO = {});
-  void AddTemplateOverloadCandidate(
-      FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
-      TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args,
-      OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
-      bool PartialOverloading = false, bool AllowExplicit = true,
-      ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
-      OverloadCandidateParamOrder PO = {},
-      bool AggregateCandidateDeduction = false);
-  bool CheckNonDependentConversions(
-      FunctionTemplateDecl *FunctionTemplate, ArrayRef ParamTypes,
-      ArrayRef Args, OverloadCandidateSet &CandidateSet,
-      ConversionSequenceList &Conversions, bool SuppressUserConversions,
-      CXXRecordDecl *ActingContext = nullptr, QualType ObjectType = QualType(),
-      Expr::Classification ObjectClassification = {},
-      OverloadCandidateParamOrder PO = {});
-  void AddConversionCandidate(
-      CXXConversionDecl *Conversion, DeclAccessPair FoundDecl,
-      CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
-      OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
-      bool AllowExplicit, bool AllowResultConversion = true);
-  void AddTemplateConversionCandidate(
-      FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
-      CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
-      OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
-      bool AllowExplicit, bool AllowResultConversion = true);
-  void AddSurrogateCandidate(CXXConversionDecl *Conversion,
-                             DeclAccessPair FoundDecl,
-                             CXXRecordDecl *ActingContext,
-                             const FunctionProtoType *Proto,
-                             Expr *Object, ArrayRef Args,
-                             OverloadCandidateSet& CandidateSet);
-  void AddNonMemberOperatorCandidates(
-      const UnresolvedSetImpl &Functions, ArrayRef Args,
-      OverloadCandidateSet &CandidateSet,
-      TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
-  void AddMemberOperatorCandidates(OverloadedOperatorKind Op,
-                                   SourceLocation OpLoc, ArrayRef Args,
-                                   OverloadCandidateSet &CandidateSet,
-                                   OverloadCandidateParamOrder PO = {});
-  void AddBuiltinCandidate(QualType *ParamTys, ArrayRef Args,
-                           OverloadCandidateSet& CandidateSet,
-                           bool IsAssignmentOperator = false,
-                           unsigned NumContextualBoolArguments = 0);
-  void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
-                                    SourceLocation OpLoc, ArrayRef Args,
-                                    OverloadCandidateSet& CandidateSet);
-  void AddArgumentDependentLookupCandidates(DeclarationName Name,
-                                            SourceLocation Loc,
-                                            ArrayRef Args,
-                                TemplateArgumentListInfo *ExplicitTemplateArgs,
-                                            OverloadCandidateSet& CandidateSet,
-                                            bool PartialOverloading = false);
+  bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI,
+                                      const Expr *E, StringRef &Str,
+                                      SourceLocation *ArgLocation = nullptr);
+  bool checkStringLiteralArgumentAttr(const ParsedAttr &Attr, unsigned ArgNum,
+                                      StringRef &Str,
+                                      SourceLocation *ArgLocation = nullptr);
 
-  // Emit as a 'note' the specific overload candidate
-  void NoteOverloadCandidate(
-      const NamedDecl *Found, const FunctionDecl *Fn,
-      OverloadCandidateRewriteKind RewriteKind = OverloadCandidateRewriteKind(),
-      QualType DestType = QualType(), bool TakingAddress = false);
+  /// Determine if type T is a valid subject for a nonnull and similar
+  /// attributes. By default, we look through references (the behavior used by
+  /// nonnull), but if the second parameter is true, then we treat a reference
+  /// type as valid.
+  bool isValidPointerAttrType(QualType T, bool RefOkay = false);
 
-  // Emit as a series of 'note's all template and non-templates identified by
-  // the expression Expr
-  void NoteAllOverloadCandidates(Expr *E, QualType DestType = QualType(),
-                                 bool TakingAddress = false);
+  /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular
+  /// declaration.
+  void AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
+                            Expr *OE);
 
-  /// Check the enable_if expressions on the given function. Returns the first
-  /// failing attribute, or NULL if they were all successful.
-  EnableIfAttr *CheckEnableIf(FunctionDecl *Function, SourceLocation CallLoc,
-                              ArrayRef Args,
-                              bool MissingImplicitThis = false);
+  /// AddAllocAlignAttr - Adds an alloc_align attribute to a particular
+  /// declaration.
+  void AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
+                         Expr *ParamExpr);
 
-  /// Find the failed Boolean condition within a given Boolean
-  /// constant expression, and describe it with a string.
-  std::pair findFailedBooleanCondition(Expr *Cond);
-
-  /// Emit diagnostics for the diagnose_if attributes on Function, ignoring any
-  /// non-ArgDependent DiagnoseIfAttrs.
-  ///
-  /// Argument-dependent diagnose_if attributes should be checked each time a
-  /// function is used as a direct callee of a function call.
-  ///
-  /// Returns true if any errors were emitted.
-  bool diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function,
-                                           const Expr *ThisArg,
-                                           ArrayRef Args,
-                                           SourceLocation Loc);
+  bool CheckAttrTarget(const ParsedAttr &CurrAttr);
+  bool CheckAttrNoArgs(const ParsedAttr &CurrAttr);
 
-  /// Emit diagnostics for the diagnose_if attributes on Function, ignoring any
-  /// ArgDependent DiagnoseIfAttrs.
-  ///
-  /// Argument-independent diagnose_if attributes should be checked on every use
-  /// of a function.
-  ///
-  /// Returns true if any errors were emitted.
-  bool diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND,
-                                             SourceLocation Loc);
+  AvailabilityAttr *
+  mergeAvailabilityAttr(NamedDecl *D, const AttributeCommonInfo &CI,
+                        IdentifierInfo *Platform, bool Implicit,
+                        VersionTuple Introduced, VersionTuple Deprecated,
+                        VersionTuple Obsoleted, bool IsUnavailable,
+                        StringRef Message, bool IsStrict, StringRef Replacement,
+                        AvailabilityMergeKind AMK, int Priority);
+  TypeVisibilityAttr *
+  mergeTypeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI,
+                          TypeVisibilityAttr::VisibilityType Vis);
+  VisibilityAttr *mergeVisibilityAttr(Decl *D, const AttributeCommonInfo &CI,
+                                      VisibilityAttr::VisibilityType Vis);
+  SectionAttr *mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI,
+                                StringRef Name);
 
-  /// Returns whether the given function's address can be taken or not,
-  /// optionally emitting a diagnostic if the address can't be taken.
-  ///
-  /// Returns false if taking the address of the function is illegal.
-  bool checkAddressOfFunctionIsAvailable(const FunctionDecl *Function,
-                                         bool Complain = false,
-                                         SourceLocation Loc = SourceLocation());
+  llvm::Error isValidSectionSpecifier(StringRef Str);
+  bool checkSectionName(SourceLocation LiteralLoc, StringRef Str);
+  CodeSegAttr *mergeCodeSegAttr(Decl *D, const AttributeCommonInfo &CI,
+                                StringRef Name);
 
-  // [PossiblyAFunctionType]  -->   [Return]
-  // NonFunctionType --> NonFunctionType
-  // R (A) --> R(A)
-  // R (*)(A) --> R (A)
-  // R (&)(A) --> R (A)
-  // R (S::*)(A) --> R (A)
-  QualType ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType);
+  bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str);
+  bool checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
+                              StringRef &Str, bool &isDefault);
+  bool checkTargetClonesAttrString(
+      SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal,
+      Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault,
+      SmallVectorImpl> &StringsBuffer);
 
-  FunctionDecl *
-  ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
-                                     QualType TargetType,
-                                     bool Complain,
-                                     DeclAccessPair &Found,
-                                     bool *pHadMultipleCandidates = nullptr);
+  ErrorAttr *mergeErrorAttr(Decl *D, const AttributeCommonInfo &CI,
+                            StringRef NewUserDiagnostic);
+  FormatAttr *mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI,
+                              IdentifierInfo *Format, int FormatIdx,
+                              int FirstArg);
 
-  FunctionDecl *
-  resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &FoundResult);
+  /// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
+  void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
+                      bool IsPackExpansion);
+  void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, TypeSourceInfo *T,
+                      bool IsPackExpansion);
 
-  bool resolveAndFixAddressOfSingleOverloadCandidate(
-      ExprResult &SrcExpr, bool DoFunctionPointerConversion = false);
+  /// AddAlignValueAttr - Adds an align_value attribute to a particular
+  /// declaration.
+  void AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E);
 
-  FunctionDecl *ResolveSingleFunctionTemplateSpecialization(
-      OverloadExpr *ovl, bool Complain = false, DeclAccessPair *Found = nullptr,
-      TemplateSpecCandidateSet *FailedTSC = nullptr);
+  /// AddAnnotationAttr - Adds an annotation Annot with Args arguments to D.
+  void AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
+                         StringRef Annot, MutableArrayRef Args);
 
-  bool ResolveAndFixSingleFunctionTemplateSpecialization(
-      ExprResult &SrcExpr, bool DoFunctionPointerConversion = false,
-      bool Complain = false, SourceRange OpRangeForComplaining = SourceRange(),
-      QualType DestTypeForComplaining = QualType(),
-      unsigned DiagIDForComplaining = 0);
+  bool checkMSInheritanceAttrOnDefinition(CXXRecordDecl *RD, SourceRange Range,
+                                          bool BestCase,
+                                          MSInheritanceModel SemanticSpelling);
 
-  ExprResult FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl,
-                                            FunctionDecl *Fn);
-  ExprResult FixOverloadedFunctionReference(ExprResult,
-                                            DeclAccessPair FoundDecl,
-                                            FunctionDecl *Fn);
+  void CheckAlignasUnderalignment(Decl *D);
 
-  void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
-                                   ArrayRef Args,
-                                   OverloadCandidateSet &CandidateSet,
-                                   bool PartialOverloading = false);
-  void AddOverloadedCallCandidates(
-      LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs,
-      ArrayRef Args, OverloadCandidateSet &CandidateSet);
+  /// AddModeAttr - Adds a mode attribute to a particular declaration.
+  void AddModeAttr(Decl *D, const AttributeCommonInfo &CI, IdentifierInfo *Name,
+                   bool InInstantiation = false);
+  AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D,
+                                          const AttributeCommonInfo &CI,
+                                          const IdentifierInfo *Ident);
+  MinSizeAttr *mergeMinSizeAttr(Decl *D, const AttributeCommonInfo &CI);
+  SwiftNameAttr *mergeSwiftNameAttr(Decl *D, const SwiftNameAttr &SNA,
+                                    StringRef Name);
+  OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D,
+                                          const AttributeCommonInfo &CI);
+  InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D, const ParsedAttr &AL);
+  InternalLinkageAttr *mergeInternalLinkageAttr(Decl *D,
+                                                const InternalLinkageAttr &AL);
 
-  // An enum used to represent the different possible results of building a
-  // range-based for loop.
-  enum ForRangeStatus {
-    FRS_Success,
-    FRS_NoViableFunction,
-    FRS_DiagnosticIssued
+  enum CUDAFunctionTarget {
+    CFT_Device,
+    CFT_Global,
+    CFT_Host,
+    CFT_HostDevice,
+    CFT_InvalidTarget
   };
 
-  ForRangeStatus BuildForRangeBeginEndCall(SourceLocation Loc,
-                                           SourceLocation RangeLoc,
-                                           const DeclarationNameInfo &NameInfo,
-                                           LookupResult &MemberLookup,
-                                           OverloadCandidateSet *CandidateSet,
-                                           Expr *Range, ExprResult *CallExpr);
+  /// Check validaty of calling convention attribute \p attr. If \p FD
+  /// is not null pointer, use \p FD to determine the CUDA/HIP host/device
+  /// target. Otherwise, it is specified by \p CFT.
+  bool CheckCallingConvAttr(const ParsedAttr &attr, CallingConv &CC,
+                            const FunctionDecl *FD = nullptr,
+                            CUDAFunctionTarget CFT = CFT_InvalidTarget);
 
-  ExprResult BuildOverloadedCallExpr(Scope *S, Expr *Fn,
-                                     UnresolvedLookupExpr *ULE,
-                                     SourceLocation LParenLoc,
-                                     MultiExprArg Args,
-                                     SourceLocation RParenLoc,
-                                     Expr *ExecConfig,
-                                     bool AllowTypoCorrection=true,
-                                     bool CalleesAddressIsTaken=false);
+  void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
+                           ParameterABI ABI);
+  bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value);
 
-  bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
-                              MultiExprArg Args, SourceLocation RParenLoc,
-                              OverloadCandidateSet *CandidateSet,
-                              ExprResult *Result);
+  /// Create an CUDALaunchBoundsAttr attribute.
+  CUDALaunchBoundsAttr *CreateLaunchBoundsAttr(const AttributeCommonInfo &CI,
+                                               Expr *MaxThreads,
+                                               Expr *MinBlocks,
+                                               Expr *MaxBlocks);
 
-  ExprResult CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass,
-                                        NestedNameSpecifierLoc NNSLoc,
-                                        DeclarationNameInfo DNI,
-                                        const UnresolvedSetImpl &Fns,
-                                        bool PerformADL = true);
+  /// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular
+  /// declaration.
+  void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,
+                           Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks);
 
-  ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
-                                     UnaryOperatorKind Opc,
-                                     const UnresolvedSetImpl &Fns,
-                                     Expr *input, bool RequiresADL = true);
+  enum class RetainOwnershipKind { NS, CF, OS };
+  void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
+                        RetainOwnershipKind K, bool IsTemplateInstantiation);
 
-  void LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet,
-                             OverloadedOperatorKind Op,
-                             const UnresolvedSetImpl &Fns,
-                             ArrayRef Args, bool RequiresADL = true);
-  ExprResult CreateOverloadedBinOp(SourceLocation OpLoc,
-                                   BinaryOperatorKind Opc,
-                                   const UnresolvedSetImpl &Fns,
-                                   Expr *LHS, Expr *RHS,
-                                   bool RequiresADL = true,
-                                   bool AllowRewrittenCandidates = true,
-                                   FunctionDecl *DefaultedFn = nullptr);
-  ExprResult BuildSynthesizedThreeWayComparison(SourceLocation OpLoc,
-                                                const UnresolvedSetImpl &Fns,
-                                                Expr *LHS, Expr *RHS,
-                                                FunctionDecl *DefaultedFn);
+  bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
 
-  ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
-                                                SourceLocation RLoc, Expr *Base,
-                                                MultiExprArg Args);
+  /// Do a check to make sure \p Name looks like a legal argument for the
+  /// swift_name attribute applied to decl \p D.  Raise a diagnostic if the name
+  /// is invalid for the given declaration.
+  ///
+  /// \p AL is used to provide caret diagnostics in case of a malformed name.
+  ///
+  /// \returns true if the name is a valid swift name for \p D, false otherwise.
+  bool DiagnoseSwiftName(Decl *D, StringRef Name, SourceLocation Loc,
+                         const ParsedAttr &AL, bool IsAsync);
 
-  ExprResult BuildCallToMemberFunction(Scope *S, Expr *MemExpr,
-                                       SourceLocation LParenLoc,
-                                       MultiExprArg Args,
-                                       SourceLocation RParenLoc,
-                                       Expr *ExecConfig = nullptr,
-                                       bool IsExecConfig = false,
-                                       bool AllowRecovery = false);
-  ExprResult
-  BuildCallToObjectOfClassType(Scope *S, Expr *Object, SourceLocation LParenLoc,
-                               MultiExprArg Args,
-                               SourceLocation RParenLoc);
+  UuidAttr *mergeUuidAttr(Decl *D, const AttributeCommonInfo &CI,
+                          StringRef UuidAsWritten, MSGuidDecl *GuidDecl);
 
-  ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
-                                      SourceLocation OpLoc,
-                                      bool *NoArrowOperatorFound = nullptr);
+  BTFDeclTagAttr *mergeBTFDeclTagAttr(Decl *D, const BTFDeclTagAttr &AL);
+  HLSLNumThreadsAttr *mergeHLSLNumThreadsAttr(Decl *D,
+                                              const AttributeCommonInfo &AL,
+                                              int X, int Y, int Z);
+  HLSLShaderAttr *mergeHLSLShaderAttr(Decl *D, const AttributeCommonInfo &AL,
+                                      HLSLShaderAttr::ShaderType ShaderType);
+  HLSLParamModifierAttr *
+  mergeHLSLParamModifierAttr(Decl *D, const AttributeCommonInfo &AL,
+                             HLSLParamModifierAttr::Spelling Spelling);
 
-  /// CheckCallReturnType - Checks that a call expression's return type is
-  /// complete. Returns true on failure. The location passed in is the location
-  /// that best represents the call.
-  bool CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
-                           CallExpr *CE, FunctionDecl *FD);
+  WebAssemblyImportNameAttr *
+  mergeImportNameAttr(Decl *D, const WebAssemblyImportNameAttr &AL);
+  WebAssemblyImportModuleAttr *
+  mergeImportModuleAttr(Decl *D, const WebAssemblyImportModuleAttr &AL);
 
-  /// Helpers for dealing with blocks and functions.
-  bool CheckParmsForFunctionDef(ArrayRef Parameters,
-                                bool CheckParameterNames);
-  void CheckCXXDefaultArguments(FunctionDecl *FD);
-  void CheckExtraCXXDefaultArguments(Declarator &D);
-  Scope *getNonFieldDeclScope(Scope *S);
+  /// Create an AMDGPUWavesPerEUAttr attribute.
+  AMDGPUFlatWorkGroupSizeAttr *
+  CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min,
+                                    Expr *Max);
 
-  /// \name Name lookup
-  ///
-  /// These routines provide name lookup that is used during semantic
-  /// analysis to resolve the various kinds of names (identifiers,
-  /// overloaded operator names, constructor names, etc.) into zero or
-  /// more declarations within a particular scope. The major entry
-  /// points are LookupName, which performs unqualified name lookup,
-  /// and LookupQualifiedName, which performs qualified name lookup.
-  ///
-  /// All name lookup is performed based on some specific criteria,
-  /// which specify what names will be visible to name lookup and how
-  /// far name lookup should work. These criteria are important both
-  /// for capturing language semantics (certain lookups will ignore
-  /// certain names, for example) and for performance, since name
-  /// lookup is often a bottleneck in the compilation of C++. Name
-  /// lookup criteria is specified via the LookupCriteria enumeration.
-  ///
-  /// The results of name lookup can vary based on the kind of name
-  /// lookup performed, the current language, and the translation
-  /// unit. In C, for example, name lookup will either return nothing
-  /// (no entity found) or a single declaration. In C++, name lookup
-  /// can additionally refer to a set of overloaded functions or
-  /// result in an ambiguity. All of the possible results of name
-  /// lookup are captured by the LookupResult class, which provides
-  /// the ability to distinguish among them.
-  //@{
+  /// addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size
+  /// attribute to a particular declaration.
+  void addAMDGPUFlatWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
+                                      Expr *Min, Expr *Max);
 
-  /// Describes the kind of name lookup to perform.
-  enum LookupNameKind {
-    /// Ordinary name lookup, which finds ordinary names (functions,
-    /// variables, typedefs, etc.) in C and most kinds of names
-    /// (functions, variables, members, types, etc.) in C++.
-    LookupOrdinaryName = 0,
-    /// Tag name lookup, which finds the names of enums, classes,
-    /// structs, and unions.
-    LookupTagName,
-    /// Label name lookup.
-    LookupLabel,
-    /// Member name lookup, which finds the names of
-    /// class/struct/union members.
-    LookupMemberName,
-    /// Look up of an operator name (e.g., operator+) for use with
-    /// operator overloading. This lookup is similar to ordinary name
-    /// lookup, but will ignore any declarations that are class members.
-    LookupOperatorName,
-    /// Look up a name following ~ in a destructor name. This is an ordinary
-    /// lookup, but prefers tags to typedefs.
-    LookupDestructorName,
-    /// Look up of a name that precedes the '::' scope resolution
-    /// operator in C++. This lookup completely ignores operator, object,
-    /// function, and enumerator names (C++ [basic.lookup.qual]p1).
-    LookupNestedNameSpecifierName,
-    /// Look up a namespace name within a C++ using directive or
-    /// namespace alias definition, ignoring non-namespace names (C++
-    /// [basic.lookup.udir]p1).
-    LookupNamespaceName,
-    /// Look up all declarations in a scope with the given name,
-    /// including resolved using declarations.  This is appropriate
-    /// for checking redeclarations for a using declaration.
-    LookupUsingDeclName,
-    /// Look up an ordinary name that is going to be redeclared as a
-    /// name with linkage. This lookup ignores any declarations that
-    /// are outside of the current scope unless they have linkage. See
-    /// C99 6.2.2p4-5 and C++ [basic.link]p6.
-    LookupRedeclarationWithLinkage,
-    /// Look up a friend of a local class. This lookup does not look
-    /// outside the innermost non-class scope. See C++11 [class.friend]p11.
-    LookupLocalFriendName,
-    /// Look up the name of an Objective-C protocol.
-    LookupObjCProtocolName,
-    /// Look up implicit 'self' parameter of an objective-c method.
-    LookupObjCImplicitSelfParam,
-    /// Look up the name of an OpenMP user-defined reduction operation.
-    LookupOMPReductionName,
-    /// Look up the name of an OpenMP user-defined mapper.
-    LookupOMPMapperName,
-    /// Look up any declaration with any name.
-    LookupAnyName
-  };
+  /// Create an AMDGPUWavesPerEUAttr attribute.
+  AMDGPUWavesPerEUAttr *
+  CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min,
+                             Expr *Max);
 
-  /// Specifies whether (or how) name lookup is being performed for a
-  /// redeclaration (vs. a reference).
-  enum RedeclarationKind {
-    /// The lookup is a reference to this name that is not for the
-    /// purpose of redeclaring the name.
-    NotForRedeclaration = 0,
-    /// The lookup results will be used for redeclaration of a name,
-    /// if an entity by that name already exists and is visible.
-    ForVisibleRedeclaration,
-    /// The lookup results will be used for redeclaration of a name
-    /// with external linkage; non-visible lookup results with external linkage
-    /// may also be found.
-    ForExternalRedeclaration
-  };
+  /// addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a
+  /// particular declaration.
+  void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI,
+                               Expr *Min, Expr *Max);
 
-  RedeclarationKind forRedeclarationInCurContext() const {
-    // A declaration with an owning module for linkage can never link against
-    // anything that is not visible. We don't need to check linkage here; if
-    // the context has internal linkage, redeclaration lookup won't find things
-    // from other TUs, and we can't safely compute linkage yet in general.
-    if (cast(CurContext)
-            ->getOwningModuleForLinkage(/*IgnoreLinkage*/true))
-      return ForVisibleRedeclaration;
-    return ForExternalRedeclaration;
-  }
+  DLLImportAttr *mergeDLLImportAttr(Decl *D, const AttributeCommonInfo &CI);
+  DLLExportAttr *mergeDLLExportAttr(Decl *D, const AttributeCommonInfo &CI);
+  MSInheritanceAttr *mergeMSInheritanceAttr(Decl *D,
+                                            const AttributeCommonInfo &CI,
+                                            bool BestCase,
+                                            MSInheritanceModel Model);
 
-  /// The possible outcomes of name lookup for a literal operator.
-  enum LiteralOperatorLookupResult {
-    /// The lookup resulted in an error.
-    LOLR_Error,
-    /// The lookup found no match but no diagnostic was issued.
-    LOLR_ErrorNoDiagnostic,
-    /// The lookup found a single 'cooked' literal operator, which
-    /// expects a normal literal to be built and passed to it.
-    LOLR_Cooked,
-    /// The lookup found a single 'raw' literal operator, which expects
-    /// a string literal containing the spelling of the literal token.
-    LOLR_Raw,
-    /// The lookup found an overload set of literal operator templates,
-    /// which expect the characters of the spelling of the literal token to be
-    /// passed as a non-type template argument pack.
-    LOLR_Template,
-    /// The lookup found an overload set of literal operator templates,
-    /// which expect the character type and characters of the spelling of the
-    /// string literal token to be passed as template arguments.
-    LOLR_StringTemplatePack,
-  };
+  bool CheckCountedByAttr(Scope *Scope, const FieldDecl *FD);
 
-  SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D,
-                                                  CXXSpecialMember SM,
-                                                  bool ConstArg,
-                                                  bool VolatileArg,
-                                                  bool RValueThis,
-                                                  bool ConstThis,
-                                                  bool VolatileThis);
+  EnforceTCBAttr *mergeEnforceTCBAttr(Decl *D, const EnforceTCBAttr &AL);
+  EnforceTCBLeafAttr *mergeEnforceTCBLeafAttr(Decl *D,
+                                              const EnforceTCBLeafAttr &AL);
 
-  typedef std::function TypoDiagnosticGenerator;
-  typedef std::function
-      TypoRecoveryCallback;
+  // Helper for delayed processing of attributes.
+  void ProcessDeclAttributeDelayed(Decl *D,
+                                   const ParsedAttributesView &AttrList);
 
-private:
-  bool CppLookupName(LookupResult &R, Scope *S);
+  // Options for ProcessDeclAttributeList().
+  struct ProcessDeclAttributeOptions {
+    ProcessDeclAttributeOptions()
+        : IncludeCXX11Attributes(true), IgnoreTypeAttributes(false) {}
 
-  struct TypoExprState {
-    std::unique_ptr Consumer;
-    TypoDiagnosticGenerator DiagHandler;
-    TypoRecoveryCallback RecoveryHandler;
-    TypoExprState();
-    TypoExprState(TypoExprState &&other) noexcept;
-    TypoExprState &operator=(TypoExprState &&other) noexcept;
-  };
+    ProcessDeclAttributeOptions WithIncludeCXX11Attributes(bool Val) {
+      ProcessDeclAttributeOptions Result = *this;
+      Result.IncludeCXX11Attributes = Val;
+      return Result;
+    }
 
-  /// The set of unhandled TypoExprs and their associated state.
-  llvm::MapVector DelayedTypos;
+    ProcessDeclAttributeOptions WithIgnoreTypeAttributes(bool Val) {
+      ProcessDeclAttributeOptions Result = *this;
+      Result.IgnoreTypeAttributes = Val;
+      return Result;
+    }
 
-  /// Creates a new TypoExpr AST node.
-  TypoExpr *createDelayedTypo(std::unique_ptr TCC,
-                              TypoDiagnosticGenerator TDG,
-                              TypoRecoveryCallback TRC, SourceLocation TypoLoc);
+    // Should C++11 attributes be processed?
+    bool IncludeCXX11Attributes;
 
-  // The set of known/encountered (unique, canonicalized) NamespaceDecls.
-  //
-  // The boolean value will be true to indicate that the namespace was loaded
-  // from an AST/PCH file, or false otherwise.
-  llvm::MapVector KnownNamespaces;
+    // Should any type attributes encountered be ignored?
+    // If this option is false, a diagnostic will be emitted for any type
+    // attributes of a kind that does not "slide" from the declaration to
+    // the decl-specifier-seq.
+    bool IgnoreTypeAttributes;
+  };
 
-  /// Whether we have already loaded known namespaces from an extenal
-  /// source.
-  bool LoadedExternalKnownNamespaces;
+  void ProcessDeclAttributeList(Scope *S, Decl *D,
+                                const ParsedAttributesView &AttrList,
+                                const ProcessDeclAttributeOptions &Options =
+                                    ProcessDeclAttributeOptions());
+  bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
+                                      const ParsedAttributesView &AttrList);
 
-  /// Helper for CorrectTypo and CorrectTypoDelayed used to create and
-  /// populate a new TypoCorrectionConsumer. Returns nullptr if typo correction
-  /// should be skipped entirely.
-  std::unique_ptr
-  makeTypoCorrectionConsumer(const DeclarationNameInfo &Typo,
-                             Sema::LookupNameKind LookupKind, Scope *S,
-                             CXXScopeSpec *SS,
-                             CorrectionCandidateCallback &CCC,
-                             DeclContext *MemberContext, bool EnteringContext,
-                             const ObjCObjectPointerType *OPT,
-                             bool ErrorRecovery);
+  void checkUnusedDeclAttributes(Declarator &D);
 
-public:
-  const TypoExprState &getTypoExprState(TypoExpr *TE) const;
+  NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II,
+                                 SourceLocation Loc);
+  void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, const WeakInfo &W);
 
-  /// Clears the state of the given TypoExpr.
-  void clearDelayedTypo(TypoExpr *TE);
+  void ProcessPragmaWeak(Scope *S, Decl *D);
+  // Decl attributes - this routine is the top level dispatcher.
+  void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD);
 
-  /// Look up a name, looking for a single declaration.  Return
-  /// null if the results were absent, ambiguous, or overloaded.
-  ///
-  /// It is preferable to use the elaborated form and explicitly handle
-  /// ambiguity and overloaded.
-  NamedDecl *LookupSingleName(Scope *S, DeclarationName Name,
-                              SourceLocation Loc,
-                              LookupNameKind NameKind,
-                              RedeclarationKind Redecl
-                                = NotForRedeclaration);
-  bool LookupBuiltin(LookupResult &R);
-  void LookupNecessaryTypesForBuiltin(Scope *S, unsigned ID);
-  bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation = false,
-                  bool ForceNoCPlusPlus = false);
-  bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
-                           bool InUnqualifiedLookup = false);
-  bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
-                           CXXScopeSpec &SS);
-  bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
-                        bool AllowBuiltinCreation = false,
-                        bool EnteringContext = false);
-  ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc,
-                                   RedeclarationKind Redecl
-                                     = NotForRedeclaration);
-  bool LookupInSuper(LookupResult &R, CXXRecordDecl *Class);
+  void PopParsingDeclaration(ParsingDeclState state, Decl *decl);
 
-  void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
-                                    UnresolvedSetImpl &Functions);
+  void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
 
-  LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
-                                 SourceLocation GnuLabelLoc = SourceLocation());
+  ///@}
 
-  DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);
-  CXXConstructorDecl *LookupDefaultConstructor(CXXRecordDecl *Class);
-  CXXConstructorDecl *LookupCopyingConstructor(CXXRecordDecl *Class,
-                                               unsigned Quals);
-  CXXMethodDecl *LookupCopyingAssignment(CXXRecordDecl *Class, unsigned Quals,
-                                         bool RValueThis, unsigned ThisQuals);
-  CXXConstructorDecl *LookupMovingConstructor(CXXRecordDecl *Class,
-                                              unsigned Quals);
-  CXXMethodDecl *LookupMovingAssignment(CXXRecordDecl *Class, unsigned Quals,
-                                        bool RValueThis, unsigned ThisQuals);
-  CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id,
-                              bool IsUDSuffix);
-  LiteralOperatorLookupResult
-  LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef ArgTys,
-                        bool AllowRaw, bool AllowTemplate,
-                        bool AllowStringTemplate, bool DiagnoseMissing,
-                        StringLiteral *StringLit = nullptr);
-  bool isKnownName(StringRef name);
+  /// \name C++ Declarations
+  /// Implementations are in SemaDeclCXX.cpp
+  ///@{
 
-  /// Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
-  enum class FunctionEmissionStatus {
-    Emitted,
-    CUDADiscarded,     // Discarded due to CUDA/HIP hostness
-    OMPDiscarded,      // Discarded due to OpenMP hostness
-    TemplateDiscarded, // Discarded due to uninstantiated templates
-    Unknown,
-  };
-  FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl,
-                                           bool Final = false);
+public:
+  void CheckDelegatingCtorCycles();
 
-  // Whether the callee should be ignored in CUDA/HIP/OpenMP host/device check.
-  bool shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee);
+  /// Called before parsing a function declarator belonging to a function
+  /// declaration.
+  void ActOnStartFunctionDeclarationDeclarator(Declarator &D,
+                                               unsigned TemplateParameterDepth);
 
-  void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
-                               ArrayRef Args, ADLResult &Functions);
+  /// Called after parsing a function declarator belonging to a function
+  /// declaration.
+  void ActOnFinishFunctionDeclarationDeclarator(Declarator &D);
 
-  void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
-                          VisibleDeclConsumer &Consumer,
-                          bool IncludeGlobalScope = true,
-                          bool LoadExternal = true);
-  void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
-                          VisibleDeclConsumer &Consumer,
-                          bool IncludeGlobalScope = true,
-                          bool IncludeDependentBases = false,
-                          bool LoadExternal = true);
+  // Act on C++ namespaces
+  Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc,
+                               SourceLocation NamespaceLoc,
+                               SourceLocation IdentLoc, IdentifierInfo *Ident,
+                               SourceLocation LBrace,
+                               const ParsedAttributesView &AttrList,
+                               UsingDirectiveDecl *&UsingDecl, bool IsNested);
+  void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace);
 
-  enum CorrectTypoKind {
-    CTK_NonError,     // CorrectTypo used in a non error recovery situation.
-    CTK_ErrorRecovery // CorrectTypo used in normal error recovery.
-  };
+  NamespaceDecl *getStdNamespace() const;
+  NamespaceDecl *getOrCreateStdNamespace();
 
-  TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
-                             Sema::LookupNameKind LookupKind,
-                             Scope *S, CXXScopeSpec *SS,
-                             CorrectionCandidateCallback &CCC,
-                             CorrectTypoKind Mode,
-                             DeclContext *MemberContext = nullptr,
-                             bool EnteringContext = false,
-                             const ObjCObjectPointerType *OPT = nullptr,
-                             bool RecordFailure = true);
+  CXXRecordDecl *getStdBadAlloc() const;
+  EnumDecl *getStdAlignValT() const;
 
-  TypoExpr *CorrectTypoDelayed(const DeclarationNameInfo &Typo,
-                               Sema::LookupNameKind LookupKind, Scope *S,
-                               CXXScopeSpec *SS,
-                               CorrectionCandidateCallback &CCC,
-                               TypoDiagnosticGenerator TDG,
-                               TypoRecoveryCallback TRC, CorrectTypoKind Mode,
-                               DeclContext *MemberContext = nullptr,
-                               bool EnteringContext = false,
-                               const ObjCObjectPointerType *OPT = nullptr);
+  ValueDecl *tryLookupUnambiguousFieldDecl(RecordDecl *ClassDecl,
+                                           const IdentifierInfo *MemberOrBase);
 
-  /// Process any TypoExprs in the given Expr and its children,
-  /// generating diagnostics as appropriate and returning a new Expr if there
-  /// were typos that were all successfully corrected and ExprError if one or
-  /// more typos could not be corrected.
-  ///
-  /// \param E The Expr to check for TypoExprs.
-  ///
-  /// \param InitDecl A VarDecl to avoid because the Expr being corrected is its
-  /// initializer.
-  ///
-  /// \param RecoverUncorrectedTypos If true, when typo correction fails, it
-  /// will rebuild the given Expr with all TypoExprs degraded to RecoveryExprs.
+  enum class ComparisonCategoryUsage {
+    /// The '<=>' operator was used in an expression and a builtin operator
+    /// was selected.
+    OperatorInExpression,
+    /// A defaulted 'operator<=>' needed the comparison category. This
+    /// typically only applies to 'std::strong_ordering', due to the implicit
+    /// fallback return value.
+    DefaultedOperator,
+  };
+
+  /// Lookup the specified comparison category types in the standard
+  ///   library, an check the VarDecls possibly returned by the operator<=>
+  ///   builtins for that type.
   ///
-  /// \param Filter A function applied to a newly rebuilt Expr to determine if
-  /// it is an acceptable/usable result from a single combination of typo
-  /// corrections. As long as the filter returns ExprError, different
-  /// combinations of corrections will be tried until all are exhausted.
-  ExprResult CorrectDelayedTyposInExpr(
-      Expr *E, VarDecl *InitDecl = nullptr,
-      bool RecoverUncorrectedTypos = false,
-      llvm::function_ref Filter =
-          [](Expr *E) -> ExprResult { return E; });
+  /// \return The type of the comparison category type corresponding to the
+  ///   specified Kind, or a null type if an error occurs
+  QualType CheckComparisonCategoryType(ComparisonCategoryType Kind,
+                                       SourceLocation Loc,
+                                       ComparisonCategoryUsage Usage);
 
-  ExprResult CorrectDelayedTyposInExpr(
-      ExprResult ER, VarDecl *InitDecl = nullptr,
-      bool RecoverUncorrectedTypos = false,
-      llvm::function_ref Filter =
-          [](Expr *E) -> ExprResult { return E; }) {
-    return ER.isInvalid()
-               ? ER
-               : CorrectDelayedTyposInExpr(ER.get(), InitDecl,
-                                           RecoverUncorrectedTypos, Filter);
-  }
+  /// Tests whether Ty is an instance of std::initializer_list and, if
+  /// it is and Element is not NULL, assigns the element type to Element.
+  bool isStdInitializerList(QualType Ty, QualType *Element);
 
-  void diagnoseTypo(const TypoCorrection &Correction,
-                    const PartialDiagnostic &TypoDiag,
-                    bool ErrorRecovery = true);
+  /// Looks for the std::initializer_list template and instantiates it
+  /// with Element, or emits an error if it's not found.
+  ///
+  /// \returns The instantiated template, or null on error.
+  QualType BuildStdInitializerList(QualType Element, SourceLocation Loc);
 
-  void diagnoseTypo(const TypoCorrection &Correction,
-                    const PartialDiagnostic &TypoDiag,
-                    const PartialDiagnostic &PrevNote,
-                    bool ErrorRecovery = true);
+  /// Determine whether Ctor is an initializer-list constructor, as
+  /// defined in [dcl.init.list]p2.
+  bool isInitListConstructor(const FunctionDecl *Ctor);
 
-  void MarkTypoCorrectedFunctionDefinition(const NamedDecl *F);
+  Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc,
+                            SourceLocation NamespcLoc, CXXScopeSpec &SS,
+                            SourceLocation IdentLoc,
+                            IdentifierInfo *NamespcName,
+                            const ParsedAttributesView &AttrList);
 
-  void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc,
-                                          ArrayRef Args,
-                                   AssociatedNamespaceSet &AssociatedNamespaces,
-                                   AssociatedClassSet &AssociatedClasses);
+  void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir);
 
-  void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
-                            bool ConsiderLinkage, bool AllowInlineNamespace);
+  Decl *ActOnNamespaceAliasDef(Scope *CurScope, SourceLocation NamespaceLoc,
+                               SourceLocation AliasLoc, IdentifierInfo *Alias,
+                               CXXScopeSpec &SS, SourceLocation IdentLoc,
+                               IdentifierInfo *Ident);
 
-  bool CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old);
-  bool CheckRedeclarationExported(NamedDecl *New, NamedDecl *Old);
-  bool CheckRedeclarationInModule(NamedDecl *New, NamedDecl *Old);
-  bool IsRedefinitionInModule(const NamedDecl *New,
-                                 const NamedDecl *Old) const;
+  void FilterUsingLookup(Scope *S, LookupResult &lookup);
+  void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow);
+  bool CheckUsingShadowDecl(BaseUsingDecl *BUD, NamedDecl *Target,
+                            const LookupResult &PreviousDecls,
+                            UsingShadowDecl *&PrevShadow);
+  UsingShadowDecl *BuildUsingShadowDecl(Scope *S, BaseUsingDecl *BUD,
+                                        NamedDecl *Target,
+                                        UsingShadowDecl *PrevDecl);
 
-  void DiagnoseAmbiguousLookup(LookupResult &Result);
-  //@}
+  bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
+                                   bool HasTypenameKeyword,
+                                   const CXXScopeSpec &SS,
+                                   SourceLocation NameLoc,
+                                   const LookupResult &Previous);
+  bool CheckUsingDeclQualifier(SourceLocation UsingLoc, bool HasTypename,
+                               const CXXScopeSpec &SS,
+                               const DeclarationNameInfo &NameInfo,
+                               SourceLocation NameLoc,
+                               const LookupResult *R = nullptr,
+                               const UsingDecl *UD = nullptr);
 
-  /// Attempts to produce a RecoveryExpr after some AST node cannot be created.
-  ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End,
-                                ArrayRef SubExprs,
-                                QualType T = QualType());
+  NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
+                                   SourceLocation UsingLoc,
+                                   bool HasTypenameKeyword,
+                                   SourceLocation TypenameLoc, CXXScopeSpec &SS,
+                                   DeclarationNameInfo NameInfo,
+                                   SourceLocation EllipsisLoc,
+                                   const ParsedAttributesView &AttrList,
+                                   bool IsInstantiation, bool IsUsingIfExists);
+  NamedDecl *BuildUsingEnumDeclaration(Scope *S, AccessSpecifier AS,
+                                       SourceLocation UsingLoc,
+                                       SourceLocation EnumLoc,
+                                       SourceLocation NameLoc,
+                                       TypeSourceInfo *EnumType, EnumDecl *ED);
+  NamedDecl *BuildUsingPackDecl(NamedDecl *InstantiatedFrom,
+                                ArrayRef Expansions);
 
-  ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id,
-                                          SourceLocation IdLoc,
-                                          bool TypoCorrection = false);
-  FunctionDecl *CreateBuiltin(IdentifierInfo *II, QualType Type, unsigned ID,
-                              SourceLocation Loc);
-  NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID,
-                                 Scope *S, bool ForRedeclaration,
-                                 SourceLocation Loc);
-  NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
-                                      Scope *S);
-  void AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(
-      FunctionDecl *FD);
-  void AddKnownFunctionAttributes(FunctionDecl *FD);
+  bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
 
-  // More parsing and symbol table subroutines.
+  /// Given a derived-class using shadow declaration for a constructor and the
+  /// correspnding base class constructor, find or create the implicit
+  /// synthesized derived class constructor to use for this initialization.
+  CXXConstructorDecl *
+  findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *BaseCtor,
+                            ConstructorUsingShadowDecl *DerivedShadow);
 
-  void ProcessPragmaWeak(Scope *S, Decl *D);
-  // Decl attributes - this routine is the top level dispatcher.
-  void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD);
-  // Helper for delayed processing of attributes.
-  void ProcessDeclAttributeDelayed(Decl *D,
-                                   const ParsedAttributesView &AttrList);
+  Decl *ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS,
+                              SourceLocation UsingLoc,
+                              SourceLocation TypenameLoc, CXXScopeSpec &SS,
+                              UnqualifiedId &Name, SourceLocation EllipsisLoc,
+                              const ParsedAttributesView &AttrList);
+  Decl *ActOnUsingEnumDeclaration(Scope *CurScope, AccessSpecifier AS,
+                                  SourceLocation UsingLoc,
+                                  SourceLocation EnumLoc,
+                                  SourceLocation IdentLoc, IdentifierInfo &II,
+                                  CXXScopeSpec *SS = nullptr);
+  Decl *ActOnAliasDeclaration(Scope *CurScope, AccessSpecifier AS,
+                              MultiTemplateParamsArg TemplateParams,
+                              SourceLocation UsingLoc, UnqualifiedId &Name,
+                              const ParsedAttributesView &AttrList,
+                              TypeResult Type, Decl *DeclFromDeclSpec);
 
-  // Options for ProcessDeclAttributeList().
-  struct ProcessDeclAttributeOptions {
-    ProcessDeclAttributeOptions()
-        : IncludeCXX11Attributes(true), IgnoreTypeAttributes(false) {}
+  /// BuildCXXConstructExpr - Creates a complete call to a constructor,
+  /// including handling of its default argument expressions.
+  ///
+  /// \param ConstructKind - a CXXConstructExpr::ConstructionKind
+  ExprResult BuildCXXConstructExpr(
+      SourceLocation ConstructLoc, QualType DeclInitType, NamedDecl *FoundDecl,
+      CXXConstructorDecl *Constructor, MultiExprArg Exprs,
+      bool HadMultipleCandidates, bool IsListInitialization,
+      bool IsStdInitListInitialization, bool RequiresZeroInit,
+      CXXConstructionKind ConstructKind, SourceRange ParenRange);
 
-    ProcessDeclAttributeOptions WithIncludeCXX11Attributes(bool Val) {
-      ProcessDeclAttributeOptions Result = *this;
-      Result.IncludeCXX11Attributes = Val;
-      return Result;
-    }
+  /// Build a CXXConstructExpr whose constructor has already been resolved if
+  /// it denotes an inherited constructor.
+  ExprResult BuildCXXConstructExpr(
+      SourceLocation ConstructLoc, QualType DeclInitType,
+      CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs,
+      bool HadMultipleCandidates, bool IsListInitialization,
+      bool IsStdInitListInitialization, bool RequiresZeroInit,
+      CXXConstructionKind ConstructKind, SourceRange ParenRange);
 
-    ProcessDeclAttributeOptions WithIgnoreTypeAttributes(bool Val) {
-      ProcessDeclAttributeOptions Result = *this;
-      Result.IgnoreTypeAttributes = Val;
-      return Result;
-    }
+  // FIXME: Can we remove this and have the above BuildCXXConstructExpr check if
+  // the constructor can be elidable?
+  ExprResult BuildCXXConstructExpr(
+      SourceLocation ConstructLoc, QualType DeclInitType, NamedDecl *FoundDecl,
+      CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs,
+      bool HadMultipleCandidates, bool IsListInitialization,
+      bool IsStdInitListInitialization, bool RequiresZeroInit,
+      CXXConstructionKind ConstructKind, SourceRange ParenRange);
 
-    // Should C++11 attributes be processed?
-    bool IncludeCXX11Attributes;
+  ExprResult ConvertMemberDefaultInitExpression(FieldDecl *FD, Expr *InitExpr,
+                                                SourceLocation InitLoc);
 
-    // Should any type attributes encountered be ignored?
-    // If this option is false, a diagnostic will be emitted for any type
-    // attributes of a kind that does not "slide" from the declaration to
-    // the decl-specifier-seq.
-    bool IgnoreTypeAttributes;
-  };
+  /// FinalizeVarWithDestructor - Prepare for calling destructor on the
+  /// constructed variable.
+  void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
 
-  void ProcessDeclAttributeList(Scope *S, Decl *D,
-                                const ParsedAttributesView &AttrList,
-                                const ProcessDeclAttributeOptions &Options =
-                                    ProcessDeclAttributeOptions());
-  bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
-                                   const ParsedAttributesView &AttrList);
+  /// Helper class that collects exception specifications for
+  /// implicitly-declared special member functions.
+  class ImplicitExceptionSpecification {
+    // Pointer to allow copying
+    Sema *Self;
+    // We order exception specifications thus:
+    // noexcept is the most restrictive, but is only used in C++11.
+    // throw() comes next.
+    // Then a throw(collected exceptions)
+    // Finally no specification, which is expressed as noexcept(false).
+    // throw(...) is used instead if any called function uses it.
+    ExceptionSpecificationType ComputedEST;
+    llvm::SmallPtrSet ExceptionsSeen;
+    SmallVector Exceptions;
 
-  void checkUnusedDeclAttributes(Declarator &D);
+    void ClearExceptions() {
+      ExceptionsSeen.clear();
+      Exceptions.clear();
+    }
 
-  /// Handles semantic checking for features that are common to all attributes,
-  /// such as checking whether a parameter was properly specified, or the
-  /// correct number of arguments were passed, etc. Returns true if the
-  /// attribute has been diagnosed.
-  bool checkCommonAttributeFeatures(const Decl *D, const ParsedAttr &A,
-                                    bool SkipArgCountCheck = false);
-  bool checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A,
-                                    bool SkipArgCountCheck = false);
+  public:
+    explicit ImplicitExceptionSpecification(Sema &Self)
+        : Self(&Self), ComputedEST(EST_BasicNoexcept) {
+      if (!Self.getLangOpts().CPlusPlus11)
+        ComputedEST = EST_DynamicNone;
+    }
 
-  /// Map any API notes provided for this declaration to attributes on the
-  /// declaration.
-  ///
-  /// Triggered by declaration-attribute processing.
-  void ProcessAPINotes(Decl *D);
+    /// Get the computed exception specification type.
+    ExceptionSpecificationType getExceptionSpecType() const {
+      assert(!isComputedNoexcept(ComputedEST) &&
+             "noexcept(expr) should not be a possible result");
+      return ComputedEST;
+    }
 
-  /// Determine if type T is a valid subject for a nonnull and similar
-  /// attributes. By default, we look through references (the behavior used by
-  /// nonnull), but if the second parameter is true, then we treat a reference
-  /// type as valid.
-  bool isValidPointerAttrType(QualType T, bool RefOkay = false);
+    /// The number of exceptions in the exception specification.
+    unsigned size() const { return Exceptions.size(); }
 
-  bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value);
+    /// The set of exceptions in the exception specification.
+    const QualType *data() const { return Exceptions.data(); }
 
-  /// Check validaty of calling convention attribute \p attr. If \p FD
-  /// is not null pointer, use \p FD to determine the CUDA/HIP host/device
-  /// target. Otherwise, it is specified by \p CFT.
-  bool CheckCallingConvAttr(const ParsedAttr &attr, CallingConv &CC,
-                            const FunctionDecl *FD = nullptr,
-                            CUDAFunctionTarget CFT = CFT_InvalidTarget);
-  bool CheckAttrTarget(const ParsedAttr &CurrAttr);
-  bool CheckAttrNoArgs(const ParsedAttr &CurrAttr);
-  bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI,
-                                      const Expr *E, StringRef &Str,
-                                      SourceLocation *ArgLocation = nullptr);
-  bool checkStringLiteralArgumentAttr(const ParsedAttr &Attr, unsigned ArgNum,
-                                      StringRef &Str,
-                                      SourceLocation *ArgLocation = nullptr);
-  llvm::Error isValidSectionSpecifier(StringRef Str);
-  bool checkSectionName(SourceLocation LiteralLoc, StringRef Str);
-  bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str);
-  bool checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
-                              StringRef &Str, bool &isDefault);
-  bool checkTargetClonesAttrString(
-      SourceLocation LiteralLoc, StringRef Str, const StringLiteral *Literal,
-      Decl *D, bool &HasDefault, bool &HasCommas, bool &HasNotDefault,
-      SmallVectorImpl> &StringsBuffer);
-  bool checkMSInheritanceAttrOnDefinition(
-      CXXRecordDecl *RD, SourceRange Range, bool BestCase,
-      MSInheritanceModel SemanticSpelling);
+    /// Integrate another called method into the collected data.
+    void CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method);
 
-  void CheckAlignasUnderalignment(Decl *D);
+    /// Integrate an invoked expression into the collected data.
+    void CalledExpr(Expr *E) { CalledStmt(E); }
 
-  bool CheckNoInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
-                         const AttributeCommonInfo &A);
-  bool CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
-                             const AttributeCommonInfo &A);
+    /// Integrate an invoked statement into the collected data.
+    void CalledStmt(Stmt *S);
 
-  bool CheckCountedByAttr(Scope *Scope, const FieldDecl *FD);
+    /// Overwrite an EPI's exception specification with this
+    /// computed exception specification.
+    FunctionProtoType::ExceptionSpecInfo getExceptionSpec() const {
+      FunctionProtoType::ExceptionSpecInfo ESI;
+      ESI.Type = getExceptionSpecType();
+      if (ESI.Type == EST_Dynamic) {
+        ESI.Exceptions = Exceptions;
+      } else if (ESI.Type == EST_None) {
+        /// C++11 [except.spec]p14:
+        ///   The exception-specification is noexcept(false) if the set of
+        ///   potential exceptions of the special member function contains "any"
+        ESI.Type = EST_NoexceptFalse;
+        ESI.NoexceptExpr =
+            Self->ActOnCXXBoolLiteral(SourceLocation(), tok::kw_false).get();
+      }
+      return ESI;
+    }
+  };
 
-  /// Adjust the calling convention of a method to be the ABI default if it
-  /// wasn't specified explicitly.  This handles method types formed from
-  /// function type typedefs and typename template arguments.
-  void adjustMemberFunctionCC(QualType &T, bool HasThisPointer,
-                              bool IsCtorOrDtor, SourceLocation Loc);
+  /// Evaluate the implicit exception specification for a defaulted
+  /// special member function.
+  void EvaluateImplicitExceptionSpec(SourceLocation Loc, FunctionDecl *FD);
 
-  // Check if there is an explicit attribute, but only look through parens.
-  // The intent is to look for an attribute on the current declarator, but not
-  // one that came from a typedef.
-  bool hasExplicitCallingConv(QualType T);
+  /// Check the given exception-specification and update the
+  /// exception specification information with the results.
+  void checkExceptionSpecification(bool IsTopLevel,
+                                   ExceptionSpecificationType EST,
+                                   ArrayRef DynamicExceptions,
+                                   ArrayRef DynamicExceptionRanges,
+                                   Expr *NoexceptExpr,
+                                   SmallVectorImpl &Exceptions,
+                                   FunctionProtoType::ExceptionSpecInfo &ESI);
 
-  /// Get the outermost AttributedType node that sets a calling convention.
-  /// Valid types should not have multiple attributes with different CCs.
-  const AttributedType *getCallingConvAttributedType(QualType T) const;
+  /// Add an exception-specification to the given member function
+  /// (or member function template). The exception-specification was parsed
+  /// after the method itself was declared.
+  void actOnDelayedExceptionSpecification(
+      Decl *Method, ExceptionSpecificationType EST,
+      SourceRange SpecificationRange, ArrayRef DynamicExceptions,
+      ArrayRef DynamicExceptionRanges, Expr *NoexceptExpr);
 
-  /// Check whether a nullability type specifier can be added to the given
-  /// type through some means not written in source (e.g. API notes).
-  ///
-  /// \param Type The type to which the nullability specifier will be
-  /// added. On success, this type will be updated appropriately.
+  /// Kinds of C++ special members.
+  enum CXXSpecialMember {
+    CXXDefaultConstructor,
+    CXXCopyConstructor,
+    CXXMoveConstructor,
+    CXXCopyAssignment,
+    CXXMoveAssignment,
+    CXXDestructor,
+    CXXInvalid
+  };
+
+  class InheritedConstructorInfo;
+
+  /// Determine if a special member function should have a deleted
+  /// definition when it is defaulted.
+  bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
+                                 InheritedConstructorInfo *ICI = nullptr,
+                                 bool Diagnose = false);
+
+  /// Produce notes explaining why a defaulted function was defined as deleted.
+  void DiagnoseDeletedDefaultedFunction(FunctionDecl *FD);
+
+  /// Declare the implicit default constructor for the given class.
   ///
-  /// \param Nullability The nullability specifier to add.
+  /// \param ClassDecl The class declaration into which the implicit
+  /// default constructor will be added.
   ///
-  /// \param DiagLoc The location to use for diagnostics.
+  /// \returns The implicitly-declared default constructor.
+  CXXConstructorDecl *
+  DeclareImplicitDefaultConstructor(CXXRecordDecl *ClassDecl);
+
+  /// DefineImplicitDefaultConstructor - Checks for feasibility of
+  /// defining this constructor as the default constructor.
+  void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
+                                        CXXConstructorDecl *Constructor);
+
+  /// Declare the implicit destructor for the given class.
   ///
-  /// \param AllowArrayTypes Whether to accept nullability specifiers on an
-  /// array type (e.g., because it will decay to a pointer).
+  /// \param ClassDecl The class declaration into which the implicit
+  /// destructor will be added.
   ///
-  /// \param OverrideExisting Whether to override an existing, locally-specified
-  /// nullability specifier rather than complaining about the conflict.
+  /// \returns The implicitly-declared destructor.
+  CXXDestructorDecl *DeclareImplicitDestructor(CXXRecordDecl *ClassDecl);
+
+  /// DefineImplicitDestructor - Checks for feasibility of
+  /// defining this destructor as the default destructor.
+  void DefineImplicitDestructor(SourceLocation CurrentLocation,
+                                CXXDestructorDecl *Destructor);
+
+  /// Build an exception spec for destructors that don't have one.
   ///
-  /// \returns true if nullability cannot be applied, false otherwise.
-  bool CheckImplicitNullabilityTypeSpecifier(QualType &Type,
-                                             NullabilityKind Nullability,
-                                             SourceLocation DiagLoc,
-                                             bool AllowArrayTypes,
-                                             bool OverrideExisting);
+  /// C++11 says that user-defined destructors with no exception spec get one
+  /// that looks as if the destructor was implicitly declared.
+  void AdjustDestructorExceptionSpec(CXXDestructorDecl *Destructor);
 
-  /// Process the attributes before creating an attributed statement. Returns
-  /// the semantic attributes that have been processed.
-  void ProcessStmtAttributes(Stmt *Stmt, const ParsedAttributes &InAttrs,
-                             SmallVectorImpl &OutAttrs);
+  /// Define the specified inheriting constructor.
+  void DefineInheritingConstructor(SourceLocation UseLoc,
+                                   CXXConstructorDecl *Constructor);
 
-  void WarnConflictingTypedMethods(ObjCMethodDecl *Method,
-                                   ObjCMethodDecl *MethodDecl,
-                                   bool IsProtocolMethodDecl);
+  /// Declare the implicit copy constructor for the given class.
+  ///
+  /// \param ClassDecl The class declaration into which the implicit
+  /// copy constructor will be added.
+  ///
+  /// \returns The implicitly-declared copy constructor.
+  CXXConstructorDecl *DeclareImplicitCopyConstructor(CXXRecordDecl *ClassDecl);
 
-  void CheckConflictingOverridingMethod(ObjCMethodDecl *Method,
-                                   ObjCMethodDecl *Overridden,
-                                   bool IsProtocolMethodDecl);
+  /// DefineImplicitCopyConstructor - Checks for feasibility of
+  /// defining this constructor as the copy constructor.
+  void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
+                                     CXXConstructorDecl *Constructor);
 
-  /// WarnExactTypedMethods - This routine issues a warning if method
-  /// implementation declaration matches exactly that of its declaration.
-  void WarnExactTypedMethods(ObjCMethodDecl *Method,
-                             ObjCMethodDecl *MethodDecl,
-                             bool IsProtocolMethodDecl);
+  /// Declare the implicit move constructor for the given class.
+  ///
+  /// \param ClassDecl The Class declaration into which the implicit
+  /// move constructor will be added.
+  ///
+  /// \returns The implicitly-declared move constructor, or NULL if it wasn't
+  /// declared.
+  CXXConstructorDecl *DeclareImplicitMoveConstructor(CXXRecordDecl *ClassDecl);
 
-  typedef llvm::SmallPtrSet SelectorSet;
+  /// DefineImplicitMoveConstructor - Checks for feasibility of
+  /// defining this constructor as the move constructor.
+  void DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
+                                     CXXConstructorDecl *Constructor);
 
-  /// CheckImplementationIvars - This routine checks if the instance variables
-  /// listed in the implelementation match those listed in the interface.
-  void CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
-                                ObjCIvarDecl **Fields, unsigned nIvars,
-                                SourceLocation Loc);
+  /// Declare the implicit copy assignment operator for the given class.
+  ///
+  /// \param ClassDecl The class declaration into which the implicit
+  /// copy assignment operator will be added.
+  ///
+  /// \returns The implicitly-declared copy assignment operator.
+  CXXMethodDecl *DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl);
 
-  /// ImplMethodsVsClassMethods - This is main routine to warn if any method
-  /// remains unimplemented in the class or category \@implementation.
-  void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
-                                 ObjCContainerDecl* IDecl,
-                                 bool IncompleteImpl = false);
+  /// Defines an implicitly-declared copy assignment operator.
+  void DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
+                                    CXXMethodDecl *MethodDecl);
 
-  /// DiagnoseUnimplementedProperties - This routine warns on those properties
-  /// which must be implemented by this implementation.
-  void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
-                                       ObjCContainerDecl *CDecl,
-                                       bool SynthesizeProperties);
+  /// Declare the implicit move assignment operator for the given class.
+  ///
+  /// \param ClassDecl The Class declaration into which the implicit
+  /// move assignment operator will be added.
+  ///
+  /// \returns The implicitly-declared move assignment operator, or NULL if it
+  /// wasn't declared.
+  CXXMethodDecl *DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl);
 
-  /// Diagnose any null-resettable synthesized setters.
-  void diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl);
+  /// Defines an implicitly-declared move assignment operator.
+  void DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
+                                    CXXMethodDecl *MethodDecl);
 
-  /// DefaultSynthesizeProperties - This routine default synthesizes all
-  /// properties which must be synthesized in the class's \@implementation.
-  void DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl,
-                                   ObjCInterfaceDecl *IDecl,
-                                   SourceLocation AtEnd);
-  void DefaultSynthesizeProperties(Scope *S, Decl *D, SourceLocation AtEnd);
+  /// Check a completed declaration of an implicit special member.
+  void CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD);
 
-  /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
-  /// an ivar synthesized for 'Method' and 'Method' is a property accessor
-  /// declared in class 'IFace'.
-  bool IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
-                                      ObjCMethodDecl *Method, ObjCIvarDecl *IV);
+  /// Determine whether the given function is an implicitly-deleted
+  /// special member function.
+  bool isImplicitlyDeleted(FunctionDecl *FD);
 
-  /// DiagnoseUnusedBackingIvarInAccessor - Issue an 'unused' warning if ivar which
-  /// backs the property is not used in the property's accessor.
-  void DiagnoseUnusedBackingIvarInAccessor(Scope *S,
-                                           const ObjCImplementationDecl *ImplD);
+  /// Check whether 'this' shows up in the type of a static member
+  /// function after the (naturally empty) cv-qualifier-seq would be.
+  ///
+  /// \returns true if an error occurred.
+  bool checkThisInStaticMemberFunctionType(CXXMethodDecl *Method);
 
-  /// GetIvarBackingPropertyAccessor - If method is a property setter/getter and
-  /// it property has a backing ivar, returns this ivar; otherwise, returns NULL.
-  /// It also returns ivar's property on success.
-  ObjCIvarDecl *GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,
-                                               const ObjCPropertyDecl *&PDecl) const;
+  /// Whether this' shows up in the exception specification of a static
+  /// member function.
+  bool checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method);
 
-  /// Called by ActOnProperty to handle \@property declarations in
-  /// class extensions.
-  ObjCPropertyDecl *HandlePropertyInClassExtension(Scope *S,
-                      SourceLocation AtLoc,
-                      SourceLocation LParenLoc,
-                      FieldDeclarator &FD,
-                      Selector GetterSel,
-                      SourceLocation GetterNameLoc,
-                      Selector SetterSel,
-                      SourceLocation SetterNameLoc,
-                      const bool isReadWrite,
-                      unsigned &Attributes,
-                      const unsigned AttributesAsWritten,
-                      QualType T,
-                      TypeSourceInfo *TSI,
-                      tok::ObjCKeywordKind MethodImplKind);
+  /// Check whether 'this' shows up in the attributes of the given
+  /// static member function.
+  ///
+  /// \returns true if an error occurred.
+  bool checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method);
 
-  /// Called by ActOnProperty and HandlePropertyInClassExtension to
-  /// handle creating the ObjcPropertyDecl for a category or \@interface.
-  ObjCPropertyDecl *CreatePropertyDecl(Scope *S,
-                                       ObjCContainerDecl *CDecl,
-                                       SourceLocation AtLoc,
-                                       SourceLocation LParenLoc,
-                                       FieldDeclarator &FD,
-                                       Selector GetterSel,
-                                       SourceLocation GetterNameLoc,
-                                       Selector SetterSel,
-                                       SourceLocation SetterNameLoc,
-                                       const bool isReadWrite,
-                                       const unsigned Attributes,
-                                       const unsigned AttributesAsWritten,
-                                       QualType T,
-                                       TypeSourceInfo *TSI,
-                                       tok::ObjCKeywordKind MethodImplKind,
-                                       DeclContext *lexicalDC = nullptr);
+  bool CheckImmediateEscalatingFunctionDefinition(
+      FunctionDecl *FD, const sema::FunctionScopeInfo *FSI);
 
-  /// AtomicPropertySetterGetterRules - This routine enforces the rule (via
-  /// warning) when atomic property has one but not the other user-declared
-  /// setter or getter.
-  void AtomicPropertySetterGetterRules(ObjCImplDecl* IMPDecl,
-                                       ObjCInterfaceDecl* IDecl);
+  void DiagnoseImmediateEscalatingReason(FunctionDecl *FD);
 
-  void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D);
+  bool CompleteConstructorCall(CXXConstructorDecl *Constructor,
+                               QualType DeclInitType, MultiExprArg ArgsPtr,
+                               SourceLocation Loc,
+                               SmallVectorImpl &ConvertedArgs,
+                               bool AllowExplicit = false,
+                               bool IsListInitialization = false);
 
-  void DiagnoseMissingDesignatedInitOverrides(
-                                          const ObjCImplementationDecl *ImplD,
-                                          const ObjCInterfaceDecl *IFD);
+  /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
+  /// initializer for the declaration 'Dcl'.
+  /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
+  /// static data member of class X, names should be looked up in the scope of
+  /// class X.
+  void ActOnCXXEnterDeclInitializer(Scope *S, Decl *Dcl);
 
-  void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID);
+  /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
+  /// initializer for the declaration 'Dcl'.
+  void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl);
 
-  enum MethodMatchStrategy {
-    MMS_loose,
-    MMS_strict
-  };
+  /// Define the "body" of the conversion from a lambda object to a
+  /// function pointer.
+  ///
+  /// This routine doesn't actually define a sensible body; rather, it fills
+  /// in the initialization expression needed to copy the lambda object into
+  /// the block, and IR generation actually generates the real body of the
+  /// block pointer conversion.
+  void
+  DefineImplicitLambdaToFunctionPointerConversion(SourceLocation CurrentLoc,
+                                                  CXXConversionDecl *Conv);
 
-  /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns
-  /// true, or false, accordingly.
-  bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method,
-                                  const ObjCMethodDecl *PrevMethod,
-                                  MethodMatchStrategy strategy = MMS_strict);
+  /// Define the "body" of the conversion from a lambda object to a
+  /// block pointer.
+  ///
+  /// This routine doesn't actually define a sensible body; rather, it fills
+  /// in the initialization expression needed to copy the lambda object into
+  /// the block, and IR generation actually generates the real body of the
+  /// block pointer conversion.
+  void DefineImplicitLambdaToBlockPointerConversion(SourceLocation CurrentLoc,
+                                                    CXXConversionDecl *Conv);
 
-  /// MatchAllMethodDeclarations - Check methods declaraed in interface or
-  /// or protocol against those declared in their implementations.
-  void MatchAllMethodDeclarations(const SelectorSet &InsMap,
-                                  const SelectorSet &ClsMap,
-                                  SelectorSet &InsMapSeen,
-                                  SelectorSet &ClsMapSeen,
-                                  ObjCImplDecl* IMPDecl,
-                                  ObjCContainerDecl* IDecl,
-                                  bool &IncompleteImpl,
-                                  bool ImmediateClass,
-                                  bool WarnCategoryMethodImpl=false);
+  Decl *ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc,
+                                       Expr *LangStr, SourceLocation LBraceLoc);
+  Decl *ActOnFinishLinkageSpecification(Scope *S, Decl *LinkageSpec,
+                                        SourceLocation RBraceLoc);
 
-  /// CheckCategoryVsClassMethodMatches - Checks that methods implemented in
-  /// category matches with those implemented in its primary class and
-  /// warns each time an exact match is found.
-  void CheckCategoryVsClassMethodMatches(ObjCCategoryImplDecl *CatIMP);
+  //===--------------------------------------------------------------------===//
+  // C++ Classes
+  //
+  CXXRecordDecl *getCurrentClass(Scope *S, const CXXScopeSpec *SS);
+  bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
+                          const CXXScopeSpec *SS = nullptr);
+  bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS);
 
-  /// Add the given method to the list of globally-known methods.
-  void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method);
+  bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc,
+                            SourceLocation ColonLoc,
+                            const ParsedAttributesView &Attrs);
 
-  /// Returns default addr space for method qualifiers.
-  LangAS getDefaultCXXMethodAddrSpace() const;
+  NamedDecl *
+  ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
+                           MultiTemplateParamsArg TemplateParameterLists,
+                           Expr *BitfieldWidth, const VirtSpecifiers &VS,
+                           InClassInitStyle InitStyle);
 
-private:
-  /// AddMethodToGlobalPool - Add an instance or factory method to the global
-  /// pool. See descriptoin of AddInstanceMethodToGlobalPool.
-  void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance);
+  void ActOnStartCXXInClassMemberInitializer();
+  void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl,
+                                              SourceLocation EqualLoc,
+                                              Expr *Init);
 
-  /// LookupMethodInGlobalPool - Returns the instance or factory method and
-  /// optionally warns if there are multiple signatures.
-  ObjCMethodDecl *LookupMethodInGlobalPool(Selector Sel, SourceRange R,
-                                           bool receiverIdOrClass,
-                                           bool instance);
+  MemInitResult
+  ActOnMemInitializer(Decl *ConstructorD, Scope *S, CXXScopeSpec &SS,
+                      IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy,
+                      const DeclSpec &DS, SourceLocation IdLoc,
+                      SourceLocation LParenLoc, ArrayRef Args,
+                      SourceLocation RParenLoc, SourceLocation EllipsisLoc);
 
-public:
-  /// - Returns instance or factory methods in global method pool for
-  /// given selector. It checks the desired kind first, if none is found, and
-  /// parameter checkTheOther is set, it then checks the other kind. If no such
-  /// method or only one method is found, function returns false; otherwise, it
-  /// returns true.
-  bool
-  CollectMultipleMethodsInGlobalPool(Selector Sel,
-                                     SmallVectorImpl& Methods,
-                                     bool InstanceFirst, bool CheckTheOther,
-                                     const ObjCObjectType *TypeBound = nullptr);
+  MemInitResult ActOnMemInitializer(Decl *ConstructorD, Scope *S,
+                                    CXXScopeSpec &SS,
+                                    IdentifierInfo *MemberOrBase,
+                                    ParsedType TemplateTypeTy,
+                                    const DeclSpec &DS, SourceLocation IdLoc,
+                                    Expr *InitList, SourceLocation EllipsisLoc);
 
-  bool
-  AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod,
-                                 SourceRange R, bool receiverIdOrClass,
-                                 SmallVectorImpl& Methods);
+  MemInitResult BuildMemInitializer(Decl *ConstructorD, Scope *S,
+                                    CXXScopeSpec &SS,
+                                    IdentifierInfo *MemberOrBase,
+                                    ParsedType TemplateTypeTy,
+                                    const DeclSpec &DS, SourceLocation IdLoc,
+                                    Expr *Init, SourceLocation EllipsisLoc);
 
-  void
-  DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl &Methods,
-                                     Selector Sel, SourceRange R,
-                                     bool receiverIdOrClass);
+  MemInitResult BuildMemberInitializer(ValueDecl *Member, Expr *Init,
+                                       SourceLocation IdLoc);
 
-private:
-  /// - Returns a selector which best matches given argument list or
-  /// nullptr if none could be found
-  ObjCMethodDecl *SelectBestMethod(Selector Sel, MultiExprArg Args,
-                                   bool IsInstance,
-                                   SmallVectorImpl& Methods);
+  MemInitResult BuildBaseInitializer(QualType BaseType,
+                                     TypeSourceInfo *BaseTInfo, Expr *Init,
+                                     CXXRecordDecl *ClassDecl,
+                                     SourceLocation EllipsisLoc);
 
+  MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
+                                           CXXRecordDecl *ClassDecl);
 
-  /// Record the typo correction failure and return an empty correction.
-  TypoCorrection FailedCorrection(IdentifierInfo *Typo, SourceLocation TypoLoc,
-                                  bool RecordFailure = true) {
-    if (RecordFailure)
-      TypoCorrectionFailures[Typo].insert(TypoLoc);
-    return TypoCorrection();
-  }
+  bool SetDelegatingInitializer(CXXConstructorDecl *Constructor,
+                                CXXCtorInitializer *Initializer);
 
-public:
-  /// AddInstanceMethodToGlobalPool - All instance methods in a translation
-  /// unit are added to a global pool. This allows us to efficiently associate
-  /// a selector with a method declaraation for purposes of typechecking
-  /// messages sent to "id" (where the class of the object is unknown).
-  void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
-    AddMethodToGlobalPool(Method, impl, /*instance*/true);
-  }
+  bool SetCtorInitializers(
+      CXXConstructorDecl *Constructor, bool AnyErrors,
+      ArrayRef Initializers = std::nullopt);
 
-  /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
-  void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
-    AddMethodToGlobalPool(Method, impl, /*instance*/false);
-  }
+  void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation);
 
-  /// AddAnyMethodToGlobalPool - Add any method, instance or factory to global
-  /// pool.
-  void AddAnyMethodToGlobalPool(Decl *D);
+  /// MarkBaseAndMemberDestructorsReferenced - Given a record decl,
+  /// mark all the non-trivial destructors of its members and bases as
+  /// referenced.
+  void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
+                                              CXXRecordDecl *Record);
 
-  /// LookupInstanceMethodInGlobalPool - Returns the method and warns if
-  /// there are multiple signatures.
-  ObjCMethodDecl *LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R,
-                                                   bool receiverIdOrClass=false) {
-    return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
-                                    /*instance*/true);
-  }
+  /// Mark destructors of virtual bases of this class referenced. In the Itanium
+  /// C++ ABI, this is done when emitting a destructor for any non-abstract
+  /// class. In the Microsoft C++ ABI, this is done any time a class's
+  /// destructor is referenced.
+  void MarkVirtualBaseDestructorsReferenced(
+      SourceLocation Location, CXXRecordDecl *ClassDecl,
+      llvm::SmallPtrSetImpl *DirectVirtualBases = nullptr);
 
-  /// LookupFactoryMethodInGlobalPool - Returns the method and warns if
-  /// there are multiple signatures.
-  ObjCMethodDecl *LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R,
-                                                  bool receiverIdOrClass=false) {
-    return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
-                                    /*instance*/false);
-  }
+  /// Do semantic checks to allow the complete destructor variant to be emitted
+  /// when the destructor is defined in another translation unit. In the Itanium
+  /// C++ ABI, destructor variants are emitted together. In the MS C++ ABI, they
+  /// can be emitted in separate TUs. To emit the complete variant, run a subset
+  /// of the checks performed when emitting a regular destructor.
+  void CheckCompleteDestructorVariant(SourceLocation CurrentLocation,
+                                      CXXDestructorDecl *Dtor);
 
-  const ObjCMethodDecl *SelectorsForTypoCorrection(Selector Sel,
-                              QualType ObjectType=QualType());
-  /// LookupImplementedMethodInGlobalPool - Returns the method which has an
-  /// implementation.
-  ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
+  /// The list of classes whose vtables have been used within
+  /// this translation unit, and the source locations at which the
+  /// first use occurred.
+  typedef std::pair VTableUse;
 
-  /// CollectIvarsToConstructOrDestruct - Collect those ivars which require
-  /// initialization.
-  void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
-                                  SmallVectorImpl &Ivars);
+  /// The list of vtables that are required but have not yet been
+  /// materialized.
+  SmallVector VTableUses;
 
-  //===--------------------------------------------------------------------===//
-  // Statement Parsing Callbacks: SemaStmt.cpp.
-public:
-  class FullExprArg {
-  public:
-    FullExprArg() : E(nullptr) { }
-    FullExprArg(Sema &actions) : E(nullptr) { }
+  /// The set of classes whose vtables have been used within
+  /// this translation unit, and a bit that will be true if the vtable is
+  /// required to be emitted (otherwise, it should be emitted only if needed
+  /// by code generation).
+  llvm::DenseMap VTablesUsed;
 
-    ExprResult release() {
-      return E;
-    }
+  /// Load any externally-stored vtable uses.
+  void LoadExternalVTableUses();
 
-    Expr *get() const { return E; }
+  /// Note that the vtable for the given class was used at the
+  /// given location.
+  void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
+                      bool DefinitionRequired = false);
 
-    Expr *operator->() {
-      return E;
-    }
+  /// Mark the exception specifications of all virtual member functions
+  /// in the given class as needed.
+  void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
+                                             const CXXRecordDecl *RD);
 
-  private:
-    // FIXME: No need to make the entire Sema class a friend when it's just
-    // Sema::MakeFullExpr that needs access to the constructor below.
-    friend class Sema;
+  /// MarkVirtualMembersReferenced - Will mark all members of the given
+  /// CXXRecordDecl referenced.
+  void MarkVirtualMembersReferenced(SourceLocation Loc, const CXXRecordDecl *RD,
+                                    bool ConstexprOnly = false);
 
-    explicit FullExprArg(Expr *expr) : E(expr) {}
+  /// Define all of the vtables that have been used in this
+  /// translation unit and reference any virtual members used by those
+  /// vtables.
+  ///
+  /// \returns true if any work was done, false otherwise.
+  bool DefineUsedVTables();
 
-    Expr *E;
-  };
+  void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
 
-  FullExprArg MakeFullExpr(Expr *Arg) {
-    return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation());
-  }
-  FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) {
-    return FullExprArg(
-        ActOnFinishFullExpr(Arg, CC, /*DiscardedValue*/ false).get());
-  }
-  FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) {
-    ExprResult FE =
-        ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(),
-                            /*DiscardedValue*/ true);
-    return FullExprArg(FE.get());
-  }
-
-  StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true);
-  StmtResult ActOnExprStmtError();
+  void ActOnMemInitializers(Decl *ConstructorDecl, SourceLocation ColonLoc,
+                            ArrayRef MemInits,
+                            bool AnyErrors);
 
-  StmtResult ActOnNullStmt(SourceLocation SemiLoc,
-                           bool HasLeadingEmptyMacro = false);
+  /// Check class-level dllimport/dllexport attribute. The caller must
+  /// ensure that referenceDLLExportedClassMethods is called some point later
+  /// when all outer classes of Class are complete.
+  void checkClassLevelDLLAttribute(CXXRecordDecl *Class);
+  void checkClassLevelCodeSegAttribute(CXXRecordDecl *Class);
 
-  void ActOnStartOfCompoundStmt(bool IsStmtExpr);
-  void ActOnAfterCompoundStatementLeadingPragmas();
-  void ActOnFinishOfCompoundStmt();
-  StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
-                               ArrayRef Elts, bool isStmtExpr);
+  void referenceDLLExportedClassMethods();
 
-  /// A RAII object to enter scope of a compound statement.
-  class CompoundScopeRAII {
-  public:
-    CompoundScopeRAII(Sema &S, bool IsStmtExpr = false) : S(S) {
-      S.ActOnStartOfCompoundStmt(IsStmtExpr);
-    }
+  void propagateDLLAttrToBaseClassTemplate(
+      CXXRecordDecl *Class, Attr *ClassAttr,
+      ClassTemplateSpecializationDecl *BaseTemplateSpec,
+      SourceLocation BaseLoc);
 
-    ~CompoundScopeRAII() {
-      S.ActOnFinishOfCompoundStmt();
-    }
+  void CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record);
 
-  private:
-    Sema &S;
-  };
+  /// Check that the C++ class annoated with "trivial_abi" satisfies all the
+  /// conditions that are needed for the attribute to have an effect.
+  void checkIllFormedTrivialABIStruct(CXXRecordDecl &RD);
 
-  /// An RAII helper that pops function a function scope on exit.
-  struct FunctionScopeRAII {
-    Sema &S;
-    bool Active;
-    FunctionScopeRAII(Sema &S) : S(S), Active(true) {}
-    ~FunctionScopeRAII() {
-      if (Active)
-        S.PopFunctionScopeInfo();
-    }
-    void disable() { Active = false; }
-  };
+  void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc,
+                                         Decl *TagDecl, SourceLocation LBrac,
+                                         SourceLocation RBrac,
+                                         const ParsedAttributesView &AttrList);
+  void ActOnFinishCXXMemberDecls();
+  void ActOnFinishCXXNonNestedClass();
 
-  StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
-                                   SourceLocation StartLoc,
-                                   SourceLocation EndLoc);
-  void ActOnForEachDeclStmt(DeclGroupPtrTy Decl);
-  StmtResult ActOnForEachLValueExpr(Expr *E);
-  ExprResult ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val);
-  StmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHS,
-                           SourceLocation DotDotDotLoc, ExprResult RHS,
-                           SourceLocation ColonLoc);
-  void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt);
+  void ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param);
+  unsigned ActOnReenterTemplateScope(Decl *Template,
+                                     llvm::function_ref EnterScope);
+  void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record);
+  void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
+  void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param);
+  void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record);
+  void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
+  void ActOnFinishDelayedMemberInitializers(Decl *Record);
 
-  StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
-                                      SourceLocation ColonLoc,
-                                      Stmt *SubStmt, Scope *CurScope);
-  StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
-                            SourceLocation ColonLoc, Stmt *SubStmt);
+  bool EvaluateStaticAssertMessageAsString(Expr *Message, std::string &Result,
+                                           ASTContext &Ctx,
+                                           bool ErrorOnInvalidMessage);
+  Decl *ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc,
+                                     Expr *AssertExpr, Expr *AssertMessageExpr,
+                                     SourceLocation RParenLoc);
+  Decl *BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
+                                     Expr *AssertExpr, Expr *AssertMessageExpr,
+                                     SourceLocation RParenLoc, bool Failed);
+  void DiagnoseStaticAssertDetails(const Expr *E);
 
-  StmtResult BuildAttributedStmt(SourceLocation AttrsLoc,
-                                 ArrayRef Attrs, Stmt *SubStmt);
-  StmtResult ActOnAttributedStmt(const ParsedAttributes &AttrList,
-                                 Stmt *SubStmt);
+  Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
+                            MultiTemplateParamsArg TemplateParams);
+  NamedDecl *ActOnFriendFunctionDecl(Scope *S, Declarator &D,
+                                     MultiTemplateParamsArg TemplateParams);
 
-  class ConditionResult;
+  QualType CheckConstructorDeclarator(Declarator &D, QualType R,
+                                      StorageClass &SC);
+  void CheckConstructor(CXXConstructorDecl *Constructor);
+  QualType CheckDestructorDeclarator(Declarator &D, QualType R,
+                                     StorageClass &SC);
+  bool CheckDestructor(CXXDestructorDecl *Destructor);
+  void CheckConversionDeclarator(Declarator &D, QualType &R, StorageClass &SC);
+  Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion);
+  bool CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
+                                     StorageClass &SC);
 
-  StmtResult ActOnIfStmt(SourceLocation IfLoc, IfStatementKind StatementKind,
-                         SourceLocation LParenLoc, Stmt *InitStmt,
-                         ConditionResult Cond, SourceLocation RParenLoc,
-                         Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal);
-  StmtResult BuildIfStmt(SourceLocation IfLoc, IfStatementKind StatementKind,
-                         SourceLocation LParenLoc, Stmt *InitStmt,
-                         ConditionResult Cond, SourceLocation RParenLoc,
-                         Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal);
-  StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
-                                    SourceLocation LParenLoc, Stmt *InitStmt,
-                                    ConditionResult Cond,
-                                    SourceLocation RParenLoc);
-  StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
-                                           Stmt *Switch, Stmt *Body);
-  StmtResult ActOnWhileStmt(SourceLocation WhileLoc, SourceLocation LParenLoc,
-                            ConditionResult Cond, SourceLocation RParenLoc,
-                            Stmt *Body);
-  StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
-                         SourceLocation WhileLoc, SourceLocation CondLParen,
-                         Expr *Cond, SourceLocation CondRParen);
+  void CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *MD);
 
-  StmtResult ActOnForStmt(SourceLocation ForLoc,
-                          SourceLocation LParenLoc,
-                          Stmt *First,
-                          ConditionResult Second,
-                          FullExprArg Third,
-                          SourceLocation RParenLoc,
-                          Stmt *Body);
-  ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc,
-                                           Expr *collection);
-  StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
-                                        Stmt *First, Expr *collection,
-                                        SourceLocation RParenLoc);
-  StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body);
+  bool CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
+                                             CXXSpecialMember CSM,
+                                             SourceLocation DefaultLoc);
+  void CheckDelayedMemberExceptionSpecs();
 
-  enum BuildForRangeKind {
-    /// Initial building of a for-range statement.
-    BFRK_Build,
-    /// Instantiation or recovery rebuild of a for-range statement. Don't
-    /// attempt any typo-correction.
-    BFRK_Rebuild,
-    /// Determining whether a for-range statement could be built. Avoid any
-    /// unnecessary or irreversible actions.
-    BFRK_Check
+  /// Kinds of defaulted comparison operator functions.
+  enum class DefaultedComparisonKind : unsigned char {
+    /// This is not a defaultable comparison operator.
+    None,
+    /// This is an operator== that should be implemented as a series of
+    /// subobject comparisons.
+    Equal,
+    /// This is an operator<=> that should be implemented as a series of
+    /// subobject comparisons.
+    ThreeWay,
+    /// This is an operator!= that should be implemented as a rewrite in terms
+    /// of a == comparison.
+    NotEqual,
+    /// This is an <, <=, >, or >= that should be implemented as a rewrite in
+    /// terms of a <=> comparison.
+    Relational,
   };
 
-  StmtResult ActOnCXXForRangeStmt(
-      Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc,
-      Stmt *InitStmt, Stmt *LoopVar, SourceLocation ColonLoc, Expr *Collection,
-      SourceLocation RParenLoc, BuildForRangeKind Kind,
-      ArrayRef LifetimeExtendTemps = {});
-  StmtResult BuildCXXForRangeStmt(
-      SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt,
-      SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *Begin, Stmt *End,
-      Expr *Cond, Expr *Inc, Stmt *LoopVarDecl, SourceLocation RParenLoc,
-      BuildForRangeKind Kind,
-      ArrayRef LifetimeExtendTemps = {});
-  StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body);
-
-  StmtResult ActOnGotoStmt(SourceLocation GotoLoc,
-                           SourceLocation LabelLoc,
-                           LabelDecl *TheDecl);
-  StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
-                                   SourceLocation StarLoc,
-                                   Expr *DestExp);
-  StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope);
-  StmtResult ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope);
+  bool CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *MD,
+                                          DefaultedComparisonKind DCK);
+  void DeclareImplicitEqualityComparison(CXXRecordDecl *RD,
+                                         FunctionDecl *Spaceship);
+  void DefineDefaultedComparison(SourceLocation Loc, FunctionDecl *FD,
+                                 DefaultedComparisonKind DCK);
 
-  void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
-                                CapturedRegionKind Kind, unsigned NumParams);
-  typedef std::pair CapturedParamNameType;
-  void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
-                                CapturedRegionKind Kind,
-                                ArrayRef Params,
-                                unsigned OpenMPCaptureLevel = 0);
-  StmtResult ActOnCapturedRegionEnd(Stmt *S);
-  void ActOnCapturedRegionError();
-  RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD,
-                                           SourceLocation Loc,
-                                           unsigned NumParams);
+  void CheckExplicitObjectMemberFunction(Declarator &D, DeclarationName Name,
+                                         QualType R, bool IsLambda,
+                                         DeclContext *DC = nullptr);
+  void CheckExplicitObjectMemberFunction(DeclContext *DC, Declarator &D,
+                                         DeclarationName Name, QualType R);
+  void CheckExplicitObjectLambda(Declarator &D);
 
-  struct NamedReturnInfo {
-    const VarDecl *Candidate;
+  //===--------------------------------------------------------------------===//
+  // C++ Derived Classes
+  //
 
-    enum Status : uint8_t { None, MoveEligible, MoveEligibleAndCopyElidable };
-    Status S;
+  /// ActOnBaseSpecifier - Parsed a base specifier
+  CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class,
+                                       SourceRange SpecifierRange, bool Virtual,
+                                       AccessSpecifier Access,
+                                       TypeSourceInfo *TInfo,
+                                       SourceLocation EllipsisLoc);
 
-    bool isMoveEligible() const { return S != None; };
-    bool isCopyElidable() const { return S == MoveEligibleAndCopyElidable; }
-  };
-  enum class SimplerImplicitMoveMode { ForceOff, Normal, ForceOn };
-  NamedReturnInfo getNamedReturnInfo(
-      Expr *&E, SimplerImplicitMoveMode Mode = SimplerImplicitMoveMode::Normal);
-  NamedReturnInfo getNamedReturnInfo(const VarDecl *VD);
-  const VarDecl *getCopyElisionCandidate(NamedReturnInfo &Info,
-                                         QualType ReturnType);
+  BaseResult ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
+                                const ParsedAttributesView &Attrs, bool Virtual,
+                                AccessSpecifier Access, ParsedType basetype,
+                                SourceLocation BaseLoc,
+                                SourceLocation EllipsisLoc);
 
-  ExprResult
-  PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
-                                  const NamedReturnInfo &NRInfo, Expr *Value,
-                                  bool SupressSimplerImplicitMoves = false);
+  bool AttachBaseSpecifiers(CXXRecordDecl *Class,
+                            MutableArrayRef Bases);
+  void ActOnBaseSpecifiers(Decl *ClassDecl,
+                           MutableArrayRef Bases);
 
-  StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
-                             Scope *CurScope);
-  StmtResult BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
-                             bool AllowRecovery = false);
-  StmtResult ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
-                                     NamedReturnInfo &NRInfo,
-                                     bool SupressSimplerImplicitMoves);
+  bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base);
+  bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
+                     CXXBasePaths &Paths);
 
-  StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
-                             bool IsVolatile, unsigned NumOutputs,
-                             unsigned NumInputs, IdentifierInfo **Names,
-                             MultiExprArg Constraints, MultiExprArg Exprs,
-                             Expr *AsmString, MultiExprArg Clobbers,
-                             unsigned NumLabels,
-                             SourceLocation RParenLoc);
+  // FIXME: I don't like this name.
+  void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath);
 
-  void FillInlineAsmIdentifierInfo(Expr *Res,
-                                   llvm::InlineAsmIdentifierInfo &Info);
-  ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS,
-                                       SourceLocation TemplateKWLoc,
-                                       UnqualifiedId &Id,
-                                       bool IsUnevaluatedContext);
-  bool LookupInlineAsmField(StringRef Base, StringRef Member,
-                            unsigned &Offset, SourceLocation AsmLoc);
-  ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member,
-                                         SourceLocation AsmLoc);
-  StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
-                            ArrayRef AsmToks,
-                            StringRef AsmString,
-                            unsigned NumOutputs, unsigned NumInputs,
-                            ArrayRef Constraints,
-                            ArrayRef Clobbers,
-                            ArrayRef Exprs,
-                            SourceLocation EndLoc);
-  LabelDecl *GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
-                                   SourceLocation Location,
-                                   bool AlwaysCreate);
-
-  VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
-                                  SourceLocation StartLoc,
-                                  SourceLocation IdLoc, IdentifierInfo *Id,
-                                  bool Invalid = false);
-
-  Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D);
+  bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+                                    SourceLocation Loc, SourceRange Range,
+                                    CXXCastPath *BasePath = nullptr,
+                                    bool IgnoreAccess = false);
+  bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
+                                    unsigned InaccessibleBaseID,
+                                    unsigned AmbiguousBaseConvID,
+                                    SourceLocation Loc, SourceRange Range,
+                                    DeclarationName Name, CXXCastPath *BasePath,
+                                    bool IgnoreAccess = false);
 
-  StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen,
-                                  Decl *Parm, Stmt *Body);
+  std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths);
 
-  StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body);
+  bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
+                                         const CXXMethodDecl *Old);
 
-  StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
-                                MultiStmtArg Catch, Stmt *Finally);
+  /// CheckOverridingFunctionReturnType - Checks whether the return types are
+  /// covariant, according to C++ [class.virtual]p5.
+  bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
+                                         const CXXMethodDecl *Old);
 
-  StmtResult BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw);
-  StmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,
-                                  Scope *CurScope);
-  ExprResult ActOnObjCAtSynchronizedOperand(SourceLocation atLoc,
-                                            Expr *operand);
-  StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
-                                         Expr *SynchExpr,
-                                         Stmt *SynchBody);
+  // Check that the overriding method has no explicit object parameter.
+  bool CheckExplicitObjectOverride(CXXMethodDecl *New,
+                                   const CXXMethodDecl *Old);
 
-  StmtResult ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body);
+  bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
 
-  VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo,
-                                     SourceLocation StartLoc,
-                                     SourceLocation IdLoc,
-                                     IdentifierInfo *Id);
+  /// CheckOverrideControl - Check C++11 override control semantics.
+  void CheckOverrideControl(NamedDecl *D);
 
-  Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
+  /// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was
+  /// not used in the declaration of an overriding method.
+  void DiagnoseAbsenceOfOverrideControl(NamedDecl *D, bool Inconsistent);
 
-  StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
-                                Decl *ExDecl, Stmt *HandlerBlock);
-  StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
-                              ArrayRef Handlers);
+  /// CheckForFunctionMarkedFinal - Checks whether a virtual member function
+  /// overrides a virtual member function marked 'final', according to
+  /// C++11 [class.virtual]p4.
+  bool CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
+                                              const CXXMethodDecl *Old);
 
-  StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ?
-                              SourceLocation TryLoc, Stmt *TryBlock,
-                              Stmt *Handler);
-  StmtResult ActOnSEHExceptBlock(SourceLocation Loc,
-                                 Expr *FilterExpr,
-                                 Stmt *Block);
-  void ActOnStartSEHFinallyBlock();
-  void ActOnAbortSEHFinallyBlock();
-  StmtResult ActOnFinishSEHFinallyBlock(SourceLocation Loc, Stmt *Block);
-  StmtResult ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope);
+  enum AbstractDiagSelID {
+    AbstractNone = -1,
+    AbstractReturnType,
+    AbstractParamType,
+    AbstractVariableType,
+    AbstractFieldType,
+    AbstractIvarType,
+    AbstractSynthesizedIvarType,
+    AbstractArrayType
+  };
 
-  void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
+  struct TypeDiagnoser;
 
-  bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const;
+  bool isAbstractType(SourceLocation Loc, QualType T);
+  bool RequireNonAbstractType(SourceLocation Loc, QualType T,
+                              TypeDiagnoser &Diagnoser);
+  template 
+  bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID,
+                              const Ts &...Args) {
+    BoundTypeDiagnoser Diagnoser(DiagID, Args...);
+    return RequireNonAbstractType(Loc, T, Diagnoser);
+  }
 
-  /// If it's a file scoped decl that must warn if not used, keep track
-  /// of it.
-  void MarkUnusedFileScopedDecl(const DeclaratorDecl *D);
+  void DiagnoseAbstractType(const CXXRecordDecl *RD);
 
-  typedef llvm::function_ref
-      DiagReceiverTy;
+  //===--------------------------------------------------------------------===//
+  // C++ Overloaded Operators [C++ 13.5]
+  //
 
-  /// DiagnoseUnusedExprResult - If the statement passed in is an expression
-  /// whose result is unused, warn.
-  void DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID);
-  void DiagnoseUnusedNestedTypedefs(const RecordDecl *D);
-  void DiagnoseUnusedNestedTypedefs(const RecordDecl *D,
-                                    DiagReceiverTy DiagReceiver);
-  void DiagnoseUnusedDecl(const NamedDecl *ND);
-  void DiagnoseUnusedDecl(const NamedDecl *ND, DiagReceiverTy DiagReceiver);
+  bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl);
 
-  /// If VD is set but not otherwise used, diagnose, for a parameter or a
-  /// variable.
-  void DiagnoseUnusedButSetDecl(const VarDecl *VD, DiagReceiverTy DiagReceiver);
+  bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl);
 
-  /// Emit \p DiagID if statement located on \p StmtLoc has a suspicious null
-  /// statement as a \p Body, and it is located on the same line.
-  ///
-  /// This helps prevent bugs due to typos, such as:
-  ///     if (condition);
-  ///       do_stuff();
-  void DiagnoseEmptyStmtBody(SourceLocation StmtLoc,
-                             const Stmt *Body,
-                             unsigned DiagID);
+  /// ActOnExplicitBoolSpecifier - Build an ExplicitSpecifier from an expression
+  /// found in an explicit(bool) specifier.
+  ExplicitSpecifier ActOnExplicitBoolSpecifier(Expr *E);
 
-  /// Warn if a for/while loop statement \p S, which is followed by
-  /// \p PossibleBody, has a suspicious null statement as a body.
-  void DiagnoseEmptyLoopBody(const Stmt *S,
-                             const Stmt *PossibleBody);
+  /// tryResolveExplicitSpecifier - Attempt to resolve the explict specifier.
+  /// Returns true if the explicit specifier is now resolved.
+  bool tryResolveExplicitSpecifier(ExplicitSpecifier &ExplicitSpec);
 
-  /// Warn if a value is moved to itself.
-  void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
-                        SourceLocation OpLoc);
+  DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D);
 
-  /// Returns a field in a CXXRecordDecl that has the same name as the decl \p
-  /// SelfAssigned when inside a CXXMethodDecl.
-  const FieldDecl *
-  getSelfAssignmentClassMemberCandidate(const ValueDecl *SelfAssigned);
+  // Emitting members of dllexported classes is delayed until the class
+  // (including field initializers) is fully parsed.
+  SmallVector DelayedDllExportClasses;
+  SmallVector DelayedDllExportMemberFunctions;
 
-  /// Warn if we're implicitly casting from a _Nullable pointer type to a
-  /// _Nonnull one.
-  void diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType,
-                                           SourceLocation Loc);
+  void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old);
+  bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S);
 
-  /// Warn when implicitly casting 0 to nullptr.
-  void diagnoseZeroToNullptrConversion(CastKind Kind, const Expr *E);
+  /// Helpers for dealing with blocks and functions.
+  void CheckCXXDefaultArguments(FunctionDecl *FD);
+  void CheckExtraCXXDefaultArguments(Declarator &D);
 
-  ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) {
-    return DelayedDiagnostics.push(pool);
+  CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD) {
+    return getDefaultedFunctionKind(MD).asSpecialMember();
   }
-  void PopParsingDeclaration(ParsingDeclState state, Decl *decl);
 
-  typedef ProcessingContextState ParsingClassState;
-  ParsingClassState PushParsingClass() {
-    ParsingClassDepth++;
-    return DelayedDiagnostics.pushUndelayed();
-  }
-  void PopParsingClass(ParsingClassState state) {
-    ParsingClassDepth--;
-    DelayedDiagnostics.popUndelayed(state);
-  }
+  VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo,
+                                     SourceLocation StartLoc,
+                                     SourceLocation IdLoc, IdentifierInfo *Id);
 
-  void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
+  Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
 
-  void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef Locs,
-                                  const ObjCInterfaceDecl *UnknownObjCClass,
-                                  bool ObjCPropertyAccess,
-                                  bool AvoidPartialAvailabilityChecks = false,
-                                  ObjCInterfaceDecl *ClassReceiver = nullptr);
+  void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
 
-  bool makeUnavailableInSystemHeader(SourceLocation loc,
-                                     UnavailableAttr::ImplicitReason reason);
+  DeclResult ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
+                                     unsigned TagSpec, SourceLocation TagLoc,
+                                     CXXScopeSpec &SS, IdentifierInfo *Name,
+                                     SourceLocation NameLoc,
+                                     const ParsedAttributesView &Attr,
+                                     MultiTemplateParamsArg TempParamLists);
 
-  /// Issue any -Wunguarded-availability warnings in \c FD
-  void DiagnoseUnguardedAvailabilityViolations(Decl *FD);
+  MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD,
+                                   SourceLocation DeclStart, Declarator &D,
+                                   Expr *BitfieldWidth,
+                                   InClassInitStyle InitStyle,
+                                   AccessSpecifier AS,
+                                   const ParsedAttr &MSPropertyAttr);
 
-  void handleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
+  void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM);
 
-  //===--------------------------------------------------------------------===//
-  // Expression Parsing Callbacks: SemaExpr.cpp.
+  enum TrivialABIHandling {
+    /// The triviality of a method unaffected by "trivial_abi".
+    TAH_IgnoreTrivialABI,
 
-  bool CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid);
-  // A version of DiagnoseUseOfDecl that should be used if overload resolution
-  // has been used to find this declaration, which means we don't have to bother
-  // checking the trailing requires clause.
-  bool DiagnoseUseOfOverloadedDecl(NamedDecl *D, SourceLocation Loc) {
-    return DiagnoseUseOfDecl(
-        D, Loc, /*UnknownObjCClass=*/nullptr, /*ObjCPropertyAccess=*/false,
-        /*AvoidPartialAvailabilityChecks=*/false, /*ClassReceiver=*/nullptr,
-        /*SkipTrailingRequiresClause=*/true);
-  }
+    /// The triviality of a method affected by "trivial_abi".
+    TAH_ConsiderTrivialABI
+  };
 
-  bool DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs,
-                         const ObjCInterfaceDecl *UnknownObjCClass = nullptr,
-                         bool ObjCPropertyAccess = false,
-                         bool AvoidPartialAvailabilityChecks = false,
-                         ObjCInterfaceDecl *ClassReciever = nullptr,
-                         bool SkipTrailingRequiresClause = false);
-  void NoteDeletedFunction(FunctionDecl *FD);
-  void NoteDeletedInheritingConstructor(CXXConstructorDecl *CD);
-  bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD,
-                                        ObjCMethodDecl *Getter,
-                                        SourceLocation Loc);
-  void DiagnoseSentinelCalls(const NamedDecl *D, SourceLocation Loc,
-                             ArrayRef Args);
+  bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
+                              TrivialABIHandling TAH = TAH_IgnoreTrivialABI,
+                              bool Diagnose = false);
 
-  void PushExpressionEvaluationContext(
-      ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = nullptr,
-      ExpressionEvaluationContextRecord::ExpressionKind Type =
-          ExpressionEvaluationContextRecord::EK_Other);
-  enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl };
-  void PushExpressionEvaluationContext(
-      ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t,
-      ExpressionEvaluationContextRecord::ExpressionKind Type =
-          ExpressionEvaluationContextRecord::EK_Other);
-  void PopExpressionEvaluationContext();
+  /// For a defaulted function, the kind of defaulted function that it is.
+  class DefaultedFunctionKind {
+    unsigned SpecialMember : 8;
+    unsigned Comparison : 8;
 
-  void DiscardCleanupsInEvaluationContext();
+  public:
+    DefaultedFunctionKind()
+        : SpecialMember(CXXInvalid),
+          Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {}
+    DefaultedFunctionKind(CXXSpecialMember CSM)
+        : SpecialMember(CSM),
+          Comparison(llvm::to_underlying(DefaultedComparisonKind::None)) {}
+    DefaultedFunctionKind(DefaultedComparisonKind Comp)
+        : SpecialMember(CXXInvalid), Comparison(llvm::to_underlying(Comp)) {}
 
-  ExprResult TransformToPotentiallyEvaluated(Expr *E);
-  TypeSourceInfo *TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo);
-  ExprResult HandleExprEvaluationContextForTypeof(Expr *E);
+    bool isSpecialMember() const { return SpecialMember != CXXInvalid; }
+    bool isComparison() const {
+      return static_cast(Comparison) !=
+             DefaultedComparisonKind::None;
+    }
 
-  ExprResult CheckUnevaluatedOperand(Expr *E);
-  void CheckUnusedVolatileAssignment(Expr *E);
+    explicit operator bool() const {
+      return isSpecialMember() || isComparison();
+    }
 
-  ExprResult ActOnConstantExpression(ExprResult Res);
-
-  // Functions for marking a declaration referenced.  These functions also
-  // contain the relevant logic for marking if a reference to a function or
-  // variable is an odr-use (in the C++11 sense).  There are separate variants
-  // for expressions referring to a decl; these exist because odr-use marking
-  // needs to be delayed for some constant variables when we build one of the
-  // named expressions.
-  //
-  // MightBeOdrUse indicates whether the use could possibly be an odr-use, and
-  // should usually be true. This only needs to be set to false if the lack of
-  // odr-use cannot be determined from the current context (for instance,
-  // because the name denotes a virtual function and was written without an
-  // explicit nested-name-specifier).
-  void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool MightBeOdrUse);
-  void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
-                              bool MightBeOdrUse = true);
-  void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var);
-  void MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base = nullptr);
-  void MarkMemberReferenced(MemberExpr *E);
-  void MarkFunctionParmPackReferenced(FunctionParmPackExpr *E);
-  void MarkCaptureUsedInEnclosingContext(ValueDecl *Capture, SourceLocation Loc,
-                                         unsigned CapturingScopeIndex);
-
-  ExprResult CheckLValueToRValueConversionOperand(Expr *E);
-  void CleanupVarDeclMarking();
+    CXXSpecialMember asSpecialMember() const {
+      return static_cast(SpecialMember);
+    }
+    DefaultedComparisonKind asComparison() const {
+      return static_cast(Comparison);
+    }
 
-  enum TryCaptureKind {
-    TryCapture_Implicit, TryCapture_ExplicitByVal, TryCapture_ExplicitByRef
+    /// Get the index of this function kind for use in diagnostics.
+    unsigned getDiagnosticIndex() const {
+      static_assert(CXXInvalid > CXXDestructor,
+                    "invalid should have highest index");
+      static_assert((unsigned)DefaultedComparisonKind::None == 0,
+                    "none should be equal to zero");
+      return SpecialMember + Comparison;
+    }
   };
 
-  /// Try to capture the given variable.
-  ///
-  /// \param Var The variable to capture.
-  ///
-  /// \param Loc The location at which the capture occurs.
-  ///
-  /// \param Kind The kind of capture, which may be implicit (for either a
-  /// block or a lambda), or explicit by-value or by-reference (for a lambda).
-  ///
-  /// \param EllipsisLoc The location of the ellipsis, if one is provided in
-  /// an explicit lambda capture.
-  ///
-  /// \param BuildAndDiagnose Whether we are actually supposed to add the
-  /// captures or diagnose errors. If false, this routine merely check whether
-  /// the capture can occur without performing the capture itself or complaining
-  /// if the variable cannot be captured.
-  ///
-  /// \param CaptureType Will be set to the type of the field used to capture
-  /// this variable in the innermost block or lambda. Only valid when the
-  /// variable can be captured.
-  ///
-  /// \param DeclRefType Will be set to the type of a reference to the capture
-  /// from within the current scope. Only valid when the variable can be
-  /// captured.
-  ///
-  /// \param FunctionScopeIndexToStopAt If non-null, it points to the index
-  /// of the FunctionScopeInfo stack beyond which we do not attempt to capture.
-  /// This is useful when enclosing lambdas must speculatively capture
-  /// variables that may or may not be used in certain specializations of
-  /// a nested generic lambda.
-  ///
-  /// \returns true if an error occurred (i.e., the variable cannot be
-  /// captured) and false if the capture succeeded.
-  bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc,
-                          TryCaptureKind Kind, SourceLocation EllipsisLoc,
-                          bool BuildAndDiagnose, QualType &CaptureType,
-                          QualType &DeclRefType,
-                          const unsigned *const FunctionScopeIndexToStopAt);
+  DefaultedFunctionKind getDefaultedFunctionKind(const FunctionDecl *FD);
 
-  /// Try to capture the given variable.
-  bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc,
-                          TryCaptureKind Kind = TryCapture_Implicit,
-                          SourceLocation EllipsisLoc = SourceLocation());
+  /// Handle a C++11 empty-declaration and attribute-declaration.
+  Decl *ActOnEmptyDeclaration(Scope *S, const ParsedAttributesView &AttrList,
+                              SourceLocation SemiLoc);
 
-  /// Checks if the variable must be captured.
-  bool NeedToCaptureVariable(ValueDecl *Var, SourceLocation Loc);
+  enum class CheckConstexprKind {
+    /// Diagnose issues that are non-constant or that are extensions.
+    Diagnose,
+    /// Identify whether this function satisfies the formal rules for constexpr
+    /// functions in the current lanugage mode (with no extensions).
+    CheckValid
+  };
 
-  /// Given a variable, determine the type that a reference to that
-  /// variable will have in the given scope.
-  QualType getCapturedDeclRefType(ValueDecl *Var, SourceLocation Loc);
+  bool CheckConstexprFunctionDefinition(const FunctionDecl *FD,
+                                        CheckConstexprKind Kind);
 
-  /// Mark all of the declarations referenced within a particular AST node as
-  /// referenced. Used when template instantiation instantiates a non-dependent
-  /// type -- entities referenced by the type are now referenced.
-  void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
-  void MarkDeclarationsReferencedInExpr(
-      Expr *E, bool SkipLocalVariables = false,
-      ArrayRef StopAt = std::nullopt);
+  void DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD);
+  void
+  FindHiddenVirtualMethods(CXXMethodDecl *MD,
+                           SmallVectorImpl &OverloadedMethods);
+  void
+  NoteHiddenVirtualMethods(CXXMethodDecl *MD,
+                           SmallVectorImpl &OverloadedMethods);
+  void ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc,
+                                 Expr *defarg);
+  void ActOnParamUnparsedDefaultArgument(Decl *param, SourceLocation EqualLoc,
+                                         SourceLocation ArgLoc);
+  void ActOnParamDefaultArgumentError(Decl *param, SourceLocation EqualLoc,
+                                      Expr *DefaultArg);
+  ExprResult ConvertParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
+                                         SourceLocation EqualLoc);
+  void SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
+                               SourceLocation EqualLoc);
 
-  /// Try to recover by turning the given expression into a
-  /// call.  Returns true if recovery was attempted or an error was
-  /// emitted; this may also leave the ExprResult invalid.
-  bool tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
-                            bool ForceComplain = false,
-                            bool (*IsPlausibleResult)(QualType) = nullptr);
+  void ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc);
+  void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
+  void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc);
 
-  /// Figure out if an expression could be turned into a call.
-  bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
-                     UnresolvedSetImpl &NonTemplateOverloads);
+  void SetFunctionBodyKind(Decl *D, SourceLocation Loc, FnBodyKind BodyKind);
+  void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D);
+  ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr);
+  ExprResult ActOnRequiresClause(ExprResult ConstraintExpr);
 
-  /// Try to convert an expression \p E to type \p Ty. Returns the result of the
-  /// conversion.
-  ExprResult tryConvertExprToType(Expr *E, QualType Ty);
+  NamedDecl *
+  ActOnDecompositionDeclarator(Scope *S, Declarator &D,
+                               MultiTemplateParamsArg TemplateParamLists);
+  void DiagPlaceholderVariableDefinition(SourceLocation Loc);
+  bool DiagRedefinedPlaceholderFieldDecl(SourceLocation Loc,
+                                         RecordDecl *ClassDecl,
+                                         const IdentifierInfo *Name);
 
-  /// Conditionally issue a diagnostic based on the statements's reachability
-  /// analysis.
-  ///
-  /// \param Stmts If Stmts is non-empty, delay reporting the diagnostic until
-  /// the function body is parsed, and then do a basic reachability analysis to
-  /// determine if the statement is reachable. If it is unreachable, the
-  /// diagnostic will not be emitted.
-  bool DiagIfReachable(SourceLocation Loc, ArrayRef Stmts,
-                       const PartialDiagnostic &PD);
+  void CheckCompleteDecompositionDeclaration(DecompositionDecl *DD);
 
-  /// Conditionally issue a diagnostic based on the current
-  /// evaluation context.
-  ///
-  /// \param Statement If Statement is non-null, delay reporting the
-  /// diagnostic until the function body is parsed, and then do a basic
-  /// reachability analysis to determine if the statement is reachable.
-  /// If it is unreachable, the diagnostic will not be emitted.
-  bool DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement,
-                           const PartialDiagnostic &PD);
-  /// Similar, but diagnostic is only produced if all the specified statements
-  /// are reachable.
-  bool DiagRuntimeBehavior(SourceLocation Loc, ArrayRef Stmts,
-                           const PartialDiagnostic &PD);
+  /// Stack containing information needed when in C++2a an 'auto' is encountered
+  /// in a function declaration parameter type specifier in order to invent a
+  /// corresponding template parameter in the enclosing abbreviated function
+  /// template. This information is also present in LambdaScopeInfo, stored in
+  /// the FunctionScopes stack.
+  SmallVector InventedParameterInfos;
 
-  // Primary Expressions.
-  SourceRange getExprRange(Expr *E) const;
+  /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
+  std::unique_ptr FieldCollector;
 
-  ExprResult ActOnIdExpression(
-      Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
-      UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand,
-      CorrectionCandidateCallback *CCC = nullptr,
-      bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr);
+  typedef llvm::SmallSetVector NamedDeclSetType;
+  /// Set containing all declared private fields that are not used.
+  NamedDeclSetType UnusedPrivateFields;
 
-  void DecomposeUnqualifiedId(const UnqualifiedId &Id,
-                              TemplateArgumentListInfo &Buffer,
-                              DeclarationNameInfo &NameInfo,
-                              const TemplateArgumentListInfo *&TemplateArgs);
+  typedef llvm::SmallPtrSet RecordDeclSetTy;
 
-  bool DiagnoseDependentMemberLookup(const LookupResult &R);
+  /// PureVirtualClassDiagSet - a set of class declarations which we have
+  /// emitted a list of pure virtual functions. Used to prevent emitting the
+  /// same list more than once.
+  std::unique_ptr PureVirtualClassDiagSet;
 
-  bool
-  DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
-                      CorrectionCandidateCallback &CCC,
-                      TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
-                      ArrayRef Args = std::nullopt,
-                      DeclContext *LookupCtx = nullptr,
-                      TypoExpr **Out = nullptr);
+  typedef LazyVector
+      DelegatingCtorDeclsType;
 
-  DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,
-                                    IdentifierInfo *II);
-  ExprResult BuildIvarRefExpr(Scope *S, SourceLocation Loc, ObjCIvarDecl *IV);
+  /// All the delegating constructors seen so far in the file, used for
+  /// cycle detection at the end of the TU.
+  DelegatingCtorDeclsType DelegatingCtorDecls;
 
-  ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S,
-                                IdentifierInfo *II,
-                                bool AllowBuiltinCreation=false);
+  /// The C++ "std" namespace, where the standard library resides.
+  LazyDeclPtr StdNamespace;
 
-  ExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS,
-                                        SourceLocation TemplateKWLoc,
-                                        const DeclarationNameInfo &NameInfo,
-                                        bool isAddressOfOperand,
-                                const TemplateArgumentListInfo *TemplateArgs);
+  /// The C++ "std::initializer_list" template, which is defined in
+  /// \.
+  ClassTemplateDecl *StdInitializerList;
 
-  /// If \p D cannot be odr-used in the current expression evaluation context,
-  /// return a reason explaining why. Otherwise, return NOUR_None.
-  NonOdrUseReason getNonOdrUseReasonInCurrentContext(ValueDecl *D);
+  // Contains the locations of the beginning of unparsed default
+  // argument locations.
+  llvm::DenseMap UnparsedDefaultArgLocs;
 
-  DeclRefExpr *BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
-                                SourceLocation Loc,
-                                const CXXScopeSpec *SS = nullptr);
-  DeclRefExpr *
-  BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
-                   const DeclarationNameInfo &NameInfo,
-                   const CXXScopeSpec *SS = nullptr,
-                   NamedDecl *FoundD = nullptr,
-                   SourceLocation TemplateKWLoc = SourceLocation(),
-                   const TemplateArgumentListInfo *TemplateArgs = nullptr);
-  DeclRefExpr *
-  BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
-                   const DeclarationNameInfo &NameInfo,
-                   NestedNameSpecifierLoc NNS,
-                   NamedDecl *FoundD = nullptr,
-                   SourceLocation TemplateKWLoc = SourceLocation(),
-                   const TemplateArgumentListInfo *TemplateArgs = nullptr);
+  /// UndefinedInternals - all the used, undefined objects which require a
+  /// definition in this translation unit.
+  llvm::MapVector UndefinedButUsed;
 
-  ExprResult
-  BuildAnonymousStructUnionMemberReference(
-      const CXXScopeSpec &SS,
-      SourceLocation nameLoc,
-      IndirectFieldDecl *indirectField,
-      DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_none),
-      Expr *baseObjectExpr = nullptr,
-      SourceLocation opLoc = SourceLocation());
+  typedef llvm::PointerIntPair
+      SpecialMemberDecl;
 
-  ExprResult BuildPossibleImplicitMemberExpr(
-      const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
-      const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
-      UnresolvedLookupExpr *AsULE = nullptr);
-  ExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS,
-                                     SourceLocation TemplateKWLoc,
-                                     LookupResult &R,
-                                const TemplateArgumentListInfo *TemplateArgs,
-                                     bool IsDefiniteInstance,
-                                     const Scope *S);
-  bool UseArgumentDependentLookup(const CXXScopeSpec &SS,
-                                  const LookupResult &R,
-                                  bool HasTrailingLParen);
+  /// The C++ special members which we are currently in the process of
+  /// declaring. If this process recursively triggers the declaration of the
+  /// same special member, we should act as if it is not yet declared.
+  llvm::SmallPtrSet SpecialMembersBeingDeclared;
 
-  ExprResult
-  BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
-                                    const DeclarationNameInfo &NameInfo,
-                                    bool IsAddressOfOperand, const Scope *S,
-                                    TypeSourceInfo **RecoveryTSI = nullptr);
+  void NoteDeletedInheritingConstructor(CXXConstructorDecl *CD);
 
-  ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
-                                       SourceLocation TemplateKWLoc,
-                                const DeclarationNameInfo &NameInfo,
-                                const TemplateArgumentListInfo *TemplateArgs);
-
-  ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS,
-                                      LookupResult &R,
-                                      bool NeedsADL,
-                                      bool AcceptInvalidDecl = false);
-  ExprResult BuildDeclarationNameExpr(
-      const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
-      NamedDecl *FoundD = nullptr,
-      const TemplateArgumentListInfo *TemplateArgs = nullptr,
-      bool AcceptInvalidDecl = false);
+  void ActOnDefaultCtorInitializers(Decl *CDtorDecl);
 
-  ExprResult BuildLiteralOperatorCall(LookupResult &R,
-                      DeclarationNameInfo &SuffixInfo,
-                      ArrayRef Args,
-                      SourceLocation LitEndLoc,
-                      TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
+  typedef ProcessingContextState ParsingClassState;
+  ParsingClassState PushParsingClass() {
+    ParsingClassDepth++;
+    return DelayedDiagnostics.pushUndelayed();
+  }
+  void PopParsingClass(ParsingClassState state) {
+    ParsingClassDepth--;
+    DelayedDiagnostics.popUndelayed(state);
+  }
 
-  // ExpandFunctionLocalPredefinedMacros - Returns a new vector of Tokens,
-  // where Tokens representing function local predefined macros (such as
-  // __FUNCTION__) are replaced (expanded) with string-literal Tokens.
-  std::vector ExpandFunctionLocalPredefinedMacros(ArrayRef Toks);
+private:
+  void setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem,
+                                      QualType ResultTy,
+                                      ArrayRef Args);
 
-  ExprResult BuildPredefinedExpr(SourceLocation Loc, PredefinedIdentKind IK);
-  ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
-  ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);
+  // A cache representing if we've fully checked the various comparison category
+  // types stored in ASTContext. The bit-index corresponds to the integer value
+  // of a ComparisonCategoryType enumerator.
+  llvm::SmallBitVector FullyCheckedComparisonCategories;
 
-  ExprResult BuildSYCLUniqueStableNameExpr(SourceLocation OpLoc,
-                                           SourceLocation LParen,
-                                           SourceLocation RParen,
-                                           TypeSourceInfo *TSI);
-  ExprResult ActOnSYCLUniqueStableNameExpr(SourceLocation OpLoc,
-                                           SourceLocation LParen,
-                                           SourceLocation RParen,
-                                           ParsedType ParsedTy);
+  ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl,
+                                         CXXScopeSpec &SS,
+                                         ParsedType TemplateTypeTy,
+                                         IdentifierInfo *MemberOrBase);
 
-  bool CheckLoopHintExpr(Expr *E, SourceLocation Loc);
+  /// Check if there is a field shadowing.
+  void CheckShadowInheritedFields(const SourceLocation &Loc,
+                                  DeclarationName FieldName,
+                                  const CXXRecordDecl *RD,
+                                  bool DeclIsField = true);
 
-  ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = nullptr);
-  ExprResult ActOnCharacterConstant(const Token &Tok,
-                                    Scope *UDLScope = nullptr);
-  ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E);
-  ExprResult ActOnParenListExpr(SourceLocation L,
-                                SourceLocation R,
-                                MultiExprArg Val);
+  ///@}
 
-  /// ActOnStringLiteral - The specified tokens were lexed as pasted string
-  /// fragments (e.g. "foo" "bar" L"baz").
-  ExprResult ActOnStringLiteral(ArrayRef StringToks,
-                                Scope *UDLScope = nullptr);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  ExprResult ActOnUnevaluatedStringLiteral(ArrayRef StringToks);
+  /// \name C++ Exception Specifications
+  /// Implementations are in SemaExceptionSpec.cpp
+  ///@{
 
-  /// ControllingExprOrType is either an opaque pointer coming out of a
-  /// ParsedType or an Expr *. FIXME: it'd be better to split this interface
-  /// into two so we don't take a void *, but that's awkward because one of
-  /// the operands is either a ParsedType or an Expr *, which doesn't lend
-  /// itself to generic code very well.
-  ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc,
-                                       SourceLocation DefaultLoc,
-                                       SourceLocation RParenLoc,
-                                       bool PredicateIsExpr,
-                                       void *ControllingExprOrType,
-                                       ArrayRef ArgTypes,
-                                       ArrayRef ArgExprs);
-  /// ControllingExprOrType is either a TypeSourceInfo * or an Expr *. FIXME:
-  /// it'd be better to split this interface into two so we don't take a
-  /// void *, but see the FIXME on ActOnGenericSelectionExpr as to why that
-  /// isn't a trivial change.
-  ExprResult CreateGenericSelectionExpr(SourceLocation KeyLoc,
-                                        SourceLocation DefaultLoc,
-                                        SourceLocation RParenLoc,
-                                        bool PredicateIsExpr,
-                                        void *ControllingExprOrType,
-                                        ArrayRef Types,
-                                        ArrayRef Exprs);
+public:
+  /// All the overriding functions seen during a class definition
+  /// that had their exception spec checks delayed, plus the overridden
+  /// function.
+  SmallVector, 2>
+      DelayedOverridingExceptionSpecChecks;
 
-  // Binary/Unary Operators.  'Tok' is the token for the operator.
-  ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
-                                  Expr *InputExpr, bool IsAfterAmp = false);
-  ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc,
-                          Expr *Input, bool IsAfterAmp = false);
-  ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op,
-                          Expr *Input, bool IsAfterAmp = false);
+  /// All the function redeclarations seen during a class definition that had
+  /// their exception spec checks delayed, plus the prior declaration they
+  /// should be checked against. Except during error recovery, the new decl
+  /// should always be a friend declaration, as that's the only valid way to
+  /// redeclare a special member before its class is complete.
+  SmallVector, 2>
+      DelayedEquivalentExceptionSpecChecks;
 
-  bool isQualifiedMemberAccess(Expr *E);
-  bool CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc,
-                                             const Expr *Op,
-                                             const CXXMethodDecl *MD);
+  /// Determine if we're in a case where we need to (incorrectly) eagerly
+  /// parse an exception specification to work around a libstdc++ bug.
+  bool isLibstdcxxEagerExceptionSpecHack(const Declarator &D);
 
-  QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
+  /// Check the given noexcept-specifier, convert its expression, and compute
+  /// the appropriate ExceptionSpecificationType.
+  ExprResult ActOnNoexceptSpec(Expr *NoexceptExpr,
+                               ExceptionSpecificationType &EST);
 
-  bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N);
+  CanThrowResult canThrow(const Stmt *E);
+  /// Determine whether the callee of a particular function call can throw.
+  /// E, D and Loc are all optional.
+  static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D,
+                                       SourceLocation Loc = SourceLocation());
+  const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc,
+                                                const FunctionProtoType *FPT);
+  void UpdateExceptionSpec(FunctionDecl *FD,
+                           const FunctionProtoType::ExceptionSpecInfo &ESI);
+  bool CheckSpecifiedExceptionType(QualType &T, SourceRange Range);
+  bool CheckDistantExceptionSpec(QualType T);
+  bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New);
+  bool CheckEquivalentExceptionSpec(const FunctionProtoType *Old,
+                                    SourceLocation OldLoc,
+                                    const FunctionProtoType *New,
+                                    SourceLocation NewLoc);
+  bool CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
+                                    const PartialDiagnostic &NoteID,
+                                    const FunctionProtoType *Old,
+                                    SourceLocation OldLoc,
+                                    const FunctionProtoType *New,
+                                    SourceLocation NewLoc);
+  bool handlerCanCatch(QualType HandlerType, QualType ExceptionType);
+  bool CheckExceptionSpecSubset(
+      const PartialDiagnostic &DiagID, const PartialDiagnostic &NestedDiagID,
+      const PartialDiagnostic &NoteID, const PartialDiagnostic &NoThrowDiagID,
+      const FunctionProtoType *Superset, bool SkipSupersetFirstParameter,
+      SourceLocation SuperLoc, const FunctionProtoType *Subset,
+      bool SkipSubsetFirstParameter, SourceLocation SubLoc);
+  bool CheckParamExceptionSpec(
+      const PartialDiagnostic &NestedDiagID, const PartialDiagnostic &NoteID,
+      const FunctionProtoType *Target, bool SkipTargetFirstParameter,
+      SourceLocation TargetLoc, const FunctionProtoType *Source,
+      bool SkipSourceFirstParameter, SourceLocation SourceLoc);
 
-  bool ActOnAlignasTypeArgument(StringRef KWName, ParsedType Ty,
-                                SourceLocation OpLoc, SourceRange R);
-  bool CheckAlignasTypeArgument(StringRef KWName, TypeSourceInfo *TInfo,
-                                SourceLocation OpLoc, SourceRange R);
+  bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
 
-  ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
-                                            SourceLocation OpLoc,
-                                            UnaryExprOrTypeTrait ExprKind,
-                                            SourceRange R);
-  ExprResult CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
-                                            UnaryExprOrTypeTrait ExprKind);
-  ExprResult
-    ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
-                                  UnaryExprOrTypeTrait ExprKind,
-                                  bool IsType, void *TyOrEx,
-                                  SourceRange ArgRange);
+  /// CheckOverridingFunctionExceptionSpec - Checks whether the exception
+  /// spec is a subset of base spec.
+  bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
+                                            const CXXMethodDecl *Old);
 
-  ExprResult CheckPlaceholderExpr(Expr *E);
-  bool CheckVecStepExpr(Expr *E);
+  ///@}
 
-  bool CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind);
-  bool CheckUnaryExprOrTypeTraitOperand(QualType ExprType, SourceLocation OpLoc,
-                                        SourceRange ExprRange,
-                                        UnaryExprOrTypeTrait ExprKind,
-                                        StringRef KWName);
-  ExprResult ActOnSizeofParameterPackExpr(Scope *S,
-                                          SourceLocation OpLoc,
-                                          IdentifierInfo &Name,
-                                          SourceLocation NameLoc,
-                                          SourceLocation RParenLoc);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  ExprResult ActOnPackIndexingExpr(Scope *S, Expr *PackExpression,
-                                   SourceLocation EllipsisLoc,
-                                   SourceLocation LSquareLoc, Expr *IndexExpr,
-                                   SourceLocation RSquareLoc);
+  /// \name Expressions
+  /// Implementations are in SemaExpr.cpp
+  ///@{
 
-  ExprResult BuildPackIndexingExpr(Expr *PackExpression,
-                                   SourceLocation EllipsisLoc, Expr *IndexExpr,
-                                   SourceLocation RSquareLoc,
-                                   ArrayRef ExpandedExprs = {},
-                                   bool EmptyPack = false);
+public:
+  /// Describes how the expressions currently being parsed are
+  /// evaluated at run-time, if at all.
+  enum class ExpressionEvaluationContext {
+    /// The current expression and its subexpressions occur within an
+    /// unevaluated operand (C++11 [expr]p7), such as the subexpression of
+    /// \c sizeof, where the type of the expression may be significant but
+    /// no code will be generated to evaluate the value of the expression at
+    /// run time.
+    Unevaluated,
 
-  ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
-                                 tok::TokenKind Kind, Expr *Input);
+    /// The current expression occurs within a braced-init-list within
+    /// an unevaluated operand. This is mostly like a regular unevaluated
+    /// context, except that we still instantiate constexpr functions that are
+    /// referenced here so that we can perform narrowing checks correctly.
+    UnevaluatedList,
 
-  ExprResult ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
-                                     MultiExprArg ArgExprs,
-                                     SourceLocation RLoc);
-  ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
-                                             Expr *Idx, SourceLocation RLoc);
+    /// The current expression occurs within a discarded statement.
+    /// This behaves largely similarly to an unevaluated operand in preventing
+    /// definitions from being required, but not in other ways.
+    DiscardedStatement,
 
-  ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx,
-                                              Expr *ColumnIdx,
-                                              SourceLocation RBLoc);
+    /// The current expression occurs within an unevaluated
+    /// operand that unconditionally permits abstract references to
+    /// fields, such as a SIZE operator in MS-style inline assembly.
+    UnevaluatedAbstract,
 
-  ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
-                                      Expr *LowerBound,
-                                      SourceLocation ColonLocFirst,
-                                      SourceLocation ColonLocSecond,
-                                      Expr *Length, Expr *Stride,
-                                      SourceLocation RBLoc);
-  ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc,
-                                      SourceLocation RParenLoc,
-                                      ArrayRef Dims,
-                                      ArrayRef Brackets);
+    /// The current context is "potentially evaluated" in C++11 terms,
+    /// but the expression is evaluated at compile-time (like the values of
+    /// cases in a switch statement).
+    ConstantEvaluated,
 
-  /// Data structure for iterator expression.
-  struct OMPIteratorData {
-    IdentifierInfo *DeclIdent = nullptr;
-    SourceLocation DeclIdentLoc;
-    ParsedType Type;
-    OMPIteratorExpr::IteratorRange Range;
-    SourceLocation AssignLoc;
-    SourceLocation ColonLoc;
-    SourceLocation SecColonLoc;
-  };
+    /// In addition of being constant evaluated, the current expression
+    /// occurs in an immediate function context - either a consteval function
+    /// or a consteval if statement.
+    ImmediateFunctionContext,
 
-  ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc,
-                                  SourceLocation LLoc, SourceLocation RLoc,
-                                  ArrayRef Data);
+    /// The current expression is potentially evaluated at run time,
+    /// which means that code may be generated to evaluate the value of the
+    /// expression at run time.
+    PotentiallyEvaluated,
 
-  // This struct is for use by ActOnMemberAccess to allow
-  // BuildMemberReferenceExpr to be able to reinvoke ActOnMemberAccess after
-  // changing the access operator from a '.' to a '->' (to see if that is the
-  // change needed to fix an error about an unknown member, e.g. when the class
-  // defines a custom operator->).
-  struct ActOnMemberAccessExtraArgs {
-    Scope *S;
-    UnqualifiedId &Id;
-    Decl *ObjCImpDecl;
+    /// The current expression is potentially evaluated, but any
+    /// declarations referenced inside that expression are only used if
+    /// in fact the current expression is used.
+    ///
+    /// This value is used when parsing default function arguments, for which
+    /// we would like to provide diagnostics (e.g., passing non-POD arguments
+    /// through varargs) but do not want to mark declarations as "referenced"
+    /// until the default argument is used.
+    PotentiallyEvaluatedIfUsed
   };
 
-  ExprResult BuildMemberReferenceExpr(
-      Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow,
-      CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
-      NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
-      const TemplateArgumentListInfo *TemplateArgs,
-      const Scope *S,
-      ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
+  /// Store a set of either DeclRefExprs or MemberExprs that contain a reference
+  /// to a variable (constant) that may or may not be odr-used in this Expr, and
+  /// we won't know until all lvalue-to-rvalue and discarded value conversions
+  /// have been applied to all subexpressions of the enclosing full expression.
+  /// This is cleared at the end of each full expression.
+  using MaybeODRUseExprSet = llvm::SmallSetVector;
+  MaybeODRUseExprSet MaybeODRUseExprs;
 
-  ExprResult
-  BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc,
-                           bool IsArrow, const CXXScopeSpec &SS,
-                           SourceLocation TemplateKWLoc,
-                           NamedDecl *FirstQualifierInScope, LookupResult &R,
-                           const TemplateArgumentListInfo *TemplateArgs,
-                           const Scope *S,
-                           bool SuppressQualifierCheck = false,
-                           ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
+  using ImmediateInvocationCandidate = llvm::PointerIntPair;
 
-  ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
-                                     SourceLocation OpLoc,
-                                     const CXXScopeSpec &SS, FieldDecl *Field,
-                                     DeclAccessPair FoundDecl,
-                                     const DeclarationNameInfo &MemberNameInfo);
+  /// Data structure used to record current or nested
+  /// expression evaluation contexts.
+  struct ExpressionEvaluationContextRecord {
+    /// The expression evaluation context.
+    ExpressionEvaluationContext Context;
 
-  ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow);
+    /// Whether the enclosing context needed a cleanup.
+    CleanupInfo ParentCleanup;
 
-  bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
-                                     const CXXScopeSpec &SS,
-                                     const LookupResult &R);
+    /// The number of active cleanup objects when we entered
+    /// this expression evaluation context.
+    unsigned NumCleanupObjects;
 
-  ExprResult ActOnDependentMemberExpr(Expr *Base, QualType BaseType,
-                                      bool IsArrow, SourceLocation OpLoc,
-                                      const CXXScopeSpec &SS,
-                                      SourceLocation TemplateKWLoc,
-                                      NamedDecl *FirstQualifierInScope,
-                               const DeclarationNameInfo &NameInfo,
-                               const TemplateArgumentListInfo *TemplateArgs);
+    /// The number of typos encountered during this expression evaluation
+    /// context (i.e. the number of TypoExprs created).
+    unsigned NumTypos;
 
-  ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base,
-                                   SourceLocation OpLoc,
-                                   tok::TokenKind OpKind,
-                                   CXXScopeSpec &SS,
-                                   SourceLocation TemplateKWLoc,
-                                   UnqualifiedId &Member,
-                                   Decl *ObjCImpDecl);
+    MaybeODRUseExprSet SavedMaybeODRUseExprs;
 
-  MemberExpr *
-  BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc,
-                  const CXXScopeSpec *SS, SourceLocation TemplateKWLoc,
-                  ValueDecl *Member, DeclAccessPair FoundDecl,
-                  bool HadMultipleCandidates,
-                  const DeclarationNameInfo &MemberNameInfo, QualType Ty,
-                  ExprValueKind VK, ExprObjectKind OK,
-                  const TemplateArgumentListInfo *TemplateArgs = nullptr);
-  MemberExpr *
-  BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc,
-                  NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
-                  ValueDecl *Member, DeclAccessPair FoundDecl,
-                  bool HadMultipleCandidates,
-                  const DeclarationNameInfo &MemberNameInfo, QualType Ty,
-                  ExprValueKind VK, ExprObjectKind OK,
-                  const TemplateArgumentListInfo *TemplateArgs = nullptr);
+    /// The lambdas that are present within this context, if it
+    /// is indeed an unevaluated context.
+    SmallVector Lambdas;
 
-  void ActOnDefaultCtorInitializers(Decl *CDtorDecl);
-  bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
-                               FunctionDecl *FDecl,
-                               const FunctionProtoType *Proto,
-                               ArrayRef Args,
-                               SourceLocation RParenLoc,
-                               bool ExecConfig = false);
-  void CheckStaticArrayArgument(SourceLocation CallLoc,
-                                ParmVarDecl *Param,
-                                const Expr *ArgExpr);
+    /// The declaration that provides context for lambda expressions
+    /// and block literals if the normal declaration context does not
+    /// suffice, e.g., in a default function argument.
+    Decl *ManglingContextDecl;
 
-  /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
-  /// This provides the location of the left/right parens and a list of comma
-  /// locations.
-  ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
-                           MultiExprArg ArgExprs, SourceLocation RParenLoc,
-                           Expr *ExecConfig = nullptr);
-  ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
-                           MultiExprArg ArgExprs, SourceLocation RParenLoc,
-                           Expr *ExecConfig = nullptr,
-                           bool IsExecConfig = false,
-                           bool AllowRecovery = false);
-  Expr *BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id,
-                             MultiExprArg CallArgs);
-  enum class AtomicArgumentOrder { API, AST };
-  ExprResult
-  BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
-                  SourceLocation RParenLoc, MultiExprArg Args,
-                  AtomicExpr::AtomicOp Op,
-                  AtomicArgumentOrder ArgOrder = AtomicArgumentOrder::API);
-  ExprResult
-  BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc,
-                        ArrayRef Arg, SourceLocation RParenLoc,
-                        Expr *Config = nullptr, bool IsExecConfig = false,
-                        ADLCallKind UsesADL = ADLCallKind::NotADL);
+    /// If we are processing a decltype type, a set of call expressions
+    /// for which we have deferred checking the completeness of the return type.
+    SmallVector DelayedDecltypeCalls;
 
-  ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
-                                     MultiExprArg ExecConfig,
-                                     SourceLocation GGGLoc);
+    /// If we are processing a decltype type, a set of temporary binding
+    /// expressions for which we have deferred checking the destructor.
+    SmallVector DelayedDecltypeBinds;
 
-  ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
-                           Declarator &D, ParsedType &Ty,
-                           SourceLocation RParenLoc, Expr *CastExpr);
-  ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc,
-                                 TypeSourceInfo *Ty,
-                                 SourceLocation RParenLoc,
-                                 Expr *Op);
-  CastKind PrepareScalarCast(ExprResult &src, QualType destType);
+    llvm::SmallPtrSet PossibleDerefs;
 
-  /// Build an altivec or OpenCL literal.
-  ExprResult BuildVectorLiteral(SourceLocation LParenLoc,
-                                SourceLocation RParenLoc, Expr *E,
-                                TypeSourceInfo *TInfo);
+    /// Expressions appearing as the LHS of a volatile assignment in this
+    /// context. We produce a warning for these when popping the context if
+    /// they are not discarded-value expressions nor unevaluated operands.
+    SmallVector VolatileAssignmentLHSs;
 
-  ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME);
+    /// Set of candidates for starting an immediate invocation.
+    llvm::SmallVector
+        ImmediateInvocationCandidates;
 
-  ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc,
-                                  ParsedType Ty,
-                                  SourceLocation RParenLoc,
-                                  Expr *InitExpr);
+    /// Set of DeclRefExprs referencing a consteval function when used in a
+    /// context not already known to be immediately invoked.
+    llvm::SmallPtrSet ReferenceToConsteval;
 
-  ExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc,
-                                      TypeSourceInfo *TInfo,
-                                      SourceLocation RParenLoc,
-                                      Expr *LiteralExpr);
+    /// P2718R0 - Lifetime extension in range-based for loops.
+    /// MaterializeTemporaryExprs in for-range-init expressions which need to
+    /// extend lifetime. Add MaterializeTemporaryExpr* if the value of
+    /// InLifetimeExtendingContext is true.
+    SmallVector ForRangeLifetimeExtendTemps;
 
-  ExprResult ActOnInitList(SourceLocation LBraceLoc,
-                           MultiExprArg InitArgList,
-                           SourceLocation RBraceLoc);
+    /// \brief Describes whether we are in an expression constext which we have
+    /// to handle differently.
+    enum ExpressionKind {
+      EK_Decltype,
+      EK_TemplateArgument,
+      EK_Other
+    } ExprContext;
 
-  ExprResult BuildInitList(SourceLocation LBraceLoc,
-                           MultiExprArg InitArgList,
-                           SourceLocation RBraceLoc);
+    // A context can be nested in both a discarded statement context and
+    // an immediate function context, so they need to be tracked independently.
+    bool InDiscardedStatement;
+    bool InImmediateFunctionContext;
+    bool InImmediateEscalatingFunctionContext;
 
-  ExprResult ActOnDesignatedInitializer(Designation &Desig,
-                                        SourceLocation EqualOrColonLoc,
-                                        bool GNUSyntax,
-                                        ExprResult Init);
+    bool IsCurrentlyCheckingDefaultArgumentOrInitializer = false;
 
-private:
-  static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind);
+    // We are in a constant context, but we also allow
+    // non constant expressions, for example for array bounds (which may be
+    // VLAs).
+    bool InConditionallyConstantEvaluateContext = false;
 
-public:
-  ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
-                        tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr);
-  ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc,
-                        BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr);
-  ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc,
-                                Expr *LHSExpr, Expr *RHSExpr);
-  void LookupBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc,
-                   UnresolvedSetImpl &Functions);
+    /// Whether we are currently in a context in which all temporaries must be
+    /// lifetime-extended, even if they're not bound to a reference (for
+    /// example, in a for-range initializer).
+    bool InLifetimeExtendingContext = false;
 
-  void DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc);
+    /// Whether we are currently in a context in which all temporaries must be
+    /// materialized.
+    ///
+    /// [class.temporary]/p2:
+    /// The materialization of a temporary object is generally delayed as long
+    /// as possible in order to avoid creating unnecessary temporary objects.
+    ///
+    /// Temporary objects are materialized:
+    ///   (2.1) when binding a reference to a prvalue ([dcl.init.ref],
+    ///   [expr.type.conv], [expr.dynamic.cast], [expr.static.cast],
+    ///   [expr.const.cast], [expr.cast]),
+    ///
+    ///   (2.2) when performing member access on a class prvalue ([expr.ref],
+    ///   [expr.mptr.oper]),
+    ///
+    ///   (2.3) when performing an array-to-pointer conversion or subscripting
+    ///   on an array prvalue ([conv.array], [expr.sub]),
+    ///
+    ///   (2.4) when initializing an object of type
+    ///   std​::​initializer_list from a braced-init-list
+    ///   ([dcl.init.list]),
+    ///
+    ///   (2.5) for certain unevaluated operands ([expr.typeid], [expr.sizeof])
+    ///
+    ///   (2.6) when a prvalue that has type other than cv void appears as a
+    ///   discarded-value expression ([expr.context]).
+    bool InMaterializeTemporaryObjectContext = false;
 
-  /// ActOnConditionalOp - Parse a ?: operation.  Note that 'LHS' may be null
-  /// in the case of a the GNU conditional expr extension.
-  ExprResult ActOnConditionalOp(SourceLocation QuestionLoc,
-                                SourceLocation ColonLoc,
-                                Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr);
+    // When evaluating immediate functions in the initializer of a default
+    // argument or default member initializer, this is the declaration whose
+    // default initializer is being evaluated and the location of the call
+    // or constructor definition.
+    struct InitializationContext {
+      InitializationContext(SourceLocation Loc, ValueDecl *Decl,
+                            DeclContext *Context)
+          : Loc(Loc), Decl(Decl), Context(Context) {
+        assert(Decl && Context && "invalid initialization context");
+      }
 
-  /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
-  ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
-                            LabelDecl *TheDecl);
+      SourceLocation Loc;
+      ValueDecl *Decl = nullptr;
+      DeclContext *Context = nullptr;
+    };
+    std::optional DelayedDefaultInitializationContext;
 
-  void ActOnStartStmtExpr();
-  ExprResult ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt,
-                           SourceLocation RPLoc);
-  ExprResult BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
-                           SourceLocation RPLoc, unsigned TemplateDepth);
-  // Handle the final expression in a statement expression.
-  ExprResult ActOnStmtExprResult(ExprResult E);
-  void ActOnStmtExprError();
+    ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
+                                      unsigned NumCleanupObjects,
+                                      CleanupInfo ParentCleanup,
+                                      Decl *ManglingContextDecl,
+                                      ExpressionKind ExprContext)
+        : Context(Context), ParentCleanup(ParentCleanup),
+          NumCleanupObjects(NumCleanupObjects), NumTypos(0),
+          ManglingContextDecl(ManglingContextDecl), ExprContext(ExprContext),
+          InDiscardedStatement(false), InImmediateFunctionContext(false),
+          InImmediateEscalatingFunctionContext(false) {}
 
-  // __builtin_offsetof(type, identifier(.identifier|[expr])*)
-  struct OffsetOfComponent {
-    SourceLocation LocStart, LocEnd;
-    bool isBrackets;  // true if [expr], false if .ident
-    union {
-      IdentifierInfo *IdentInfo;
-      Expr *E;
-    } U;
-  };
+    bool isUnevaluated() const {
+      return Context == ExpressionEvaluationContext::Unevaluated ||
+             Context == ExpressionEvaluationContext::UnevaluatedAbstract ||
+             Context == ExpressionEvaluationContext::UnevaluatedList;
+    }
 
-  /// __builtin_offsetof(type, a.b[123][456].c)
-  ExprResult BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
-                                  TypeSourceInfo *TInfo,
-                                  ArrayRef Components,
-                                  SourceLocation RParenLoc);
-  ExprResult ActOnBuiltinOffsetOf(Scope *S,
-                                  SourceLocation BuiltinLoc,
-                                  SourceLocation TypeLoc,
-                                  ParsedType ParsedArgTy,
-                                  ArrayRef Components,
-                                  SourceLocation RParenLoc);
-
-  // __builtin_choose_expr(constExpr, expr1, expr2)
-  ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
-                             Expr *CondExpr, Expr *LHSExpr,
-                             Expr *RHSExpr, SourceLocation RPLoc);
-
-  // __builtin_va_arg(expr, type)
-  ExprResult ActOnVAArg(SourceLocation BuiltinLoc, Expr *E, ParsedType Ty,
-                        SourceLocation RPLoc);
-  ExprResult BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E,
-                            TypeSourceInfo *TInfo, SourceLocation RPLoc);
-
-  // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FUNCSIG(),
-  // __builtin_FILE(), __builtin_COLUMN(), __builtin_source_location()
-  ExprResult ActOnSourceLocExpr(SourceLocIdentKind Kind,
-                                SourceLocation BuiltinLoc,
-                                SourceLocation RPLoc);
+    bool isConstantEvaluated() const {
+      return Context == ExpressionEvaluationContext::ConstantEvaluated ||
+             Context == ExpressionEvaluationContext::ImmediateFunctionContext;
+    }
 
-  // Build a potentially resolved SourceLocExpr.
-  ExprResult BuildSourceLocExpr(SourceLocIdentKind Kind, QualType ResultTy,
-                                SourceLocation BuiltinLoc, SourceLocation RPLoc,
-                                DeclContext *ParentContext);
+    bool isImmediateFunctionContext() const {
+      return Context == ExpressionEvaluationContext::ImmediateFunctionContext ||
+             (Context == ExpressionEvaluationContext::DiscardedStatement &&
+              InImmediateFunctionContext) ||
+             // C++23 [expr.const]p14:
+             // An expression or conversion is in an immediate function
+             // context if it is potentially evaluated and either:
+             //   * its innermost enclosing non-block scope is a function
+             //     parameter scope of an immediate function, or
+             //   * its enclosing statement is enclosed by the compound-
+             //     statement of a consteval if statement.
+             (Context == ExpressionEvaluationContext::PotentiallyEvaluated &&
+              InImmediateFunctionContext);
+    }
 
-  // __null
-  ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
+    bool isDiscardedStatementContext() const {
+      return Context == ExpressionEvaluationContext::DiscardedStatement ||
+             (Context ==
+                  ExpressionEvaluationContext::ImmediateFunctionContext &&
+              InDiscardedStatement);
+    }
+  };
 
-  bool CheckCaseExpression(Expr *E);
+  const ExpressionEvaluationContextRecord ¤tEvaluationContext() const {
+    assert(!ExprEvalContexts.empty() &&
+           "Must be in an expression evaluation context");
+    return ExprEvalContexts.back();
+  };
 
-  /// Describes the result of an "if-exists" condition check.
-  enum IfExistsResult {
-    /// The symbol exists.
-    IER_Exists,
+  /// Increment when we find a reference; decrement when we find an ignored
+  /// assignment.  Ultimately the value is 0 if every reference is an ignored
+  /// assignment.
+  llvm::DenseMap RefsMinusAssignments;
 
-    /// The symbol does not exist.
-    IER_DoesNotExist,
+  /// Used to control the generation of ExprWithCleanups.
+  CleanupInfo Cleanup;
 
-    /// The name is a dependent name, so the results will differ
-    /// from one instantiation to the next.
-    IER_Dependent,
+  /// ExprCleanupObjects - This is the stack of objects requiring
+  /// cleanup that are created by the current full expression.
+  SmallVector ExprCleanupObjects;
 
-    /// An error occurred.
-    IER_Error
+  // AssignmentAction - This is used by all the assignment diagnostic functions
+  // to represent what is actually causing the operation
+  enum AssignmentAction {
+    AA_Assigning,
+    AA_Passing,
+    AA_Returning,
+    AA_Converting,
+    AA_Initializing,
+    AA_Sending,
+    AA_Casting,
+    AA_Passing_CFAudited
   };
 
-  IfExistsResult
-  CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS,
-                               const DeclarationNameInfo &TargetNameInfo);
+  bool CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid);
+  // A version of DiagnoseUseOfDecl that should be used if overload resolution
+  // has been used to find this declaration, which means we don't have to bother
+  // checking the trailing requires clause.
+  bool DiagnoseUseOfOverloadedDecl(NamedDecl *D, SourceLocation Loc) {
+    return DiagnoseUseOfDecl(
+        D, Loc, /*UnknownObjCClass=*/nullptr, /*ObjCPropertyAccess=*/false,
+        /*AvoidPartialAvailabilityChecks=*/false, /*ClassReceiver=*/nullptr,
+        /*SkipTrailingRequiresClause=*/true);
+  }
 
-  IfExistsResult
-  CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
-                               bool IsIfExists, CXXScopeSpec &SS,
-                               UnqualifiedId &Name);
+  bool DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs,
+                         const ObjCInterfaceDecl *UnknownObjCClass = nullptr,
+                         bool ObjCPropertyAccess = false,
+                         bool AvoidPartialAvailabilityChecks = false,
+                         ObjCInterfaceDecl *ClassReciever = nullptr,
+                         bool SkipTrailingRequiresClause = false);
+  void NoteDeletedFunction(FunctionDecl *FD);
 
-  StmtResult BuildMSDependentExistsStmt(SourceLocation KeywordLoc,
-                                        bool IsIfExists,
-                                        NestedNameSpecifierLoc QualifierLoc,
-                                        DeclarationNameInfo NameInfo,
-                                        Stmt *Nested);
-  StmtResult ActOnMSDependentExistsStmt(SourceLocation KeywordLoc,
-                                        bool IsIfExists,
-                                        CXXScopeSpec &SS, UnqualifiedId &Name,
-                                        Stmt *Nested);
+  void DiagnoseSentinelCalls(const NamedDecl *D, SourceLocation Loc,
+                             ArrayRef Args);
 
-  //===------------------------- "Block" Extension ------------------------===//
+  void PushExpressionEvaluationContext(
+      ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = nullptr,
+      ExpressionEvaluationContextRecord::ExpressionKind Type =
+          ExpressionEvaluationContextRecord::EK_Other);
+  enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl };
+  void PushExpressionEvaluationContext(
+      ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t,
+      ExpressionEvaluationContextRecord::ExpressionKind Type =
+          ExpressionEvaluationContextRecord::EK_Other);
+  void PopExpressionEvaluationContext();
 
-  /// ActOnBlockStart - This callback is invoked when a block literal is
-  /// started.
-  void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
+  void DiscardCleanupsInEvaluationContext();
 
-  /// ActOnBlockArguments - This callback allows processing of block arguments.
-  /// If there are no arguments, this is still invoked.
-  void ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
-                           Scope *CurScope);
+  ExprResult TransformToPotentiallyEvaluated(Expr *E);
+  TypeSourceInfo *TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo);
+  ExprResult HandleExprEvaluationContextForTypeof(Expr *E);
 
-  /// ActOnBlockError - If there is an error parsing a block, this callback
-  /// is invoked to pop the information about the block from the action impl.
-  void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope);
+  void CheckUnusedVolatileAssignment(Expr *E);
 
-  /// ActOnBlockStmtExpr - This is called when the body of a block statement
-  /// literal was successfully completed.  ^(int x){...}
-  ExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body,
-                                Scope *CurScope);
+  ExprResult ActOnConstantExpression(ExprResult Res);
 
-  //===---------------------------- Clang Extensions ----------------------===//
+  // Functions for marking a declaration referenced.  These functions also
+  // contain the relevant logic for marking if a reference to a function or
+  // variable is an odr-use (in the C++11 sense).  There are separate variants
+  // for expressions referring to a decl; these exist because odr-use marking
+  // needs to be delayed for some constant variables when we build one of the
+  // named expressions.
+  //
+  // MightBeOdrUse indicates whether the use could possibly be an odr-use, and
+  // should usually be true. This only needs to be set to false if the lack of
+  // odr-use cannot be determined from the current context (for instance,
+  // because the name denotes a virtual function and was written without an
+  // explicit nested-name-specifier).
+  void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool MightBeOdrUse);
+  void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
+                              bool MightBeOdrUse = true);
+  void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var);
+  void MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base = nullptr);
+  void MarkMemberReferenced(MemberExpr *E);
+  void MarkFunctionParmPackReferenced(FunctionParmPackExpr *E);
+  void MarkCaptureUsedInEnclosingContext(ValueDecl *Capture, SourceLocation Loc,
+                                         unsigned CapturingScopeIndex);
 
-  /// __builtin_convertvector(...)
-  ExprResult ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy,
-                                    SourceLocation BuiltinLoc,
-                                    SourceLocation RParenLoc);
+  ExprResult CheckLValueToRValueConversionOperand(Expr *E);
+  void CleanupVarDeclMarking();
 
-  //===---------------------------- OpenCL Features -----------------------===//
+  enum TryCaptureKind {
+    TryCapture_Implicit,
+    TryCapture_ExplicitByVal,
+    TryCapture_ExplicitByRef
+  };
 
-  /// __builtin_astype(...)
-  ExprResult ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
-                             SourceLocation BuiltinLoc,
-                             SourceLocation RParenLoc);
-  ExprResult BuildAsTypeExpr(Expr *E, QualType DestTy,
-                             SourceLocation BuiltinLoc,
-                             SourceLocation RParenLoc);
+  /// Try to capture the given variable.
+  ///
+  /// \param Var The variable to capture.
+  ///
+  /// \param Loc The location at which the capture occurs.
+  ///
+  /// \param Kind The kind of capture, which may be implicit (for either a
+  /// block or a lambda), or explicit by-value or by-reference (for a lambda).
+  ///
+  /// \param EllipsisLoc The location of the ellipsis, if one is provided in
+  /// an explicit lambda capture.
+  ///
+  /// \param BuildAndDiagnose Whether we are actually supposed to add the
+  /// captures or diagnose errors. If false, this routine merely check whether
+  /// the capture can occur without performing the capture itself or complaining
+  /// if the variable cannot be captured.
+  ///
+  /// \param CaptureType Will be set to the type of the field used to capture
+  /// this variable in the innermost block or lambda. Only valid when the
+  /// variable can be captured.
+  ///
+  /// \param DeclRefType Will be set to the type of a reference to the capture
+  /// from within the current scope. Only valid when the variable can be
+  /// captured.
+  ///
+  /// \param FunctionScopeIndexToStopAt If non-null, it points to the index
+  /// of the FunctionScopeInfo stack beyond which we do not attempt to capture.
+  /// This is useful when enclosing lambdas must speculatively capture
+  /// variables that may or may not be used in certain specializations of
+  /// a nested generic lambda.
+  ///
+  /// \returns true if an error occurred (i.e., the variable cannot be
+  /// captured) and false if the capture succeeded.
+  bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc,
+                          TryCaptureKind Kind, SourceLocation EllipsisLoc,
+                          bool BuildAndDiagnose, QualType &CaptureType,
+                          QualType &DeclRefType,
+                          const unsigned *const FunctionScopeIndexToStopAt);
 
-  //===---------------------------- HLSL Features -------------------------===//
-  Decl *ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer,
-                             SourceLocation KwLoc, IdentifierInfo *Ident,
-                             SourceLocation IdentLoc, SourceLocation LBrace);
-  void ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace);
+  /// Try to capture the given variable.
+  bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc,
+                          TryCaptureKind Kind = TryCapture_Implicit,
+                          SourceLocation EllipsisLoc = SourceLocation());
 
-  //===---------------------------- C++ Features --------------------------===//
+  /// Checks if the variable must be captured.
+  bool NeedToCaptureVariable(ValueDecl *Var, SourceLocation Loc);
 
-  // Act on C++ namespaces
-  Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc,
-                               SourceLocation NamespaceLoc,
-                               SourceLocation IdentLoc, IdentifierInfo *Ident,
-                               SourceLocation LBrace,
-                               const ParsedAttributesView &AttrList,
-                               UsingDirectiveDecl *&UsingDecl, bool IsNested);
-  void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace);
+  /// Given a variable, determine the type that a reference to that
+  /// variable will have in the given scope.
+  QualType getCapturedDeclRefType(ValueDecl *Var, SourceLocation Loc);
 
-  NamespaceDecl *getStdNamespace() const;
-  NamespaceDecl *getOrCreateStdNamespace();
+  /// Mark all of the declarations referenced within a particular AST node as
+  /// referenced. Used when template instantiation instantiates a non-dependent
+  /// type -- entities referenced by the type are now referenced.
+  void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
+  void MarkDeclarationsReferencedInExpr(
+      Expr *E, bool SkipLocalVariables = false,
+      ArrayRef StopAt = std::nullopt);
 
-  CXXRecordDecl *getStdBadAlloc() const;
-  EnumDecl *getStdAlignValT() const;
-
-  ValueDecl *tryLookupUnambiguousFieldDecl(RecordDecl *ClassDecl,
-                                           const IdentifierInfo *MemberOrBase);
-
-private:
-  // A cache representing if we've fully checked the various comparison category
-  // types stored in ASTContext. The bit-index corresponds to the integer value
-  // of a ComparisonCategoryType enumerator.
-  llvm::SmallBitVector FullyCheckedComparisonCategories;
-
-  ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl,
-                                         CXXScopeSpec &SS,
-                                         ParsedType TemplateTypeTy,
-                                         IdentifierInfo *MemberOrBase);
-
-public:
-  enum class ComparisonCategoryUsage {
-    /// The '<=>' operator was used in an expression and a builtin operator
-    /// was selected.
-    OperatorInExpression,
-    /// A defaulted 'operator<=>' needed the comparison category. This
-    /// typically only applies to 'std::strong_ordering', due to the implicit
-    /// fallback return value.
-    DefaultedOperator,
-  };
+  /// Try to convert an expression \p E to type \p Ty. Returns the result of the
+  /// conversion.
+  ExprResult tryConvertExprToType(Expr *E, QualType Ty);
 
-  /// Lookup the specified comparison category types in the standard
-  ///   library, an check the VarDecls possibly returned by the operator<=>
-  ///   builtins for that type.
+  /// Conditionally issue a diagnostic based on the statements's reachability
+  /// analysis.
   ///
-  /// \return The type of the comparison category type corresponding to the
-  ///   specified Kind, or a null type if an error occurs
-  QualType CheckComparisonCategoryType(ComparisonCategoryType Kind,
-                                       SourceLocation Loc,
-                                       ComparisonCategoryUsage Usage);
-
-  /// Tests whether Ty is an instance of std::initializer_list and, if
-  /// it is and Element is not NULL, assigns the element type to Element.
-  bool isStdInitializerList(QualType Ty, QualType *Element);
+  /// \param Stmts If Stmts is non-empty, delay reporting the diagnostic until
+  /// the function body is parsed, and then do a basic reachability analysis to
+  /// determine if the statement is reachable. If it is unreachable, the
+  /// diagnostic will not be emitted.
+  bool DiagIfReachable(SourceLocation Loc, ArrayRef Stmts,
+                       const PartialDiagnostic &PD);
 
-  /// Looks for the std::initializer_list template and instantiates it
-  /// with Element, or emits an error if it's not found.
+  /// Conditionally issue a diagnostic based on the current
+  /// evaluation context.
   ///
-  /// \returns The instantiated template, or null on error.
-  QualType BuildStdInitializerList(QualType Element, SourceLocation Loc);
-
-  /// Determine whether Ctor is an initializer-list constructor, as
-  /// defined in [dcl.init.list]p2.
-  bool isInitListConstructor(const FunctionDecl *Ctor);
+  /// \param Statement If Statement is non-null, delay reporting the
+  /// diagnostic until the function body is parsed, and then do a basic
+  /// reachability analysis to determine if the statement is reachable.
+  /// If it is unreachable, the diagnostic will not be emitted.
+  bool DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement,
+                           const PartialDiagnostic &PD);
+  /// Similar, but diagnostic is only produced if all the specified statements
+  /// are reachable.
+  bool DiagRuntimeBehavior(SourceLocation Loc, ArrayRef Stmts,
+                           const PartialDiagnostic &PD);
 
-  Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc,
-                            SourceLocation NamespcLoc, CXXScopeSpec &SS,
-                            SourceLocation IdentLoc,
-                            IdentifierInfo *NamespcName,
-                            const ParsedAttributesView &AttrList);
+  // Primary Expressions.
+  SourceRange getExprRange(Expr *E) const;
 
-  void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir);
+  ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
+                               SourceLocation TemplateKWLoc, UnqualifiedId &Id,
+                               bool HasTrailingLParen, bool IsAddressOfOperand,
+                               CorrectionCandidateCallback *CCC = nullptr,
+                               bool IsInlineAsmIdentifier = false,
+                               Token *KeywordReplacement = nullptr);
 
-  Decl *ActOnNamespaceAliasDef(Scope *CurScope,
-                               SourceLocation NamespaceLoc,
-                               SourceLocation AliasLoc,
-                               IdentifierInfo *Alias,
-                               CXXScopeSpec &SS,
-                               SourceLocation IdentLoc,
-                               IdentifierInfo *Ident);
+  void DecomposeUnqualifiedId(const UnqualifiedId &Id,
+                              TemplateArgumentListInfo &Buffer,
+                              DeclarationNameInfo &NameInfo,
+                              const TemplateArgumentListInfo *&TemplateArgs);
 
-  void FilterUsingLookup(Scope *S, LookupResult &lookup);
-  void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow);
-  bool CheckUsingShadowDecl(BaseUsingDecl *BUD, NamedDecl *Target,
-                            const LookupResult &PreviousDecls,
-                            UsingShadowDecl *&PrevShadow);
-  UsingShadowDecl *BuildUsingShadowDecl(Scope *S, BaseUsingDecl *BUD,
-                                        NamedDecl *Target,
-                                        UsingShadowDecl *PrevDecl);
+  bool DiagnoseDependentMemberLookup(const LookupResult &R);
 
-  bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
-                                   bool HasTypenameKeyword,
-                                   const CXXScopeSpec &SS,
-                                   SourceLocation NameLoc,
-                                   const LookupResult &Previous);
-  bool CheckUsingDeclQualifier(SourceLocation UsingLoc, bool HasTypename,
-                               const CXXScopeSpec &SS,
-                               const DeclarationNameInfo &NameInfo,
-                               SourceLocation NameLoc,
-                               const LookupResult *R = nullptr,
-                               const UsingDecl *UD = nullptr);
+  bool
+  DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
+                      CorrectionCandidateCallback &CCC,
+                      TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
+                      ArrayRef Args = std::nullopt,
+                      DeclContext *LookupCtx = nullptr,
+                      TypoExpr **Out = nullptr);
 
-  NamedDecl *BuildUsingDeclaration(
-      Scope *S, AccessSpecifier AS, SourceLocation UsingLoc,
-      bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS,
-      DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc,
-      const ParsedAttributesView &AttrList, bool IsInstantiation,
-      bool IsUsingIfExists);
-  NamedDecl *BuildUsingEnumDeclaration(Scope *S, AccessSpecifier AS,
-                                       SourceLocation UsingLoc,
-                                       SourceLocation EnumLoc,
-                                       SourceLocation NameLoc,
-                                       TypeSourceInfo *EnumType, EnumDecl *ED);
-  NamedDecl *BuildUsingPackDecl(NamedDecl *InstantiatedFrom,
-                                ArrayRef Expansions);
+  DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,
+                                    IdentifierInfo *II);
+  ExprResult BuildIvarRefExpr(Scope *S, SourceLocation Loc, ObjCIvarDecl *IV);
 
-  bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
+  ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S,
+                                IdentifierInfo *II,
+                                bool AllowBuiltinCreation = false);
 
-  /// Given a derived-class using shadow declaration for a constructor and the
-  /// correspnding base class constructor, find or create the implicit
-  /// synthesized derived class constructor to use for this initialization.
-  CXXConstructorDecl *
-  findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *BaseCtor,
-                            ConstructorUsingShadowDecl *DerivedShadow);
+  /// If \p D cannot be odr-used in the current expression evaluation context,
+  /// return a reason explaining why. Otherwise, return NOUR_None.
+  NonOdrUseReason getNonOdrUseReasonInCurrentContext(ValueDecl *D);
 
-  Decl *ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS,
-                              SourceLocation UsingLoc,
-                              SourceLocation TypenameLoc, CXXScopeSpec &SS,
-                              UnqualifiedId &Name, SourceLocation EllipsisLoc,
-                              const ParsedAttributesView &AttrList);
-  Decl *ActOnUsingEnumDeclaration(Scope *CurScope, AccessSpecifier AS,
-                                  SourceLocation UsingLoc,
-                                  SourceLocation EnumLoc,
-                                  SourceLocation IdentLoc, IdentifierInfo &II,
-                                  CXXScopeSpec *SS = nullptr);
-  Decl *ActOnAliasDeclaration(Scope *CurScope, AccessSpecifier AS,
-                              MultiTemplateParamsArg TemplateParams,
-                              SourceLocation UsingLoc, UnqualifiedId &Name,
-                              const ParsedAttributesView &AttrList,
-                              TypeResult Type, Decl *DeclFromDeclSpec);
+  DeclRefExpr *BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
+                                SourceLocation Loc,
+                                const CXXScopeSpec *SS = nullptr);
+  DeclRefExpr *
+  BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
+                   const DeclarationNameInfo &NameInfo,
+                   const CXXScopeSpec *SS = nullptr,
+                   NamedDecl *FoundD = nullptr,
+                   SourceLocation TemplateKWLoc = SourceLocation(),
+                   const TemplateArgumentListInfo *TemplateArgs = nullptr);
+  DeclRefExpr *
+  BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
+                   const DeclarationNameInfo &NameInfo,
+                   NestedNameSpecifierLoc NNS, NamedDecl *FoundD = nullptr,
+                   SourceLocation TemplateKWLoc = SourceLocation(),
+                   const TemplateArgumentListInfo *TemplateArgs = nullptr);
 
-  /// BuildCXXConstructExpr - Creates a complete call to a constructor,
-  /// including handling of its default argument expressions.
-  ///
-  /// \param ConstructKind - a CXXConstructExpr::ConstructionKind
-  ExprResult BuildCXXConstructExpr(
-      SourceLocation ConstructLoc, QualType DeclInitType, NamedDecl *FoundDecl,
-      CXXConstructorDecl *Constructor, MultiExprArg Exprs,
-      bool HadMultipleCandidates, bool IsListInitialization,
-      bool IsStdInitListInitialization, bool RequiresZeroInit,
-      CXXConstructionKind ConstructKind, SourceRange ParenRange);
+  bool UseArgumentDependentLookup(const CXXScopeSpec &SS, const LookupResult &R,
+                                  bool HasTrailingLParen);
 
-  /// Build a CXXConstructExpr whose constructor has already been resolved if
-  /// it denotes an inherited constructor.
-  ExprResult BuildCXXConstructExpr(
-      SourceLocation ConstructLoc, QualType DeclInitType,
-      CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs,
-      bool HadMultipleCandidates, bool IsListInitialization,
-      bool IsStdInitListInitialization, bool RequiresZeroInit,
-      CXXConstructionKind ConstructKind, SourceRange ParenRange);
+  ExprResult
+  BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
+                                    const DeclarationNameInfo &NameInfo,
+                                    bool IsAddressOfOperand, const Scope *S,
+                                    TypeSourceInfo **RecoveryTSI = nullptr);
 
-  // FIXME: Can we remove this and have the above BuildCXXConstructExpr check if
-  // the constructor can be elidable?
-  ExprResult BuildCXXConstructExpr(
-      SourceLocation ConstructLoc, QualType DeclInitType, NamedDecl *FoundDecl,
-      CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs,
-      bool HadMultipleCandidates, bool IsListInitialization,
-      bool IsStdInitListInitialization, bool RequiresZeroInit,
-      CXXConstructionKind ConstructKind, SourceRange ParenRange);
+  ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R,
+                                      bool NeedsADL,
+                                      bool AcceptInvalidDecl = false);
+  ExprResult BuildDeclarationNameExpr(
+      const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
+      NamedDecl *FoundD = nullptr,
+      const TemplateArgumentListInfo *TemplateArgs = nullptr,
+      bool AcceptInvalidDecl = false);
 
-  ExprResult ConvertMemberDefaultInitExpression(FieldDecl *FD, Expr *InitExpr,
-                                                SourceLocation InitLoc);
+  // ExpandFunctionLocalPredefinedMacros - Returns a new vector of Tokens,
+  // where Tokens representing function local predefined macros (such as
+  // __FUNCTION__) are replaced (expanded) with string-literal Tokens.
+  std::vector ExpandFunctionLocalPredefinedMacros(ArrayRef Toks);
 
-  ExprResult BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field);
+  ExprResult BuildPredefinedExpr(SourceLocation Loc, PredefinedIdentKind IK);
+  ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
+  ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);
 
+  ExprResult BuildSYCLUniqueStableNameExpr(SourceLocation OpLoc,
+                                           SourceLocation LParen,
+                                           SourceLocation RParen,
+                                           TypeSourceInfo *TSI);
+  ExprResult ActOnSYCLUniqueStableNameExpr(SourceLocation OpLoc,
+                                           SourceLocation LParen,
+                                           SourceLocation RParen,
+                                           ParsedType ParsedTy);
 
-  /// Instantiate or parse a C++ default argument expression as necessary.
-  /// Return true on error.
-  bool CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
-                              ParmVarDecl *Param, Expr *Init = nullptr,
-                              bool SkipImmediateInvocations = true);
+  bool CheckLoopHintExpr(Expr *E, SourceLocation Loc);
 
-  /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
-  /// the default expr if needed.
-  ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
-                                    ParmVarDecl *Param, Expr *Init = nullptr);
+  ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = nullptr);
+  ExprResult ActOnCharacterConstant(const Token &Tok,
+                                    Scope *UDLScope = nullptr);
+  ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E);
+  ExprResult ActOnParenListExpr(SourceLocation L, SourceLocation R,
+                                MultiExprArg Val);
 
-  /// FinalizeVarWithDestructor - Prepare for calling destructor on the
-  /// constructed variable.
-  void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
+  /// ActOnStringLiteral - The specified tokens were lexed as pasted string
+  /// fragments (e.g. "foo" "bar" L"baz").
+  ExprResult ActOnStringLiteral(ArrayRef StringToks,
+                                Scope *UDLScope = nullptr);
 
-  /// Helper class that collects exception specifications for
-  /// implicitly-declared special member functions.
-  class ImplicitExceptionSpecification {
-    // Pointer to allow copying
-    Sema *Self;
-    // We order exception specifications thus:
-    // noexcept is the most restrictive, but is only used in C++11.
-    // throw() comes next.
-    // Then a throw(collected exceptions)
-    // Finally no specification, which is expressed as noexcept(false).
-    // throw(...) is used instead if any called function uses it.
-    ExceptionSpecificationType ComputedEST;
-    llvm::SmallPtrSet ExceptionsSeen;
-    SmallVector Exceptions;
+  ExprResult ActOnUnevaluatedStringLiteral(ArrayRef StringToks);
 
-    void ClearExceptions() {
-      ExceptionsSeen.clear();
-      Exceptions.clear();
-    }
+  /// ControllingExprOrType is either an opaque pointer coming out of a
+  /// ParsedType or an Expr *. FIXME: it'd be better to split this interface
+  /// into two so we don't take a void *, but that's awkward because one of
+  /// the operands is either a ParsedType or an Expr *, which doesn't lend
+  /// itself to generic code very well.
+  ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc,
+                                       SourceLocation DefaultLoc,
+                                       SourceLocation RParenLoc,
+                                       bool PredicateIsExpr,
+                                       void *ControllingExprOrType,
+                                       ArrayRef ArgTypes,
+                                       ArrayRef ArgExprs);
+  /// ControllingExprOrType is either a TypeSourceInfo * or an Expr *. FIXME:
+  /// it'd be better to split this interface into two so we don't take a
+  /// void *, but see the FIXME on ActOnGenericSelectionExpr as to why that
+  /// isn't a trivial change.
+  ExprResult CreateGenericSelectionExpr(SourceLocation KeyLoc,
+                                        SourceLocation DefaultLoc,
+                                        SourceLocation RParenLoc,
+                                        bool PredicateIsExpr,
+                                        void *ControllingExprOrType,
+                                        ArrayRef Types,
+                                        ArrayRef Exprs);
 
-  public:
-    explicit ImplicitExceptionSpecification(Sema &Self)
-      : Self(&Self), ComputedEST(EST_BasicNoexcept) {
-      if (!Self.getLangOpts().CPlusPlus11)
-        ComputedEST = EST_DynamicNone;
-    }
+  // Binary/Unary Operators.  'Tok' is the token for the operator.
+  ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
+                                  Expr *InputExpr, bool IsAfterAmp = false);
+  ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc,
+                          Expr *Input, bool IsAfterAmp = false);
+  ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op,
+                          Expr *Input, bool IsAfterAmp = false);
 
-    /// Get the computed exception specification type.
-    ExceptionSpecificationType getExceptionSpecType() const {
-      assert(!isComputedNoexcept(ComputedEST) &&
-             "noexcept(expr) should not be a possible result");
-      return ComputedEST;
-    }
+  bool isQualifiedMemberAccess(Expr *E);
+  bool CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc,
+                                             const Expr *Op,
+                                             const CXXMethodDecl *MD);
 
-    /// The number of exceptions in the exception specification.
-    unsigned size() const { return Exceptions.size(); }
+  QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
 
-    /// The set of exceptions in the exception specification.
-    const QualType *data() const { return Exceptions.data(); }
+  bool ActOnAlignasTypeArgument(StringRef KWName, ParsedType Ty,
+                                SourceLocation OpLoc, SourceRange R);
+  bool CheckAlignasTypeArgument(StringRef KWName, TypeSourceInfo *TInfo,
+                                SourceLocation OpLoc, SourceRange R);
 
-    /// Integrate another called method into the collected data.
-    void CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method);
+  ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
+                                            SourceLocation OpLoc,
+                                            UnaryExprOrTypeTrait ExprKind,
+                                            SourceRange R);
+  ExprResult CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
+                                            UnaryExprOrTypeTrait ExprKind);
+  ExprResult ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
+                                           UnaryExprOrTypeTrait ExprKind,
+                                           bool IsType, void *TyOrEx,
+                                           SourceRange ArgRange);
 
-    /// Integrate an invoked expression into the collected data.
-    void CalledExpr(Expr *E) { CalledStmt(E); }
+  ExprResult CheckPlaceholderExpr(Expr *E);
+  bool CheckVecStepExpr(Expr *E);
 
-    /// Integrate an invoked statement into the collected data.
-    void CalledStmt(Stmt *S);
+  bool CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind);
+  bool CheckUnaryExprOrTypeTraitOperand(QualType ExprType, SourceLocation OpLoc,
+                                        SourceRange ExprRange,
+                                        UnaryExprOrTypeTrait ExprKind,
+                                        StringRef KWName);
 
-    /// Overwrite an EPI's exception specification with this
-    /// computed exception specification.
-    FunctionProtoType::ExceptionSpecInfo getExceptionSpec() const {
-      FunctionProtoType::ExceptionSpecInfo ESI;
-      ESI.Type = getExceptionSpecType();
-      if (ESI.Type == EST_Dynamic) {
-        ESI.Exceptions = Exceptions;
-      } else if (ESI.Type == EST_None) {
-        /// C++11 [except.spec]p14:
-        ///   The exception-specification is noexcept(false) if the set of
-        ///   potential exceptions of the special member function contains "any"
-        ESI.Type = EST_NoexceptFalse;
-        ESI.NoexceptExpr = Self->ActOnCXXBoolLiteral(SourceLocation(),
-                                                     tok::kw_false).get();
-      }
-      return ESI;
-    }
-  };
+  ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
+                                 tok::TokenKind Kind, Expr *Input);
 
-  /// Evaluate the implicit exception specification for a defaulted
-  /// special member function.
-  void EvaluateImplicitExceptionSpec(SourceLocation Loc, FunctionDecl *FD);
+  ExprResult ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
+                                     MultiExprArg ArgExprs,
+                                     SourceLocation RLoc);
+  ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
+                                             Expr *Idx, SourceLocation RLoc);
 
-  /// Check the given noexcept-specifier, convert its expression, and compute
-  /// the appropriate ExceptionSpecificationType.
-  ExprResult ActOnNoexceptSpec(Expr *NoexceptExpr,
-                               ExceptionSpecificationType &EST);
+  ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx,
+                                              Expr *ColumnIdx,
+                                              SourceLocation RBLoc);
 
-  /// Check the given exception-specification and update the
-  /// exception specification information with the results.
-  void checkExceptionSpecification(bool IsTopLevel,
-                                   ExceptionSpecificationType EST,
-                                   ArrayRef DynamicExceptions,
-                                   ArrayRef DynamicExceptionRanges,
-                                   Expr *NoexceptExpr,
-                                   SmallVectorImpl &Exceptions,
-                                   FunctionProtoType::ExceptionSpecInfo &ESI);
+  ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
+                                      Expr *LowerBound,
+                                      SourceLocation ColonLocFirst,
+                                      SourceLocation ColonLocSecond,
+                                      Expr *Length, Expr *Stride,
+                                      SourceLocation RBLoc);
+  ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc,
+                                      SourceLocation RParenLoc,
+                                      ArrayRef Dims,
+                                      ArrayRef Brackets);
 
-  /// Determine if we're in a case where we need to (incorrectly) eagerly
-  /// parse an exception specification to work around a libstdc++ bug.
-  bool isLibstdcxxEagerExceptionSpecHack(const Declarator &D);
+  /// Data structure for iterator expression.
+  struct OMPIteratorData {
+    IdentifierInfo *DeclIdent = nullptr;
+    SourceLocation DeclIdentLoc;
+    ParsedType Type;
+    OMPIteratorExpr::IteratorRange Range;
+    SourceLocation AssignLoc;
+    SourceLocation ColonLoc;
+    SourceLocation SecColonLoc;
+  };
 
-  /// Add an exception-specification to the given member function
-  /// (or member function template). The exception-specification was parsed
-  /// after the method itself was declared.
-  void actOnDelayedExceptionSpecification(Decl *Method,
-         ExceptionSpecificationType EST,
-         SourceRange SpecificationRange,
-         ArrayRef DynamicExceptions,
-         ArrayRef DynamicExceptionRanges,
-         Expr *NoexceptExpr);
+  ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc,
+                                  SourceLocation LLoc, SourceLocation RLoc,
+                                  ArrayRef Data);
 
-  class InheritedConstructorInfo;
+  bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, FunctionDecl *FDecl,
+                               const FunctionProtoType *Proto,
+                               ArrayRef Args, SourceLocation RParenLoc,
+                               bool ExecConfig = false);
+  void CheckStaticArrayArgument(SourceLocation CallLoc, ParmVarDecl *Param,
+                                const Expr *ArgExpr);
 
-  /// Determine if a special member function should have a deleted
-  /// definition when it is defaulted.
-  bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
-                                 InheritedConstructorInfo *ICI = nullptr,
-                                 bool Diagnose = false);
+  /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
+  /// This provides the location of the left/right parens and a list of comma
+  /// locations.
+  ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
+                           MultiExprArg ArgExprs, SourceLocation RParenLoc,
+                           Expr *ExecConfig = nullptr);
+  ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
+                           MultiExprArg ArgExprs, SourceLocation RParenLoc,
+                           Expr *ExecConfig = nullptr,
+                           bool IsExecConfig = false,
+                           bool AllowRecovery = false);
+  Expr *BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id,
+                             MultiExprArg CallArgs);
 
-  /// Produce notes explaining why a defaulted function was defined as deleted.
-  void DiagnoseDeletedDefaultedFunction(FunctionDecl *FD);
+  using ADLCallKind = CallExpr::ADLCallKind;
 
-  /// Declare the implicit default constructor for the given class.
-  ///
-  /// \param ClassDecl The class declaration into which the implicit
-  /// default constructor will be added.
-  ///
-  /// \returns The implicitly-declared default constructor.
-  CXXConstructorDecl *DeclareImplicitDefaultConstructor(
-                                                     CXXRecordDecl *ClassDecl);
+  ExprResult
+  BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc,
+                        ArrayRef Arg, SourceLocation RParenLoc,
+                        Expr *Config = nullptr, bool IsExecConfig = false,
+                        ADLCallKind UsesADL = ADLCallKind::NotADL);
 
-  /// DefineImplicitDefaultConstructor - Checks for feasibility of
-  /// defining this constructor as the default constructor.
-  void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
-                                        CXXConstructorDecl *Constructor);
+  ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, Declarator &D,
+                           ParsedType &Ty, SourceLocation RParenLoc,
+                           Expr *CastExpr);
 
-  /// Declare the implicit destructor for the given class.
-  ///
-  /// \param ClassDecl The class declaration into which the implicit
-  /// destructor will be added.
-  ///
-  /// \returns The implicitly-declared destructor.
-  CXXDestructorDecl *DeclareImplicitDestructor(CXXRecordDecl *ClassDecl);
+  CastKind PrepareScalarCast(ExprResult &src, QualType destType);
 
-  /// DefineImplicitDestructor - Checks for feasibility of
-  /// defining this destructor as the default destructor.
-  void DefineImplicitDestructor(SourceLocation CurrentLocation,
-                                CXXDestructorDecl *Destructor);
+  /// Build an altivec or OpenCL literal.
+  ExprResult BuildVectorLiteral(SourceLocation LParenLoc,
+                                SourceLocation RParenLoc, Expr *E,
+                                TypeSourceInfo *TInfo);
 
-  /// Build an exception spec for destructors that don't have one.
-  ///
-  /// C++11 says that user-defined destructors with no exception spec get one
-  /// that looks as if the destructor was implicitly declared.
-  void AdjustDestructorExceptionSpec(CXXDestructorDecl *Destructor);
+  ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME);
 
-  /// Define the specified inheriting constructor.
-  void DefineInheritingConstructor(SourceLocation UseLoc,
-                                   CXXConstructorDecl *Constructor);
+  ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
+                                  SourceLocation RParenLoc, Expr *InitExpr);
 
-  /// Declare the implicit copy constructor for the given class.
-  ///
-  /// \param ClassDecl The class declaration into which the implicit
-  /// copy constructor will be added.
-  ///
-  /// \returns The implicitly-declared copy constructor.
-  CXXConstructorDecl *DeclareImplicitCopyConstructor(CXXRecordDecl *ClassDecl);
+  ExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc,
+                                      TypeSourceInfo *TInfo,
+                                      SourceLocation RParenLoc,
+                                      Expr *LiteralExpr);
 
-  /// DefineImplicitCopyConstructor - Checks for feasibility of
-  /// defining this constructor as the copy constructor.
-  void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
-                                     CXXConstructorDecl *Constructor);
+  ExprResult ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
+                           SourceLocation RBraceLoc);
 
-  /// Declare the implicit move constructor for the given class.
-  ///
-  /// \param ClassDecl The Class declaration into which the implicit
-  /// move constructor will be added.
-  ///
-  /// \returns The implicitly-declared move constructor, or NULL if it wasn't
-  /// declared.
-  CXXConstructorDecl *DeclareImplicitMoveConstructor(CXXRecordDecl *ClassDecl);
+  ExprResult BuildInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
+                           SourceLocation RBraceLoc);
 
-  /// DefineImplicitMoveConstructor - Checks for feasibility of
-  /// defining this constructor as the move constructor.
-  void DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
-                                     CXXConstructorDecl *Constructor);
+  ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind,
+                        Expr *LHSExpr, Expr *RHSExpr);
+  ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc,
+                        Expr *LHSExpr, Expr *RHSExpr);
+  ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc,
+                                Expr *LHSExpr, Expr *RHSExpr);
+  void LookupBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc,
+                   UnresolvedSetImpl &Functions);
 
-  /// Declare the implicit copy assignment operator for the given class.
-  ///
-  /// \param ClassDecl The class declaration into which the implicit
-  /// copy assignment operator will be added.
-  ///
-  /// \returns The implicitly-declared copy assignment operator.
-  CXXMethodDecl *DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl);
+  void DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc);
 
-  /// Defines an implicitly-declared copy assignment operator.
-  void DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
-                                    CXXMethodDecl *MethodDecl);
+  /// ActOnConditionalOp - Parse a ?: operation.  Note that 'LHS' may be null
+  /// in the case of a the GNU conditional expr extension.
+  ExprResult ActOnConditionalOp(SourceLocation QuestionLoc,
+                                SourceLocation ColonLoc, Expr *CondExpr,
+                                Expr *LHSExpr, Expr *RHSExpr);
 
-  /// Declare the implicit move assignment operator for the given class.
-  ///
-  /// \param ClassDecl The Class declaration into which the implicit
-  /// move assignment operator will be added.
-  ///
-  /// \returns The implicitly-declared move assignment operator, or NULL if it
-  /// wasn't declared.
-  CXXMethodDecl *DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl);
+  /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
+  ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
+                            LabelDecl *TheDecl);
 
-  /// Defines an implicitly-declared move assignment operator.
-  void DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
-                                    CXXMethodDecl *MethodDecl);
+  void ActOnStartStmtExpr();
+  ExprResult ActOnStmtExpr(Scope *S, SourceLocation LPLoc, Stmt *SubStmt,
+                           SourceLocation RPLoc);
+  ExprResult BuildStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
+                           SourceLocation RPLoc, unsigned TemplateDepth);
+  // Handle the final expression in a statement expression.
+  ExprResult ActOnStmtExprResult(ExprResult E);
+  void ActOnStmtExprError();
 
-  /// Force the declaration of any implicitly-declared members of this
-  /// class.
-  void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class);
+  // __builtin_offsetof(type, identifier(.identifier|[expr])*)
+  struct OffsetOfComponent {
+    SourceLocation LocStart, LocEnd;
+    bool isBrackets; // true if [expr], false if .ident
+    union {
+      IdentifierInfo *IdentInfo;
+      Expr *E;
+    } U;
+  };
 
-  /// Check a completed declaration of an implicit special member.
-  void CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD);
+  /// __builtin_offsetof(type, a.b[123][456].c)
+  ExprResult BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,
+                                  TypeSourceInfo *TInfo,
+                                  ArrayRef Components,
+                                  SourceLocation RParenLoc);
+  ExprResult ActOnBuiltinOffsetOf(Scope *S, SourceLocation BuiltinLoc,
+                                  SourceLocation TypeLoc,
+                                  ParsedType ParsedArgTy,
+                                  ArrayRef Components,
+                                  SourceLocation RParenLoc);
 
-  /// Determine whether the given function is an implicitly-deleted
-  /// special member function.
-  bool isImplicitlyDeleted(FunctionDecl *FD);
+  // __builtin_choose_expr(constExpr, expr1, expr2)
+  ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc, Expr *CondExpr,
+                             Expr *LHSExpr, Expr *RHSExpr,
+                             SourceLocation RPLoc);
 
-  /// Check whether 'this' shows up in the type of a static member
-  /// function after the (naturally empty) cv-qualifier-seq would be.
-  ///
-  /// \returns true if an error occurred.
-  bool checkThisInStaticMemberFunctionType(CXXMethodDecl *Method);
+  // __builtin_va_arg(expr, type)
+  ExprResult ActOnVAArg(SourceLocation BuiltinLoc, Expr *E, ParsedType Ty,
+                        SourceLocation RPLoc);
+  ExprResult BuildVAArgExpr(SourceLocation BuiltinLoc, Expr *E,
+                            TypeSourceInfo *TInfo, SourceLocation RPLoc);
 
-  /// Whether this' shows up in the exception specification of a static
-  /// member function.
-  bool checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method);
+  // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FUNCSIG(),
+  // __builtin_FILE(), __builtin_COLUMN(), __builtin_source_location()
+  ExprResult ActOnSourceLocExpr(SourceLocIdentKind Kind,
+                                SourceLocation BuiltinLoc,
+                                SourceLocation RPLoc);
 
-  /// Check whether 'this' shows up in the attributes of the given
-  /// static member function.
-  ///
-  /// \returns true if an error occurred.
-  bool checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method);
+  // Build a potentially resolved SourceLocExpr.
+  ExprResult BuildSourceLocExpr(SourceLocIdentKind Kind, QualType ResultTy,
+                                SourceLocation BuiltinLoc, SourceLocation RPLoc,
+                                DeclContext *ParentContext);
 
-  /// MaybeBindToTemporary - If the passed in expression has a record type with
-  /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
-  /// it simply returns the passed in expression.
-  ExprResult MaybeBindToTemporary(Expr *E);
+  // __null
+  ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
 
-  /// Wrap the expression in a ConstantExpr if it is a potential immediate
-  /// invocation.
-  ExprResult CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl);
+  bool CheckCaseExpression(Expr *E);
 
-  bool CheckImmediateEscalatingFunctionDefinition(
-      FunctionDecl *FD, const sema::FunctionScopeInfo *FSI);
+  //===------------------------- "Block" Extension ------------------------===//
 
-  void MarkExpressionAsImmediateEscalating(Expr *E);
+  /// ActOnBlockStart - This callback is invoked when a block literal is
+  /// started.
+  void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
 
-  void DiagnoseImmediateEscalatingReason(FunctionDecl *FD);
+  /// ActOnBlockArguments - This callback allows processing of block arguments.
+  /// If there are no arguments, this is still invoked.
+  void ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo,
+                           Scope *CurScope);
 
-  bool CompleteConstructorCall(CXXConstructorDecl *Constructor,
-                               QualType DeclInitType, MultiExprArg ArgsPtr,
-                               SourceLocation Loc,
-                               SmallVectorImpl &ConvertedArgs,
-                               bool AllowExplicit = false,
-                               bool IsListInitialization = false);
+  /// ActOnBlockError - If there is an error parsing a block, this callback
+  /// is invoked to pop the information about the block from the action impl.
+  void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope);
 
-  ParsedType getInheritingConstructorName(CXXScopeSpec &SS,
-                                          SourceLocation NameLoc,
-                                          IdentifierInfo &Name);
+  /// ActOnBlockStmtExpr - This is called when the body of a block statement
+  /// literal was successfully completed.  ^(int x){...}
+  ExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body,
+                                Scope *CurScope);
 
-  ParsedType getConstructorName(IdentifierInfo &II, SourceLocation NameLoc,
-                                Scope *S, CXXScopeSpec &SS,
-                                bool EnteringContext);
-  ParsedType getDestructorName(IdentifierInfo &II, SourceLocation NameLoc,
-                               Scope *S, CXXScopeSpec &SS,
-                               ParsedType ObjectType, bool EnteringContext);
+  //===---------------------------- Clang Extensions ----------------------===//
 
-  ParsedType getDestructorTypeForDecltype(const DeclSpec &DS,
-                                          ParsedType ObjectType);
+  /// __builtin_convertvector(...)
+  ExprResult ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy,
+                                    SourceLocation BuiltinLoc,
+                                    SourceLocation RParenLoc);
 
-  // Checks that reinterpret casts don't have undefined behavior.
-  void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
-                                      bool IsDereference, SourceRange Range);
+  //===---------------------------- OpenCL Features -----------------------===//
 
-  // Checks that the vector type should be initialized from a scalar
-  // by splatting the value rather than populating a single element.
-  // This is the case for AltiVecVector types as well as with
-  // AltiVecPixel and AltiVecBool when -faltivec-src-compat=xl is specified.
-  bool ShouldSplatAltivecScalarInCast(const VectorType *VecTy);
+  /// __builtin_astype(...)
+  ExprResult ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
+                             SourceLocation BuiltinLoc,
+                             SourceLocation RParenLoc);
+  ExprResult BuildAsTypeExpr(Expr *E, QualType DestTy,
+                             SourceLocation BuiltinLoc,
+                             SourceLocation RParenLoc);
 
-  // Checks if the -faltivec-src-compat=gcc option is specified.
-  // If so, AltiVecVector, AltiVecBool and AltiVecPixel types are
-  // treated the same way as they are when trying to initialize
-  // these vectors on gcc (an error is emitted).
-  bool CheckAltivecInitFromScalar(SourceRange R, QualType VecTy,
-                                  QualType SrcTy);
+  /// Attempts to produce a RecoveryExpr after some AST node cannot be created.
+  ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End,
+                                ArrayRef SubExprs,
+                                QualType T = QualType());
 
-  /// ActOnCXXNamedCast - Parse
-  /// {dynamic,static,reinterpret,const,addrspace}_cast's.
-  ExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
-                               tok::TokenKind Kind,
-                               SourceLocation LAngleBracketLoc,
-                               Declarator &D,
-                               SourceLocation RAngleBracketLoc,
-                               SourceLocation LParenLoc,
-                               Expr *E,
-                               SourceLocation RParenLoc);
+  // Note that LK_String is intentionally after the other literals, as
+  // this is used for diagnostics logic.
+  enum ObjCLiteralKind {
+    LK_Array,
+    LK_Dictionary,
+    LK_Numeric,
+    LK_Boxed,
+    LK_String,
+    LK_Block,
+    LK_None
+  };
+  ObjCLiteralKind CheckLiteralKind(Expr *FromE);
 
-  ExprResult BuildCXXNamedCast(SourceLocation OpLoc,
-                               tok::TokenKind Kind,
-                               TypeSourceInfo *Ty,
-                               Expr *E,
-                               SourceRange AngleBrackets,
-                               SourceRange Parens);
+  ExprResult PerformObjectMemberConversion(Expr *From,
+                                           NestedNameSpecifier *Qualifier,
+                                           NamedDecl *FoundDecl,
+                                           NamedDecl *Member);
 
-  ExprResult ActOnBuiltinBitCastExpr(SourceLocation KWLoc, Declarator &Dcl,
-                                     ExprResult Operand,
-                                     SourceLocation RParenLoc);
+  /// CheckCallReturnType - Checks that a call expression's return type is
+  /// complete. Returns true on failure. The location passed in is the location
+  /// that best represents the call.
+  bool CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
+                           CallExpr *CE, FunctionDecl *FD);
 
-  ExprResult BuildBuiltinBitCastExpr(SourceLocation KWLoc, TypeSourceInfo *TSI,
-                                     Expr *Operand, SourceLocation RParenLoc);
+  /// Emit a warning for all pending noderef expressions that we recorded.
+  void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec);
 
-  ExprResult BuildCXXTypeId(QualType TypeInfoType,
-                            SourceLocation TypeidLoc,
-                            TypeSourceInfo *Operand,
-                            SourceLocation RParenLoc);
-  ExprResult BuildCXXTypeId(QualType TypeInfoType,
-                            SourceLocation TypeidLoc,
-                            Expr *Operand,
-                            SourceLocation RParenLoc);
+  ExprResult BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field);
 
-  /// ActOnCXXTypeid - Parse typeid( something ).
-  ExprResult ActOnCXXTypeid(SourceLocation OpLoc,
-                            SourceLocation LParenLoc, bool isType,
-                            void *TyOrExpr,
-                            SourceLocation RParenLoc);
+  /// Instantiate or parse a C++ default argument expression as necessary.
+  /// Return true on error.
+  bool CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
+                              ParmVarDecl *Param, Expr *Init = nullptr,
+                              bool SkipImmediateInvocations = true);
 
-  ExprResult BuildCXXUuidof(QualType TypeInfoType,
-                            SourceLocation TypeidLoc,
-                            TypeSourceInfo *Operand,
-                            SourceLocation RParenLoc);
-  ExprResult BuildCXXUuidof(QualType TypeInfoType,
-                            SourceLocation TypeidLoc,
-                            Expr *Operand,
-                            SourceLocation RParenLoc);
+  /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
+  /// the default expr if needed.
+  ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
+                                    ParmVarDecl *Param, Expr *Init = nullptr);
 
-  /// ActOnCXXUuidof - Parse __uuidof( something ).
-  ExprResult ActOnCXXUuidof(SourceLocation OpLoc,
-                            SourceLocation LParenLoc, bool isType,
-                            void *TyOrExpr,
-                            SourceLocation RParenLoc);
+  /// Wrap the expression in a ConstantExpr if it is a potential immediate
+  /// invocation.
+  ExprResult CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl);
 
-  /// Handle a C++1z fold-expression: ( expr op ... op expr ).
-  ExprResult ActOnCXXFoldExpr(Scope *S, SourceLocation LParenLoc, Expr *LHS,
-                              tok::TokenKind Operator,
-                              SourceLocation EllipsisLoc, Expr *RHS,
-                              SourceLocation RParenLoc);
-  ExprResult BuildCXXFoldExpr(UnresolvedLookupExpr *Callee,
-                              SourceLocation LParenLoc, Expr *LHS,
-                              BinaryOperatorKind Operator,
-                              SourceLocation EllipsisLoc, Expr *RHS,
-                              SourceLocation RParenLoc,
-                              std::optional NumExpansions);
-  ExprResult BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc,
-                                   BinaryOperatorKind Operator);
+  void MarkExpressionAsImmediateEscalating(Expr *E);
 
-  //// ActOnCXXThis -  Parse 'this' pointer.
-  ExprResult ActOnCXXThis(SourceLocation loc);
+  bool IsInvalidSMECallConversion(QualType FromType, QualType ToType);
 
-  /// Build a CXXThisExpr and mark it referenced in the current context.
-  Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit);
-  void MarkThisReferenced(CXXThisExpr *This);
+  const DeclContext *getCurObjCLexicalContext() const {
+    const DeclContext *DC = getCurLexicalContext();
+    // A category implicitly has the attribute of the interface.
+    if (const ObjCCategoryDecl *CatD = dyn_cast(DC))
+      DC = CatD->getClassInterface();
+    return DC;
+  }
 
-  /// Try to retrieve the type of the 'this' pointer.
-  ///
-  /// \returns The type of 'this', if possible. Otherwise, returns a NULL type.
-  QualType getCurrentThisType();
+  /// Abstract base class used for diagnosing integer constant
+  /// expression violations.
+  class VerifyICEDiagnoser {
+  public:
+    bool Suppress;
 
-  /// When non-NULL, the C++ 'this' expression is allowed despite the
-  /// current context not being a non-static member function. In such cases,
-  /// this provides the type used for 'this'.
-  QualType CXXThisTypeOverride;
+    VerifyICEDiagnoser(bool Suppress = false) : Suppress(Suppress) {}
 
-  /// RAII object used to temporarily allow the C++ 'this' expression
-  /// to be used, with the given qualifiers on the current class type.
-  class CXXThisScopeRAII {
-    Sema &S;
-    QualType OldCXXThisTypeOverride;
-    bool Enabled;
-
-  public:
-    /// Introduce a new scope where 'this' may be allowed (when enabled),
-    /// using the given declaration (which is either a class template or a
-    /// class) along with the given qualifiers.
-    /// along with the qualifiers placed on '*this'.
-    CXXThisScopeRAII(Sema &S, Decl *ContextDecl, Qualifiers CXXThisTypeQuals,
-                     bool Enabled = true);
-
-    ~CXXThisScopeRAII();
+    virtual SemaDiagnosticBuilder
+    diagnoseNotICEType(Sema &S, SourceLocation Loc, QualType T);
+    virtual SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
+                                                 SourceLocation Loc) = 0;
+    virtual SemaDiagnosticBuilder diagnoseFold(Sema &S, SourceLocation Loc);
+    virtual ~VerifyICEDiagnoser() {}
   };
 
-  /// Make sure the value of 'this' is actually available in the current
-  /// context, if it is a potentially evaluated context.
-  ///
-  /// \param Loc The location at which the capture of 'this' occurs.
-  ///
-  /// \param Explicit Whether 'this' is explicitly captured in a lambda
-  /// capture list.
-  ///
-  /// \param FunctionScopeIndexToStopAt If non-null, it points to the index
-  /// of the FunctionScopeInfo stack beyond which we do not attempt to capture.
-  /// This is useful when enclosing lambdas must speculatively capture
-  /// 'this' that may or may not be used in certain specializations of
-  /// a nested generic lambda (depending on whether the name resolves to
-  /// a non-static member function or a static function).
-  /// \return returns 'true' if failed, 'false' if success.
-  bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false,
-      bool BuildAndDiagnose = true,
-      const unsigned *const FunctionScopeIndexToStopAt = nullptr,
-      bool ByCopy = false);
+  enum AllowFoldKind {
+    NoFold,
+    AllowFold,
+  };
 
-  /// Determine whether the given type is the type of *this that is used
-  /// outside of the body of a member function for a type that is currently
-  /// being defined.
-  bool isThisOutsideMemberFunctionBody(QualType BaseType);
+  /// VerifyIntegerConstantExpression - Verifies that an expression is an ICE,
+  /// and reports the appropriate diagnostics. Returns false on success.
+  /// Can optionally return the value of the expression.
+  ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
+                                             VerifyICEDiagnoser &Diagnoser,
+                                             AllowFoldKind CanFold = NoFold);
+  ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
+                                             unsigned DiagID,
+                                             AllowFoldKind CanFold = NoFold);
+  ExprResult VerifyIntegerConstantExpression(Expr *E,
+                                             llvm::APSInt *Result = nullptr,
+                                             AllowFoldKind CanFold = NoFold);
+  ExprResult VerifyIntegerConstantExpression(Expr *E,
+                                             AllowFoldKind CanFold = NoFold) {
+    return VerifyIntegerConstantExpression(E, nullptr, CanFold);
+  }
 
-  /// ActOnCXXBoolLiteral - Parse {true,false} literals.
-  ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
+  /// DiagnoseAssignmentAsCondition - Given that an expression is
+  /// being used as a boolean condition, warn if it's an assignment.
+  void DiagnoseAssignmentAsCondition(Expr *E);
 
+  /// Redundant parentheses over an equality comparison can indicate
+  /// that the user intended an assignment used as condition.
+  void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE);
 
-  /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.
-  ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
+  class FullExprArg {
+  public:
+    FullExprArg() : E(nullptr) {}
+    FullExprArg(Sema &actions) : E(nullptr) {}
 
-  ExprResult
-  ActOnObjCAvailabilityCheckExpr(llvm::ArrayRef AvailSpecs,
-                                 SourceLocation AtLoc, SourceLocation RParen);
+    ExprResult release() { return E; }
 
-  /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
-  ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
+    Expr *get() const { return E; }
 
-  //// ActOnCXXThrow -  Parse throw expressions.
-  ExprResult ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *expr);
-  ExprResult BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
-                           bool IsThrownVarInScope);
-  bool CheckCXXThrowOperand(SourceLocation ThrowLoc, QualType ThrowTy, Expr *E);
+    Expr *operator->() { return E; }
 
-  /// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
-  /// Can be interpreted either as function-style casting ("int(x)")
-  /// or class type construction ("ClassType(x,y,z)")
-  /// or creation of a value-initialized type ("int()").
-  ExprResult ActOnCXXTypeConstructExpr(ParsedType TypeRep,
-                                       SourceLocation LParenOrBraceLoc,
-                                       MultiExprArg Exprs,
-                                       SourceLocation RParenOrBraceLoc,
-                                       bool ListInitialization);
+  private:
+    // FIXME: No need to make the entire Sema class a friend when it's just
+    // Sema::MakeFullExpr that needs access to the constructor below.
+    friend class Sema;
 
-  ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type,
-                                       SourceLocation LParenLoc,
-                                       MultiExprArg Exprs,
-                                       SourceLocation RParenLoc,
-                                       bool ListInitialization);
+    explicit FullExprArg(Expr *expr) : E(expr) {}
 
-  /// ActOnCXXNew - Parsed a C++ 'new' expression.
-  ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
-                         SourceLocation PlacementLParen,
-                         MultiExprArg PlacementArgs,
-                         SourceLocation PlacementRParen,
-                         SourceRange TypeIdParens, Declarator &D,
-                         Expr *Initializer);
-  ExprResult
-  BuildCXXNew(SourceRange Range, bool UseGlobal, SourceLocation PlacementLParen,
-              MultiExprArg PlacementArgs, SourceLocation PlacementRParen,
-              SourceRange TypeIdParens, QualType AllocType,
-              TypeSourceInfo *AllocTypeInfo, std::optional ArraySize,
-              SourceRange DirectInitRange, Expr *Initializer);
+    Expr *E;
+  };
 
-  /// Determine whether \p FD is an aligned allocation or deallocation
-  /// function that is unavailable.
-  bool isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const;
+  FullExprArg MakeFullExpr(Expr *Arg) {
+    return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation());
+  }
+  FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) {
+    return FullExprArg(
+        ActOnFinishFullExpr(Arg, CC, /*DiscardedValue*/ false).get());
+  }
+  FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) {
+    ExprResult FE =
+        ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(),
+                            /*DiscardedValue*/ true);
+    return FullExprArg(FE.get());
+  }
 
-  /// Produce diagnostics if \p FD is an aligned allocation or deallocation
-  /// function that is unavailable.
-  void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
-                                            SourceLocation Loc);
+  class ConditionResult {
+    Decl *ConditionVar;
+    FullExprArg Condition;
+    bool Invalid;
+    std::optional KnownValue;
 
-  bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
-                          SourceRange R);
+    friend class Sema;
+    ConditionResult(Sema &S, Decl *ConditionVar, FullExprArg Condition,
+                    bool IsConstexpr)
+        : ConditionVar(ConditionVar), Condition(Condition), Invalid(false) {
+      if (IsConstexpr && Condition.get()) {
+        if (std::optional Val =
+                Condition.get()->getIntegerConstantExpr(S.Context)) {
+          KnownValue = !!(*Val);
+        }
+      }
+    }
+    explicit ConditionResult(bool Invalid)
+        : ConditionVar(nullptr), Condition(nullptr), Invalid(Invalid),
+          KnownValue(std::nullopt) {}
 
-  /// The scope in which to find allocation functions.
-  enum AllocationFunctionScope {
-    /// Only look for allocation functions in the global scope.
-    AFS_Global,
-    /// Only look for allocation functions in the scope of the
-    /// allocated class.
-    AFS_Class,
-    /// Look for allocation functions in both the global scope
-    /// and in the scope of the allocated class.
-    AFS_Both
+  public:
+    ConditionResult() : ConditionResult(false) {}
+    bool isInvalid() const { return Invalid; }
+    std::pair get() const {
+      return std::make_pair(cast_or_null(ConditionVar),
+                            Condition.get());
+    }
+    std::optional getKnownValue() const { return KnownValue; }
   };
+  static ConditionResult ConditionError() { return ConditionResult(true); }
 
-  /// Finds the overloads of operator new and delete that are appropriate
-  /// for the allocation.
-  bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
-                               AllocationFunctionScope NewScope,
-                               AllocationFunctionScope DeleteScope,
-                               QualType AllocType, bool IsArray,
-                               bool &PassAlignment, MultiExprArg PlaceArgs,
-                               FunctionDecl *&OperatorNew,
-                               FunctionDecl *&OperatorDelete,
-                               bool Diagnose = true);
-  void DeclareGlobalNewDelete();
-  void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
-                                       ArrayRef Params);
+  /// CheckBooleanCondition - Diagnose problems involving the use of
+  /// the given expression as a boolean condition (e.g. in an if
+  /// statement).  Also performs the standard function and array
+  /// decays, possibly changing the input variable.
+  ///
+  /// \param Loc - A location associated with the condition, e.g. the
+  /// 'if' keyword.
+  /// \return true iff there were any errors
+  ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E,
+                                   bool IsConstexpr = false);
 
-  bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
-                                DeclarationName Name, FunctionDecl *&Operator,
-                                bool Diagnose = true, bool WantSize = false,
-                                bool WantAligned = false);
-  FunctionDecl *FindUsualDeallocationFunction(SourceLocation StartLoc,
-                                              bool CanProvideSize,
-                                              bool Overaligned,
-                                              DeclarationName Name);
-  FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc,
-                                                      CXXRecordDecl *RD);
+  enum class ConditionKind {
+    Boolean,     ///< A boolean condition, from 'if', 'while', 'for', or 'do'.
+    ConstexprIf, ///< A constant boolean condition from 'if constexpr'.
+    Switch       ///< An integral condition for a 'switch' statement.
+  };
 
-  /// ActOnCXXDelete - Parsed a C++ 'delete' expression
-  ExprResult ActOnCXXDelete(SourceLocation StartLoc,
-                            bool UseGlobal, bool ArrayForm,
-                            Expr *Operand);
-  void CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc,
-                            bool IsDelete, bool CallCanBeVirtual,
-                            bool WarnOnNonAbstractTypes,
-                            SourceLocation DtorLoc);
+  ConditionResult ActOnCondition(Scope *S, SourceLocation Loc, Expr *SubExpr,
+                                 ConditionKind CK, bool MissingOK = false);
 
-  ExprResult ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation LParen,
-                               Expr *Operand, SourceLocation RParen);
-  ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
-                                  SourceLocation RParen);
+  QualType CheckConditionalOperands( // C99 6.5.15
+      ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK,
+      ExprObjectKind &OK, SourceLocation QuestionLoc);
 
-  /// Parsed one of the type trait support pseudo-functions.
-  ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
-                            ArrayRef Args,
-                            SourceLocation RParenLoc);
-  ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
-                            ArrayRef Args,
-                            SourceLocation RParenLoc);
+  QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
+                                        SourceLocation QuestionLoc);
 
-  /// ActOnArrayTypeTrait - Parsed one of the binary type trait support
-  /// pseudo-functions.
-  ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT,
-                                 SourceLocation KWLoc,
-                                 ParsedType LhsTy,
-                                 Expr *DimExpr,
-                                 SourceLocation RParen);
+  bool DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr,
+                                  SourceLocation QuestionLoc);
 
-  ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT,
-                                 SourceLocation KWLoc,
-                                 TypeSourceInfo *TSInfo,
-                                 Expr *DimExpr,
-                                 SourceLocation RParen);
+  /// type checking for vector binary operators.
+  QualType CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
+                               SourceLocation Loc, bool IsCompAssign,
+                               bool AllowBothBool, bool AllowBoolConversion,
+                               bool AllowBoolOperation, bool ReportInvalid);
+  QualType GetSignedVectorType(QualType V);
+  QualType GetSignedSizelessVectorType(QualType V);
+  QualType CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
+                                      SourceLocation Loc,
+                                      BinaryOperatorKind Opc);
+  QualType CheckSizelessVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
+                                              SourceLocation Loc,
+                                              BinaryOperatorKind Opc);
+  QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
+                                      SourceLocation Loc);
 
-  /// ActOnExpressionTrait - Parsed one of the unary type trait support
-  /// pseudo-functions.
-  ExprResult ActOnExpressionTrait(ExpressionTrait OET,
-                                  SourceLocation KWLoc,
-                                  Expr *Queried,
-                                  SourceLocation RParen);
+  /// Context in which we're performing a usual arithmetic conversion.
+  enum ArithConvKind {
+    /// An arithmetic operation.
+    ACK_Arithmetic,
+    /// A bitwise operation.
+    ACK_BitwiseOp,
+    /// A comparison.
+    ACK_Comparison,
+    /// A conditional (?:) operator.
+    ACK_Conditional,
+    /// A compound assignment expression.
+    ACK_CompAssign,
+  };
 
-  ExprResult BuildExpressionTrait(ExpressionTrait OET,
-                                  SourceLocation KWLoc,
-                                  Expr *Queried,
-                                  SourceLocation RParen);
+  // type checking for sizeless vector binary operators.
+  QualType CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS,
+                                       SourceLocation Loc, bool IsCompAssign,
+                                       ArithConvKind OperationKind);
 
-  ExprResult ActOnStartCXXMemberReference(Scope *S,
-                                          Expr *Base,
-                                          SourceLocation OpLoc,
-                                          tok::TokenKind OpKind,
-                                          ParsedType &ObjectType,
-                                          bool &MayBePseudoDestructor);
+  /// Type checking for matrix binary operators.
+  QualType CheckMatrixElementwiseOperands(ExprResult &LHS, ExprResult &RHS,
+                                          SourceLocation Loc,
+                                          bool IsCompAssign);
+  QualType CheckMatrixMultiplyOperands(ExprResult &LHS, ExprResult &RHS,
+                                       SourceLocation Loc, bool IsCompAssign);
 
-  ExprResult BuildPseudoDestructorExpr(Expr *Base,
-                                       SourceLocation OpLoc,
-                                       tok::TokenKind OpKind,
-                                       const CXXScopeSpec &SS,
-                                       TypeSourceInfo *ScopeType,
-                                       SourceLocation CCLoc,
-                                       SourceLocation TildeLoc,
-                                     PseudoDestructorTypeStorage DestroyedType);
+  bool isValidSveBitcast(QualType srcType, QualType destType);
+  bool isValidRVVBitcast(QualType srcType, QualType destType);
 
-  ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
-                                       SourceLocation OpLoc,
-                                       tok::TokenKind OpKind,
-                                       CXXScopeSpec &SS,
-                                       UnqualifiedId &FirstTypeName,
-                                       SourceLocation CCLoc,
-                                       SourceLocation TildeLoc,
-                                       UnqualifiedId &SecondTypeName);
+  bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy);
 
-  ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
-                                       SourceLocation OpLoc,
-                                       tok::TokenKind OpKind,
-                                       SourceLocation TildeLoc,
-                                       const DeclSpec& DS);
+  bool areVectorTypesSameSize(QualType srcType, QualType destType);
+  bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
+  bool isLaxVectorConversion(QualType srcType, QualType destType);
+  bool anyAltivecTypes(QualType srcType, QualType destType);
 
-  /// MaybeCreateExprWithCleanups - If the current full-expression
-  /// requires any cleanups, surround it with a ExprWithCleanups node.
-  /// Otherwise, just returns the passed-in expression.
-  Expr *MaybeCreateExprWithCleanups(Expr *SubExpr);
-  Stmt *MaybeCreateStmtWithCleanups(Stmt *SubStmt);
-  ExprResult MaybeCreateExprWithCleanups(ExprResult SubExpr);
+  // type checking C++ declaration initializers (C++ [dcl.init]).
 
-  MaterializeTemporaryExpr *
-  CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
-                                 bool BoundToLvalueReference);
+  ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType,
+                                 Expr *CastExpr, CastKind &CastKind,
+                                 ExprValueKind &VK, CXXCastPath &Path);
 
-  ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue) {
-    return ActOnFinishFullExpr(
-        Expr, Expr ? Expr->getExprLoc() : SourceLocation(), DiscardedValue);
-  }
-  ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC,
-                                 bool DiscardedValue, bool IsConstexpr = false,
-                                 bool IsTemplateArgument = false);
-  StmtResult ActOnFinishFullStmt(Stmt *Stmt);
+  /// Force an expression with unknown-type to an expression of the
+  /// given type.
+  ExprResult forceUnknownAnyToType(Expr *E, QualType ToType);
 
-  // Marks SS invalid if it represents an incomplete type.
-  bool RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC);
-  // Complete an enum decl, maybe without a scope spec.
-  bool RequireCompleteEnumDecl(EnumDecl *D, SourceLocation L,
-                               CXXScopeSpec *SS = nullptr);
+  /// Type-check an expression that's being passed to an
+  /// __unknown_anytype parameter.
+  ExprResult checkUnknownAnyArg(SourceLocation callLoc, Expr *result,
+                                QualType ¶mType);
 
-  DeclContext *computeDeclContext(QualType T);
-  DeclContext *computeDeclContext(const CXXScopeSpec &SS,
-                                  bool EnteringContext = false);
-  bool isDependentScopeSpecifier(const CXXScopeSpec &SS);
-  CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
+  // CheckMatrixCast - Check type constraints for matrix casts.
+  // We allow casting between matrixes of the same dimensions i.e. when they
+  // have the same number of rows and column. Returns true if the cast is
+  // invalid.
+  bool CheckMatrixCast(SourceRange R, QualType DestTy, QualType SrcTy,
+                       CastKind &Kind);
 
-  /// The parser has parsed a global nested-name-specifier '::'.
-  ///
-  /// \param CCLoc The location of the '::'.
-  ///
-  /// \param SS The nested-name-specifier, which will be updated in-place
-  /// to reflect the parsed nested-name-specifier.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool ActOnCXXGlobalScopeSpecifier(SourceLocation CCLoc, CXXScopeSpec &SS);
+  // CheckVectorCast - check type constraints for vectors.
+  // Since vectors are an extension, there are no C standard reference for this.
+  // We allow casting between vectors and integer datatypes of the same size.
+  // returns true if the cast is invalid
+  bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
+                       CastKind &Kind);
 
-  /// The parser has parsed a '__super' nested-name-specifier.
-  ///
-  /// \param SuperLoc The location of the '__super' keyword.
-  ///
-  /// \param ColonColonLoc The location of the '::'.
-  ///
-  /// \param SS The nested-name-specifier, which will be updated in-place
-  /// to reflect the parsed nested-name-specifier.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool ActOnSuperScopeSpecifier(SourceLocation SuperLoc,
-                                SourceLocation ColonColonLoc, CXXScopeSpec &SS);
+  /// Prepare `SplattedExpr` for a vector splat operation, adding
+  /// implicit casts if necessary.
+  ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr);
 
-  bool isAcceptableNestedNameSpecifier(const NamedDecl *SD,
-                                       bool *CanCorrect = nullptr);
-  NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
+  // CheckExtVectorCast - check type constraints for extended vectors.
+  // Since vectors are an extension, there are no C standard reference for this.
+  // We allow casting between vectors and integer datatypes of the same size,
+  // or vectors and the element type of that vector.
+  // returns the cast expr
+  ExprResult CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *CastExpr,
+                                CastKind &Kind);
 
-  /// Keeps information about an identifier in a nested-name-spec.
-  ///
-  struct NestedNameSpecInfo {
-    /// The type of the object, if we're parsing nested-name-specifier in
-    /// a member access expression.
-    ParsedType ObjectType;
+  QualType PreferredConditionType(ConditionKind K) const {
+    return K == ConditionKind::Switch ? Context.IntTy : Context.BoolTy;
+  }
 
-    /// The identifier preceding the '::'.
-    IdentifierInfo *Identifier;
+  // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
+  // functions and arrays to their respective pointers (C99 6.3.2.1).
+  ExprResult UsualUnaryConversions(Expr *E);
 
-    /// The location of the identifier.
-    SourceLocation IdentifierLoc;
+  /// CallExprUnaryConversions - a special case of an unary conversion
+  /// performed on a function designator of a call expression.
+  ExprResult CallExprUnaryConversions(Expr *E);
 
-    /// The location of the '::'.
-    SourceLocation CCLoc;
+  // DefaultFunctionArrayConversion - converts functions and arrays
+  // to their respective pointers (C99 6.3.2.1).
+  ExprResult DefaultFunctionArrayConversion(Expr *E, bool Diagnose = true);
 
-    /// Creates info object for the most typical case.
-    NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc,
-             SourceLocation ColonColonLoc, ParsedType ObjectType = ParsedType())
-      : ObjectType(ObjectType), Identifier(II), IdentifierLoc(IdLoc),
-        CCLoc(ColonColonLoc) {
-    }
+  // DefaultFunctionArrayLvalueConversion - converts functions and
+  // arrays to their respective pointers and performs the
+  // lvalue-to-rvalue conversion.
+  ExprResult DefaultFunctionArrayLvalueConversion(Expr *E,
+                                                  bool Diagnose = true);
 
-    NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc,
-                       SourceLocation ColonColonLoc, QualType ObjectType)
-      : ObjectType(ParsedType::make(ObjectType)), Identifier(II),
-        IdentifierLoc(IdLoc), CCLoc(ColonColonLoc) {
-    }
-  };
+  // DefaultLvalueConversion - performs lvalue-to-rvalue conversion on
+  // the operand. This function is a no-op if the operand has a function type
+  // or an array type.
+  ExprResult DefaultLvalueConversion(Expr *E);
 
-  bool BuildCXXNestedNameSpecifier(Scope *S,
-                                   NestedNameSpecInfo &IdInfo,
-                                   bool EnteringContext,
-                                   CXXScopeSpec &SS,
-                                   NamedDecl *ScopeLookupResult,
-                                   bool ErrorRecoveryLookup,
-                                   bool *IsCorrectedToColon = nullptr,
-                                   bool OnlyNamespace = false);
+  // DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
+  // do not have a prototype. Integer promotions are performed on each
+  // argument, and arguments that have type float are promoted to double.
+  ExprResult DefaultArgumentPromotion(Expr *E);
 
-  /// The parser has parsed a nested-name-specifier 'identifier::'.
-  ///
-  /// \param S The scope in which this nested-name-specifier occurs.
-  ///
-  /// \param IdInfo Parser information about an identifier in the
-  /// nested-name-spec.
-  ///
-  /// \param EnteringContext Whether we're entering the context nominated by
-  /// this nested-name-specifier.
-  ///
-  /// \param SS The nested-name-specifier, which is both an input
-  /// parameter (the nested-name-specifier before this type) and an
-  /// output parameter (containing the full nested-name-specifier,
-  /// including this new type).
-  ///
-  /// \param IsCorrectedToColon If not null, suggestions to replace '::' -> ':'
-  /// are allowed.  The bool value pointed by this parameter is set to 'true'
-  /// if the identifier is treated as if it was followed by ':', not '::'.
-  ///
-  /// \param OnlyNamespace If true, only considers namespaces in lookup.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool ActOnCXXNestedNameSpecifier(Scope *S,
-                                   NestedNameSpecInfo &IdInfo,
-                                   bool EnteringContext,
-                                   CXXScopeSpec &SS,
-                                   bool *IsCorrectedToColon = nullptr,
-                                   bool OnlyNamespace = false);
+  VariadicCallType getVariadicCallType(FunctionDecl *FDecl,
+                                       const FunctionProtoType *Proto,
+                                       Expr *Fn);
 
-  ExprResult ActOnDecltypeExpression(Expr *E);
+  // Used for determining in which context a type is allowed to be passed to a
+  // vararg function.
+  enum VarArgKind {
+    VAK_Valid,
+    VAK_ValidInCXX11,
+    VAK_Undefined,
+    VAK_MSVCUndefined,
+    VAK_Invalid
+  };
 
-  bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
-                                           const DeclSpec &DS,
-                                           SourceLocation ColonColonLoc);
+  // Determines which VarArgKind fits an expression.
+  VarArgKind isValidVarArgType(const QualType &Ty);
 
-  bool ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS,
-                                              const DeclSpec &DS,
-                                              SourceLocation ColonColonLoc,
-                                              QualType Type);
+  /// Check to see if the given expression is a valid argument to a variadic
+  /// function, issuing a diagnostic if not.
+  void checkVariadicArgument(const Expr *E, VariadicCallType CT);
 
-  bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
-                                 NestedNameSpecInfo &IdInfo,
-                                 bool EnteringContext);
+  /// GatherArgumentsForCall - Collector argument expressions for various
+  /// form of call prototypes.
+  bool GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
+                              const FunctionProtoType *Proto,
+                              unsigned FirstParam, ArrayRef Args,
+                              SmallVectorImpl &AllArgs,
+                              VariadicCallType CallType = VariadicDoesNotApply,
+                              bool AllowExplicit = false,
+                              bool IsListInitialization = false);
 
-  bool IsInvalidSMECallConversion(QualType FromType, QualType ToType);
+  // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
+  // will create a runtime trap if the resulting type is not a POD type.
+  ExprResult DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
+                                              FunctionDecl *FDecl);
 
-  /// The parser has parsed a nested-name-specifier
-  /// 'template[opt] template-name < template-args >::'.
-  ///
-  /// \param S The scope in which this nested-name-specifier occurs.
-  ///
-  /// \param SS The nested-name-specifier, which is both an input
-  /// parameter (the nested-name-specifier before this type) and an
-  /// output parameter (containing the full nested-name-specifier,
-  /// including this new type).
-  ///
-  /// \param TemplateKWLoc the location of the 'template' keyword, if any.
-  /// \param TemplateName the template name.
-  /// \param TemplateNameLoc The location of the template name.
-  /// \param LAngleLoc The location of the opening angle bracket  ('<').
-  /// \param TemplateArgs The template arguments.
-  /// \param RAngleLoc The location of the closing angle bracket  ('>').
-  /// \param CCLoc The location of the '::'.
-  ///
-  /// \param EnteringContext Whether we're entering the context of the
-  /// nested-name-specifier.
-  ///
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool ActOnCXXNestedNameSpecifier(Scope *S,
-                                   CXXScopeSpec &SS,
-                                   SourceLocation TemplateKWLoc,
-                                   TemplateTy TemplateName,
-                                   SourceLocation TemplateNameLoc,
-                                   SourceLocation LAngleLoc,
-                                   ASTTemplateArgsPtr TemplateArgs,
-                                   SourceLocation RAngleLoc,
-                                   SourceLocation CCLoc,
-                                   bool EnteringContext);
+  // UsualArithmeticConversions - performs the UsualUnaryConversions on it's
+  // operands and then handles various conversions that are common to binary
+  // operators (C99 6.3.1.8). If both operands aren't arithmetic, this
+  // routine returns the first non-arithmetic type found. The client is
+  // responsible for emitting appropriate error diagnostics.
+  QualType UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
+                                      SourceLocation Loc, ArithConvKind ACK);
 
-  /// Given a C++ nested-name-specifier, produce an annotation value
-  /// that the parser can use later to reconstruct the given
-  /// nested-name-specifier.
-  ///
-  /// \param SS A nested-name-specifier.
-  ///
-  /// \returns A pointer containing all of the information in the
-  /// nested-name-specifier \p SS.
-  void *SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS);
+  /// AssignConvertType - All of the 'assignment' semantic checks return this
+  /// enum to indicate whether the assignment was allowed.  These checks are
+  /// done for simple assignments, as well as initialization, return from
+  /// function, argument passing, etc.  The query is phrased in terms of a
+  /// source and destination type.
+  enum AssignConvertType {
+    /// Compatible - the types are compatible according to the standard.
+    Compatible,
 
-  /// Given an annotation pointer for a nested-name-specifier, restore
-  /// the nested-name-specifier structure.
-  ///
-  /// \param Annotation The annotation pointer, produced by
-  /// \c SaveNestedNameSpecifierAnnotation().
-  ///
-  /// \param AnnotationRange The source range corresponding to the annotation.
-  ///
-  /// \param SS The nested-name-specifier that will be updated with the contents
-  /// of the annotation pointer.
-  void RestoreNestedNameSpecifierAnnotation(void *Annotation,
-                                            SourceRange AnnotationRange,
-                                            CXXScopeSpec &SS);
+    /// PointerToInt - The assignment converts a pointer to an int, which we
+    /// accept as an extension.
+    PointerToInt,
 
-  bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+    /// IntToPointer - The assignment converts an int to a pointer, which we
+    /// accept as an extension.
+    IntToPointer,
 
-  /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
-  /// scope or nested-name-specifier) is parsed, part of a declarator-id.
-  /// After this method is called, according to [C++ 3.4.3p3], names should be
-  /// looked up in the declarator-id's scope, until the declarator is parsed and
-  /// ActOnCXXExitDeclaratorScope is called.
-  /// The 'SS' should be a non-empty valid CXXScopeSpec.
-  bool ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS);
+    /// FunctionVoidPointer - The assignment is between a function pointer and
+    /// void*, which the standard doesn't allow, but we accept as an extension.
+    FunctionVoidPointer,
 
-  /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
-  /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same
-  /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well.
-  /// Used to indicate that names should revert to being looked up in the
-  /// defining scope.
-  void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+    /// IncompatiblePointer - The assignment is between two pointers types that
+    /// are not compatible, but we accept them as an extension.
+    IncompatiblePointer,
 
-  /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
-  /// initializer for the declaration 'Dcl'.
-  /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
-  /// static data member of class X, names should be looked up in the scope of
-  /// class X.
-  void ActOnCXXEnterDeclInitializer(Scope *S, Decl *Dcl);
+    /// IncompatibleFunctionPointer - The assignment is between two function
+    /// pointers types that are not compatible, but we accept them as an
+    /// extension.
+    IncompatibleFunctionPointer,
 
-  /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
-  /// initializer for the declaration 'Dcl'.
-  void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl);
+    /// IncompatibleFunctionPointerStrict - The assignment is between two
+    /// function pointer types that are not identical, but are compatible,
+    /// unless compiled with -fsanitize=cfi, in which case the type mismatch
+    /// may trip an indirect call runtime check.
+    IncompatibleFunctionPointerStrict,
 
-  /// Create a new lambda closure type.
-  CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
-                                         TypeSourceInfo *Info,
-                                         unsigned LambdaDependencyKind,
-                                         LambdaCaptureDefault CaptureDefault);
+    /// IncompatiblePointerSign - The assignment is between two pointers types
+    /// which point to integers which have a different sign, but are otherwise
+    /// identical. This is a subset of the above, but broken out because it's by
+    /// far the most common case of incompatible pointers.
+    IncompatiblePointerSign,
 
-  /// Number lambda for linkage purposes if necessary.
-  void handleLambdaNumbering(CXXRecordDecl *Class, CXXMethodDecl *Method,
-                             std::optional
-                                 NumberingOverride = std::nullopt);
+    /// CompatiblePointerDiscardsQualifiers - The assignment discards
+    /// c/v/r qualifiers, which we accept as an extension.
+    CompatiblePointerDiscardsQualifiers,
 
-  /// Endow the lambda scope info with the relevant properties.
-  void buildLambdaScope(sema::LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator,
-                        SourceRange IntroducerRange,
-                        LambdaCaptureDefault CaptureDefault,
-                        SourceLocation CaptureDefaultLoc, bool ExplicitParams,
-                        bool Mutable);
+    /// IncompatiblePointerDiscardsQualifiers - The assignment
+    /// discards qualifiers that we don't permit to be discarded,
+    /// like address spaces.
+    IncompatiblePointerDiscardsQualifiers,
 
-  CXXMethodDecl *CreateLambdaCallOperator(SourceRange IntroducerRange,
-                                          CXXRecordDecl *Class);
+    /// IncompatibleNestedPointerAddressSpaceMismatch - The assignment
+    /// changes address spaces in nested pointer types which is not allowed.
+    /// For instance, converting __private int ** to __generic int ** is
+    /// illegal even though __private could be converted to __generic.
+    IncompatibleNestedPointerAddressSpaceMismatch,
 
-  void AddTemplateParametersToLambdaCallOperator(
-      CXXMethodDecl *CallOperator, CXXRecordDecl *Class,
-      TemplateParameterList *TemplateParams);
+    /// IncompatibleNestedPointerQualifiers - The assignment is between two
+    /// nested pointer types, and the qualifiers other than the first two
+    /// levels differ e.g. char ** -> const char **, but we accept them as an
+    /// extension.
+    IncompatibleNestedPointerQualifiers,
 
-  void CompleteLambdaCallOperator(
-      CXXMethodDecl *Method, SourceLocation LambdaLoc,
-      SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause,
-      TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind,
-      StorageClass SC, ArrayRef Params,
-      bool HasExplicitResultType);
+    /// IncompatibleVectors - The assignment is between two vector types that
+    /// have the same size, which we accept as an extension.
+    IncompatibleVectors,
 
-  void DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method);
+    /// IntToBlockPointer - The assignment converts an int to a block
+    /// pointer. We disallow this.
+    IntToBlockPointer,
 
-  /// Perform initialization analysis of the init-capture and perform
-  /// any implicit conversions such as an lvalue-to-rvalue conversion if
-  /// not being used to initialize a reference.
-  ParsedType actOnLambdaInitCaptureInitialization(
-      SourceLocation Loc, bool ByRef, SourceLocation EllipsisLoc,
-      IdentifierInfo *Id, LambdaCaptureInitKind InitKind, Expr *&Init) {
-    return ParsedType::make(buildLambdaInitCaptureInitialization(
-        Loc, ByRef, EllipsisLoc, std::nullopt, Id,
-        InitKind != LambdaCaptureInitKind::CopyInit, Init));
-  }
-  QualType buildLambdaInitCaptureInitialization(
-      SourceLocation Loc, bool ByRef, SourceLocation EllipsisLoc,
-      std::optional NumExpansions, IdentifierInfo *Id,
-      bool DirectInit, Expr *&Init);
+    /// IncompatibleBlockPointer - The assignment is between two block
+    /// pointers types that are not compatible.
+    IncompatibleBlockPointer,
 
-  /// Create a dummy variable within the declcontext of the lambda's
-  ///  call operator, for name lookup purposes for a lambda init capture.
-  ///
-  ///  CodeGen handles emission of lambda captures, ignoring these dummy
-  ///  variables appropriately.
-  VarDecl *createLambdaInitCaptureVarDecl(
-      SourceLocation Loc, QualType InitCaptureType, SourceLocation EllipsisLoc,
-      IdentifierInfo *Id, unsigned InitStyle, Expr *Init, DeclContext *DeclCtx);
+    /// IncompatibleObjCQualifiedId - The assignment is between a qualified
+    /// id type and something else (that is incompatible with it). For example,
+    /// "id " = "Foo *", where "Foo *" doesn't implement the XXX protocol.
+    IncompatibleObjCQualifiedId,
 
-  /// Add an init-capture to a lambda scope.
-  void addInitCapture(sema::LambdaScopeInfo *LSI, VarDecl *Var, bool ByRef);
+    /// IncompatibleObjCWeakRef - Assigning a weak-unavailable object to an
+    /// object with __weak qualifier.
+    IncompatibleObjCWeakRef,
 
-  /// Note that we have finished the explicit captures for the
-  /// given lambda.
-  void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
+    /// Incompatible - We reject this conversion outright, it is invalid to
+    /// represent it in the AST.
+    Incompatible
+  };
 
-  /// Deduce a block or lambda's return type based on the return
-  /// statements present in the body.
-  void deduceClosureReturnType(sema::CapturingScopeInfo &CSI);
+  /// DiagnoseAssignmentResult - Emit a diagnostic, if required, for the
+  /// assignment conversion type specified by ConvTy.  This returns true if the
+  /// conversion was invalid or false if the conversion was accepted.
+  bool DiagnoseAssignmentResult(AssignConvertType ConvTy, SourceLocation Loc,
+                                QualType DstType, QualType SrcType,
+                                Expr *SrcExpr, AssignmentAction Action,
+                                bool *Complained = nullptr);
 
-  /// Once the Lambdas capture are known, we can start to create the closure,
-  /// call operator method, and keep track of the captures.
-  /// We do the capture lookup here, but they are not actually captured until
-  /// after we know what the qualifiers of the call operator are.
-  void ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
-                                            Scope *CurContext);
+  /// CheckAssignmentConstraints - Perform type checking for assignment,
+  /// argument passing, variable initialization, and function return values.
+  /// C99 6.5.16.
+  AssignConvertType CheckAssignmentConstraints(SourceLocation Loc,
+                                               QualType LHSType,
+                                               QualType RHSType);
 
-  /// This is called after parsing the explicit template parameter list
-  /// on a lambda (if it exists) in C++2a.
-  void ActOnLambdaExplicitTemplateParameterList(LambdaIntroducer &Intro,
-                                                SourceLocation LAngleLoc,
-                                                ArrayRef TParams,
-                                                SourceLocation RAngleLoc,
-                                                ExprResult RequiresClause);
+  /// Check assignment constraints and optionally prepare for a conversion of
+  /// the RHS to the LHS type. The conversion is prepared for if ConvertRHS
+  /// is true.
+  AssignConvertType CheckAssignmentConstraints(QualType LHSType,
+                                               ExprResult &RHS, CastKind &Kind,
+                                               bool ConvertRHS = true);
 
-  void ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro,
-                                    SourceLocation MutableLoc);
+  /// Check assignment constraints for an assignment of RHS to LHSType.
+  ///
+  /// \param LHSType The destination type for the assignment.
+  /// \param RHS The source expression for the assignment.
+  /// \param Diagnose If \c true, diagnostics may be produced when checking
+  ///        for assignability. If a diagnostic is produced, \p RHS will be
+  ///        set to ExprError(). Note that this function may still return
+  ///        without producing a diagnostic, even for an invalid assignment.
+  /// \param DiagnoseCFAudited If \c true, the target is a function parameter
+  ///        in an audited Core Foundation API and does not need to be checked
+  ///        for ARC retain issues.
+  /// \param ConvertRHS If \c true, \p RHS will be updated to model the
+  ///        conversions necessary to perform the assignment. If \c false,
+  ///        \p Diagnose must also be \c false.
+  AssignConvertType CheckSingleAssignmentConstraints(
+      QualType LHSType, ExprResult &RHS, bool Diagnose = true,
+      bool DiagnoseCFAudited = false, bool ConvertRHS = true);
 
-  void ActOnLambdaClosureParameters(
-      Scope *LambdaScope,
-      MutableArrayRef ParamInfo);
+  // If the lhs type is a transparent union, check whether we
+  // can initialize the transparent union with the given expression.
+  AssignConvertType CheckTransparentUnionArgumentConstraints(QualType ArgType,
+                                                             ExprResult &RHS);
 
-  /// ActOnStartOfLambdaDefinition - This is called just before we start
-  /// parsing the body of a lambda; it analyzes the explicit captures and
-  /// arguments, and sets up various data-structures for the body of the
-  /// lambda.
-  void ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
-                                    Declarator &ParamInfo, const DeclSpec &DS);
+  /// the following "Check" methods will return a valid/converted QualType
+  /// or a null QualType (indicating an error diagnostic was issued).
 
-  /// ActOnLambdaError - If there is an error parsing a lambda, this callback
-  /// is invoked to pop the information about the lambda.
-  void ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
-                        bool IsInstantiation = false);
-
-  /// ActOnLambdaExpr - This is called when the body of a lambda expression
-  /// was successfully completed.
-  ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body);
-
-  /// Does copying/destroying the captured variable have side effects?
-  bool CaptureHasSideEffects(const sema::Capture &From);
-
-  /// Diagnose if an explicit lambda capture is unused. Returns true if a
-  /// diagnostic is emitted.
-  bool DiagnoseUnusedLambdaCapture(SourceRange CaptureRange,
-                                   const sema::Capture &From);
-
-  /// Build a FieldDecl suitable to hold the given capture.
-  FieldDecl *BuildCaptureField(RecordDecl *RD, const sema::Capture &Capture);
+  /// type checking binary operators (subroutines of CreateBuiltinBinOp).
+  QualType InvalidOperands(SourceLocation Loc, ExprResult &LHS,
+                           ExprResult &RHS);
+  QualType InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS,
+                                        ExprResult &RHS);
 
-  /// Initialize the given capture with a suitable expression.
-  ExprResult BuildCaptureInit(const sema::Capture &Capture,
-                              SourceLocation ImplicitCaptureLoc,
-                              bool IsOpenMPMapping = false);
+  QualType CheckMultiplyDivideOperands( // C99 6.5.5
+      ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign,
+      bool IsDivide);
+  QualType CheckRemainderOperands( // C99 6.5.5
+      ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+      bool IsCompAssign = false);
+  QualType CheckAdditionOperands( // C99 6.5.6
+      ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+      BinaryOperatorKind Opc, QualType *CompLHSTy = nullptr);
+  QualType CheckSubtractionOperands( // C99 6.5.6
+      ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+      QualType *CompLHSTy = nullptr);
+  QualType CheckShiftOperands( // C99 6.5.7
+      ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+      BinaryOperatorKind Opc, bool IsCompAssign = false);
+  void CheckPtrComparisonWithNullChar(ExprResult &E, ExprResult &NullE);
+  QualType CheckCompareOperands( // C99 6.5.8/9
+      ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+      BinaryOperatorKind Opc);
+  QualType CheckBitwiseOperands( // C99 6.5.[10...12]
+      ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+      BinaryOperatorKind Opc);
+  QualType CheckLogicalOperands( // C99 6.5.[13,14]
+      ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
+      BinaryOperatorKind Opc);
+  // CheckAssignmentOperands is used for both simple and compound assignment.
+  // For simple assignment, pass both expressions and a null converted type.
+  // For compound assignment, pass both expressions and the converted type.
+  QualType CheckAssignmentOperands( // C99 6.5.16.[1,2]
+      Expr *LHSExpr, ExprResult &RHS, SourceLocation Loc, QualType CompoundType,
+      BinaryOperatorKind Opc);
 
-  /// Complete a lambda-expression having processed and attached the
-  /// lambda body.
-  ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
-                             sema::LambdaScopeInfo *LSI);
+  bool CheckConversionToObjCLiteral(QualType DstType, Expr *&SrcExpr,
+                                    bool Diagnose = true);
 
-  /// Get the return type to use for a lambda's conversion function(s) to
-  /// function pointer type, given the type of the call operator.
-  QualType
-  getLambdaConversionFunctionResultType(const FunctionProtoType *CallOpType,
-                                        CallingConv CC);
+  /// To be used for checking whether the arguments being passed to
+  /// function exceeds the number of parameters expected for it.
+  static bool TooManyArguments(size_t NumParams, size_t NumArgs,
+                               bool PartialOverloading = false) {
+    // We check whether we're just after a comma in code-completion.
+    if (NumArgs > 0 && PartialOverloading)
+      return NumArgs + 1 > NumParams; // If so, we view as an extra argument.
+    return NumArgs > NumParams;
+  }
 
-  /// Define the "body" of the conversion from a lambda object to a
-  /// function pointer.
-  ///
-  /// This routine doesn't actually define a sensible body; rather, it fills
-  /// in the initialization expression needed to copy the lambda object into
-  /// the block, and IR generation actually generates the real body of the
-  /// block pointer conversion.
-  void DefineImplicitLambdaToFunctionPointerConversion(
-         SourceLocation CurrentLoc, CXXConversionDecl *Conv);
+  /// Whether the AST is currently being rebuilt to correct immediate
+  /// invocations. Immediate invocation candidates and references to consteval
+  /// functions aren't tracked when this is set.
+  bool RebuildingImmediateInvocation = false;
 
-  /// Define the "body" of the conversion from a lambda object to a
-  /// block pointer.
-  ///
-  /// This routine doesn't actually define a sensible body; rather, it fills
-  /// in the initialization expression needed to copy the lambda object into
-  /// the block, and IR generation actually generates the real body of the
-  /// block pointer conversion.
-  void DefineImplicitLambdaToBlockPointerConversion(SourceLocation CurrentLoc,
-                                                    CXXConversionDecl *Conv);
+  bool isAlwaysConstantEvaluatedContext() const {
+    const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
+    return (Ctx.isConstantEvaluated() || isConstantEvaluatedOverride) &&
+           !Ctx.InConditionallyConstantEvaluateContext;
+  }
 
-  ExprResult BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
-                                           SourceLocation ConvLocation,
-                                           CXXConversionDecl *Conv,
-                                           Expr *Src);
+  /// Determines whether we are currently in a context that
+  /// is not evaluated as per C++ [expr] p5.
+  bool isUnevaluatedContext() const {
+    return currentEvaluationContext().isUnevaluated();
+  }
 
-  sema::LambdaScopeInfo *RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator);
+  bool isImmediateFunctionContext() const {
+    return currentEvaluationContext().isImmediateFunctionContext();
+  }
 
-  class LambdaScopeForCallOperatorInstantiationRAII
-      : private FunctionScopeRAII {
-  public:
-    LambdaScopeForCallOperatorInstantiationRAII(
-        Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL,
-        LocalInstantiationScope &Scope,
-        bool ShouldAddDeclsFromParentScope = true);
-  };
+  bool isInLifetimeExtendingContext() const {
+    assert(!ExprEvalContexts.empty() &&
+           "Must be in an expression evaluation context");
+    return ExprEvalContexts.back().InLifetimeExtendingContext;
+  }
 
-  /// Check whether the given expression is a valid constraint expression.
-  /// A diagnostic is emitted if it is not, false is returned, and
-  /// PossibleNonPrimary will be set to true if the failure might be due to a
-  /// non-primary expression being used as an atomic constraint.
-  bool CheckConstraintExpression(const Expr *CE, Token NextToken = Token(),
-                                 bool *PossibleNonPrimary = nullptr,
-                                 bool IsTrailingRequiresClause = false);
+  bool isCheckingDefaultArgumentOrInitializer() const {
+    const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
+    return (Ctx.Context ==
+            ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed) ||
+           Ctx.IsCurrentlyCheckingDefaultArgumentOrInitializer;
+  }
 
-private:
-  /// Caches pairs of template-like decls whose associated constraints were
-  /// checked for subsumption and whether or not the first's constraints did in
-  /// fact subsume the second's.
-  llvm::DenseMap, bool> SubsumptionCache;
-  /// Caches the normalized associated constraints of declarations (concepts or
-  /// constrained declarations). If an error occurred while normalizing the
-  /// associated constraints of the template or concept, nullptr will be cached
-  /// here.
-  llvm::DenseMap
-      NormalizationCache;
+  std::optional
+  InnermostDeclarationWithDelayedImmediateInvocations() const {
+    assert(!ExprEvalContexts.empty() &&
+           "Must be in an expression evaluation context");
+    for (const auto &Ctx : llvm::reverse(ExprEvalContexts)) {
+      if (Ctx.Context == ExpressionEvaluationContext::PotentiallyEvaluated &&
+          Ctx.DelayedDefaultInitializationContext)
+        return Ctx.DelayedDefaultInitializationContext;
+      if (Ctx.isConstantEvaluated() || Ctx.isImmediateFunctionContext() ||
+          Ctx.isUnevaluated())
+        break;
+    }
+    return std::nullopt;
+  }
 
-  llvm::ContextualFoldingSet
-      SatisfactionCache;
+  std::optional
+  OutermostDeclarationWithDelayedImmediateInvocations() const {
+    assert(!ExprEvalContexts.empty() &&
+           "Must be in an expression evaluation context");
+    std::optional Res;
+    for (auto &Ctx : llvm::reverse(ExprEvalContexts)) {
+      if (Ctx.Context == ExpressionEvaluationContext::PotentiallyEvaluated &&
+          !Ctx.DelayedDefaultInitializationContext && Res)
+        break;
+      if (Ctx.isConstantEvaluated() || Ctx.isImmediateFunctionContext() ||
+          Ctx.isUnevaluated())
+        break;
+      Res = Ctx.DelayedDefaultInitializationContext;
+    }
+    return Res;
+  }
 
-  /// Introduce the instantiated local variables into the local
-  /// instantiation scope.
-  void addInstantiatedLocalVarsToScope(FunctionDecl *Function,
-                                       const FunctionDecl *PatternDecl,
-                                       LocalInstantiationScope &Scope);
-  /// Introduce the instantiated function parameters into the local
-  /// instantiation scope, and set the parameter names to those used
-  /// in the template.
-  bool addInstantiatedParametersToScope(
-      FunctionDecl *Function, const FunctionDecl *PatternDecl,
-      LocalInstantiationScope &Scope,
-      const MultiLevelTemplateArgumentList &TemplateArgs);
+  /// keepInLifetimeExtendingContext - Pull down InLifetimeExtendingContext
+  /// flag from previous context.
+  void keepInLifetimeExtendingContext() {
+    if (ExprEvalContexts.size() > 2 &&
+        ExprEvalContexts[ExprEvalContexts.size() - 2]
+            .InLifetimeExtendingContext) {
+      auto &LastRecord = ExprEvalContexts.back();
+      auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2];
+      LastRecord.InLifetimeExtendingContext =
+          PrevRecord.InLifetimeExtendingContext;
+    }
+  }
 
-  /// Introduce the instantiated captures of the lambda into the local
-  /// instantiation scope.
-  bool addInstantiatedCapturesToScope(
-      FunctionDecl *Function, const FunctionDecl *PatternDecl,
-      LocalInstantiationScope &Scope,
-      const MultiLevelTemplateArgumentList &TemplateArgs);
+  /// keepInMaterializeTemporaryObjectContext - Pull down
+  /// InMaterializeTemporaryObjectContext flag from previous context.
+  void keepInMaterializeTemporaryObjectContext() {
+    if (ExprEvalContexts.size() > 2 &&
+        ExprEvalContexts[ExprEvalContexts.size() - 2]
+            .InMaterializeTemporaryObjectContext) {
+      auto &LastRecord = ExprEvalContexts.back();
+      auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2];
+      LastRecord.InMaterializeTemporaryObjectContext =
+          PrevRecord.InMaterializeTemporaryObjectContext;
+    }
+  }
 
-  /// used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in
-  /// the case of lambdas) set up the LocalInstantiationScope of the current
-  /// function.
-  bool SetupConstraintScope(
-      FunctionDecl *FD, std::optional> TemplateArgs,
-      MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope);
+  DefaultedComparisonKind getDefaultedComparisonKind(const FunctionDecl *FD) {
+    return getDefaultedFunctionKind(FD).asComparison();
+  }
 
-  /// Used during constraint checking, sets up the constraint template argument
-  /// lists, and calls SetupConstraintScope to set up the
-  /// LocalInstantiationScope to have the proper set of ParVarDecls configured.
-  std::optional
-  SetupConstraintCheckingTemplateArgumentsAndScope(
-      FunctionDecl *FD, std::optional> TemplateArgs,
-      LocalInstantiationScope &Scope);
+  /// Returns a field in a CXXRecordDecl that has the same name as the decl \p
+  /// SelfAssigned when inside a CXXMethodDecl.
+  const FieldDecl *
+  getSelfAssignmentClassMemberCandidate(const ValueDecl *SelfAssigned);
 
-private:
-  // The current stack of constraint satisfactions, so we can exit-early.
-  using SatisfactionStackEntryTy =
-      std::pair;
-  llvm::SmallVector
-      SatisfactionStack;
+  void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D);
 
-public:
-  void PushSatisfactionStackEntry(const NamedDecl *D,
-                                  const llvm::FoldingSetNodeID &ID) {
-    const NamedDecl *Can = cast(D->getCanonicalDecl());
-    SatisfactionStack.emplace_back(Can, ID);
+  template 
+  bool RequireCompleteSizedType(SourceLocation Loc, QualType T, unsigned DiagID,
+                                const Ts &...Args) {
+    SizelessTypeDiagnoser Diagnoser(DiagID, Args...);
+    return RequireCompleteType(Loc, T, CompleteTypeKind::Normal, Diagnoser);
   }
 
-  void PopSatisfactionStackEntry() { SatisfactionStack.pop_back(); }
-
-  bool SatisfactionStackContains(const NamedDecl *D,
-                                 const llvm::FoldingSetNodeID &ID) const {
-    const NamedDecl *Can = cast(D->getCanonicalDecl());
-    return llvm::find(SatisfactionStack,
-                      SatisfactionStackEntryTy{Can, ID}) !=
-           SatisfactionStack.end();
+  template 
+  bool RequireCompleteSizedExprType(Expr *E, unsigned DiagID,
+                                    const Ts &...Args) {
+    SizelessTypeDiagnoser Diagnoser(DiagID, Args...);
+    return RequireCompleteExprType(E, CompleteTypeKind::Normal, Diagnoser);
   }
 
-  // Resets the current SatisfactionStack for cases where we are instantiating
-  // constraints as a 'side effect' of normal instantiation in a way that is not
-  // indicative of recursive definition.
-  class SatisfactionStackResetRAII {
-    llvm::SmallVector
-        BackupSatisfactionStack;
-    Sema &SemaRef;
+  /// Abstract class used to diagnose incomplete types.
+  struct TypeDiagnoser {
+    TypeDiagnoser() {}
+
+    virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0;
+    virtual ~TypeDiagnoser() {}
+  };
+
+  template  class BoundTypeDiagnoser : public TypeDiagnoser {
+  protected:
+    unsigned DiagID;
+    std::tuple Args;
+
+    template 
+    void emit(const SemaDiagnosticBuilder &DB,
+              std::index_sequence) const {
+      // Apply all tuple elements to the builder in order.
+      bool Dummy[] = {false, (DB << getPrintable(std::get(Args)))...};
+      (void)Dummy;
+    }
 
   public:
-    SatisfactionStackResetRAII(Sema &S) : SemaRef(S) {
-      SemaRef.SwapSatisfactionStack(BackupSatisfactionStack);
+    BoundTypeDiagnoser(unsigned DiagID, const Ts &...Args)
+        : TypeDiagnoser(), DiagID(DiagID), Args(Args...) {
+      assert(DiagID != 0 && "no diagnostic for type diagnoser");
     }
 
-    ~SatisfactionStackResetRAII() {
-      SemaRef.SwapSatisfactionStack(BackupSatisfactionStack);
+    void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
+      const SemaDiagnosticBuilder &DB = S.Diag(Loc, DiagID);
+      emit(DB, std::index_sequence_for());
+      DB << T;
     }
   };
 
-  void SwapSatisfactionStack(
-      llvm::SmallVectorImpl &NewSS) {
-    SatisfactionStack.swap(NewSS);
-  }
+  /// A derivative of BoundTypeDiagnoser for which the diagnostic's type
+  /// parameter is preceded by a 0/1 enum that is 1 if the type is sizeless.
+  /// For example, a diagnostic with no other parameters would generally have
+  /// the form "...%select{incomplete|sizeless}0 type %1...".
+  template 
+  class SizelessTypeDiagnoser : public BoundTypeDiagnoser {
+  public:
+    SizelessTypeDiagnoser(unsigned DiagID, const Ts &...Args)
+        : BoundTypeDiagnoser(DiagID, Args...) {}
 
-  const NormalizedConstraint *
-  getNormalizedAssociatedConstraints(
-      NamedDecl *ConstrainedDecl, ArrayRef AssociatedConstraints);
+    void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
+      const SemaDiagnosticBuilder &DB = S.Diag(Loc, this->DiagID);
+      this->emit(DB, std::index_sequence_for());
+      DB << T->isSizelessType() << T;
+    }
+  };
 
-  /// \brief Check whether the given declaration's associated constraints are
-  /// at least as constrained than another declaration's according to the
-  /// partial ordering of constraints.
-  ///
-  /// \param Result If no error occurred, receives the result of true if D1 is
-  /// at least constrained than D2, and false otherwise.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool IsAtLeastAsConstrained(NamedDecl *D1, MutableArrayRef AC1,
-                              NamedDecl *D2, MutableArrayRef AC2,
-                              bool &Result);
+  /// Check an argument list for placeholders that we won't try to
+  /// handle later.
+  bool CheckArgsForPlaceholders(MultiExprArg args);
 
-  /// If D1 was not at least as constrained as D2, but would've been if a pair
-  /// of atomic constraints involved had been declared in a concept and not
-  /// repeated in two separate places in code.
-  /// \returns true if such a diagnostic was emitted, false otherwise.
-  bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
-      ArrayRef AC1, NamedDecl *D2, ArrayRef AC2);
+  /// The C++ "std::source_location::__impl" struct, defined in
+  /// \.
+  RecordDecl *StdSourceLocationImplDecl;
 
-  /// \brief Check whether the given list of constraint expressions are
-  /// satisfied (as if in a 'conjunction') given template arguments.
-  /// \param Template the template-like entity that triggered the constraints
-  /// check (either a concept or a constrained entity).
-  /// \param ConstraintExprs a list of constraint expressions, treated as if
-  /// they were 'AND'ed together.
-  /// \param TemplateArgLists the list of template arguments to substitute into
-  /// the constraint expression.
-  /// \param TemplateIDRange The source range of the template id that
-  /// caused the constraints check.
-  /// \param Satisfaction if true is returned, will contain details of the
-  /// satisfaction, with enough information to diagnose an unsatisfied
-  /// expression.
-  /// \returns true if an error occurred and satisfaction could not be checked,
-  /// false otherwise.
-  bool CheckConstraintSatisfaction(
-      const NamedDecl *Template, ArrayRef ConstraintExprs,
-      const MultiLevelTemplateArgumentList &TemplateArgLists,
-      SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
-    llvm::SmallVector Converted;
-    return CheckConstraintSatisfaction(Template, ConstraintExprs, Converted,
-                                       TemplateArgLists, TemplateIDRange,
-                                       Satisfaction);
-  }
+  /// A stack of expression evaluation contexts.
+  SmallVector ExprEvalContexts;
 
-  /// \brief Check whether the given list of constraint expressions are
-  /// satisfied (as if in a 'conjunction') given template arguments.
-  /// Additionally, takes an empty list of Expressions which is populated with
-  /// the instantiated versions of the ConstraintExprs.
-  /// \param Template the template-like entity that triggered the constraints
-  /// check (either a concept or a constrained entity).
-  /// \param ConstraintExprs a list of constraint expressions, treated as if
-  /// they were 'AND'ed together.
-  /// \param ConvertedConstraints a out parameter that will get populated with
-  /// the instantiated version of the ConstraintExprs if we successfully checked
-  /// satisfaction.
-  /// \param TemplateArgList the multi-level list of template arguments to
-  /// substitute into the constraint expression. This should be relative to the
-  /// top-level (hence multi-level), since we need to instantiate fully at the
-  /// time of checking.
-  /// \param TemplateIDRange The source range of the template id that
-  /// caused the constraints check.
-  /// \param Satisfaction if true is returned, will contain details of the
-  /// satisfaction, with enough information to diagnose an unsatisfied
-  /// expression.
-  /// \returns true if an error occurred and satisfaction could not be checked,
-  /// false otherwise.
-  bool CheckConstraintSatisfaction(
-      const NamedDecl *Template, ArrayRef ConstraintExprs,
-      llvm::SmallVectorImpl &ConvertedConstraints,
-      const MultiLevelTemplateArgumentList &TemplateArgList,
-      SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
+  // Set of failed immediate invocations to avoid double diagnosing.
+  llvm::SmallPtrSet FailedImmediateInvocations;
 
-  /// \brief Check whether the given non-dependent constraint expression is
-  /// satisfied. Returns false and updates Satisfaction with the satisfaction
-  /// verdict if successful, emits a diagnostic and returns true if an error
-  /// occurred and satisfaction could not be determined.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool CheckConstraintSatisfaction(const Expr *ConstraintExpr,
-                                   ConstraintSatisfaction &Satisfaction);
+  /// List of SourceLocations where 'self' is implicitly retained inside a
+  /// block.
+  llvm::SmallVector, 1>
+      ImplicitlyRetainedSelfLocs;
 
-  /// Check whether the given function decl's trailing requires clause is
-  /// satisfied, if any. Returns false and updates Satisfaction with the
-  /// satisfaction verdict if successful, emits a diagnostic and returns true if
-  /// an error occurred and satisfaction could not be determined.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool CheckFunctionConstraints(const FunctionDecl *FD,
-                                ConstraintSatisfaction &Satisfaction,
-                                SourceLocation UsageLoc = SourceLocation(),
-                                bool ForOverloadResolution = false);
+private:
+  static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind);
 
-  /// \brief Ensure that the given template arguments satisfy the constraints
-  /// associated with the given template, emitting a diagnostic if they do not.
-  ///
-  /// \param Template The template to which the template arguments are being
-  /// provided.
-  ///
-  /// \param TemplateArgs The converted, canonicalized template arguments.
-  ///
-  /// \param TemplateIDRange The source range of the template id that
-  /// caused the constraints check.
-  ///
-  /// \returns true if the constrains are not satisfied or could not be checked
-  /// for satisfaction, false if the constraints are satisfied.
-  bool EnsureTemplateArgumentListConstraints(
-      TemplateDecl *Template,
-      const MultiLevelTemplateArgumentList &TemplateArgs,
-      SourceRange TemplateIDRange);
+  /// Methods for marking which expressions involve dereferencing a pointer
+  /// marked with the 'noderef' attribute. Expressions are checked bottom up as
+  /// they are parsed, meaning that a noderef pointer may not be accessed. For
+  /// example, in `&*p` where `p` is a noderef pointer, we will first parse the
+  /// `*p`, but need to check that `address of` is called on it. This requires
+  /// keeping a container of all pending expressions and checking if the address
+  /// of them are eventually taken.
+  void CheckSubscriptAccessOfNoDeref(const ArraySubscriptExpr *E);
+  void CheckAddressOfNoDeref(const Expr *E);
 
-  /// \brief Emit diagnostics explaining why a constraint expression was deemed
-  /// unsatisfied.
-  /// \param First whether this is the first time an unsatisfied constraint is
-  /// diagnosed for this error.
-  void
-  DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction,
-                                bool First = true);
+  ///@}
 
-  /// \brief Emit diagnostics explaining why a constraint expression was deemed
-  /// unsatisfied.
-  void
-  DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction,
-                                bool First = true);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  // ParseObjCStringLiteral - Parse Objective-C string literals.
-  ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
-                                    ArrayRef Strings);
+  /// \name C++ Expressions
+  /// Implementations are in SemaExprCXX.cpp
+  ///@{
 
-  ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S);
+public:
+  /// The C++ "std::bad_alloc" class, which is defined by the C++
+  /// standard library.
+  LazyDeclPtr StdBadAlloc;
 
-  /// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the
-  /// numeric literal expression. Type of the expression will be "NSNumber *"
-  /// or "id" if NSNumber is unavailable.
-  ExprResult BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number);
-  ExprResult ActOnObjCBoolLiteral(SourceLocation AtLoc, SourceLocation ValueLoc,
-                                  bool Value);
-  ExprResult BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements);
+  /// The C++ "std::align_val_t" enum class, which is defined by the C++
+  /// standard library.
+  LazyDeclPtr StdAlignValT;
 
-  /// BuildObjCBoxedExpr - builds an ObjCBoxedExpr AST node for the
-  /// '@' prefixed parenthesized expression. The type of the expression will
-  /// either be "NSNumber *", "NSString *" or "NSValue *" depending on the type
-  /// of ValueType, which is allowed to be a built-in numeric type, "char *",
-  /// "const char *" or C structure with attribute 'objc_boxable'.
-  ExprResult BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr);
+  /// The C++ "type_info" declaration, which is defined in \.
+  RecordDecl *CXXTypeInfoDecl;
 
-  ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
-                                          Expr *IndexExpr,
-                                          ObjCMethodDecl *getterMethod,
-                                          ObjCMethodDecl *setterMethod);
+  /// A flag to remember whether the implicit forms of operator new and delete
+  /// have been declared.
+  bool GlobalNewDeleteDeclared;
 
-  ExprResult BuildObjCDictionaryLiteral(SourceRange SR,
-                               MutableArrayRef Elements);
+  /// Delete-expressions to be analyzed at the end of translation unit
+  ///
+  /// This list contains class members, and locations of delete-expressions
+  /// that could not be proven as to whether they mismatch with new-expression
+  /// used in initializer of the field.
+  llvm::MapVector DeleteExprs;
 
-  ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc,
-                                  TypeSourceInfo *EncodedTypeInfo,
-                                  SourceLocation RParenLoc);
-  ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
-                                    CXXConversionDecl *Method,
-                                    bool HadMultipleCandidates);
+  bool isInMaterializeTemporaryObjectContext() const {
+    assert(!ExprEvalContexts.empty() &&
+           "Must be in an expression evaluation context");
+    return ExprEvalContexts.back().InMaterializeTemporaryObjectContext;
+  }
 
-  ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
-                                       SourceLocation EncodeLoc,
-                                       SourceLocation LParenLoc,
-                                       ParsedType Ty,
-                                       SourceLocation RParenLoc);
+  ParsedType getInheritingConstructorName(CXXScopeSpec &SS,
+                                          SourceLocation NameLoc,
+                                          IdentifierInfo &Name);
 
-  /// ParseObjCSelectorExpression - Build selector expression for \@selector
-  ExprResult ParseObjCSelectorExpression(Selector Sel,
-                                         SourceLocation AtLoc,
-                                         SourceLocation SelLoc,
-                                         SourceLocation LParenLoc,
-                                         SourceLocation RParenLoc,
-                                         bool WarnMultipleSelectors);
+  ParsedType getConstructorName(IdentifierInfo &II, SourceLocation NameLoc,
+                                Scope *S, CXXScopeSpec &SS,
+                                bool EnteringContext);
+  ParsedType getDestructorName(IdentifierInfo &II, SourceLocation NameLoc,
+                               Scope *S, CXXScopeSpec &SS,
+                               ParsedType ObjectType, bool EnteringContext);
 
-  /// ParseObjCProtocolExpression - Build protocol expression for \@protocol
-  ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
-                                         SourceLocation AtLoc,
-                                         SourceLocation ProtoLoc,
-                                         SourceLocation LParenLoc,
-                                         SourceLocation ProtoIdLoc,
-                                         SourceLocation RParenLoc);
+  ParsedType getDestructorTypeForDecltype(const DeclSpec &DS,
+                                          ParsedType ObjectType);
 
-  //===--------------------------------------------------------------------===//
-  // C++ Declarations
-  //
-  Decl *ActOnStartLinkageSpecification(Scope *S,
-                                       SourceLocation ExternLoc,
-                                       Expr *LangStr,
-                                       SourceLocation LBraceLoc);
-  Decl *ActOnFinishLinkageSpecification(Scope *S,
-                                        Decl *LinkageSpec,
-                                        SourceLocation RBraceLoc);
+  ExprResult BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc,
+                            TypeSourceInfo *Operand, SourceLocation RParenLoc);
+  ExprResult BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc,
+                            Expr *Operand, SourceLocation RParenLoc);
 
+  /// ActOnCXXTypeid - Parse typeid( something ).
+  ExprResult ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
+                            bool isType, void *TyOrExpr,
+                            SourceLocation RParenLoc);
 
-  //===--------------------------------------------------------------------===//
-  // C++ Classes
-  //
-  CXXRecordDecl *getCurrentClass(Scope *S, const CXXScopeSpec *SS);
-  bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
-                          const CXXScopeSpec *SS = nullptr);
-  bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS);
+  ExprResult BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc,
+                            TypeSourceInfo *Operand, SourceLocation RParenLoc);
+  ExprResult BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc,
+                            Expr *Operand, SourceLocation RParenLoc);
 
-  bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc,
-                            SourceLocation ColonLoc,
-                            const ParsedAttributesView &Attrs);
+  /// ActOnCXXUuidof - Parse __uuidof( something ).
+  ExprResult ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc,
+                            bool isType, void *TyOrExpr,
+                            SourceLocation RParenLoc);
 
-  NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
-                                 Declarator &D,
-                                 MultiTemplateParamsArg TemplateParameterLists,
-                                 Expr *BitfieldWidth, const VirtSpecifiers &VS,
-                                 InClassInitStyle InitStyle);
+  //// ActOnCXXThis -  Parse 'this' pointer.
+  ExprResult ActOnCXXThis(SourceLocation loc);
 
-  void ActOnStartCXXInClassMemberInitializer();
-  void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl,
-                                              SourceLocation EqualLoc,
-                                              Expr *Init);
+  /// Build a CXXThisExpr and mark it referenced in the current context.
+  Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit);
+  void MarkThisReferenced(CXXThisExpr *This);
 
-  MemInitResult ActOnMemInitializer(Decl *ConstructorD,
-                                    Scope *S,
-                                    CXXScopeSpec &SS,
-                                    IdentifierInfo *MemberOrBase,
-                                    ParsedType TemplateTypeTy,
-                                    const DeclSpec &DS,
-                                    SourceLocation IdLoc,
-                                    SourceLocation LParenLoc,
-                                    ArrayRef Args,
-                                    SourceLocation RParenLoc,
-                                    SourceLocation EllipsisLoc);
+  /// Try to retrieve the type of the 'this' pointer.
+  ///
+  /// \returns The type of 'this', if possible. Otherwise, returns a NULL type.
+  QualType getCurrentThisType();
 
-  MemInitResult ActOnMemInitializer(Decl *ConstructorD,
-                                    Scope *S,
-                                    CXXScopeSpec &SS,
-                                    IdentifierInfo *MemberOrBase,
-                                    ParsedType TemplateTypeTy,
-                                    const DeclSpec &DS,
-                                    SourceLocation IdLoc,
-                                    Expr *InitList,
-                                    SourceLocation EllipsisLoc);
+  /// When non-NULL, the C++ 'this' expression is allowed despite the
+  /// current context not being a non-static member function. In such cases,
+  /// this provides the type used for 'this'.
+  QualType CXXThisTypeOverride;
 
-  MemInitResult BuildMemInitializer(Decl *ConstructorD,
-                                    Scope *S,
-                                    CXXScopeSpec &SS,
-                                    IdentifierInfo *MemberOrBase,
-                                    ParsedType TemplateTypeTy,
-                                    const DeclSpec &DS,
-                                    SourceLocation IdLoc,
-                                    Expr *Init,
-                                    SourceLocation EllipsisLoc);
+  /// RAII object used to temporarily allow the C++ 'this' expression
+  /// to be used, with the given qualifiers on the current class type.
+  class CXXThisScopeRAII {
+    Sema &S;
+    QualType OldCXXThisTypeOverride;
+    bool Enabled;
 
-  MemInitResult BuildMemberInitializer(ValueDecl *Member,
-                                       Expr *Init,
-                                       SourceLocation IdLoc);
+  public:
+    /// Introduce a new scope where 'this' may be allowed (when enabled),
+    /// using the given declaration (which is either a class template or a
+    /// class) along with the given qualifiers.
+    /// along with the qualifiers placed on '*this'.
+    CXXThisScopeRAII(Sema &S, Decl *ContextDecl, Qualifiers CXXThisTypeQuals,
+                     bool Enabled = true);
 
-  MemInitResult BuildBaseInitializer(QualType BaseType,
-                                     TypeSourceInfo *BaseTInfo,
-                                     Expr *Init,
-                                     CXXRecordDecl *ClassDecl,
-                                     SourceLocation EllipsisLoc);
+    ~CXXThisScopeRAII();
+  };
 
-  MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo,
-                                           Expr *Init,
-                                           CXXRecordDecl *ClassDecl);
+  /// Make sure the value of 'this' is actually available in the current
+  /// context, if it is a potentially evaluated context.
+  ///
+  /// \param Loc The location at which the capture of 'this' occurs.
+  ///
+  /// \param Explicit Whether 'this' is explicitly captured in a lambda
+  /// capture list.
+  ///
+  /// \param FunctionScopeIndexToStopAt If non-null, it points to the index
+  /// of the FunctionScopeInfo stack beyond which we do not attempt to capture.
+  /// This is useful when enclosing lambdas must speculatively capture
+  /// 'this' that may or may not be used in certain specializations of
+  /// a nested generic lambda (depending on whether the name resolves to
+  /// a non-static member function or a static function).
+  /// \return returns 'true' if failed, 'false' if success.
+  bool CheckCXXThisCapture(
+      SourceLocation Loc, bool Explicit = false, bool BuildAndDiagnose = true,
+      const unsigned *const FunctionScopeIndexToStopAt = nullptr,
+      bool ByCopy = false);
 
-  bool SetDelegatingInitializer(CXXConstructorDecl *Constructor,
-                                CXXCtorInitializer *Initializer);
+  /// Determine whether the given type is the type of *this that is used
+  /// outside of the body of a member function for a type that is currently
+  /// being defined.
+  bool isThisOutsideMemberFunctionBody(QualType BaseType);
 
-  bool SetCtorInitializers(
-      CXXConstructorDecl *Constructor, bool AnyErrors,
-      ArrayRef Initializers = std::nullopt);
+  /// ActOnCXXBoolLiteral - Parse {true,false} literals.
+  ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
 
-  void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation);
+  /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.
+  ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
 
+  ExprResult
+  ActOnObjCAvailabilityCheckExpr(llvm::ArrayRef AvailSpecs,
+                                 SourceLocation AtLoc, SourceLocation RParen);
 
-  /// MarkBaseAndMemberDestructorsReferenced - Given a record decl,
-  /// mark all the non-trivial destructors of its members and bases as
-  /// referenced.
-  void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
-                                              CXXRecordDecl *Record);
+  /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
+  ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
 
-  /// Mark destructors of virtual bases of this class referenced. In the Itanium
-  /// C++ ABI, this is done when emitting a destructor for any non-abstract
-  /// class. In the Microsoft C++ ABI, this is done any time a class's
-  /// destructor is referenced.
-  void MarkVirtualBaseDestructorsReferenced(
-      SourceLocation Location, CXXRecordDecl *ClassDecl,
-      llvm::SmallPtrSetImpl *DirectVirtualBases = nullptr);
+  //// ActOnCXXThrow -  Parse throw expressions.
+  ExprResult ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *expr);
+  ExprResult BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
+                           bool IsThrownVarInScope);
+  bool CheckCXXThrowOperand(SourceLocation ThrowLoc, QualType ThrowTy, Expr *E);
 
-  /// Do semantic checks to allow the complete destructor variant to be emitted
-  /// when the destructor is defined in another translation unit. In the Itanium
-  /// C++ ABI, destructor variants are emitted together. In the MS C++ ABI, they
-  /// can be emitted in separate TUs. To emit the complete variant, run a subset
-  /// of the checks performed when emitting a regular destructor.
-  void CheckCompleteDestructorVariant(SourceLocation CurrentLocation,
-                                      CXXDestructorDecl *Dtor);
+  /// ActOnCXXTypeConstructExpr - Parse construction of a specified type.
+  /// Can be interpreted either as function-style casting ("int(x)")
+  /// or class type construction ("ClassType(x,y,z)")
+  /// or creation of a value-initialized type ("int()").
+  ExprResult ActOnCXXTypeConstructExpr(ParsedType TypeRep,
+                                       SourceLocation LParenOrBraceLoc,
+                                       MultiExprArg Exprs,
+                                       SourceLocation RParenOrBraceLoc,
+                                       bool ListInitialization);
 
-  /// The list of classes whose vtables have been used within
-  /// this translation unit, and the source locations at which the
-  /// first use occurred.
-  typedef std::pair VTableUse;
+  ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type,
+                                       SourceLocation LParenLoc,
+                                       MultiExprArg Exprs,
+                                       SourceLocation RParenLoc,
+                                       bool ListInitialization);
 
-  /// The list of vtables that are required but have not yet been
-  /// materialized.
-  SmallVector VTableUses;
+  /// ActOnCXXNew - Parsed a C++ 'new' expression.
+  ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
+                         SourceLocation PlacementLParen,
+                         MultiExprArg PlacementArgs,
+                         SourceLocation PlacementRParen,
+                         SourceRange TypeIdParens, Declarator &D,
+                         Expr *Initializer);
+  ExprResult
+  BuildCXXNew(SourceRange Range, bool UseGlobal, SourceLocation PlacementLParen,
+              MultiExprArg PlacementArgs, SourceLocation PlacementRParen,
+              SourceRange TypeIdParens, QualType AllocType,
+              TypeSourceInfo *AllocTypeInfo, std::optional ArraySize,
+              SourceRange DirectInitRange, Expr *Initializer);
 
-  /// The set of classes whose vtables have been used within
-  /// this translation unit, and a bit that will be true if the vtable is
-  /// required to be emitted (otherwise, it should be emitted only if needed
-  /// by code generation).
-  llvm::DenseMap VTablesUsed;
+  /// Determine whether \p FD is an aligned allocation or deallocation
+  /// function that is unavailable.
+  bool isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const;
 
-  /// Load any externally-stored vtable uses.
-  void LoadExternalVTableUses();
+  /// Produce diagnostics if \p FD is an aligned allocation or deallocation
+  /// function that is unavailable.
+  void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
+                                            SourceLocation Loc);
 
-  /// Note that the vtable for the given class was used at the
-  /// given location.
-  void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
-                      bool DefinitionRequired = false);
+  bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
+                          SourceRange R);
 
-  /// Mark the exception specifications of all virtual member functions
-  /// in the given class as needed.
-  void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
-                                             const CXXRecordDecl *RD);
+  /// The scope in which to find allocation functions.
+  enum AllocationFunctionScope {
+    /// Only look for allocation functions in the global scope.
+    AFS_Global,
+    /// Only look for allocation functions in the scope of the
+    /// allocated class.
+    AFS_Class,
+    /// Look for allocation functions in both the global scope
+    /// and in the scope of the allocated class.
+    AFS_Both
+  };
 
-  /// MarkVirtualMembersReferenced - Will mark all members of the given
-  /// CXXRecordDecl referenced.
-  void MarkVirtualMembersReferenced(SourceLocation Loc, const CXXRecordDecl *RD,
-                                    bool ConstexprOnly = false);
+  /// Finds the overloads of operator new and delete that are appropriate
+  /// for the allocation.
+  bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
+                               AllocationFunctionScope NewScope,
+                               AllocationFunctionScope DeleteScope,
+                               QualType AllocType, bool IsArray,
+                               bool &PassAlignment, MultiExprArg PlaceArgs,
+                               FunctionDecl *&OperatorNew,
+                               FunctionDecl *&OperatorDelete,
+                               bool Diagnose = true);
+  void DeclareGlobalNewDelete();
+  void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
+                                       ArrayRef Params);
 
-  /// Define all of the vtables that have been used in this
-  /// translation unit and reference any virtual members used by those
-  /// vtables.
-  ///
-  /// \returns true if any work was done, false otherwise.
-  bool DefineUsedVTables();
+  bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
+                                DeclarationName Name, FunctionDecl *&Operator,
+                                bool Diagnose = true, bool WantSize = false,
+                                bool WantAligned = false);
+  FunctionDecl *FindUsualDeallocationFunction(SourceLocation StartLoc,
+                                              bool CanProvideSize,
+                                              bool Overaligned,
+                                              DeclarationName Name);
+  FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc,
+                                                      CXXRecordDecl *RD);
 
-  void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
+  /// ActOnCXXDelete - Parsed a C++ 'delete' expression
+  ExprResult ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
+                            bool ArrayForm, Expr *Operand);
+  void CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc,
+                            bool IsDelete, bool CallCanBeVirtual,
+                            bool WarnOnNonAbstractTypes,
+                            SourceLocation DtorLoc);
 
-  void ActOnMemInitializers(Decl *ConstructorDecl,
-                            SourceLocation ColonLoc,
-                            ArrayRef MemInits,
-                            bool AnyErrors);
+  ExprResult ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation LParen,
+                               Expr *Operand, SourceLocation RParen);
+  ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
+                                  SourceLocation RParen);
 
-  /// Check class-level dllimport/dllexport attribute. The caller must
-  /// ensure that referenceDLLExportedClassMethods is called some point later
-  /// when all outer classes of Class are complete.
-  void checkClassLevelDLLAttribute(CXXRecordDecl *Class);
-  void checkClassLevelCodeSegAttribute(CXXRecordDecl *Class);
+  ExprResult ActOnStartCXXMemberReference(Scope *S, Expr *Base,
+                                          SourceLocation OpLoc,
+                                          tok::TokenKind OpKind,
+                                          ParsedType &ObjectType,
+                                          bool &MayBePseudoDestructor);
 
-  void referenceDLLExportedClassMethods();
+  ExprResult BuildPseudoDestructorExpr(
+      Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind,
+      const CXXScopeSpec &SS, TypeSourceInfo *ScopeType, SourceLocation CCLoc,
+      SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType);
 
-  void propagateDLLAttrToBaseClassTemplate(
-      CXXRecordDecl *Class, Attr *ClassAttr,
-      ClassTemplateSpecializationDecl *BaseTemplateSpec,
-      SourceLocation BaseLoc);
+  ExprResult ActOnPseudoDestructorExpr(
+      Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind,
+      CXXScopeSpec &SS, UnqualifiedId &FirstTypeName, SourceLocation CCLoc,
+      SourceLocation TildeLoc, UnqualifiedId &SecondTypeName);
 
-  /// Add gsl::Pointer attribute to std::container::iterator
-  /// \param ND The declaration that introduces the name
-  /// std::container::iterator. \param UnderlyingRecord The record named by ND.
-  void inferGslPointerAttribute(NamedDecl *ND, CXXRecordDecl *UnderlyingRecord);
+  ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
+                                       SourceLocation OpLoc,
+                                       tok::TokenKind OpKind,
+                                       SourceLocation TildeLoc,
+                                       const DeclSpec &DS);
 
-  /// Add [[gsl::Owner]] and [[gsl::Pointer]] attributes for std:: types.
-  void inferGslOwnerPointerAttribute(CXXRecordDecl *Record);
+  /// MaybeCreateExprWithCleanups - If the current full-expression
+  /// requires any cleanups, surround it with a ExprWithCleanups node.
+  /// Otherwise, just returns the passed-in expression.
+  Expr *MaybeCreateExprWithCleanups(Expr *SubExpr);
+  Stmt *MaybeCreateStmtWithCleanups(Stmt *SubStmt);
+  ExprResult MaybeCreateExprWithCleanups(ExprResult SubExpr);
 
-  /// Add [[gsl::Pointer]] attributes for std:: types.
-  void inferGslPointerAttribute(TypedefNameDecl *TD);
+  ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue) {
+    return ActOnFinishFullExpr(
+        Expr, Expr ? Expr->getExprLoc() : SourceLocation(), DiscardedValue);
+  }
+  ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC,
+                                 bool DiscardedValue, bool IsConstexpr = false,
+                                 bool IsTemplateArgument = false);
+  StmtResult ActOnFinishFullStmt(Stmt *Stmt);
 
-  void CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record);
+  ExprResult ActOnDecltypeExpression(Expr *E);
 
-  /// Check that the C++ class annoated with "trivial_abi" satisfies all the
-  /// conditions that are needed for the attribute to have an effect.
-  void checkIllFormedTrivialABIStruct(CXXRecordDecl &RD);
+  bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id,
+                              bool IsUDSuffix);
 
-  void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc,
-                                         Decl *TagDecl, SourceLocation LBrac,
-                                         SourceLocation RBrac,
-                                         const ParsedAttributesView &AttrList);
-  void ActOnFinishCXXMemberDecls();
-  void ActOnFinishCXXNonNestedClass();
+  bool isUsualDeallocationFunction(const CXXMethodDecl *FD);
 
-  void ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param);
-  unsigned ActOnReenterTemplateScope(Decl *Template,
-                                     llvm::function_ref EnterScope);
-  void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record);
-  void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
-  void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param);
-  void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record);
-  void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
-  void ActOnFinishDelayedMemberInitializers(Decl *Record);
-  void MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD,
-                                CachedTokens &Toks);
-  void UnmarkAsLateParsedTemplate(FunctionDecl *FD);
-  bool IsInsideALocalClassWithinATemplateFunction();
+  ConditionResult ActOnConditionVariable(Decl *ConditionVar,
+                                         SourceLocation StmtLoc,
+                                         ConditionKind CK);
 
-  bool EvaluateStaticAssertMessageAsString(Expr *Message, std::string &Result,
-                                           ASTContext &Ctx,
-                                           bool ErrorOnInvalidMessage);
-  Decl *ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc,
-                                     Expr *AssertExpr,
-                                     Expr *AssertMessageExpr,
-                                     SourceLocation RParenLoc);
-  Decl *BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
-                                     Expr *AssertExpr, Expr *AssertMessageExpr,
-                                     SourceLocation RParenLoc, bool Failed);
-  void DiagnoseStaticAssertDetails(const Expr *E);
+  ExprResult CheckConditionVariable(VarDecl *ConditionVar,
+                                    SourceLocation StmtLoc, ConditionKind CK);
 
-  Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
-                            MultiTemplateParamsArg TemplateParams);
-  NamedDecl *ActOnFriendFunctionDecl(Scope *S, Declarator &D,
-                                     MultiTemplateParamsArg TemplateParams);
+  /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid.
+  ExprResult CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr = false);
 
-  QualType CheckConstructorDeclarator(Declarator &D, QualType R,
-                                      StorageClass& SC);
-  void CheckConstructor(CXXConstructorDecl *Constructor);
-  QualType CheckDestructorDeclarator(Declarator &D, QualType R,
-                                     StorageClass& SC);
-  bool CheckDestructor(CXXDestructorDecl *Destructor);
-  void CheckConversionDeclarator(Declarator &D, QualType &R,
-                                 StorageClass& SC);
-  Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion);
-  bool CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
-                                     StorageClass &SC);
-  void CheckDeductionGuideTemplate(FunctionTemplateDecl *TD);
+  bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
 
-  void CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *MD);
+  ExprResult
+  PerformImplicitConversion(Expr *From, QualType ToType,
+                            const ImplicitConversionSequence &ICS,
+                            AssignmentAction Action,
+                            CheckedConversionKind CCK = CCK_ImplicitConversion);
+  ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
+                                       const StandardConversionSequence &SCS,
+                                       AssignmentAction Action,
+                                       CheckedConversionKind CCK);
 
-  bool CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
-                                             CXXSpecialMember CSM,
-                                             SourceLocation DefaultLoc);
-  void CheckDelayedMemberExceptionSpecs();
+  bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N);
 
-  bool CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *MD,
-                                          DefaultedComparisonKind DCK);
-  void DeclareImplicitEqualityComparison(CXXRecordDecl *RD,
-                                         FunctionDecl *Spaceship);
-  void DefineDefaultedComparison(SourceLocation Loc, FunctionDecl *FD,
-                                 DefaultedComparisonKind DCK);
+  /// Parsed one of the type trait support pseudo-functions.
+  ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
+                            ArrayRef Args,
+                            SourceLocation RParenLoc);
+  ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
+                            ArrayRef Args,
+                            SourceLocation RParenLoc);
 
-  void CheckExplicitObjectMemberFunction(Declarator &D, DeclarationName Name,
-                                         QualType R, bool IsLambda,
-                                         DeclContext *DC = nullptr);
-  void CheckExplicitObjectMemberFunction(DeclContext *DC, Declarator &D,
-                                         DeclarationName Name, QualType R);
-  void CheckExplicitObjectLambda(Declarator &D);
+  /// ActOnArrayTypeTrait - Parsed one of the binary type trait support
+  /// pseudo-functions.
+  ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc,
+                                 ParsedType LhsTy, Expr *DimExpr,
+                                 SourceLocation RParen);
 
-  //===--------------------------------------------------------------------===//
-  // C++ Derived Classes
-  //
+  ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc,
+                                 TypeSourceInfo *TSInfo, Expr *DimExpr,
+                                 SourceLocation RParen);
 
-  /// ActOnBaseSpecifier - Parsed a base specifier
-  CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class,
-                                       SourceRange SpecifierRange,
-                                       bool Virtual, AccessSpecifier Access,
-                                       TypeSourceInfo *TInfo,
-                                       SourceLocation EllipsisLoc);
+  /// ActOnExpressionTrait - Parsed one of the unary type trait support
+  /// pseudo-functions.
+  ExprResult ActOnExpressionTrait(ExpressionTrait OET, SourceLocation KWLoc,
+                                  Expr *Queried, SourceLocation RParen);
 
-  BaseResult ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
-                                const ParsedAttributesView &Attrs, bool Virtual,
-                                AccessSpecifier Access, ParsedType basetype,
-                                SourceLocation BaseLoc,
-                                SourceLocation EllipsisLoc);
+  ExprResult BuildExpressionTrait(ExpressionTrait OET, SourceLocation KWLoc,
+                                  Expr *Queried, SourceLocation RParen);
 
-  bool AttachBaseSpecifiers(CXXRecordDecl *Class,
-                            MutableArrayRef Bases);
-  void ActOnBaseSpecifiers(Decl *ClassDecl,
-                           MutableArrayRef Bases);
+  QualType CheckPointerToMemberOperands( // C++ 5.5
+      ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, SourceLocation OpLoc,
+      bool isIndirect);
+  QualType CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
+                                       ExprResult &RHS,
+                                       SourceLocation QuestionLoc);
 
-  bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base);
-  bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
-                     CXXBasePaths &Paths);
+  QualType CheckSizelessVectorConditionalTypes(ExprResult &Cond,
+                                               ExprResult &LHS, ExprResult &RHS,
+                                               SourceLocation QuestionLoc);
 
-  // FIXME: I don't like this name.
-  void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath);
+  QualType CXXCheckConditionalOperands( // C++ 5.16
+      ExprResult &cond, ExprResult &lhs, ExprResult &rhs, ExprValueKind &VK,
+      ExprObjectKind &OK, SourceLocation questionLoc);
 
-  bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
-                                    SourceLocation Loc, SourceRange Range,
-                                    CXXCastPath *BasePath = nullptr,
-                                    bool IgnoreAccess = false);
-  bool CheckDerivedToBaseConversion(QualType Derived, QualType Base,
-                                    unsigned InaccessibleBaseID,
-                                    unsigned AmbiguousBaseConvID,
-                                    SourceLocation Loc, SourceRange Range,
-                                    DeclarationName Name,
-                                    CXXCastPath *BasePath,
-                                    bool IgnoreAccess = false);
+  QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2,
+                                    bool ConvertArgs = true);
+  QualType FindCompositePointerType(SourceLocation Loc, ExprResult &E1,
+                                    ExprResult &E2, bool ConvertArgs = true) {
+    Expr *E1Tmp = E1.get(), *E2Tmp = E2.get();
+    QualType Composite =
+        FindCompositePointerType(Loc, E1Tmp, E2Tmp, ConvertArgs);
+    E1 = E1Tmp;
+    E2 = E2Tmp;
+    return Composite;
+  }
 
-  std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths);
+  /// MaybeBindToTemporary - If the passed in expression has a record type with
+  /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
+  /// it simply returns the passed in expression.
+  ExprResult MaybeBindToTemporary(Expr *E);
 
-  bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
-                                         const CXXMethodDecl *Old);
+  /// IgnoredValueConversions - Given that an expression's result is
+  /// syntactically ignored, perform any conversions that are
+  /// required.
+  ExprResult IgnoredValueConversions(Expr *E);
 
-  /// CheckOverridingFunctionReturnType - Checks whether the return types are
-  /// covariant, according to C++ [class.virtual]p5.
-  bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
-                                         const CXXMethodDecl *Old);
+  ExprResult CheckUnevaluatedOperand(Expr *E);
 
-  // Check that the overriding method has no explicit object parameter.
-  bool CheckExplicitObjectOverride(CXXMethodDecl *New,
-                                   const CXXMethodDecl *Old);
+  /// Process any TypoExprs in the given Expr and its children,
+  /// generating diagnostics as appropriate and returning a new Expr if there
+  /// were typos that were all successfully corrected and ExprError if one or
+  /// more typos could not be corrected.
+  ///
+  /// \param E The Expr to check for TypoExprs.
+  ///
+  /// \param InitDecl A VarDecl to avoid because the Expr being corrected is its
+  /// initializer.
+  ///
+  /// \param RecoverUncorrectedTypos If true, when typo correction fails, it
+  /// will rebuild the given Expr with all TypoExprs degraded to RecoveryExprs.
+  ///
+  /// \param Filter A function applied to a newly rebuilt Expr to determine if
+  /// it is an acceptable/usable result from a single combination of typo
+  /// corrections. As long as the filter returns ExprError, different
+  /// combinations of corrections will be tried until all are exhausted.
+  ExprResult CorrectDelayedTyposInExpr(
+      Expr *E, VarDecl *InitDecl = nullptr,
+      bool RecoverUncorrectedTypos = false,
+      llvm::function_ref Filter =
+          [](Expr *E) -> ExprResult { return E; });
 
-  /// CheckOverridingFunctionExceptionSpec - Checks whether the exception
-  /// spec is a subset of base spec.
-  bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
-                                            const CXXMethodDecl *Old);
+  ExprResult CorrectDelayedTyposInExpr(
+      ExprResult ER, VarDecl *InitDecl = nullptr,
+      bool RecoverUncorrectedTypos = false,
+      llvm::function_ref Filter =
+          [](Expr *E) -> ExprResult { return E; }) {
+    return ER.isInvalid()
+               ? ER
+               : CorrectDelayedTyposInExpr(ER.get(), InitDecl,
+                                           RecoverUncorrectedTypos, Filter);
+  }
 
-  bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
+  /// Describes the result of an "if-exists" condition check.
+  enum IfExistsResult {
+    /// The symbol exists.
+    IER_Exists,
 
-  /// CheckOverrideControl - Check C++11 override control semantics.
-  void CheckOverrideControl(NamedDecl *D);
+    /// The symbol does not exist.
+    IER_DoesNotExist,
 
-  /// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was
-  /// not used in the declaration of an overriding method.
-  void DiagnoseAbsenceOfOverrideControl(NamedDecl *D, bool Inconsistent);
+    /// The name is a dependent name, so the results will differ
+    /// from one instantiation to the next.
+    IER_Dependent,
 
-  /// CheckForFunctionMarkedFinal - Checks whether a virtual member function
-  /// overrides a virtual member function marked 'final', according to
-  /// C++11 [class.virtual]p4.
-  bool CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
-                                              const CXXMethodDecl *Old);
+    /// An error occurred.
+    IER_Error
+  };
 
+  IfExistsResult
+  CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS,
+                               const DeclarationNameInfo &TargetNameInfo);
 
-  //===--------------------------------------------------------------------===//
-  // C++ Access Control
-  //
+  IfExistsResult CheckMicrosoftIfExistsSymbol(Scope *S,
+                                              SourceLocation KeywordLoc,
+                                              bool IsIfExists, CXXScopeSpec &SS,
+                                              UnqualifiedId &Name);
 
-  enum AccessResult {
-    AR_accessible,
-    AR_inaccessible,
-    AR_dependent,
-    AR_delayed
-  };
+  RequiresExprBodyDecl *
+  ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
+                         ArrayRef LocalParameters,
+                         Scope *BodyScope);
+  void ActOnFinishRequiresExpr();
+  concepts::Requirement *ActOnSimpleRequirement(Expr *E);
+  concepts::Requirement *ActOnTypeRequirement(SourceLocation TypenameKWLoc,
+                                              CXXScopeSpec &SS,
+                                              SourceLocation NameLoc,
+                                              IdentifierInfo *TypeName,
+                                              TemplateIdAnnotation *TemplateId);
+  concepts::Requirement *ActOnCompoundRequirement(Expr *E,
+                                                  SourceLocation NoexceptLoc);
+  concepts::Requirement *ActOnCompoundRequirement(
+      Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS,
+      TemplateIdAnnotation *TypeConstraint, unsigned Depth);
+  concepts::Requirement *ActOnNestedRequirement(Expr *Constraint);
+  concepts::ExprRequirement *BuildExprRequirement(
+      Expr *E, bool IsSatisfied, SourceLocation NoexceptLoc,
+      concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement);
+  concepts::ExprRequirement *BuildExprRequirement(
+      concepts::Requirement::SubstitutionDiagnostic *ExprSubstDiag,
+      bool IsSatisfied, SourceLocation NoexceptLoc,
+      concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement);
+  concepts::TypeRequirement *BuildTypeRequirement(TypeSourceInfo *Type);
+  concepts::TypeRequirement *BuildTypeRequirement(
+      concepts::Requirement::SubstitutionDiagnostic *SubstDiag);
+  concepts::NestedRequirement *BuildNestedRequirement(Expr *E);
+  concepts::NestedRequirement *
+  BuildNestedRequirement(StringRef InvalidConstraintEntity,
+                         const ASTConstraintSatisfaction &Satisfaction);
+  ExprResult ActOnRequiresExpr(SourceLocation RequiresKWLoc,
+                               RequiresExprBodyDecl *Body,
+                               SourceLocation LParenLoc,
+                               ArrayRef LocalParameters,
+                               SourceLocation RParenLoc,
+                               ArrayRef Requirements,
+                               SourceLocation ClosingBraceLoc);
 
-  bool SetMemberAccessSpecifier(NamedDecl *MemberDecl,
-                                NamedDecl *PrevMemberDecl,
-                                AccessSpecifier LexicalAS);
+private:
+  ExprResult SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult,
+                                                    bool IsDelete);
 
-  AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
-                                           DeclAccessPair FoundDecl);
-  AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
-                                           DeclAccessPair FoundDecl);
-  AccessResult CheckAllocationAccess(SourceLocation OperatorLoc,
-                                     SourceRange PlacementRange,
-                                     CXXRecordDecl *NamingClass,
-                                     DeclAccessPair FoundDecl,
-                                     bool Diagnose = true);
-  AccessResult CheckConstructorAccess(SourceLocation Loc,
-                                      CXXConstructorDecl *D,
-                                      DeclAccessPair FoundDecl,
-                                      const InitializedEntity &Entity,
-                                      bool IsCopyBindingRefToTemp = false);
-  AccessResult CheckConstructorAccess(SourceLocation Loc,
-                                      CXXConstructorDecl *D,
-                                      DeclAccessPair FoundDecl,
-                                      const InitializedEntity &Entity,
-                                      const PartialDiagnostic &PDiag);
-  AccessResult CheckDestructorAccess(SourceLocation Loc,
-                                     CXXDestructorDecl *Dtor,
-                                     const PartialDiagnostic &PDiag,
-                                     QualType objectType = QualType());
-  AccessResult CheckFriendAccess(NamedDecl *D);
-  AccessResult CheckMemberAccess(SourceLocation UseLoc,
-                                 CXXRecordDecl *NamingClass,
-                                 DeclAccessPair Found);
-  AccessResult
-  CheckStructuredBindingMemberAccess(SourceLocation UseLoc,
-                                     CXXRecordDecl *DecomposedClass,
-                                     DeclAccessPair Field);
-  AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr,
-                                         const SourceRange &,
-                                         DeclAccessPair FoundDecl);
-  AccessResult CheckMemberOperatorAccess(SourceLocation Loc,
-                                         Expr *ObjectExpr,
-                                         Expr *ArgExpr,
-                                         DeclAccessPair FoundDecl);
-  AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr,
-                                         ArrayRef ArgExprs,
-                                         DeclAccessPair FoundDecl);
-  AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr,
-                                          DeclAccessPair FoundDecl);
-  AccessResult CheckBaseClassAccess(SourceLocation AccessLoc,
-                                    QualType Base, QualType Derived,
-                                    const CXXBasePath &Path,
-                                    unsigned DiagID,
-                                    bool ForceCheck = false,
-                                    bool ForceUnprivileged = false);
-  void CheckLookupAccess(const LookupResult &R);
-  bool IsSimplyAccessible(NamedDecl *Decl, CXXRecordDecl *NamingClass,
-                          QualType BaseType);
-  bool isMemberAccessibleForDeletion(CXXRecordDecl *NamingClass,
-                                     DeclAccessPair Found, QualType ObjectType,
-                                     SourceLocation Loc,
-                                     const PartialDiagnostic &Diag);
-  bool isMemberAccessibleForDeletion(CXXRecordDecl *NamingClass,
-                                     DeclAccessPair Found,
-                                     QualType ObjectType) {
-    return isMemberAccessibleForDeletion(NamingClass, Found, ObjectType,
-                                         SourceLocation(), PDiag());
-  }
+  void AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE);
+  void AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc,
+                                 bool DeleteWasArrayForm);
 
-  void HandleDependentAccessCheck(const DependentDiagnostic &DD,
-                         const MultiLevelTemplateArgumentList &TemplateArgs);
-  void PerformDependentDiagnostics(const DeclContext *Pattern,
-                        const MultiLevelTemplateArgumentList &TemplateArgs);
+  ///@}
 
-  void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// When true, access checking violations are treated as SFINAE
-  /// failures rather than hard errors.
-  bool AccessCheckingSFINAE;
+  /// \name Member Access Expressions
+  /// Implementations are in SemaExprMember.cpp
+  ///@{
 
-  enum AbstractDiagSelID {
-    AbstractNone = -1,
-    AbstractReturnType,
-    AbstractParamType,
-    AbstractVariableType,
-    AbstractFieldType,
-    AbstractIvarType,
-    AbstractSynthesizedIvarType,
-    AbstractArrayType
-  };
+public:
+  ExprResult BuildPossibleImplicitMemberExpr(
+      const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
+      const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
+      UnresolvedLookupExpr *AsULE = nullptr);
+  ExprResult
+  BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+                          LookupResult &R,
+                          const TemplateArgumentListInfo *TemplateArgs,
+                          bool IsDefiniteInstance, const Scope *S);
+
+  ExprResult ActOnDependentMemberExpr(
+      Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OpLoc,
+      const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+      NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
+      const TemplateArgumentListInfo *TemplateArgs);
 
-  bool isAbstractType(SourceLocation Loc, QualType T);
-  bool RequireNonAbstractType(SourceLocation Loc, QualType T,
-                              TypeDiagnoser &Diagnoser);
-  template 
-  bool RequireNonAbstractType(SourceLocation Loc, QualType T, unsigned DiagID,
-                              const Ts &...Args) {
-    BoundTypeDiagnoser Diagnoser(DiagID, Args...);
-    return RequireNonAbstractType(Loc, T, Diagnoser);
-  }
+  ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
+                                   tok::TokenKind OpKind, CXXScopeSpec &SS,
+                                   SourceLocation TemplateKWLoc,
+                                   UnqualifiedId &Member, Decl *ObjCImpDecl);
+
+  MemberExpr *BuildMemberExpr(
+      Expr *Base, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec *SS,
+      SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
+      bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
+      QualType Ty, ExprValueKind VK, ExprObjectKind OK,
+      const TemplateArgumentListInfo *TemplateArgs = nullptr);
+  MemberExpr *
+  BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc,
+                  NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
+                  ValueDecl *Member, DeclAccessPair FoundDecl,
+                  bool HadMultipleCandidates,
+                  const DeclarationNameInfo &MemberNameInfo, QualType Ty,
+                  ExprValueKind VK, ExprObjectKind OK,
+                  const TemplateArgumentListInfo *TemplateArgs = nullptr);
 
-  void DiagnoseAbstractType(const CXXRecordDecl *RD);
+  bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
+                                     const CXXScopeSpec &SS,
+                                     const LookupResult &R);
 
-  //===--------------------------------------------------------------------===//
-  // C++ Overloaded Operators [C++ 13.5]
-  //
+  // This struct is for use by ActOnMemberAccess to allow
+  // BuildMemberReferenceExpr to be able to reinvoke ActOnMemberAccess after
+  // changing the access operator from a '.' to a '->' (to see if that is the
+  // change needed to fix an error about an unknown member, e.g. when the class
+  // defines a custom operator->).
+  struct ActOnMemberAccessExtraArgs {
+    Scope *S;
+    UnqualifiedId &Id;
+    Decl *ObjCImpDecl;
+  };
 
-  bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl);
+  ExprResult BuildMemberReferenceExpr(
+      Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow,
+      CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+      NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
+      const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
+      ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
 
-  bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl);
+  ExprResult
+  BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc,
+                           bool IsArrow, const CXXScopeSpec &SS,
+                           SourceLocation TemplateKWLoc,
+                           NamedDecl *FirstQualifierInScope, LookupResult &R,
+                           const TemplateArgumentListInfo *TemplateArgs,
+                           const Scope *S, bool SuppressQualifierCheck = false,
+                           ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
 
-  //===--------------------------------------------------------------------===//
-  // C++ Templates [C++ 14]
-  //
-  void FilterAcceptableTemplateNames(LookupResult &R,
-                                     bool AllowFunctionTemplates = true,
-                                     bool AllowDependent = true);
-  bool hasAnyAcceptableTemplateNames(LookupResult &R,
-                                     bool AllowFunctionTemplates = true,
-                                     bool AllowDependent = true,
-                                     bool AllowNonTemplateFunctions = false);
-  /// Try to interpret the lookup result D as a template-name.
-  ///
-  /// \param D A declaration found by name lookup.
-  /// \param AllowFunctionTemplates Whether function templates should be
-  ///        considered valid results.
-  /// \param AllowDependent Whether unresolved using declarations (that might
-  ///        name templates) should be considered valid results.
-  static NamedDecl *getAsTemplateNameDecl(NamedDecl *D,
-                                          bool AllowFunctionTemplates = true,
-                                          bool AllowDependent = true);
+  ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
+                                     SourceLocation OpLoc,
+                                     const CXXScopeSpec &SS, FieldDecl *Field,
+                                     DeclAccessPair FoundDecl,
+                                     const DeclarationNameInfo &MemberNameInfo);
 
-  enum TemplateNameIsRequiredTag { TemplateNameIsRequired };
-  /// Whether and why a template name is required in this lookup.
-  class RequiredTemplateKind {
-  public:
-    /// Template name is required if TemplateKWLoc is valid.
-    RequiredTemplateKind(SourceLocation TemplateKWLoc = SourceLocation())
-        : TemplateKW(TemplateKWLoc) {}
-    /// Template name is unconditionally required.
-    RequiredTemplateKind(TemplateNameIsRequiredTag) {}
+  ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow);
 
-    SourceLocation getTemplateKeywordLoc() const {
-      return TemplateKW.value_or(SourceLocation());
-    }
-    bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }
-    bool isRequired() const { return TemplateKW != SourceLocation(); }
-    explicit operator bool() const { return isRequired(); }
+  ExprResult BuildAnonymousStructUnionMemberReference(
+      const CXXScopeSpec &SS, SourceLocation nameLoc,
+      IndirectFieldDecl *indirectField,
+      DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_none),
+      Expr *baseObjectExpr = nullptr, SourceLocation opLoc = SourceLocation());
 
-  private:
-    std::optional TemplateKW;
-  };
+private:
+  void CheckMemberAccessOfNoDeref(const MemberExpr *E);
 
-  enum class AssumedTemplateKind {
-    /// This is not assumed to be a template name.
-    None,
-    /// This is assumed to be a template name because lookup found nothing.
-    FoundNothing,
-    /// This is assumed to be a template name because lookup found one or more
-    /// functions (but no function templates).
-    FoundFunctions,
-  };
-  bool LookupTemplateName(
-      LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType,
-      bool EnteringContext, bool &MemberOfUnknownSpecialization,
-      RequiredTemplateKind RequiredTemplate = SourceLocation(),
-      AssumedTemplateKind *ATK = nullptr, bool AllowTypoCorrection = true);
+  ///@}
 
-  TemplateNameKind isTemplateName(Scope *S,
-                                  CXXScopeSpec &SS,
-                                  bool hasTemplateKeyword,
-                                  const UnqualifiedId &Name,
-                                  ParsedType ObjectType,
-                                  bool EnteringContext,
-                                  TemplateTy &Template,
-                                  bool &MemberOfUnknownSpecialization,
-                                  bool Disambiguation = false);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Try to resolve an undeclared template name as a type template.
-  ///
-  /// Sets II to the identifier corresponding to the template name, and updates
-  /// Name to a corresponding (typo-corrected) type template name and TNK to
-  /// the corresponding kind, if possible.
-  void ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &Name,
-                                       TemplateNameKind &TNK,
-                                       SourceLocation NameLoc,
-                                       IdentifierInfo *&II);
+  /// \name Initializers
+  /// Implementations are in SemaInit.cpp
+  ///@{
 
-  bool resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name,
-                                        SourceLocation NameLoc,
-                                        bool Diagnose = true);
+public:
+  /// Stack of types that correspond to the parameter entities that are
+  /// currently being copy-initialized. Can be empty.
+  llvm::SmallVector CurrentParameterCopyTypes;
 
-  /// Determine whether a particular identifier might be the name in a C++1z
-  /// deduction-guide declaration.
-  bool isDeductionGuideName(Scope *S, const IdentifierInfo &Name,
-                            SourceLocation NameLoc, CXXScopeSpec &SS,
-                            ParsedTemplateTy *Template = nullptr);
-
-  bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
-                                   SourceLocation IILoc,
-                                   Scope *S,
-                                   const CXXScopeSpec *SS,
-                                   TemplateTy &SuggestedTemplate,
-                                   TemplateNameKind &SuggestedKind);
-
-  bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
-                                      NamedDecl *Instantiation,
-                                      bool InstantiatedFromMember,
-                                      const NamedDecl *Pattern,
-                                      const NamedDecl *PatternDef,
-                                      TemplateSpecializationKind TSK,
-                                      bool Complain = true);
+  llvm::DenseMap
+      AggregateDeductionCandidates;
 
-  /// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
-  /// that the template parameter 'PrevDecl' is being shadowed by a new
-  /// declaration at location Loc. Returns true to indicate that this is
-  /// an error, and false otherwise.
-  ///
-  /// \param Loc The location of the declaration that shadows a template
-  ///            parameter.
-  ///
-  /// \param PrevDecl The template parameter that the declaration shadows.
-  ///
-  /// \param SupportedForCompatibility Whether to issue the diagnostic as
-  ///        a warning for compatibility with older versions of clang.
-  ///        Ignored when MSVC compatibility is enabled.
-  void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl,
-                                       bool SupportedForCompatibility = false);
-  TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
+  bool IsStringInit(Expr *Init, const ArrayType *AT);
 
-  NamedDecl *ActOnTypeParameter(Scope *S, bool Typename,
-                                SourceLocation EllipsisLoc,
-                                SourceLocation KeyLoc,
-                                IdentifierInfo *ParamName,
-                                SourceLocation ParamNameLoc,
-                                unsigned Depth, unsigned Position,
-                                SourceLocation EqualLoc,
-                                ParsedType DefaultArg, bool HasTypeConstraint);
+  bool CanPerformAggregateInitializationForOverloadResolution(
+      const InitializedEntity &Entity, InitListExpr *From);
 
-  bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint);
+  ExprResult ActOnDesignatedInitializer(Designation &Desig,
+                                        SourceLocation EqualOrColonLoc,
+                                        bool GNUSyntax, ExprResult Init);
 
-  bool ActOnTypeConstraint(const CXXScopeSpec &SS,
-                           TemplateIdAnnotation *TypeConstraint,
-                           TemplateTypeParmDecl *ConstrainedParameter,
-                           SourceLocation EllipsisLoc);
-  bool BuildTypeConstraint(const CXXScopeSpec &SS,
-                           TemplateIdAnnotation *TypeConstraint,
-                           TemplateTypeParmDecl *ConstrainedParameter,
-                           SourceLocation EllipsisLoc,
-                           bool AllowUnexpandedPack);
+  /// Check that the lifetime of the initializer (and its subobjects) is
+  /// sufficient for initializing the entity, and perform lifetime extension
+  /// (when permitted) if not.
+  void checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init);
 
-  bool AttachTypeConstraint(NestedNameSpecifierLoc NS,
-                            DeclarationNameInfo NameInfo,
-                            ConceptDecl *NamedConcept,
-                            const TemplateArgumentListInfo *TemplateArgs,
-                            TemplateTypeParmDecl *ConstrainedParameter,
-                            SourceLocation EllipsisLoc);
+  MaterializeTemporaryExpr *
+  CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
+                                 bool BoundToLvalueReference);
 
-  bool AttachTypeConstraint(AutoTypeLoc TL,
-                            NonTypeTemplateParmDecl *NewConstrainedParm,
-                            NonTypeTemplateParmDecl *OrigConstrainedParm,
-                            SourceLocation EllipsisLoc);
+  /// If \p E is a prvalue denoting an unmaterialized temporary, materialize
+  /// it as an xvalue. In C++98, the result will still be a prvalue, because
+  /// we don't have xvalues there.
+  ExprResult TemporaryMaterializationConversion(Expr *E);
 
-  bool RequireStructuralType(QualType T, SourceLocation Loc);
+  ExprResult PerformQualificationConversion(
+      Expr *E, QualType Ty, ExprValueKind VK = VK_PRValue,
+      CheckedConversionKind CCK = CCK_ImplicitConversion);
 
-  QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
-                                             SourceLocation Loc);
-  QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
+  bool CanPerformCopyInitialization(const InitializedEntity &Entity,
+                                    ExprResult Init);
+  ExprResult PerformCopyInitialization(const InitializedEntity &Entity,
+                                       SourceLocation EqualLoc, ExprResult Init,
+                                       bool TopLevelOfInitList = false,
+                                       bool AllowExplicit = false);
 
-  NamedDecl *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
-                                      unsigned Depth,
-                                      unsigned Position,
-                                      SourceLocation EqualLoc,
-                                      Expr *DefaultArg);
-  NamedDecl *ActOnTemplateTemplateParameter(Scope *S,
-                                       SourceLocation TmpLoc,
-                                       TemplateParameterList *Params,
-                                       SourceLocation EllipsisLoc,
-                                       IdentifierInfo *ParamName,
-                                       SourceLocation ParamNameLoc,
-                                       unsigned Depth,
-                                       unsigned Position,
-                                       SourceLocation EqualLoc,
-                                       ParsedTemplateArgument DefaultArg);
+  QualType DeduceTemplateSpecializationFromInitializer(
+      TypeSourceInfo *TInfo, const InitializedEntity &Entity,
+      const InitializationKind &Kind, MultiExprArg Init);
 
-  TemplateParameterList *
-  ActOnTemplateParameterList(unsigned Depth,
-                             SourceLocation ExportLoc,
-                             SourceLocation TemplateLoc,
-                             SourceLocation LAngleLoc,
-                             ArrayRef Params,
-                             SourceLocation RAngleLoc,
-                             Expr *RequiresClause);
+  ///@}
 
-  /// The context in which we are checking a template parameter list.
-  enum TemplateParamListContext {
-    TPC_ClassTemplate,
-    TPC_VarTemplate,
-    TPC_FunctionTemplate,
-    TPC_ClassTemplateMember,
-    TPC_FriendClassTemplate,
-    TPC_FriendFunctionTemplate,
-    TPC_FriendFunctionTemplateDefinition,
-    TPC_TypeAliasTemplate
-  };
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  bool CheckTemplateParameterList(TemplateParameterList *NewParams,
-                                  TemplateParameterList *OldParams,
-                                  TemplateParamListContext TPC,
-                                  SkipBodyInfo *SkipBody = nullptr);
-  TemplateParameterList *MatchTemplateParametersToScopeSpecifier(
-      SourceLocation DeclStartLoc, SourceLocation DeclLoc,
-      const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId,
-      ArrayRef ParamLists,
-      bool IsFriend, bool &IsMemberSpecialization, bool &Invalid,
-      bool SuppressDiagnostic = false);
+  /// \name C++ Lambda Expressions
+  /// Implementations are in SemaLambda.cpp
+  ///@{
 
-  DeclResult CheckClassTemplate(
-      Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
-      CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
-      const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
-      AccessSpecifier AS, SourceLocation ModulePrivateLoc,
-      SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists,
-      TemplateParameterList **OuterTemplateParamLists,
-      SkipBodyInfo *SkipBody = nullptr);
+public:
+  /// Create a new lambda closure type.
+  CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
+                                         TypeSourceInfo *Info,
+                                         unsigned LambdaDependencyKind,
+                                         LambdaCaptureDefault CaptureDefault);
 
-  TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
-                                                    QualType NTTPType,
-                                                    SourceLocation Loc);
+  /// Number lambda for linkage purposes if necessary.
+  void handleLambdaNumbering(CXXRecordDecl *Class, CXXMethodDecl *Method,
+                             std::optional
+                                 NumberingOverride = std::nullopt);
 
-  /// Get a template argument mapping the given template parameter to itself,
-  /// e.g. for X in \c template, this would return an expression template
-  /// argument referencing X.
-  TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param,
-                                                     SourceLocation Location);
+  /// Endow the lambda scope info with the relevant properties.
+  void buildLambdaScope(sema::LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator,
+                        SourceRange IntroducerRange,
+                        LambdaCaptureDefault CaptureDefault,
+                        SourceLocation CaptureDefaultLoc, bool ExplicitParams,
+                        bool Mutable);
 
-  void translateTemplateArguments(const ASTTemplateArgsPtr &In,
-                                  TemplateArgumentListInfo &Out);
+  CXXMethodDecl *CreateLambdaCallOperator(SourceRange IntroducerRange,
+                                          CXXRecordDecl *Class);
 
-  ParsedTemplateArgument ActOnTemplateTypeArgument(TypeResult ParsedType);
+  void AddTemplateParametersToLambdaCallOperator(
+      CXXMethodDecl *CallOperator, CXXRecordDecl *Class,
+      TemplateParameterList *TemplateParams);
 
-  void NoteAllFoundTemplates(TemplateName Name);
+  void CompleteLambdaCallOperator(
+      CXXMethodDecl *Method, SourceLocation LambdaLoc,
+      SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause,
+      TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind,
+      StorageClass SC, ArrayRef Params,
+      bool HasExplicitResultType);
 
-  QualType CheckTemplateIdType(TemplateName Template,
-                               SourceLocation TemplateLoc,
-                              TemplateArgumentListInfo &TemplateArgs);
+  void DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method);
 
-  TypeResult
-  ActOnTemplateIdType(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
-                      TemplateTy Template, IdentifierInfo *TemplateII,
-                      SourceLocation TemplateIILoc, SourceLocation LAngleLoc,
-                      ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc,
-                      bool IsCtorOrDtorName = false, bool IsClassName = false,
-                      ImplicitTypenameContext AllowImplicitTypename =
-                          ImplicitTypenameContext::No);
+  /// Perform initialization analysis of the init-capture and perform
+  /// any implicit conversions such as an lvalue-to-rvalue conversion if
+  /// not being used to initialize a reference.
+  ParsedType actOnLambdaInitCaptureInitialization(
+      SourceLocation Loc, bool ByRef, SourceLocation EllipsisLoc,
+      IdentifierInfo *Id, LambdaCaptureInitKind InitKind, Expr *&Init) {
+    return ParsedType::make(buildLambdaInitCaptureInitialization(
+        Loc, ByRef, EllipsisLoc, std::nullopt, Id,
+        InitKind != LambdaCaptureInitKind::CopyInit, Init));
+  }
+  QualType buildLambdaInitCaptureInitialization(
+      SourceLocation Loc, bool ByRef, SourceLocation EllipsisLoc,
+      std::optional NumExpansions, IdentifierInfo *Id,
+      bool DirectInit, Expr *&Init);
 
-  /// Parsed an elaborated-type-specifier that refers to a template-id,
-  /// such as \c class T::template apply.
-  TypeResult ActOnTagTemplateIdType(TagUseKind TUK,
-                                    TypeSpecifierType TagSpec,
-                                    SourceLocation TagLoc,
-                                    CXXScopeSpec &SS,
-                                    SourceLocation TemplateKWLoc,
-                                    TemplateTy TemplateD,
-                                    SourceLocation TemplateLoc,
-                                    SourceLocation LAngleLoc,
-                                    ASTTemplateArgsPtr TemplateArgsIn,
-                                    SourceLocation RAngleLoc);
+  /// Create a dummy variable within the declcontext of the lambda's
+  ///  call operator, for name lookup purposes for a lambda init capture.
+  ///
+  ///  CodeGen handles emission of lambda captures, ignoring these dummy
+  ///  variables appropriately.
+  VarDecl *createLambdaInitCaptureVarDecl(
+      SourceLocation Loc, QualType InitCaptureType, SourceLocation EllipsisLoc,
+      IdentifierInfo *Id, unsigned InitStyle, Expr *Init, DeclContext *DeclCtx);
 
-  DeclResult ActOnVarTemplateSpecialization(
-      Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
-      SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
-      StorageClass SC, bool IsPartialSpecialization);
+  /// Add an init-capture to a lambda scope.
+  void addInitCapture(sema::LambdaScopeInfo *LSI, VarDecl *Var, bool ByRef);
 
-  /// Get the specialization of the given variable template corresponding to
-  /// the specified argument list, or a null-but-valid result if the arguments
-  /// are dependent.
-  DeclResult CheckVarTemplateId(VarTemplateDecl *Template,
-                                SourceLocation TemplateLoc,
-                                SourceLocation TemplateNameLoc,
-                                const TemplateArgumentListInfo &TemplateArgs);
+  /// Note that we have finished the explicit captures for the
+  /// given lambda.
+  void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
 
-  /// Form a reference to the specialization of the given variable template
-  /// corresponding to the specified argument list, or a null-but-valid result
-  /// if the arguments are dependent.
-  ExprResult CheckVarTemplateId(const CXXScopeSpec &SS,
-                                const DeclarationNameInfo &NameInfo,
-                                VarTemplateDecl *Template, NamedDecl *FoundD,
-                                SourceLocation TemplateLoc,
-                                const TemplateArgumentListInfo *TemplateArgs);
+  /// Deduce a block or lambda's return type based on the return
+  /// statements present in the body.
+  void deduceClosureReturnType(sema::CapturingScopeInfo &CSI);
 
-  ExprResult
-  CheckConceptTemplateId(const CXXScopeSpec &SS,
-                         SourceLocation TemplateKWLoc,
-                         const DeclarationNameInfo &ConceptNameInfo,
-                         NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
-                         const TemplateArgumentListInfo *TemplateArgs);
+  /// Once the Lambdas capture are known, we can start to create the closure,
+  /// call operator method, and keep track of the captures.
+  /// We do the capture lookup here, but they are not actually captured until
+  /// after we know what the qualifiers of the call operator are.
+  void ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro,
+                                            Scope *CurContext);
 
-  void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
+  /// This is called after parsing the explicit template parameter list
+  /// on a lambda (if it exists) in C++2a.
+  void ActOnLambdaExplicitTemplateParameterList(LambdaIntroducer &Intro,
+                                                SourceLocation LAngleLoc,
+                                                ArrayRef TParams,
+                                                SourceLocation RAngleLoc,
+                                                ExprResult RequiresClause);
 
-  ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
-                                 SourceLocation TemplateKWLoc,
-                                 LookupResult &R,
-                                 bool RequiresADL,
-                               const TemplateArgumentListInfo *TemplateArgs);
+  void ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro,
+                                    SourceLocation MutableLoc);
 
-  ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
-                                          SourceLocation TemplateKWLoc,
-                               const DeclarationNameInfo &NameInfo,
-                               const TemplateArgumentListInfo *TemplateArgs);
+  void ActOnLambdaClosureParameters(
+      Scope *LambdaScope,
+      MutableArrayRef ParamInfo);
 
-  TemplateNameKind ActOnTemplateName(
-      Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
-      const UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext,
-      TemplateTy &Template, bool AllowInjectedClassName = false);
-
-  DeclResult ActOnClassTemplateSpecialization(
-      Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
-      SourceLocation ModulePrivateLoc, CXXScopeSpec &SS,
-      TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr,
-      MultiTemplateParamsArg TemplateParameterLists,
-      SkipBodyInfo *SkipBody = nullptr);
-
-  bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc,
-                                              TemplateDecl *PrimaryTemplate,
-                                              unsigned NumExplicitArgs,
-                                              ArrayRef Args);
-  void CheckTemplatePartialSpecialization(
-      ClassTemplatePartialSpecializationDecl *Partial);
-  void CheckTemplatePartialSpecialization(
-      VarTemplatePartialSpecializationDecl *Partial);
+  /// ActOnStartOfLambdaDefinition - This is called just before we start
+  /// parsing the body of a lambda; it analyzes the explicit captures and
+  /// arguments, and sets up various data-structures for the body of the
+  /// lambda.
+  void ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
+                                    Declarator &ParamInfo, const DeclSpec &DS);
 
-  Decl *ActOnTemplateDeclarator(Scope *S,
-                                MultiTemplateParamsArg TemplateParameterLists,
-                                Declarator &D);
+  /// ActOnLambdaError - If there is an error parsing a lambda, this callback
+  /// is invoked to pop the information about the lambda.
+  void ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
+                        bool IsInstantiation = false);
 
-  bool
-  CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
-                                         TemplateSpecializationKind NewTSK,
-                                         NamedDecl *PrevDecl,
-                                         TemplateSpecializationKind PrevTSK,
-                                         SourceLocation PrevPtOfInstantiation,
-                                         bool &SuppressNew);
+  /// ActOnLambdaExpr - This is called when the body of a lambda expression
+  /// was successfully completed.
+  ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body);
 
-  bool CheckDependentFunctionTemplateSpecialization(
-      FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
-      LookupResult &Previous);
+  /// Does copying/destroying the captured variable have side effects?
+  bool CaptureHasSideEffects(const sema::Capture &From);
 
-  bool CheckFunctionTemplateSpecialization(
-      FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
-      LookupResult &Previous, bool QualifiedFriend = false);
-  bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
-  void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
+  /// Diagnose if an explicit lambda capture is unused. Returns true if a
+  /// diagnostic is emitted.
+  bool DiagnoseUnusedLambdaCapture(SourceRange CaptureRange,
+                                   const sema::Capture &From);
 
-  DeclResult ActOnExplicitInstantiation(
-      Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc,
-      unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS,
-      TemplateTy Template, SourceLocation TemplateNameLoc,
-      SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs,
-      SourceLocation RAngleLoc, const ParsedAttributesView &Attr);
+  /// Build a FieldDecl suitable to hold the given capture.
+  FieldDecl *BuildCaptureField(RecordDecl *RD, const sema::Capture &Capture);
 
-  DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
-                                        SourceLocation TemplateLoc,
-                                        unsigned TagSpec, SourceLocation KWLoc,
-                                        CXXScopeSpec &SS, IdentifierInfo *Name,
-                                        SourceLocation NameLoc,
-                                        const ParsedAttributesView &Attr);
+  /// Initialize the given capture with a suitable expression.
+  ExprResult BuildCaptureInit(const sema::Capture &Capture,
+                              SourceLocation ImplicitCaptureLoc,
+                              bool IsOpenMPMapping = false);
 
-  DeclResult ActOnExplicitInstantiation(Scope *S,
-                                        SourceLocation ExternLoc,
-                                        SourceLocation TemplateLoc,
-                                        Declarator &D);
+  /// Complete a lambda-expression having processed and attached the
+  /// lambda body.
+  ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
+                             sema::LambdaScopeInfo *LSI);
 
-  TemplateArgumentLoc SubstDefaultTemplateArgumentIfAvailable(
-      TemplateDecl *Template, SourceLocation TemplateLoc,
-      SourceLocation RAngleLoc, Decl *Param,
-      ArrayRef SugaredConverted,
-      ArrayRef CanonicalConverted, bool &HasDefaultArg);
+  /// Get the return type to use for a lambda's conversion function(s) to
+  /// function pointer type, given the type of the call operator.
+  QualType
+  getLambdaConversionFunctionResultType(const FunctionProtoType *CallOpType,
+                                        CallingConv CC);
 
-  SourceLocation getTopMostPointOfInstantiation(const NamedDecl *) const;
+  ExprResult BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
+                                           SourceLocation ConvLocation,
+                                           CXXConversionDecl *Conv, Expr *Src);
 
-  /// Specifies the context in which a particular template
-  /// argument is being checked.
-  enum CheckTemplateArgumentKind {
-    /// The template argument was specified in the code or was
-    /// instantiated with some deduced template arguments.
-    CTAK_Specified,
+  class LambdaScopeForCallOperatorInstantiationRAII
+      : private FunctionScopeRAII {
+  public:
+    LambdaScopeForCallOperatorInstantiationRAII(
+        Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL,
+        LocalInstantiationScope &Scope,
+        bool ShouldAddDeclsFromParentScope = true);
+  };
 
-    /// The template argument was deduced via template argument
-    /// deduction.
-    CTAK_Deduced,
+  /// Compute the mangling number context for a lambda expression or
+  /// block literal. Also return the extra mangling decl if any.
+  ///
+  /// \param DC - The DeclContext containing the lambda expression or
+  /// block literal.
+  std::tuple
+  getCurrentMangleNumberContext(const DeclContext *DC);
 
-    /// The template argument was deduced from an array bound
-    /// via template argument deduction.
-    CTAK_DeducedFromArrayBound
-  };
+  ///@}
 
-  bool
-  CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &Arg,
-                        NamedDecl *Template, SourceLocation TemplateLoc,
-                        SourceLocation RAngleLoc, unsigned ArgumentPackIndex,
-                        SmallVectorImpl &SugaredConverted,
-                        SmallVectorImpl &CanonicalConverted,
-                        CheckTemplateArgumentKind CTAK);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Check that the given template arguments can be provided to
-  /// the given template, converting the arguments along the way.
-  ///
-  /// \param Template The template to which the template arguments are being
-  /// provided.
-  ///
-  /// \param TemplateLoc The location of the template name in the source.
-  ///
-  /// \param TemplateArgs The list of template arguments. If the template is
-  /// a template template parameter, this function may extend the set of
-  /// template arguments to also include substituted, defaulted template
-  /// arguments.
+  /// \name Name Lookup
   ///
-  /// \param PartialTemplateArgs True if the list of template arguments is
-  /// intentionally partial, e.g., because we're checking just the initial
-  /// set of template arguments.
-  ///
-  /// \param Converted Will receive the converted, canonicalized template
-  /// arguments.
+  /// These routines provide name lookup that is used during semantic
+  /// analysis to resolve the various kinds of names (identifiers,
+  /// overloaded operator names, constructor names, etc.) into zero or
+  /// more declarations within a particular scope. The major entry
+  /// points are LookupName, which performs unqualified name lookup,
+  /// and LookupQualifiedName, which performs qualified name lookup.
   ///
-  /// \param UpdateArgsWithConversions If \c true, update \p TemplateArgs to
-  /// contain the converted forms of the template arguments as written.
-  /// Otherwise, \p TemplateArgs will not be modified.
+  /// All name lookup is performed based on some specific criteria,
+  /// which specify what names will be visible to name lookup and how
+  /// far name lookup should work. These criteria are important both
+  /// for capturing language semantics (certain lookups will ignore
+  /// certain names, for example) and for performance, since name
+  /// lookup is often a bottleneck in the compilation of C++. Name
+  /// lookup criteria is specified via the LookupCriteria enumeration.
   ///
-  /// \param ConstraintsNotSatisfied If provided, and an error occurred, will
-  /// receive true if the cause for the error is the associated constraints of
-  /// the template not being satisfied by the template arguments.
+  /// The results of name lookup can vary based on the kind of name
+  /// lookup performed, the current language, and the translation
+  /// unit. In C, for example, name lookup will either return nothing
+  /// (no entity found) or a single declaration. In C++, name lookup
+  /// can additionally refer to a set of overloaded functions or
+  /// result in an ambiguity. All of the possible results of name
+  /// lookup are captured by the LookupResult class, which provides
+  /// the ability to distinguish among them.
   ///
-  /// \returns true if an error occurred, false otherwise.
-  bool CheckTemplateArgumentList(
-      TemplateDecl *Template, SourceLocation TemplateLoc,
-      TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs,
-      SmallVectorImpl &SugaredConverted,
-      SmallVectorImpl &CanonicalConverted,
-      bool UpdateArgsWithConversions = true,
-      bool *ConstraintsNotSatisfied = nullptr);
+  /// Implementations are in SemaLookup.cpp
+  ///@{
 
-  bool CheckTemplateTypeArgument(
-      TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
-      SmallVectorImpl &SugaredConverted,
-      SmallVectorImpl &CanonicalConverted);
+public:
+  /// Tracks whether we are in a context where typo correction is
+  /// disabled.
+  bool DisableTypoCorrection;
 
-  bool CheckTemplateArgument(TypeSourceInfo *Arg);
-  ExprResult CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
-                                   QualType InstantiatedParamType, Expr *Arg,
-                                   TemplateArgument &SugaredConverted,
-                                   TemplateArgument &CanonicalConverted,
-                                   CheckTemplateArgumentKind CTAK);
-  bool CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
-                                     TemplateParameterList *Params,
-                                     TemplateArgumentLoc &Arg);
+  /// The number of typos corrected by CorrectTypo.
+  unsigned TyposCorrected;
 
-  void NoteTemplateLocation(const NamedDecl &Decl,
-                            std::optional ParamRange = {});
-  void NoteTemplateParameterLocation(const NamedDecl &Decl);
+  typedef llvm::SmallSet SrcLocSet;
+  typedef llvm::DenseMap IdentifierSourceLocations;
 
-  ExprResult
-  BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
-                                          QualType ParamType,
-                                          SourceLocation Loc);
-  ExprResult
-  BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
-                                             SourceLocation Loc);
+  /// A cache containing identifiers for which typo correction failed and
+  /// their locations, so that repeated attempts to correct an identifier in a
+  /// given location are ignored if typo correction already failed for it.
+  IdentifierSourceLocations TypoCorrectionFailures;
 
-  /// Enumeration describing how template parameter lists are compared
-  /// for equality.
-  enum TemplateParameterListEqualKind {
-    /// We are matching the template parameter lists of two templates
-    /// that might be redeclarations.
-    ///
-    /// \code
-    /// template struct X;
-    /// template struct X;
-    /// \endcode
-    TPL_TemplateMatch,
+  /// SpecialMemberOverloadResult - The overloading result for a special member
+  /// function.
+  ///
+  /// This is basically a wrapper around PointerIntPair. The lowest bits of the
+  /// integer are used to determine whether overload resolution succeeded.
+  class SpecialMemberOverloadResult {
+  public:
+    enum Kind { NoMemberOrDeleted, Ambiguous, Success };
 
-    /// We are matching the template parameter lists of two template
-    /// template parameters as part of matching the template parameter lists
-    /// of two templates that might be redeclarations.
-    ///
-    /// \code
-    /// template class TT> struct X;
-    /// template class Other> struct X;
-    /// \endcode
-    TPL_TemplateTemplateParmMatch,
+  private:
+    llvm::PointerIntPair Pair;
 
-    /// We are matching the template parameter lists of a template
-    /// template argument against the template parameter lists of a template
-    /// template parameter.
-    ///
-    /// \code
-    /// template class Metafun> struct X;
-    /// template struct integer_c;
-    /// X xic;
-    /// \endcode
-    TPL_TemplateTemplateArgumentMatch,
+  public:
+    SpecialMemberOverloadResult() {}
+    SpecialMemberOverloadResult(CXXMethodDecl *MD)
+        : Pair(MD, MD->isDeleted() ? NoMemberOrDeleted : Success) {}
 
-    /// We are determining whether the template-parameters are equivalent
-    /// according to C++ [temp.over.link]/6. This comparison does not consider
-    /// constraints.
-    ///
-    /// \code
-    /// template void f(T);
-    /// template void f(T);
-    /// \endcode
-    TPL_TemplateParamsEquivalent,
-  };
+    CXXMethodDecl *getMethod() const { return Pair.getPointer(); }
+    void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); }
 
-  // A struct to represent the 'new' declaration, which is either itself just
-  // the named decl, or the important information we need about it in order to
-  // do constraint comparisons.
-  class TemplateCompareNewDeclInfo {
-    const NamedDecl *ND = nullptr;
-    const DeclContext *DC = nullptr;
-    const DeclContext *LexicalDC = nullptr;
-    SourceLocation Loc;
+    Kind getKind() const { return static_cast(Pair.getInt()); }
+    void setKind(Kind K) { Pair.setInt(K); }
+  };
 
+  class SpecialMemberOverloadResultEntry : public llvm::FastFoldingSetNode,
+                                           public SpecialMemberOverloadResult {
   public:
-    TemplateCompareNewDeclInfo(const NamedDecl *ND) : ND(ND) {}
-    TemplateCompareNewDeclInfo(const DeclContext *DeclCtx,
-                               const DeclContext *LexicalDeclCtx,
-                               SourceLocation Loc)
-
-        : DC(DeclCtx), LexicalDC(LexicalDeclCtx), Loc(Loc) {
-      assert(DC && LexicalDC &&
-             "Constructor only for cases where we have the information to put "
-             "in here");
-    }
-
-    // If this was constructed with no information, we cannot do substitution
-    // for constraint comparison, so make sure we can check that.
-    bool isInvalid() const { return !ND && !DC; }
+    SpecialMemberOverloadResultEntry(const llvm::FoldingSetNodeID &ID)
+        : FastFoldingSetNode(ID) {}
+  };
 
-    const NamedDecl *getDecl() const { return ND; }
+  /// A cache of special member function overload resolution results
+  /// for C++ records.
+  llvm::FoldingSet SpecialMemberCache;
 
-    bool ContainsDecl(const NamedDecl *ND) const { return this->ND == ND; }
+  /// Holds TypoExprs that are created from `createDelayedTypo`. This is used by
+  /// `TransformTypos` in order to keep track of any TypoExprs that are created
+  /// recursively during typo correction and wipe them away if the correction
+  /// fails.
+  llvm::SmallVector TypoExprs;
 
-    const DeclContext *getLexicalDeclContext() const {
-      return ND ? ND->getLexicalDeclContext() : LexicalDC;
-    }
+  enum class AcceptableKind { Visible, Reachable };
 
-    const DeclContext *getDeclContext() const {
-      return ND ? ND->getDeclContext() : DC;
-    }
+  // Members have to be NamespaceDecl* or TranslationUnitDecl*.
+  // TODO: make this is a typesafe union.
+  typedef llvm::SmallSetVector AssociatedNamespaceSet;
+  typedef llvm::SmallSetVector AssociatedClassSet;
 
-    SourceLocation getLocation() const { return ND ? ND->getLocation() : Loc; }
+  /// Describes the kind of name lookup to perform.
+  enum LookupNameKind {
+    /// Ordinary name lookup, which finds ordinary names (functions,
+    /// variables, typedefs, etc.) in C and most kinds of names
+    /// (functions, variables, members, types, etc.) in C++.
+    LookupOrdinaryName = 0,
+    /// Tag name lookup, which finds the names of enums, classes,
+    /// structs, and unions.
+    LookupTagName,
+    /// Label name lookup.
+    LookupLabel,
+    /// Member name lookup, which finds the names of
+    /// class/struct/union members.
+    LookupMemberName,
+    /// Look up of an operator name (e.g., operator+) for use with
+    /// operator overloading. This lookup is similar to ordinary name
+    /// lookup, but will ignore any declarations that are class members.
+    LookupOperatorName,
+    /// Look up a name following ~ in a destructor name. This is an ordinary
+    /// lookup, but prefers tags to typedefs.
+    LookupDestructorName,
+    /// Look up of a name that precedes the '::' scope resolution
+    /// operator in C++. This lookup completely ignores operator, object,
+    /// function, and enumerator names (C++ [basic.lookup.qual]p1).
+    LookupNestedNameSpecifierName,
+    /// Look up a namespace name within a C++ using directive or
+    /// namespace alias definition, ignoring non-namespace names (C++
+    /// [basic.lookup.udir]p1).
+    LookupNamespaceName,
+    /// Look up all declarations in a scope with the given name,
+    /// including resolved using declarations.  This is appropriate
+    /// for checking redeclarations for a using declaration.
+    LookupUsingDeclName,
+    /// Look up an ordinary name that is going to be redeclared as a
+    /// name with linkage. This lookup ignores any declarations that
+    /// are outside of the current scope unless they have linkage. See
+    /// C99 6.2.2p4-5 and C++ [basic.link]p6.
+    LookupRedeclarationWithLinkage,
+    /// Look up a friend of a local class. This lookup does not look
+    /// outside the innermost non-class scope. See C++11 [class.friend]p11.
+    LookupLocalFriendName,
+    /// Look up the name of an Objective-C protocol.
+    LookupObjCProtocolName,
+    /// Look up implicit 'self' parameter of an objective-c method.
+    LookupObjCImplicitSelfParam,
+    /// Look up the name of an OpenMP user-defined reduction operation.
+    LookupOMPReductionName,
+    /// Look up the name of an OpenMP user-defined mapper.
+    LookupOMPMapperName,
+    /// Look up any declaration with any name.
+    LookupAnyName
   };
 
-  bool TemplateParameterListsAreEqual(
-      const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New,
-      const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain,
-      TemplateParameterListEqualKind Kind,
-      SourceLocation TemplateArgLoc = SourceLocation());
+  /// The possible outcomes of name lookup for a literal operator.
+  enum LiteralOperatorLookupResult {
+    /// The lookup resulted in an error.
+    LOLR_Error,
+    /// The lookup found no match but no diagnostic was issued.
+    LOLR_ErrorNoDiagnostic,
+    /// The lookup found a single 'cooked' literal operator, which
+    /// expects a normal literal to be built and passed to it.
+    LOLR_Cooked,
+    /// The lookup found a single 'raw' literal operator, which expects
+    /// a string literal containing the spelling of the literal token.
+    LOLR_Raw,
+    /// The lookup found an overload set of literal operator templates,
+    /// which expect the characters of the spelling of the literal token to be
+    /// passed as a non-type template argument pack.
+    LOLR_Template,
+    /// The lookup found an overload set of literal operator templates,
+    /// which expect the character type and characters of the spelling of the
+    /// string literal token to be passed as template arguments.
+    LOLR_StringTemplatePack,
+  };
 
-  bool TemplateParameterListsAreEqual(
-      TemplateParameterList *New, TemplateParameterList *Old, bool Complain,
-      TemplateParameterListEqualKind Kind,
-      SourceLocation TemplateArgLoc = SourceLocation()) {
-    return TemplateParameterListsAreEqual(nullptr, New, nullptr, Old, Complain,
-                                          Kind, TemplateArgLoc);
-  }
+  SpecialMemberOverloadResult
+  LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMember SM, bool ConstArg,
+                      bool VolatileArg, bool RValueThis, bool ConstThis,
+                      bool VolatileThis);
 
-  // Calculates whether two constraint expressions are equal irrespective of a
-  // difference in 'depth'. This takes a pair of optional 'NamedDecl's 'Old' and
-  // 'New', which are the "source" of the constraint, since this is necessary
-  // for figuring out the relative 'depth' of the constraint. The depth of the
-  // 'primary template' and the 'instantiated from' templates aren't necessarily
-  // the same, such as a case when one is a 'friend' defined in a class.
-  bool AreConstraintExpressionsEqual(const NamedDecl *Old,
-                                     const Expr *OldConstr,
-                                     const TemplateCompareNewDeclInfo &New,
-                                     const Expr *NewConstr);
+  typedef std::function TypoDiagnosticGenerator;
+  typedef std::function
+      TypoRecoveryCallback;
 
-  bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams);
+  /// Specifies whether (or how) name lookup is being performed for a
+  /// redeclaration (vs. a reference).
+  enum RedeclarationKind {
+    /// The lookup is a reference to this name that is not for the
+    /// purpose of redeclaring the name.
+    NotForRedeclaration = 0,
+    /// The lookup results will be used for redeclaration of a name,
+    /// if an entity by that name already exists and is visible.
+    ForVisibleRedeclaration,
+    /// The lookup results will be used for redeclaration of a name
+    /// with external linkage; non-visible lookup results with external linkage
+    /// may also be found.
+    ForExternalRedeclaration
+  };
 
-  /// Called when the parser has parsed a C++ typename
-  /// specifier, e.g., "typename T::type".
-  ///
-  /// \param S The scope in which this typename type occurs.
-  /// \param TypenameLoc the location of the 'typename' keyword
-  /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
-  /// \param II the identifier we're retrieving (e.g., 'type' in the example).
-  /// \param IdLoc the location of the identifier.
-  /// \param IsImplicitTypename context where T::type refers to a type.
-  TypeResult ActOnTypenameType(
-      Scope *S, SourceLocation TypenameLoc, const CXXScopeSpec &SS,
-      const IdentifierInfo &II, SourceLocation IdLoc,
-      ImplicitTypenameContext IsImplicitTypename = ImplicitTypenameContext::No);
+  RedeclarationKind forRedeclarationInCurContext() const {
+    // A declaration with an owning module for linkage can never link against
+    // anything that is not visible. We don't need to check linkage here; if
+    // the context has internal linkage, redeclaration lookup won't find things
+    // from other TUs, and we can't safely compute linkage yet in general.
+    if (cast(CurContext)
+            ->getOwningModuleForLinkage(/*IgnoreLinkage*/ true))
+      return ForVisibleRedeclaration;
+    return ForExternalRedeclaration;
+  }
 
-  /// Called when the parser has parsed a C++ typename
-  /// specifier that ends in a template-id, e.g.,
-  /// "typename MetaFun::template apply".
+  /// Look up a name, looking for a single declaration.  Return
+  /// null if the results were absent, ambiguous, or overloaded.
   ///
-  /// \param S The scope in which this typename type occurs.
-  /// \param TypenameLoc the location of the 'typename' keyword
-  /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
-  /// \param TemplateLoc the location of the 'template' keyword, if any.
-  /// \param TemplateName The template name.
-  /// \param TemplateII The identifier used to name the template.
-  /// \param TemplateIILoc The location of the template name.
-  /// \param LAngleLoc The location of the opening angle bracket  ('<').
-  /// \param TemplateArgs The template arguments.
-  /// \param RAngleLoc The location of the closing angle bracket  ('>').
-  TypeResult
-  ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
-                    const CXXScopeSpec &SS,
-                    SourceLocation TemplateLoc,
-                    TemplateTy TemplateName,
-                    IdentifierInfo *TemplateII,
-                    SourceLocation TemplateIILoc,
-                    SourceLocation LAngleLoc,
-                    ASTTemplateArgsPtr TemplateArgs,
-                    SourceLocation RAngleLoc);
+  /// It is preferable to use the elaborated form and explicitly handle
+  /// ambiguity and overloaded.
+  NamedDecl *LookupSingleName(Scope *S, DeclarationName Name,
+                              SourceLocation Loc, LookupNameKind NameKind,
+                              RedeclarationKind Redecl = NotForRedeclaration);
+  bool LookupBuiltin(LookupResult &R);
+  void LookupNecessaryTypesForBuiltin(Scope *S, unsigned ID);
+  bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation = false,
+                  bool ForceNoCPlusPlus = false);
+  bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
+                           bool InUnqualifiedLookup = false);
+  bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
+                           CXXScopeSpec &SS);
+  bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
+                        bool AllowBuiltinCreation = false,
+                        bool EnteringContext = false);
+  ObjCProtocolDecl *
+  LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc,
+                 RedeclarationKind Redecl = NotForRedeclaration);
+  bool LookupInSuper(LookupResult &R, CXXRecordDecl *Class);
 
-  QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
-                             SourceLocation KeywordLoc,
-                             NestedNameSpecifierLoc QualifierLoc,
-                             const IdentifierInfo &II,
-                             SourceLocation IILoc,
-                             TypeSourceInfo **TSI,
-                             bool DeducedTSTContext);
+  void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
+                                    UnresolvedSetImpl &Functions);
 
-  QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
-                             SourceLocation KeywordLoc,
-                             NestedNameSpecifierLoc QualifierLoc,
-                             const IdentifierInfo &II,
-                             SourceLocation IILoc,
-                             bool DeducedTSTContext = true);
+  LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
+                                 SourceLocation GnuLabelLoc = SourceLocation());
 
+  DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);
+  CXXConstructorDecl *LookupDefaultConstructor(CXXRecordDecl *Class);
+  CXXConstructorDecl *LookupCopyingConstructor(CXXRecordDecl *Class,
+                                               unsigned Quals);
+  CXXMethodDecl *LookupCopyingAssignment(CXXRecordDecl *Class, unsigned Quals,
+                                         bool RValueThis, unsigned ThisQuals);
+  CXXConstructorDecl *LookupMovingConstructor(CXXRecordDecl *Class,
+                                              unsigned Quals);
+  CXXMethodDecl *LookupMovingAssignment(CXXRecordDecl *Class, unsigned Quals,
+                                        bool RValueThis, unsigned ThisQuals);
+  CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
 
-  TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
-                                                    SourceLocation Loc,
-                                                    DeclarationName Name);
-  bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS);
+  /// Force the declaration of any implicitly-declared members of this
+  /// class.
+  void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class);
 
-  ExprResult RebuildExprInCurrentInstantiation(Expr *E);
-  bool RebuildTemplateParamsInCurrentInstantiation(
-                                                TemplateParameterList *Params);
+  /// Make a merged definition of an existing hidden definition \p ND
+  /// visible at the specified location.
+  void makeMergedDefinitionVisible(NamedDecl *ND);
 
-  std::string
-  getTemplateArgumentBindingsText(const TemplateParameterList *Params,
-                                  const TemplateArgumentList &Args);
+  /// Get the set of additional modules that should be checked during
+  /// name lookup. A module and its imports become visible when instanting a
+  /// template defined within it.
+  llvm::DenseSet &getLookupModules();
 
-  std::string
-  getTemplateArgumentBindingsText(const TemplateParameterList *Params,
-                                  const TemplateArgument *Args,
-                                  unsigned NumArgs);
+  bool hasVisibleMergedDefinition(const NamedDecl *Def);
+  bool hasMergedDefinitionInCurrentModule(const NamedDecl *Def);
 
-  //===--------------------------------------------------------------------===//
-  // C++ Concepts
-  //===--------------------------------------------------------------------===//
-  Decl *ActOnConceptDefinition(
-      Scope *S, MultiTemplateParamsArg TemplateParameterLists,
-      IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr);
+  /// Determine if the template parameter \p D has a visible default argument.
+  bool
+  hasVisibleDefaultArgument(const NamedDecl *D,
+                            llvm::SmallVectorImpl *Modules = nullptr);
+  /// Determine if the template parameter \p D has a reachable default argument.
+  bool hasReachableDefaultArgument(
+      const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr);
+  /// Determine if the template parameter \p D has a reachable default argument.
+  bool hasAcceptableDefaultArgument(const NamedDecl *D,
+                                    llvm::SmallVectorImpl *Modules,
+                                    Sema::AcceptableKind Kind);
 
-  void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous,
-                                bool &AddToScope);
+  /// Determine if there is a visible declaration of \p D that is an explicit
+  /// specialization declaration for a specialization of a template. (For a
+  /// member specialization, use hasVisibleMemberSpecialization.)
+  bool hasVisibleExplicitSpecialization(
+      const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr);
+  /// Determine if there is a reachable declaration of \p D that is an explicit
+  /// specialization declaration for a specialization of a template. (For a
+  /// member specialization, use hasReachableMemberSpecialization.)
+  bool hasReachableExplicitSpecialization(
+      const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr);
 
-  RequiresExprBodyDecl *
-  ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
-                         ArrayRef LocalParameters,
-                         Scope *BodyScope);
-  void ActOnFinishRequiresExpr();
-  concepts::Requirement *ActOnSimpleRequirement(Expr *E);
-  concepts::Requirement *ActOnTypeRequirement(
-      SourceLocation TypenameKWLoc, CXXScopeSpec &SS, SourceLocation NameLoc,
-      IdentifierInfo *TypeName, TemplateIdAnnotation *TemplateId);
-  concepts::Requirement *ActOnCompoundRequirement(Expr *E,
-                                                  SourceLocation NoexceptLoc);
-  concepts::Requirement *
-  ActOnCompoundRequirement(
-      Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS,
-      TemplateIdAnnotation *TypeConstraint, unsigned Depth);
-  concepts::Requirement *ActOnNestedRequirement(Expr *Constraint);
-  concepts::ExprRequirement *
-  BuildExprRequirement(
-      Expr *E, bool IsSatisfied, SourceLocation NoexceptLoc,
-      concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement);
-  concepts::ExprRequirement *
-  BuildExprRequirement(
-      concepts::Requirement::SubstitutionDiagnostic *ExprSubstDiag,
-      bool IsSatisfied, SourceLocation NoexceptLoc,
-      concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement);
-  concepts::TypeRequirement *BuildTypeRequirement(TypeSourceInfo *Type);
-  concepts::TypeRequirement *
-  BuildTypeRequirement(
-      concepts::Requirement::SubstitutionDiagnostic *SubstDiag);
-  concepts::NestedRequirement *BuildNestedRequirement(Expr *E);
-  concepts::NestedRequirement *
-  BuildNestedRequirement(StringRef InvalidConstraintEntity,
-                         const ASTConstraintSatisfaction &Satisfaction);
-  ExprResult ActOnRequiresExpr(SourceLocation RequiresKWLoc,
-                               RequiresExprBodyDecl *Body,
-                               SourceLocation LParenLoc,
-                               ArrayRef LocalParameters,
-                               SourceLocation RParenLoc,
-                               ArrayRef Requirements,
-                               SourceLocation ClosingBraceLoc);
+  /// Determine if there is a visible declaration of \p D that is a member
+  /// specialization declaration (as opposed to an instantiated declaration).
+  bool hasVisibleMemberSpecialization(
+      const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr);
+  /// Determine if there is a reachable declaration of \p D that is a member
+  /// specialization declaration (as opposed to an instantiated declaration).
+  bool hasReachableMemberSpecialization(
+      const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr);
 
-  //===--------------------------------------------------------------------===//
-  // C++ Variadic Templates (C++0x [temp.variadic])
-  //===--------------------------------------------------------------------===//
+  bool isModuleVisible(const Module *M, bool ModulePrivate = false);
 
-  /// Determine whether an unexpanded parameter pack might be permitted in this
-  /// location. Useful for error recovery.
-  bool isUnexpandedParameterPackPermitted();
+  /// Determine whether any declaration of an entity is visible.
+  bool
+  hasVisibleDeclaration(const NamedDecl *D,
+                        llvm::SmallVectorImpl *Modules = nullptr) {
+    return isVisible(D) || hasVisibleDeclarationSlow(D, Modules);
+  }
 
-  /// The context in which an unexpanded parameter pack is
-  /// being diagnosed.
-  ///
-  /// Note that the values of this enumeration line up with the first
-  /// argument to the \c err_unexpanded_parameter_pack diagnostic.
-  enum UnexpandedParameterPackContext {
-    /// An arbitrary expression.
-    UPPC_Expression = 0,
+  bool hasVisibleDeclarationSlow(const NamedDecl *D,
+                                 llvm::SmallVectorImpl *Modules);
+  /// Determine whether any declaration of an entity is reachable.
+  bool
+  hasReachableDeclaration(const NamedDecl *D,
+                          llvm::SmallVectorImpl *Modules = nullptr) {
+    return isReachable(D) || hasReachableDeclarationSlow(D, Modules);
+  }
+  bool hasReachableDeclarationSlow(
+      const NamedDecl *D, llvm::SmallVectorImpl *Modules = nullptr);
 
-    /// The base type of a class type.
-    UPPC_BaseType,
+  void diagnoseTypo(const TypoCorrection &Correction,
+                    const PartialDiagnostic &TypoDiag,
+                    bool ErrorRecovery = true);
 
-    /// The type of an arbitrary declaration.
-    UPPC_DeclarationType,
+  void diagnoseTypo(const TypoCorrection &Correction,
+                    const PartialDiagnostic &TypoDiag,
+                    const PartialDiagnostic &PrevNote,
+                    bool ErrorRecovery = true);
 
-    /// The type of a data member.
-    UPPC_DataMemberType,
+  void FindAssociatedClassesAndNamespaces(
+      SourceLocation InstantiationLoc, ArrayRef Args,
+      AssociatedNamespaceSet &AssociatedNamespaces,
+      AssociatedClassSet &AssociatedClasses);
 
-    /// The size of a bit-field.
-    UPPC_BitFieldWidth,
+  void DiagnoseAmbiguousLookup(LookupResult &Result);
 
-    /// The expression in a static assertion.
-    UPPC_StaticAssertExpression,
+  LiteralOperatorLookupResult
+  LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef ArgTys,
+                        bool AllowRaw, bool AllowTemplate,
+                        bool AllowStringTemplate, bool DiagnoseMissing,
+                        StringLiteral *StringLit = nullptr);
 
-    /// The fixed underlying type of an enumeration.
-    UPPC_FixedUnderlyingType,
+  void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
+                               ArrayRef Args, ADLResult &Functions);
 
-    /// The enumerator value.
-    UPPC_EnumeratorValue,
+  void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
+                          VisibleDeclConsumer &Consumer,
+                          bool IncludeGlobalScope = true,
+                          bool LoadExternal = true);
+  void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind,
+                          VisibleDeclConsumer &Consumer,
+                          bool IncludeGlobalScope = true,
+                          bool IncludeDependentBases = false,
+                          bool LoadExternal = true);
 
-    /// A using declaration.
-    UPPC_UsingDeclaration,
+  enum CorrectTypoKind {
+    CTK_NonError,     // CorrectTypo used in a non error recovery situation.
+    CTK_ErrorRecovery // CorrectTypo used in normal error recovery.
+  };
 
-    /// A friend declaration.
-    UPPC_FriendDeclaration,
+  TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
+                             Sema::LookupNameKind LookupKind, Scope *S,
+                             CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
+                             CorrectTypoKind Mode,
+                             DeclContext *MemberContext = nullptr,
+                             bool EnteringContext = false,
+                             const ObjCObjectPointerType *OPT = nullptr,
+                             bool RecordFailure = true);
 
-    /// A declaration qualifier.
-    UPPC_DeclarationQualifier,
+  TypoExpr *CorrectTypoDelayed(
+      const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind,
+      Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
+      TypoDiagnosticGenerator TDG, TypoRecoveryCallback TRC,
+      CorrectTypoKind Mode, DeclContext *MemberContext = nullptr,
+      bool EnteringContext = false, const ObjCObjectPointerType *OPT = nullptr);
 
-    /// An initializer.
-    UPPC_Initializer,
+  /// Kinds of missing import. Note, the values of these enumerators correspond
+  /// to %select values in diagnostics.
+  enum class MissingImportKind {
+    Declaration,
+    Definition,
+    DefaultArgument,
+    ExplicitSpecialization,
+    PartialSpecialization
+  };
 
-    /// A default argument.
-    UPPC_DefaultArgument,
+  /// Diagnose that the specified declaration needs to be visible but
+  /// isn't, and suggest a module import that would resolve the problem.
+  void diagnoseMissingImport(SourceLocation Loc, const NamedDecl *Decl,
+                             MissingImportKind MIK, bool Recover = true);
+  void diagnoseMissingImport(SourceLocation Loc, const NamedDecl *Decl,
+                             SourceLocation DeclLoc, ArrayRef Modules,
+                             MissingImportKind MIK, bool Recover);
 
-    /// The type of a non-type template parameter.
-    UPPC_NonTypeTemplateParameterType,
+  struct TypoExprState {
+    std::unique_ptr Consumer;
+    TypoDiagnosticGenerator DiagHandler;
+    TypoRecoveryCallback RecoveryHandler;
+    TypoExprState();
+    TypoExprState(TypoExprState &&other) noexcept;
+    TypoExprState &operator=(TypoExprState &&other) noexcept;
+  };
 
-    /// The type of an exception.
-    UPPC_ExceptionType,
+  const TypoExprState &getTypoExprState(TypoExpr *TE) const;
 
-    /// Explicit specialization.
-    UPPC_ExplicitSpecialization,
+  /// Clears the state of the given TypoExpr.
+  void clearDelayedTypo(TypoExpr *TE);
 
-    /// Partial specialization.
-    UPPC_PartialSpecialization,
+  /// Called on #pragma clang __debug dump II
+  void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
 
-    /// Microsoft __if_exists.
-    UPPC_IfExists,
+  /// Called on #pragma clang __debug dump E
+  void ActOnPragmaDump(Expr *E);
 
-    /// Microsoft __if_not_exists.
-    UPPC_IfNotExists,
+private:
+  // The set of known/encountered (unique, canonicalized) NamespaceDecls.
+  //
+  // The boolean value will be true to indicate that the namespace was loaded
+  // from an AST/PCH file, or false otherwise.
+  llvm::MapVector KnownNamespaces;
 
-    /// Lambda expression.
-    UPPC_Lambda,
+  /// Whether we have already loaded known namespaces from an extenal
+  /// source.
+  bool LoadedExternalKnownNamespaces;
 
-    /// Block expression.
-    UPPC_Block,
+  bool CppLookupName(LookupResult &R, Scope *S);
 
-    /// A type constraint.
-    UPPC_TypeConstraint,
+  bool isUsableModule(const Module *M);
 
-    // A requirement in a requires-expression.
-    UPPC_Requirement,
+  /// Helper for CorrectTypo and CorrectTypoDelayed used to create and
+  /// populate a new TypoCorrectionConsumer. Returns nullptr if typo correction
+  /// should be skipped entirely.
+  std::unique_ptr makeTypoCorrectionConsumer(
+      const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind,
+      Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC,
+      DeclContext *MemberContext, bool EnteringContext,
+      const ObjCObjectPointerType *OPT, bool ErrorRecovery);
 
-    // A requires-clause.
-    UPPC_RequiresClause,
-  };
+  /// The set of unhandled TypoExprs and their associated state.
+  llvm::MapVector DelayedTypos;
 
-  /// Diagnose unexpanded parameter packs.
-  ///
-  /// \param Loc The location at which we should emit the diagnostic.
-  ///
-  /// \param UPPC The context in which we are diagnosing unexpanded
-  /// parameter packs.
-  ///
-  /// \param Unexpanded the set of unexpanded parameter packs.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
-                                        UnexpandedParameterPackContext UPPC,
-                                  ArrayRef Unexpanded);
+  /// Creates a new TypoExpr AST node.
+  TypoExpr *createDelayedTypo(std::unique_ptr TCC,
+                              TypoDiagnosticGenerator TDG,
+                              TypoRecoveryCallback TRC, SourceLocation TypoLoc);
 
-  /// If the given type contains an unexpanded parameter pack,
-  /// diagnose the error.
-  ///
-  /// \param Loc The source location where a diagnostc should be emitted.
-  ///
-  /// \param T The type that is being checked for unexpanded parameter
-  /// packs.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T,
-                                       UnexpandedParameterPackContext UPPC);
+  /// Cache for module units which is usable for current module.
+  llvm::DenseSet UsableModuleUnitsCache;
 
-  /// If the given expression contains an unexpanded parameter
-  /// pack, diagnose the error.
-  ///
-  /// \param E The expression that is being checked for unexpanded
-  /// parameter packs.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool DiagnoseUnexpandedParameterPack(Expr *E,
-                       UnexpandedParameterPackContext UPPC = UPPC_Expression);
+  /// Record the typo correction failure and return an empty correction.
+  TypoCorrection FailedCorrection(IdentifierInfo *Typo, SourceLocation TypoLoc,
+                                  bool RecordFailure = true) {
+    if (RecordFailure)
+      TypoCorrectionFailures[Typo].insert(TypoLoc);
+    return TypoCorrection();
+  }
 
-  /// If the given requirees-expression contains an unexpanded reference to one
-  /// of its own parameter packs, diagnose the error.
-  ///
-  /// \param RE The requiress-expression that is being checked for unexpanded
-  /// parameter packs.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool DiagnoseUnexpandedParameterPackInRequiresExpr(RequiresExpr *RE);
+  bool isAcceptableSlow(const NamedDecl *D, AcceptableKind Kind);
 
-  /// If the given nested-name-specifier contains an unexpanded
-  /// parameter pack, diagnose the error.
-  ///
-  /// \param SS The nested-name-specifier that is being checked for
-  /// unexpanded parameter packs.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
-                                       UnexpandedParameterPackContext UPPC);
+  /// Determine whether two declarations should be linked together, given that
+  /// the old declaration might not be visible and the new declaration might
+  /// not have external linkage.
+  bool shouldLinkPossiblyHiddenDecl(const NamedDecl *Old,
+                                    const NamedDecl *New) {
+    if (isVisible(Old))
+      return true;
+    // See comment in below overload for why it's safe to compute the linkage
+    // of the new declaration here.
+    if (New->isExternallyDeclarable()) {
+      assert(Old->isExternallyDeclarable() &&
+             "should not have found a non-externally-declarable previous decl");
+      return true;
+    }
+    return false;
+  }
+  bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New);
 
-  /// If the given name contains an unexpanded parameter pack,
-  /// diagnose the error.
-  ///
-  /// \param NameInfo The name (with source location information) that
-  /// is being checked for unexpanded parameter packs.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
-                                       UnexpandedParameterPackContext UPPC);
+  ///@}
 
-  /// If the given template name contains an unexpanded parameter pack,
-  /// diagnose the error.
-  ///
-  /// \param Loc The location of the template name.
-  ///
-  /// \param Template The template name that is being checked for unexpanded
-  /// parameter packs.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool DiagnoseUnexpandedParameterPack(SourceLocation Loc,
-                                       TemplateName Template,
-                                       UnexpandedParameterPackContext UPPC);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// If the given template argument contains an unexpanded parameter
-  /// pack, diagnose the error.
-  ///
-  /// \param Arg The template argument that is being checked for unexpanded
-  /// parameter packs.
-  ///
-  /// \returns true if an error occurred, false otherwise.
-  bool DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg,
-                                       UnexpandedParameterPackContext UPPC);
+  /// \name Modules
+  /// Implementations are in SemaModule.cpp
+  ///@{
 
-  /// Collect the set of unexpanded parameter packs within the given
-  /// template argument.
-  ///
-  /// \param Arg The template argument that will be traversed to find
-  /// unexpanded parameter packs.
-  void collectUnexpandedParameterPacks(TemplateArgument Arg,
-                   SmallVectorImpl &Unexpanded);
+public:
+  /// Get the module unit whose scope we are currently within.
+  Module *getCurrentModule() const {
+    return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
+  }
 
-  /// Collect the set of unexpanded parameter packs within the given
-  /// template argument.
-  ///
-  /// \param Arg The template argument that will be traversed to find
-  /// unexpanded parameter packs.
-  void collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
-                    SmallVectorImpl &Unexpanded);
+  /// Is the module scope we are an implementation unit?
+  bool currentModuleIsImplementation() const {
+    return ModuleScopes.empty()
+               ? false
+               : ModuleScopes.back().Module->isModuleImplementation();
+  }
 
-  /// Collect the set of unexpanded parameter packs within the given
-  /// type.
-  ///
-  /// \param T The type that will be traversed to find
-  /// unexpanded parameter packs.
-  void collectUnexpandedParameterPacks(QualType T,
-                   SmallVectorImpl &Unexpanded);
+  // When loading a non-modular PCH files, this is used to restore module
+  // visibility.
+  void makeModuleVisible(Module *Mod, SourceLocation ImportLoc) {
+    VisibleModules.setVisible(Mod, ImportLoc);
+  }
 
-  /// Collect the set of unexpanded parameter packs within the given
-  /// type.
-  ///
-  /// \param TL The type that will be traversed to find
-  /// unexpanded parameter packs.
-  void collectUnexpandedParameterPacks(TypeLoc TL,
-                   SmallVectorImpl &Unexpanded);
+  enum class ModuleDeclKind {
+    Interface,               ///< 'export module X;'
+    Implementation,          ///< 'module X;'
+    PartitionInterface,      ///< 'export module X:Y;'
+    PartitionImplementation, ///< 'module X:Y;'
+  };
 
-  /// Collect the set of unexpanded parameter packs within the given
-  /// nested-name-specifier.
-  ///
-  /// \param NNS The nested-name-specifier that will be traversed to find
-  /// unexpanded parameter packs.
-  void collectUnexpandedParameterPacks(NestedNameSpecifierLoc NNS,
-                         SmallVectorImpl &Unexpanded);
+  /// An enumeration to represent the transition of states in parsing module
+  /// fragments and imports.  If we are not parsing a C++20 TU, or we find
+  /// an error in state transition, the state is set to NotACXX20Module.
+  enum class ModuleImportState {
+    FirstDecl,      ///< Parsing the first decl in a TU.
+    GlobalFragment, ///< after 'module;' but before 'module X;'
+    ImportAllowed,  ///< after 'module X;' but before any non-import decl.
+    ImportFinished, ///< after any non-import decl.
+    PrivateFragmentImportAllowed,  ///< after 'module :private;' but before any
+                                   ///< non-import decl.
+    PrivateFragmentImportFinished, ///< after 'module :private;' but a
+                                   ///< non-import decl has already been seen.
+    NotACXX20Module ///< Not a C++20 TU, or an invalid state was found.
+  };
 
-  /// Collect the set of unexpanded parameter packs within the given
-  /// name.
-  ///
-  /// \param NameInfo The name that will be traversed to find
-  /// unexpanded parameter packs.
-  void collectUnexpandedParameterPacks(const DeclarationNameInfo &NameInfo,
-                         SmallVectorImpl &Unexpanded);
+  /// The parser has processed a module-declaration that begins the definition
+  /// of a module interface or implementation.
+  DeclGroupPtrTy ActOnModuleDecl(SourceLocation StartLoc,
+                                 SourceLocation ModuleLoc, ModuleDeclKind MDK,
+                                 ModuleIdPath Path, ModuleIdPath Partition,
+                                 ModuleImportState &ImportState);
 
-  /// Invoked when parsing a template argument followed by an
-  /// ellipsis, which creates a pack expansion.
-  ///
-  /// \param Arg The template argument preceding the ellipsis, which
-  /// may already be invalid.
-  ///
-  /// \param EllipsisLoc The location of the ellipsis.
-  ParsedTemplateArgument ActOnPackExpansion(const ParsedTemplateArgument &Arg,
-                                            SourceLocation EllipsisLoc);
+  /// The parser has processed a global-module-fragment declaration that begins
+  /// the definition of the global module fragment of the current module unit.
+  /// \param ModuleLoc The location of the 'module' keyword.
+  DeclGroupPtrTy ActOnGlobalModuleFragmentDecl(SourceLocation ModuleLoc);
 
-  /// Invoked when parsing a type followed by an ellipsis, which
-  /// creates a pack expansion.
-  ///
-  /// \param Type The type preceding the ellipsis, which will become
-  /// the pattern of the pack expansion.
+  /// The parser has processed a private-module-fragment declaration that begins
+  /// the definition of the private module fragment of the current module unit.
+  /// \param ModuleLoc The location of the 'module' keyword.
+  /// \param PrivateLoc The location of the 'private' keyword.
+  DeclGroupPtrTy ActOnPrivateModuleFragmentDecl(SourceLocation ModuleLoc,
+                                                SourceLocation PrivateLoc);
+
+  /// The parser has processed a module import declaration.
   ///
-  /// \param EllipsisLoc The location of the ellipsis.
-  TypeResult ActOnPackExpansion(ParsedType Type, SourceLocation EllipsisLoc);
+  /// \param StartLoc The location of the first token in the declaration. This
+  ///        could be the location of an '@', 'export', or 'import'.
+  /// \param ExportLoc The location of the 'export' keyword, if any.
+  /// \param ImportLoc The location of the 'import' keyword.
+  /// \param Path The module toplevel name as an access path.
+  /// \param IsPartition If the name is for a partition.
+  DeclResult ActOnModuleImport(SourceLocation StartLoc,
+                               SourceLocation ExportLoc,
+                               SourceLocation ImportLoc, ModuleIdPath Path,
+                               bool IsPartition = false);
+  DeclResult ActOnModuleImport(SourceLocation StartLoc,
+                               SourceLocation ExportLoc,
+                               SourceLocation ImportLoc, Module *M,
+                               ModuleIdPath Path = {});
 
-  /// Construct a pack expansion type from the pattern of the pack
-  /// expansion.
-  TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern,
-                                     SourceLocation EllipsisLoc,
-                                     std::optional NumExpansions);
+  /// The parser has processed a module import translated from a
+  /// #include or similar preprocessing directive.
+  void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
+  void BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod);
 
-  /// Construct a pack expansion type from the pattern of the pack
-  /// expansion.
-  QualType CheckPackExpansion(QualType Pattern, SourceRange PatternRange,
-                              SourceLocation EllipsisLoc,
-                              std::optional NumExpansions);
+  /// The parsed has entered a submodule.
+  void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod);
+  /// The parser has left a submodule.
+  void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod);
 
-  /// Invoked when parsing an expression followed by an ellipsis, which
-  /// creates a pack expansion.
-  ///
-  /// \param Pattern The expression preceding the ellipsis, which will become
-  /// the pattern of the pack expansion.
+  /// Create an implicit import of the given module at the given
+  /// source location, for error recovery, if possible.
   ///
-  /// \param EllipsisLoc The location of the ellipsis.
-  ExprResult ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc);
+  /// This routine is typically used when an entity found by name lookup
+  /// is actually hidden within a module that we know about but the user
+  /// has forgotten to import.
+  void createImplicitModuleImportForErrorRecovery(SourceLocation Loc,
+                                                  Module *Mod);
 
-  /// Invoked when parsing an expression followed by an ellipsis, which
-  /// creates a pack expansion.
-  ///
-  /// \param Pattern The expression preceding the ellipsis, which will become
-  /// the pattern of the pack expansion.
-  ///
-  /// \param EllipsisLoc The location of the ellipsis.
-  ExprResult CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
-                                std::optional NumExpansions);
+  Decl *ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc,
+                             SourceLocation LBraceLoc);
+  Decl *ActOnFinishExportDecl(Scope *S, Decl *ExportDecl,
+                              SourceLocation RBraceLoc);
 
-  /// Determine whether we could expand a pack expansion with the
-  /// given set of parameter packs into separate arguments by repeatedly
-  /// transforming the pattern.
-  ///
-  /// \param EllipsisLoc The location of the ellipsis that identifies the
-  /// pack expansion.
-  ///
-  /// \param PatternRange The source range that covers the entire pattern of
-  /// the pack expansion.
-  ///
-  /// \param Unexpanded The set of unexpanded parameter packs within the
-  /// pattern.
-  ///
-  /// \param ShouldExpand Will be set to \c true if the transformer should
-  /// expand the corresponding pack expansions into separate arguments. When
-  /// set, \c NumExpansions must also be set.
-  ///
-  /// \param RetainExpansion Whether the caller should add an unexpanded
-  /// pack expansion after all of the expanded arguments. This is used
-  /// when extending explicitly-specified template argument packs per
-  /// C++0x [temp.arg.explicit]p9.
-  ///
-  /// \param NumExpansions The number of separate arguments that will be in
-  /// the expanded form of the corresponding pack expansion. This is both an
-  /// input and an output parameter, which can be set by the caller if the
-  /// number of expansions is known a priori (e.g., due to a prior substitution)
-  /// and will be set by the callee when the number of expansions is known.
-  /// The callee must set this value when \c ShouldExpand is \c true; it may
-  /// set this value in other cases.
-  ///
-  /// \returns true if an error occurred (e.g., because the parameter packs
-  /// are to be instantiated with arguments of different lengths), false
-  /// otherwise. If false, \c ShouldExpand (and possibly \c NumExpansions)
-  /// must be set.
-  bool CheckParameterPacksForExpansion(
-      SourceLocation EllipsisLoc, SourceRange PatternRange,
-      ArrayRef Unexpanded,
-      const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand,
-      bool &RetainExpansion, std::optional &NumExpansions);
+private:
+  /// The parser has begun a translation unit to be compiled as a C++20
+  /// Header Unit, helper for ActOnStartOfTranslationUnit() only.
+  void HandleStartOfHeaderUnit();
 
-  /// Determine the number of arguments in the given pack expansion
-  /// type.
-  ///
-  /// This routine assumes that the number of arguments in the expansion is
-  /// consistent across all of the unexpanded parameter packs in its pattern.
-  ///
-  /// Returns an empty Optional if the type can't be expanded.
-  std::optional getNumArgumentsInExpansion(
-      QualType T, const MultiLevelTemplateArgumentList &TemplateArgs);
+  struct ModuleScope {
+    SourceLocation BeginLoc;
+    clang::Module *Module = nullptr;
+    VisibleModuleSet OuterVisibleModules;
+  };
+  /// The modules we're currently parsing.
+  llvm::SmallVector ModuleScopes;
 
-  /// Determine whether the given declarator contains any unexpanded
-  /// parameter packs.
-  ///
-  /// This routine is used by the parser to disambiguate function declarators
-  /// with an ellipsis prior to the ')', e.g.,
-  ///
-  /// \code
-  ///   void f(T...);
-  /// \endcode
-  ///
-  /// To determine whether we have an (unnamed) function parameter pack or
-  /// a variadic function.
-  ///
-  /// \returns true if the declarator contains any unexpanded parameter packs,
-  /// false otherwise.
-  bool containsUnexpandedParameterPacks(Declarator &D);
+  /// For an interface unit, this is the implicitly imported interface unit.
+  clang::Module *ThePrimaryInterface = nullptr;
 
-  /// Returns the pattern of the pack expansion for a template argument.
-  ///
-  /// \param OrigLoc The template argument to expand.
-  ///
-  /// \param Ellipsis Will be set to the location of the ellipsis.
-  ///
-  /// \param NumExpansions Will be set to the number of expansions that will
-  /// be generated from this pack expansion, if known a priori.
-  TemplateArgumentLoc getTemplateArgumentPackExpansionPattern(
-      TemplateArgumentLoc OrigLoc, SourceLocation &Ellipsis,
-      std::optional &NumExpansions) const;
+  /// The explicit global module fragment of the current translation unit.
+  /// The explicit Global Module Fragment, as specified in C++
+  /// [module.global.frag].
+  clang::Module *TheGlobalModuleFragment = nullptr;
 
-  /// Given a template argument that contains an unexpanded parameter pack, but
-  /// which has already been substituted, attempt to determine the number of
-  /// elements that will be produced once this argument is fully-expanded.
+  /// The implicit global module fragments of the current translation unit.
   ///
-  /// This is intended for use when transforming 'sizeof...(Arg)' in order to
-  /// avoid actually expanding the pack where possible.
-  std::optional getFullyPackExpandedSize(TemplateArgument Arg);
+  /// The contents in the implicit global module fragment can't be discarded.
+  clang::Module *TheImplicitGlobalModuleFragment = nullptr;
 
-  //===--------------------------------------------------------------------===//
-  // C++ Template Argument Deduction (C++ [temp.deduct])
-  //===--------------------------------------------------------------------===//
+  /// Namespace definitions that we will export when they finish.
+  llvm::SmallPtrSet DeferredExportedNamespaces;
 
-  /// Adjust the type \p ArgFunctionType to match the calling convention,
-  /// noreturn, and optionally the exception specification of \p FunctionType.
-  /// Deduction often wants to ignore these properties when matching function
-  /// types.
-  QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType,
-                               bool AdjustExceptionSpec = false);
+  /// In a C++ standard module, inline declarations require a definition to be
+  /// present at the end of a definition domain.  This set holds the decls to
+  /// be checked at the end of the TU.
+  llvm::SmallPtrSet PendingInlineFuncDecls;
 
-  TemplateDeductionResult
-  DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
-                          ArrayRef TemplateArgs,
-                          sema::TemplateDeductionInfo &Info);
+  /// Helper function to judge if we are in module purview.
+  /// Return false if we are not in a module.
+  bool isCurrentModulePurview() const;
 
-  TemplateDeductionResult
-  DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
-                          ArrayRef TemplateArgs,
-                          sema::TemplateDeductionInfo &Info);
+  /// Enter the scope of the explicit global module fragment.
+  Module *PushGlobalModuleFragment(SourceLocation BeginLoc);
+  /// Leave the scope of the explicit global module fragment.
+  void PopGlobalModuleFragment();
 
-  TemplateDeductionResult SubstituteExplicitTemplateArguments(
-      FunctionTemplateDecl *FunctionTemplate,
-      TemplateArgumentListInfo &ExplicitTemplateArgs,
-      SmallVectorImpl &Deduced,
-      SmallVectorImpl &ParamTypes, QualType *FunctionType,
-      sema::TemplateDeductionInfo &Info);
+  /// Enter the scope of an implicit global module fragment.
+  Module *PushImplicitGlobalModuleFragment(SourceLocation BeginLoc);
+  /// Leave the scope of an implicit global module fragment.
+  void PopImplicitGlobalModuleFragment();
 
-  /// brief A function argument from which we performed template argument
-  // deduction for a call.
-  struct OriginalCallArg {
-    OriginalCallArg(QualType OriginalParamType, bool DecomposedParam,
-                    unsigned ArgIdx, QualType OriginalArgType)
-        : OriginalParamType(OriginalParamType),
-          DecomposedParam(DecomposedParam), ArgIdx(ArgIdx),
-          OriginalArgType(OriginalArgType) {}
+  VisibleModuleSet VisibleModules;
 
-    QualType OriginalParamType;
-    bool DecomposedParam;
-    unsigned ArgIdx;
-    QualType OriginalArgType;
-  };
+  ///@}
 
-  TemplateDeductionResult FinishTemplateArgumentDeduction(
-      FunctionTemplateDecl *FunctionTemplate,
-      SmallVectorImpl &Deduced,
-      unsigned NumExplicitlySpecified, FunctionDecl *&Specialization,
-      sema::TemplateDeductionInfo &Info,
-      SmallVectorImpl const *OriginalCallArgs = nullptr,
-      bool PartialOverloading = false,
-      llvm::function_ref CheckNonDependent = []{ return false; });
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  TemplateDeductionResult DeduceTemplateArguments(
-      FunctionTemplateDecl *FunctionTemplate,
-      TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args,
-      FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info,
-      bool PartialOverloading, bool AggregateDeductionCandidate,
-      QualType ObjectType, Expr::Classification ObjectClassification,
-      llvm::function_ref)> CheckNonDependent);
+  /// \name C++ Overloading
+  /// Implementations are in SemaOverload.cpp
+  ///@{
 
-  TemplateDeductionResult
-  DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
-                          TemplateArgumentListInfo *ExplicitTemplateArgs,
-                          QualType ArgFunctionType,
-                          FunctionDecl *&Specialization,
-                          sema::TemplateDeductionInfo &Info,
-                          bool IsAddressOfFunction = false);
+public:
+  /// Whether deferrable diagnostics should be deferred.
+  bool DeferDiags = false;
 
-  TemplateDeductionResult DeduceTemplateArguments(
-      FunctionTemplateDecl *FunctionTemplate, QualType ObjectType,
-      Expr::Classification ObjectClassification, QualType ToType,
-      CXXConversionDecl *&Specialization, sema::TemplateDeductionInfo &Info);
+  /// RAII class to control scope of DeferDiags.
+  class DeferDiagsRAII {
+    Sema &S;
+    bool SavedDeferDiags = false;
 
-  TemplateDeductionResult
-  DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
-                          TemplateArgumentListInfo *ExplicitTemplateArgs,
-                          FunctionDecl *&Specialization,
-                          sema::TemplateDeductionInfo &Info,
-                          bool IsAddressOfFunction = false);
+  public:
+    DeferDiagsRAII(Sema &S, bool DeferDiags)
+        : S(S), SavedDeferDiags(S.DeferDiags) {
+      S.DeferDiags = DeferDiags;
+    }
+    ~DeferDiagsRAII() { S.DeferDiags = SavedDeferDiags; }
+  };
 
-  /// Substitute Replacement for \p auto in \p TypeWithAuto
-  QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
-  /// Substitute Replacement for auto in TypeWithAuto
-  TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
-                                          QualType Replacement);
+  /// Flag indicating if Sema is building a recovery call expression.
+  ///
+  /// This flag is used to avoid building recovery call expressions
+  /// if Sema is already doing so, which would cause infinite recursions.
+  bool IsBuildingRecoveryCallExpr;
 
-  // Substitute auto in TypeWithAuto for a Dependent auto type
-  QualType SubstAutoTypeDependent(QualType TypeWithAuto);
+  enum OverloadKind {
+    /// This is a legitimate overload: the existing declarations are
+    /// functions or function templates with different signatures.
+    Ovl_Overload,
 
-  // Substitute auto in TypeWithAuto for a Dependent auto type
-  TypeSourceInfo *
-  SubstAutoTypeSourceInfoDependent(TypeSourceInfo *TypeWithAuto);
+    /// This is not an overload because the signature exactly matches
+    /// an existing declaration.
+    Ovl_Match,
 
-  /// Completely replace the \c auto in \p TypeWithAuto by
-  /// \p Replacement. This does not retain any \c auto type sugar.
-  QualType ReplaceAutoType(QualType TypeWithAuto, QualType Replacement);
-  TypeSourceInfo *ReplaceAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
-                                            QualType Replacement);
+    /// This is not an overload because the lookup results contain a
+    /// non-function.
+    Ovl_NonFunction
+  };
+  OverloadKind CheckOverload(Scope *S, FunctionDecl *New,
+                             const LookupResult &OldDecls, NamedDecl *&OldDecl,
+                             bool UseMemberUsingDeclRules);
+  bool IsOverload(FunctionDecl *New, FunctionDecl *Old,
+                  bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs = true);
 
-  TemplateDeductionResult
-  DeduceAutoType(TypeLoc AutoTypeLoc, Expr *Initializer, QualType &Result,
-                 sema::TemplateDeductionInfo &Info,
-                 bool DependentDeduction = false,
-                 bool IgnoreConstraints = false,
-                 TemplateSpecCandidateSet *FailedTSC = nullptr);
-  void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init);
-  bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
-                        bool Diagnose = true);
+  // Checks whether MD constitutes an override the base class method BaseMD.
+  // When checking for overrides, the object object members are ignored.
+  bool IsOverride(FunctionDecl *MD, FunctionDecl *BaseMD,
+                  bool UseMemberUsingDeclRules, bool ConsiderCudaAttrs = true);
 
-  bool CheckIfFunctionSpecializationIsImmediate(FunctionDecl *FD,
-                                                SourceLocation Loc);
+  enum class AllowedExplicit {
+    /// Allow no explicit functions to be used.
+    None,
+    /// Allow explicit conversion functions but not explicit constructors.
+    Conversions,
+    /// Allow both explicit conversion functions and explicit constructors.
+    All
+  };
 
-  /// Declare implicit deduction guides for a class template if we've
-  /// not already done so.
-  void DeclareImplicitDeductionGuides(TemplateDecl *Template,
-                                      SourceLocation Loc);
-  FunctionTemplateDecl *DeclareImplicitDeductionGuideFromInitList(
-      TemplateDecl *Template, MutableArrayRef ParamTypes,
-      SourceLocation Loc);
-  llvm::DenseMap
-      AggregateDeductionCandidates;
+  ImplicitConversionSequence TryImplicitConversion(
+      Expr *From, QualType ToType, bool SuppressUserConversions,
+      AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle,
+      bool AllowObjCWritebackConversion);
 
-  QualType DeduceTemplateSpecializationFromInitializer(
-      TypeSourceInfo *TInfo, const InitializedEntity &Entity,
-      const InitializationKind &Kind, MultiExprArg Init);
-
-  QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name,
-                                        QualType Type, TypeSourceInfo *TSI,
-                                        SourceRange Range, bool DirectInit,
-                                        Expr *Init);
+  ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
+                                       AssignmentAction Action,
+                                       bool AllowExplicit = false);
 
-  TypeLoc getReturnTypeLoc(FunctionDecl *FD) const;
+  bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType);
+  bool IsFloatingPointPromotion(QualType FromType, QualType ToType);
+  bool IsComplexPromotion(QualType FromType, QualType ToType);
+  bool IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
+                           bool InOverloadResolution, QualType &ConvertedType,
+                           bool &IncompatibleObjC);
+  bool isObjCPointerConversion(QualType FromType, QualType ToType,
+                               QualType &ConvertedType, bool &IncompatibleObjC);
+  bool isObjCWritebackConversion(QualType FromType, QualType ToType,
+                                 QualType &ConvertedType);
+  bool IsBlockPointerConversion(QualType FromType, QualType ToType,
+                                QualType &ConvertedType);
 
-  bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
-                                        SourceLocation ReturnLoc, Expr *RetExpr,
-                                        const AutoType *AT);
+  bool FunctionParamTypesAreEqual(ArrayRef Old,
+                                  ArrayRef New,
+                                  unsigned *ArgPos = nullptr,
+                                  bool Reversed = false);
 
-  FunctionTemplateDecl *getMoreSpecializedTemplate(
-      FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc,
-      TemplatePartialOrderingContext TPOC, unsigned NumCallArguments1,
-      unsigned NumCallArguments2, bool Reversed = false);
-  UnresolvedSetIterator
-  getMostSpecialized(UnresolvedSetIterator SBegin, UnresolvedSetIterator SEnd,
-                     TemplateSpecCandidateSet &FailedCandidates,
-                     SourceLocation Loc,
-                     const PartialDiagnostic &NoneDiag,
-                     const PartialDiagnostic &AmbigDiag,
-                     const PartialDiagnostic &CandidateDiag,
-                     bool Complain = true, QualType TargetType = QualType());
+  bool FunctionParamTypesAreEqual(const FunctionProtoType *OldType,
+                                  const FunctionProtoType *NewType,
+                                  unsigned *ArgPos = nullptr,
+                                  bool Reversed = false);
 
-  ClassTemplatePartialSpecializationDecl *
-  getMoreSpecializedPartialSpecialization(
-                                  ClassTemplatePartialSpecializationDecl *PS1,
-                                  ClassTemplatePartialSpecializationDecl *PS2,
-                                  SourceLocation Loc);
+  bool FunctionNonObjectParamTypesAreEqual(const FunctionDecl *OldFunction,
+                                           const FunctionDecl *NewFunction,
+                                           unsigned *ArgPos = nullptr,
+                                           bool Reversed = false);
 
-  bool isMoreSpecializedThanPrimary(ClassTemplatePartialSpecializationDecl *T,
-                                    sema::TemplateDeductionInfo &Info);
+  void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, QualType FromType,
+                                  QualType ToType);
 
-  VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpecialization(
-      VarTemplatePartialSpecializationDecl *PS1,
-      VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc);
+  bool CheckPointerConversion(Expr *From, QualType ToType, CastKind &Kind,
+                              CXXCastPath &BasePath, bool IgnoreBaseAccess,
+                              bool Diagnose = true);
+  bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType,
+                                 bool InOverloadResolution,
+                                 QualType &ConvertedType);
+  bool CheckMemberPointerConversion(Expr *From, QualType ToType, CastKind &Kind,
+                                    CXXCastPath &BasePath,
+                                    bool IgnoreBaseAccess);
+  bool IsQualificationConversion(QualType FromType, QualType ToType,
+                                 bool CStyle, bool &ObjCLifetimeConversion);
+  bool IsFunctionConversion(QualType FromType, QualType ToType,
+                            QualType &ResultTy);
+  bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
 
-  bool isMoreSpecializedThanPrimary(VarTemplatePartialSpecializationDecl *T,
-                                    sema::TemplateDeductionInfo &Info);
+  ExprResult InitializeExplicitObjectArgument(Sema &S, Expr *Obj,
+                                              FunctionDecl *Fun);
+  ExprResult PerformImplicitObjectArgumentInitialization(
+      Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl,
+      CXXMethodDecl *Method);
 
-  bool isTemplateTemplateParameterAtLeastAsSpecializedAs(
-      TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc);
+  ExprResult PerformContextuallyConvertToBool(Expr *From);
+  ExprResult PerformContextuallyConvertToObjCPointer(Expr *From);
 
-  void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
-                                  unsigned Depth, llvm::SmallBitVector &Used);
+  /// Contexts in which a converted constant expression is required.
+  enum CCEKind {
+    CCEK_CaseValue,    ///< Expression in a case label.
+    CCEK_Enumerator,   ///< Enumerator value with fixed underlying type.
+    CCEK_TemplateArg,  ///< Value of a non-type template parameter.
+    CCEK_ArrayBound,   ///< Array bound in array declarator or new-expression.
+    CCEK_ExplicitBool, ///< Condition in an explicit(bool) specifier.
+    CCEK_Noexcept,     ///< Condition in a noexcept(bool) specifier.
+    CCEK_StaticAssertMessageSize, ///< Call to size() in a static assert
+                                  ///< message.
+    CCEK_StaticAssertMessageData, ///< Call to data() in a static assert
+                                  ///< message.
+  };
 
-  void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
-                                  bool OnlyDeduced,
-                                  unsigned Depth,
-                                  llvm::SmallBitVector &Used);
-  void MarkDeducedTemplateParameters(
-                                  const FunctionTemplateDecl *FunctionTemplate,
-                                  llvm::SmallBitVector &Deduced) {
-    return MarkDeducedTemplateParameters(Context, FunctionTemplate, Deduced);
-  }
-  static void MarkDeducedTemplateParameters(ASTContext &Ctx,
-                                  const FunctionTemplateDecl *FunctionTemplate,
-                                  llvm::SmallBitVector &Deduced);
+  ExprResult BuildConvertedConstantExpression(Expr *From, QualType T,
+                                              CCEKind CCE,
+                                              NamedDecl *Dest = nullptr);
 
-  //===--------------------------------------------------------------------===//
-  // C++ Template Instantiation
-  //
+  ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
+                                              llvm::APSInt &Value, CCEKind CCE);
+  ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
+                                              APValue &Value, CCEKind CCE,
+                                              NamedDecl *Dest = nullptr);
 
-  MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
-      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);
+  ExprResult
+  EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value,
+                                      CCEKind CCE, bool RequireInt,
+                                      const APValue &PreNarrowingValue);
 
-  /// A context in which code is being synthesized (where a source location
-  /// alone is not sufficient to identify the context). This covers template
-  /// instantiation and various forms of implicitly-generated functions.
-  struct CodeSynthesisContext {
-    /// The kind of template instantiation we are performing
-    enum SynthesisKind {
-      /// We are instantiating a template declaration. The entity is
-      /// the declaration we're instantiating (e.g., a CXXRecordDecl).
-      TemplateInstantiation,
+  /// Abstract base class used to perform a contextual implicit
+  /// conversion from an expression to any type passing a filter.
+  class ContextualImplicitConverter {
+  public:
+    bool Suppress;
+    bool SuppressConversion;
 
-      /// We are instantiating a default argument for a template
-      /// parameter. The Entity is the template parameter whose argument is
-      /// being instantiated, the Template is the template, and the
-      /// TemplateArgs/NumTemplateArguments provide the template arguments as
-      /// specified.
-      DefaultTemplateArgumentInstantiation,
+    ContextualImplicitConverter(bool Suppress = false,
+                                bool SuppressConversion = false)
+        : Suppress(Suppress), SuppressConversion(SuppressConversion) {}
 
-      /// We are instantiating a default argument for a function.
-      /// The Entity is the ParmVarDecl, and TemplateArgs/NumTemplateArgs
-      /// provides the template arguments as specified.
-      DefaultFunctionArgumentInstantiation,
+    /// Determine whether the specified type is a valid destination type
+    /// for this conversion.
+    virtual bool match(QualType T) = 0;
 
-      /// We are substituting explicit template arguments provided for
-      /// a function template. The entity is a FunctionTemplateDecl.
-      ExplicitTemplateArgumentSubstitution,
+    /// Emits a diagnostic complaining that the expression does not have
+    /// integral or enumeration type.
+    virtual SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc,
+                                                  QualType T) = 0;
 
-      /// We are substituting template argument determined as part of
-      /// template argument deduction for either a class template
-      /// partial specialization or a function template. The
-      /// Entity is either a {Class|Var}TemplatePartialSpecializationDecl or
-      /// a TemplateDecl.
-      DeducedTemplateArgumentSubstitution,
+    /// Emits a diagnostic when the expression has incomplete class type.
+    virtual SemaDiagnosticBuilder
+    diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) = 0;
 
-      /// We are substituting into a lambda expression.
-      LambdaExpressionSubstitution,
+    /// Emits a diagnostic when the only matching conversion function
+    /// is explicit.
+    virtual SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S,
+                                                       SourceLocation Loc,
+                                                       QualType T,
+                                                       QualType ConvTy) = 0;
 
-      /// We are substituting prior template arguments into a new
-      /// template parameter. The template parameter itself is either a
-      /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl.
-      PriorTemplateArgumentSubstitution,
+    /// Emits a note for the explicit conversion function.
+    virtual SemaDiagnosticBuilder
+    noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
 
-      /// We are checking the validity of a default template argument that
-      /// has been used when naming a template-id.
-      DefaultTemplateArgumentChecking,
+    /// Emits a diagnostic when there are multiple possible conversion
+    /// functions.
+    virtual SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
+                                                    QualType T) = 0;
 
-      /// We are computing the exception specification for a defaulted special
-      /// member function.
-      ExceptionSpecEvaluation,
+    /// Emits a note for one of the candidate conversions.
+    virtual SemaDiagnosticBuilder
+    noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
 
-      /// We are instantiating the exception specification for a function
-      /// template which was deferred until it was needed.
-      ExceptionSpecInstantiation,
+    /// Emits a diagnostic when we picked a conversion function
+    /// (for cases when we are not allowed to pick a conversion function).
+    virtual SemaDiagnosticBuilder diagnoseConversion(Sema &S,
+                                                     SourceLocation Loc,
+                                                     QualType T,
+                                                     QualType ConvTy) = 0;
 
-      /// We are instantiating a requirement of a requires expression.
-      RequirementInstantiation,
+    virtual ~ContextualImplicitConverter() {}
+  };
 
-      /// We are checking the satisfaction of a nested requirement of a requires
-      /// expression.
-      NestedRequirementConstraintsCheck,
+  class ICEConvertDiagnoser : public ContextualImplicitConverter {
+    bool AllowScopedEnumerations;
 
-      /// We are declaring an implicit special member function.
-      DeclaringSpecialMember,
+  public:
+    ICEConvertDiagnoser(bool AllowScopedEnumerations, bool Suppress,
+                        bool SuppressConversion)
+        : ContextualImplicitConverter(Suppress, SuppressConversion),
+          AllowScopedEnumerations(AllowScopedEnumerations) {}
 
-      /// We are declaring an implicit 'operator==' for a defaulted
-      /// 'operator<=>'.
-      DeclaringImplicitEqualityComparison,
+    /// Match an integral or (possibly scoped) enumeration type.
+    bool match(QualType T) override;
 
-      /// We are defining a synthesized function (such as a defaulted special
-      /// member).
-      DefiningSynthesizedFunction,
+    SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc,
+                                          QualType T) override {
+      return diagnoseNotInt(S, Loc, T);
+    }
 
-      // We are checking the constraints associated with a constrained entity or
-      // the constraint expression of a concept. This includes the checks that
-      // atomic constraints have the type 'bool' and that they can be constant
-      // evaluated.
-      ConstraintsCheck,
+    /// Emits a diagnostic complaining that the expression does not have
+    /// integral or enumeration type.
+    virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
+                                                 QualType T) = 0;
+  };
 
-      // We are substituting template arguments into a constraint expression.
-      ConstraintSubstitution,
+  /// Perform a contextual implicit conversion.
+  ExprResult
+  PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE,
+                                      ContextualImplicitConverter &Converter);
 
-      // We are normalizing a constraint expression.
-      ConstraintNormalization,
+  /// ReferenceCompareResult - Expresses the result of comparing two
+  /// types (cv1 T1 and cv2 T2) to determine their compatibility for the
+  /// purposes of initialization by reference (C++ [dcl.init.ref]p4).
+  enum ReferenceCompareResult {
+    /// Ref_Incompatible - The two types are incompatible, so direct
+    /// reference binding is not possible.
+    Ref_Incompatible = 0,
+    /// Ref_Related - The two types are reference-related, which means
+    /// that their unqualified forms (T1 and T2) are either the same
+    /// or T1 is a base class of T2.
+    Ref_Related,
+    /// Ref_Compatible - The two types are reference-compatible.
+    Ref_Compatible
+  };
 
-      // Instantiating a Requires Expression parameter clause.
-      RequirementParameterInstantiation,
+  // Fake up a scoped enumeration that still contextually converts to bool.
+  struct ReferenceConversionsScope {
+    /// The conversions that would be performed on an lvalue of type T2 when
+    /// binding a reference of type T1 to it, as determined when evaluating
+    /// whether T1 is reference-compatible with T2.
+    enum ReferenceConversions {
+      Qualification = 0x1,
+      NestedQualification = 0x2,
+      Function = 0x4,
+      DerivedToBase = 0x8,
+      ObjC = 0x10,
+      ObjCLifetime = 0x20,
 
-      // We are substituting into the parameter mapping of an atomic constraint
-      // during normalization.
-      ParameterMappingSubstitution,
+      LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ObjCLifetime)
+    };
+  };
+  using ReferenceConversions = ReferenceConversionsScope::ReferenceConversions;
 
-      /// We are rewriting a comparison operator in terms of an operator<=>.
-      RewritingOperatorAsSpaceship,
-
-      /// We are initializing a structured binding.
-      InitializingStructuredBinding,
-
-      /// We are marking a class as __dllexport.
-      MarkingClassDllexported,
-
-      /// We are building an implied call from __builtin_dump_struct. The
-      /// arguments are in CallArgs.
-      BuildingBuiltinDumpStructCall,
+  ReferenceCompareResult
+  CompareReferenceRelationship(SourceLocation Loc, QualType T1, QualType T2,
+                               ReferenceConversions *Conv = nullptr);
 
-      /// Added for Template instantiation observation.
-      /// Memoization means we are _not_ instantiating a template because
-      /// it is already instantiated (but we entered a context where we
-      /// would have had to if it was not already instantiated).
-      Memoization,
+  void AddOverloadCandidate(
+      FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef Args,
+      OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
+      bool PartialOverloading = false, bool AllowExplicit = true,
+      bool AllowExplicitConversion = false,
+      ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
+      ConversionSequenceList EarlyConversions = std::nullopt,
+      OverloadCandidateParamOrder PO = {},
+      bool AggregateCandidateDeduction = false);
+  void AddFunctionCandidates(
+      const UnresolvedSetImpl &Functions, ArrayRef Args,
+      OverloadCandidateSet &CandidateSet,
+      TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
+      bool SuppressUserConversions = false, bool PartialOverloading = false,
+      bool FirstArgumentIsBase = false);
+  void AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType,
+                          Expr::Classification ObjectClassification,
+                          ArrayRef Args,
+                          OverloadCandidateSet &CandidateSet,
+                          bool SuppressUserConversion = false,
+                          OverloadCandidateParamOrder PO = {});
+  void
+  AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
+                     CXXRecordDecl *ActingContext, QualType ObjectType,
+                     Expr::Classification ObjectClassification,
+                     ArrayRef Args, OverloadCandidateSet &CandidateSet,
+                     bool SuppressUserConversions = false,
+                     bool PartialOverloading = false,
+                     ConversionSequenceList EarlyConversions = std::nullopt,
+                     OverloadCandidateParamOrder PO = {});
+  void AddMethodTemplateCandidate(
+      FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl,
+      CXXRecordDecl *ActingContext,
+      TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType,
+      Expr::Classification ObjectClassification, ArrayRef Args,
+      OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
+      bool PartialOverloading = false, OverloadCandidateParamOrder PO = {});
+  void AddTemplateOverloadCandidate(
+      FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
+      TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args,
+      OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false,
+      bool PartialOverloading = false, bool AllowExplicit = true,
+      ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
+      OverloadCandidateParamOrder PO = {},
+      bool AggregateCandidateDeduction = false);
+  bool CheckNonDependentConversions(
+      FunctionTemplateDecl *FunctionTemplate, ArrayRef ParamTypes,
+      ArrayRef Args, OverloadCandidateSet &CandidateSet,
+      ConversionSequenceList &Conversions, bool SuppressUserConversions,
+      CXXRecordDecl *ActingContext = nullptr, QualType ObjectType = QualType(),
+      Expr::Classification ObjectClassification = {},
+      OverloadCandidateParamOrder PO = {});
+  void AddConversionCandidate(
+      CXXConversionDecl *Conversion, DeclAccessPair FoundDecl,
+      CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
+      OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
+      bool AllowExplicit, bool AllowResultConversion = true);
+  void AddTemplateConversionCandidate(
+      FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl,
+      CXXRecordDecl *ActingContext, Expr *From, QualType ToType,
+      OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit,
+      bool AllowExplicit, bool AllowResultConversion = true);
+  void AddSurrogateCandidate(CXXConversionDecl *Conversion,
+                             DeclAccessPair FoundDecl,
+                             CXXRecordDecl *ActingContext,
+                             const FunctionProtoType *Proto, Expr *Object,
+                             ArrayRef Args,
+                             OverloadCandidateSet &CandidateSet);
+  void AddNonMemberOperatorCandidates(
+      const UnresolvedSetImpl &Functions, ArrayRef Args,
+      OverloadCandidateSet &CandidateSet,
+      TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
+  void AddMemberOperatorCandidates(OverloadedOperatorKind Op,
+                                   SourceLocation OpLoc, ArrayRef Args,
+                                   OverloadCandidateSet &CandidateSet,
+                                   OverloadCandidateParamOrder PO = {});
+  void AddBuiltinCandidate(QualType *ParamTys, ArrayRef Args,
+                           OverloadCandidateSet &CandidateSet,
+                           bool IsAssignmentOperator = false,
+                           unsigned NumContextualBoolArguments = 0);
+  void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
+                                    SourceLocation OpLoc, ArrayRef Args,
+                                    OverloadCandidateSet &CandidateSet);
+  void AddArgumentDependentLookupCandidates(
+      DeclarationName Name, SourceLocation Loc, ArrayRef Args,
+      TemplateArgumentListInfo *ExplicitTemplateArgs,
+      OverloadCandidateSet &CandidateSet, bool PartialOverloading = false);
 
-      /// We are building deduction guides for a class.
-      BuildingDeductionGuides,
-    } Kind;
+  /// Check the enable_if expressions on the given function. Returns the first
+  /// failing attribute, or NULL if they were all successful.
+  EnableIfAttr *CheckEnableIf(FunctionDecl *Function, SourceLocation CallLoc,
+                              ArrayRef Args,
+                              bool MissingImplicitThis = false);
 
-    /// Was the enclosing context a non-instantiation SFINAE context?
-    bool SavedInNonInstantiationSFINAEContext;
+  /// Emit diagnostics for the diagnose_if attributes on Function, ignoring any
+  /// non-ArgDependent DiagnoseIfAttrs.
+  ///
+  /// Argument-dependent diagnose_if attributes should be checked each time a
+  /// function is used as a direct callee of a function call.
+  ///
+  /// Returns true if any errors were emitted.
+  bool diagnoseArgDependentDiagnoseIfAttrs(const FunctionDecl *Function,
+                                           const Expr *ThisArg,
+                                           ArrayRef Args,
+                                           SourceLocation Loc);
 
-    /// The point of instantiation or synthesis within the source code.
-    SourceLocation PointOfInstantiation;
+  /// Emit diagnostics for the diagnose_if attributes on Function, ignoring any
+  /// ArgDependent DiagnoseIfAttrs.
+  ///
+  /// Argument-independent diagnose_if attributes should be checked on every use
+  /// of a function.
+  ///
+  /// Returns true if any errors were emitted.
+  bool diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND,
+                                             SourceLocation Loc);
 
-    /// The entity that is being synthesized.
-    Decl *Entity;
+  /// Determine if \p A and \p B are equivalent internal linkage declarations
+  /// from different modules, and thus an ambiguity error can be downgraded to
+  /// an extension warning.
+  bool isEquivalentInternalLinkageDeclaration(const NamedDecl *A,
+                                              const NamedDecl *B);
+  void diagnoseEquivalentInternalLinkageDeclarations(
+      SourceLocation Loc, const NamedDecl *D,
+      ArrayRef Equiv);
 
-    /// The template (or partial specialization) in which we are
-    /// performing the instantiation, for substitutions of prior template
-    /// arguments.
-    NamedDecl *Template;
+  // Emit as a 'note' the specific overload candidate
+  void NoteOverloadCandidate(
+      const NamedDecl *Found, const FunctionDecl *Fn,
+      OverloadCandidateRewriteKind RewriteKind = OverloadCandidateRewriteKind(),
+      QualType DestType = QualType(), bool TakingAddress = false);
 
-    union {
-      /// The list of template arguments we are substituting, if they
-      /// are not part of the entity.
-      const TemplateArgument *TemplateArgs;
+  // Emit as a series of 'note's all template and non-templates identified by
+  // the expression Expr
+  void NoteAllOverloadCandidates(Expr *E, QualType DestType = QualType(),
+                                 bool TakingAddress = false);
 
-      /// The list of argument expressions in a synthesized call.
-      const Expr *const *CallArgs;
-    };
+  /// Returns whether the given function's address can be taken or not,
+  /// optionally emitting a diagnostic if the address can't be taken.
+  ///
+  /// Returns false if taking the address of the function is illegal.
+  bool checkAddressOfFunctionIsAvailable(const FunctionDecl *Function,
+                                         bool Complain = false,
+                                         SourceLocation Loc = SourceLocation());
 
-    // FIXME: Wrap this union around more members, or perhaps store the
-    // kind-specific members in the RAII object owning the context.
-    union {
-      /// The number of template arguments in TemplateArgs.
-      unsigned NumTemplateArgs;
+  // [PossiblyAFunctionType]  -->   [Return]
+  // NonFunctionType --> NonFunctionType
+  // R (A) --> R(A)
+  // R (*)(A) --> R (A)
+  // R (&)(A) --> R (A)
+  // R (S::*)(A) --> R (A)
+  QualType ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType);
 
-      /// The number of expressions in CallArgs.
-      unsigned NumCallArgs;
+  FunctionDecl *
+  ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType,
+                                     bool Complain, DeclAccessPair &Found,
+                                     bool *pHadMultipleCandidates = nullptr);
 
-      /// The special member being declared or defined.
-      CXXSpecialMember SpecialMember;
-    };
+  FunctionDecl *
+  resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &FoundResult);
 
-    ArrayRef template_arguments() const {
-      assert(Kind != DeclaringSpecialMember);
-      return {TemplateArgs, NumTemplateArgs};
-    }
+  bool resolveAndFixAddressOfSingleOverloadCandidate(
+      ExprResult &SrcExpr, bool DoFunctionPointerConversion = false);
 
-    /// The template deduction info object associated with the
-    /// substitution or checking of explicit or deduced template arguments.
-    sema::TemplateDeductionInfo *DeductionInfo;
+  FunctionDecl *ResolveSingleFunctionTemplateSpecialization(
+      OverloadExpr *ovl, bool Complain = false, DeclAccessPair *Found = nullptr,
+      TemplateSpecCandidateSet *FailedTSC = nullptr);
 
-    /// The source range that covers the construct that cause
-    /// the instantiation, e.g., the template-id that causes a class
-    /// template instantiation.
-    SourceRange InstantiationRange;
+  bool ResolveAndFixSingleFunctionTemplateSpecialization(
+      ExprResult &SrcExpr, bool DoFunctionPointerConversion = false,
+      bool Complain = false, SourceRange OpRangeForComplaining = SourceRange(),
+      QualType DestTypeForComplaining = QualType(),
+      unsigned DiagIDForComplaining = 0);
 
-    CodeSynthesisContext()
-        : Kind(TemplateInstantiation),
-          SavedInNonInstantiationSFINAEContext(false), Entity(nullptr),
-          Template(nullptr), TemplateArgs(nullptr), NumTemplateArgs(0),
-          DeductionInfo(nullptr) {}
+  void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
+                                   ArrayRef Args,
+                                   OverloadCandidateSet &CandidateSet,
+                                   bool PartialOverloading = false);
+  void AddOverloadedCallCandidates(
+      LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs,
+      ArrayRef Args, OverloadCandidateSet &CandidateSet);
 
-    /// Determines whether this template is an actual instantiation
-    /// that should be counted toward the maximum instantiation depth.
-    bool isInstantiationRecord() const;
+  // An enum used to represent the different possible results of building a
+  // range-based for loop.
+  enum ForRangeStatus {
+    FRS_Success,
+    FRS_NoViableFunction,
+    FRS_DiagnosticIssued
   };
 
-  /// List of active code synthesis contexts.
-  ///
-  /// This vector is treated as a stack. As synthesis of one entity requires
-  /// synthesis of another, additional contexts are pushed onto the stack.
-  SmallVector CodeSynthesisContexts;
-
-  /// Specializations whose definitions are currently being instantiated.
-  llvm::DenseSet> InstantiatingSpecializations;
+  ForRangeStatus BuildForRangeBeginEndCall(SourceLocation Loc,
+                                           SourceLocation RangeLoc,
+                                           const DeclarationNameInfo &NameInfo,
+                                           LookupResult &MemberLookup,
+                                           OverloadCandidateSet *CandidateSet,
+                                           Expr *Range, ExprResult *CallExpr);
 
-  /// Non-dependent types used in templates that have already been instantiated
-  /// by some template instantiation.
-  llvm::DenseSet InstantiatedNonDependentTypes;
+  ExprResult BuildOverloadedCallExpr(
+      Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc,
+      MultiExprArg Args, SourceLocation RParenLoc, Expr *ExecConfig,
+      bool AllowTypoCorrection = true, bool CalleesAddressIsTaken = false);
 
-  /// Extra modules inspected when performing a lookup during a template
-  /// instantiation. Computed lazily.
-  SmallVector CodeSynthesisContextLookupModules;
+  bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
+                              MultiExprArg Args, SourceLocation RParenLoc,
+                              OverloadCandidateSet *CandidateSet,
+                              ExprResult *Result);
 
-  /// Cache of additional modules that should be used for name lookup
-  /// within the current template instantiation. Computed lazily; use
-  /// getLookupModules() to get a complete set.
-  llvm::DenseSet LookupModulesCache;
+  ExprResult CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass,
+                                        NestedNameSpecifierLoc NNSLoc,
+                                        DeclarationNameInfo DNI,
+                                        const UnresolvedSetImpl &Fns,
+                                        bool PerformADL = true);
 
-  /// Get the set of additional modules that should be checked during
-  /// name lookup. A module and its imports become visible when instanting a
-  /// template defined within it.
-  llvm::DenseSet &getLookupModules();
+  ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
+                                     UnaryOperatorKind Opc,
+                                     const UnresolvedSetImpl &Fns, Expr *input,
+                                     bool RequiresADL = true);
 
-  /// Map from the most recent declaration of a namespace to the most
-  /// recent visible declaration of that namespace.
-  llvm::DenseMap VisibleNamespaceCache;
-
-  /// Whether we are in a SFINAE context that is not associated with
-  /// template instantiation.
-  ///
-  /// This is used when setting up a SFINAE trap (\c see SFINAETrap) outside
-  /// of a template instantiation or template argument deduction.
-  bool InNonInstantiationSFINAEContext;
+  void LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet,
+                             OverloadedOperatorKind Op,
+                             const UnresolvedSetImpl &Fns,
+                             ArrayRef Args, bool RequiresADL = true);
+  ExprResult CreateOverloadedBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc,
+                                   const UnresolvedSetImpl &Fns, Expr *LHS,
+                                   Expr *RHS, bool RequiresADL = true,
+                                   bool AllowRewrittenCandidates = true,
+                                   FunctionDecl *DefaultedFn = nullptr);
+  ExprResult BuildSynthesizedThreeWayComparison(SourceLocation OpLoc,
+                                                const UnresolvedSetImpl &Fns,
+                                                Expr *LHS, Expr *RHS,
+                                                FunctionDecl *DefaultedFn);
 
-  /// The number of \p CodeSynthesisContexts that are not template
-  /// instantiations and, therefore, should not be counted as part of the
-  /// instantiation depth.
-  ///
-  /// When the instantiation depth reaches the user-configurable limit
-  /// \p LangOptions::InstantiationDepth we will abort instantiation.
-  // FIXME: Should we have a similar limit for other forms of synthesis?
-  unsigned NonInstantiationEntries;
+  ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+                                                SourceLocation RLoc, Expr *Base,
+                                                MultiExprArg Args);
 
-  /// The depth of the context stack at the point when the most recent
-  /// error or warning was produced.
-  ///
-  /// This value is used to suppress printing of redundant context stacks
-  /// when there are multiple errors or warnings in the same instantiation.
-  // FIXME: Does this belong in Sema? It's tough to implement it anywhere else.
-  unsigned LastEmittedCodeSynthesisContextDepth = 0;
+  ExprResult BuildCallToMemberFunction(
+      Scope *S, Expr *MemExpr, SourceLocation LParenLoc, MultiExprArg Args,
+      SourceLocation RParenLoc, Expr *ExecConfig = nullptr,
+      bool IsExecConfig = false, bool AllowRecovery = false);
+  ExprResult BuildCallToObjectOfClassType(Scope *S, Expr *Object,
+                                          SourceLocation LParenLoc,
+                                          MultiExprArg Args,
+                                          SourceLocation RParenLoc);
 
-  /// The template instantiation callbacks to trace or track
-  /// instantiations (objects can be chained).
-  ///
-  /// This callbacks is used to print, trace or track template
-  /// instantiations as they are being constructed.
-  std::vector>
-      TemplateInstCallbacks;
+  ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
+                                      SourceLocation OpLoc,
+                                      bool *NoArrowOperatorFound = nullptr);
 
-  /// The current index into pack expansion arguments that will be
-  /// used for substitution of parameter packs.
-  ///
-  /// The pack expansion index will be -1 to indicate that parameter packs
-  /// should be instantiated as themselves. Otherwise, the index specifies
-  /// which argument within the parameter pack will be used for substitution.
-  int ArgumentPackSubstitutionIndex;
+  ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
+                                    CXXConversionDecl *Method,
+                                    bool HadMultipleCandidates);
 
-  /// RAII object used to change the argument pack substitution index
-  /// within a \c Sema object.
-  ///
-  /// See \c ArgumentPackSubstitutionIndex for more information.
-  class ArgumentPackSubstitutionIndexRAII {
-    Sema &Self;
-    int OldSubstitutionIndex;
+  ExprResult BuildLiteralOperatorCall(
+      LookupResult &R, DeclarationNameInfo &SuffixInfo, ArrayRef Args,
+      SourceLocation LitEndLoc,
+      TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
 
-  public:
-    ArgumentPackSubstitutionIndexRAII(Sema &Self, int NewSubstitutionIndex)
-      : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) {
-      Self.ArgumentPackSubstitutionIndex = NewSubstitutionIndex;
-    }
+  ExprResult FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl,
+                                            FunctionDecl *Fn);
+  ExprResult FixOverloadedFunctionReference(ExprResult,
+                                            DeclAccessPair FoundDecl,
+                                            FunctionDecl *Fn);
 
-    ~ArgumentPackSubstitutionIndexRAII() {
-      Self.ArgumentPackSubstitutionIndex = OldSubstitutionIndex;
-    }
-  };
+private:
+  /// - Returns a selector which best matches given argument list or
+  /// nullptr if none could be found
+  ObjCMethodDecl *SelectBestMethod(Selector Sel, MultiExprArg Args,
+                                   bool IsInstance,
+                                   SmallVectorImpl &Methods);
 
-  friend class ArgumentPackSubstitutionRAII;
+  ///@}
 
-  /// For each declaration that involved template argument deduction, the
-  /// set of diagnostics that were suppressed during that template argument
-  /// deduction.
-  ///
-  /// FIXME: Serialize this structure to the AST file.
-  typedef llvm::DenseMap >
-    SuppressedDiagnosticsMap;
-  SuppressedDiagnosticsMap SuppressedDiagnostics;
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// A stack object to be created when performing template
-  /// instantiation.
-  ///
-  /// Construction of an object of type \c InstantiatingTemplate
-  /// pushes the current instantiation onto the stack of active
-  /// instantiations. If the size of this stack exceeds the maximum
-  /// number of recursive template instantiations, construction
-  /// produces an error and evaluates true.
-  ///
-  /// Destruction of this object will pop the named instantiation off
-  /// the stack.
-  struct InstantiatingTemplate {
-    /// Note that we are instantiating a class template,
-    /// function template, variable template, alias template,
-    /// or a member thereof.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          Decl *Entity,
-                          SourceRange InstantiationRange = SourceRange());
+  /// \name Pseudo-Object
+  /// Implementations are in SemaPseudoObject.cpp
+  ///@{
 
-    struct ExceptionSpecification {};
-    /// Note that we are instantiating an exception specification
-    /// of a function template.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          FunctionDecl *Entity, ExceptionSpecification,
-                          SourceRange InstantiationRange = SourceRange());
+public:
+  void maybeExtendBlockObject(ExprResult &E);
+  CastKind PrepareCastToObjCObjectPointer(ExprResult &E);
 
-    /// Note that we are instantiating a default argument in a
-    /// template-id.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          TemplateParameter Param, TemplateDecl *Template,
-                          ArrayRef TemplateArgs,
-                          SourceRange InstantiationRange = SourceRange());
+  enum ObjCSubscriptKind { OS_Array, OS_Dictionary, OS_Error };
+  ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE);
 
-    /// Note that we are substituting either explicitly-specified or
-    /// deduced template arguments during function template argument deduction.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          FunctionTemplateDecl *FunctionTemplate,
-                          ArrayRef TemplateArgs,
-                          CodeSynthesisContext::SynthesisKind Kind,
-                          sema::TemplateDeductionInfo &DeductionInfo,
-                          SourceRange InstantiationRange = SourceRange());
+  ExprResult checkPseudoObjectIncDec(Scope *S, SourceLocation OpLoc,
+                                     UnaryOperatorKind Opcode, Expr *Op);
+  ExprResult checkPseudoObjectAssignment(Scope *S, SourceLocation OpLoc,
+                                         BinaryOperatorKind Opcode, Expr *LHS,
+                                         Expr *RHS);
+  ExprResult checkPseudoObjectRValue(Expr *E);
+  Expr *recreateSyntacticForm(PseudoObjectExpr *E);
 
-    /// Note that we are instantiating as part of template
-    /// argument deduction for a class template declaration.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          TemplateDecl *Template,
-                          ArrayRef TemplateArgs,
-                          sema::TemplateDeductionInfo &DeductionInfo,
-                          SourceRange InstantiationRange = SourceRange());
+  ///@}
 
-    /// Note that we are instantiating as part of template
-    /// argument deduction for a class template partial
-    /// specialization.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          ClassTemplatePartialSpecializationDecl *PartialSpec,
-                          ArrayRef TemplateArgs,
-                          sema::TemplateDeductionInfo &DeductionInfo,
-                          SourceRange InstantiationRange = SourceRange());
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-    /// Note that we are instantiating as part of template
-    /// argument deduction for a variable template partial
-    /// specialization.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          VarTemplatePartialSpecializationDecl *PartialSpec,
-                          ArrayRef TemplateArgs,
-                          sema::TemplateDeductionInfo &DeductionInfo,
-                          SourceRange InstantiationRange = SourceRange());
+  /// \name Statements
+  /// Implementations are in SemaStmt.cpp
+  ///@{
 
-    /// Note that we are instantiating a default argument for a function
-    /// parameter.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          ParmVarDecl *Param,
-                          ArrayRef TemplateArgs,
-                          SourceRange InstantiationRange = SourceRange());
+public:
+  /// Stack of active SEH __finally scopes.  Can be empty.
+  SmallVector CurrentSEHFinally;
 
-    /// Note that we are substituting prior template arguments into a
-    /// non-type parameter.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          NamedDecl *Template,
-                          NonTypeTemplateParmDecl *Param,
-                          ArrayRef TemplateArgs,
-                          SourceRange InstantiationRange);
+  StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true);
+  StmtResult ActOnExprStmtError();
 
-    /// Note that we are substituting prior template arguments into a
-    /// template template parameter.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          NamedDecl *Template,
-                          TemplateTemplateParmDecl *Param,
-                          ArrayRef TemplateArgs,
-                          SourceRange InstantiationRange);
+  StmtResult ActOnNullStmt(SourceLocation SemiLoc,
+                           bool HasLeadingEmptyMacro = false);
 
-    /// Note that we are checking the default template argument
-    /// against the template parameter for a given template-id.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          TemplateDecl *Template,
-                          NamedDecl *Param,
-                          ArrayRef TemplateArgs,
-                          SourceRange InstantiationRange);
+  StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc,
+                           SourceLocation EndLoc);
+  void ActOnForEachDeclStmt(DeclGroupPtrTy Decl);
 
-    struct ConstraintsCheck {};
-    /// \brief Note that we are checking the constraints associated with some
-    /// constrained entity (a concept declaration or a template with associated
-    /// constraints).
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          ConstraintsCheck, NamedDecl *Template,
-                          ArrayRef TemplateArgs,
-                          SourceRange InstantiationRange);
+  /// DiagnoseUnusedExprResult - If the statement passed in is an expression
+  /// whose result is unused, warn.
+  void DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID);
 
-    struct ConstraintSubstitution {};
-    /// \brief Note that we are checking a constraint expression associated
-    /// with a template declaration or as part of the satisfaction check of a
-    /// concept.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          ConstraintSubstitution, NamedDecl *Template,
-                          sema::TemplateDeductionInfo &DeductionInfo,
-                          SourceRange InstantiationRange);
+  void ActOnStartOfCompoundStmt(bool IsStmtExpr);
+  void ActOnAfterCompoundStatementLeadingPragmas();
+  void ActOnFinishOfCompoundStmt();
+  StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
+                               ArrayRef Elts, bool isStmtExpr);
 
-    struct ConstraintNormalization {};
-    /// \brief Note that we are normalizing a constraint expression.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          ConstraintNormalization, NamedDecl *Template,
-                          SourceRange InstantiationRange);
+  sema::CompoundScopeInfo &getCurCompoundScope() const;
 
-    struct ParameterMappingSubstitution {};
-    /// \brief Note that we are subtituting into the parameter mapping of an
-    /// atomic constraint during constraint normalization.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          ParameterMappingSubstitution, NamedDecl *Template,
-                          SourceRange InstantiationRange);
+  ExprResult ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val);
+  StmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHS,
+                           SourceLocation DotDotDotLoc, ExprResult RHS,
+                           SourceLocation ColonLoc);
+  void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt);
 
-    /// \brief Note that we are substituting template arguments into a part of
-    /// a requirement of a requires expression.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          concepts::Requirement *Req,
-                          sema::TemplateDeductionInfo &DeductionInfo,
-                          SourceRange InstantiationRange = SourceRange());
+  StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
+                              SourceLocation ColonLoc, Stmt *SubStmt,
+                              Scope *CurScope);
+  StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
+                            SourceLocation ColonLoc, Stmt *SubStmt);
 
-    /// \brief Note that we are checking the satisfaction of the constraint
-    /// expression inside of a nested requirement.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          concepts::NestedRequirement *Req, ConstraintsCheck,
-                          SourceRange InstantiationRange = SourceRange());
+  StmtResult BuildAttributedStmt(SourceLocation AttrsLoc,
+                                 ArrayRef Attrs, Stmt *SubStmt);
+  StmtResult ActOnAttributedStmt(const ParsedAttributes &AttrList,
+                                 Stmt *SubStmt);
 
-    /// \brief Note that we are checking a requires clause.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          const RequiresExpr *E,
-                          sema::TemplateDeductionInfo &DeductionInfo,
-                          SourceRange InstantiationRange);
+  /// Check whether the given statement can have musttail applied to it,
+  /// issuing a diagnostic and returning false if not. In the success case,
+  /// the statement is rewritten to remove implicit nodes from the return
+  /// value.
+  bool checkAndRewriteMustTailAttr(Stmt *St, const Attr &MTA);
 
-    struct BuildingDeductionGuidesTag {};
-    /// \brief Note that we are building deduction guides.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          TemplateDecl *Entity, BuildingDeductionGuidesTag,
-                          SourceRange InstantiationRange = SourceRange());
+  StmtResult ActOnIfStmt(SourceLocation IfLoc, IfStatementKind StatementKind,
+                         SourceLocation LParenLoc, Stmt *InitStmt,
+                         ConditionResult Cond, SourceLocation RParenLoc,
+                         Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal);
+  StmtResult BuildIfStmt(SourceLocation IfLoc, IfStatementKind StatementKind,
+                         SourceLocation LParenLoc, Stmt *InitStmt,
+                         ConditionResult Cond, SourceLocation RParenLoc,
+                         Stmt *ThenVal, SourceLocation ElseLoc, Stmt *ElseVal);
 
-    /// Note that we have finished instantiating this template.
-    void Clear();
+  ExprResult CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond);
 
-    ~InstantiatingTemplate() { Clear(); }
+  StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
+                                    SourceLocation LParenLoc, Stmt *InitStmt,
+                                    ConditionResult Cond,
+                                    SourceLocation RParenLoc);
+  StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
+                                   Stmt *Body);
 
-    /// Determines whether we have exceeded the maximum
-    /// recursive template instantiations.
-    bool isInvalid() const { return Invalid; }
+  /// DiagnoseAssignmentEnum - Warn if assignment to enum is a constant
+  /// integer not in the range of enum values.
+  void DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
+                              Expr *SrcExpr);
 
-    /// Determine whether we are already instantiating this
-    /// specialization in some surrounding active instantiation.
-    bool isAlreadyInstantiating() const { return AlreadyInstantiating; }
+  StmtResult ActOnWhileStmt(SourceLocation WhileLoc, SourceLocation LParenLoc,
+                            ConditionResult Cond, SourceLocation RParenLoc,
+                            Stmt *Body);
+  StmtResult ActOnDoStmt(SourceLocation DoLoc, Stmt *Body,
+                         SourceLocation WhileLoc, SourceLocation CondLParen,
+                         Expr *Cond, SourceLocation CondRParen);
 
-  private:
-    Sema &SemaRef;
-    bool Invalid;
-    bool AlreadyInstantiating;
-    bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
-                                 SourceRange InstantiationRange);
+  StmtResult ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
+                          Stmt *First, ConditionResult Second,
+                          FullExprArg Third, SourceLocation RParenLoc,
+                          Stmt *Body);
 
-    InstantiatingTemplate(
-        Sema &SemaRef, CodeSynthesisContext::SynthesisKind Kind,
-        SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
-        Decl *Entity, NamedDecl *Template = nullptr,
-        ArrayRef TemplateArgs = std::nullopt,
-        sema::TemplateDeductionInfo *DeductionInfo = nullptr);
+  StmtResult ActOnForEachLValueExpr(Expr *E);
 
-    InstantiatingTemplate(const InstantiatingTemplate&) = delete;
+  ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc,
+                                           Expr *collection);
+  StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, Stmt *First,
+                                        Expr *collection,
+                                        SourceLocation RParenLoc);
+  StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body);
 
-    InstantiatingTemplate&
-    operator=(const InstantiatingTemplate&) = delete;
+  enum BuildForRangeKind {
+    /// Initial building of a for-range statement.
+    BFRK_Build,
+    /// Instantiation or recovery rebuild of a for-range statement. Don't
+    /// attempt any typo-correction.
+    BFRK_Rebuild,
+    /// Determining whether a for-range statement could be built. Avoid any
+    /// unnecessary or irreversible actions.
+    BFRK_Check
   };
 
-  void pushCodeSynthesisContext(CodeSynthesisContext Ctx);
-  void popCodeSynthesisContext();
+  StmtResult ActOnCXXForRangeStmt(
+      Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc,
+      Stmt *InitStmt, Stmt *LoopVar, SourceLocation ColonLoc, Expr *Collection,
+      SourceLocation RParenLoc, BuildForRangeKind Kind,
+      ArrayRef LifetimeExtendTemps = {});
+  StmtResult BuildCXXForRangeStmt(
+      SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt,
+      SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *Begin, Stmt *End,
+      Expr *Cond, Expr *Inc, Stmt *LoopVarDecl, SourceLocation RParenLoc,
+      BuildForRangeKind Kind,
+      ArrayRef LifetimeExtendTemps = {});
+  StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body);
 
-  /// Determine whether we are currently performing template instantiation.
-  bool inTemplateInstantiation() const {
-    return CodeSynthesisContexts.size() > NonInstantiationEntries;
-  }
+  StmtResult ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
+                           LabelDecl *TheDecl);
+  StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
+                                   SourceLocation StarLoc, Expr *DestExp);
+  StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope);
+  StmtResult ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope);
 
-  void PrintContextStack() {
-    if (!CodeSynthesisContexts.empty() &&
-        CodeSynthesisContexts.size() != LastEmittedCodeSynthesisContextDepth) {
-      PrintInstantiationStack();
-      LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size();
-    }
-    if (PragmaAttributeCurrentTargetDecl)
-      PrintPragmaAttributeInstantiationPoint();
-  }
-  void PrintInstantiationStack();
+  struct NamedReturnInfo {
+    const VarDecl *Candidate;
 
-  void PrintPragmaAttributeInstantiationPoint();
+    enum Status : uint8_t { None, MoveEligible, MoveEligibleAndCopyElidable };
+    Status S;
 
-  /// Determines whether we are currently in a context where
-  /// template argument substitution failures are not considered
-  /// errors.
-  ///
-  /// \returns An empty \c Optional if we're not in a SFINAE context.
-  /// Otherwise, contains a pointer that, if non-NULL, contains the nearest
-  /// template-deduction context object, which can be used to capture
-  /// diagnostics that will be suppressed.
-  std::optional isSFINAEContext() const;
+    bool isMoveEligible() const { return S != None; };
+    bool isCopyElidable() const { return S == MoveEligibleAndCopyElidable; }
+  };
+  enum class SimplerImplicitMoveMode { ForceOff, Normal, ForceOn };
+  NamedReturnInfo getNamedReturnInfo(
+      Expr *&E, SimplerImplicitMoveMode Mode = SimplerImplicitMoveMode::Normal);
+  NamedReturnInfo getNamedReturnInfo(const VarDecl *VD);
+  const VarDecl *getCopyElisionCandidate(NamedReturnInfo &Info,
+                                         QualType ReturnType);
 
-  /// Whether the AST is currently being rebuilt to correct immediate
-  /// invocations. Immediate invocation candidates and references to consteval
-  /// functions aren't tracked when this is set.
-  bool RebuildingImmediateInvocation = false;
+  ExprResult
+  PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
+                                  const NamedReturnInfo &NRInfo, Expr *Value,
+                                  bool SupressSimplerImplicitMoves = false);
 
-  /// Used to change context to isConstantEvaluated without pushing a heavy
-  /// ExpressionEvaluationContextRecord object.
-  bool isConstantEvaluatedOverride = false;
+  TypeLoc getReturnTypeLoc(FunctionDecl *FD) const;
 
-  const ExpressionEvaluationContextRecord ¤tEvaluationContext() const {
-    assert(!ExprEvalContexts.empty() &&
-           "Must be in an expression evaluation context");
-    return ExprEvalContexts.back();
-  };
+  bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
+                                        SourceLocation ReturnLoc, Expr *RetExpr,
+                                        const AutoType *AT);
 
-  bool isConstantEvaluatedContext() const {
-    return currentEvaluationContext().isConstantEvaluated() ||
-           isConstantEvaluatedOverride;
-  }
+  StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
+                             Scope *CurScope);
+  StmtResult BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
+                             bool AllowRecovery = false);
+  StmtResult ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
+                                     NamedReturnInfo &NRInfo,
+                                     bool SupressSimplerImplicitMoves);
 
-  bool isAlwaysConstantEvaluatedContext() const {
-    const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
-    return (Ctx.isConstantEvaluated() || isConstantEvaluatedOverride) &&
-           !Ctx.InConditionallyConstantEvaluateContext;
-  }
+  StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen,
+                                  Decl *Parm, Stmt *Body);
 
-  /// Determines whether we are currently in a context that
-  /// is not evaluated as per C++ [expr] p5.
-  bool isUnevaluatedContext() const {
-    return currentEvaluationContext().isUnevaluated();
-  }
+  StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body);
 
-  bool isImmediateFunctionContext() const {
-    return currentEvaluationContext().isImmediateFunctionContext();
-  }
+  StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
+                                MultiStmtArg Catch, Stmt *Finally);
 
-  bool isInLifetimeExtendingContext() const {
-    assert(!ExprEvalContexts.empty() &&
-           "Must be in an expression evaluation context");
-    return ExprEvalContexts.back().InLifetimeExtendingContext;
-  }
+  StmtResult BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw);
+  StmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,
+                                  Scope *CurScope);
+  ExprResult ActOnObjCAtSynchronizedOperand(SourceLocation atLoc,
+                                            Expr *operand);
+  StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SynchExpr,
+                                         Stmt *SynchBody);
 
-  bool isInMaterializeTemporaryObjectContext() const {
-    assert(!ExprEvalContexts.empty() &&
-           "Must be in an expression evaluation context");
-    return ExprEvalContexts.back().InMaterializeTemporaryObjectContext;
-  }
+  StmtResult ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body);
 
-  bool isCheckingDefaultArgumentOrInitializer() const {
-    const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
-    return (Ctx.Context ==
-            ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed) ||
-           Ctx.IsCurrentlyCheckingDefaultArgumentOrInitializer;
-  }
+  StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl,
+                                Stmt *HandlerBlock);
+  StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
+                              ArrayRef Handlers);
 
-  std::optional
-  InnermostDeclarationWithDelayedImmediateInvocations() const {
-    assert(!ExprEvalContexts.empty() &&
-           "Must be in an expression evaluation context");
-    for (const auto &Ctx : llvm::reverse(ExprEvalContexts)) {
-      if (Ctx.Context == ExpressionEvaluationContext::PotentiallyEvaluated &&
-          Ctx.DelayedDefaultInitializationContext)
-        return Ctx.DelayedDefaultInitializationContext;
-      if (Ctx.isConstantEvaluated() || Ctx.isImmediateFunctionContext() ||
-          Ctx.isUnevaluated())
-        break;
-    }
-    return std::nullopt;
-  }
+  StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ?
+                              SourceLocation TryLoc, Stmt *TryBlock,
+                              Stmt *Handler);
+  StmtResult ActOnSEHExceptBlock(SourceLocation Loc, Expr *FilterExpr,
+                                 Stmt *Block);
+  void ActOnStartSEHFinallyBlock();
+  void ActOnAbortSEHFinallyBlock();
+  StmtResult ActOnFinishSEHFinallyBlock(SourceLocation Loc, Stmt *Block);
+  StmtResult ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope);
 
-  std::optional
-  OutermostDeclarationWithDelayedImmediateInvocations() const {
-    assert(!ExprEvalContexts.empty() &&
-           "Must be in an expression evaluation context");
-    std::optional Res;
-    for (auto &Ctx : llvm::reverse(ExprEvalContexts)) {
-      if (Ctx.Context == ExpressionEvaluationContext::PotentiallyEvaluated &&
-          !Ctx.DelayedDefaultInitializationContext && Res)
-        break;
-      if (Ctx.isConstantEvaluated() || Ctx.isImmediateFunctionContext() ||
-          Ctx.isUnevaluated())
-        break;
-      Res = Ctx.DelayedDefaultInitializationContext;
-    }
-    return Res;
-  }
+  StmtResult BuildMSDependentExistsStmt(SourceLocation KeywordLoc,
+                                        bool IsIfExists,
+                                        NestedNameSpecifierLoc QualifierLoc,
+                                        DeclarationNameInfo NameInfo,
+                                        Stmt *Nested);
+  StmtResult ActOnMSDependentExistsStmt(SourceLocation KeywordLoc,
+                                        bool IsIfExists, CXXScopeSpec &SS,
+                                        UnqualifiedId &Name, Stmt *Nested);
 
-  /// keepInLifetimeExtendingContext - Pull down InLifetimeExtendingContext
-  /// flag from previous context.
-  void keepInLifetimeExtendingContext() {
-    if (ExprEvalContexts.size() > 2 &&
-        ExprEvalContexts[ExprEvalContexts.size() - 2]
-            .InLifetimeExtendingContext) {
-      auto &LastRecord = ExprEvalContexts.back();
-      auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2];
-      LastRecord.InLifetimeExtendingContext =
-          PrevRecord.InLifetimeExtendingContext;
-    }
-  }
-
-  /// keepInMaterializeTemporaryObjectContext - Pull down
-  /// InMaterializeTemporaryObjectContext flag from previous context.
-  void keepInMaterializeTemporaryObjectContext() {
-    if (ExprEvalContexts.size() > 2 &&
-        ExprEvalContexts[ExprEvalContexts.size() - 2]
-            .InMaterializeTemporaryObjectContext) {
-      auto &LastRecord = ExprEvalContexts.back();
-      auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2];
-      LastRecord.InMaterializeTemporaryObjectContext =
-          PrevRecord.InMaterializeTemporaryObjectContext;
-    }
-  }
-
-  /// RAII class used to determine whether SFINAE has
-  /// trapped any errors that occur during template argument
-  /// deduction.
-  class SFINAETrap {
-    Sema &SemaRef;
-    unsigned PrevSFINAEErrors;
-    bool PrevInNonInstantiationSFINAEContext;
-    bool PrevAccessCheckingSFINAE;
-    bool PrevLastDiagnosticIgnored;
-
-  public:
-    explicit SFINAETrap(Sema &SemaRef, bool AccessCheckingSFINAE = false)
-      : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors),
-        PrevInNonInstantiationSFINAEContext(
-                                      SemaRef.InNonInstantiationSFINAEContext),
-        PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE),
-        PrevLastDiagnosticIgnored(
-            SemaRef.getDiagnostics().isLastDiagnosticIgnored())
-    {
-      if (!SemaRef.isSFINAEContext())
-        SemaRef.InNonInstantiationSFINAEContext = true;
-      SemaRef.AccessCheckingSFINAE = AccessCheckingSFINAE;
-    }
-
-    ~SFINAETrap() {
-      SemaRef.NumSFINAEErrors = PrevSFINAEErrors;
-      SemaRef.InNonInstantiationSFINAEContext
-        = PrevInNonInstantiationSFINAEContext;
-      SemaRef.AccessCheckingSFINAE = PrevAccessCheckingSFINAE;
-      SemaRef.getDiagnostics().setLastDiagnosticIgnored(
-          PrevLastDiagnosticIgnored);
-    }
-
-    /// Determine whether any SFINAE errors have been trapped.
-    bool hasErrorOccurred() const {
-      return SemaRef.NumSFINAEErrors > PrevSFINAEErrors;
-    }
-  };
+  void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
+                                CapturedRegionKind Kind, unsigned NumParams);
+  typedef std::pair CapturedParamNameType;
+  void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
+                                CapturedRegionKind Kind,
+                                ArrayRef Params,
+                                unsigned OpenMPCaptureLevel = 0);
+  StmtResult ActOnCapturedRegionEnd(Stmt *S);
+  void ActOnCapturedRegionError();
+  RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD,
+                                           SourceLocation Loc,
+                                           unsigned NumParams);
 
-  /// RAII class used to indicate that we are performing provisional
-  /// semantic analysis to determine the validity of a construct, so
-  /// typo-correction and diagnostics in the immediate context (not within
-  /// implicitly-instantiated templates) should be suppressed.
-  class TentativeAnalysisScope {
-    Sema &SemaRef;
-    // FIXME: Using a SFINAETrap for this is a hack.
-    SFINAETrap Trap;
-    bool PrevDisableTypoCorrection;
-  public:
-    explicit TentativeAnalysisScope(Sema &SemaRef)
-        : SemaRef(SemaRef), Trap(SemaRef, true),
-          PrevDisableTypoCorrection(SemaRef.DisableTypoCorrection) {
-      SemaRef.DisableTypoCorrection = true;
-    }
-    ~TentativeAnalysisScope() {
-      SemaRef.DisableTypoCorrection = PrevDisableTypoCorrection;
-    }
-  };
+private:
+  /// Check whether the given statement can have musttail applied to it,
+  /// issuing a diagnostic and returning false if not.
+  bool checkMustTailAttr(const Stmt *St, const Attr &MTA);
 
-  /// The current instantiation scope used to store local
-  /// variables.
-  LocalInstantiationScope *CurrentInstantiationScope;
+  /// Check if the given expression contains 'break' or 'continue'
+  /// statement that produces control flow different from GCC.
+  void CheckBreakContinueBinding(Expr *E);
 
-  /// Tracks whether we are in a context where typo correction is
-  /// disabled.
-  bool DisableTypoCorrection;
+  ///@}
 
-  /// The number of typos corrected by CorrectTypo.
-  unsigned TyposCorrected;
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  typedef llvm::SmallSet SrcLocSet;
-  typedef llvm::DenseMap IdentifierSourceLocations;
+  /// \name `inline asm` Statement
+  /// Implementations are in SemaStmtAsm.cpp
+  ///@{
 
-  /// A cache containing identifiers for which typo correction failed and
-  /// their locations, so that repeated attempts to correct an identifier in a
-  /// given location are ignored if typo correction already failed for it.
-  IdentifierSourceLocations TypoCorrectionFailures;
+public:
+  StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
+                             bool IsVolatile, unsigned NumOutputs,
+                             unsigned NumInputs, IdentifierInfo **Names,
+                             MultiExprArg Constraints, MultiExprArg Exprs,
+                             Expr *AsmString, MultiExprArg Clobbers,
+                             unsigned NumLabels, SourceLocation RParenLoc);
 
-  /// Worker object for performing CFG-based warnings.
-  sema::AnalysisBasedWarnings AnalysisWarnings;
-  threadSafety::BeforeSet *ThreadSafetyDeclCache;
+  void FillInlineAsmIdentifierInfo(Expr *Res,
+                                   llvm::InlineAsmIdentifierInfo &Info);
+  ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS,
+                                       SourceLocation TemplateKWLoc,
+                                       UnqualifiedId &Id,
+                                       bool IsUnevaluatedContext);
+  bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset,
+                            SourceLocation AsmLoc);
+  ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member,
+                                         SourceLocation AsmLoc);
+  StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
+                            ArrayRef AsmToks, StringRef AsmString,
+                            unsigned NumOutputs, unsigned NumInputs,
+                            ArrayRef Constraints,
+                            ArrayRef Clobbers,
+                            ArrayRef Exprs, SourceLocation EndLoc);
+  LabelDecl *GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
+                                   SourceLocation Location, bool AlwaysCreate);
 
-  /// An entity for which implicit template instantiation is required.
-  ///
-  /// The source location associated with the declaration is the first place in
-  /// the source code where the declaration was "used". It is not necessarily
-  /// the point of instantiation (which will be either before or after the
-  /// namespace-scope declaration that triggered this implicit instantiation),
-  /// However, it is the location that diagnostics should generally refer to,
-  /// because users will need to know what code triggered the instantiation.
-  typedef std::pair PendingImplicitInstantiation;
+  ///@}
 
-  /// The queue of implicit template instantiations that are required
-  /// but have not yet been performed.
-  std::deque PendingInstantiations;
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Queue of implicit template instantiations that cannot be performed
-  /// eagerly.
-  SmallVector LateParsedInstantiations;
+  /// \name Statement Attribute Handling
+  /// Implementations are in SemaStmtAttr.cpp
+  ///@{
 
-  SmallVector, 8> SavedVTableUses;
-  SmallVector, 8>
-      SavedPendingInstantiations;
+public:
+  bool CheckNoInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
+                         const AttributeCommonInfo &A);
+  bool CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
+                             const AttributeCommonInfo &A);
 
-  class GlobalEagerInstantiationScope {
-  public:
-    GlobalEagerInstantiationScope(Sema &S, bool Enabled)
-        : S(S), Enabled(Enabled) {
-      if (!Enabled) return;
+  CodeAlignAttr *BuildCodeAlignAttr(const AttributeCommonInfo &CI, Expr *E);
+  bool CheckRebuiltStmtAttributes(ArrayRef Attrs);
 
-      S.SavedPendingInstantiations.emplace_back();
-      S.SavedPendingInstantiations.back().swap(S.PendingInstantiations);
+  /// Process the attributes before creating an attributed statement. Returns
+  /// the semantic attributes that have been processed.
+  void ProcessStmtAttributes(Stmt *Stmt, const ParsedAttributes &InAttrs,
+                             SmallVectorImpl &OutAttrs);
 
-      S.SavedVTableUses.emplace_back();
-      S.SavedVTableUses.back().swap(S.VTableUses);
-    }
+  ExprResult ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A,
+                                SourceRange Range);
+  ExprResult BuildCXXAssumeExpr(Expr *Assumption,
+                                const IdentifierInfo *AttrName,
+                                SourceRange Range);
 
-    void perform() {
-      if (Enabled) {
-        S.DefineUsedVTables();
-        S.PerformPendingInstantiations();
-      }
-    }
+  ///@}
 
-    ~GlobalEagerInstantiationScope() {
-      if (!Enabled) return;
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-      // Restore the set of pending vtables.
-      assert(S.VTableUses.empty() &&
-             "VTableUses should be empty before it is discarded.");
-      S.VTableUses.swap(S.SavedVTableUses.back());
-      S.SavedVTableUses.pop_back();
+  /// \name C++ Templates
+  /// Implementations are in SemaTemplate.cpp
+  ///@{
 
-      // Restore the set of pending implicit instantiations.
-      if (S.TUKind != TU_Prefix || !S.LangOpts.PCHInstantiateTemplates) {
-        assert(S.PendingInstantiations.empty() &&
-               "PendingInstantiations should be empty before it is discarded.");
-        S.PendingInstantiations.swap(S.SavedPendingInstantiations.back());
-        S.SavedPendingInstantiations.pop_back();
-      } else {
-        // Template instantiations in the PCH may be delayed until the TU.
-        S.PendingInstantiations.swap(S.SavedPendingInstantiations.back());
-        S.PendingInstantiations.insert(
-            S.PendingInstantiations.end(),
-            S.SavedPendingInstantiations.back().begin(),
-            S.SavedPendingInstantiations.back().end());
-        S.SavedPendingInstantiations.pop_back();
-      }
+public:
+  // Saves the current floating-point pragma stack and clear it in this Sema.
+  class FpPragmaStackSaveRAII {
+  public:
+    FpPragmaStackSaveRAII(Sema &S)
+        : S(S), SavedStack(std::move(S.FpPragmaStack)) {
+      S.FpPragmaStack.Stack.clear();
     }
+    ~FpPragmaStackSaveRAII() { S.FpPragmaStack = std::move(SavedStack); }
 
   private:
     Sema &S;
-    bool Enabled;
+    PragmaStack SavedStack;
   };
 
-  /// The queue of implicit template instantiations that are required
-  /// and must be performed within the current local scope.
-  ///
-  /// This queue is only used for member functions of local classes in
-  /// templates, which must be instantiated in the same scope as their
-  /// enclosing function, so that they can reference function-local
-  /// types, static variables, enumerators, etc.
-  std::deque PendingLocalImplicitInstantiations;
-
-  class LocalEagerInstantiationScope {
-  public:
-    LocalEagerInstantiationScope(Sema &S) : S(S) {
-      SavedPendingLocalImplicitInstantiations.swap(
-          S.PendingLocalImplicitInstantiations);
-    }
+  void resetFPOptions(FPOptions FPO) {
+    CurFPFeatures = FPO;
+    FpPragmaStack.CurrentValue = FPO.getChangesFrom(FPOptions(LangOpts));
+  }
 
-    void perform() { S.PerformPendingInstantiations(/*LocalOnly=*/true); }
+  ArrayRef getInventedParameterInfos() const {
+    return llvm::ArrayRef(InventedParameterInfos.begin() +
+                              InventedParameterInfosStart,
+                          InventedParameterInfos.end());
+  }
 
-    ~LocalEagerInstantiationScope() {
-      assert(S.PendingLocalImplicitInstantiations.empty() &&
-             "there shouldn't be any pending local implicit instantiations");
-      SavedPendingLocalImplicitInstantiations.swap(
-          S.PendingLocalImplicitInstantiations);
-    }
+  /// The number of SFINAE diagnostics that have been trapped.
+  unsigned NumSFINAEErrors;
 
-  private:
-    Sema &S;
-    std::deque
-        SavedPendingLocalImplicitInstantiations;
-  };
+  ArrayRef getFunctionScopes() const {
+    return llvm::ArrayRef(FunctionScopes.begin() + FunctionScopesStart,
+                          FunctionScopes.end());
+  }
 
-  /// A helper class for building up ExtParameterInfos.
-  class ExtParameterInfoBuilder {
-    SmallVector Infos;
-    bool HasInteresting = false;
+  typedef llvm::MapVector>
+      LateParsedTemplateMapT;
+  LateParsedTemplateMapT LateParsedTemplateMap;
 
+  /// Determine the number of levels of enclosing template parameters. This is
+  /// only usable while parsing. Note that this does not include dependent
+  /// contexts in which no template parameters have yet been declared, such as
+  /// in a terse function template or generic lambda before the first 'auto' is
+  /// encountered.
+  unsigned getTemplateDepth(Scope *S) const;
+
+  void FilterAcceptableTemplateNames(LookupResult &R,
+                                     bool AllowFunctionTemplates = true,
+                                     bool AllowDependent = true);
+  bool hasAnyAcceptableTemplateNames(LookupResult &R,
+                                     bool AllowFunctionTemplates = true,
+                                     bool AllowDependent = true,
+                                     bool AllowNonTemplateFunctions = false);
+  /// Try to interpret the lookup result D as a template-name.
+  ///
+  /// \param D A declaration found by name lookup.
+  /// \param AllowFunctionTemplates Whether function templates should be
+  ///        considered valid results.
+  /// \param AllowDependent Whether unresolved using declarations (that might
+  ///        name templates) should be considered valid results.
+  static NamedDecl *getAsTemplateNameDecl(NamedDecl *D,
+                                          bool AllowFunctionTemplates = true,
+                                          bool AllowDependent = true);
+
+  enum TemplateNameIsRequiredTag { TemplateNameIsRequired };
+  /// Whether and why a template name is required in this lookup.
+  class RequiredTemplateKind {
   public:
-    /// Set the ExtParameterInfo for the parameter at the given index,
-    ///
-    void set(unsigned index, FunctionProtoType::ExtParameterInfo info) {
-      assert(Infos.size() <= index);
-      Infos.resize(index);
-      Infos.push_back(info);
+    /// Template name is required if TemplateKWLoc is valid.
+    RequiredTemplateKind(SourceLocation TemplateKWLoc = SourceLocation())
+        : TemplateKW(TemplateKWLoc) {}
+    /// Template name is unconditionally required.
+    RequiredTemplateKind(TemplateNameIsRequiredTag) {}
 
-      if (!HasInteresting)
-        HasInteresting = (info != FunctionProtoType::ExtParameterInfo());
+    SourceLocation getTemplateKeywordLoc() const {
+      return TemplateKW.value_or(SourceLocation());
     }
-
-    /// Return a pointer (suitable for setting in an ExtProtoInfo) to the
-    /// ExtParameterInfo array we've built up.
-    const FunctionProtoType::ExtParameterInfo *
-    getPointerOrNull(unsigned numParams) {
-      if (!HasInteresting) return nullptr;
-      Infos.resize(numParams);
-      return Infos.data();
+    bool hasTemplateKeyword() const {
+      return getTemplateKeywordLoc().isValid();
     }
-  };
+    bool isRequired() const { return TemplateKW != SourceLocation(); }
+    explicit operator bool() const { return isRequired(); }
 
-  void PerformPendingInstantiations(bool LocalOnly = false);
+  private:
+    std::optional TemplateKW;
+  };
 
-  TypeSourceInfo *SubstType(TypeSourceInfo *T,
-                            const MultiLevelTemplateArgumentList &TemplateArgs,
-                            SourceLocation Loc, DeclarationName Entity,
-                            bool AllowDeducedTST = false);
+  enum class AssumedTemplateKind {
+    /// This is not assumed to be a template name.
+    None,
+    /// This is assumed to be a template name because lookup found nothing.
+    FoundNothing,
+    /// This is assumed to be a template name because lookup found one or more
+    /// functions (but no function templates).
+    FoundFunctions,
+  };
+  bool LookupTemplateName(
+      LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType,
+      bool EnteringContext, bool &MemberOfUnknownSpecialization,
+      RequiredTemplateKind RequiredTemplate = SourceLocation(),
+      AssumedTemplateKind *ATK = nullptr, bool AllowTypoCorrection = true);
 
-  QualType SubstType(QualType T,
-                     const MultiLevelTemplateArgumentList &TemplateArgs,
-                     SourceLocation Loc, DeclarationName Entity);
+  TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS,
+                                  bool hasTemplateKeyword,
+                                  const UnqualifiedId &Name,
+                                  ParsedType ObjectType, bool EnteringContext,
+                                  TemplateTy &Template,
+                                  bool &MemberOfUnknownSpecialization,
+                                  bool Disambiguation = false);
 
-  TypeSourceInfo *SubstType(TypeLoc TL,
-                            const MultiLevelTemplateArgumentList &TemplateArgs,
-                            SourceLocation Loc, DeclarationName Entity);
+  /// Try to resolve an undeclared template name as a type template.
+  ///
+  /// Sets II to the identifier corresponding to the template name, and updates
+  /// Name to a corresponding (typo-corrected) type template name and TNK to
+  /// the corresponding kind, if possible.
+  void ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &Name,
+                                       TemplateNameKind &TNK,
+                                       SourceLocation NameLoc,
+                                       IdentifierInfo *&II);
 
-  TypeSourceInfo *SubstFunctionDeclType(
-      TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs,
-      SourceLocation Loc, DeclarationName Entity, CXXRecordDecl *ThisContext,
-      Qualifiers ThisTypeQuals, bool EvaluateConstraints = true);
-  void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
-                          const MultiLevelTemplateArgumentList &Args);
-  bool SubstExceptionSpec(SourceLocation Loc,
-                          FunctionProtoType::ExceptionSpecInfo &ESI,
-                          SmallVectorImpl &ExceptionStorage,
-                          const MultiLevelTemplateArgumentList &Args);
-  ParmVarDecl *
-  SubstParmVarDecl(ParmVarDecl *D,
-                   const MultiLevelTemplateArgumentList &TemplateArgs,
-                   int indexAdjustment, std::optional NumExpansions,
-                   bool ExpectParameterPack, bool EvaluateConstraints = true);
-  bool SubstParmTypes(SourceLocation Loc, ArrayRef Params,
-                      const FunctionProtoType::ExtParameterInfo *ExtParamInfos,
-                      const MultiLevelTemplateArgumentList &TemplateArgs,
-                      SmallVectorImpl &ParamTypes,
-                      SmallVectorImpl *OutParams,
-                      ExtParameterInfoBuilder &ParamInfos);
-  bool SubstDefaultArgument(SourceLocation Loc, ParmVarDecl *Param,
-                            const MultiLevelTemplateArgumentList &TemplateArgs,
-                            bool ForCallExpr = false);
-  ExprResult SubstExpr(Expr *E,
-                       const MultiLevelTemplateArgumentList &TemplateArgs);
+  bool resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name,
+                                        SourceLocation NameLoc,
+                                        bool Diagnose = true);
 
-  // A RAII type used by the TemplateDeclInstantiator and TemplateInstantiator
-  // to disable constraint evaluation, then restore the state.
-  template  struct ConstraintEvalRAII {
-    InstTy &TI;
-    bool OldValue;
+  /// Determine whether a particular identifier might be the name in a C++1z
+  /// deduction-guide declaration.
+  bool isDeductionGuideName(Scope *S, const IdentifierInfo &Name,
+                            SourceLocation NameLoc, CXXScopeSpec &SS,
+                            ParsedTemplateTy *Template = nullptr);
 
-    ConstraintEvalRAII(InstTy &TI)
-        : TI(TI), OldValue(TI.getEvaluateConstraints()) {
-      TI.setEvaluateConstraints(false);
-    }
-    ~ConstraintEvalRAII() { TI.setEvaluateConstraints(OldValue); }
-  };
+  bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
+                                   SourceLocation IILoc, Scope *S,
+                                   const CXXScopeSpec *SS,
+                                   TemplateTy &SuggestedTemplate,
+                                   TemplateNameKind &SuggestedKind);
 
-  // Must be used instead of SubstExpr at 'constraint checking' time.
-  ExprResult
-  SubstConstraintExpr(Expr *E,
-                      const MultiLevelTemplateArgumentList &TemplateArgs);
-  // Unlike the above, this does not evaluates constraints.
-  ExprResult SubstConstraintExprWithoutSatisfaction(
-      Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs);
+  bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
+                                      NamedDecl *Instantiation,
+                                      bool InstantiatedFromMember,
+                                      const NamedDecl *Pattern,
+                                      const NamedDecl *PatternDef,
+                                      TemplateSpecializationKind TSK,
+                                      bool Complain = true);
 
-  /// Substitute the given template arguments into a list of
-  /// expressions, expanding pack expansions if required.
-  ///
-  /// \param Exprs The list of expressions to substitute into.
-  ///
-  /// \param IsCall Whether this is some form of call, in which case
-  /// default arguments will be dropped.
+  /// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
+  /// that the template parameter 'PrevDecl' is being shadowed by a new
+  /// declaration at location Loc. Returns true to indicate that this is
+  /// an error, and false otherwise.
   ///
-  /// \param TemplateArgs The set of template arguments to substitute.
+  /// \param Loc The location of the declaration that shadows a template
+  ///            parameter.
   ///
-  /// \param Outputs Will receive all of the substituted arguments.
+  /// \param PrevDecl The template parameter that the declaration shadows.
   ///
-  /// \returns true if an error occurred, false otherwise.
-  bool SubstExprs(ArrayRef Exprs, bool IsCall,
-                  const MultiLevelTemplateArgumentList &TemplateArgs,
-                  SmallVectorImpl &Outputs);
-
-  StmtResult SubstStmt(Stmt *S,
-                       const MultiLevelTemplateArgumentList &TemplateArgs);
+  /// \param SupportedForCompatibility Whether to issue the diagnostic as
+  ///        a warning for compatibility with older versions of clang.
+  ///        Ignored when MSVC compatibility is enabled.
+  void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl,
+                                       bool SupportedForCompatibility = false);
+  TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
 
-  TemplateParameterList *
-  SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner,
-                      const MultiLevelTemplateArgumentList &TemplateArgs,
-                      bool EvaluateConstraints = true);
+  NamedDecl *ActOnTypeParameter(Scope *S, bool Typename,
+                                SourceLocation EllipsisLoc,
+                                SourceLocation KeyLoc,
+                                IdentifierInfo *ParamName,
+                                SourceLocation ParamNameLoc, unsigned Depth,
+                                unsigned Position, SourceLocation EqualLoc,
+                                ParsedType DefaultArg, bool HasTypeConstraint);
 
-  bool
-  SubstTemplateArguments(ArrayRef Args,
-                         const MultiLevelTemplateArgumentList &TemplateArgs,
-                         TemplateArgumentListInfo &Outputs);
+  bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint);
 
-  Decl *SubstDecl(Decl *D, DeclContext *Owner,
-                  const MultiLevelTemplateArgumentList &TemplateArgs);
+  bool ActOnTypeConstraint(const CXXScopeSpec &SS,
+                           TemplateIdAnnotation *TypeConstraint,
+                           TemplateTypeParmDecl *ConstrainedParameter,
+                           SourceLocation EllipsisLoc);
+  bool BuildTypeConstraint(const CXXScopeSpec &SS,
+                           TemplateIdAnnotation *TypeConstraint,
+                           TemplateTypeParmDecl *ConstrainedParameter,
+                           SourceLocation EllipsisLoc,
+                           bool AllowUnexpandedPack);
 
-  /// Substitute the name and return type of a defaulted 'operator<=>' to form
-  /// an implicit 'operator=='.
-  FunctionDecl *SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD,
-                                           FunctionDecl *Spaceship);
+  bool AttachTypeConstraint(NestedNameSpecifierLoc NS,
+                            DeclarationNameInfo NameInfo,
+                            ConceptDecl *NamedConcept,
+                            const TemplateArgumentListInfo *TemplateArgs,
+                            TemplateTypeParmDecl *ConstrainedParameter,
+                            SourceLocation EllipsisLoc);
 
-  ExprResult SubstInitializer(Expr *E,
-                       const MultiLevelTemplateArgumentList &TemplateArgs,
-                       bool CXXDirectInit);
+  bool AttachTypeConstraint(AutoTypeLoc TL,
+                            NonTypeTemplateParmDecl *NewConstrainedParm,
+                            NonTypeTemplateParmDecl *OrigConstrainedParm,
+                            SourceLocation EllipsisLoc);
 
-  bool
-  SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
-                      CXXRecordDecl *Pattern,
-                      const MultiLevelTemplateArgumentList &TemplateArgs);
+  bool RequireStructuralType(QualType T, SourceLocation Loc);
 
-  bool
-  InstantiateClass(SourceLocation PointOfInstantiation,
-                   CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
-                   const MultiLevelTemplateArgumentList &TemplateArgs,
-                   TemplateSpecializationKind TSK,
-                   bool Complain = true);
+  QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
+                                             SourceLocation Loc);
+  QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
 
-  bool InstantiateEnum(SourceLocation PointOfInstantiation,
-                       EnumDecl *Instantiation, EnumDecl *Pattern,
-                       const MultiLevelTemplateArgumentList &TemplateArgs,
-                       TemplateSpecializationKind TSK);
+  NamedDecl *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+                                           unsigned Depth, unsigned Position,
+                                           SourceLocation EqualLoc,
+                                           Expr *DefaultArg);
+  NamedDecl *ActOnTemplateTemplateParameter(
+      Scope *S, SourceLocation TmpLoc, TemplateParameterList *Params,
+      SourceLocation EllipsisLoc, IdentifierInfo *ParamName,
+      SourceLocation ParamNameLoc, unsigned Depth, unsigned Position,
+      SourceLocation EqualLoc, ParsedTemplateArgument DefaultArg);
+
+  TemplateParameterList *ActOnTemplateParameterList(
+      unsigned Depth, SourceLocation ExportLoc, SourceLocation TemplateLoc,
+      SourceLocation LAngleLoc, ArrayRef Params,
+      SourceLocation RAngleLoc, Expr *RequiresClause);
 
-  bool InstantiateInClassInitializer(
-      SourceLocation PointOfInstantiation, FieldDecl *Instantiation,
-      FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs);
+  /// The context in which we are checking a template parameter list.
+  enum TemplateParamListContext {
+    TPC_ClassTemplate,
+    TPC_VarTemplate,
+    TPC_FunctionTemplate,
+    TPC_ClassTemplateMember,
+    TPC_FriendClassTemplate,
+    TPC_FriendFunctionTemplate,
+    TPC_FriendFunctionTemplateDefinition,
+    TPC_TypeAliasTemplate
+  };
 
-  struct LateInstantiatedAttribute {
-    const Attr *TmplAttr;
-    LocalInstantiationScope *Scope;
-    Decl *NewDecl;
-
-    LateInstantiatedAttribute(const Attr *A, LocalInstantiationScope *S,
-                              Decl *D)
-      : TmplAttr(A), Scope(S), NewDecl(D)
-    { }
-  };
-  typedef SmallVector LateInstantiatedAttrVec;
-
-  void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
-                        const Decl *Pattern, Decl *Inst,
-                        LateInstantiatedAttrVec *LateAttrs = nullptr,
-                        LocalInstantiationScope *OuterMostScope = nullptr);
-  void updateAttrsForLateParsedTemplate(const Decl *Pattern, Decl *Inst);
+  bool CheckTemplateParameterList(TemplateParameterList *NewParams,
+                                  TemplateParameterList *OldParams,
+                                  TemplateParamListContext TPC,
+                                  SkipBodyInfo *SkipBody = nullptr);
+  TemplateParameterList *MatchTemplateParametersToScopeSpecifier(
+      SourceLocation DeclStartLoc, SourceLocation DeclLoc,
+      const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId,
+      ArrayRef ParamLists, bool IsFriend,
+      bool &IsMemberSpecialization, bool &Invalid,
+      bool SuppressDiagnostic = false);
 
-  void
-  InstantiateAttrsForDecl(const MultiLevelTemplateArgumentList &TemplateArgs,
-                          const Decl *Pattern, Decl *Inst,
-                          LateInstantiatedAttrVec *LateAttrs = nullptr,
-                          LocalInstantiationScope *OuterMostScope = nullptr);
+  DeclResult CheckClassTemplate(
+      Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
+      CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
+      const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
+      AccessSpecifier AS, SourceLocation ModulePrivateLoc,
+      SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists,
+      TemplateParameterList **OuterTemplateParamLists,
+      SkipBodyInfo *SkipBody = nullptr);
 
-  void InstantiateDefaultCtorDefaultArgs(CXXConstructorDecl *Ctor);
+  void translateTemplateArguments(const ASTTemplateArgsPtr &In,
+                                  TemplateArgumentListInfo &Out);
 
-  bool usesPartialOrExplicitSpecialization(
-      SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec);
+  ParsedTemplateArgument ActOnTemplateTypeArgument(TypeResult ParsedType);
 
-  bool
-  InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
-                           ClassTemplateSpecializationDecl *ClassTemplateSpec,
-                           TemplateSpecializationKind TSK,
-                           bool Complain = true);
+  void NoteAllFoundTemplates(TemplateName Name);
 
-  void InstantiateClassMembers(SourceLocation PointOfInstantiation,
-                               CXXRecordDecl *Instantiation,
-                            const MultiLevelTemplateArgumentList &TemplateArgs,
-                               TemplateSpecializationKind TSK);
+  QualType CheckTemplateIdType(TemplateName Template,
+                               SourceLocation TemplateLoc,
+                               TemplateArgumentListInfo &TemplateArgs);
 
-  void InstantiateClassTemplateSpecializationMembers(
-                                          SourceLocation PointOfInstantiation,
-                           ClassTemplateSpecializationDecl *ClassTemplateSpec,
-                                                TemplateSpecializationKind TSK);
+  TypeResult
+  ActOnTemplateIdType(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+                      TemplateTy Template, IdentifierInfo *TemplateII,
+                      SourceLocation TemplateIILoc, SourceLocation LAngleLoc,
+                      ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc,
+                      bool IsCtorOrDtorName = false, bool IsClassName = false,
+                      ImplicitTypenameContext AllowImplicitTypename =
+                          ImplicitTypenameContext::No);
 
-  NestedNameSpecifierLoc
-  SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
-                           const MultiLevelTemplateArgumentList &TemplateArgs);
+  /// Parsed an elaborated-type-specifier that refers to a template-id,
+  /// such as \c class T::template apply.
+  TypeResult ActOnTagTemplateIdType(
+      TagUseKind TUK, TypeSpecifierType TagSpec, SourceLocation TagLoc,
+      CXXScopeSpec &SS, SourceLocation TemplateKWLoc, TemplateTy TemplateD,
+      SourceLocation TemplateLoc, SourceLocation LAngleLoc,
+      ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc);
 
-  DeclarationNameInfo
-  SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
-                           const MultiLevelTemplateArgumentList &TemplateArgs);
-  TemplateName
-  SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name,
-                    SourceLocation Loc,
-                    const MultiLevelTemplateArgumentList &TemplateArgs);
+  DeclResult ActOnVarTemplateSpecialization(
+      Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
+      SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
+      StorageClass SC, bool IsPartialSpecialization);
 
-  bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint *TC,
-                           const MultiLevelTemplateArgumentList &TemplateArgs,
-                           bool EvaluateConstraint);
+  /// Get the specialization of the given variable template corresponding to
+  /// the specified argument list, or a null-but-valid result if the arguments
+  /// are dependent.
+  DeclResult CheckVarTemplateId(VarTemplateDecl *Template,
+                                SourceLocation TemplateLoc,
+                                SourceLocation TemplateNameLoc,
+                                const TemplateArgumentListInfo &TemplateArgs);
 
-  bool InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
-                                  ParmVarDecl *Param);
-  void InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
-                                FunctionDecl *Function);
-  bool CheckInstantiatedFunctionTemplateConstraints(
-      SourceLocation PointOfInstantiation, FunctionDecl *Decl,
-      ArrayRef TemplateArgs,
-      ConstraintSatisfaction &Satisfaction);
-  FunctionDecl *InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
-                                               const TemplateArgumentList *Args,
-                                               SourceLocation Loc);
-  void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
-                                     FunctionDecl *Function,
-                                     bool Recursive = false,
-                                     bool DefinitionRequired = false,
-                                     bool AtEndOfTU = false);
-  VarTemplateSpecializationDecl *BuildVarTemplateInstantiation(
-      VarTemplateDecl *VarTemplate, VarDecl *FromVar,
-      const TemplateArgumentList *PartialSpecArgs,
-      const TemplateArgumentListInfo &TemplateArgsInfo,
-      SmallVectorImpl &Converted,
-      SourceLocation PointOfInstantiation,
-      LateInstantiatedAttrVec *LateAttrs = nullptr,
-      LocalInstantiationScope *StartingScope = nullptr);
-  VarTemplateSpecializationDecl *CompleteVarTemplateSpecializationDecl(
-      VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl,
-      const MultiLevelTemplateArgumentList &TemplateArgs);
-  void
-  BuildVariableInstantiation(VarDecl *NewVar, VarDecl *OldVar,
-                             const MultiLevelTemplateArgumentList &TemplateArgs,
-                             LateInstantiatedAttrVec *LateAttrs,
-                             DeclContext *Owner,
-                             LocalInstantiationScope *StartingScope,
-                             bool InstantiatingVarTemplate = false,
-                             VarTemplateSpecializationDecl *PrevVTSD = nullptr);
+  /// Form a reference to the specialization of the given variable template
+  /// corresponding to the specified argument list, or a null-but-valid result
+  /// if the arguments are dependent.
+  ExprResult CheckVarTemplateId(const CXXScopeSpec &SS,
+                                const DeclarationNameInfo &NameInfo,
+                                VarTemplateDecl *Template, NamedDecl *FoundD,
+                                SourceLocation TemplateLoc,
+                                const TemplateArgumentListInfo *TemplateArgs);
 
-  void InstantiateVariableInitializer(
-      VarDecl *Var, VarDecl *OldVar,
-      const MultiLevelTemplateArgumentList &TemplateArgs);
-  void InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
-                                     VarDecl *Var, bool Recursive = false,
-                                     bool DefinitionRequired = false,
-                                     bool AtEndOfTU = false);
+  ExprResult
+  CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+                         const DeclarationNameInfo &ConceptNameInfo,
+                         NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
+                         const TemplateArgumentListInfo *TemplateArgs);
 
-  void InstantiateMemInitializers(CXXConstructorDecl *New,
-                                  const CXXConstructorDecl *Tmpl,
-                            const MultiLevelTemplateArgumentList &TemplateArgs);
+  void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
 
-  ExplicitSpecifier instantiateExplicitSpecifier(
-      const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier ES);
+  ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
+                                 SourceLocation TemplateKWLoc, LookupResult &R,
+                                 bool RequiresADL,
+                                 const TemplateArgumentListInfo *TemplateArgs);
 
-  NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
-                          const MultiLevelTemplateArgumentList &TemplateArgs,
-                          bool FindingInstantiatedContext = false);
-  DeclContext *FindInstantiatedContext(SourceLocation Loc, DeclContext *DC,
-                          const MultiLevelTemplateArgumentList &TemplateArgs);
+  ExprResult
+  BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+                               const DeclarationNameInfo &NameInfo,
+                               const TemplateArgumentListInfo *TemplateArgs);
 
-  // Objective-C declarations.
-  enum ObjCContainerKind {
-    OCK_None = -1,
-    OCK_Interface = 0,
-    OCK_Protocol,
-    OCK_Category,
-    OCK_ClassExtension,
-    OCK_Implementation,
-    OCK_CategoryImplementation
-  };
-  ObjCContainerKind getObjCContainerKind() const;
+  TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec &SS,
+                                     SourceLocation TemplateKWLoc,
+                                     const UnqualifiedId &Name,
+                                     ParsedType ObjectType,
+                                     bool EnteringContext, TemplateTy &Template,
+                                     bool AllowInjectedClassName = false);
 
-  DeclResult actOnObjCTypeParam(Scope *S,
-                                ObjCTypeParamVariance variance,
-                                SourceLocation varianceLoc,
-                                unsigned index,
-                                IdentifierInfo *paramName,
-                                SourceLocation paramLoc,
-                                SourceLocation colonLoc,
-                                ParsedType typeBound);
+  DeclResult ActOnClassTemplateSpecialization(
+      Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
+      SourceLocation ModulePrivateLoc, CXXScopeSpec &SS,
+      TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr,
+      MultiTemplateParamsArg TemplateParameterLists,
+      SkipBodyInfo *SkipBody = nullptr);
 
-  ObjCTypeParamList *actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc,
-                                            ArrayRef typeParams,
-                                            SourceLocation rAngleLoc);
-  void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList);
+  bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc,
+                                              TemplateDecl *PrimaryTemplate,
+                                              unsigned NumExplicitArgs,
+                                              ArrayRef Args);
+  void CheckTemplatePartialSpecialization(
+      ClassTemplatePartialSpecializationDecl *Partial);
+  void CheckTemplatePartialSpecialization(
+      VarTemplatePartialSpecializationDecl *Partial);
 
-  ObjCInterfaceDecl *ActOnStartClassInterface(
-      Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName,
-      SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,
-      IdentifierInfo *SuperName, SourceLocation SuperLoc,
-      ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange,
-      Decl *const *ProtoRefs, unsigned NumProtoRefs,
-      const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
-      const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody);
+  Decl *ActOnTemplateDeclarator(Scope *S,
+                                MultiTemplateParamsArg TemplateParameterLists,
+                                Declarator &D);
 
-  void ActOnSuperClassOfClassInterface(Scope *S,
-                                       SourceLocation AtInterfaceLoc,
-                                       ObjCInterfaceDecl *IDecl,
-                                       IdentifierInfo *ClassName,
-                                       SourceLocation ClassLoc,
-                                       IdentifierInfo *SuperName,
-                                       SourceLocation SuperLoc,
-                                       ArrayRef SuperTypeArgs,
-                                       SourceRange SuperTypeArgsRange);
+  bool CheckSpecializationInstantiationRedecl(
+      SourceLocation NewLoc,
+      TemplateSpecializationKind ActOnExplicitInstantiationNewTSK,
+      NamedDecl *PrevDecl, TemplateSpecializationKind PrevTSK,
+      SourceLocation PrevPtOfInstantiation, bool &SuppressNew);
 
-  void ActOnTypedefedProtocols(SmallVectorImpl &ProtocolRefs,
-                               SmallVectorImpl &ProtocolLocs,
-                               IdentifierInfo *SuperName,
-                               SourceLocation SuperLoc);
+  bool CheckDependentFunctionTemplateSpecialization(
+      FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
+      LookupResult &Previous);
 
-  Decl *ActOnCompatibilityAlias(
-                    SourceLocation AtCompatibilityAliasLoc,
-                    IdentifierInfo *AliasName,  SourceLocation AliasLocation,
-                    IdentifierInfo *ClassName, SourceLocation ClassLocation);
+  bool CheckFunctionTemplateSpecialization(
+      FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
+      LookupResult &Previous, bool QualifiedFriend = false);
+  bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
+  void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
 
-  bool CheckForwardProtocolDeclarationForCircularDependency(
-    IdentifierInfo *PName,
-    SourceLocation &PLoc, SourceLocation PrevLoc,
-    const ObjCList &PList);
+  DeclResult ActOnExplicitInstantiation(
+      Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc,
+      unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS,
+      TemplateTy Template, SourceLocation TemplateNameLoc,
+      SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs,
+      SourceLocation RAngleLoc, const ParsedAttributesView &Attr);
 
-  ObjCProtocolDecl *ActOnStartProtocolInterface(
-      SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,
-      SourceLocation ProtocolLoc, Decl *const *ProtoRefNames,
-      unsigned NumProtoRefs, const SourceLocation *ProtoLocs,
-      SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList,
-      SkipBodyInfo *SkipBody);
+  DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
+                                        SourceLocation TemplateLoc,
+                                        unsigned TagSpec, SourceLocation KWLoc,
+                                        CXXScopeSpec &SS, IdentifierInfo *Name,
+                                        SourceLocation NameLoc,
+                                        const ParsedAttributesView &Attr);
 
-  ObjCCategoryDecl *ActOnStartCategoryInterface(
-      SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName,
-      SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,
-      IdentifierInfo *CategoryName, SourceLocation CategoryLoc,
-      Decl *const *ProtoRefs, unsigned NumProtoRefs,
-      const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
-      const ParsedAttributesView &AttrList);
+  DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
+                                        SourceLocation TemplateLoc,
+                                        Declarator &D);
 
-  ObjCImplementationDecl *ActOnStartClassImplementation(
-      SourceLocation AtClassImplLoc, IdentifierInfo *ClassName,
-      SourceLocation ClassLoc, IdentifierInfo *SuperClassname,
-      SourceLocation SuperClassLoc, const ParsedAttributesView &AttrList);
+  TemplateArgumentLoc SubstDefaultTemplateArgumentIfAvailable(
+      TemplateDecl *Template, SourceLocation TemplateLoc,
+      SourceLocation RAngleLoc, Decl *Param,
+      ArrayRef SugaredConverted,
+      ArrayRef CanonicalConverted, bool &HasDefaultArg);
 
-  ObjCCategoryImplDecl *ActOnStartCategoryImplementation(
-      SourceLocation AtCatImplLoc, IdentifierInfo *ClassName,
-      SourceLocation ClassLoc, IdentifierInfo *CatName, SourceLocation CatLoc,
-      const ParsedAttributesView &AttrList);
+  SourceLocation getTopMostPointOfInstantiation(const NamedDecl *) const;
 
-  DeclGroupPtrTy ActOnFinishObjCImplementation(Decl *ObjCImpDecl,
-                                               ArrayRef Decls);
+  /// Specifies the context in which a particular template
+  /// argument is being checked.
+  enum CheckTemplateArgumentKind {
+    /// The template argument was specified in the code or was
+    /// instantiated with some deduced template arguments.
+    CTAK_Specified,
 
-  DeclGroupPtrTy ActOnForwardClassDeclaration(SourceLocation Loc,
-                   IdentifierInfo **IdentList,
-                   SourceLocation *IdentLocs,
-                   ArrayRef TypeParamLists,
-                   unsigned NumElts);
+    /// The template argument was deduced via template argument
+    /// deduction.
+    CTAK_Deduced,
 
-  DeclGroupPtrTy
-  ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
-                                  ArrayRef IdentList,
-                                  const ParsedAttributesView &attrList);
+    /// The template argument was deduced from an array bound
+    /// via template argument deduction.
+    CTAK_DeducedFromArrayBound
+  };
 
-  void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
-                               ArrayRef ProtocolId,
-                               SmallVectorImpl &Protocols);
+  bool
+  CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &Arg,
+                        NamedDecl *Template, SourceLocation TemplateLoc,
+                        SourceLocation RAngleLoc, unsigned ArgumentPackIndex,
+                        SmallVectorImpl &SugaredConverted,
+                        SmallVectorImpl &CanonicalConverted,
+                        CheckTemplateArgumentKind CTAK);
 
-  void DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId,
-                                    SourceLocation ProtocolLoc,
-                                    IdentifierInfo *TypeArgId,
-                                    SourceLocation TypeArgLoc,
-                                    bool SelectProtocolFirst = false);
+  /// Check that the given template arguments can be provided to
+  /// the given template, converting the arguments along the way.
+  ///
+  /// \param Template The template to which the template arguments are being
+  /// provided.
+  ///
+  /// \param TemplateLoc The location of the template name in the source.
+  ///
+  /// \param TemplateArgs The list of template arguments. If the template is
+  /// a template template parameter, this function may extend the set of
+  /// template arguments to also include substituted, defaulted template
+  /// arguments.
+  ///
+  /// \param PartialTemplateArgs True if the list of template arguments is
+  /// intentionally partial, e.g., because we're checking just the initial
+  /// set of template arguments.
+  ///
+  /// \param Converted Will receive the converted, canonicalized template
+  /// arguments.
+  ///
+  /// \param UpdateArgsWithConversions If \c true, update \p TemplateArgs to
+  /// contain the converted forms of the template arguments as written.
+  /// Otherwise, \p TemplateArgs will not be modified.
+  ///
+  /// \param ConstraintsNotSatisfied If provided, and an error occurred, will
+  /// receive true if the cause for the error is the associated constraints of
+  /// the template not being satisfied by the template arguments.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool CheckTemplateArgumentList(
+      TemplateDecl *Template, SourceLocation TemplateLoc,
+      TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs,
+      SmallVectorImpl &SugaredConverted,
+      SmallVectorImpl &CanonicalConverted,
+      bool UpdateArgsWithConversions = true,
+      bool *ConstraintsNotSatisfied = nullptr);
 
-  /// Given a list of identifiers (and their locations), resolve the
-  /// names to either Objective-C protocol qualifiers or type
-  /// arguments, as appropriate.
-  void actOnObjCTypeArgsOrProtocolQualifiers(
-         Scope *S,
-         ParsedType baseType,
-         SourceLocation lAngleLoc,
-         ArrayRef identifiers,
-         ArrayRef identifierLocs,
-         SourceLocation rAngleLoc,
-         SourceLocation &typeArgsLAngleLoc,
-         SmallVectorImpl &typeArgs,
-         SourceLocation &typeArgsRAngleLoc,
-         SourceLocation &protocolLAngleLoc,
-         SmallVectorImpl &protocols,
-         SourceLocation &protocolRAngleLoc,
-         bool warnOnIncompleteProtocols);
+  bool CheckTemplateTypeArgument(
+      TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
+      SmallVectorImpl &SugaredConverted,
+      SmallVectorImpl &CanonicalConverted);
 
-  /// Build a an Objective-C protocol-qualified 'id' type where no
-  /// base type was specified.
-  TypeResult actOnObjCProtocolQualifierType(
-               SourceLocation lAngleLoc,
-               ArrayRef protocols,
-               ArrayRef protocolLocs,
-               SourceLocation rAngleLoc);
+  bool CheckTemplateArgument(TypeSourceInfo *Arg);
+  ExprResult CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
+                                   QualType InstantiatedParamType, Expr *Arg,
+                                   TemplateArgument &SugaredConverted,
+                                   TemplateArgument &CanonicalConverted,
+                                   CheckTemplateArgumentKind CTAK);
+  bool CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param,
+                                     TemplateParameterList *Params,
+                                     TemplateArgumentLoc &Arg);
 
-  /// Build a specialized and/or protocol-qualified Objective-C type.
-  TypeResult actOnObjCTypeArgsAndProtocolQualifiers(
-               Scope *S,
-               SourceLocation Loc,
-               ParsedType BaseType,
-               SourceLocation TypeArgsLAngleLoc,
-               ArrayRef TypeArgs,
-               SourceLocation TypeArgsRAngleLoc,
-               SourceLocation ProtocolLAngleLoc,
-               ArrayRef Protocols,
-               ArrayRef ProtocolLocs,
-               SourceLocation ProtocolRAngleLoc);
+  void NoteTemplateLocation(const NamedDecl &Decl,
+                            std::optional ParamRange = {});
+  void NoteTemplateParameterLocation(const NamedDecl &Decl);
 
-  /// Build an Objective-C type parameter type.
-  QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
-                                  SourceLocation ProtocolLAngleLoc,
-                                  ArrayRef Protocols,
-                                  ArrayRef ProtocolLocs,
-                                  SourceLocation ProtocolRAngleLoc,
-                                  bool FailOnError = false);
+  ExprResult BuildExpressionFromDeclTemplateArgument(
+      const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc);
+  ExprResult
+  BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
+                                             SourceLocation Loc);
 
-  /// Build an Objective-C object pointer type.
-  QualType BuildObjCObjectType(
-      QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc,
-      ArrayRef TypeArgs, SourceLocation TypeArgsRAngleLoc,
-      SourceLocation ProtocolLAngleLoc, ArrayRef Protocols,
-      ArrayRef ProtocolLocs, SourceLocation ProtocolRAngleLoc,
-      bool FailOnError, bool Rebuilding);
+  /// Enumeration describing how template parameter lists are compared
+  /// for equality.
+  enum TemplateParameterListEqualKind {
+    /// We are matching the template parameter lists of two templates
+    /// that might be redeclarations.
+    ///
+    /// \code
+    /// template struct X;
+    /// template struct X;
+    /// \endcode
+    TPL_TemplateMatch,
 
-  /// Ensure attributes are consistent with type.
-  /// \param [in, out] Attributes The attributes to check; they will
-  /// be modified to be consistent with \p PropertyTy.
-  void CheckObjCPropertyAttributes(Decl *PropertyPtrTy,
-                                   SourceLocation Loc,
-                                   unsigned &Attributes,
-                                   bool propertyInPrimaryClass);
+    /// We are matching the template parameter lists of two template
+    /// template parameters as part of matching the template parameter lists
+    /// of two templates that might be redeclarations.
+    ///
+    /// \code
+    /// template class TT> struct X;
+    /// template class Other> struct X;
+    /// \endcode
+    TPL_TemplateTemplateParmMatch,
 
-  /// Process the specified property declaration and create decls for the
-  /// setters and getters as needed.
-  /// \param property The property declaration being processed
-  void ProcessPropertyDecl(ObjCPropertyDecl *property);
+    /// We are matching the template parameter lists of a template
+    /// template argument against the template parameter lists of a template
+    /// template parameter.
+    ///
+    /// \code
+    /// template class Metafun> struct X;
+    /// template struct integer_c;
+    /// X xic;
+    /// \endcode
+    TPL_TemplateTemplateArgumentMatch,
 
+    /// We are determining whether the template-parameters are equivalent
+    /// according to C++ [temp.over.link]/6. This comparison does not consider
+    /// constraints.
+    ///
+    /// \code
+    /// template void f(T);
+    /// template void f(T);
+    /// \endcode
+    TPL_TemplateParamsEquivalent,
+  };
 
-  void DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
-                                ObjCPropertyDecl *SuperProperty,
-                                const IdentifierInfo *Name,
-                                bool OverridingProtocolProperty);
+  // A struct to represent the 'new' declaration, which is either itself just
+  // the named decl, or the important information we need about it in order to
+  // do constraint comparisons.
+  class TemplateCompareNewDeclInfo {
+    const NamedDecl *ND = nullptr;
+    const DeclContext *DC = nullptr;
+    const DeclContext *LexicalDC = nullptr;
+    SourceLocation Loc;
 
-  void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
-                                        ObjCInterfaceDecl *ID);
+  public:
+    TemplateCompareNewDeclInfo(const NamedDecl *ND) : ND(ND) {}
+    TemplateCompareNewDeclInfo(const DeclContext *DeclCtx,
+                               const DeclContext *LexicalDeclCtx,
+                               SourceLocation Loc)
 
-  Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd,
-                   ArrayRef allMethods = std::nullopt,
-                   ArrayRef allTUVars = std::nullopt);
+        : DC(DeclCtx), LexicalDC(LexicalDeclCtx), Loc(Loc) {
+      assert(DC && LexicalDC &&
+             "Constructor only for cases where we have the information to put "
+             "in here");
+    }
 
-  Decl *ActOnProperty(Scope *S, SourceLocation AtLoc,
-                      SourceLocation LParenLoc,
-                      FieldDeclarator &FD, ObjCDeclSpec &ODS,
-                      Selector GetterSel, Selector SetterSel,
-                      tok::ObjCKeywordKind MethodImplKind,
-                      DeclContext *lexicalDC = nullptr);
+    // If this was constructed with no information, we cannot do substitution
+    // for constraint comparison, so make sure we can check that.
+    bool isInvalid() const { return !ND && !DC; }
 
-  Decl *ActOnPropertyImplDecl(Scope *S,
-                              SourceLocation AtLoc,
-                              SourceLocation PropertyLoc,
-                              bool ImplKind,
-                              IdentifierInfo *PropertyId,
-                              IdentifierInfo *PropertyIvar,
-                              SourceLocation PropertyIvarLoc,
-                              ObjCPropertyQueryKind QueryKind);
+    const NamedDecl *getDecl() const { return ND; }
 
-  enum ObjCSpecialMethodKind {
-    OSMK_None,
-    OSMK_Alloc,
-    OSMK_New,
-    OSMK_Copy,
-    OSMK_RetainingInit,
-    OSMK_NonRetainingInit
-  };
+    bool ContainsDecl(const NamedDecl *ND) const { return this->ND == ND; }
 
-  struct ObjCArgInfo {
-    IdentifierInfo *Name;
-    SourceLocation NameLoc;
-    // The Type is null if no type was specified, and the DeclSpec is invalid
-    // in this case.
-    ParsedType Type;
-    ObjCDeclSpec DeclSpec;
+    const DeclContext *getLexicalDeclContext() const {
+      return ND ? ND->getLexicalDeclContext() : LexicalDC;
+    }
 
-    /// ArgAttrs - Attribute list for this argument.
-    ParsedAttributesView ArgAttrs;
-  };
+    const DeclContext *getDeclContext() const {
+      return ND ? ND->getDeclContext() : DC;
+    }
 
-  Decl *ActOnMethodDeclaration(
-      Scope *S,
-      SourceLocation BeginLoc, // location of the + or -.
-      SourceLocation EndLoc,   // location of the ; or {.
-      tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
-      ArrayRef SelectorLocs, Selector Sel,
-      // optional arguments. The number of types/arguments is obtained
-      // from the Sel.getNumArgs().
-      ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo,
-      unsigned CNumArgs, // c-style args
-      const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodImplKind,
-      bool isVariadic, bool MethodDefinition);
+    SourceLocation getLocation() const { return ND ? ND->getLocation() : Loc; }
+  };
 
-  ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel,
-                                              const ObjCObjectPointerType *OPT,
-                                              bool IsInstance);
-  ObjCMethodDecl *LookupMethodInObjectType(Selector Sel, QualType Ty,
-                                           bool IsInstance);
+  bool TemplateParameterListsAreEqual(
+      const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New,
+      const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain,
+      TemplateParameterListEqualKind Kind,
+      SourceLocation TemplateArgLoc = SourceLocation());
 
-  bool CheckARCMethodDecl(ObjCMethodDecl *method);
-  bool inferObjCARCLifetime(ValueDecl *decl);
+  bool TemplateParameterListsAreEqual(
+      TemplateParameterList *New, TemplateParameterList *Old, bool Complain,
+      TemplateParameterListEqualKind Kind,
+      SourceLocation TemplateArgLoc = SourceLocation()) {
+    return TemplateParameterListsAreEqual(nullptr, New, nullptr, Old, Complain,
+                                          Kind, TemplateArgLoc);
+  }
 
-  void deduceOpenCLAddressSpace(ValueDecl *decl);
+  bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams);
 
-  ExprResult
-  HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
-                            Expr *BaseExpr,
-                            SourceLocation OpLoc,
-                            DeclarationName MemberName,
-                            SourceLocation MemberLoc,
-                            SourceLocation SuperLoc, QualType SuperType,
-                            bool Super);
+  /// Called when the parser has parsed a C++ typename
+  /// specifier, e.g., "typename T::type".
+  ///
+  /// \param S The scope in which this typename type occurs.
+  /// \param TypenameLoc the location of the 'typename' keyword
+  /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
+  /// \param II the identifier we're retrieving (e.g., 'type' in the example).
+  /// \param IdLoc the location of the identifier.
+  /// \param IsImplicitTypename context where T::type refers to a type.
+  TypeResult ActOnTypenameType(
+      Scope *S, SourceLocation TypenameLoc, const CXXScopeSpec &SS,
+      const IdentifierInfo &II, SourceLocation IdLoc,
+      ImplicitTypenameContext IsImplicitTypename = ImplicitTypenameContext::No);
 
-  ExprResult
-  ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
-                            IdentifierInfo &propertyName,
-                            SourceLocation receiverNameLoc,
-                            SourceLocation propertyNameLoc);
+  /// Called when the parser has parsed a C++ typename
+  /// specifier that ends in a template-id, e.g.,
+  /// "typename MetaFun::template apply".
+  ///
+  /// \param S The scope in which this typename type occurs.
+  /// \param TypenameLoc the location of the 'typename' keyword
+  /// \param SS the nested-name-specifier following the typename (e.g., 'T::').
+  /// \param TemplateLoc the location of the 'template' keyword, if any.
+  /// \param TemplateName The template name.
+  /// \param TemplateII The identifier used to name the template.
+  /// \param TemplateIILoc The location of the template name.
+  /// \param LAngleLoc The location of the opening angle bracket  ('<').
+  /// \param TemplateArgs The template arguments.
+  /// \param RAngleLoc The location of the closing angle bracket  ('>').
+  TypeResult
+  ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
+                    const CXXScopeSpec &SS, SourceLocation TemplateLoc,
+                    TemplateTy TemplateName, IdentifierInfo *TemplateII,
+                    SourceLocation TemplateIILoc, SourceLocation LAngleLoc,
+                    ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc);
 
-  ObjCMethodDecl *tryCaptureObjCSelf(SourceLocation Loc);
+  QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
+                             SourceLocation KeywordLoc,
+                             NestedNameSpecifierLoc QualifierLoc,
+                             const IdentifierInfo &II, SourceLocation IILoc,
+                             TypeSourceInfo **TSI, bool DeducedTSTContext);
 
-  /// Describes the kind of message expression indicated by a message
-  /// send that starts with an identifier.
-  enum ObjCMessageKind {
-    /// The message is sent to 'super'.
-    ObjCSuperMessage,
-    /// The message is an instance message.
-    ObjCInstanceMessage,
-    /// The message is a class message, and the identifier is a type
-    /// name.
-    ObjCClassMessage
-  };
+  QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
+                             SourceLocation KeywordLoc,
+                             NestedNameSpecifierLoc QualifierLoc,
+                             const IdentifierInfo &II, SourceLocation IILoc,
+                             bool DeducedTSTContext = true);
 
-  ObjCMessageKind getObjCMessageKind(Scope *S,
-                                     IdentifierInfo *Name,
-                                     SourceLocation NameLoc,
-                                     bool IsSuper,
-                                     bool HasTrailingDot,
-                                     ParsedType &ReceiverType);
+  TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
+                                                    SourceLocation Loc,
+                                                    DeclarationName Name);
+  bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS);
 
-  ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
-                               Selector Sel,
-                               SourceLocation LBracLoc,
-                               ArrayRef SelectorLocs,
-                               SourceLocation RBracLoc,
-                               MultiExprArg Args);
+  ExprResult RebuildExprInCurrentInstantiation(Expr *E);
+  bool
+  RebuildTemplateParamsInCurrentInstantiation(TemplateParameterList *Params);
 
-  ExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
-                               QualType ReceiverType,
-                               SourceLocation SuperLoc,
-                               Selector Sel,
-                               ObjCMethodDecl *Method,
-                               SourceLocation LBracLoc,
-                               ArrayRef SelectorLocs,
-                               SourceLocation RBracLoc,
-                               MultiExprArg Args,
-                               bool isImplicit = false);
+  std::string
+  getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+                                  const TemplateArgumentList &Args);
 
-  ExprResult BuildClassMessageImplicit(QualType ReceiverType,
-                                       bool isSuperReceiver,
-                                       SourceLocation Loc,
-                                       Selector Sel,
-                                       ObjCMethodDecl *Method,
-                                       MultiExprArg Args);
+  std::string
+  getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+                                  const TemplateArgument *Args,
+                                  unsigned NumArgs);
 
-  ExprResult ActOnClassMessage(Scope *S,
-                               ParsedType Receiver,
-                               Selector Sel,
-                               SourceLocation LBracLoc,
-                               ArrayRef SelectorLocs,
-                               SourceLocation RBracLoc,
-                               MultiExprArg Args);
+  void diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,
+                                          SourceLocation Less,
+                                          SourceLocation Greater);
 
-  ExprResult BuildInstanceMessage(Expr *Receiver,
-                                  QualType ReceiverType,
-                                  SourceLocation SuperLoc,
-                                  Selector Sel,
-                                  ObjCMethodDecl *Method,
-                                  SourceLocation LBracLoc,
-                                  ArrayRef SelectorLocs,
-                                  SourceLocation RBracLoc,
-                                  MultiExprArg Args,
-                                  bool isImplicit = false);
+  ExprResult ActOnDependentIdExpression(
+      const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+      const DeclarationNameInfo &NameInfo, bool isAddressOfOperand,
+      const TemplateArgumentListInfo *TemplateArgs);
 
-  ExprResult BuildInstanceMessageImplicit(Expr *Receiver,
-                                          QualType ReceiverType,
-                                          SourceLocation Loc,
-                                          Selector Sel,
-                                          ObjCMethodDecl *Method,
-                                          MultiExprArg Args);
+  ExprResult
+  BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+                            SourceLocation TemplateKWLoc,
+                            const DeclarationNameInfo &NameInfo,
+                            const TemplateArgumentListInfo *TemplateArgs);
 
-  ExprResult ActOnInstanceMessage(Scope *S,
-                                  Expr *Receiver,
-                                  Selector Sel,
-                                  SourceLocation LBracLoc,
-                                  ArrayRef SelectorLocs,
-                                  SourceLocation RBracLoc,
-                                  MultiExprArg Args);
+  // Calculates whether the expression Constraint depends on an enclosing
+  // template, for the purposes of [temp.friend] p9.
+  // TemplateDepth is the 'depth' of the friend function, which is used to
+  // compare whether a declaration reference is referring to a containing
+  // template, or just the current friend function. A 'lower' TemplateDepth in
+  // the AST refers to a 'containing' template. As the constraint is
+  // uninstantiated, this is relative to the 'top' of the TU.
+  bool
+  ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend,
+                                                 unsigned TemplateDepth,
+                                                 const Expr *Constraint);
 
-  ExprResult BuildObjCBridgedCast(SourceLocation LParenLoc,
-                                  ObjCBridgeCastKind Kind,
-                                  SourceLocation BridgeKeywordLoc,
-                                  TypeSourceInfo *TSInfo,
-                                  Expr *SubExpr);
+  /// Declare implicit deduction guides for a class template if we've
+  /// not already done so.
+  void DeclareImplicitDeductionGuides(TemplateDecl *Template,
+                                      SourceLocation Loc);
+  FunctionTemplateDecl *DeclareImplicitDeductionGuideFromInitList(
+      TemplateDecl *Template, MutableArrayRef ParamTypes,
+      SourceLocation Loc);
 
-  ExprResult ActOnObjCBridgedCast(Scope *S,
-                                  SourceLocation LParenLoc,
-                                  ObjCBridgeCastKind Kind,
-                                  SourceLocation BridgeKeywordLoc,
-                                  ParsedType Type,
-                                  SourceLocation RParenLoc,
-                                  Expr *SubExpr);
+  /// Find the failed Boolean condition within a given Boolean
+  /// constant expression, and describe it with a string.
+  std::pair findFailedBooleanCondition(Expr *Cond);
 
-  void CheckTollFreeBridgeCast(QualType castType, Expr *castExpr);
+  void CheckDeductionGuideTemplate(FunctionTemplateDecl *TD);
 
-  void CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr);
+  Decl *ActOnConceptDefinition(Scope *S,
+                               MultiTemplateParamsArg TemplateParameterLists,
+                               IdentifierInfo *Name, SourceLocation NameLoc,
+                               Expr *ConstraintExpr);
 
-  bool CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,
-                                     CastKind &Kind);
+  void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous,
+                                bool &AddToScope);
 
-  bool checkObjCBridgeRelatedComponents(SourceLocation Loc,
-                                        QualType DestType, QualType SrcType,
-                                        ObjCInterfaceDecl *&RelatedClass,
-                                        ObjCMethodDecl *&ClassMethod,
-                                        ObjCMethodDecl *&InstanceMethod,
-                                        TypedefNameDecl *&TDNDecl,
-                                        bool CfToNs, bool Diagnose = true);
+  TypeResult ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+                               const CXXScopeSpec &SS, IdentifierInfo *Name,
+                               SourceLocation TagLoc, SourceLocation NameLoc);
 
-  bool CheckObjCBridgeRelatedConversions(SourceLocation Loc,
-                                         QualType DestType, QualType SrcType,
-                                         Expr *&SrcExpr, bool Diagnose = true);
+  void MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD,
+                                CachedTokens &Toks);
+  void UnmarkAsLateParsedTemplate(FunctionDecl *FD);
+  bool IsInsideALocalClassWithinATemplateFunction();
 
-  bool CheckConversionToObjCLiteral(QualType DstType, Expr *&SrcExpr,
-                                    bool Diagnose = true);
+  /// We've found a use of a templated declaration that would trigger an
+  /// implicit instantiation. Check that any relevant explicit specializations
+  /// and partial specializations are visible/reachable, and diagnose if not.
+  void checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec);
+  void checkSpecializationReachability(SourceLocation Loc, NamedDecl *Spec);
 
-  bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall);
+  ///@}
 
-  /// Check whether the given new method is a valid override of the
-  /// given overridden method, and set any properties that should be inherited.
-  void CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
-                               const ObjCMethodDecl *Overridden);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Describes the compatibility of a result type with its method.
-  enum ResultTypeCompatibilityKind {
-    RTC_Compatible,
-    RTC_Incompatible,
-    RTC_Unknown
-  };
+  /// \name C++ Template Argument Deduction
+  /// Implementations are in SemaTemplateDeduction.cpp
+  ///@{
 
-  void CheckObjCMethodDirectOverrides(ObjCMethodDecl *method,
-                                      ObjCMethodDecl *overridden);
+public:
+  /// When true, access checking violations are treated as SFINAE
+  /// failures rather than hard errors.
+  bool AccessCheckingSFINAE;
 
-  void CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
-                                ObjCInterfaceDecl *CurrentClass,
-                                ResultTypeCompatibilityKind RTC);
+  /// RAII class used to determine whether SFINAE has
+  /// trapped any errors that occur during template argument
+  /// deduction.
+  class SFINAETrap {
+    Sema &SemaRef;
+    unsigned PrevSFINAEErrors;
+    bool PrevInNonInstantiationSFINAEContext;
+    bool PrevAccessCheckingSFINAE;
+    bool PrevLastDiagnosticIgnored;
 
-  enum PragmaOptionsAlignKind {
-    POAK_Native,  // #pragma options align=native
-    POAK_Natural, // #pragma options align=natural
-    POAK_Packed,  // #pragma options align=packed
-    POAK_Power,   // #pragma options align=power
-    POAK_Mac68k,  // #pragma options align=mac68k
-    POAK_Reset    // #pragma options align=reset
-  };
+  public:
+    explicit SFINAETrap(Sema &SemaRef, bool AccessCheckingSFINAE = false)
+        : SemaRef(SemaRef), PrevSFINAEErrors(SemaRef.NumSFINAEErrors),
+          PrevInNonInstantiationSFINAEContext(
+              SemaRef.InNonInstantiationSFINAEContext),
+          PrevAccessCheckingSFINAE(SemaRef.AccessCheckingSFINAE),
+          PrevLastDiagnosticIgnored(
+              SemaRef.getDiagnostics().isLastDiagnosticIgnored()) {
+      if (!SemaRef.isSFINAEContext())
+        SemaRef.InNonInstantiationSFINAEContext = true;
+      SemaRef.AccessCheckingSFINAE = AccessCheckingSFINAE;
+    }
 
-  /// ActOnPragmaClangSection - Called on well formed \#pragma clang section
-  void ActOnPragmaClangSection(SourceLocation PragmaLoc,
-                               PragmaClangSectionAction Action,
-                               PragmaClangSectionKind SecKind, StringRef SecName);
+    ~SFINAETrap() {
+      SemaRef.NumSFINAEErrors = PrevSFINAEErrors;
+      SemaRef.InNonInstantiationSFINAEContext =
+          PrevInNonInstantiationSFINAEContext;
+      SemaRef.AccessCheckingSFINAE = PrevAccessCheckingSFINAE;
+      SemaRef.getDiagnostics().setLastDiagnosticIgnored(
+          PrevLastDiagnosticIgnored);
+    }
 
-  /// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align.
-  void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
-                               SourceLocation PragmaLoc);
+    /// Determine whether any SFINAE errors have been trapped.
+    bool hasErrorOccurred() const {
+      return SemaRef.NumSFINAEErrors > PrevSFINAEErrors;
+    }
+  };
 
-  /// ActOnPragmaPack - Called on well formed \#pragma pack(...).
-  void ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
-                       StringRef SlotLabel, Expr *Alignment);
+  /// RAII class used to indicate that we are performing provisional
+  /// semantic analysis to determine the validity of a construct, so
+  /// typo-correction and diagnostics in the immediate context (not within
+  /// implicitly-instantiated templates) should be suppressed.
+  class TentativeAnalysisScope {
+    Sema &SemaRef;
+    // FIXME: Using a SFINAETrap for this is a hack.
+    SFINAETrap Trap;
+    bool PrevDisableTypoCorrection;
 
-  enum class PragmaAlignPackDiagnoseKind {
-    NonDefaultStateAtInclude,
-    ChangedStateAtExit
+  public:
+    explicit TentativeAnalysisScope(Sema &SemaRef)
+        : SemaRef(SemaRef), Trap(SemaRef, true),
+          PrevDisableTypoCorrection(SemaRef.DisableTypoCorrection) {
+      SemaRef.DisableTypoCorrection = true;
+    }
+    ~TentativeAnalysisScope() {
+      SemaRef.DisableTypoCorrection = PrevDisableTypoCorrection;
+    }
   };
 
-  void DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind,
-                                         SourceLocation IncludeLoc);
-  void DiagnoseUnterminatedPragmaAlignPack();
+  /// For each declaration that involved template argument deduction, the
+  /// set of diagnostics that were suppressed during that template argument
+  /// deduction.
+  ///
+  /// FIXME: Serialize this structure to the AST file.
+  typedef llvm::DenseMap>
+      SuppressedDiagnosticsMap;
+  SuppressedDiagnosticsMap SuppressedDiagnostics;
 
-  /// ActOnPragmaMSStrictGuardStackCheck - Called on well formed \#pragma
-  /// strict_gs_check.
-  void ActOnPragmaMSStrictGuardStackCheck(SourceLocation PragmaLocation,
-                                          PragmaMsStackAction Action,
-                                          bool Value);
+  bool isSameOrCompatibleFunctionType(QualType Param, QualType Arg);
 
-  /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off].
-  void ActOnPragmaMSStruct(PragmaMSStructKind Kind);
+  TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
+                                                    QualType NTTPType,
+                                                    SourceLocation Loc);
 
-  /// ActOnPragmaMSComment - Called on well formed
-  /// \#pragma comment(kind, "arg").
-  void ActOnPragmaMSComment(SourceLocation CommentLoc, PragmaMSCommentKind Kind,
-                            StringRef Arg);
+  /// Get a template argument mapping the given template parameter to itself,
+  /// e.g. for X in \c template, this would return an expression template
+  /// argument referencing X.
+  TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param,
+                                                     SourceLocation Location);
 
-  /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma
-  /// pointers_to_members(representation method[, general purpose
-  /// representation]).
-  void ActOnPragmaMSPointersToMembers(
-      LangOptions::PragmaMSPointersToMembersKind Kind,
-      SourceLocation PragmaLoc);
+  /// Adjust the type \p ArgFunctionType to match the calling convention,
+  /// noreturn, and optionally the exception specification of \p FunctionType.
+  /// Deduction often wants to ignore these properties when matching function
+  /// types.
+  QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType,
+                               bool AdjustExceptionSpec = false);
 
-  /// Called on well formed \#pragma vtordisp().
-  void ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
-                             SourceLocation PragmaLoc,
-                             MSVtorDispMode Value);
-
-  enum PragmaSectionKind {
-    PSK_DataSeg,
-    PSK_BSSSeg,
-    PSK_ConstSeg,
-    PSK_CodeSeg,
-  };
+  TemplateDeductionResult
+  DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
+                          ArrayRef TemplateArgs,
+                          sema::TemplateDeductionInfo &Info);
 
-  bool UnifySection(StringRef SectionName, int SectionFlags,
-                    NamedDecl *TheDecl);
-  bool UnifySection(StringRef SectionName,
-                    int SectionFlags,
-                    SourceLocation PragmaSectionLocation);
+  TemplateDeductionResult
+  DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
+                          ArrayRef TemplateArgs,
+                          sema::TemplateDeductionInfo &Info);
 
-  /// Called on well formed \#pragma bss_seg/data_seg/const_seg/code_seg.
-  void ActOnPragmaMSSeg(SourceLocation PragmaLocation,
-                        PragmaMsStackAction Action,
-                        llvm::StringRef StackSlotLabel,
-                        StringLiteral *SegmentName,
-                        llvm::StringRef PragmaName);
+  TemplateDeductionResult DeduceTemplateArguments(
+      TemplateParameterList *TemplateParams, ArrayRef Ps,
+      ArrayRef As, sema::TemplateDeductionInfo &Info,
+      SmallVectorImpl &Deduced,
+      bool NumberOfArgumentsMustMatch);
 
-  /// Called on well formed \#pragma section().
-  void ActOnPragmaMSSection(SourceLocation PragmaLocation,
-                            int SectionFlags, StringLiteral *SegmentName);
+  TemplateDeductionResult SubstituteExplicitTemplateArguments(
+      FunctionTemplateDecl *FunctionTemplate,
+      TemplateArgumentListInfo &ExplicitTemplateArgs,
+      SmallVectorImpl &Deduced,
+      SmallVectorImpl &ParamTypes, QualType *FunctionType,
+      sema::TemplateDeductionInfo &Info);
 
-  /// Called on well-formed \#pragma init_seg().
-  void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
-                            StringLiteral *SegmentName);
+  /// brief A function argument from which we performed template argument
+  // deduction for a call.
+  struct OriginalCallArg {
+    OriginalCallArg(QualType OriginalParamType, bool DecomposedParam,
+                    unsigned ArgIdx, QualType OriginalArgType)
+        : OriginalParamType(OriginalParamType),
+          DecomposedParam(DecomposedParam), ArgIdx(ArgIdx),
+          OriginalArgType(OriginalArgType) {}
 
-  /// Called on well-formed \#pragma alloc_text().
-  void ActOnPragmaMSAllocText(
-      SourceLocation PragmaLocation, StringRef Section,
-      const SmallVector>
-          &Functions);
+    QualType OriginalParamType;
+    bool DecomposedParam;
+    unsigned ArgIdx;
+    QualType OriginalArgType;
+  };
 
-  /// Called on #pragma clang __debug dump II
-  void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
+  TemplateDeductionResult FinishTemplateArgumentDeduction(
+      FunctionTemplateDecl *FunctionTemplate,
+      SmallVectorImpl &Deduced,
+      unsigned NumExplicitlySpecified, FunctionDecl *&Specialization,
+      sema::TemplateDeductionInfo &Info,
+      SmallVectorImpl const *OriginalCallArgs = nullptr,
+      bool PartialOverloading = false,
+      llvm::function_ref CheckNonDependent = [] { return false; });
 
-  /// Called on #pragma clang __debug dump E
-  void ActOnPragmaDump(Expr *E);
+  TemplateDeductionResult DeduceTemplateArguments(
+      FunctionTemplateDecl *FunctionTemplate,
+      TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef Args,
+      FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info,
+      bool PartialOverloading, bool AggregateDeductionCandidate,
+      QualType ObjectType, Expr::Classification ObjectClassification,
+      llvm::function_ref)> CheckNonDependent);
 
-  /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
-  void ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
-                                 StringRef Value);
+  TemplateDeductionResult DeduceTemplateArguments(
+      FunctionTemplateDecl *FunctionTemplate,
+      TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType,
+      FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info,
+      bool IsAddressOfFunction = false);
 
-  /// Are precise floating point semantics currently enabled?
-  bool isPreciseFPEnabled() {
-    return !CurFPFeatures.getAllowFPReassociate() &&
-           !CurFPFeatures.getNoSignedZero() &&
-           !CurFPFeatures.getAllowReciprocal() &&
-           !CurFPFeatures.getAllowApproxFunc();
-  }
+  TemplateDeductionResult DeduceTemplateArguments(
+      FunctionTemplateDecl *FunctionTemplate, QualType ObjectType,
+      Expr::Classification ObjectClassification, QualType ToType,
+      CXXConversionDecl *&Specialization, sema::TemplateDeductionInfo &Info);
 
-  void ActOnPragmaFPEvalMethod(SourceLocation Loc,
-                               LangOptions::FPEvalMethodKind Value);
+  TemplateDeductionResult
+  DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                          TemplateArgumentListInfo *ExplicitTemplateArgs,
+                          FunctionDecl *&Specialization,
+                          sema::TemplateDeductionInfo &Info,
+                          bool IsAddressOfFunction = false);
 
-  /// ActOnPragmaFloatControl - Call on well-formed \#pragma float_control
-  void ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action,
-                               PragmaFloatControlKind Value);
+  /// Substitute Replacement for \p auto in \p TypeWithAuto
+  QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
+  /// Substitute Replacement for auto in TypeWithAuto
+  TypeSourceInfo *SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
+                                          QualType Replacement);
 
-  /// ActOnPragmaUnused - Called on well-formed '\#pragma unused'.
-  void ActOnPragmaUnused(const Token &Identifier,
-                         Scope *curScope,
-                         SourceLocation PragmaLoc);
+  // Substitute auto in TypeWithAuto for a Dependent auto type
+  QualType SubstAutoTypeDependent(QualType TypeWithAuto);
 
-  /// ActOnPragmaVisibility - Called on well formed \#pragma GCC visibility... .
-  void ActOnPragmaVisibility(const IdentifierInfo* VisType,
-                             SourceLocation PragmaLoc);
+  // Substitute auto in TypeWithAuto for a Dependent auto type
+  TypeSourceInfo *
+  SubstAutoTypeSourceInfoDependent(TypeSourceInfo *TypeWithAuto);
 
-  NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II,
-                                 SourceLocation Loc);
-  void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, const WeakInfo &W);
+  /// Completely replace the \c auto in \p TypeWithAuto by
+  /// \p Replacement. This does not retain any \c auto type sugar.
+  QualType ReplaceAutoType(QualType TypeWithAuto, QualType Replacement);
+  TypeSourceInfo *ReplaceAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
+                                            QualType Replacement);
 
-  /// ActOnPragmaWeakID - Called on well formed \#pragma weak ident.
-  void ActOnPragmaWeakID(IdentifierInfo* WeakName,
-                         SourceLocation PragmaLoc,
-                         SourceLocation WeakNameLoc);
+  TemplateDeductionResult
+  DeduceAutoType(TypeLoc AutoTypeLoc, Expr *Initializer, QualType &Result,
+                 sema::TemplateDeductionInfo &Info,
+                 bool DependentDeduction = false,
+                 bool IgnoreConstraints = false,
+                 TemplateSpecCandidateSet *FailedTSC = nullptr);
+  void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init);
+  bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
+                        bool Diagnose = true);
 
-  /// ActOnPragmaRedefineExtname - Called on well formed
-  /// \#pragma redefine_extname oldname newname.
-  void ActOnPragmaRedefineExtname(IdentifierInfo* WeakName,
-                                  IdentifierInfo* AliasName,
-                                  SourceLocation PragmaLoc,
-                                  SourceLocation WeakNameLoc,
-                                  SourceLocation AliasNameLoc);
+  bool CheckIfFunctionSpecializationIsImmediate(FunctionDecl *FD,
+                                                SourceLocation Loc);
 
-  /// ActOnPragmaWeakAlias - Called on well formed \#pragma weak ident = ident.
-  void ActOnPragmaWeakAlias(IdentifierInfo* WeakName,
-                            IdentifierInfo* AliasName,
-                            SourceLocation PragmaLoc,
-                            SourceLocation WeakNameLoc,
-                            SourceLocation AliasNameLoc);
+  ClassTemplatePartialSpecializationDecl *
+  getMoreSpecializedPartialSpecialization(
+      ClassTemplatePartialSpecializationDecl *PS1,
+      ClassTemplatePartialSpecializationDecl *PS2, SourceLocation Loc);
 
-  /// ActOnPragmaFPContract - Called on well formed
-  /// \#pragma {STDC,OPENCL} FP_CONTRACT and
-  /// \#pragma clang fp contract
-  void ActOnPragmaFPContract(SourceLocation Loc, LangOptions::FPModeKind FPC);
+  bool isMoreSpecializedThanPrimary(ClassTemplatePartialSpecializationDecl *T,
+                                    sema::TemplateDeductionInfo &Info);
 
-  /// Called on well formed
-  /// \#pragma clang fp reassociate
-  /// or
-  /// \#pragma clang fp reciprocal
-  void ActOnPragmaFPValueChangingOption(SourceLocation Loc, PragmaFPKind Kind,
-                                        bool IsEnabled);
+  VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpecialization(
+      VarTemplatePartialSpecializationDecl *PS1,
+      VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc);
 
-  /// ActOnPragmaFenvAccess - Called on well formed
-  /// \#pragma STDC FENV_ACCESS
-  void ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled);
+  bool isMoreSpecializedThanPrimary(VarTemplatePartialSpecializationDecl *T,
+                                    sema::TemplateDeductionInfo &Info);
 
-  /// ActOnPragmaCXLimitedRange - Called on well formed
-  /// \#pragma STDC CX_LIMITED_RANGE
-  void ActOnPragmaCXLimitedRange(SourceLocation Loc,
-                                 LangOptions::ComplexRangeKind Range);
+  bool isTemplateTemplateParameterAtLeastAsSpecializedAs(
+      TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc);
 
-  /// Called on well formed '\#pragma clang fp' that has option 'exceptions'.
-  void ActOnPragmaFPExceptions(SourceLocation Loc,
-                               LangOptions::FPExceptionModeKind);
+  void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
+                                  unsigned Depth, llvm::SmallBitVector &Used);
 
-  /// Called to set constant rounding mode for floating point operations.
-  void ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode);
+  void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs,
+                                  bool OnlyDeduced, unsigned Depth,
+                                  llvm::SmallBitVector &Used);
+  void
+  MarkDeducedTemplateParameters(const FunctionTemplateDecl *FunctionTemplate,
+                                llvm::SmallBitVector &Deduced) {
+    return MarkDeducedTemplateParameters(Context, FunctionTemplate, Deduced);
+  }
+  static void
+  MarkDeducedTemplateParameters(ASTContext &Ctx,
+                                const FunctionTemplateDecl *FunctionTemplate,
+                                llvm::SmallBitVector &Deduced);
 
-  /// Called to set exception behavior for floating point operations.
-  void setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind);
+  FunctionTemplateDecl *getMoreSpecializedTemplate(
+      FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc,
+      TemplatePartialOrderingContext TPOC, unsigned NumCallArguments1,
+      QualType RawObj1Ty = {}, QualType RawObj2Ty = {}, bool Reversed = false);
 
-  /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
-  /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'.
-  void AddAlignmentAttributesForRecord(RecordDecl *RD);
+  UnresolvedSetIterator
+  getMostSpecialized(UnresolvedSetIterator SBegin, UnresolvedSetIterator SEnd,
+                     TemplateSpecCandidateSet &FailedCandidates,
+                     SourceLocation Loc, const PartialDiagnostic &NoneDiag,
+                     const PartialDiagnostic &AmbigDiag,
+                     const PartialDiagnostic &CandidateDiag,
+                     bool Complain = true, QualType TargetType = QualType());
 
-  /// AddMsStructLayoutForRecord - Adds ms_struct layout attribute to record.
-  void AddMsStructLayoutForRecord(RecordDecl *RD);
+  ///@}
 
-  /// PushNamespaceVisibilityAttr - Note that we've entered a
-  /// namespace with a visibility attribute.
-  void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
-                                   SourceLocation Loc);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// AddPushedVisibilityAttribute - If '\#pragma GCC visibility' was used,
-  /// add an appropriate visibility attribute.
-  void AddPushedVisibilityAttribute(Decl *RD);
+  /// \name C++ Template Instantiation
+  /// Implementations are in SemaTemplateInstantiate.cpp
+  ///@{
 
-  /// PopPragmaVisibility - Pop the top element of the visibility stack; used
-  /// for '\#pragma GCC visibility' and visibility attributes on namespaces.
-  void PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc);
+public:
+  /// A helper class for building up ExtParameterInfos.
+  class ExtParameterInfoBuilder {
+    SmallVector Infos;
+    bool HasInteresting = false;
 
-  /// FreeVisContext - Deallocate and null out VisContext.
-  void FreeVisContext();
+  public:
+    /// Set the ExtParameterInfo for the parameter at the given index,
+    ///
+    void set(unsigned index, FunctionProtoType::ExtParameterInfo info) {
+      assert(Infos.size() <= index);
+      Infos.resize(index);
+      Infos.push_back(info);
 
-  /// AddCFAuditedAttribute - Check whether we're currently within
-  /// '\#pragma clang arc_cf_code_audited' and, if so, consider adding
-  /// the appropriate attribute.
-  void AddCFAuditedAttribute(Decl *D);
+      if (!HasInteresting)
+        HasInteresting = (info != FunctionProtoType::ExtParameterInfo());
+    }
 
-  void ActOnPragmaAttributeAttribute(ParsedAttr &Attribute,
-                                     SourceLocation PragmaLoc,
-                                     attr::ParsedSubjectMatchRuleSet Rules);
-  void ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc,
-                                     const IdentifierInfo *Namespace);
+    /// Return a pointer (suitable for setting in an ExtProtoInfo) to the
+    /// ExtParameterInfo array we've built up.
+    const FunctionProtoType::ExtParameterInfo *
+    getPointerOrNull(unsigned numParams) {
+      if (!HasInteresting)
+        return nullptr;
+      Infos.resize(numParams);
+      return Infos.data();
+    }
+  };
 
-  /// Called on well-formed '\#pragma clang attribute pop'.
-  void ActOnPragmaAttributePop(SourceLocation PragmaLoc,
-                               const IdentifierInfo *Namespace);
+  /// The current instantiation scope used to store local
+  /// variables.
+  LocalInstantiationScope *CurrentInstantiationScope;
 
-  /// Adds the attributes that have been specified using the
-  /// '\#pragma clang attribute push' directives to the given declaration.
-  void AddPragmaAttributes(Scope *S, Decl *D);
+  typedef llvm::DenseMap>
+      UnparsedDefaultArgInstantiationsMap;
 
-  void DiagnoseUnterminatedPragmaAttribute();
+  /// A mapping from parameters with unparsed default arguments to the
+  /// set of instantiations of each parameter.
+  ///
+  /// This mapping is a temporary data structure used when parsing
+  /// nested class templates or nested classes of class templates,
+  /// where we might end up instantiating an inner class before the
+  /// default arguments of its methods have been parsed.
+  UnparsedDefaultArgInstantiationsMap UnparsedDefaultArgInstantiations;
 
-  /// Called on well formed \#pragma clang optimize.
-  void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc);
+  /// A context in which code is being synthesized (where a source location
+  /// alone is not sufficient to identify the context). This covers template
+  /// instantiation and various forms of implicitly-generated functions.
+  struct CodeSynthesisContext {
+    /// The kind of template instantiation we are performing
+    enum SynthesisKind {
+      /// We are instantiating a template declaration. The entity is
+      /// the declaration we're instantiating (e.g., a CXXRecordDecl).
+      TemplateInstantiation,
 
-  /// #pragma optimize("[optimization-list]", on | off).
-  void ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn);
+      /// We are instantiating a default argument for a template
+      /// parameter. The Entity is the template parameter whose argument is
+      /// being instantiated, the Template is the template, and the
+      /// TemplateArgs/NumTemplateArguments provide the template arguments as
+      /// specified.
+      DefaultTemplateArgumentInstantiation,
 
-  /// Call on well formed \#pragma function.
-  void
-  ActOnPragmaMSFunction(SourceLocation Loc,
-                        const llvm::SmallVectorImpl &NoBuiltins);
+      /// We are instantiating a default argument for a function.
+      /// The Entity is the ParmVarDecl, and TemplateArgs/NumTemplateArgs
+      /// provides the template arguments as specified.
+      DefaultFunctionArgumentInstantiation,
 
-  /// Get the location for the currently active "\#pragma clang optimize
-  /// off". If this location is invalid, then the state of the pragma is "on".
-  SourceLocation getOptimizeOffPragmaLocation() const {
-    return OptimizeOffPragmaLocation;
-  }
+      /// We are substituting explicit template arguments provided for
+      /// a function template. The entity is a FunctionTemplateDecl.
+      ExplicitTemplateArgumentSubstitution,
 
-  /// Only called on function definitions; if there is a pragma in scope
-  /// with the effect of a range-based optnone, consider marking the function
-  /// with attribute optnone.
-  void AddRangeBasedOptnone(FunctionDecl *FD);
+      /// We are substituting template argument determined as part of
+      /// template argument deduction for either a class template
+      /// partial specialization or a function template. The
+      /// Entity is either a {Class|Var}TemplatePartialSpecializationDecl or
+      /// a TemplateDecl.
+      DeducedTemplateArgumentSubstitution,
 
-  /// Only called on function definitions; if there is a `#pragma alloc_text`
-  /// that decides which code section the function should be in, add
-  /// attribute section to the function.
-  void AddSectionMSAllocText(FunctionDecl *FD);
+      /// We are substituting into a lambda expression.
+      LambdaExpressionSubstitution,
 
-  /// Adds the 'optnone' attribute to the function declaration if there
-  /// are no conflicts; Loc represents the location causing the 'optnone'
-  /// attribute to be added (usually because of a pragma).
-  void AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc);
+      /// We are substituting prior template arguments into a new
+      /// template parameter. The template parameter itself is either a
+      /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl.
+      PriorTemplateArgumentSubstitution,
 
-  /// Only called on function definitions; if there is a MSVC #pragma optimize
-  /// in scope, consider changing the function's attributes based on the
-  /// optimization list passed to the pragma.
-  void ModifyFnAttributesMSPragmaOptimize(FunctionDecl *FD);
+      /// We are checking the validity of a default template argument that
+      /// has been used when naming a template-id.
+      DefaultTemplateArgumentChecking,
 
-  /// Only called on function definitions; if there is a pragma in scope
-  /// with the effect of a range-based no_builtin, consider marking the function
-  /// with attribute no_builtin.
-  void AddImplicitMSFunctionNoBuiltinAttr(FunctionDecl *FD);
+      /// We are computing the exception specification for a defaulted special
+      /// member function.
+      ExceptionSpecEvaluation,
 
-  /// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
-  void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
-                      bool IsPackExpansion);
-  void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, TypeSourceInfo *T,
-                      bool IsPackExpansion);
+      /// We are instantiating the exception specification for a function
+      /// template which was deferred until it was needed.
+      ExceptionSpecInstantiation,
 
-  /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular
-  /// declaration.
-  void AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
-                            Expr *OE);
+      /// We are instantiating a requirement of a requires expression.
+      RequirementInstantiation,
 
-  /// AddAllocAlignAttr - Adds an alloc_align attribute to a particular
-  /// declaration.
-  void AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
-                         Expr *ParamExpr);
+      /// We are checking the satisfaction of a nested requirement of a requires
+      /// expression.
+      NestedRequirementConstraintsCheck,
 
-  /// AddAlignValueAttr - Adds an align_value attribute to a particular
-  /// declaration.
-  void AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E);
+      /// We are declaring an implicit special member function.
+      DeclaringSpecialMember,
 
-  /// AddAnnotationAttr - Adds an annotation Annot with Args arguments to D.
-  void AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
-                         StringRef Annot, MutableArrayRef Args);
+      /// We are declaring an implicit 'operator==' for a defaulted
+      /// 'operator<=>'.
+      DeclaringImplicitEqualityComparison,
 
-  /// ConstantFoldAttrArgs - Folds attribute arguments into ConstantExprs
-  /// (unless they are value dependent or type dependent). Returns false
-  /// and emits a diagnostic if one or more of the arguments could not be
-  /// folded into a constant.
-  bool ConstantFoldAttrArgs(const AttributeCommonInfo &CI,
-                            MutableArrayRef Args);
+      /// We are defining a synthesized function (such as a defaulted special
+      /// member).
+      DefiningSynthesizedFunction,
 
-  /// Create an CUDALaunchBoundsAttr attribute.
-  CUDALaunchBoundsAttr *CreateLaunchBoundsAttr(const AttributeCommonInfo &CI,
-                                               Expr *MaxThreads,
-                                               Expr *MinBlocks,
-                                               Expr *MaxBlocks);
+      // We are checking the constraints associated with a constrained entity or
+      // the constraint expression of a concept. This includes the checks that
+      // atomic constraints have the type 'bool' and that they can be constant
+      // evaluated.
+      ConstraintsCheck,
 
-  /// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular
-  /// declaration.
-  void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,
-                           Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks);
+      // We are substituting template arguments into a constraint expression.
+      ConstraintSubstitution,
 
-  /// AddModeAttr - Adds a mode attribute to a particular declaration.
-  void AddModeAttr(Decl *D, const AttributeCommonInfo &CI, IdentifierInfo *Name,
-                   bool InInstantiation = false);
+      // We are normalizing a constraint expression.
+      ConstraintNormalization,
 
-  void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
-                           ParameterABI ABI);
+      // Instantiating a Requires Expression parameter clause.
+      RequirementParameterInstantiation,
 
-  enum class RetainOwnershipKind {NS, CF, OS};
-  void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
-                        RetainOwnershipKind K, bool IsTemplateInstantiation);
+      // We are substituting into the parameter mapping of an atomic constraint
+      // during normalization.
+      ParameterMappingSubstitution,
 
-  /// Create an AMDGPUWavesPerEUAttr attribute.
-  AMDGPUFlatWorkGroupSizeAttr *
-  CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min,
-                                    Expr *Max);
+      /// We are rewriting a comparison operator in terms of an operator<=>.
+      RewritingOperatorAsSpaceship,
 
-  /// addAMDGPUFlatWorkGroupSizeAttr - Adds an amdgpu_flat_work_group_size
-  /// attribute to a particular declaration.
-  void addAMDGPUFlatWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
-                                      Expr *Min, Expr *Max);
+      /// We are initializing a structured binding.
+      InitializingStructuredBinding,
 
-  /// Create an AMDGPUWavesPerEUAttr attribute.
-  AMDGPUWavesPerEUAttr *
-  CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min,
-                             Expr *Max);
+      /// We are marking a class as __dllexport.
+      MarkingClassDllexported,
 
-  /// addAMDGPUWavePersEUAttr - Adds an amdgpu_waves_per_eu attribute to a
-  /// particular declaration.
-  void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI,
-                               Expr *Min, Expr *Max);
+      /// We are building an implied call from __builtin_dump_struct. The
+      /// arguments are in CallArgs.
+      BuildingBuiltinDumpStructCall,
 
-  bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
+      /// Added for Template instantiation observation.
+      /// Memoization means we are _not_ instantiating a template because
+      /// it is already instantiated (but we entered a context where we
+      /// would have had to if it was not already instantiated).
+      Memoization,
 
-  //===--------------------------------------------------------------------===//
-  // C++ Coroutines
-  //
-  bool ActOnCoroutineBodyStart(Scope *S, SourceLocation KwLoc,
-                               StringRef Keyword);
-  ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E);
-  ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E);
-  StmtResult ActOnCoreturnStmt(Scope *S, SourceLocation KwLoc, Expr *E);
+      /// We are building deduction guides for a class.
+      BuildingDeductionGuides,
+    } Kind;
 
-  ExprResult BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc);
-  ExprResult BuildOperatorCoawaitCall(SourceLocation Loc, Expr *E,
-                                      UnresolvedLookupExpr *Lookup);
-  ExprResult BuildResolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand,
-                                      Expr *Awaiter, bool IsImplicit = false);
-  ExprResult BuildUnresolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand,
-                                        UnresolvedLookupExpr *Lookup);
-  ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E);
-  StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E,
-                               bool IsImplicit = false);
-  StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs);
-  bool buildCoroutineParameterMoves(SourceLocation Loc);
-  VarDecl *buildCoroutinePromise(SourceLocation Loc);
-  void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body);
+    /// Was the enclosing context a non-instantiation SFINAE context?
+    bool SavedInNonInstantiationSFINAEContext;
 
-  // Heuristically tells if the function is `get_return_object` member of a
-  // coroutine promise_type by matching the function name.
-  static bool CanBeGetReturnObject(const FunctionDecl *FD);
-  static bool CanBeGetReturnTypeOnAllocFailure(const FunctionDecl *FD);
+    /// The point of instantiation or synthesis within the source code.
+    SourceLocation PointOfInstantiation;
 
-  // As a clang extension, enforces that a non-coroutine function must be marked
-  // with [[clang::coro_wrapper]] if it returns a type marked with
-  // [[clang::coro_return_type]].
-  // Expects that FD is not a coroutine.
-  void CheckCoroutineWrapper(FunctionDecl *FD);
-  /// Lookup 'coroutine_traits' in std namespace and std::experimental
-  /// namespace. The namespace found is recorded in Namespace.
-  ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc,
-                                           SourceLocation FuncLoc);
-  /// Check that the expression co_await promise.final_suspend() shall not be
-  /// potentially-throwing.
-  bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend);
+    /// The entity that is being synthesized.
+    Decl *Entity;
 
-  //===--------------------------------------------------------------------===//
-  // OpenMP directives and clauses.
-  //
-private:
-  void *VarDataSharingAttributesStack;
+    /// The template (or partial specialization) in which we are
+    /// performing the instantiation, for substitutions of prior template
+    /// arguments.
+    NamedDecl *Template;
 
-  struct DeclareTargetContextInfo {
-    struct MapInfo {
-      OMPDeclareTargetDeclAttr::MapTypeTy MT;
-      SourceLocation Loc;
-    };
-    /// Explicitly listed variables and functions in a 'to' or 'link' clause.
-    llvm::DenseMap ExplicitlyMapped;
+    union {
+      /// The list of template arguments we are substituting, if they
+      /// are not part of the entity.
+      const TemplateArgument *TemplateArgs;
 
-    /// The 'device_type' as parsed from the clause.
-    OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
+      /// The list of argument expressions in a synthesized call.
+      const Expr *const *CallArgs;
+    };
 
-    /// The directive kind, `begin declare target` or `declare target`.
-    OpenMPDirectiveKind Kind;
-
-    /// The directive with indirect clause.
-    std::optional Indirect;
-
-    /// The directive location.
-    SourceLocation Loc;
-
-    DeclareTargetContextInfo(OpenMPDirectiveKind Kind, SourceLocation Loc)
-        : Kind(Kind), Loc(Loc) {}
-  };
+    // FIXME: Wrap this union around more members, or perhaps store the
+    // kind-specific members in the RAII object owning the context.
+    union {
+      /// The number of template arguments in TemplateArgs.
+      unsigned NumTemplateArgs;
 
-  /// Number of nested '#pragma omp declare target' directives.
-  SmallVector DeclareTargetNesting;
+      /// The number of expressions in CallArgs.
+      unsigned NumCallArgs;
 
-  /// Initialization of data-sharing attributes stack.
-  void InitDataSharingAttributesStack();
-  void DestroyDataSharingAttributesStack();
+      /// The special member being declared or defined.
+      CXXSpecialMember SpecialMember;
+    };
 
-  /// Returns OpenMP nesting level for current directive.
-  unsigned getOpenMPNestingLevel() const;
+    ArrayRef template_arguments() const {
+      assert(Kind != DeclaringSpecialMember);
+      return {TemplateArgs, NumTemplateArgs};
+    }
 
-  /// Adjusts the function scopes index for the target-based regions.
-  void adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
-                                    unsigned Level) const;
+    /// The template deduction info object associated with the
+    /// substitution or checking of explicit or deduced template arguments.
+    sema::TemplateDeductionInfo *DeductionInfo;
 
-  /// Returns the number of scopes associated with the construct on the given
-  /// OpenMP level.
-  int getNumberOfConstructScopes(unsigned Level) const;
+    /// The source range that covers the construct that cause
+    /// the instantiation, e.g., the template-id that causes a class
+    /// template instantiation.
+    SourceRange InstantiationRange;
 
-  /// Push new OpenMP function region for non-capturing function.
-  void pushOpenMPFunctionRegion();
+    CodeSynthesisContext()
+        : Kind(TemplateInstantiation),
+          SavedInNonInstantiationSFINAEContext(false), Entity(nullptr),
+          Template(nullptr), TemplateArgs(nullptr), NumTemplateArgs(0),
+          DeductionInfo(nullptr) {}
 
-  /// Pop OpenMP function region for non-capturing function.
-  void popOpenMPFunctionRegion(const sema::FunctionScopeInfo *OldFSI);
+    /// Determines whether this template is an actual instantiation
+    /// that should be counted toward the maximum instantiation depth.
+    bool isInstantiationRecord() const;
+  };
 
-  /// Analyzes and checks a loop nest for use by a loop transformation.
+  /// A stack object to be created when performing template
+  /// instantiation.
   ///
-  /// \param Kind          The loop transformation directive kind.
-  /// \param NumLoops      How many nested loops the directive is expecting.
-  /// \param AStmt         Associated statement of the transformation directive.
-  /// \param LoopHelpers   [out] The loop analysis result.
-  /// \param Body          [out] The body code nested in \p NumLoops loop.
-  /// \param OriginalInits [out] Collection of statements and declarations that
-  ///                      must have been executed/declared before entering the
-  ///                      loop.
+  /// Construction of an object of type \c InstantiatingTemplate
+  /// pushes the current instantiation onto the stack of active
+  /// instantiations. If the size of this stack exceeds the maximum
+  /// number of recursive template instantiations, construction
+  /// produces an error and evaluates true.
   ///
-  /// \return Whether there was any error.
-  bool checkTransformableLoopNest(
-      OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
-      SmallVectorImpl &LoopHelpers,
-      Stmt *&Body,
-      SmallVectorImpl, 0>>
-          &OriginalInits);
+  /// Destruction of this object will pop the named instantiation off
+  /// the stack.
+  struct InstantiatingTemplate {
+    /// Note that we are instantiating a class template,
+    /// function template, variable template, alias template,
+    /// or a member thereof.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          Decl *Entity,
+                          SourceRange InstantiationRange = SourceRange());
 
-  /// Helper to keep information about the current `omp begin/end declare
-  /// variant` nesting.
-  struct OMPDeclareVariantScope {
-    /// The associated OpenMP context selector.
-    OMPTraitInfo *TI;
+    struct ExceptionSpecification {};
+    /// Note that we are instantiating an exception specification
+    /// of a function template.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          FunctionDecl *Entity, ExceptionSpecification,
+                          SourceRange InstantiationRange = SourceRange());
 
-    /// The associated OpenMP context selector mangling.
-    std::string NameSuffix;
+    /// Note that we are instantiating a default argument in a
+    /// template-id.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          TemplateParameter Param, TemplateDecl *Template,
+                          ArrayRef TemplateArgs,
+                          SourceRange InstantiationRange = SourceRange());
 
-    OMPDeclareVariantScope(OMPTraitInfo &TI);
-  };
+    /// Note that we are substituting either explicitly-specified or
+    /// deduced template arguments during function template argument deduction.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          FunctionTemplateDecl *FunctionTemplate,
+                          ArrayRef TemplateArgs,
+                          CodeSynthesisContext::SynthesisKind Kind,
+                          sema::TemplateDeductionInfo &DeductionInfo,
+                          SourceRange InstantiationRange = SourceRange());
 
-  /// Return the OMPTraitInfo for the surrounding scope, if any.
-  OMPTraitInfo *getOMPTraitInfoForSurroundingScope() {
-    return OMPDeclareVariantScopes.empty() ? nullptr
-                                           : OMPDeclareVariantScopes.back().TI;
-  }
+    /// Note that we are instantiating as part of template
+    /// argument deduction for a class template declaration.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          TemplateDecl *Template,
+                          ArrayRef TemplateArgs,
+                          sema::TemplateDeductionInfo &DeductionInfo,
+                          SourceRange InstantiationRange = SourceRange());
 
-  /// The current `omp begin/end declare variant` scopes.
-  SmallVector OMPDeclareVariantScopes;
+    /// Note that we are instantiating as part of template
+    /// argument deduction for a class template partial
+    /// specialization.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          ClassTemplatePartialSpecializationDecl *PartialSpec,
+                          ArrayRef TemplateArgs,
+                          sema::TemplateDeductionInfo &DeductionInfo,
+                          SourceRange InstantiationRange = SourceRange());
 
-  /// The current `omp begin/end assumes` scopes.
-  SmallVector OMPAssumeScoped;
+    /// Note that we are instantiating as part of template
+    /// argument deduction for a variable template partial
+    /// specialization.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          VarTemplatePartialSpecializationDecl *PartialSpec,
+                          ArrayRef TemplateArgs,
+                          sema::TemplateDeductionInfo &DeductionInfo,
+                          SourceRange InstantiationRange = SourceRange());
 
-  /// All `omp assumes` we encountered so far.
-  SmallVector OMPAssumeGlobal;
+    /// Note that we are instantiating a default argument for a function
+    /// parameter.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          ParmVarDecl *Param,
+                          ArrayRef TemplateArgs,
+                          SourceRange InstantiationRange = SourceRange());
 
-  /// OMPD_loop is mapped to OMPD_for, OMPD_distribute or OMPD_simd depending
-  /// on the parameter of the bind clause. In the methods for the
-  /// mapped directives, check the parameters of the lastprivate clause.
-  bool checkLastPrivateForMappedDirectives(ArrayRef Clauses);
-  /// Depending on the bind clause of OMPD_loop map the directive to new
-  /// directives.
-  ///    1) loop bind(parallel) --> OMPD_for
-  ///    2) loop bind(teams) --> OMPD_distribute
-  ///    3) loop bind(thread) --> OMPD_simd
-  /// This is being handled in Sema instead of Codegen because of the need for
-  /// rigorous semantic checking in the new mapped directives.
-  bool mapLoopConstruct(llvm::SmallVector &ClausesWithoutBind,
-                        ArrayRef Clauses,
-                        OpenMPBindClauseKind &BindKind,
-                        OpenMPDirectiveKind &Kind,
-                        OpenMPDirectiveKind &PrevMappedDirective,
-                        SourceLocation StartLoc, SourceLocation EndLoc,
-                        const DeclarationNameInfo &DirName,
-                        OpenMPDirectiveKind CancelRegion);
+    /// Note that we are substituting prior template arguments into a
+    /// non-type parameter.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          NamedDecl *Template, NonTypeTemplateParmDecl *Param,
+                          ArrayRef TemplateArgs,
+                          SourceRange InstantiationRange);
 
-public:
-  /// The declarator \p D defines a function in the scope \p S which is nested
-  /// in an `omp begin/end declare variant` scope. In this method we create a
-  /// declaration for \p D and rename \p D according to the OpenMP context
-  /// selector of the surrounding scope. Return all base functions in \p Bases.
-  void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(
-      Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists,
-      SmallVectorImpl &Bases);
+    /// Note that we are substituting prior template arguments into a
+    /// template template parameter.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          NamedDecl *Template, TemplateTemplateParmDecl *Param,
+                          ArrayRef TemplateArgs,
+                          SourceRange InstantiationRange);
 
-  /// Register \p D as specialization of all base functions in \p Bases in the
-  /// current `omp begin/end declare variant` scope.
-  void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
-      Decl *D, SmallVectorImpl &Bases);
+    /// Note that we are checking the default template argument
+    /// against the template parameter for a given template-id.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          TemplateDecl *Template, NamedDecl *Param,
+                          ArrayRef TemplateArgs,
+                          SourceRange InstantiationRange);
 
-  /// Act on \p D, a function definition inside of an `omp [begin/end] assumes`.
-  void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D);
+    struct ConstraintsCheck {};
+    /// \brief Note that we are checking the constraints associated with some
+    /// constrained entity (a concept declaration or a template with associated
+    /// constraints).
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          ConstraintsCheck, NamedDecl *Template,
+                          ArrayRef TemplateArgs,
+                          SourceRange InstantiationRange);
 
-  /// Can we exit an OpenMP declare variant scope at the moment.
-  bool isInOpenMPDeclareVariantScope() const {
-    return !OMPDeclareVariantScopes.empty();
-  }
+    struct ConstraintSubstitution {};
+    /// \brief Note that we are checking a constraint expression associated
+    /// with a template declaration or as part of the satisfaction check of a
+    /// concept.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          ConstraintSubstitution, NamedDecl *Template,
+                          sema::TemplateDeductionInfo &DeductionInfo,
+                          SourceRange InstantiationRange);
 
-  ExprResult
-  VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind,
-                                        bool StrictlyPositive = true,
-                                        bool SuppressExprDiags = false);
+    struct ConstraintNormalization {};
+    /// \brief Note that we are normalizing a constraint expression.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          ConstraintNormalization, NamedDecl *Template,
+                          SourceRange InstantiationRange);
 
-  /// Given the potential call expression \p Call, determine if there is a
-  /// specialization via the OpenMP declare variant mechanism available. If
-  /// there is, return the specialized call expression, otherwise return the
-  /// original \p Call.
-  ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope,
-                             SourceLocation LParenLoc, MultiExprArg ArgExprs,
-                             SourceLocation RParenLoc, Expr *ExecConfig);
+    struct ParameterMappingSubstitution {};
+    /// \brief Note that we are subtituting into the parameter mapping of an
+    /// atomic constraint during constraint normalization.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          ParameterMappingSubstitution, NamedDecl *Template,
+                          SourceRange InstantiationRange);
 
-  /// Handle a `omp begin declare variant`.
-  void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI);
+    /// \brief Note that we are substituting template arguments into a part of
+    /// a requirement of a requires expression.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          concepts::Requirement *Req,
+                          sema::TemplateDeductionInfo &DeductionInfo,
+                          SourceRange InstantiationRange = SourceRange());
 
-  /// Handle a `omp end declare variant`.
-  void ActOnOpenMPEndDeclareVariant();
+    /// \brief Note that we are checking the satisfaction of the constraint
+    /// expression inside of a nested requirement.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          concepts::NestedRequirement *Req, ConstraintsCheck,
+                          SourceRange InstantiationRange = SourceRange());
 
-  /// Checks if the variant/multiversion functions are compatible.
-  bool areMultiversionVariantFunctionsCompatible(
-      const FunctionDecl *OldFD, const FunctionDecl *NewFD,
-      const PartialDiagnostic &NoProtoDiagID,
-      const PartialDiagnosticAt &NoteCausedDiagIDAt,
-      const PartialDiagnosticAt &NoSupportDiagIDAt,
-      const PartialDiagnosticAt &DiffDiagIDAt, bool TemplatesSupported,
-      bool ConstexprSupported, bool CLinkageMayDiffer);
+    /// \brief Note that we are checking a requires clause.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          const RequiresExpr *E,
+                          sema::TemplateDeductionInfo &DeductionInfo,
+                          SourceRange InstantiationRange);
 
-  /// Function tries to capture lambda's captured variables in the OpenMP region
-  /// before the original lambda is captured.
-  void tryCaptureOpenMPLambdas(ValueDecl *V);
+    struct BuildingDeductionGuidesTag {};
+    /// \brief Note that we are building deduction guides.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          TemplateDecl *Entity, BuildingDeductionGuidesTag,
+                          SourceRange InstantiationRange = SourceRange());
 
-  /// Return true if the provided declaration \a VD should be captured by
-  /// reference.
-  /// \param Level Relative level of nested OpenMP construct for that the check
-  /// is performed.
-  /// \param OpenMPCaptureLevel Capture level within an OpenMP construct.
-  bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
-                             unsigned OpenMPCaptureLevel) const;
+    /// Note that we have finished instantiating this template.
+    void Clear();
 
-  /// Check if the specified variable is used in one of the private
-  /// clauses (private, firstprivate, lastprivate, reduction etc.) in OpenMP
-  /// constructs.
-  VarDecl *isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo = false,
-                                unsigned StopAt = 0);
+    ~InstantiatingTemplate() { Clear(); }
 
-  /// The member expression(this->fd) needs to be rebuilt in the template
-  /// instantiation to generate private copy for OpenMP when default
-  /// clause is used. The function will return true if default
-  /// cluse is used.
-  bool isOpenMPRebuildMemberExpr(ValueDecl *D);
+    /// Determines whether we have exceeded the maximum
+    /// recursive template instantiations.
+    bool isInvalid() const { return Invalid; }
 
-  ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
-                                   ExprObjectKind OK, SourceLocation Loc);
+    /// Determine whether we are already instantiating this
+    /// specialization in some surrounding active instantiation.
+    bool isAlreadyInstantiating() const { return AlreadyInstantiating; }
 
-  /// If the current region is a loop-based region, mark the start of the loop
-  /// construct.
-  void startOpenMPLoop();
+  private:
+    Sema &SemaRef;
+    bool Invalid;
+    bool AlreadyInstantiating;
+    bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
+                                 SourceRange InstantiationRange);
 
-  /// If the current region is a range loop-based region, mark the start of the
-  /// loop construct.
-  void startOpenMPCXXRangeFor();
+    InstantiatingTemplate(
+        Sema &SemaRef, CodeSynthesisContext::SynthesisKind Kind,
+        SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
+        Decl *Entity, NamedDecl *Template = nullptr,
+        ArrayRef TemplateArgs = std::nullopt,
+        sema::TemplateDeductionInfo *DeductionInfo = nullptr);
 
-  /// Check if the specified variable is used in 'private' clause.
-  /// \param Level Relative level of nested OpenMP construct for that the check
-  /// is performed.
-  OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
-                                       unsigned CapLevel) const;
+    InstantiatingTemplate(const InstantiatingTemplate &) = delete;
 
-  /// Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.)
-  /// for \p FD based on DSA for the provided corresponding captured declaration
-  /// \p D.
-  void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level);
+    InstantiatingTemplate &operator=(const InstantiatingTemplate &) = delete;
+  };
 
-  /// Check if the specified variable is captured  by 'target' directive.
-  /// \param Level Relative level of nested OpenMP construct for that the check
-  /// is performed.
-  bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
-                                  unsigned CaptureLevel) const;
+  bool SubstTemplateArgument(const TemplateArgumentLoc &Input,
+                             const MultiLevelTemplateArgumentList &TemplateArgs,
+                             TemplateArgumentLoc &Output);
+  bool
+  SubstTemplateArguments(ArrayRef Args,
+                         const MultiLevelTemplateArgumentList &TemplateArgs,
+                         TemplateArgumentListInfo &Outputs);
 
-  /// Check if the specified global variable must be captured  by outer capture
-  /// regions.
-  /// \param Level Relative level of nested OpenMP construct for that
-  /// the check is performed.
-  bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
-                                  unsigned CaptureLevel) const;
+  MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
+      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);
 
-  ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc,
-                                                    Expr *Op);
-  /// Called on start of new data sharing attribute block.
-  void StartOpenMPDSABlock(OpenMPDirectiveKind K,
-                           const DeclarationNameInfo &DirName, Scope *CurScope,
-                           SourceLocation Loc);
-  /// Start analysis of clauses.
-  void StartOpenMPClause(OpenMPClauseKind K);
-  /// End analysis of clauses.
-  void EndOpenMPClause();
-  /// Called on end of data sharing attribute block.
-  void EndOpenMPDSABlock(Stmt *CurDirective);
+  /// RAII object to handle the state changes required to synthesize
+  /// a function body.
+  class SynthesizedFunctionScope {
+    Sema &S;
+    Sema::ContextRAII SavedContext;
+    bool PushedCodeSynthesisContext = false;
 
-  /// Check if the current region is an OpenMP loop region and if it is,
-  /// mark loop control variable, used in \p Init for loop initialization, as
-  /// private by default.
-  /// \param Init First part of the for loop.
-  void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init);
+  public:
+    SynthesizedFunctionScope(Sema &S, DeclContext *DC)
+        : S(S), SavedContext(S, DC) {
+      auto *FD = dyn_cast(DC);
+      S.PushFunctionScope();
+      S.PushExpressionEvaluationContext(
+          (FD && FD->isConsteval())
+              ? ExpressionEvaluationContext::ImmediateFunctionContext
+              : ExpressionEvaluationContext::PotentiallyEvaluated);
+      if (FD) {
+        FD->setWillHaveBody(true);
+        S.ExprEvalContexts.back().InImmediateFunctionContext =
+            FD->isImmediateFunction() ||
+            S.ExprEvalContexts[S.ExprEvalContexts.size() - 2]
+                .isConstantEvaluated();
+        S.ExprEvalContexts.back().InImmediateEscalatingFunctionContext =
+            S.getLangOpts().CPlusPlus20 && FD->isImmediateEscalating();
+      } else
+        assert(isa(DC));
+    }
 
-  /// Called on well-formed '\#pragma omp metadirective' after parsing
-  /// of the  associated statement.
-  StmtResult ActOnOpenMPMetaDirective(ArrayRef Clauses,
-                                      Stmt *AStmt, SourceLocation StartLoc,
-                                      SourceLocation EndLoc);
+    void addContextNote(SourceLocation UseLoc) {
+      assert(!PushedCodeSynthesisContext);
 
-  // OpenMP directives and clauses.
-  /// Called on correct id-expression from the '#pragma omp
-  /// threadprivate'.
-  ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec,
-                                     const DeclarationNameInfo &Id,
-                                     OpenMPDirectiveKind Kind);
-  /// Called on well-formed '#pragma omp threadprivate'.
-  DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(
-                                     SourceLocation Loc,
-                                     ArrayRef VarList);
-  /// Builds a new OpenMPThreadPrivateDecl and checks its correctness.
-  OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(SourceLocation Loc,
-                                                  ArrayRef VarList);
-  /// Called on well-formed '#pragma omp allocate'.
-  DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc,
-                                              ArrayRef VarList,
-                                              ArrayRef Clauses,
-                                              DeclContext *Owner = nullptr);
+      Sema::CodeSynthesisContext Ctx;
+      Ctx.Kind = Sema::CodeSynthesisContext::DefiningSynthesizedFunction;
+      Ctx.PointOfInstantiation = UseLoc;
+      Ctx.Entity = cast(S.CurContext);
+      S.pushCodeSynthesisContext(Ctx);
 
-  /// Called on well-formed '#pragma omp [begin] assume[s]'.
-  void ActOnOpenMPAssumesDirective(SourceLocation Loc,
-                                   OpenMPDirectiveKind DKind,
-                                   ArrayRef Assumptions,
-                                   bool SkippedClauses);
+      PushedCodeSynthesisContext = true;
+    }
 
-  /// Check if there is an active global `omp begin assumes` directive.
-  bool isInOpenMPAssumeScope() const { return !OMPAssumeScoped.empty(); }
+    ~SynthesizedFunctionScope() {
+      if (PushedCodeSynthesisContext)
+        S.popCodeSynthesisContext();
+      if (auto *FD = dyn_cast(S.CurContext)) {
+        FD->setWillHaveBody(false);
+        S.CheckImmediateEscalatingFunctionDefinition(FD, S.getCurFunction());
+      }
+      S.PopExpressionEvaluationContext();
+      S.PopFunctionScopeInfo();
+    }
+  };
 
-  /// Check if there is an active global `omp assumes` directive.
-  bool hasGlobalOpenMPAssumes() const { return !OMPAssumeGlobal.empty(); }
+  /// List of active code synthesis contexts.
+  ///
+  /// This vector is treated as a stack. As synthesis of one entity requires
+  /// synthesis of another, additional contexts are pushed onto the stack.
+  SmallVector CodeSynthesisContexts;
 
-  /// Called on well-formed '#pragma omp end assumes'.
-  void ActOnOpenMPEndAssumesDirective();
+  /// Specializations whose definitions are currently being instantiated.
+  llvm::DenseSet> InstantiatingSpecializations;
 
-  /// Called on well-formed '#pragma omp requires'.
-  DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc,
-                                              ArrayRef ClauseList);
-  /// Check restrictions on Requires directive
-  OMPRequiresDecl *CheckOMPRequiresDecl(SourceLocation Loc,
-                                        ArrayRef Clauses);
-  /// Check if the specified type is allowed to be used in 'omp declare
-  /// reduction' construct.
-  QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
-                                           TypeResult ParsedType);
-  /// Called on start of '#pragma omp declare reduction'.
-  DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(
-      Scope *S, DeclContext *DC, DeclarationName Name,
-      ArrayRef> ReductionTypes,
-      AccessSpecifier AS, Decl *PrevDeclInScope = nullptr);
-  /// Initialize declare reduction construct initializer.
-  void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D);
-  /// Finish current declare reduction construct initializer.
-  void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner);
-  /// Initialize declare reduction construct initializer.
-  /// \return omp_priv variable.
-  VarDecl *ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D);
-  /// Finish current declare reduction construct initializer.
-  void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer,
-                                                 VarDecl *OmpPrivParm);
-  /// Called at the end of '#pragma omp declare reduction'.
-  DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(
-      Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid);
+  /// Non-dependent types used in templates that have already been instantiated
+  /// by some template instantiation.
+  llvm::DenseSet InstantiatedNonDependentTypes;
 
-  /// Check variable declaration in 'omp declare mapper' construct.
-  TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D);
-  /// Check if the specified type is allowed to be used in 'omp declare
-  /// mapper' construct.
-  QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
-                                        TypeResult ParsedType);
-  /// Called on start of '#pragma omp declare mapper'.
-  DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(
-      Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
-      SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
-      Expr *MapperVarRef, ArrayRef Clauses,
-      Decl *PrevDeclInScope = nullptr);
-  /// Build the mapper variable of '#pragma omp declare mapper'.
-  ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S,
-                                                      QualType MapperType,
-                                                      SourceLocation StartLoc,
-                                                      DeclarationName VN);
-  void ActOnOpenMPIteratorVarDecl(VarDecl *VD);
-  bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const;
-  const ValueDecl *getOpenMPDeclareMapperVarName() const;
+  /// Extra modules inspected when performing a lookup during a template
+  /// instantiation. Computed lazily.
+  SmallVector CodeSynthesisContextLookupModules;
 
-  /// Called on the start of target region i.e. '#pragma omp declare target'.
-  bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI);
+  /// Cache of additional modules that should be used for name lookup
+  /// within the current template instantiation. Computed lazily; use
+  /// getLookupModules() to get a complete set.
+  llvm::DenseSet LookupModulesCache;
 
-  /// Called at the end of target region i.e. '#pragma omp end declare target'.
-  const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective();
+  /// Map from the most recent declaration of a namespace to the most
+  /// recent visible declaration of that namespace.
+  llvm::DenseMap VisibleNamespaceCache;
 
-  /// Called once a target context is completed, that can be when a
-  /// '#pragma omp end declare target' was encountered or when a
-  /// '#pragma omp declare target' without declaration-definition-seq was
-  /// encountered.
-  void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI);
+  /// Whether we are in a SFINAE context that is not associated with
+  /// template instantiation.
+  ///
+  /// This is used when setting up a SFINAE trap (\c see SFINAETrap) outside
+  /// of a template instantiation or template argument deduction.
+  bool InNonInstantiationSFINAEContext;
 
-  /// Report unterminated 'omp declare target' or 'omp begin declare target' at
-  /// the end of a compilation unit.
-  void DiagnoseUnterminatedOpenMPDeclareTarget();
+  /// The number of \p CodeSynthesisContexts that are not template
+  /// instantiations and, therefore, should not be counted as part of the
+  /// instantiation depth.
+  ///
+  /// When the instantiation depth reaches the user-configurable limit
+  /// \p LangOptions::InstantiationDepth we will abort instantiation.
+  // FIXME: Should we have a similar limit for other forms of synthesis?
+  unsigned NonInstantiationEntries;
 
-  /// Searches for the provided declaration name for OpenMP declare target
-  /// directive.
-  NamedDecl *lookupOpenMPDeclareTargetName(Scope *CurScope,
-                                           CXXScopeSpec &ScopeSpec,
-                                           const DeclarationNameInfo &Id);
+  /// The depth of the context stack at the point when the most recent
+  /// error or warning was produced.
+  ///
+  /// This value is used to suppress printing of redundant context stacks
+  /// when there are multiple errors or warnings in the same instantiation.
+  // FIXME: Does this belong in Sema? It's tough to implement it anywhere else.
+  unsigned LastEmittedCodeSynthesisContextDepth = 0;
 
-  /// Called on correct id-expression from the '#pragma omp declare target'.
-  void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
-                                    OMPDeclareTargetDeclAttr::MapTypeTy MT,
-                                    DeclareTargetContextInfo &DTCI);
+  /// The template instantiation callbacks to trace or track
+  /// instantiations (objects can be chained).
+  ///
+  /// This callbacks is used to print, trace or track template
+  /// instantiations as they are being constructed.
+  std::vector>
+      TemplateInstCallbacks;
 
-  /// Check declaration inside target region.
-  void
-  checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
-                                   SourceLocation IdLoc = SourceLocation());
+  /// The current index into pack expansion arguments that will be
+  /// used for substitution of parameter packs.
+  ///
+  /// The pack expansion index will be -1 to indicate that parameter packs
+  /// should be instantiated as themselves. Otherwise, the index specifies
+  /// which argument within the parameter pack will be used for substitution.
+  int ArgumentPackSubstitutionIndex;
 
-  /// Adds OMPDeclareTargetDeclAttr to referenced variables in declare target
-  /// directive.
-  void ActOnOpenMPDeclareTargetInitializer(Decl *D);
+  /// RAII object used to change the argument pack substitution index
+  /// within a \c Sema object.
+  ///
+  /// See \c ArgumentPackSubstitutionIndex for more information.
+  class ArgumentPackSubstitutionIndexRAII {
+    Sema &Self;
+    int OldSubstitutionIndex;
 
-  /// Finishes analysis of the deferred functions calls that may be declared as
-  /// host/nohost during device/host compilation.
-  void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
-                                     const FunctionDecl *Callee,
-                                     SourceLocation Loc);
+  public:
+    ArgumentPackSubstitutionIndexRAII(Sema &Self, int NewSubstitutionIndex)
+        : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) {
+      Self.ArgumentPackSubstitutionIndex = NewSubstitutionIndex;
+    }
 
-  /// Return true if currently in OpenMP task with untied clause context.
-  bool isInOpenMPTaskUntiedContext() const;
+    ~ArgumentPackSubstitutionIndexRAII() {
+      Self.ArgumentPackSubstitutionIndex = OldSubstitutionIndex;
+    }
+  };
 
-  /// Return true inside OpenMP declare target region.
-  bool isInOpenMPDeclareTargetContext() const {
-    return !DeclareTargetNesting.empty();
+  friend class ArgumentPackSubstitutionRAII;
+
+  void pushCodeSynthesisContext(CodeSynthesisContext Ctx);
+  void popCodeSynthesisContext();
+
+  void PrintContextStack() {
+    if (!CodeSynthesisContexts.empty() &&
+        CodeSynthesisContexts.size() != LastEmittedCodeSynthesisContextDepth) {
+      PrintInstantiationStack();
+      LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size();
+    }
+    if (PragmaAttributeCurrentTargetDecl)
+      PrintPragmaAttributeInstantiationPoint();
   }
-  /// Return true inside OpenMP target region.
-  bool isInOpenMPTargetExecutionDirective() const;
+  void PrintInstantiationStack();
 
-  /// Return the number of captured regions created for an OpenMP directive.
-  static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind);
+  /// Determines whether we are currently in a context where
+  /// template argument substitution failures are not considered
+  /// errors.
+  ///
+  /// \returns An empty \c Optional if we're not in a SFINAE context.
+  /// Otherwise, contains a pointer that, if non-NULL, contains the nearest
+  /// template-deduction context object, which can be used to capture
+  /// diagnostics that will be suppressed.
+  std::optional isSFINAEContext() const;
 
-  /// Initialization of captured region for OpenMP region.
-  void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope);
+  TypeSourceInfo *SubstType(TypeSourceInfo *T,
+                            const MultiLevelTemplateArgumentList &TemplateArgs,
+                            SourceLocation Loc, DeclarationName Entity,
+                            bool AllowDeducedTST = false);
 
-  /// Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to
-  /// an OpenMP loop directive.
-  StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt);
+  QualType SubstType(QualType T,
+                     const MultiLevelTemplateArgumentList &TemplateArgs,
+                     SourceLocation Loc, DeclarationName Entity);
 
-  /// Process a canonical OpenMP loop nest that can either be a canonical
-  /// literal loop (ForStmt or CXXForRangeStmt), or the generated loop of an
-  /// OpenMP loop transformation construct.
-  StmtResult ActOnOpenMPLoopnest(Stmt *AStmt);
+  TypeSourceInfo *SubstType(TypeLoc TL,
+                            const MultiLevelTemplateArgumentList &TemplateArgs,
+                            SourceLocation Loc, DeclarationName Entity);
 
-  /// End of OpenMP region.
+  TypeSourceInfo *SubstFunctionDeclType(
+      TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs,
+      SourceLocation Loc, DeclarationName Entity, CXXRecordDecl *ThisContext,
+      Qualifiers ThisTypeQuals, bool EvaluateConstraints = true);
+  void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
+                          const MultiLevelTemplateArgumentList &Args);
+  bool SubstExceptionSpec(SourceLocation Loc,
+                          FunctionProtoType::ExceptionSpecInfo &ESI,
+                          SmallVectorImpl &ExceptionStorage,
+                          const MultiLevelTemplateArgumentList &Args);
+  ParmVarDecl *
+  SubstParmVarDecl(ParmVarDecl *D,
+                   const MultiLevelTemplateArgumentList &TemplateArgs,
+                   int indexAdjustment, std::optional NumExpansions,
+                   bool ExpectParameterPack, bool EvaluateConstraints = true);
+  bool SubstParmTypes(SourceLocation Loc, ArrayRef Params,
+                      const FunctionProtoType::ExtParameterInfo *ExtParamInfos,
+                      const MultiLevelTemplateArgumentList &TemplateArgs,
+                      SmallVectorImpl &ParamTypes,
+                      SmallVectorImpl *OutParams,
+                      ExtParameterInfoBuilder &ParamInfos);
+  bool SubstDefaultArgument(SourceLocation Loc, ParmVarDecl *Param,
+                            const MultiLevelTemplateArgumentList &TemplateArgs,
+                            bool ForCallExpr = false);
+  ExprResult SubstExpr(Expr *E,
+                       const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  // A RAII type used by the TemplateDeclInstantiator and TemplateInstantiator
+  // to disable constraint evaluation, then restore the state.
+  template  struct ConstraintEvalRAII {
+    InstTy &TI;
+    bool OldValue;
+
+    ConstraintEvalRAII(InstTy &TI)
+        : TI(TI), OldValue(TI.getEvaluateConstraints()) {
+      TI.setEvaluateConstraints(false);
+    }
+    ~ConstraintEvalRAII() { TI.setEvaluateConstraints(OldValue); }
+  };
+
+  // Must be used instead of SubstExpr at 'constraint checking' time.
+  ExprResult
+  SubstConstraintExpr(Expr *E,
+                      const MultiLevelTemplateArgumentList &TemplateArgs);
+  // Unlike the above, this does not evaluates constraints.
+  ExprResult SubstConstraintExprWithoutSatisfaction(
+      Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  /// Substitute the given template arguments into a list of
+  /// expressions, expanding pack expansions if required.
   ///
-  /// \param S Statement associated with the current OpenMP region.
-  /// \param Clauses List of clauses for the current OpenMP region.
+  /// \param Exprs The list of expressions to substitute into.
   ///
-  /// \returns Statement for finished OpenMP region.
-  StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef Clauses);
-  StmtResult ActOnOpenMPExecutableDirective(
-      OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
-      OpenMPDirectiveKind CancelRegion, ArrayRef Clauses,
-      Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc,
-      OpenMPDirectiveKind PrevMappedDirective = llvm::omp::OMPD_unknown);
-  /// Called on well-formed '\#pragma omp parallel' after parsing
-  /// of the  associated statement.
-  StmtResult ActOnOpenMPParallelDirective(ArrayRef Clauses,
-                                          Stmt *AStmt,
-                                          SourceLocation StartLoc,
-                                          SourceLocation EndLoc);
-  using VarsWithInheritedDSAType =
-      llvm::SmallDenseMap;
-  /// Called on well-formed '\#pragma omp simd' after parsing
-  /// of the associated statement.
-  StmtResult
-  ActOnOpenMPSimdDirective(ArrayRef Clauses, Stmt *AStmt,
-                           SourceLocation StartLoc, SourceLocation EndLoc,
-                           VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '#pragma omp tile' after parsing of its clauses and
-  /// the associated statement.
-  StmtResult ActOnOpenMPTileDirective(ArrayRef Clauses,
-                                      Stmt *AStmt, SourceLocation StartLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed '#pragma omp unroll' after parsing of its clauses
-  /// and the associated statement.
-  StmtResult ActOnOpenMPUnrollDirective(ArrayRef Clauses,
-                                        Stmt *AStmt, SourceLocation StartLoc,
-                                        SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp for' after parsing
-  /// of the associated statement.
-  StmtResult
-  ActOnOpenMPForDirective(ArrayRef Clauses, Stmt *AStmt,
-                          SourceLocation StartLoc, SourceLocation EndLoc,
-                          VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp for simd' after parsing
-  /// of the associated statement.
-  StmtResult
-  ActOnOpenMPForSimdDirective(ArrayRef Clauses, Stmt *AStmt,
-                              SourceLocation StartLoc, SourceLocation EndLoc,
-                              VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp sections' after parsing
-  /// of the associated statement.
-  StmtResult ActOnOpenMPSectionsDirective(ArrayRef Clauses,
-                                          Stmt *AStmt, SourceLocation StartLoc,
-                                          SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp section' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc,
-                                         SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp scope' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPScopeDirective(ArrayRef Clauses,
-                                       Stmt *AStmt, SourceLocation StartLoc,
-                                       SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp single' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPSingleDirective(ArrayRef Clauses,
-                                        Stmt *AStmt, SourceLocation StartLoc,
-                                        SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp master' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc,
-                                        SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp critical' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName,
-                                          ArrayRef Clauses,
-                                          Stmt *AStmt, SourceLocation StartLoc,
-                                          SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp parallel for' after parsing
-  /// of the  associated statement.
-  StmtResult ActOnOpenMPParallelForDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp parallel for simd' after
-  /// parsing of the  associated statement.
-  StmtResult ActOnOpenMPParallelForSimdDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp parallel master' after
-  /// parsing of the  associated statement.
-  StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef Clauses,
-                                                Stmt *AStmt,
-                                                SourceLocation StartLoc,
-                                                SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp parallel masked' after
-  /// parsing of the associated statement.
-  StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef Clauses,
-                                                Stmt *AStmt,
-                                                SourceLocation StartLoc,
-                                                SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp parallel sections' after
-  /// parsing of the  associated statement.
-  StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef Clauses,
-                                                  Stmt *AStmt,
-                                                  SourceLocation StartLoc,
-                                                  SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp task' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPTaskDirective(ArrayRef Clauses,
-                                      Stmt *AStmt, SourceLocation StartLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp taskyield'.
-  StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
-                                           SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp error'.
-  /// Error direcitive is allowed in both declared and excutable contexts.
-  /// Adding InExContext to identify which context is called from.
-  StmtResult ActOnOpenMPErrorDirective(ArrayRef Clauses,
-                                       SourceLocation StartLoc,
-                                       SourceLocation EndLoc,
-                                       bool InExContext = true);
-  /// Called on well-formed '\#pragma omp barrier'.
-  StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
-                                         SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp taskwait'.
-  StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef Clauses,
-                                          SourceLocation StartLoc,
-                                          SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp taskgroup'.
-  StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef Clauses,
-                                           Stmt *AStmt, SourceLocation StartLoc,
-                                           SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp flush'.
-  StmtResult ActOnOpenMPFlushDirective(ArrayRef Clauses,
-                                       SourceLocation StartLoc,
-                                       SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp depobj'.
-  StmtResult ActOnOpenMPDepobjDirective(ArrayRef Clauses,
-                                        SourceLocation StartLoc,
-                                        SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp scan'.
-  StmtResult ActOnOpenMPScanDirective(ArrayRef Clauses,
-                                      SourceLocation StartLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp ordered' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPOrderedDirective(ArrayRef Clauses,
-                                         Stmt *AStmt, SourceLocation StartLoc,
-                                         SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp atomic' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPAtomicDirective(ArrayRef Clauses,
-                                        Stmt *AStmt, SourceLocation StartLoc,
-                                        SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp target' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPTargetDirective(ArrayRef Clauses,
-                                        Stmt *AStmt, SourceLocation StartLoc,
-                                        SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp target data' after parsing of
-  /// the associated statement.
-  StmtResult ActOnOpenMPTargetDataDirective(ArrayRef Clauses,
-                                            Stmt *AStmt, SourceLocation StartLoc,
-                                            SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp target enter data' after
-  /// parsing of the associated statement.
-  StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef Clauses,
-                                                 SourceLocation StartLoc,
-                                                 SourceLocation EndLoc,
-                                                 Stmt *AStmt);
-  /// Called on well-formed '\#pragma omp target exit data' after
-  /// parsing of the associated statement.
-  StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef Clauses,
-                                                SourceLocation StartLoc,
-                                                SourceLocation EndLoc,
-                                                Stmt *AStmt);
-  /// Called on well-formed '\#pragma omp target parallel' after
-  /// parsing of the associated statement.
-  StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef Clauses,
-                                                Stmt *AStmt,
-                                                SourceLocation StartLoc,
-                                                SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp target parallel for' after
-  /// parsing of the  associated statement.
-  StmtResult ActOnOpenMPTargetParallelForDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp teams' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPTeamsDirective(ArrayRef Clauses,
-                                       Stmt *AStmt, SourceLocation StartLoc,
-                                       SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp teams loop' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPTeamsGenericLoopDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp target teams loop' after parsing of
-  /// the associated statement.
-  StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp parallel loop' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPParallelGenericLoopDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp target parallel loop' after parsing
-  /// of the associated statement.
-  StmtResult ActOnOpenMPTargetParallelGenericLoopDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp cancellation point'.
-  StmtResult
-  ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
-                                        SourceLocation EndLoc,
-                                        OpenMPDirectiveKind CancelRegion);
-  /// Called on well-formed '\#pragma omp cancel'.
-  StmtResult ActOnOpenMPCancelDirective(ArrayRef Clauses,
-                                        SourceLocation StartLoc,
-                                        SourceLocation EndLoc,
-                                        OpenMPDirectiveKind CancelRegion);
-  /// Called on well-formed '\#pragma omp taskloop' after parsing of the
-  /// associated statement.
-  StmtResult
-  ActOnOpenMPTaskLoopDirective(ArrayRef Clauses, Stmt *AStmt,
-                               SourceLocation StartLoc, SourceLocation EndLoc,
-                               VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp taskloop simd' after parsing of
-  /// the associated statement.
-  StmtResult ActOnOpenMPTaskLoopSimdDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp master taskloop' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPMasterTaskLoopDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp master taskloop simd' after parsing of
-  /// the associated statement.
-  StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp parallel master taskloop' after
-  /// parsing of the associated statement.
-  StmtResult ActOnOpenMPParallelMasterTaskLoopDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp parallel master taskloop simd' after
-  /// parsing of the associated statement.
-  StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp masked taskloop' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPMaskedTaskLoopDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp masked taskloop simd' after parsing of
-  /// the associated statement.
-  StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp parallel masked taskloop' after
-  /// parsing of the associated statement.
-  StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp parallel masked taskloop simd' after
-  /// parsing of the associated statement.
-  StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp distribute' after parsing
-  /// of the associated statement.
-  StmtResult
-  ActOnOpenMPDistributeDirective(ArrayRef Clauses, Stmt *AStmt,
-                                 SourceLocation StartLoc, SourceLocation EndLoc,
-                                 VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp target update'.
-  StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef Clauses,
-                                              SourceLocation StartLoc,
-                                              SourceLocation EndLoc,
-                                              Stmt *AStmt);
-  /// Called on well-formed '\#pragma omp distribute parallel for' after
-  /// parsing of the associated statement.
-  StmtResult ActOnOpenMPDistributeParallelForDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp distribute parallel for simd'
-  /// after parsing of the associated statement.
-  StmtResult ActOnOpenMPDistributeParallelForSimdDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp distribute simd' after
-  /// parsing of the associated statement.
-  StmtResult ActOnOpenMPDistributeSimdDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp target parallel for simd' after
-  /// parsing of the associated statement.
-  StmtResult ActOnOpenMPTargetParallelForSimdDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp target simd' after parsing of
-  /// the associated statement.
-  StmtResult
-  ActOnOpenMPTargetSimdDirective(ArrayRef Clauses, Stmt *AStmt,
-                                 SourceLocation StartLoc, SourceLocation EndLoc,
-                                 VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp teams distribute' after parsing of
-  /// the associated statement.
-  StmtResult ActOnOpenMPTeamsDistributeDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp teams distribute simd' after parsing
-  /// of the associated statement.
-  StmtResult ActOnOpenMPTeamsDistributeSimdDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp teams distribute parallel for simd'
-  /// after parsing of the associated statement.
-  StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp teams distribute parallel for'
-  /// after parsing of the associated statement.
-  StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp target teams' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef Clauses,
-                                             Stmt *AStmt,
-                                             SourceLocation StartLoc,
-                                             SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp target teams distribute' after parsing
-  /// of the associated statement.
-  StmtResult ActOnOpenMPTargetTeamsDistributeDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp target teams distribute parallel for'
-  /// after parsing of the associated statement.
-  StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp target teams distribute parallel for
-  /// simd' after parsing of the associated statement.
-  StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp target teams distribute simd' after
-  /// parsing of the associated statement.
-  StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
-  /// Called on well-formed '\#pragma omp interop'.
-  StmtResult ActOnOpenMPInteropDirective(ArrayRef Clauses,
-                                         SourceLocation StartLoc,
-                                         SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp dispatch' after parsing of the
-  // /associated statement.
-  StmtResult ActOnOpenMPDispatchDirective(ArrayRef Clauses,
-                                          Stmt *AStmt, SourceLocation StartLoc,
-                                          SourceLocation EndLoc);
-  /// Called on well-formed '\#pragma omp masked' after parsing of the
-  // /associated statement.
-  StmtResult ActOnOpenMPMaskedDirective(ArrayRef Clauses,
-                                        Stmt *AStmt, SourceLocation StartLoc,
-                                        SourceLocation EndLoc);
+  /// \param IsCall Whether this is some form of call, in which case
+  /// default arguments will be dropped.
+  ///
+  /// \param TemplateArgs The set of template arguments to substitute.
+  ///
+  /// \param Outputs Will receive all of the substituted arguments.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool SubstExprs(ArrayRef Exprs, bool IsCall,
+                  const MultiLevelTemplateArgumentList &TemplateArgs,
+                  SmallVectorImpl &Outputs);
+
+  StmtResult SubstStmt(Stmt *S,
+                       const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  ExprResult
+  SubstInitializer(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs,
+                   bool CXXDirectInit);
+
+  bool SubstBaseSpecifiers(CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
+                           const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  bool InstantiateClass(SourceLocation PointOfInstantiation,
+                        CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
+                        const MultiLevelTemplateArgumentList &TemplateArgs,
+                        TemplateSpecializationKind TSK, bool Complain = true);
+
+  bool InstantiateEnum(SourceLocation PointOfInstantiation,
+                       EnumDecl *Instantiation, EnumDecl *Pattern,
+                       const MultiLevelTemplateArgumentList &TemplateArgs,
+                       TemplateSpecializationKind TSK);
+
+  bool InstantiateInClassInitializer(
+      SourceLocation PointOfInstantiation, FieldDecl *Instantiation,
+      FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  bool usesPartialOrExplicitSpecialization(
+      SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec);
+
+  bool InstantiateClassTemplateSpecialization(
+      SourceLocation PointOfInstantiation,
+      ClassTemplateSpecializationDecl *ClassTemplateSpec,
+      TemplateSpecializationKind TSK, bool Complain = true);
+
+  void
+  InstantiateClassMembers(SourceLocation PointOfInstantiation,
+                          CXXRecordDecl *Instantiation,
+                          const MultiLevelTemplateArgumentList &TemplateArgs,
+                          TemplateSpecializationKind TSK);
+
+  void InstantiateClassTemplateSpecializationMembers(
+      SourceLocation PointOfInstantiation,
+      ClassTemplateSpecializationDecl *ClassTemplateSpec,
+      TemplateSpecializationKind TSK);
+
+  NestedNameSpecifierLoc SubstNestedNameSpecifierLoc(
+      NestedNameSpecifierLoc NNS,
+      const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  DeclarationNameInfo
+  SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
+                           const MultiLevelTemplateArgumentList &TemplateArgs);
+  TemplateName
+  SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name,
+                    SourceLocation Loc,
+                    const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint *TC,
+                           const MultiLevelTemplateArgumentList &TemplateArgs,
+                           bool EvaluateConstraint);
+
+  /// Determine whether we are currently performing template instantiation.
+  bool inTemplateInstantiation() const {
+    return CodeSynthesisContexts.size() > NonInstantiationEntries;
+  }
+
+  ///@}
+
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \name C++ Template Declaration Instantiation
+  /// Implementations are in SemaTemplateInstantiateDecl.cpp
+  ///@{
+
+public:
+  /// An entity for which implicit template instantiation is required.
+  ///
+  /// The source location associated with the declaration is the first place in
+  /// the source code where the declaration was "used". It is not necessarily
+  /// the point of instantiation (which will be either before or after the
+  /// namespace-scope declaration that triggered this implicit instantiation),
+  /// However, it is the location that diagnostics should generally refer to,
+  /// because users will need to know what code triggered the instantiation.
+  typedef std::pair PendingImplicitInstantiation;
+
+  /// The queue of implicit template instantiations that are required
+  /// but have not yet been performed.
+  std::deque PendingInstantiations;
+
+  /// Queue of implicit template instantiations that cannot be performed
+  /// eagerly.
+  SmallVector LateParsedInstantiations;
+
+  SmallVector, 8> SavedVTableUses;
+  SmallVector, 8>
+      SavedPendingInstantiations;
+
+  /// The queue of implicit template instantiations that are required
+  /// and must be performed within the current local scope.
+  ///
+  /// This queue is only used for member functions of local classes in
+  /// templates, which must be instantiated in the same scope as their
+  /// enclosing function, so that they can reference function-local
+  /// types, static variables, enumerators, etc.
+  std::deque PendingLocalImplicitInstantiations;
+
+  class LocalEagerInstantiationScope {
+  public:
+    LocalEagerInstantiationScope(Sema &S) : S(S) {
+      SavedPendingLocalImplicitInstantiations.swap(
+          S.PendingLocalImplicitInstantiations);
+    }
+
+    void perform() { S.PerformPendingInstantiations(/*LocalOnly=*/true); }
+
+    ~LocalEagerInstantiationScope() {
+      assert(S.PendingLocalImplicitInstantiations.empty() &&
+             "there shouldn't be any pending local implicit instantiations");
+      SavedPendingLocalImplicitInstantiations.swap(
+          S.PendingLocalImplicitInstantiations);
+    }
+
+  private:
+    Sema &S;
+    std::deque
+        SavedPendingLocalImplicitInstantiations;
+  };
+
+  /// Records and restores the CurFPFeatures state on entry/exit of compound
+  /// statements.
+  class FPFeaturesStateRAII {
+  public:
+    FPFeaturesStateRAII(Sema &S);
+    ~FPFeaturesStateRAII();
+    FPOptionsOverride getOverrides() { return OldOverrides; }
+
+  private:
+    Sema &S;
+    FPOptions OldFPFeaturesState;
+    FPOptionsOverride OldOverrides;
+    LangOptions::FPEvalMethodKind OldEvalMethod;
+    SourceLocation OldFPPragmaLocation;
+  };
+
+  class GlobalEagerInstantiationScope {
+  public:
+    GlobalEagerInstantiationScope(Sema &S, bool Enabled)
+        : S(S), Enabled(Enabled) {
+      if (!Enabled)
+        return;
+
+      S.SavedPendingInstantiations.emplace_back();
+      S.SavedPendingInstantiations.back().swap(S.PendingInstantiations);
+
+      S.SavedVTableUses.emplace_back();
+      S.SavedVTableUses.back().swap(S.VTableUses);
+    }
+
+    void perform() {
+      if (Enabled) {
+        S.DefineUsedVTables();
+        S.PerformPendingInstantiations();
+      }
+    }
+
+    ~GlobalEagerInstantiationScope() {
+      if (!Enabled)
+        return;
+
+      // Restore the set of pending vtables.
+      assert(S.VTableUses.empty() &&
+             "VTableUses should be empty before it is discarded.");
+      S.VTableUses.swap(S.SavedVTableUses.back());
+      S.SavedVTableUses.pop_back();
+
+      // Restore the set of pending implicit instantiations.
+      if (S.TUKind != TU_Prefix || !S.LangOpts.PCHInstantiateTemplates) {
+        assert(S.PendingInstantiations.empty() &&
+               "PendingInstantiations should be empty before it is discarded.");
+        S.PendingInstantiations.swap(S.SavedPendingInstantiations.back());
+        S.SavedPendingInstantiations.pop_back();
+      } else {
+        // Template instantiations in the PCH may be delayed until the TU.
+        S.PendingInstantiations.swap(S.SavedPendingInstantiations.back());
+        S.PendingInstantiations.insert(
+            S.PendingInstantiations.end(),
+            S.SavedPendingInstantiations.back().begin(),
+            S.SavedPendingInstantiations.back().end());
+        S.SavedPendingInstantiations.pop_back();
+      }
+    }
+
+  private:
+    Sema &S;
+    bool Enabled;
+  };
+
+  ExplicitSpecifier instantiateExplicitSpecifier(
+      const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier ES);
+
+  struct LateInstantiatedAttribute {
+    const Attr *TmplAttr;
+    LocalInstantiationScope *Scope;
+    Decl *NewDecl;
+
+    LateInstantiatedAttribute(const Attr *A, LocalInstantiationScope *S,
+                              Decl *D)
+        : TmplAttr(A), Scope(S), NewDecl(D) {}
+  };
+  typedef SmallVector LateInstantiatedAttrVec;
+
+  void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
+                        const Decl *Pattern, Decl *Inst,
+                        LateInstantiatedAttrVec *LateAttrs = nullptr,
+                        LocalInstantiationScope *OuterMostScope = nullptr);
+  void updateAttrsForLateParsedTemplate(const Decl *Pattern, Decl *Inst);
+
+  void
+  InstantiateAttrsForDecl(const MultiLevelTemplateArgumentList &TemplateArgs,
+                          const Decl *Pattern, Decl *Inst,
+                          LateInstantiatedAttrVec *LateAttrs = nullptr,
+                          LocalInstantiationScope *OuterMostScope = nullptr);
+
+  void InstantiateDefaultCtorDefaultArgs(CXXConstructorDecl *Ctor);
+
+  bool InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
+                                  ParmVarDecl *Param);
+  void InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
+                                FunctionDecl *Function);
+  FunctionDecl *InstantiateFunctionDeclaration(
+      FunctionTemplateDecl *FTD, const TemplateArgumentList *Args,
+      SourceLocation Loc,
+      CodeSynthesisContext::SynthesisKind CSC =
+          CodeSynthesisContext::ExplicitTemplateArgumentSubstitution);
+  void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+                                     FunctionDecl *Function,
+                                     bool Recursive = false,
+                                     bool DefinitionRequired = false,
+                                     bool AtEndOfTU = false);
+  VarTemplateSpecializationDecl *BuildVarTemplateInstantiation(
+      VarTemplateDecl *VarTemplate, VarDecl *FromVar,
+      const TemplateArgumentList *PartialSpecArgs,
+      const TemplateArgumentListInfo &TemplateArgsInfo,
+      SmallVectorImpl &Converted,
+      SourceLocation PointOfInstantiation,
+      LateInstantiatedAttrVec *LateAttrs = nullptr,
+      LocalInstantiationScope *StartingScope = nullptr);
+  VarTemplateSpecializationDecl *CompleteVarTemplateSpecializationDecl(
+      VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl,
+      const MultiLevelTemplateArgumentList &TemplateArgs);
+  void
+  BuildVariableInstantiation(VarDecl *NewVar, VarDecl *OldVar,
+                             const MultiLevelTemplateArgumentList &TemplateArgs,
+                             LateInstantiatedAttrVec *LateAttrs,
+                             DeclContext *Owner,
+                             LocalInstantiationScope *StartingScope,
+                             bool InstantiatingVarTemplate = false,
+                             VarTemplateSpecializationDecl *PrevVTSD = nullptr);
+
+  void InstantiateVariableInitializer(
+      VarDecl *Var, VarDecl *OldVar,
+      const MultiLevelTemplateArgumentList &TemplateArgs);
+  void InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
+                                     VarDecl *Var, bool Recursive = false,
+                                     bool DefinitionRequired = false,
+                                     bool AtEndOfTU = false);
+
+  void InstantiateMemInitializers(
+      CXXConstructorDecl *New, const CXXConstructorDecl *Tmpl,
+      const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  NamedDecl *
+  FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
+                       const MultiLevelTemplateArgumentList &TemplateArgs,
+                       bool FindingInstantiatedContext = false);
+  DeclContext *
+  FindInstantiatedContext(SourceLocation Loc, DeclContext *DC,
+                          const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  Decl *SubstDecl(Decl *D, DeclContext *Owner,
+                  const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  /// Substitute the name and return type of a defaulted 'operator<=>' to form
+  /// an implicit 'operator=='.
+  FunctionDecl *SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD,
+                                           FunctionDecl *Spaceship);
+
+  void PerformPendingInstantiations(bool LocalOnly = false);
+
+  TemplateParameterList *
+  SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner,
+                      const MultiLevelTemplateArgumentList &TemplateArgs,
+                      bool EvaluateConstraints = true);
+
+  void PerformDependentDiagnostics(
+      const DeclContext *Pattern,
+      const MultiLevelTemplateArgumentList &TemplateArgs);
+
+private:
+  /// Introduce the instantiated local variables into the local
+  /// instantiation scope.
+  void addInstantiatedLocalVarsToScope(FunctionDecl *Function,
+                                       const FunctionDecl *PatternDecl,
+                                       LocalInstantiationScope &Scope);
+  /// Introduce the instantiated function parameters into the local
+  /// instantiation scope, and set the parameter names to those used
+  /// in the template.
+  bool addInstantiatedParametersToScope(
+      FunctionDecl *Function, const FunctionDecl *PatternDecl,
+      LocalInstantiationScope &Scope,
+      const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  int ParsingClassDepth = 0;
+
+  class SavePendingParsedClassStateRAII {
+  public:
+    SavePendingParsedClassStateRAII(Sema &S) : S(S) { swapSavedState(); }
+
+    ~SavePendingParsedClassStateRAII() {
+      assert(S.DelayedOverridingExceptionSpecChecks.empty() &&
+             "there shouldn't be any pending delayed exception spec checks");
+      assert(S.DelayedEquivalentExceptionSpecChecks.empty() &&
+             "there shouldn't be any pending delayed exception spec checks");
+      swapSavedState();
+    }
+
+  private:
+    Sema &S;
+    decltype(DelayedOverridingExceptionSpecChecks)
+        SavedOverridingExceptionSpecChecks;
+    decltype(DelayedEquivalentExceptionSpecChecks)
+        SavedEquivalentExceptionSpecChecks;
+
+    void swapSavedState() {
+      SavedOverridingExceptionSpecChecks.swap(
+          S.DelayedOverridingExceptionSpecChecks);
+      SavedEquivalentExceptionSpecChecks.swap(
+          S.DelayedEquivalentExceptionSpecChecks);
+    }
+  };
+
+  ///@}
+
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \name C++ Variadic Templates
+  /// Implementations are in SemaTemplateVariadic.cpp
+  ///@{
+
+public:
+  /// Determine whether an unexpanded parameter pack might be permitted in this
+  /// location. Useful for error recovery.
+  bool isUnexpandedParameterPackPermitted();
+
+  /// The context in which an unexpanded parameter pack is
+  /// being diagnosed.
+  ///
+  /// Note that the values of this enumeration line up with the first
+  /// argument to the \c err_unexpanded_parameter_pack diagnostic.
+  enum UnexpandedParameterPackContext {
+    /// An arbitrary expression.
+    UPPC_Expression = 0,
+
+    /// The base type of a class type.
+    UPPC_BaseType,
+
+    /// The type of an arbitrary declaration.
+    UPPC_DeclarationType,
+
+    /// The type of a data member.
+    UPPC_DataMemberType,
+
+    /// The size of a bit-field.
+    UPPC_BitFieldWidth,
+
+    /// The expression in a static assertion.
+    UPPC_StaticAssertExpression,
+
+    /// The fixed underlying type of an enumeration.
+    UPPC_FixedUnderlyingType,
+
+    /// The enumerator value.
+    UPPC_EnumeratorValue,
+
+    /// A using declaration.
+    UPPC_UsingDeclaration,
+
+    /// A friend declaration.
+    UPPC_FriendDeclaration,
+
+    /// A declaration qualifier.
+    UPPC_DeclarationQualifier,
+
+    /// An initializer.
+    UPPC_Initializer,
+
+    /// A default argument.
+    UPPC_DefaultArgument,
+
+    /// The type of a non-type template parameter.
+    UPPC_NonTypeTemplateParameterType,
+
+    /// The type of an exception.
+    UPPC_ExceptionType,
+
+    /// Explicit specialization.
+    UPPC_ExplicitSpecialization,
+
+    /// Partial specialization.
+    UPPC_PartialSpecialization,
+
+    /// Microsoft __if_exists.
+    UPPC_IfExists,
+
+    /// Microsoft __if_not_exists.
+    UPPC_IfNotExists,
+
+    /// Lambda expression.
+    UPPC_Lambda,
+
+    /// Block expression.
+    UPPC_Block,
+
+    /// A type constraint.
+    UPPC_TypeConstraint,
+
+    // A requirement in a requires-expression.
+    UPPC_Requirement,
+
+    // A requires-clause.
+    UPPC_RequiresClause,
+  };
+
+  /// Diagnose unexpanded parameter packs.
+  ///
+  /// \param Loc The location at which we should emit the diagnostic.
+  ///
+  /// \param UPPC The context in which we are diagnosing unexpanded
+  /// parameter packs.
+  ///
+  /// \param Unexpanded the set of unexpanded parameter packs.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool DiagnoseUnexpandedParameterPacks(
+      SourceLocation Loc, UnexpandedParameterPackContext UPPC,
+      ArrayRef Unexpanded);
+
+  /// If the given type contains an unexpanded parameter pack,
+  /// diagnose the error.
+  ///
+  /// \param Loc The source location where a diagnostc should be emitted.
+  ///
+  /// \param T The type that is being checked for unexpanded parameter
+  /// packs.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T,
+                                       UnexpandedParameterPackContext UPPC);
+
+  /// If the given expression contains an unexpanded parameter
+  /// pack, diagnose the error.
+  ///
+  /// \param E The expression that is being checked for unexpanded
+  /// parameter packs.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool DiagnoseUnexpandedParameterPack(
+      Expr *E, UnexpandedParameterPackContext UPPC = UPPC_Expression);
+
+  /// If the given requirees-expression contains an unexpanded reference to one
+  /// of its own parameter packs, diagnose the error.
+  ///
+  /// \param RE The requiress-expression that is being checked for unexpanded
+  /// parameter packs.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool DiagnoseUnexpandedParameterPackInRequiresExpr(RequiresExpr *RE);
+
+  /// If the given nested-name-specifier contains an unexpanded
+  /// parameter pack, diagnose the error.
+  ///
+  /// \param SS The nested-name-specifier that is being checked for
+  /// unexpanded parameter packs.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS,
+                                       UnexpandedParameterPackContext UPPC);
+
+  /// If the given name contains an unexpanded parameter pack,
+  /// diagnose the error.
+  ///
+  /// \param NameInfo The name (with source location information) that
+  /// is being checked for unexpanded parameter packs.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo,
+                                       UnexpandedParameterPackContext UPPC);
+
+  /// If the given template name contains an unexpanded parameter pack,
+  /// diagnose the error.
+  ///
+  /// \param Loc The location of the template name.
+  ///
+  /// \param Template The template name that is being checked for unexpanded
+  /// parameter packs.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool DiagnoseUnexpandedParameterPack(SourceLocation Loc,
+                                       TemplateName Template,
+                                       UnexpandedParameterPackContext UPPC);
+
+  /// If the given template argument contains an unexpanded parameter
+  /// pack, diagnose the error.
+  ///
+  /// \param Arg The template argument that is being checked for unexpanded
+  /// parameter packs.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg,
+                                       UnexpandedParameterPackContext UPPC);
+
+  /// Collect the set of unexpanded parameter packs within the given
+  /// template argument.
+  ///
+  /// \param Arg The template argument that will be traversed to find
+  /// unexpanded parameter packs.
+  void collectUnexpandedParameterPacks(
+      TemplateArgument Arg,
+      SmallVectorImpl &Unexpanded);
+
+  /// Collect the set of unexpanded parameter packs within the given
+  /// template argument.
+  ///
+  /// \param Arg The template argument that will be traversed to find
+  /// unexpanded parameter packs.
+  void collectUnexpandedParameterPacks(
+      TemplateArgumentLoc Arg,
+      SmallVectorImpl &Unexpanded);
+
+  /// Collect the set of unexpanded parameter packs within the given
+  /// type.
+  ///
+  /// \param T The type that will be traversed to find
+  /// unexpanded parameter packs.
+  void collectUnexpandedParameterPacks(
+      QualType T, SmallVectorImpl &Unexpanded);
+
+  /// Collect the set of unexpanded parameter packs within the given
+  /// type.
+  ///
+  /// \param TL The type that will be traversed to find
+  /// unexpanded parameter packs.
+  void collectUnexpandedParameterPacks(
+      TypeLoc TL, SmallVectorImpl &Unexpanded);
+
+  /// Collect the set of unexpanded parameter packs within the given
+  /// nested-name-specifier.
+  ///
+  /// \param NNS The nested-name-specifier that will be traversed to find
+  /// unexpanded parameter packs.
+  void collectUnexpandedParameterPacks(
+      NestedNameSpecifierLoc NNS,
+      SmallVectorImpl &Unexpanded);
+
+  /// Collect the set of unexpanded parameter packs within the given
+  /// name.
+  ///
+  /// \param NameInfo The name that will be traversed to find
+  /// unexpanded parameter packs.
+  void collectUnexpandedParameterPacks(
+      const DeclarationNameInfo &NameInfo,
+      SmallVectorImpl &Unexpanded);
+
+  /// Invoked when parsing a template argument followed by an
+  /// ellipsis, which creates a pack expansion.
+  ///
+  /// \param Arg The template argument preceding the ellipsis, which
+  /// may already be invalid.
+  ///
+  /// \param EllipsisLoc The location of the ellipsis.
+  ParsedTemplateArgument ActOnPackExpansion(const ParsedTemplateArgument &Arg,
+                                            SourceLocation EllipsisLoc);
+
+  /// Invoked when parsing a type followed by an ellipsis, which
+  /// creates a pack expansion.
+  ///
+  /// \param Type The type preceding the ellipsis, which will become
+  /// the pattern of the pack expansion.
+  ///
+  /// \param EllipsisLoc The location of the ellipsis.
+  TypeResult ActOnPackExpansion(ParsedType Type, SourceLocation EllipsisLoc);
+
+  /// Construct a pack expansion type from the pattern of the pack
+  /// expansion.
+  TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern,
+                                     SourceLocation EllipsisLoc,
+                                     std::optional NumExpansions);
+
+  /// Construct a pack expansion type from the pattern of the pack
+  /// expansion.
+  QualType CheckPackExpansion(QualType Pattern, SourceRange PatternRange,
+                              SourceLocation EllipsisLoc,
+                              std::optional NumExpansions);
+
+  /// Invoked when parsing an expression followed by an ellipsis, which
+  /// creates a pack expansion.
+  ///
+  /// \param Pattern The expression preceding the ellipsis, which will become
+  /// the pattern of the pack expansion.
+  ///
+  /// \param EllipsisLoc The location of the ellipsis.
+  ExprResult ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc);
+
+  /// Invoked when parsing an expression followed by an ellipsis, which
+  /// creates a pack expansion.
+  ///
+  /// \param Pattern The expression preceding the ellipsis, which will become
+  /// the pattern of the pack expansion.
+  ///
+  /// \param EllipsisLoc The location of the ellipsis.
+  ExprResult CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
+                                std::optional NumExpansions);
+
+  /// Determine whether we could expand a pack expansion with the
+  /// given set of parameter packs into separate arguments by repeatedly
+  /// transforming the pattern.
+  ///
+  /// \param EllipsisLoc The location of the ellipsis that identifies the
+  /// pack expansion.
+  ///
+  /// \param PatternRange The source range that covers the entire pattern of
+  /// the pack expansion.
+  ///
+  /// \param Unexpanded The set of unexpanded parameter packs within the
+  /// pattern.
+  ///
+  /// \param ShouldExpand Will be set to \c true if the transformer should
+  /// expand the corresponding pack expansions into separate arguments. When
+  /// set, \c NumExpansions must also be set.
+  ///
+  /// \param RetainExpansion Whether the caller should add an unexpanded
+  /// pack expansion after all of the expanded arguments. This is used
+  /// when extending explicitly-specified template argument packs per
+  /// C++0x [temp.arg.explicit]p9.
+  ///
+  /// \param NumExpansions The number of separate arguments that will be in
+  /// the expanded form of the corresponding pack expansion. This is both an
+  /// input and an output parameter, which can be set by the caller if the
+  /// number of expansions is known a priori (e.g., due to a prior substitution)
+  /// and will be set by the callee when the number of expansions is known.
+  /// The callee must set this value when \c ShouldExpand is \c true; it may
+  /// set this value in other cases.
+  ///
+  /// \returns true if an error occurred (e.g., because the parameter packs
+  /// are to be instantiated with arguments of different lengths), false
+  /// otherwise. If false, \c ShouldExpand (and possibly \c NumExpansions)
+  /// must be set.
+  bool CheckParameterPacksForExpansion(
+      SourceLocation EllipsisLoc, SourceRange PatternRange,
+      ArrayRef Unexpanded,
+      const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand,
+      bool &RetainExpansion, std::optional &NumExpansions);
+
+  /// Determine the number of arguments in the given pack expansion
+  /// type.
+  ///
+  /// This routine assumes that the number of arguments in the expansion is
+  /// consistent across all of the unexpanded parameter packs in its pattern.
+  ///
+  /// Returns an empty Optional if the type can't be expanded.
+  std::optional getNumArgumentsInExpansion(
+      QualType T, const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  /// Determine whether the given declarator contains any unexpanded
+  /// parameter packs.
+  ///
+  /// This routine is used by the parser to disambiguate function declarators
+  /// with an ellipsis prior to the ')', e.g.,
+  ///
+  /// \code
+  ///   void f(T...);
+  /// \endcode
+  ///
+  /// To determine whether we have an (unnamed) function parameter pack or
+  /// a variadic function.
+  ///
+  /// \returns true if the declarator contains any unexpanded parameter packs,
+  /// false otherwise.
+  bool containsUnexpandedParameterPacks(Declarator &D);
+
+  /// Returns the pattern of the pack expansion for a template argument.
+  ///
+  /// \param OrigLoc The template argument to expand.
+  ///
+  /// \param Ellipsis Will be set to the location of the ellipsis.
+  ///
+  /// \param NumExpansions Will be set to the number of expansions that will
+  /// be generated from this pack expansion, if known a priori.
+  TemplateArgumentLoc getTemplateArgumentPackExpansionPattern(
+      TemplateArgumentLoc OrigLoc, SourceLocation &Ellipsis,
+      std::optional &NumExpansions) const;
+
+  /// Given a template argument that contains an unexpanded parameter pack, but
+  /// which has already been substituted, attempt to determine the number of
+  /// elements that will be produced once this argument is fully-expanded.
+  ///
+  /// This is intended for use when transforming 'sizeof...(Arg)' in order to
+  /// avoid actually expanding the pack where possible.
+  std::optional getFullyPackExpandedSize(TemplateArgument Arg);
+
+  ExprResult ActOnSizeofParameterPackExpr(Scope *S, SourceLocation OpLoc,
+                                          IdentifierInfo &Name,
+                                          SourceLocation NameLoc,
+                                          SourceLocation RParenLoc);
+
+  ExprResult ActOnPackIndexingExpr(Scope *S, Expr *PackExpression,
+                                   SourceLocation EllipsisLoc,
+                                   SourceLocation LSquareLoc, Expr *IndexExpr,
+                                   SourceLocation RSquareLoc);
+
+  ExprResult BuildPackIndexingExpr(Expr *PackExpression,
+                                   SourceLocation EllipsisLoc, Expr *IndexExpr,
+                                   SourceLocation RSquareLoc,
+                                   ArrayRef ExpandedExprs = {},
+                                   bool EmptyPack = false);
+
+  /// Handle a C++1z fold-expression: ( expr op ... op expr ).
+  ExprResult ActOnCXXFoldExpr(Scope *S, SourceLocation LParenLoc, Expr *LHS,
+                              tok::TokenKind Operator,
+                              SourceLocation EllipsisLoc, Expr *RHS,
+                              SourceLocation RParenLoc);
+  ExprResult BuildCXXFoldExpr(UnresolvedLookupExpr *Callee,
+                              SourceLocation LParenLoc, Expr *LHS,
+                              BinaryOperatorKind Operator,
+                              SourceLocation EllipsisLoc, Expr *RHS,
+                              SourceLocation RParenLoc,
+                              std::optional NumExpansions);
+  ExprResult BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc,
+                                   BinaryOperatorKind Operator);
+
+  ///@}
+
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \name Constraints and Concepts
+  /// Implementations are in SemaConcept.cpp
+  ///@{
+
+public:
+  void PushSatisfactionStackEntry(const NamedDecl *D,
+                                  const llvm::FoldingSetNodeID &ID) {
+    const NamedDecl *Can = cast(D->getCanonicalDecl());
+    SatisfactionStack.emplace_back(Can, ID);
+  }
+
+  void PopSatisfactionStackEntry() { SatisfactionStack.pop_back(); }
+
+  bool SatisfactionStackContains(const NamedDecl *D,
+                                 const llvm::FoldingSetNodeID &ID) const {
+    const NamedDecl *Can = cast(D->getCanonicalDecl());
+    return llvm::find(SatisfactionStack, SatisfactionStackEntryTy{Can, ID}) !=
+           SatisfactionStack.end();
+  }
+
+  using SatisfactionStackEntryTy =
+      std::pair;
+
+  // Resets the current SatisfactionStack for cases where we are instantiating
+  // constraints as a 'side effect' of normal instantiation in a way that is not
+  // indicative of recursive definition.
+  class SatisfactionStackResetRAII {
+    llvm::SmallVector BackupSatisfactionStack;
+    Sema &SemaRef;
+
+  public:
+    SatisfactionStackResetRAII(Sema &S) : SemaRef(S) {
+      SemaRef.SwapSatisfactionStack(BackupSatisfactionStack);
+    }
+
+    ~SatisfactionStackResetRAII() {
+      SemaRef.SwapSatisfactionStack(BackupSatisfactionStack);
+    }
+  };
+
+  void SwapSatisfactionStack(
+      llvm::SmallVectorImpl &NewSS) {
+    SatisfactionStack.swap(NewSS);
+  }
+
+  /// Check whether the given expression is a valid constraint expression.
+  /// A diagnostic is emitted if it is not, false is returned, and
+  /// PossibleNonPrimary will be set to true if the failure might be due to a
+  /// non-primary expression being used as an atomic constraint.
+  bool CheckConstraintExpression(const Expr *CE, Token NextToken = Token(),
+                                 bool *PossibleNonPrimary = nullptr,
+                                 bool IsTrailingRequiresClause = false);
+
+  /// \brief Check whether the given list of constraint expressions are
+  /// satisfied (as if in a 'conjunction') given template arguments.
+  /// \param Template the template-like entity that triggered the constraints
+  /// check (either a concept or a constrained entity).
+  /// \param ConstraintExprs a list of constraint expressions, treated as if
+  /// they were 'AND'ed together.
+  /// \param TemplateArgLists the list of template arguments to substitute into
+  /// the constraint expression.
+  /// \param TemplateIDRange The source range of the template id that
+  /// caused the constraints check.
+  /// \param Satisfaction if true is returned, will contain details of the
+  /// satisfaction, with enough information to diagnose an unsatisfied
+  /// expression.
+  /// \returns true if an error occurred and satisfaction could not be checked,
+  /// false otherwise.
+  bool CheckConstraintSatisfaction(
+      const NamedDecl *Template, ArrayRef ConstraintExprs,
+      const MultiLevelTemplateArgumentList &TemplateArgLists,
+      SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
+    llvm::SmallVector Converted;
+    return CheckConstraintSatisfaction(Template, ConstraintExprs, Converted,
+                                       TemplateArgLists, TemplateIDRange,
+                                       Satisfaction);
+  }
+
+  /// \brief Check whether the given list of constraint expressions are
+  /// satisfied (as if in a 'conjunction') given template arguments.
+  /// Additionally, takes an empty list of Expressions which is populated with
+  /// the instantiated versions of the ConstraintExprs.
+  /// \param Template the template-like entity that triggered the constraints
+  /// check (either a concept or a constrained entity).
+  /// \param ConstraintExprs a list of constraint expressions, treated as if
+  /// they were 'AND'ed together.
+  /// \param ConvertedConstraints a out parameter that will get populated with
+  /// the instantiated version of the ConstraintExprs if we successfully checked
+  /// satisfaction.
+  /// \param TemplateArgList the multi-level list of template arguments to
+  /// substitute into the constraint expression. This should be relative to the
+  /// top-level (hence multi-level), since we need to instantiate fully at the
+  /// time of checking.
+  /// \param TemplateIDRange The source range of the template id that
+  /// caused the constraints check.
+  /// \param Satisfaction if true is returned, will contain details of the
+  /// satisfaction, with enough information to diagnose an unsatisfied
+  /// expression.
+  /// \returns true if an error occurred and satisfaction could not be checked,
+  /// false otherwise.
+  bool CheckConstraintSatisfaction(
+      const NamedDecl *Template, ArrayRef ConstraintExprs,
+      llvm::SmallVectorImpl &ConvertedConstraints,
+      const MultiLevelTemplateArgumentList &TemplateArgList,
+      SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
+
+  /// \brief Check whether the given non-dependent constraint expression is
+  /// satisfied. Returns false and updates Satisfaction with the satisfaction
+  /// verdict if successful, emits a diagnostic and returns true if an error
+  /// occurred and satisfaction could not be determined.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool CheckConstraintSatisfaction(const Expr *ConstraintExpr,
+                                   ConstraintSatisfaction &Satisfaction);
+
+  /// Check whether the given function decl's trailing requires clause is
+  /// satisfied, if any. Returns false and updates Satisfaction with the
+  /// satisfaction verdict if successful, emits a diagnostic and returns true if
+  /// an error occurred and satisfaction could not be determined.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool CheckFunctionConstraints(const FunctionDecl *FD,
+                                ConstraintSatisfaction &Satisfaction,
+                                SourceLocation UsageLoc = SourceLocation(),
+                                bool ForOverloadResolution = false);
+
+  // Calculates whether two constraint expressions are equal irrespective of a
+  // difference in 'depth'. This takes a pair of optional 'NamedDecl's 'Old' and
+  // 'New', which are the "source" of the constraint, since this is necessary
+  // for figuring out the relative 'depth' of the constraint. The depth of the
+  // 'primary template' and the 'instantiated from' templates aren't necessarily
+  // the same, such as a case when one is a 'friend' defined in a class.
+  bool AreConstraintExpressionsEqual(const NamedDecl *Old,
+                                     const Expr *OldConstr,
+                                     const TemplateCompareNewDeclInfo &New,
+                                     const Expr *NewConstr);
+
+  // Calculates whether the friend function depends on an enclosing template for
+  // the purposes of [temp.friend] p9.
+  bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD);
+
+  /// \brief Ensure that the given template arguments satisfy the constraints
+  /// associated with the given template, emitting a diagnostic if they do not.
+  ///
+  /// \param Template The template to which the template arguments are being
+  /// provided.
+  ///
+  /// \param TemplateArgs The converted, canonicalized template arguments.
+  ///
+  /// \param TemplateIDRange The source range of the template id that
+  /// caused the constraints check.
+  ///
+  /// \returns true if the constrains are not satisfied or could not be checked
+  /// for satisfaction, false if the constraints are satisfied.
+  bool EnsureTemplateArgumentListConstraints(
+      TemplateDecl *Template,
+      const MultiLevelTemplateArgumentList &TemplateArgs,
+      SourceRange TemplateIDRange);
+
+  bool CheckInstantiatedFunctionTemplateConstraints(
+      SourceLocation PointOfInstantiation, FunctionDecl *Decl,
+      ArrayRef TemplateArgs,
+      ConstraintSatisfaction &Satisfaction);
+
+  /// \brief Emit diagnostics explaining why a constraint expression was deemed
+  /// unsatisfied.
+  /// \param First whether this is the first time an unsatisfied constraint is
+  /// diagnosed for this error.
+  void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction,
+                                     bool First = true);
+
+  /// \brief Emit diagnostics explaining why a constraint expression was deemed
+  /// unsatisfied.
+  void
+  DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction,
+                                bool First = true);
+
+  const NormalizedConstraint *getNormalizedAssociatedConstraints(
+      NamedDecl *ConstrainedDecl, ArrayRef AssociatedConstraints);
+
+  /// \brief Check whether the given declaration's associated constraints are
+  /// at least as constrained than another declaration's according to the
+  /// partial ordering of constraints.
+  ///
+  /// \param Result If no error occurred, receives the result of true if D1 is
+  /// at least constrained than D2, and false otherwise.
+  ///
+  /// \returns true if an error occurred, false otherwise.
+  bool IsAtLeastAsConstrained(NamedDecl *D1, MutableArrayRef AC1,
+                              NamedDecl *D2, MutableArrayRef AC2,
+                              bool &Result);
+
+  /// If D1 was not at least as constrained as D2, but would've been if a pair
+  /// of atomic constraints involved had been declared in a concept and not
+  /// repeated in two separate places in code.
+  /// \returns true if such a diagnostic was emitted, false otherwise.
+  bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
+      NamedDecl *D1, ArrayRef AC1, NamedDecl *D2,
+      ArrayRef AC2);
+
+private:
+  /// Caches pairs of template-like decls whose associated constraints were
+  /// checked for subsumption and whether or not the first's constraints did in
+  /// fact subsume the second's.
+  llvm::DenseMap, bool> SubsumptionCache;
+  /// Caches the normalized associated constraints of declarations (concepts or
+  /// constrained declarations). If an error occurred while normalizing the
+  /// associated constraints of the template or concept, nullptr will be cached
+  /// here.
+  llvm::DenseMap NormalizationCache;
+
+  llvm::ContextualFoldingSet
+      SatisfactionCache;
+
+  // The current stack of constraint satisfactions, so we can exit-early.
+  llvm::SmallVector SatisfactionStack;
+
+  /// Introduce the instantiated captures of the lambda into the local
+  /// instantiation scope.
+  bool addInstantiatedCapturesToScope(
+      FunctionDecl *Function, const FunctionDecl *PatternDecl,
+      LocalInstantiationScope &Scope,
+      const MultiLevelTemplateArgumentList &TemplateArgs);
+
+  /// Used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in
+  /// the case of lambdas) set up the LocalInstantiationScope of the current
+  /// function.
+  bool
+  SetupConstraintScope(FunctionDecl *FD,
+                       std::optional> TemplateArgs,
+                       const MultiLevelTemplateArgumentList &MLTAL,
+                       LocalInstantiationScope &Scope);
+
+  /// Used during constraint checking, sets up the constraint template argument
+  /// lists, and calls SetupConstraintScope to set up the
+  /// LocalInstantiationScope to have the proper set of ParVarDecls configured.
+  std::optional
+  SetupConstraintCheckingTemplateArgumentsAndScope(
+      FunctionDecl *FD, std::optional> TemplateArgs,
+      LocalInstantiationScope &Scope);
+
+  ///@}
+
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \name Types
+  /// Implementations are in SemaType.cpp
+  ///@{
+
+public:
+  /// A mapping that describes the nullability we've seen in each header file.
+  FileNullabilityMap NullabilityMap;
+
+  static int getPrintable(int I) { return I; }
+  static unsigned getPrintable(unsigned I) { return I; }
+  static bool getPrintable(bool B) { return B; }
+  static const char *getPrintable(const char *S) { return S; }
+  static StringRef getPrintable(StringRef S) { return S; }
+  static const std::string &getPrintable(const std::string &S) { return S; }
+  static const IdentifierInfo *getPrintable(const IdentifierInfo *II) {
+    return II;
+  }
+  static DeclarationName getPrintable(DeclarationName N) { return N; }
+  static QualType getPrintable(QualType T) { return T; }
+  static SourceRange getPrintable(SourceRange R) { return R; }
+  static SourceRange getPrintable(SourceLocation L) { return L; }
+  static SourceRange getPrintable(const Expr *E) { return E->getSourceRange(); }
+  static SourceRange getPrintable(TypeLoc TL) { return TL.getSourceRange(); }
+
+  enum class CompleteTypeKind {
+    /// Apply the normal rules for complete types.  In particular,
+    /// treat all sizeless types as incomplete.
+    Normal,
+
+    /// Relax the normal rules for complete types so that they include
+    /// sizeless built-in types.
+    AcceptSizeless,
+
+    // FIXME: Eventually we should flip the default to Normal and opt in
+    // to AcceptSizeless rather than opt out of it.
+    Default = AcceptSizeless
+  };
+
+  /// Build a an Objective-C protocol-qualified 'id' type where no
+  /// base type was specified.
+  TypeResult actOnObjCProtocolQualifierType(
+      SourceLocation lAngleLoc, ArrayRef protocols,
+      ArrayRef protocolLocs, SourceLocation rAngleLoc);
+
+  /// Build a specialized and/or protocol-qualified Objective-C type.
+  TypeResult actOnObjCTypeArgsAndProtocolQualifiers(
+      Scope *S, SourceLocation Loc, ParsedType BaseType,
+      SourceLocation TypeArgsLAngleLoc, ArrayRef TypeArgs,
+      SourceLocation TypeArgsRAngleLoc, SourceLocation ProtocolLAngleLoc,
+      ArrayRef Protocols, ArrayRef ProtocolLocs,
+      SourceLocation ProtocolRAngleLoc);
 
-  /// Called on well-formed '\#pragma omp loop' after parsing of the
-  /// associated statement.
-  StmtResult ActOnOpenMPGenericLoopDirective(
-      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
-      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Build an Objective-C type parameter type.
+  QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
+                                  SourceLocation ProtocolLAngleLoc,
+                                  ArrayRef Protocols,
+                                  ArrayRef ProtocolLocs,
+                                  SourceLocation ProtocolRAngleLoc,
+                                  bool FailOnError = false);
 
-  /// Checks correctness of linear modifiers.
-  bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
-                                 SourceLocation LinLoc);
-  /// Checks that the specified declaration matches requirements for the linear
-  /// decls.
-  bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
-                             OpenMPLinearClauseKind LinKind, QualType Type,
-                             bool IsDeclareSimd = false);
+  /// Build an Objective-C object pointer type.
+  QualType BuildObjCObjectType(
+      QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc,
+      ArrayRef TypeArgs, SourceLocation TypeArgsRAngleLoc,
+      SourceLocation ProtocolLAngleLoc, ArrayRef Protocols,
+      ArrayRef ProtocolLocs, SourceLocation ProtocolRAngleLoc,
+      bool FailOnError, bool Rebuilding);
 
-  /// Called on well-formed '\#pragma omp declare simd' after parsing of
-  /// the associated method/function.
-  DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(
-      DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS,
-      Expr *Simdlen, ArrayRef Uniforms, ArrayRef Aligneds,
-      ArrayRef Alignments, ArrayRef Linears,
-      ArrayRef LinModifiers, ArrayRef Steps, SourceRange SR);
+  QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs,
+                              const DeclSpec *DS = nullptr);
+  QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVRA,
+                              const DeclSpec *DS = nullptr);
+  QualType BuildPointerType(QualType T, SourceLocation Loc,
+                            DeclarationName Entity);
+  QualType BuildReferenceType(QualType T, bool LValueRef, SourceLocation Loc,
+                              DeclarationName Entity);
+  QualType BuildArrayType(QualType T, ArraySizeModifier ASM, Expr *ArraySize,
+                          unsigned Quals, SourceRange Brackets,
+                          DeclarationName Entity);
+  QualType BuildVectorType(QualType T, Expr *VecSize, SourceLocation AttrLoc);
+  QualType BuildExtVectorType(QualType T, Expr *ArraySize,
+                              SourceLocation AttrLoc);
+  QualType BuildMatrixType(QualType T, Expr *NumRows, Expr *NumColumns,
+                           SourceLocation AttrLoc);
 
-  /// Checks '\#pragma omp declare variant' variant function and original
-  /// functions after parsing of the associated method/function.
-  /// \param DG Function declaration to which declare variant directive is
-  /// applied to.
-  /// \param VariantRef Expression that references the variant function, which
-  /// must be used instead of the original one, specified in \p DG.
-  /// \param TI The trait info object representing the match clause.
-  /// \param NumAppendArgs The number of omp_interop_t arguments to account for
-  /// in checking.
-  /// \returns std::nullopt, if the function/variant function are not compatible
-  /// with the pragma, pair of original function/variant ref expression
-  /// otherwise.
-  std::optional>
-  checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef,
-                                    OMPTraitInfo &TI, unsigned NumAppendArgs,
-                                    SourceRange SR);
+  QualType BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace,
+                                 SourceLocation AttrLoc);
 
-  /// Called on well-formed '\#pragma omp declare variant' after parsing of
-  /// the associated method/function.
-  /// \param FD Function declaration to which declare variant directive is
-  /// applied to.
-  /// \param VariantRef Expression that references the variant function, which
-  /// must be used instead of the original one, specified in \p DG.
-  /// \param TI The context traits associated with the function variant.
-  /// \param AdjustArgsNothing The list of 'nothing' arguments.
-  /// \param AdjustArgsNeedDevicePtr The list of 'need_device_ptr' arguments.
-  /// \param AppendArgs The list of 'append_args' arguments.
-  /// \param AdjustArgsLoc The Location of an 'adjust_args' clause.
-  /// \param AppendArgsLoc The Location of an 'append_args' clause.
-  /// \param SR The SourceRange of the 'declare variant' directive.
-  void ActOnOpenMPDeclareVariantDirective(
-      FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
-      ArrayRef AdjustArgsNothing,
-      ArrayRef AdjustArgsNeedDevicePtr,
-      ArrayRef AppendArgs, SourceLocation AdjustArgsLoc,
-      SourceLocation AppendArgsLoc, SourceRange SR);
+  /// Same as above, but constructs the AddressSpace index if not provided.
+  QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
+                                 SourceLocation AttrLoc);
+
+  bool CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc);
+
+  bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
+
+  /// Build a function type.
+  ///
+  /// This routine checks the function type according to C++ rules and
+  /// under the assumption that the result type and parameter types have
+  /// just been instantiated from a template. It therefore duplicates
+  /// some of the behavior of GetTypeForDeclarator, but in a much
+  /// simpler form that is only suitable for this narrow use case.
+  ///
+  /// \param T The return type of the function.
+  ///
+  /// \param ParamTypes The parameter types of the function. This array
+  /// will be modified to account for adjustments to the types of the
+  /// function parameters.
+  ///
+  /// \param Loc The location of the entity whose type involves this
+  /// function type or, if there is no such entity, the location of the
+  /// type that will have function type.
+  ///
+  /// \param Entity The name of the entity that involves the function
+  /// type, if known.
+  ///
+  /// \param EPI Extra information about the function type. Usually this will
+  /// be taken from an existing function with the same prototype.
+  ///
+  /// \returns A suitable function type, if there are no errors. The
+  /// unqualified type will always be a FunctionProtoType.
+  /// Otherwise, returns a NULL type.
+  QualType BuildFunctionType(QualType T, MutableArrayRef ParamTypes,
+                             SourceLocation Loc, DeclarationName Entity,
+                             const FunctionProtoType::ExtProtoInfo &EPI);
+
+  QualType BuildMemberPointerType(QualType T, QualType Class,
+                                  SourceLocation Loc, DeclarationName Entity);
+  QualType BuildBlockPointerType(QualType T, SourceLocation Loc,
+                                 DeclarationName Entity);
+  QualType BuildParenType(QualType T);
+  QualType BuildAtomicType(QualType T, SourceLocation Loc);
+  QualType BuildReadPipeType(QualType T, SourceLocation Loc);
+  QualType BuildWritePipeType(QualType T, SourceLocation Loc);
+  QualType BuildBitIntType(bool IsUnsigned, Expr *BitWidth, SourceLocation Loc);
+
+  TypeSourceInfo *GetTypeForDeclarator(Declarator &D);
+  TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
+
+  /// Package the given type and TSI into a ParsedType.
+  ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo);
+  static QualType GetTypeFromParser(ParsedType Ty,
+                                    TypeSourceInfo **TInfo = nullptr);
+
+  TypeResult ActOnTypeName(Declarator &D);
+
+  /// The parser has parsed the context-sensitive type 'instancetype'
+  /// in an Objective-C message declaration. Return the appropriate type.
+  ParsedType ActOnObjCInstanceType(SourceLocation Loc);
+
+  // Check whether the size of array element of type \p EltTy is a multiple of
+  // its alignment and return false if it isn't.
+  bool checkArrayElementAlignment(QualType EltTy, SourceLocation Loc);
+
+  void
+  diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
+                            SourceLocation FallbackLoc,
+                            SourceLocation ConstQualLoc = SourceLocation(),
+                            SourceLocation VolatileQualLoc = SourceLocation(),
+                            SourceLocation RestrictQualLoc = SourceLocation(),
+                            SourceLocation AtomicQualLoc = SourceLocation(),
+                            SourceLocation UnalignedQualLoc = SourceLocation());
+
+  /// Retrieve the keyword associated
+  IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability);
+
+  /// The struct behind the CFErrorRef pointer.
+  RecordDecl *CFError = nullptr;
+  bool isCFError(RecordDecl *D);
+
+  /// Retrieve the identifier "NSError".
+  IdentifierInfo *getNSErrorIdent();
+
+  /// Adjust the calling convention of a method to be the ABI default if it
+  /// wasn't specified explicitly.  This handles method types formed from
+  /// function type typedefs and typename template arguments.
+  void adjustMemberFunctionCC(QualType &T, bool HasThisPointer,
+                              bool IsCtorOrDtor, SourceLocation Loc);
+
+  // Check if there is an explicit attribute, but only look through parens.
+  // The intent is to look for an attribute on the current declarator, but not
+  // one that came from a typedef.
+  bool hasExplicitCallingConv(QualType T);
+
+  /// Check whether a nullability type specifier can be added to the given
+  /// type through some means not written in source (e.g. API notes).
+  ///
+  /// \param Type The type to which the nullability specifier will be
+  /// added. On success, this type will be updated appropriately.
+  ///
+  /// \param Nullability The nullability specifier to add.
+  ///
+  /// \param DiagLoc The location to use for diagnostics.
+  ///
+  /// \param AllowArrayTypes Whether to accept nullability specifiers on an
+  /// array type (e.g., because it will decay to a pointer).
+  ///
+  /// \param OverrideExisting Whether to override an existing, locally-specified
+  /// nullability specifier rather than complaining about the conflict.
+  ///
+  /// \returns true if nullability cannot be applied, false otherwise.
+  bool CheckImplicitNullabilityTypeSpecifier(QualType &Type,
+                                             NullabilityKind Nullability,
+                                             SourceLocation DiagLoc,
+                                             bool AllowArrayTypes,
+                                             bool OverrideExisting);
+
+  /// Get the type of expression E, triggering instantiation to complete the
+  /// type if necessary -- that is, if the expression refers to a templated
+  /// static data member of incomplete array type.
+  ///
+  /// May still return an incomplete type if instantiation was not possible or
+  /// if the type is incomplete for a different reason. Use
+  /// RequireCompleteExprType instead if a diagnostic is expected for an
+  /// incomplete expression type.
+  QualType getCompletedType(Expr *E);
+
+  void completeExprArrayBound(Expr *E);
+  bool RequireCompleteExprType(Expr *E, CompleteTypeKind Kind,
+                               TypeDiagnoser &Diagnoser);
+  bool RequireCompleteExprType(Expr *E, unsigned DiagID);
+
+  template 
+  bool RequireCompleteExprType(Expr *E, unsigned DiagID, const Ts &...Args) {
+    BoundTypeDiagnoser Diagnoser(DiagID, Args...);
+    return RequireCompleteExprType(E, CompleteTypeKind::Default, Diagnoser);
+  }
+
+  QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
+                             const CXXScopeSpec &SS, QualType T,
+                             TagDecl *OwnedTagDecl = nullptr);
+
+  // Returns the underlying type of a decltype with the given expression.
+  QualType getDecltypeForExpr(Expr *E);
+
+  QualType BuildTypeofExprType(Expr *E, TypeOfKind Kind);
+  /// If AsUnevaluated is false, E is treated as though it were an evaluated
+  /// context, such as when building a type for decltype(auto).
+  QualType BuildDecltypeType(Expr *E, bool AsUnevaluated = true);
+
+  QualType ActOnPackIndexingType(QualType Pattern, Expr *IndexExpr,
+                                 SourceLocation Loc,
+                                 SourceLocation EllipsisLoc);
+  QualType BuildPackIndexingType(QualType Pattern, Expr *IndexExpr,
+                                 SourceLocation Loc, SourceLocation EllipsisLoc,
+                                 bool FullySubstituted = false,
+                                 ArrayRef Expansions = {});
+
+  using UTTKind = UnaryTransformType::UTTKind;
+  QualType BuildUnaryTransformType(QualType BaseType, UTTKind UKind,
+                                   SourceLocation Loc);
+  QualType BuiltinEnumUnderlyingType(QualType BaseType, SourceLocation Loc);
+  QualType BuiltinAddPointer(QualType BaseType, SourceLocation Loc);
+  QualType BuiltinRemovePointer(QualType BaseType, SourceLocation Loc);
+  QualType BuiltinDecay(QualType BaseType, SourceLocation Loc);
+  QualType BuiltinAddReference(QualType BaseType, UTTKind UKind,
+                               SourceLocation Loc);
+  QualType BuiltinRemoveExtent(QualType BaseType, UTTKind UKind,
+                               SourceLocation Loc);
+  QualType BuiltinRemoveReference(QualType BaseType, UTTKind UKind,
+                                  SourceLocation Loc);
+  QualType BuiltinChangeCVRQualifiers(QualType BaseType, UTTKind UKind,
+                                      SourceLocation Loc);
+  QualType BuiltinChangeSignedness(QualType BaseType, UTTKind UKind,
+                                   SourceLocation Loc);
 
-  OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
-                                         Expr *Expr,
-                                         SourceLocation StartLoc,
-                                         SourceLocation LParenLoc,
-                                         SourceLocation EndLoc);
-  /// Called on well-formed 'allocator' clause.
-  OMPClause *ActOnOpenMPAllocatorClause(Expr *Allocator,
-                                        SourceLocation StartLoc,
-                                        SourceLocation LParenLoc,
-                                        SourceLocation EndLoc);
-  /// Called on well-formed 'if' clause.
-  OMPClause *ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
-                                 Expr *Condition, SourceLocation StartLoc,
-                                 SourceLocation LParenLoc,
-                                 SourceLocation NameModifierLoc,
-                                 SourceLocation ColonLoc,
-                                 SourceLocation EndLoc);
-  /// Called on well-formed 'final' clause.
-  OMPClause *ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc,
-                                    SourceLocation LParenLoc,
-                                    SourceLocation EndLoc);
-  /// Called on well-formed 'num_threads' clause.
-  OMPClause *ActOnOpenMPNumThreadsClause(Expr *NumThreads,
-                                         SourceLocation StartLoc,
-                                         SourceLocation LParenLoc,
-                                         SourceLocation EndLoc);
-  /// Called on well-formed 'align' clause.
-  OMPClause *ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc,
-                                    SourceLocation LParenLoc,
-                                    SourceLocation EndLoc);
-  /// Called on well-formed 'safelen' clause.
-  OMPClause *ActOnOpenMPSafelenClause(Expr *Length,
-                                      SourceLocation StartLoc,
-                                      SourceLocation LParenLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed 'simdlen' clause.
-  OMPClause *ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc,
-                                      SourceLocation LParenLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-form 'sizes' clause.
-  OMPClause *ActOnOpenMPSizesClause(ArrayRef SizeExprs,
-                                    SourceLocation StartLoc,
-                                    SourceLocation LParenLoc,
-                                    SourceLocation EndLoc);
-  /// Called on well-form 'full' clauses.
-  OMPClause *ActOnOpenMPFullClause(SourceLocation StartLoc,
-                                   SourceLocation EndLoc);
-  /// Called on well-form 'partial' clauses.
-  OMPClause *ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc,
-                                      SourceLocation LParenLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed 'collapse' clause.
-  OMPClause *ActOnOpenMPCollapseClause(Expr *NumForLoops,
-                                       SourceLocation StartLoc,
-                                       SourceLocation LParenLoc,
-                                       SourceLocation EndLoc);
-  /// Called on well-formed 'ordered' clause.
-  OMPClause *
-  ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc,
-                           SourceLocation LParenLoc = SourceLocation(),
-                           Expr *NumForLoops = nullptr);
-  /// Called on well-formed 'grainsize' clause.
-  OMPClause *ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier,
-                                        Expr *Size, SourceLocation StartLoc,
-                                        SourceLocation LParenLoc,
-                                        SourceLocation ModifierLoc,
-                                        SourceLocation EndLoc);
-  /// Called on well-formed 'num_tasks' clause.
-  OMPClause *ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier,
-                                       Expr *NumTasks, SourceLocation StartLoc,
-                                       SourceLocation LParenLoc,
-                                       SourceLocation ModifierLoc,
-                                       SourceLocation EndLoc);
-  /// Called on well-formed 'hint' clause.
-  OMPClause *ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
-                                   SourceLocation LParenLoc,
-                                   SourceLocation EndLoc);
-  /// Called on well-formed 'detach' clause.
-  OMPClause *ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc,
-                                     SourceLocation LParenLoc,
-                                     SourceLocation EndLoc);
+  bool RequireLiteralType(SourceLocation Loc, QualType T,
+                          TypeDiagnoser &Diagnoser);
+  bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID);
 
-  OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind,
-                                     unsigned Argument,
-                                     SourceLocation ArgumentLoc,
-                                     SourceLocation StartLoc,
-                                     SourceLocation LParenLoc,
-                                     SourceLocation EndLoc);
-  /// Called on well-formed 'when' clause.
-  OMPClause *ActOnOpenMPWhenClause(OMPTraitInfo &TI, SourceLocation StartLoc,
-                                   SourceLocation LParenLoc,
-                                   SourceLocation EndLoc);
-  /// Called on well-formed 'default' clause.
-  OMPClause *ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind,
-                                      SourceLocation KindLoc,
-                                      SourceLocation StartLoc,
-                                      SourceLocation LParenLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed 'proc_bind' clause.
-  OMPClause *ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind,
-                                       SourceLocation KindLoc,
-                                       SourceLocation StartLoc,
-                                       SourceLocation LParenLoc,
-                                       SourceLocation EndLoc);
-  /// Called on well-formed 'order' clause.
-  OMPClause *ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier,
-                                    OpenMPOrderClauseKind Kind,
-                                    SourceLocation StartLoc,
-                                    SourceLocation LParenLoc,
-                                    SourceLocation MLoc, SourceLocation KindLoc,
-                                    SourceLocation EndLoc);
-  /// Called on well-formed 'update' clause.
-  OMPClause *ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,
-                                     SourceLocation KindLoc,
-                                     SourceLocation StartLoc,
-                                     SourceLocation LParenLoc,
-                                     SourceLocation EndLoc);
+  template 
+  bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID,
+                          const Ts &...Args) {
+    BoundTypeDiagnoser Diagnoser(DiagID, Args...);
+    return RequireLiteralType(Loc, T, Diagnoser);
+  }
 
-  OMPClause *ActOnOpenMPSingleExprWithArgClause(
-      OpenMPClauseKind Kind, ArrayRef Arguments, Expr *Expr,
-      SourceLocation StartLoc, SourceLocation LParenLoc,
-      ArrayRef ArgumentsLoc, SourceLocation DelimLoc,
-      SourceLocation EndLoc);
-  /// Called on well-formed 'schedule' clause.
-  OMPClause *ActOnOpenMPScheduleClause(
-      OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
-      OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
-      SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
-      SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc);
+  bool isCompleteType(SourceLocation Loc, QualType T,
+                      CompleteTypeKind Kind = CompleteTypeKind::Default) {
+    return !RequireCompleteTypeImpl(Loc, T, Kind, nullptr);
+  }
+  bool RequireCompleteType(SourceLocation Loc, QualType T,
+                           CompleteTypeKind Kind, TypeDiagnoser &Diagnoser);
+  bool RequireCompleteType(SourceLocation Loc, QualType T,
+                           CompleteTypeKind Kind, unsigned DiagID);
 
-  OMPClause *ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc,
-                               SourceLocation EndLoc);
-  /// Called on well-formed 'nowait' clause.
-  OMPClause *ActOnOpenMPNowaitClause(SourceLocation StartLoc,
-                                     SourceLocation EndLoc);
-  /// Called on well-formed 'untied' clause.
-  OMPClause *ActOnOpenMPUntiedClause(SourceLocation StartLoc,
-                                     SourceLocation EndLoc);
-  /// Called on well-formed 'mergeable' clause.
-  OMPClause *ActOnOpenMPMergeableClause(SourceLocation StartLoc,
-                                        SourceLocation EndLoc);
-  /// Called on well-formed 'read' clause.
-  OMPClause *ActOnOpenMPReadClause(SourceLocation StartLoc,
-                                   SourceLocation EndLoc);
-  /// Called on well-formed 'write' clause.
-  OMPClause *ActOnOpenMPWriteClause(SourceLocation StartLoc,
-                                    SourceLocation EndLoc);
-  /// Called on well-formed 'update' clause.
-  OMPClause *ActOnOpenMPUpdateClause(SourceLocation StartLoc,
-                                     SourceLocation EndLoc);
-  /// Called on well-formed 'capture' clause.
-  OMPClause *ActOnOpenMPCaptureClause(SourceLocation StartLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed 'compare' clause.
-  OMPClause *ActOnOpenMPCompareClause(SourceLocation StartLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed 'fail' clause.
-  OMPClause *ActOnOpenMPFailClause(SourceLocation StartLoc,
-                                   SourceLocation EndLoc);
-  OMPClause *ActOnOpenMPFailClause(
-      OpenMPClauseKind Kind, SourceLocation KindLoc,
-      SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
+  bool RequireCompleteType(SourceLocation Loc, QualType T,
+                           TypeDiagnoser &Diagnoser) {
+    return RequireCompleteType(Loc, T, CompleteTypeKind::Default, Diagnoser);
+  }
+  bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID) {
+    return RequireCompleteType(Loc, T, CompleteTypeKind::Default, DiagID);
+  }
 
-  /// Called on well-formed 'seq_cst' clause.
-  OMPClause *ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
-                                     SourceLocation EndLoc);
-  /// Called on well-formed 'acq_rel' clause.
-  OMPClause *ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
-                                     SourceLocation EndLoc);
-  /// Called on well-formed 'acquire' clause.
-  OMPClause *ActOnOpenMPAcquireClause(SourceLocation StartLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed 'release' clause.
-  OMPClause *ActOnOpenMPReleaseClause(SourceLocation StartLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed 'relaxed' clause.
-  OMPClause *ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed 'weak' clause.
-  OMPClause *ActOnOpenMPWeakClause(SourceLocation StartLoc,
-                                   SourceLocation EndLoc);
+  template 
+  bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID,
+                           const Ts &...Args) {
+    BoundTypeDiagnoser Diagnoser(DiagID, Args...);
+    return RequireCompleteType(Loc, T, Diagnoser);
+  }
 
-  /// Called on well-formed 'init' clause.
-  OMPClause *
-  ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo,
-                        SourceLocation StartLoc, SourceLocation LParenLoc,
-                        SourceLocation VarLoc, SourceLocation EndLoc);
+  /// Determine whether a declaration is visible to name lookup.
+  bool isVisible(const NamedDecl *D) {
+    return D->isUnconditionallyVisible() ||
+           isAcceptableSlow(D, AcceptableKind::Visible);
+  }
 
-  /// Called on well-formed 'use' clause.
-  OMPClause *ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc,
-                                  SourceLocation LParenLoc,
-                                  SourceLocation VarLoc, SourceLocation EndLoc);
+  /// Determine whether a declaration is reachable.
+  bool isReachable(const NamedDecl *D) {
+    // All visible declarations are reachable.
+    return D->isUnconditionallyVisible() ||
+           isAcceptableSlow(D, AcceptableKind::Reachable);
+  }
 
-  /// Called on well-formed 'destroy' clause.
-  OMPClause *ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc,
-                                      SourceLocation LParenLoc,
-                                      SourceLocation VarLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed 'novariants' clause.
-  OMPClause *ActOnOpenMPNovariantsClause(Expr *Condition,
-                                         SourceLocation StartLoc,
-                                         SourceLocation LParenLoc,
-                                         SourceLocation EndLoc);
-  /// Called on well-formed 'nocontext' clause.
-  OMPClause *ActOnOpenMPNocontextClause(Expr *Condition,
-                                        SourceLocation StartLoc,
-                                        SourceLocation LParenLoc,
-                                        SourceLocation EndLoc);
-  /// Called on well-formed 'filter' clause.
-  OMPClause *ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc,
-                                     SourceLocation LParenLoc,
-                                     SourceLocation EndLoc);
-  /// Called on well-formed 'threads' clause.
-  OMPClause *ActOnOpenMPThreadsClause(SourceLocation StartLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed 'simd' clause.
-  OMPClause *ActOnOpenMPSIMDClause(SourceLocation StartLoc,
-                                   SourceLocation EndLoc);
-  /// Called on well-formed 'nogroup' clause.
-  OMPClause *ActOnOpenMPNogroupClause(SourceLocation StartLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed 'unified_address' clause.
-  OMPClause *ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
-                                             SourceLocation EndLoc);
+  /// Determine whether a declaration is acceptable (visible/reachable).
+  bool isAcceptable(const NamedDecl *D, AcceptableKind Kind) {
+    return Kind == AcceptableKind::Visible ? isVisible(D) : isReachable(D);
+  }
 
-  /// Called on well-formed 'unified_address' clause.
-  OMPClause *ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
-                                                  SourceLocation EndLoc);
+  /// Determine if \p D and \p Suggested have a structurally compatible
+  /// layout as described in C11 6.2.7/1.
+  bool hasStructuralCompatLayout(Decl *D, Decl *Suggested);
 
-  /// Called on well-formed 'reverse_offload' clause.
-  OMPClause *ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
-                                             SourceLocation EndLoc);
+  /// Determine if \p D has a visible definition. If not, suggest a declaration
+  /// that should be made visible to expose the definition.
+  bool hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested,
+                            bool OnlyNeedComplete = false);
+  bool hasVisibleDefinition(const NamedDecl *D) {
+    NamedDecl *Hidden;
+    return hasVisibleDefinition(const_cast(D), &Hidden);
+  }
 
-  /// Called on well-formed 'dynamic_allocators' clause.
-  OMPClause *ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
-                                                SourceLocation EndLoc);
+  /// Determine if \p D has a reachable definition. If not, suggest a
+  /// declaration that should be made reachable to expose the definition.
+  bool hasReachableDefinition(NamedDecl *D, NamedDecl **Suggested,
+                              bool OnlyNeedComplete = false);
+  bool hasReachableDefinition(NamedDecl *D) {
+    NamedDecl *Hidden;
+    return hasReachableDefinition(D, &Hidden);
+  }
 
-  /// Called on well-formed 'atomic_default_mem_order' clause.
-  OMPClause *ActOnOpenMPAtomicDefaultMemOrderClause(
-      OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc,
-      SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
+  bool hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested,
+                               AcceptableKind Kind,
+                               bool OnlyNeedComplete = false);
+  bool hasAcceptableDefinition(NamedDecl *D, AcceptableKind Kind) {
+    NamedDecl *Hidden;
+    return hasAcceptableDefinition(D, &Hidden, Kind);
+  }
 
-  /// Called on well-formed 'at' clause.
-  OMPClause *ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
-                                 SourceLocation KindLoc,
-                                 SourceLocation StartLoc,
-                                 SourceLocation LParenLoc,
-                                 SourceLocation EndLoc);
+private:
+  bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
+                               CompleteTypeKind Kind, TypeDiagnoser *Diagnoser);
 
-  /// Called on well-formed 'severity' clause.
-  OMPClause *ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
-                                       SourceLocation KindLoc,
-                                       SourceLocation StartLoc,
-                                       SourceLocation LParenLoc,
-                                       SourceLocation EndLoc);
+  /// Nullability type specifiers.
+  IdentifierInfo *Ident__Nonnull = nullptr;
+  IdentifierInfo *Ident__Nullable = nullptr;
+  IdentifierInfo *Ident__Nullable_result = nullptr;
+  IdentifierInfo *Ident__Null_unspecified = nullptr;
 
-  /// Called on well-formed 'message' clause.
-  /// passing string for message.
-  OMPClause *ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc,
-                                      SourceLocation LParenLoc,
-                                      SourceLocation EndLoc);
+  IdentifierInfo *Ident_NSError = nullptr;
 
-  /// Data used for processing a list of variables in OpenMP clauses.
-  struct OpenMPVarListDataTy final {
-    Expr *DepModOrTailExpr = nullptr;
-    Expr *IteratorExpr = nullptr;
-    SourceLocation ColonLoc;
-    SourceLocation RLoc;
-    CXXScopeSpec ReductionOrMapperIdScopeSpec;
-    DeclarationNameInfo ReductionOrMapperId;
-    int ExtraModifier = -1; ///< Additional modifier for linear, map, depend or
-                            ///< lastprivate clause.
-    SmallVector
-        MapTypeModifiers;
-    SmallVector
-        MapTypeModifiersLoc;
-    SmallVector
-        MotionModifiers;
-    SmallVector MotionModifiersLoc;
-    bool IsMapTypeImplicit = false;
-    SourceLocation ExtraModifierLoc;
-    SourceLocation OmpAllMemoryLoc;
-    SourceLocation
-        StepModifierLoc; /// 'step' modifier location for linear clause
-  };
+  ///@}
 
-  OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
-                                      ArrayRef Vars,
-                                      const OMPVarListLocTy &Locs,
-                                      OpenMPVarListDataTy &Data);
-  /// Called on well-formed 'inclusive' clause.
-  OMPClause *ActOnOpenMPInclusiveClause(ArrayRef VarList,
-                                        SourceLocation StartLoc,
-                                        SourceLocation LParenLoc,
-                                        SourceLocation EndLoc);
-  /// Called on well-formed 'exclusive' clause.
-  OMPClause *ActOnOpenMPExclusiveClause(ArrayRef VarList,
-                                        SourceLocation StartLoc,
-                                        SourceLocation LParenLoc,
-                                        SourceLocation EndLoc);
-  /// Called on well-formed 'allocate' clause.
-  OMPClause *
-  ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef VarList,
-                            SourceLocation StartLoc, SourceLocation ColonLoc,
-                            SourceLocation LParenLoc, SourceLocation EndLoc);
-  /// Called on well-formed 'private' clause.
-  OMPClause *ActOnOpenMPPrivateClause(ArrayRef VarList,
-                                      SourceLocation StartLoc,
-                                      SourceLocation LParenLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed 'firstprivate' clause.
-  OMPClause *ActOnOpenMPFirstprivateClause(ArrayRef VarList,
-                                           SourceLocation StartLoc,
-                                           SourceLocation LParenLoc,
-                                           SourceLocation EndLoc);
-  /// Called on well-formed 'lastprivate' clause.
-  OMPClause *ActOnOpenMPLastprivateClause(
-      ArrayRef VarList, OpenMPLastprivateModifier LPKind,
-      SourceLocation LPKindLoc, SourceLocation ColonLoc,
-      SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
-  /// Called on well-formed 'shared' clause.
-  OMPClause *ActOnOpenMPSharedClause(ArrayRef VarList,
-                                     SourceLocation StartLoc,
-                                     SourceLocation LParenLoc,
-                                     SourceLocation EndLoc);
-  /// Called on well-formed 'reduction' clause.
-  OMPClause *ActOnOpenMPReductionClause(
-      ArrayRef VarList, OpenMPReductionClauseModifier Modifier,
-      SourceLocation StartLoc, SourceLocation LParenLoc,
-      SourceLocation ModifierLoc, SourceLocation ColonLoc,
-      SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,
-      const DeclarationNameInfo &ReductionId,
-      ArrayRef UnresolvedReductions = std::nullopt);
-  /// Called on well-formed 'task_reduction' clause.
-  OMPClause *ActOnOpenMPTaskReductionClause(
-      ArrayRef VarList, SourceLocation StartLoc,
-      SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
-      CXXScopeSpec &ReductionIdScopeSpec,
-      const DeclarationNameInfo &ReductionId,
-      ArrayRef UnresolvedReductions = std::nullopt);
-  /// Called on well-formed 'in_reduction' clause.
-  OMPClause *ActOnOpenMPInReductionClause(
-      ArrayRef VarList, SourceLocation StartLoc,
-      SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
-      CXXScopeSpec &ReductionIdScopeSpec,
-      const DeclarationNameInfo &ReductionId,
-      ArrayRef UnresolvedReductions = std::nullopt);
-  /// Called on well-formed 'linear' clause.
-  OMPClause *ActOnOpenMPLinearClause(
-      ArrayRef VarList, Expr *Step, SourceLocation StartLoc,
-      SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
-      SourceLocation LinLoc, SourceLocation ColonLoc,
-      SourceLocation StepModifierLoc, SourceLocation EndLoc);
-  /// Called on well-formed 'aligned' clause.
-  OMPClause *ActOnOpenMPAlignedClause(ArrayRef VarList,
-                                      Expr *Alignment,
-                                      SourceLocation StartLoc,
-                                      SourceLocation LParenLoc,
-                                      SourceLocation ColonLoc,
-                                      SourceLocation EndLoc);
-  /// Called on well-formed 'copyin' clause.
-  OMPClause *ActOnOpenMPCopyinClause(ArrayRef VarList,
-                                     SourceLocation StartLoc,
-                                     SourceLocation LParenLoc,
-                                     SourceLocation EndLoc);
-  /// Called on well-formed 'copyprivate' clause.
-  OMPClause *ActOnOpenMPCopyprivateClause(ArrayRef VarList,
-                                          SourceLocation StartLoc,
-                                          SourceLocation LParenLoc,
-                                          SourceLocation EndLoc);
-  /// Called on well-formed 'flush' pseudo clause.
-  OMPClause *ActOnOpenMPFlushClause(ArrayRef VarList,
-                                    SourceLocation StartLoc,
-                                    SourceLocation LParenLoc,
-                                    SourceLocation EndLoc);
-  /// Called on well-formed 'depobj' pseudo clause.
-  OMPClause *ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc,
-                                     SourceLocation LParenLoc,
-                                     SourceLocation EndLoc);
-  /// Called on well-formed 'depend' clause.
-  OMPClause *ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
-                                     Expr *DepModifier,
-                                     ArrayRef VarList,
-                                     SourceLocation StartLoc,
-                                     SourceLocation LParenLoc,
-                                     SourceLocation EndLoc);
-  /// Called on well-formed 'device' clause.
-  OMPClause *ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,
-                                     Expr *Device, SourceLocation StartLoc,
-                                     SourceLocation LParenLoc,
-                                     SourceLocation ModifierLoc,
-                                     SourceLocation EndLoc);
-  /// Called on well-formed 'map' clause.
-  OMPClause *ActOnOpenMPMapClause(
-      Expr *IteratorModifier, ArrayRef MapTypeModifiers,
-      ArrayRef MapTypeModifiersLoc,
-      CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
-      OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
-      SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef VarList,
-      const OMPVarListLocTy &Locs, bool NoDiagnose = false,
-      ArrayRef UnresolvedMappers = std::nullopt);
-  /// Called on well-formed 'num_teams' clause.
-  OMPClause *ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc,
-                                       SourceLocation LParenLoc,
-                                       SourceLocation EndLoc);
-  /// Called on well-formed 'thread_limit' clause.
-  OMPClause *ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
-                                          SourceLocation StartLoc,
-                                          SourceLocation LParenLoc,
-                                          SourceLocation EndLoc);
-  /// Called on well-formed 'priority' clause.
-  OMPClause *ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc,
-                                       SourceLocation LParenLoc,
-                                       SourceLocation EndLoc);
-  /// Called on well-formed 'dist_schedule' clause.
-  OMPClause *ActOnOpenMPDistScheduleClause(
-      OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize,
-      SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc,
-      SourceLocation CommaLoc, SourceLocation EndLoc);
-  /// Called on well-formed 'defaultmap' clause.
-  OMPClause *ActOnOpenMPDefaultmapClause(
-      OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
-      SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
-      SourceLocation KindLoc, SourceLocation EndLoc);
-  /// Called on well-formed 'to' clause.
-  OMPClause *
-  ActOnOpenMPToClause(ArrayRef MotionModifiers,
-                      ArrayRef MotionModifiersLoc,
-                      CXXScopeSpec &MapperIdScopeSpec,
-                      DeclarationNameInfo &MapperId, SourceLocation ColonLoc,
-                      ArrayRef VarList, const OMPVarListLocTy &Locs,
-                      ArrayRef UnresolvedMappers = std::nullopt);
-  /// Called on well-formed 'from' clause.
-  OMPClause *
-  ActOnOpenMPFromClause(ArrayRef MotionModifiers,
-                        ArrayRef MotionModifiersLoc,
-                        CXXScopeSpec &MapperIdScopeSpec,
-                        DeclarationNameInfo &MapperId, SourceLocation ColonLoc,
-                        ArrayRef VarList, const OMPVarListLocTy &Locs,
-                        ArrayRef UnresolvedMappers = std::nullopt);
-  /// Called on well-formed 'use_device_ptr' clause.
-  OMPClause *ActOnOpenMPUseDevicePtrClause(ArrayRef VarList,
-                                           const OMPVarListLocTy &Locs);
-  /// Called on well-formed 'use_device_addr' clause.
-  OMPClause *ActOnOpenMPUseDeviceAddrClause(ArrayRef VarList,
-                                            const OMPVarListLocTy &Locs);
-  /// Called on well-formed 'is_device_ptr' clause.
-  OMPClause *ActOnOpenMPIsDevicePtrClause(ArrayRef VarList,
-                                          const OMPVarListLocTy &Locs);
-  /// Called on well-formed 'has_device_addr' clause.
-  OMPClause *ActOnOpenMPHasDeviceAddrClause(ArrayRef VarList,
-                                            const OMPVarListLocTy &Locs);
-  /// Called on well-formed 'nontemporal' clause.
-  OMPClause *ActOnOpenMPNontemporalClause(ArrayRef VarList,
-                                          SourceLocation StartLoc,
-                                          SourceLocation LParenLoc,
-                                          SourceLocation EndLoc);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Data for list of allocators.
-  struct UsesAllocatorsData {
-    /// Allocator.
-    Expr *Allocator = nullptr;
-    /// Allocator traits.
-    Expr *AllocatorTraits = nullptr;
-    /// Locations of '(' and ')' symbols.
-    SourceLocation LParenLoc, RParenLoc;
+  /// \name ObjC Declarations
+  /// Implementations are in SemaDeclObjC.cpp
+  ///@{
+
+public:
+  enum ObjCSpecialMethodKind {
+    OSMK_None,
+    OSMK_Alloc,
+    OSMK_New,
+    OSMK_Copy,
+    OSMK_RetainingInit,
+    OSMK_NonRetainingInit
   };
-  /// Called on well-formed 'uses_allocators' clause.
-  OMPClause *ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc,
-                                            SourceLocation LParenLoc,
-                                            SourceLocation EndLoc,
-                                            ArrayRef Data);
-  /// Called on well-formed 'affinity' clause.
-  OMPClause *ActOnOpenMPAffinityClause(SourceLocation StartLoc,
-                                       SourceLocation LParenLoc,
-                                       SourceLocation ColonLoc,
-                                       SourceLocation EndLoc, Expr *Modifier,
-                                       ArrayRef Locators);
-  /// Called on a well-formed 'bind' clause.
-  OMPClause *ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
-                                   SourceLocation KindLoc,
-                                   SourceLocation StartLoc,
-                                   SourceLocation LParenLoc,
-                                   SourceLocation EndLoc);
 
-  /// Called on a well-formed 'ompx_dyn_cgroup_mem' clause.
-  OMPClause *ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc,
-                                            SourceLocation LParenLoc,
-                                            SourceLocation EndLoc);
+  /// Method selectors used in a \@selector expression. Used for implementation
+  /// of -Wselector.
+  llvm::MapVector ReferencedSelectors;
 
-  /// Called on well-formed 'doacross' clause.
-  OMPClause *
-  ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType,
-                            SourceLocation DepLoc, SourceLocation ColonLoc,
-                            ArrayRef VarList, SourceLocation StartLoc,
-                            SourceLocation LParenLoc, SourceLocation EndLoc);
+  class GlobalMethodPool {
+  public:
+    using Lists = std::pair;
+    using iterator = llvm::DenseMap::iterator;
+    iterator begin() { return Methods.begin(); }
+    iterator end() { return Methods.end(); }
+    iterator find(Selector Sel) { return Methods.find(Sel); }
+    std::pair insert(std::pair &&Val) {
+      return Methods.insert(Val);
+    }
+    int count(Selector Sel) const { return Methods.count(Sel); }
+    bool empty() const { return Methods.empty(); }
 
-  /// Called on a well-formed 'ompx_attribute' clause.
-  OMPClause *ActOnOpenMPXAttributeClause(ArrayRef Attrs,
-                                         SourceLocation StartLoc,
-                                         SourceLocation LParenLoc,
-                                         SourceLocation EndLoc);
+  private:
+    llvm::DenseMap Methods;
+  };
 
-  /// Called on a well-formed 'ompx_bare' clause.
-  OMPClause *ActOnOpenMPXBareClause(SourceLocation StartLoc,
-                                    SourceLocation EndLoc);
+  /// Method Pool - allows efficient lookup when typechecking messages to "id".
+  /// We need to maintain a list, since selectors can have differing signatures
+  /// across classes. In Cocoa, this happens to be extremely uncommon (only 1%
+  /// of selectors are "overloaded").
+  /// At the head of the list it is recorded whether there were 0, 1, or >= 2
+  /// methods inside categories with a particular selector.
+  GlobalMethodPool MethodPool;
 
-  //===--------------------------------------------------------------------===//
-  // OpenACC directives and clauses.
+  /// Check ODR hashes for C/ObjC when merging types from modules.
+  /// Differently from C++, actually parse the body and reject in case
+  /// of a mismatch.
+  template ::value>>
+  bool ActOnDuplicateODRHashDefinition(T *Duplicate, T *Previous) {
+    if (Duplicate->getODRHash() != Previous->getODRHash())
+      return false;
 
-  /// Called after parsing an OpenACC Clause so that it can be checked.
-  bool ActOnOpenACCClause(OpenACCClauseKind ClauseKind,
-                          SourceLocation StartLoc);
+    // Make the previous decl visible.
+    makeMergedDefinitionVisible(Previous);
+    return true;
+  }
 
-  /// Called after the construct has been parsed, but clauses haven't been
-  /// parsed.  This allows us to diagnose not-implemented, as well as set up any
-  /// state required for parsing the clauses.
-  void ActOnOpenACCConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc);
+  typedef llvm::SmallPtrSet SelectorSet;
 
-  /// Called after the directive, including its clauses, have been parsed and
-  /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES
-  /// happen before any associated declarations or statements have been parsed.
-  /// This function is only called when we are parsing a 'statement' context.
-  bool ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K,
-                                      SourceLocation StartLoc);
+  enum MethodMatchStrategy { MMS_loose, MMS_strict };
 
-  /// Called after the directive, including its clauses, have been parsed and
-  /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES
-  /// happen before any associated declarations or statements have been parsed.
-  /// This function is only called when we are parsing a 'Decl' context.
-  bool ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K,
-                                      SourceLocation StartLoc);
-  /// Called when we encounter an associated statement for our construct, this
-  /// should check legality of the statement as it appertains to this Construct.
-  StmtResult ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K,
-                                        StmtResult AssocStmt);
+  enum ObjCContainerKind {
+    OCK_None = -1,
+    OCK_Interface = 0,
+    OCK_Protocol,
+    OCK_Category,
+    OCK_ClassExtension,
+    OCK_Implementation,
+    OCK_CategoryImplementation
+  };
+  ObjCContainerKind getObjCContainerKind() const;
 
-  /// Called after the directive has been completely parsed, including the
-  /// declaration group or associated statement.
-  StmtResult ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K,
-                                          SourceLocation StartLoc,
-                                          SourceLocation EndLoc,
-                                          StmtResult AssocStmt);
-  /// Called after the directive has been completely parsed, including the
-  /// declaration group or associated statement.
-  DeclGroupRef ActOnEndOpenACCDeclDirective();
+  DeclResult actOnObjCTypeParam(Scope *S, ObjCTypeParamVariance variance,
+                                SourceLocation varianceLoc, unsigned index,
+                                IdentifierInfo *paramName,
+                                SourceLocation paramLoc,
+                                SourceLocation colonLoc, ParsedType typeBound);
 
-  /// The kind of conversion being performed.
-  enum CheckedConversionKind {
-    /// An implicit conversion.
-    CCK_ImplicitConversion,
-    /// A C-style cast.
-    CCK_CStyleCast,
-    /// A functional-style cast.
-    CCK_FunctionalCast,
-    /// A cast other than a C-style cast.
-    CCK_OtherCast,
-    /// A conversion for an operand of a builtin overloaded operator.
-    CCK_ForBuiltinOverloadedOp
+  ObjCTypeParamList *actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc,
+                                            ArrayRef typeParams,
+                                            SourceLocation rAngleLoc);
+  void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList);
+
+  ObjCInterfaceDecl *ActOnStartClassInterface(
+      Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName,
+      SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,
+      IdentifierInfo *SuperName, SourceLocation SuperLoc,
+      ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange,
+      Decl *const *ProtoRefs, unsigned NumProtoRefs,
+      const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
+      const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody);
+
+  void ActOnSuperClassOfClassInterface(
+      Scope *S, SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *IDecl,
+      IdentifierInfo *ClassName, SourceLocation ClassLoc,
+      IdentifierInfo *SuperName, SourceLocation SuperLoc,
+      ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange);
+
+  void ActOnTypedefedProtocols(SmallVectorImpl &ProtocolRefs,
+                               SmallVectorImpl &ProtocolLocs,
+                               IdentifierInfo *SuperName,
+                               SourceLocation SuperLoc);
+
+  Decl *ActOnCompatibilityAlias(SourceLocation AtCompatibilityAliasLoc,
+                                IdentifierInfo *AliasName,
+                                SourceLocation AliasLocation,
+                                IdentifierInfo *ClassName,
+                                SourceLocation ClassLocation);
+
+  bool CheckForwardProtocolDeclarationForCircularDependency(
+      IdentifierInfo *PName, SourceLocation &PLoc, SourceLocation PrevLoc,
+      const ObjCList &PList);
+
+  ObjCProtocolDecl *ActOnStartProtocolInterface(
+      SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,
+      SourceLocation ProtocolLoc, Decl *const *ProtoRefNames,
+      unsigned NumProtoRefs, const SourceLocation *ProtoLocs,
+      SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList,
+      SkipBodyInfo *SkipBody);
+
+  ObjCCategoryDecl *ActOnStartCategoryInterface(
+      SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName,
+      SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,
+      IdentifierInfo *CategoryName, SourceLocation CategoryLoc,
+      Decl *const *ProtoRefs, unsigned NumProtoRefs,
+      const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
+      const ParsedAttributesView &AttrList);
+
+  ObjCImplementationDecl *ActOnStartClassImplementation(
+      SourceLocation AtClassImplLoc, IdentifierInfo *ClassName,
+      SourceLocation ClassLoc, IdentifierInfo *SuperClassname,
+      SourceLocation SuperClassLoc, const ParsedAttributesView &AttrList);
+
+  ObjCCategoryImplDecl *ActOnStartCategoryImplementation(
+      SourceLocation AtCatImplLoc, IdentifierInfo *ClassName,
+      SourceLocation ClassLoc, IdentifierInfo *CatName, SourceLocation CatLoc,
+      const ParsedAttributesView &AttrList);
+
+  DeclGroupPtrTy ActOnFinishObjCImplementation(Decl *ObjCImpDecl,
+                                               ArrayRef Decls);
+
+  DeclGroupPtrTy
+  ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
+                                  ArrayRef IdentList,
+                                  const ParsedAttributesView &attrList);
+
+  void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
+                               ArrayRef ProtocolId,
+                               SmallVectorImpl &Protocols);
+
+  void DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId,
+                                    SourceLocation ProtocolLoc,
+                                    IdentifierInfo *TypeArgId,
+                                    SourceLocation TypeArgLoc,
+                                    bool SelectProtocolFirst = false);
+
+  /// Given a list of identifiers (and their locations), resolve the
+  /// names to either Objective-C protocol qualifiers or type
+  /// arguments, as appropriate.
+  void actOnObjCTypeArgsOrProtocolQualifiers(
+      Scope *S, ParsedType baseType, SourceLocation lAngleLoc,
+      ArrayRef identifiers,
+      ArrayRef identifierLocs, SourceLocation rAngleLoc,
+      SourceLocation &typeArgsLAngleLoc, SmallVectorImpl &typeArgs,
+      SourceLocation &typeArgsRAngleLoc, SourceLocation &protocolLAngleLoc,
+      SmallVectorImpl &protocols, SourceLocation &protocolRAngleLoc,
+      bool warnOnIncompleteProtocols);
+
+  void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
+                                        ObjCInterfaceDecl *ID);
+
+  Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd,
+                   ArrayRef allMethods = std::nullopt,
+                   ArrayRef allTUVars = std::nullopt);
+
+  struct ObjCArgInfo {
+    IdentifierInfo *Name;
+    SourceLocation NameLoc;
+    // The Type is null if no type was specified, and the DeclSpec is invalid
+    // in this case.
+    ParsedType Type;
+    ObjCDeclSpec DeclSpec;
+
+    /// ArgAttrs - Attribute list for this argument.
+    ParsedAttributesView ArgAttrs;
+  };
+
+  Decl *ActOnMethodDeclaration(
+      Scope *S,
+      SourceLocation BeginLoc, // location of the + or -.
+      SourceLocation EndLoc,   // location of the ; or {.
+      tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
+      ArrayRef SelectorLocs, Selector Sel,
+      // optional arguments. The number of types/arguments is obtained
+      // from the Sel.getNumArgs().
+      ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo,
+      unsigned CNumArgs, // c-style args
+      const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodImplKind,
+      bool isVariadic, bool MethodDefinition);
+
+  bool CheckARCMethodDecl(ObjCMethodDecl *method);
+
+  bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall);
+
+  /// Check whether the given new method is a valid override of the
+  /// given overridden method, and set any properties that should be inherited.
+  void CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
+                               const ObjCMethodDecl *Overridden);
+
+  /// Describes the compatibility of a result type with its method.
+  enum ResultTypeCompatibilityKind {
+    RTC_Compatible,
+    RTC_Incompatible,
+    RTC_Unknown
   };
 
-  static bool isCast(CheckedConversionKind CCK) {
-    return CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast ||
-           CCK == CCK_OtherCast;
-  }
+  void CheckObjCMethodDirectOverrides(ObjCMethodDecl *method,
+                                      ObjCMethodDecl *overridden);
 
-  /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit
-  /// cast.  If there is already an implicit cast, merge into the existing one.
-  /// If isLvalue, the result of the cast is an lvalue.
-  ExprResult
-  ImpCastExprToType(Expr *E, QualType Type, CastKind CK,
-                    ExprValueKind VK = VK_PRValue,
-                    const CXXCastPath *BasePath = nullptr,
-                    CheckedConversionKind CCK = CCK_ImplicitConversion);
+  void CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
+                                ObjCInterfaceDecl *CurrentClass,
+                                ResultTypeCompatibilityKind RTC);
 
-  /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
-  /// to the conversion from scalar type ScalarTy to the Boolean type.
-  static CastKind ScalarTypeToBooleanCastKind(QualType ScalarTy);
+  /// AddAnyMethodToGlobalPool - Add any method, instance or factory to global
+  /// pool.
+  void AddAnyMethodToGlobalPool(Decl *D);
 
-  /// IgnoredValueConversions - Given that an expression's result is
-  /// syntactically ignored, perform any conversions that are
-  /// required.
-  ExprResult IgnoredValueConversions(Expr *E);
+  void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
+  bool isObjCMethodDecl(Decl *D) { return D && isa(D); }
 
-  // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
-  // functions and arrays to their respective pointers (C99 6.3.2.1).
-  ExprResult UsualUnaryConversions(Expr *E);
+  /// CheckImplementationIvars - This routine checks if the instance variables
+  /// listed in the implelementation match those listed in the interface.
+  void CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
+                                ObjCIvarDecl **Fields, unsigned nIvars,
+                                SourceLocation Loc);
 
-  /// CallExprUnaryConversions - a special case of an unary conversion
-  /// performed on a function designator of a call expression.
-  ExprResult CallExprUnaryConversions(Expr *E);
+  void WarnConflictingTypedMethods(ObjCMethodDecl *Method,
+                                   ObjCMethodDecl *MethodDecl,
+                                   bool IsProtocolMethodDecl);
 
-  // DefaultFunctionArrayConversion - converts functions and arrays
-  // to their respective pointers (C99 6.3.2.1).
-  ExprResult DefaultFunctionArrayConversion(Expr *E, bool Diagnose = true);
+  void CheckConflictingOverridingMethod(ObjCMethodDecl *Method,
+                                        ObjCMethodDecl *Overridden,
+                                        bool IsProtocolMethodDecl);
 
-  // DefaultFunctionArrayLvalueConversion - converts functions and
-  // arrays to their respective pointers and performs the
-  // lvalue-to-rvalue conversion.
-  ExprResult DefaultFunctionArrayLvalueConversion(Expr *E,
-                                                  bool Diagnose = true);
+  /// WarnExactTypedMethods - This routine issues a warning if method
+  /// implementation declaration matches exactly that of its declaration.
+  void WarnExactTypedMethods(ObjCMethodDecl *Method, ObjCMethodDecl *MethodDecl,
+                             bool IsProtocolMethodDecl);
 
-  // DefaultLvalueConversion - performs lvalue-to-rvalue conversion on
-  // the operand. This function is a no-op if the operand has a function type
-  // or an array type.
-  ExprResult DefaultLvalueConversion(Expr *E);
+  /// MatchAllMethodDeclarations - Check methods declaraed in interface or
+  /// or protocol against those declared in their implementations.
+  void MatchAllMethodDeclarations(
+      const SelectorSet &InsMap, const SelectorSet &ClsMap,
+      SelectorSet &InsMapSeen, SelectorSet &ClsMapSeen, ObjCImplDecl *IMPDecl,
+      ObjCContainerDecl *IDecl, bool &IncompleteImpl, bool ImmediateClass,
+      bool WarnCategoryMethodImpl = false);
 
-  // DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that
-  // do not have a prototype. Integer promotions are performed on each
-  // argument, and arguments that have type float are promoted to double.
-  ExprResult DefaultArgumentPromotion(Expr *E);
+  /// CheckCategoryVsClassMethodMatches - Checks that methods implemented in
+  /// category matches with those implemented in its primary class and
+  /// warns each time an exact match is found.
+  void CheckCategoryVsClassMethodMatches(ObjCCategoryImplDecl *CatIMP);
 
-  /// If \p E is a prvalue denoting an unmaterialized temporary, materialize
-  /// it as an xvalue. In C++98, the result will still be a prvalue, because
-  /// we don't have xvalues there.
-  ExprResult TemporaryMaterializationConversion(Expr *E);
+  /// ImplMethodsVsClassMethods - This is main routine to warn if any method
+  /// remains unimplemented in the class or category \@implementation.
+  void ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl *IMPDecl,
+                                 ObjCContainerDecl *IDecl,
+                                 bool IncompleteImpl = false);
 
-  // Used for emitting the right warning by DefaultVariadicArgumentPromotion
-  enum VariadicCallType {
-    VariadicFunction,
-    VariadicBlock,
-    VariadicMethod,
-    VariadicConstructor,
-    VariadicDoesNotApply
-  };
+  DeclGroupPtrTy ActOnForwardClassDeclaration(
+      SourceLocation Loc, IdentifierInfo **IdentList, SourceLocation *IdentLocs,
+      ArrayRef TypeParamLists, unsigned NumElts);
 
-  VariadicCallType getVariadicCallType(FunctionDecl *FDecl,
-                                       const FunctionProtoType *Proto,
-                                       Expr *Fn);
+  /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns
+  /// true, or false, accordingly.
+  bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method,
+                                  const ObjCMethodDecl *PrevMethod,
+                                  MethodMatchStrategy strategy = MMS_strict);
 
-  // Used for determining in which context a type is allowed to be passed to a
-  // vararg function.
-  enum VarArgKind {
-    VAK_Valid,
-    VAK_ValidInCXX11,
-    VAK_Undefined,
-    VAK_MSVCUndefined,
-    VAK_Invalid
-  };
+  /// Add the given method to the list of globally-known methods.
+  void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method);
 
-  // Determines which VarArgKind fits an expression.
-  VarArgKind isValidVarArgType(const QualType &Ty);
+  void ReadMethodPool(Selector Sel);
+  void updateOutOfDateSelector(Selector Sel);
 
-  /// Check to see if the given expression is a valid argument to a variadic
-  /// function, issuing a diagnostic if not.
-  void checkVariadicArgument(const Expr *E, VariadicCallType CT);
+  /// - Returns instance or factory methods in global method pool for
+  /// given selector. It checks the desired kind first, if none is found, and
+  /// parameter checkTheOther is set, it then checks the other kind. If no such
+  /// method or only one method is found, function returns false; otherwise, it
+  /// returns true.
+  bool
+  CollectMultipleMethodsInGlobalPool(Selector Sel,
+                                     SmallVectorImpl &Methods,
+                                     bool InstanceFirst, bool CheckTheOther,
+                                     const ObjCObjectType *TypeBound = nullptr);
 
-  /// Check whether the given statement can have musttail applied to it,
-  /// issuing a diagnostic and returning false if not. In the success case,
-  /// the statement is rewritten to remove implicit nodes from the return
-  /// value.
-  bool checkAndRewriteMustTailAttr(Stmt *St, const Attr &MTA);
+  bool
+  AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod,
+                                 SourceRange R, bool receiverIdOrClass,
+                                 SmallVectorImpl &Methods);
 
-private:
-  /// Check whether the given statement can have musttail applied to it,
-  /// issuing a diagnostic and returning false if not.
-  bool checkMustTailAttr(const Stmt *St, const Attr &MTA);
+  void
+  DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl &Methods,
+                                     Selector Sel, SourceRange R,
+                                     bool receiverIdOrClass);
 
-public:
-  /// Check to see if a given expression could have '.c_str()' called on it.
-  bool hasCStrMethod(const Expr *E);
+  const ObjCMethodDecl *
+  SelectorsForTypoCorrection(Selector Sel, QualType ObjectType = QualType());
+  /// LookupImplementedMethodInGlobalPool - Returns the method which has an
+  /// implementation.
+  ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
 
-  /// GatherArgumentsForCall - Collector argument expressions for various
-  /// form of call prototypes.
-  bool GatherArgumentsForCall(SourceLocation CallLoc, FunctionDecl *FDecl,
-                              const FunctionProtoType *Proto,
-                              unsigned FirstParam, ArrayRef Args,
-                              SmallVectorImpl &AllArgs,
-                              VariadicCallType CallType = VariadicDoesNotApply,
-                              bool AllowExplicit = false,
-                              bool IsListInitialization = false);
+  void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID);
 
-  // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but
-  // will create a runtime trap if the resulting type is not a POD type.
-  ExprResult DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
-                                              FunctionDecl *FDecl);
+  /// Checks that the Objective-C declaration is declared in the global scope.
+  /// Emits an error and marks the declaration as invalid if it's not declared
+  /// in the global scope.
+  bool CheckObjCDeclScope(Decl *D);
 
-  /// Context in which we're performing a usual arithmetic conversion.
-  enum ArithConvKind {
-    /// An arithmetic operation.
-    ACK_Arithmetic,
-    /// A bitwise operation.
-    ACK_BitwiseOp,
-    /// A comparison.
-    ACK_Comparison,
-    /// A conditional (?:) operator.
-    ACK_Conditional,
-    /// A compound assignment expression.
-    ACK_CompAssign,
-  };
+  void ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
+                 IdentifierInfo *ClassName, SmallVectorImpl &Decls);
 
-  // UsualArithmeticConversions - performs the UsualUnaryConversions on it's
-  // operands and then handles various conversions that are common to binary
-  // operators (C99 6.3.1.8). If both operands aren't arithmetic, this
-  // routine returns the first non-arithmetic type found. The client is
-  // responsible for emitting appropriate error diagnostics.
-  QualType UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
-                                      SourceLocation Loc, ArithConvKind ACK);
+  VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
+                                  SourceLocation StartLoc, SourceLocation IdLoc,
+                                  IdentifierInfo *Id, bool Invalid = false);
 
-  /// AssignConvertType - All of the 'assignment' semantic checks return this
-  /// enum to indicate whether the assignment was allowed.  These checks are
-  /// done for simple assignments, as well as initialization, return from
-  /// function, argument passing, etc.  The query is phrased in terms of a
-  /// source and destination type.
-  enum AssignConvertType {
-    /// Compatible - the types are compatible according to the standard.
-    Compatible,
+  Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D);
 
-    /// PointerToInt - The assignment converts a pointer to an int, which we
-    /// accept as an extension.
-    PointerToInt,
+  /// CollectIvarsToConstructOrDestruct - Collect those ivars which require
+  /// initialization.
+  void
+  CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
+                                    SmallVectorImpl &Ivars);
 
-    /// IntToPointer - The assignment converts an int to a pointer, which we
-    /// accept as an extension.
-    IntToPointer,
+  void DiagnoseUseOfUnimplementedSelectors();
 
-    /// FunctionVoidPointer - The assignment is between a function pointer and
-    /// void*, which the standard doesn't allow, but we accept as an extension.
-    FunctionVoidPointer,
+  /// DiagnoseUnusedBackingIvarInAccessor - Issue an 'unused' warning if ivar
+  /// which backs the property is not used in the property's accessor.
+  void DiagnoseUnusedBackingIvarInAccessor(Scope *S,
+                                           const ObjCImplementationDecl *ImplD);
 
-    /// IncompatiblePointer - The assignment is between two pointers types that
-    /// are not compatible, but we accept them as an extension.
-    IncompatiblePointer,
+  /// GetIvarBackingPropertyAccessor - If method is a property setter/getter and
+  /// it property has a backing ivar, returns this ivar; otherwise, returns
+  /// NULL. It also returns ivar's property on success.
+  ObjCIvarDecl *
+  GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,
+                                 const ObjCPropertyDecl *&PDecl) const;
 
-    /// IncompatibleFunctionPointer - The assignment is between two function
-    /// pointers types that are not compatible, but we accept them as an
-    /// extension.
-    IncompatibleFunctionPointer,
+  /// AddInstanceMethodToGlobalPool - All instance methods in a translation
+  /// unit are added to a global pool. This allows us to efficiently associate
+  /// a selector with a method declaraation for purposes of typechecking
+  /// messages sent to "id" (where the class of the object is unknown).
+  void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method,
+                                     bool impl = false) {
+    AddMethodToGlobalPool(Method, impl, /*instance*/ true);
+  }
 
-    /// IncompatibleFunctionPointerStrict - The assignment is between two
-    /// function pointer types that are not identical, but are compatible,
-    /// unless compiled with -fsanitize=cfi, in which case the type mismatch
-    /// may trip an indirect call runtime check.
-    IncompatibleFunctionPointerStrict,
+  /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
+  void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl = false) {
+    AddMethodToGlobalPool(Method, impl, /*instance*/ false);
+  }
 
-    /// IncompatiblePointerSign - The assignment is between two pointers types
-    /// which point to integers which have a different sign, but are otherwise
-    /// identical. This is a subset of the above, but broken out because it's by
-    /// far the most common case of incompatible pointers.
-    IncompatiblePointerSign,
+private:
+  /// AddMethodToGlobalPool - Add an instance or factory method to the global
+  /// pool. See descriptoin of AddInstanceMethodToGlobalPool.
+  void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance);
+
+  /// LookupMethodInGlobalPool - Returns the instance or factory method and
+  /// optionally warns if there are multiple signatures.
+  ObjCMethodDecl *LookupMethodInGlobalPool(Selector Sel, SourceRange R,
+                                           bool receiverIdOrClass,
+                                           bool instance);
+
+  ///@}
+
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-    /// CompatiblePointerDiscardsQualifiers - The assignment discards
-    /// c/v/r qualifiers, which we accept as an extension.
-    CompatiblePointerDiscardsQualifiers,
+  /// \name ObjC Expressions
+  /// Implementations are in SemaExprObjC.cpp
+  ///@{
 
-    /// IncompatiblePointerDiscardsQualifiers - The assignment
-    /// discards qualifiers that we don't permit to be discarded,
-    /// like address spaces.
-    IncompatiblePointerDiscardsQualifiers,
+public:
+  /// Caches identifiers/selectors for NSFoundation APIs.
+  std::unique_ptr NSAPIObj;
 
-    /// IncompatibleNestedPointerAddressSpaceMismatch - The assignment
-    /// changes address spaces in nested pointer types which is not allowed.
-    /// For instance, converting __private int ** to __generic int ** is
-    /// illegal even though __private could be converted to __generic.
-    IncompatibleNestedPointerAddressSpaceMismatch,
+  /// The declaration of the Objective-C NSNumber class.
+  ObjCInterfaceDecl *NSNumberDecl;
 
-    /// IncompatibleNestedPointerQualifiers - The assignment is between two
-    /// nested pointer types, and the qualifiers other than the first two
-    /// levels differ e.g. char ** -> const char **, but we accept them as an
-    /// extension.
-    IncompatibleNestedPointerQualifiers,
+  /// The declaration of the Objective-C NSValue class.
+  ObjCInterfaceDecl *NSValueDecl;
 
-    /// IncompatibleVectors - The assignment is between two vector types that
-    /// have the same size, which we accept as an extension.
-    IncompatibleVectors,
+  /// Pointer to NSNumber type (NSNumber *).
+  QualType NSNumberPointer;
 
-    /// IntToBlockPointer - The assignment converts an int to a block
-    /// pointer. We disallow this.
-    IntToBlockPointer,
+  /// Pointer to NSValue type (NSValue *).
+  QualType NSValuePointer;
 
-    /// IncompatibleBlockPointer - The assignment is between two block
-    /// pointers types that are not compatible.
-    IncompatibleBlockPointer,
+  /// The Objective-C NSNumber methods used to create NSNumber literals.
+  ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods];
 
-    /// IncompatibleObjCQualifiedId - The assignment is between a qualified
-    /// id type and something else (that is incompatible with it). For example,
-    /// "id " = "Foo *", where "Foo *" doesn't implement the XXX protocol.
-    IncompatibleObjCQualifiedId,
+  /// The declaration of the Objective-C NSString class.
+  ObjCInterfaceDecl *NSStringDecl;
 
-    /// IncompatibleObjCWeakRef - Assigning a weak-unavailable object to an
-    /// object with __weak qualifier.
-    IncompatibleObjCWeakRef,
+  /// Pointer to NSString type (NSString *).
+  QualType NSStringPointer;
 
-    /// Incompatible - We reject this conversion outright, it is invalid to
-    /// represent it in the AST.
-    Incompatible
-  };
+  /// The declaration of the stringWithUTF8String: method.
+  ObjCMethodDecl *StringWithUTF8StringMethod;
 
-  /// DiagnoseAssignmentResult - Emit a diagnostic, if required, for the
-  /// assignment conversion type specified by ConvTy.  This returns true if the
-  /// conversion was invalid or false if the conversion was accepted.
-  bool DiagnoseAssignmentResult(AssignConvertType ConvTy,
-                                SourceLocation Loc,
-                                QualType DstType, QualType SrcType,
-                                Expr *SrcExpr, AssignmentAction Action,
-                                bool *Complained = nullptr);
+  /// The declaration of the valueWithBytes:objCType: method.
+  ObjCMethodDecl *ValueWithBytesObjCTypeMethod;
 
-  /// IsValueInFlagEnum - Determine if a value is allowed as part of a flag
-  /// enum. If AllowMask is true, then we also allow the complement of a valid
-  /// value, to be used as a mask.
-  bool IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
-                         bool AllowMask) const;
+  /// The declaration of the Objective-C NSArray class.
+  ObjCInterfaceDecl *NSArrayDecl;
 
-  /// DiagnoseAssignmentEnum - Warn if assignment to enum is a constant
-  /// integer not in the range of enum values.
-  void DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,
-                              Expr *SrcExpr);
+  /// The declaration of the arrayWithObjects:count: method.
+  ObjCMethodDecl *ArrayWithObjectsMethod;
 
-  /// CheckAssignmentConstraints - Perform type checking for assignment,
-  /// argument passing, variable initialization, and function return values.
-  /// C99 6.5.16.
-  AssignConvertType CheckAssignmentConstraints(SourceLocation Loc,
-                                               QualType LHSType,
-                                               QualType RHSType);
+  /// The declaration of the Objective-C NSDictionary class.
+  ObjCInterfaceDecl *NSDictionaryDecl;
 
-  /// Check assignment constraints and optionally prepare for a conversion of
-  /// the RHS to the LHS type. The conversion is prepared for if ConvertRHS
-  /// is true.
-  AssignConvertType CheckAssignmentConstraints(QualType LHSType,
-                                               ExprResult &RHS,
-                                               CastKind &Kind,
-                                               bool ConvertRHS = true);
+  /// The declaration of the dictionaryWithObjects:forKeys:count: method.
+  ObjCMethodDecl *DictionaryWithObjectsMethod;
 
-  /// Check assignment constraints for an assignment of RHS to LHSType.
-  ///
-  /// \param LHSType The destination type for the assignment.
-  /// \param RHS The source expression for the assignment.
-  /// \param Diagnose If \c true, diagnostics may be produced when checking
-  ///        for assignability. If a diagnostic is produced, \p RHS will be
-  ///        set to ExprError(). Note that this function may still return
-  ///        without producing a diagnostic, even for an invalid assignment.
-  /// \param DiagnoseCFAudited If \c true, the target is a function parameter
-  ///        in an audited Core Foundation API and does not need to be checked
-  ///        for ARC retain issues.
-  /// \param ConvertRHS If \c true, \p RHS will be updated to model the
-  ///        conversions necessary to perform the assignment. If \c false,
-  ///        \p Diagnose must also be \c false.
-  AssignConvertType CheckSingleAssignmentConstraints(
-      QualType LHSType, ExprResult &RHS, bool Diagnose = true,
-      bool DiagnoseCFAudited = false, bool ConvertRHS = true);
+  /// id type.
+  QualType QIDNSCopying;
 
-  // If the lhs type is a transparent union, check whether we
-  // can initialize the transparent union with the given expression.
-  AssignConvertType CheckTransparentUnionArgumentConstraints(QualType ArgType,
-                                                             ExprResult &RHS);
+  /// will hold 'respondsToSelector:'
+  Selector RespondsToSelectorSel;
 
-  bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
+  ExprResult HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
+                                       Expr *BaseExpr, SourceLocation OpLoc,
+                                       DeclarationName MemberName,
+                                       SourceLocation MemberLoc,
+                                       SourceLocation SuperLoc,
+                                       QualType SuperType, bool Super);
 
-  bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
+  ExprResult ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+                                       IdentifierInfo &propertyName,
+                                       SourceLocation receiverNameLoc,
+                                       SourceLocation propertyNameLoc);
 
-  ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
-                                       AssignmentAction Action,
-                                       bool AllowExplicit = false);
-  ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
-                                       const ImplicitConversionSequence& ICS,
-                                       AssignmentAction Action,
-                                       CheckedConversionKind CCK
-                                          = CCK_ImplicitConversion);
-  ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
-                                       const StandardConversionSequence& SCS,
-                                       AssignmentAction Action,
-                                       CheckedConversionKind CCK);
+  // ParseObjCStringLiteral - Parse Objective-C string literals.
+  ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
+                                    ArrayRef Strings);
 
-  ExprResult PerformQualificationConversion(
-      Expr *E, QualType Ty, ExprValueKind VK = VK_PRValue,
-      CheckedConversionKind CCK = CCK_ImplicitConversion);
+  ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S);
 
-  /// the following "Check" methods will return a valid/converted QualType
-  /// or a null QualType (indicating an error diagnostic was issued).
+  /// BuildObjCNumericLiteral - builds an ObjCBoxedExpr AST node for the
+  /// numeric literal expression. Type of the expression will be "NSNumber *"
+  /// or "id" if NSNumber is unavailable.
+  ExprResult BuildObjCNumericLiteral(SourceLocation AtLoc, Expr *Number);
+  ExprResult ActOnObjCBoolLiteral(SourceLocation AtLoc, SourceLocation ValueLoc,
+                                  bool Value);
+  ExprResult BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements);
 
-  /// type checking binary operators (subroutines of CreateBuiltinBinOp).
-  QualType InvalidOperands(SourceLocation Loc, ExprResult &LHS,
-                           ExprResult &RHS);
-  QualType InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS,
-                                 ExprResult &RHS);
-  QualType CheckPointerToMemberOperands( // C++ 5.5
-    ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK,
-    SourceLocation OpLoc, bool isIndirect);
-  QualType CheckMultiplyDivideOperands( // C99 6.5.5
-    ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign,
-    bool IsDivide);
-  QualType CheckRemainderOperands( // C99 6.5.5
-    ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
-    bool IsCompAssign = false);
-  QualType CheckAdditionOperands( // C99 6.5.6
-    ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
-    BinaryOperatorKind Opc, QualType* CompLHSTy = nullptr);
-  QualType CheckSubtractionOperands( // C99 6.5.6
-    ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
-    QualType* CompLHSTy = nullptr);
-  QualType CheckShiftOperands( // C99 6.5.7
-    ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
-    BinaryOperatorKind Opc, bool IsCompAssign = false);
-  void CheckPtrComparisonWithNullChar(ExprResult &E, ExprResult &NullE);
-  QualType CheckCompareOperands( // C99 6.5.8/9
-      ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
-      BinaryOperatorKind Opc);
-  QualType CheckBitwiseOperands( // C99 6.5.[10...12]
-      ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
-      BinaryOperatorKind Opc);
-  QualType CheckLogicalOperands( // C99 6.5.[13,14]
-    ExprResult &LHS, ExprResult &RHS, SourceLocation Loc,
-    BinaryOperatorKind Opc);
-  // CheckAssignmentOperands is used for both simple and compound assignment.
-  // For simple assignment, pass both expressions and a null converted type.
-  // For compound assignment, pass both expressions and the converted type.
-  QualType CheckAssignmentOperands( // C99 6.5.16.[1,2]
-      Expr *LHSExpr, ExprResult &RHS, SourceLocation Loc, QualType CompoundType,
-      BinaryOperatorKind Opc);
+  /// BuildObjCBoxedExpr - builds an ObjCBoxedExpr AST node for the
+  /// '@' prefixed parenthesized expression. The type of the expression will
+  /// either be "NSNumber *", "NSString *" or "NSValue *" depending on the type
+  /// of ValueType, which is allowed to be a built-in numeric type, "char *",
+  /// "const char *" or C structure with attribute 'objc_boxable'.
+  ExprResult BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr);
 
-  ExprResult checkPseudoObjectIncDec(Scope *S, SourceLocation OpLoc,
-                                     UnaryOperatorKind Opcode, Expr *Op);
-  ExprResult checkPseudoObjectAssignment(Scope *S, SourceLocation OpLoc,
-                                         BinaryOperatorKind Opcode,
-                                         Expr *LHS, Expr *RHS);
-  ExprResult checkPseudoObjectRValue(Expr *E);
-  Expr *recreateSyntacticForm(PseudoObjectExpr *E);
+  ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
+                                          Expr *IndexExpr,
+                                          ObjCMethodDecl *getterMethod,
+                                          ObjCMethodDecl *setterMethod);
 
-  QualType CheckConditionalOperands( // C99 6.5.15
-    ExprResult &Cond, ExprResult &LHS, ExprResult &RHS,
-    ExprValueKind &VK, ExprObjectKind &OK, SourceLocation QuestionLoc);
-  QualType CXXCheckConditionalOperands( // C++ 5.16
-    ExprResult &cond, ExprResult &lhs, ExprResult &rhs,
-    ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
-  QualType CheckVectorConditionalTypes(ExprResult &Cond, ExprResult &LHS,
-                                       ExprResult &RHS,
-                                       SourceLocation QuestionLoc);
+  ExprResult
+  BuildObjCDictionaryLiteral(SourceRange SR,
+                             MutableArrayRef Elements);
 
-  QualType CheckSizelessVectorConditionalTypes(ExprResult &Cond,
-                                               ExprResult &LHS, ExprResult &RHS,
-                                               SourceLocation QuestionLoc);
-  QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2,
-                                    bool ConvertArgs = true);
-  QualType FindCompositePointerType(SourceLocation Loc,
-                                    ExprResult &E1, ExprResult &E2,
-                                    bool ConvertArgs = true) {
-    Expr *E1Tmp = E1.get(), *E2Tmp = E2.get();
-    QualType Composite =
-        FindCompositePointerType(Loc, E1Tmp, E2Tmp, ConvertArgs);
-    E1 = E1Tmp;
-    E2 = E2Tmp;
-    return Composite;
-  }
+  ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc,
+                                       TypeSourceInfo *EncodedTypeInfo,
+                                       SourceLocation RParenLoc);
 
-  QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
-                                        SourceLocation QuestionLoc);
+  ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
+                                       SourceLocation EncodeLoc,
+                                       SourceLocation LParenLoc, ParsedType Ty,
+                                       SourceLocation RParenLoc);
 
-  bool DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr,
-                                  SourceLocation QuestionLoc);
+  /// ParseObjCSelectorExpression - Build selector expression for \@selector
+  ExprResult ParseObjCSelectorExpression(Selector Sel, SourceLocation AtLoc,
+                                         SourceLocation SelLoc,
+                                         SourceLocation LParenLoc,
+                                         SourceLocation RParenLoc,
+                                         bool WarnMultipleSelectors);
 
-  void DiagnoseAlwaysNonNullPointer(Expr *E,
-                                    Expr::NullPointerConstantKind NullType,
-                                    bool IsEqual, SourceRange Range);
+  /// ParseObjCProtocolExpression - Build protocol expression for \@protocol
+  ExprResult ParseObjCProtocolExpression(IdentifierInfo *ProtocolName,
+                                         SourceLocation AtLoc,
+                                         SourceLocation ProtoLoc,
+                                         SourceLocation LParenLoc,
+                                         SourceLocation ProtoIdLoc,
+                                         SourceLocation RParenLoc);
 
-  /// type checking for vector binary operators.
-  QualType CheckVectorOperands(ExprResult &LHS, ExprResult &RHS,
-                               SourceLocation Loc, bool IsCompAssign,
-                               bool AllowBothBool, bool AllowBoolConversion,
-                               bool AllowBoolOperation, bool ReportInvalid);
-  QualType GetSignedVectorType(QualType V);
-  QualType GetSignedSizelessVectorType(QualType V);
-  QualType CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
-                                      SourceLocation Loc,
-                                      BinaryOperatorKind Opc);
-  QualType CheckSizelessVectorCompareOperands(ExprResult &LHS, ExprResult &RHS,
-                                              SourceLocation Loc,
-                                              BinaryOperatorKind Opc);
-  QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
-                                      SourceLocation Loc);
+  ObjCMethodDecl *tryCaptureObjCSelf(SourceLocation Loc);
 
-  // type checking for sizeless vector binary operators.
-  QualType CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS,
-                                       SourceLocation Loc, bool IsCompAssign,
-                                       ArithConvKind OperationKind);
+  /// Describes the kind of message expression indicated by a message
+  /// send that starts with an identifier.
+  enum ObjCMessageKind {
+    /// The message is sent to 'super'.
+    ObjCSuperMessage,
+    /// The message is an instance message.
+    ObjCInstanceMessage,
+    /// The message is a class message, and the identifier is a type
+    /// name.
+    ObjCClassMessage
+  };
 
-  /// Type checking for matrix binary operators.
-  QualType CheckMatrixElementwiseOperands(ExprResult &LHS, ExprResult &RHS,
-                                          SourceLocation Loc,
-                                          bool IsCompAssign);
-  QualType CheckMatrixMultiplyOperands(ExprResult &LHS, ExprResult &RHS,
-                                       SourceLocation Loc, bool IsCompAssign);
+  ObjCMessageKind getObjCMessageKind(Scope *S, IdentifierInfo *Name,
+                                     SourceLocation NameLoc, bool IsSuper,
+                                     bool HasTrailingDot,
+                                     ParsedType &ReceiverType);
 
-  bool isValidSveBitcast(QualType srcType, QualType destType);
-  bool isValidRVVBitcast(QualType srcType, QualType destType);
+  ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc, Selector Sel,
+                               SourceLocation LBracLoc,
+                               ArrayRef SelectorLocs,
+                               SourceLocation RBracLoc, MultiExprArg Args);
 
-  bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy);
+  ExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
+                               QualType ReceiverType, SourceLocation SuperLoc,
+                               Selector Sel, ObjCMethodDecl *Method,
+                               SourceLocation LBracLoc,
+                               ArrayRef SelectorLocs,
+                               SourceLocation RBracLoc, MultiExprArg Args,
+                               bool isImplicit = false);
 
-  bool areVectorTypesSameSize(QualType srcType, QualType destType);
-  bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
-  bool isLaxVectorConversion(QualType srcType, QualType destType);
-  bool anyAltivecTypes(QualType srcType, QualType destType);
+  ExprResult BuildClassMessageImplicit(QualType ReceiverType,
+                                       bool isSuperReceiver, SourceLocation Loc,
+                                       Selector Sel, ObjCMethodDecl *Method,
+                                       MultiExprArg Args);
 
-  /// type checking declaration initializers (C99 6.7.8)
-  bool CheckForConstantInitializer(Expr *e, QualType t);
+  ExprResult ActOnClassMessage(Scope *S, ParsedType Receiver, Selector Sel,
+                               SourceLocation LBracLoc,
+                               ArrayRef SelectorLocs,
+                               SourceLocation RBracLoc, MultiExprArg Args);
 
-  // type checking C++ declaration initializers (C++ [dcl.init]).
+  ExprResult BuildInstanceMessage(Expr *Receiver, QualType ReceiverType,
+                                  SourceLocation SuperLoc, Selector Sel,
+                                  ObjCMethodDecl *Method,
+                                  SourceLocation LBracLoc,
+                                  ArrayRef SelectorLocs,
+                                  SourceLocation RBracLoc, MultiExprArg Args,
+                                  bool isImplicit = false);
 
-  /// ReferenceCompareResult - Expresses the result of comparing two
-  /// types (cv1 T1 and cv2 T2) to determine their compatibility for the
-  /// purposes of initialization by reference (C++ [dcl.init.ref]p4).
-  enum ReferenceCompareResult {
-    /// Ref_Incompatible - The two types are incompatible, so direct
-    /// reference binding is not possible.
-    Ref_Incompatible = 0,
-    /// Ref_Related - The two types are reference-related, which means
-    /// that their unqualified forms (T1 and T2) are either the same
-    /// or T1 is a base class of T2.
-    Ref_Related,
-    /// Ref_Compatible - The two types are reference-compatible.
-    Ref_Compatible
-  };
+  ExprResult BuildInstanceMessageImplicit(Expr *Receiver, QualType ReceiverType,
+                                          SourceLocation Loc, Selector Sel,
+                                          ObjCMethodDecl *Method,
+                                          MultiExprArg Args);
 
-  // Fake up a scoped enumeration that still contextually converts to bool.
-  struct ReferenceConversionsScope {
-    /// The conversions that would be performed on an lvalue of type T2 when
-    /// binding a reference of type T1 to it, as determined when evaluating
-    /// whether T1 is reference-compatible with T2.
-    enum ReferenceConversions {
-      Qualification = 0x1,
-      NestedQualification = 0x2,
-      Function = 0x4,
-      DerivedToBase = 0x8,
-      ObjC = 0x10,
-      ObjCLifetime = 0x20,
+  ExprResult ActOnInstanceMessage(Scope *S, Expr *Receiver, Selector Sel,
+                                  SourceLocation LBracLoc,
+                                  ArrayRef SelectorLocs,
+                                  SourceLocation RBracLoc, MultiExprArg Args);
 
-      LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ObjCLifetime)
-    };
-  };
-  using ReferenceConversions = ReferenceConversionsScope::ReferenceConversions;
+  ExprResult BuildObjCBridgedCast(SourceLocation LParenLoc,
+                                  ObjCBridgeCastKind Kind,
+                                  SourceLocation BridgeKeywordLoc,
+                                  TypeSourceInfo *TSInfo, Expr *SubExpr);
 
-  ReferenceCompareResult
-  CompareReferenceRelationship(SourceLocation Loc, QualType T1, QualType T2,
-                               ReferenceConversions *Conv = nullptr);
+  ExprResult ActOnObjCBridgedCast(Scope *S, SourceLocation LParenLoc,
+                                  ObjCBridgeCastKind Kind,
+                                  SourceLocation BridgeKeywordLoc,
+                                  ParsedType Type, SourceLocation RParenLoc,
+                                  Expr *SubExpr);
 
-  ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType,
-                                 Expr *CastExpr, CastKind &CastKind,
-                                 ExprValueKind &VK, CXXCastPath &Path);
+  void CheckTollFreeBridgeCast(QualType castType, Expr *castExpr);
 
-  /// Force an expression with unknown-type to an expression of the
-  /// given type.
-  ExprResult forceUnknownAnyToType(Expr *E, QualType ToType);
+  void CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr);
 
-  /// Type-check an expression that's being passed to an
-  /// __unknown_anytype parameter.
-  ExprResult checkUnknownAnyArg(SourceLocation callLoc,
-                                Expr *result, QualType ¶mType);
+  bool CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,
+                                     CastKind &Kind);
 
-  // CheckMatrixCast - Check type constraints for matrix casts.
-  // We allow casting between matrixes of the same dimensions i.e. when they
-  // have the same number of rows and column. Returns true if the cast is
-  // invalid.
-  bool CheckMatrixCast(SourceRange R, QualType DestTy, QualType SrcTy,
-                       CastKind &Kind);
+  bool checkObjCBridgeRelatedComponents(SourceLocation Loc, QualType DestType,
+                                        QualType SrcType,
+                                        ObjCInterfaceDecl *&RelatedClass,
+                                        ObjCMethodDecl *&ClassMethod,
+                                        ObjCMethodDecl *&InstanceMethod,
+                                        TypedefNameDecl *&TDNDecl, bool CfToNs,
+                                        bool Diagnose = true);
 
-  // CheckVectorCast - check type constraints for vectors.
-  // Since vectors are an extension, there are no C standard reference for this.
-  // We allow casting between vectors and integer datatypes of the same size.
-  // returns true if the cast is invalid
-  bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
-                       CastKind &Kind);
+  bool CheckObjCBridgeRelatedConversions(SourceLocation Loc, QualType DestType,
+                                         QualType SrcType, Expr *&SrcExpr,
+                                         bool Diagnose = true);
 
-  /// Prepare `SplattedExpr` for a vector splat operation, adding
-  /// implicit casts if necessary.
-  ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr);
+  /// Private Helper predicate to check for 'self'.
+  bool isSelfExpr(Expr *RExpr);
+  bool isSelfExpr(Expr *RExpr, const ObjCMethodDecl *Method);
 
-  // CheckExtVectorCast - check type constraints for extended vectors.
-  // Since vectors are an extension, there are no C standard reference for this.
-  // We allow casting between vectors and integer datatypes of the same size,
-  // or vectors and the element type of that vector.
-  // returns the cast expr
-  ExprResult CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *CastExpr,
-                                CastKind &Kind);
+  ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel,
+                                              const ObjCObjectPointerType *OPT,
+                                              bool IsInstance);
+  ObjCMethodDecl *LookupMethodInObjectType(Selector Sel, QualType Ty,
+                                           bool IsInstance);
 
-  ExprResult BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo, QualType Type,
-                                        SourceLocation LParenLoc,
-                                        Expr *CastExpr,
-                                        SourceLocation RParenLoc);
+  bool isKnownName(StringRef name);
 
   enum ARCConversionResult { ACR_okay, ACR_unbridged, ACR_error };
 
@@ -13305,8 +12629,7 @@ public:
                                           CheckedConversionKind CCK,
                                           bool Diagnose = true,
                                           bool DiagnoseCFAudited = false,
-                                          BinaryOperatorKind Opc = BO_PtrMemD
-                                          );
+                                          BinaryOperatorKind Opc = BO_PtrMemD);
 
   Expr *stripARCUnbridgedCast(Expr *e);
   void diagnoseARCUnbridgedCast(Expr *e);
@@ -13314,20 +12637,6 @@ public:
   bool CheckObjCARCUnavailableWeakConversion(QualType castType,
                                              QualType ExprType);
 
-  /// checkRetainCycles - Check whether an Objective-C message send
-  /// might create an obvious retain cycle.
-  void checkRetainCycles(ObjCMessageExpr *msg);
-  void checkRetainCycles(Expr *receiver, Expr *argument);
-  void checkRetainCycles(VarDecl *Var, Expr *Init);
-
-  /// checkUnsafeAssigns - Check whether +1 expr is being assigned
-  /// to weak/__unsafe_unretained type.
-  bool checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS);
-
-  /// checkUnsafeExprAssigns - Check whether +1 expr is being assigned
-  /// to weak/__unsafe_unretained expression.
-  void checkUnsafeExprAssigns(SourceLocation Loc, Expr *LHS, Expr *RHS);
-
   /// CheckMessageArgumentTypes - Check types in an Obj-C message send.
   /// \param Method - May be null.
   /// \param [out] ReturnType - The return type of the send.
@@ -13356,142 +12665,398 @@ public:
   /// type, and if so, emit a note describing what happened.
   void EmitRelatedResultTypeNoteForReturn(QualType destType);
 
-  class ConditionResult {
-    Decl *ConditionVar;
-    FullExprArg Condition;
-    bool Invalid;
-    std::optional KnownValue;
+  /// LookupInstanceMethodInGlobalPool - Returns the method and warns if
+  /// there are multiple signatures.
+  ObjCMethodDecl *
+  LookupInstanceMethodInGlobalPool(Selector Sel, SourceRange R,
+                                   bool receiverIdOrClass = false) {
+    return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
+                                    /*instance*/ true);
+  }
 
-    friend class Sema;
-    ConditionResult(Sema &S, Decl *ConditionVar, FullExprArg Condition,
-                    bool IsConstexpr)
-        : ConditionVar(ConditionVar), Condition(Condition), Invalid(false) {
-      if (IsConstexpr && Condition.get()) {
-        if (std::optional Val =
-                Condition.get()->getIntegerConstantExpr(S.Context)) {
-          KnownValue = !!(*Val);
-        }
-      }
-    }
-    explicit ConditionResult(bool Invalid)
-        : ConditionVar(nullptr), Condition(nullptr), Invalid(Invalid),
-          KnownValue(std::nullopt) {}
+  /// LookupFactoryMethodInGlobalPool - Returns the method and warns if
+  /// there are multiple signatures.
+  ObjCMethodDecl *
+  LookupFactoryMethodInGlobalPool(Selector Sel, SourceRange R,
+                                  bool receiverIdOrClass = false) {
+    return LookupMethodInGlobalPool(Sel, R, receiverIdOrClass,
+                                    /*instance*/ false);
+  }
 
-  public:
-    ConditionResult() : ConditionResult(false) {}
-    bool isInvalid() const { return Invalid; }
-    std::pair get() const {
-      return std::make_pair(cast_or_null(ConditionVar),
-                            Condition.get());
-    }
-    std::optional getKnownValue() const { return KnownValue; }
-  };
-  static ConditionResult ConditionError() { return ConditionResult(true); }
+  ///@}
 
-  enum class ConditionKind {
-    Boolean,     ///< A boolean condition, from 'if', 'while', 'for', or 'do'.
-    ConstexprIf, ///< A constant boolean condition from 'if constexpr'.
-    Switch       ///< An integral condition for a 'switch' statement.
-  };
-  QualType PreferredConditionType(ConditionKind K) const {
-    return K == ConditionKind::Switch ? Context.IntTy : Context.BoolTy;
-  }
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \name ObjC @property and @synthesize
+  /// Implementations are in SemaObjCProperty.cpp
+  ///@{
+
+public:
+  /// Ensure attributes are consistent with type.
+  /// \param [in, out] Attributes The attributes to check; they will
+  /// be modified to be consistent with \p PropertyTy.
+  void CheckObjCPropertyAttributes(Decl *PropertyPtrTy, SourceLocation Loc,
+                                   unsigned &Attributes,
+                                   bool propertyInPrimaryClass);
+
+  /// Process the specified property declaration and create decls for the
+  /// setters and getters as needed.
+  /// \param property The property declaration being processed
+  void ProcessPropertyDecl(ObjCPropertyDecl *property);
+
+  Decl *ActOnProperty(Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc,
+                      FieldDeclarator &FD, ObjCDeclSpec &ODS,
+                      Selector GetterSel, Selector SetterSel,
+                      tok::ObjCKeywordKind MethodImplKind,
+                      DeclContext *lexicalDC = nullptr);
+
+  Decl *ActOnPropertyImplDecl(Scope *S, SourceLocation AtLoc,
+                              SourceLocation PropertyLoc, bool ImplKind,
+                              IdentifierInfo *PropertyId,
+                              IdentifierInfo *PropertyIvar,
+                              SourceLocation PropertyIvarLoc,
+                              ObjCPropertyQueryKind QueryKind);
+
+  /// Called by ActOnProperty to handle \@property declarations in
+  /// class extensions.
+  ObjCPropertyDecl *HandlePropertyInClassExtension(
+      Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc,
+      FieldDeclarator &FD, Selector GetterSel, SourceLocation GetterNameLoc,
+      Selector SetterSel, SourceLocation SetterNameLoc, const bool isReadWrite,
+      unsigned &Attributes, const unsigned AttributesAsWritten, QualType T,
+      TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind);
+
+  /// Called by ActOnProperty and HandlePropertyInClassExtension to
+  /// handle creating the ObjcPropertyDecl for a category or \@interface.
+  ObjCPropertyDecl *
+  CreatePropertyDecl(Scope *S, ObjCContainerDecl *CDecl, SourceLocation AtLoc,
+                     SourceLocation LParenLoc, FieldDeclarator &FD,
+                     Selector GetterSel, SourceLocation GetterNameLoc,
+                     Selector SetterSel, SourceLocation SetterNameLoc,
+                     const bool isReadWrite, const unsigned Attributes,
+                     const unsigned AttributesAsWritten, QualType T,
+                     TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind,
+                     DeclContext *lexicalDC = nullptr);
+
+  void DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
+                                ObjCPropertyDecl *SuperProperty,
+                                const IdentifierInfo *Name,
+                                bool OverridingProtocolProperty);
+
+  bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD,
+                                        ObjCMethodDecl *Getter,
+                                        SourceLocation Loc);
+
+  /// DiagnoseUnimplementedProperties - This routine warns on those properties
+  /// which must be implemented by this implementation.
+  void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl *IMPDecl,
+                                       ObjCContainerDecl *CDecl,
+                                       bool SynthesizeProperties);
+
+  /// Diagnose any null-resettable synthesized setters.
+  void diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl);
+
+  /// DefaultSynthesizeProperties - This routine default synthesizes all
+  /// properties which must be synthesized in the class's \@implementation.
+  void DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl,
+                                   ObjCInterfaceDecl *IDecl,
+                                   SourceLocation AtEnd);
+  void DefaultSynthesizeProperties(Scope *S, Decl *D, SourceLocation AtEnd);
+
+  /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
+  /// an ivar synthesized for 'Method' and 'Method' is a property accessor
+  /// declared in class 'IFace'.
+  bool IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
+                                      ObjCMethodDecl *Method, ObjCIvarDecl *IV);
+
+  void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D);
+
+  void
+  DiagnoseMissingDesignatedInitOverrides(const ObjCImplementationDecl *ImplD,
+                                         const ObjCInterfaceDecl *IFD);
+
+  /// AtomicPropertySetterGetterRules - This routine enforces the rule (via
+  /// warning) when atomic property has one but not the other user-declared
+  /// setter or getter.
+  void AtomicPropertySetterGetterRules(ObjCImplDecl *IMPDecl,
+                                       ObjCInterfaceDecl *IDecl);
 
-  ConditionResult ActOnCondition(Scope *S, SourceLocation Loc, Expr *SubExpr,
-                                 ConditionKind CK, bool MissingOK = false);
+  ///@}
 
-  ConditionResult ActOnConditionVariable(Decl *ConditionVar,
-                                         SourceLocation StmtLoc,
-                                         ConditionKind CK);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D);
+  /// \name Code Completion
+  /// Implementations are in SemaCodeComplete.cpp
+  ///@{
 
-  ExprResult CheckConditionVariable(VarDecl *ConditionVar,
-                                    SourceLocation StmtLoc,
-                                    ConditionKind CK);
-  ExprResult CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond);
+public:
+  /// Code-completion consumer.
+  CodeCompleteConsumer *CodeCompleter;
 
-  /// CheckBooleanCondition - Diagnose problems involving the use of
-  /// the given expression as a boolean condition (e.g. in an if
-  /// statement).  Also performs the standard function and array
-  /// decays, possibly changing the input variable.
+  /// Describes the context in which code completion occurs.
+  enum ParserCompletionContext {
+    /// Code completion occurs at top-level or namespace context.
+    PCC_Namespace,
+    /// Code completion occurs within a class, struct, or union.
+    PCC_Class,
+    /// Code completion occurs within an Objective-C interface, protocol,
+    /// or category.
+    PCC_ObjCInterface,
+    /// Code completion occurs within an Objective-C implementation or
+    /// category implementation
+    PCC_ObjCImplementation,
+    /// Code completion occurs within the list of instance variables
+    /// in an Objective-C interface, protocol, category, or implementation.
+    PCC_ObjCInstanceVariableList,
+    /// Code completion occurs following one or more template
+    /// headers.
+    PCC_Template,
+    /// Code completion occurs following one or more template
+    /// headers within a class.
+    PCC_MemberTemplate,
+    /// Code completion occurs within an expression.
+    PCC_Expression,
+    /// Code completion occurs within a statement, which may
+    /// also be an expression or a declaration.
+    PCC_Statement,
+    /// Code completion occurs at the beginning of the
+    /// initialization statement (or expression) in a for loop.
+    PCC_ForInit,
+    /// Code completion occurs within the condition of an if,
+    /// while, switch, or for statement.
+    PCC_Condition,
+    /// Code completion occurs within the body of a function on a
+    /// recovery path, where we do not have a specific handle on our position
+    /// in the grammar.
+    PCC_RecoveryInFunction,
+    /// Code completion occurs where only a type is permitted.
+    PCC_Type,
+    /// Code completion occurs in a parenthesized expression, which
+    /// might also be a type cast.
+    PCC_ParenthesizedExpression,
+    /// Code completion occurs within a sequence of declaration
+    /// specifiers within a function, method, or block.
+    PCC_LocalDeclarationSpecifiers,
+    /// Code completion occurs at top-level in a REPL session
+    PCC_TopLevelOrExpression,
+  };
+
+  void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path);
+  void CodeCompleteOrdinaryName(Scope *S,
+                                ParserCompletionContext CompletionContext);
+  void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, bool AllowNonIdentifiers,
+                            bool AllowNestedNameSpecifiers);
+
+  struct CodeCompleteExpressionData;
+  void CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data);
+  void CodeCompleteExpression(Scope *S, QualType PreferredType,
+                              bool IsParenthesized = false);
+  void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase,
+                                       SourceLocation OpLoc, bool IsArrow,
+                                       bool IsBaseExprStatement,
+                                       QualType PreferredType);
+  void CodeCompletePostfixExpression(Scope *S, ExprResult LHS,
+                                     QualType PreferredType);
+  void CodeCompleteTag(Scope *S, unsigned TagSpec);
+  void CodeCompleteTypeQualifiers(DeclSpec &DS);
+  void CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
+                                      const VirtSpecifiers *VS = nullptr);
+  void CodeCompleteBracketDeclarator(Scope *S);
+  void CodeCompleteCase(Scope *S);
+  enum class AttributeCompletion {
+    Attribute,
+    Scope,
+    None,
+  };
+  void CodeCompleteAttribute(
+      AttributeCommonInfo::Syntax Syntax,
+      AttributeCompletion Completion = AttributeCompletion::Attribute,
+      const IdentifierInfo *Scope = nullptr);
+  /// Determines the preferred type of the current function argument, by
+  /// examining the signatures of all possible overloads.
+  /// Returns null if unknown or ambiguous, or if code completion is off.
   ///
-  /// \param Loc - A location associated with the condition, e.g. the
-  /// 'if' keyword.
-  /// \return true iff there were any errors
-  ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E,
-                                   bool IsConstexpr = false);
+  /// If the code completion point has been reached, also reports the function
+  /// signatures that were considered.
+  ///
+  /// FIXME: rename to GuessCallArgumentType to reduce confusion.
+  QualType ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args,
+                                    SourceLocation OpenParLoc);
+  QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc,
+                                           ArrayRef Args,
+                                           SourceLocation OpenParLoc,
+                                           bool Braced);
+  QualType ProduceCtorInitMemberSignatureHelp(
+      Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
+      ArrayRef ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc,
+      bool Braced);
+  QualType ProduceTemplateArgumentSignatureHelp(
+      TemplateTy, ArrayRef, SourceLocation LAngleLoc);
+  void CodeCompleteInitializer(Scope *S, Decl *D);
+  /// Trigger code completion for a record of \p BaseType. \p InitExprs are
+  /// expressions in the initializer list seen so far and \p D is the current
+  /// Designation being parsed.
+  void CodeCompleteDesignator(const QualType BaseType,
+                              llvm::ArrayRef InitExprs,
+                              const Designation &D);
+  void CodeCompleteAfterIf(Scope *S, bool IsBracedThen);
 
-  /// ActOnExplicitBoolSpecifier - Build an ExplicitSpecifier from an expression
-  /// found in an explicit(bool) specifier.
-  ExplicitSpecifier ActOnExplicitBoolSpecifier(Expr *E);
+  void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext,
+                               bool IsUsingDeclaration, QualType BaseType,
+                               QualType PreferredType);
+  void CodeCompleteUsing(Scope *S);
+  void CodeCompleteUsingDirective(Scope *S);
+  void CodeCompleteNamespaceDecl(Scope *S);
+  void CodeCompleteNamespaceAliasDecl(Scope *S);
+  void CodeCompleteOperatorName(Scope *S);
+  void CodeCompleteConstructorInitializer(
+      Decl *Constructor, ArrayRef Initializers);
 
-  /// tryResolveExplicitSpecifier - Attempt to resolve the explict specifier.
-  /// Returns true if the explicit specifier is now resolved.
-  bool tryResolveExplicitSpecifier(ExplicitSpecifier &ExplicitSpec);
+  void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
+                                    bool AfterAmpersand);
+  void CodeCompleteAfterFunctionEquals(Declarator &D);
 
-  /// DiagnoseAssignmentAsCondition - Given that an expression is
-  /// being used as a boolean condition, warn if it's an assignment.
-  void DiagnoseAssignmentAsCondition(Expr *E);
+  void CodeCompleteObjCAtDirective(Scope *S);
+  void CodeCompleteObjCAtVisibility(Scope *S);
+  void CodeCompleteObjCAtStatement(Scope *S);
+  void CodeCompleteObjCAtExpression(Scope *S);
+  void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS);
+  void CodeCompleteObjCPropertyGetter(Scope *S);
+  void CodeCompleteObjCPropertySetter(Scope *S);
+  void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
+                                   bool IsParameter);
+  void CodeCompleteObjCMessageReceiver(Scope *S);
+  void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
+                                    ArrayRef SelIdents,
+                                    bool AtArgumentExpression);
+  void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
+                                    ArrayRef SelIdents,
+                                    bool AtArgumentExpression,
+                                    bool IsSuper = false);
+  void CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
+                                       ArrayRef SelIdents,
+                                       bool AtArgumentExpression,
+                                       ObjCInterfaceDecl *Super = nullptr);
+  void CodeCompleteObjCForCollection(Scope *S, DeclGroupPtrTy IterationVar);
+  void CodeCompleteObjCSelector(Scope *S, ArrayRef SelIdents);
+  void
+  CodeCompleteObjCProtocolReferences(ArrayRef Protocols);
+  void CodeCompleteObjCProtocolDecl(Scope *S);
+  void CodeCompleteObjCInterfaceDecl(Scope *S);
+  void CodeCompleteObjCClassForwardDecl(Scope *S);
+  void CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
+                                  SourceLocation ClassNameLoc);
+  void CodeCompleteObjCImplementationDecl(Scope *S);
+  void CodeCompleteObjCInterfaceCategory(Scope *S, IdentifierInfo *ClassName,
+                                         SourceLocation ClassNameLoc);
+  void CodeCompleteObjCImplementationCategory(Scope *S,
+                                              IdentifierInfo *ClassName,
+                                              SourceLocation ClassNameLoc);
+  void CodeCompleteObjCPropertyDefinition(Scope *S);
+  void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
+                                              IdentifierInfo *PropertyName);
+  void CodeCompleteObjCMethodDecl(Scope *S,
+                                  std::optional IsInstanceMethod,
+                                  ParsedType ReturnType);
+  void CodeCompleteObjCMethodDeclSelector(Scope *S, bool IsInstanceMethod,
+                                          bool AtParameterName,
+                                          ParsedType ReturnType,
+                                          ArrayRef SelIdents);
+  void CodeCompleteObjCClassPropertyRefExpr(Scope *S, IdentifierInfo &ClassName,
+                                            SourceLocation ClassNameLoc,
+                                            bool IsBaseExprStatement);
+  void CodeCompletePreprocessorDirective(bool InConditional);
+  void CodeCompleteInPreprocessorConditionalExclusion(Scope *S);
+  void CodeCompletePreprocessorMacroName(bool IsDefinition);
+  void CodeCompletePreprocessorExpression();
+  void CodeCompletePreprocessorMacroArgument(Scope *S, IdentifierInfo *Macro,
+                                             MacroInfo *MacroInfo,
+                                             unsigned Argument);
+  void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled);
+  void CodeCompleteNaturalLanguage();
+  void CodeCompleteAvailabilityPlatformName();
+  void
+  GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
+                              CodeCompletionTUInfo &CCTUInfo,
+                              SmallVectorImpl &Results);
 
-  /// Redundant parentheses over an equality comparison can indicate
-  /// that the user intended an assignment used as condition.
-  void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE);
+  ///@}
 
-  /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid.
-  ExprResult CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr = false);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Checks that the Objective-C declaration is declared in the global scope.
-  /// Emits an error and marks the declaration as invalid if it's not declared
-  /// in the global scope.
-  bool CheckObjCDeclScope(Decl *D);
+  /// \name FixIt Helpers
+  /// Implementations are in SemaFixItUtils.cpp
+  ///@{
 
-  /// Abstract base class used for diagnosing integer constant
-  /// expression violations.
-  class VerifyICEDiagnoser {
-  public:
-    bool Suppress;
+public:
+  /// Get a string to suggest for zero-initialization of a type.
+  std::string getFixItZeroInitializerForType(QualType T,
+                                             SourceLocation Loc) const;
+  std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const;
 
-    VerifyICEDiagnoser(bool Suppress = false) : Suppress(Suppress) { }
+  ///@}
 
-    virtual SemaDiagnosticBuilder
-    diagnoseNotICEType(Sema &S, SourceLocation Loc, QualType T);
-    virtual SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
-                                                 SourceLocation Loc) = 0;
-    virtual SemaDiagnosticBuilder diagnoseFold(Sema &S, SourceLocation Loc);
-    virtual ~VerifyICEDiagnoser() {}
-  };
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  enum AllowFoldKind {
-    NoFold,
-    AllowFold,
-  };
+  /// \name API Notes
+  /// Implementations are in SemaAPINotes.cpp
+  ///@{
 
-  /// VerifyIntegerConstantExpression - Verifies that an expression is an ICE,
-  /// and reports the appropriate diagnostics. Returns false on success.
-  /// Can optionally return the value of the expression.
-  ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
-                                             VerifyICEDiagnoser &Diagnoser,
-                                             AllowFoldKind CanFold = NoFold);
-  ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
-                                             unsigned DiagID,
-                                             AllowFoldKind CanFold = NoFold);
-  ExprResult VerifyIntegerConstantExpression(Expr *E,
-                                             llvm::APSInt *Result = nullptr,
-                                             AllowFoldKind CanFold = NoFold);
-  ExprResult VerifyIntegerConstantExpression(Expr *E,
-                                             AllowFoldKind CanFold = NoFold) {
-    return VerifyIntegerConstantExpression(E, nullptr, CanFold);
-  }
+public:
+  /// Map any API notes provided for this declaration to attributes on the
+  /// declaration.
+  ///
+  /// Triggered by declaration-attribute processing.
+  void ProcessAPINotes(Decl *D);
 
-  /// VerifyBitField - verifies that a bit field expression is an ICE and has
-  /// the correct width, and that the field type is valid.
-  /// Returns false on success.
-  ExprResult VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
-                            QualType FieldTy, bool IsMsStruct, Expr *BitWidth);
+  ///@}
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \name Name Lookup for RISC-V Vector Intrinsic
+  /// Implementations are in SemaRISCVVectorLookup.cpp
+  ///@{
+
+public:
+  /// Indicate RISC-V vector builtin functions enabled or not.
+  bool DeclareRISCVVBuiltins = false;
+
+  /// Indicate RISC-V SiFive vector builtin functions enabled or not.
+  bool DeclareRISCVSiFiveVectorBuiltins = false;
 
 private:
-  unsigned ForceCUDAHostDeviceDepth = 0;
+  std::unique_ptr RVIntrinsicManager;
+
+  ///@}
+
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \name CUDA
+  /// Implementations are in SemaCUDA.cpp
+  ///@{
 
 public:
   /// Increments our count of the number of times we've seen a pragma forcing
@@ -13504,6 +13069,10 @@ public:
   /// before incrementing, so you can emit an error.
   bool PopForceCUDAHostDevice();
 
+  ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
+                                     MultiExprArg ExecConfig,
+                                     SourceLocation GGGLoc);
+
   /// Diagnostics that are emitted only if we discover that the given function
   /// must be codegen'ed.  Because handling these correctly adds overhead to
   /// compilation, this is currently only enabled for CUDA compilations.
@@ -13558,54 +13127,6 @@ public:
   /// Same as CUDADiagIfDeviceCode, with "host" and "device" switched.
   SemaDiagnosticBuilder CUDADiagIfHostCode(SourceLocation Loc, unsigned DiagID);
 
-  /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current
-  /// context is "used as device code".
-  ///
-  /// - If CurContext is a `declare target` function or it is known that the
-  /// function is emitted for the device, emits the diagnostics immediately.
-  /// - If CurContext is a non-`declare target` function and we are compiling
-  ///   for the device, creates a diagnostic which is emitted if and when we
-  ///   realize that the function will be codegen'ed.
-  ///
-  /// Example usage:
-  ///
-  ///  // Variable-length arrays are not allowed in NVPTX device code.
-  ///  if (diagIfOpenMPDeviceCode(Loc, diag::err_vla_unsupported))
-  ///    return ExprError();
-  ///  // Otherwise, continue parsing as normal.
-  SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc,
-                                               unsigned DiagID,
-                                               const FunctionDecl *FD);
-
-  /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current
-  /// context is "used as host code".
-  ///
-  /// - If CurContext is a `declare target` function or it is known that the
-  /// function is emitted for the host, emits the diagnostics immediately.
-  /// - If CurContext is a non-host function, just ignore it.
-  ///
-  /// Example usage:
-  ///
-  ///  // Variable-length arrays are not allowed in NVPTX device code.
-  ///  if (diagIfOpenMPHostode(Loc, diag::err_vla_unsupported))
-  ///    return ExprError();
-  ///  // Otherwise, continue parsing as normal.
-  SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc,
-                                             unsigned DiagID,
-                                             const FunctionDecl *FD);
-
-  SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID,
-                                   const FunctionDecl *FD = nullptr);
-  SemaDiagnosticBuilder targetDiag(SourceLocation Loc,
-                                   const PartialDiagnostic &PD,
-                                   const FunctionDecl *FD = nullptr) {
-    return targetDiag(Loc, PD.getDiagID(), FD) << PD;
-  }
-
-  /// Check if the type is allowed to be used for the current target.
-  void checkTypeSupport(QualType Ty, SourceLocation Loc,
-                        ValueDecl *D = nullptr);
-
   /// Determines whether the given function is a CUDA device/host/kernel/etc.
   /// function.
   ///
@@ -13696,7 +13217,6 @@ public:
   /// and current compilation settings.
   void MaybeAddCUDAConstantAttr(VarDecl *VD);
 
-public:
   /// Check whether we're allowed to call Callee from the current context.
   ///
   /// - If the call is never allowed in a semantically-correct program
@@ -13747,742 +13267,1491 @@ public:
   bool inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl,
                                                CXXSpecialMember CSM,
                                                CXXMethodDecl *MemberDecl,
-                                               bool ConstRHS,
-                                               bool Diagnose);
+                                               bool ConstRHS, bool Diagnose);
+
+  /// \return true if \p CD can be considered empty according to CUDA
+  /// (E.2.3.1 in CUDA 7.5 Programming guide).
+  bool isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD);
+  bool isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *CD);
+
+  // \brief Checks that initializers of \p Var satisfy CUDA restrictions. In
+  // case of error emits appropriate diagnostic and invalidates \p Var.
+  //
+  // \details CUDA allows only empty constructors as initializers for global
+  // variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all
+  // __shared__ variables whether they are local or not (they all are implicitly
+  // static in CUDA). One exception is that CUDA allows constant initializers
+  // for __constant__ and __device__ variables.
+  void checkAllowedCUDAInitializer(VarDecl *VD);
+
+  /// Check whether NewFD is a valid overload for CUDA. Emits
+  /// diagnostics and invalidates NewFD if not.
+  void checkCUDATargetOverload(FunctionDecl *NewFD,
+                               const LookupResult &Previous);
+  /// Copies target attributes from the template TD to the function FD.
+  void inheritCUDATargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD);
+
+  /// Returns the name of the launch configuration function.  This is the name
+  /// of the function that will be called to configure kernel call, with the
+  /// parameters specified via <<<>>>.
+  std::string getCudaConfigureFuncName() const;
+
+private:
+  unsigned ForceCUDAHostDeviceDepth = 0;
+
+  ///@}
+
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \name HLSL Constructs
+  /// Implementations are in SemaHLSL.cpp
+  ///@{
+
+public:
+  Decl *ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer,
+                             SourceLocation KwLoc, IdentifierInfo *Ident,
+                             SourceLocation IdentLoc, SourceLocation LBrace);
+  void ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace);
+
+  bool CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
+
+  bool SemaBuiltinVectorMath(CallExpr *TheCall, QualType &Res);
+  bool SemaBuiltinVectorToScalarMath(CallExpr *TheCall);
+
+  ///@}
+
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \name OpenACC Constructs
+  /// Implementations are in SemaOpenACC.cpp
+  ///@{
+
+public:
+  /// Called after parsing an OpenACC Clause so that it can be checked.
+  bool ActOnOpenACCClause(OpenACCClauseKind ClauseKind,
+                          SourceLocation StartLoc);
+
+  /// Called after the construct has been parsed, but clauses haven't been
+  /// parsed.  This allows us to diagnose not-implemented, as well as set up any
+  /// state required for parsing the clauses.
+  void ActOnOpenACCConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc);
+
+  /// Called after the directive, including its clauses, have been parsed and
+  /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES
+  /// happen before any associated declarations or statements have been parsed.
+  /// This function is only called when we are parsing a 'statement' context.
+  bool ActOnStartOpenACCStmtDirective(OpenACCDirectiveKind K,
+                                      SourceLocation StartLoc);
+
+  /// Called after the directive, including its clauses, have been parsed and
+  /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES
+  /// happen before any associated declarations or statements have been parsed.
+  /// This function is only called when we are parsing a 'Decl' context.
+  bool ActOnStartOpenACCDeclDirective(OpenACCDirectiveKind K,
+                                      SourceLocation StartLoc);
+  /// Called when we encounter an associated statement for our construct, this
+  /// should check legality of the statement as it appertains to this Construct.
+  StmtResult ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K,
+                                        StmtResult AssocStmt);
+
+  /// Called after the directive has been completely parsed, including the
+  /// declaration group or associated statement.
+  StmtResult ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K,
+                                          SourceLocation StartLoc,
+                                          SourceLocation EndLoc,
+                                          StmtResult AssocStmt);
+  /// Called after the directive has been completely parsed, including the
+  /// declaration group or associated statement.
+  DeclGroupRef ActOnEndOpenACCDeclDirective();
+
+  ///@}
+
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \name OpenMP Directives and Clauses
+  /// Implementations are in SemaOpenMP.cpp
+  ///@{
+
+public:
+  /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current
+  /// context is "used as device code".
+  ///
+  /// - If CurContext is a `declare target` function or it is known that the
+  /// function is emitted for the device, emits the diagnostics immediately.
+  /// - If CurContext is a non-`declare target` function and we are compiling
+  ///   for the device, creates a diagnostic which is emitted if and when we
+  ///   realize that the function will be codegen'ed.
+  ///
+  /// Example usage:
+  ///
+  ///  // Variable-length arrays are not allowed in NVPTX device code.
+  ///  if (diagIfOpenMPDeviceCode(Loc, diag::err_vla_unsupported))
+  ///    return ExprError();
+  ///  // Otherwise, continue parsing as normal.
+  SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc,
+                                               unsigned DiagID,
+                                               const FunctionDecl *FD);
+
+  /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current
+  /// context is "used as host code".
+  ///
+  /// - If CurContext is a `declare target` function or it is known that the
+  /// function is emitted for the host, emits the diagnostics immediately.
+  /// - If CurContext is a non-host function, just ignore it.
+  ///
+  /// Example usage:
+  ///
+  ///  // Variable-length arrays are not allowed in NVPTX device code.
+  ///  if (diagIfOpenMPHostode(Loc, diag::err_vla_unsupported))
+  ///    return ExprError();
+  ///  // Otherwise, continue parsing as normal.
+  SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc,
+                                             unsigned DiagID,
+                                             const FunctionDecl *FD);
+
+  /// Register \p D as specialization of all base functions in \p Bases in the
+  /// current `omp begin/end declare variant` scope.
+  void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
+      Decl *D, SmallVectorImpl &Bases);
+
+  /// Act on \p D, a function definition inside of an `omp [begin/end] assumes`.
+  void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D);
+
+  /// Can we exit an OpenMP declare variant scope at the moment.
+  bool isInOpenMPDeclareVariantScope() const {
+    return !OMPDeclareVariantScopes.empty();
+  }
+
+  ExprResult
+  VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind,
+                                        bool StrictlyPositive = true,
+                                        bool SuppressExprDiags = false);
+
+  /// Given the potential call expression \p Call, determine if there is a
+  /// specialization via the OpenMP declare variant mechanism available. If
+  /// there is, return the specialized call expression, otherwise return the
+  /// original \p Call.
+  ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope,
+                             SourceLocation LParenLoc, MultiExprArg ArgExprs,
+                             SourceLocation RParenLoc, Expr *ExecConfig);
+
+  /// Handle a `omp begin declare variant`.
+  void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI);
+
+  /// Handle a `omp end declare variant`.
+  void ActOnOpenMPEndDeclareVariant();
+
+  /// Function tries to capture lambda's captured variables in the OpenMP region
+  /// before the original lambda is captured.
+  void tryCaptureOpenMPLambdas(ValueDecl *V);
 
-  /// \return true if \p CD can be considered empty according to CUDA
-  /// (E.2.3.1 in CUDA 7.5 Programming guide).
-  bool isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD);
-  bool isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *CD);
+  /// Return true if the provided declaration \a VD should be captured by
+  /// reference.
+  /// \param Level Relative level of nested OpenMP construct for that the check
+  /// is performed.
+  /// \param OpenMPCaptureLevel Capture level within an OpenMP construct.
+  bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
+                             unsigned OpenMPCaptureLevel) const;
 
-  // \brief Checks that initializers of \p Var satisfy CUDA restrictions. In
-  // case of error emits appropriate diagnostic and invalidates \p Var.
-  //
-  // \details CUDA allows only empty constructors as initializers for global
-  // variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all
-  // __shared__ variables whether they are local or not (they all are implicitly
-  // static in CUDA). One exception is that CUDA allows constant initializers
-  // for __constant__ and __device__ variables.
-  void checkAllowedCUDAInitializer(VarDecl *VD);
+  /// Check if the specified variable is used in one of the private
+  /// clauses (private, firstprivate, lastprivate, reduction etc.) in OpenMP
+  /// constructs.
+  VarDecl *isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo = false,
+                                unsigned StopAt = 0);
 
-  /// Check whether NewFD is a valid overload for CUDA. Emits
-  /// diagnostics and invalidates NewFD if not.
-  void checkCUDATargetOverload(FunctionDecl *NewFD,
-                               const LookupResult &Previous);
-  /// Copies target attributes from the template TD to the function FD.
-  void inheritCUDATargetAttrs(FunctionDecl *FD, const FunctionTemplateDecl &TD);
+  /// The member expression(this->fd) needs to be rebuilt in the template
+  /// instantiation to generate private copy for OpenMP when default
+  /// clause is used. The function will return true if default
+  /// cluse is used.
+  bool isOpenMPRebuildMemberExpr(ValueDecl *D);
 
-  /// Returns the name of the launch configuration function.  This is the name
-  /// of the function that will be called to configure kernel call, with the
-  /// parameters specified via <<<>>>.
-  std::string getCudaConfigureFuncName() const;
+  ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
+                                   ExprObjectKind OK, SourceLocation Loc);
 
-  /// \name Code completion
-  //@{
-  /// Describes the context in which code completion occurs.
-  enum ParserCompletionContext {
-    /// Code completion occurs at top-level or namespace context.
-    PCC_Namespace,
-    /// Code completion occurs within a class, struct, or union.
-    PCC_Class,
-    /// Code completion occurs within an Objective-C interface, protocol,
-    /// or category.
-    PCC_ObjCInterface,
-    /// Code completion occurs within an Objective-C implementation or
-    /// category implementation
-    PCC_ObjCImplementation,
-    /// Code completion occurs within the list of instance variables
-    /// in an Objective-C interface, protocol, category, or implementation.
-    PCC_ObjCInstanceVariableList,
-    /// Code completion occurs following one or more template
-    /// headers.
-    PCC_Template,
-    /// Code completion occurs following one or more template
-    /// headers within a class.
-    PCC_MemberTemplate,
-    /// Code completion occurs within an expression.
-    PCC_Expression,
-    /// Code completion occurs within a statement, which may
-    /// also be an expression or a declaration.
-    PCC_Statement,
-    /// Code completion occurs at the beginning of the
-    /// initialization statement (or expression) in a for loop.
-    PCC_ForInit,
-    /// Code completion occurs within the condition of an if,
-    /// while, switch, or for statement.
-    PCC_Condition,
-    /// Code completion occurs within the body of a function on a
-    /// recovery path, where we do not have a specific handle on our position
-    /// in the grammar.
-    PCC_RecoveryInFunction,
-    /// Code completion occurs where only a type is permitted.
-    PCC_Type,
-    /// Code completion occurs in a parenthesized expression, which
-    /// might also be a type cast.
-    PCC_ParenthesizedExpression,
-    /// Code completion occurs within a sequence of declaration
-    /// specifiers within a function, method, or block.
-    PCC_LocalDeclarationSpecifiers,
-    /// Code completion occurs at top-level in a REPL session
-    PCC_TopLevelOrExpression,
-  };
+  /// If the current region is a loop-based region, mark the start of the loop
+  /// construct.
+  void startOpenMPLoop();
 
-  void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path);
-  void CodeCompleteOrdinaryName(Scope *S,
-                                ParserCompletionContext CompletionContext);
-  void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
-                            bool AllowNonIdentifiers,
-                            bool AllowNestedNameSpecifiers);
+  /// If the current region is a range loop-based region, mark the start of the
+  /// loop construct.
+  void startOpenMPCXXRangeFor();
 
-  struct CodeCompleteExpressionData;
-  void CodeCompleteExpression(Scope *S,
-                              const CodeCompleteExpressionData &Data);
-  void CodeCompleteExpression(Scope *S, QualType PreferredType,
-                              bool IsParenthesized = false);
-  void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase,
-                                       SourceLocation OpLoc, bool IsArrow,
-                                       bool IsBaseExprStatement,
-                                       QualType PreferredType);
-  void CodeCompletePostfixExpression(Scope *S, ExprResult LHS,
-                                     QualType PreferredType);
-  void CodeCompleteTag(Scope *S, unsigned TagSpec);
-  void CodeCompleteTypeQualifiers(DeclSpec &DS);
-  void CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
-                                      const VirtSpecifiers *VS = nullptr);
-  void CodeCompleteBracketDeclarator(Scope *S);
-  void CodeCompleteCase(Scope *S);
-  enum class AttributeCompletion {
-    Attribute,
-    Scope,
-    None,
-  };
-  void CodeCompleteAttribute(
-      AttributeCommonInfo::Syntax Syntax,
-      AttributeCompletion Completion = AttributeCompletion::Attribute,
-      const IdentifierInfo *Scope = nullptr);
-  /// Determines the preferred type of the current function argument, by
-  /// examining the signatures of all possible overloads.
-  /// Returns null if unknown or ambiguous, or if code completion is off.
-  ///
-  /// If the code completion point has been reached, also reports the function
-  /// signatures that were considered.
-  ///
-  /// FIXME: rename to GuessCallArgumentType to reduce confusion.
-  QualType ProduceCallSignatureHelp(Expr *Fn, ArrayRef Args,
-                                    SourceLocation OpenParLoc);
-  QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc,
-                                           ArrayRef Args,
-                                           SourceLocation OpenParLoc,
-                                           bool Braced);
-  QualType ProduceCtorInitMemberSignatureHelp(
-      Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
-      ArrayRef ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc,
-      bool Braced);
-  QualType ProduceTemplateArgumentSignatureHelp(
-      TemplateTy, ArrayRef, SourceLocation LAngleLoc);
-  void CodeCompleteInitializer(Scope *S, Decl *D);
-  /// Trigger code completion for a record of \p BaseType. \p InitExprs are
-  /// expressions in the initializer list seen so far and \p D is the current
-  /// Designation being parsed.
-  void CodeCompleteDesignator(const QualType BaseType,
-                              llvm::ArrayRef InitExprs,
-                              const Designation &D);
-  void CodeCompleteAfterIf(Scope *S, bool IsBracedThen);
+  /// Check if the specified variable is used in 'private' clause.
+  /// \param Level Relative level of nested OpenMP construct for that the check
+  /// is performed.
+  OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level,
+                                       unsigned CapLevel) const;
 
-  void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext,
-                               bool IsUsingDeclaration, QualType BaseType,
-                               QualType PreferredType);
-  void CodeCompleteUsing(Scope *S);
-  void CodeCompleteUsingDirective(Scope *S);
-  void CodeCompleteNamespaceDecl(Scope *S);
-  void CodeCompleteNamespaceAliasDecl(Scope *S);
-  void CodeCompleteOperatorName(Scope *S);
-  void CodeCompleteConstructorInitializer(
-                                Decl *Constructor,
-                                ArrayRef Initializers);
+  /// Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.)
+  /// for \p FD based on DSA for the provided corresponding captured declaration
+  /// \p D.
+  void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level);
 
-  void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
-                                    bool AfterAmpersand);
-  void CodeCompleteAfterFunctionEquals(Declarator &D);
+  /// Check if the specified variable is captured  by 'target' directive.
+  /// \param Level Relative level of nested OpenMP construct for that the check
+  /// is performed.
+  bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level,
+                                  unsigned CaptureLevel) const;
 
-  void CodeCompleteObjCAtDirective(Scope *S);
-  void CodeCompleteObjCAtVisibility(Scope *S);
-  void CodeCompleteObjCAtStatement(Scope *S);
-  void CodeCompleteObjCAtExpression(Scope *S);
-  void CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS);
-  void CodeCompleteObjCPropertyGetter(Scope *S);
-  void CodeCompleteObjCPropertySetter(Scope *S);
-  void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
-                                   bool IsParameter);
-  void CodeCompleteObjCMessageReceiver(Scope *S);
-  void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
-                                    ArrayRef SelIdents,
-                                    bool AtArgumentExpression);
-  void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
-                                    ArrayRef SelIdents,
-                                    bool AtArgumentExpression,
-                                    bool IsSuper = false);
-  void CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
-                                       ArrayRef SelIdents,
-                                       bool AtArgumentExpression,
-                                       ObjCInterfaceDecl *Super = nullptr);
-  void CodeCompleteObjCForCollection(Scope *S,
-                                     DeclGroupPtrTy IterationVar);
-  void CodeCompleteObjCSelector(Scope *S,
-                                ArrayRef SelIdents);
-  void CodeCompleteObjCProtocolReferences(
-                                         ArrayRef Protocols);
-  void CodeCompleteObjCProtocolDecl(Scope *S);
-  void CodeCompleteObjCInterfaceDecl(Scope *S);
-  void CodeCompleteObjCClassForwardDecl(Scope *S);
-  void CodeCompleteObjCSuperclass(Scope *S,
-                                  IdentifierInfo *ClassName,
-                                  SourceLocation ClassNameLoc);
-  void CodeCompleteObjCImplementationDecl(Scope *S);
-  void CodeCompleteObjCInterfaceCategory(Scope *S,
-                                         IdentifierInfo *ClassName,
-                                         SourceLocation ClassNameLoc);
-  void CodeCompleteObjCImplementationCategory(Scope *S,
-                                              IdentifierInfo *ClassName,
-                                              SourceLocation ClassNameLoc);
-  void CodeCompleteObjCPropertyDefinition(Scope *S);
-  void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
-                                              IdentifierInfo *PropertyName);
-  void CodeCompleteObjCMethodDecl(Scope *S,
-                                  std::optional IsInstanceMethod,
-                                  ParsedType ReturnType);
-  void CodeCompleteObjCMethodDeclSelector(Scope *S,
-                                          bool IsInstanceMethod,
-                                          bool AtParameterName,
-                                          ParsedType ReturnType,
-                                          ArrayRef SelIdents);
-  void CodeCompleteObjCClassPropertyRefExpr(Scope *S, IdentifierInfo &ClassName,
-                                            SourceLocation ClassNameLoc,
-                                            bool IsBaseExprStatement);
-  void CodeCompletePreprocessorDirective(bool InConditional);
-  void CodeCompleteInPreprocessorConditionalExclusion(Scope *S);
-  void CodeCompletePreprocessorMacroName(bool IsDefinition);
-  void CodeCompletePreprocessorExpression();
-  void CodeCompletePreprocessorMacroArgument(Scope *S,
-                                             IdentifierInfo *Macro,
-                                             MacroInfo *MacroInfo,
-                                             unsigned Argument);
-  void CodeCompleteIncludedFile(llvm::StringRef Dir, bool IsAngled);
-  void CodeCompleteNaturalLanguage();
-  void CodeCompleteAvailabilityPlatformName();
-  void GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
-                                   CodeCompletionTUInfo &CCTUInfo,
-                  SmallVectorImpl &Results);
-  //@}
+  /// Check if the specified global variable must be captured  by outer capture
+  /// regions.
+  /// \param Level Relative level of nested OpenMP construct for that
+  /// the check is performed.
+  bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level,
+                                  unsigned CaptureLevel) const;
 
-  //===--------------------------------------------------------------------===//
-  // Extra semantic analysis beyond the C type system
+  ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc,
+                                                    Expr *Op);
+  /// Called on start of new data sharing attribute block.
+  void StartOpenMPDSABlock(OpenMPDirectiveKind K,
+                           const DeclarationNameInfo &DirName, Scope *CurScope,
+                           SourceLocation Loc);
+  /// Start analysis of clauses.
+  void StartOpenMPClause(OpenMPClauseKind K);
+  /// End analysis of clauses.
+  void EndOpenMPClause();
+  /// Called on end of data sharing attribute block.
+  void EndOpenMPDSABlock(Stmt *CurDirective);
 
-public:
-  SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
-                                                unsigned ByteNo) const;
+  /// Check if the current region is an OpenMP loop region and if it is,
+  /// mark loop control variable, used in \p Init for loop initialization, as
+  /// private by default.
+  /// \param Init First part of the for loop.
+  void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init);
 
-  enum FormatArgumentPassingKind {
-    FAPK_Fixed,    // values to format are fixed (no C-style variadic arguments)
-    FAPK_Variadic, // values to format are passed as variadic arguments
-    FAPK_VAList,   // values to format are passed in a va_list
-  };
+  /// Called on well-formed '\#pragma omp metadirective' after parsing
+  /// of the  associated statement.
+  StmtResult ActOnOpenMPMetaDirective(ArrayRef Clauses,
+                                      Stmt *AStmt, SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
 
-  // Used to grab the relevant information from a FormatAttr and a
-  // FunctionDeclaration.
-  struct FormatStringInfo {
-    unsigned FormatIdx;
-    unsigned FirstDataArg;
-    FormatArgumentPassingKind ArgPassingKind;
-  };
+  // OpenMP directives and clauses.
+  /// Called on correct id-expression from the '#pragma omp
+  /// threadprivate'.
+  ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec,
+                                     const DeclarationNameInfo &Id,
+                                     OpenMPDirectiveKind Kind);
+  /// Called on well-formed '#pragma omp threadprivate'.
+  DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc,
+                                                   ArrayRef VarList);
+  /// Builds a new OpenMPThreadPrivateDecl and checks its correctness.
+  OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(SourceLocation Loc,
+                                                  ArrayRef VarList);
+  /// Called on well-formed '#pragma omp allocate'.
+  DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc,
+                                              ArrayRef VarList,
+                                              ArrayRef Clauses,
+                                              DeclContext *Owner = nullptr);
 
-  static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
-                                  bool IsVariadic, FormatStringInfo *FSI);
+  /// Called on well-formed '#pragma omp [begin] assume[s]'.
+  void ActOnOpenMPAssumesDirective(SourceLocation Loc,
+                                   OpenMPDirectiveKind DKind,
+                                   ArrayRef Assumptions,
+                                   bool SkippedClauses);
 
-private:
-  void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
-                        const ArraySubscriptExpr *ASE = nullptr,
-                        bool AllowOnePastEnd = true, bool IndexNegated = false);
-  void CheckArrayAccess(const Expr *E);
+  /// Check if there is an active global `omp begin assumes` directive.
+  bool isInOpenMPAssumeScope() const { return !OMPAssumeScoped.empty(); }
 
-  bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall,
-                         const FunctionProtoType *Proto);
-  bool CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation loc,
-                           ArrayRef Args);
-  bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall,
-                        const FunctionProtoType *Proto);
-  bool CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto);
-  void CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType,
-                            ArrayRef Args,
-                            const FunctionProtoType *Proto, SourceLocation Loc);
+  /// Check if there is an active global `omp assumes` directive.
+  bool hasGlobalOpenMPAssumes() const { return !OMPAssumeGlobal.empty(); }
 
-  void checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg);
+  /// Called on well-formed '#pragma omp end assumes'.
+  void ActOnOpenMPEndAssumesDirective();
 
-  void CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl,
-                         StringRef ParamName, QualType ArgTy, QualType ParamTy);
+  /// Called on well-formed '#pragma omp requires'.
+  DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc,
+                                              ArrayRef ClauseList);
+  /// Check restrictions on Requires directive
+  OMPRequiresDecl *CheckOMPRequiresDecl(SourceLocation Loc,
+                                        ArrayRef Clauses);
+  /// Check if the specified type is allowed to be used in 'omp declare
+  /// reduction' construct.
+  QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc,
+                                           TypeResult ParsedType);
+  /// Called on start of '#pragma omp declare reduction'.
+  DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(
+      Scope *S, DeclContext *DC, DeclarationName Name,
+      ArrayRef> ReductionTypes,
+      AccessSpecifier AS, Decl *PrevDeclInScope = nullptr);
+  /// Initialize declare reduction construct initializer.
+  void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D);
+  /// Finish current declare reduction construct initializer.
+  void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner);
+  /// Initialize declare reduction construct initializer.
+  /// \return omp_priv variable.
+  VarDecl *ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D);
+  /// Finish current declare reduction construct initializer.
+  void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer,
+                                                 VarDecl *OmpPrivParm);
+  /// Called at the end of '#pragma omp declare reduction'.
+  DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(
+      Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid);
 
-  void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
-                 const Expr *ThisArg, ArrayRef Args,
-                 bool IsMemberFunction, SourceLocation Loc, SourceRange Range,
-                 VariadicCallType CallType);
+  /// Check variable declaration in 'omp declare mapper' construct.
+  TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D);
+  /// Check if the specified type is allowed to be used in 'omp declare
+  /// mapper' construct.
+  QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc,
+                                        TypeResult ParsedType);
+  /// Called on start of '#pragma omp declare mapper'.
+  DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(
+      Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
+      SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS,
+      Expr *MapperVarRef, ArrayRef Clauses,
+      Decl *PrevDeclInScope = nullptr);
+  /// Build the mapper variable of '#pragma omp declare mapper'.
+  ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S,
+                                                      QualType MapperType,
+                                                      SourceLocation StartLoc,
+                                                      DeclarationName VN);
+  void ActOnOpenMPIteratorVarDecl(VarDecl *VD);
+  bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const;
+  const ValueDecl *getOpenMPDeclareMapperVarName() const;
 
-  bool CheckObjCString(Expr *Arg);
-  ExprResult CheckOSLogFormatStringArg(Expr *Arg);
+  struct DeclareTargetContextInfo {
+    struct MapInfo {
+      OMPDeclareTargetDeclAttr::MapTypeTy MT;
+      SourceLocation Loc;
+    };
+    /// Explicitly listed variables and functions in a 'to' or 'link' clause.
+    llvm::DenseMap ExplicitlyMapped;
 
-  ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl,
-                                      unsigned BuiltinID, CallExpr *TheCall);
+    /// The 'device_type' as parsed from the clause.
+    OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
 
-  bool CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
-                                  CallExpr *TheCall);
+    /// The directive kind, `begin declare target` or `declare target`.
+    OpenMPDirectiveKind Kind;
 
-  void checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, CallExpr *TheCall);
+    /// The directive with indirect clause.
+    std::optional Indirect;
 
-  bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
-                                    unsigned MaxWidth);
-  bool CheckNeonBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
-                                    CallExpr *TheCall);
-  bool CheckMVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
-  bool CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
-  bool ParseSVEImmChecks(CallExpr *TheCall,
-                         SmallVector, 3> &ImmChecks);
-  bool CheckSMEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
-  bool CheckCDEBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
-                                   CallExpr *TheCall);
-  bool CheckARMCoprocessorImmediate(const TargetInfo &TI, const Expr *CoprocArg,
-                                    bool WantCDE);
-  bool CheckARMBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
-                                   CallExpr *TheCall);
+    /// The directive location.
+    SourceLocation Loc;
 
-  bool CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
-                                       CallExpr *TheCall);
-  bool CheckBPFBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
-  bool CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
-  bool CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
-  bool CheckMipsBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
-                                    CallExpr *TheCall);
-  bool CheckMipsBuiltinCpu(const TargetInfo &TI, unsigned BuiltinID,
-                           CallExpr *TheCall);
-  bool CheckMipsBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall);
-  bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
-  bool CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall);
-  bool CheckX86BuiltinGatherScatterScale(unsigned BuiltinID, CallExpr *TheCall);
-  bool CheckX86BuiltinTileArguments(unsigned BuiltinID, CallExpr *TheCall);
-  bool CheckX86BuiltinTileArgumentsRange(CallExpr *TheCall,
-                                         ArrayRef ArgNums);
-  bool CheckX86BuiltinTileDuplicate(CallExpr *TheCall, ArrayRef ArgNums);
-  bool CheckX86BuiltinTileRangeAndDuplicate(CallExpr *TheCall,
-                                            ArrayRef ArgNums);
-  bool CheckX86BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
-                                   CallExpr *TheCall);
-  bool CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
-                                   CallExpr *TheCall);
-  bool CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
-  bool CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall);
-  bool CheckRISCVLMUL(CallExpr *TheCall, unsigned ArgNum);
-  bool CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
-                                     CallExpr *TheCall);
-  void checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D);
-  bool CheckLoongArchBuiltinFunctionCall(const TargetInfo &TI,
-                                         unsigned BuiltinID, CallExpr *TheCall);
-  bool CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI,
-                                           unsigned BuiltinID,
-                                           CallExpr *TheCall);
-  bool CheckNVPTXBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
-                                     CallExpr *TheCall);
+    DeclareTargetContextInfo(OpenMPDirectiveKind Kind, SourceLocation Loc)
+        : Kind(Kind), Loc(Loc) {}
+  };
 
-  bool SemaBuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall);
-  bool SemaBuiltinVAStartARMMicrosoft(CallExpr *Call);
-  bool SemaBuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID);
-  bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs,
-                                   unsigned BuiltinID);
-  bool SemaBuiltinComplex(CallExpr *TheCall);
-  bool SemaBuiltinVSX(CallExpr *TheCall);
-  bool SemaBuiltinOSLogFormat(CallExpr *TheCall);
-  bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
+  /// Called on the start of target region i.e. '#pragma omp declare target'.
+  bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI);
 
-public:
-  bool IsLayoutCompatible(QualType T1, QualType T2) const;
+  /// Called at the end of target region i.e. '#pragma omp end declare target'.
+  const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective();
 
-  // Used by C++ template instantiation.
-  ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
-  ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
-                                   SourceLocation BuiltinLoc,
-                                   SourceLocation RParenLoc);
+  /// Called once a target context is completed, that can be when a
+  /// '#pragma omp end declare target' was encountered or when a
+  /// '#pragma omp declare target' without declaration-definition-seq was
+  /// encountered.
+  void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI);
 
-private:
-  bool SemaBuiltinPrefetch(CallExpr *TheCall);
-  bool SemaBuiltinAllocaWithAlign(CallExpr *TheCall);
-  bool SemaBuiltinArithmeticFence(CallExpr *TheCall);
-  bool SemaBuiltinAssume(CallExpr *TheCall);
-  bool SemaBuiltinAssumeAligned(CallExpr *TheCall);
-  bool SemaBuiltinLongjmp(CallExpr *TheCall);
-  bool SemaBuiltinSetjmp(CallExpr *TheCall);
-  ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult);
-  ExprResult SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult);
-  ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult,
-                                     AtomicExpr::AtomicOp Op);
-  ExprResult SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult,
-                                                    bool IsDelete);
-  bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum,
-                              llvm::APSInt &Result);
-  bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low,
-                                   int High, bool RangeIsError = true);
-  bool SemaBuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum,
-                                      unsigned Multiple);
-  bool SemaBuiltinConstantArgPower2(CallExpr *TheCall, int ArgNum);
-  bool SemaBuiltinConstantArgShiftedByte(CallExpr *TheCall, int ArgNum,
-                                         unsigned ArgBits);
-  bool SemaBuiltinConstantArgShiftedByteOrXXFF(CallExpr *TheCall, int ArgNum,
-                                               unsigned ArgBits);
-  bool SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall,
-                                int ArgNum, unsigned ExpectedFieldNum,
-                                bool AllowName);
-  bool SemaBuiltinARMMemoryTaggingCall(unsigned BuiltinID, CallExpr *TheCall);
-  bool SemaBuiltinPPCMMACall(CallExpr *TheCall, unsigned BuiltinID,
-                             const char *TypeDesc);
+  /// Report unterminated 'omp declare target' or 'omp begin declare target' at
+  /// the end of a compilation unit.
+  void DiagnoseUnterminatedOpenMPDeclareTarget();
 
-  bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc);
+  /// Searches for the provided declaration name for OpenMP declare target
+  /// directive.
+  NamedDecl *lookupOpenMPDeclareTargetName(Scope *CurScope,
+                                           CXXScopeSpec &ScopeSpec,
+                                           const DeclarationNameInfo &Id);
+
+  /// Called on correct id-expression from the '#pragma omp declare target'.
+  void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
+                                    OMPDeclareTargetDeclAttr::MapTypeTy MT,
+                                    DeclareTargetContextInfo &DTCI);
 
-  bool SemaBuiltinVectorMath(CallExpr *TheCall, QualType &Res);
-  bool SemaBuiltinVectorToScalarMath(CallExpr *TheCall);
-  bool SemaBuiltinElementwiseMath(CallExpr *TheCall);
-  bool SemaBuiltinElementwiseTernaryMath(CallExpr *TheCall);
-  bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall);
-  bool PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall);
+  /// Check declaration inside target region.
+  void
+  checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
+                                   SourceLocation IdLoc = SourceLocation());
 
-  bool SemaBuiltinNonDeterministicValue(CallExpr *TheCall);
+  /// Adds OMPDeclareTargetDeclAttr to referenced variables in declare target
+  /// directive.
+  void ActOnOpenMPDeclareTargetInitializer(Decl *D);
 
-  // Matrix builtin handling.
-  ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall,
-                                        ExprResult CallResult);
-  ExprResult SemaBuiltinMatrixColumnMajorLoad(CallExpr *TheCall,
-                                              ExprResult CallResult);
-  ExprResult SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall,
-                                               ExprResult CallResult);
+  /// Finishes analysis of the deferred functions calls that may be declared as
+  /// host/nohost during device/host compilation.
+  void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller,
+                                     const FunctionDecl *Callee,
+                                     SourceLocation Loc);
 
-  // WebAssembly builtin handling.
-  bool BuiltinWasmRefNullExtern(CallExpr *TheCall);
-  bool BuiltinWasmRefNullFunc(CallExpr *TheCall);
-  bool BuiltinWasmTableGet(CallExpr *TheCall);
-  bool BuiltinWasmTableSet(CallExpr *TheCall);
-  bool BuiltinWasmTableSize(CallExpr *TheCall);
-  bool BuiltinWasmTableGrow(CallExpr *TheCall);
-  bool BuiltinWasmTableFill(CallExpr *TheCall);
-  bool BuiltinWasmTableCopy(CallExpr *TheCall);
+  /// Return true if currently in OpenMP task with untied clause context.
+  bool isInOpenMPTaskUntiedContext() const;
 
-public:
-  enum FormatStringType {
-    FST_Scanf,
-    FST_Printf,
-    FST_NSString,
-    FST_Strftime,
-    FST_Strfmon,
-    FST_Kprintf,
-    FST_FreeBSDKPrintf,
-    FST_OSTrace,
-    FST_OSLog,
-    FST_Unknown
-  };
-  static FormatStringType GetFormatStringType(const FormatAttr *Format);
+  /// Return true inside OpenMP declare target region.
+  bool isInOpenMPDeclareTargetContext() const {
+    return !DeclareTargetNesting.empty();
+  }
+  /// Return true inside OpenMP target region.
+  bool isInOpenMPTargetExecutionDirective() const;
 
-  bool FormatStringHasSArg(const StringLiteral *FExpr);
+  /// Return the number of captured regions created for an OpenMP directive.
+  static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind);
 
-  static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);
+  /// Initialization of captured region for OpenMP region.
+  void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope);
 
-private:
-  bool CheckFormatArguments(const FormatAttr *Format,
-                            ArrayRef Args, bool IsCXXMember,
-                            VariadicCallType CallType, SourceLocation Loc,
-                            SourceRange Range,
-                            llvm::SmallBitVector &CheckedVarArgs);
-  bool CheckFormatArguments(ArrayRef Args,
-                            FormatArgumentPassingKind FAPK, unsigned format_idx,
-                            unsigned firstDataArg, FormatStringType Type,
-                            VariadicCallType CallType, SourceLocation Loc,
-                            SourceRange range,
-                            llvm::SmallBitVector &CheckedVarArgs);
+  /// Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to
+  /// an OpenMP loop directive.
+  StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt);
 
-  void CheckInfNaNFunction(const CallExpr *Call, const FunctionDecl *FDecl);
+  /// Process a canonical OpenMP loop nest that can either be a canonical
+  /// literal loop (ForStmt or CXXForRangeStmt), or the generated loop of an
+  /// OpenMP loop transformation construct.
+  StmtResult ActOnOpenMPLoopnest(Stmt *AStmt);
 
-  void CheckAbsoluteValueFunction(const CallExpr *Call,
-                                  const FunctionDecl *FDecl);
+  /// End of OpenMP region.
+  ///
+  /// \param S Statement associated with the current OpenMP region.
+  /// \param Clauses List of clauses for the current OpenMP region.
+  ///
+  /// \returns Statement for finished OpenMP region.
+  StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef Clauses);
+  StmtResult ActOnOpenMPExecutableDirective(
+      OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
+      OpenMPDirectiveKind CancelRegion, ArrayRef Clauses,
+      Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc,
+      OpenMPDirectiveKind PrevMappedDirective = llvm::omp::OMPD_unknown);
+  /// Called on well-formed '\#pragma omp parallel' after parsing
+  /// of the  associated statement.
+  StmtResult ActOnOpenMPParallelDirective(ArrayRef Clauses,
+                                          Stmt *AStmt, SourceLocation StartLoc,
+                                          SourceLocation EndLoc);
+  using VarsWithInheritedDSAType =
+      llvm::SmallDenseMap;
+  /// Called on well-formed '\#pragma omp simd' after parsing
+  /// of the associated statement.
+  StmtResult
+  ActOnOpenMPSimdDirective(ArrayRef Clauses, Stmt *AStmt,
+                           SourceLocation StartLoc, SourceLocation EndLoc,
+                           VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '#pragma omp tile' after parsing of its clauses and
+  /// the associated statement.
+  StmtResult ActOnOpenMPTileDirective(ArrayRef Clauses,
+                                      Stmt *AStmt, SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed '#pragma omp unroll' after parsing of its clauses
+  /// and the associated statement.
+  StmtResult ActOnOpenMPUnrollDirective(ArrayRef Clauses,
+                                        Stmt *AStmt, SourceLocation StartLoc,
+                                        SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp for' after parsing
+  /// of the associated statement.
+  StmtResult
+  ActOnOpenMPForDirective(ArrayRef Clauses, Stmt *AStmt,
+                          SourceLocation StartLoc, SourceLocation EndLoc,
+                          VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp for simd' after parsing
+  /// of the associated statement.
+  StmtResult
+  ActOnOpenMPForSimdDirective(ArrayRef Clauses, Stmt *AStmt,
+                              SourceLocation StartLoc, SourceLocation EndLoc,
+                              VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp sections' after parsing
+  /// of the associated statement.
+  StmtResult ActOnOpenMPSectionsDirective(ArrayRef Clauses,
+                                          Stmt *AStmt, SourceLocation StartLoc,
+                                          SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp section' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc,
+                                         SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp scope' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPScopeDirective(ArrayRef Clauses,
+                                       Stmt *AStmt, SourceLocation StartLoc,
+                                       SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp single' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPSingleDirective(ArrayRef Clauses,
+                                        Stmt *AStmt, SourceLocation StartLoc,
+                                        SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp master' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc,
+                                        SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp critical' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName,
+                                          ArrayRef Clauses,
+                                          Stmt *AStmt, SourceLocation StartLoc,
+                                          SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp parallel for' after parsing
+  /// of the  associated statement.
+  StmtResult ActOnOpenMPParallelForDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp parallel for simd' after
+  /// parsing of the  associated statement.
+  StmtResult ActOnOpenMPParallelForSimdDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp parallel master' after
+  /// parsing of the  associated statement.
+  StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef Clauses,
+                                                Stmt *AStmt,
+                                                SourceLocation StartLoc,
+                                                SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp parallel masked' after
+  /// parsing of the associated statement.
+  StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef Clauses,
+                                                Stmt *AStmt,
+                                                SourceLocation StartLoc,
+                                                SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp parallel sections' after
+  /// parsing of the  associated statement.
+  StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef Clauses,
+                                                  Stmt *AStmt,
+                                                  SourceLocation StartLoc,
+                                                  SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp task' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPTaskDirective(ArrayRef Clauses,
+                                      Stmt *AStmt, SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp taskyield'.
+  StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc,
+                                           SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp error'.
+  /// Error direcitive is allowed in both declared and excutable contexts.
+  /// Adding InExContext to identify which context is called from.
+  StmtResult ActOnOpenMPErrorDirective(ArrayRef Clauses,
+                                       SourceLocation StartLoc,
+                                       SourceLocation EndLoc,
+                                       bool InExContext = true);
+  /// Called on well-formed '\#pragma omp barrier'.
+  StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
+                                         SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp taskwait'.
+  StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef Clauses,
+                                          SourceLocation StartLoc,
+                                          SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp taskgroup'.
+  StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef Clauses,
+                                           Stmt *AStmt, SourceLocation StartLoc,
+                                           SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp flush'.
+  StmtResult ActOnOpenMPFlushDirective(ArrayRef Clauses,
+                                       SourceLocation StartLoc,
+                                       SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp depobj'.
+  StmtResult ActOnOpenMPDepobjDirective(ArrayRef Clauses,
+                                        SourceLocation StartLoc,
+                                        SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp scan'.
+  StmtResult ActOnOpenMPScanDirective(ArrayRef Clauses,
+                                      SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp ordered' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPOrderedDirective(ArrayRef Clauses,
+                                         Stmt *AStmt, SourceLocation StartLoc,
+                                         SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp atomic' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPAtomicDirective(ArrayRef Clauses,
+                                        Stmt *AStmt, SourceLocation StartLoc,
+                                        SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp target' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPTargetDirective(ArrayRef Clauses,
+                                        Stmt *AStmt, SourceLocation StartLoc,
+                                        SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp target data' after parsing of
+  /// the associated statement.
+  StmtResult ActOnOpenMPTargetDataDirective(ArrayRef Clauses,
+                                            Stmt *AStmt,
+                                            SourceLocation StartLoc,
+                                            SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp target enter data' after
+  /// parsing of the associated statement.
+  StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef Clauses,
+                                                 SourceLocation StartLoc,
+                                                 SourceLocation EndLoc,
+                                                 Stmt *AStmt);
+  /// Called on well-formed '\#pragma omp target exit data' after
+  /// parsing of the associated statement.
+  StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef Clauses,
+                                                SourceLocation StartLoc,
+                                                SourceLocation EndLoc,
+                                                Stmt *AStmt);
+  /// Called on well-formed '\#pragma omp target parallel' after
+  /// parsing of the associated statement.
+  StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef Clauses,
+                                                Stmt *AStmt,
+                                                SourceLocation StartLoc,
+                                                SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp target parallel for' after
+  /// parsing of the  associated statement.
+  StmtResult ActOnOpenMPTargetParallelForDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp teams' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPTeamsDirective(ArrayRef Clauses,
+                                       Stmt *AStmt, SourceLocation StartLoc,
+                                       SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp teams loop' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPTeamsGenericLoopDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp target teams loop' after parsing of
+  /// the associated statement.
+  StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp parallel loop' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPParallelGenericLoopDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp target parallel loop' after parsing
+  /// of the associated statement.
+  StmtResult ActOnOpenMPTargetParallelGenericLoopDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp cancellation point'.
+  StmtResult
+  ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc,
+                                        SourceLocation EndLoc,
+                                        OpenMPDirectiveKind CancelRegion);
+  /// Called on well-formed '\#pragma omp cancel'.
+  StmtResult ActOnOpenMPCancelDirective(ArrayRef Clauses,
+                                        SourceLocation StartLoc,
+                                        SourceLocation EndLoc,
+                                        OpenMPDirectiveKind CancelRegion);
+  /// Called on well-formed '\#pragma omp taskloop' after parsing of the
+  /// associated statement.
+  StmtResult
+  ActOnOpenMPTaskLoopDirective(ArrayRef Clauses, Stmt *AStmt,
+                               SourceLocation StartLoc, SourceLocation EndLoc,
+                               VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp taskloop simd' after parsing of
+  /// the associated statement.
+  StmtResult ActOnOpenMPTaskLoopSimdDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp master taskloop' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPMasterTaskLoopDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp master taskloop simd' after parsing of
+  /// the associated statement.
+  StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp parallel master taskloop' after
+  /// parsing of the associated statement.
+  StmtResult ActOnOpenMPParallelMasterTaskLoopDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp parallel master taskloop simd' after
+  /// parsing of the associated statement.
+  StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp masked taskloop' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPMaskedTaskLoopDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp masked taskloop simd' after parsing of
+  /// the associated statement.
+  StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp parallel masked taskloop' after
+  /// parsing of the associated statement.
+  StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp parallel masked taskloop simd' after
+  /// parsing of the associated statement.
+  StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp distribute' after parsing
+  /// of the associated statement.
+  StmtResult
+  ActOnOpenMPDistributeDirective(ArrayRef Clauses, Stmt *AStmt,
+                                 SourceLocation StartLoc, SourceLocation EndLoc,
+                                 VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp target update'.
+  StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef Clauses,
+                                              SourceLocation StartLoc,
+                                              SourceLocation EndLoc,
+                                              Stmt *AStmt);
+  /// Called on well-formed '\#pragma omp distribute parallel for' after
+  /// parsing of the associated statement.
+  StmtResult ActOnOpenMPDistributeParallelForDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp distribute parallel for simd'
+  /// after parsing of the associated statement.
+  StmtResult ActOnOpenMPDistributeParallelForSimdDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp distribute simd' after
+  /// parsing of the associated statement.
+  StmtResult ActOnOpenMPDistributeSimdDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp target parallel for simd' after
+  /// parsing of the associated statement.
+  StmtResult ActOnOpenMPTargetParallelForSimdDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp target simd' after parsing of
+  /// the associated statement.
+  StmtResult
+  ActOnOpenMPTargetSimdDirective(ArrayRef Clauses, Stmt *AStmt,
+                                 SourceLocation StartLoc, SourceLocation EndLoc,
+                                 VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp teams distribute' after parsing of
+  /// the associated statement.
+  StmtResult ActOnOpenMPTeamsDistributeDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp teams distribute simd' after parsing
+  /// of the associated statement.
+  StmtResult ActOnOpenMPTeamsDistributeSimdDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp teams distribute parallel for simd'
+  /// after parsing of the associated statement.
+  StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp teams distribute parallel for'
+  /// after parsing of the associated statement.
+  StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp target teams' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef Clauses,
+                                             Stmt *AStmt,
+                                             SourceLocation StartLoc,
+                                             SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp target teams distribute' after parsing
+  /// of the associated statement.
+  StmtResult ActOnOpenMPTargetTeamsDistributeDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp target teams distribute parallel for'
+  /// after parsing of the associated statement.
+  StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp target teams distribute parallel for
+  /// simd' after parsing of the associated statement.
+  StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp target teams distribute simd' after
+  /// parsing of the associated statement.
+  StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
+  /// Called on well-formed '\#pragma omp interop'.
+  StmtResult ActOnOpenMPInteropDirective(ArrayRef Clauses,
+                                         SourceLocation StartLoc,
+                                         SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp dispatch' after parsing of the
+  // /associated statement.
+  StmtResult ActOnOpenMPDispatchDirective(ArrayRef Clauses,
+                                          Stmt *AStmt, SourceLocation StartLoc,
+                                          SourceLocation EndLoc);
+  /// Called on well-formed '\#pragma omp masked' after parsing of the
+  // /associated statement.
+  StmtResult ActOnOpenMPMaskedDirective(ArrayRef Clauses,
+                                        Stmt *AStmt, SourceLocation StartLoc,
+                                        SourceLocation EndLoc);
 
-  void CheckMaxUnsignedZero(const CallExpr *Call, const FunctionDecl *FDecl);
+  /// Called on well-formed '\#pragma omp loop' after parsing of the
+  /// associated statement.
+  StmtResult ActOnOpenMPGenericLoopDirective(
+      ArrayRef Clauses, Stmt *AStmt, SourceLocation StartLoc,
+      SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA);
 
-  void CheckMemaccessArguments(const CallExpr *Call,
-                               unsigned BId,
-                               IdentifierInfo *FnName);
+  /// Checks correctness of linear modifiers.
+  bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind,
+                                 SourceLocation LinLoc);
+  /// Checks that the specified declaration matches requirements for the linear
+  /// decls.
+  bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc,
+                             OpenMPLinearClauseKind LinKind, QualType Type,
+                             bool IsDeclareSimd = false);
 
-  void CheckStrlcpycatArguments(const CallExpr *Call,
-                                IdentifierInfo *FnName);
+  /// Called on well-formed '\#pragma omp declare simd' after parsing of
+  /// the associated method/function.
+  DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(
+      DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS,
+      Expr *Simdlen, ArrayRef Uniforms, ArrayRef Aligneds,
+      ArrayRef Alignments, ArrayRef Linears,
+      ArrayRef LinModifiers, ArrayRef Steps, SourceRange SR);
 
-  void CheckStrncatArguments(const CallExpr *Call,
-                             IdentifierInfo *FnName);
+  /// Checks '\#pragma omp declare variant' variant function and original
+  /// functions after parsing of the associated method/function.
+  /// \param DG Function declaration to which declare variant directive is
+  /// applied to.
+  /// \param VariantRef Expression that references the variant function, which
+  /// must be used instead of the original one, specified in \p DG.
+  /// \param TI The trait info object representing the match clause.
+  /// \param NumAppendArgs The number of omp_interop_t arguments to account for
+  /// in checking.
+  /// \returns std::nullopt, if the function/variant function are not compatible
+  /// with the pragma, pair of original function/variant ref expression
+  /// otherwise.
+  std::optional>
+  checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef,
+                                    OMPTraitInfo &TI, unsigned NumAppendArgs,
+                                    SourceRange SR);
 
-  void CheckFreeArguments(const CallExpr *E);
+  /// Called on well-formed '\#pragma omp declare variant' after parsing of
+  /// the associated method/function.
+  /// \param FD Function declaration to which declare variant directive is
+  /// applied to.
+  /// \param VariantRef Expression that references the variant function, which
+  /// must be used instead of the original one, specified in \p DG.
+  /// \param TI The context traits associated with the function variant.
+  /// \param AdjustArgsNothing The list of 'nothing' arguments.
+  /// \param AdjustArgsNeedDevicePtr The list of 'need_device_ptr' arguments.
+  /// \param AppendArgs The list of 'append_args' arguments.
+  /// \param AdjustArgsLoc The Location of an 'adjust_args' clause.
+  /// \param AppendArgsLoc The Location of an 'append_args' clause.
+  /// \param SR The SourceRange of the 'declare variant' directive.
+  void ActOnOpenMPDeclareVariantDirective(
+      FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
+      ArrayRef AdjustArgsNothing,
+      ArrayRef AdjustArgsNeedDevicePtr,
+      ArrayRef AppendArgs, SourceLocation AdjustArgsLoc,
+      SourceLocation AppendArgsLoc, SourceRange SR);
 
-  void CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
-                          SourceLocation ReturnLoc,
-                          bool isObjCMethod = false,
-                          const AttrVec *Attrs = nullptr,
-                          const FunctionDecl *FD = nullptr);
+  OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr,
+                                         SourceLocation StartLoc,
+                                         SourceLocation LParenLoc,
+                                         SourceLocation EndLoc);
+  /// Called on well-formed 'allocator' clause.
+  OMPClause *ActOnOpenMPAllocatorClause(Expr *Allocator,
+                                        SourceLocation StartLoc,
+                                        SourceLocation LParenLoc,
+                                        SourceLocation EndLoc);
+  /// Called on well-formed 'if' clause.
+  OMPClause *ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier,
+                                 Expr *Condition, SourceLocation StartLoc,
+                                 SourceLocation LParenLoc,
+                                 SourceLocation NameModifierLoc,
+                                 SourceLocation ColonLoc,
+                                 SourceLocation EndLoc);
+  /// Called on well-formed 'final' clause.
+  OMPClause *ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc,
+                                    SourceLocation LParenLoc,
+                                    SourceLocation EndLoc);
+  /// Called on well-formed 'num_threads' clause.
+  OMPClause *ActOnOpenMPNumThreadsClause(Expr *NumThreads,
+                                         SourceLocation StartLoc,
+                                         SourceLocation LParenLoc,
+                                         SourceLocation EndLoc);
+  /// Called on well-formed 'align' clause.
+  OMPClause *ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc,
+                                    SourceLocation LParenLoc,
+                                    SourceLocation EndLoc);
+  /// Called on well-formed 'safelen' clause.
+  OMPClause *ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc,
+                                      SourceLocation LParenLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed 'simdlen' clause.
+  OMPClause *ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc,
+                                      SourceLocation LParenLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-form 'sizes' clause.
+  OMPClause *ActOnOpenMPSizesClause(ArrayRef SizeExprs,
+                                    SourceLocation StartLoc,
+                                    SourceLocation LParenLoc,
+                                    SourceLocation EndLoc);
+  /// Called on well-form 'full' clauses.
+  OMPClause *ActOnOpenMPFullClause(SourceLocation StartLoc,
+                                   SourceLocation EndLoc);
+  /// Called on well-form 'partial' clauses.
+  OMPClause *ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc,
+                                      SourceLocation LParenLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed 'collapse' clause.
+  OMPClause *ActOnOpenMPCollapseClause(Expr *NumForLoops,
+                                       SourceLocation StartLoc,
+                                       SourceLocation LParenLoc,
+                                       SourceLocation EndLoc);
+  /// Called on well-formed 'ordered' clause.
+  OMPClause *
+  ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc,
+                           SourceLocation LParenLoc = SourceLocation(),
+                           Expr *NumForLoops = nullptr);
+  /// Called on well-formed 'grainsize' clause.
+  OMPClause *ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier,
+                                        Expr *Size, SourceLocation StartLoc,
+                                        SourceLocation LParenLoc,
+                                        SourceLocation ModifierLoc,
+                                        SourceLocation EndLoc);
+  /// Called on well-formed 'num_tasks' clause.
+  OMPClause *ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier,
+                                       Expr *NumTasks, SourceLocation StartLoc,
+                                       SourceLocation LParenLoc,
+                                       SourceLocation ModifierLoc,
+                                       SourceLocation EndLoc);
+  /// Called on well-formed 'hint' clause.
+  OMPClause *ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc,
+                                   SourceLocation LParenLoc,
+                                   SourceLocation EndLoc);
+  /// Called on well-formed 'detach' clause.
+  OMPClause *ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc,
+                                     SourceLocation LParenLoc,
+                                     SourceLocation EndLoc);
 
-public:
-  void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
-                            BinaryOperatorKind Opcode);
+  OMPClause *ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument,
+                                     SourceLocation ArgumentLoc,
+                                     SourceLocation StartLoc,
+                                     SourceLocation LParenLoc,
+                                     SourceLocation EndLoc);
+  /// Called on well-formed 'when' clause.
+  OMPClause *ActOnOpenMPWhenClause(OMPTraitInfo &TI, SourceLocation StartLoc,
+                                   SourceLocation LParenLoc,
+                                   SourceLocation EndLoc);
+  /// Called on well-formed 'default' clause.
+  OMPClause *ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind,
+                                      SourceLocation KindLoc,
+                                      SourceLocation StartLoc,
+                                      SourceLocation LParenLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed 'proc_bind' clause.
+  OMPClause *ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind,
+                                       SourceLocation KindLoc,
+                                       SourceLocation StartLoc,
+                                       SourceLocation LParenLoc,
+                                       SourceLocation EndLoc);
+  /// Called on well-formed 'order' clause.
+  OMPClause *ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier,
+                                    OpenMPOrderClauseKind Kind,
+                                    SourceLocation StartLoc,
+                                    SourceLocation LParenLoc,
+                                    SourceLocation MLoc, SourceLocation KindLoc,
+                                    SourceLocation EndLoc);
+  /// Called on well-formed 'update' clause.
+  OMPClause *ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind,
+                                     SourceLocation KindLoc,
+                                     SourceLocation StartLoc,
+                                     SourceLocation LParenLoc,
+                                     SourceLocation EndLoc);
 
-private:
-  void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
-  void CheckBoolLikeConversion(Expr *E, SourceLocation CC);
-  void CheckForIntOverflow(const Expr *E);
-  void CheckUnsequencedOperations(const Expr *E);
+  OMPClause *ActOnOpenMPSingleExprWithArgClause(
+      OpenMPClauseKind Kind, ArrayRef Arguments, Expr *Expr,
+      SourceLocation StartLoc, SourceLocation LParenLoc,
+      ArrayRef ArgumentsLoc, SourceLocation DelimLoc,
+      SourceLocation EndLoc);
+  /// Called on well-formed 'schedule' clause.
+  OMPClause *ActOnOpenMPScheduleClause(
+      OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
+      OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
+      SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
+      SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc);
 
-  /// Perform semantic checks on a completed expression. This will either
-  /// be a full-expression or a default argument expression.
-  void CheckCompletedExpr(Expr *E, SourceLocation CheckLoc = SourceLocation(),
-                          bool IsConstexpr = false);
+  OMPClause *ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc,
+                               SourceLocation EndLoc);
+  /// Called on well-formed 'nowait' clause.
+  OMPClause *ActOnOpenMPNowaitClause(SourceLocation StartLoc,
+                                     SourceLocation EndLoc);
+  /// Called on well-formed 'untied' clause.
+  OMPClause *ActOnOpenMPUntiedClause(SourceLocation StartLoc,
+                                     SourceLocation EndLoc);
+  /// Called on well-formed 'mergeable' clause.
+  OMPClause *ActOnOpenMPMergeableClause(SourceLocation StartLoc,
+                                        SourceLocation EndLoc);
+  /// Called on well-formed 'read' clause.
+  OMPClause *ActOnOpenMPReadClause(SourceLocation StartLoc,
+                                   SourceLocation EndLoc);
+  /// Called on well-formed 'write' clause.
+  OMPClause *ActOnOpenMPWriteClause(SourceLocation StartLoc,
+                                    SourceLocation EndLoc);
+  /// Called on well-formed 'update' clause.
+  OMPClause *ActOnOpenMPUpdateClause(SourceLocation StartLoc,
+                                     SourceLocation EndLoc);
+  /// Called on well-formed 'capture' clause.
+  OMPClause *ActOnOpenMPCaptureClause(SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed 'compare' clause.
+  OMPClause *ActOnOpenMPCompareClause(SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed 'fail' clause.
+  OMPClause *ActOnOpenMPFailClause(SourceLocation StartLoc,
+                                   SourceLocation EndLoc);
+  OMPClause *ActOnOpenMPFailClause(OpenMPClauseKind Kind,
+                                   SourceLocation KindLoc,
+                                   SourceLocation StartLoc,
+                                   SourceLocation LParenLoc,
+                                   SourceLocation EndLoc);
 
-  void CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *Field,
-                                   Expr *Init);
+  /// Called on well-formed 'seq_cst' clause.
+  OMPClause *ActOnOpenMPSeqCstClause(SourceLocation StartLoc,
+                                     SourceLocation EndLoc);
+  /// Called on well-formed 'acq_rel' clause.
+  OMPClause *ActOnOpenMPAcqRelClause(SourceLocation StartLoc,
+                                     SourceLocation EndLoc);
+  /// Called on well-formed 'acquire' clause.
+  OMPClause *ActOnOpenMPAcquireClause(SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed 'release' clause.
+  OMPClause *ActOnOpenMPReleaseClause(SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed 'relaxed' clause.
+  OMPClause *ActOnOpenMPRelaxedClause(SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed 'weak' clause.
+  OMPClause *ActOnOpenMPWeakClause(SourceLocation StartLoc,
+                                   SourceLocation EndLoc);
 
-  /// Check if there is a field shadowing.
-  void CheckShadowInheritedFields(const SourceLocation &Loc,
-                                  DeclarationName FieldName,
-                                  const CXXRecordDecl *RD,
-                                  bool DeclIsField = true);
+  /// Called on well-formed 'init' clause.
+  OMPClause *
+  ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo,
+                        SourceLocation StartLoc, SourceLocation LParenLoc,
+                        SourceLocation VarLoc, SourceLocation EndLoc);
 
-  /// Check if the given expression contains 'break' or 'continue'
-  /// statement that produces control flow different from GCC.
-  void CheckBreakContinueBinding(Expr *E);
+  /// Called on well-formed 'use' clause.
+  OMPClause *ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc,
+                                  SourceLocation LParenLoc,
+                                  SourceLocation VarLoc, SourceLocation EndLoc);
 
-  /// Check whether receiver is mutable ObjC container which
-  /// attempts to add itself into the container
-  void CheckObjCCircularContainer(ObjCMessageExpr *Message);
+  /// Called on well-formed 'destroy' clause.
+  OMPClause *ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc,
+                                      SourceLocation LParenLoc,
+                                      SourceLocation VarLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed 'novariants' clause.
+  OMPClause *ActOnOpenMPNovariantsClause(Expr *Condition,
+                                         SourceLocation StartLoc,
+                                         SourceLocation LParenLoc,
+                                         SourceLocation EndLoc);
+  /// Called on well-formed 'nocontext' clause.
+  OMPClause *ActOnOpenMPNocontextClause(Expr *Condition,
+                                        SourceLocation StartLoc,
+                                        SourceLocation LParenLoc,
+                                        SourceLocation EndLoc);
+  /// Called on well-formed 'filter' clause.
+  OMPClause *ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc,
+                                     SourceLocation LParenLoc,
+                                     SourceLocation EndLoc);
+  /// Called on well-formed 'threads' clause.
+  OMPClause *ActOnOpenMPThreadsClause(SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed 'simd' clause.
+  OMPClause *ActOnOpenMPSIMDClause(SourceLocation StartLoc,
+                                   SourceLocation EndLoc);
+  /// Called on well-formed 'nogroup' clause.
+  OMPClause *ActOnOpenMPNogroupClause(SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed 'unified_address' clause.
+  OMPClause *ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc,
+                                             SourceLocation EndLoc);
 
-  void CheckTCBEnforcement(const SourceLocation CallExprLoc,
-                           const NamedDecl *Callee);
+  /// Called on well-formed 'unified_address' clause.
+  OMPClause *ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
+                                                  SourceLocation EndLoc);
 
-  void AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE);
-  void AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc,
-                                 bool DeleteWasArrayForm);
-public:
-  /// Register a magic integral constant to be used as a type tag.
-  void RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind,
-                                  uint64_t MagicValue, QualType Type,
-                                  bool LayoutCompatible, bool MustBeNull);
+  /// Called on well-formed 'reverse_offload' clause.
+  OMPClause *ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
+                                             SourceLocation EndLoc);
 
-  struct TypeTagData {
-    TypeTagData() {}
+  /// Called on well-formed 'dynamic_allocators' clause.
+  OMPClause *ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
+                                                SourceLocation EndLoc);
 
-    TypeTagData(QualType Type, bool LayoutCompatible, bool MustBeNull) :
-        Type(Type), LayoutCompatible(LayoutCompatible),
-        MustBeNull(MustBeNull)
-    {}
+  /// Called on well-formed 'atomic_default_mem_order' clause.
+  OMPClause *ActOnOpenMPAtomicDefaultMemOrderClause(
+      OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc,
+      SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
 
-    QualType Type;
+  /// Called on well-formed 'at' clause.
+  OMPClause *ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
+                                 SourceLocation KindLoc,
+                                 SourceLocation StartLoc,
+                                 SourceLocation LParenLoc,
+                                 SourceLocation EndLoc);
 
-    /// If true, \c Type should be compared with other expression's types for
-    /// layout-compatibility.
-    LLVM_PREFERRED_TYPE(bool)
-    unsigned LayoutCompatible : 1;
-    LLVM_PREFERRED_TYPE(bool)
-    unsigned MustBeNull : 1;
+  /// Called on well-formed 'severity' clause.
+  OMPClause *ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
+                                       SourceLocation KindLoc,
+                                       SourceLocation StartLoc,
+                                       SourceLocation LParenLoc,
+                                       SourceLocation EndLoc);
+
+  /// Called on well-formed 'message' clause.
+  /// passing string for message.
+  OMPClause *ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc,
+                                      SourceLocation LParenLoc,
+                                      SourceLocation EndLoc);
+
+  /// Data used for processing a list of variables in OpenMP clauses.
+  struct OpenMPVarListDataTy final {
+    Expr *DepModOrTailExpr = nullptr;
+    Expr *IteratorExpr = nullptr;
+    SourceLocation ColonLoc;
+    SourceLocation RLoc;
+    CXXScopeSpec ReductionOrMapperIdScopeSpec;
+    DeclarationNameInfo ReductionOrMapperId;
+    int ExtraModifier = -1; ///< Additional modifier for linear, map, depend or
+                            ///< lastprivate clause.
+    SmallVector
+        MapTypeModifiers;
+    SmallVector
+        MapTypeModifiersLoc;
+    SmallVector
+        MotionModifiers;
+    SmallVector MotionModifiersLoc;
+    bool IsMapTypeImplicit = false;
+    SourceLocation ExtraModifierLoc;
+    SourceLocation OmpAllMemoryLoc;
+    SourceLocation
+        StepModifierLoc; /// 'step' modifier location for linear clause
   };
 
-  /// A pair of ArgumentKind identifier and magic value.  This uniquely
-  /// identifies the magic value.
-  typedef std::pair TypeTagMagicValue;
+  OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
+                                      ArrayRef Vars,
+                                      const OMPVarListLocTy &Locs,
+                                      OpenMPVarListDataTy &Data);
+  /// Called on well-formed 'inclusive' clause.
+  OMPClause *ActOnOpenMPInclusiveClause(ArrayRef VarList,
+                                        SourceLocation StartLoc,
+                                        SourceLocation LParenLoc,
+                                        SourceLocation EndLoc);
+  /// Called on well-formed 'exclusive' clause.
+  OMPClause *ActOnOpenMPExclusiveClause(ArrayRef VarList,
+                                        SourceLocation StartLoc,
+                                        SourceLocation LParenLoc,
+                                        SourceLocation EndLoc);
+  /// Called on well-formed 'allocate' clause.
+  OMPClause *
+  ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef VarList,
+                            SourceLocation StartLoc, SourceLocation ColonLoc,
+                            SourceLocation LParenLoc, SourceLocation EndLoc);
+  /// Called on well-formed 'private' clause.
+  OMPClause *ActOnOpenMPPrivateClause(ArrayRef VarList,
+                                      SourceLocation StartLoc,
+                                      SourceLocation LParenLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed 'firstprivate' clause.
+  OMPClause *ActOnOpenMPFirstprivateClause(ArrayRef VarList,
+                                           SourceLocation StartLoc,
+                                           SourceLocation LParenLoc,
+                                           SourceLocation EndLoc);
+  /// Called on well-formed 'lastprivate' clause.
+  OMPClause *ActOnOpenMPLastprivateClause(
+      ArrayRef VarList, OpenMPLastprivateModifier LPKind,
+      SourceLocation LPKindLoc, SourceLocation ColonLoc,
+      SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
+  /// Called on well-formed 'shared' clause.
+  OMPClause *ActOnOpenMPSharedClause(ArrayRef VarList,
+                                     SourceLocation StartLoc,
+                                     SourceLocation LParenLoc,
+                                     SourceLocation EndLoc);
+  /// Called on well-formed 'reduction' clause.
+  OMPClause *ActOnOpenMPReductionClause(
+      ArrayRef VarList, OpenMPReductionClauseModifier Modifier,
+      SourceLocation StartLoc, SourceLocation LParenLoc,
+      SourceLocation ModifierLoc, SourceLocation ColonLoc,
+      SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,
+      const DeclarationNameInfo &ReductionId,
+      ArrayRef UnresolvedReductions = std::nullopt);
+  /// Called on well-formed 'task_reduction' clause.
+  OMPClause *ActOnOpenMPTaskReductionClause(
+      ArrayRef VarList, SourceLocation StartLoc,
+      SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
+      CXXScopeSpec &ReductionIdScopeSpec,
+      const DeclarationNameInfo &ReductionId,
+      ArrayRef UnresolvedReductions = std::nullopt);
+  /// Called on well-formed 'in_reduction' clause.
+  OMPClause *ActOnOpenMPInReductionClause(
+      ArrayRef VarList, SourceLocation StartLoc,
+      SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
+      CXXScopeSpec &ReductionIdScopeSpec,
+      const DeclarationNameInfo &ReductionId,
+      ArrayRef UnresolvedReductions = std::nullopt);
+  /// Called on well-formed 'linear' clause.
+  OMPClause *ActOnOpenMPLinearClause(
+      ArrayRef VarList, Expr *Step, SourceLocation StartLoc,
+      SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
+      SourceLocation LinLoc, SourceLocation ColonLoc,
+      SourceLocation StepModifierLoc, SourceLocation EndLoc);
+  /// Called on well-formed 'aligned' clause.
+  OMPClause *ActOnOpenMPAlignedClause(ArrayRef VarList, Expr *Alignment,
+                                      SourceLocation StartLoc,
+                                      SourceLocation LParenLoc,
+                                      SourceLocation ColonLoc,
+                                      SourceLocation EndLoc);
+  /// Called on well-formed 'copyin' clause.
+  OMPClause *ActOnOpenMPCopyinClause(ArrayRef VarList,
+                                     SourceLocation StartLoc,
+                                     SourceLocation LParenLoc,
+                                     SourceLocation EndLoc);
+  /// Called on well-formed 'copyprivate' clause.
+  OMPClause *ActOnOpenMPCopyprivateClause(ArrayRef VarList,
+                                          SourceLocation StartLoc,
+                                          SourceLocation LParenLoc,
+                                          SourceLocation EndLoc);
+  /// Called on well-formed 'flush' pseudo clause.
+  OMPClause *ActOnOpenMPFlushClause(ArrayRef VarList,
+                                    SourceLocation StartLoc,
+                                    SourceLocation LParenLoc,
+                                    SourceLocation EndLoc);
+  /// Called on well-formed 'depobj' pseudo clause.
+  OMPClause *ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc,
+                                     SourceLocation LParenLoc,
+                                     SourceLocation EndLoc);
+  /// Called on well-formed 'depend' clause.
+  OMPClause *ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
+                                     Expr *DepModifier,
+                                     ArrayRef VarList,
+                                     SourceLocation StartLoc,
+                                     SourceLocation LParenLoc,
+                                     SourceLocation EndLoc);
+  /// Called on well-formed 'device' clause.
+  OMPClause *ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,
+                                     Expr *Device, SourceLocation StartLoc,
+                                     SourceLocation LParenLoc,
+                                     SourceLocation ModifierLoc,
+                                     SourceLocation EndLoc);
+  /// Called on well-formed 'map' clause.
+  OMPClause *ActOnOpenMPMapClause(
+      Expr *IteratorModifier, ArrayRef MapTypeModifiers,
+      ArrayRef MapTypeModifiersLoc,
+      CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
+      OpenMPMapClauseKind MapType, bool IsMapTypeImplicit,
+      SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef VarList,
+      const OMPVarListLocTy &Locs, bool NoDiagnose = false,
+      ArrayRef UnresolvedMappers = std::nullopt);
+  /// Called on well-formed 'num_teams' clause.
+  OMPClause *ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc,
+                                       SourceLocation LParenLoc,
+                                       SourceLocation EndLoc);
+  /// Called on well-formed 'thread_limit' clause.
+  OMPClause *ActOnOpenMPThreadLimitClause(Expr *ThreadLimit,
+                                          SourceLocation StartLoc,
+                                          SourceLocation LParenLoc,
+                                          SourceLocation EndLoc);
+  /// Called on well-formed 'priority' clause.
+  OMPClause *ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc,
+                                       SourceLocation LParenLoc,
+                                       SourceLocation EndLoc);
+  /// Called on well-formed 'dist_schedule' clause.
+  OMPClause *ActOnOpenMPDistScheduleClause(
+      OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize,
+      SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc,
+      SourceLocation CommaLoc, SourceLocation EndLoc);
+  /// Called on well-formed 'defaultmap' clause.
+  OMPClause *ActOnOpenMPDefaultmapClause(
+      OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind,
+      SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
+      SourceLocation KindLoc, SourceLocation EndLoc);
+  /// Called on well-formed 'to' clause.
+  OMPClause *
+  ActOnOpenMPToClause(ArrayRef MotionModifiers,
+                      ArrayRef MotionModifiersLoc,
+                      CXXScopeSpec &MapperIdScopeSpec,
+                      DeclarationNameInfo &MapperId, SourceLocation ColonLoc,
+                      ArrayRef VarList, const OMPVarListLocTy &Locs,
+                      ArrayRef UnresolvedMappers = std::nullopt);
+  /// Called on well-formed 'from' clause.
+  OMPClause *
+  ActOnOpenMPFromClause(ArrayRef MotionModifiers,
+                        ArrayRef MotionModifiersLoc,
+                        CXXScopeSpec &MapperIdScopeSpec,
+                        DeclarationNameInfo &MapperId, SourceLocation ColonLoc,
+                        ArrayRef VarList, const OMPVarListLocTy &Locs,
+                        ArrayRef UnresolvedMappers = std::nullopt);
+  /// Called on well-formed 'use_device_ptr' clause.
+  OMPClause *ActOnOpenMPUseDevicePtrClause(ArrayRef VarList,
+                                           const OMPVarListLocTy &Locs);
+  /// Called on well-formed 'use_device_addr' clause.
+  OMPClause *ActOnOpenMPUseDeviceAddrClause(ArrayRef VarList,
+                                            const OMPVarListLocTy &Locs);
+  /// Called on well-formed 'is_device_ptr' clause.
+  OMPClause *ActOnOpenMPIsDevicePtrClause(ArrayRef VarList,
+                                          const OMPVarListLocTy &Locs);
+  /// Called on well-formed 'has_device_addr' clause.
+  OMPClause *ActOnOpenMPHasDeviceAddrClause(ArrayRef VarList,
+                                            const OMPVarListLocTy &Locs);
+  /// Called on well-formed 'nontemporal' clause.
+  OMPClause *ActOnOpenMPNontemporalClause(ArrayRef VarList,
+                                          SourceLocation StartLoc,
+                                          SourceLocation LParenLoc,
+                                          SourceLocation EndLoc);
+
+  /// Data for list of allocators.
+  struct UsesAllocatorsData {
+    /// Allocator.
+    Expr *Allocator = nullptr;
+    /// Allocator traits.
+    Expr *AllocatorTraits = nullptr;
+    /// Locations of '(' and ')' symbols.
+    SourceLocation LParenLoc, RParenLoc;
+  };
+  /// Called on well-formed 'uses_allocators' clause.
+  OMPClause *ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc,
+                                            SourceLocation LParenLoc,
+                                            SourceLocation EndLoc,
+                                            ArrayRef Data);
+  /// Called on well-formed 'affinity' clause.
+  OMPClause *ActOnOpenMPAffinityClause(SourceLocation StartLoc,
+                                       SourceLocation LParenLoc,
+                                       SourceLocation ColonLoc,
+                                       SourceLocation EndLoc, Expr *Modifier,
+                                       ArrayRef Locators);
+  /// Called on a well-formed 'bind' clause.
+  OMPClause *ActOnOpenMPBindClause(OpenMPBindClauseKind Kind,
+                                   SourceLocation KindLoc,
+                                   SourceLocation StartLoc,
+                                   SourceLocation LParenLoc,
+                                   SourceLocation EndLoc);
 
-private:
-  /// A map from magic value to type information.
-  std::unique_ptr>
-      TypeTagForDatatypeMagicValues;
+  /// Called on a well-formed 'ompx_dyn_cgroup_mem' clause.
+  OMPClause *ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc,
+                                            SourceLocation LParenLoc,
+                                            SourceLocation EndLoc);
 
-  /// Peform checks on a call of a function with argument_with_type_tag
-  /// or pointer_with_type_tag attributes.
-  void CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr,
-                                const ArrayRef ExprArgs,
-                                SourceLocation CallSiteLoc);
+  /// Called on well-formed 'doacross' clause.
+  OMPClause *
+  ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType,
+                            SourceLocation DepLoc, SourceLocation ColonLoc,
+                            ArrayRef VarList, SourceLocation StartLoc,
+                            SourceLocation LParenLoc, SourceLocation EndLoc);
 
-  /// Check if we are taking the address of a packed field
-  /// as this may be a problem if the pointer value is dereferenced.
-  void CheckAddressOfPackedMember(Expr *rhs);
+  /// Called on a well-formed 'ompx_attribute' clause.
+  OMPClause *ActOnOpenMPXAttributeClause(ArrayRef Attrs,
+                                         SourceLocation StartLoc,
+                                         SourceLocation LParenLoc,
+                                         SourceLocation EndLoc);
 
-  /// The parser's current scope.
-  ///
-  /// The parser maintains this state here.
-  Scope *CurScope;
+  /// Called on a well-formed 'ompx_bare' clause.
+  OMPClause *ActOnOpenMPXBareClause(SourceLocation StartLoc,
+                                    SourceLocation EndLoc);
 
-  mutable IdentifierInfo *Ident_super;
+private:
+  void *VarDataSharingAttributesStack;
 
-  /// Nullability type specifiers.
-  IdentifierInfo *Ident__Nonnull = nullptr;
-  IdentifierInfo *Ident__Nullable = nullptr;
-  IdentifierInfo *Ident__Nullable_result = nullptr;
-  IdentifierInfo *Ident__Null_unspecified = nullptr;
+  /// Number of nested '#pragma omp declare target' directives.
+  SmallVector DeclareTargetNesting;
 
-  IdentifierInfo *Ident_NSError = nullptr;
+  /// Initialization of data-sharing attributes stack.
+  void InitDataSharingAttributesStack();
+  void DestroyDataSharingAttributesStack();
 
-  /// The handler for the FileChanged preprocessor events.
-  ///
-  /// Used for diagnostics that implement custom semantic analysis for #include
-  /// directives, like -Wpragma-pack.
-  sema::SemaPPCallbacks *SemaPPCallbackHandler;
+  /// Returns OpenMP nesting level for current directive.
+  unsigned getOpenMPNestingLevel() const;
 
-protected:
-  friend class Parser;
-  friend class InitializationSequence;
-  friend class ASTReader;
-  friend class ASTDeclReader;
-  friend class ASTWriter;
+  /// Adjusts the function scopes index for the target-based regions.
+  void adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
+                                    unsigned Level) const;
 
-public:
-  /// Retrieve the keyword associated
-  IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability);
+  /// Returns the number of scopes associated with the construct on the given
+  /// OpenMP level.
+  int getNumberOfConstructScopes(unsigned Level) const;
 
-  /// The struct behind the CFErrorRef pointer.
-  RecordDecl *CFError = nullptr;
-  bool isCFError(RecordDecl *D);
+  /// Push new OpenMP function region for non-capturing function.
+  void pushOpenMPFunctionRegion();
 
-  /// Retrieve the identifier "NSError".
-  IdentifierInfo *getNSErrorIdent();
+  /// Pop OpenMP function region for non-capturing function.
+  void popOpenMPFunctionRegion(const sema::FunctionScopeInfo *OldFSI);
 
-  /// Retrieve the parser's current scope.
+  /// Analyzes and checks a loop nest for use by a loop transformation.
   ///
-  /// This routine must only be used when it is certain that semantic analysis
-  /// and the parser are in precisely the same context, which is not the case
-  /// when, e.g., we are performing any kind of template instantiation.
-  /// Therefore, the only safe places to use this scope are in the parser
-  /// itself and in routines directly invoked from the parser and *never* from
-  /// template substitution or instantiation.
-  Scope *getCurScope() const { return CurScope; }
-
-  void incrementMSManglingNumber() const {
-    return CurScope->incrementMSManglingNumber();
-  }
-
-  IdentifierInfo *getSuperIdentifier() const;
-
-  ObjCContainerDecl *getObjCDeclContext() const;
+  /// \param Kind          The loop transformation directive kind.
+  /// \param NumLoops      How many nested loops the directive is expecting.
+  /// \param AStmt         Associated statement of the transformation directive.
+  /// \param LoopHelpers   [out] The loop analysis result.
+  /// \param Body          [out] The body code nested in \p NumLoops loop.
+  /// \param OriginalInits [out] Collection of statements and declarations that
+  ///                      must have been executed/declared before entering the
+  ///                      loop.
+  ///
+  /// \return Whether there was any error.
+  bool checkTransformableLoopNest(
+      OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
+      SmallVectorImpl &LoopHelpers,
+      Stmt *&Body,
+      SmallVectorImpl, 0>>
+          &OriginalInits);
 
-  DeclContext *getCurLexicalContext() const {
-    return OriginalLexicalContext ? OriginalLexicalContext : CurContext;
-  }
+  /// Helper to keep information about the current `omp begin/end declare
+  /// variant` nesting.
+  struct OMPDeclareVariantScope {
+    /// The associated OpenMP context selector.
+    OMPTraitInfo *TI;
 
-  const DeclContext *getCurObjCLexicalContext() const {
-    const DeclContext *DC = getCurLexicalContext();
-    // A category implicitly has the attribute of the interface.
-    if (const ObjCCategoryDecl *CatD = dyn_cast(DC))
-      DC = CatD->getClassInterface();
-    return DC;
-  }
+    /// The associated OpenMP context selector mangling.
+    std::string NameSuffix;
 
-  /// Determine the number of levels of enclosing template parameters. This is
-  /// only usable while parsing. Note that this does not include dependent
-  /// contexts in which no template parameters have yet been declared, such as
-  /// in a terse function template or generic lambda before the first 'auto' is
-  /// encountered.
-  unsigned getTemplateDepth(Scope *S) const;
+    OMPDeclareVariantScope(OMPTraitInfo &TI);
+  };
 
-  /// To be used for checking whether the arguments being passed to
-  /// function exceeds the number of parameters expected for it.
-  static bool TooManyArguments(size_t NumParams, size_t NumArgs,
-                               bool PartialOverloading = false) {
-    // We check whether we're just after a comma in code-completion.
-    if (NumArgs > 0 && PartialOverloading)
-      return NumArgs + 1 > NumParams; // If so, we view as an extra argument.
-    return NumArgs > NumParams;
+  /// Return the OMPTraitInfo for the surrounding scope, if any.
+  OMPTraitInfo *getOMPTraitInfoForSurroundingScope() {
+    return OMPDeclareVariantScopes.empty() ? nullptr
+                                           : OMPDeclareVariantScopes.back().TI;
   }
 
-  // Emitting members of dllexported classes is delayed until the class
-  // (including field initializers) is fully parsed.
-  SmallVector DelayedDllExportClasses;
-  SmallVector DelayedDllExportMemberFunctions;
-
-private:
-  int ParsingClassDepth = 0;
-
-  class SavePendingParsedClassStateRAII {
-  public:
-    SavePendingParsedClassStateRAII(Sema &S) : S(S) { swapSavedState(); }
-
-    ~SavePendingParsedClassStateRAII() {
-      assert(S.DelayedOverridingExceptionSpecChecks.empty() &&
-             "there shouldn't be any pending delayed exception spec checks");
-      assert(S.DelayedEquivalentExceptionSpecChecks.empty() &&
-             "there shouldn't be any pending delayed exception spec checks");
-      swapSavedState();
-    }
+  /// The current `omp begin/end declare variant` scopes.
+  SmallVector OMPDeclareVariantScopes;
 
-  private:
-    Sema &S;
-    decltype(DelayedOverridingExceptionSpecChecks)
-        SavedOverridingExceptionSpecChecks;
-    decltype(DelayedEquivalentExceptionSpecChecks)
-        SavedEquivalentExceptionSpecChecks;
+  /// The current `omp begin/end assumes` scopes.
+  SmallVector OMPAssumeScoped;
 
-    void swapSavedState() {
-      SavedOverridingExceptionSpecChecks.swap(
-          S.DelayedOverridingExceptionSpecChecks);
-      SavedEquivalentExceptionSpecChecks.swap(
-          S.DelayedEquivalentExceptionSpecChecks);
-    }
-  };
+  /// All `omp assumes` we encountered so far.
+  SmallVector OMPAssumeGlobal;
 
-  /// Helper class that collects misaligned member designations and
-  /// their location info for delayed diagnostics.
-  struct MisalignedMember {
-    Expr *E;
-    RecordDecl *RD;
-    ValueDecl *MD;
-    CharUnits Alignment;
+  /// OMPD_loop is mapped to OMPD_for, OMPD_distribute or OMPD_simd depending
+  /// on the parameter of the bind clause. In the methods for the
+  /// mapped directives, check the parameters of the lastprivate clause.
+  bool checkLastPrivateForMappedDirectives(ArrayRef Clauses);
+  /// Depending on the bind clause of OMPD_loop map the directive to new
+  /// directives.
+  ///    1) loop bind(parallel) --> OMPD_for
+  ///    2) loop bind(teams) --> OMPD_distribute
+  ///    3) loop bind(thread) --> OMPD_simd
+  /// This is being handled in Sema instead of Codegen because of the need for
+  /// rigorous semantic checking in the new mapped directives.
+  bool mapLoopConstruct(llvm::SmallVector &ClausesWithoutBind,
+                        ArrayRef Clauses,
+                        OpenMPBindClauseKind &BindKind,
+                        OpenMPDirectiveKind &Kind,
+                        OpenMPDirectiveKind &PrevMappedDirective,
+                        SourceLocation StartLoc, SourceLocation EndLoc,
+                        const DeclarationNameInfo &DirName,
+                        OpenMPDirectiveKind CancelRegion);
 
-    MisalignedMember() : E(), RD(), MD() {}
-    MisalignedMember(Expr *E, RecordDecl *RD, ValueDecl *MD,
-                     CharUnits Alignment)
-        : E(E), RD(RD), MD(MD), Alignment(Alignment) {}
-    explicit MisalignedMember(Expr *E)
-        : MisalignedMember(E, nullptr, nullptr, CharUnits()) {}
+  ///@}
 
-    bool operator==(const MisalignedMember &m) { return this->E == m.E; }
-  };
-  /// Small set of gathered accesses to potentially misaligned members
-  /// due to the packed attribute.
-  SmallVector MisalignedMembers;
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Adds an expression to the set of gathered misaligned members.
-  void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,
-                                     CharUnits Alignment);
+  /// \name SYCL Constructs
+  /// Implementations are in SemaSYCL.cpp
+  ///@{
 
 public:
-  /// Diagnoses the current set of gathered accesses. This typically
-  /// happens at full expression level. The set is cleared after emitting the
-  /// diagnostics.
-  void DiagnoseMisalignedMembers();
-
-  /// This function checks if the expression is in the sef of potentially
-  /// misaligned members and it is converted to some pointer type T with lower
-  /// or equal alignment requirements. If so it removes it. This is used when
-  /// we do not want to diagnose such misaligned access (e.g. in conversions to
-  /// void*).
-  void DiscardMisalignedMemberAddress(const Type *T, Expr *E);
-
-  /// This function calls Action when it determines that E designates a
-  /// misaligned member due to the packed attribute. This is used to emit
-  /// local diagnostics like in reference binding.
-  void RefersToMemberWithReducedAlignment(
-      Expr *E,
-      llvm::function_ref
-          Action);
-
-  /// Describes the reason a calling convention specification was ignored, used
-  /// for diagnostics.
-  enum class CallingConventionIgnoredReason {
-    ForThisTarget = 0,
-    VariadicFunction,
-    ConstructorDestructor,
-    BuiltinFunction
-  };
   /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current
   /// context is "used as device code".
   ///
@@ -14507,6 +14776,8 @@ public:
   void deepTypeCheckForSYCLDevice(SourceLocation UsedAt,
                                   llvm::DenseSet Visited,
                                   ValueDecl *DeclToCheck);
+
+  ///@}
 };
 
 DeductionFailureInfo
diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h
index 2002bf23c9595f7f21598db723f2e20506482258..370d8037a4da17933e80256f651ddfa104d78203 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -2456,13 +2456,6 @@ private:
   uint32_t Value;
   uint32_t CurrentBitsIndex = ~0;
 };
-
-inline bool shouldSkipCheckingODR(const Decl *D) {
-  return D->getOwningModule() &&
-         D->getASTContext().getLangOpts().SkipODRCheckInGMF &&
-         D->getOwningModule()->isExplicitGlobalModule();
-}
-
 } // namespace clang
 
 #endif // LLVM_CLANG_SERIALIZATION_ASTREADER_H
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index 5e2f305b294caf4f6615f2304ce0f5e79f203c61..e5db486a71a490565692cb90c2ecc2055007f530 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -166,6 +166,10 @@ private:
   /// Indicates that the AST contained compiler errors.
   bool ASTHasCompilerErrors = false;
 
+  /// Indicates that we're going to generate the reduced BMI for C++20
+  /// named modules.
+  bool GeneratingReducedBMI = false;
+
   /// Mapping from input file entries to the index into the
   /// offset table where information about that input file is stored.
   llvm::DenseMap InputFileIDs;
@@ -596,7 +600,8 @@ public:
   ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl &Buffer,
             InMemoryModuleCache &ModuleCache,
             ArrayRef> Extensions,
-            bool IncludeTimestamps = true, bool BuildingImplicitModule = false);
+            bool IncludeTimestamps = true, bool BuildingImplicitModule = false,
+            bool GeneratingReducedBMI = false);
   ~ASTWriter() override;
 
   ASTContext &getASTContext() const {
@@ -856,6 +861,13 @@ protected:
   const ASTWriter &getWriter() const { return Writer; }
   SmallVectorImpl &getPCH() const { return Buffer->Data; }
 
+  bool isComplete() const { return Buffer->IsComplete; }
+  PCHBuffer *getBufferPtr() { return Buffer.get(); }
+  StringRef getOutputFile() const { return OutputFile; }
+  DiagnosticsEngine &getDiagnostics() const {
+    return SemaPtr->getDiagnostics();
+  }
+
 public:
   PCHGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
                StringRef OutputFile, StringRef isysroot,
@@ -863,7 +875,8 @@ public:
                ArrayRef> Extensions,
                bool AllowASTWithErrors = false, bool IncludeTimestamps = true,
                bool BuildingImplicitModule = false,
-               bool ShouldCacheASTInMemory = false);
+               bool ShouldCacheASTInMemory = false,
+               bool GeneratingReducedBMI = false);
   ~PCHGenerator() override;
 
   void InitializeSema(Sema &S) override { SemaPtr = &S; }
@@ -873,6 +886,21 @@ public:
   bool hasEmittedPCH() const { return Buffer->IsComplete; }
 };
 
+class ReducedBMIGenerator : public PCHGenerator {
+public:
+  ReducedBMIGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
+                      StringRef OutputFile, std::shared_ptr Buffer,
+                      bool IncludeTimestamps);
+
+  void HandleTranslationUnit(ASTContext &Ctx) override;
+};
+
+/// If we can elide the definition of \param D in reduced BMI.
+///
+/// Generally, we can elide the definition of a declaration if it won't affect
+/// the ABI. e.g., the non-inline function bodies.
+bool CanElideDeclDef(const Decl *D);
+
 /// A simple helper class to pack several bits in order into (a) 32 bit
 /// integer(s).
 class BitsPacker {
diff --git a/clang/include/clang/Serialization/PCHContainerOperations.h b/clang/include/clang/Serialization/PCHContainerOperations.h
index be10feb5e351c3938e2d183135e3e7fdc30b84d5..ddfddf2dafadf9f616a7b9327891f189cc71e51b 100644
--- a/clang/include/clang/Serialization/PCHContainerOperations.h
+++ b/clang/include/clang/Serialization/PCHContainerOperations.h
@@ -1,4 +1,4 @@
-//===--- Serialization/PCHContainerOperations.h - PCH Containers --*- C++ -*-===//
+//===-- PCHContainerOperations.h - PCH Containers ---------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index a224b81c33a624bad5eb969317e6ee2cde0fb07b..686e5e99f4a62c4a2649ea40849998968aa3e92b 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -1654,6 +1654,10 @@ def StdCLibraryFunctionsTesterChecker : Checker<"StdCLibraryFunctionsTester">,
   WeakDependencies<[StdCLibraryFunctionsChecker]>,
   Documentation;
 
+def CheckerDocumentationChecker : Checker<"CheckerDocumentation">,
+  HelpText<"Defines an empty checker callback for all possible handlers.">,
+  Documentation;
+
 } // end "debug"
 
 
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
index 2694aac478cd475bf35671fbd0c097e9f6e9064c..88a9d76f248878a8908dccd850b1fa309d73c84a 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
@@ -1,4 +1,4 @@
-//===--- PathDiagnosticConsumers.h - Path Diagnostic Clients ------*- C++ -*-===//
+//===--- PathDiagnosticConsumers.h - Path Diagnostic Clients ----*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h
index 3432d2648633c25a575e93087c766688bcd6ede6..b4e1636130ca7c2d10586749bff69519e8363ed1 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h
@@ -41,12 +41,8 @@ public:
     ///  - We also accept calls where the number of arguments or parameters is
     ///    greater than the specified value.
     /// For the exact heuristics, see CheckerContext::isCLibraryFunction().
-    /// Note that functions whose declaration context is not a TU (e.g.
-    /// methods, functions in namespaces) are not accepted as C library
-    /// functions.
-    /// FIXME: If I understand it correctly, this discards calls where C++ code
-    /// refers a C library function through the namespace `std::` via headers
-    /// like .
+    /// (This mode only matches functions that are declared either directly
+    /// within a TU or in the namespace `std`.)
     CLibrary,
 
     /// Matches "simple" functions that are not methods. (Static methods are
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
index 65982457ad8393bb5a21769455312d787048c903..60421e5437d82f7d35e2b3da4473098735d2c7dc 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
@@ -13,6 +13,9 @@
 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERHELPERS_H
 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERHELPERS_H
 
+#include "ProgramState_Fwd.h"
+#include "SVals.h"
+
 #include "clang/AST/OperationKinds.h"
 #include "clang/AST/Stmt.h"
 #include "clang/Basic/OperatorKinds.h"
@@ -110,6 +113,9 @@ public:
 OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK,
                                                  bool IsBinary);
 
+std::optional getPointeeDefVal(SVal PtrSVal,
+                                            ProgramStateRef State);
+
 } // namespace ento
 
 } // namespace clang
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index 8dbe767cef9d7eb8935918441f275e295e194231..8e392421fef9bb1cb270f7816df358879bca66b7 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -149,12 +149,6 @@ public:
   bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
                        ProgramStateRef InitState);
 
-  /// Returns true if there is still simulation state on the worklist.
-  bool ExecuteWorkListWithInitialState(const LocationContext *L,
-                                       unsigned Steps,
-                                       ProgramStateRef InitState,
-                                       ExplodedNodeSet &Dst);
-
   /// Dispatch the work list item based on the given location information.
   /// Use Pred parameter as the predecessor state.
   void dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index ed5c4adb5e3d5679b49e4ad93be6d4fa7876230b..f7894fb83ce65cd30b165ce5aa8b73242bfa75a3 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -190,16 +190,6 @@ public:
     return Engine.ExecuteWorkList(L, Steps, nullptr);
   }
 
-  /// Execute the work list with an initial state. Nodes that reaches the exit
-  /// of the function are added into the Dst set, which represent the exit
-  /// state of the function call. Returns true if there is still simulation
-  /// state on the worklist.
-  bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
-                                       ProgramStateRef InitState,
-                                       ExplodedNodeSet &Dst) {
-    return Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
-  }
-
   /// getContext - Return the ASTContext associated with this analysis.
   ASTContext &getContext() const { return AMgr.getASTContext(); }
 
diff --git a/clang/include/clang/Testing/CommandLineArgs.h b/clang/include/clang/Testing/CommandLineArgs.h
index 4dd28718dfa67c81add0b1641e3e3392cda0cab8..e71907e8bbd0c60a0ebc5f2ec97d256d0273a2aa 100644
--- a/clang/include/clang/Testing/CommandLineArgs.h
+++ b/clang/include/clang/Testing/CommandLineArgs.h
@@ -28,6 +28,7 @@ enum TestLanguage {
   Lang_CXX14,
   Lang_CXX17,
   Lang_CXX20,
+  Lang_CXX23,
   Lang_OpenCL,
   Lang_OBJC,
   Lang_OBJCXX
diff --git a/clang/include/clang/Testing/TestClangConfig.h b/clang/include/clang/Testing/TestClangConfig.h
index 92d5cc3cff994fbd8fca397e373c60e2076723ee..1b4efca80e9d47cc072867fda1e14a17d66f555e 100644
--- a/clang/include/clang/Testing/TestClangConfig.h
+++ b/clang/include/clang/Testing/TestClangConfig.h
@@ -34,24 +34,30 @@ struct TestClangConfig {
   bool isCXX() const {
     return Language == Lang_CXX03 || Language == Lang_CXX11 ||
            Language == Lang_CXX14 || Language == Lang_CXX17 ||
-           Language == Lang_CXX20;
+           Language == Lang_CXX20 || Language == Lang_CXX23;
   }
 
   bool isCXX11OrLater() const {
     return Language == Lang_CXX11 || Language == Lang_CXX14 ||
-           Language == Lang_CXX17 || Language == Lang_CXX20;
+           Language == Lang_CXX17 || Language == Lang_CXX20 ||
+           Language == Lang_CXX23;
   }
 
   bool isCXX14OrLater() const {
     return Language == Lang_CXX14 || Language == Lang_CXX17 ||
-           Language == Lang_CXX20;
+           Language == Lang_CXX20 || Language == Lang_CXX23;
   }
 
   bool isCXX17OrLater() const {
-    return Language == Lang_CXX17 || Language == Lang_CXX20;
+    return Language == Lang_CXX17 || Language == Lang_CXX20 ||
+           Language == Lang_CXX23;
   }
 
-  bool isCXX20OrLater() const { return Language == Lang_CXX20; }
+  bool isCXX20OrLater() const {
+    return Language == Lang_CXX20 || Language == Lang_CXX23;
+  }
+
+  bool isCXX23OrLater() const { return Language == Lang_CXX23; }
 
   bool supportsCXXDynamicExceptionSpecification() const {
     return Language == Lang_CXX03 || Language == Lang_CXX11 ||
diff --git a/clang/lib/APINotes/APINotesManager.cpp b/clang/lib/APINotes/APINotesManager.cpp
index d3aef09dac91056758e9b8d4abb0263bc710b71f..f60f09e2b3c23198b2cb58eea29beba8312efdb0 100644
--- a/clang/lib/APINotes/APINotesManager.cpp
+++ b/clang/lib/APINotes/APINotesManager.cpp
@@ -224,7 +224,7 @@ APINotesManager::getCurrentModuleAPINotes(Module *M, bool LookInModule,
   llvm::SmallVector APINotes;
 
   // First, look relative to the module itself.
-  if (LookInModule) {
+  if (LookInModule && M->Directory) {
     // Local function to try loading an API notes file in the given directory.
     auto tryAPINotes = [&](DirectoryEntryRef Dir, bool WantPublic) {
       if (auto File = findAPINotesFile(Dir, ModuleName, WantPublic)) {
diff --git a/clang/lib/ARCMigrate/TransGCAttrs.cpp b/clang/lib/ARCMigrate/TransGCAttrs.cpp
index 28d1db7f43766849953295c7101a5b34e38f1890..85e3fe77660b5c7d8ebb5b5093cca407d26903fb 100644
--- a/clang/lib/ARCMigrate/TransGCAttrs.cpp
+++ b/clang/lib/ARCMigrate/TransGCAttrs.cpp
@@ -1,4 +1,4 @@
-//===--- TransGCAttrs.cpp - Transformations to ARC mode --------------------===//
+//===--- TransGCAttrs.cpp - Transformations to ARC mode -------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt
index 6ea1ca3e76cf33e645669e2a6f273c01a776e9e4..3fba052d916c9ea031659c0bba312d75e6d3312f 100644
--- a/clang/lib/AST/CMakeLists.txt
+++ b/clang/lib/AST/CMakeLists.txt
@@ -66,7 +66,6 @@ add_clang_library(clangAST
   InheritViz.cpp
   Interp/ByteCodeEmitter.cpp
   Interp/ByteCodeExprGen.cpp
-  Interp/ByteCodeGenError.cpp
   Interp/ByteCodeStmtGen.cpp
   Interp/Context.cpp
   Interp/Descriptor.cpp
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 57a92357f6e5baa5ad36ce2a38c779e0fb926d31..8626f04012f7d497af9d0b222b3c11842262e752 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2465,7 +2465,7 @@ bool VarDecl::mightBeUsableInConstantExpressions(const ASTContext &C) const {
 
   // OpenCL permits const integral variables to be used in constant
   // expressions, like in C++98.
-  if (!Lang.CPlusPlus && !Lang.OpenCL)
+  if (!Lang.CPlusPlus && !Lang.OpenCL && !Lang.C23)
     return false;
 
   // Function parameters are never usable in constant expressions.
@@ -2487,14 +2487,19 @@ bool VarDecl::mightBeUsableInConstantExpressions(const ASTContext &C) const {
   if (!getType().isConstant(C) || getType().isVolatileQualified())
     return false;
 
-  // In C++, const, non-volatile variables of integral or enumeration types
-  // can be used in constant expressions.
-  if (getType()->isIntegralOrEnumerationType())
+  // In C++, but not in C, const, non-volatile variables of integral or
+  // enumeration types can be used in constant expressions.
+  if (getType()->isIntegralOrEnumerationType() && !Lang.C23)
     return true;
 
+  // C23 6.6p7: An identifier that is:
+  // ...
+  // - declared with storage-class specifier constexpr and has an object type,
+  // is a named constant, ... such a named constant is a constant expression
+  // with the type and value of the declared object.
   // Additionally, in C++11, non-volatile constexpr variables can be used in
   // constant expressions.
-  return Lang.CPlusPlus11 && isConstexpr();
+  return (Lang.CPlusPlus11 || Lang.C23) && isConstexpr();
 }
 
 bool VarDecl::isUsableInConstantExpressions(const ASTContext &Context) const {
@@ -2572,11 +2577,11 @@ APValue *VarDecl::evaluateValueImpl(SmallVectorImpl &Notes,
   bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, Ctx, this, Notes,
                                             IsConstantInitialization);
 
-  // In C++, this isn't a constant initializer if we produced notes. In that
+  // In C++/C23, this isn't a constant initializer if we produced notes. In that
   // case, we can't keep the result, because it may only be correct under the
   // assumption that the initializer is a constant context.
-  if (IsConstantInitialization && Ctx.getLangOpts().CPlusPlus &&
-      !Notes.empty())
+  if (IsConstantInitialization &&
+      (Ctx.getLangOpts().CPlusPlus || Ctx.getLangOpts().C23) && !Notes.empty())
     Result = false;
 
   // Ensure the computed APValue is cleaned up later if evaluation succeeded,
@@ -2634,7 +2639,9 @@ bool VarDecl::checkForConstantInitialization(
   // std::is_constant_evaluated()).
   assert(!Eval->WasEvaluated &&
          "already evaluated var value before checking for constant init");
-  assert(getASTContext().getLangOpts().CPlusPlus && "only meaningful in C++");
+  assert((getASTContext().getLangOpts().CPlusPlus ||
+          getASTContext().getLangOpts().C23) &&
+         "only meaningful in C++/C23");
 
   assert(!getInit()->isValueDependent());
 
@@ -4489,7 +4496,7 @@ unsigned FunctionDecl::getODRHash() {
   }
 
   class ODRHash Hash;
-  Hash.AddFunctionDecl(this);
+  Hash.AddFunctionDecl(this, /*SkipBody=*/shouldSkipCheckingODR());
   setHasODRHash(true);
   ODRHash = Hash.CalculateHash();
   return ODRHash;
@@ -5545,14 +5552,13 @@ FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C,
 void TopLevelStmtDecl::anchor() {}
 
 TopLevelStmtDecl *TopLevelStmtDecl::Create(ASTContext &C, Stmt *Statement) {
-  assert(Statement);
   assert(C.getLangOpts().IncrementalExtensions &&
          "Must be used only in incremental mode");
 
-  SourceLocation BeginLoc = Statement->getBeginLoc();
+  SourceLocation Loc = Statement ? Statement->getBeginLoc() : SourceLocation();
   DeclContext *DC = C.getTranslationUnitDecl();
 
-  return new (C, DC) TopLevelStmtDecl(DC, BeginLoc, Statement);
+  return new (C, DC) TopLevelStmtDecl(DC, Loc, Statement);
 }
 
 TopLevelStmtDecl *TopLevelStmtDecl::CreateDeserialized(ASTContext &C,
@@ -5565,6 +5571,12 @@ SourceRange TopLevelStmtDecl::getSourceRange() const {
   return SourceRange(getLocation(), Statement->getEndLoc());
 }
 
+void TopLevelStmtDecl::setStmt(Stmt *S) {
+  assert(S);
+  Statement = S;
+  setLocation(Statement->getBeginLoc());
+}
+
 void EmptyDecl::anchor() {}
 
 EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 10fe8bb97ce660e783e83f8d2e31fa9e5c96a6b0..04bbc49ab2f3192aea29e9dd2d198c3d3fa6908c 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -1102,6 +1102,11 @@ bool Decl::isInAnotherModuleUnit() const {
   return M != getASTContext().getCurrentNamedModule();
 }
 
+bool Decl::shouldSkipCheckingODR() const {
+  return getASTContext().getLangOpts().SkipODRCheckInGMF && getOwningModule() &&
+         getOwningModule()->isExplicitGlobalModule();
+}
+
 static Decl::Kind getKind(const Decl *D) { return D->getKind(); }
 static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); }
 
@@ -1352,6 +1357,7 @@ DeclContext *DeclContext::getPrimaryContext() {
   case Decl::ExternCContext:
   case Decl::LinkageSpec:
   case Decl::Export:
+  case Decl::TopLevelStmt:
   case Decl::Block:
   case Decl::Captured:
   case Decl::OMPDeclareReduction:
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index b4f2327d9c560ad354dfe1787a55bf005a762f0c..1c3dcf63465c68a6f3bacc3a8abba4fc97ade130 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -400,10 +400,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
 
       // C++11 [class.ctor]p6:
       //   If that user-written default constructor would satisfy the
-      //   requirements of a constexpr constructor, the implicitly-defined
-      //   default constructor is constexpr.
+      //   requirements of a constexpr constructor/function(C++23), the
+      //   implicitly-defined default constructor is constexpr.
       if (!BaseClassDecl->hasConstexprDefaultConstructor())
-        data().DefaultedDefaultConstructorIsConstexpr = false;
+        data().DefaultedDefaultConstructorIsConstexpr =
+            C.getLangOpts().CPlusPlus23;
 
       // C++1z [class.copy]p8:
       //   The implicitly-declared copy constructor for a class X will have
@@ -548,7 +549,8 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
   //   -- for every subobject of class type or (possibly multi-dimensional)
   //      array thereof, that class type shall have a constexpr destructor
   if (!Subobj->hasConstexprDestructor())
-    data().DefaultedDestructorIsConstexpr = false;
+    data().DefaultedDestructorIsConstexpr =
+        getASTContext().getLangOpts().CPlusPlus23;
 
   // C++20 [temp.param]p7:
   //   A structural type is [...] a literal class type [for which] the types
@@ -1297,7 +1299,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
             !FieldRec->hasConstexprDefaultConstructor() && !isUnion())
           // The standard requires any in-class initializer to be a constant
           // expression. We consider this to be a defect.
-          data().DefaultedDefaultConstructorIsConstexpr = false;
+          data().DefaultedDefaultConstructorIsConstexpr =
+              Context.getLangOpts().CPlusPlus23;
 
         // C++11 [class.copy]p8:
         //   The implicitly-declared copy constructor for a class X will have
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 43d221968ea3fba214a753266cf05426db1217ed..b701581b2474a96d16cd45828eb4170076c83971 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -1517,6 +1517,11 @@ void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
     return;
   }
   bool eolnOut = false;
+  if (OID->hasAttrs()) {
+    prettyPrintAttributes(OID);
+    Out << "\n";
+  }
+
   Out << "@interface " << I;
 
   if (auto TypeParams = OID->getTypeParamListAsWritten()) {
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index fcf8f6591a79234b13a032d6c7c90cc54dc357d6..726415cfbde08aeed17415b11669b498cb459281 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2778,7 +2778,9 @@ static bool CheckedIntArithmetic(EvalInfo &Info, const Expr *E,
     if (Info.checkingForUndefinedBehavior())
       Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
                                        diag::warn_integer_constant_overflow)
-          << toString(Result, 10) << E->getType() << E->getSourceRange();
+          << toString(Result, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
+                      /*UpperCase=*/true, /*InsertSeparators=*/true)
+          << E->getType() << E->getSourceRange();
     return HandleOverflow(Info, E, Value, E->getType());
   }
   return true;
@@ -4131,6 +4133,10 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
     }
 
     bool IsConstant = BaseType.isConstant(Info.Ctx);
+    bool ConstexprVar = false;
+    if (const auto *VD = dyn_cast_if_present(
+            Info.EvaluatingDecl.dyn_cast()))
+      ConstexprVar = VD->isConstexpr();
 
     // Unless we're looking at a local variable or argument in a constexpr call,
     // the variable we're reading must be const.
@@ -4150,6 +4156,9 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
         return CompleteObject();
       } else if (VD->isConstexpr()) {
         // OK, we can read this variable.
+      } else if (Info.getLangOpts().C23 && ConstexprVar) {
+        Info.FFDiag(E);
+        return CompleteObject();
       } else if (BaseType->isIntegralOrEnumerationType()) {
         if (!IsConstant) {
           if (!IsAccess)
@@ -5573,6 +5582,29 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
     MSConstexprContextRAII ConstexprContext(
         *Info.CurrentCall, hasSpecificAttr(AS->getAttrs()) &&
                                isa(SS));
+
+    auto LO = Info.getCtx().getLangOpts();
+    if (LO.CXXAssumptions && !LO.MSVCCompat) {
+      for (auto *Attr : AS->getAttrs()) {
+        auto *AA = dyn_cast(Attr);
+        if (!AA)
+          continue;
+
+        auto *Assumption = AA->getAssumption();
+        if (Assumption->isValueDependent())
+          return ESR_Failed;
+
+        bool Value;
+        if (!EvaluateAsBooleanCondition(Assumption, Value, Info))
+          return ESR_Failed;
+        if (!Value) {
+          Info.CCEDiag(Assumption->getExprLoc(),
+                       diag::note_constexpr_assumption_failed);
+          return ESR_Failed;
+        }
+      }
+    }
+
     return EvaluateStmt(Result, Info, SS, Case);
   }
 
@@ -12474,6 +12506,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
   case Builtin::BI__builtin_popcount:
   case Builtin::BI__builtin_popcountl:
   case Builtin::BI__builtin_popcountll:
+  case Builtin::BI__builtin_popcountg:
   case Builtin::BI__popcnt16: // Microsoft variants of popcount
   case Builtin::BI__popcnt:
   case Builtin::BI__popcnt64: {
@@ -13910,7 +13943,9 @@ bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
       if (Info.checkingForUndefinedBehavior())
         Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
                                          diag::warn_integer_constant_overflow)
-            << toString(Value, 10) << E->getType() << E->getSourceRange();
+            << toString(Value, 10, Value.isSigned(), /*formatAsCLiteral=*/false,
+                        /*UpperCase=*/true, /*InsertSeparators=*/true)
+            << E->getType() << E->getSourceRange();
 
       if (!HandleOverflow(Info, E, -Value.extend(Value.getBitWidth() + 1),
                           E->getType()))
@@ -15822,7 +15857,8 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
   EStatus.Diag = &Notes;
 
   EvalInfo Info(Ctx, EStatus,
-                (IsConstantInitialization && Ctx.getLangOpts().CPlusPlus)
+                (IsConstantInitialization &&
+                 (Ctx.getLangOpts().CPlusPlus || Ctx.getLangOpts().C23))
                     ? EvalInfo::EM_ConstantExpression
                     : EvalInfo::EM_ConstantFold);
   Info.setEvaluatingDecl(VD, Value);
diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
index 4fbfc0930fbaa1d0ea953d6228adffb3175e4614..d912c101449d80a9766405fca57cb06c9965bd75 100644
--- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "ByteCodeEmitter.h"
-#include "ByteCodeGenError.h"
 #include "Context.h"
 #include "Floating.h"
 #include "IntegralAP.h"
diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.h b/clang/lib/AST/Interp/ByteCodeEmitter.h
index 548769329b7f8c427a9978101dea35bee963a109..5612a8c1481a723639b3e3fbe3dd87e9945a3e2c 100644
--- a/clang/lib/AST/Interp/ByteCodeEmitter.h
+++ b/clang/lib/AST/Interp/ByteCodeEmitter.h
@@ -1,4 +1,4 @@
-//===--- ByteCodeEmitter.h - Instruction emitter for the VM ---------*- C++ -*-===//
+//===--- ByteCodeEmitter.h - Instruction emitter for the VM -----*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index b4110d5856d5129bf3c990cbdbaa764f2711293f..86304a54473ceaef838db08179681a0061da9949 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -8,7 +8,6 @@
 
 #include "ByteCodeExprGen.h"
 #include "ByteCodeEmitter.h"
-#include "ByteCodeGenError.h"
 #include "ByteCodeStmtGen.h"
 #include "Context.h"
 #include "Floating.h"
@@ -315,11 +314,7 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) {
     for (unsigned I = 0; I != 2; ++I) {
       if (!this->emitGetLocal(PT_Ptr, *SubExprOffset, CE))
         return false;
-      if (!this->emitConstUint8(I, CE))
-        return false;
-      if (!this->emitArrayElemPtrPopUint8(CE))
-        return false;
-      if (!this->emitLoadPop(SourceElemT, CE))
+      if (!this->emitArrayElemPop(SourceElemT, I, CE))
         return false;
 
       // Do the cast.
@@ -394,12 +389,16 @@ bool ByteCodeExprGen::VisitBinaryOperator(const BinaryOperator *BO) {
   if (BO->isLogicalOp())
     return this->VisitLogicalBinOp(BO);
 
-  if (BO->getType()->isAnyComplexType())
-    return this->VisitComplexBinOp(BO);
-
   const Expr *LHS = BO->getLHS();
   const Expr *RHS = BO->getRHS();
 
+  if (BO->getType()->isAnyComplexType())
+    return this->VisitComplexBinOp(BO);
+  if ((LHS->getType()->isAnyComplexType() ||
+       RHS->getType()->isAnyComplexType()) &&
+      BO->isComparisonOp())
+    return this->emitComplexComparison(LHS, RHS, BO);
+
   if (BO->isPtrMemOp())
     return this->visit(RHS);
 
@@ -726,11 +725,8 @@ bool ByteCodeExprGen::VisitComplexBinOp(const BinaryOperator *E) {
     if (IsComplex) {
       if (!this->emitGetLocal(PT_Ptr, Offset, E))
         return false;
-      if (!this->emitConstUint8(ElemIndex, E))
-        return false;
-      if (!this->emitArrayElemPtrPopUint8(E))
-        return false;
-      return this->emitLoadPop(classifyComplexElementType(E->getType()), E);
+      return this->emitArrayElemPop(classifyComplexElementType(E->getType()),
+                                    ElemIndex, E);
     }
     if (ElemIndex == 0)
       return this->emitGetLocal(classifyPrim(E->getType()), Offset, E);
@@ -1650,7 +1646,8 @@ bool ByteCodeExprGen::VisitMaterializeTemporaryExpr(
             SubExpr, *SubExprT, /*IsConst=*/true, /*IsExtended=*/true)) {
       if (!this->visit(SubExpr))
         return false;
-      this->emitSetLocal(*SubExprT, *LocalIndex, E);
+      if (!this->emitSetLocal(*SubExprT, *LocalIndex, E))
+        return false;
       return this->emitGetPtrLocal(*LocalIndex, E);
     }
   } else {
@@ -2730,6 +2727,18 @@ bool ByteCodeExprGen::VisitBuiltinCallExpr(const CallExpr *E) {
   if (!Func)
     return false;
 
+  QualType ReturnType = E->getType();
+  std::optional ReturnT = classify(E);
+
+  // Non-primitive return type. Prepare storage.
+  if (!Initializing && !ReturnT && !ReturnType->isVoidType()) {
+    std::optional LocalIndex = allocateLocal(E, /*IsExtended=*/false);
+    if (!LocalIndex)
+      return false;
+    if (!this->emitGetPtrLocal(*LocalIndex, E))
+      return false;
+  }
+
   if (!Func->isUnevaluatedBuiltin()) {
     // Put arguments on the stack.
     for (const auto *Arg : E->arguments()) {
@@ -2741,10 +2750,9 @@ bool ByteCodeExprGen::VisitBuiltinCallExpr(const CallExpr *E) {
   if (!this->emitCallBI(Func, E, E))
     return false;
 
-  QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
   if (DiscardResult && !ReturnType->isVoidType()) {
-    PrimType T = classifyPrim(ReturnType);
-    return this->emitPop(T, E);
+    assert(ReturnT);
+    return this->emitPop(*ReturnT, E);
   }
 
   return true;
@@ -2951,6 +2959,8 @@ bool ByteCodeExprGen::VisitCXXThisExpr(const CXXThisExpr *E) {
 template 
 bool ByteCodeExprGen::VisitUnaryOperator(const UnaryOperator *E) {
   const Expr *SubExpr = E->getSubExpr();
+  if (SubExpr->getType()->isAnyComplexType())
+    return this->VisitComplexUnaryOperator(E);
   std::optional T = classify(SubExpr->getType());
 
   switch (E->getOpcode()) {
@@ -3101,36 +3111,115 @@ bool ByteCodeExprGen::VisitUnaryOperator(const UnaryOperator *E) {
       return false;
     return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
   case UO_Real: // __real x
-    if (T)
-      return this->delegate(SubExpr);
-    return this->emitComplexReal(SubExpr);
+    assert(T);
+    return this->delegate(SubExpr);
   case UO_Imag: { // __imag x
-    if (T) {
-      if (!this->discard(SubExpr))
+    assert(T);
+    if (!this->discard(SubExpr))
+      return false;
+    return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr);
+  }
+  case UO_Extension:
+    return this->delegate(SubExpr);
+  case UO_Coawait:
+    assert(false && "Unhandled opcode");
+  }
+
+  return false;
+}
+
+template 
+bool ByteCodeExprGen::VisitComplexUnaryOperator(
+    const UnaryOperator *E) {
+  const Expr *SubExpr = E->getSubExpr();
+  assert(SubExpr->getType()->isAnyComplexType());
+
+  if (DiscardResult)
+    return this->discard(SubExpr);
+
+  std::optional ResT = classify(E);
+  auto prepareResult = [=]() -> bool {
+    if (!ResT && !Initializing) {
+      std::optional LocalIndex =
+          allocateLocal(SubExpr, /*IsExtended=*/false);
+      if (!LocalIndex)
+        return false;
+      return this->emitGetPtrLocal(*LocalIndex, E);
+    }
+
+    return true;
+  };
+
+  // The offset of the temporary, if we created one.
+  unsigned SubExprOffset = ~0u;
+  auto createTemp = [=, &SubExprOffset]() -> bool {
+    SubExprOffset = this->allocateLocalPrimitive(SubExpr, PT_Ptr, true, false);
+    if (!this->visit(SubExpr))
+      return false;
+    return this->emitSetLocal(PT_Ptr, SubExprOffset, E);
+  };
+
+  PrimType ElemT = classifyComplexElementType(SubExpr->getType());
+  auto getElem = [=](unsigned Offset, unsigned Index) -> bool {
+    if (!this->emitGetLocal(PT_Ptr, Offset, E))
+      return false;
+    return this->emitArrayElemPop(ElemT, Index, E);
+  };
+
+  switch (E->getOpcode()) {
+  case UO_Minus:
+    if (!prepareResult())
+      return false;
+    if (!createTemp())
+      return false;
+    for (unsigned I = 0; I != 2; ++I) {
+      if (!getElem(SubExprOffset, I))
+        return false;
+      if (!this->emitNeg(ElemT, E))
+        return false;
+      if (!this->emitInitElem(ElemT, I, E))
         return false;
-      return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr);
     }
+    break;
 
+  case UO_Plus:   // +x
+  case UO_AddrOf: // &x
+  case UO_Deref:  // *x
+    return this->delegate(SubExpr);
+
+  case UO_LNot:
     if (!this->visit(SubExpr))
       return false;
-    if (!this->emitConstUint8(1, E))
+    if (!this->emitComplexBoolCast(SubExpr))
       return false;
-    if (!this->emitArrayElemPtrPopUint8(E))
+    if (!this->emitInvBool(E))
+      return false;
+    if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool)
+      return this->emitCast(PT_Bool, ET, E);
+    return true;
+
+  case UO_Real:
+    return this->emitComplexReal(SubExpr);
+
+  case UO_Imag:
+    if (!this->visit(SubExpr))
       return false;
 
+    if (SubExpr->isLValue()) {
+      if (!this->emitConstUint8(1, E))
+        return false;
+      return this->emitArrayElemPtrPopUint8(E);
+    }
+
     // Since our _Complex implementation does not map to a primitive type,
     // we sometimes have to do the lvalue-to-rvalue conversion here manually.
-    if (!SubExpr->isLValue())
-      return this->emitLoadPop(classifyPrim(E->getType()), E);
-    return true;
-  }
-  case UO_Extension:
-    return this->delegate(SubExpr);
-  case UO_Coawait:
-    assert(false && "Unhandled opcode");
+    return this->emitArrayElemPop(classifyPrim(E->getType()), 1, E);
+
+  default:
+    return this->emitInvalid(E);
   }
 
-  return false;
+  return true;
 }
 
 template 
@@ -3333,17 +3422,15 @@ bool ByteCodeExprGen::emitComplexReal(const Expr *SubExpr) {
 
   if (!this->visit(SubExpr))
     return false;
-  if (!this->emitConstUint8(0, SubExpr))
-    return false;
-  if (!this->emitArrayElemPtrPopUint8(SubExpr))
-    return false;
+  if (SubExpr->isLValue()) {
+    if (!this->emitConstUint8(0, SubExpr))
+      return false;
+    return this->emitArrayElemPtrPopUint8(SubExpr);
+  }
 
-  // Since our _Complex implementation does not map to a primitive type,
-  // we sometimes have to do the lvalue-to-rvalue conversion here manually.
-  if (!SubExpr->isLValue())
-    return this->emitLoadPop(classifyComplexElementType(SubExpr->getType()),
-                             SubExpr);
-  return true;
+  // Rvalue, load the actual element.
+  return this->emitArrayElemPop(classifyComplexElementType(SubExpr->getType()),
+                                0, SubExpr);
 }
 
 template 
@@ -3352,11 +3439,7 @@ bool ByteCodeExprGen::emitComplexBoolCast(const Expr *E) {
   PrimType ElemT = classifyComplexElementType(E->getType());
   // We emit the expression (__real(E) != 0 || __imag(E) != 0)
   // for us, that means (bool)E[0] || (bool)E[1]
-  if (!this->emitConstUint8(0, E))
-    return false;
-  if (!this->emitArrayElemPtrUint8(E))
-    return false;
-  if (!this->emitLoadPop(ElemT, E))
+  if (!this->emitArrayElem(ElemT, 0, E))
     return false;
   if (ElemT == PT_Float) {
     if (!this->emitCastFloatingIntegral(PT_Bool, E))
@@ -3371,11 +3454,7 @@ bool ByteCodeExprGen::emitComplexBoolCast(const Expr *E) {
   if (!this->jumpTrue(LabelTrue))
     return false;
 
-  if (!this->emitConstUint8(1, E))
-    return false;
-  if (!this->emitArrayElemPtrPopUint8(E))
-    return false;
-  if (!this->emitLoadPop(ElemT, E))
+  if (!this->emitArrayElemPop(ElemT, 1, E))
     return false;
   if (ElemT == PT_Float) {
     if (!this->emitCastFloatingIntegral(PT_Bool, E))
@@ -3400,6 +3479,102 @@ bool ByteCodeExprGen::emitComplexBoolCast(const Expr *E) {
   return true;
 }
 
+template 
+bool ByteCodeExprGen::emitComplexComparison(const Expr *LHS,
+                                                     const Expr *RHS,
+                                                     const BinaryOperator *E) {
+  assert(E->isComparisonOp());
+  assert(!Initializing);
+  assert(!DiscardResult);
+
+  PrimType ElemT;
+  bool LHSIsComplex;
+  unsigned LHSOffset;
+  if (LHS->getType()->isAnyComplexType()) {
+    LHSIsComplex = true;
+    ElemT = classifyComplexElementType(LHS->getType());
+    LHSOffset = allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true,
+                                       /*IsExtended=*/false);
+    if (!this->visit(LHS))
+      return false;
+    if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))
+      return false;
+  } else {
+    LHSIsComplex = false;
+    PrimType LHST = classifyPrim(LHS->getType());
+    LHSOffset = this->allocateLocalPrimitive(LHS, LHST, true, false);
+    if (!this->visit(LHS))
+      return false;
+    if (!this->emitSetLocal(LHST, LHSOffset, E))
+      return false;
+  }
+
+  bool RHSIsComplex;
+  unsigned RHSOffset;
+  if (RHS->getType()->isAnyComplexType()) {
+    RHSIsComplex = true;
+    ElemT = classifyComplexElementType(RHS->getType());
+    RHSOffset = allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true,
+                                       /*IsExtended=*/false);
+    if (!this->visit(RHS))
+      return false;
+    if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))
+      return false;
+  } else {
+    RHSIsComplex = false;
+    PrimType RHST = classifyPrim(RHS->getType());
+    RHSOffset = this->allocateLocalPrimitive(RHS, RHST, true, false);
+    if (!this->visit(RHS))
+      return false;
+    if (!this->emitSetLocal(RHST, RHSOffset, E))
+      return false;
+  }
+
+  auto getElem = [&](unsigned LocalOffset, unsigned Index,
+                     bool IsComplex) -> bool {
+    if (IsComplex) {
+      if (!this->emitGetLocal(PT_Ptr, LocalOffset, E))
+        return false;
+      return this->emitArrayElemPop(ElemT, Index, E);
+    }
+    return this->emitGetLocal(ElemT, LocalOffset, E);
+  };
+
+  for (unsigned I = 0; I != 2; ++I) {
+    // Get both values.
+    if (!getElem(LHSOffset, I, LHSIsComplex))
+      return false;
+    if (!getElem(RHSOffset, I, RHSIsComplex))
+      return false;
+    // And compare them.
+    if (!this->emitEQ(ElemT, E))
+      return false;
+
+    if (!this->emitCastBoolUint8(E))
+      return false;
+  }
+
+  // We now have two bool values on the stack. Compare those.
+  if (!this->emitAddUint8(E))
+    return false;
+  if (!this->emitConstUint8(2, E))
+    return false;
+
+  if (E->getOpcode() == BO_EQ) {
+    if (!this->emitEQUint8(E))
+      return false;
+  } else if (E->getOpcode() == BO_NE) {
+    if (!this->emitNEUint8(E))
+      return false;
+  } else
+    return false;
+
+  // In C, this returns an int.
+  if (PrimType ResT = classifyPrim(E->getType()); ResT != PT_Bool)
+    return this->emitCast(PT_Bool, ResT, E);
+  return true;
+}
+
 /// When calling this, we have a pointer of the local-to-destroy
 /// on the stack.
 /// Emit destruction of record types (or arrays of record types).
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index acbbcc3dc9619add10e8149ca50982612a3b73ad..5ad2e74d7c269324ad8e08847e5d014387490f30 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -75,6 +75,7 @@ public:
   bool VisitGNUNullExpr(const GNUNullExpr *E);
   bool VisitCXXThisExpr(const CXXThisExpr *E);
   bool VisitUnaryOperator(const UnaryOperator *E);
+  bool VisitComplexUnaryOperator(const UnaryOperator *E);
   bool VisitDeclRefExpr(const DeclRefExpr *E);
   bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E);
   bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E);
@@ -268,6 +269,8 @@ private:
 
   bool emitComplexReal(const Expr *SubExpr);
   bool emitComplexBoolCast(const Expr *E);
+  bool emitComplexComparison(const Expr *LHS, const Expr *RHS,
+                             const BinaryOperator *E);
 
   bool emitRecordDestruction(const Record *R);
   bool emitDestruction(const Descriptor *Desc);
diff --git a/clang/lib/AST/Interp/ByteCodeGenError.h b/clang/lib/AST/Interp/ByteCodeGenError.h
deleted file mode 100644
index af464b5ed4ab150c5cb28aa5399c907199b4cec7..0000000000000000000000000000000000000000
--- a/clang/lib/AST/Interp/ByteCodeGenError.h
+++ /dev/null
@@ -1,46 +0,0 @@
-//===--- ByteCodeGenError.h - Byte code generation error ----------*- 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_CLANG_AST_INTERP_BYTECODEGENERROR_H
-#define LLVM_CLANG_AST_INTERP_BYTECODEGENERROR_H
-
-#include "clang/AST/Decl.h"
-#include "clang/AST/Stmt.h"
-#include "clang/Basic/SourceLocation.h"
-#include "llvm/Support/Error.h"
-
-namespace clang {
-namespace interp {
-
-/// Error thrown by the compiler.
-struct ByteCodeGenError : public llvm::ErrorInfo {
-public:
-  ByteCodeGenError(SourceRange Range) : Range(Range) {}
-  ByteCodeGenError(const Stmt *S) : ByteCodeGenError(S->getSourceRange()) {}
-  ByteCodeGenError(const Decl *D) : ByteCodeGenError(D->getSourceRange()) {}
-
-  void log(raw_ostream &OS) const override { OS << "unimplemented feature"; }
-
-  const SourceRange &getRange() const { return Range; }
-
-  static char ID;
-
-private:
-  // Range of the item where the error occurred.
-  SourceRange Range;
-
-  // Users are not expected to use error_code.
-  std::error_code convertToErrorCode() const override {
-    return llvm::inconvertibleErrorCode();
-  }
-};
-
-} // namespace interp
-} // namespace clang
-
-#endif
diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
index d9213b12cbd08b1fa541b33f4f93b54b2e5240a3..6da3860f98d8c022d53781eaba72b5167295b086 100644
--- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp
@@ -8,7 +8,6 @@
 
 #include "ByteCodeStmtGen.h"
 #include "ByteCodeEmitter.h"
-#include "ByteCodeGenError.h"
 #include "Context.h"
 #include "Function.h"
 #include "PrimType.h"
diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp
index 017095352dc235748365caa76e533565e0fb45ec..15a9d46880e954acf13d2a7fc4d7ac33d3e62ede 100644
--- a/clang/lib/AST/Interp/Context.cpp
+++ b/clang/lib/AST/Interp/Context.cpp
@@ -9,7 +9,6 @@
 #include "Context.h"
 #include "ByteCodeEmitter.h"
 #include "ByteCodeExprGen.h"
-#include "ByteCodeGenError.h"
 #include "ByteCodeStmtGen.h"
 #include "EvalEmitter.h"
 #include "Interp.h"
@@ -208,17 +207,6 @@ bool Context::Run(State &Parent, const Function *Func, APValue &Result) {
   return false;
 }
 
-bool Context::Check(State &Parent, llvm::Expected &&Flag) {
-  if (Flag)
-    return *Flag;
-  handleAllErrors(Flag.takeError(), [&Parent](ByteCodeGenError &Err) {
-    Parent.FFDiag(Err.getRange().getBegin(),
-                  diag::err_experimental_clang_interp_failed)
-        << Err.getRange();
-  });
-  return false;
-}
-
 // TODO: Virtual bases?
 const CXXMethodDecl *
 Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl,
diff --git a/clang/lib/AST/Interp/Context.h b/clang/lib/AST/Interp/Context.h
index dbb63e3691816147a9cbb3c390748bff76fd1cf2..23c439ad8912a74839c8c93a788893247b913a15 100644
--- a/clang/lib/AST/Interp/Context.h
+++ b/clang/lib/AST/Interp/Context.h
@@ -108,9 +108,6 @@ private:
   /// Runs a function.
   bool Run(State &Parent, const Function *Func, APValue &Result);
 
-  /// Checks a result from the interpreter.
-  bool Check(State &Parent, llvm::Expected &&R);
-
   /// Current compilation context.
   ASTContext &Ctx;
   /// Interpreter stack, shared across invocations.
diff --git a/clang/lib/AST/Interp/EvalEmitter.cpp b/clang/lib/AST/Interp/EvalEmitter.cpp
index bfd502d21b4ceccf6f7d2d7da3cf896889ad25be..caffb69d83e379a8d62225359889a0f1d22d1f9b 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "EvalEmitter.h"
-#include "ByteCodeGenError.h"
 #include "Context.h"
 #include "IntegralAP.h"
 #include "Interp.h"
diff --git a/clang/lib/AST/Interp/FunctionPointer.h b/clang/lib/AST/Interp/FunctionPointer.h
index bb3da9b50aa55229cdd374c871e5d855099c3964..2ff691b1cd3e186323e4907d4e7ca78dfa0a7327 100644
--- a/clang/lib/AST/Interp/FunctionPointer.h
+++ b/clang/lib/AST/Interp/FunctionPointer.h
@@ -1,4 +1,4 @@
-//===--- FunctionPointer.h - Types for the constexpr VM ----------*- C++ -*-===//
+//===--- FunctionPointer.h - Types for the constexpr VM ---------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 3d49f73a567621c8cb096023d74e8b765521fab7..bb220657c2dadc18628a27078d691c6ab898d8bc 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -287,7 +287,9 @@ bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS,
   QualType Type = E->getType();
   if (S.checkingForUndefinedBehavior()) {
     SmallString<32> Trunc;
-    Value.trunc(Result.bitWidth()).toString(Trunc, 10);
+    Value.trunc(Result.bitWidth())
+        .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
+                  /*UpperCase=*/true, /*InsertSeparators=*/true);
     auto Loc = E->getExprLoc();
     S.report(Loc, diag::warn_integer_constant_overflow)
         << Trunc << Type << E->getSourceRange();
@@ -499,7 +501,9 @@ bool Neg(InterpState &S, CodePtr OpPC) {
 
   if (S.checkingForUndefinedBehavior()) {
     SmallString<32> Trunc;
-    NegatedValue.trunc(Result.bitWidth()).toString(Trunc, 10);
+    NegatedValue.trunc(Result.bitWidth())
+        .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
+                  /*UpperCase=*/true, /*InsertSeparators=*/true);
     auto Loc = E->getExprLoc();
     S.report(Loc, diag::warn_integer_constant_overflow)
         << Trunc << Type << E->getSourceRange();
@@ -521,8 +525,7 @@ enum class IncDecOp {
 
 template 
 bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
-  if (Ptr.isDummy())
-    return false;
+  assert(!Ptr.isDummy());
 
   if constexpr (std::is_same_v) {
     if (!S.getLangOpts().CPlusPlus14)
@@ -561,7 +564,9 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
   QualType Type = E->getType();
   if (S.checkingForUndefinedBehavior()) {
     SmallString<32> Trunc;
-    APResult.trunc(Result.bitWidth()).toString(Trunc, 10);
+    APResult.trunc(Result.bitWidth())
+        .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
+                  /*UpperCase=*/true, /*InsertSeparators=*/true);
     auto Loc = E->getExprLoc();
     S.report(Loc, diag::warn_integer_constant_overflow)
         << Trunc << Type << E->getSourceRange();
@@ -579,7 +584,7 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
 template ::T>
 bool Inc(InterpState &S, CodePtr OpPC) {
   const Pointer &Ptr = S.Stk.pop();
-  if (Ptr.isDummy())
+  if (!CheckDummy(S, OpPC, Ptr))
     return false;
   if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
     return false;
@@ -593,7 +598,7 @@ bool Inc(InterpState &S, CodePtr OpPC) {
 template ::T>
 bool IncPop(InterpState &S, CodePtr OpPC) {
   const Pointer &Ptr = S.Stk.pop();
-  if (Ptr.isDummy())
+  if (!CheckDummy(S, OpPC, Ptr))
     return false;
   if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
     return false;
@@ -608,7 +613,7 @@ bool IncPop(InterpState &S, CodePtr OpPC) {
 template ::T>
 bool Dec(InterpState &S, CodePtr OpPC) {
   const Pointer &Ptr = S.Stk.pop();
-  if (Ptr.isDummy())
+  if (!CheckDummy(S, OpPC, Ptr))
     return false;
   if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
     return false;
@@ -622,7 +627,7 @@ bool Dec(InterpState &S, CodePtr OpPC) {
 template ::T>
 bool DecPop(InterpState &S, CodePtr OpPC) {
   const Pointer &Ptr = S.Stk.pop();
-  if (Ptr.isDummy())
+  if (!CheckDummy(S, OpPC, Ptr))
     return false;
   if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
     return false;
@@ -746,6 +751,17 @@ inline bool CmpHelperEQ(InterpState &S, CodePtr OpPC,
                                          CompareFn Fn) {
   const auto &RHS = S.Stk.pop();
   const auto &LHS = S.Stk.pop();
+
+  // We cannot compare against weak declarations at compile time.
+  for (const auto &FP : {LHS, RHS}) {
+    if (!FP.isZero() && FP.getFunction()->getDecl()->isWeak()) {
+      const SourceInfo &Loc = S.Current->getSource(OpPC);
+      S.FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison)
+          << FP.toDiagnosticString(S.getCtx());
+      return false;
+    }
+  }
+
   S.Stk.push(Boolean::from(Fn(LHS.compare(RHS))));
   return true;
 }
@@ -1207,7 +1223,8 @@ inline bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
 inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) {
   const Pointer &Ptr = S.Stk.pop();
 
-  if (S.inConstantContext() && !CheckNull(S, OpPC, Ptr, CSK_Field))
+  if (S.getLangOpts().CPlusPlus && S.inConstantContext() &&
+      !CheckNull(S, OpPC, Ptr, CSK_Field))
     return false;
 
   if (CheckDummy(S, OpPC, Ptr)) {
@@ -1942,10 +1959,24 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
   return NarrowPtr(S, OpPC);
 }
 
+template ::T>
+inline bool ArrayElem(InterpState &S, CodePtr OpPC, uint32_t Index) {
+  const Pointer &Ptr = S.Stk.peek();
+
+  if (!CheckLoad(S, OpPC, Ptr))
+    return false;
+
+  S.Stk.push(Ptr.atIndex(Index).deref());
+  return true;
+}
+
 template ::T>
 inline bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index) {
   const Pointer &Ptr = S.Stk.pop();
 
+  if (!CheckLoad(S, OpPC, Ptr))
+    return false;
+
   S.Stk.push(Ptr.atIndex(Index).deref());
   return true;
 }
diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp
index cc457ce41af595e4617b31980cec6050ee92dd8b..c500b9d502d707813a322faabbacd2a43f6c1ec6 100644
--- a/clang/lib/AST/Interp/InterpBuiltin.cpp
+++ b/clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -53,11 +53,7 @@ static APSInt peekToAPSInt(InterpStack &Stk, PrimType T, size_t Offset = 0) {
     Offset = align(primSize(T));
 
   APSInt R;
-  INT_TYPE_SWITCH(T, {
-    T Val = Stk.peek(Offset);
-    R = APSInt(APInt(Val.bitWidth(), static_cast(Val), T::isSigned()),
-               !T::isSigned());
-  });
+  INT_TYPE_SWITCH(T, R = Stk.peek(Offset).toAPSInt());
 
   return R;
 }
@@ -900,6 +896,25 @@ static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,
   return false;
 }
 
+/// __builtin_complex(Float A, float B);
+static bool interp__builtin_complex(InterpState &S, CodePtr OpPC,
+                                    const InterpFrame *Frame,
+                                    const Function *Func,
+                                    const CallExpr *Call) {
+  const Floating &Arg2 = S.Stk.peek();
+  const Floating &Arg1 = S.Stk.peek(align(primSize(PT_Float)) * 2);
+  Pointer &Result = S.Stk.peek(align(primSize(PT_Float)) * 2 +
+                                        align(primSize(PT_Ptr)));
+
+  Result.atIndex(0).deref() = Arg1;
+  Result.atIndex(0).initialize();
+  Result.atIndex(1).deref() = Arg2;
+  Result.atIndex(1).initialize();
+  Result.initialize();
+
+  return true;
+}
+
 bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
                       const CallExpr *Call) {
   InterpFrame *Frame = S.Current;
@@ -907,9 +922,6 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
 
   std::optional ReturnT = S.getContext().classify(Call);
 
-  // If classify failed, we assume void.
-  assert(ReturnT || Call->getType()->isVoidType());
-
   switch (F->getBuiltinID()) {
   case Builtin::BI__builtin_is_constant_evaluated:
     S.Stk.push(Boolean::from(S.inConstantContext()));
@@ -1036,6 +1048,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
   case Builtin::BI__builtin_popcount:
   case Builtin::BI__builtin_popcountl:
   case Builtin::BI__builtin_popcountll:
+  case Builtin::BI__builtin_popcountg:
   case Builtin::BI__popcnt16: // Microsoft variants of popcount
   case Builtin::BI__popcnt:
   case Builtin::BI__popcnt64:
@@ -1206,6 +1219,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
       return false;
     break;
 
+  case Builtin::BI__builtin_complex:
+    if (!interp__builtin_complex(S, OpPC, Frame, F, Call))
+      return false;
+    break;
+
   default:
     S.FFDiag(S.Current->getLocation(OpPC),
              diag::note_invalid_subexpr_in_const_expr)
diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td
index ffc54646f0279e407b33dea065af94ce00c50a7e..9b99aa0ccb558a92b4913124c3ca9c72b7701b8b 100644
--- a/clang/lib/AST/Interp/Opcodes.td
+++ b/clang/lib/AST/Interp/Opcodes.td
@@ -368,6 +368,14 @@ def ArrayElemPop : Opcode {
   let HasGroup = 1;
 }
 
+def ArrayElem : Opcode {
+  let Args = [ArgUint32];
+  let Types = [AllTypeClass];
+  let HasGroup = 1;
+}
+
+
+
 //===----------------------------------------------------------------------===//
 // Direct field accessors
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/AST/Interp/PrimType.h b/clang/lib/AST/Interp/PrimType.h
index 24a24a71a07b5742b35f6439a346626bf54c1459..2bc83b334643e352d2e9e2594b0f571d58b3b424 100644
--- a/clang/lib/AST/Interp/PrimType.h
+++ b/clang/lib/AST/Interp/PrimType.h
@@ -1,4 +1,4 @@
-//===--- PrimType.h - Types for the constexpr VM --------------------*- C++ -*-===//
+//===--- PrimType.h - Types for the constexpr VM ----------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/AST/Interp/Program.h b/clang/lib/AST/Interp/Program.h
index 045bf7ab7745b1b9d4a8f8c23912271e49f7a879..50bdb575e805cf61bf1589bacf7489285bbbf666 100644
--- a/clang/lib/AST/Interp/Program.h
+++ b/clang/lib/AST/Interp/Program.h
@@ -34,7 +34,6 @@ class VarDecl;
 
 namespace interp {
 class Context;
-class Record;
 
 /// The program contains and links the bytecode for all functions.
 class Program final {
diff --git a/clang/lib/AST/StmtOpenACC.cpp b/clang/lib/AST/StmtOpenACC.cpp
index f74a777cd695baec2d855424aa83cf65ca425c2f..e6191bc6db7080a5c71a710838d7f1bd1bcd2bef 100644
--- a/clang/lib/AST/StmtOpenACC.cpp
+++ b/clang/lib/AST/StmtOpenACC.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements the subclesses of Stmt class declared in StmtOpenACC.h
+// This file implements the subclasses of Stmt class declared in StmtOpenACC.h
 //
 //===----------------------------------------------------------------------===//
 
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 78dcd3f4007a5ad169931a5359b3d6b08c782209..22666184c56ccfc9579fb2b6d28eb49c165e667d 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2682,6 +2682,8 @@ bool QualType::isTriviallyRelocatableType(const ASTContext &Context) const {
     return false;
   } else if (const auto *RD = BaseElementType->getAsRecordDecl()) {
     return RD->canPassInRegisters();
+  } else if (BaseElementType.isTriviallyCopyableType(Context)) {
+    return true;
   } else {
     switch (isNonTrivialToPrimitiveDestructiveMove()) {
     case PCK_Trivial:
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 15dad022df5fe092508ee2f4ba3bdbd1e1d64673..2c75e6beb743015fa823ad6b115bb5c8715d36b1 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -432,6 +432,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(isExpansionInMainFile);
   REGISTER_MATCHER(isExpansionInSystemHeader);
   REGISTER_MATCHER(isExplicit);
+  REGISTER_MATCHER(isExplicitObjectMemberFunction);
   REGISTER_MATCHER(isExplicitTemplateSpecialization);
   REGISTER_MATCHER(isExpr);
   REGISTER_MATCHER(isExternC);
diff --git a/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp b/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
index 8aed19544be6a2a387830c755d95f04ef1f0e773..7c9f8fbb0a7009cfa6bc5587cc7a25b67062f358 100644
--- a/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
+++ b/clang/lib/Analysis/FlowSensitive/ControlFlowContext.cpp
@@ -94,6 +94,38 @@ static llvm::BitVector findReachableBlocks(const CFG &Cfg) {
   return BlockReachable;
 }
 
+static llvm::DenseSet
+buildContainsExprConsumedInDifferentBlock(
+    const CFG &Cfg,
+    const llvm::DenseMap &StmtToBlock) {
+  llvm::DenseSet Result;
+
+  auto CheckChildExprs = [&Result, &StmtToBlock](const Stmt *S,
+                                                 const CFGBlock *Block) {
+    for (const Stmt *Child : S->children()) {
+      if (!isa(Child))
+        continue;
+      const CFGBlock *ChildBlock = StmtToBlock.lookup(Child);
+      if (ChildBlock != Block)
+        Result.insert(ChildBlock);
+    }
+  };
+
+  for (const CFGBlock *Block : Cfg) {
+    if (Block == nullptr)
+      continue;
+
+    for (const CFGElement &Element : *Block)
+      if (auto S = Element.getAs())
+        CheckChildExprs(S->getStmt(), Block);
+
+    if (const Stmt *TerminatorCond = Block->getTerminatorCondition())
+      CheckChildExprs(TerminatorCond, Block);
+  }
+
+  return Result;
+}
+
 llvm::Expected
 ControlFlowContext::build(const FunctionDecl &Func) {
   if (!Func.doesThisDeclarationHaveABody())
@@ -140,8 +172,12 @@ ControlFlowContext::build(const Decl &D, Stmt &S, ASTContext &C) {
 
   llvm::BitVector BlockReachable = findReachableBlocks(*Cfg);
 
+  llvm::DenseSet ContainsExprConsumedInDifferentBlock =
+      buildContainsExprConsumedInDifferentBlock(*Cfg, StmtToBlock);
+
   return ControlFlowContext(D, std::move(Cfg), std::move(StmtToBlock),
-                            std::move(BlockReachable));
+                            std::move(BlockReachable),
+                            std::move(ContainsExprConsumedInDifferentBlock));
 }
 
 } // namespace dataflow
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index fd7b06efcc7861808e7a3b9023a04b156155c2b6..1d2bd9a9b08af363c0db33bc1523c40878f08fae 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -48,6 +48,24 @@ static llvm::DenseMap intersectDeclToLoc(
   return Result;
 }
 
+// Performs a join on either `ExprToLoc` or `ExprToVal`.
+// The maps must be consistent in the sense that any entries for the same
+// expression must map to the same location / value. This is the case if we are
+// performing a join for control flow within a full-expression (which is the
+// only case when this function should be used).
+template  MapT joinExprMaps(const MapT &Map1, const MapT &Map2) {
+  MapT Result = Map1;
+
+  for (const auto &Entry : Map2) {
+    [[maybe_unused]] auto [It, Inserted] = Result.insert(Entry);
+    // If there was an existing entry, its value should be the same as for the
+    // entry we were trying to insert.
+    assert(It->second == Entry.second);
+  }
+
+  return Result;
+}
+
 // Whether to consider equivalent two values with an unknown relation.
 //
 // FIXME: this function is a hack enabling unsoundness to support
@@ -414,8 +432,15 @@ void Environment::initialize() {
       }
     } else if (MethodDecl->isImplicitObjectMemberFunction()) {
       QualType ThisPointeeType = MethodDecl->getFunctionObjectParameterType();
-      setThisPointeeStorageLocation(
-          cast(createObject(ThisPointeeType)));
+      auto &ThisLoc =
+          cast(createStorageLocation(ThisPointeeType));
+      setThisPointeeStorageLocation(ThisLoc);
+      refreshRecordValue(ThisLoc, *this);
+      // Initialize fields of `*this` with values, but only if we're not
+      // analyzing a constructor; after all, it's the constructor's job to do
+      // this (and we want to be able to test that).
+      if (!isa(MethodDecl))
+        initializeFieldsWithValues(ThisLoc);
     }
   }
 }
@@ -627,7 +652,8 @@ LatticeJoinEffect Environment::widen(const Environment &PrevEnv,
 }
 
 Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
-                              Environment::ValueModel &Model) {
+                              Environment::ValueModel &Model,
+                              ExprJoinBehavior ExprBehavior) {
   assert(EnvA.DACtx == EnvB.DACtx);
   assert(EnvA.ThisPointeeLoc == EnvB.ThisPointeeLoc);
   assert(EnvA.CallStack == EnvB.CallStack);
@@ -675,9 +701,10 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
   JoinedEnv.LocToVal =
       joinLocToVal(EnvA.LocToVal, EnvB.LocToVal, EnvA, EnvB, JoinedEnv, Model);
 
-  // We intentionally leave `JoinedEnv.ExprToLoc` and `JoinedEnv.ExprToVal`
-  // empty, as we never need to access entries in these maps outside of the
-  // basic block that sets them.
+  if (ExprBehavior == KeepExprState) {
+    JoinedEnv.ExprToVal = joinExprMaps(EnvA.ExprToVal, EnvB.ExprToVal);
+    JoinedEnv.ExprToLoc = joinExprMaps(EnvA.ExprToLoc, EnvB.ExprToLoc);
+  }
 
   return JoinedEnv;
 }
@@ -799,6 +826,16 @@ PointerValue &Environment::getOrCreateNullPointerValue(QualType PointeeType) {
   return DACtx->getOrCreateNullPointerValue(PointeeType);
 }
 
+void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc) {
+  llvm::DenseSet Visited;
+  int CreatedValuesCount = 0;
+  initializeFieldsWithValues(Loc, Visited, 0, CreatedValuesCount);
+  if (CreatedValuesCount > MaxCompositeValueSize) {
+    llvm::errs() << "Attempting to initialize a huge value of type: "
+                 << Loc.getType() << '\n';
+  }
+}
+
 void Environment::setValue(const StorageLocation &Loc, Value &Val) {
   assert(!isa(&Val) || &cast(&Val)->getLoc() == &Loc);
 
diff --git a/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp b/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp
index ff4e18de2c70f1fa377ebc94672c6a64b47628af..6afd66d9dc6ac57c291ee76e3fda11010e5da9d8 100644
--- a/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp
+++ b/clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp
@@ -500,7 +500,7 @@ private:
     for (unsigned I = 0; I < CFG.getNumBlockIDs(); ++I) {
       std::string Name = blockID(I);
       // Rightwards arrow, vertical line
-      char ConvergenceMarker[] = u8"\\n\u2192\u007c";
+      const char *ConvergenceMarker = (const char *)u8"\\n\u2192\u007c";
       if (BlockConverged[I])
         Name += ConvergenceMarker;
       GraphS << "  " << blockID(I) << " [id=" << blockID(I) << " label=\""
diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
index 4c88c46142d64de062fd7283eebc0a931e5d545f..939247c047c66e8d48bfdd4c121cfaa6859b72c3 100644
--- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -221,6 +221,7 @@ private:
 // Avoids unneccesary copies of the environment.
 class JoinedStateBuilder {
   AnalysisContext &AC;
+  Environment::ExprJoinBehavior JoinBehavior;
   std::vector All;
   std::deque Owned;
 
@@ -228,11 +229,13 @@ class JoinedStateBuilder {
   join(const TypeErasedDataflowAnalysisState &L,
        const TypeErasedDataflowAnalysisState &R) {
     return {AC.Analysis.joinTypeErased(L.Lattice, R.Lattice),
-            Environment::join(L.Env, R.Env, AC.Analysis)};
+            Environment::join(L.Env, R.Env, AC.Analysis, JoinBehavior)};
   }
 
 public:
-  JoinedStateBuilder(AnalysisContext &AC) : AC(AC) {}
+  JoinedStateBuilder(AnalysisContext &AC,
+                     Environment::ExprJoinBehavior JoinBehavior)
+      : AC(AC), JoinBehavior(JoinBehavior) {}
 
   void addOwned(TypeErasedDataflowAnalysisState State) {
     Owned.push_back(std::move(State));
@@ -248,12 +251,12 @@ public:
       // initialize the state of each basic block differently.
       return {AC.Analysis.typeErasedInitialElement(), AC.InitEnv.fork()};
     if (All.size() == 1)
-      // Join the environment with itself so that we discard the entries from
-      // `ExprToLoc` and `ExprToVal`.
+      // Join the environment with itself so that we discard expression state if
+      // desired.
       // FIXME: We could consider writing special-case code for this that only
       // does the discarding, but it's not clear if this is worth it.
-      return {All[0]->Lattice,
-              Environment::join(All[0]->Env, All[0]->Env, AC.Analysis)};
+      return {All[0]->Lattice, Environment::join(All[0]->Env, All[0]->Env,
+                                                 AC.Analysis, JoinBehavior)};
 
     auto Result = join(*All[0], *All[1]);
     for (unsigned I = 2; I < All.size(); ++I)
@@ -307,7 +310,22 @@ computeBlockInputState(const CFGBlock &Block, AnalysisContext &AC) {
     }
   }
 
-  JoinedStateBuilder Builder(AC);
+  // If any of the predecessor blocks contains an expression consumed in a
+  // different block, we need to keep expression state.
+  // Note that in this case, we keep expression state for all predecessors,
+  // rather than only those predecessors that actually contain an expression
+  // consumed in a different block. While this is potentially suboptimal, it's
+  // actually likely, if we have control flow within a full expression, that
+  // all predecessors have expression state consumed in a different block.
+  Environment::ExprJoinBehavior JoinBehavior = Environment::DiscardExprState;
+  for (const CFGBlock *Pred : Preds) {
+    if (Pred && AC.CFCtx.containsExprConsumedInDifferentBlock(*Pred)) {
+      JoinBehavior = Environment::KeepExprState;
+      break;
+    }
+  }
+
+  JoinedStateBuilder Builder(AC, JoinBehavior);
   for (const CFGBlock *Pred : Preds) {
     // Skip if the `Block` is unreachable or control flow cannot get past it.
     if (!Pred || Pred->hasNoReturnElement())
@@ -388,7 +406,6 @@ builtinTransferInitializer(const CFGInitializer &Elt,
     }
   }
   assert(Member != nullptr);
-  assert(MemberLoc != nullptr);
 
   // FIXME: Instead of these case distinctions, we would ideally want to be able
   // to simply use `Environment::createObject()` here, the same way that we do
@@ -404,6 +421,7 @@ builtinTransferInitializer(const CFGInitializer &Elt,
 
     ParentLoc->setChild(*Member, InitExprLoc);
   } else if (auto *InitExprVal = Env.getValue(*InitExpr)) {
+    assert(MemberLoc != nullptr);
     if (Member->getType()->isRecordType()) {
       auto *InitValStruct = cast(InitExprVal);
       // FIXME: Rather than performing a copy here, we should really be
diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp
index 44a4f1890d39e11bc70678b7cbc1cbe514b367f9..867d241a2cf8479363a3e683a458027a2117f4f7 100644
--- a/clang/lib/Basic/Attributes.cpp
+++ b/clang/lib/Basic/Attributes.cpp
@@ -47,8 +47,12 @@ int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax,
   // attributes. We support those, but not through the typical attribute
   // machinery that goes through TableGen. We support this in all OpenMP modes
   // so long as double square brackets are enabled.
-  if (LangOpts.OpenMP && ScopeName == "omp")
-    return (Name == "directive" || Name == "sequence") ? 1 : 0;
+  //
+  // Other OpenMP attributes (e.g. [[omp::assume]]) are handled via the
+  // regular attribute parsing machinery.
+  if (LangOpts.OpenMP && ScopeName == "omp" &&
+      (Name == "directive" || Name == "sequence"))
+    return 1;
 
   int res = hasAttributeImpl(Syntax, Name, ScopeName, Target, LangOpts);
   if (res)
diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp
index 1c5043a618fff32ebae9e80ee62a3f1b417a3138..9f597dcf8b0f5a59f347d888f6d7856ecc097e36 100644
--- a/clang/lib/Basic/Module.cpp
+++ b/clang/lib/Basic/Module.cpp
@@ -722,14 +722,6 @@ void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
   VisitModule({M, nullptr});
 }
 
-void VisibleModuleSet::makeTransitiveImportsVisible(Module *M,
-                                                    SourceLocation Loc,
-                                                    VisibleCallback Vis,
-                                                    ConflictCallback Cb) {
-  for (auto *I : M->Imports)
-    setVisible(I, Loc, Vis, Cb);
-}
-
 ASTSourceDescriptor::ASTSourceDescriptor(Module &M)
     : Signature(M.Signature), ClangModule(&M) {
   if (M.Directory)
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 6c31b0824eb8a4c7bbab5ba1a0bfd7a54f8cd4a9..b3e9affbb3e58ac0f671d3b01c28ef93c32f0074 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -574,31 +574,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
 }
 
 bool clang::isOpenMPLoopDirective(OpenMPDirectiveKind DKind) {
-  return DKind == OMPD_simd || DKind == OMPD_for || DKind == OMPD_for_simd ||
-         DKind == OMPD_parallel_for || DKind == OMPD_parallel_for_simd ||
-         DKind == OMPD_taskloop || DKind == OMPD_taskloop_simd ||
-         DKind == OMPD_master_taskloop || DKind == OMPD_master_taskloop_simd ||
-         DKind == OMPD_parallel_master_taskloop ||
-         DKind == OMPD_parallel_master_taskloop_simd ||
-         DKind == OMPD_masked_taskloop || DKind == OMPD_masked_taskloop_simd ||
-         DKind == OMPD_parallel_masked_taskloop || DKind == OMPD_distribute ||
-         DKind == OMPD_parallel_masked_taskloop_simd ||
-         DKind == OMPD_target_parallel_for ||
-         DKind == OMPD_distribute_parallel_for ||
-         DKind == OMPD_distribute_parallel_for_simd ||
-         DKind == OMPD_distribute_simd ||
-         DKind == OMPD_target_parallel_for_simd || DKind == OMPD_target_simd ||
-         DKind == OMPD_teams_distribute ||
-         DKind == OMPD_teams_distribute_simd ||
-         DKind == OMPD_teams_distribute_parallel_for_simd ||
-         DKind == OMPD_teams_distribute_parallel_for ||
-         DKind == OMPD_target_teams_distribute ||
-         DKind == OMPD_target_teams_distribute_parallel_for ||
-         DKind == OMPD_target_teams_distribute_parallel_for_simd ||
-         DKind == OMPD_target_teams_distribute_simd || DKind == OMPD_tile ||
-         DKind == OMPD_unroll || DKind == OMPD_loop ||
-         DKind == OMPD_teams_loop || DKind == OMPD_target_teams_loop ||
-         DKind == OMPD_parallel_loop || DKind == OMPD_target_parallel_loop;
+  return getDirectiveAssociation(DKind) == Association::Loop;
 }
 
 bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) {
@@ -619,44 +595,20 @@ bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) {
 }
 
 bool clang::isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind) {
-  return DKind == OMPD_taskloop || DKind == OMPD_taskloop_simd ||
-         DKind == OMPD_master_taskloop || DKind == OMPD_master_taskloop_simd ||
-         DKind == OMPD_parallel_master_taskloop ||
-         DKind == OMPD_masked_taskloop || DKind == OMPD_masked_taskloop_simd ||
-         DKind == OMPD_parallel_masked_taskloop ||
-         DKind == OMPD_parallel_masked_taskloop_simd ||
-         DKind == OMPD_parallel_master_taskloop_simd;
+  return DKind == OMPD_taskloop ||
+         llvm::is_contained(getLeafConstructs(DKind), OMPD_taskloop);
 }
 
 bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) {
-  return DKind == OMPD_parallel || DKind == OMPD_parallel_for ||
-         DKind == OMPD_parallel_for_simd || DKind == OMPD_parallel_sections ||
-         DKind == OMPD_target_parallel || DKind == OMPD_target_parallel_for ||
-         DKind == OMPD_distribute_parallel_for ||
-         DKind == OMPD_distribute_parallel_for_simd ||
-         DKind == OMPD_target_parallel_for_simd ||
-         DKind == OMPD_teams_distribute_parallel_for ||
-         DKind == OMPD_teams_distribute_parallel_for_simd ||
-         DKind == OMPD_target_teams_distribute_parallel_for ||
-         DKind == OMPD_target_teams_distribute_parallel_for_simd ||
-         DKind == OMPD_parallel_master || DKind == OMPD_parallel_masked ||
-         DKind == OMPD_parallel_master_taskloop ||
-         DKind == OMPD_parallel_master_taskloop_simd ||
-         DKind == OMPD_parallel_masked_taskloop ||
-         DKind == OMPD_parallel_masked_taskloop_simd ||
-         DKind == OMPD_parallel_loop || DKind == OMPD_target_parallel_loop ||
-         DKind == OMPD_teams_loop;
+  if (DKind == OMPD_teams_loop)
+    return true;
+  return DKind == OMPD_parallel ||
+         llvm::is_contained(getLeafConstructs(DKind), OMPD_parallel);
 }
 
 bool clang::isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind) {
-  return DKind == OMPD_target || DKind == OMPD_target_parallel ||
-         DKind == OMPD_target_parallel_for ||
-         DKind == OMPD_target_parallel_for_simd || DKind == OMPD_target_simd ||
-         DKind == OMPD_target_teams || DKind == OMPD_target_teams_distribute ||
-         DKind == OMPD_target_teams_distribute_parallel_for ||
-         DKind == OMPD_target_teams_distribute_parallel_for_simd ||
-         DKind == OMPD_target_teams_distribute_simd ||
-         DKind == OMPD_target_teams_loop || DKind == OMPD_target_parallel_loop;
+  return DKind == OMPD_target ||
+         llvm::is_contained(getLeafConstructs(DKind), OMPD_target);
 }
 
 bool clang::isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind) {
@@ -665,60 +617,45 @@ bool clang::isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind) {
 }
 
 bool clang::isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind) {
-  return DKind == OMPD_teams || DKind == OMPD_teams_distribute ||
-         DKind == OMPD_teams_distribute_simd ||
-         DKind == OMPD_teams_distribute_parallel_for_simd ||
-         DKind == OMPD_teams_distribute_parallel_for ||
-         DKind == OMPD_teams_loop;
+  if (DKind == OMPD_teams)
+    return true;
+  ArrayRef Leaves = getLeafConstructs(DKind);
+  return !Leaves.empty() && Leaves.front() == OMPD_teams;
 }
 
 bool clang::isOpenMPTeamsDirective(OpenMPDirectiveKind DKind) {
-  return isOpenMPNestingTeamsDirective(DKind) || DKind == OMPD_target_teams ||
-         DKind == OMPD_target_teams_distribute ||
-         DKind == OMPD_target_teams_distribute_parallel_for ||
-         DKind == OMPD_target_teams_distribute_parallel_for_simd ||
-         DKind == OMPD_target_teams_distribute_simd ||
-         DKind == OMPD_target_teams_loop;
+  return DKind == OMPD_teams ||
+         llvm::is_contained(getLeafConstructs(DKind), OMPD_teams);
 }
 
 bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) {
-  return DKind == OMPD_simd || DKind == OMPD_for_simd ||
-         DKind == OMPD_parallel_for_simd || DKind == OMPD_taskloop_simd ||
-         DKind == OMPD_master_taskloop_simd ||
-         DKind == OMPD_masked_taskloop_simd ||
-         DKind == OMPD_parallel_master_taskloop_simd ||
-         DKind == OMPD_parallel_masked_taskloop_simd ||
-         DKind == OMPD_distribute_parallel_for_simd ||
-         DKind == OMPD_distribute_simd || DKind == OMPD_target_simd ||
-         DKind == OMPD_teams_distribute_simd ||
-         DKind == OMPD_teams_distribute_parallel_for_simd ||
-         DKind == OMPD_target_teams_distribute_parallel_for_simd ||
-         DKind == OMPD_target_teams_distribute_simd ||
-         DKind == OMPD_target_parallel_for_simd;
+  // Avoid OMPD_declare_simd
+  if (getDirectiveAssociation(DKind) != Association::Loop)
+    return false;
+  // Formally, OMPD_end_do_simd also has a loop association, but
+  // it's a Fortran-specific directive.
+
+  return DKind == OMPD_simd ||
+         llvm::is_contained(getLeafConstructs(DKind), OMPD_simd);
 }
 
 bool clang::isOpenMPNestingDistributeDirective(OpenMPDirectiveKind Kind) {
-  return Kind == OMPD_distribute || Kind == OMPD_distribute_parallel_for ||
-         Kind == OMPD_distribute_parallel_for_simd ||
-         Kind == OMPD_distribute_simd;
-  // TODO add next directives.
+  if (Kind == OMPD_distribute)
+    return true;
+  ArrayRef Leaves = getLeafConstructs(Kind);
+  return !Leaves.empty() && Leaves.front() == OMPD_distribute;
 }
 
 bool clang::isOpenMPDistributeDirective(OpenMPDirectiveKind Kind) {
-  return isOpenMPNestingDistributeDirective(Kind) ||
-         Kind == OMPD_teams_distribute || Kind == OMPD_teams_distribute_simd ||
-         Kind == OMPD_teams_distribute_parallel_for_simd ||
-         Kind == OMPD_teams_distribute_parallel_for ||
-         Kind == OMPD_target_teams_distribute ||
-         Kind == OMPD_target_teams_distribute_parallel_for ||
-         Kind == OMPD_target_teams_distribute_parallel_for_simd ||
-         Kind == OMPD_target_teams_distribute_simd;
+  return Kind == OMPD_distribute ||
+         llvm::is_contained(getLeafConstructs(Kind), OMPD_distribute);
 }
 
 bool clang::isOpenMPGenericLoopDirective(OpenMPDirectiveKind Kind) {
-  return Kind == OMPD_loop || Kind == OMPD_teams_loop ||
-         Kind == OMPD_target_teams_loop || Kind == OMPD_parallel_loop ||
-         Kind == OMPD_target_parallel_loop;
+  if (Kind == OMPD_loop)
+    return true;
+  ArrayRef Leaves = getLeafConstructs(Kind);
+  return !Leaves.empty() && Leaves.back() == OMPD_loop;
 }
 
 bool clang::isOpenMPPrivate(OpenMPClauseKind Kind) {
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 056f790d41853d1480a650e5423caac066978421..82b30b8d815629d367a9282abf1b4b3be99cce63 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -76,6 +76,7 @@
 #include "llvm/Transforms/Instrumentation/MemProfiler.h"
 #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
 #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
+#include "llvm/Transforms/Instrumentation/RemoveTrapsPass.h"
 #include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
 #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
 #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
@@ -83,6 +84,7 @@
 #include "llvm/Transforms/Scalar/EarlyCSE.h"
 #include "llvm/Transforms/Scalar/GVN.h"
 #include "llvm/Transforms/Scalar/JumpThreading.h"
+#include "llvm/Transforms/Scalar/SimplifyCFG.h"
 #include "llvm/Transforms/Utils/Debugify.h"
 #include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
@@ -98,6 +100,10 @@ using namespace llvm;
 namespace llvm {
 extern cl::opt PrintPipelinePasses;
 
+cl::opt ClRemoveTraps("clang-remove-traps", cl::Optional,
+                            cl::desc("Insert remove-traps pass."),
+                            cl::init(false));
+
 // Experiment to move sanitizers earlier.
 static cl::opt ClSanitizeOnOptimizerEarlyEP(
     "sanitizer-early-opt-ep", cl::Optional,
@@ -356,8 +362,6 @@ static bool initTargetOptions(DiagnosticsEngine &Diags,
       llvm::TargetMachine::parseBinutilsVersion(CodeGenOpts.BinutilsVersion);
   Options.UseInitArray = CodeGenOpts.UseInitArray;
   Options.DisableIntegratedAS = CodeGenOpts.DisableIntegratedAS;
-  Options.CompressDebugSections = CodeGenOpts.getCompressDebugSections();
-  Options.RelaxELFRelocations = CodeGenOpts.RelaxELFRelocations;
 
   // Set EABI version.
   Options.EABIVersion = TargetOpts.EABIVersion;
@@ -460,6 +464,9 @@ static bool initTargetOptions(DiagnosticsEngine &Diags,
   Options.MCOptions.AsmVerbose = CodeGenOpts.AsmVerbose;
   Options.MCOptions.Dwarf64 = CodeGenOpts.Dwarf64;
   Options.MCOptions.PreserveAsmComments = CodeGenOpts.PreserveAsmComments;
+  Options.MCOptions.X86RelaxRelocations = CodeGenOpts.RelaxELFRelocations;
+  Options.MCOptions.CompressDebugSections =
+      CodeGenOpts.getCompressDebugSections();
   Options.MCOptions.ABIName = TargetOpts.ABI;
   for (const auto &Entry : HSOpts.UserEntries)
     if (!Entry.IsFramework &&
@@ -743,6 +750,21 @@ static void addSanitizers(const Triple &TargetTriple,
     // LastEP does not need GlobalsAA.
     PB.registerOptimizerLastEPCallback(SanitizersCallback);
   }
+
+  if (ClRemoveTraps) {
+    // We can optimize after inliner, and PGO profile matching. The hook below
+    // is called at the end `buildFunctionSimplificationPipeline`, which called
+    // from `buildInlinerPipeline`, which called after profile matching.
+    PB.registerScalarOptimizerLateEPCallback(
+        [](FunctionPassManager &FPM, OptimizationLevel Level) {
+          // RemoveTrapsPass expects trap blocks preceded by conditional
+          // branches, which usually is not the case without SimplifyCFG.
+          // TODO: Remove `SimplifyCFGPass` after switching to dedicated
+          // intrinsic.
+          FPM.addPass(SimplifyCFGPass());
+          FPM.addPass(RemoveTrapsPass());
+        });
+  }
 }
 
 void EmitAssemblyHelper::RunOptimizationPipeline(
diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index a8d846b4f6a592b05cb5551fad6e36aa473273ba..fb03d013e8afc7ba7c9e952eadabd44ae9e005a9 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -194,12 +194,14 @@ namespace {
     RValue convertAtomicTempToRValue(Address addr, AggValueSlot resultSlot,
                                      SourceLocation loc, bool AsValue) const;
 
-    /// Converts a rvalue to integer value.
-    llvm::Value *convertRValueToInt(RValue RVal) const;
+    llvm::Value *getScalarRValValueOrNull(RValue RVal) const;
 
-    RValue ConvertIntToValueOrAtomic(llvm::Value *IntVal,
-                                     AggValueSlot ResultSlot,
-                                     SourceLocation Loc, bool AsValue) const;
+    /// Converts an rvalue to integer value if needed.
+    llvm::Value *convertRValueToInt(RValue RVal, bool CastFP = true) const;
+
+    RValue ConvertToValueOrAtomic(llvm::Value *IntVal, AggValueSlot ResultSlot,
+                                  SourceLocation Loc, bool AsValue,
+                                  bool CastFP = true) const;
 
     /// Copy an atomic r-value into atomic-layout memory.
     void emitCopyIntoMemory(RValue rvalue) const;
@@ -261,7 +263,8 @@ namespace {
     void EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
                                llvm::AtomicOrdering AO, bool IsVolatile);
     /// Emits atomic load as LLVM instruction.
-    llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile);
+    llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile,
+                                  bool CastFP = true);
     /// Emits atomic compare-and-exchange op as a libcall.
     llvm::Value *EmitAtomicCompareExchangeLibcall(
         llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr,
@@ -1396,12 +1399,13 @@ RValue AtomicInfo::convertAtomicTempToRValue(Address addr,
       LVal.getBaseInfo(), TBAAAccessInfo()));
 }
 
-RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal,
-                                             AggValueSlot ResultSlot,
-                                             SourceLocation Loc,
-                                             bool AsValue) const {
+RValue AtomicInfo::ConvertToValueOrAtomic(llvm::Value *Val,
+                                          AggValueSlot ResultSlot,
+                                          SourceLocation Loc, bool AsValue,
+                                          bool CastFP) const {
   // Try not to in some easy cases.
-  assert(IntVal->getType()->isIntegerTy() && "Expected integer value");
+  assert((Val->getType()->isIntegerTy() || Val->getType()->isIEEELikeFPTy()) &&
+         "Expected integer or floating point value");
   if (getEvaluationKind() == TEK_Scalar &&
       (((!LVal.isBitField() ||
          LVal.getBitFieldInfo().Size == ValueSizeInBits) &&
@@ -1410,13 +1414,14 @@ RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal,
     auto *ValTy = AsValue
                       ? CGF.ConvertTypeForMem(ValueTy)
                       : getAtomicAddress().getElementType();
-    if (ValTy->isIntegerTy()) {
-      assert(IntVal->getType() == ValTy && "Different integer types.");
-      return RValue::get(CGF.EmitFromMemory(IntVal, ValueTy));
+    if (ValTy->isIntegerTy() || (!CastFP && ValTy->isIEEELikeFPTy())) {
+      assert((!ValTy->isIntegerTy() || Val->getType() == ValTy) &&
+             "Different integer types.");
+      return RValue::get(CGF.EmitFromMemory(Val, ValueTy));
     } else if (ValTy->isPointerTy())
-      return RValue::get(CGF.Builder.CreateIntToPtr(IntVal, ValTy));
-    else if (llvm::CastInst::isBitCastable(IntVal->getType(), ValTy))
-      return RValue::get(CGF.Builder.CreateBitCast(IntVal, ValTy));
+      return RValue::get(CGF.Builder.CreateIntToPtr(Val, ValTy));
+    else if (llvm::CastInst::isBitCastable(Val->getType(), ValTy))
+      return RValue::get(CGF.Builder.CreateBitCast(Val, ValTy));
   }
 
   // Create a temporary.  This needs to be big enough to hold the
@@ -1433,8 +1438,7 @@ RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal,
 
   // Slam the integer into the temporary.
   Address CastTemp = castToAtomicIntPointer(Temp);
-  CGF.Builder.CreateStore(IntVal, CastTemp)
-      ->setVolatile(TempIsVolatile);
+  CGF.Builder.CreateStore(Val, CastTemp)->setVolatile(TempIsVolatile);
 
   return convertAtomicTempToRValue(Temp, ResultSlot, Loc, AsValue);
 }
@@ -1453,9 +1457,11 @@ void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
 }
 
 llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO,
-                                          bool IsVolatile) {
+                                          bool IsVolatile, bool CastFP) {
   // Okay, we're doing this natively.
-  Address Addr = getAtomicAddressAsAtomicIntPointer();
+  Address Addr = getAtomicAddress();
+  if (!(Addr.getElementType()->isIEEELikeFPTy() && !CastFP))
+    Addr = castToAtomicIntPointer(Addr);
   llvm::LoadInst *Load = CGF.Builder.CreateLoad(Addr, "atomic-load");
   Load->setAtomic(AO);
 
@@ -1515,7 +1521,7 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,
   }
 
   // Okay, we're doing this natively.
-  auto *Load = EmitAtomicLoadOp(AO, IsVolatile);
+  auto *Load = EmitAtomicLoadOp(AO, IsVolatile, /*CastFP=*/false);
 
   // If we're ignoring an aggregate return, don't do anything.
   if (getEvaluationKind() == TEK_Aggregate && ResultSlot.isIgnored())
@@ -1523,7 +1529,8 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,
 
   // Okay, turn that back into the original value or atomic (for non-simple
   // lvalues) type.
-  return ConvertIntToValueOrAtomic(Load, ResultSlot, Loc, AsValue);
+  return ConvertToValueOrAtomic(Load, ResultSlot, Loc, AsValue,
+                                /*CastFP=*/false);
 }
 
 /// Emit a load from an l-value of atomic type.  Note that the r-value
@@ -1586,12 +1593,18 @@ Address AtomicInfo::materializeRValue(RValue rvalue) const {
   return TempLV.getAddress(CGF);
 }
 
-llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal) const {
+llvm::Value *AtomicInfo::getScalarRValValueOrNull(RValue RVal) const {
+  if (RVal.isScalar() && (!hasPadding() || !LVal.isSimple()))
+    return RVal.getScalarVal();
+  return nullptr;
+}
+
+llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal, bool CastFP) const {
   // If we've got a scalar value of the right size, try to avoid going
-  // through memory.
-  if (RVal.isScalar() && (!hasPadding() || !LVal.isSimple())) {
-    llvm::Value *Value = RVal.getScalarVal();
-    if (isa(Value->getType()))
+  // through memory. Floats get casted if needed by AtomicExpandPass.
+  if (llvm::Value *Value = getScalarRValValueOrNull(RVal)) {
+    if (isa(Value->getType()) ||
+        (!CastFP && Value->getType()->isIEEELikeFPTy()))
       return CGF.EmitToMemory(Value, ValueTy);
     else {
       llvm::IntegerType *InputIntTy = llvm::IntegerType::get(
@@ -1677,8 +1690,8 @@ std::pair AtomicInfo::EmitAtomicCompareExchange(
   auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success,
                                          Failure, IsWeak);
   return std::make_pair(
-      ConvertIntToValueOrAtomic(Res.first, AggValueSlot::ignored(),
-                                SourceLocation(), /*AsValue=*/false),
+      ConvertToValueOrAtomic(Res.first, AggValueSlot::ignored(),
+                             SourceLocation(), /*AsValue=*/false),
       Res.second);
 }
 
@@ -1787,8 +1800,8 @@ void AtomicInfo::EmitAtomicUpdateOp(
       requiresMemSetZero(getAtomicAddress().getElementType())) {
     CGF.Builder.CreateStore(PHI, NewAtomicIntAddr);
   }
-  auto OldRVal = ConvertIntToValueOrAtomic(PHI, AggValueSlot::ignored(),
-                                           SourceLocation(), /*AsValue=*/false);
+  auto OldRVal = ConvertToValueOrAtomic(PHI, AggValueSlot::ignored(),
+                                        SourceLocation(), /*AsValue=*/false);
   EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, NewAtomicAddr);
   auto *DesiredVal = CGF.Builder.CreateLoad(NewAtomicIntAddr);
   // Try to write new value using cmpxchg operation.
@@ -1953,13 +1966,22 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,
     }
 
     // Okay, we're doing this natively.
-    llvm::Value *intValue = atomics.convertRValueToInt(rvalue);
+    llvm::Value *ValToStore =
+        atomics.convertRValueToInt(rvalue, /*CastFP=*/false);
 
     // Do the atomic store.
-    Address addr = atomics.castToAtomicIntPointer(atomics.getAtomicAddress());
-    intValue = Builder.CreateIntCast(
-        intValue, addr.getElementType(), /*isSigned=*/false);
-    llvm::StoreInst *store = Builder.CreateStore(intValue, addr);
+    Address Addr = atomics.getAtomicAddress();
+    bool ShouldCastToInt = true;
+    if (llvm::Value *Value = atomics.getScalarRValValueOrNull(rvalue))
+      if (isa(Value->getType()) ||
+          Value->getType()->isIEEELikeFPTy())
+        ShouldCastToInt = false;
+    if (ShouldCastToInt) {
+      Addr = atomics.castToAtomicIntPointer(Addr);
+      ValToStore = Builder.CreateIntCast(ValToStore, Addr.getElementType(),
+                                         /*isSigned=*/false);
+    }
+    llvm::StoreInst *store = Builder.CreateStore(ValToStore, Addr);
 
     if (AO == llvm::AtomicOrdering::Acquire)
       AO = llvm::AtomicOrdering::Monotonic;
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 9ee51ca7142c77fd9b9a968029764513e7691ddd..93ab465079777bf9ad70c2bae38a0e4b4d1a39fe 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5460,7 +5460,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
   }
 
   // OpenCL v2.0, s6.13.17 - Enqueue kernel function.
-  // It contains four different overload formats specified in Table 6.13.17.1.
+  // Table 6.13.17.1 specifies four overload forms of enqueue_kernel.
+  // The code below expands the builtin call to a call to one of the following
+  // functions that an OpenCL runtime library will have to provide:
+  //   __enqueue_kernel_basic
+  //   __enqueue_kernel_varargs
+  //   __enqueue_kernel_basic_events
+  //   __enqueue_kernel_events_varargs
   case Builtin::BIenqueue_kernel: {
     StringRef Name; // Generated function call name
     unsigned NumArgs = E->getNumArgs();
@@ -17963,6 +17969,12 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
     return nullptr;
 
   switch (BuiltinID) {
+  case Builtin::BI__builtin_hlsl_elementwise_any: {
+    Value *Op0 = EmitScalarExpr(E->getArg(0));
+    return Builder.CreateIntrinsic(
+        /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
+        Intrinsic::dx_any, ArrayRef{Op0}, nullptr, "dx.any");
+  }
   case Builtin::BI__builtin_hlsl_dot: {
     Value *Op0 = EmitScalarExpr(E->getArg(0));
     Value *Op1 = EmitScalarExpr(E->getArg(1));
@@ -17996,7 +18008,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
            "Dot product requires vectors to be of the same size.");
 
     return Builder.CreateIntrinsic(
-        /*ReturnType*/ T0->getScalarType(), Intrinsic::dx_dot,
+        /*ReturnType=*/T0->getScalarType(), Intrinsic::dx_dot,
         ArrayRef{Op0, Op1}, nullptr, "dx.dot");
   } break;
   case Builtin::BI__builtin_hlsl_lerp: {
@@ -18033,7 +18045,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
            XVecTy->getElementType() == SVecTy->getElementType() &&
            "Lerp requires float vectors to be of the same type.");
     return Builder.CreateIntrinsic(
-        /*ReturnType*/ Xty, Intrinsic::dx_lerp, ArrayRef{X, Y, S},
+        /*ReturnType=*/Xty, Intrinsic::dx_lerp, ArrayRef{X, Y, S},
         nullptr, "dx.lerp");
   }
   case Builtin::BI__builtin_hlsl_elementwise_frac: {
@@ -18041,9 +18053,36 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
     if (!E->getArg(0)->getType()->hasFloatingRepresentation())
       llvm_unreachable("frac operand must have a float representation");
     return Builder.CreateIntrinsic(
-        /*ReturnType*/ Op0->getType(), Intrinsic::dx_frac,
+        /*ReturnType=*/Op0->getType(), Intrinsic::dx_frac,
         ArrayRef{Op0}, nullptr, "dx.frac");
   }
+  case Builtin::BI__builtin_hlsl_mad: {
+    Value *M = EmitScalarExpr(E->getArg(0));
+    Value *A = EmitScalarExpr(E->getArg(1));
+    Value *B = EmitScalarExpr(E->getArg(2));
+    if (E->getArg(0)->getType()->hasFloatingRepresentation()) {
+      return Builder.CreateIntrinsic(
+          /*ReturnType*/ M->getType(), Intrinsic::fmuladd,
+          ArrayRef{M, A, B}, nullptr, "dx.fmad");
+    }
+    if (E->getArg(0)->getType()->hasSignedIntegerRepresentation()) {
+      return Builder.CreateIntrinsic(
+          /*ReturnType*/ M->getType(), Intrinsic::dx_imad,
+          ArrayRef{M, A, B}, nullptr, "dx.imad");
+    }
+    assert(E->getArg(0)->getType()->hasUnsignedIntegerRepresentation());
+    return Builder.CreateIntrinsic(
+        /*ReturnType=*/M->getType(), Intrinsic::dx_umad,
+        ArrayRef{M, A, B}, nullptr, "dx.umad");
+  }
+  case Builtin::BI__builtin_hlsl_elementwise_rcp: {
+    Value *Op0 = EmitScalarExpr(E->getArg(0));
+    if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+      llvm_unreachable("rcp operand must have a float representation");
+    return Builder.CreateIntrinsic(
+        /*ReturnType=*/Op0->getType(), Intrinsic::dx_rcp,
+        ArrayRef{Op0}, nullptr, "dx.rcp");
+  }
   }
   return nullptr;
 }
@@ -18406,6 +18445,17 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
         CGM.getIntrinsic(Intrinsic::amdgcn_global_load_tr, {ArgTy});
     return Builder.CreateCall(F, {Addr});
   }
+  case AMDGPU::BI__builtin_amdgcn_get_fpenv: {
+    Function *F = CGM.getIntrinsic(Intrinsic::get_fpenv,
+                                   {llvm::Type::getInt64Ty(getLLVMContext())});
+    return Builder.CreateCall(F);
+  }
+  case AMDGPU::BI__builtin_amdgcn_set_fpenv: {
+    Function *F = CGM.getIntrinsic(Intrinsic::set_fpenv,
+                                   {llvm::Type::getInt64Ty(getLLVMContext())});
+    llvm::Value *Env = EmitScalarExpr(E->getArg(0));
+    return Builder.CreateCall(F, {Env});
+  }
   case AMDGPU::BI__builtin_amdgcn_read_exec:
     return EmitAMDGCNBallotForExec(*this, E, Int64Ty, Int64Ty, false);
   case AMDGPU::BI__builtin_amdgcn_read_exec_lo:
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 13f68237b464d60e48c232feab1d02beb07aeb91..a28d7888715d858430ff9893a80a4d86c23f9dfd 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1796,14 +1796,14 @@ static void AddAttributesFromFunctionProtoType(ASTContext &Ctx,
     FuncAttrs.addAttribute("aarch64_inout_zt0");
 }
 
-static void AddAttributesFromAssumes(llvm::AttrBuilder &FuncAttrs,
-                                     const Decl *Callee) {
+static void AddAttributesFromOMPAssumes(llvm::AttrBuilder &FuncAttrs,
+                                        const Decl *Callee) {
   if (!Callee)
     return;
 
   SmallVector Attrs;
 
-  for (const AssumptionAttr *AA : Callee->specific_attrs())
+  for (const OMPAssumeAttr *AA : Callee->specific_attrs())
     AA->getAssumption().split(Attrs, ",");
 
   if (!Attrs.empty())
@@ -2344,7 +2344,7 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
 
   // Attach assumption attributes to the declaration. If this is a call
   // site, attach assumptions from the caller to the call as well.
-  AddAttributesFromAssumes(FuncAttrs, TargetDecl);
+  AddAttributesFromOMPAssumes(FuncAttrs, TargetDecl);
 
   bool HasOptnone = false;
   // The NoBuiltinAttr attached to the target FunctionDecl.
diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp
index 888d30bfb3e1d6a45f1d9e57ba84257dd7f16cfd..b7142ec08af986d16656fdb7e10aed35b98912d1 100644
--- a/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/clang/lib/CodeGen/CGCoroutine.cpp
@@ -141,7 +141,7 @@ static bool FunctionCanThrow(const FunctionDecl *D) {
          Proto->canThrow() != CT_Cannot;
 }
 
-static bool ResumeStmtCanThrow(const Stmt *S) {
+static bool StmtCanThrow(const Stmt *S) {
   if (const auto *CE = dyn_cast(S)) {
     const auto *Callee = CE->getDirectCallee();
     if (!Callee)
@@ -167,7 +167,7 @@ static bool ResumeStmtCanThrow(const Stmt *S) {
   }
 
   for (const auto *child : S->children())
-    if (ResumeStmtCanThrow(child))
+    if (StmtCanThrow(child))
       return true;
 
   return false;
@@ -178,18 +178,31 @@ static bool ResumeStmtCanThrow(const Stmt *S) {
 //   auto && x = CommonExpr();
 //   if (!x.await_ready()) {
 //      llvm_coro_save();
-//      x.await_suspend(...);     (*)
-//      llvm_coro_suspend(); (**)
+//      llvm_coro_await_suspend(&x, frame, wrapper) (*) (**)
+//      llvm_coro_suspend(); (***)
 //   }
 //   x.await_resume();
 //
 // where the result of the entire expression is the result of x.await_resume()
 //
-//   (*) If x.await_suspend return type is bool, it allows to veto a suspend:
+//   (*) llvm_coro_await_suspend_{void, bool, handle} is lowered to
+//      wrapper(&x, frame) when it's certain not to interfere with
+//      coroutine transform. await_suspend expression is
+//      asynchronous to the coroutine body and not all analyses
+//      and transformations can handle it correctly at the moment.
+//
+//      Wrapper function encapsulates x.await_suspend(...) call and looks like:
+//
+//      auto __await_suspend_wrapper(auto& awaiter, void* frame) {
+//        std::coroutine_handle<> handle(frame);
+//        return awaiter.await_suspend(handle);
+//      }
+//
+//  (**) If x.await_suspend return type is bool, it allows to veto a suspend:
 //      if (x.await_suspend(...))
 //        llvm_coro_suspend();
 //
-//  (**) llvm_coro_suspend() encodes three possible continuations as
+//  (***) llvm_coro_suspend() encodes three possible continuations as
 //       a switch instruction:
 //
 //  %where-to = call i8 @llvm.coro.suspend(...)
@@ -212,9 +225,10 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co
                                     bool ignoreResult, bool forLValue) {
   auto *E = S.getCommonExpr();
 
-  auto Binder =
+  auto CommonBinder =
       CodeGenFunction::OpaqueValueMappingData::bind(CGF, S.getOpaqueValue(), E);
-  auto UnbindOnExit = llvm::make_scope_exit([&] { Binder.unbind(CGF); });
+  auto UnbindCommonOnExit =
+      llvm::make_scope_exit([&] { CommonBinder.unbind(CGF); });
 
   auto Prefix = buildSuspendPrefixStr(Coro, Kind);
   BasicBlock *ReadyBlock = CGF.createBasicBlock(Prefix + Twine(".ready"));
@@ -232,16 +246,73 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co
   auto *NullPtr = llvm::ConstantPointerNull::get(CGF.CGM.Int8PtrTy);
   auto *SaveCall = Builder.CreateCall(CoroSave, {NullPtr});
 
+  auto SuspendWrapper = CodeGenFunction(CGF.CGM).generateAwaitSuspendWrapper(
+      CGF.CurFn->getName(), Prefix, S);
+
   CGF.CurCoro.InSuspendBlock = true;
-  auto *SuspendRet = CGF.EmitScalarExpr(S.getSuspendExpr());
+
+  assert(CGF.CurCoro.Data && CGF.CurCoro.Data->CoroBegin &&
+         "expected to be called in coroutine context");
+
+  SmallVector SuspendIntrinsicCallArgs;
+  SuspendIntrinsicCallArgs.push_back(
+      CGF.getOrCreateOpaqueLValueMapping(S.getOpaqueValue()).getPointer(CGF));
+
+  SuspendIntrinsicCallArgs.push_back(CGF.CurCoro.Data->CoroBegin);
+  SuspendIntrinsicCallArgs.push_back(SuspendWrapper);
+
+  const auto SuspendReturnType = S.getSuspendReturnType();
+  llvm::Intrinsic::ID AwaitSuspendIID;
+
+  switch (SuspendReturnType) {
+  case CoroutineSuspendExpr::SuspendReturnType::SuspendVoid:
+    AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_void;
+    break;
+  case CoroutineSuspendExpr::SuspendReturnType::SuspendBool:
+    AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_bool;
+    break;
+  case CoroutineSuspendExpr::SuspendReturnType::SuspendHandle:
+    AwaitSuspendIID = llvm::Intrinsic::coro_await_suspend_handle;
+    break;
+  }
+
+  llvm::Function *AwaitSuspendIntrinsic = CGF.CGM.getIntrinsic(AwaitSuspendIID);
+
+  const auto AwaitSuspendCanThrow = StmtCanThrow(S.getSuspendExpr());
+
+  llvm::CallBase *SuspendRet = nullptr;
+  // FIXME: add call attributes?
+  if (AwaitSuspendCanThrow)
+    SuspendRet =
+        CGF.EmitCallOrInvoke(AwaitSuspendIntrinsic, SuspendIntrinsicCallArgs);
+  else
+    SuspendRet = CGF.EmitNounwindRuntimeCall(AwaitSuspendIntrinsic,
+                                             SuspendIntrinsicCallArgs);
+
+  assert(SuspendRet);
   CGF.CurCoro.InSuspendBlock = false;
 
-  if (SuspendRet != nullptr && SuspendRet->getType()->isIntegerTy(1)) {
+  switch (SuspendReturnType) {
+  case CoroutineSuspendExpr::SuspendReturnType::SuspendVoid:
+    assert(SuspendRet->getType()->isVoidTy());
+    break;
+  case CoroutineSuspendExpr::SuspendReturnType::SuspendBool: {
+    assert(SuspendRet->getType()->isIntegerTy());
+
     // Veto suspension if requested by bool returning await_suspend.
     BasicBlock *RealSuspendBlock =
         CGF.createBasicBlock(Prefix + Twine(".suspend.bool"));
     CGF.Builder.CreateCondBr(SuspendRet, RealSuspendBlock, ReadyBlock);
     CGF.EmitBlock(RealSuspendBlock);
+    break;
+  }
+  case CoroutineSuspendExpr::SuspendReturnType::SuspendHandle: {
+    assert(SuspendRet->getType()->isPointerTy());
+
+    auto ResumeIntrinsic = CGF.CGM.getIntrinsic(llvm::Intrinsic::coro_resume);
+    Builder.CreateCall(ResumeIntrinsic, SuspendRet);
+    break;
+  }
   }
 
   // Emit the suspend point.
@@ -267,7 +338,7 @@ static LValueOrRValue emitSuspendExpression(CodeGenFunction &CGF, CGCoroData &Co
   // is marked as 'noexcept', we avoid generating this additional IR.
   CXXTryStmt *TryStmt = nullptr;
   if (Coro.ExceptionHandler && Kind == AwaitKind::Init &&
-      ResumeStmtCanThrow(S.getResumeExpr())) {
+      StmtCanThrow(S.getResumeExpr())) {
     Coro.ResumeEHVar =
         CGF.CreateTempAlloca(Builder.getInt1Ty(), Prefix + Twine("resume.eh"));
     Builder.CreateFlagStore(true, Coro.ResumeEHVar);
@@ -338,6 +409,69 @@ static QualType getCoroutineSuspendExprReturnType(const ASTContext &Ctx,
 }
 #endif
 
+llvm::Function *
+CodeGenFunction::generateAwaitSuspendWrapper(Twine const &CoroName,
+                                             Twine const &SuspendPointName,
+                                             CoroutineSuspendExpr const &S) {
+  std::string FuncName = "__await_suspend_wrapper_";
+  FuncName += CoroName.str();
+  FuncName += '_';
+  FuncName += SuspendPointName.str();
+
+  ASTContext &C = getContext();
+
+  FunctionArgList args;
+
+  ImplicitParamDecl AwaiterDecl(C, C.VoidPtrTy, ImplicitParamKind::Other);
+  ImplicitParamDecl FrameDecl(C, C.VoidPtrTy, ImplicitParamKind::Other);
+  QualType ReturnTy = S.getSuspendExpr()->getType();
+
+  args.push_back(&AwaiterDecl);
+  args.push_back(&FrameDecl);
+
+  const CGFunctionInfo &FI =
+      CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
+
+  llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
+
+  llvm::Function *Fn = llvm::Function::Create(
+      LTy, llvm::GlobalValue::PrivateLinkage, FuncName, &CGM.getModule());
+
+  Fn->addParamAttr(0, llvm::Attribute::AttrKind::NonNull);
+  Fn->addParamAttr(0, llvm::Attribute::AttrKind::NoUndef);
+
+  Fn->addParamAttr(1, llvm::Attribute::AttrKind::NoUndef);
+
+  Fn->setMustProgress();
+  Fn->addFnAttr(llvm::Attribute::AttrKind::AlwaysInline);
+
+  StartFunction(GlobalDecl(), ReturnTy, Fn, FI, args);
+
+  // FIXME: add TBAA metadata to the loads
+  llvm::Value *AwaiterPtr = Builder.CreateLoad(GetAddrOfLocalVar(&AwaiterDecl));
+  auto AwaiterLValue =
+      MakeNaturalAlignAddrLValue(AwaiterPtr, AwaiterDecl.getType());
+
+  CurAwaitSuspendWrapper.FramePtr =
+      Builder.CreateLoad(GetAddrOfLocalVar(&FrameDecl));
+
+  auto AwaiterBinder = CodeGenFunction::OpaqueValueMappingData::bind(
+      *this, S.getOpaqueValue(), AwaiterLValue);
+
+  auto *SuspendRet = EmitScalarExpr(S.getSuspendExpr());
+
+  auto UnbindCommonOnExit =
+      llvm::make_scope_exit([&] { AwaiterBinder.unbind(*this); });
+  if (SuspendRet != nullptr) {
+    Fn->addRetAttr(llvm::Attribute::AttrKind::NoUndef);
+    Builder.CreateStore(SuspendRet, ReturnValue);
+  }
+
+  CurAwaitSuspendWrapper.FramePtr = nullptr;
+  FinishFunction();
+  return Fn;
+}
+
 LValue
 CodeGenFunction::EmitCoawaitLValue(const CoawaitExpr *E) {
   assert(getCoroutineSuspendExprReturnType(getContext(), E)->isReferenceType() &&
@@ -834,6 +968,11 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const CallExpr *E,
     if (CurCoro.Data && CurCoro.Data->CoroBegin) {
       return RValue::get(CurCoro.Data->CoroBegin);
     }
+
+    if (CurAwaitSuspendWrapper.FramePtr) {
+      return RValue::get(CurAwaitSuspendWrapper.FramePtr);
+    }
+
     CGM.Error(E->getBeginLoc(), "this builtin expect that __builtin_coro_begin "
                                 "has been used earlier in this function");
     auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getPtrTy());
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index e887d35198b3c7b6e5b0e7962664c3b45a3951ed..794d93358b0a4c3573524b15e21e83885506e3dd 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/Basic/TargetOptions.h"
 #include "llvm/IR/IntrinsicsDirectX.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/FormatVariadic.h"
@@ -342,8 +343,19 @@ llvm::Value *CGHLSLRuntime::emitInputSemantic(IRBuilder<> &B,
     return B.CreateCall(FunctionCallee(DxGroupIndex));
   }
   if (D.hasAttr()) {
-    llvm::Function *DxThreadID = CGM.getIntrinsic(Intrinsic::dx_thread_id);
-    return buildVectorInput(B, DxThreadID, Ty);
+    llvm::Function *ThreadIDIntrinsic;
+    switch (CGM.getTarget().getTriple().getArch()) {
+    case llvm::Triple::dxil:
+      ThreadIDIntrinsic = CGM.getIntrinsic(Intrinsic::dx_thread_id);
+      break;
+    case llvm::Triple::spirv:
+      ThreadIDIntrinsic = CGM.getIntrinsic(Intrinsic::spv_thread_id);
+      break;
+    default:
+      llvm_unreachable("Input semantic not supported by target");
+      break;
+    }
+    return buildVectorInput(B, ThreadIDIntrinsic, Ty);
   }
   assert(false && "Unhandled parameter attribute");
   return nullptr;
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index 27d77e9a8a5511d473f6090a26f8fa5a1550a3af..e815e097e1fb48e7e3037d8983174ed471259245 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -1593,12 +1593,20 @@ private:
   }
 
   bool isClassLayoutKnownStatically(const ObjCInterfaceDecl *ID) {
-    // NSObject is a fixed size. If we can see the @implementation of a class
-    // which inherits from NSObject then we know that all it's offsets also must
-    // be fixed. FIXME: Can we do this if see a chain of super classes with
-    // implementations leading to NSObject?
-    return ID->getImplementation() && ID->getSuperClass() &&
-           ID->getSuperClass()->getName() == "NSObject";
+    // Test a class by checking its superclasses up to
+    // its base class if it has one.
+    for (; ID; ID = ID->getSuperClass()) {
+      // The layout of base class NSObject
+      // is guaranteed to be statically known
+      if (ID->getIdentifier()->getName() == "NSObject")
+        return true;
+
+      // If we cannot see the @implementation of a class,
+      // we cannot statically know the class layout.
+      if (!ID->getImplementation())
+        return false;
+    }
+    return false;
   }
 
 public:
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index a7b72df6d9f897964e5c6e4f7d01ecb4b67f3af2..e8a68dbcc68709c7afd7249032674409dd711e9f 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -2647,6 +2647,9 @@ void CGOpenMPRuntime::emitDistributeStaticInit(
 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
                                           SourceLocation Loc,
                                           OpenMPDirectiveKind DKind) {
+  assert(DKind == OMPD_distribute || DKind == OMPD_for ||
+         DKind == OMPD_sections &&
+             "Expected distribute, for, or sections directive kind");
   if (!CGF.HaveInsertPoint())
     return;
   // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index d0a3a716ad75e1f39f581b0e1404a714a47695db..8898e3f22a7df6d6ff8cd69b5255279d3ed8005a 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -728,11 +728,19 @@ void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) {
     case attr::AlwaysInline:
       alwaysinline = true;
       break;
-    case attr::MustTail:
+    case attr::MustTail: {
       const Stmt *Sub = S.getSubStmt();
       const ReturnStmt *R = cast(Sub);
       musttail = cast(R->getRetValue()->IgnoreParens());
-      break;
+    } break;
+    case attr::CXXAssume: {
+      const Expr *Assumption = cast(A)->getAssumption();
+      if (getLangOpts().CXXAssumptions &&
+          !Assumption->HasSideEffects(getContext())) {
+        llvm::Value *AssumptionVal = EvaluateExprAsBool(Assumption);
+        Builder.CreateAssumption(AssumptionVal);
+      }
+    } break;
     }
   }
   SaveAndRestore save_nomerge(InNoMergeAttributedStmt, nomerge);
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 3fbd2e03eb61df89440d821821a9baf06084b320..452ce6983f6ac195785cbc0e508e5b46941dd206 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -2910,10 +2910,10 @@ void CodeGenFunction::EmitOMPOuterLoop(
   EmitBlock(LoopExit.getBlock());
 
   // Tell the runtime we are done.
-  auto &&CodeGen = [DynamicOrOrdered, &S](CodeGenFunction &CGF) {
+  auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
     if (!DynamicOrOrdered)
       CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
-                                                     S.getDirectiveKind());
+                                                     LoopArgs.DKind);
   };
   OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen);
 }
@@ -3019,6 +3019,7 @@ void CodeGenFunction::EmitOMPForOuterLoop(
   OuterLoopArgs.Cond = S.getCond();
   OuterLoopArgs.NextLB = S.getNextLowerBound();
   OuterLoopArgs.NextUB = S.getNextUpperBound();
+  OuterLoopArgs.DKind = LoopArgs.DKind;
   EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
                    emitOMPLoopBodyWithStopPoint, CodeGenOrdered);
 }
@@ -3080,6 +3081,7 @@ void CodeGenFunction::EmitOMPDistributeOuterLoop(
   OuterLoopArgs.NextUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
                              ? S.getCombinedNextUpperBound()
                              : S.getNextUpperBound();
+  OuterLoopArgs.DKind = OMPD_distribute;
 
   EmitOMPOuterLoop(/* DynamicOrOrdered = */ false, /* IsMonotonic = */ false, S,
                    LoopScope, OuterLoopArgs, CodeGenLoopContent,
@@ -3452,15 +3454,16 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
         // Tell the runtime we are done.
         auto &&CodeGen = [&S](CodeGenFunction &CGF) {
           CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
-                                                         S.getDirectiveKind());
+                                                         OMPD_for);
         };
         OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen);
       } else {
         // Emit the outer loop, which requests its work chunk [LB..UB] from
         // runtime and runs the inner loop to process it.
-        const OMPLoopArguments LoopArguments(
+        OMPLoopArguments LoopArguments(
             LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this),
             IL.getAddress(*this), Chunk, EUB);
+        LoopArguments.DKind = OMPD_for;
         EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
                             LoopArguments, CGDispatchBounds);
       }
@@ -4082,7 +4085,7 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
     // Tell the runtime we are done.
     auto &&CodeGen = [&S](CodeGenFunction &CGF) {
       CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
-                                                     S.getDirectiveKind());
+                                                     OMPD_sections);
     };
     CGF.OMPCancelStack.emitExit(CGF, S.getDirectiveKind(), CodeGen);
     CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
@@ -5782,7 +5785,7 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
             });
         EmitBlock(LoopExit.getBlock());
         // Tell the runtime we are done.
-        RT.emitForStaticFinish(*this, S.getEndLoc(), S.getDirectiveKind());
+        RT.emitForStaticFinish(*this, S.getEndLoc(), OMPD_distribute);
       } else {
         // Emit the outer loop, which requests its work chunk [LB..UB] from
         // runtime and runs the inner loop to process it.
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index b87fc86f4e635f344ad947858f4436936b6395aa..4a3ff49b0007a3c6d70d9ef8974a1d7e00cc73ff 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -31,6 +31,7 @@
 #include "clang/AST/StmtObjC.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/CodeGenOptions.h"
+#include "clang/Basic/TargetBuiltins.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
@@ -2613,6 +2614,24 @@ void CGBuilderInserter::InsertHelper(
 // called function.
 void CodeGenFunction::checkTargetFeatures(const CallExpr *E,
                                           const FunctionDecl *TargetDecl) {
+  // SemaChecking cannot handle below x86 builtins because they have different
+  // parameter ranges with different TargetAttribute of caller.
+  if (CGM.getContext().getTargetInfo().getTriple().isX86()) {
+    unsigned BuiltinID = TargetDecl->getBuiltinID();
+    if (BuiltinID == X86::BI__builtin_ia32_cmpps ||
+        BuiltinID == X86::BI__builtin_ia32_cmpss ||
+        BuiltinID == X86::BI__builtin_ia32_cmppd ||
+        BuiltinID == X86::BI__builtin_ia32_cmpsd) {
+      const FunctionDecl *FD = dyn_cast_or_null(CurCodeDecl);
+      llvm::StringMap TargetFetureMap;
+      CGM.getContext().getFunctionFeatureMap(TargetFetureMap, FD);
+      llvm::APSInt Result =
+          *(E->getArg(2)->getIntegerConstantExpr(CGM.getContext()));
+      if (Result.getSExtValue() > 7 && !TargetFetureMap.lookup("avx"))
+        CGM.getDiags().Report(E->getBeginLoc(), diag::err_builtin_needs_feature)
+            << TargetDecl->getDeclName() << "avx";
+    }
+  }
   return checkTargetFeatures(E->getBeginLoc(), TargetDecl);
 }
 
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 06327a1847177882943f24fabd1018e2641c0210..e8f8aa601ed017b559d2b87548110423e5c78107 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -352,6 +352,25 @@ public:
     return isCoroutine() && CurCoro.InSuspendBlock;
   }
 
+  // Holds FramePtr for await_suspend wrapper generation,
+  // so that __builtin_coro_frame call can be lowered
+  // directly to value of its second argument
+  struct AwaitSuspendWrapperInfo {
+    llvm::Value *FramePtr = nullptr;
+  };
+  AwaitSuspendWrapperInfo CurAwaitSuspendWrapper;
+
+  // Generates wrapper function for `llvm.coro.await.suspend.*` intrinisics.
+  // It encapsulates SuspendExpr in a function, to separate it's body
+  // from the main coroutine to avoid miscompilations. Intrinisic
+  // is lowered to this function call in CoroSplit pass
+  // Function signature is:
+  //  __await_suspend_wrapper_(ptr %awaiter, ptr %hdl)
+  // where type is one of (void, i1, ptr)
+  llvm::Function *generateAwaitSuspendWrapper(Twine const &CoroName,
+                                              Twine const &SuspendPointName,
+                                              CoroutineSuspendExpr const &S);
+
   /// CurGD - The GlobalDecl for the current function being compiled.
   GlobalDecl CurGD;
 
@@ -3812,6 +3831,8 @@ private:
     Expr *NextLB = nullptr;
     /// Update of UB after a whole chunk has been executed
     Expr *NextUB = nullptr;
+    /// Distinguish between the for distribute and sections
+    OpenMPDirectiveKind DKind = llvm::omp::OMPD_unknown;
     OMPLoopArguments() = default;
     OMPLoopArguments(Address LB, Address UB, Address ST, Address IL,
                      llvm::Value *Chunk = nullptr, Expr *EUB = nullptr,
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 82a97ecfaa00789f9e5440ff7699c215b2a73eb2..967319bdfc4571168f370c42b3b6ad26d21b8c6c 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -872,12 +872,12 @@ void CodeGenModule::Release() {
     EmitMainVoidAlias();
 
   if (getTriple().isAMDGPU()) {
-    // Emit amdgpu_code_object_version module flag, which is code object version
+    // Emit amdhsa_code_object_version module flag, which is code object version
     // times 100.
     if (getTarget().getTargetOpts().CodeObjectVersion !=
         llvm::CodeObjectVersionKind::COV_None) {
       getModule().addModuleFlag(llvm::Module::Error,
-                                "amdgpu_code_object_version",
+                                "amdhsa_code_object_version",
                                 getTarget().getTargetOpts().CodeObjectVersion);
     }
 
@@ -916,7 +916,7 @@ void CodeGenModule::Release() {
         llvm::ConstantArray::get(ATy, UsedArray), "__clang_gpu_used_external");
     addCompilerUsedGlobal(GV);
   }
-  if (LangOpts.HIP) {
+  if (LangOpts.HIP && !getLangOpts().OffloadingNewDriver) {
     // Emit a unique ID so that host and device binaries from the same
     // compilation unit can be associated.
     auto *GV = new llvm::GlobalVariable(
diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp
index 8a081612193978e2a03789473430122bd25ebed2..a1e14c5f0a8c784e58154c2c85cce1bd0b77e749 100644
--- a/clang/lib/CodeGen/CodeGenTBAA.cpp
+++ b/clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -286,6 +286,14 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
   /* Things not handled yet include: C++ base classes, bitfields, */
 
   if (const RecordType *TTy = QTy->getAs()) {
+    if (TTy->isUnionType()) {
+      uint64_t Size = Context.getTypeSizeInChars(QTy).getQuantity();
+      llvm::MDNode *TBAAType = getChar();
+      llvm::MDNode *TBAATag = getAccessTagInfo(TBAAAccessInfo(TBAAType, Size));
+      Fields.push_back(
+          llvm::MDBuilder::TBAAStructField(BaseOffset, Size, TBAATag));
+      return true;
+    }
     const RecordDecl *RD = TTy->getDecl()->getDefinition();
     if (RD->hasFlexibleArrayMember())
       return false;
@@ -343,6 +351,9 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
 
 llvm::MDNode *
 CodeGenTBAA::getTBAAStructInfo(QualType QTy) {
+  if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing)
+    return nullptr;
+
   const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
 
   if (llvm::MDNode *N = StructMetadataCache[Ty])
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index 725e8a70fddfe6910cf9cc0f27e42bab4cd5115f..85117366de0ee8470b1f28f7a2b52a35e9ab4301 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -886,9 +886,11 @@ void AArch64ABIInfo::appendAttributeMangling(StringRef AttrStr,
     return LHS.compare(RHS) < 0;
   });
 
+  llvm::SmallDenseSet UniqueFeats;
   for (auto &Feat : Features)
     if (auto Ext = llvm::AArch64::parseArchExtension(Feat))
-      Out << 'M' << Ext->Name;
+      if (UniqueFeats.insert(Ext->Name).second)
+        Out << 'M' << Ext->Name;
 }
 
 std::unique_ptr
diff --git a/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp b/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp
index beca9586988b526876c0787ae9d0e62345268c4f..2ffbc1a226958a0a8ecf6cca1965cdb9235e9ef6 100644
--- a/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp
+++ b/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp
@@ -333,8 +333,7 @@ llvm::Expected> clang::DirectoryWatcher::creat
   const int InotifyFD = inotify_init1(IN_CLOEXEC);
   if (InotifyFD == -1)
     return llvm::make_error(
-        std::string("inotify_init1() error: ") + strerror(errno),
-        llvm::inconvertibleErrorCode());
+        llvm::errnoAsErrorCode(), std::string(": inotify_init1()"));
 
   const int InotifyWD = inotify_add_watch(
       InotifyFD, Path.str().c_str(),
@@ -346,15 +345,13 @@ llvm::Expected> clang::DirectoryWatcher::creat
       );
   if (InotifyWD == -1)
     return llvm::make_error(
-        std::string("inotify_add_watch() error: ") + strerror(errno),
-        llvm::inconvertibleErrorCode());
+        llvm::errnoAsErrorCode(), std::string(": inotify_add_watch()"));
 
   auto InotifyPollingStopper = SemaphorePipe::create();
 
   if (!InotifyPollingStopper)
     return llvm::make_error(
-        std::string("SemaphorePipe::create() error: ") + strerror(errno),
-        llvm::inconvertibleErrorCode());
+        llvm::errnoAsErrorCode(), std::string(": SemaphorePipe::create()"));
 
   return std::make_unique(
       Path, Receiver, WaitForInitialSync, InotifyFD, InotifyWD,
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index b8ec0791dc51f755ae36bd26a82b87ad817fe24d..190782a79a24562d9058de0b53d8edf16b49cdbe 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2196,12 +2196,6 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
     return false;
   }
 
-  if (C.getArgs().hasArg(options::OPT_print_std_module_manifest_path)) {
-    llvm::outs() << GetStdModuleManifestPath(C, C.getDefaultToolChain())
-                 << '\n';
-    return false;
-  }
-
   if (C.getArgs().hasArg(options::OPT_print_runtime_dir)) {
     if (std::optional RuntimePath = TC.getRuntimePath())
       llvm::outs() << *RuntimePath << '\n';
@@ -3240,7 +3234,7 @@ class OffloadingActionBuilder final {
     CudaActionBuilder(Compilation &C, DerivedArgList &Args,
                       const Driver::InputList &Inputs)
         : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_Cuda) {
-      DefaultCudaArch = CudaArch::SM_35;
+      DefaultCudaArch = CudaArch::CudaDefault;
     }
 
     StringRef getCanonicalOffloadArch(StringRef ArchStr) override {
@@ -3379,7 +3373,7 @@ class OffloadingActionBuilder final {
                      const Driver::InputList &Inputs)
         : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) {
 
-      DefaultCudaArch = CudaArch::GFX906;
+      DefaultCudaArch = CudaArch::HIPDefault;
 
       if (Args.hasArg(options::OPT_fhip_emit_relocatable,
                       options::OPT_fno_hip_emit_relocatable)) {
@@ -4631,12 +4625,25 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
       DDeps.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
       OffloadAction::DeviceDependences DDep;
       DDep.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
+
+      // Compiling CUDA in non-RDC mode uses the PTX output if available.
+      for (Action *Input : A->getInputs())
+        if (Kind == Action::OFK_Cuda && A->getType() == types::TY_Object &&
+            !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
+                          false))
+          DDep.add(*Input, *TCAndArch->first, TCAndArch->second.data(), Kind);
       OffloadActions.push_back(C.MakeAction(DDep, A->getType()));
+
       ++TCAndArch;
     }
   }
 
-  if (offloadDeviceOnly())
+  // All kinds exit now in device-only mode except for non-RDC mode HIP.
+  if (offloadDeviceOnly() &&
+      (!C.isOffloadingHostKind(Action::OFK_HIP) ||
+       !Args.hasFlag(options::OPT_gpu_bundle_output,
+                     options::OPT_no_gpu_bundle_output, true) ||
+       Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false)))
     return C.MakeAction(DDeps, types::TY_Nothing);
 
   if (OffloadActions.empty())
@@ -4669,6 +4676,10 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
              nullptr, C.getActiveOffloadKinds());
   }
 
+  // HIP wants '--offload-device-only' to create a fatbinary by default.
+  if (offloadDeviceOnly())
+    return C.MakeAction(DDep, types::TY_Nothing);
+
   // If we are unable to embed a single device output into the host, we need to
   // add each device output as a host dependency to ensure they are still built.
   bool SingleDeviceOutput = !llvm::any_of(OffloadActions, [](Action *A) {
@@ -6174,44 +6185,6 @@ std::string Driver::GetProgramPath(StringRef Name, const ToolChain &TC) const {
   return std::string(Name);
 }
 
-std::string Driver::GetStdModuleManifestPath(const Compilation &C,
-                                             const ToolChain &TC) const {
-  std::string error = "";
-
-  switch (TC.GetCXXStdlibType(C.getArgs())) {
-  case ToolChain::CST_Libcxx: {
-    std::string lib = GetFilePath("libc++.so", TC);
-
-    // Note when there are multiple flavours of libc++ the module json needs to
-    // look at the command-line arguments for the proper json.
-    // These flavours do not exist at the moment, but there are plans to
-    // provide a variant that is built with sanitizer instrumentation enabled.
-
-    // For example
-    //  StringRef modules = [&] {
-    //    const SanitizerArgs &Sanitize = TC.getSanitizerArgs(C.getArgs());
-    //    if (Sanitize.needsAsanRt())
-    //      return "modules-asan.json";
-    //    return "modules.json";
-    //  }();
-
-    SmallString<128> path(lib.begin(), lib.end());
-    llvm::sys::path::remove_filename(path);
-    llvm::sys::path::append(path, "modules.json");
-    if (TC.getVFS().exists(path))
-      return static_cast(path);
-
-    return error;
-  }
-
-  case ToolChain::CST_Libstdcxx:
-    // libstdc++ does not provide Standard library modules yet.
-    return error;
-  }
-
-  return error;
-}
-
 std::string Driver::GetTemporaryPath(StringRef Prefix, StringRef Suffix) const {
   SmallString<128> Path;
   std::error_code EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path);
diff --git a/clang/lib/Driver/OffloadBundler.cpp b/clang/lib/Driver/OffloadBundler.cpp
index 99a34d25cfcd56e5609815e1c9f9aacd52951229..77c89356bc76bb38a4b0771b739b281a92bb709f 100644
--- a/clang/lib/Driver/OffloadBundler.cpp
+++ b/clang/lib/Driver/OffloadBundler.cpp
@@ -590,7 +590,8 @@ public:
     // Copy fat object contents to the output when extracting host bundle.
     std::string ModifiedContent;
     if (Content.size() == 1u && Content.front() == 0) {
-      auto HostBundleOrErr = getHostBundle();
+      auto HostBundleOrErr = getHostBundle(
+          StringRef(Input.getBufferStart(), Input.getBufferSize()));
       if (!HostBundleOrErr)
         return HostBundleOrErr.takeError();
 
@@ -700,7 +701,7 @@ private:
     return Error::success();
   }
 
-  Expected getHostBundle() {
+  Expected getHostBundle(StringRef Input) {
     TempFileHandlerRAII TempFiles;
 
     auto ModifiedObjPathOrErr = TempFiles.Create(std::nullopt);
@@ -715,7 +716,24 @@ private:
     ObjcopyArgs.push_back("--regex");
     ObjcopyArgs.push_back("--remove-section=__CLANG_OFFLOAD_BUNDLE__.*");
     ObjcopyArgs.push_back("--");
-    ObjcopyArgs.push_back(BundlerConfig.InputFileNames.front());
+
+    StringRef ObjcopyInputFileName;
+    // When unbundling an archive, the content of each object file in the
+    // archive is passed to this function by parameter Input, which is different
+    // from the content of the original input archive file, therefore it needs
+    // to be saved to a temporary file before passed to llvm-objcopy. Otherwise,
+    // Input is the same as the content of the original input file, therefore
+    // temporary file is not needed.
+    if (StringRef(BundlerConfig.FilesType).starts_with("a")) {
+      auto InputFileOrErr =
+          TempFiles.Create(ArrayRef(Input.data(), Input.size()));
+      if (!InputFileOrErr)
+        return InputFileOrErr.takeError();
+      ObjcopyInputFileName = *InputFileOrErr;
+    } else
+      ObjcopyInputFileName = BundlerConfig.InputFileNames.front();
+
+    ObjcopyArgs.push_back(ObjcopyInputFileName);
     ObjcopyArgs.push_back(ModifiedObjPath);
 
     if (Error Err = executeObjcopy(BundlerConfig.ObjcopyPath, ObjcopyArgs))
@@ -906,6 +924,17 @@ CreateFileHandler(MemoryBuffer &FirstInput,
 }
 
 OffloadBundlerConfig::OffloadBundlerConfig() {
+  if (llvm::compression::zstd::isAvailable()) {
+    CompressionFormat = llvm::compression::Format::Zstd;
+    // Compression level 3 is usually sufficient for zstd since long distance
+    // matching is enabled.
+    CompressionLevel = 3;
+  } else if (llvm::compression::zlib::isAvailable()) {
+    CompressionFormat = llvm::compression::Format::Zlib;
+    // Use default level for zlib since higher level does not have significant
+    // improvement.
+    CompressionLevel = llvm::compression::zlib::DefaultCompression;
+  }
   auto IgnoreEnvVarOpt =
       llvm::sys::Process::GetEnv("OFFLOAD_BUNDLER_IGNORE_ENV_VAR");
   if (IgnoreEnvVarOpt.has_value() && IgnoreEnvVarOpt.value() == "1")
@@ -919,11 +948,41 @@ OffloadBundlerConfig::OffloadBundlerConfig() {
       llvm::sys::Process::GetEnv("OFFLOAD_BUNDLER_COMPRESS");
   if (CompressEnvVarOpt.has_value())
     Compress = CompressEnvVarOpt.value() == "1";
+
+  auto CompressionLevelEnvVarOpt =
+      llvm::sys::Process::GetEnv("OFFLOAD_BUNDLER_COMPRESSION_LEVEL");
+  if (CompressionLevelEnvVarOpt.has_value()) {
+    llvm::StringRef CompressionLevelStr = CompressionLevelEnvVarOpt.value();
+    int Level;
+    if (!CompressionLevelStr.getAsInteger(10, Level))
+      CompressionLevel = Level;
+    else
+      llvm::errs()
+          << "Warning: Invalid value for OFFLOAD_BUNDLER_COMPRESSION_LEVEL: "
+          << CompressionLevelStr.str() << ". Ignoring it.\n";
+  }
+}
+
+// Utility function to format numbers with commas
+static std::string formatWithCommas(unsigned long long Value) {
+  std::string Num = std::to_string(Value);
+  int InsertPosition = Num.length() - 3;
+  while (InsertPosition > 0) {
+    Num.insert(InsertPosition, ",");
+    InsertPosition -= 3;
+  }
+  return Num;
 }
 
 llvm::Expected>
-CompressedOffloadBundle::compress(const llvm::MemoryBuffer &Input,
+CompressedOffloadBundle::compress(llvm::compression::Params P,
+                                  const llvm::MemoryBuffer &Input,
                                   bool Verbose) {
+  if (!llvm::compression::zstd::isAvailable() &&
+      !llvm::compression::zlib::isAvailable())
+    return createStringError(llvm::inconvertibleErrorCode(),
+                             "Compression not supported");
+
   llvm::Timer HashTimer("Hash Calculation Timer", "Hash calculation time",
                         ClangOffloadBundlerTimerGroup);
   if (Verbose)
@@ -941,25 +1000,15 @@ CompressedOffloadBundle::compress(const llvm::MemoryBuffer &Input,
       reinterpret_cast(Input.getBuffer().data()),
       Input.getBuffer().size());
 
-  llvm::compression::Format CompressionFormat;
-
-  if (llvm::compression::zstd::isAvailable())
-    CompressionFormat = llvm::compression::Format::Zstd;
-  else if (llvm::compression::zlib::isAvailable())
-    CompressionFormat = llvm::compression::Format::Zlib;
-  else
-    return createStringError(llvm::inconvertibleErrorCode(),
-                             "Compression not supported");
-
   llvm::Timer CompressTimer("Compression Timer", "Compression time",
                             ClangOffloadBundlerTimerGroup);
   if (Verbose)
     CompressTimer.startTimer();
-  llvm::compression::compress(CompressionFormat, BufferUint8, CompressedBuffer);
+  llvm::compression::compress(P, BufferUint8, CompressedBuffer);
   if (Verbose)
     CompressTimer.stopTimer();
 
-  uint16_t CompressionMethod = static_cast(CompressionFormat);
+  uint16_t CompressionMethod = static_cast(P.format);
   uint32_t UncompressedSize = Input.getBuffer().size();
 
   SmallVector FinalBuffer;
@@ -977,17 +1026,29 @@ CompressedOffloadBundle::compress(const llvm::MemoryBuffer &Input,
 
   if (Verbose) {
     auto MethodUsed =
-        CompressionFormat == llvm::compression::Format::Zstd ? "zstd" : "zlib";
+        P.format == llvm::compression::Format::Zstd ? "zstd" : "zlib";
+    double CompressionRate =
+        static_cast(UncompressedSize) / CompressedBuffer.size();
+    double CompressionTimeSeconds = CompressTimer.getTotalTime().getWallTime();
+    double CompressionSpeedMBs =
+        (UncompressedSize / (1024.0 * 1024.0)) / CompressionTimeSeconds;
+
     llvm::errs() << "Compressed bundle format version: " << Version << "\n"
                  << "Compression method used: " << MethodUsed << "\n"
-                 << "Binary size before compression: " << UncompressedSize
-                 << " bytes\n"
-                 << "Binary size after compression: " << CompressedBuffer.size()
-                 << " bytes\n"
+                 << "Compression level: " << P.level << "\n"
+                 << "Binary size before compression: "
+                 << formatWithCommas(UncompressedSize) << " bytes\n"
+                 << "Binary size after compression: "
+                 << formatWithCommas(CompressedBuffer.size()) << " bytes\n"
+                 << "Compression rate: "
+                 << llvm::format("%.2lf", CompressionRate) << "\n"
+                 << "Compression ratio: "
+                 << llvm::format("%.2lf%%", 100.0 / CompressionRate) << "\n"
+                 << "Compression speed: "
+                 << llvm::format("%.2lf MB/s", CompressionSpeedMBs) << "\n"
                  << "Truncated MD5 hash: "
                  << llvm::format_hex(TruncatedHash, 16) << "\n";
   }
-
   return llvm::MemoryBuffer::getMemBufferCopy(
       llvm::StringRef(FinalBuffer.data(), FinalBuffer.size()));
 }
@@ -1052,7 +1113,10 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
   if (Verbose) {
     DecompressTimer.stopTimer();
 
-    // Recalculate MD5 hash
+    double DecompressionTimeSeconds =
+        DecompressTimer.getTotalTime().getWallTime();
+
+    // Recalculate MD5 hash for integrity check
     llvm::Timer HashRecalcTimer("Hash Recalculation Timer",
                                 "Hash recalculation time",
                                 ClangOffloadBundlerTimerGroup);
@@ -1066,16 +1130,27 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
     HashRecalcTimer.stopTimer();
     bool HashMatch = (StoredHash == RecalculatedHash);
 
+    double CompressionRate =
+        static_cast(UncompressedSize) / CompressedData.size();
+    double DecompressionSpeedMBs =
+        (UncompressedSize / (1024.0 * 1024.0)) / DecompressionTimeSeconds;
+
     llvm::errs() << "Compressed bundle format version: " << ThisVersion << "\n"
                  << "Decompression method: "
                  << (CompressionFormat == llvm::compression::Format::Zlib
                          ? "zlib"
                          : "zstd")
                  << "\n"
-                 << "Size before decompression: " << CompressedData.size()
-                 << " bytes\n"
-                 << "Size after decompression: " << UncompressedSize
-                 << " bytes\n"
+                 << "Size before decompression: "
+                 << formatWithCommas(CompressedData.size()) << " bytes\n"
+                 << "Size after decompression: "
+                 << formatWithCommas(UncompressedSize) << " bytes\n"
+                 << "Compression rate: "
+                 << llvm::format("%.2lf", CompressionRate) << "\n"
+                 << "Compression ratio: "
+                 << llvm::format("%.2lf%%", 100.0 / CompressionRate) << "\n"
+                 << "Decompression speed: "
+                 << llvm::format("%.2lf MB/s", DecompressionSpeedMBs) << "\n"
                  << "Stored hash: " << llvm::format_hex(StoredHash, 16) << "\n"
                  << "Recalculated hash: "
                  << llvm::format_hex(RecalculatedHash, 16) << "\n"
@@ -1269,8 +1344,10 @@ Error OffloadBundler::BundleFiles() {
     std::unique_ptr BufferMemory =
         llvm::MemoryBuffer::getMemBufferCopy(
             llvm::StringRef(Buffer.data(), Buffer.size()));
-    auto CompressionResult =
-        CompressedOffloadBundle::compress(*BufferMemory, BundlerConfig.Verbose);
+    auto CompressionResult = CompressedOffloadBundle::compress(
+        {BundlerConfig.CompressionFormat, BundlerConfig.CompressionLevel,
+         /*zstdEnableLdm=*/true},
+        *BufferMemory, BundlerConfig.Verbose);
     if (auto Error = CompressionResult.takeError())
       return Error;
 
@@ -1628,10 +1705,8 @@ Error OffloadBundler::UnbundleArchive() {
     while (!CodeObject.empty()) {
       SmallVector CompatibleTargets;
       auto CodeObjectInfo = OffloadTargetInfo(CodeObject, BundlerConfig);
-      if (CodeObjectInfo.hasHostKind()) {
-        // Do nothing, we don't extract host code yet.
-      } else if (getCompatibleOffloadTargets(CodeObjectInfo, CompatibleTargets,
-                                             BundlerConfig)) {
+      if (getCompatibleOffloadTargets(CodeObjectInfo, CompatibleTargets,
+                                      BundlerConfig)) {
         std::string BundleData;
         raw_string_ostream DataStream(BundleData);
         if (Error Err = FileHandler->ReadBundle(DataStream, CodeObjectBuffer))
diff --git a/clang/lib/Driver/ToolChains/Arch/Mips.h b/clang/lib/Driver/ToolChains/Arch/Mips.h
index 62211c7114207ea73cd0975a3e445f2667386be4..674c21744b523b289e434d6d07f221811a6e2ea0 100644
--- a/clang/lib/Driver/ToolChains/Arch/Mips.h
+++ b/clang/lib/Driver/ToolChains/Arch/Mips.h
@@ -1,4 +1,4 @@
-//===--- Mips.h - Mips-specific Tool Helpers ----------------------*- C++ -*-===//
+//===--- Mips.h - Mips-specific Tool Helpers --------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/Driver/ToolChains/Arch/Sparc.h b/clang/lib/Driver/ToolChains/Arch/Sparc.h
index 44658c4259c696992495c2137f8922cf4e9b7deb..2b178d9df1ee36e9c6662371191311917d0894f4 100644
--- a/clang/lib/Driver/ToolChains/Arch/Sparc.h
+++ b/clang/lib/Driver/ToolChains/Arch/Sparc.h
@@ -1,4 +1,4 @@
-//===--- Sparc.h - Sparc-specific Tool Helpers ----------------------*- C++ -*-===//
+//===--- Sparc.h - Sparc-specific Tool Helpers ------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 858d20fbfac0158047e5ff5aa265e402f537d577..3a7a1cf99c79aca2913d52d5cd5fb7e338832f11 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -2687,8 +2687,8 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
   }
 }
 
-static StringRef EnumComplexRangeToStr(LangOptions::ComplexRangeKind Range) {
-  StringRef RangeStr = "";
+static StringRef EnumComplexRangeToStr(LangOptions::ComplexRangeKind Range,
+                                       StringRef Option) {
   switch (Range) {
   case LangOptions::ComplexRangeKind::CX_Limited:
     return "-fcx-limited-range";
@@ -2697,17 +2697,32 @@ static StringRef EnumComplexRangeToStr(LangOptions::ComplexRangeKind Range) {
     return "-fcx-fortran-rules";
     break;
   default:
-    return RangeStr;
+    return Option;
     break;
   }
 }
 
 static void EmitComplexRangeDiag(const Driver &D,
                                  LangOptions::ComplexRangeKind Range1,
-                                 LangOptions::ComplexRangeKind Range2) {
-  if (Range1 != Range2 && Range1 != LangOptions::ComplexRangeKind::CX_None)
-    D.Diag(clang::diag::warn_drv_overriding_option)
-        << EnumComplexRangeToStr(Range1) << EnumComplexRangeToStr(Range2);
+                                 LangOptions::ComplexRangeKind Range2,
+                                 StringRef Option = StringRef()) {
+  if (Range1 != Range2 && Range1 != LangOptions::ComplexRangeKind::CX_None) {
+    bool NegateFortranOption = false;
+    bool NegateLimitedOption = false;
+    if (!Option.empty()) {
+      NegateFortranOption =
+          Range1 == LangOptions::ComplexRangeKind::CX_Fortran &&
+          Option == "-fno-cx-fortran-rules";
+      NegateLimitedOption =
+          Range1 == LangOptions::ComplexRangeKind::CX_Limited &&
+          Option == "-fno-cx-limited-range";
+    }
+    if (Option.empty() ||
+        (!Option.empty() && !NegateFortranOption && !NegateLimitedOption))
+      D.Diag(clang::diag::warn_drv_overriding_option)
+          << EnumComplexRangeToStr(Range1, Option)
+          << EnumComplexRangeToStr(Range2, Option);
+  }
 }
 
 static std::string
@@ -2815,7 +2830,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
       break;
     }
     case options::OPT_fno_cx_limited_range:
-      EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full);
+      EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full,
+                           "-fno-cx-limited-range");
       Range = LangOptions::ComplexRangeKind::CX_Full;
       break;
     case options::OPT_fcx_fortran_rules: {
@@ -2824,7 +2840,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
       break;
     }
     case options::OPT_fno_cx_fortran_rules:
-      EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full);
+      EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full,
+                           "-fno-cx-fortran-rules");
       Range = LangOptions::ComplexRangeKind::CX_Full;
       break;
     case options::OPT_ffp_model_EQ: {
@@ -4478,14 +4495,20 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T,
       Args.getLastArg(options::OPT_ggnu_pubnames, options::OPT_gno_gnu_pubnames,
                       options::OPT_gpubnames, options::OPT_gno_pubnames);
   if (DwarfFission != DwarfFissionKind::None ||
-      (PubnamesArg && checkDebugInfoOption(PubnamesArg, Args, D, TC)))
-    if (!PubnamesArg ||
-        (!PubnamesArg->getOption().matches(options::OPT_gno_gnu_pubnames) &&
-         !PubnamesArg->getOption().matches(options::OPT_gno_pubnames)))
+      (PubnamesArg && checkDebugInfoOption(PubnamesArg, Args, D, TC))) {
+    const bool OptionSet =
+        (PubnamesArg &&
+         (PubnamesArg->getOption().matches(options::OPT_gpubnames) ||
+          PubnamesArg->getOption().matches(options::OPT_ggnu_pubnames)));
+    if ((DebuggerTuning != llvm::DebuggerKind::LLDB || OptionSet) &&
+        (!PubnamesArg ||
+         (!PubnamesArg->getOption().matches(options::OPT_gno_gnu_pubnames) &&
+          !PubnamesArg->getOption().matches(options::OPT_gno_pubnames))))
       CmdArgs.push_back(PubnamesArg && PubnamesArg->getOption().matches(
                                            options::OPT_gpubnames)
                             ? "-gpubnames"
                             : "-ggnu-pubnames");
+  }
   const auto *SimpleTemplateNamesArg =
       Args.getLastArg(options::OPT_gsimple_template_names,
                       options::OPT_gno_simple_template_names);
@@ -6976,6 +6999,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
                         (!IsWindowsMSVC || IsMSVC2015Compatible)))
     CmdArgs.push_back("-fno-threadsafe-statics");
 
+  // Add -fno-assumptions, if it was specified.
+  if (!Args.hasFlag(options::OPT_fassumptions, options::OPT_fno_assumptions,
+                    true))
+    CmdArgs.push_back("-fno-assumptions");
+
   // -fgnu-keywords default varies depending on language; only pass if
   // specified.
   Args.AddLastArg(CmdArgs, options::OPT_fgnu_keywords,
@@ -8518,7 +8546,6 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
 }
 
 // Begin OffloadBundler
-
 void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
                                   const InputInfo &Output,
                                   const InputInfoList &Inputs,
@@ -8616,11 +8643,7 @@ void OffloadBundler::ConstructJob(Compilation &C, const JobAction &JA,
     }
     CmdArgs.push_back(TCArgs.MakeArgString(UB));
   }
-  if (TCArgs.hasFlag(options::OPT_offload_compress,
-                     options::OPT_no_offload_compress, false))
-    CmdArgs.push_back("-compress");
-  if (TCArgs.hasArg(options::OPT_v))
-    CmdArgs.push_back("-verbose");
+  addOffloadCompressArgs(TCArgs, CmdArgs);
   // All the inputs are encoded as commands.
   C.addCommand(std::make_unique(
       JA, *this, ResponseFileSupport::None(),
@@ -8886,10 +8909,11 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
   // Add the linker arguments to be forwarded by the wrapper.
   CmdArgs.push_back(Args.MakeArgString(Twine("--linker-path=") +
                                        LinkCommand->getExecutable()));
-  CmdArgs.push_back("--");
   for (const char *LinkArg : LinkCommand->getArguments())
     CmdArgs.push_back(LinkArg);
 
+  addOffloadCompressArgs(Args, CmdArgs);
+
   const char *Exec =
       Args.MakeArgString(getToolChain().GetProgramPath("clang-linker-wrapper"));
 
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 7f0f78b41e79ed358922b2bcc68ccefe58ad066f..100e71245394d845430bb371ff289d53c5e4af92 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -2863,3 +2863,15 @@ void tools::addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC,
     CmdArgs.push_back("+outline-atomics");
   }
 }
+
+void tools::addOffloadCompressArgs(const llvm::opt::ArgList &TCArgs,
+                                   llvm::opt::ArgStringList &CmdArgs) {
+  if (TCArgs.hasFlag(options::OPT_offload_compress,
+                     options::OPT_no_offload_compress, false))
+    CmdArgs.push_back("-compress");
+  if (TCArgs.hasArg(options::OPT_v))
+    CmdArgs.push_back("-verbose");
+  if (auto *Arg = TCArgs.getLastArg(options::OPT_offload_compression_level_EQ))
+    CmdArgs.push_back(
+        TCArgs.MakeArgString(Twine("-compression-level=") + Arg->getValue()));
+}
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h
index b8f649aab4bdd2124984eca2531c1eade995e9b1..bb37be4bd6ea05f04d08f3abad37ec256a59850f 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -221,6 +221,8 @@ void addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC,
                            const llvm::opt::ArgList &Args,
                            llvm::opt::ArgStringList &CmdArgs,
                            const llvm::Triple &Triple);
+void addOffloadCompressArgs(const llvm::opt::ArgList &TCArgs,
+                            llvm::opt::ArgStringList &CmdArgs);
 
 } // end namespace tools
 } // end namespace driver
diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp
index 177fd6310e7ee28d00362a5bccf871bcbe467c81..c6007d3cfab8643ec7bb1510e1fde1dc4f7967cb 100644
--- a/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -503,18 +503,20 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
       Exec, CmdArgs, Inputs, Output));
 }
 
-static bool shouldIncludePTX(const ArgList &Args, const char *gpu_arch) {
-  bool includePTX = true;
-  for (Arg *A : Args) {
-    if (!(A->getOption().matches(options::OPT_cuda_include_ptx_EQ) ||
-          A->getOption().matches(options::OPT_no_cuda_include_ptx_EQ)))
-      continue;
+static bool shouldIncludePTX(const ArgList &Args, StringRef InputArch) {
+  // The new driver does not include PTX by default to avoid overhead.
+  bool includePTX = !Args.hasFlag(options::OPT_offload_new_driver,
+                                  options::OPT_no_offload_new_driver, false);
+  for (Arg *A : Args.filtered(options::OPT_cuda_include_ptx_EQ,
+                              options::OPT_no_cuda_include_ptx_EQ)) {
     A->claim();
     const StringRef ArchStr = A->getValue();
-    if (ArchStr == "all" || ArchStr == gpu_arch) {
-      includePTX = A->getOption().matches(options::OPT_cuda_include_ptx_EQ);
-      continue;
-    }
+    if (A->getOption().matches(options::OPT_cuda_include_ptx_EQ) &&
+        (ArchStr == "all" || ArchStr == InputArch))
+      includePTX = true;
+    else if (A->getOption().matches(options::OPT_no_cuda_include_ptx_EQ) &&
+             (ArchStr == "all" || ArchStr == InputArch))
+      includePTX = false;
   }
   return includePTX;
 }
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index 9d698f775839502adfff163ae3a3ca6b48bd4dbf..c5757ddebb0f3eed4b96200be1f5f0243d93dd03 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -133,6 +133,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                    const char *LinkingOutput) const {
   const auto &ToolChain = static_cast(getToolChain());
   const Driver &D = ToolChain.getDriver();
+  const llvm::Triple &Triple = ToolChain.getTriple();
   const llvm::Triple::ArchType Arch = ToolChain.getArch();
   const bool IsPIE =
       !Args.hasArg(options::OPT_shared) &&
@@ -165,8 +166,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
       CmdArgs.push_back("-dynamic-linker");
       CmdArgs.push_back("/libexec/ld-elf.so.1");
     }
-    const llvm::Triple &T = ToolChain.getTriple();
-    if (Arch == llvm::Triple::arm || T.isX86())
+    if (Arch == llvm::Triple::arm || Triple.isX86())
       CmdArgs.push_back("--hash-style=both");
     CmdArgs.push_back("--enable-new-dtags");
   }
@@ -212,12 +212,17 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   case llvm::Triple::riscv64:
     CmdArgs.push_back("-m");
     CmdArgs.push_back("elf64lriscv");
-    CmdArgs.push_back("-X");
     break;
   default:
     break;
   }
 
+  if (Triple.isRISCV64()) {
+    CmdArgs.push_back("-X");
+    if (Args.hasArg(options::OPT_mno_relax))
+      CmdArgs.push_back("--no-relax");
+  }
+
   if (Arg *A = Args.getLastArg(options::OPT_G)) {
     if (ToolChain.getTriple().isMIPS()) {
       StringRef v = A->getValue();
diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp
index 9123ddf2fe991f23b1aeff15623a5f6be6daa700..598289f48ff4306348968d10cb0726c8e74d2383 100644
--- a/clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -119,8 +119,11 @@ void fuchsia::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back(Args.MakeArgString(Dyld));
   }
 
-  if (ToolChain.getArch() == llvm::Triple::riscv64)
+  if (Triple.isRISCV64()) {
     CmdArgs.push_back("-X");
+    if (Args.hasArg(options::OPT_mno_relax))
+      CmdArgs.push_back("--no-relax");
+  }
 
   CmdArgs.push_back("-o");
   CmdArgs.push_back(Output.getFilename());
diff --git a/clang/lib/Driver/ToolChains/HIPUtility.cpp b/clang/lib/Driver/ToolChains/HIPUtility.cpp
index fcecf2e1313bb5e106dac7f2780e678c47284d17..08c647dfcb6f728f52ff9f2e4dcb662c0860ad0b 100644
--- a/clang/lib/Driver/ToolChains/HIPUtility.cpp
+++ b/clang/lib/Driver/ToolChains/HIPUtility.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "HIPUtility.h"
+#include "Clang.h"
 #include "CommonArgs.h"
 #include "clang/Driver/Compilation.h"
 #include "clang/Driver/Options.h"
@@ -258,11 +259,7 @@ void HIP::constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
       Args.MakeArgString(std::string("-output=").append(Output));
   BundlerArgs.push_back(BundlerOutputArg);
 
-  if (Args.hasFlag(options::OPT_offload_compress,
-                   options::OPT_no_offload_compress, false))
-    BundlerArgs.push_back("-compress");
-  if (Args.hasArg(options::OPT_v))
-    BundlerArgs.push_back("-verbose");
+  addOffloadCompressArgs(Args, BundlerArgs);
 
   const char *Bundler = Args.MakeArgString(
       T.getToolChain().GetProgramPath("clang-offload-bundler"));
diff --git a/clang/lib/Driver/ToolChains/Haiku.cpp b/clang/lib/Driver/ToolChains/Haiku.cpp
index ca7faa68765abf4bc5abd6b74e03a96310ea36da..30464e2229e65be28b81ddf7941320b754607233 100644
--- a/clang/lib/Driver/ToolChains/Haiku.cpp
+++ b/clang/lib/Driver/ToolChains/Haiku.cpp
@@ -25,7 +25,7 @@ void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                    const char *LinkingOutput) const {
   const auto &ToolChain = static_cast(getToolChain());
   const Driver &D = ToolChain.getDriver();
-  const llvm::Triple::ArchType Arch = ToolChain.getArch();
+  const llvm::Triple &Triple = ToolChain.getTriple();
   const bool Static = Args.hasArg(options::OPT_static);
   const bool Shared = Args.hasArg(options::OPT_shared);
   ArgStringList CmdArgs;
@@ -61,8 +61,11 @@ void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   if (!Shared)
     CmdArgs.push_back("--no-undefined");
 
-  if (Arch == llvm::Triple::riscv64)
+  if (Triple.isRISCV64()) {
     CmdArgs.push_back("-X");
+    if (Args.hasArg(options::OPT_mno_relax))
+      CmdArgs.push_back("--no-relax");
+  }
 
   assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
   if (Output.isFilename()) {
diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp
index 645d0311641f34604665d53cda869713a34e24e9..0eec8fddabd5db6c53f18162549fc5516be95ddb 100644
--- a/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -240,8 +240,11 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     break;
   }
 
-  if (Triple.isRISCV())
+  if (Triple.isRISCV()) {
     CmdArgs.push_back("-X");
+    if (Args.hasArg(options::OPT_mno_relax))
+      CmdArgs.push_back("--no-relax");
+  }
 
   assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
   if (Output.isFilename()) {
diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp
index 97f88b7b79dfbef5f1f92cea1aa7b2c31a066ad7..6da6728585df93582b6e00ad6fc92264910239e6 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -111,6 +111,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                    const char *LinkingOutput) const {
   const auto &ToolChain = static_cast(getToolChain());
   const Driver &D = ToolChain.getDriver();
+  const llvm::Triple &Triple = ToolChain.getTriple();
   const llvm::Triple::ArchType Arch = ToolChain.getArch();
   const bool Static = Args.hasArg(options::OPT_static);
   const bool Shared = Args.hasArg(options::OPT_shared);
@@ -160,8 +161,11 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   if (Nopie || Profiling)
     CmdArgs.push_back("-nopie");
 
-  if (Arch == llvm::Triple::riscv64)
+  if (Triple.isRISCV64()) {
     CmdArgs.push_back("-X");
+    if (Args.hasArg(options::OPT_mno_relax))
+      CmdArgs.push_back("--no-relax");
+  }
 
   assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
   if (Output.isFilename()) {
diff --git a/clang/lib/Format/FormatToken.cpp b/clang/lib/Format/FormatToken.cpp
index 56a7b2d63877652a89330ce72e090d1cad64a325..4fb70ffac706d06cd8602159b247589a92af6822 100644
--- a/clang/lib/Format/FormatToken.cpp
+++ b/clang/lib/Format/FormatToken.cpp
@@ -71,8 +71,22 @@ bool FormatToken::isSimpleTypeSpecifier() const {
   }
 }
 
-bool FormatToken::isTypeOrIdentifier() const {
-  return isSimpleTypeSpecifier() || Tok.isOneOf(tok::kw_auto, tok::identifier);
+// Sorted common C++ non-keyword types.
+static SmallVector CppNonKeywordTypes = {
+    "clock_t",  "int16_t",   "int32_t", "int64_t",   "int8_t",
+    "intptr_t", "ptrdiff_t", "size_t",  "time_t",    "uint16_t",
+    "uint32_t", "uint64_t",  "uint8_t", "uintptr_t",
+};
+
+bool FormatToken::isTypeName(bool IsCpp) const {
+  return is(TT_TypeName) || isSimpleTypeSpecifier() ||
+         (IsCpp && is(tok::identifier) &&
+          std::binary_search(CppNonKeywordTypes.begin(),
+                             CppNonKeywordTypes.end(), TokenText));
+}
+
+bool FormatToken::isTypeOrIdentifier(bool IsCpp) const {
+  return isTypeName(IsCpp) || isOneOf(tok::kw_auto, tok::identifier);
 }
 
 bool FormatToken::isBlockIndentedInitRBrace(const FormatStyle &Style) const {
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 312454950419600b15775f4c703c262fab148126..f4566e4a335138ebcf359af24a76f86ae8a3c3c9 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -676,7 +676,9 @@ public:
   /// Determine whether the token is a simple-type-specifier.
   [[nodiscard]] bool isSimpleTypeSpecifier() const;
 
-  [[nodiscard]] bool isTypeOrIdentifier() const;
+  [[nodiscard]] bool isTypeName(bool IsCpp) const;
+
+  [[nodiscard]] bool isTypeOrIdentifier(bool IsCpp) const;
 
   bool isObjCAccessSpecifier() const {
     return is(tok::at) && Next &&
diff --git a/clang/lib/Format/QualifierAlignmentFixer.cpp b/clang/lib/Format/QualifierAlignmentFixer.cpp
index 0c63d330b5aed47906d9e333c15b745a2fd4a6e9..c263530456727cf77f5d22dad68b12bdc576ecc9 100644
--- a/clang/lib/Format/QualifierAlignmentFixer.cpp
+++ b/clang/lib/Format/QualifierAlignmentFixer.cpp
@@ -268,11 +268,13 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight(
   if (isPossibleMacro(TypeToken))
     return Tok;
 
+  const bool IsCpp = Style.isCpp();
+
   // The case `const long long int volatile` -> `long long int const volatile`
   // The case `long const long int volatile` -> `long long int const volatile`
   // The case `long long volatile int const` -> `long long int const volatile`
   // The case `const long long volatile int` -> `long long int const volatile`
-  if (TypeToken->isSimpleTypeSpecifier()) {
+  if (TypeToken->isTypeName(IsCpp)) {
     // The case `const decltype(foo)` -> `const decltype(foo)`
     // The case `const typeof(foo)` -> `const typeof(foo)`
     // The case `const _Atomic(foo)` -> `const _Atomic(foo)`
@@ -280,8 +282,10 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight(
       return Tok;
 
     const FormatToken *LastSimpleTypeSpecifier = TypeToken;
-    while (isQualifierOrType(LastSimpleTypeSpecifier->getNextNonComment()))
+    while (isQualifierOrType(LastSimpleTypeSpecifier->getNextNonComment(),
+                             IsCpp)) {
       LastSimpleTypeSpecifier = LastSimpleTypeSpecifier->getNextNonComment();
+    }
 
     rotateTokens(SourceMgr, Fixes, Tok, LastSimpleTypeSpecifier,
                  /*Left=*/false);
@@ -291,7 +295,7 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight(
   // The case  `unsigned short const` -> `unsigned short const`
   // The case:
   // `unsigned short volatile const` -> `unsigned short const volatile`
-  if (PreviousCheck && PreviousCheck->isSimpleTypeSpecifier()) {
+  if (PreviousCheck && PreviousCheck->isTypeName(IsCpp)) {
     if (LastQual != Tok)
       rotateTokens(SourceMgr, Fixes, Tok, LastQual, /*Left=*/false);
     return Tok;
@@ -408,11 +412,11 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeLeft(
   // The case `volatile long long const int` -> `const volatile long long int`
   // The case `const long long volatile int` -> `const volatile long long int`
   // The case `long volatile long int const` -> `const volatile long long int`
-  if (TypeToken->isSimpleTypeSpecifier()) {
+  if (const bool IsCpp = Style.isCpp(); TypeToken->isTypeName(IsCpp)) {
     const FormatToken *LastSimpleTypeSpecifier = TypeToken;
     while (isConfiguredQualifierOrType(
         LastSimpleTypeSpecifier->getPreviousNonComment(),
-        ConfiguredQualifierTokens)) {
+        ConfiguredQualifierTokens, IsCpp)) {
       LastSimpleTypeSpecifier =
           LastSimpleTypeSpecifier->getPreviousNonComment();
     }
@@ -610,16 +614,16 @@ void prepareLeftRightOrderingForQualifierAlignmentFixer(
   }
 }
 
-bool LeftRightQualifierAlignmentFixer::isQualifierOrType(
-    const FormatToken *const Tok) {
-  return Tok && (Tok->isSimpleTypeSpecifier() || Tok->is(tok::kw_auto) ||
-                 isQualifier(Tok));
+bool LeftRightQualifierAlignmentFixer::isQualifierOrType(const FormatToken *Tok,
+                                                         bool IsCpp) {
+  return Tok &&
+         (Tok->isTypeName(IsCpp) || Tok->is(tok::kw_auto) || isQualifier(Tok));
 }
 
 bool LeftRightQualifierAlignmentFixer::isConfiguredQualifierOrType(
-    const FormatToken *const Tok,
-    const std::vector &Qualifiers) {
-  return Tok && (Tok->isSimpleTypeSpecifier() || Tok->is(tok::kw_auto) ||
+    const FormatToken *Tok, const std::vector &Qualifiers,
+    bool IsCpp) {
+  return Tok && (Tok->isTypeName(IsCpp) || Tok->is(tok::kw_auto) ||
                  isConfiguredQualifier(Tok, Qualifiers));
 }
 
diff --git a/clang/lib/Format/QualifierAlignmentFixer.h b/clang/lib/Format/QualifierAlignmentFixer.h
index e922d8005595103cdebc9afecd5bb0922467d2c5..e1cc27e62b13a0cfa2f9313dab534f7416fa56c9 100644
--- a/clang/lib/Format/QualifierAlignmentFixer.h
+++ b/clang/lib/Format/QualifierAlignmentFixer.h
@@ -71,10 +71,11 @@ public:
                                  tok::TokenKind QualifierType);
 
   // Is the Token a simple or qualifier type
-  static bool isQualifierOrType(const FormatToken *Tok);
+  static bool isQualifierOrType(const FormatToken *Tok, bool IsCpp = true);
   static bool
   isConfiguredQualifierOrType(const FormatToken *Tok,
-                              const std::vector &Qualifiers);
+                              const std::vector &Qualifiers,
+                              bool IsCpp = true);
 
   // Is the Token likely a Macro
   static bool isPossibleMacro(const FormatToken *Tok);
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 04f0374b674e53ad71e538ce4a90b2dd14a0868e..d7b84e309e09644fabc2604b6dc11615a6c1411e 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -562,7 +562,7 @@ private:
           (CurrentToken->is(tok::l_paren) && CurrentToken->Next &&
            CurrentToken->Next->isOneOf(tok::star, tok::amp, tok::caret));
       if ((CurrentToken->Previous->isOneOf(tok::kw_const, tok::kw_auto) ||
-           CurrentToken->Previous->isSimpleTypeSpecifier()) &&
+           CurrentToken->Previous->isTypeName(IsCpp)) &&
           !(CurrentToken->is(tok::l_brace) ||
             (CurrentToken->is(tok::l_paren) && !ProbablyFunctionTypeLParen))) {
         Contexts.back().IsExpression = false;
@@ -2573,7 +2573,7 @@ private:
       return true;
 
     // MyClass a;
-    if (PreviousNotConst->isSimpleTypeSpecifier())
+    if (PreviousNotConst->isTypeName(IsCpp))
       return true;
 
     // type[] a in Java
@@ -2704,9 +2704,10 @@ private:
     }
 
     // Heuristically try to determine whether the parentheses contain a type.
-    auto IsQualifiedPointerOrReference = [](FormatToken *T) {
+    auto IsQualifiedPointerOrReference = [this](FormatToken *T) {
       // This is used to handle cases such as x = (foo *const)&y;
-      assert(!T->isSimpleTypeSpecifier() && "Should have already been checked");
+      assert(!T->isTypeName(IsCpp) && "Should have already been checked");
+      (void)IsCpp; // Avoid -Wunused-lambda-capture when assertion is disabled.
       // Strip trailing qualifiers such as const or volatile when checking
       // whether the parens could be a cast to a pointer/reference type.
       while (T) {
@@ -2738,7 +2739,7 @@ private:
     bool ParensAreType =
         !Tok.Previous ||
         Tok.Previous->isOneOf(TT_TemplateCloser, TT_TypeDeclarationParen) ||
-        Tok.Previous->isSimpleTypeSpecifier() ||
+        Tok.Previous->isTypeName(IsCpp) ||
         IsQualifiedPointerOrReference(Tok.Previous);
     bool ParensCouldEndDecl =
         Tok.Next->isOneOf(tok::equal, tok::semi, tok::l_brace, tok::greater);
@@ -3595,7 +3596,8 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
   if (!Current.Tok.getIdentifierInfo())
     return false;
 
-  auto skipOperatorName = [](const FormatToken *Next) -> const FormatToken * {
+  auto skipOperatorName =
+      [IsCpp](const FormatToken *Next) -> const FormatToken * {
     for (; Next; Next = Next->Next) {
       if (Next->is(TT_OverloadedOperatorLParen))
         return Next;
@@ -3614,7 +3616,7 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
         Next = Next->Next;
         continue;
       }
-      if ((Next->isSimpleTypeSpecifier() || Next->is(tok::identifier)) &&
+      if ((Next->isTypeName(IsCpp) || Next->is(tok::identifier)) &&
           Next->Next && Next->Next->isPointerOrReference()) {
         // For operator void*(), operator char*(), operator Foo*().
         Next = Next->Next;
@@ -3712,9 +3714,8 @@ static bool isFunctionDeclarationName(bool IsCpp, const FormatToken &Current,
       Tok = Tok->MatchingParen;
       continue;
     }
-    if (Tok->is(tok::kw_const) || Tok->isSimpleTypeSpecifier() ||
-        Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis,
-                     TT_TypeName)) {
+    if (Tok->is(tok::kw_const) || Tok->isTypeName(IsCpp) ||
+        Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis)) {
       return true;
     }
     if (Tok->isOneOf(tok::l_brace, TT_ObjCMethodExpr) || Tok->Tok.isLiteral())
@@ -4376,7 +4377,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
     if (Left.Tok.isLiteral())
       return true;
     // for (auto a = 0, b = 0; const auto & c : {1, 2, 3})
-    if (Left.isTypeOrIdentifier() && Right.Next && Right.Next->Next &&
+    if (Left.isTypeOrIdentifier(IsCpp) && Right.Next && Right.Next->Next &&
         Right.Next->Next->is(TT_RangeBasedForLoopColon)) {
       return getTokenPointerOrReferenceAlignment(Right) !=
              FormatStyle::PAS_Left;
@@ -4419,8 +4420,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
     if (Right.is(tok::l_brace) && Right.is(BK_Block))
       return true;
     // for (auto a = 0, b = 0; const auto& c : {1, 2, 3})
-    if (Left.Previous && Left.Previous->isTypeOrIdentifier() && Right.Next &&
-        Right.Next->is(TT_RangeBasedForLoopColon)) {
+    if (Left.Previous && Left.Previous->isTypeOrIdentifier(IsCpp) &&
+        Right.Next && Right.Next->is(TT_RangeBasedForLoopColon)) {
       return getTokenPointerOrReferenceAlignment(Left) !=
              FormatStyle::PAS_Right;
     }
@@ -4458,7 +4459,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
   if (Right.isPointerOrReference()) {
     const FormatToken *Previous = &Left;
     while (Previous && Previous->isNot(tok::kw_operator)) {
-      if (Previous->is(tok::identifier) || Previous->isSimpleTypeSpecifier()) {
+      if (Previous->is(tok::identifier) || Previous->isTypeName(IsCpp)) {
         Previous = Previous->getPreviousNonComment();
         continue;
       }
@@ -4647,7 +4648,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
   if (!Style.isVerilog() &&
       (Left.isOneOf(tok::identifier, tok::greater, tok::r_square,
                     tok::r_paren) ||
-       Left.isSimpleTypeSpecifier()) &&
+       Left.isTypeName(IsCpp)) &&
       Right.is(tok::l_brace) && Right.getNextNonComment() &&
       Right.isNot(BK_Block)) {
     return false;
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 2ce291da11b86ae822b610685694927cb1678cdc..e3f0af176b567d1bfc15153714e765423ede3005 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -1865,8 +1865,7 @@ void UnwrappedLineParser::parseStructuralElement(
     case tok::caret:
       nextToken();
       // Block return type.
-      if (FormatTok->Tok.isAnyIdentifier() ||
-          FormatTok->isSimpleTypeSpecifier()) {
+      if (FormatTok->Tok.isAnyIdentifier() || FormatTok->isTypeName(IsCpp)) {
         nextToken();
         // Return types: pointers are ok too.
         while (FormatTok->is(tok::star))
@@ -2222,7 +2221,7 @@ bool UnwrappedLineParser::tryToParseLambda() {
   bool InTemplateParameterList = false;
 
   while (FormatTok->isNot(tok::l_brace)) {
-    if (FormatTok->isSimpleTypeSpecifier()) {
+    if (FormatTok->isTypeName(IsCpp)) {
       nextToken();
       continue;
     }
@@ -3415,7 +3414,7 @@ bool clang::format::UnwrappedLineParser::parseRequires() {
     break;
   }
   default:
-    if (PreviousNonComment->isTypeOrIdentifier()) {
+    if (PreviousNonComment->isTypeOrIdentifier(IsCpp)) {
       // This is a requires clause.
       parseRequiresClause(RequiresToken);
       return true;
@@ -3478,7 +3477,7 @@ bool clang::format::UnwrappedLineParser::parseRequires() {
       --OpenAngles;
       break;
     default:
-      if (NextToken->isSimpleTypeSpecifier()) {
+      if (NextToken->isTypeName(IsCpp)) {
         FormatTok = Tokens->setPosition(StoredPosition);
         parseRequiresExpression(RequiresToken);
         return false;
@@ -3962,8 +3961,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
       }
       if (FormatTok->is(tok::l_square)) {
         FormatToken *Previous = FormatTok->Previous;
-        if (!Previous ||
-            !(Previous->is(tok::r_paren) || Previous->isTypeOrIdentifier())) {
+        if (!Previous || (Previous->isNot(tok::r_paren) &&
+                          !Previous->isTypeOrIdentifier(IsCpp))) {
           // Don't try parsing a lambda if we had a closing parenthesis before,
           // it was probably a pointer to an array: int (*)[].
           if (!tryToParseLambda())
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 444ffff307377511f05cec379abe84870941717d..ec4e68209d657d93398f3d845562c8bb30d3de33 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1591,6 +1591,14 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
   }
 }
 
+static void checkConfigMacros(Preprocessor &PP, Module *M,
+                              SourceLocation ImportLoc) {
+  clang::Module *TopModule = M->getTopLevelModule();
+  for (const StringRef ConMacro : TopModule->ConfigMacros) {
+    checkConfigMacro(PP, ConMacro, M, ImportLoc);
+  }
+}
+
 /// Write a new timestamp file with the given path.
 static void writeTimestampFile(StringRef TimestampFile) {
   std::error_code EC;
@@ -1829,6 +1837,13 @@ ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST(
   Module *M =
       HS.lookupModule(ModuleName, ImportLoc, true, !IsInclusionDirective);
 
+  // Check for any configuration macros that have changed. This is done
+  // immediately before potentially building a module in case this module
+  // depends on having one of its configuration macros defined to successfully
+  // build. If this is not done the user will never see the warning.
+  if (M)
+    checkConfigMacros(getPreprocessor(), M, ImportLoc);
+
   // Select the source and filename for loading the named module.
   std::string ModuleFilename;
   ModuleSource Source =
@@ -2006,12 +2021,23 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
   if (auto MaybeModule = MM.getCachedModuleLoad(*Path[0].first)) {
     // Use the cached result, which may be nullptr.
     Module = *MaybeModule;
+    // Config macros are already checked before building a module, but they need
+    // to be checked at each import location in case any of the config macros
+    // have a new value at the current `ImportLoc`.
+    if (Module)
+      checkConfigMacros(getPreprocessor(), Module, ImportLoc);
   } else if (ModuleName == getLangOpts().CurrentModule) {
     // This is the module we're building.
     Module = PP->getHeaderSearchInfo().lookupModule(
         ModuleName, ImportLoc, /*AllowSearch*/ true,
         /*AllowExtraModuleMapSearch*/ !IsInclusionDirective);
 
+    // Config macros do not need to be checked here for two reasons.
+    // * This will always be textual inclusion, and thus the config macros
+    //   actually do impact the content of the header.
+    // * `Preprocessor::HandleHeaderIncludeOrImport` will never call this
+    //   function as the `#include` or `#import` is textual.
+
     MM.cacheModuleLoad(*Path[0].first, Module);
   } else {
     ModuleLoadResult Result = findOrCompileModuleAndReadAST(
@@ -2146,18 +2172,11 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
     TheASTReader->makeModuleVisible(Module, Visibility, ImportLoc);
   }
 
-  // Check for any configuration macros that have changed.
-  clang::Module *TopModule = Module->getTopLevelModule();
-  for (unsigned I = 0, N = TopModule->ConfigMacros.size(); I != N; ++I) {
-    checkConfigMacro(getPreprocessor(), TopModule->ConfigMacros[I],
-                     Module, ImportLoc);
-  }
-
   // Resolve any remaining module using export_as for this one.
   getPreprocessor()
       .getHeaderSearchInfo()
       .getModuleMap()
-      .resolveLinkAsDependencies(TopModule);
+      .resolveLinkAsDependencies(Module->getTopLevelModule());
 
   LastModuleImportLoc = ImportLoc;
   LastModuleImportResult = ModuleLoadResult(Module);
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 691f3b989b81e566b0240cad400fb2be324d2290..451bdb9386f58779ef0c6ab4e6e3b96bece176a7 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2556,6 +2556,8 @@ static const auto &getFrontendActionTable() {
 
       {frontend::GenerateModule, OPT_emit_module},
       {frontend::GenerateModuleInterface, OPT_emit_module_interface},
+      {frontend::GenerateReducedModuleInterface,
+       OPT_emit_reduced_module_interface},
       {frontend::GenerateHeaderUnit, OPT_emit_header_unit},
       {frontend::GeneratePCH, OPT_emit_pch},
       {frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs},
@@ -4280,6 +4282,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
   case frontend::FixIt:
   case frontend::GenerateModule:
   case frontend::GenerateModuleInterface:
+  case frontend::GenerateReducedModuleInterface:
   case frontend::GenerateHeaderUnit:
   case frontend::GeneratePCH:
   case frontend::GenerateInterfaceStubs:
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index b9ed5dedfa42235b30a259d7ee8fc41945321ae3..50338bfa670f8302e529c614d85eb2f82446e858 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -184,12 +184,12 @@ bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI) {
   return true;
 }
 
-std::unique_ptr
-GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
-                                        StringRef InFile) {
+std::vector>
+GenerateModuleAction::CreateMultiplexConsumer(CompilerInstance &CI,
+                                              StringRef InFile) {
   std::unique_ptr OS = CreateOutputFile(CI, InFile);
   if (!OS)
-    return nullptr;
+    return {};
 
   std::string OutputFile = CI.getFrontendOpts().OutputFile;
   std::string Sysroot;
@@ -210,6 +210,17 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
       +CI.getFrontendOpts().BuildingImplicitModule));
   Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(
       CI, std::string(InFile), OutputFile, std::move(OS), Buffer));
+  return Consumers;
+}
+
+std::unique_ptr
+GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
+                                        StringRef InFile) {
+  std::vector> Consumers =
+      CreateMultiplexConsumer(CI, InFile);
+  if (Consumers.empty())
+    return nullptr;
+
   return std::make_unique(std::move(Consumers));
 }
 
@@ -265,7 +276,12 @@ GenerateModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,
   CI.getHeaderSearchOpts().ModulesSkipHeaderSearchPaths = true;
   CI.getHeaderSearchOpts().ModulesSkipPragmaDiagnosticMappings = true;
 
-  return GenerateModuleAction::CreateASTConsumer(CI, InFile);
+  std::vector> Consumers =
+      CreateMultiplexConsumer(CI, InFile);
+  if (Consumers.empty())
+    return nullptr;
+
+  return std::make_unique(std::move(Consumers));
 }
 
 std::unique_ptr
@@ -274,6 +290,16 @@ GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,
   return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
 }
 
+std::unique_ptr
+GenerateReducedModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,
+                                                        StringRef InFile) {
+  auto Buffer = std::make_shared();
+  return std::make_unique(
+      CI.getPreprocessor(), CI.getModuleCache(),
+      CI.getFrontendOpts().OutputFile, Buffer,
+      /*IncludeTimestamps=*/+CI.getFrontendOpts().IncludeTimestamps);
+}
+
 bool GenerateHeaderUnitAction::BeginSourceFileAction(CompilerInstance &CI) {
   if (!CI.getLangOpts().CPlusPlusModules) {
     CI.getDiagnostics().Report(diag::err_module_interface_requires_cpp_modules);
@@ -839,7 +865,6 @@ void DumpModuleInfoAction::ExecuteAction() {
 
   const LangOptions &LO = getCurrentASTUnit().getLangOpts();
   if (LO.CPlusPlusModules && !LO.CurrentModule.empty()) {
-
     ASTReader *R = getCurrentASTUnit().getASTReader().get();
     unsigned SubModuleCount = R->getTotalNumSubmodules();
     serialization::ModuleFile &MF = R->getModuleManager().getPrimaryModule();
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 9b979d810fa127bf2f23ebd8576feb06c8be9cd8..48ad92063bd46165c5ed481c38708fe4a6733090 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -736,7 +736,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
   }
   // C++23 features.
   if (LangOpts.CPlusPlus23) {
-    Builder.defineMacro("__cpp_implicit_move", "202011L");
+    Builder.defineMacro("__cpp_implicit_move", "202207L");
     Builder.defineMacro("__cpp_size_t_suffix", "202011L");
     Builder.defineMacro("__cpp_if_consteval", "202106L");
     Builder.defineMacro("__cpp_multidimensional_subscript", "202211L");
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 925879a68cbd094aae691ebdd6b7aa88924fa0ca..2446aee571f440e9ee95803d7962325f8e4f9e95 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -65,6 +65,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
     return std::make_unique();
   case GenerateModuleInterface:
     return std::make_unique();
+  case GenerateReducedModuleInterface:
+    return std::make_unique();
   case GenerateHeaderUnit:
     return std::make_unique();
   case GeneratePCH:            return std::make_unique();
diff --git a/clang/lib/Headers/avxintrin.h b/clang/lib/Headers/avxintrin.h
index f116d8bc3a94c726fcae3aa9dc44087fd58f842d..ecd9bf18a41ca0d9ceb5bbf73d402c3cdbeff778 100644
--- a/clang/lib/Headers/avxintrin.h
+++ b/clang/lib/Headers/avxintrin.h
@@ -1574,14 +1574,6 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
                                      (__v4df)(__m256d)(b), (int)(mask)))
 
 /* Compare */
-#define _CMP_EQ_OQ    0x00 /* Equal (ordered, non-signaling)  */
-#define _CMP_LT_OS    0x01 /* Less-than (ordered, signaling)  */
-#define _CMP_LE_OS    0x02 /* Less-than-or-equal (ordered, signaling)  */
-#define _CMP_UNORD_Q  0x03 /* Unordered (non-signaling)  */
-#define _CMP_NEQ_UQ   0x04 /* Not-equal (unordered, non-signaling)  */
-#define _CMP_NLT_US   0x05 /* Not-less-than (unordered, signaling)  */
-#define _CMP_NLE_US   0x06 /* Not-less-than-or-equal (unordered, signaling)  */
-#define _CMP_ORD_Q    0x07 /* Ordered (non-signaling)   */
 #define _CMP_EQ_UQ    0x08 /* Equal (unordered, non-signaling)  */
 #define _CMP_NGE_US   0x09 /* Not-greater-than-or-equal (unordered, signaling)  */
 #define _CMP_NGT_US   0x0a /* Not-greater-than (unordered, signaling)  */
@@ -1607,6 +1599,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
 #define _CMP_GT_OQ    0x1e /* Greater-than (ordered, non-signaling)  */
 #define _CMP_TRUE_US  0x1f /* True (unordered, signaling)  */
 
+/* Below intrinsic defined in emmintrin.h can be used for AVX */
 /// Compares each of the corresponding double-precision values of two
 ///    128-bit vectors of [2 x double], using the operation specified by the
 ///    immediate integer operand.
@@ -1663,10 +1656,9 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
 ///    0x1E: Greater-than (ordered, non-signaling) \n
 ///    0x1F: True (unordered, signaling)
 /// \returns A 128-bit vector of [2 x double] containing the comparison results.
-#define _mm_cmp_pd(a, b, c) \
-  ((__m128d)__builtin_ia32_cmppd((__v2df)(__m128d)(a), \
-                                 (__v2df)(__m128d)(b), (c)))
+/// \fn __m128d _mm_cmp_pd(__m128d a, __m128d b, const int c)
 
+/* Below intrinsic defined in xmmintrin.h can be used for AVX */
 /// Compares each of the corresponding values of two 128-bit vectors of
 ///    [4 x float], using the operation specified by the immediate integer
 ///    operand.
@@ -1723,9 +1715,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
 ///    0x1E: Greater-than (ordered, non-signaling) \n
 ///    0x1F: True (unordered, signaling)
 /// \returns A 128-bit vector of [4 x float] containing the comparison results.
-#define _mm_cmp_ps(a, b, c) \
-  ((__m128)__builtin_ia32_cmpps((__v4sf)(__m128)(a), \
-                                (__v4sf)(__m128)(b), (c)))
+/// \fn __m128 _mm_cmp_ps(__m128 a, __m128 b, const int c)
 
 /// Compares each of the corresponding double-precision values of two
 ///    256-bit vectors of [4 x double], using the operation specified by the
@@ -1847,6 +1837,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
   ((__m256)__builtin_ia32_cmpps256((__v8sf)(__m256)(a), \
                                    (__v8sf)(__m256)(b), (c)))
 
+/* Below intrinsic defined in emmintrin.h can be used for AVX */
 /// Compares each of the corresponding scalar double-precision values of
 ///    two 128-bit vectors of [2 x double], using the operation specified by the
 ///    immediate integer operand.
@@ -1902,10 +1893,9 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
 ///    0x1E: Greater-than (ordered, non-signaling) \n
 ///    0x1F: True (unordered, signaling)
 /// \returns A 128-bit vector of [2 x double] containing the comparison results.
-#define _mm_cmp_sd(a, b, c) \
-  ((__m128d)__builtin_ia32_cmpsd((__v2df)(__m128d)(a), \
-                                 (__v2df)(__m128d)(b), (c)))
+/// \fn __m128d _mm_cmp_sd(__m128d a, __m128d b, const int c)
 
+/* Below intrinsic defined in xmmintrin.h can be used for AVX */
 /// Compares each of the corresponding scalar values of two 128-bit
 ///    vectors of [4 x float], using the operation specified by the immediate
 ///    integer operand.
@@ -1961,9 +1951,7 @@ _mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __c)
 ///    0x1E: Greater-than (ordered, non-signaling) \n
 ///    0x1F: True (unordered, signaling)
 /// \returns A 128-bit vector of [4 x float] containing the comparison results.
-#define _mm_cmp_ss(a, b, c) \
-  ((__m128)__builtin_ia32_cmpss((__v4sf)(__m128)(a), \
-                                (__v4sf)(__m128)(b), (c)))
+/// \fn __m128 _mm_cmp_ss(__m128 a, __m128 b, const int c)
 
 /// Takes a [8 x i32] vector and returns the vector element value
 ///    indexed by the immediate constant operand.
diff --git a/clang/lib/Headers/emmintrin.h b/clang/lib/Headers/emmintrin.h
index 1d451b5f5b25de4afe105ef7ea8e9212d26826d4..984f0cf917e99bf576b4ab82c80a07106be86c65 100644
--- a/clang/lib/Headers/emmintrin.h
+++ b/clang/lib/Headers/emmintrin.h
@@ -410,8 +410,9 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_xor_pd(__m128d __a,
 }
 
 /// Compares each of the corresponding double-precision values of the
-///    128-bit vectors of [2 x double] for equality. Each comparison yields 0x0
-///    for false, 0xFFFFFFFFFFFFFFFF for true.
+///    128-bit vectors of [2 x double] for equality.
+///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
 ///
 /// \headerfile 
 ///
@@ -429,8 +430,9 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpeq_pd(__m128d __a,
 
 /// Compares each of the corresponding double-precision values of the
 ///    128-bit vectors of [2 x double] to determine if the values in the first
-///    operand are less than those in the second operand. Each comparison
-///    yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
+///    operand are less than those in the second operand.
+///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
 ///
 /// \headerfile 
 ///
@@ -949,8 +951,8 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpnge_sd(__m128d __a,
 /// Compares the lower double-precision floating-point values in each of
 ///    the two 128-bit floating-point vectors of [2 x double] for equality.
 ///
-///    The comparison yields 0 for false, 1 for true. If either of the two
-///    lower double-precision values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower double-precision values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -962,8 +964,7 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_cmpnge_sd(__m128d __a,
 /// \param __b
 ///    A 128-bit vector of [2 x double]. The lower double-precision value is
 ///    compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results. If either of the two
-///    lower double-precision values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS _mm_comieq_sd(__m128d __a,
                                                        __m128d __b) {
   return __builtin_ia32_comisdeq((__v2df)__a, (__v2df)__b);
@@ -974,8 +975,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comieq_sd(__m128d __a,
 ///    the value in the first parameter is less than the corresponding value in
 ///    the second parameter.
 ///
-///    The comparison yields 0 for false, 1 for true. If either of the two
-///    lower double-precision values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower double-precision values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -987,8 +988,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comieq_sd(__m128d __a,
 /// \param __b
 ///    A 128-bit vector of [2 x double]. The lower double-precision value is
 ///    compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results. If either of the two
-///     lower double-precision values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS _mm_comilt_sd(__m128d __a,
                                                        __m128d __b) {
   return __builtin_ia32_comisdlt((__v2df)__a, (__v2df)__b);
@@ -999,8 +999,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comilt_sd(__m128d __a,
 ///    the value in the first parameter is less than or equal to the
 ///    corresponding value in the second parameter.
 ///
-///    The comparison yields 0 for false, 1 for true. If either of the two
-///    lower double-precision values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower double-precision values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1012,8 +1012,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comilt_sd(__m128d __a,
 /// \param __b
 ///     A 128-bit vector of [2 x double]. The lower double-precision value is
 ///     compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results. If either of the two
-///     lower double-precision values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS _mm_comile_sd(__m128d __a,
                                                        __m128d __b) {
   return __builtin_ia32_comisdle((__v2df)__a, (__v2df)__b);
@@ -1024,8 +1023,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comile_sd(__m128d __a,
 ///    the value in the first parameter is greater than the corresponding value
 ///    in the second parameter.
 ///
-///    The comparison yields 0 for false, 1 for true. If either of the two
-///    lower double-precision values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower double-precision values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1037,8 +1036,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comile_sd(__m128d __a,
 /// \param __b
 ///    A 128-bit vector of [2 x double]. The lower double-precision value is
 ///    compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results. If either of the two
-///     lower double-precision values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS _mm_comigt_sd(__m128d __a,
                                                        __m128d __b) {
   return __builtin_ia32_comisdgt((__v2df)__a, (__v2df)__b);
@@ -1049,8 +1047,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comigt_sd(__m128d __a,
 ///    the value in the first parameter is greater than or equal to the
 ///    corresponding value in the second parameter.
 ///
-///    The comparison yields 0 for false, 1 for true. If either of the two
-///    lower double-precision values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower double-precision values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1062,8 +1060,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comigt_sd(__m128d __a,
 /// \param __b
 ///    A 128-bit vector of [2 x double]. The lower double-precision value is
 ///    compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results. If either of the two
-///    lower double-precision values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS _mm_comige_sd(__m128d __a,
                                                        __m128d __b) {
   return __builtin_ia32_comisdge((__v2df)__a, (__v2df)__b);
@@ -1074,7 +1071,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comige_sd(__m128d __a,
 ///    the value in the first parameter is unequal to the corresponding value in
 ///    the second parameter.
 ///
-///    The comparison yields 0 for false, 1 for true. If either of the two
+///    The comparison returns 0 for false, 1 for true. If either of the two
 ///    lower double-precision values is NaN, 1 is returned.
 ///
 /// \headerfile 
@@ -1087,18 +1084,17 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comige_sd(__m128d __a,
 /// \param __b
 ///    A 128-bit vector of [2 x double]. The lower double-precision value is
 ///    compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results. If either of the two
-///     lower double-precision values is NaN, 1 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS _mm_comineq_sd(__m128d __a,
                                                         __m128d __b) {
   return __builtin_ia32_comisdneq((__v2df)__a, (__v2df)__b);
 }
 
 /// Compares the lower double-precision floating-point values in each of
-///    the two 128-bit floating-point vectors of [2 x double] for equality. The
-///    comparison yields 0 for false, 1 for true.
+///    the two 128-bit floating-point vectors of [2 x double] for equality.
 ///
-///    If either of the two lower double-precision values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower double-precision values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1110,8 +1106,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_comineq_sd(__m128d __a,
 /// \param __b
 ///    A 128-bit vector of [2 x double]. The lower double-precision value is
 ///    compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results. If either of the two
-///    lower double-precision values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomieq_sd(__m128d __a,
                                                         __m128d __b) {
   return __builtin_ia32_ucomisdeq((__v2df)__a, (__v2df)__b);
@@ -1122,8 +1117,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomieq_sd(__m128d __a,
 ///    the value in the first parameter is less than the corresponding value in
 ///    the second parameter.
 ///
-///    The comparison yields 0 for false, 1 for true. If either of the two lower
-///    double-precision values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower double-precision values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1135,8 +1130,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomieq_sd(__m128d __a,
 /// \param __b
 ///    A 128-bit vector of [2 x double]. The lower double-precision value is
 ///    compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results. If either of the two
-///    lower double-precision values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomilt_sd(__m128d __a,
                                                         __m128d __b) {
   return __builtin_ia32_ucomisdlt((__v2df)__a, (__v2df)__b);
@@ -1147,8 +1141,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomilt_sd(__m128d __a,
 ///    the value in the first parameter is less than or equal to the
 ///    corresponding value in the second parameter.
 ///
-///    The comparison yields 0 for false, 1 for true. If either of the two lower
-///    double-precision values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower double-precision values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1160,8 +1154,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomilt_sd(__m128d __a,
 /// \param __b
 ///     A 128-bit vector of [2 x double]. The lower double-precision value is
 ///     compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results. If either of the two
-///     lower double-precision values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomile_sd(__m128d __a,
                                                         __m128d __b) {
   return __builtin_ia32_ucomisdle((__v2df)__a, (__v2df)__b);
@@ -1172,8 +1165,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomile_sd(__m128d __a,
 ///    the value in the first parameter is greater than the corresponding value
 ///    in the second parameter.
 ///
-///    The comparison yields 0 for false, 1 for true. If either of the two lower
-///    double-precision values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower double-precision values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1185,8 +1178,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomile_sd(__m128d __a,
 /// \param __b
 ///     A 128-bit vector of [2 x double]. The lower double-precision value is
 ///     compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results. If either of the two
-///     lower double-precision values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomigt_sd(__m128d __a,
                                                         __m128d __b) {
   return __builtin_ia32_ucomisdgt((__v2df)__a, (__v2df)__b);
@@ -1197,8 +1189,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomigt_sd(__m128d __a,
 ///    the value in the first parameter is greater than or equal to the
 ///    corresponding value in the second parameter.
 ///
-///    The comparison yields 0 for false, 1 for true.  If either of the two
-///    lower double-precision values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true.  If either of the two
+///    lower double-precision values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1210,8 +1202,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomigt_sd(__m128d __a,
 /// \param __b
 ///    A 128-bit vector of [2 x double]. The lower double-precision value is
 ///    compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison results. If either of the two
-///    lower double-precision values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomige_sd(__m128d __a,
                                                         __m128d __b) {
   return __builtin_ia32_ucomisdge((__v2df)__a, (__v2df)__b);
@@ -1222,8 +1213,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomige_sd(__m128d __a,
 ///    the value in the first parameter is unequal to the corresponding value in
 ///    the second parameter.
 ///
-///    The comparison yields 0 for false, 1 for true. If either of the two lower
-///    double-precision values is NaN, 1 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower double-precision values is NaN, 1 is returned.
 ///
 /// \headerfile 
 ///
@@ -1235,8 +1226,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomige_sd(__m128d __a,
 /// \param __b
 ///    A 128-bit vector of [2 x double]. The lower double-precision value is
 ///    compared to the lower double-precision value of \a __a.
-/// \returns An integer containing the comparison result. If either of the two
-///    lower double-precision values is NaN, 1 is returned.
+/// \returns An integer containing the comparison result.
 static __inline__ int __DEFAULT_FN_ATTRS _mm_ucomineq_sd(__m128d __a,
                                                          __m128d __b) {
   return __builtin_ia32_ucomisdneq((__v2df)__a, (__v2df)__b);
@@ -3023,8 +3013,9 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_srl_epi64(__m128i __a,
 }
 
 /// Compares each of the corresponding 8-bit values of the 128-bit
-///    integer vectors for equality. Each comparison yields 0x0 for false, 0xFF
-///    for true.
+///    integer vectors for equality.
+///
+///    Each comparison yields 0x0 for false, 0xFF for true.
 ///
 /// \headerfile 
 ///
@@ -3041,8 +3032,9 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cmpeq_epi8(__m128i __a,
 }
 
 /// Compares each of the corresponding 16-bit values of the 128-bit
-///    integer vectors for equality. Each comparison yields 0x0 for false,
-///    0xFFFF for true.
+///    integer vectors for equality.
+///
+///    Each comparison yields 0x0 for false, 0xFFFF for true.
 ///
 /// \headerfile 
 ///
@@ -3059,8 +3051,9 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cmpeq_epi16(__m128i __a,
 }
 
 /// Compares each of the corresponding 32-bit values of the 128-bit
-///    integer vectors for equality. Each comparison yields 0x0 for false,
-///    0xFFFFFFFF for true.
+///    integer vectors for equality.
+///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
 ///
 /// \headerfile 
 ///
@@ -3078,8 +3071,9 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cmpeq_epi32(__m128i __a,
 
 /// Compares each of the corresponding signed 8-bit values of the 128-bit
 ///    integer vectors to determine if the values in the first operand are
-///    greater than those in the second operand. Each comparison yields 0x0 for
-///    false, 0xFF for true.
+///    greater than those in the second operand.
+///
+///    Each comparison yields 0x0 for false, 0xFF for true.
 ///
 /// \headerfile 
 ///
@@ -4745,6 +4739,74 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_castsi128_pd(__m128i __a) {
   return (__m128d)__a;
 }
 
+/// Compares each of the corresponding double-precision values of two
+///    128-bit vectors of [2 x double], using the operation specified by the
+///    immediate integer operand.
+///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
+///
+/// \headerfile 
+///
+/// \code
+/// __m128d _mm_cmp_pd(__m128d a, __m128d b, const int c);
+/// \endcode
+///
+/// This intrinsic corresponds to the  (V)CMPPD  instruction.
+///
+/// \param a
+///    A 128-bit vector of [2 x double].
+/// \param b
+///    A 128-bit vector of [2 x double].
+/// \param c
+///    An immediate integer operand, with bits [4:0] specifying which comparison
+///    operation to use: \n
+///    0x00: Equal (ordered, non-signaling) \n
+///    0x01: Less-than (ordered, signaling) \n
+///    0x02: Less-than-or-equal (ordered, signaling) \n
+///    0x03: Unordered (non-signaling) \n
+///    0x04: Not-equal (unordered, non-signaling) \n
+///    0x05: Not-less-than (unordered, signaling) \n
+///    0x06: Not-less-than-or-equal (unordered, signaling) \n
+///    0x07: Ordered (non-signaling) \n
+/// \returns A 128-bit vector of [2 x double] containing the comparison results.
+#define _mm_cmp_pd(a, b, c)                                                    \
+  ((__m128d)__builtin_ia32_cmppd((__v2df)(__m128d)(a), (__v2df)(__m128d)(b),   \
+                                 (c)))
+
+/// Compares each of the corresponding scalar double-precision values of
+///    two 128-bit vectors of [2 x double], using the operation specified by the
+///    immediate integer operand.
+///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
+///
+/// \headerfile 
+///
+/// \code
+/// __m128d _mm_cmp_sd(__m128d a, __m128d b, const int c);
+/// \endcode
+///
+/// This intrinsic corresponds to the  (V)CMPSD  instruction.
+///
+/// \param a
+///    A 128-bit vector of [2 x double].
+/// \param b
+///    A 128-bit vector of [2 x double].
+/// \param c
+///    An immediate integer operand, with bits [4:0] specifying which comparison
+///    operation to use: \n
+///    0x00: Equal (ordered, non-signaling) \n
+///    0x01: Less-than (ordered, signaling) \n
+///    0x02: Less-than-or-equal (ordered, signaling) \n
+///    0x03: Unordered (non-signaling) \n
+///    0x04: Not-equal (unordered, non-signaling) \n
+///    0x05: Not-less-than (unordered, signaling) \n
+///    0x06: Not-less-than-or-equal (unordered, signaling) \n
+///    0x07: Ordered (non-signaling) \n
+/// \returns A 128-bit vector of [2 x double] containing the comparison results.
+#define _mm_cmp_sd(a, b, c)                                                    \
+  ((__m128d)__builtin_ia32_cmpsd((__v2df)(__m128d)(a), (__v2df)(__m128d)(b),   \
+                                 (c)))
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
diff --git a/clang/lib/Headers/hlsl/hlsl_basic_types.h b/clang/lib/Headers/hlsl/hlsl_basic_types.h
index 3d0d296aadca3ab2ba8600616e5deb9217b14e7a..da6903df65ffed7b211de81c777aa84d254ee6ce 100644
--- a/clang/lib/Headers/hlsl/hlsl_basic_types.h
+++ b/clang/lib/Headers/hlsl/hlsl_basic_types.h
@@ -42,7 +42,9 @@ typedef vector uint16_t2;
 typedef vector uint16_t3;
 typedef vector uint16_t4;
 #endif
-
+typedef vector bool2;
+typedef vector bool3;
+typedef vector bool4;
 typedef vector int2;
 typedef vector int3;
 typedef vector int4;
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 5180530363889f9f8513242b11f482b026994b33..45f8544392584e49d3c5708b2be329f6d2e7b7e8 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -100,6 +100,118 @@ double3 abs(double3);
 _HLSL_BUILTIN_ALIAS(__builtin_elementwise_abs)
 double4 abs(double4);
 
+//===----------------------------------------------------------------------===//
+// any builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn bool any(T x)
+/// \brief Returns True if any components of the \a x parameter are non-zero;
+/// otherwise, false. \param x The input value.
+
+#ifdef __HLSL_ENABLE_16_BIT
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(int16_t);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(int16_t2);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(int16_t3);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(int16_t4);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(uint16_t);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(uint16_t2);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(uint16_t3);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(uint16_t4);
+#endif
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(bool);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(bool2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(bool3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(bool4);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(int);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(int2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(int3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(int4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(uint);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(uint2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(uint3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(uint4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(float4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(int64_t);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(int64_t2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(int64_t3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(int64_t4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(uint64_t);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(uint64_t2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(uint64_t3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(uint64_t4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(double);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(double2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(double3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_any)
+bool any(double4);
+
 //===----------------------------------------------------------------------===//
 // ceil builtins
 //===----------------------------------------------------------------------===//
@@ -277,6 +389,70 @@ uint64_t dot(uint64_t3, uint64_t3);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_dot)
 uint64_t dot(uint64_t4, uint64_t4);
 
+//===----------------------------------------------------------------------===//
+// exp builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn T exp(T x)
+/// \brief Returns the base-e exponential, or \a e**x, of the specified value.
+/// \param x The specified input value.
+///
+/// The return value is the base-e exponential of the \a x parameter.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp)
+half exp(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp)
+half2 exp(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp)
+half3 exp(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp)
+half4 exp(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp)
+float exp(float);
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp)
+float2 exp(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp)
+float3 exp(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp)
+float4 exp(float4);
+
+//===----------------------------------------------------------------------===//
+// exp2 builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn T exp2(T x)
+/// \brief Returns the base 2 exponential, or \a 2**x, of the specified value.
+/// \param x The specified input value.
+///
+/// The base 2 exponential of the \a x parameter.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2)
+half exp2(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2)
+half2 exp2(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2)
+half3 exp2(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2)
+half4 exp2(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2)
+float exp2(float);
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2)
+float2 exp2(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2)
+float3 exp2(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_exp2)
+float4 exp2(float4);
+
 //===----------------------------------------------------------------------===//
 // floor builtins
 //===----------------------------------------------------------------------===//
@@ -511,6 +687,111 @@ double3 log2(double3);
 _HLSL_BUILTIN_ALIAS(__builtin_elementwise_log2)
 double4 log2(double4);
 
+//===----------------------------------------------------------------------===//
+// mad builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn T mad(T M, T A, T B)
+/// \brief The result of \a M * \a A + \a B.
+/// \param M The multiplication value.
+/// \param A The first addition value.
+/// \param B The second addition value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+half mad(half, half, half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+half2 mad(half2, half2, half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+half3 mad(half3, half3, half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+half4 mad(half4, half4, half4);
+
+#ifdef __HLSL_ENABLE_16_BIT
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+int16_t mad(int16_t, int16_t, int16_t);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+int16_t2 mad(int16_t2, int16_t2, int16_t2);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+int16_t3 mad(int16_t3, int16_t3, int16_t3);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+int16_t4 mad(int16_t4, int16_t4, int16_t4);
+
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+uint16_t mad(uint16_t, uint16_t, uint16_t);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+uint16_t2 mad(uint16_t2, uint16_t2, uint16_t2);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+uint16_t3 mad(uint16_t3, uint16_t3, uint16_t3);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+uint16_t4 mad(uint16_t4, uint16_t4, uint16_t4);
+#endif
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+int mad(int, int, int);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+int2 mad(int2, int2, int2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+int3 mad(int3, int3, int3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+int4 mad(int4, int4, int4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+uint mad(uint, uint, uint);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+uint2 mad(uint2, uint2, uint2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+uint3 mad(uint3, uint3, uint3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+uint4 mad(uint4, uint4, uint4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+int64_t mad(int64_t, int64_t, int64_t);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+int64_t2 mad(int64_t2, int64_t2, int64_t2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+int64_t3 mad(int64_t3, int64_t3, int64_t3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+int64_t4 mad(int64_t4, int64_t4, int64_t4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+uint64_t mad(uint64_t, uint64_t, uint64_t);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+uint64_t2 mad(uint64_t2, uint64_t2, uint64_t2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+uint64_t3 mad(uint64_t3, uint64_t3, uint64_t3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+uint64_t4 mad(uint64_t4, uint64_t4, uint64_t4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+float mad(float, float, float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+float2 mad(float2, float2, float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+float3 mad(float3, float3, float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+float4 mad(float4, float4, float4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+double mad(double, double, double);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+double2 mad(double2, double2, double2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+double3 mad(double3, double3, double3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_mad)
+double4 mad(double4, double4, double4);
+
 //===----------------------------------------------------------------------===//
 // max builtins
 //===----------------------------------------------------------------------===//
@@ -831,6 +1112,47 @@ uint64_t3 reversebits(uint64_t3);
 _HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse)
 uint64_t4 reversebits(uint64_t4);
 
+//===----------------------------------------------------------------------===//
+// rcp builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn T rcp(T x)
+/// \brief Calculates a fast, approximate, per-component reciprocal ie 1 / \a x.
+/// \param x The specified input value.
+///
+/// The return value is the reciprocal of the \a x parameter.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp)
+half rcp(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp)
+half2 rcp(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp)
+half3 rcp(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp)
+half4 rcp(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp)
+float rcp(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp)
+float2 rcp(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp)
+float3 rcp(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp)
+float4 rcp(float4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp)
+double rcp(double);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp)
+double2 rcp(double2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp)
+double3 rcp(double3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_rcp)
+double4 rcp(double4);
+
 //===----------------------------------------------------------------------===//
 // round builtins
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Headers/larchintrin.h b/clang/lib/Headers/larchintrin.h
index a613e5ca0e5ecdb8f355d4bf93a7ad7db2c50841..f4218295919a0d0d633e6a7b2f1bb81f83c96eda 100644
--- a/clang/lib/Headers/larchintrin.h
+++ b/clang/lib/Headers/larchintrin.h
@@ -156,7 +156,7 @@ extern __inline unsigned char
   return (unsigned char)__builtin_loongarch_iocsrrd_b((unsigned int)_1);
 }
 
-extern __inline unsigned char
+extern __inline unsigned short
     __attribute__((__gnu_inline__, __always_inline__, __artificial__))
     __iocsrrd_h(unsigned int _1) {
   return (unsigned short)__builtin_loongarch_iocsrrd_h((unsigned int)_1);
diff --git a/clang/lib/Headers/llvm_libc_wrappers/assert.h b/clang/lib/Headers/llvm_libc_wrappers/assert.h
index de650ca8442a1969a55b6484290a9de1961fb699..610ed96a458c6a09fd3d48b5eb00637865d9c290 100644
--- a/clang/lib/Headers/llvm_libc_wrappers/assert.h
+++ b/clang/lib/Headers/llvm_libc_wrappers/assert.h
@@ -1,4 +1,4 @@
-//===-- Wrapper for C standard assert.h declarations on the GPU ------------===//
+//===-- Wrapper for C standard assert.h declarations on the GPU -*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/Headers/smmintrin.h b/clang/lib/Headers/smmintrin.h
index c52ffb77e33d5c4e986bab30f42d0553312257b9..9fb9cc9b01348cae2302249e55020fc0c36a58fb 100644
--- a/clang/lib/Headers/smmintrin.h
+++ b/clang/lib/Headers/smmintrin.h
@@ -1188,6 +1188,8 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_testnzc_si128(__m128i __M,
 /// Compares each of the corresponding 64-bit values of the 128-bit
 ///    integer vectors for equality.
 ///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
+///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VPCMPEQQ / PCMPEQQ  instruction.
@@ -2301,6 +2303,8 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_minpos_epu16(__m128i __V) {
 ///    integer vectors to determine if the values in the first operand are
 ///    greater than those in the second operand.
 ///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
+///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VPCMPGTQ / PCMPGTQ  instruction.
diff --git a/clang/lib/Headers/xmmintrin.h b/clang/lib/Headers/xmmintrin.h
index 47368f3c23d2d6224d1a2855f0f48bd2de95a36d..8e386a72cde78989cbb0324aaf011ef46bbe11d9 100644
--- a/clang/lib/Headers/xmmintrin.h
+++ b/clang/lib/Headers/xmmintrin.h
@@ -474,7 +474,9 @@ _mm_xor_ps(__m128 __a, __m128 __b)
 }
 
 /// Compares two 32-bit float values in the low-order bits of both
-///    operands for equality and returns the result of the comparison in the
+///    operands for equality.
+///
+///    The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the
 ///    low-order bits of a vector [4 x float].
 ///
 /// \headerfile 
@@ -498,6 +500,8 @@ _mm_cmpeq_ss(__m128 __a, __m128 __b)
 /// Compares each of the corresponding 32-bit float values of the
 ///    128-bit vectors of [4 x float] for equality.
 ///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
+///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VCMPEQPS / CMPEQPS  instructions.
@@ -515,8 +519,10 @@ _mm_cmpeq_ps(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the value in the first operand is less than the
-///    corresponding value in the second operand and returns the result of the
-///    comparison in the low-order bits of a vector of [4 x float].
+///    corresponding value in the second operand.
+///
+///    The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the
+///    low-order bits of a vector of [4 x float].
 ///
 /// \headerfile 
 ///
@@ -540,6 +546,8 @@ _mm_cmplt_ss(__m128 __a, __m128 __b)
 ///    128-bit vectors of [4 x float] to determine if the values in the first
 ///    operand are less than those in the second operand.
 ///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
+///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VCMPLTPS / CMPLTPS  instructions.
@@ -557,9 +565,10 @@ _mm_cmplt_ps(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the value in the first operand is less than or
-///    equal to the corresponding value in the second operand and returns the
-///    result of the comparison in the low-order bits of a vector of
-///    [4 x float].
+///    equal to the corresponding value in the second operand.
+///
+///    The comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true, in
+///    the low-order bits of a vector of [4 x float].
 ///
 /// \headerfile 
 ///
@@ -583,6 +592,8 @@ _mm_cmple_ss(__m128 __a, __m128 __b)
 ///    128-bit vectors of [4 x float] to determine if the values in the first
 ///    operand are less than or equal to those in the second operand.
 ///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
+///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VCMPLEPS / CMPLEPS  instructions.
@@ -600,8 +611,10 @@ _mm_cmple_ps(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the value in the first operand is greater than
-///    the corresponding value in the second operand and returns the result of
-///    the comparison in the low-order bits of a vector of [4 x float].
+///    the corresponding value in the second operand.
+///
+///    The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the
+///    low-order bits of a vector of [4 x float].
 ///
 /// \headerfile 
 ///
@@ -627,6 +640,8 @@ _mm_cmpgt_ss(__m128 __a, __m128 __b)
 ///    128-bit vectors of [4 x float] to determine if the values in the first
 ///    operand are greater than those in the second operand.
 ///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
+///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VCMPLTPS / CMPLTPS  instructions.
@@ -644,9 +659,10 @@ _mm_cmpgt_ps(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the value in the first operand is greater than
-///    or equal to the corresponding value in the second operand and returns
-///    the result of the comparison in the low-order bits of a vector of
-///    [4 x float].
+///    or equal to the corresponding value in the second operand.
+///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the
+///    low-order bits of a vector of [4 x float].
 ///
 /// \headerfile 
 ///
@@ -672,6 +688,8 @@ _mm_cmpge_ss(__m128 __a, __m128 __b)
 ///    128-bit vectors of [4 x float] to determine if the values in the first
 ///    operand are greater than or equal to those in the second operand.
 ///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFFFFFFFFFF for true.
+///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VCMPLEPS / CMPLEPS  instructions.
@@ -687,8 +705,10 @@ _mm_cmpge_ps(__m128 __a, __m128 __b)
   return (__m128)__builtin_ia32_cmpleps((__v4sf)__b, (__v4sf)__a);
 }
 
-/// Compares two 32-bit float values in the low-order bits of both
-///    operands for inequality and returns the result of the comparison in the
+/// Compares two 32-bit float values in the low-order bits of both operands
+///    for inequality.
+///
+///    The comparison yields 0x0 for false, 0xFFFFFFFF for true, in the
 ///    low-order bits of a vector of [4 x float].
 ///
 /// \headerfile 
@@ -713,6 +733,8 @@ _mm_cmpneq_ss(__m128 __a, __m128 __b)
 /// Compares each of the corresponding 32-bit float values of the
 ///    128-bit vectors of [4 x float] for inequality.
 ///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
+///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VCMPNEQPS / CMPNEQPS 
@@ -731,8 +753,10 @@ _mm_cmpneq_ps(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the value in the first operand is not less than
-///    the corresponding value in the second operand and returns the result of
-///    the comparison in the low-order bits of a vector of [4 x float].
+///    the corresponding value in the second operand.
+///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the
+///    low-order bits of a vector of [4 x float].
 ///
 /// \headerfile 
 ///
@@ -757,6 +781,8 @@ _mm_cmpnlt_ss(__m128 __a, __m128 __b)
 ///    128-bit vectors of [4 x float] to determine if the values in the first
 ///    operand are not less than those in the second operand.
 ///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
+///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VCMPNLTPS / CMPNLTPS 
@@ -775,9 +801,10 @@ _mm_cmpnlt_ps(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the value in the first operand is not less than
-///    or equal to the corresponding value in the second operand and returns
-///    the result of the comparison in the low-order bits of a vector of
-///    [4 x float].
+///    or equal to the corresponding value in the second operand.
+///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the
+///    low-order bits of a vector of [4 x float].
 ///
 /// \headerfile 
 ///
@@ -802,6 +829,8 @@ _mm_cmpnle_ss(__m128 __a, __m128 __b)
 ///    128-bit vectors of [4 x float] to determine if the values in the first
 ///    operand are not less than or equal to those in the second operand.
 ///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
+///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VCMPNLEPS / CMPNLEPS 
@@ -820,9 +849,10 @@ _mm_cmpnle_ps(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the value in the first operand is not greater
-///    than the corresponding value in the second operand and returns the
-///    result of the comparison in the low-order bits of a vector of
-///    [4 x float].
+///    than the corresponding value in the second operand.
+///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the
+///    low-order bits of a vector of [4 x float].
 ///
 /// \headerfile 
 ///
@@ -849,6 +879,8 @@ _mm_cmpngt_ss(__m128 __a, __m128 __b)
 ///    128-bit vectors of [4 x float] to determine if the values in the first
 ///    operand are not greater than those in the second operand.
 ///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
+///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VCMPNLTPS / CMPNLTPS 
@@ -867,9 +899,10 @@ _mm_cmpngt_ps(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the value in the first operand is not greater
-///    than or equal to the corresponding value in the second operand and
-///    returns the result of the comparison in the low-order bits of a vector
-///    of [4 x float].
+///    than or equal to the corresponding value in the second operand.
+///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the
+///    low-order bits of a vector of [4 x float].
 ///
 /// \headerfile 
 ///
@@ -896,6 +929,8 @@ _mm_cmpnge_ss(__m128 __a, __m128 __b)
 ///    128-bit vectors of [4 x float] to determine if the values in the first
 ///    operand are not greater than or equal to those in the second operand.
 ///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
+///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VCMPNLEPS / CMPNLEPS 
@@ -914,9 +949,10 @@ _mm_cmpnge_ps(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the value in the first operand is ordered with
-///    respect to the corresponding value in the second operand and returns the
-///    result of the comparison in the low-order bits of a vector of
-///    [4 x float].
+///    respect to the corresponding value in the second operand.
+///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the
+///    low-order bits of a vector of [4 x float].
 ///
 /// \headerfile 
 ///
@@ -941,6 +977,8 @@ _mm_cmpord_ss(__m128 __a, __m128 __b)
 ///    128-bit vectors of [4 x float] to determine if the values in the first
 ///    operand are ordered with respect to those in the second operand.
 ///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
+///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VCMPORDPS / CMPORDPS 
@@ -959,9 +997,10 @@ _mm_cmpord_ps(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the value in the first operand is unordered
-///    with respect to the corresponding value in the second operand and
-///    returns the result of the comparison in the low-order bits of a vector
-///    of [4 x float].
+///    with respect to the corresponding value in the second operand.
+///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true, in the
+///    low-order bits of a vector of [4 x float].
 ///
 /// \headerfile 
 ///
@@ -986,6 +1025,8 @@ _mm_cmpunord_ss(__m128 __a, __m128 __b)
 ///    128-bit vectors of [4 x float] to determine if the values in the first
 ///    operand are unordered with respect to those in the second operand.
 ///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
+///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VCMPUNORDPS / CMPUNORDPS 
@@ -1003,9 +1044,10 @@ _mm_cmpunord_ps(__m128 __a, __m128 __b)
 }
 
 /// Compares two 32-bit float values in the low-order bits of both
-///    operands for equality and returns the result of the comparison.
+///    operands for equality.
 ///
-///    If either of the two lower 32-bit values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower floating-point values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1018,8 +1060,7 @@ _mm_cmpunord_ps(__m128 __a, __m128 __b)
 /// \param __b
 ///    A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
 ///    used in the comparison.
-/// \returns An integer containing the comparison results. If either of the
-///    two lower 32-bit values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS
 _mm_comieq_ss(__m128 __a, __m128 __b)
 {
@@ -1028,9 +1069,10 @@ _mm_comieq_ss(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the first operand is less than the second
-///    operand and returns the result of the comparison.
+///    operand.
 ///
-///    If either of the two lower 32-bit values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower floating-point values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1043,8 +1085,7 @@ _mm_comieq_ss(__m128 __a, __m128 __b)
 /// \param __b
 ///    A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
 ///    used in the comparison.
-/// \returns An integer containing the comparison results. If either of the two
-///     lower 32-bit values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS
 _mm_comilt_ss(__m128 __a, __m128 __b)
 {
@@ -1053,9 +1094,10 @@ _mm_comilt_ss(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the first operand is less than or equal to the
-///    second operand and returns the result of the comparison.
+///    second operand.
 ///
-///    If either of the two lower 32-bit values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower floating-point values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1067,8 +1109,7 @@ _mm_comilt_ss(__m128 __a, __m128 __b)
 /// \param __b
 ///    A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
 ///    used in the comparison.
-/// \returns An integer containing the comparison results. If either of the two
-///     lower 32-bit values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS
 _mm_comile_ss(__m128 __a, __m128 __b)
 {
@@ -1077,9 +1118,10 @@ _mm_comile_ss(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the first operand is greater than the second
-///    operand and returns the result of the comparison.
+///    operand.
 ///
-///    If either of the two lower 32-bit values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower floating-point values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1091,8 +1133,7 @@ _mm_comile_ss(__m128 __a, __m128 __b)
 /// \param __b
 ///    A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
 ///    used in the comparison.
-/// \returns An integer containing the comparison results. If either of the
-///     two lower 32-bit values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS
 _mm_comigt_ss(__m128 __a, __m128 __b)
 {
@@ -1101,9 +1142,10 @@ _mm_comigt_ss(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the first operand is greater than or equal to
-///    the second operand and returns the result of the comparison.
+///    the second operand.
 ///
-///    If either of the two lower 32-bit values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower floating-point values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1115,8 +1157,7 @@ _mm_comigt_ss(__m128 __a, __m128 __b)
 /// \param __b
 ///    A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
 ///    used in the comparison.
-/// \returns An integer containing the comparison results. If either of the two
-///    lower 32-bit values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS
 _mm_comige_ss(__m128 __a, __m128 __b)
 {
@@ -1125,9 +1166,10 @@ _mm_comige_ss(__m128 __a, __m128 __b)
 
 /// Compares two 32-bit float values in the low-order bits of both
 ///    operands to determine if the first operand is not equal to the second
-///    operand and returns the result of the comparison.
+///    operand.
 ///
-///    If either of the two lower 32-bit values is NaN, 1 is returned.
+///    The comparison returns 0 for false, 1 for true. If either of the two
+///    lower floating-point values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1139,8 +1181,7 @@ _mm_comige_ss(__m128 __a, __m128 __b)
 /// \param __b
 ///    A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
 ///    used in the comparison.
-/// \returns An integer containing the comparison results. If either of the
-///     two lower 32-bit values is NaN, 1 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS
 _mm_comineq_ss(__m128 __a, __m128 __b)
 {
@@ -1148,10 +1189,10 @@ _mm_comineq_ss(__m128 __a, __m128 __b)
 }
 
 /// Performs an unordered comparison of two 32-bit float values using
-///    the low-order bits of both operands to determine equality and returns
-///    the result of the comparison.
+///    the low-order bits of both operands to determine equality.
 ///
-///    If either of the two lower 32-bit values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true.  If either of the two
+///    lower floating-point values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1163,8 +1204,7 @@ _mm_comineq_ss(__m128 __a, __m128 __b)
 /// \param __b
 ///    A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
 ///    used in the comparison.
-/// \returns An integer containing the comparison results. If either of the two
-///     lower 32-bit values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS
 _mm_ucomieq_ss(__m128 __a, __m128 __b)
 {
@@ -1173,9 +1213,10 @@ _mm_ucomieq_ss(__m128 __a, __m128 __b)
 
 /// Performs an unordered comparison of two 32-bit float values using
 ///    the low-order bits of both operands to determine if the first operand is
-///    less than the second operand and returns the result of the comparison.
+///    less than the second operand.
 ///
-///    If either of the two lower 32-bit values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true.  If either of the two
+///    lower floating-point values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1187,8 +1228,7 @@ _mm_ucomieq_ss(__m128 __a, __m128 __b)
 /// \param __b
 ///    A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
 ///    used in the comparison.
-/// \returns An integer containing the comparison results. If either of the two
-///    lower 32-bit values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS
 _mm_ucomilt_ss(__m128 __a, __m128 __b)
 {
@@ -1197,10 +1237,10 @@ _mm_ucomilt_ss(__m128 __a, __m128 __b)
 
 /// Performs an unordered comparison of two 32-bit float values using
 ///    the low-order bits of both operands to determine if the first operand is
-///    less than or equal to the second operand and returns the result of the
-///    comparison.
+///    less than or equal to the second operand.
 ///
-///    If either of the two lower 32-bit values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true.  If either of the two
+///    lower floating-point values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1212,8 +1252,7 @@ _mm_ucomilt_ss(__m128 __a, __m128 __b)
 /// \param __b
 ///    A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
 ///    used in the comparison.
-/// \returns An integer containing the comparison results. If either of the two
-///     lower 32-bit values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS
 _mm_ucomile_ss(__m128 __a, __m128 __b)
 {
@@ -1222,10 +1261,10 @@ _mm_ucomile_ss(__m128 __a, __m128 __b)
 
 /// Performs an unordered comparison of two 32-bit float values using
 ///    the low-order bits of both operands to determine if the first operand is
-///    greater than the second operand and returns the result of the
-///    comparison.
+///    greater than the second operand.
 ///
-///    If either of the two lower 32-bit values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true.  If either of the two
+///    lower floating-point values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1237,8 +1276,7 @@ _mm_ucomile_ss(__m128 __a, __m128 __b)
 /// \param __b
 ///    A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
 ///    used in the comparison.
-/// \returns An integer containing the comparison results. If either of the two
-///     lower 32-bit values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS
 _mm_ucomigt_ss(__m128 __a, __m128 __b)
 {
@@ -1247,10 +1285,10 @@ _mm_ucomigt_ss(__m128 __a, __m128 __b)
 
 /// Performs an unordered comparison of two 32-bit float values using
 ///    the low-order bits of both operands to determine if the first operand is
-///    greater than or equal to the second operand and returns the result of
-///    the comparison.
+///    greater than or equal to the second operand.
 ///
-///    If either of the two lower 32-bit values is NaN, 0 is returned.
+///    The comparison returns 0 for false, 1 for true.  If either of the two
+///    lower floating-point values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1262,8 +1300,7 @@ _mm_ucomigt_ss(__m128 __a, __m128 __b)
 /// \param __b
 ///    A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
 ///    used in the comparison.
-/// \returns An integer containing the comparison results. If either of the two
-///     lower 32-bit values is NaN, 0 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS
 _mm_ucomige_ss(__m128 __a, __m128 __b)
 {
@@ -1271,10 +1308,10 @@ _mm_ucomige_ss(__m128 __a, __m128 __b)
 }
 
 /// Performs an unordered comparison of two 32-bit float values using
-///    the low-order bits of both operands to determine inequality and returns
-///    the result of the comparison.
+///    the low-order bits of both operands to determine inequality.
 ///
-///    If either of the two lower 32-bit values is NaN, 1 is returned.
+///    The comparison returns 0 for false, 1 for true.  If either of the two
+///    lower floating-point values is NaN, returns 0.
 ///
 /// \headerfile 
 ///
@@ -1286,8 +1323,7 @@ _mm_ucomige_ss(__m128 __a, __m128 __b)
 /// \param __b
 ///    A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
 ///    used in the comparison.
-/// \returns An integer containing the comparison results. If either of the two
-///    lower 32-bit values is NaN, 1 is returned.
+/// \returns An integer containing the comparison results.
 static __inline__ int __DEFAULT_FN_ATTRS
 _mm_ucomineq_ss(__m128 __a, __m128 __b)
 {
@@ -2940,6 +2976,81 @@ _mm_movemask_ps(__m128 __a)
   return __builtin_ia32_movmskps((__v4sf)__a);
 }
 
+/* Compare */
+#define _CMP_EQ_OQ    0x00 /* Equal (ordered, non-signaling)  */
+#define _CMP_LT_OS    0x01 /* Less-than (ordered, signaling)  */
+#define _CMP_LE_OS    0x02 /* Less-than-or-equal (ordered, signaling)  */
+#define _CMP_UNORD_Q  0x03 /* Unordered (non-signaling)  */
+#define _CMP_NEQ_UQ   0x04 /* Not-equal (unordered, non-signaling)  */
+#define _CMP_NLT_US   0x05 /* Not-less-than (unordered, signaling)  */
+#define _CMP_NLE_US   0x06 /* Not-less-than-or-equal (unordered, signaling)  */
+#define _CMP_ORD_Q    0x07 /* Ordered (non-signaling)   */
+
+/// Compares each of the corresponding values of two 128-bit vectors of
+///    [4 x float], using the operation specified by the immediate integer
+///    operand.
+///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
+///
+/// \headerfile 
+///
+/// \code
+/// __m128 _mm_cmp_ps(__m128 a, __m128 b, const int c);
+/// \endcode
+///
+/// This intrinsic corresponds to the  (V)CMPPS  instruction.
+///
+/// \param a
+///    A 128-bit vector of [4 x float].
+/// \param b
+///    A 128-bit vector of [4 x float].
+/// \param c
+///    An immediate integer operand, with bits [4:0] specifying which comparison
+///    operation to use: \n
+///    0x00: Equal (ordered, non-signaling) \n
+///    0x01: Less-than (ordered, signaling) \n
+///    0x02: Less-than-or-equal (ordered, signaling) \n
+///    0x03: Unordered (non-signaling) \n
+///    0x04: Not-equal (unordered, non-signaling) \n
+///    0x05: Not-less-than (unordered, signaling) \n
+///    0x06: Not-less-than-or-equal (unordered, signaling) \n
+///    0x07: Ordered (non-signaling) \n
+/// \returns A 128-bit vector of [4 x float] containing the comparison results.
+#define _mm_cmp_ps(a, b, c)                                                    \
+  ((__m128)__builtin_ia32_cmpps((__v4sf)(__m128)(a), (__v4sf)(__m128)(b), (c)))
+
+/// Compares each of the corresponding scalar values of two 128-bit
+///    vectors of [4 x float], using the operation specified by the immediate
+///    integer operand.
+///
+///    Each comparison yields 0x0 for false, 0xFFFFFFFF for true.
+///
+/// \headerfile 
+///
+/// \code
+/// __m128 _mm_cmp_ss(__m128 a, __m128 b, const int c);
+/// \endcode
+///
+/// This intrinsic corresponds to the  (V)CMPSS  instruction.
+///
+/// \param a
+///    A 128-bit vector of [4 x float].
+/// \param b
+///    A 128-bit vector of [4 x float].
+/// \param c
+///    An immediate integer operand, with bits [4:0] specifying which comparison
+///    operation to use: \n
+///    0x00: Equal (ordered, non-signaling) \n
+///    0x01: Less-than (ordered, signaling) \n
+///    0x02: Less-than-or-equal (ordered, signaling) \n
+///    0x03: Unordered (non-signaling) \n
+///    0x04: Not-equal (unordered, non-signaling) \n
+///    0x05: Not-less-than (unordered, signaling) \n
+///    0x06: Not-less-than-or-equal (unordered, signaling) \n
+///    0x07: Ordered (non-signaling) \n
+/// \returns A 128-bit vector of [4 x float] containing the comparison results.
+#define _mm_cmp_ss(a, b, c)                                                    \
+  ((__m128)__builtin_ia32_cmpss((__v4sf)(__m128)(a), (__v4sf)(__m128)(b), (c)))
 
 #define _MM_ALIGN16 __attribute__((aligned(16)))
 
diff --git a/clang/lib/InstallAPI/Frontend.cpp b/clang/lib/InstallAPI/Frontend.cpp
index caa6e7e8a40544c170a56e96a452a7a7ec7d146b..0d526fe1da666794d57278cdbbdae9dc4ee4189f 100644
--- a/clang/lib/InstallAPI/Frontend.cpp
+++ b/clang/lib/InstallAPI/Frontend.cpp
@@ -19,9 +19,10 @@ namespace clang::installapi {
 GlobalRecord *FrontendRecordsSlice::addGlobal(
     StringRef Name, RecordLinkage Linkage, GlobalRecord::Kind GV,
     const clang::AvailabilityInfo Avail, const Decl *D, const HeaderType Access,
-    SymbolFlags Flags) {
+    SymbolFlags Flags, bool Inlined) {
 
-  auto *GR = llvm::MachO::RecordsSlice::addGlobal(Name, Linkage, GV, Flags);
+  auto *GR =
+      llvm::MachO::RecordsSlice::addGlobal(Name, Linkage, GV, Flags, Inlined);
   FrontendRecords.insert({GR, FrontendAttrs{Avail, D, Access}});
   return GR;
 }
@@ -39,6 +40,31 @@ ObjCInterfaceRecord *FrontendRecordsSlice::addObjCInterface(
   return ObjCR;
 }
 
+ObjCCategoryRecord *FrontendRecordsSlice::addObjCCategory(
+    StringRef ClassToExtend, StringRef CategoryName,
+    const clang::AvailabilityInfo Avail, const Decl *D, HeaderType Access) {
+  auto *ObjCR =
+      llvm::MachO::RecordsSlice::addObjCCategory(ClassToExtend, CategoryName);
+  FrontendRecords.insert({ObjCR, FrontendAttrs{Avail, D, Access}});
+  return ObjCR;
+}
+
+ObjCIVarRecord *FrontendRecordsSlice::addObjCIVar(
+    ObjCContainerRecord *Container, StringRef IvarName, RecordLinkage Linkage,
+    const clang::AvailabilityInfo Avail, const Decl *D, HeaderType Access,
+    const clang::ObjCIvarDecl::AccessControl AC) {
+  // If the decl otherwise would have been exported, check their access control.
+  // Ivar's linkage is also determined by this.
+  if ((Linkage == RecordLinkage::Exported) &&
+      ((AC == ObjCIvarDecl::Private) || (AC == ObjCIvarDecl::Package)))
+    Linkage = RecordLinkage::Internal;
+  auto *ObjCR =
+      llvm::MachO::RecordsSlice::addObjCIVar(Container, IvarName, Linkage);
+  FrontendRecords.insert({ObjCR, FrontendAttrs{Avail, D, Access}});
+
+  return nullptr;
+}
+
 std::optional
 InstallAPIContext::findAndRecordFile(const FileEntry *FE,
                                      const Preprocessor &PP) {
@@ -111,9 +137,9 @@ std::unique_ptr createInputBuffer(InstallAPIContext &Ctx) {
     else
       OS << "#import ";
     if (H.useIncludeName())
-      OS << "<" << H.getIncludeName() << ">";
+      OS << "<" << H.getIncludeName() << ">\n";
     else
-      OS << "\"" << H.getPath() << "\"";
+      OS << "\"" << H.getPath() << "\"\n";
 
     Ctx.addKnownHeader(H);
   }
diff --git a/clang/lib/InstallAPI/Visitor.cpp b/clang/lib/InstallAPI/Visitor.cpp
index 355a092520c3cd469fef4f5098219c316b4c767e..aded94f7a94a3227bd6983f74d08ba58bbc7ccc6 100644
--- a/clang/lib/InstallAPI/Visitor.cpp
+++ b/clang/lib/InstallAPI/Visitor.cpp
@@ -7,6 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/InstallAPI/Visitor.h"
+#include "clang/AST/Availability.h"
+#include "clang/AST/ParentMapContext.h"
+#include "clang/AST/VTableBuilder.h"
 #include "clang/Basic/Linkage.h"
 #include "clang/InstallAPI/Frontend.h"
 #include "llvm/ADT/SmallString.h"
@@ -17,6 +20,15 @@
 using namespace llvm;
 using namespace llvm::MachO;
 
+namespace {
+enum class CXXLinkage {
+  ExternalLinkage,
+  LinkOnceODRLinkage,
+  WeakODRLinkage,
+  PrivateLinkage,
+};
+}
+
 namespace clang::installapi {
 
 // Exported NamedDecl needs to have external linkage and
@@ -27,7 +39,32 @@ static bool isExported(const NamedDecl *D) {
          (LV.getVisibility() == DefaultVisibility);
 }
 
-static SymbolFlags getFlags(bool WeakDef, bool ThreadLocal) {
+static bool isInlined(const FunctionDecl *D) {
+  bool HasInlineAttribute = false;
+  bool NoCXXAttr =
+      (!D->getASTContext().getLangOpts().CPlusPlus &&
+       !D->getASTContext().getTargetInfo().getCXXABI().isMicrosoft() &&
+       !D->hasAttr());
+
+  // Check all redeclarations to find an inline attribute or keyword.
+  for (const auto *RD : D->redecls()) {
+    if (!RD->isInlined())
+      continue;
+    HasInlineAttribute = true;
+    if (!(NoCXXAttr || RD->hasAttr()))
+      continue;
+    if (RD->doesThisDeclarationHaveABody() &&
+        RD->isInlineDefinitionExternallyVisible())
+      return false;
+  }
+
+  if (!HasInlineAttribute)
+    return false;
+
+  return true;
+}
+
+static SymbolFlags getFlags(bool WeakDef, bool ThreadLocal = false) {
   SymbolFlags Result = SymbolFlags::None;
   if (WeakDef)
     Result |= SymbolFlags::WeakDefined;
@@ -99,6 +136,29 @@ static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *D) {
 
   return false;
 }
+void InstallAPIVisitor::recordObjCInstanceVariables(
+    const ASTContext &ASTCtx, ObjCContainerRecord *Record, StringRef SuperClass,
+    const llvm::iterator_range<
+        DeclContext::specific_decl_iterator>
+        Ivars) {
+  RecordLinkage Linkage = RecordLinkage::Exported;
+  const RecordLinkage ContainerLinkage = Record->getLinkage();
+  // If fragile, set to unknown.
+  if (ASTCtx.getLangOpts().ObjCRuntime.isFragile())
+    Linkage = RecordLinkage::Unknown;
+  // Linkage should be inherited from container.
+  else if (ContainerLinkage != RecordLinkage::Unknown)
+    Linkage = ContainerLinkage;
+  for (const auto *IV : Ivars) {
+    auto Access = getAccessForDecl(IV);
+    if (!Access)
+      continue;
+    StringRef Name = IV->getName();
+    const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(IV);
+    auto AC = IV->getCanonicalAccessControl();
+    Ctx.Slice->addObjCIVar(Record, Name, Linkage, Avail, IV, *Access, AC);
+  }
+}
 
 bool InstallAPIVisitor::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
   // Skip forward declaration for classes (@class)
@@ -118,7 +178,33 @@ bool InstallAPIVisitor::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
       (!D->getASTContext().getLangOpts().ObjCRuntime.isFragile() &&
        hasObjCExceptionAttribute(D));
 
-  Ctx.Slice->addObjCInterface(Name, Linkage, Avail, D, *Access, IsEHType);
+  ObjCInterfaceRecord *Class =
+      Ctx.Slice->addObjCInterface(Name, Linkage, Avail, D, *Access, IsEHType);
+
+  // Get base class.
+  StringRef SuperClassName;
+  if (const auto *SuperClass = D->getSuperClass())
+    SuperClassName = SuperClass->getObjCRuntimeNameAsString();
+
+  recordObjCInstanceVariables(D->getASTContext(), Class, SuperClassName,
+                              D->ivars());
+  return true;
+}
+
+bool InstallAPIVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
+  StringRef CategoryName = D->getName();
+  // Skip over declarations that access could not be collected for.
+  auto Access = getAccessForDecl(D);
+  if (!Access)
+    return true;
+  const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
+  const ObjCInterfaceDecl *InterfaceD = D->getClassInterface();
+  const StringRef InterfaceName = InterfaceD->getName();
+
+  ObjCCategoryRecord *Category = Ctx.Slice->addObjCCategory(
+      InterfaceName, CategoryName, Avail, D, *Access);
+  recordObjCInstanceVariables(D->getASTContext(), Category, InterfaceName,
+                              D->ivars());
   return true;
 }
 
@@ -155,4 +241,465 @@ bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) {
   return true;
 }
 
+bool InstallAPIVisitor::VisitFunctionDecl(const FunctionDecl *D) {
+  if (const CXXMethodDecl *M = dyn_cast(D)) {
+    // Skip member function in class templates.
+    if (M->getParent()->getDescribedClassTemplate() != nullptr)
+      return true;
+
+    // Skip methods in CXX RecordDecls.
+    for (auto P : D->getASTContext().getParents(*M)) {
+      if (P.get())
+        return true;
+    }
+
+    // Skip CXX ConstructorDecls and DestructorDecls.
+    if (isa(M) || isa(M))
+      return true;
+  }
+
+  // Skip templated functions.
+  switch (D->getTemplatedKind()) {
+  case FunctionDecl::TK_NonTemplate:
+  case FunctionDecl::TK_DependentNonTemplate:
+    break;
+  case FunctionDecl::TK_MemberSpecialization:
+  case FunctionDecl::TK_FunctionTemplateSpecialization:
+    if (auto *TempInfo = D->getTemplateSpecializationInfo()) {
+      if (!TempInfo->isExplicitInstantiationOrSpecialization())
+        return true;
+    }
+    break;
+  case FunctionDecl::TK_FunctionTemplate:
+  case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
+    return true;
+  }
+
+  auto Access = getAccessForDecl(D);
+  if (!Access)
+    return true;
+  auto Name = getMangledName(D);
+  const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
+  const bool ExplicitInstantiation = D->getTemplateSpecializationKind() ==
+                                     TSK_ExplicitInstantiationDeclaration;
+  const bool WeakDef = ExplicitInstantiation || D->hasAttr();
+  const bool Inlined = isInlined(D);
+  const RecordLinkage Linkage = (Inlined || !isExported(D))
+                                    ? RecordLinkage::Internal
+                                    : RecordLinkage::Exported;
+  Ctx.Slice->addGlobal(Name, Linkage, GlobalRecord::Kind::Function, Avail, D,
+                       *Access, getFlags(WeakDef), Inlined);
+  return true;
+}
+
+static bool hasVTable(const CXXRecordDecl *D) {
+  // Check if vtable symbols should be emitted, only dynamic classes need
+  // vtables.
+  if (!D->hasDefinition() || !D->isDynamicClass())
+    return false;
+
+  assert(D->isExternallyVisible() && "Should be externally visible");
+  assert(D->isCompleteDefinition() && "Only works on complete definitions");
+
+  const CXXMethodDecl *KeyFunctionD =
+      D->getASTContext().getCurrentKeyFunction(D);
+  // If this class has a key function, then there is a vtable, possibly internal
+  // though.
+  if (KeyFunctionD) {
+    switch (KeyFunctionD->getTemplateSpecializationKind()) {
+    case TSK_Undeclared:
+    case TSK_ExplicitSpecialization:
+    case TSK_ImplicitInstantiation:
+    case TSK_ExplicitInstantiationDefinition:
+      return true;
+    case TSK_ExplicitInstantiationDeclaration:
+      llvm_unreachable(
+          "Unexpected TemplateSpecializationKind for key function");
+    }
+  } else if (D->isAbstract()) {
+    // If the class is abstract and it doesn't have a key function, it is a
+    // 'pure' virtual class. It doesn't need a vtable.
+    return false;
+  }
+
+  switch (D->getTemplateSpecializationKind()) {
+  case TSK_Undeclared:
+  case TSK_ExplicitSpecialization:
+  case TSK_ImplicitInstantiation:
+    return false;
+
+  case TSK_ExplicitInstantiationDeclaration:
+  case TSK_ExplicitInstantiationDefinition:
+    return true;
+  }
+
+  llvm_unreachable("Invalid TemplateSpecializationKind!");
+}
+
+static CXXLinkage getVTableLinkage(const CXXRecordDecl *D) {
+  assert((D->hasDefinition() && D->isDynamicClass()) && "Record has no vtable");
+  assert(D->isExternallyVisible() && "Record should be externally visible");
+  if (D->getVisibility() == HiddenVisibility)
+    return CXXLinkage::PrivateLinkage;
+
+  const CXXMethodDecl *KeyFunctionD =
+      D->getASTContext().getCurrentKeyFunction(D);
+  if (KeyFunctionD) {
+    // If this class has a key function, use that to determine the
+    // linkage of the vtable.
+    switch (KeyFunctionD->getTemplateSpecializationKind()) {
+    case TSK_Undeclared:
+    case TSK_ExplicitSpecialization:
+      if (isInlined(KeyFunctionD))
+        return CXXLinkage::LinkOnceODRLinkage;
+      return CXXLinkage::ExternalLinkage;
+    case TSK_ImplicitInstantiation:
+      llvm_unreachable("No external vtable for implicit instantiations");
+    case TSK_ExplicitInstantiationDefinition:
+      return CXXLinkage::WeakODRLinkage;
+    case TSK_ExplicitInstantiationDeclaration:
+      llvm_unreachable(
+          "Unexpected TemplateSpecializationKind for key function");
+    }
+  }
+
+  switch (D->getTemplateSpecializationKind()) {
+  case TSK_Undeclared:
+  case TSK_ExplicitSpecialization:
+  case TSK_ImplicitInstantiation:
+    return CXXLinkage::LinkOnceODRLinkage;
+  case TSK_ExplicitInstantiationDeclaration:
+  case TSK_ExplicitInstantiationDefinition:
+    return CXXLinkage::WeakODRLinkage;
+  }
+
+  llvm_unreachable("Invalid TemplateSpecializationKind!");
+}
+
+static bool isRTTIWeakDef(const CXXRecordDecl *D) {
+  if (D->hasAttr())
+    return true;
+
+  if (D->isAbstract() && D->getASTContext().getCurrentKeyFunction(D) == nullptr)
+    return true;
+
+  if (D->isDynamicClass())
+    return getVTableLinkage(D) != CXXLinkage::ExternalLinkage;
+
+  return false;
+}
+
+static bool hasRTTI(const CXXRecordDecl *D) {
+  if (!D->getASTContext().getLangOpts().RTTI)
+    return false;
+
+  if (!D->hasDefinition())
+    return false;
+
+  if (!D->isDynamicClass())
+    return false;
+
+  // Don't emit weak-def RTTI information. InstallAPI cannot reliably determine
+  // if the final binary will have those weak defined RTTI symbols. This depends
+  // on the optimization level and if the class has been instantiated and used.
+  //
+  // Luckily, the Apple static linker doesn't need those weak defined RTTI
+  // symbols for linking. They are only needed by the runtime linker. That means
+  // they can be safely dropped.
+  if (isRTTIWeakDef(D))
+    return false;
+
+  return true;
+}
+
+std::string
+InstallAPIVisitor::getMangledCXXRTTIName(const CXXRecordDecl *D) const {
+  SmallString<256> Name;
+  raw_svector_ostream NameStream(Name);
+  MC->mangleCXXRTTIName(QualType(D->getTypeForDecl(), 0), NameStream);
+
+  return getBackendMangledName(Name);
+}
+
+std::string InstallAPIVisitor::getMangledCXXRTTI(const CXXRecordDecl *D) const {
+  SmallString<256> Name;
+  raw_svector_ostream NameStream(Name);
+  MC->mangleCXXRTTI(QualType(D->getTypeForDecl(), 0), NameStream);
+
+  return getBackendMangledName(Name);
+}
+
+std::string
+InstallAPIVisitor::getMangledCXXVTableName(const CXXRecordDecl *D) const {
+  SmallString<256> Name;
+  raw_svector_ostream NameStream(Name);
+  MC->mangleCXXVTable(D, NameStream);
+
+  return getBackendMangledName(Name);
+}
+
+std::string
+InstallAPIVisitor::getMangledCXXThunk(const GlobalDecl &D,
+                                      const ThunkInfo &Thunk) const {
+  SmallString<256> Name;
+  raw_svector_ostream NameStream(Name);
+  const auto *Method = cast(D.getDecl());
+  if (const auto *Dtor = dyn_cast(Method))
+    MC->mangleCXXDtorThunk(Dtor, D.getDtorType(), Thunk.This, NameStream);
+  else
+    MC->mangleThunk(Method, Thunk, NameStream);
+
+  return getBackendMangledName(Name);
+}
+
+std::string InstallAPIVisitor::getMangledCtorDtor(const CXXMethodDecl *D,
+                                                  int Type) const {
+  SmallString<256> Name;
+  raw_svector_ostream NameStream(Name);
+  GlobalDecl GD;
+  if (const auto *Ctor = dyn_cast(D))
+    GD = GlobalDecl(Ctor, CXXCtorType(Type));
+  else {
+    const auto *Dtor = cast(D);
+    GD = GlobalDecl(Dtor, CXXDtorType(Type));
+  }
+  MC->mangleName(GD, NameStream);
+  return getBackendMangledName(Name);
+}
+
+void InstallAPIVisitor::emitVTableSymbols(const CXXRecordDecl *D,
+                                          const AvailabilityInfo &Avail,
+                                          const HeaderType Access,
+                                          bool EmittedVTable) {
+  if (hasVTable(D)) {
+    EmittedVTable = true;
+    const CXXLinkage VTableLinkage = getVTableLinkage(D);
+    if (VTableLinkage == CXXLinkage::ExternalLinkage ||
+        VTableLinkage == CXXLinkage::WeakODRLinkage) {
+      const std::string Name = getMangledCXXVTableName(D);
+      const bool WeakDef = VTableLinkage == CXXLinkage::WeakODRLinkage;
+      Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
+                           GlobalRecord::Kind::Variable, Avail, D, Access,
+                           getFlags(WeakDef));
+      if (!D->getDescribedClassTemplate() && !D->isInvalidDecl()) {
+        VTableContextBase *VTable = D->getASTContext().getVTableContext();
+        auto AddThunk = [&](GlobalDecl GD) {
+          const ItaniumVTableContext::ThunkInfoVectorTy *Thunks =
+              VTable->getThunkInfo(GD);
+          if (!Thunks)
+            return;
+
+          for (const auto &Thunk : *Thunks) {
+            const std::string Name = getMangledCXXThunk(GD, Thunk);
+            Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
+                                 GlobalRecord::Kind::Function, Avail,
+                                 GD.getDecl(), Access);
+          }
+        };
+
+        for (const auto *Method : D->methods()) {
+          if (isa(Method) || !Method->isVirtual())
+            continue;
+
+          if (auto Dtor = dyn_cast(Method)) {
+            // Skip default destructor.
+            if (Dtor->isDefaulted())
+              continue;
+            AddThunk({Dtor, Dtor_Deleting});
+            AddThunk({Dtor, Dtor_Complete});
+          } else
+            AddThunk(Method);
+        }
+      }
+    }
+  }
+
+  if (!EmittedVTable)
+    return;
+
+  if (hasRTTI(D)) {
+    std::string Name = getMangledCXXRTTI(D);
+    Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
+                         GlobalRecord::Kind::Variable, Avail, D, Access);
+
+    Name = getMangledCXXRTTIName(D);
+    Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
+                         GlobalRecord::Kind::Variable, Avail, D, Access);
+  }
+
+  for (const auto &It : D->bases()) {
+    const CXXRecordDecl *Base =
+        cast(It.getType()->castAs()->getDecl());
+    const auto BaseAccess = getAccessForDecl(Base);
+    if (!BaseAccess)
+      continue;
+    const AvailabilityInfo BaseAvail = AvailabilityInfo::createFromDecl(Base);
+    emitVTableSymbols(Base, BaseAvail, *BaseAccess, /*EmittedVTable=*/true);
+  }
+}
+
+bool InstallAPIVisitor::VisitCXXRecordDecl(const CXXRecordDecl *D) {
+  if (!D->isCompleteDefinition())
+    return true;
+
+  // Skip templated classes.
+  if (D->getDescribedClassTemplate() != nullptr)
+    return true;
+
+  // Skip partial templated classes too.
+  if (isa(D))
+    return true;
+
+  auto Access = getAccessForDecl(D);
+  if (!Access)
+    return true;
+  const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
+
+  // Check whether to emit the vtable/rtti symbols.
+  if (isExported(D))
+    emitVTableSymbols(D, Avail, *Access);
+
+  TemplateSpecializationKind ClassSK = TSK_Undeclared;
+  bool KeepInlineAsWeak = false;
+  if (auto *Templ = dyn_cast(D)) {
+    ClassSK = Templ->getTemplateSpecializationKind();
+    if (ClassSK == TSK_ExplicitInstantiationDeclaration)
+      KeepInlineAsWeak = true;
+  }
+
+  // Record the class methods.
+  for (const auto *M : D->methods()) {
+    // Inlined methods are usually not emitted, except when it comes from a
+    // specialized template.
+    bool WeakDef = false;
+    if (isInlined(M)) {
+      if (!KeepInlineAsWeak)
+        continue;
+
+      WeakDef = true;
+    }
+
+    if (!isExported(M))
+      continue;
+
+    switch (M->getTemplateSpecializationKind()) {
+    case TSK_Undeclared:
+    case TSK_ExplicitSpecialization:
+      break;
+    case TSK_ImplicitInstantiation:
+      continue;
+    case TSK_ExplicitInstantiationDeclaration:
+      if (ClassSK == TSK_ExplicitInstantiationDeclaration)
+        WeakDef = true;
+      break;
+    case TSK_ExplicitInstantiationDefinition:
+      WeakDef = true;
+      break;
+    }
+
+    if (!M->isUserProvided())
+      continue;
+
+    // Methods that are deleted are not exported.
+    if (M->isDeleted())
+      continue;
+
+    const auto Access = getAccessForDecl(M);
+    if (!Access)
+      return true;
+    const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(M);
+
+    if (const auto *Ctor = dyn_cast(M)) {
+      // Defaulted constructors are not exported.
+      if (Ctor->isDefaulted())
+        continue;
+
+      std::string Name = getMangledCtorDtor(M, Ctor_Base);
+      Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
+                           GlobalRecord::Kind::Function, Avail, D, *Access,
+                           getFlags(WeakDef));
+
+      if (!D->isAbstract()) {
+        std::string Name = getMangledCtorDtor(M, Ctor_Complete);
+        Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
+                             GlobalRecord::Kind::Function, Avail, D, *Access,
+                             getFlags(WeakDef));
+      }
+
+      continue;
+    }
+
+    if (const auto *Dtor = dyn_cast(M)) {
+      // Defaulted destructors are not exported.
+      if (Dtor->isDefaulted())
+        continue;
+
+      std::string Name = getMangledCtorDtor(M, Dtor_Base);
+      Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
+                           GlobalRecord::Kind::Function, Avail, D, *Access,
+                           getFlags(WeakDef));
+
+      Name = getMangledCtorDtor(M, Dtor_Complete);
+      Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
+                           GlobalRecord::Kind::Function, Avail, D, *Access,
+                           getFlags(WeakDef));
+
+      if (Dtor->isVirtual()) {
+        Name = getMangledCtorDtor(M, Dtor_Deleting);
+        Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
+                             GlobalRecord::Kind::Function, Avail, D, *Access,
+                             getFlags(WeakDef));
+      }
+
+      continue;
+    }
+
+    // Though abstract methods can map to exports, this is generally unexpected.
+    // Except in the case of destructors. Only ignore pure virtuals after
+    // checking if the member function was a destructor.
+    if (M->isPureVirtual())
+      continue;
+
+    std::string Name = getMangledName(M);
+    Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
+                         GlobalRecord::Kind::Function, Avail, D, *Access,
+                         getFlags(WeakDef));
+  }
+
+  if (auto *Templ = dyn_cast(D)) {
+    if (!Templ->isExplicitInstantiationOrSpecialization())
+      return true;
+  }
+
+  using var_iter = CXXRecordDecl::specific_decl_iterator;
+  using var_range = iterator_range;
+  for (const auto *Var : var_range(D->decls())) {
+    // Skip const static member variables.
+    // \code
+    // struct S {
+    //   static const int x = 0;
+    // };
+    // \endcode
+    if (Var->isStaticDataMember() && Var->hasInit())
+      continue;
+
+    // Skip unexported var decls.
+    if (!isExported(Var))
+      continue;
+
+    const std::string Name = getMangledName(Var);
+    const auto Access = getAccessForDecl(Var);
+    if (!Access)
+      return true;
+    const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(Var);
+    const bool WeakDef = Var->hasAttr() || KeepInlineAsWeak;
+
+    Ctx.Slice->addGlobal(Name, RecordLinkage::Exported,
+                         GlobalRecord::Kind::Variable, Avail, D, *Access,
+                         getFlags(WeakDef));
+  }
+
+  return true;
+}
+
 } // namespace clang::installapi
diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp
index 9f97a3c6b0be9e6a064d8ab55ccfa17e22709cae..7fa52f2f15fc4951da35e5700deb54ecc4e6b64d 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -132,7 +132,8 @@ CreateCI(const llvm::opt::ArgStringList &Argv) {
 } // anonymous namespace
 
 llvm::Expected>
-IncrementalCompilerBuilder::create(std::vector &ClangArgv) {
+IncrementalCompilerBuilder::create(std::string TT,
+                                   std::vector &ClangArgv) {
 
   // If we don't know ClangArgv0 or the address of main() at this point, try
   // to guess it anyway (it's possible on some platforms).
@@ -162,8 +163,7 @@ IncrementalCompilerBuilder::create(std::vector &ClangArgv) {
   TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
   DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);
 
-  driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0],
-                        llvm::sys::getProcessTriple(), Diags);
+  driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], TT, Diags);
   Driver.setCheckInputsExist(false); // the input comes from mem buffers
   llvm::ArrayRef RF = llvm::ArrayRef(ClangArgv);
   std::unique_ptr Compilation(Driver.BuildCompilation(RF));
@@ -185,7 +185,8 @@ IncrementalCompilerBuilder::CreateCpp() {
   Argv.push_back("-xc++");
   Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
 
-  return IncrementalCompilerBuilder::create(Argv);
+  std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
+  return IncrementalCompilerBuilder::create(TT, Argv);
 }
 
 llvm::Expected>
@@ -213,7 +214,8 @@ IncrementalCompilerBuilder::createCuda(bool device) {
 
   Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
 
-  return IncrementalCompilerBuilder::create(Argv);
+  std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
+  return IncrementalCompilerBuilder::create(TT, Argv);
 }
 
 llvm::Expected>
@@ -278,15 +280,14 @@ Interpreter::create(std::unique_ptr CI) {
   if (Err)
     return std::move(Err);
 
+  // Add runtime code and set a marker to hide it from user code. Undo will not
+  // go through that.
   auto PTU = Interp->Parse(Runtimes);
   if (!PTU)
     return PTU.takeError();
+  Interp->markUserCodeStart();
 
   Interp->ValuePrintingInfo.resize(4);
-  // FIXME: This is a ugly hack. Undo command checks its availability by looking
-  // at the size of the PTU list. However we have parsed something in the
-  // beginning of the REPL so we have to mark them as 'Irrevocable'.
-  Interp->InitPTUSize = Interp->IncrParser->getPTUs().size();
   return std::move(Interp);
 }
 
@@ -343,6 +344,11 @@ const ASTContext &Interpreter::getASTContext() const {
   return getCompilerInstance()->getASTContext();
 }
 
+void Interpreter::markUserCodeStart() {
+  assert(!InitPTUSize && "We only do this once");
+  InitPTUSize = IncrParser->getPTUs().size();
+}
+
 size_t Interpreter::getEffectivePTUSize() const {
   std::list &PTUs = IncrParser->getPTUs();
   assert(PTUs.size() >= InitPTUSize && "empty PTU list?");
@@ -369,6 +375,10 @@ Interpreter::Parse(llvm::StringRef Code) {
 llvm::Error Interpreter::CreateExecutor() {
   const clang::TargetInfo &TI =
       getCompilerInstance()->getASTContext().getTargetInfo();
+  if (IncrExecutor)
+    return llvm::make_error("Operation failed. "
+                                               "Execution engine exists",
+                                               std::error_code());
   llvm::Error Err = llvm::Error::success();
   auto Executor = std::make_unique(*TSCtx, Err, TI);
   if (!Err)
@@ -377,6 +387,8 @@ llvm::Error Interpreter::CreateExecutor() {
   return Err;
 }
 
+void Interpreter::ResetExecutor() { IncrExecutor.reset(); }
+
 llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
   assert(T.TheModule);
   if (!IncrExecutor) {
@@ -505,9 +517,13 @@ static constexpr llvm::StringRef MagicRuntimeInterface[] = {
     "__clang_Interpreter_SetValueWithAlloc",
     "__clang_Interpreter_SetValueCopyArr", "__ci_newtag"};
 
-bool Interpreter::FindRuntimeInterface() {
+static std::unique_ptr
+createInProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &Ctx,
+                                       Sema &S);
+
+std::unique_ptr Interpreter::FindRuntimeInterface() {
   if (llvm::all_of(ValuePrintingInfo, [](Expr *E) { return E != nullptr; }))
-    return true;
+    return nullptr;
 
   Sema &S = getCompilerInstance()->getSema();
   ASTContext &Ctx = S.getASTContext();
@@ -526,120 +542,34 @@ bool Interpreter::FindRuntimeInterface() {
 
   if (!LookupInterface(ValuePrintingInfo[NoAlloc],
                        MagicRuntimeInterface[NoAlloc]))
-    return false;
+    return nullptr;
   if (!LookupInterface(ValuePrintingInfo[WithAlloc],
                        MagicRuntimeInterface[WithAlloc]))
-    return false;
+    return nullptr;
   if (!LookupInterface(ValuePrintingInfo[CopyArray],
                        MagicRuntimeInterface[CopyArray]))
-    return false;
+    return nullptr;
   if (!LookupInterface(ValuePrintingInfo[NewTag],
                        MagicRuntimeInterface[NewTag]))
-    return false;
-  return true;
+    return nullptr;
+
+  return createInProcessRuntimeInterfaceBuilder(*this, Ctx, S);
 }
 
 namespace {
 
-class RuntimeInterfaceBuilder
-    : public TypeVisitor {
-  clang::Interpreter &Interp;
+class InterfaceKindVisitor
+    : public TypeVisitor {
+  friend class InProcessRuntimeInterfaceBuilder;
+
   ASTContext &Ctx;
   Sema &S;
   Expr *E;
   llvm::SmallVector Args;
 
 public:
-  RuntimeInterfaceBuilder(clang::Interpreter &In, ASTContext &C, Sema &SemaRef,
-                          Expr *VE, ArrayRef FixedArgs)
-      : Interp(In), Ctx(C), S(SemaRef), E(VE) {
-    // The Interpreter* parameter and the out parameter `OutVal`.
-    for (Expr *E : FixedArgs)
-      Args.push_back(E);
-
-    // Get rid of ExprWithCleanups.
-    if (auto *EWC = llvm::dyn_cast_if_present(E))
-      E = EWC->getSubExpr();
-  }
-
-  ExprResult getCall() {
-    QualType Ty = E->getType();
-    QualType DesugaredTy = Ty.getDesugaredType(Ctx);
-
-    // For lvalue struct, we treat it as a reference.
-    if (DesugaredTy->isRecordType() && E->isLValue()) {
-      DesugaredTy = Ctx.getLValueReferenceType(DesugaredTy);
-      Ty = Ctx.getLValueReferenceType(Ty);
-    }
-
-    Expr *TypeArg =
-        CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)Ty.getAsOpaquePtr());
-    // The QualType parameter `OpaqueType`, represented as `void*`.
-    Args.push_back(TypeArg);
-
-    // We push the last parameter based on the type of the Expr. Note we need
-    // special care for rvalue struct.
-    Interpreter::InterfaceKind Kind = Visit(&*DesugaredTy);
-    switch (Kind) {
-    case Interpreter::InterfaceKind::WithAlloc:
-    case Interpreter::InterfaceKind::CopyArray: {
-      // __clang_Interpreter_SetValueWithAlloc.
-      ExprResult AllocCall = S.ActOnCallExpr(
-          /*Scope=*/nullptr,
-          Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc],
-          E->getBeginLoc(), Args, E->getEndLoc());
-      assert(!AllocCall.isInvalid() && "Can't create runtime interface call!");
-
-      TypeSourceInfo *TSI = Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation());
-
-      // Force CodeGen to emit destructor.
-      if (auto *RD = Ty->getAsCXXRecordDecl()) {
-        auto *Dtor = S.LookupDestructor(RD);
-        Dtor->addAttr(UsedAttr::CreateImplicit(Ctx));
-        Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl(
-            DeclGroupRef(Dtor));
-      }
-
-      // __clang_Interpreter_SetValueCopyArr.
-      if (Kind == Interpreter::InterfaceKind::CopyArray) {
-        const auto *ConstantArrTy =
-            cast(DesugaredTy.getTypePtr());
-        size_t ArrSize = Ctx.getConstantArrayElementCount(ConstantArrTy);
-        Expr *ArrSizeExpr = IntegerLiteralExpr(Ctx, ArrSize);
-        Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr};
-        return S.ActOnCallExpr(
-            /*Scope *=*/nullptr,
-            Interp
-                .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray],
-            SourceLocation(), Args, SourceLocation());
-      }
-      Expr *Args[] = {
-          AllocCall.get(),
-          Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]};
-      ExprResult CXXNewCall = S.BuildCXXNew(
-          E->getSourceRange(),
-          /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args,
-          /*PlacementRParen=*/SourceLocation(),
-          /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt,
-          E->getSourceRange(), E);
-
-      assert(!CXXNewCall.isInvalid() &&
-             "Can't create runtime placement new call!");
-
-      return S.ActOnFinishFullExpr(CXXNewCall.get(),
-                                   /*DiscardedValue=*/false);
-    }
-      // __clang_Interpreter_SetValueNoAlloc.
-    case Interpreter::InterfaceKind::NoAlloc: {
-      return S.ActOnCallExpr(
-          /*Scope=*/nullptr,
-          Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc],
-          E->getBeginLoc(), Args, E->getEndLoc());
-    }
-    default:
-      llvm_unreachable("Unhandled Interpreter::InterfaceKind");
-    }
-  }
+  InterfaceKindVisitor(ASTContext &Ctx, Sema &S, Expr *E)
+      : Ctx(Ctx), S(S), E(E) {}
 
   Interpreter::InterfaceKind VisitRecordType(const RecordType *Ty) {
     return Interpreter::InterfaceKind::WithAlloc;
@@ -711,8 +641,124 @@ private:
     Args.push_back(CastedExpr.get());
   }
 };
+
+class InProcessRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder {
+  Interpreter &Interp;
+  ASTContext &Ctx;
+  Sema &S;
+
+public:
+  InProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &C, Sema &S)
+      : Interp(Interp), Ctx(C), S(S) {}
+
+  TransformExprFunction *getPrintValueTransformer() override {
+    return &transformForValuePrinting;
+  }
+
+private:
+  static ExprResult transformForValuePrinting(RuntimeInterfaceBuilder *Builder,
+                                              Expr *E,
+                                              ArrayRef FixedArgs) {
+    auto *B = static_cast(Builder);
+
+    // Get rid of ExprWithCleanups.
+    if (auto *EWC = llvm::dyn_cast_if_present(E))
+      E = EWC->getSubExpr();
+
+    InterfaceKindVisitor Visitor(B->Ctx, B->S, E);
+
+    // The Interpreter* parameter and the out parameter `OutVal`.
+    for (Expr *E : FixedArgs)
+      Visitor.Args.push_back(E);
+
+    QualType Ty = E->getType();
+    QualType DesugaredTy = Ty.getDesugaredType(B->Ctx);
+
+    // For lvalue struct, we treat it as a reference.
+    if (DesugaredTy->isRecordType() && E->isLValue()) {
+      DesugaredTy = B->Ctx.getLValueReferenceType(DesugaredTy);
+      Ty = B->Ctx.getLValueReferenceType(Ty);
+    }
+
+    Expr *TypeArg = CStyleCastPtrExpr(B->S, B->Ctx.VoidPtrTy,
+                                      (uintptr_t)Ty.getAsOpaquePtr());
+    // The QualType parameter `OpaqueType`, represented as `void*`.
+    Visitor.Args.push_back(TypeArg);
+
+    // We push the last parameter based on the type of the Expr. Note we need
+    // special care for rvalue struct.
+    Interpreter::InterfaceKind Kind = Visitor.Visit(&*DesugaredTy);
+    switch (Kind) {
+    case Interpreter::InterfaceKind::WithAlloc:
+    case Interpreter::InterfaceKind::CopyArray: {
+      // __clang_Interpreter_SetValueWithAlloc.
+      ExprResult AllocCall = B->S.ActOnCallExpr(
+          /*Scope=*/nullptr,
+          B->Interp
+              .getValuePrintingInfo()[Interpreter::InterfaceKind::WithAlloc],
+          E->getBeginLoc(), Visitor.Args, E->getEndLoc());
+      assert(!AllocCall.isInvalid() && "Can't create runtime interface call!");
+
+      TypeSourceInfo *TSI =
+          B->Ctx.getTrivialTypeSourceInfo(Ty, SourceLocation());
+
+      // Force CodeGen to emit destructor.
+      if (auto *RD = Ty->getAsCXXRecordDecl()) {
+        auto *Dtor = B->S.LookupDestructor(RD);
+        Dtor->addAttr(UsedAttr::CreateImplicit(B->Ctx));
+        B->Interp.getCompilerInstance()->getASTConsumer().HandleTopLevelDecl(
+            DeclGroupRef(Dtor));
+      }
+
+      // __clang_Interpreter_SetValueCopyArr.
+      if (Kind == Interpreter::InterfaceKind::CopyArray) {
+        const auto *ConstantArrTy =
+            cast(DesugaredTy.getTypePtr());
+        size_t ArrSize = B->Ctx.getConstantArrayElementCount(ConstantArrTy);
+        Expr *ArrSizeExpr = IntegerLiteralExpr(B->Ctx, ArrSize);
+        Expr *Args[] = {E, AllocCall.get(), ArrSizeExpr};
+        return B->S.ActOnCallExpr(
+            /*Scope *=*/nullptr,
+            B->Interp
+                .getValuePrintingInfo()[Interpreter::InterfaceKind::CopyArray],
+            SourceLocation(), Args, SourceLocation());
+      }
+      Expr *Args[] = {
+          AllocCall.get(),
+          B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NewTag]};
+      ExprResult CXXNewCall = B->S.BuildCXXNew(
+          E->getSourceRange(),
+          /*UseGlobal=*/true, /*PlacementLParen=*/SourceLocation(), Args,
+          /*PlacementRParen=*/SourceLocation(),
+          /*TypeIdParens=*/SourceRange(), TSI->getType(), TSI, std::nullopt,
+          E->getSourceRange(), E);
+
+      assert(!CXXNewCall.isInvalid() &&
+             "Can't create runtime placement new call!");
+
+      return B->S.ActOnFinishFullExpr(CXXNewCall.get(),
+                                      /*DiscardedValue=*/false);
+    }
+      // __clang_Interpreter_SetValueNoAlloc.
+    case Interpreter::InterfaceKind::NoAlloc: {
+      return B->S.ActOnCallExpr(
+          /*Scope=*/nullptr,
+          B->Interp.getValuePrintingInfo()[Interpreter::InterfaceKind::NoAlloc],
+          E->getBeginLoc(), Visitor.Args, E->getEndLoc());
+    }
+    default:
+      llvm_unreachable("Unhandled Interpreter::InterfaceKind");
+    }
+  }
+};
 } // namespace
 
+static std::unique_ptr
+createInProcessRuntimeInterfaceBuilder(Interpreter &Interp, ASTContext &Ctx,
+                                       Sema &S) {
+  return std::make_unique(Interp, Ctx, S);
+}
+
 // This synthesizes a call expression to a speciall
 // function that is responsible for generating the Value.
 // In general, we transform:
@@ -731,8 +777,13 @@ Expr *Interpreter::SynthesizeExpr(Expr *E) {
   Sema &S = getCompilerInstance()->getSema();
   ASTContext &Ctx = S.getASTContext();
 
-  if (!FindRuntimeInterface())
-    llvm_unreachable("We can't find the runtime iterface for pretty print!");
+  if (!RuntimeIB) {
+    RuntimeIB = FindRuntimeInterface();
+    AddPrintValueCall = RuntimeIB->getPrintValueTransformer();
+  }
+
+  assert(AddPrintValueCall &&
+         "We don't have a runtime interface for pretty print!");
 
   // Create parameter `ThisInterp`.
   auto *ThisInterp = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)this);
@@ -741,9 +792,9 @@ Expr *Interpreter::SynthesizeExpr(Expr *E) {
   auto *OutValue = CStyleCastPtrExpr(S, Ctx.VoidPtrTy, (uintptr_t)&LastValue);
 
   // Build `__clang_Interpreter_SetValue*` call.
-  RuntimeInterfaceBuilder Builder(*this, Ctx, S, E, {ThisInterp, OutValue});
+  ExprResult Result =
+      AddPrintValueCall(RuntimeIB.get(), E, {ThisInterp, OutValue});
 
-  ExprResult Result = Builder.getCall();
   // It could fail, like printing an array type in C. (not supported)
   if (Result.isInvalid())
     return E;
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index edfab11c37cf0f3717d1493e0e9da4de8eba4a95..dd179414a14191e814779047d74c794e2ab1f844 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -1234,8 +1234,11 @@ void Parser::ParseAvailabilityAttribute(
   }
   IdentifierLoc *Platform = ParseIdentifierLoc();
   if (const IdentifierInfo *const Ident = Platform->Ident) {
+    // Disallow xrOS for availability attributes.
+    if (Ident->getName().contains("xrOS") || Ident->getName().contains("xros"))
+      Diag(Platform->Loc, diag::warn_availability_unknown_platform) << Ident;
     // Canonicalize platform name from "macosx" to "macos".
-    if (Ident->getName() == "macosx")
+    else if (Ident->getName() == "macosx")
       Platform->Ident = PP.getIdentifierInfo("macos");
     // Canonicalize platform name from "macosx_app_extension" to
     // "macos_app_extension".
@@ -4265,6 +4268,8 @@ void Parser::ParseDeclarationSpecifiers(
 
     // constexpr, consteval, constinit specifiers
     case tok::kw_constexpr:
+      if (getLangOpts().C23)
+        Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();
       isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constexpr, Loc,
                                       PrevSpec, DiagID);
       break;
@@ -5676,24 +5681,32 @@ Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() {
   // Parse a top-level-stmt.
   Parser::StmtVector Stmts;
   ParsedStmtContext SubStmtCtx = ParsedStmtContext();
-  Actions.PushFunctionScope();
+  ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |
+                               Scope::CompoundStmtScope);
+  TopLevelStmtDecl *TLSD = Actions.ActOnStartTopLevelStmtDecl(getCurScope());
   StmtResult R = ParseStatementOrDeclaration(Stmts, SubStmtCtx);
-  Actions.PopFunctionScopeInfo();
   if (!R.isUsable())
     return nullptr;
 
-  SmallVector DeclsInGroup;
-  DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(R.get()));
+  Actions.ActOnFinishTopLevelStmtDecl(TLSD, R.get());
 
   if (Tok.is(tok::annot_repl_input_end) &&
       Tok.getAnnotationValue() != nullptr) {
     ConsumeAnnotationToken();
-    cast(DeclsInGroup.back())->setSemiMissing();
+    TLSD->setSemiMissing();
   }
 
-  // Currently happens for things like  -fms-extensions and use `__if_exists`.
-  for (Stmt *S : Stmts)
-    DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(S));
+  SmallVector DeclsInGroup;
+  DeclsInGroup.push_back(TLSD);
+
+  // Currently happens for things like -fms-extensions and use `__if_exists`.
+  for (Stmt *S : Stmts) {
+    // Here we should be safe as `__if_exists` and friends are not introducing
+    // new variables which need to live outside file scope.
+    TopLevelStmtDecl *D = Actions.ActOnStartTopLevelStmtDecl(getCurScope());
+    Actions.ActOnFinishTopLevelStmtDecl(D, S);
+    DeclsInGroup.push_back(D);
+  }
 
   return Actions.BuildDeclaratorGroup(DeclsInGroup);
 }
@@ -7928,7 +7941,7 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) {
   // Adding back the bracket info to the end of the Declarator.
   for (unsigned i = 0, e = TempDeclarator.getNumTypeObjects(); i < e; ++i) {
     const DeclaratorChunk &Chunk = TempDeclarator.getTypeObject(i);
-    D.AddTypeInfo(Chunk, SourceLocation());
+    D.AddTypeInfo(Chunk, TempDeclarator.getAttributePool(), SourceLocation());
   }
 
   // The missing identifier would have been diagnosed in ParseDirectDeclarator.
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 62632b2d79792efeb7c2d57ad20de7000a3b88d3..77d2382ea6d907ae94d1caeefb7b0d0e8756331d 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4528,6 +4528,61 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
   }
 }
 
+/// Parse the argument to C++23's [[assume()]] attribute.
+bool Parser::ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs,
+                                        IdentifierInfo *AttrName,
+                                        SourceLocation AttrNameLoc,
+                                        SourceLocation *EndLoc) {
+  assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");
+  BalancedDelimiterTracker T(*this, tok::l_paren);
+  T.consumeOpen();
+
+  // [dcl.attr.assume]: The expression is potentially evaluated.
+  EnterExpressionEvaluationContext Unevaluated(
+      Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
+
+  TentativeParsingAction TPA(*this);
+  ExprResult Res(
+      Actions.CorrectDelayedTyposInExpr(ParseConditionalExpression()));
+  if (Res.isInvalid()) {
+    TPA.Commit();
+    SkipUntil(tok::r_paren, tok::r_square, StopAtSemi | StopBeforeMatch);
+    if (Tok.is(tok::r_paren))
+      T.consumeClose();
+    return true;
+  }
+
+  if (!Tok.isOneOf(tok::r_paren, tok::r_square)) {
+    // Emit a better diagnostic if this is an otherwise valid expression that
+    // is not allowed here.
+    TPA.Revert();
+    Res = ParseExpression();
+    if (!Res.isInvalid()) {
+      auto *E = Res.get();
+      Diag(E->getExprLoc(), diag::err_assume_attr_expects_cond_expr)
+          << AttrName << FixItHint::CreateInsertion(E->getBeginLoc(), "(")
+          << FixItHint::CreateInsertion(PP.getLocForEndOfToken(E->getEndLoc()),
+                                        ")")
+          << E->getSourceRange();
+    }
+
+    T.consumeClose();
+    return true;
+  }
+
+  TPA.Commit();
+  ArgsUnion Assumption = Res.get();
+  auto RParen = Tok.getLocation();
+  T.consumeClose();
+  Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), nullptr,
+               SourceLocation(), &Assumption, 1, ParsedAttr::Form::CXX11());
+
+  if (EndLoc)
+    *EndLoc = RParen;
+
+  return false;
+}
+
 /// ParseCXX11AttributeArgs -- Parse a C++11 attribute-argument-clause.
 ///
 /// [C++11] attribute-argument-clause:
@@ -4579,7 +4634,9 @@ bool Parser::ParseCXX11AttributeArgs(
     return true;
   }
 
-  if (ScopeName && ScopeName->isStr("omp")) {
+  // [[omp::directive]] and [[omp::sequence]] need special handling.
+  if (ScopeName && ScopeName->isStr("omp") &&
+      (AttrName->isStr("directive") || AttrName->isStr("sequence"))) {
     Diag(AttrNameLoc, getLangOpts().OpenMP >= 51
                           ? diag::warn_omp51_compat_attributes
                           : diag::ext_omp_attributes);
@@ -4596,7 +4653,12 @@ bool Parser::ParseCXX11AttributeArgs(
   if (ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang")))
     NumArgs = ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc,
                                       ScopeName, ScopeLoc, Form);
-  else
+  // So does C++23's assume() attribute.
+  else if (!ScopeName && AttrName->isStr("assume")) {
+    if (ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc))
+      return true;
+    NumArgs = 1;
+  } else
     NumArgs = ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
                                        ScopeName, ScopeLoc, Form);
 
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 4bf954b5cc4db5f85f0cbe7c75e47da9581cb54c..88c3a1469e8ed44e9bb7622cf1c64f6fe1aa65f7 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -179,6 +179,19 @@ ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) {
   return ParseRHSOfBinaryExpression(LHS, prec::Assignment);
 }
 
+ExprResult Parser::ParseConditionalExpression() {
+  if (Tok.is(tok::code_completion)) {
+    cutOffParsing();
+    Actions.CodeCompleteExpression(getCurScope(),
+                                   PreferredType.get(Tok.getLocation()));
+    return ExprError();
+  }
+
+  ExprResult LHS = ParseCastExpression(
+      AnyCastExpr, /*isAddressOfOperand=*/false, NotTypeCast);
+  return ParseRHSOfBinaryExpression(LHS, prec::Conditional);
+}
+
 /// Parse an assignment expression where part of an Objective-C message
 /// send has already been parsed.
 ///
@@ -3863,7 +3876,8 @@ std::optional Parser::ParseAvailabilitySpec() {
     StringRef Platform =
         AvailabilityAttr::canonicalizePlatformName(GivenPlatform);
 
-    if (AvailabilityAttr::getPrettyPlatformName(Platform).empty()) {
+    if (AvailabilityAttr::getPrettyPlatformName(Platform).empty() ||
+        (GivenPlatform.contains("xros") || GivenPlatform.contains("xrOS"))) {
       Diag(PlatformIdentifier->Loc,
            diag::err_avail_query_unrecognized_platform_name)
           << GivenPlatform;
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 22ee60af4616d25fa8eeec12934fd8d93a7f0465..9471f6f725efb17dde13f4c1c42b1365a13777ce 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -3908,7 +3908,10 @@ ExprResult Parser::ParseTypeTrait() {
   SmallVector Args;
   do {
     // Parse the next type.
-    TypeResult Ty = ParseTypeName();
+    TypeResult Ty =
+        ParseTypeName(/*SourceRange=*/nullptr,
+                      getLangOpts().CPlusPlus ? DeclaratorContext::TemplateArg
+                                              : DeclaratorContext::TypeName);
     if (Ty.isInvalid()) {
       Parens.skipToEnd();
       return ExprError();
@@ -3950,7 +3953,8 @@ ExprResult Parser::ParseArrayTypeTrait() {
   if (T.expectAndConsume())
     return ExprError();
 
-  TypeResult Ty = ParseTypeName();
+  TypeResult Ty =
+      ParseTypeName(/*SourceRange=*/nullptr, DeclaratorContext::TemplateArg);
   if (Ty.isInvalid()) {
     SkipUntil(tok::comma, StopAtSemi);
     SkipUntil(tok::r_paren, StopAtSemi);
diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp
index 4946a61fca007f8aba866e71ed104c6bb06c7a8c..50e3c39f60919b8d0d7a60c241f9a9f4f1d923a5 100644
--- a/clang/lib/Parse/ParseOpenACC.cpp
+++ b/clang/lib/Parse/ParseOpenACC.cpp
@@ -555,6 +555,8 @@ bool doesDirectiveHaveAssociatedStmt(OpenACCDirectiveKind DirKind) {
   default:
     return false;
   case OpenACCDirectiveKind::Parallel:
+  case OpenACCDirectiveKind::Serial:
+  case OpenACCDirectiveKind::Kernels:
     return true;
   }
   llvm_unreachable("Unhandled directive->assoc stmt");
@@ -563,6 +565,8 @@ bool doesDirectiveHaveAssociatedStmt(OpenACCDirectiveKind DirKind) {
 unsigned getOpenACCScopeFlags(OpenACCDirectiveKind DirKind) {
   switch (DirKind) {
   case OpenACCDirectiveKind::Parallel:
+  case OpenACCDirectiveKind::Serial:
+  case OpenACCDirectiveKind::Kernels:
     // Mark this as a BreakScope/ContinueScope as well as a compute construct
     // so that we can diagnose trying to 'break'/'continue' inside of one.
     return Scope::BreakScope | Scope::ContinueScope |
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index bfc31f2653c2370260597eab2e691efca6e63fb8..814126e321d3bc930877a4022cd9562332ab43cc 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -2984,8 +2984,29 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
     OMPDirectiveScope.Exit();
     break;
   }
+  case OMPD_declare_target: {
+    SourceLocation DTLoc = ConsumeAnyToken();
+    bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);
+    Sema::DeclareTargetContextInfo DTCI(DKind, DTLoc);
+    if (HasClauses)
+      ParseOMPDeclareTargetClauses(DTCI);
+    bool HasImplicitMappings =
+        !HasClauses || (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
+
+    if (HasImplicitMappings) {
+      Diag(Tok, diag::err_omp_unexpected_directive)
+          << 1 << getOpenMPDirectiveName(DKind);
+      SkipUntil(tok::annot_pragma_openmp_end);
+      break;
+    }
+
+    // Skip the last annot_pragma_openmp_end.
+    ConsumeAnyToken();
+
+    Actions.ActOnFinishedOpenMPDeclareTargetContext(DTCI);
+    break;
+  }
   case OMPD_declare_simd:
-  case OMPD_declare_target:
   case OMPD_begin_declare_target:
   case OMPD_end_declare_target:
   case OMPD_requires:
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 8239ba49429d3c5c6fede316a11034c24783cf49..6992ba9ad9a7564ee9c2325f610fcb29ff2fa8fc 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -1,4 +1,4 @@
-//=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- C++ -*-=//
+//=== AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis ------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index aede602f1de84c7b3e4c9961856d4ca186175388..b79683bb32a69ec559c401fb3329c648cfdea686 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -1377,6 +1377,20 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) {
       ThreadStorageClassSpec = TSCS_unspecified;
       ThreadStorageClassSpecLoc = SourceLocation();
     }
+    if (S.getLangOpts().C23 &&
+        getConstexprSpecifier() == ConstexprSpecKind::Constexpr) {
+      S.Diag(ConstexprLoc, diag::err_invalid_decl_spec_combination)
+          << DeclSpec::getSpecifierName(getThreadStorageClassSpec())
+          << SourceRange(getThreadStorageClassSpecLoc());
+    }
+  }
+
+  if (S.getLangOpts().C23 &&
+      getConstexprSpecifier() == ConstexprSpecKind::Constexpr &&
+      StorageClassSpec == SCS_extern) {
+    S.Diag(ConstexprLoc, diag::err_invalid_decl_spec_combination)
+        << DeclSpec::getSpecifierName(getStorageClassSpec())
+        << SourceRange(getStorageClassSpecLoc());
   }
 
   // If no type specifier was provided and we're parsing a language where
diff --git a/clang/lib/Sema/ParsedAttr.cpp b/clang/lib/Sema/ParsedAttr.cpp
index 06c213267c7ef5da8e8c657e9ec1b7eefc285d4c..6abc90336c9946aa0a3bd3b44078603ee899a999 100644
--- a/clang/lib/Sema/ParsedAttr.cpp
+++ b/clang/lib/Sema/ParsedAttr.cpp
@@ -100,6 +100,12 @@ void AttributePool::takePool(AttributePool &pool) {
   pool.Attrs.clear();
 }
 
+void AttributePool::takeFrom(ParsedAttributesView &List, AttributePool &Pool) {
+  assert(&Pool != this && "AttributePool can't take attributes from itself");
+  llvm::for_each(List.AttrList, [&Pool](ParsedAttr *A) { Pool.remove(A); });
+  Attrs.insert(Attrs.end(), List.AttrList.begin(), List.AttrList.end());
+}
+
 namespace {
 
 #include "clang/Sema/AttrParsedAttrImpl.inc"
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index cfb653e665ea03dcd422634b8a54f14a95098b7f..720d5fd5f0428dda84bc7c90008debb5e0c7ba89 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -188,38 +188,38 @@ const uint64_t Sema::MaximumAlignment;
 
 Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
            TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter)
-    : ExternalSource(nullptr), CurFPFeatures(pp.getLangOpts()),
+    : CollectStats(false), TUKind(TUKind), CurFPFeatures(pp.getLangOpts()),
       LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer),
       Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
-      APINotes(SourceMgr, LangOpts), CollectStats(false),
-      CodeCompleter(CodeCompleter), CurContext(nullptr),
-      OriginalLexicalContext(nullptr), MSStructPragmaOn(false),
+      APINotes(SourceMgr, LangOpts), AnalysisWarnings(*this),
+      ThreadSafetyDeclCache(nullptr), LateTemplateParser(nullptr),
+      LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr),
+      CurContext(nullptr), ExternalSource(nullptr), CurScope(nullptr),
+      Ident_super(nullptr),
       MSPointerToMemberRepresentationMethod(
           LangOpts.getMSPointerToMemberRepresentationMethod()),
-      VtorDispStack(LangOpts.getVtorDispMode()),
+      MSStructPragmaOn(false), VtorDispStack(LangOpts.getVtorDispMode()),
       AlignPackStack(AlignPackInfo(getLangOpts().XLPragmaPack)),
       DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
       CodeSegStack(nullptr), StrictGuardStackCheckStack(false),
       FpPragmaStack(FPOptionsOverride()), CurInitSeg(nullptr),
       VisContext(nullptr), PragmaAttributeCurrentTargetDecl(nullptr),
-      IsBuildingRecoveryCallExpr(false), LateTemplateParser(nullptr),
-      LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),
-      StdInitializerList(nullptr), StdCoroutineTraitsCache(nullptr),
-      CXXTypeInfoDecl(nullptr), StdSourceLocationImplDecl(nullptr),
+      StdCoroutineTraitsCache(nullptr), IdResolver(pp),
+      OriginalLexicalContext(nullptr), StdInitializerList(nullptr),
+      FullyCheckedComparisonCategories(
+          static_cast(ComparisonCategoryType::Last) + 1),
+      StdSourceLocationImplDecl(nullptr), CXXTypeInfoDecl(nullptr),
+      GlobalNewDeleteDeclared(false), DisableTypoCorrection(false),
+      TyposCorrected(0), IsBuildingRecoveryCallExpr(false), NumSFINAEErrors(0),
+      AccessCheckingSFINAE(false), CurrentInstantiationScope(nullptr),
+      InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
+      ArgumentPackSubstitutionIndex(-1), SatisfactionCache(Context),
       NSNumberDecl(nullptr), NSValueDecl(nullptr), NSStringDecl(nullptr),
       StringWithUTF8StringMethod(nullptr),
       ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr),
       ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr),
-      DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false),
-      TUKind(TUKind), NumSFINAEErrors(0),
-      FullyCheckedComparisonCategories(
-          static_cast(ComparisonCategoryType::Last) + 1),
-      SatisfactionCache(Context), AccessCheckingSFINAE(false),
-      InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0),
-      ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(nullptr),
-      DisableTypoCorrection(false), TyposCorrected(0), AnalysisWarnings(*this),
-      ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr),
-      CurScope(nullptr), Ident_super(nullptr) {
+      DictionaryWithObjectsMethod(nullptr), CodeCompleter(CodeCompleter),
+      VarDataSharingAttributesStack(nullptr) {
   assert(pp.TUKind == TUKind);
   TUScope = nullptr;
 
diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp
index 6a66ecf6f94c178da3dbf86687175c4f63d76f7d..4d4f4b6a2d4d95a6a1313266e71d1ea449ea0ff7 100644
--- a/clang/lib/Sema/SemaCUDA.cpp
+++ b/clang/lib/Sema/SemaCUDA.cpp
@@ -895,7 +895,10 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) {
   if (DiagKind == SemaDiagnosticBuilder::K_Nop) {
     // For -fgpu-rdc, keep track of external kernels used by host functions.
     if (LangOpts.CUDAIsDevice && LangOpts.GPURelocatableDeviceCode &&
-        Callee->hasAttr() && !Callee->isDefined())
+        Callee->hasAttr() && !Callee->isDefined() &&
+        (!Caller || (!Caller->getDescribedFunctionTemplate() &&
+                     getASTContext().GetGVALinkageForFunction(Caller) ==
+                         GVA_StrongExternal)))
       getASTContext().CUDAExternalDeviceDeclODRUsedByHost.insert(Callee);
     return true;
   }
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 0d4d57db01c93ad828072b120ed7eee51e9eb868..a5f42b630c3fa2459b7d6e360838597d22028186 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5271,6 +5271,11 @@ bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall) {
 // returning an ExprError
 bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
   switch (BuiltinID) {
+  case Builtin::BI__builtin_hlsl_elementwise_any: {
+    if (checkArgCount(*this, TheCall, 1))
+      return true;
+    break;
+  }
   case Builtin::BI__builtin_hlsl_dot: {
     if (checkArgCount(*this, TheCall, 2))
       return true;
@@ -5280,6 +5285,7 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
       return true;
     break;
   }
+  case Builtin::BI__builtin_hlsl_elementwise_rcp:
   case Builtin::BI__builtin_hlsl_elementwise_frac: {
     if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))
       return true;
@@ -5298,6 +5304,14 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
       return true;
     break;
   }
+  case Builtin::BI__builtin_hlsl_mad: {
+    if (checkArgCount(*this, TheCall, 3))
+      return true;
+    if (CheckVectorElementCallArgs(this, TheCall))
+      return true;
+    if (SemaBuiltinElementwiseTernaryMath(TheCall, /*CheckForFloatArgs*/ false))
+      return true;
+  }
   }
   return false;
 }
@@ -5307,6 +5321,9 @@ bool Sema::CheckAMDGCNBuiltinFunctionCall(unsigned BuiltinID,
   // position of memory order and scope arguments in the builtin
   unsigned OrderIndex, ScopeIndex;
   switch (BuiltinID) {
+  case AMDGPU::BI__builtin_amdgcn_get_fpenv:
+  case AMDGPU::BI__builtin_amdgcn_set_fpenv:
+    return false;
   case AMDGPU::BI__builtin_amdgcn_atomic_inc32:
   case AMDGPU::BI__builtin_amdgcn_atomic_inc64:
   case AMDGPU::BI__builtin_amdgcn_atomic_dec32:
@@ -6377,10 +6394,14 @@ void Sema::checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D) {
   unsigned EltSize = Context.getTypeSize(Info.ElementType);
   unsigned MinElts = Info.EC.getKnownMinValue();
 
+  if (Info.ElementType->isSpecificBuiltinType(BuiltinType::Double) &&
+      !TI.hasFeature("zve64d"))
+    Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve64d";
   // (ELEN, LMUL) pairs of (8, mf8), (16, mf4), (32, mf2), (64, m1) requires at
   // least zve64x
-  if (((EltSize == 64 && Info.ElementType->isIntegerType()) || MinElts == 1) &&
-      !TI.hasFeature("zve64x"))
+  else if (((EltSize == 64 && Info.ElementType->isIntegerType()) ||
+            MinElts == 1) &&
+           !TI.hasFeature("zve64x"))
     Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve64x";
   else if (Info.ElementType->isFloat16Type() && !TI.hasFeature("zvfh") &&
            !TI.hasFeature("zvfhmin"))
@@ -6392,9 +6413,6 @@ void Sema::checkRVVTypeSupport(QualType Ty, SourceLocation Loc, Decl *D) {
   else if (Info.ElementType->isSpecificBuiltinType(BuiltinType::Float) &&
            !TI.hasFeature("zve32f"))
     Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve32f";
-  else if (Info.ElementType->isSpecificBuiltinType(BuiltinType::Double) &&
-           !TI.hasFeature("zve64d"))
-    Diag(Loc, diag::err_riscv_type_requires_extension, D) << Ty << "zve64d";
   // Given that caller already checked isRVVType() before calling this function,
   // if we don't have at least zve32x supported, then we need to emit error.
   else if (!TI.hasFeature("zve32x"))
@@ -11509,7 +11527,7 @@ void CheckFormatHandler::EmitFormatDiagnostic(
   }
 }
 
-//===--- CHECK: Printf format string checking ------------------------------===//
+//===--- CHECK: Printf format string checking -----------------------------===//
 
 namespace {
 
@@ -17624,20 +17642,8 @@ public:
       return VisitExpr(CCE);
 
     // In C++11, list initializations are sequenced.
-    SmallVector Elts;
-    SequenceTree::Seq Parent = Region;
-    for (CXXConstructExpr::const_arg_iterator I = CCE->arg_begin(),
-                                              E = CCE->arg_end();
-         I != E; ++I) {
-      Region = Tree.allocate(Parent);
-      Elts.push_back(Region);
-      Visit(*I);
-    }
-
-    // Forget that the initializers are sequenced.
-    Region = Parent;
-    for (unsigned I = 0; I < Elts.size(); ++I)
-      Tree.merge(Elts[I]);
+    SequenceExpressionsInOrder(
+        llvm::ArrayRef(CCE->getArgs(), CCE->getNumArgs()));
   }
 
   void VisitInitListExpr(const InitListExpr *ILE) {
@@ -17645,10 +17651,20 @@ public:
       return VisitExpr(ILE);
 
     // In C++11, list initializations are sequenced.
+    SequenceExpressionsInOrder(ILE->inits());
+  }
+
+  void VisitCXXParenListInitExpr(const CXXParenListInitExpr *PLIE) {
+    // C++20 parenthesized list initializations are sequenced. See C++20
+    // [decl.init.general]p16.5 and [decl.init.general]p16.6.2.2.
+    SequenceExpressionsInOrder(PLIE->getInitExprs());
+  }
+
+private:
+  void SequenceExpressionsInOrder(ArrayRef ExpressionList) {
     SmallVector Elts;
     SequenceTree::Seq Parent = Region;
-    for (unsigned I = 0; I < ILE->getNumInits(); ++I) {
-      const Expr *E = ILE->getInit(I);
+    for (const Expr *E : ExpressionList) {
       if (!E)
         continue;
       Region = Tree.allocate(Parent);
@@ -19077,18 +19093,17 @@ void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
   LHSExpr = LHSExpr->IgnoreParenImpCasts();
   RHSExpr = RHSExpr->IgnoreParenImpCasts();
 
-  // Check for a call expression
-  const CallExpr *CE = dyn_cast(RHSExpr);
-  if (!CE || CE->getNumArgs() != 1)
-    return;
-
-  // Check for a call to std::move
-  if (!CE->isCallToStdMove())
+  // Check for a call to std::move or for a static_cast(..) to an xvalue
+  // which we can treat as an inlined std::move
+  if (const auto *CE = dyn_cast(RHSExpr);
+      CE && CE->getNumArgs() == 1 && CE->isCallToStdMove())
+    RHSExpr = CE->getArg(0);
+  else if (const auto *CXXSCE = dyn_cast(RHSExpr);
+           CXXSCE && CXXSCE->isXValue())
+    RHSExpr = CXXSCE->getSubExpr();
+  else
     return;
 
-  // Get argument from std::move
-  RHSExpr = CE->getArg(0);
-
   const DeclRefExpr *LHSDeclRef = dyn_cast(LHSExpr);
   const DeclRefExpr *RHSDeclRef = dyn_cast(RHSExpr);
 
@@ -19169,8 +19184,24 @@ static bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) {
 }
 
 /// Check if two fields are layout-compatible.
+/// Can be used on union members, which are exempt from alignment requirement
+/// of common initial sequence.
 static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
-                               FieldDecl *Field2) {
+                               FieldDecl *Field2,
+                               bool AreUnionMembers = false) {
+  [[maybe_unused]] const Type *Field1Parent =
+      Field1->getParent()->getTypeForDecl();
+  [[maybe_unused]] const Type *Field2Parent =
+      Field2->getParent()->getTypeForDecl();
+  assert(((Field1Parent->isStructureOrClassType() &&
+           Field2Parent->isStructureOrClassType()) ||
+          (Field1Parent->isUnionType() && Field2Parent->isUnionType())) &&
+         "Can't evaluate layout compatibility between a struct field and a "
+         "union field.");
+  assert(((!AreUnionMembers && Field1Parent->isStructureOrClassType()) ||
+          (AreUnionMembers && Field1Parent->isUnionType())) &&
+         "AreUnionMembers should be 'true' for union fields (only).");
+
   if (!isLayoutCompatible(C, Field1->getType(), Field2->getType()))
     return false;
 
@@ -19189,6 +19220,11 @@ static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
   if (Field1->hasAttr() ||
       Field2->hasAttr())
     return false;
+
+  if (!AreUnionMembers &&
+      Field1->getMaxAlignment() != Field2->getMaxAlignment())
+    return false;
+
   return true;
 }
 
@@ -19250,7 +19286,7 @@ static bool isLayoutCompatibleUnion(ASTContext &C, RecordDecl *RD1,
         E = UnmatchedFields.end();
 
     for ( ; I != E; ++I) {
-      if (isLayoutCompatible(C, Field1, *I)) {
+      if (isLayoutCompatible(C, Field1, *I, /*IsUnionMember=*/true)) {
         bool Result = UnmatchedFields.erase(*I);
         (void) Result;
         assert(Result);
@@ -19800,7 +19836,8 @@ bool Sema::SemaBuiltinVectorMath(CallExpr *TheCall, QualType &Res) {
   return false;
 }
 
-bool Sema::SemaBuiltinElementwiseTernaryMath(CallExpr *TheCall) {
+bool Sema::SemaBuiltinElementwiseTernaryMath(CallExpr *TheCall,
+                                             bool CheckForFloatArgs) {
   if (checkArgCount(*this, TheCall, 3))
     return true;
 
@@ -19812,11 +19849,20 @@ bool Sema::SemaBuiltinElementwiseTernaryMath(CallExpr *TheCall) {
     Args[I] = Converted.get();
   }
 
-  int ArgOrdinal = 1;
-  for (Expr *Arg : Args) {
-    if (checkFPMathBuiltinElementType(*this, Arg->getBeginLoc(), Arg->getType(),
+  if (CheckForFloatArgs) {
+    int ArgOrdinal = 1;
+    for (Expr *Arg : Args) {
+      if (checkFPMathBuiltinElementType(*this, Arg->getBeginLoc(),
+                                        Arg->getType(), ArgOrdinal++))
+        return true;
+    }
+  } else {
+    int ArgOrdinal = 1;
+    for (Expr *Arg : Args) {
+      if (checkMathBuiltinElementType(*this, Arg->getBeginLoc(), Arg->getType(),
                                       ArgOrdinal++))
-      return true;
+        return true;
+    }
   }
 
   for (int I = 1; I < 3; ++I) {
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index c44be0df9b0a853f2ee2fcb88e59691a5398f27c..8d75239009401e22a2f57370b2be4f5725852098 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -6137,6 +6137,7 @@ ProduceSignatureHelp(Sema &SemaRef, MutableArrayRef Candidates,
 // so that we can recover argument names from it.
 static FunctionProtoTypeLoc GetPrototypeLoc(Expr *Fn) {
   TypeLoc Target;
+
   if (const auto *T = Fn->getType().getTypePtr()->getAs()) {
     Target = T->getDecl()->getTypeSourceInfo()->getTypeLoc();
 
@@ -6145,6 +6146,11 @@ static FunctionProtoTypeLoc GetPrototypeLoc(Expr *Fn) {
     if (const auto *const VD = dyn_cast(D)) {
       Target = VD->getTypeSourceInfo()->getTypeLoc();
     }
+  } else if (const auto *ME = dyn_cast(Fn)) {
+    const auto *MD = ME->getMemberDecl();
+    if (const auto *FD = dyn_cast(MD)) {
+      Target = FD->getTypeSourceInfo()->getTypeLoc();
+    }
   }
 
   if (!Target)
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 2878e4d31ee8fec53aea5be2323baa7f7bb749e6..a8e387e35fb4c90095cb18212f413a34c6b7f87a 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -586,7 +586,8 @@ bool Sema::addInstantiatedCapturesToScope(
 
 bool Sema::SetupConstraintScope(
     FunctionDecl *FD, std::optional> TemplateArgs,
-    MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope) {
+    const MultiLevelTemplateArgumentList &MLTAL,
+    LocalInstantiationScope &Scope) {
   if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
     FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
     InstantiatingTemplate Inst(
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index a969b9383563b22a22b36137a852570f88c4249f..736632857efc36997d039c0037e7ffdbe1e88b98 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -347,99 +347,15 @@ static Expr *maybeTailCall(Sema &S, QualType RetType, Expr *E,
 
   Expr *JustAddress = AddressExpr.get();
 
-  // FIXME: Without optimizations, the temporary result from `await_suspend()`
-  // may be put on the coroutine frame since the coroutine frame constructor
-  // will think the temporary variable will escape from the
-  // `coroutine_handle<>::address()` call. This is problematic since the
-  // coroutine should be considered to be suspended after it enters
-  // `await_suspend` so it shouldn't access/update the coroutine frame after
-  // that.
-  //
-  // See https://github.com/llvm/llvm-project/issues/65054 for the report.
-  //
-  // The long term solution may wrap the whole logic about `await-suspend`
-  // into a standalone function. This is similar to the proposed solution
-  // in tryMarkAwaitSuspendNoInline. See the comments there for details.
-  //
-  // The short term solution here is to mark `coroutine_handle<>::address()`
-  // function as always-inline so that the coroutine frame constructor won't
-  // think the temporary result is escaped incorrectly.
-  if (auto *FD = cast(JustAddress)->getDirectCallee())
-    if (!FD->hasAttr() && !FD->hasAttr())
-      FD->addAttr(AlwaysInlineAttr::CreateImplicit(S.getASTContext(),
-                                                   FD->getLocation()));
-
   // Check that the type of AddressExpr is void*
   if (!JustAddress->getType().getTypePtr()->isVoidPointerType())
     S.Diag(cast(JustAddress)->getCalleeDecl()->getLocation(),
            diag::warn_coroutine_handle_address_invalid_return_type)
         << JustAddress->getType();
 
-  // Clean up temporary objects so that they don't live across suspension points
-  // unnecessarily. We choose to clean up before the call to
-  // __builtin_coro_resume so that the cleanup code are not inserted in-between
-  // the resume call and return instruction, which would interfere with the
-  // musttail call contract.
-  JustAddress = S.MaybeCreateExprWithCleanups(JustAddress);
-  return S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_resume,
-                                JustAddress);
-}
-
-/// The await_suspend call performed by co_await is essentially asynchronous
-/// to the execution of the coroutine. Inlining it normally into an unsplit
-/// coroutine can cause miscompilation because the coroutine CFG misrepresents
-/// the true control flow of the program: things that happen in the
-/// await_suspend are not guaranteed to happen prior to the resumption of the
-/// coroutine, and things that happen after the resumption of the coroutine
-/// (including its exit and the potential deallocation of the coroutine frame)
-/// are not guaranteed to happen only after the end of await_suspend.
-///
-/// See https://github.com/llvm/llvm-project/issues/56301 and
-/// https://reviews.llvm.org/D157070 for the example and the full discussion.
-///
-/// The short-term solution to this problem is to mark the call as uninlinable.
-/// But we don't want to do this if the call is known to be trivial, which is
-/// very common.
-///
-/// The long-term solution may introduce patterns like:
-///
-///  call @llvm.coro.await_suspend(ptr %awaiter, ptr %handle,
-///                                ptr @awaitSuspendFn)
-///
-/// Then it is much easier to perform the safety analysis in the middle end.
-/// If it is safe to inline the call to awaitSuspend, we can replace it in the
-/// CoroEarly pass. Otherwise we could replace it in the CoroSplit pass.
-static void tryMarkAwaitSuspendNoInline(Sema &S, OpaqueValueExpr *Awaiter,
-                                        CallExpr *AwaitSuspend) {
-  // The method here to extract the awaiter decl is not precise.
-  // This is intentional. Since it is hard to perform the analysis in the
-  // frontend due to the complexity of C++'s type systems.
-  // And we prefer to perform such analysis in the middle end since it is
-  // easier to implement and more powerful.
-  CXXRecordDecl *AwaiterDecl =
-      Awaiter->getType().getNonReferenceType()->getAsCXXRecordDecl();
-
-  if (AwaiterDecl && AwaiterDecl->field_empty())
-    return;
-
-  FunctionDecl *FD = AwaitSuspend->getDirectCallee();
-
-  assert(FD);
-
-  // If the `await_suspend()` function is marked as `always_inline` explicitly,
-  // we should give the user the right to control the codegen.
-  if (FD->hasAttr() || FD->hasAttr())
-    return;
-
-  // This is problematic if the user calls the await_suspend standalone. But on
-  // the on hand, it is not incorrect semantically since inlining is not part
-  // of the standard. On the other hand, it is relatively rare to call
-  // the await_suspend function standalone.
-  //
-  // And given we've already had the long-term plan, the current workaround
-  // looks relatively tolerant.
-  FD->addAttr(
-      NoInlineAttr::CreateImplicit(S.getASTContext(), FD->getLocation()));
+  // Clean up temporary objects, because the resulting expression
+  // will become the body of await_suspend wrapper.
+  return S.MaybeCreateExprWithCleanups(JustAddress);
 }
 
 /// Build calls to await_ready, await_suspend, and await_resume for a co_await
@@ -513,10 +429,6 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise,
     //     type Z.
     QualType RetType = AwaitSuspend->getCallReturnType(S.Context);
 
-    // We need to mark await_suspend as noinline temporarily. See the comment
-    // of tryMarkAwaitSuspendNoInline for details.
-    tryMarkAwaitSuspendNoInline(S, Operand, AwaitSuspend);
-
     // Support for coroutine_handle returning await_suspend.
     if (Expr *TailCallSuspend =
             maybeTailCall(S, RetType, AwaitSuspend, Loc))
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 3ae78748a4e4994160d41b03ed634e6ca01b8eeb..1f4a041e88dfff1b2fea8154c549322808beb66d 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -5144,6 +5144,8 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
       Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag)
           << GetDiagnosticTypeSpecifierID(DS)
           << static_cast(DS.getConstexprSpecifier());
+    else if (getLangOpts().C23)
+      Diag(DS.getConstexprSpecLoc(), diag::err_c23_constexpr_not_variable);
     else
       Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_wrong_decl_kind)
           << static_cast(DS.getConstexprSpecifier());
@@ -8646,6 +8648,38 @@ static bool checkForConflictWithNonVisibleExternC(Sema &S, const T *ND,
   return false;
 }
 
+static bool CheckC23ConstexprVarType(Sema &SemaRef, SourceLocation VarLoc,
+                                     QualType T) {
+  QualType CanonT = SemaRef.Context.getCanonicalType(T);
+  // C23 6.7.1p5: An object declared with storage-class specifier constexpr or
+  // any of its members, even recursively, shall not have an atomic type, or a
+  // variably modified type, or a type that is volatile or restrict qualified.
+  if (CanonT->isVariablyModifiedType()) {
+    SemaRef.Diag(VarLoc, diag::err_c23_constexpr_invalid_type) << T;
+    return true;
+  }
+
+  // Arrays are qualified by their element type, so get the base type (this
+  // works on non-arrays as well).
+  CanonT = SemaRef.Context.getBaseElementType(CanonT);
+
+  if (CanonT->isAtomicType() || CanonT.isVolatileQualified() ||
+      CanonT.isRestrictQualified()) {
+    SemaRef.Diag(VarLoc, diag::err_c23_constexpr_invalid_type) << T;
+    return true;
+  }
+
+  if (CanonT->isRecordType()) {
+    const RecordDecl *RD = CanonT->getAsRecordDecl();
+    if (llvm::any_of(RD->fields(), [&SemaRef, VarLoc](const FieldDecl *F) {
+          return CheckC23ConstexprVarType(SemaRef, VarLoc, F->getType());
+        }))
+      return true;
+  }
+
+  return false;
+}
+
 void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
   // If the decl is already known invalid, don't check it.
   if (NewVD->isInvalidDecl())
@@ -8896,6 +8930,12 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
     return;
   }
 
+  if (getLangOpts().C23 && NewVD->isConstexpr() &&
+      CheckC23ConstexprVarType(*this, NewVD->getLocation(), T)) {
+    NewVD->setInvalidDecl();
+    return;
+  }
+
   if (NewVD->isConstexpr() && !T->isDependentType() &&
       RequireLiteralType(NewVD->getLocation(), T,
                          diag::err_constexpr_var_non_literal)) {
@@ -9278,6 +9318,22 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
   FunctionDecl *NewFD = nullptr;
   bool isInline = D.getDeclSpec().isInlineSpecified();
 
+  ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier();
+  if (ConstexprKind == ConstexprSpecKind::Constinit ||
+      (SemaRef.getLangOpts().C23 &&
+       ConstexprKind == ConstexprSpecKind::Constexpr)) {
+
+    if (SemaRef.getLangOpts().C23)
+      SemaRef.Diag(D.getDeclSpec().getConstexprSpecLoc(),
+                   diag::err_c23_constexpr_not_variable);
+    else
+      SemaRef.Diag(D.getDeclSpec().getConstexprSpecLoc(),
+                   diag::err_constexpr_wrong_decl_kind)
+          << static_cast(ConstexprKind);
+    ConstexprKind = ConstexprSpecKind::Unspecified;
+    D.getMutableDeclSpec().ClearConstexprSpec();
+  }
+
   if (!SemaRef.getLangOpts().CPlusPlus) {
     // Determine whether the function was written with a prototype. This is
     // true when:
@@ -9311,15 +9367,6 @@ static FunctionDecl *CreateNewFunctionDecl(Sema &SemaRef, Declarator &D,
   }
 
   ExplicitSpecifier ExplicitSpecifier = D.getDeclSpec().getExplicitSpecifier();
-
-  ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier();
-  if (ConstexprKind == ConstexprSpecKind::Constinit) {
-    SemaRef.Diag(D.getDeclSpec().getConstexprSpecLoc(),
-                 diag::err_constexpr_wrong_decl_kind)
-        << static_cast(ConstexprKind);
-    ConstexprKind = ConstexprSpecKind::Unspecified;
-    D.getMutableDeclSpec().ClearConstexprSpec();
-  }
   Expr *TrailingRequiresClause = D.getTrailingRequiresClause();
 
   SemaRef.CheckExplicitObjectMemberFunction(DC, D, Name, R);
@@ -11429,6 +11476,16 @@ static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD,
                                              bool &Redeclaration,
                                              NamedDecl *&OldDecl,
                                              LookupResult &Previous) {
+  assert(!OldFD->isMultiVersion() && "Unexpected MultiVersion");
+
+  // The definitions should be allowed in any order. If we have discovered
+  // a new target version and the preceeding was the default, then add the
+  // corresponding attribute to it.
+  if (OldFD->getMultiVersionKind() == MultiVersionKind::None &&
+      NewFD->getMultiVersionKind() == MultiVersionKind::TargetVersion)
+    OldFD->addAttr(TargetVersionAttr::CreateImplicit(S.Context, "default",
+                                                     OldFD->getSourceRange()));
+
   const auto *NewTA = NewFD->getAttr();
   const auto *NewTVA = NewFD->getAttr();
   const auto *OldTA = OldFD->getAttr();
@@ -11455,9 +11512,8 @@ static bool CheckTargetCausesMultiVersioning(Sema &S, FunctionDecl *OldFD,
   }
 
   // If this is 'default', permit the forward declaration.
-  if (!OldFD->isMultiVersion() &&
-      ((NewTA && NewTA->isDefaultVersion() && !OldTA) ||
-       (NewTVA && NewTVA->isDefaultVersion() && !OldTVA))) {
+  if ((NewTA && NewTA->isDefaultVersion() && !OldTA) ||
+      (NewTVA && NewTVA->isDefaultVersion() && !OldTVA)) {
     Redeclaration = true;
     OldDecl = OldFD;
     OldFD->setIsMultiVersion();
@@ -13906,7 +13962,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
       VDecl->setStorageClass(SC_Extern);
 
     // C99 6.7.8p4. All file scoped initializers need to be constant.
-    if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl())
+    // Avoid duplicate diagnostics for constexpr variables.
+    if (!getLangOpts().CPlusPlus && !VDecl->isInvalidDecl() &&
+        !VDecl->isConstexpr())
       CheckForConstantInitializer(Init, DclT);
   }
 
@@ -14517,9 +14575,13 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
   QualType baseType = Context.getBaseElementType(type);
   bool HasConstInit = true;
 
+  if (getLangOpts().C23 && var->isConstexpr() && !Init)
+    Diag(var->getLocation(), diag::err_constexpr_var_requires_const_init)
+        << var;
+
   // Check whether the initializer is sufficiently constant.
-  if (getLangOpts().CPlusPlus && !type->isDependentType() && Init &&
-      !Init->isValueDependent() &&
+  if ((getLangOpts().CPlusPlus || (getLangOpts().C23 && var->isConstexpr())) &&
+      !type->isDependentType() && Init && !Init->isValueDependent() &&
       (GlobalStorage || var->isConstexpr() ||
        var->mightBeUsableInConstantExpressions(Context))) {
     // If this variable might have a constant initializer or might be usable in
@@ -14527,7 +14589,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
     // do this lazily, because the result might depend on things that change
     // later, such as which constexpr functions happen to be defined.
     SmallVector Notes;
-    if (!getLangOpts().CPlusPlus11) {
+    if (!getLangOpts().CPlusPlus11 && !getLangOpts().C23) {
       // Prior to C++11, in contexts where a constant initializer is required,
       // the set of valid constant initializers is described by syntactic rules
       // in [expr.const]p2-6.
@@ -15730,10 +15792,19 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
   // captures during transformation of nested lambdas, it is necessary to
   // have the LSI properly restored.
   if (isGenericLambdaCallOperatorSpecialization(FD)) {
-    assert(inTemplateInstantiation() &&
-           "There should be an active template instantiation on the stack "
-           "when instantiating a generic lambda!");
-    RebuildLambdaScopeInfo(cast(D));
+    // C++2c 7.5.5.2p17 A member of a closure type shall not be explicitly
+    // instantiated, explicitly specialized.
+    if (FD->getTemplateSpecializationInfo()
+            ->isExplicitInstantiationOrSpecialization()) {
+      Diag(FD->getLocation(), diag::err_lambda_explicit_spec);
+      FD->setInvalidDecl();
+      PushFunctionScope();
+    } else {
+      assert(inTemplateInstantiation() &&
+             "There should be an active template instantiation on the stack "
+             "when instantiating a generic lambda!");
+      RebuildLambdaScopeInfo(cast(D));
+    }
   } else {
     // Enter a new function scope
     PushFunctionScope();
@@ -16252,9 +16323,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
         }
       }
 
-      assert(
-          (FD == getCurFunctionDecl() || getCurLambda()->CallOperator == FD) &&
-          "Function parsing confused");
+      assert((FD == getCurFunctionDecl(/*AllowLambdas=*/true)) &&
+             "Function parsing confused");
     } else if (ObjCMethodDecl *MD = dyn_cast_or_null(dcl)) {
       assert(MD == getCurMethodDecl() && "Method parsing confused");
       MD->setBody(Body);
@@ -20454,12 +20524,22 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr,
   return New;
 }
 
-Decl *Sema::ActOnTopLevelStmtDecl(Stmt *Statement) {
-  auto *New = TopLevelStmtDecl::Create(Context, Statement);
-  Context.getTranslationUnitDecl()->addDecl(New);
+TopLevelStmtDecl *Sema::ActOnStartTopLevelStmtDecl(Scope *S) {
+  auto *New = TopLevelStmtDecl::Create(Context, /*Statement=*/nullptr);
+  CurContext->addDecl(New);
+  PushDeclContext(S, New);
+  PushFunctionScope();
+  PushCompoundScope(false);
   return New;
 }
 
+void Sema::ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl *D, Stmt *Statement) {
+  D->setStmt(Statement);
+  PopCompoundScope();
+  PopFunctionScopeInfo();
+  PopDeclContext();
+}
+
 void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name,
                                       IdentifierInfo* AliasName,
                                       SourceLocation PragmaLoc,
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 397b5db0dc066994364e4b9ede72548eb8c9aeb8..c00120b59d396ebaf31c42fc88148f59b9f12576 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -1771,8 +1771,8 @@ void Sema::AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
 }
 
 /// Check if \p AssumptionStr is a known assumption and warn if not.
-static void checkAssumptionAttr(Sema &S, SourceLocation Loc,
-                                StringRef AssumptionStr) {
+static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc,
+                               StringRef AssumptionStr) {
   if (llvm::KnownAssumptionStrings.count(AssumptionStr))
     return;
 
@@ -1788,22 +1788,23 @@ static void checkAssumptionAttr(Sema &S, SourceLocation Loc,
   }
 
   if (!Suggestion.empty())
-    S.Diag(Loc, diag::warn_assume_attribute_string_unknown_suggested)
+    S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
         << AssumptionStr << Suggestion;
   else
-    S.Diag(Loc, diag::warn_assume_attribute_string_unknown) << AssumptionStr;
+    S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
+        << AssumptionStr;
 }
 
-static void handleAssumumptionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+static void handleOMPAssumeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   // Handle the case where the attribute has a text message.
   StringRef Str;
   SourceLocation AttrStrLoc;
   if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
     return;
 
-  checkAssumptionAttr(S, AttrStrLoc, Str);
+  checkOMPAssumeAttr(S, AttrStrLoc, Str);
 
-  D->addAttr(::new (S.Context) AssumptionAttr(S.Context, AL, Str));
+  D->addAttr(::new (S.Context) OMPAssumeAttr(S.Context, AL, Str));
 }
 
 /// Normalize the attribute, __foo__ becomes foo.
@@ -4877,7 +4878,9 @@ void Sema::AddModeAttr(Decl *D, const AttributeCommonInfo &CI,
     NewElemTy = Context.getRealTypeForBitwidth(DestWidth, ExplicitType);
 
   if (NewElemTy.isNull()) {
-    Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
+    // Only emit diagnostic on host for 128-bit mode attribute
+    if (!(DestWidth == 128 && getLangOpts().CUDAIsDevice))
+      Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
     return;
   }
 
@@ -9489,8 +9492,8 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
   case ParsedAttr::AT_Unavailable:
     handleAttrWithMessage(S, D, AL);
     break;
-  case ParsedAttr::AT_Assumption:
-    handleAssumumptionAttr(S, D, AL);
+  case ParsedAttr::AT_OMPAssume:
+    handleOMPAssumeAttr(S, D, AL);
     break;
   case ParsedAttr::AT_ObjCDirect:
     handleObjCDirectAttr(S, D, AL);
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 199f2523cfb5d26dedbaf7092cb38c7d97b5d389..e258a4f7c894154a062757bb06924166709df94f 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1715,6 +1715,8 @@ static bool CheckLiteralType(Sema &SemaRef, Sema::CheckConstexprKind Kind,
 static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
                                                const CXXDestructorDecl *DD,
                                                Sema::CheckConstexprKind Kind) {
+  assert(!SemaRef.getLangOpts().CPlusPlus23 &&
+         "this check is obsolete for C++23");
   auto Check = [&](SourceLocation Loc, QualType T, const FieldDecl *FD) {
     const CXXRecordDecl *RD =
         T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
@@ -1746,6 +1748,8 @@ static bool CheckConstexprDestructorSubobjects(Sema &SemaRef,
 static bool CheckConstexprParameterTypes(Sema &SemaRef,
                                          const FunctionDecl *FD,
                                          Sema::CheckConstexprKind Kind) {
+  assert(!SemaRef.getLangOpts().CPlusPlus23 &&
+         "this check is obsolete for C++23");
   unsigned ArgIndex = 0;
   const auto *FT = FD->getType()->castAs();
   for (FunctionProtoType::param_type_iterator i = FT->param_type_begin(),
@@ -1767,6 +1771,8 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef,
 /// true. If not, produce a suitable diagnostic and return false.
 static bool CheckConstexprReturnType(Sema &SemaRef, const FunctionDecl *FD,
                                      Sema::CheckConstexprKind Kind) {
+  assert(!SemaRef.getLangOpts().CPlusPlus23 &&
+         "this check is obsolete for C++23");
   if (CheckLiteralType(SemaRef, Kind, FD->getLocation(), FD->getReturnType(),
                        diag::err_constexpr_non_literal_return,
                        FD->isConsteval()))
@@ -1856,16 +1862,18 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD,
       }
     }
 
-    // - its return type shall be a literal type;
-    if (!CheckConstexprReturnType(*this, NewFD, Kind))
+    // - its return type shall be a literal type; (removed in C++23)
+    if (!getLangOpts().CPlusPlus23 &&
+        !CheckConstexprReturnType(*this, NewFD, Kind))
       return false;
   }
 
   if (auto *Dtor = dyn_cast(NewFD)) {
     // A destructor can be constexpr only if the defaulted destructor could be;
     // we don't need to check the members and bases if we already know they all
-    // have constexpr destructors.
-    if (!Dtor->getParent()->defaultedDestructorIsConstexpr()) {
+    // have constexpr destructors. (removed in C++23)
+    if (!getLangOpts().CPlusPlus23 &&
+        !Dtor->getParent()->defaultedDestructorIsConstexpr()) {
       if (Kind == CheckConstexprKind::CheckValid)
         return false;
       if (!CheckConstexprDestructorSubobjects(*this, Dtor, Kind))
@@ -1873,8 +1881,9 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD,
     }
   }
 
-  // - each of its parameter types shall be a literal type;
-  if (!CheckConstexprParameterTypes(*this, NewFD, Kind))
+  // - each of its parameter types shall be a literal type; (removed in C++23)
+  if (!getLangOpts().CPlusPlus23 &&
+      !CheckConstexprParameterTypes(*this, NewFD, Kind))
     return false;
 
   Stmt *Body = NewFD->getBody();
@@ -2457,7 +2466,8 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
   // function", so is not checked in CheckValid mode.
   SmallVector Diags;
   if (Kind == Sema::CheckConstexprKind::Diagnose &&
-      !Expr::isPotentialConstantExpr(Dcl, Diags)) {
+      !Expr::isPotentialConstantExpr(Dcl, Diags) &&
+      !SemaRef.getLangOpts().CPlusPlus23) {
     SemaRef.Diag(Dcl->getLocation(),
                  diag::ext_constexpr_function_never_constant_expr)
         << isa(Dcl) << Dcl->isConsteval()
@@ -7535,21 +7545,23 @@ static bool defaultedSpecialMemberIsConstexpr(
 
   // C++1y [class.copy]p26:
   //   -- [the class] is a literal type, and
-  if (!Ctor && !ClassDecl->isLiteral())
+  if (!Ctor && !ClassDecl->isLiteral() && !S.getLangOpts().CPlusPlus23)
     return false;
 
   //   -- every constructor involved in initializing [...] base class
   //      sub-objects shall be a constexpr constructor;
   //   -- the assignment operator selected to copy/move each direct base
   //      class is a constexpr function, and
-  for (const auto &B : ClassDecl->bases()) {
-    const RecordType *BaseType = B.getType()->getAs();
-    if (!BaseType)
-      continue;
-    CXXRecordDecl *BaseClassDecl = cast(BaseType->getDecl());
-    if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg,
-                                  InheritedCtor, Inherited))
-      return false;
+  if (!S.getLangOpts().CPlusPlus23) {
+    for (const auto &B : ClassDecl->bases()) {
+      const RecordType *BaseType = B.getType()->getAs();
+      if (!BaseType)
+        continue;
+      CXXRecordDecl *BaseClassDecl = cast(BaseType->getDecl());
+      if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg,
+                                    InheritedCtor, Inherited))
+        return false;
+    }
   }
 
   //   -- every constructor involved in initializing non-static data members
@@ -7559,20 +7571,22 @@ static bool defaultedSpecialMemberIsConstexpr(
   //   -- for each non-static data member of X that is of class type (or array
   //      thereof), the assignment operator selected to copy/move that member is
   //      a constexpr function
-  for (const auto *F : ClassDecl->fields()) {
-    if (F->isInvalidDecl())
-      continue;
-    if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer())
-      continue;
-    QualType BaseType = S.Context.getBaseElementType(F->getType());
-    if (const RecordType *RecordTy = BaseType->getAs()) {
-      CXXRecordDecl *FieldRecDecl = cast(RecordTy->getDecl());
-      if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM,
-                                    BaseType.getCVRQualifiers(),
-                                    ConstArg && !F->isMutable()))
+  if (!S.getLangOpts().CPlusPlus23) {
+    for (const auto *F : ClassDecl->fields()) {
+      if (F->isInvalidDecl())
+        continue;
+      if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer())
+        continue;
+      QualType BaseType = S.Context.getBaseElementType(F->getType());
+      if (const RecordType *RecordTy = BaseType->getAs()) {
+        CXXRecordDecl *FieldRecDecl = cast(RecordTy->getDecl());
+        if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM,
+                                      BaseType.getCVRQualifiers(),
+                                      ConstArg && !F->isMutable()))
+          return false;
+      } else if (CSM == Sema::CXXDefaultConstructor) {
         return false;
-    } else if (CSM == Sema::CXXDefaultConstructor) {
-      return false;
+      }
     }
   }
 
@@ -7858,18 +7872,17 @@ bool Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
       MD->isConstexpr() && !Constexpr &&
       MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
         if (!MD->isConsteval() && RD->getNumVBases()) {
-          Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr_with_vb)
+          Diag(MD->getBeginLoc(),
+               diag::err_incorrect_defaulted_constexpr_with_vb)
               << CSM;
           for (const auto &I : RD->vbases())
             Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here);
         } else {
-          Diag(MD->getBeginLoc(), MD->isConsteval()
-                                      ? diag::err_incorrect_defaulted_consteval
-                                      : diag::err_incorrect_defaulted_constexpr)
-              << CSM;
+          Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr)
+              << CSM << MD->isConsteval();
         }
-    // FIXME: Explain why the special member can't be constexpr.
-    HadError = true;
+        HadError = true;
+        // FIXME: Explain why the special member can't be constexpr.
   }
 
   if (First) {
@@ -9101,13 +9114,11 @@ bool Sema::CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *FD,
   //    - if the function is a constructor or destructor, its class does not
   //      have any virtual base classes.
   if (FD->isConstexpr()) {
-    if (CheckConstexprReturnType(*this, FD, CheckConstexprKind::Diagnose) &&
+    if (!getLangOpts().CPlusPlus23 &&
+        CheckConstexprReturnType(*this, FD, CheckConstexprKind::Diagnose) &&
         CheckConstexprParameterTypes(*this, FD, CheckConstexprKind::Diagnose) &&
         !Info.Constexpr) {
-      Diag(FD->getBeginLoc(),
-           getLangOpts().CPlusPlus23
-               ? diag::warn_cxx23_compat_defaulted_comparison_constexpr_mismatch
-               : diag::ext_defaulted_comparison_constexpr_mismatch)
+      Diag(FD->getBeginLoc(), diag::err_defaulted_comparison_constexpr_mismatch)
           << FD->isImplicit() << (int)DCK << FD->isConsteval();
       DefaultedComparisonAnalyzer(*this, RD, FD, DCK,
                                   DefaultedComparisonAnalyzer::ExplainConstexpr)
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 3563b4f683f0794a60025c2bebbfd16d6c51b38f..00384f9dc16aa04bf43ff94243bda82f8aefb4fd 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1017,13 +1017,13 @@ CanThrowResult Sema::canCalleeThrow(Sema &S, const Expr *E, const Decl *D,
                                     SourceLocation Loc) {
   // As an extension, we assume that __attribute__((nothrow)) functions don't
   // throw.
-  if (D && isa(D) && D->hasAttr())
+  if (isa_and_nonnull(D) && D->hasAttr())
     return CT_Cannot;
 
   QualType T;
 
   // In C++1z, just look at the function type of the callee.
-  if (S.getLangOpts().CPlusPlus17 && E && isa(E)) {
+  if (S.getLangOpts().CPlusPlus17 && isa_and_nonnull(E)) {
     E = cast(E)->getCallee();
     T = E->getType();
     if (T->isSpecificPlaceholderType(BuiltinType::BoundMember)) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 0a449fc1082bd4c995f57181cdfa55ab28ba0a9a..93f82e68ab644047ec31fbc03150060bda3358f9 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6227,12 +6227,6 @@ struct ImmediateCallVisitor : public RecursiveASTVisitor {
     return VisitCXXMethodDecl(E->getCallOperator());
   }
 
-  // Blocks don't support default parameters, and, as for lambdas,
-  // we don't consider their body a subexpression.
-  bool VisitBlockDecl(BlockDecl *B) { return false; }
-
-  bool VisitCompoundStmt(CompoundStmt *B) { return false; }
-
   bool VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
     return TraverseStmt(E->getExpr());
   }
@@ -19224,7 +19218,10 @@ MarkVarDeclODRUsed(ValueDecl *V, SourceLocation Loc, Sema &SemaRef,
       // externalize the static device side variable ODR-used by host code.
       if (!Var->hasExternalStorage())
         SemaRef.getASTContext().CUDADeviceVarODRUsedByHost.insert(Var);
-      else if (SemaRef.LangOpts.GPURelocatableDeviceCode)
+      else if (SemaRef.LangOpts.GPURelocatableDeviceCode &&
+               (!FD || (!FD->getDescribedFunctionTemplate() &&
+                        SemaRef.getASTContext().GetGVALinkageForFunction(FD) ==
+                            GVA_StrongExternal)))
         SemaRef.getASTContext().CUDAExternalDeviceDeclODRUsedByHost.insert(Var);
     }
   }
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 0fd458837163e5ff895bfea3922a8972eafcc7fd..aa470adb30b47f545e063cf7102c8c2ac7c32e02 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -190,13 +190,35 @@ static void updateGNUCompoundLiteralRValue(Expr *E) {
   }
 }
 
+static bool initializingConstexprVariable(const InitializedEntity &Entity) {
+  Decl *D = Entity.getDecl();
+  const InitializedEntity *Parent = &Entity;
+
+  while (Parent) {
+    D = Parent->getDecl();
+    Parent = Parent->getParent();
+  }
+
+  if (const auto *VD = dyn_cast_if_present(D); VD && VD->isConstexpr())
+    return true;
+
+  return false;
+}
+
+static void CheckC23ConstexprInitStringLiteral(const StringLiteral *SE,
+                                               Sema &SemaRef, QualType &TT);
+
 static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT,
-                            Sema &S) {
+                            Sema &S, bool CheckC23ConstexprInit = false) {
   // Get the length of the string as parsed.
   auto *ConstantArrayTy =
       cast(Str->getType()->getAsArrayTypeUnsafe());
   uint64_t StrLength = ConstantArrayTy->getSize().getZExtValue();
 
+  if (CheckC23ConstexprInit)
+    if (const StringLiteral *SL = dyn_cast(Str->IgnoreParens()))
+      CheckC23ConstexprInitStringLiteral(SL, S, DeclT);
+
   if (const IncompleteArrayType *IAT = dyn_cast(AT)) {
     // C99 6.7.8p14. We have an array of character type with unknown size
     // being initialized to a string literal.
@@ -1476,7 +1498,9 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity,
     if (IsStringInit(expr, arrayType, SemaRef.Context) == SIF_None) {
       // FIXME: Should we do this checking in verify-only mode?
       if (!VerifyOnly)
-        CheckStringInit(expr, ElemType, arrayType, SemaRef);
+        CheckStringInit(expr, ElemType, arrayType, SemaRef,
+                        SemaRef.getLangOpts().C23 &&
+                            initializingConstexprVariable(Entity));
       if (StructuredList)
         UpdateStructuredListElement(StructuredList, StructuredIndex, expr);
       ++Index;
@@ -1941,7 +1965,9 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
       // constant for each string.
       // FIXME: Should we do these checks in verify-only mode too?
       if (!VerifyOnly)
-        CheckStringInit(IList->getInit(Index), DeclType, arrayType, SemaRef);
+        CheckStringInit(IList->getInit(Index), DeclType, arrayType, SemaRef,
+                        SemaRef.getLangOpts().C23 &&
+                            initializingConstexprVariable(Entity));
       if (StructuredList) {
         UpdateStructuredListElement(StructuredList, StructuredIndex,
                                     IList->getInit(Index));
@@ -2227,8 +2253,6 @@ void InitListChecker::CheckStructUnionTypes(
   size_t NumRecordDecls = llvm::count_if(RD->decls(), [&](const Decl *D) {
     return isa(D) || isa(D);
   });
-  bool CheckForMissingFields =
-    !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
   bool HasDesignatedInit = false;
 
   llvm::SmallPtrSet InitializedFields;
@@ -2269,11 +2293,6 @@ void InitListChecker::CheckStructUnionTypes(
       }
 
       InitializedSomething = true;
-
-      // Disable check for missing fields when designators are used.
-      // This matches gcc behaviour.
-      if (!SemaRef.getLangOpts().CPlusPlus)
-        CheckForMissingFields = false;
       continue;
     }
 
@@ -2285,7 +2304,7 @@ void InitListChecker::CheckStructUnionTypes(
     // These are okay for randomized structures. [C99 6.7.8p19]
     //
     // Also, if there is only one element in the structure, we allow something
-    // like this, because it's really not randomized in the tranditional sense.
+    // like this, because it's really not randomized in the traditional sense.
     //
     //   struct foo h = {bar};
     auto IsZeroInitializer = [&](const Expr *I) {
@@ -2363,8 +2382,13 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   // Emit warnings for missing struct field initializers.
-  if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
-      !RD->isUnion()) {
+  // This check is disabled for designated initializers in C.
+  // This matches gcc behaviour.
+  bool IsCDesignatedInitializer =
+      HasDesignatedInit && !SemaRef.getLangOpts().CPlusPlus;
+  if (!VerifyOnly && InitializedSomething && !RD->isUnion() &&
+      !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) &&
+      !IsCDesignatedInitializer) {
     // It is possible we have one or more unnamed bitfields remaining.
     // Find first (if any) named field and emit warning.
     for (RecordDecl::field_iterator it = HasDesignatedInit ? RD->field_begin()
@@ -2376,9 +2400,10 @@ void InitListChecker::CheckStructUnionTypes(
 
       if (!it->isUnnamedBitfield() && !it->hasInClassInitializer() &&
           !it->getType()->isIncompleteArrayType()) {
-        SemaRef.Diag(IList->getSourceRange().getEnd(),
-                     diag::warn_missing_field_initializers)
-            << *it;
+        auto Diag = HasDesignatedInit
+                        ? diag::warn_missing_designated_field_initializers
+                        : diag::warn_missing_field_initializers;
+        SemaRef.Diag(IList->getSourceRange().getEnd(), Diag) << *it;
         break;
       }
     }
@@ -7734,6 +7759,14 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
     break;
   }
 
+  case Stmt::CompoundLiteralExprClass: {
+    if (auto *CLE = dyn_cast(Init)) {
+      if (!CLE->isFileScope())
+        Visit(Path, Local(CLE), RK);
+    }
+    break;
+  }
+
   // FIXME: Visit the left-hand side of an -> or ->*.
 
   default:
@@ -8289,6 +8322,10 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity,
         if (LK == LK_StmtExprResult)
           return false;
         Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
+      } else if (auto *CLE = dyn_cast(L)) {
+        Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
+            << Entity.getType()->isReferenceType() << CLE->getInitializer() << 2
+            << DiagRange;
       } else {
         Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
          << Entity.getType()->isReferenceType() << DiagRange;
@@ -8366,6 +8403,9 @@ static void DiagnoseNarrowingInInitList(Sema &S,
                                         QualType EntityType,
                                         const Expr *PostInit);
 
+static void CheckC23ConstexprInitConversion(Sema &S, QualType FromType,
+                                            QualType ToType, Expr *Init);
+
 /// Provide warnings when std::move is used on construction.
 static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
                                     bool IsReturnStmt) {
@@ -9192,6 +9232,23 @@ ExprResult InitializationSequence::Perform(Sema &S,
         return ExprError();
       CurInit = CurInitExprRes;
 
+      if (S.getLangOpts().C23 && initializingConstexprVariable(Entity)) {
+        CheckC23ConstexprInitConversion(S, SourceType, Entity.getType(),
+                                        CurInit.get());
+
+        // C23 6.7.1p6: If an object or subobject declared with storage-class
+        // specifier constexpr has pointer, integer, or arithmetic type, any
+        // explicit initializer value for it shall be null, an integer
+        // constant expression, or an arithmetic constant expression,
+        // respectively.
+        Expr::EvalResult ER;
+        if (Entity.getType()->getAs() &&
+            CurInit.get()->EvaluateAsRValue(ER, S.Context) &&
+            !ER.Val.isNullPointer()) {
+          S.Diag(Kind.getLocation(), diag::err_c23_constexpr_pointer_not_null);
+        }
+      }
+
       bool Complained;
       if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(),
                                      Step->Type, SourceType,
@@ -9209,7 +9266,9 @@ ExprResult InitializationSequence::Perform(Sema &S,
       QualType Ty = Step->Type;
       bool UpdateType = ResultType && Entity.getType()->isIncompleteArrayType();
       CheckStringInit(CurInit.get(), UpdateType ? *ResultType : Ty,
-                      S.Context.getAsArrayType(Ty), S);
+                      S.Context.getAsArrayType(Ty), S,
+                      S.getLangOpts().C23 &&
+                          initializingConstexprVariable(Entity));
       break;
     }
 
@@ -10498,6 +10557,69 @@ static void DiagnoseNarrowingInInitList(Sema &S,
              S.getLocForEndOfToken(PostInit->getEndLoc()), ")");
 }
 
+static void CheckC23ConstexprInitConversion(Sema &S, QualType FromType,
+                                            QualType ToType, Expr *Init) {
+  assert(S.getLangOpts().C23);
+  ImplicitConversionSequence ICS = S.TryImplicitConversion(
+      Init->IgnoreParenImpCasts(), ToType, /*SuppressUserConversions*/ false,
+      Sema::AllowedExplicit::None,
+      /*InOverloadResolution*/ false,
+      /*CStyle*/ false,
+      /*AllowObjCWritebackConversion=*/false);
+
+  if (!ICS.isStandard())
+    return;
+
+  APValue Value;
+  QualType PreNarrowingType;
+  // Reuse C++ narrowing check.
+  switch (ICS.Standard.getNarrowingKind(
+      S.Context, Init, Value, PreNarrowingType,
+      /*IgnoreFloatToIntegralConversion*/ false)) {
+  // The value doesn't fit.
+  case NK_Constant_Narrowing:
+    S.Diag(Init->getBeginLoc(), diag::err_c23_constexpr_init_not_representable)
+        << Value.getAsString(S.Context, PreNarrowingType) << ToType;
+    return;
+
+  // Conversion to a narrower type.
+  case NK_Type_Narrowing:
+    S.Diag(Init->getBeginLoc(), diag::err_c23_constexpr_init_type_mismatch)
+        << ToType << FromType;
+    return;
+
+  // Since we only reuse narrowing check for C23 constexpr variables here, we're
+  // not really interested in these cases.
+  case NK_Dependent_Narrowing:
+  case NK_Variable_Narrowing:
+  case NK_Not_Narrowing:
+    return;
+  }
+  llvm_unreachable("unhandled case in switch");
+}
+
+static void CheckC23ConstexprInitStringLiteral(const StringLiteral *SE,
+                                               Sema &SemaRef, QualType &TT) {
+  assert(SemaRef.getLangOpts().C23);
+  // character that string literal contains fits into TT - target type.
+  const ArrayType *AT = SemaRef.Context.getAsArrayType(TT);
+  QualType CharType = AT->getElementType();
+  uint32_t BitWidth = SemaRef.Context.getTypeSize(CharType);
+  bool isUnsigned = CharType->isUnsignedIntegerType();
+  llvm::APSInt Value(BitWidth, isUnsigned);
+  for (unsigned I = 0, N = SE->getLength(); I != N; ++I) {
+    int64_t C = SE->getCodeUnitS(I, SemaRef.Context.getCharWidth());
+    Value = C;
+    if (Value != C) {
+      SemaRef.Diag(SemaRef.getLocationOfStringLiteralByte(SE, I),
+                   diag::err_c23_constexpr_init_not_representable)
+          << C << CharType;
+      return;
+    }
+  }
+  return;
+}
+
 //===----------------------------------------------------------------------===//
 // Initialization helper functions
 //===----------------------------------------------------------------------===//
@@ -10598,13 +10720,40 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
   if (TemplateName.isDependent())
     return SubstAutoTypeDependent(TSInfo->getType());
 
-  // We can only perform deduction for class templates.
+  // We can only perform deduction for class templates or alias templates.
   auto *Template =
       dyn_cast_or_null(TemplateName.getAsTemplateDecl());
+  TemplateDecl *LookupTemplateDecl = Template;
+  if (!Template) {
+    if (auto *AliasTemplate = dyn_cast_or_null(
+            TemplateName.getAsTemplateDecl())) {
+      Diag(Kind.getLocation(),
+           diag::warn_cxx17_compat_ctad_for_alias_templates);
+      LookupTemplateDecl = AliasTemplate;
+      auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+                                ->getUnderlyingType()
+                                .getCanonicalType();
+      // C++ [over.match.class.deduct#3]: ..., the defining-type-id of A must be
+      // of the form
+      //   [typename] [nested-name-specifier] [template] simple-template-id
+      if (const auto *TST =
+              UnderlyingType->getAs()) {
+        Template = dyn_cast_or_null(
+            TST->getTemplateName().getAsTemplateDecl());
+      } else if (const auto *RT = UnderlyingType->getAs()) {
+        // Cases where template arguments in the RHS of the alias are not
+        // dependent. e.g.
+        //   using AliasFoo = Foo;
+        if (const auto *CTSD = llvm::dyn_cast(
+                RT->getAsCXXRecordDecl()))
+          Template = CTSD->getSpecializedTemplate();
+      }
+    }
+  }
   if (!Template) {
     Diag(Kind.getLocation(),
-         diag::err_deduced_non_class_template_specialization_type)
-      << (int)getTemplateNameKindForDiagnostics(TemplateName) << TemplateName;
+         diag::err_deduced_non_class_or_alias_template_specialization_type)
+        << (int)getTemplateNameKindForDiagnostics(TemplateName) << TemplateName;
     if (auto *TD = TemplateName.getAsTemplateDecl())
       NoteTemplateLocation(*TD);
     return QualType();
@@ -10631,10 +10780,10 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
   //     template-name, a function template [...]
   //  - For each deduction-guide, a function or function template [...]
   DeclarationNameInfo NameInfo(
-      Context.DeclarationNames.getCXXDeductionGuideName(Template),
+      Context.DeclarationNames.getCXXDeductionGuideName(LookupTemplateDecl),
       TSInfo->getTypeLoc().getEndLoc());
   LookupResult Guides(*this, NameInfo, LookupOrdinaryName);
-  LookupQualifiedName(Guides, Template->getDeclContext());
+  LookupQualifiedName(Guides, LookupTemplateDecl->getDeclContext());
 
   // FIXME: Do not diagnose inaccessible deduction guides. The standard isn't
   // clear on this, but they're not found by name so access does not apply.
diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index ed7f626971f345ea9a80420fa334f2b05d7eef6b..f08c1cb3a13ef525add8252751fe1bebf4dff677 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -73,6 +73,90 @@ static std::string stringFromPath(ModuleIdPath Path) {
   return Name;
 }
 
+/// Helper function for makeTransitiveImportsVisible to decide whether
+/// the \param Imported module unit is in the same module with the \param
+/// CurrentModule.
+/// \param FoundPrimaryModuleInterface is a helper parameter to record the
+/// primary module interface unit corresponding to the module \param
+/// CurrentModule. Since currently it is expensive to decide whether two module
+/// units come from the same module by comparing the module name.
+static bool
+isImportingModuleUnitFromSameModule(Module *Imported, Module *CurrentModule,
+                                    Module *&FoundPrimaryModuleInterface) {
+  if (!Imported->isNamedModule())
+    return false;
+
+  // The a partition unit we're importing must be in the same module of the
+  // current module.
+  if (Imported->isModulePartition())
+    return true;
+
+  // If we found the primary module interface during the search process, we can
+  // return quickly to avoid expensive string comparison.
+  if (FoundPrimaryModuleInterface)
+    return Imported == FoundPrimaryModuleInterface;
+
+  if (!CurrentModule)
+    return false;
+
+  // Then the imported module must be a primary module interface unit.  It
+  // is only allowed to import the primary module interface unit from the same
+  // module in the implementation unit and the implementation partition unit.
+
+  // Since we'll handle implementation unit above. We can only care
+  // about the implementation partition unit here.
+  if (!CurrentModule->isModulePartitionImplementation())
+    return false;
+
+  if (Imported->getPrimaryModuleInterfaceName() ==
+      CurrentModule->getPrimaryModuleInterfaceName()) {
+    assert(!FoundPrimaryModuleInterface ||
+           FoundPrimaryModuleInterface == Imported);
+    FoundPrimaryModuleInterface = Imported;
+    return true;
+  }
+
+  return false;
+}
+
+/// [module.import]p7:
+///   Additionally, when a module-import-declaration in a module unit of some
+///   module M imports another module unit U of M, it also imports all
+///   translation units imported by non-exported module-import-declarations in
+///   the module unit purview of U. These rules can in turn lead to the
+///   importation of yet more translation units.
+static void
+makeTransitiveImportsVisible(VisibleModuleSet &VisibleModules, Module *Imported,
+                             Module *CurrentModule, SourceLocation ImportLoc,
+                             bool IsImportingPrimaryModuleInterface = false) {
+  assert(Imported->isNamedModule() &&
+         "'makeTransitiveImportsVisible()' is intended for standard C++ named "
+         "modules only.");
+
+  llvm::SmallVector Worklist;
+  Worklist.push_back(Imported);
+
+  Module *FoundPrimaryModuleInterface =
+      IsImportingPrimaryModuleInterface ? Imported : nullptr;
+
+  while (!Worklist.empty()) {
+    Module *Importing = Worklist.pop_back_val();
+
+    if (VisibleModules.isVisible(Importing))
+      continue;
+
+    // FIXME: The ImportLoc here is not meaningful. It may be problematic if we
+    // use the sourcelocation loaded from the visible modules.
+    VisibleModules.setVisible(Importing, ImportLoc);
+
+    if (isImportingModuleUnitFromSameModule(Importing, CurrentModule,
+                                            FoundPrimaryModuleInterface))
+      for (Module *TransImported : Importing->Imports)
+        if (!VisibleModules.isVisible(TransImported))
+          Worklist.push_back(TransImported);
+  }
+}
+
 Sema::DeclGroupPtrTy
 Sema::ActOnGlobalModuleFragmentDecl(SourceLocation ModuleLoc) {
   // We start in the global module;
@@ -396,8 +480,8 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
   // and return the import decl to be added to the current TU.
   if (Interface) {
 
-    VisibleModules.setVisible(Interface, ModuleLoc);
-    VisibleModules.makeTransitiveImportsVisible(Interface, ModuleLoc);
+    makeTransitiveImportsVisible(VisibleModules, Interface, Mod, ModuleLoc,
+                                 /*IsImportingPrimaryModuleInterface=*/true);
 
     // Make the import decl for the interface in the impl module.
     ImportDecl *Import = ImportDecl::Create(Context, CurContext, ModuleLoc,
@@ -554,7 +638,11 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
   if (Mod->isHeaderUnit())
     Diag(ImportLoc, diag::warn_experimental_header_unit);
 
-  VisibleModules.setVisible(Mod, ImportLoc);
+  if (Mod->isNamedModule())
+    makeTransitiveImportsVisible(VisibleModules, Mod, getCurrentModule(),
+                                 ImportLoc);
+  else
+    VisibleModules.setVisible(Mod, ImportLoc);
 
   checkModuleImportContext(*this, Mod, ImportLoc, CurContext);
 
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index d365a5151a4582ba5128ba8653ecbc7ed1dff77a..d3a602d1c382fa601b7eda1c369402a20bc0fc72 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -27,6 +27,8 @@ bool diagnoseConstructAppertainment(Sema &S, OpenACCDirectiveKind K,
     // do anything.
     break;
   case OpenACCDirectiveKind::Parallel:
+  case OpenACCDirectiveKind::Serial:
+  case OpenACCDirectiveKind::Kernels:
     if (!IsStmt)
       return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K;
     break;
@@ -55,6 +57,8 @@ void Sema::ActOnOpenACCConstruct(OpenACCDirectiveKind K,
     // rules anywhere.
     break;
   case OpenACCDirectiveKind::Parallel:
+  case OpenACCDirectiveKind::Serial:
+  case OpenACCDirectiveKind::Kernels:
     // Nothing to do here, there is no real legalization that needs to happen
     // here as these constructs do not take any arguments.
     break;
@@ -79,6 +83,8 @@ StmtResult Sema::ActOnEndOpenACCStmtDirective(OpenACCDirectiveKind K,
   case OpenACCDirectiveKind::Invalid:
     return StmtError();
   case OpenACCDirectiveKind::Parallel:
+  case OpenACCDirectiveKind::Serial:
+  case OpenACCDirectiveKind::Kernels:
     return OpenACCComputeConstruct::Create(
         getASTContext(), K, StartLoc, EndLoc,
         AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
@@ -92,6 +98,8 @@ StmtResult Sema::ActOnOpenACCAssociatedStmt(OpenACCDirectiveKind K,
   default:
     llvm_unreachable("Unimplemented associated statement application");
   case OpenACCDirectiveKind::Parallel:
+  case OpenACCDirectiveKind::Serial:
+  case OpenACCDirectiveKind::Kernels:
     // There really isn't any checking here that could happen. As long as we
     // have a statement to associate, this should be fine.
     // OpenACC 3.3 Section 6:
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index f4364a259ad57f6ac6010990d3da2148c85bf3cd..0cc0cbacb375489dd7d2d596d81bb7a4dfe8745d 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -3496,7 +3496,7 @@ void Sema::ActOnOpenMPAssumesDirective(SourceLocation Loc,
         << llvm::omp::getAllAssumeClauseOptions()
         << llvm::omp::getOpenMPDirectiveName(DKind);
 
-  auto *AA = AssumptionAttr::Create(Context, llvm::join(Assumptions, ","), Loc);
+  auto *AA = OMPAssumeAttr::Create(Context, llvm::join(Assumptions, ","), Loc);
   if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
     OMPAssumeScoped.push_back(AA);
     return;
@@ -7275,10 +7275,10 @@ void Sema::ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D) {
   // only global ones. We apply scoped assumption to the template definition
   // though.
   if (!inTemplateInstantiation()) {
-    for (AssumptionAttr *AA : OMPAssumeScoped)
+    for (OMPAssumeAttr *AA : OMPAssumeScoped)
       FD->addAttr(AA);
   }
-  for (AssumptionAttr *AA : OMPAssumeGlobal)
+  for (OMPAssumeAttr *AA : OMPAssumeGlobal)
     FD->addAttr(AA);
 }
 
@@ -23353,6 +23353,15 @@ void Sema::ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
           isa(ND)) &&
          "Expected variable, function or function template.");
 
+  if (auto *VD = dyn_cast(ND)) {
+    // Only global variables can be marked as declare target.
+    if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
+        !VD->isStaticDataMember()) {
+      Diag(Loc, diag::err_omp_declare_target_has_local_vars)
+          << VD->getNameAsString();
+      return;
+    }
+  }
   // Diagnose marking after use as it may lead to incorrect diagnosis and
   // codegen.
   if (LangOpts.OpenMP >= 50 &&
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 7d38043890ca20809e8d4b2aac77803254b9ed5a..f6bd85bdc64692e3de882b9006694bdf40e505eb 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -332,7 +332,8 @@ static const Expr *IgnoreNarrowingConversion(ASTContext &Ctx,
 NarrowingKind StandardConversionSequence::getNarrowingKind(
     ASTContext &Ctx, const Expr *Converted, APValue &ConstantValue,
     QualType &ConstantType, bool IgnoreFloatToIntegralConversion) const {
-  assert(Ctx.getLangOpts().CPlusPlus && "narrowing check outside C++");
+  assert((Ctx.getLangOpts().CPlusPlus || Ctx.getLangOpts().C23) &&
+         "narrowing check outside C++");
 
   // C++11 [dcl.init.list]p7:
   //   A narrowing conversion is an implicit conversion ...
@@ -414,20 +415,41 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
       if (Initializer->isValueDependent())
         return NK_Dependent_Narrowing;
 
-      if (Initializer->isCXX11ConstantExpr(Ctx, &ConstantValue)) {
+      Expr::EvalResult R;
+      if ((Ctx.getLangOpts().C23 && Initializer->EvaluateAsRValue(R, Ctx)) ||
+          Initializer->isCXX11ConstantExpr(Ctx, &ConstantValue)) {
         // Constant!
+        if (Ctx.getLangOpts().C23)
+          ConstantValue = R.Val;
         assert(ConstantValue.isFloat());
         llvm::APFloat FloatVal = ConstantValue.getFloat();
         // Convert the source value into the target type.
         bool ignored;
-        llvm::APFloat::opStatus ConvertStatus = FloatVal.convert(
-          Ctx.getFloatTypeSemantics(ToType),
-          llvm::APFloat::rmNearestTiesToEven, &ignored);
-        // If there was no overflow, the source value is within the range of
-        // values that can be represented.
-        if (ConvertStatus & llvm::APFloat::opOverflow) {
-          ConstantType = Initializer->getType();
-          return NK_Constant_Narrowing;
+        llvm::APFloat Converted = FloatVal;
+        llvm::APFloat::opStatus ConvertStatus =
+            Converted.convert(Ctx.getFloatTypeSemantics(ToType),
+                              llvm::APFloat::rmNearestTiesToEven, &ignored);
+        Converted.convert(Ctx.getFloatTypeSemantics(FromType),
+                          llvm::APFloat::rmNearestTiesToEven, &ignored);
+        if (Ctx.getLangOpts().C23) {
+          if (FloatVal.isNaN() && Converted.isNaN() &&
+              !FloatVal.isSignaling() && !Converted.isSignaling()) {
+            // Quiet NaNs are considered the same value, regardless of
+            // payloads.
+            return NK_Not_Narrowing;
+          }
+          // For normal values, check exact equality.
+          if (!Converted.bitwiseIsEqual(FloatVal)) {
+            ConstantType = Initializer->getType();
+            return NK_Constant_Narrowing;
+          }
+        } else {
+          // If there was no overflow, the source value is within the range of
+          // values that can be represented.
+          if (ConvertStatus & llvm::APFloat::opOverflow) {
+            ConstantType = Initializer->getType();
+            return NK_Constant_Narrowing;
+          }
         }
       } else {
         return NK_Variable_Narrowing;
@@ -494,7 +516,30 @@ NarrowingKind StandardConversionSequence::getNarrowingKind(
     }
     return NK_Not_Narrowing;
   }
+  case ICK_Complex_Real:
+    if (FromType->isComplexType() && !ToType->isComplexType())
+      return NK_Type_Narrowing;
+    return NK_Not_Narrowing;
 
+  case ICK_Floating_Promotion:
+    if (Ctx.getLangOpts().C23) {
+      const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted);
+      Expr::EvalResult R;
+      if (Initializer->EvaluateAsRValue(R, Ctx)) {
+        ConstantValue = R.Val;
+        assert(ConstantValue.isFloat());
+        llvm::APFloat FloatVal = ConstantValue.getFloat();
+        // C23 6.7.3p6 If the initializer has real type and a signaling NaN
+        // value, the unqualified versions of the type of the initializer and
+        // the corresponding real type of the object declared shall be
+        // compatible.
+        if (FloatVal.isNaN() && FloatVal.isSignaling()) {
+          ConstantType = Initializer->getType();
+          return NK_Constant_Narrowing;
+        }
+      }
+    }
+    return NK_Not_Narrowing;
   default:
     // Other kinds of conversions are not narrowings.
     return NK_Not_Narrowing;
@@ -8471,6 +8516,9 @@ class BuiltinCandidateTypeSet  {
   /// candidates.
   TypeSet MatrixTypes;
 
+  /// The set of _BitInt types that will be used in the built-in candidates.
+  TypeSet BitIntTypes;
+
   /// A flag indicating non-record types are viable candidates
   bool HasNonRecordTypes;
 
@@ -8519,6 +8567,7 @@ public:
   }
   llvm::iterator_range vector_types() { return VectorTypes; }
   llvm::iterator_range matrix_types() { return MatrixTypes; }
+  llvm::iterator_range bitint_types() { return BitIntTypes; }
 
   bool containsMatrixType(QualType Ty) const { return MatrixTypes.count(Ty); }
   bool hasNonRecordTypes() { return HasNonRecordTypes; }
@@ -8690,6 +8739,9 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
   } else if (Ty->isEnumeralType()) {
     HasArithmeticOrEnumeralTypes = true;
     EnumerationTypes.insert(Ty);
+  } else if (Ty->isBitIntType()) {
+    HasArithmeticOrEnumeralTypes = true;
+    BitIntTypes.insert(Ty);
   } else if (Ty->isVectorType()) {
     // We treat vector types as arithmetic types in many contexts as an
     // extension.
@@ -8868,7 +8920,7 @@ class BuiltinOperatorOverloadBuilder {
   SmallVectorImpl &CandidateTypes;
   OverloadCandidateSet &CandidateSet;
 
-  static constexpr int ArithmeticTypesCap = 24;
+  static constexpr int ArithmeticTypesCap = 26;
   SmallVector ArithmeticTypes;
 
   // Define some indices used to iterate over the arithmetic types in
@@ -8910,6 +8962,20 @@ class BuiltinOperatorOverloadBuilder {
         (S.Context.getAuxTargetInfo() &&
          S.Context.getAuxTargetInfo()->hasInt128Type()))
       ArithmeticTypes.push_back(S.Context.UnsignedInt128Ty);
+
+    /// We add candidates for the unique, unqualified _BitInt types present in
+    /// the candidate type set. The candidate set already handled ensuring the
+    /// type is unqualified and canonical, but because we're adding from N
+    /// different sets, we need to do some extra work to unique things. Insert
+    /// the candidates into a unique set, then move from that set into the list
+    /// of arithmetic types.
+    llvm::SmallSetVector BitIntCandidates;
+    llvm::for_each(CandidateTypes, [&BitIntCandidates](
+                                       BuiltinCandidateTypeSet &Candidate) {
+      for (QualType BitTy : Candidate.bitint_types())
+        BitIntCandidates.insert(CanQualType::CreateUnsafe(BitTy));
+    });
+    llvm::move(BitIntCandidates, std::back_inserter(ArithmeticTypes));
     LastPromotedIntegralType = ArithmeticTypes.size();
     LastPromotedArithmeticType = ArithmeticTypes.size();
     // End of promoted types.
@@ -8930,7 +8996,11 @@ class BuiltinOperatorOverloadBuilder {
     // End of integral types.
     // FIXME: What about complex? What about half?
 
-    assert(ArithmeticTypes.size() <= ArithmeticTypesCap &&
+    // We don't know for sure how many bit-precise candidates were involved, so
+    // we subtract those from the total when testing whether we're under the
+    // cap or not.
+    assert(ArithmeticTypes.size() - BitIntCandidates.size() <=
+               ArithmeticTypesCap &&
            "Enough inline storage for all arithmetic types.");
   }
 
@@ -10526,14 +10596,23 @@ bool clang::isBetterOverloadCandidate(
   //      according to the partial ordering rules described in 14.5.5.2, or,
   //      if not that,
   if (Cand1IsSpecialization && Cand2IsSpecialization) {
+    const auto *Obj1Context =
+        dyn_cast(Cand1.FoundDecl->getDeclContext());
+    const auto *Obj2Context =
+        dyn_cast(Cand2.FoundDecl->getDeclContext());
     if (FunctionTemplateDecl *BetterTemplate = S.getMoreSpecializedTemplate(
             Cand1.Function->getPrimaryTemplate(),
             Cand2.Function->getPrimaryTemplate(), Loc,
             isa(Cand1.Function) ? TPOC_Conversion
                                                    : TPOC_Call,
-            Cand1.ExplicitCallArguments, Cand2.ExplicitCallArguments,
-            Cand1.isReversed() ^ Cand2.isReversed()))
+            Cand1.ExplicitCallArguments,
+            Obj1Context ? QualType(Obj1Context->getTypeForDecl(), 0)
+                        : QualType{},
+            Obj2Context ? QualType(Obj2Context->getTypeForDecl(), 0)
+                        : QualType{},
+            Cand1.isReversed() ^ Cand2.isReversed())) {
       return BetterTemplate == Cand1.Function->getPrimaryTemplate();
+    }
   }
 
   //   -— F1 and F2 are non-template functions with the same
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp
index e6a4d3e63e4aa87e7173e1e3fc01dd5e3bf74fef..691857e88beb490089f23789e85e7c1709ceaeae 100644
--- a/clang/lib/Sema/SemaStmtAttr.cpp
+++ b/clang/lib/Sema/SemaStmtAttr.cpp
@@ -303,6 +303,15 @@ static Attr *handleAlwaysInlineAttr(Sema &S, Stmt *St, const ParsedAttr &A,
   return ::new (S.Context) AlwaysInlineAttr(S.Context, A);
 }
 
+static Attr *handleCXXAssumeAttr(Sema &S, Stmt *St, const ParsedAttr &A,
+                                 SourceRange Range) {
+  ExprResult Res = S.ActOnCXXAssumeAttr(St, A, Range);
+  if (!Res.isUsable())
+    return nullptr;
+
+  return ::new (S.Context) CXXAssumeAttr(S.Context, A, Res.get());
+}
+
 static Attr *handleMustTailAttr(Sema &S, Stmt *St, const ParsedAttr &A,
                                 SourceRange Range) {
   // Validation is in Sema::ActOnAttributedStmt().
@@ -594,6 +603,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
   switch (A.getKind()) {
   case ParsedAttr::AT_AlwaysInline:
     return handleAlwaysInlineAttr(S, St, A, Range);
+  case ParsedAttr::AT_CXXAssume:
+    return handleCXXAssumeAttr(S, St, A, Range);
   case ParsedAttr::AT_FallThrough:
     return handleFallThroughAttr(S, St, A, Range);
   case ParsedAttr::AT_LoopHint:
@@ -641,3 +652,47 @@ bool Sema::CheckRebuiltStmtAttributes(ArrayRef Attrs) {
   CheckForDuplicateLoopAttrs(*this, Attrs);
   return false;
 }
+
+ExprResult Sema::ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A,
+                                    SourceRange Range) {
+  if (A.getNumArgs() != 1 || !A.getArgAsExpr(0)) {
+    Diag(A.getLoc(), diag::err_assume_attr_args) << A.getAttrName() << Range;
+    return ExprError();
+  }
+
+  auto *Assumption = A.getArgAsExpr(0);
+  if (Assumption->getDependence() == ExprDependence::None) {
+    ExprResult Res = BuildCXXAssumeExpr(Assumption, A.getAttrName(), Range);
+    if (Res.isInvalid())
+      return ExprError();
+    Assumption = Res.get();
+  }
+
+  if (!getLangOpts().CPlusPlus23)
+    Diag(A.getLoc(), diag::ext_cxx23_attr) << A << Range;
+
+  return Assumption;
+}
+
+ExprResult Sema::BuildCXXAssumeExpr(Expr *Assumption,
+                                    const IdentifierInfo *AttrName,
+                                    SourceRange Range) {
+  ExprResult Res = CorrectDelayedTyposInExpr(Assumption);
+  if (Res.isInvalid())
+    return ExprError();
+
+  Res = CheckPlaceholderExpr(Res.get());
+  if (Res.isInvalid())
+    return ExprError();
+
+  Res = PerformContextuallyConvertToBool(Res.get());
+  if (Res.isInvalid())
+    return ExprError();
+
+  Assumption = Res.get();
+  if (Assumption->HasSideEffects(Context))
+    Diag(Assumption->getBeginLoc(), diag::warn_assume_side_effects)
+        << AttrName << Range;
+
+  return Assumption;
+}
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 873ea10ebe06605afd01a72b0669f45fdd8547bb..d62095558d0ffbd29b1703e8f9fba23153062432 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -2262,6 +2262,92 @@ public:
   }
 };
 
+// Build a deduction guide with the specified parameter types.
+FunctionTemplateDecl *buildDeductionGuide(
+    Sema &SemaRef, TemplateDecl *OriginalTemplate,
+    TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
+    ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
+    SourceLocation Loc, SourceLocation LocEnd, bool IsImplicit,
+    llvm::ArrayRef MaterializedTypedefs = {}) {
+  DeclContext *DC = OriginalTemplate->getDeclContext();
+  auto DeductionGuideName =
+      SemaRef.Context.DeclarationNames.getCXXDeductionGuideName(
+          OriginalTemplate);
+
+  DeclarationNameInfo Name(DeductionGuideName, Loc);
+  ArrayRef Params =
+      TInfo->getTypeLoc().castAs().getParams();
+
+  // Build the implicit deduction guide template.
+  auto *Guide =
+      CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
+                                    TInfo->getType(), TInfo, LocEnd, Ctor);
+  Guide->setImplicit(IsImplicit);
+  Guide->setParams(Params);
+
+  for (auto *Param : Params)
+    Param->setDeclContext(Guide);
+  for (auto *TD : MaterializedTypedefs)
+    TD->setDeclContext(Guide);
+
+  auto *GuideTemplate = FunctionTemplateDecl::Create(
+      SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
+  GuideTemplate->setImplicit(IsImplicit);
+  Guide->setDescribedFunctionTemplate(GuideTemplate);
+
+  if (isa(DC)) {
+    Guide->setAccess(AS_public);
+    GuideTemplate->setAccess(AS_public);
+  }
+
+  DC->addDecl(GuideTemplate);
+  return GuideTemplate;
+}
+
+// Transform a given template type parameter `TTP`.
+TemplateTypeParmDecl *
+transformTemplateTypeParam(Sema &SemaRef, DeclContext *DC,
+                           TemplateTypeParmDecl *TTP,
+                           MultiLevelTemplateArgumentList &Args,
+                           unsigned NewDepth, unsigned NewIndex) {
+  // TemplateTypeParmDecl's index cannot be changed after creation, so
+  // substitute it directly.
+  auto *NewTTP = TemplateTypeParmDecl::Create(
+      SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(), NewDepth,
+      NewIndex, TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
+      TTP->isParameterPack(), TTP->hasTypeConstraint(),
+      TTP->isExpandedParameterPack()
+          ? std::optional(TTP->getNumExpansionParameters())
+          : std::nullopt);
+  if (const auto *TC = TTP->getTypeConstraint())
+    SemaRef.SubstTypeConstraint(NewTTP, TC, Args,
+                                /*EvaluateConstraint=*/true);
+  if (TTP->hasDefaultArgument()) {
+    TypeSourceInfo *InstantiatedDefaultArg =
+        SemaRef.SubstType(TTP->getDefaultArgumentInfo(), Args,
+                          TTP->getDefaultArgumentLoc(), TTP->getDeclName());
+    if (InstantiatedDefaultArg)
+      NewTTP->setDefaultArgument(InstantiatedDefaultArg);
+  }
+  SemaRef.CurrentInstantiationScope->InstantiatedLocal(TTP, NewTTP);
+  return NewTTP;
+}
+// Similar to above, but for non-type template or template template parameters.
+template 
+NonTypeTemplateOrTemplateTemplateParmDecl *
+transformTemplateParam(Sema &SemaRef, DeclContext *DC,
+                       NonTypeTemplateOrTemplateTemplateParmDecl *OldParam,
+                       MultiLevelTemplateArgumentList &Args, unsigned NewIndex,
+                       unsigned NewDepth) {
+  // Ask the template instantiator to do the heavy lifting for us, then adjust
+  // the index of the parameter once it's done.
+  auto *NewParam = cast(
+      SemaRef.SubstDecl(OldParam, DC, Args));
+  NewParam->setPosition(NewIndex);
+  NewParam->setDepth(NewDepth);
+  return NewParam;
+}
+
 /// Transform to convert portions of a constructor declaration into the
 /// corresponding deduction guide, per C++1z [over.match.class.deduct]p1.
 struct ConvertConstructorToDeductionGuideTransform {
@@ -2338,7 +2424,6 @@ struct ConvertConstructorToDeductionGuideTransform {
         NamedDecl *NewParam = transformTemplateParameter(Param, Args);
         if (!NewParam)
           return nullptr;
-
         // Constraints require that we substitute depth-1 arguments
         // to match depths when substituted for evaluation later
         Depth1Args.push_back(SemaRef.Context.getCanonicalTemplateArgument(
@@ -2411,9 +2496,10 @@ struct ConvertConstructorToDeductionGuideTransform {
       return nullptr;
     TypeSourceInfo *NewTInfo = TLB.getTypeSourceInfo(SemaRef.Context, NewType);
 
-    return buildDeductionGuide(TemplateParams, CD, CD->getExplicitSpecifier(),
-                               NewTInfo, CD->getBeginLoc(), CD->getLocation(),
-                               CD->getEndLoc(), MaterializedTypedefs);
+    return buildDeductionGuide(
+        SemaRef, Template, TemplateParams, CD, CD->getExplicitSpecifier(),
+        NewTInfo, CD->getBeginLoc(), CD->getLocation(), CD->getEndLoc(),
+        /*IsImplicit=*/true, MaterializedTypedefs);
   }
 
   /// Build a deduction guide with the specified parameter types.
@@ -2448,8 +2534,9 @@ struct ConvertConstructorToDeductionGuideTransform {
       Params.push_back(NewParam);
     }
 
-    return buildDeductionGuide(GetTemplateParameterList(Template), nullptr,
-                               ExplicitSpecifier(), TSI, Loc, Loc, Loc);
+    return buildDeductionGuide(
+        SemaRef, Template, GetTemplateParameterList(Template), nullptr,
+        ExplicitSpecifier(), TSI, Loc, Loc, Loc, /*IsImplicit=*/true);
   }
 
 private:
@@ -2458,50 +2545,18 @@ private:
   /// renumbering as we go.
   NamedDecl *transformTemplateParameter(NamedDecl *TemplateParam,
                                         MultiLevelTemplateArgumentList &Args) {
-    if (auto *TTP = dyn_cast(TemplateParam)) {
-      // TemplateTypeParmDecl's index cannot be changed after creation, so
-      // substitute it directly.
-      auto *NewTTP = TemplateTypeParmDecl::Create(
-          SemaRef.Context, DC, TTP->getBeginLoc(), TTP->getLocation(),
-          TTP->getDepth() - 1, Depth1IndexAdjustment + TTP->getIndex(),
-          TTP->getIdentifier(), TTP->wasDeclaredWithTypename(),
-          TTP->isParameterPack(), TTP->hasTypeConstraint(),
-          TTP->isExpandedParameterPack()
-              ? std::optional(TTP->getNumExpansionParameters())
-              : std::nullopt);
-      if (const auto *TC = TTP->getTypeConstraint())
-        SemaRef.SubstTypeConstraint(NewTTP, TC, Args,
-                                    /*EvaluateConstraint*/ true);
-      if (TTP->hasDefaultArgument()) {
-        TypeSourceInfo *InstantiatedDefaultArg =
-            SemaRef.SubstType(TTP->getDefaultArgumentInfo(), Args,
-                              TTP->getDefaultArgumentLoc(), TTP->getDeclName());
-        if (InstantiatedDefaultArg)
-          NewTTP->setDefaultArgument(InstantiatedDefaultArg);
-      }
-      SemaRef.CurrentInstantiationScope->InstantiatedLocal(TemplateParam,
-                                                           NewTTP);
-      return NewTTP;
-    }
-
+    if (auto *TTP = dyn_cast(TemplateParam))
+      return transformTemplateTypeParam(
+          SemaRef, DC, TTP, Args, TTP->getDepth() - 1,
+          Depth1IndexAdjustment + TTP->getIndex());
     if (auto *TTP = dyn_cast(TemplateParam))
-      return transformTemplateParameterImpl(TTP, Args);
-
-    return transformTemplateParameterImpl(
-        cast(TemplateParam), Args);
-  }
-  template
-  TemplateParmDecl *
-  transformTemplateParameterImpl(TemplateParmDecl *OldParam,
-                                 MultiLevelTemplateArgumentList &Args) {
-    // Ask the template instantiator to do the heavy lifting for us, then adjust
-    // the index of the parameter once it's done.
-    auto *NewParam =
-        cast(SemaRef.SubstDecl(OldParam, DC, Args));
-    assert(NewParam->getDepth() == OldParam->getDepth() - 1 &&
-           "unexpected template param depth");
-    NewParam->setPosition(NewParam->getPosition() + Depth1IndexAdjustment);
-    return NewParam;
+      return transformTemplateParam(SemaRef, DC, TTP, Args,
+                                    Depth1IndexAdjustment + TTP->getIndex(),
+                                    TTP->getDepth() - 1);
+    auto *NTTP = cast(TemplateParam);
+    return transformTemplateParam(SemaRef, DC, NTTP, Args,
+                                  Depth1IndexAdjustment + NTTP->getIndex(),
+                                  NTTP->getDepth() - 1);
   }
 
   QualType transformFunctionProtoType(
@@ -2616,44 +2671,310 @@ private:
     SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
     return NewParam;
   }
+};
+
+// Find all template parameters that appear in the given DeducedArgs.
+// Return the indices of the template parameters in the TemplateParams.
+SmallVector TemplateParamsReferencedInTemplateArgumentList(
+    ArrayRef TemplateParams,
+    ArrayRef DeducedArgs) {
+  struct TemplateParamsReferencedFinder
+      : public RecursiveASTVisitor {
+    llvm::DenseSet TemplateParams;
+    llvm::DenseSet ReferencedTemplateParams;
+
+    TemplateParamsReferencedFinder(ArrayRef TemplateParams)
+        : TemplateParams(TemplateParams.begin(), TemplateParams.end()) {}
+
+    bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) {
+      TTP->getIndex();
+      MarkAppeared(TTP->getDecl());
+      return true;
+    }
+    bool VisitDeclRefExpr(DeclRefExpr *DRE) {
+      MarkAppeared(DRE->getFoundDecl());
+      return true;
+    }
+
+    void MarkAppeared(NamedDecl *ND) {
+      if (TemplateParams.contains(ND))
+        ReferencedTemplateParams.insert(ND);
+    }
+  };
+  TemplateParamsReferencedFinder Finder(TemplateParams);
+  Finder.TraverseTemplateArguments(DeducedArgs);
 
-  FunctionTemplateDecl *buildDeductionGuide(
-      TemplateParameterList *TemplateParams, CXXConstructorDecl *Ctor,
-      ExplicitSpecifier ES, TypeSourceInfo *TInfo, SourceLocation LocStart,
-      SourceLocation Loc, SourceLocation LocEnd,
-      llvm::ArrayRef MaterializedTypedefs = {}) {
-    DeclarationNameInfo Name(DeductionGuideName, Loc);
-    ArrayRef Params =
-        TInfo->getTypeLoc().castAs().getParams();
+  SmallVector Results;
+  for (unsigned Index = 0; Index < TemplateParams.size(); ++Index) {
+    if (Finder.ReferencedTemplateParams.contains(TemplateParams[Index]))
+      Results.push_back(Index);
+  }
+  return Results;
+}
 
-    // Build the implicit deduction guide template.
-    auto *Guide =
-        CXXDeductionGuideDecl::Create(SemaRef.Context, DC, LocStart, ES, Name,
-                                      TInfo->getType(), TInfo, LocEnd, Ctor);
-    Guide->setImplicit();
-    Guide->setParams(Params);
+bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
+  // Check whether we've already declared deduction guides for this template.
+  // FIXME: Consider storing a flag on the template to indicate this.
+  assert(Name.getNameKind() ==
+             DeclarationName::NameKind::CXXDeductionGuideName &&
+         "name must be a deduction guide name");
+  auto Existing = DC->lookup(Name);
+  for (auto *D : Existing)
+    if (D->isImplicit())
+      return true;
+  return false;
+}
 
-    for (auto *Param : Params)
-      Param->setDeclContext(Guide);
-    for (auto *TD : MaterializedTypedefs)
-      TD->setDeclContext(Guide);
+// Build deduction guides for a type alias template.
+void DeclareImplicitDeductionGuidesForTypeAlias(
+    Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
+  auto &Context = SemaRef.Context;
+  // FIXME: if there is an explicit deduction guide after the first use of the
+  // type alias usage, we will not cover this explicit deduction guide. fix this
+  // case.
+  if (hasDeclaredDeductionGuides(
+          Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate),
+          AliasTemplate->getDeclContext()))
+    return;
+  // Unwrap the sugared ElaboratedType.
+  auto RhsType = AliasTemplate->getTemplatedDecl()
+                     ->getUnderlyingType()
+                     .getSingleStepDesugaredType(Context);
+  TemplateDecl *Template = nullptr;
+  llvm::ArrayRef AliasRhsTemplateArgs;
+  if (const auto *TST = RhsType->getAs()) {
+    // Cases where the RHS of the alias is dependent. e.g.
+    //   template
+    //   using AliasFoo1 = Foo; // a class/type alias template specialization
+    Template = TST->getTemplateName().getAsTemplateDecl();
+    AliasRhsTemplateArgs = TST->template_arguments();
+  } else if (const auto *RT = RhsType->getAs()) {
+    // Cases where template arguments in the RHS of the alias are not
+    // dependent. e.g.
+    //   using AliasFoo = Foo;
+    if (const auto *CTSD = llvm::dyn_cast(
+            RT->getAsCXXRecordDecl())) {
+      Template = CTSD->getSpecializedTemplate();
+      AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray();
+    }
+  } else {
+    assert(false && "unhandled RHS type of the alias");
+  }
+  if (!Template)
+    return;
+  DeclarationNameInfo NameInfo(
+      Context.DeclarationNames.getCXXDeductionGuideName(Template), Loc);
+  LookupResult Guides(SemaRef, NameInfo, clang::Sema::LookupOrdinaryName);
+  SemaRef.LookupQualifiedName(Guides, Template->getDeclContext());
+  Guides.suppressDiagnostics();
+
+  for (auto *G : Guides) {
+    FunctionTemplateDecl *F = dyn_cast(G);
+    if (!F)
+      continue;
+    auto RType = F->getTemplatedDecl()->getReturnType();
+    // The (trailing) return type of the deduction guide.
+    const TemplateSpecializationType *FReturnType =
+        RType->getAs();
+    if (const auto *InjectedCNT = RType->getAs())
+      // implicitly-generated deduction guide.
+      FReturnType = InjectedCNT->getInjectedTST();
+    else if (const auto *ET = RType->getAs())
+      // explicit deduction guide.
+      FReturnType = ET->getNamedType()->getAs();
+    assert(FReturnType && "expected to see a return type");
+    // Deduce template arguments of the deduction guide f from the RHS of
+    // the alias.
+    //
+    // C++ [over.match.class.deduct]p3: ...For each function or function
+    // template f in the guides of the template named by the
+    // simple-template-id of the defining-type-id, the template arguments
+    // of the return type of f are deduced from the defining-type-id of A
+    // according to the process in [temp.deduct.type] with the exception
+    // that deduction does not fail if not all template arguments are
+    // deduced.
+    //
+    //
+    //  template
+    //  f(X, Y) -> f;
+    //
+    //  template
+    //  using alias = f;
+    //
+    // The RHS of alias is f, we deduced the template arguments of
+    // the return type of the deduction guide from it: Y->int, X->U
+    sema::TemplateDeductionInfo TDeduceInfo(Loc);
+    // Must initialize n elements, this is required by DeduceTemplateArguments.
+    SmallVector DeduceResults(
+        F->getTemplateParameters()->size());
+
+    // FIXME: DeduceTemplateArguments stops immediately at the first
+    // non-deducible template argument. However, this doesn't seem to casue
+    // issues for practice cases, we probably need to extend it to continue
+    // performing deduction for rest of arguments to align with the C++
+    // standard.
+    SemaRef.DeduceTemplateArguments(
+        F->getTemplateParameters(), FReturnType->template_arguments(),
+        AliasRhsTemplateArgs, TDeduceInfo, DeduceResults,
+        /*NumberOfArgumentsMustMatch=*/false);
+
+    SmallVector DeducedArgs;
+    SmallVector NonDeducedTemplateParamsInFIndex;
+    // !!NOTE: DeduceResults respects the sequence of template parameters of
+    // the deduction guide f.
+    for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {
+      if (const auto &D = DeduceResults[Index]; !D.isNull()) // Deduced
+        DeducedArgs.push_back(D);
+      else
+        NonDeducedTemplateParamsInFIndex.push_back(Index);
+    }
+    auto DeducedAliasTemplateParams =
+        TemplateParamsReferencedInTemplateArgumentList(
+            AliasTemplate->getTemplateParameters()->asArray(), DeducedArgs);
+    // All template arguments null by default.
+    SmallVector TemplateArgsForBuildingFPrime(
+        F->getTemplateParameters()->size());
+
+    Sema::InstantiatingTemplate BuildingDeductionGuides(
+        SemaRef, AliasTemplate->getLocation(), F,
+        Sema::InstantiatingTemplate::BuildingDeductionGuidesTag{});
+    if (BuildingDeductionGuides.isInvalid())
+      return;
+    LocalInstantiationScope Scope(SemaRef);
 
-    auto *GuideTemplate = FunctionTemplateDecl::Create(
-        SemaRef.Context, DC, Loc, DeductionGuideName, TemplateParams, Guide);
-    GuideTemplate->setImplicit();
-    Guide->setDescribedFunctionTemplate(GuideTemplate);
+    // Create a template parameter list for the synthesized deduction guide f'.
+    //
+    // C++ [over.match.class.deduct]p3.2:
+    //   If f is a function template, f' is a function template whose template
+    //   parameter list consists of all the template parameters of A
+    //   (including their default template arguments) that appear in the above
+    //   deductions or (recursively) in their default template arguments
+    SmallVector FPrimeTemplateParams;
+    // Store template arguments that refer to the newly-created template
+    // parameters, used for building `TemplateArgsForBuildingFPrime`.
+    SmallVector TransformedDeducedAliasArgs(
+        AliasTemplate->getTemplateParameters()->size());
+    auto TransformTemplateParameter =
+        [&SemaRef](DeclContext *DC, NamedDecl *TemplateParam,
+                   MultiLevelTemplateArgumentList &Args,
+                   unsigned NewIndex) -> NamedDecl * {
+      if (auto *TTP = dyn_cast(TemplateParam))
+        return transformTemplateTypeParam(SemaRef, DC, TTP, Args,
+                                          TTP->getDepth(), NewIndex);
+      if (auto *TTP = dyn_cast(TemplateParam))
+        return transformTemplateParam(SemaRef, DC, TTP, Args, NewIndex,
+                                      TTP->getDepth());
+      if (auto *NTTP = dyn_cast(TemplateParam))
+        return transformTemplateParam(SemaRef, DC, NTTP, Args, NewIndex,
+                                      NTTP->getDepth());
+      return nullptr;
+    };
 
-    if (isa(DC)) {
-      Guide->setAccess(AS_public);
-      GuideTemplate->setAccess(AS_public);
+    for (unsigned AliasTemplateParamIdx : DeducedAliasTemplateParams) {
+      auto *TP = AliasTemplate->getTemplateParameters()->getParam(
+          AliasTemplateParamIdx);
+      // Rebuild any internal references to earlier parameters and reindex as
+      // we go.
+      MultiLevelTemplateArgumentList Args;
+      Args.setKind(TemplateSubstitutionKind::Rewrite);
+      Args.addOuterTemplateArguments(TransformedDeducedAliasArgs);
+      NamedDecl *NewParam =
+          TransformTemplateParameter(AliasTemplate->getDeclContext(), TP, Args,
+                                     /*NewIndex*/ FPrimeTemplateParams.size());
+      FPrimeTemplateParams.push_back(NewParam);
+
+      auto NewTemplateArgument = Context.getCanonicalTemplateArgument(
+          Context.getInjectedTemplateArg(NewParam));
+      TransformedDeducedAliasArgs[AliasTemplateParamIdx] = NewTemplateArgument;
+    }
+    //   ...followed by the template parameters of f that were not deduced
+    //   (including their default template arguments)
+    for (unsigned FTemplateParamIdx : NonDeducedTemplateParamsInFIndex) {
+      auto *TP = F->getTemplateParameters()->getParam(FTemplateParamIdx);
+      MultiLevelTemplateArgumentList Args;
+      Args.setKind(TemplateSubstitutionKind::Rewrite);
+      // We take a shortcut here, it is ok to reuse the
+      // TemplateArgsForBuildingFPrime.
+      Args.addOuterTemplateArguments(TemplateArgsForBuildingFPrime);
+      NamedDecl *NewParam = TransformTemplateParameter(
+          F->getDeclContext(), TP, Args, FPrimeTemplateParams.size());
+      FPrimeTemplateParams.push_back(NewParam);
+
+      assert(TemplateArgsForBuildingFPrime[FTemplateParamIdx].isNull() &&
+             "The argument must be null before setting");
+      TemplateArgsForBuildingFPrime[FTemplateParamIdx] =
+          Context.getCanonicalTemplateArgument(
+              Context.getInjectedTemplateArg(NewParam));
+    }
+    // FIXME: implement the associated constraint per C++
+    // [over.match.class.deduct]p3.3:
+    //    The associated constraints ([temp.constr.decl]) are the
+    //    conjunction of the associated constraints of g and a
+    //    constraint that is satisfied if and only if the arguments
+    //    of A are deducible (see below) from the return type.
+    auto *FPrimeTemplateParamList = TemplateParameterList::Create(
+        Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(),
+        AliasTemplate->getTemplateParameters()->getLAngleLoc(),
+        FPrimeTemplateParams,
+        AliasTemplate->getTemplateParameters()->getRAngleLoc(),
+        /*RequiresClause=*/nullptr);
+
+    // To form a deduction guide f' from f, we leverage clang's instantiation
+    // mechanism, we construct a template argument list where the template
+    // arguments refer to the newly-created template parameters of f', and
+    // then apply instantiation on this template argument list to instantiate
+    // f, this ensures all template parameter occurrences are updated
+    // correctly.
+    //
+    // The template argument list is formed from the `DeducedArgs`, two parts:
+    //  1) appeared template parameters of alias: transfrom the deduced
+    //  template argument;
+    //  2) non-deduced template parameters of f: rebuild a
+    //  template argument;
+    //
+    // 2) has been built already (when rebuilding the new template
+    // parameters), we now perform 1).
+    MultiLevelTemplateArgumentList Args;
+    Args.setKind(TemplateSubstitutionKind::Rewrite);
+    Args.addOuterTemplateArguments(TransformedDeducedAliasArgs);
+    for (unsigned Index = 0; Index < DeduceResults.size(); ++Index) {
+      const auto &D = DeduceResults[Index];
+      if (D.isNull()) {
+        // 2): Non-deduced template parameter has been built already.
+        assert(!TemplateArgsForBuildingFPrime[Index].isNull() &&
+               "template arguments for non-deduced template parameters should "
+               "be been set!");
+        continue;
+      }
+      TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc(
+          D, QualType(), SourceLocation{});
+      TemplateArgumentLoc Output;
+      if (!SemaRef.SubstTemplateArgument(Input, Args, Output)) {
+        assert(TemplateArgsForBuildingFPrime[Index].isNull() &&
+               "InstantiatedArgs must be null before setting");
+        TemplateArgsForBuildingFPrime[Index] = (Output.getArgument());
+      }
     }
 
-    DC->addDecl(GuideTemplate);
-    return GuideTemplate;
+    auto *TemplateArgListForBuildingFPrime = TemplateArgumentList::CreateCopy(
+        Context, TemplateArgsForBuildingFPrime);
+    // Form the f' by substituting the template arguments into f.
+    if (auto *FPrime = SemaRef.InstantiateFunctionDeclaration(
+            F, TemplateArgListForBuildingFPrime, AliasTemplate->getLocation(),
+            Sema::CodeSynthesisContext::BuildingDeductionGuides)) {
+      auto *GG = dyn_cast(FPrime);
+      buildDeductionGuide(SemaRef, AliasTemplate, FPrimeTemplateParamList,
+                          GG->getCorrespondingConstructor(),
+                          GG->getExplicitSpecifier(), GG->getTypeSourceInfo(),
+                          AliasTemplate->getBeginLoc(),
+                          AliasTemplate->getLocation(),
+                          AliasTemplate->getEndLoc(), F->isImplicit());
+    }
   }
-};
 }
 
+} // namespace
+
 FunctionTemplateDecl *Sema::DeclareImplicitDeductionGuideFromInitList(
     TemplateDecl *Template, MutableArrayRef ParamTypes,
     SourceLocation Loc) {
@@ -2697,6 +3018,10 @@ FunctionTemplateDecl *Sema::DeclareImplicitDeductionGuideFromInitList(
 
 void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
                                           SourceLocation Loc) {
+  if (auto *AliasTemplate = llvm::dyn_cast(Template)) {
+    DeclareImplicitDeductionGuidesForTypeAlias(*this, AliasTemplate, Loc);
+    return;
+  }
   if (CXXRecordDecl *DefRecord =
           cast(Template->getTemplatedDecl())->getDefinition()) {
     if (TemplateDecl *DescribedTemplate = DefRecord->getDescribedClassTemplate())
@@ -2712,12 +3037,8 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
   if (!isCompleteType(Loc, Transform.DeducedType))
     return;
 
-  // Check whether we've already declared deduction guides for this template.
-  // FIXME: Consider storing a flag on the template to indicate this.
-  auto Existing = DC->lookup(Transform.DeductionGuideName);
-  for (auto *D : Existing)
-    if (D->isImplicit())
-      return;
+  if (hasDeclaredDeductionGuides(Transform.DeductionGuideName, DC))
+    return;
 
   // In case we were expanding a pack when we attempted to declare deduction
   // guides, turn off pack expansion for everything we're about to do.
@@ -5368,6 +5689,15 @@ bool Sema::CheckTemplateTypeArgument(
     [[fallthrough]];
   }
   default: {
+    // We allow instantiateing a template with template argument packs when
+    // building deduction guides.
+    if (Arg.getKind() == TemplateArgument::Pack &&
+        CodeSynthesisContexts.back().Kind ==
+            Sema::CodeSynthesisContext::BuildingDeductionGuides) {
+      SugaredConverted.push_back(Arg);
+      CanonicalConverted.push_back(Arg);
+      return false;
+    }
     // We have a template type parameter but the template argument
     // is not a type.
     SourceRange SR = AL.getSourceRange();
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 563491f76f547841e2a2ef2d14c0f7e697ebb4ba..97f8445bf819c8fa4cb8da6a5a8356afaa35e571 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2531,6 +2531,15 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams,
   return TemplateDeductionResult::Success;
 }
 
+TemplateDeductionResult Sema::DeduceTemplateArguments(
+    TemplateParameterList *TemplateParams, ArrayRef Ps,
+    ArrayRef As, sema::TemplateDeductionInfo &Info,
+    SmallVectorImpl &Deduced,
+    bool NumberOfArgumentsMustMatch) {
+  return ::DeduceTemplateArguments(*this, TemplateParams, Ps, As, Info, Deduced,
+                                   NumberOfArgumentsMustMatch);
+}
+
 /// Determine whether two template arguments are the same.
 static bool isSameTemplateArg(ASTContext &Context,
                               TemplateArgument X,
@@ -5333,38 +5342,38 @@ bool Sema::CheckIfFunctionSpecializationIsImmediate(FunctionDecl *FD,
   return false;
 }
 
-/// If this is a non-static member function,
-static void
-AddImplicitObjectParameterType(ASTContext &Context,
-                               CXXMethodDecl *Method,
-                               SmallVectorImpl &ArgTypes) {
-  // C++11 [temp.func.order]p3:
-  //   [...] The new parameter is of type "reference to cv A," where cv are
-  //   the cv-qualifiers of the function template (if any) and A is
-  //   the class of which the function template is a member.
+static QualType GetImplicitObjectParameterType(ASTContext &Context,
+                                               const CXXMethodDecl *Method,
+                                               QualType RawType,
+                                               bool IsOtherRvr) {
+  // C++20 [temp.func.order]p3.1, p3.2:
+  //  - The type X(M) is "rvalue reference to cv A" if the optional
+  //    ref-qualifier of M is && or if M has no ref-qualifier and the
+  //    positionally-corresponding parameter of the other transformed template
+  //    has rvalue reference type; if this determination depends recursively
+  //    upon whether X(M) is an rvalue reference type, it is not considered to
+  //    have rvalue reference type.
   //
-  // The standard doesn't say explicitly, but we pick the appropriate kind of
-  // reference type based on [over.match.funcs]p4.
-  assert(Method && Method->isImplicitObjectMemberFunction() &&
-         "expected an implicit objet function");
-  QualType ArgTy = Context.getTypeDeclType(Method->getParent());
-  ArgTy = Context.getQualifiedType(ArgTy, Method->getMethodQualifiers());
-  if (Method->getRefQualifier() == RQ_RValue)
-    ArgTy = Context.getRValueReferenceType(ArgTy);
-  else
-    ArgTy = Context.getLValueReferenceType(ArgTy);
-  ArgTypes.push_back(ArgTy);
+  //  - Otherwise, X(M) is "lvalue reference to cv A".
+  assert(Method && !Method->isExplicitObjectMemberFunction() &&
+         "expected a member function with no explicit object parameter");
+
+  RawType = Context.getQualifiedType(RawType, Method->getMethodQualifiers());
+  if (Method->getRefQualifier() == RQ_RValue ||
+      (IsOtherRvr && Method->getRefQualifier() == RQ_None))
+    return Context.getRValueReferenceType(RawType);
+  return Context.getLValueReferenceType(RawType);
 }
 
 /// Determine whether the function template \p FT1 is at least as
 /// specialized as \p FT2.
-static bool isAtLeastAsSpecializedAs(Sema &S,
-                                     SourceLocation Loc,
-                                     FunctionTemplateDecl *FT1,
-                                     FunctionTemplateDecl *FT2,
+static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc,
+                                     const FunctionTemplateDecl *FT1,
+                                     const FunctionTemplateDecl *FT2,
                                      TemplatePartialOrderingContext TPOC,
-                                     unsigned NumCallArguments1,
-                                     bool Reversed) {
+                                     bool Reversed,
+                                     const SmallVector &Args1,
+                                     const SmallVector &Args2) {
   assert(!Reversed || TPOC == TPOC_Call);
 
   FunctionDecl *FD1 = FT1->getTemplatedDecl();
@@ -5381,66 +5390,8 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
   //   The types used to determine the ordering depend on the context in which
   //   the partial ordering is done:
   TemplateDeductionInfo Info(Loc);
-  SmallVector Args2;
   switch (TPOC) {
-  case TPOC_Call: {
-    //   - In the context of a function call, the function parameter types are
-    //     used.
-    CXXMethodDecl *Method1 = dyn_cast(FD1);
-    CXXMethodDecl *Method2 = dyn_cast(FD2);
-
-    // C++11 [temp.func.order]p3:
-    //   [...] If only one of the function templates is a non-static
-    //   member, that function template is considered to have a new
-    //   first parameter inserted in its function parameter list. The
-    //   new parameter is of type "reference to cv A," where cv are
-    //   the cv-qualifiers of the function template (if any) and A is
-    //   the class of which the function template is a member.
-    //
-    // Note that we interpret this to mean "if one of the function
-    // templates is a non-static member and the other is a non-member";
-    // otherwise, the ordering rules for static functions against non-static
-    // functions don't make any sense.
-    //
-    // C++98/03 doesn't have this provision but we've extended DR532 to cover
-    // it as wording was broken prior to it.
-    SmallVector Args1;
-
-    unsigned NumComparedArguments = NumCallArguments1;
-
-    if (!Method2 && Method1 && Method1->isImplicitObjectMemberFunction()) {
-      // Compare 'this' from Method1 against first parameter from Method2.
-      AddImplicitObjectParameterType(S.Context, Method1, Args1);
-      ++NumComparedArguments;
-    } else if (!Method1 && Method2 &&
-               Method2->isImplicitObjectMemberFunction()) {
-      // Compare 'this' from Method2 against first parameter from Method1.
-      AddImplicitObjectParameterType(S.Context, Method2, Args2);
-    } else if (Method1 && Method2 && Reversed &&
-               Method1->isImplicitObjectMemberFunction() &&
-               Method2->isImplicitObjectMemberFunction()) {
-      // Compare 'this' from Method1 against second parameter from Method2
-      // and 'this' from Method2 against second parameter from Method1.
-      AddImplicitObjectParameterType(S.Context, Method1, Args1);
-      AddImplicitObjectParameterType(S.Context, Method2, Args2);
-      ++NumComparedArguments;
-    }
-
-    Args1.insert(Args1.end(), Proto1->param_type_begin(),
-                 Proto1->param_type_end());
-    Args2.insert(Args2.end(), Proto2->param_type_begin(),
-                 Proto2->param_type_end());
-
-    // C++ [temp.func.order]p5:
-    //   The presence of unused ellipsis and default arguments has no effect on
-    //   the partial ordering of function templates.
-    if (Args1.size() > NumComparedArguments)
-      Args1.resize(NumComparedArguments);
-    if (Args2.size() > NumComparedArguments)
-      Args2.resize(NumComparedArguments);
-    if (Reversed)
-      std::reverse(Args2.begin(), Args2.end());
-
+  case TPOC_Call:
     if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(),
                                 Args1.data(), Args1.size(), Info, Deduced,
                                 TDF_None, /*PartialOrdering=*/true) !=
@@ -5448,7 +5399,6 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
       return false;
 
     break;
-  }
 
   case TPOC_Conversion:
     //   - In the context of a call to a conversion operator, the return types
@@ -5536,8 +5486,13 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
 /// \param NumCallArguments1 The number of arguments in the call to FT1, used
 /// only when \c TPOC is \c TPOC_Call.
 ///
-/// \param NumCallArguments2 The number of arguments in the call to FT2, used
-/// only when \c TPOC is \c TPOC_Call.
+/// \param RawObj1Ty The type of the object parameter of FT1 if a member
+/// function only used if \c TPOC is \c TPOC_Call and FT1 is a Function
+/// template from a member function
+///
+/// \param RawObj2Ty The type of the object parameter of FT2 if a member
+/// function only used if \c TPOC is \c TPOC_Call and FT2 is a Function
+/// template from a member function
 ///
 /// \param Reversed If \c true, exactly one of FT1 and FT2 is an overload
 /// candidate with a reversed parameter order. In this case, the corresponding
@@ -5548,13 +5503,76 @@ static bool isAtLeastAsSpecializedAs(Sema &S,
 FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
     FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc,
     TemplatePartialOrderingContext TPOC, unsigned NumCallArguments1,
-    unsigned NumCallArguments2, bool Reversed) {
+    QualType RawObj1Ty, QualType RawObj2Ty, bool Reversed) {
+  SmallVector Args1;
+  SmallVector Args2;
+  const FunctionDecl *FD1 = FT1->getTemplatedDecl();
+  const FunctionDecl *FD2 = FT2->getTemplatedDecl();
+  bool ShouldConvert1 = false;
+  bool ShouldConvert2 = false;
+  QualType Obj1Ty;
+  QualType Obj2Ty;
+  if (TPOC == TPOC_Call) {
+    const FunctionProtoType *Proto1 =
+        FD1->getType()->getAs();
+    const FunctionProtoType *Proto2 =
+        FD2->getType()->getAs();
+
+    //   - In the context of a function call, the function parameter types are
+    //     used.
+    const CXXMethodDecl *Method1 = dyn_cast(FD1);
+    const CXXMethodDecl *Method2 = dyn_cast(FD2);
+    // C++20 [temp.func.order]p3
+    //   [...] Each function template M that is a member function is
+    //   considered to have a new first parameter of type
+    //   X(M), described below, inserted in its function parameter list.
+    //
+    // Note that we interpret "that is a member function" as
+    // "that is a member function with no expicit object argument".
+    // Otherwise the ordering rules for methods with expicit objet arguments
+    // against anything else make no sense.
+    ShouldConvert1 = Method1 && !Method1->isExplicitObjectMemberFunction();
+    ShouldConvert2 = Method2 && !Method2->isExplicitObjectMemberFunction();
+    if (ShouldConvert1) {
+      bool IsRValRef2 =
+          ShouldConvert2
+              ? Method2->getRefQualifier() == RQ_RValue
+              : Proto2->param_type_begin()[0]->isRValueReferenceType();
+      // Compare 'this' from Method1 against first parameter from Method2.
+      Obj1Ty = GetImplicitObjectParameterType(this->Context, Method1, RawObj1Ty,
+                                              IsRValRef2);
+      Args1.push_back(Obj1Ty);
+    }
+    if (ShouldConvert2) {
+      bool IsRValRef1 =
+          ShouldConvert1
+              ? Method1->getRefQualifier() == RQ_RValue
+              : Proto1->param_type_begin()[0]->isRValueReferenceType();
+      // Compare 'this' from Method2 against first parameter from Method1.
+      Obj2Ty = GetImplicitObjectParameterType(this->Context, Method2, RawObj2Ty,
+                                              IsRValRef1);
+      Args2.push_back(Obj2Ty);
+    }
+    size_t NumComparedArguments = NumCallArguments1 + ShouldConvert1;
+
+    Args1.insert(Args1.end(), Proto1->param_type_begin(),
+                 Proto1->param_type_end());
+    Args2.insert(Args2.end(), Proto2->param_type_begin(),
+                 Proto2->param_type_end());
 
-  bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC,
-                                          NumCallArguments1, Reversed);
-  bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
-                                          NumCallArguments2, Reversed);
+    // C++ [temp.func.order]p5:
+    //   The presence of unused ellipsis and default arguments has no effect on
+    //   the partial ordering of function templates.
+    Args1.resize(std::min(Args1.size(), NumComparedArguments));
+    Args2.resize(std::min(Args2.size(), NumComparedArguments));
 
+    if (Reversed)
+      std::reverse(Args2.begin(), Args2.end());
+  }
+  bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC, Reversed,
+                                          Args1, Args2);
+  bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC, Reversed,
+                                          Args2, Args1);
   // C++ [temp.deduct.partial]p10:
   //   F is more specialized than G if F is at least as specialized as G and G
   //   is not at least as specialized as F.
@@ -5568,12 +5586,28 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
   //   ... and if G has a trailing function parameter pack for which F does not
   //   have a corresponding parameter, and if F does not have a trailing
   //   function parameter pack, then F is more specialized than G.
-  FunctionDecl *FD1 = FT1->getTemplatedDecl();
-  FunctionDecl *FD2 = FT2->getTemplatedDecl();
-  unsigned NumParams1 = FD1->getNumParams();
-  unsigned NumParams2 = FD2->getNumParams();
-  bool Variadic1 = NumParams1 && FD1->parameters().back()->isParameterPack();
-  bool Variadic2 = NumParams2 && FD2->parameters().back()->isParameterPack();
+
+  SmallVector Param1;
+  Param1.reserve(FD1->param_size() + ShouldConvert1);
+  if (ShouldConvert1)
+    Param1.push_back(Obj1Ty);
+  for (const auto &P : FD1->parameters())
+    Param1.push_back(P->getType());
+
+  SmallVector Param2;
+  Param2.reserve(FD2->param_size() + ShouldConvert2);
+  if (ShouldConvert2)
+    Param2.push_back(Obj2Ty);
+  for (const auto &P : FD2->parameters())
+    Param2.push_back(P->getType());
+
+  unsigned NumParams1 = Param1.size();
+  unsigned NumParams2 = Param2.size();
+
+  bool Variadic1 =
+      FD1->param_size() && FD1->parameters().back()->isParameterPack();
+  bool Variadic2 =
+      FD2->param_size() && FD2->parameters().back()->isParameterPack();
   if (Variadic1 != Variadic2) {
     if (Variadic1 && NumParams1 > NumParams2)
       return FT2;
@@ -5584,8 +5618,8 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
   // This a speculative fix for CWG1432 (Similar to the fix for CWG1395) that
   // there is no wording or even resolution for this issue.
   for (int i = 0, e = std::min(NumParams1, NumParams2); i < e; ++i) {
-    QualType T1 = FD1->getParamDecl(i)->getType().getCanonicalType();
-    QualType T2 = FD2->getParamDecl(i)->getType().getCanonicalType();
+    QualType T1 = Param1[i].getCanonicalType();
+    QualType T2 = Param2[i].getCanonicalType();
     auto *TST1 = dyn_cast(T1);
     auto *TST2 = dyn_cast(T2);
     if (!TST1 || !TST2)
@@ -5644,8 +5678,7 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
   // Any top-level cv-qualifiers modifying a parameter type are deleted when
   // forming the function type.
   for (unsigned i = 0; i < NumParams1; ++i)
-    if (!Context.hasSameUnqualifiedType(FD1->getParamDecl(i)->getType(),
-                                        FD2->getParamDecl(i)->getType()))
+    if (!Context.hasSameUnqualifiedType(Param1[i], Param2[i]))
       return nullptr;
 
   // C++20 [temp.func.order]p6.3:
@@ -5733,8 +5766,8 @@ UnresolvedSetIterator Sema::getMostSpecialized(
     FunctionTemplateDecl *Challenger
       = cast(*I)->getPrimaryTemplate();
     assert(Challenger && "Not a function template specialization?");
-    if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
-                                                  Loc, TPOC_Other, 0, 0),
+    if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, Loc,
+                                                  TPOC_Other, 0),
                        Challenger)) {
       Best = I;
       BestTemplate = Challenger;
@@ -5749,7 +5782,7 @@ UnresolvedSetIterator Sema::getMostSpecialized(
       = cast(*I)->getPrimaryTemplate();
     if (I != Best &&
         !isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger,
-                                                   Loc, TPOC_Other, 0, 0),
+                                                   Loc, TPOC_Other, 0),
                         BestTemplate)) {
       Ambiguous = true;
       break;
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 371378485626c2cfccbe1f0e20e49cd8875b008c..1a0c88703aca01c49c2556ee2886bd9ed1d9ebc8 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -21,6 +21,7 @@
 #include "clang/AST/ExprConcepts.h"
 #include "clang/AST/PrettyDeclStackTrace.h"
 #include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
 #include "clang/AST/TypeVisitor.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/Stack.h"
@@ -547,9 +548,9 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
     : InstantiatingTemplate(SemaRef, Kind, PointOfInstantiation,
                             InstantiationRange, FunctionTemplate, nullptr,
                             TemplateArgs, &DeductionInfo) {
-  assert(
-    Kind == CodeSynthesisContext::ExplicitTemplateArgumentSubstitution ||
-    Kind == CodeSynthesisContext::DeducedTemplateArgumentSubstitution);
+  assert(Kind == CodeSynthesisContext::ExplicitTemplateArgumentSubstitution ||
+         Kind == CodeSynthesisContext::DeducedTemplateArgumentSubstitution ||
+         Kind == CodeSynthesisContext::BuildingDeductionGuides);
 }
 
 Sema::InstantiatingTemplate::InstantiatingTemplate(
@@ -1410,6 +1411,7 @@ namespace {
                           NamedDecl *FirstQualifierInScope = nullptr,
                           bool AllowInjectedClassName = false);
 
+    const CXXAssumeAttr *TransformCXXAssumeAttr(const CXXAssumeAttr *AA);
     const LoopHintAttr *TransformLoopHintAttr(const LoopHintAttr *LH);
     const NoInlineAttr *TransformStmtNoInlineAttr(const Stmt *OrigS,
                                                   const Stmt *InstS,
@@ -1446,6 +1448,59 @@ namespace {
       return inherited::TransformFunctionProtoType(TLB, TL);
     }
 
+    QualType TransformInjectedClassNameType(TypeLocBuilder &TLB,
+                                            InjectedClassNameTypeLoc TL) {
+      auto Type = inherited::TransformInjectedClassNameType(TLB, TL);
+      // Special case for transforming a deduction guide, we return a
+      // transformed TemplateSpecializationType.
+      if (Type.isNull() &&
+          SemaRef.CodeSynthesisContexts.back().Kind ==
+              Sema::CodeSynthesisContext::BuildingDeductionGuides) {
+        // Return a TemplateSpecializationType for transforming a deduction
+        // guide.
+        if (auto *ICT = TL.getType()->getAs()) {
+          auto Type =
+              inherited::TransformType(ICT->getInjectedSpecializationType());
+          TLB.pushTrivial(SemaRef.Context, Type, TL.getNameLoc());
+          return Type;
+        }
+      }
+      return Type;
+    }
+    // Override the default version to handle a rewrite-template-arg-pack case
+    // for building a deduction guide.
+    bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
+                                   TemplateArgumentLoc &Output,
+                                   bool Uneval = false) {
+      const TemplateArgument &Arg = Input.getArgument();
+      std::vector TArgs;
+      switch (Arg.getKind()) {
+      case TemplateArgument::Pack:
+        // Literally rewrite the template argument pack, instead of unpacking
+        // it.
+        assert(
+            SemaRef.CodeSynthesisContexts.back().Kind ==
+                Sema::CodeSynthesisContext::BuildingDeductionGuides &&
+            "Transforming a template argument pack is only allowed in building "
+            "deduction guide");
+        for (auto &pack : Arg.getPackAsArray()) {
+          TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc(
+              pack, QualType(), SourceLocation{});
+          TemplateArgumentLoc Output;
+          if (SemaRef.SubstTemplateArgument(Input, TemplateArgs, Output))
+            return true; // fails
+          TArgs.push_back(Output.getArgument());
+        }
+        Output = SemaRef.getTrivialTemplateArgumentLoc(
+            TemplateArgument(llvm::ArrayRef(TArgs).copy(SemaRef.Context)),
+            QualType(), SourceLocation{});
+        return false;
+      default:
+        break;
+      }
+      return inherited::TransformTemplateArgument(Input, Output, Uneval);
+    }
+
     template
     QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
                                         FunctionProtoTypeLoc TL,
@@ -1926,6 +1981,21 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
                                          Arg, PackIndex);
 }
 
+const CXXAssumeAttr *
+TemplateInstantiator::TransformCXXAssumeAttr(const CXXAssumeAttr *AA) {
+  ExprResult Res = getDerived().TransformExpr(AA->getAssumption());
+  if (!Res.isUsable())
+    return AA;
+
+  Res = getSema().BuildCXXAssumeExpr(Res.get(), AA->getAttrName(),
+                                     AA->getRange());
+  if (!Res.isUsable())
+    return AA;
+
+  return CXXAssumeAttr::CreateImplicit(getSema().Context, Res.get(),
+                                       AA->getRange());
+}
+
 const LoopHintAttr *
 TemplateInstantiator::TransformLoopHintAttr(const LoopHintAttr *LH) {
   Expr *TransformedExpr = getDerived().TransformExpr(LH->getValue()).get();
@@ -4138,6 +4208,15 @@ Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
   return Instantiator.TransformStmt(S);
 }
 
+bool Sema::SubstTemplateArgument(
+    const TemplateArgumentLoc &Input,
+    const MultiLevelTemplateArgumentList &TemplateArgs,
+    TemplateArgumentLoc &Output) {
+  TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
+                                    DeclarationName());
+  return Instantiator.TransformTemplateArgument(Input, Output);
+}
+
 bool Sema::SubstTemplateArguments(
     ArrayRef Args,
     const MultiLevelTemplateArgumentList &TemplateArgs,
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 9c696e072ba4a78a9323dc4ca882878af0bc03af..20c2c93ac9c7b415ece248f4119532bde1b0ab5e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2219,7 +2219,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
       FunctionTemplate->setInstantiatedFromMemberTemplate(
                                            D->getDescribedFunctionTemplate());
     }
-  } else if (FunctionTemplate) {
+  } else if (FunctionTemplate &&
+             SemaRef.CodeSynthesisContexts.back().Kind !=
+                 Sema::CodeSynthesisContext::BuildingDeductionGuides) {
     // Record this function template specialization.
     ArrayRef Innermost = TemplateArgs.getInnermost();
     Function->setFunctionTemplateSpecialization(FunctionTemplate,
@@ -4853,16 +4855,13 @@ bool TemplateDeclInstantiator::SubstDefaultedFunction(FunctionDecl *New,
 ///
 /// Usually this should not be used, and template argument deduction should be
 /// used in its place.
-FunctionDecl *
-Sema::InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
-                                     const TemplateArgumentList *Args,
-                                     SourceLocation Loc) {
+FunctionDecl *Sema::InstantiateFunctionDeclaration(
+    FunctionTemplateDecl *FTD, const TemplateArgumentList *Args,
+    SourceLocation Loc, CodeSynthesisContext::SynthesisKind CSC) {
   FunctionDecl *FD = FTD->getTemplatedDecl();
 
   sema::TemplateDeductionInfo Info(Loc);
-  InstantiatingTemplate Inst(
-      *this, Loc, FTD, Args->asArray(),
-      CodeSynthesisContext::ExplicitTemplateArgumentSubstitution, Info);
+  InstantiatingTemplate Inst(*this, Loc, FTD, Args->asArray(), CSC, Info);
   if (Inst.isInvalid())
     return nullptr;
 
@@ -6286,8 +6285,18 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
           QualType T = CheckTemplateIdType(TemplateName(TD), Loc, Args);
           if (T.isNull())
             return nullptr;
-          auto *SubstRecord = T->getAsCXXRecordDecl();
-          assert(SubstRecord && "class template id not a class type?");
+          CXXRecordDecl *SubstRecord = T->getAsCXXRecordDecl();
+
+          if (!SubstRecord) {
+            // T can be a dependent TemplateSpecializationType when performing a
+            // substitution for building a deduction guide.
+            assert(CodeSynthesisContexts.back().Kind ==
+                   CodeSynthesisContext::BuildingDeductionGuides);
+            // Return a nullptr as a sentinel value, we handle it properly in
+            // the TemplateInstantiator::TransformInjectedClassNameType
+            // override, which we transform it to a TemplateSpecializationType.
+            return nullptr;
+          }
           // Check that this template-id names the primary template and not a
           // partial or explicit specialization. (In the latter cases, it's
           // meaningless to attempt to find an instantiation of D within the
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 1e43e36016a66f37751ff7908a2d9e5a68830203..3148299f6467af7f260b10de9d820947ed305128 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -1561,7 +1561,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
     break;
   case DeclSpec::TST_float128:
     if (!S.Context.getTargetInfo().hasFloat128Type() &&
-        !S.getLangOpts().SYCLIsDevice &&
+        !S.getLangOpts().SYCLIsDevice && !S.getLangOpts().CUDAIsDevice &&
         !(S.getLangOpts().OpenMP && S.getLangOpts().OpenMPIsTargetDevice))
       S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported)
         << "__float128";
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 7389a48fe56fccad0ded3f29ecd3291656489edb..2d22692f3ab7502543bc78bdb6d6d9ffac584fc9 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -4785,6 +4785,14 @@ bool TreeTransform::TransformTemplateArguments(
     TemplateArgumentLoc In = *First;
 
     if (In.getArgument().getKind() == TemplateArgument::Pack) {
+      // When building the deduction guides, we rewrite the argument packs
+      // instead of unpacking.
+      if (getSema().CodeSynthesisContexts.back().Kind ==
+          Sema::CodeSynthesisContext::BuildingDeductionGuides) {
+        if (getDerived().TransformTemplateArgument(In, Out, Uneval))
+          return true;
+        continue;
+      }
       // Unpack argument packs, which we translate them into separate
       // arguments.
       // FIXME: We could do much better if we could guarantee that the
@@ -13649,10 +13657,29 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) {
   // use evaluation contexts to distinguish the function parameter case.
   CXXRecordDecl::LambdaDependencyKind DependencyKind =
       CXXRecordDecl::LDK_Unknown;
+  DeclContext *DC = getSema().CurContext;
+  // A RequiresExprBodyDecl is not interesting for dependencies.
+  // For the following case,
+  //
+  // template 
+  // concept C = requires { [] {}; };
+  //
+  // template 
+  // struct Widget;
+  //
+  // template 
+  // struct Widget {};
+  //
+  // While we are substituting Widget, the parent of DC would be
+  // the template specialization itself. Thus, the lambda expression
+  // will be deemed as dependent even if there are no dependent template
+  // arguments.
+  // (A ClassTemplateSpecializationDecl is always a dependent context.)
+  while (DC->getDeclKind() == Decl::Kind::RequiresExprBody)
+    DC = DC->getParent();
   if ((getSema().isUnevaluatedContext() ||
        getSema().isConstantEvaluatedContext()) &&
-      (getSema().CurContext->isFileContext() ||
-       !getSema().CurContext->getParent()->isDependentContext()))
+      (DC->isFileContext() || !DC->getParent()->isDependentContext()))
     DependencyKind = CXXRecordDecl::LDK_NeverDependent;
 
   CXXRecordDecl *OldClass = E->getLambdaClass();
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 683a076e6bc3998b500c580fb8f1001fb52f2933..ede9f6e93469b7ea32c4c3bc5eb863f145ffe75f 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -9762,7 +9762,7 @@ void ASTReader::finishPendingActions() {
             !NonConstDefn->isLateTemplateParsed() &&
             // We only perform ODR checks for decls not in the explicit
             // global module fragment.
-            !shouldSkipCheckingODR(FD) &&
+            !FD->shouldSkipCheckingODR() &&
             FD->getODRHash() != NonConstDefn->getODRHash()) {
           if (!isa(FD)) {
             PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn);
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index d5309e3fc31f709921845aec951d2107fbea89b9..a22f760408c634f93adde1c846fa09e7b5bd8263 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -832,7 +832,7 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
       Reader.mergeDefinitionVisibility(OldDef, ED);
       // We don't want to check the ODR hash value for declarations from global
       // module fragment.
-      if (!shouldSkipCheckingODR(ED) &&
+      if (!ED->shouldSkipCheckingODR() &&
           OldDef->getODRHash() != ED->getODRHash())
         Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED);
     } else {
@@ -874,7 +874,7 @@ void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) {
   VisitRecordDeclImpl(RD);
   // We should only reach here if we're in C/Objective-C. There is no
   // global module fragment.
-  assert(!shouldSkipCheckingODR(RD));
+  assert(!RD->shouldSkipCheckingODR());
   RD->setODRHash(Record.readInt());
 
   // Maintain the invariant of a redeclaration chain containing only
@@ -2152,7 +2152,7 @@ void ASTDeclReader::MergeDefinitionData(
   }
 
   // We don't want to check ODR for decls in the global module fragment.
-  if (shouldSkipCheckingODR(MergeDD.Definition))
+  if (MergeDD.Definition->shouldSkipCheckingODR())
     return;
 
   if (D->getODRHash() != MergeDD.ODRHash) {
@@ -3526,7 +3526,7 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
   // same template specialization into the same CXXRecordDecl.
   auto MergedDCIt = Reader.MergedDeclContexts.find(D->getLexicalDeclContext());
   if (MergedDCIt != Reader.MergedDeclContexts.end() &&
-      !shouldSkipCheckingODR(D) && MergedDCIt->second == D->getDeclContext())
+      !D->shouldSkipCheckingODR() && MergedDCIt->second == D->getDeclContext())
     Reader.PendingOdrMergeChecks.push_back(D);
 
   return FindExistingResult(Reader, D, /*Existing=*/nullptr,
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 3da44ffccc38a280c65d7a7c781703672630416d..674ed47581dfd3098fe5990fc1452483e993641e 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -2805,7 +2805,7 @@ void ASTStmtReader::VisitOpenACCAssociatedStmtConstruct(
 
 void ASTStmtReader::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) {
   VisitStmt(S);
-  VisitOpenACCConstructStmt(S);
+  VisitOpenACCAssociatedStmtConstruct(S);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index a9edc7e68b53b311071632a4af9f8232eac99349..3653d94c6e073964eac259647f47059a90c0751c 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4623,10 +4623,12 @@ ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream,
                      SmallVectorImpl &Buffer,
                      InMemoryModuleCache &ModuleCache,
                      ArrayRef> Extensions,
-                     bool IncludeTimestamps, bool BuildingImplicitModule)
+                     bool IncludeTimestamps, bool BuildingImplicitModule,
+                     bool GeneratingReducedBMI)
     : Stream(Stream), Buffer(Buffer), ModuleCache(ModuleCache),
       IncludeTimestamps(IncludeTimestamps),
-      BuildingImplicitModule(BuildingImplicitModule) {
+      BuildingImplicitModule(BuildingImplicitModule),
+      GeneratingReducedBMI(GeneratingReducedBMI) {
   for (const auto &Ext : Extensions) {
     if (auto Writer = Ext->createExtensionWriter(*this))
       ModuleFileExtensionWriters.push_back(std::move(Writer));
@@ -5457,18 +5459,20 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
 
     // Add a trailing update record, if any. These must go last because we
     // lazily load their attached statement.
-    if (HasUpdatedBody) {
-      const auto *Def = cast(D);
-      Record.push_back(UPD_CXX_ADDED_FUNCTION_DEFINITION);
-      Record.push_back(Def->isInlined());
-      Record.AddSourceLocation(Def->getInnerLocStart());
-      Record.AddFunctionDefinition(Def);
-    } else if (HasAddedVarDefinition) {
-      const auto *VD = cast(D);
-      Record.push_back(UPD_CXX_ADDED_VAR_DEFINITION);
-      Record.push_back(VD->isInline());
-      Record.push_back(VD->isInlineSpecified());
-      Record.AddVarDeclInit(VD);
+    if (!GeneratingReducedBMI || !CanElideDeclDef(D)) {
+      if (HasUpdatedBody) {
+        const auto *Def = cast(D);
+        Record.push_back(UPD_CXX_ADDED_FUNCTION_DEFINITION);
+        Record.push_back(Def->isInlined());
+        Record.AddSourceLocation(Def->getInnerLocStart());
+        Record.AddFunctionDefinition(Def);
+      } else if (HasAddedVarDefinition) {
+        const auto *VD = cast(D);
+        Record.push_back(UPD_CXX_ADDED_VAR_DEFINITION);
+        Record.push_back(VD->isInline());
+        Record.push_back(VD->isInlineSpecified());
+        Record.AddVarDeclInit(VD);
+      }
     }
 
     OffsetsRecord.push_back(GetDeclRef(D));
@@ -6056,7 +6060,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
 
   BitsPacker DefinitionBits;
 
-  bool ShouldSkipCheckingODR = shouldSkipCheckingODR(D);
+  bool ShouldSkipCheckingODR = D->shouldSkipCheckingODR();
   DefinitionBits.addBit(ShouldSkipCheckingODR);
 
 #define FIELD(Name, Width, Merge)                                              \
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index e73800100e3ccfc16a729d0197c291e0cd6c8ed3..d04e1c781b4e286ef1e74de74ef5cfea52501627 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -16,6 +16,7 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/DeclVisitor.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/ODRHash.h"
 #include "clang/AST/OpenMPClause.h"
 #include "clang/AST/PrettyDeclStackTrace.h"
 #include "clang/Basic/SourceManager.h"
@@ -40,11 +41,14 @@ namespace clang {
     serialization::DeclCode Code;
     unsigned AbbrevToUse;
 
+    bool GeneratingReducedBMI = false;
+
   public:
     ASTDeclWriter(ASTWriter &Writer, ASTContext &Context,
-                  ASTWriter::RecordDataImpl &Record)
+                  ASTWriter::RecordDataImpl &Record, bool GeneratingReducedBMI)
         : Writer(Writer), Context(Context), Record(Writer, Record),
-          Code((serialization::DeclCode)0), AbbrevToUse(0) {}
+          Code((serialization::DeclCode)0), AbbrevToUse(0),
+          GeneratingReducedBMI(GeneratingReducedBMI) {}
 
     uint64_t Emit(Decl *D) {
       if (!Code)
@@ -270,6 +274,27 @@ namespace clang {
   };
 }
 
+bool clang::CanElideDeclDef(const Decl *D) {
+  if (auto *FD = dyn_cast(D)) {
+    if (FD->isInlined() || FD->isConstexpr())
+      return false;
+
+    if (FD->isDependentContext())
+      return false;
+  }
+
+  if (auto *VD = dyn_cast(D)) {
+    if (!VD->getDeclContext()->getRedeclContext()->isFileContext() ||
+        VD->isInline() || VD->isConstexpr() || isa(VD))
+      return false;
+
+    if (VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+      return false;
+  }
+
+  return true;
+}
+
 void ASTDeclWriter::Visit(Decl *D) {
   DeclVisitor::Visit(D);
 
@@ -285,9 +310,12 @@ void ASTDeclWriter::Visit(Decl *D) {
   // have been written. We want it last because we will not read it back when
   // retrieving it from the AST, we'll just lazily set the offset.
   if (auto *FD = dyn_cast(D)) {
-    Record.push_back(FD->doesThisDeclarationHaveABody());
-    if (FD->doesThisDeclarationHaveABody())
-      Record.AddFunctionDefinition(FD);
+    if (!GeneratingReducedBMI || !CanElideDeclDef(FD)) {
+      Record.push_back(FD->doesThisDeclarationHaveABody());
+      if (FD->doesThisDeclarationHaveABody())
+        Record.AddFunctionDefinition(FD);
+    } else
+      Record.push_back(0);
   }
 
   // Similar to FunctionDecls, handle VarDecl's initializer here and write it
@@ -295,7 +323,10 @@ void ASTDeclWriter::Visit(Decl *D) {
   // we have finished recursive deserialization, because it can recursively
   // refer back to the variable.
   if (auto *VD = dyn_cast(D)) {
-    Record.AddVarDeclInit(VD);
+    if (!GeneratingReducedBMI || !CanElideDeclDef(VD))
+      Record.AddVarDeclInit(VD);
+    else
+      Record.push_back(0);
   }
 
   // And similarly for FieldDecls. We already serialized whether there is a
@@ -488,7 +519,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
   BitsPacker EnumDeclBits;
   EnumDeclBits.addBits(D->getNumPositiveBits(), /*BitWidth=*/8);
   EnumDeclBits.addBits(D->getNumNegativeBits(), /*BitWidth=*/8);
-  bool ShouldSkipCheckingODR = shouldSkipCheckingODR(D);
+  bool ShouldSkipCheckingODR = D->shouldSkipCheckingODR();
   EnumDeclBits.addBit(ShouldSkipCheckingODR);
   EnumDeclBits.addBit(D->isScoped());
   EnumDeclBits.addBit(D->isScopedUsingClassTag());
@@ -514,7 +545,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
       !D->isTopLevelDeclInObjCContainer() &&
       !CXXRecordDecl::classofKind(D->getKind()) &&
       !D->getIntegerTypeSourceInfo() && !D->getMemberSpecializationInfo() &&
-      !needsAnonymousDeclarationNumber(D) && !shouldSkipCheckingODR(D) &&
+      !needsAnonymousDeclarationNumber(D) && !D->shouldSkipCheckingODR() &&
       D->getDeclName().getNameKind() == DeclarationName::Identifier)
     AbbrevToUse = Writer.getDeclEnumAbbrev();
 
@@ -680,7 +711,7 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
   // FIXME: stable encoding
   FunctionDeclBits.addBits(llvm::to_underlying(D->getLinkageInternal()), 3);
   FunctionDeclBits.addBits((uint32_t)D->getStorageClass(), /*BitWidth=*/3);
-  bool ShouldSkipCheckingODR = shouldSkipCheckingODR(D);
+  bool ShouldSkipCheckingODR = D->shouldSkipCheckingODR();
   FunctionDeclBits.addBit(ShouldSkipCheckingODR);
   FunctionDeclBits.addBit(D->isInlineSpecified());
   FunctionDeclBits.addBit(D->isInlined());
@@ -1514,7 +1545,7 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
       D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() &&
       !D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() &&
       D->getDeclName().getNameKind() == DeclarationName::Identifier &&
-      !shouldSkipCheckingODR(D) && !D->hasExtInfo() &&
+      !D->shouldSkipCheckingODR() && !D->hasExtInfo() &&
       !D->isExplicitlyDefaulted()) {
     if (D->getTemplatedKind() == FunctionDecl::TK_NonTemplate ||
         D->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate ||
@@ -2729,7 +2760,7 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
   assert(ID >= FirstDeclID && "invalid decl ID");
 
   RecordData Record;
-  ASTDeclWriter W(*this, Context, Record);
+  ASTDeclWriter W(*this, Context, Record, GeneratingReducedBMI);
 
   // Build a record for this declaration
   W.Visit(D);
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 484621ae813093ed071517f2cf3a53001c431a38..7ce48fede383ea6f200146f8d8438ec929c2124c 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2855,7 +2855,7 @@ void ASTStmtWriter::VisitOpenACCAssociatedStmtConstruct(
 
 void ASTStmtWriter::VisitOpenACCComputeConstruct(OpenACCComputeConstruct *S) {
   VisitStmt(S);
-  VisitOpenACCConstructStmt(S);
+  VisitOpenACCAssociatedStmtConstruct(S);
   Code = serialization::STMT_OPENACC_COMPUTE_CONSTRUCT;
 }
 
diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp
index cf8084333811f138bde9556cdae38aed3eaf8332..2b511b2d5a90a219c655d8e73bbbf7f2dccbff27 100644
--- a/clang/lib/Serialization/GeneratePCH.cpp
+++ b/clang/lib/Serialization/GeneratePCH.cpp
@@ -12,9 +12,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/AST/ASTContext.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/SemaConsumer.h"
+#include "clang/Serialization/ASTReader.h"
 #include "clang/Serialization/ASTWriter.h"
 #include "llvm/Bitstream/BitstreamWriter.h"
 
@@ -25,11 +27,12 @@ PCHGenerator::PCHGenerator(
     StringRef OutputFile, StringRef isysroot, std::shared_ptr Buffer,
     ArrayRef> Extensions,
     bool AllowASTWithErrors, bool IncludeTimestamps,
-    bool BuildingImplicitModule, bool ShouldCacheASTInMemory)
+    bool BuildingImplicitModule, bool ShouldCacheASTInMemory,
+    bool GeneratingReducedBMI)
     : PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()),
       SemaPtr(nullptr), Buffer(std::move(Buffer)), Stream(this->Buffer->Data),
       Writer(Stream, this->Buffer->Data, ModuleCache, Extensions,
-             IncludeTimestamps, BuildingImplicitModule),
+             IncludeTimestamps, BuildingImplicitModule, GeneratingReducedBMI),
       AllowASTWithErrors(AllowASTWithErrors),
       ShouldCacheASTInMemory(ShouldCacheASTInMemory) {
   this->Buffer->IsComplete = false;
@@ -78,3 +81,33 @@ ASTMutationListener *PCHGenerator::GetASTMutationListener() {
 ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
   return &Writer;
 }
+
+ReducedBMIGenerator::ReducedBMIGenerator(const Preprocessor &PP,
+                                         InMemoryModuleCache &ModuleCache,
+                                         StringRef OutputFile,
+                                         std::shared_ptr Buffer,
+                                         bool IncludeTimestamps)
+    : PCHGenerator(
+          PP, ModuleCache, OutputFile, llvm::StringRef(), Buffer,
+          /*Extensions=*/ArrayRef>(),
+          /*AllowASTWithErrors*/ false, /*IncludeTimestamps=*/IncludeTimestamps,
+          /*BuildingImplicitModule=*/false, /*ShouldCacheASTInMemory=*/false,
+          /*GeneratingReducedBMI=*/true) {}
+
+void ReducedBMIGenerator::HandleTranslationUnit(ASTContext &Ctx) {
+  PCHGenerator::HandleTranslationUnit(Ctx);
+
+  if (!isComplete())
+    return;
+
+  std::error_code EC;
+  auto OS = std::make_unique(getOutputFile(), EC);
+  if (EC) {
+    getDiagnostics().Report(diag::err_fe_unable_to_open_output)
+        << getOutputFile() << EC.message() << "\n";
+    return;
+  }
+
+  *OS << getBufferPtr()->Data;
+  OS->flush();
+}
diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
index 0ca0c487b645508bc8b90482242cd312632feea1..153a1b1acbfa1941a2a7fab445a1b47caa2c4123 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
@@ -33,30 +33,36 @@ namespace ento {
 /// checking.
 ///
 /// \sa CheckerContext
-class CheckerDocumentation : public Checker< check::PreStmt,
-                                       check::PostStmt,
-                                       check::PreObjCMessage,
-                                       check::PostObjCMessage,
-                                       check::ObjCMessageNil,
-                                       check::PreCall,
-                                       check::PostCall,
-                                       check::BranchCondition,
-                                       check::NewAllocator,
-                                       check::Location,
-                                       check::Bind,
-                                       check::DeadSymbols,
-                                       check::BeginFunction,
-                                       check::EndFunction,
-                                       check::EndAnalysis,
-                                       check::EndOfTranslationUnit,
-                                       eval::Call,
-                                       eval::Assume,
-                                       check::LiveSymbols,
-                                       check::RegionChanges,
-                                       check::PointerEscape,
-                                       check::ConstPointerEscape,
-                                       check::Event,
-                                       check::ASTDecl > {
+class CheckerDocumentation
+    : public Checker<
+          // clang-format off
+          check::ASTCodeBody,
+          check::ASTDecl,
+          check::BeginFunction,
+          check::Bind,
+          check::BranchCondition,
+          check::ConstPointerEscape,
+          check::DeadSymbols,
+          check::EndAnalysis,
+          check::EndFunction,
+          check::EndOfTranslationUnit,
+          check::Event,
+          check::LiveSymbols,
+          check::Location,
+          check::NewAllocator,
+          check::ObjCMessageNil,
+          check::PointerEscape,
+          check::PostCall,
+          check::PostObjCMessage,
+          check::PostStmt,
+          check::PreCall,
+          check::PreObjCMessage,
+          check::PreStmt,
+          check::RegionChanges,
+          eval::Assume,
+          eval::Call
+          // clang-format on
+          > {
 public:
   /// Pre-visit the Statement.
   ///
@@ -137,10 +143,7 @@ public:
   /// (2) and (3). Post-call for the allocator is called after step (1).
   /// Pre-statement for the new-expression is called on step (4) when the value
   /// of the expression is evaluated.
-  /// \param NE     The C++ new-expression that triggered the allocation.
-  /// \param Target The allocated region, casted to the class type.
-  void checkNewAllocator(const CXXNewExpr *NE, SVal Target,
-                         CheckerContext &) const {}
+  void checkNewAllocator(const CXXAllocatorCall &, CheckerContext &) const {}
 
   /// Called on a load from and a store to a location.
   ///
@@ -324,11 +327,26 @@ public:
   void checkASTDecl(const FunctionDecl *D,
                     AnalysisManager &Mgr,
                     BugReporter &BR) const {}
+
+  /// Check every declaration that has a statement body in the AST.
+  ///
+  /// As AST traversal callback, which should only be used when the checker is
+  /// not path sensitive. It will be called for every Declaration in the AST.
+  void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
+                        BugReporter &BR) const {}
 };
 
 void CheckerDocumentation::checkPostStmt(const DeclStmt *DS,
                                          CheckerContext &C) const {
 }
 
+void registerCheckerDocumentationChecker(CheckerManager &Mgr) {
+  Mgr.registerChecker();
+}
+
+bool shouldRegisterCheckerDocumentationChecker(const CheckerManager &) {
+  return false;
+}
+
 } // end namespace ento
 } // end namespace clang
diff --git a/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp b/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
index 49486ea796c2632699b7ae35bffe617fafc400c6..fc174e29be470a1ca235cbffa169d146c58092bb 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DirectIvarAssignment.cpp
@@ -1,4 +1,4 @@
-//=- DirectIvarAssignment.cpp - Check rules on ObjC properties -*- C++ ----*-==//
+//===- DirectIvarAssignment.cpp - Check rules on ObjC properties -*- C++ -*-==//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index b27ca6a449597442c8f05c1bf147a8e0505a3cd7..03cb7696707fe2f215db6192ee244e4a22784c50 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -382,6 +382,8 @@ private:
   CHECK_FN(checkGMemdup)
   CHECK_FN(checkGMallocN)
   CHECK_FN(checkGMallocN0)
+  CHECK_FN(preGetdelim)
+  CHECK_FN(checkGetdelim)
   CHECK_FN(checkReallocN)
   CHECK_FN(checkOwnershipAttr)
 
@@ -391,6 +393,11 @@ private:
   using CheckFn = std::function;
 
+  const CallDescriptionMap PreFnMap{
+      {{{"getline"}, 3}, &MallocChecker::preGetdelim},
+      {{{"getdelim"}, 4}, &MallocChecker::preGetdelim},
+  };
+
   const CallDescriptionMap FreeingMemFnMap{
       {{{"free"}, 1}, &MallocChecker::checkFree},
       {{{"if_freenameindex"}, 1}, &MallocChecker::checkIfFreeNameIndex},
@@ -439,6 +446,8 @@ private:
        std::bind(&MallocChecker::checkRealloc, _1, _2, _3, false)},
       {{{"g_realloc_n"}, 3}, &MallocChecker::checkReallocN},
       {{{"g_try_realloc_n"}, 3}, &MallocChecker::checkReallocN},
+      {{{"getline"}, 3}, &MallocChecker::checkGetdelim},
+      {{{"getdelim"}, 4}, &MallocChecker::checkGetdelim},
   };
 
   bool isMemCall(const CallEvent &Call) const;
@@ -588,11 +597,14 @@ private:
   ///      }
   /// \param [in] ReturnsNullOnFailure Whether the memory deallocation function
   ///   we're modeling returns with Null on failure.
+  /// \param [in] ArgValOpt Optional value to use for the argument instead of
+  /// the one obtained from ArgExpr.
   /// \returns The ProgramState right after deallocation.
   [[nodiscard]] ProgramStateRef
   FreeMemAux(CheckerContext &C, const Expr *ArgExpr, const CallEvent &Call,
              ProgramStateRef State, bool Hold, bool &IsKnownToBeAllocated,
-             AllocationFamily Family, bool ReturnsNullOnFailure = false) const;
+             AllocationFamily Family, bool ReturnsNullOnFailure = false,
+             std::optional ArgValOpt = {}) const;
 
   // TODO: Needs some refactoring, as all other deallocation modeling
   // functions are suffering from out parameters and messy code due to how
@@ -1423,6 +1435,50 @@ void MallocChecker::checkGMallocN0(const CallEvent &Call,
   C.addTransition(State);
 }
 
+void MallocChecker::preGetdelim(const CallEvent &Call,
+                                CheckerContext &C) const {
+  if (!Call.isGlobalCFunction())
+    return;
+
+  ProgramStateRef State = C.getState();
+  const auto LinePtr = getPointeeDefVal(Call.getArgSVal(0), State);
+  if (!LinePtr)
+    return;
+
+  // FreeMemAux takes IsKnownToBeAllocated as an output parameter, and it will
+  // be true after the call if the symbol was registered by this checker.
+  // We do not need this value here, as FreeMemAux will take care
+  // of reporting any violation of the preconditions.
+  bool IsKnownToBeAllocated = false;
+  State = FreeMemAux(C, Call.getArgExpr(0), Call, State, false,
+                     IsKnownToBeAllocated, AF_Malloc, false, LinePtr);
+  if (State)
+    C.addTransition(State);
+}
+
+void MallocChecker::checkGetdelim(const CallEvent &Call,
+                                  CheckerContext &C) const {
+  if (!Call.isGlobalCFunction())
+    return;
+
+  ProgramStateRef State = C.getState();
+  // Handle the post-conditions of getline and getdelim:
+  // Register the new conjured value as an allocated buffer.
+  const CallExpr *CE = dyn_cast_or_null(Call.getOriginExpr());
+  if (!CE)
+    return;
+
+  SValBuilder &SVB = C.getSValBuilder();
+
+  const auto LinePtr = getPointeeDefVal(Call.getArgSVal(0), State);
+  const auto Size = getPointeeDefVal(Call.getArgSVal(1), State);
+  if (!LinePtr || !Size || !LinePtr->getAsRegion())
+    return;
+
+  State = setDynamicExtent(State, LinePtr->getAsRegion(), *Size, SVB);
+  C.addTransition(MallocUpdateRefState(C, CE, State, AF_Malloc, *LinePtr));
+}
+
 void MallocChecker::checkReallocN(const CallEvent &Call,
                                   CheckerContext &C) const {
   ProgramStateRef State = C.getState();
@@ -1895,15 +1951,17 @@ static void printExpectedDeallocName(raw_ostream &os, AllocationFamily Family) {
   }
 }
 
-ProgramStateRef MallocChecker::FreeMemAux(
-    CheckerContext &C, const Expr *ArgExpr, const CallEvent &Call,
-    ProgramStateRef State, bool Hold, bool &IsKnownToBeAllocated,
-    AllocationFamily Family, bool ReturnsNullOnFailure) const {
+ProgramStateRef
+MallocChecker::FreeMemAux(CheckerContext &C, const Expr *ArgExpr,
+                          const CallEvent &Call, ProgramStateRef State,
+                          bool Hold, bool &IsKnownToBeAllocated,
+                          AllocationFamily Family, bool ReturnsNullOnFailure,
+                          std::optional ArgValOpt) const {
 
   if (!State)
     return nullptr;
 
-  SVal ArgVal = C.getSVal(ArgExpr);
+  SVal ArgVal = ArgValOpt.value_or(C.getSVal(ArgExpr));
   if (!isa(ArgVal))
     return nullptr;
   DefinedOrUnknownSVal location = ArgVal.castAs();
@@ -2881,6 +2939,13 @@ void MallocChecker::checkPreCall(const CallEvent &Call,
       return;
   }
 
+  // We need to handle getline pre-conditions here before the pointed region
+  // gets invalidated by StreamChecker
+  if (const auto *PreFN = PreFnMap.lookup(Call)) {
+    (*PreFN)(this, Call, C);
+    return;
+  }
+
   // We will check for double free in the post visit.
   if (const AnyFunctionCall *FC = dyn_cast(&Call)) {
     const FunctionDecl *FD = FC->getDecl();
diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
index 514f53b4804f500973d02b0c6b259e11c1f5fac1..e7fd14d4558b2b99bb511241c9fbf27b16876bc3 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp
@@ -1,4 +1,4 @@
-//===- ObjCAutoreleaseWriteChecker.cpp ----------------------------*- C++ -*-==//
+//===- ObjCAutoreleaseWriteChecker.cpp ---------------------------*- C++ -*-==//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
index 788f2875863c3e374f6e1c4ecd9b7f2b71dda899..a5173a05636a0904bfd9cb66a30b84c16c210cb7 100644
--- a/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp
@@ -1,4 +1,4 @@
-//===-- STLAlgorithmModeling.cpp -----------------------------------*- C++ -*--//
+//===-- STLAlgorithmModeling.cpp ----------------------------------*- C++ -*--//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
index 7cbe271dfbf93a24df30c542b2d66644a591c92e..50d50562d3e756559d9f81c51e0bfb5620e70487 100644
--- a/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
@@ -1,4 +1,4 @@
-//===-- SimpleStreamChecker.cpp -----------------------------------------*- C++ -*--//
+//===-- SimpleStreamChecker.cpp -----------------------------------*- C++ -*--//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 0208f94e1b5a2a73fa4788702d44d1d1143edd66..10972158f3986232db1dd2d9c0a5a0415a6b9e97 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -307,52 +307,64 @@ private:
       {{{"fclose"}, 1},
        {&StreamChecker::preDefault, &StreamChecker::evalFclose, 0}},
       {{{"fread"}, 4},
-       {std::bind(&StreamChecker::preReadWrite, _1, _2, _3, _4, true),
+       {&StreamChecker::preRead,
         std::bind(&StreamChecker::evalFreadFwrite, _1, _2, _3, _4, true), 3}},
       {{{"fwrite"}, 4},
-       {std::bind(&StreamChecker::preReadWrite, _1, _2, _3, _4, false),
+       {&StreamChecker::preWrite,
         std::bind(&StreamChecker::evalFreadFwrite, _1, _2, _3, _4, false), 3}},
       {{{"fgetc"}, 1},
-       {std::bind(&StreamChecker::preReadWrite, _1, _2, _3, _4, true),
+       {&StreamChecker::preRead,
         std::bind(&StreamChecker::evalFgetx, _1, _2, _3, _4, true), 0}},
       {{{"fgets"}, 3},
-       {std::bind(&StreamChecker::preReadWrite, _1, _2, _3, _4, true),
+       {&StreamChecker::preRead,
         std::bind(&StreamChecker::evalFgetx, _1, _2, _3, _4, false), 2}},
+      {{{"getc"}, 1},
+       {&StreamChecker::preRead,
+        std::bind(&StreamChecker::evalFgetx, _1, _2, _3, _4, true), 0}},
       {{{"fputc"}, 2},
-       {std::bind(&StreamChecker::preReadWrite, _1, _2, _3, _4, false),
+       {&StreamChecker::preWrite,
         std::bind(&StreamChecker::evalFputx, _1, _2, _3, _4, true), 1}},
       {{{"fputs"}, 2},
-       {std::bind(&StreamChecker::preReadWrite, _1, _2, _3, _4, false),
+       {&StreamChecker::preWrite,
         std::bind(&StreamChecker::evalFputx, _1, _2, _3, _4, false), 1}},
+      {{{"putc"}, 2},
+       {&StreamChecker::preWrite,
+        std::bind(&StreamChecker::evalFputx, _1, _2, _3, _4, true), 1}},
       {{{"fprintf"}},
-       {std::bind(&StreamChecker::preReadWrite, _1, _2, _3, _4, false),
+       {&StreamChecker::preWrite,
+        std::bind(&StreamChecker::evalFprintf, _1, _2, _3, _4), 0}},
+      {{{"vfprintf"}, 3},
+       {&StreamChecker::preWrite,
         std::bind(&StreamChecker::evalFprintf, _1, _2, _3, _4), 0}},
       {{{"fscanf"}},
-       {std::bind(&StreamChecker::preReadWrite, _1, _2, _3, _4, true),
+       {&StreamChecker::preRead,
+        std::bind(&StreamChecker::evalFscanf, _1, _2, _3, _4), 0}},
+      {{{"vfscanf"}, 3},
+       {&StreamChecker::preRead,
         std::bind(&StreamChecker::evalFscanf, _1, _2, _3, _4), 0}},
       {{{"ungetc"}, 2},
-       {std::bind(&StreamChecker::preReadWrite, _1, _2, _3, _4, false),
+       {&StreamChecker::preWrite,
         std::bind(&StreamChecker::evalUngetc, _1, _2, _3, _4), 1}},
       {{{"getdelim"}, 4},
-       {std::bind(&StreamChecker::preReadWrite, _1, _2, _3, _4, true),
+       {&StreamChecker::preRead,
         std::bind(&StreamChecker::evalGetdelim, _1, _2, _3, _4), 3}},
       {{{"getline"}, 3},
-       {std::bind(&StreamChecker::preReadWrite, _1, _2, _3, _4, true),
+       {&StreamChecker::preRead,
         std::bind(&StreamChecker::evalGetdelim, _1, _2, _3, _4), 2}},
       {{{"fseek"}, 3},
        {&StreamChecker::preFseek, &StreamChecker::evalFseek, 0}},
       {{{"fseeko"}, 3},
        {&StreamChecker::preFseek, &StreamChecker::evalFseek, 0}},
       {{{"ftell"}, 1},
-       {&StreamChecker::preDefault, &StreamChecker::evalFtell, 0}},
+       {&StreamChecker::preWrite, &StreamChecker::evalFtell, 0}},
       {{{"ftello"}, 1},
-       {&StreamChecker::preDefault, &StreamChecker::evalFtell, 0}},
+       {&StreamChecker::preWrite, &StreamChecker::evalFtell, 0}},
       {{{"fflush"}, 1},
        {&StreamChecker::preFflush, &StreamChecker::evalFflush, 0}},
       {{{"rewind"}, 1},
        {&StreamChecker::preDefault, &StreamChecker::evalRewind, 0}},
       {{{"fgetpos"}, 2},
-       {&StreamChecker::preDefault, &StreamChecker::evalFgetpos, 0}},
+       {&StreamChecker::preWrite, &StreamChecker::evalFgetpos, 0}},
       {{{"fsetpos"}, 2},
        {&StreamChecker::preDefault, &StreamChecker::evalFsetpos, 0}},
       {{{"clearerr"}, 1},
@@ -372,12 +384,18 @@ private:
   CallDescriptionMap FnTestDescriptions = {
       {{{"StreamTesterChecker_make_feof_stream"}, 1},
        {nullptr,
-        std::bind(&StreamChecker::evalSetFeofFerror, _1, _2, _3, _4, ErrorFEof),
+        std::bind(&StreamChecker::evalSetFeofFerror, _1, _2, _3, _4, ErrorFEof,
+                  false),
         0}},
       {{{"StreamTesterChecker_make_ferror_stream"}, 1},
        {nullptr,
         std::bind(&StreamChecker::evalSetFeofFerror, _1, _2, _3, _4,
-                  ErrorFError),
+                  ErrorFError, false),
+        0}},
+      {{{"StreamTesterChecker_make_ferror_indeterminate_stream"}, 1},
+       {nullptr,
+        std::bind(&StreamChecker::evalSetFeofFerror, _1, _2, _3, _4,
+                  ErrorFError, true),
         0}},
   };
 
@@ -389,6 +407,8 @@ private:
   mutable int SeekCurVal = 1;
   /// Expanded value of SEEK_END, 2 if not found.
   mutable int SeekEndVal = 2;
+  /// The built-in va_list type is platform-specific
+  mutable QualType VaListType;
 
   void evalFopen(const FnDescription *Desc, const CallEvent &Call,
                  CheckerContext &C) const;
@@ -401,8 +421,11 @@ private:
   void evalFclose(const FnDescription *Desc, const CallEvent &Call,
                   CheckerContext &C) const;
 
-  void preReadWrite(const FnDescription *Desc, const CallEvent &Call,
-                    CheckerContext &C, bool IsRead) const;
+  void preRead(const FnDescription *Desc, const CallEvent &Call,
+               CheckerContext &C) const;
+
+  void preWrite(const FnDescription *Desc, const CallEvent &Call,
+                CheckerContext &C) const;
 
   void evalFreadFwrite(const FnDescription *Desc, const CallEvent &Call,
                        CheckerContext &C, bool IsFread) const;
@@ -453,8 +476,8 @@ private:
                       const StreamErrorState &ErrorKind) const;
 
   void evalSetFeofFerror(const FnDescription *Desc, const CallEvent &Call,
-                         CheckerContext &C,
-                         const StreamErrorState &ErrorKind) const;
+                         CheckerContext &C, const StreamErrorState &ErrorKind,
+                         bool Indeterminate) const;
 
   void preFflush(const FnDescription *Desc, const CallEvent &Call,
                  CheckerContext &C) const;
@@ -518,7 +541,8 @@ private:
       return nullptr;
     for (auto *P : Call.parameters()) {
       QualType T = P->getType();
-      if (!T->isIntegralOrEnumerationType() && !T->isPointerType())
+      if (!T->isIntegralOrEnumerationType() && !T->isPointerType() &&
+          T.getCanonicalType() != VaListType)
         return nullptr;
     }
 
@@ -557,6 +581,10 @@ private:
       SeekCurVal = *OptInt;
   }
 
+  void initVaListType(CheckerContext &C) const {
+    VaListType = C.getASTContext().getBuiltinVaListType().getCanonicalType();
+  }
+
   /// Searches for the ExplodedNode where the file descriptor was acquired for
   /// StreamSym.
   static const ExplodedNode *getAcquisitionSite(const ExplodedNode *N,
@@ -705,6 +733,7 @@ static ProgramStateRef escapeArgs(ProgramStateRef State, CheckerContext &C,
 void StreamChecker::checkPreCall(const CallEvent &Call,
                                  CheckerContext &C) const {
   initMacroValues(C);
+  initVaListType(C);
 
   const FnDescription *Desc = lookupFn(Call);
   if (!Desc || !Desc->PreFn)
@@ -829,9 +858,8 @@ void StreamChecker::evalFclose(const FnDescription *Desc, const CallEvent &Call,
   C.addTransition(E.bindReturnValue(State, C, *EofVal));
 }
 
-void StreamChecker::preReadWrite(const FnDescription *Desc,
-                                 const CallEvent &Call, CheckerContext &C,
-                                 bool IsRead) const {
+void StreamChecker::preRead(const FnDescription *Desc, const CallEvent &Call,
+                            CheckerContext &C) const {
   ProgramStateRef State = C.getState();
   SVal StreamVal = getStreamArg(Desc, Call);
   State = ensureStreamNonNull(StreamVal, Call.getArgExpr(Desc->StreamArgNo), C,
@@ -845,11 +873,6 @@ void StreamChecker::preReadWrite(const FnDescription *Desc,
   if (!State)
     return;
 
-  if (!IsRead) {
-    C.addTransition(State);
-    return;
-  }
-
   SymbolRef Sym = StreamVal.getAsSymbol();
   if (Sym && State->get(Sym)) {
     const StreamState *SS = State->get(Sym);
@@ -860,6 +883,24 @@ void StreamChecker::preReadWrite(const FnDescription *Desc,
   }
 }
 
+void StreamChecker::preWrite(const FnDescription *Desc, const CallEvent &Call,
+                             CheckerContext &C) const {
+  ProgramStateRef State = C.getState();
+  SVal StreamVal = getStreamArg(Desc, Call);
+  State = ensureStreamNonNull(StreamVal, Call.getArgExpr(Desc->StreamArgNo), C,
+                              State);
+  if (!State)
+    return;
+  State = ensureStreamOpened(StreamVal, C, State);
+  if (!State)
+    return;
+  State = ensureNoFilePositionIndeterminate(StreamVal, C, State);
+  if (!State)
+    return;
+
+  C.addTransition(State);
+}
+
 void StreamChecker::evalFreadFwrite(const FnDescription *Desc,
                                     const CallEvent &Call, CheckerContext &C,
                                     bool IsFread) const {
@@ -1085,10 +1126,13 @@ void StreamChecker::evalFscanf(const FnDescription *Desc, const CallEvent &Call,
     if (!StateNotFailed)
       return;
 
-    SmallVector EscArgs;
-    for (auto EscArg : llvm::seq(2u, Call.getNumArgs()))
-      EscArgs.push_back(EscArg);
-    StateNotFailed = escapeArgs(StateNotFailed, C, Call, EscArgs);
+    if (auto const *Callee = Call.getCalleeIdentifier();
+        !Callee || !Callee->getName().equals("vfscanf")) {
+      SmallVector EscArgs;
+      for (auto EscArg : llvm::seq(2u, Call.getNumArgs()))
+        EscArgs.push_back(EscArg);
+      StateNotFailed = escapeArgs(StateNotFailed, C, Call, EscArgs);
+    }
 
     if (StateNotFailed)
       C.addTransition(StateNotFailed);
@@ -1473,14 +1517,16 @@ void StreamChecker::preDefault(const FnDescription *Desc, const CallEvent &Call,
 
 void StreamChecker::evalSetFeofFerror(const FnDescription *Desc,
                                       const CallEvent &Call, CheckerContext &C,
-                                      const StreamErrorState &ErrorKind) const {
+                                      const StreamErrorState &ErrorKind,
+                                      bool Indeterminate) const {
   ProgramStateRef State = C.getState();
   SymbolRef StreamSym = getStreamArg(Desc, Call).getAsSymbol();
   assert(StreamSym && "Operation not permitted on non-symbolic stream value.");
   const StreamState *SS = State->get(StreamSym);
   assert(SS && "Stream should be tracked by the checker.");
   State = State->set(
-      StreamSym, StreamState::getOpened(SS->LastOperation, ErrorKind));
+      StreamSym,
+      StreamState::getOpened(SS->LastOperation, ErrorKind, Indeterminate));
   C.addTransition(State);
 }
 
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 01b191ab0eeaf4558bc7c1fdc0f5c638781d89d8..287f6a52870056e63d099ae910c8ce9ee7cebe38 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -253,6 +253,19 @@ class TrivialFunctionAnalysisVisitor
     return true;
   }
 
+  template 
+  bool WithCachedResult(const Stmt *S, CheckFunction Function) {
+    // If the statement isn't in the cache, conservatively assume that
+    // it's not trivial until analysis completes. Insert false to the cache
+    // first to avoid infinite recursion.
+    auto [It, IsNew] = Cache.insert(std::make_pair(S, false));
+    if (!IsNew)
+      return It->second;
+    bool Result = Function();
+    Cache[S] = Result;
+    return Result;
+  }
+
 public:
   using CacheTy = TrivialFunctionAnalysis::CacheTy;
 
@@ -267,7 +280,7 @@ public:
   bool VisitCompoundStmt(const CompoundStmt *CS) {
     // A compound statement is allowed as long each individual sub-statement
     // is trivial.
-    return VisitChildren(CS);
+    return WithCachedResult(CS, [&]() { return VisitChildren(CS); });
   }
 
   bool VisitReturnStmt(const ReturnStmt *RS) {
@@ -279,17 +292,36 @@ public:
 
   bool VisitDeclStmt(const DeclStmt *DS) { return VisitChildren(DS); }
   bool VisitDoStmt(const DoStmt *DS) { return VisitChildren(DS); }
-  bool VisitIfStmt(const IfStmt *IS) { return VisitChildren(IS); }
+  bool VisitIfStmt(const IfStmt *IS) {
+    return WithCachedResult(IS, [&]() { return VisitChildren(IS); });
+  }
+  bool VisitForStmt(const ForStmt *FS) {
+    return WithCachedResult(FS, [&]() { return VisitChildren(FS); });
+  }
+  bool VisitCXXForRangeStmt(const CXXForRangeStmt *FS) {
+    return WithCachedResult(FS, [&]() { return VisitChildren(FS); });
+  }
+  bool VisitWhileStmt(const WhileStmt *WS) {
+    return WithCachedResult(WS, [&]() { return VisitChildren(WS); });
+  }
   bool VisitSwitchStmt(const SwitchStmt *SS) { return VisitChildren(SS); }
   bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
   bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
 
   bool VisitUnaryOperator(const UnaryOperator *UO) {
     // Operator '*' and '!' are allowed as long as the operand is trivial.
-    if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_AddrOf ||
-        UO->getOpcode() == UO_LNot)
+    auto op = UO->getOpcode();
+    if (op == UO_Deref || op == UO_AddrOf || op == UO_LNot)
       return Visit(UO->getSubExpr());
 
+    if (UO->isIncrementOp() || UO->isDecrementOp()) {
+      // Allow increment or decrement of a POD type.
+      if (auto *RefExpr = dyn_cast(UO->getSubExpr())) {
+        if (auto *Decl = dyn_cast(RefExpr->getDecl()))
+          return Decl->isLocalVarDeclOrParm() &&
+                 Decl->getType().isPODType(Decl->getASTContext());
+      }
+    }
     // Other operators are non-trivial.
     return false;
   }
@@ -304,22 +336,6 @@ public:
     return VisitChildren(CO);
   }
 
-  bool VisitDeclRefExpr(const DeclRefExpr *DRE) {
-    if (auto *decl = DRE->getDecl()) {
-      if (isa(decl))
-        return true;
-      if (isa(decl))
-        return true;
-      if (auto *VD = dyn_cast(decl)) {
-        if (VD->hasConstantInitialization() && VD->getEvaluatedValue())
-          return true;
-        auto *Init = VD->getInit();
-        return !Init || Visit(Init);
-      }
-    }
-    return false;
-  }
-
   bool VisitAtomicExpr(const AtomicExpr *E) { return VisitChildren(E); }
 
   bool VisitStaticAssertDecl(const StaticAssertDecl *SAD) {
@@ -436,6 +452,11 @@ public:
     return true;
   }
 
+  bool VisitDeclRefExpr(const DeclRefExpr *DRE) {
+    // The use of a variable is trivial.
+    return true;
+  }
+
   // Constant literal expressions are always trivial
   bool VisitIntegerLiteral(const IntegerLiteral *E) { return true; }
   bool VisitFloatingLiteral(const FloatingLiteral *E) { return true; }
@@ -449,7 +470,7 @@ public:
   }
 
 private:
-  CacheTy Cache;
+  CacheTy &Cache;
 };
 
 bool TrivialFunctionAnalysis::isTrivialImpl(
@@ -474,4 +495,17 @@ bool TrivialFunctionAnalysis::isTrivialImpl(
   return Result;
 }
 
+bool TrivialFunctionAnalysis::isTrivialImpl(
+    const Stmt *S, TrivialFunctionAnalysis::CacheTy &Cache) {
+  // If the statement isn't in the cache, conservatively assume that
+  // it's not trivial until analysis completes. Unlike a function case,
+  // we don't insert an entry into the cache until Visit returns
+  // since Visit* functions themselves make use of the cache.
+
+  TrivialFunctionAnalysisVisitor V(Cache);
+  bool Result = V.Visit(S);
+  assert(Cache.contains(S) && "Top-level statement not properly cached!");
+  return Result;
+}
+
 } // namespace clang
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
index e07cd31395747dca71250155e487083d1a459860..9ed8e7cab6abb9ed1484829899d926e7bb134239 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
@@ -11,6 +11,7 @@
 
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
 #include 
 
 namespace clang {
@@ -19,6 +20,7 @@ class CXXMethodDecl;
 class CXXRecordDecl;
 class Decl;
 class FunctionDecl;
+class Stmt;
 class Type;
 
 // Ref-countability of a type is implicitly defined by Ref and RefPtr
@@ -71,14 +73,17 @@ class TrivialFunctionAnalysis {
 public:
   /// \returns true if \p D is a "trivial" function.
   bool isTrivial(const Decl *D) const { return isTrivialImpl(D, TheCache); }
+  bool isTrivial(const Stmt *S) const { return isTrivialImpl(S, TheCache); }
 
 private:
   friend class TrivialFunctionAnalysisVisitor;
 
-  using CacheTy = llvm::DenseMap;
+  using CacheTy =
+      llvm::DenseMap, bool>;
   mutable CacheTy TheCache{};
 
   static bool isTrivialImpl(const Decl *D, CacheTy &Cache);
+  static bool isTrivialImpl(const Stmt *S, CacheTy &Cache);
 };
 
 } // namespace clang
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp
index 5a72f53b12edaafe6f5db142ab3e2b2164beb03d..6036ad58cf253cbad374824c48024e1c2bcafdc1 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLocalVarsChecker.cpp
@@ -26,28 +26,6 @@ using namespace ento;
 
 namespace {
 
-// for ( int a = ...) ... true
-// for ( int a : ...) ... true
-// if ( int* a = ) ... true
-// anything else ... false
-bool isDeclaredInForOrIf(const VarDecl *Var) {
-  assert(Var);
-  auto &ASTCtx = Var->getASTContext();
-  auto parent = ASTCtx.getParents(*Var);
-
-  if (parent.size() == 1) {
-    if (auto *DS = parent.begin()->get()) {
-      DynTypedNodeList grandParent = ASTCtx.getParents(*DS);
-      if (grandParent.size() == 1) {
-        return grandParent.begin()->get() ||
-               grandParent.begin()->get() ||
-               grandParent.begin()->get();
-      }
-    }
-  }
-  return false;
-}
-
 // FIXME: should be defined by anotations in the future
 bool isRefcountedStringsHack(const VarDecl *V) {
   assert(V);
@@ -143,6 +121,11 @@ public:
     // want to visit those, so we make our own RecursiveASTVisitor.
     struct LocalVisitor : public RecursiveASTVisitor {
       const UncountedLocalVarsChecker *Checker;
+
+      TrivialFunctionAnalysis TFA;
+
+      using Base = RecursiveASTVisitor;
+
       explicit LocalVisitor(const UncountedLocalVarsChecker *Checker)
           : Checker(Checker) {
         assert(Checker);
@@ -155,6 +138,36 @@ public:
         Checker->visitVarDecl(V);
         return true;
       }
+
+      bool TraverseIfStmt(IfStmt *IS) {
+        if (!TFA.isTrivial(IS))
+          return Base::TraverseIfStmt(IS);
+        return true;
+      }
+
+      bool TraverseForStmt(ForStmt *FS) {
+        if (!TFA.isTrivial(FS))
+          return Base::TraverseForStmt(FS);
+        return true;
+      }
+
+      bool TraverseCXXForRangeStmt(CXXForRangeStmt *FRS) {
+        if (!TFA.isTrivial(FRS))
+          return Base::TraverseCXXForRangeStmt(FRS);
+        return true;
+      }
+
+      bool TraverseWhileStmt(WhileStmt *WS) {
+        if (!TFA.isTrivial(WS))
+          return Base::TraverseWhileStmt(WS);
+        return true;
+      }
+
+      bool TraverseCompoundStmt(CompoundStmt *CS) {
+        if (!TFA.isTrivial(CS))
+          return Base::TraverseCompoundStmt(CS);
+        return true;
+      }
     };
 
     LocalVisitor visitor(this);
@@ -189,18 +202,16 @@ public:
                 dyn_cast_or_null(Ref->getFoundDecl())) {
           const auto *MaybeGuardianArgType =
               MaybeGuardian->getType().getTypePtr();
-          if (!MaybeGuardianArgType)
-            return;
-          const CXXRecordDecl *const MaybeGuardianArgCXXRecord =
-              MaybeGuardianArgType->getAsCXXRecordDecl();
-          if (!MaybeGuardianArgCXXRecord)
-            return;
-
-          if (MaybeGuardian->isLocalVarDecl() &&
-              (isRefCounted(MaybeGuardianArgCXXRecord) ||
-               isRefcountedStringsHack(MaybeGuardian)) &&
-              isGuardedScopeEmbeddedInGuardianScope(V, MaybeGuardian)) {
-            return;
+          if (MaybeGuardianArgType) {
+            const CXXRecordDecl *const MaybeGuardianArgCXXRecord =
+                MaybeGuardianArgType->getAsCXXRecordDecl();
+            if (MaybeGuardianArgCXXRecord) {
+              if (MaybeGuardian->isLocalVarDecl() &&
+                  (isRefCounted(MaybeGuardianArgCXXRecord) ||
+                   isRefcountedStringsHack(MaybeGuardian)) &&
+                  isGuardedScopeEmbeddedInGuardianScope(V, MaybeGuardian))
+                return;
+            }
           }
 
           // Parameters are guaranteed to be safe for the duration of the call
@@ -219,9 +230,6 @@ public:
     if (!V->isLocalVarDecl())
       return true;
 
-    if (isDeclaredInForOrIf(V))
-      return true;
-
     return false;
   }
 
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 2f9965036b9ef91fe9181c50fad3c88269f5e739..a0822513a6d02ea0e5e295c260235bf30dd2ba84 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -2883,6 +2883,16 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond, BugReporterContext &BRC,
   // previous program state we assuming the newly seen constraint information.
   // If we cannot evaluate the condition (and the constraints are the same)
   // the analyzer has no information about the value and just assuming it.
+  // FIXME: This logic is not entirely correct, because e.g. in code like
+  //   void f(unsigned arg) {
+  //     if (arg >= 0) {
+  //       // ...
+  //     }
+  //   }
+  // it will say that the "arg >= 0" check is _assuming_ something new because
+  // the constraint that "$arg >= 0" is 1 was added to the list of known
+  // constraints. However, the unsigned value is always >= 0 so semantically
+  // this is not a "real" assumption.
   bool IsAssuming =
       !BRC.getStateManager().haveEqualConstraints(CurrentState, PrevState) ||
       CurrentState->getSVal(Cond, LCtx).isUnknownOrUndef();
diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 0ac1d91b79beb5ac2d00838a45b2097f15b8fe32..bc14aea27f6736e8e0c9b3a4344fdaff65d83fb5 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -1409,7 +1409,7 @@ CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State,
   if (const auto *OpCE = dyn_cast(CE)) {
     const FunctionDecl *DirectCallee = OpCE->getDirectCallee();
     if (const auto *MD = dyn_cast(DirectCallee))
-      if (MD->isInstance())
+      if (MD->isImplicitObjectMemberFunction())
         return create(OpCE, State, LCtx, ElemRef);
 
   } else if (CE->getCallee()->getType()->isBlockPointerType()) {
diff --git a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
index d6d4cec9dd3d4d01dd5ab2ffb9fbbeab337e4ddb..1a9bff529e9bb124eff2747629b93e52c0535c75 100644
--- a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp
@@ -87,9 +87,11 @@ bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD,
   if (!II)
     return false;
 
-  // Look through 'extern "C"' and anything similar invented in the future.
-  // If this function is not in TU directly, it is not a C library function.
-  if (!FD->getDeclContext()->getRedeclContext()->isTranslationUnit())
+  // C library functions are either declared directly within a TU (the common
+  // case) or they are accessed through the namespace `std` (when they are used
+  // in C++ via headers like ).
+  const DeclContext *DC = FD->getDeclContext()->getRedeclContext();
+  if (!(DC->isTranslationUnit() || DC->isStdNamespace()))
     return false;
 
   // If this function is not externally visible, it is not a C library function.
diff --git a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
index 84ad20a548079290a68a9b43809a4428e7c20640..364c87e910b7b51a28c68705dbe8faadc6197cd1 100644
--- a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp
@@ -14,6 +14,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
 #include "clang/Lex/Preprocessor.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
 #include 
 
 namespace clang {
@@ -182,5 +183,13 @@ OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK,
   }
 }
 
+std::optional getPointeeDefVal(SVal PtrSVal,
+                                            ProgramStateRef State) {
+  if (const auto *Ptr = PtrSVal.getAsRegion()) {
+    return State->getSVal(Ptr).getAs();
+  }
+  return std::nullopt;
+}
+
 } // namespace ento
 } // namespace clang
diff --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
index d3499e7a917d34d6907f0a98db3bb688fccb1264..141d0cb320bffab360efd622b44ceb9229a94013 100644
--- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -222,18 +222,6 @@ void CoreEngine::dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
   }
 }
 
-bool CoreEngine::ExecuteWorkListWithInitialState(const LocationContext *L,
-                                                 unsigned Steps,
-                                                 ProgramStateRef InitState,
-                                                 ExplodedNodeSet &Dst) {
-  bool DidNotFinish = ExecuteWorkList(L, Steps, InitState);
-  for (ExplodedGraph::eop_iterator I = G.eop_begin(), E = G.eop_end(); I != E;
-       ++I) {
-    Dst.Add(*I);
-  }
-  return DidNotFinish;
-}
-
 void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
   const CFGBlock *Blk = L.getDst();
   NodeBuilderContext BuilderCtx(*this, Blk, Pred);
diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 2d8498e360155664d50a5f3df2ad0bf1d39423f5..c6f87b45ab887a8c1a3d3eee43ad3721ed533a8d 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -3038,7 +3038,7 @@ ProgramStateRef RangeConstraintManager::setRange(ProgramStateRef State,
 
 //===------------------------------------------------------------------------===
 // assumeSymX methods: protected interface for RangeConstraintManager.
-//===------------------------------------------------------------------------===/
+//===------------------------------------------------------------------------===
 
 // The syntax for ranges below is mathematical, using [x, y] for closed ranges
 // and (x, y) for open ranges. These ranges are modular, corresponding with
diff --git a/clang/lib/Testing/CommandLineArgs.cpp b/clang/lib/Testing/CommandLineArgs.cpp
index 0da087c33e3f4ea6c950233ddf03bd18adfaa9bc..3abc689b93e8d05b5b061e1cae61d11dec3ce94f 100644
--- a/clang/lib/Testing/CommandLineArgs.cpp
+++ b/clang/lib/Testing/CommandLineArgs.cpp
@@ -37,6 +37,9 @@ std::vector getCommandLineArgsForTesting(TestLanguage Lang) {
   case Lang_CXX20:
     Args = {"-std=c++20", "-frtti"};
     break;
+  case Lang_CXX23:
+    Args = {"-std=c++23", "-frtti"};
+    break;
   case Lang_OBJC:
     Args = {"-x", "objective-c", "-frtti", "-fobjc-nonfragile-abi"};
     break;
@@ -73,6 +76,9 @@ std::vector getCC1ArgsForTesting(TestLanguage Lang) {
   case Lang_CXX20:
     Args = {"-std=c++20"};
     break;
+  case Lang_CXX23:
+    Args = {"-std=c++23"};
+    break;
   case Lang_OBJC:
     Args = {"-xobjective-c"};
     break;
@@ -96,6 +102,7 @@ StringRef getFilenameForTesting(TestLanguage Lang) {
   case Lang_CXX14:
   case Lang_CXX17:
   case Lang_CXX20:
+  case Lang_CXX23:
     return "input.cc";
 
   case Lang_OpenCL:
diff --git a/clang/lib/Tooling/AllTUsExecution.cpp b/clang/lib/Tooling/AllTUsExecution.cpp
index f327d013994141d2db4bb1ec87f4c8c7077c1f45..9cad8680447be9c1546196b5322e9d7fea04a7fa 100644
--- a/clang/lib/Tooling/AllTUsExecution.cpp
+++ b/clang/lib/Tooling/AllTUsExecution.cpp
@@ -115,7 +115,7 @@ llvm::Error AllTUsToolExecutor::execute(
   auto &Action = Actions.front();
 
   {
-    llvm::ThreadPool Pool(llvm::hardware_concurrency(ThreadCount));
+    llvm::DefaultThreadPool Pool(llvm::hardware_concurrency(ThreadCount));
     for (std::string File : Files) {
       Pool.async(
           [&](std::string Path) {
diff --git a/clang/lib/Tooling/Refactoring/AtomicChange.cpp b/clang/lib/Tooling/Refactoring/AtomicChange.cpp
index 3d5ae2fed014c441aeba7271c9f15967089d2009..dfc98355c6642b3b03a07bade20e14f2377d712e 100644
--- a/clang/lib/Tooling/Refactoring/AtomicChange.cpp
+++ b/clang/lib/Tooling/Refactoring/AtomicChange.cpp
@@ -1,4 +1,4 @@
-//===--- AtomicChange.cpp - AtomicChange implementation -----------------*- C++ -*-===//
+//===--- AtomicChange.cpp - AtomicChange implementation ---------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp
index ab8abac4b36e34f684994a6b1d4471f0f9bc5a1c..08fca8428cf5e8ed1406ddbdbde5f7a113924efe 100644
--- a/clang/test/AST/Interp/builtin-functions.cpp
+++ b/clang/test/AST/Interp/builtin-functions.cpp
@@ -268,6 +268,24 @@ namespace popcount {
   static_assert(__builtin_popcountl(0) == 0, "");
   static_assert(__builtin_popcountll(~0ull) == __CHAR_BIT__ * sizeof(unsigned long long), "");
   static_assert(__builtin_popcountll(0) == 0, "");
+  static_assert(__builtin_popcountg((unsigned char)~0) == __CHAR_BIT__ * sizeof(unsigned char), "");
+  static_assert(__builtin_popcountg((unsigned char)0) == 0, "");
+  static_assert(__builtin_popcountg((unsigned short)~0) == __CHAR_BIT__ * sizeof(unsigned short), "");
+  static_assert(__builtin_popcountg((unsigned short)0) == 0, "");
+  static_assert(__builtin_popcountg(~0u) == __CHAR_BIT__ * sizeof(unsigned int), "");
+  static_assert(__builtin_popcountg(0u) == 0, "");
+  static_assert(__builtin_popcountg(~0ul) == __CHAR_BIT__ * sizeof(unsigned long), "");
+  static_assert(__builtin_popcountg(0ul) == 0, "");
+  static_assert(__builtin_popcountg(~0ull) == __CHAR_BIT__ * sizeof(unsigned long long), "");
+  static_assert(__builtin_popcountg(0ull) == 0, "");
+#ifdef __SIZEOF_INT128__
+  static_assert(__builtin_popcountg(~(unsigned __int128)0) == __CHAR_BIT__ * sizeof(unsigned __int128), "");
+  static_assert(__builtin_popcountg((unsigned __int128)0) == 0, "");
+#endif
+#ifndef __AVR__
+  static_assert(__builtin_popcountg(~(unsigned _BitInt(128))0) == __CHAR_BIT__ * sizeof(unsigned _BitInt(128)), "");
+  static_assert(__builtin_popcountg((unsigned _BitInt(128))0) == 0, "");
+#endif
 
   /// From test/Sema/constant-builtins-2.c
   char popcount1[__builtin_popcount(0) == 0 ? 1 : -1];
@@ -280,6 +298,17 @@ namespace popcount {
   char popcount8[__builtin_popcountll(0LL) == 0 ? 1 : -1];
   char popcount9[__builtin_popcountll(0xF0F0LL) == 8 ? 1 : -1];
   char popcount10[__builtin_popcountll(~0LL) == BITSIZE(long long) ? 1 : -1];
+  char popcount11[__builtin_popcountg(0U) == 0 ? 1 : -1];
+  char popcount12[__builtin_popcountg(0xF0F0U) == 8 ? 1 : -1];
+  char popcount13[__builtin_popcountg(~0U) == BITSIZE(int) ? 1 : -1];
+  char popcount14[__builtin_popcountg(~0UL) == BITSIZE(long) ? 1 : -1];
+  char popcount15[__builtin_popcountg(~0ULL) == BITSIZE(long long) ? 1 : -1];
+#ifdef __SIZEOF_INT128__
+  char popcount16[__builtin_popcountg(~(unsigned __int128)0) == BITSIZE(__int128) ? 1 : -1];
+#endif
+#ifndef __AVR__
+  char popcount17[__builtin_popcountg(~(unsigned _BitInt(128))0) == BITSIZE(_BitInt(128)) ? 1 : -1];
+#endif
 }
 
 namespace parity {
diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c
index 260e5bdfeefb2b5598fc54c7432e3dc6433a9ee0..8de6139efbea09c620cc32fc44368129e96a7d84 100644
--- a/clang/test/AST/Interp/c.c
+++ b/clang/test/AST/Interp/c.c
@@ -79,6 +79,11 @@ int a2[(intptr_t)&((struct y*)0)->y]; // all-warning {{folded to constant array}
 const struct y *yy = (struct y*)0;
 const intptr_t L = (intptr_t)(&(yy->y)); // all-error {{not a compile-time constant}}
 
+_Static_assert((long)&((struct y*)0)->y > 0, ""); // pedantic-ref-warning {{GNU extension}} \
+                                                  // pedantic-ref-note {{this conversion is not allowed in a constant expression}} \
+                                                  // pedantic-expected-warning {{GNU extension}} \
+                                                  // pedantic-expected-note {{this conversion is not allowed in a constant expression}}
+
 const ptrdiff_t m = &m + 137 - &m;
 _Static_assert(m == 137, ""); // pedantic-ref-warning {{GNU extension}} \
                               // pedantic-expected-warning {{GNU extension}}
@@ -95,7 +100,7 @@ int chooseexpr[__builtin_choose_expr(1, 1, expr)];
 
 int somefunc(int i) {
   return (i, 65537) * 65537; // all-warning {{left operand of comma operator has no effect}} \
-                             // all-warning {{overflow in expression; result is 131073}}
+                             // all-warning {{overflow in expression; result is 131'073 with type 'int'}}
 }
 
 /// FIXME: The following test is incorrect in the new interpreter.
diff --git a/clang/test/AST/Interp/complex.c b/clang/test/AST/Interp/complex.c
index b07d0241da12d60c62172ae984b32b2dc730bf99..b5f30b87baa79a513cd2e75603ff566d8b0db71f 100644
--- a/clang/test/AST/Interp/complex.c
+++ b/clang/test/AST/Interp/complex.c
@@ -1,9 +1,6 @@
 // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both -Wno-unused-value %s
 // RUN: %clang_cc1 -verify=ref,both -Wno-unused-value %s
 
-// expected-no-diagnostics
-// ref-no-diagnostics
-
 void blah() {
   __complex__ unsigned xx;
   __complex__ signed yy;
@@ -12,3 +9,13 @@ void blah() {
   /// The following line calls into the constant interpreter.
   result = xx * yy;
 }
+
+
+_Static_assert((0.0 + 0.0j) == (0.0 + 0.0j), "");
+_Static_assert((0.0 + 0.0j) != (0.0 + 0.0j), ""); // both-error {{static assertion}} \
+                                                  // both-note {{evaluates to}}
+
+const _Complex float FC = {0.0f, 0.0f};
+_Static_assert(!FC, "");
+const _Complex float FI = {0, 0};
+_Static_assert(!FI, "");
diff --git a/clang/test/AST/Interp/complex.cpp b/clang/test/AST/Interp/complex.cpp
index b6091d90867a0149e0e5ccd7fa6bd366d9816f9d..6a42afc68d26c78b1c016a0430839c8a763af5ac 100644
--- a/clang/test/AST/Interp/complex.cpp
+++ b/clang/test/AST/Interp/complex.cpp
@@ -1,8 +1,5 @@
-// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify -Wno-unused-value %s
-// RUN: %clang_cc1 -verify=ref -Wno-unused-value %s
-
-// expected-no-diagnostics
-// ref-no-diagnostics
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=both,expected -Wno-unused-value %s
+// RUN: %clang_cc1 -verify=both,ref -Wno-unused-value %s
 
 constexpr _Complex double z1 = {1.0, 2.0};
 static_assert(__real(z1) == 1.0, "");
@@ -256,3 +253,63 @@ namespace DeclRefCopy {
   }
   static_assert(localComplexArray() == (24 + 42), "");
 }
+
+namespace Builtin {
+  constexpr _Complex float A = __builtin_complex(10.0f, 20.0f);
+  static_assert(__real(A) == 10, "");
+  static_assert(__imag(A) == 20, "");
+
+  constexpr _Complex double B = __builtin_complex(10.0, 20.0);
+  static_assert(__real(B) == 10, "");
+  static_assert(__imag(B) == 20, "");
+
+
+  constexpr _Complex float C = __builtin_complex(10.0f, 20.0); // both-error {{arguments are of different types}}
+}
+
+namespace Cmp {
+  static_assert((0.0 + 0.0j) == (0.0 + 0.0j));
+  static_assert((0.0 + 0.0j) != (0.0 + 0.0j)); // both-error {{static assertion}} \
+                                               // both-note {{evaluates to}}
+
+  static_assert((0.0 + 0.0j) == 0.0);
+  static_assert(0.0 == (0.0 + 0.0j));
+  static_assert(0.0 == 0.0j);
+  static_assert((0.0 + 1.0j) != 0.0);
+  static_assert(1.0 != (0.0 + 0.0j));
+  static_assert(0.0 != 1.0j);
+
+  // Walk around the complex plane stepping between angular differences and
+  // equality.
+  static_assert((1.0 + 0.0j) == (0.0 + 0.0j)); // both-error {{static assertion}} \
+                                               // both-note {{evaluates to}}
+  static_assert((1.0 + 0.0j) == (1.0 + 0.0j));
+  static_assert((1.0 + 1.0j) == (1.0 + 0.0j)); // both-error {{static assertion}} \
+                                               // both-note {{evaluates to}}
+  static_assert((1.0 + 1.0j) == (1.0 + 1.0j));
+  static_assert((0.0 + 1.0j) == (1.0 + 1.0j)); // both-error {{static assertion}} \
+                                               // both-note {{evaluates to}}
+  static_assert((0.0 + 1.0j) == (0.0 + 1.0j));
+  static_assert((-1.0 + 1.0j) == (0.0 + 1.0j)); // both-error {{static assertion}} \
+                                                // both-note {{evaluates to}}
+  static_assert((-1.0 + 1.0j) == (-1.0 + 1.0j));
+  static_assert((-1.0 + 0.0j) == (-1.0 + 1.0j)); // both-error {{static assertion}} \
+                                                 // both-note {{evaluates to}}
+  static_assert((-1.0 + 0.0j) == (-1.0 + 0.0j));
+  static_assert((-1.0 - 1.0j) == (-1.0 + 0.0j)); // both-error {{static assertion}} \
+                                                 // both-note {{evaluates to}}
+  static_assert((-1.0 - 1.0j) == (-1.0 - 1.0j));
+  static_assert((0.0 - 1.0j) == (-1.0 - 1.0j)); // both-error {{static assertion}} \
+                                                // both-note {{evaluates to}}
+  static_assert((0.0 - 1.0j) == (0.0 - 1.0j));
+  static_assert((1.0 - 1.0j) == (0.0 - 1.0j)); // both-error {{static assertion}} \
+                                               // both-note {{evaluates to}}
+  static_assert((1.0 - 1.0j) == (1.0 - 1.0j));
+
+  /// Make sure these are rejected before reaching the constexpr interpreter.
+  static_assert((0.0 + 0.0j) & (0.0 + 0.0j)); // both-error {{invalid operands to binary expression}}
+  static_assert((0.0 + 0.0j) | (0.0 + 0.0j)); // both-error {{invalid operands to binary expression}}
+  static_assert((0.0 + 0.0j) < (0.0 + 0.0j)); // both-error {{invalid operands to binary expression}}
+  static_assert((0.0 + 0.0j) > (0.0 + 0.0j)); // both-error {{invalid operands to binary expression}}
+  static_assert((0.0 + 0.0j) ^ (0.0 + 0.0j)); // both-error {{invalid operands to binary expression}}
+}
diff --git a/clang/test/AST/Interp/cxx23.cpp b/clang/test/AST/Interp/cxx23.cpp
index f1df936a5abe74d8ba2a5e63911df1deefb5f355..127b58915127cf2d07307052e4056600f7593eb6 100644
--- a/clang/test/AST/Interp/cxx23.cpp
+++ b/clang/test/AST/Interp/cxx23.cpp
@@ -1,82 +1,58 @@
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref20,all %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref20,all,all-20 %s
 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=ref23,all %s
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20,all %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20,all,all-20 %s -fexperimental-new-constant-interpreter
 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=expected23,all %s -fexperimental-new-constant-interpreter
 
 /// FIXME: The new interpreter is missing all the 'control flows through...' diagnostics.
 
 constexpr int f(int n) {  // ref20-error {{constexpr function never produces a constant expression}} \
-                          // ref23-error {{constexpr function never produces a constant expression}} \
-                          // expected20-error {{constexpr function never produces a constant expression}} \
-                          // expected23-error {{constexpr function never produces a constant expression}}
+                          // expected20-error {{constexpr function never produces a constant expression}}
   static const int m = n; // ref20-note {{control flows through the definition of a static variable}} \
                           // ref20-warning {{is a C++23 extension}} \
-                          // ref23-note {{control flows through the definition of a static variable}} \
                           // expected20-warning {{is a C++23 extension}} \
                           // expected20-note {{declared here}} \
-                          // expected23-note {{declared here}}
 
-  return m; // expected20-note {{initializer of 'm' is not a constant expression}} \
-            // expected23-note {{initializer of 'm' is not a constant expression}}
+  return m; // expected20-note {{initializer of 'm' is not a constant expression}}
 }
 constexpr int g(int n) {        // ref20-error {{constexpr function never produces a constant expression}} \
-                                // ref23-error {{constexpr function never produces a constant expression}} \
-                                // expected20-error {{constexpr function never produces a constant expression}} \
-                                // expected23-error {{constexpr function never produces a constant expression}}
+                                // expected20-error {{constexpr function never produces a constant expression}}
   thread_local const int m = n; // ref20-note {{control flows through the definition of a thread_local variable}} \
                                 // ref20-warning {{is a C++23 extension}} \
-                                // ref23-note {{control flows through the definition of a thread_local variable}} \
                                 // expected20-warning {{is a C++23 extension}} \
-                                // expected20-note {{declared here}} \
-                                // expected23-note {{declared here}}
-  return m; // expected20-note {{initializer of 'm' is not a constant expression}} \
-            // expected23-note {{initializer of 'm' is not a constant expression}}
+                                // expected20-note {{declared here}}
+  return m; // expected20-note {{initializer of 'm' is not a constant expression}}
 
 }
 
 constexpr int c_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
-                                      // ref23-error {{constexpr function never produces a constant expression}} \
-                                      // expected20-error {{constexpr function never produces a constant expression}} \
-                                      // expected23-error {{constexpr function never produces a constant expression}}
+                                      // expected20-error {{constexpr function never produces a constant expression}}
   static _Thread_local int m = 0;     // ref20-note {{control flows through the definition of a thread_local variable}} \
                                       // ref20-warning {{is a C++23 extension}} \
-                                      // ref23-note {{control flows through the definition of a thread_local variable}} \
                                       // expected20-warning {{is a C++23 extension}} \
-                                      // expected20-note {{declared here}} \
-                                      // expected23-note {{declared here}}
-  return m; // expected20-note {{read of non-const variable}} \
-            // expected23-note {{read of non-const variable}}
+                                      // expected20-note {{declared here}}
+  return m; // expected20-note {{read of non-const variable}}
 }
 
 
 constexpr int gnu_thread_local(int n) { // ref20-error {{constexpr function never produces a constant expression}} \
-                                        // ref23-error {{constexpr function never produces a constant expression}} \
-                                        // expected20-error {{constexpr function never produces a constant expression}} \
-                                        // expected23-error {{constexpr function never produces a constant expression}}
+                                        // expected20-error {{constexpr function never produces a constant expression}}
   static __thread int m = 0;            // ref20-note {{control flows through the definition of a thread_local variable}} \
                                         // ref20-warning {{is a C++23 extension}} \
-                                        // ref23-note {{control flows through the definition of a thread_local variable}} \
                                         // expected20-warning {{is a C++23 extension}} \
-                                        // expected20-note {{declared here}} \
-                                        // expected23-note {{declared here}}
-  return m; // expected20-note {{read of non-const variable}} \
-            // expected23-note {{read of non-const variable}}
+                                        // expected20-note {{declared here}}
+  return m; // expected20-note {{read of non-const variable}}
 }
 
-constexpr int h(int n) {  // ref20-error {{constexpr function never produces a constant expression}} \
-                          // ref23-error {{constexpr function never produces a constant expression}}
+constexpr int h(int n) {  // ref20-error {{constexpr function never produces a constant expression}}
   static const int m = n; // ref20-note {{control flows through the definition of a static variable}} \
                           // ref20-warning {{is a C++23 extension}} \
-                          // ref23-note {{control flows through the definition of a static variable}} \
                           // expected20-warning {{is a C++23 extension}}
   return &m - &m;
 }
 
-constexpr int i(int n) {        // ref20-error {{constexpr function never produces a constant expression}} \
-                                // ref23-error {{constexpr function never produces a constant expression}}
+constexpr int i(int n) {        // ref20-error {{constexpr function never produces a constant expression}}
   thread_local const int m = n; // ref20-note {{control flows through the definition of a thread_local variable}} \
                                 // ref20-warning {{is a C++23 extension}} \
-                                // ref23-note {{control flows through the definition of a thread_local variable}} \
                                 // expected20-warning {{is a C++23 extension}}
   return &m - &m;
 }
@@ -132,8 +108,9 @@ namespace StaticOperators {
   static_assert(f2() == 3);
 
   struct S1 {
-    constexpr S1() { // all-error {{never produces a constant expression}}
-      throw; // all-note 2{{not valid in a constant expression}}
+    constexpr S1() { // all-20-error {{never produces a constant expression}}
+      throw; // all-note {{not valid in a constant expression}} \
+             // all-20-note {{not valid in a constant expression}}
     }
     static constexpr int operator()() { return 3; } // ref20-warning {{C++23 extension}} \
                                                     // expected20-warning {{C++23 extension}}
diff --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/Interp/functions.cpp
index 38f761f563bef7bce3c1f853ff0447e1e944d519..67fd9036d81e768e316bb913870aaeb883b8dacc 100644
--- a/clang/test/AST/Interp/functions.cpp
+++ b/clang/test/AST/Interp/functions.cpp
@@ -565,3 +565,13 @@ namespace VariadicOperator {
     float &fr = c(10);
   }
 }
+
+namespace WeakCompare {
+  [[gnu::weak]]void weak_method();
+  static_assert(weak_method != nullptr, ""); // both-error {{not an integral constant expression}} \
+                                         // both-note {{comparison against address of weak declaration '&weak_method' can only be performed at runtim}}
+
+  constexpr auto A = &weak_method;
+  static_assert(A != nullptr, ""); // both-error {{not an integral constant expression}} \
+                               // both-note {{comparison against address of weak declaration '&weak_method' can only be performed at runtim}}
+}
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index d86609108ca44644e81e73bbb41b235626665c9c..7ae8499b1156dd2c2fbe9be4d81ccb6120a3ce4e 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -839,6 +839,18 @@ namespace IncDec {
     return a[1];
   }
   static_assert(f() == 3, "");
+
+  int nonconst(int a) { // both-note 4{{declared here}}
+    static_assert(a++, ""); // both-error {{not an integral constant expression}} \
+                            // both-note {{function parameter 'a' with unknown value cannot be used in a constant expression}}
+    static_assert(a--, ""); // both-error {{not an integral constant expression}} \
+                            // both-note {{function parameter 'a' with unknown value cannot be used in a constant expression}}
+    static_assert(++a, ""); // both-error {{not an integral constant expression}} \
+                            // both-note {{function parameter 'a' with unknown value cannot be used in a constant expression}}
+    static_assert(--a, ""); // both-error {{not an integral constant expression}} \
+                            // both-note {{function parameter 'a' with unknown value cannot be used in a constant expression}}
+  }
+
 };
 #endif
 
diff --git a/clang/test/AST/ast-print-objectivec.m b/clang/test/AST/ast-print-objectivec.m
index 05a0a5d4aa74c47fb7592dd0b08b6d796733d8ae..a0652f38e713fa87e5b0dfddbc722d866c1eba51 100644
--- a/clang/test/AST/ast-print-objectivec.m
+++ b/clang/test/AST/ast-print-objectivec.m
@@ -21,6 +21,10 @@
 - (void)methodWithArg:(int)x andAnotherOne:(int)y { }
 @end
 
+__attribute__((availability(macosx,introduced=10.1.0,deprecated=10.2)))
+@interface InterfaceWithAttribute
+@end
+
 // CHECK: @protocol P
 // CHECK: - (void)MethP __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2)));
 // CHECK: @end
@@ -45,6 +49,10 @@
 
 // CHECK: @end
 
+// CHECK: __attribute__((availability(macos, introduced=10.1.0, deprecated=10.2)))
+// CHECK: @interface InterfaceWithAttribute
+// CHECK: @end
+
 @class C1;
 struct __attribute__((objc_bridge_related(C1,,))) S1;
 
diff --git a/clang/test/AST/coroutine-locals-cleanup.cpp b/clang/test/AST/coroutine-locals-cleanup.cpp
index ce106b8e230a10ede5b14118a7766e8b5ef38219..6264df01fa2acb299b579f738c73ba1edfa33e8a 100644
--- a/clang/test/AST/coroutine-locals-cleanup.cpp
+++ b/clang/test/AST/coroutine-locals-cleanup.cpp
@@ -90,10 +90,7 @@ Task bar() {
 // CHECK:                 ExprWithCleanups {{.*}} 'bool'
 // CHECK-NEXT:              CXXMemberCallExpr {{.*}} 'bool'
 // CHECK-NEXT:                MemberExpr {{.*}} .await_ready
-// CHECK:                 CallExpr {{.*}} 'void'
-// CHECK-NEXT:              ImplicitCastExpr {{.*}} 'void (*)(void *)'
-// CHECK-NEXT:                DeclRefExpr {{.*}} '__builtin_coro_resume' 'void (void *)'
-// CHECK-NEXT:              ExprWithCleanups {{.*}} 'void *'
+// CHECK:                 ExprWithCleanups {{.*}} 'void *'
 
 // CHECK:           CaseStmt
 // CHECK:             ExprWithCleanups {{.*}} 'void'
@@ -103,7 +100,4 @@ Task bar() {
 // CHECK:                 ExprWithCleanups {{.*}} 'bool'
 // CHECK-NEXT:              CXXMemberCallExpr {{.*}} 'bool'
 // CHECK-NEXT:                MemberExpr {{.*}} .await_ready
-// CHECK:                 CallExpr {{.*}} 'void'
-// CHECK-NEXT:              ImplicitCastExpr {{.*}} 'void (*)(void *)'
-// CHECK-NEXT:                DeclRefExpr {{.*}} '__builtin_coro_resume' 'void (void *)'
-// CHECK-NEXT:              ExprWithCleanups {{.*}} 'void *'
+// CHECK:                 ExprWithCleanups {{.*}} 'void *'
diff --git a/clang/test/Analysis/Checkers/WebKit/mock-types.h b/clang/test/Analysis/Checkers/WebKit/mock-types.h
index e2b3401d4073921eae874640c485e332b0777912..aab99197dfa49ea7286700175c374842ae21c1cd 100644
--- a/clang/test/Analysis/Checkers/WebKit/mock-types.h
+++ b/clang/test/Analysis/Checkers/WebKit/mock-types.h
@@ -62,6 +62,8 @@ struct RefCountable {
   static Ref create();
   void ref() {}
   void deref() {}
+  void method();
+  int trivial() { return 123; }
 };
 
 template  T *downcast(T *t) { return t; }
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
index 0fcd3b21376caf8895eb75c56448e08643fe4218..00673e91f471ea2de029a2ef115352eab501e51e 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-local-vars.cpp
@@ -2,6 +2,8 @@
 
 #include "mock-types.h"
 
+void someFunction();
+
 namespace raw_ptr {
 void foo() {
   RefCountable *bar;
@@ -16,6 +18,13 @@ void foo_ref() {
   RefCountable automatic;
   RefCountable &bar = automatic;
   // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
+  someFunction();
+  bar.method();
+}
+
+void foo_ref_trivial() {
+  RefCountable automatic;
+  RefCountable &bar = automatic;
 }
 
 void bar_ref(RefCountable &) {}
@@ -32,6 +41,8 @@ void foo2() {
   // missing embedded scope here
   RefCountable *bar = foo.get();
   // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
+  someFunction();
+  bar->method();
 }
 
 void foo3() {
@@ -47,11 +58,35 @@ void foo4() {
     { RefCountable *bar = foo.get(); }
   }
 }
+
+void foo5() {
+  RefPtr foo;
+  auto* bar = foo.get();
+  bar->trivial();
+}
+
+void foo6() {
+  RefPtr foo;
+  auto* bar = foo.get();
+  // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
+  bar->method();
+}
+
+struct SelfReferencingStruct {
+  SelfReferencingStruct* ptr;
+  RefCountable* obj { nullptr };
+};
+
+void foo7(RefCountable* obj) {
+  SelfReferencingStruct bar = { &bar, obj };
+  bar.obj->method();
+}
+
 } // namespace guardian_scopes
 
 namespace auto_keyword {
 class Foo {
-  RefCountable *provide_ref_ctnbl() { return nullptr; }
+  RefCountable *provide_ref_ctnbl();
 
   void evil_func() {
     RefCountable *bar = provide_ref_ctnbl();
@@ -62,13 +97,24 @@ class Foo {
     // expected-warning@-1{{Local variable 'baz2' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
     [[clang::suppress]] auto *baz_suppressed = provide_ref_ctnbl(); // no-warning
   }
+
+  void func() {
+    RefCountable *bar = provide_ref_ctnbl();
+    // expected-warning@-1{{Local variable 'bar' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
+    if (bar)
+      bar->method();
+  }
 };
 } // namespace auto_keyword
 
 namespace guardian_casts {
 void foo1() {
   RefPtr foo;
-  { RefCountable *bar = downcast(foo.get()); }
+  {
+    RefCountable *bar = downcast(foo.get());
+    bar->method();
+  }
+  foo->method();
 }
 
 void foo2() {
@@ -76,6 +122,7 @@ void foo2() {
   {
     RefCountable *bar =
         static_cast(downcast(foo.get()));
+    someFunction();
   }
 }
 } // namespace guardian_casts
@@ -83,7 +130,11 @@ void foo2() {
 namespace guardian_ref_conversion_operator {
 void foo() {
   Ref rc;
-  { RefCountable &rr = rc; }
+  {
+    RefCountable &rr = rc;
+    rr.method();
+    someFunction();
+  }
 }
 } // namespace guardian_ref_conversion_operator
 
@@ -92,9 +143,47 @@ RefCountable *provide_ref_ctnbl() { return nullptr; }
 
 void foo() {
   // no warnings
-  if (RefCountable *a = provide_ref_ctnbl()) { }
-  for (RefCountable *a = provide_ref_ctnbl(); a != nullptr;) { }
+  if (RefCountable *a = provide_ref_ctnbl())
+    a->trivial();
+  for (RefCountable *b = provide_ref_ctnbl(); b != nullptr;)
+    b->trivial();
   RefCountable *array[1];
-  for (RefCountable *a : array) { }
+  for (RefCountable *c : array)
+    c->trivial();
+  while (RefCountable *d = provide_ref_ctnbl())
+    d->trivial();
+  do {
+    RefCountable *e = provide_ref_ctnbl();
+    e->trivial();
+  } while (1);
+  someFunction();
 }
+
+void bar() {
+  if (RefCountable *a = provide_ref_ctnbl()) {
+    // expected-warning@-1{{Local variable 'a' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
+    a->method();    
+  }
+  for (RefCountable *b = provide_ref_ctnbl(); b != nullptr;) {
+    // expected-warning@-1{{Local variable 'b' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
+    b->method();
+  }
+  RefCountable *array[1];
+  for (RefCountable *c : array) {
+    // expected-warning@-1{{Local variable 'c' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
+    c->method();
+  }
+
+  while (RefCountable *d = provide_ref_ctnbl()) {
+    // expected-warning@-1{{Local variable 'd' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
+    d->method();
+  }
+  do {
+    RefCountable *e = provide_ref_ctnbl();
+    // expected-warning@-1{{Local variable 'e' is uncounted and unsafe [alpha.webkit.UncountedLocalVarsChecker]}}
+    e->method();
+  } while (1);
+  someFunction();
+}
+
 } // namespace ignore_for_if
diff --git a/clang/test/Analysis/Inputs/system-header-simulator-for-malloc.h b/clang/test/Analysis/Inputs/system-header-simulator-for-malloc.h
index e76455655e9e2e920bd8a14b23a095d12b308fe3..bc7009eb0d1beaf19119e6f387cb91fe16e637c6 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-for-malloc.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-for-malloc.h
@@ -9,6 +9,7 @@ typedef __typeof(sizeof(int)) size_t;
 void *malloc(size_t);
 void *calloc(size_t, size_t);
 void free(void *);
+void *alloca(size_t);
 
 
 #if __OBJC__
diff --git a/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h b/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
index 098a2208fecbe91813edf277e16f0443e219208e..c26d3582149120eb36bc3b221972e862352b4fb3 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-for-simple-stream.h
@@ -5,7 +5,7 @@
 // suppressed.
 #pragma clang system_header
 
-typedef struct __sFILE {
+typedef struct _FILE {
   unsigned char *_p;
 } FILE;
 FILE *fopen(const char *restrict, const char *restrict) __asm("_" "fopen" );
diff --git a/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h b/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
index 7299b61353d460d44841c900c3c1221a4627923f..720944abb8ad47cb5c947f8a1e4b4fb6dec97d71 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-for-valist.h
@@ -10,6 +10,8 @@
 #define restrict /*restrict*/
 #endif
 
+typedef struct _FILE FILE;
+
 typedef __builtin_va_list va_list;
 
 #define va_start(ap, param) __builtin_va_start(ap, param)
@@ -21,6 +23,10 @@ int vprintf (const char *restrict format, va_list arg);
 
 int vsprintf (char *restrict s, const char *restrict format, va_list arg);
 
+int vfprintf(FILE *stream, const char *format, va_list ap);
+
+int vfscanf(FILE *stream, const char *format, va_list ap);
+
 int some_library_function(int n, va_list arg);
 
 // No warning from system header.
diff --git a/clang/test/Analysis/Inputs/system-header-simulator.h b/clang/test/Analysis/Inputs/system-header-simulator.h
index 15986984802c0e6257babb6a31deb57b61938e5d..8fd51449ecc0a425ad40637f3b7ba226932d190b 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator.h
@@ -73,6 +73,9 @@ int ferror(FILE *stream);
 int fileno(FILE *stream);
 int fflush(FILE *stream);
 
+
+int getc(FILE *stream);
+
 size_t strlen(const char *);
 
 char *strcpy(char *restrict, const char *restrict);
diff --git a/clang/test/Analysis/assuming-unsigned-ge-0.c b/clang/test/Analysis/assuming-unsigned-ge-0.c
new file mode 100644
index 0000000000000000000000000000000000000000..553e68cb96c6bd37bedd1a9fc445d7f09d1e909d
--- /dev/null
+++ b/clang/test/Analysis/assuming-unsigned-ge-0.c
@@ -0,0 +1,19 @@
+// RUN: %clang_analyze_cc1 -analyzer-output=text        \
+// RUN:     -analyzer-checker=core -verify %s
+
+int assuming_unsigned_ge_0(unsigned arg) {
+  // TODO This testcase demonstrates the current incorrect behavior of Clang
+  // Static Analyzer: here 'arg' is unsigned, so "arg >= 0" is not a fresh
+  // assumption, but it still appears in the diagnostics as if it's fresh:
+  // expected-note@+2 {{Assuming 'arg' is >= 0}}
+  // expected-note@+1 {{Taking false branch}}
+  if (arg < 0)
+    return 0;
+  // expected-note@+2 {{Assuming 'arg' is <= 0}}
+  // expected-note@+1 {{Taking false branch}}
+  if (arg > 0)
+    return 0;
+  // expected-note@+2 {{Division by zero}}
+  // expected-warning@+1 {{Division by zero}}
+  return 100 / arg;
+}
diff --git a/clang/test/Analysis/cxx2b-deducing-this.cpp b/clang/test/Analysis/cxx2b-deducing-this.cpp
index d22a897097bec0599e4f3dcdbbcf557390431a07..2ec9e96bf0f84f21e456af4d9aff80abb14e4aa8 100644
--- a/clang/test/Analysis/cxx2b-deducing-this.cpp
+++ b/clang/test/Analysis/cxx2b-deducing-this.cpp
@@ -60,3 +60,14 @@ void top() {
   s.c();
   s.c(11);
 }
+
+
+struct S2 {
+  bool operator==(this auto, S2) {
+    return true;
+  }
+};
+void use_deducing_this() {
+  int result = S2{} == S2{}; // no-crash
+  clang_analyzer_dump(result); // expected-warning {{1 S32b}}
+}
diff --git a/clang/test/Analysis/getline-alloc.c b/clang/test/Analysis/getline-alloc.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b5c716cb605a725aee409eaa841a355feb5d054
--- /dev/null
+++ b/clang/test/Analysis/getline-alloc.c
@@ -0,0 +1,95 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,debug.ExprInspection -verify %s
+
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,alpha.unix,debug.ExprInspection -verify %s
+
+#include "Inputs/system-header-simulator.h"
+#include "Inputs/system-header-simulator-for-malloc.h"
+
+void test_getline_null_buffer() {
+  FILE *F1 = tmpfile();
+  if (!F1)
+    return;
+  char *buffer = NULL;
+  size_t n = 0;
+  if (getline(&buffer, &n, F1) > 0) {
+    char c = buffer[0]; // ok
+  }
+  free(buffer);
+  fclose(F1);
+}
+
+void test_getline_malloc_buffer() {
+  FILE *F1 = tmpfile();
+  if (!F1)
+    return;
+
+  size_t n = 10;
+  char *buffer = malloc(n);
+  char *ptr = buffer;
+
+  ssize_t r = getdelim(&buffer, &n, '\r', F1);
+  // ptr may be dangling
+  free(ptr);    // expected-warning {{Attempt to free released memory}}
+  free(buffer); // ok
+  fclose(F1);
+}
+
+void test_getline_alloca() {
+  FILE *F1 = tmpfile();
+  if (!F1)
+    return;
+  size_t n = 10;
+  char *buffer = alloca(n);
+  getline(&buffer, &n, F1); // expected-warning {{Memory allocated by alloca() should not be deallocated}}
+  fclose(F1);
+}
+
+void test_getline_invalid_ptr() {
+  FILE *F1 = tmpfile();
+  if (!F1)
+    return;
+  size_t n = 10;
+  char *buffer = (char*)test_getline_invalid_ptr;
+  getline(&buffer, &n, F1); // expected-warning {{Argument to getline() is the address of the function 'test_getline_invalid_ptr', which is not memory allocated by malloc()}}
+  fclose(F1);
+}
+
+void test_getline_leak() {
+  FILE *F1 = tmpfile();
+  if (!F1)
+    return;
+
+  char *buffer = NULL;
+  size_t n = 0;
+  ssize_t read;
+
+  while ((read = getline(&buffer, &n, F1)) != -1) {
+    printf("%s\n", buffer);
+  }
+
+  fclose(F1); // expected-warning {{Potential memory leak}}
+}
+
+void test_getline_stack() {
+  size_t n = 10;
+  char buffer[10];
+  char *ptr = buffer;
+
+  FILE *F1 = tmpfile();
+  if (!F1)
+    return;
+
+  getline(&ptr, &n, F1); // expected-warning {{Argument to getline() is the address of the local variable 'buffer', which is not memory allocated by malloc()}}
+}
+
+void test_getline_static() {
+  static size_t n = 10;
+  static char buffer[10];
+  char *ptr = buffer;
+
+  FILE *F1 = tmpfile();
+  if (!F1)
+    return;
+
+  getline(&ptr, &n, F1); // expected-warning {{Argument to getline() is the address of the static variable 'buffer', which is not memory allocated by malloc()}}
+}
diff --git a/clang/test/Analysis/misc-ps-region-store.mm b/clang/test/Analysis/misc-ps-region-store.mm
index 7722f01e35bc8221d7b65f2b63c288c5ae8b052c..3a2df83d4f41f5aeadb7fa329b2f886c002a5176 100644
--- a/clang/test/Analysis/misc-ps-region-store.mm
+++ b/clang/test/Analysis/misc-ps-region-store.mm
@@ -2,9 +2,9 @@
 // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin9 -analyzer-checker=core,alpha.core -verify -fblocks   %s
 // expected-no-diagnostics
 
-//===------------------------------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 // This files tests our path-sensitive handling of Objective-c++ files.
-//===------------------------------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 
 // Test basic handling of references.
 char &test1_aux();
diff --git a/clang/test/Analysis/stack-addr-ps.c b/clang/test/Analysis/stack-addr-ps.c
index 26e1cc58350cab87a78bf732f43bfc9147706d40..e469396e1bb22a9cb46450d147f9db43c4ec61e9 100644
--- a/clang/test/Analysis/stack-addr-ps.c
+++ b/clang/test/Analysis/stack-addr-ps.c
@@ -20,13 +20,13 @@ int* f3(int x, int *y) {
 
 void* compound_literal(int x, int y) {
   if (x)
-    return &(unsigned short){((unsigned short)0x22EF)}; // expected-warning{{Address of stack memory}}
+    return &(unsigned short){((unsigned short)0x22EF)}; // expected-warning{{Address of stack memory}} expected-warning{{address of stack memory}}
 
   int* array[] = {};
   struct s { int z; double y; int w; };
   
   if (y)
-    return &((struct s){ 2, 0.4, 5 * 8 }); // expected-warning{{Address of stack memory}}
+    return &((struct s){ 2, 0.4, 5 * 8 }); // expected-warning{{Address of stack memory}} expected-warning{{address of stack memory}}
     
   
   void* p = &((struct s){ 42, 0.4, x ? 42 : 0 });
diff --git a/clang/test/Analysis/stream-error.c b/clang/test/Analysis/stream-error.c
index ac31083bfc691fb5928bddd09219e1429e89bf3d..88f7de4234ffb4689a7e298e4f22dc8766b80887 100644
--- a/clang/test/Analysis/stream-error.c
+++ b/clang/test/Analysis/stream-error.c
@@ -11,6 +11,7 @@ void clang_analyzer_dump(int);
 void clang_analyzer_warnIfReached(void);
 void StreamTesterChecker_make_feof_stream(FILE *);
 void StreamTesterChecker_make_ferror_stream(FILE *);
+void StreamTesterChecker_make_ferror_indeterminate_stream(FILE *);
 
 void error_fopen(void) {
   FILE *F = fopen("file", "r");
@@ -52,6 +53,8 @@ void stream_error_feof(void) {
   clearerr(F);
   clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
+  StreamTesterChecker_make_ferror_indeterminate_stream(F);
+  clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
   fclose(F);
 }
 
@@ -65,6 +68,8 @@ void stream_error_ferror(void) {
   clearerr(F);
   clang_analyzer_eval(feof(F));   // expected-warning {{FALSE}}
   clang_analyzer_eval(ferror(F)); // expected-warning {{FALSE}}
+  StreamTesterChecker_make_ferror_indeterminate_stream(F);
+  clang_analyzer_eval(ferror(F)); // expected-warning {{TRUE}}
   fclose(F);
 }
 
@@ -233,7 +238,7 @@ void error_fscanf(int *A) {
   fscanf(F, "ccc"); // expected-warning {{Stream might be already closed}}
 }
 
-void error_ungetc() {
+void error_ungetc(int TestIndeterminate) {
   FILE *F = tmpfile();
   if (!F)
     return;
@@ -245,8 +250,12 @@ void error_ungetc() {
     clang_analyzer_eval(Ret == 'X');         // expected-warning {{TRUE}}
   }
   fputc('Y', F);                             // no-warning
+  if (TestIndeterminate) {
+    StreamTesterChecker_make_ferror_indeterminate_stream(F);
+    ungetc('X', F);                          // expected-warning {{might be 'indeterminate'}}
+  }
   fclose(F);
-  ungetc('A', F); // expected-warning {{Stream might be already closed}}
+  ungetc('A', F);                            // expected-warning {{Stream might be already closed}}
 }
 
 void error_getdelim(char *P, size_t Sz) {
@@ -449,7 +458,7 @@ void error_fseeko_0(void) {
   fclose(F);
 }
 
-void error_ftell(void) {
+void error_ftell(int TestIndeterminate) {
   FILE *F = fopen("file", "r");
   if (!F)
     return;
@@ -467,10 +476,14 @@ void error_ftell(void) {
   rc = ftell(F);
   clang_analyzer_eval(feof(F));              // expected-warning {{FALSE}}
   clang_analyzer_eval(ferror(F));            // expected-warning {{TRUE}}
+  if (TestIndeterminate) {
+    StreamTesterChecker_make_ferror_indeterminate_stream(F);
+    ftell(F);                                // expected-warning {{might be 'indeterminate'}}
+  }
   fclose(F);
 }
 
-void error_ftello(void) {
+void error_ftello(int TestIndeterminate) {
   FILE *F = fopen("file", "r");
   if (!F)
     return;
@@ -488,6 +501,10 @@ void error_ftello(void) {
   rc = ftello(F);
   clang_analyzer_eval(feof(F));              // expected-warning {{FALSE}}
   clang_analyzer_eval(ferror(F));            // expected-warning {{TRUE}}
+  if (TestIndeterminate) {
+    StreamTesterChecker_make_ferror_indeterminate_stream(F);
+    ftell(F);                                // expected-warning {{might be 'indeterminate'}}
+  }
   fclose(F);
 }
 
@@ -506,6 +523,8 @@ void error_fileno(void) {
   N = fileno(F);
   clang_analyzer_eval(feof(F));              // expected-warning {{FALSE}}
   clang_analyzer_eval(ferror(F));            // expected-warning {{TRUE}}
+  StreamTesterChecker_make_ferror_indeterminate_stream(F);
+  fileno(F);                                 // no warning
   fclose(F);
 }
 
diff --git a/clang/test/Analysis/stream-invalidate.c b/clang/test/Analysis/stream-invalidate.c
index 6745d11a2fe7017465ae9c4a1ab355b802ddbd00..5046a356d0583d5dbd87aa8549d29eb2edf80c61 100644
--- a/clang/test/Analysis/stream-invalidate.c
+++ b/clang/test/Analysis/stream-invalidate.c
@@ -4,6 +4,7 @@
 // RUN: -analyzer-checker=debug.ExprInspection
 
 #include "Inputs/system-header-simulator.h"
+#include "Inputs/system-header-simulator-for-valist.h"
 
 void clang_analyzer_eval(int);
 void clang_analyzer_dump(int);
@@ -145,3 +146,44 @@ void test_fgetpos() {
 
   fclose(F);
 }
+
+void test_fprintf() {
+  FILE *F1 = tmpfile();
+  if (!F1)
+    return;
+
+  unsigned a = 42;
+  char *output = "HELLO";
+  int r = fprintf(F1, "%s\t%u\n", output, a);
+  // fprintf does not invalidate any of its input
+  // 69 is ascii for 'E'
+  clang_analyzer_dump(a); // expected-warning {{42 S32b}}
+  clang_analyzer_dump(output[1]); // expected-warning {{69 S32b}}
+  fclose(F1);
+}
+
+int test_vfscanf_inner(const char *fmt, ...) {
+  FILE *F1 = tmpfile();
+  if (!F1)
+    return EOF;
+
+  va_list ap;
+  va_start(ap, fmt);
+
+  int r = vfscanf(F1, fmt, ap);
+
+  fclose(F1);
+  va_end(ap);
+  return r;
+}
+
+void test_vfscanf() {
+  int i = 42;
+  int j = 43;
+  int r = test_vfscanf_inner("%d", &i);
+  if (r != EOF) {
+    // i gets invalidated by the call to test_vfscanf_inner, not by vfscanf.
+    clang_analyzer_dump(i); // expected-warning {{conj_$}}
+    clang_analyzer_dump(j); // expected-warning {{43 S32b}}
+  }
+}
diff --git a/clang/test/Analysis/stream.c b/clang/test/Analysis/stream.c
index 378c9154f8f6a879e8fa03b02ab60e3583e067ed..7ba27740a93796a8e89066395a85a2bbb55afe7e 100644
--- a/clang/test/Analysis/stream.c
+++ b/clang/test/Analysis/stream.c
@@ -1,6 +1,10 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.unix.Stream,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -triple=x86_64-pc-linux-gnu -analyzer-checker=core,alpha.unix.Stream,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -triple=armv8-none-linux-eabi -analyzer-checker=core,alpha.unix.Stream,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -triple=aarch64-linux-gnu -analyzer-checker=core,alpha.unix.Stream,debug.ExprInspection -verify %s
+// RUN: %clang_analyze_cc1 -triple=hexagon -analyzer-checker=core,alpha.unix.Stream,debug.ExprInspection -verify %s
 
 #include "Inputs/system-header-simulator.h"
+#include "Inputs/system-header-simulator-for-valist.h"
 
 void clang_analyzer_eval(int);
 
@@ -65,12 +69,24 @@ void check_fseek(void) {
   fclose(fp);
 }
 
+void check_fseeko(void) {
+  FILE *fp = tmpfile();
+  fseeko(fp, 0, 0); // expected-warning {{Stream pointer might be NULL}}
+  fclose(fp);
+}
+
 void check_ftell(void) {
   FILE *fp = tmpfile();
   ftell(fp); // expected-warning {{Stream pointer might be NULL}}
   fclose(fp);
 }
 
+void check_ftello(void) {
+  FILE *fp = tmpfile();
+  ftello(fp); // expected-warning {{Stream pointer might be NULL}}
+  fclose(fp);
+}
+
 void check_rewind(void) {
   FILE *fp = tmpfile();
   rewind(fp); // expected-warning {{Stream pointer might be NULL}}
@@ -129,6 +145,18 @@ void f_dopen(int fd) {
   fclose(F);
 }
 
+void f_vfprintf(int fd, va_list args) {
+  FILE *F = fdopen(fd, "r");
+  vfprintf(F, "%d", args); // expected-warning {{Stream pointer might be NULL}}
+  fclose(F);
+}
+
+void f_vfscanf(int fd, va_list args) {
+  FILE *F = fdopen(fd, "r");
+  vfscanf(F, "%u", args); // expected-warning {{Stream pointer might be NULL}}
+  fclose(F);
+}
+
 void f_seek(void) {
   FILE *p = fopen("foo", "r");
   if (!p)
@@ -138,6 +166,15 @@ void f_seek(void) {
   fclose(p);
 }
 
+void f_seeko(void) {
+  FILE *p = fopen("foo", "r");
+  if (!p)
+    return;
+  fseeko(p, 1, SEEK_SET); // no-warning
+  fseeko(p, 1, 3); // expected-warning {{The whence argument to fseek() should be SEEK_SET, SEEK_END, or SEEK_CUR}}
+  fclose(p);
+}
+
 void f_double_close(void) {
   FILE *p = fopen("foo", "r");
   if (!p)
diff --git a/clang/test/C/C2x/n3018.c b/clang/test/C/C2x/n3018.c
new file mode 100644
index 0000000000000000000000000000000000000000..0d54d53b7499fc5e340adc54027ec80979802c8f
--- /dev/null
+++ b/clang/test/C/C2x/n3018.c
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -std=c23 -verify -triple x86_64 -pedantic -Wno-conversion -Wno-constant-conversion %s
+
+/* WG14 N3018: Full
+ * The constexpr specifier for object definitions
+ */
+
+#define ULLONG_MAX (__LONG_LONG_MAX__*2ULL+1ULL)
+#define UINT_MAX  (__INT_MAX__  *2U +1U)
+
+void Example0() {
+  constexpr unsigned int minusOne    = -1;
+  // expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned int'}}
+  constexpr unsigned int uint_max    = -1U;
+  constexpr double onethird          = 1.0/3.0;
+  constexpr double onethirdtrunc     = (double)(1.0/3.0);
+
+  constexpr char string[] = { "\xFF", };
+  constexpr unsigned char ucstring[] = { "\xFF", };
+  // expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned char'}}
+  constexpr char string1[] = { -1, 0, };
+  constexpr unsigned char ucstring1[] = { -1, 0, };
+  // expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned char'}}
+
+  // TODO: Make sure these work correctly once char8_t and _Decimal are supported
+  // constexpr char8_t u8string[] = { 255, 0, }; // ok
+  // constexpr char8_t u8string[]       = { u8"\xFF", };     // ok
+  // constexpr _Decimal32 small         = DEC64_TRUE_MIN * 0;// constraint violation
+}
+
+void Example1() {
+  constexpr int K = 47;
+  enum {
+      A = K,
+  };
+  constexpr int L = K;
+  static int b    = K + 1;
+  int array[K];
+  _Static_assert(K == 47);
+}
+
+constexpr int K = 47;
+static const int b = K + 1;
+
+void Example2() {
+  constexpr int A          = 42LL;
+  constexpr signed short B = ULLONG_MAX;
+  // expected-error@-1 {{constexpr initializer evaluates to 18446744073709551615 which is not exactly representable in type 'const short'}}
+  constexpr float C        = 47u;
+
+  constexpr float D = 432000000;
+  constexpr float E = 1.0 / 3.0;
+  // expected-error@-1 {{constexpr initializer evaluates to 3.333333e-01 which is not exactly representable in type 'const float'}}
+  constexpr float F = 1.0f / 3.0f;
+}
+
+
+void Example3() {
+  constexpr static unsigned short array[] = {
+      3000,
+      300000,
+      // expected-error@-1 {{constexpr initializer evaluates to 300000 which is not exactly representable in type 'const unsigned short'}}
+      -1
+      // expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned short'}}
+  };
+
+  constexpr static unsigned short array1[] = {
+      3000,
+      3000,
+      -1
+       // expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned short'}}
+  };
+
+  struct S {
+      int x, y;
+  };
+  constexpr struct S s = {
+      .x = __INT_MAX__,
+      .y = UINT_MAX,
+      // expected-error@-1 {{constexpr initializer evaluates to 4294967295 which is not exactly representable in type 'int'}}
+  };
+}
+
+void Example4() {
+  struct s { void *p; };
+  constexpr struct s A = { nullptr };
+  constexpr struct s B = A;
+}
diff --git a/clang/test/C/drs/dr0xx.c b/clang/test/C/drs/dr0xx.c
index d9c1fbe4ee40aba8bf5aaa8a556f151e72f217c8..c93cfb63d604cfaf77af8b58bc7cbf494e115188 100644
--- a/clang/test/C/drs/dr0xx.c
+++ b/clang/test/C/drs/dr0xx.c
@@ -214,7 +214,7 @@ _Static_assert(__builtin_types_compatible_p(struct S { int a; }, union U { int a
  */
 void dr031(int i) {
   switch (i) {
-  case __INT_MAX__ + 1: break; /* expected-warning {{overflow in expression; result is -2147483648 with type 'int'}} */
+  case __INT_MAX__ + 1: break; /* expected-warning {{overflow in expression; result is -2'147'483'648 with type 'int'}} */
   #pragma clang diagnostic push
   #pragma clang diagnostic ignored "-Wswitch"
   /* Silence the targets which issue:
diff --git a/clang/test/C/drs/dr2xx.c b/clang/test/C/drs/dr2xx.c
index 9c8d77518ab55e8d262042859597cdc4807116d9..1b68b65acca6af77b46b5cf5aa40308987c49f7e 100644
--- a/clang/test/C/drs/dr2xx.c
+++ b/clang/test/C/drs/dr2xx.c
@@ -277,7 +277,7 @@ void dr258(void) {
 void dr261(void) {
   /* This is still an integer constant expression despite the overflow. */
   enum e1 {
-    ex1 = __INT_MAX__ + 1  /* expected-warning {{overflow in expression; result is -2147483648 with type 'int'}} */
+    ex1 = __INT_MAX__ + 1  /* expected-warning {{overflow in expression; result is -2'147'483'648 with type 'int'}} */
   };
 
   /* This is not an integer constant expression, because of the comma operator,
diff --git a/clang/test/CXX/basic/basic.link/p10-ex2.cpp b/clang/test/CXX/basic/basic.link/p10-ex2.cpp
index 95fdb56f78d62508627ac9f3302fbd8a74e268f2..e985ce37a934959455142e912fd3e8f2ab9ff687 100644
--- a/clang/test/CXX/basic/basic.link/p10-ex2.cpp
+++ b/clang/test/CXX/basic/basic.link/p10-ex2.cpp
@@ -5,7 +5,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 M.cpp -fsyntax-only -DTEST_INTERFACE -verify
 // RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm
+// RUN: %clang_cc1 -std=c++20 M.cpp -emit-reduced-module-interface -o M.reduced.pcm
 // RUN: %clang_cc1 -std=c++20 useM.cpp -fsyntax-only -fmodule-file=M=M.pcm -verify
+// RUN: %clang_cc1 -std=c++20 useM.cpp -fsyntax-only -fmodule-file=M=M.reduced.pcm -verify
 
 //--- decls.h
 int f(); // #1, attached to the global module
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp
index 638057cbd681f062b7eae84a1310c04130640fb7..3c120654f2ee5da02f8869ad449c1b7d25f1584e 100644
--- a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4-friend-in-reachable-class.cpp
@@ -8,7 +8,10 @@
 // RUN: split-file %s %t
 //
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/Friend-in-reachable-class.cppm -o %t/X.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/Friend-in-reachable-class.cppm \
+// RUN:   -o %t/X.reduced.pcm
+// RUN: %clang_cc1 -std=c++20 -fmodule-file=X=%t/X.pcm %t/Use.cpp -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 -fmodule-file=X=%t/X.reduced.pcm %t/Use.cpp -verify -fsyntax-only
 //
 //--- Friend-in-reachable-class.cppm
 module;
diff --git a/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp b/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp
index 166bd97e2731cb01d4fc084d6e6a9d4f5f4d7e3c..c73eb0dee99515be29fd6efe2c1a134fdd957553 100644
--- a/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp
+++ b/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp
@@ -1,8 +1,8 @@
 // This test is for the [class.compare.default]p3 added by P2002R0
-// Also covers modifications made by P2448R2 and extension warnings
+// Also covers modifications made by P2448R2
 
-// RUN: %clang_cc1 -std=c++2a -verify %s
-// RUN: %clang_cc1 -std=c++2a -Wc++23-default-comp-relaxed-constexpr -verify=expected,extension %s
+// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx2a %s
+// RUN: %clang_cc1 -std=c++23 -verify=expected %s
 
 namespace std {
   struct strong_ordering {
@@ -82,10 +82,12 @@ struct TestB {
 };
 
 struct C {
-  friend bool operator==(const C&, const C&); // expected-note {{previous}} extension-note 2{{non-constexpr comparison function declared here}}
+  friend bool operator==(const C&, const C&); // expected-note {{previous}} \
+                                              // cxx2a-note 2{{declared here}}
   friend bool operator!=(const C&, const C&) = default; // expected-note {{previous}}
 
-  friend std::strong_ordering operator<=>(const C&, const C&); // expected-note {{previous}} extension-note 2{{non-constexpr comparison function declared here}}
+  friend std::strong_ordering operator<=>(const C&, const C&); // expected-note {{previous}} \
+                                                               // cxx2a-note 2{{declared here}}
   friend bool operator<(const C&, const C&) = default; // expected-note {{previous}}
   friend bool operator<=(const C&, const C&) = default; // expected-note {{previous}}
   friend bool operator>(const C&, const C&) = default; // expected-note {{previous}}
@@ -129,23 +131,23 @@ struct TestD {
 
 struct E {
   A a;
-  C c; // extension-note 2{{non-constexpr comparison function would be used to compare member 'c'}}
+  C c; // cxx2a-note 2{{non-constexpr comparison function would be used to compare member 'c'}}
   A b;
-  friend constexpr bool operator==(const E&, const E&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
+  friend constexpr bool operator==(const E&, const E&) = default; // cxx2a-error {{cannot be declared constexpr}}
   friend constexpr bool operator!=(const E&, const E&) = default;
 
-  friend constexpr std::strong_ordering operator<=>(const E&, const E&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
+  friend constexpr std::strong_ordering operator<=>(const E&, const E&) = default; // cxx2a-error {{cannot be declared constexpr}}
   friend constexpr bool operator<(const E&, const E&) = default;
   friend constexpr bool operator<=(const E&, const E&) = default;
   friend constexpr bool operator>(const E&, const E&) = default;
   friend constexpr bool operator>=(const E&, const E&) = default;
 };
 
-struct E2 : A, C { // extension-note 2{{non-constexpr comparison function would be used to compare base class 'C'}}
-  friend constexpr bool operator==(const E2&, const E2&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
+struct E2 : A, C { // cxx2a-note 2{{non-constexpr comparison function would be used to compare base class 'C'}}
+  friend constexpr bool operator==(const E2&, const E2&) = default; // cxx2a-error {{cannot be declared constexpr}}
   friend constexpr bool operator!=(const E2&, const E2&) = default;
 
-  friend constexpr std::strong_ordering operator<=>(const E2&, const E2&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
+  friend constexpr std::strong_ordering operator<=>(const E2&, const E2&) = default; // cxx2a-error {{cannot be declared constexpr}}
   friend constexpr bool operator<(const E2&, const E2&) = default;
   friend constexpr bool operator<=(const E2&, const E2&) = default;
   friend constexpr bool operator>(const E2&, const E2&) = default;
@@ -153,14 +155,14 @@ struct E2 : A, C { // extension-note 2{{non-constexpr comparison function would
 };
 
 struct F {
-  friend bool operator==(const F&, const F&); // extension-note {{non-constexpr comparison function declared here}}
-  friend constexpr bool operator!=(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
-
-  friend std::strong_ordering operator<=>(const F&, const F&); // extension-note 4{{non-constexpr comparison function declared here}}
-  friend constexpr bool operator<(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
-  friend constexpr bool operator<=(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
-  friend constexpr bool operator>(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
-  friend constexpr bool operator>=(const F&, const F&) = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
+  friend bool operator==(const F&, const F&); // cxx2a-note {{declared here}}
+  friend constexpr bool operator!=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
+
+  friend std::strong_ordering operator<=>(const F&, const F&); // cxx2a-note 4{{non-constexpr comparison function declared here}}
+  friend constexpr bool operator<(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
+  friend constexpr bool operator<=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
+  friend constexpr bool operator>(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
+  friend constexpr bool operator>=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
 };
 
 // No implicit 'constexpr' if it's not the first declaration.
diff --git a/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp b/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
index 02cdd7f85aebfa58cb0b78d586941dbf65374c39..534c3b34d8832a4a96f19332e74d7bc160ddbe60 100644
--- a/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
+++ b/clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 -std=c++2a -verify %s
-// RUN: %clang_cc1 -std=c++2a -Wc++23-default-comp-relaxed-constexpr -verify=expected,extension %s
+// RUN: %clang_cc1 -std=c++2a -verify=expected,cxx2a %s
+// RUN: %clang_cc1 -std=c++23 -verify=expected %s
 
 // This test is for [class.compare.default]p3 as modified and renumbered to p4
 // by P2002R0.
-// Also covers modifications made by P2448R2 and extension warnings
+// Also covers modifications made by P2448R2
 
 namespace std {
   struct strong_ordering {
@@ -78,13 +78,13 @@ void use_g(G g) {
 }
 
 struct H {
-  bool operator==(const H&) const; // extension-note {{non-constexpr comparison function declared here}}
+  bool operator==(const H&) const; // cxx2a-note {{non-constexpr comparison function declared here}}
   constexpr std::strong_ordering operator<=>(const H&) const { return std::strong_ordering::equal; }
 };
 
 struct I {
-  H h; // extension-note {{non-constexpr comparison function would be used to compare member 'h'}}
-  constexpr std::strong_ordering operator<=>(const I&) const = default; // extension-warning {{implicit 'operator=='  invokes a non-constexpr comparison function is a C++23 extension}}
+  H h; // cxx2a-note {{non-constexpr comparison function would be used to compare member 'h'}}
+  constexpr std::strong_ordering operator<=>(const I&) const = default; // cxx2a-error {{cannot be declared constexpr}}
 };
 
 struct J {
@@ -148,16 +148,16 @@ namespace NoInjectionIfOperatorEqualsDeclared {
 
 namespace GH61238 {
 template  struct my_struct {
-    A value; // extension-note {{non-constexpr comparison function would be used to compare member 'value'}}
+    A value; // cxx2a-note {{non-constexpr comparison function would be used to compare member 'value'}}
 
-    constexpr friend bool operator==(const my_struct &, const my_struct &) noexcept = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
+    constexpr friend bool operator==(const my_struct &, const my_struct &) noexcept = default; // cxx2a-error {{cannot be declared constexpr}}
 };
 
 struct non_constexpr_type {
-    friend bool operator==(non_constexpr_type, non_constexpr_type) noexcept { // extension-note {{non-constexpr comparison function declared here}}
+    friend bool operator==(non_constexpr_type, non_constexpr_type) noexcept { // cxx2a-note {{non-constexpr comparison function declared here}}
         return false;
     }
 };
 
-my_struct obj; // extension-note {{in instantiation of template class 'GH61238::my_struct' requested here}}
+my_struct obj; // cxx2a-note {{in instantiation of template class 'GH61238::my_struct' requested here}}
 }
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
index 7ad2e582a8126834623d1bd1348742feda9ca1e5..48bc8fb426bcb198fada867822dc6635ef8e2033 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/dtor.cpp
@@ -58,12 +58,12 @@ namespace subobject {
   struct A {
     ~A();
   };
-  struct B : A { // expected-note {{here}}
-    constexpr ~B() {} // expected-error {{destructor cannot be declared constexpr because base class 'A' does not have a constexpr destructor}}
+  struct B : A { // cxx2a-note {{here}}
+    constexpr ~B() {} // cxx2a-error {{destructor cannot be declared constexpr because base class 'A' does not have a constexpr destructor}}
   };
   struct C {
-    A a; // expected-note {{here}}
-    constexpr ~C() {} // expected-error {{destructor cannot be declared constexpr because data member 'a' does not have a constexpr destructor}}
+    A a; // cxx2a-note {{here}}
+    constexpr ~C() {} // cxx2a-error {{destructor cannot be declared constexpr because data member 'a' does not have a constexpr destructor}}
   };
   struct D : A {
     A a;
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp
index c07502c0555b504bb5cbdc6863899e8808147e06..8cb37ae6d1cdece52f94e0ced7643fa35fcb95a4 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3-2b.cpp
@@ -14,9 +14,8 @@ constexpr int i(int n) {
   return m;
 }
 
-constexpr int g() { // expected-error {{constexpr function never produces a constant expression}}
-  goto test;        // expected-note {{subexpression not valid in a constant expression}} \
-           // expected-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++23}}
+constexpr int g() {
+  goto test; // expected-warning {{use of this statement in a constexpr function is incompatible with C++ standards before C++23}}
 test:
   return 0;
 }
@@ -29,9 +28,8 @@ struct NonLiteral { // expected-note 2 {{'NonLiteral' is not literal}}
   NonLiteral() {}
 };
 
-constexpr void non_literal() { // expected-error {{constexpr function never produces a constant expression}}
-  NonLiteral n;                // expected-note {{non-literal type 'NonLiteral' cannot be used in a constant expression}} \
-                               // expected-warning {{definition of a variable of non-literal type in a constexpr function is incompatible with C++ standards before C++23}}
+constexpr void non_literal() {
+  NonLiteral n; // expected-warning {{definition of a variable of non-literal type in a constexpr function is incompatible with C++ standards before C++23}}
 }
 
 constexpr void non_literal2(bool b) {
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
index 6214ff8006d67f31b3044a9bdc5e6e2a5e048b58..4416c825226494b413c6c5887af470ac9a322d92 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -fcxx-exceptions -verify=expected,beforecxx14,beforecxx20,beforecxx23 -std=c++11 %s
-// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,beforecxx20,beforecxx23 -std=c++14 %s
-// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20,beforecxx23 -std=c++20  %s
+// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,beforecxx20,beforecxx23,cxx14_20 -std=c++14 %s
+// RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20,beforecxx23,cxx14_20 -std=c++20  %s
 // RUN: %clang_cc1 -fcxx-exceptions -verify=expected,aftercxx14,aftercxx20 -std=c++23 %s
 
 namespace N {
@@ -11,7 +11,7 @@ namespace M {
   typedef double D;
 }
 
-struct NonLiteral { // expected-note 2{{no constexpr constructors}}
+struct NonLiteral { // beforecxx23-note 2{{no constexpr constructors}}
   NonLiteral() {}
   NonLiteral(int) {}
 };
@@ -43,7 +43,7 @@ struct T : SS, NonLiteral {
   //  - its return type shall be a literal type;
   // Once we support P2448R2 constexpr functions will be allowd to return non-literal types
   // The destructor will also be allowed
-  constexpr NonLiteral NonLiteralReturn() const { return {}; } // expected-error {{constexpr function's return type 'NonLiteral' is not a literal type}}
+  constexpr NonLiteral NonLiteralReturn() const { return {}; } // beforecxx23-error {{constexpr function's return type 'NonLiteral' is not a literal type}}
   constexpr void VoidReturn() const { return; }                // beforecxx14-error {{constexpr function's return type 'void' is not a literal type}}
   constexpr ~T();                                              // beforecxx20-error {{destructor cannot be declared constexpr}}
 
@@ -52,7 +52,7 @@ struct T : SS, NonLiteral {
 
   //  - each of its parameter types shall be a literal type;
   // Once we support P2448R2 constexpr functions will be allowd to have parameters of non-literal types
-  constexpr int NonLiteralParam(NonLiteral) const { return 0; } // expected-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}
+  constexpr int NonLiteralParam(NonLiteral) const { return 0; } // beforecxx23-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}
   typedef int G(NonLiteral) const;
   constexpr G NonLiteralParam2; // ok until definition
 
@@ -66,7 +66,7 @@ struct T : SS, NonLiteral {
   // constexpr since they can't be const.
   constexpr T &operator=(const T &) = default; // beforecxx14-error {{an explicitly-defaulted copy assignment operator may not have 'const', 'constexpr' or 'volatile' qualifiers}} \
                                                // beforecxx14-warning {{C++14}} \
-                                               // aftercxx14-error{{defaulted definition of copy assignment operator is not constexpr}}
+                                               // cxx14_20-error{{defaulted definition of copy assignment operator cannot be marked constexpr}}
 };
 
 constexpr int T::OutOfLineVirtual() const { return 0; }
@@ -229,9 +229,9 @@ namespace DR1364 {
     return k; // ok, even though lvalue-to-rvalue conversion of a function
               // parameter is not allowed in a constant expression.
   }
-  int kGlobal; // expected-note {{here}}
-  constexpr int f() { // expected-error {{constexpr function never produces a constant expression}}
-    return kGlobal;   // expected-note {{read of non-const}}
+  int kGlobal; // beforecxx23-note {{here}}
+  constexpr int f() { // beforecxx23-error {{constexpr function never produces a constant expression}}
+    return kGlobal;   // beforecxx23-note {{read of non-const}}
   }
 }
 
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
index f1f677ebfcd341430b18a56b3aee48f7943cc8b6..92698ec1c7387d63f33c163b973477acbd40d589 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
@@ -272,7 +272,7 @@ struct X {
 
 union XU1 { int a; constexpr XU1() = default; };
 #ifndef CXX2A
-// expected-error@-2{{not constexpr}}
+// expected-error@-2{{cannot be marked constexpr}}
 #endif
 union XU2 { int a = 1; constexpr XU2() = default; };
 
@@ -282,7 +282,7 @@ struct XU3 {
   };
   constexpr XU3() = default;
 #ifndef CXX2A
-  // expected-error@-2{{not constexpr}}
+  // expected-error@-2{{cannot be marked constexpr}}
 #endif
 };
 struct XU4 {
@@ -333,7 +333,7 @@ namespace CtorLookup {
     constexpr B(B&);
   };
   constexpr B::B(const B&) = default;
-  constexpr B::B(B&) = default; // expected-error {{not constexpr}}
+  constexpr B::B(B&) = default; // expected-error {{cannot be marked constexpr}}
 
   struct C {
     A a;
@@ -342,7 +342,7 @@ namespace CtorLookup {
     constexpr C(C&);
   };
   constexpr C::C(const C&) = default;
-  constexpr C::C(C&) = default; // expected-error {{not constexpr}}
+  constexpr C::C(C&) = default; // expected-error {{cannot be marked constexpr}}
 }
 
 namespace PR14503 {
diff --git a/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
index 5b525fc91aba1c0b6bef6453674aab773037a3b7..849594307390f488ec7e63ec7761c1a204ff0b72 100644
--- a/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
+++ b/clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp
@@ -3,7 +3,7 @@
 // An explicitly-defaulted function may be declared constexpr only if it would
 // have been implicitly declared as constexpr.
 struct S1 {
-  constexpr S1() = default; // expected-error {{defaulted definition of default constructor is not constexpr}}
+  constexpr S1() = default; // expected-error {{defaulted definition of default constructor cannot be marked constexpr}}
   constexpr S1(const S1&) = default;
   constexpr S1(S1&&) = default;
   constexpr S1 &operator=(const S1&) const = default; // expected-error {{explicitly-defaulted copy assignment operator may not have}}
@@ -18,8 +18,8 @@ struct NoCopyMove {
 };
 struct S2 {
   constexpr S2() = default;
-  constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor is not constexpr}}
-  constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor is not constexpr}}
+  constexpr S2(const S2&) = default; // expected-error {{defaulted definition of copy constructor cannot be marked constexpr}}
+  constexpr S2(S2&&) = default; // expected-error {{defaulted definition of move constructor cannot be marked}}
   NoCopyMove ncm;
 };
 
diff --git a/clang/test/CXX/drs/dr13xx.cpp b/clang/test/CXX/drs/dr13xx.cpp
index effdc53040d0b0083943998ffa8e87aa7138f2c1..d8e3b5d87bd149043e2b00062760ad7607018c5d 100644
--- a/clang/test/CXX/drs/dr13xx.cpp
+++ b/clang/test/CXX/drs/dr13xx.cpp
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-17,cxx11-14,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-17,cxx11-14,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-17,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-20,cxx11-17,cxx11-14,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-20,cxx11-17,cxx11-14,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-20,cxx11-17,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++20 %s -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
 // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
 // RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
 
@@ -485,11 +485,11 @@ namespace dr1358 { // dr1358: 3.1
   struct B : Virt {
     int member;
     constexpr B(NonLit u) : member(u) {}
-    // since-cxx11-error@-1 {{constexpr constructor's 1st parameter type 'NonLit' is not a literal type}}
-    //   since-cxx11-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+    // cxx11-20-error@-1 {{constexpr constructor's 1st parameter type 'NonLit' is not a literal type}}
+    //   cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
     constexpr NonLit f(NonLit u) const { return NonLit(); }
-    // since-cxx11-error@-1 {{constexpr function's return type 'NonLit' is not a literal type}}
-    //   since-cxx11-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+    // cxx11-20-error@-1 {{constexpr function's return type 'NonLit' is not a literal type}}
+    //   cxx11-20-note@#dr1358-NonLit {{'NonLit' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
   };
 #endif
 }
@@ -498,13 +498,13 @@ namespace dr1359 { // dr1359: 3.5
 #if __cplusplus >= 201103L
   union A { constexpr A() = default; };
   union B { constexpr B() = default; int a; }; // #dr1359-B
-  // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}}
+  // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr before C++23}}
   union C { constexpr C() = default; int a, b; }; // #dr1359-C
-  // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}} 
+  // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} 
   struct X { constexpr X() = default; union {}; };
   // since-cxx11-error@-1 {{declaration does not declare anything}}
   struct Y { constexpr Y() = default; union { int a; }; }; // #dr1359-Y
-  // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}}
+  // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}}
 
   constexpr A a = A();
   constexpr B b = B();
diff --git a/clang/test/CXX/drs/dr14xx.cpp b/clang/test/CXX/drs/dr14xx.cpp
index 58a2b3a0d0275d911b23a8b80ab393dc6fdeb47f..ed6dda731fd5187b96191e1fc73f45250cae0a3b 100644
--- a/clang/test/CXX/drs/dr14xx.cpp
+++ b/clang/test/CXX/drs/dr14xx.cpp
@@ -153,16 +153,16 @@ namespace dr1460 { // dr1460: 3.5
   namespace Defaulted {
     union A { constexpr A() = default; };
     union B { int n; constexpr B() = default; };
-    // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}}
+    // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}}
     union C { int n = 0; constexpr C() = default; };
     struct D { union {}; constexpr D() = default; };
     // expected-error@-1 {{declaration does not declare anything}}
     struct E { union { int n; }; constexpr E() = default; };
-    // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}}
+    // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}}
     struct F { union { int n = 0; }; constexpr F() = default; };
 
     struct G { union { int n = 0; }; union { int m; }; constexpr G() = default; };
-    // cxx11-17-error@-1 {{defaulted definition of default constructor is not constexpr}}
+    // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}}
     struct H {
       union {
         int n = 0;
diff --git a/clang/test/CXX/drs/dr15xx.cpp b/clang/test/CXX/drs/dr15xx.cpp
index ac503db625ba0e6af7708283f6b749ab04c3ec2a..195c0fa610d579fc1bf041363694bf902ec222fe 100644
--- a/clang/test/CXX/drs/dr15xx.cpp
+++ b/clang/test/CXX/drs/dr15xx.cpp
@@ -1,10 +1,10 @@
 // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11-14,cxx14-17 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,cxx11-14,cxx14-17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx20,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
 
 namespace dr1512 { // dr1512: 4
   void f(char *p) {
@@ -407,7 +407,7 @@ namespace dr1573 { // dr1573: 3.9
   B b(1, 'x', 4.0, "hello"); // ok
 
   // inherited constructor is effectively constexpr if the user-written constructor would be
-  struct C { C(); constexpr C(int) {} };
+  struct C { C(); constexpr C(int) {} }; // #dr1573-C
   struct D : C { using C::C; };
   constexpr D d = D(0); // ok
   struct E : C { using C::C; A a; }; // #dr1573-E
@@ -420,8 +420,11 @@ namespace dr1573 { // dr1573: 3.9
   struct F : C { using C::C; C c; }; // #dr1573-F
   constexpr F f = F(0);
   // since-cxx11-error@-1 {{constexpr variable 'f' must be initialized by a constant expression}}
-  //   since-cxx11-note@-2 {{constructor inherited from base class 'C' cannot be used in a constant expression; derived class cannot be implicitly initialized}}
-  //   since-cxx11-note@#dr1573-F {{declared here}}
+  //   cxx11-20-note@-2 {{constructor inherited from base class 'C' cannot be used in a constant expression; derived class cannot be implicitly initialized}}
+  //   since-cxx23-note@-3 {{in implicit initialization for inherited constructor of 'F'}}
+  //   since-cxx23-note@#dr1573-F {{non-constexpr constructor 'C' cannot be used in a constant expression}}
+  //   cxx11-20-note@#dr1573-F {{declared here}}
+  //   since-cxx23-note@#dr1573-C {{declared here}}
 
   // inherited constructor is effectively deleted if the user-written constructor would be
   struct G { G(int); };
diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp
index 2dd7d1502e59fb204f54572d2404451b3fab8be7..766c90d3bc7bda9ec619928b7245e051a04e8331 100644
--- a/clang/test/CXX/drs/dr16xx.cpp
+++ b/clang/test/CXX/drs/dr16xx.cpp
@@ -1,10 +1,10 @@
 // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,cxx11-20,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx23,since-cxx14,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
 
 #if __cplusplus == 199711L
 #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
@@ -256,12 +256,12 @@ namespace dr1658 { // dr1658: 5
     struct A { A(A&); };
     struct B : virtual A { virtual void f() = 0; };
     struct C : virtual A { virtual void f(); };
-    struct D : A { virtual void f() = 0; };
+    struct D : A { virtual void f() = 0; }; // since-cxx23-note {{previous declaration is here}}
 
     struct X {
       friend B::B(const B&) throw();
       friend C::C(C&);
-      friend D::D(D&);
+      friend D::D(D&); // since-cxx23-error {{non-constexpr declaration of 'D' follows constexpr declaration}}
     };
   }
 
@@ -350,8 +350,8 @@ namespace dr1684 { // dr1684: 3.6
   };
   constexpr int f(NonLiteral &) { return 0; }
   constexpr int f(NonLiteral) { return 0; }
-  // since-cxx11-error@-1 {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}
-  //   since-cxx11-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+  // cxx11-20-error@-1 {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}}
+  //   cxx11-20-note@#dr1684-struct {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
 #endif
 }
 
diff --git a/clang/test/CXX/drs/dr24xx.cpp b/clang/test/CXX/drs/dr24xx.cpp
index ae8dda3351f48ece4d060277f7f99629be262c3e..4534ed26e56d076831fe8a33a89a0af307b684e7 100644
--- a/clang/test/CXX/drs/dr24xx.cpp
+++ b/clang/test/CXX/drs/dr24xx.cpp
@@ -68,3 +68,64 @@ template struct X {};
 X<1> x;
 #endif
 }
+
+namespace dr2445 { // dr2445: 19
+#if __cplusplus >= 202002L
+  template  constexpr bool F = false;
+  template  struct A { };
+
+  template 
+  bool operator==(T, A);
+
+  template 
+  bool operator!=(A, U) {
+   static_assert(F, "Isn't this less specialized?");
+   return false;
+  }
+
+  bool f(A ax, A ay) { return ay != ax; }
+
+  template concept AlwaysTrue=true;
+  template  struct B {
+    template 
+    bool operator==(const B&)const;
+  };
+
+
+  template 
+  bool operator==(const B&,const B&) {
+   static_assert(F, "Isn't this less specialized?");
+   return false;
+  }
+
+  bool g(B bx, B by) { return bx == by; }
+
+  struct C{
+    template
+    int operator+(T){return 0;}
+    template
+    void operator-(T){}
+  };
+  template
+  void operator+(C&&,T){}
+  template
+  int operator-(C&&,T){return 0;}
+
+  void t(int* iptr){
+    int x1 = C{} + iptr;
+    int x2 = C{} - iptr;
+  }
+
+  struct D{
+    template
+    int operator+(T) volatile {return 1;}
+  };
+
+  template
+  void operator+(volatile D&,T) {}
+
+  int foo(volatile D& d){
+    return d + 1;
+  }
+#endif
+}
diff --git a/clang/test/CXX/drs/dr25xx.cpp b/clang/test/CXX/drs/dr25xx.cpp
index 9fc7cf59485caad3473073f14967ef1cb0b8ea0c..46532486e50e53efe52c43be5f2f0c6ce470f680 100644
--- a/clang/test/CXX/drs/dr25xx.cpp
+++ b/clang/test/CXX/drs/dr25xx.cpp
@@ -211,6 +211,32 @@ namespace dr2565 { // dr2565: 16 open 2023-06-07
 #endif
 }
 
+namespace dr2583 { // dr2583: 19
+#if __cplusplus >= 201103L
+struct A {
+  int i;
+  char c;
+};
+
+struct B {
+  int i;
+  alignas(8) char c;
+};
+
+union U {
+  A a;
+  B b;
+};
+
+union V {
+  A a;
+  alignas(64) B b;
+};
+
+static_assert(!__is_layout_compatible(A, B), "");
+static_assert(__is_layout_compatible(U, V), "");
+#endif
+} // namespace dr2583
 
 namespace dr2598 { // dr2598: 18
 #if __cplusplus >= 201103L
diff --git a/clang/test/CXX/drs/dr438.cpp b/clang/test/CXX/drs/dr438.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a6ed39b88c2420f5741993d675498d573247b334
--- /dev/null
+++ b/clang/test/CXX/drs/dr438.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+
+namespace dr438 { // dr438: 2.7
+
+void f() {
+  long A[2];
+  A[0] = 0;
+  A[A[0]] = 1;
+}
+
+} // namespace dr438
+
+// CHECK-LABEL: define {{.*}} void @dr438::f()()
+// CHECK:         [[A:%.+]] = alloca [2 x i64]
+// CHECK:         {{.+}} = getelementptr inbounds [2 x i64], ptr [[A]], i64 0, i64 0
+// CHECK:         [[ARRAYIDX1:%.+]] = getelementptr inbounds [2 x i64], ptr [[A]], i64 0, i64 0
+// CHECK-NEXT:    [[TEMPIDX:%.+]] = load i64, ptr [[ARRAYIDX1]]
+// CHECK-NEXT:    [[ARRAYIDX2:%.+]] = getelementptr inbounds [2 x i64], ptr [[A]], i64 0, i64 [[TEMPIDX]]
+// CHECK-LABEL: }
diff --git a/clang/test/CXX/drs/dr439.cpp b/clang/test/CXX/drs/dr439.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..46960af93bb9aaf012a9c1e93243bc5e71d36bbe
--- /dev/null
+++ b/clang/test/CXX/drs/dr439.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+
+namespace dr439 { // dr439: 2.7
+
+void f() {
+  int* p1 = new int;
+  const int* p2 = static_cast(static_cast(p1));
+  bool b = p1 == p2; // b will have the value true.
+}
+
+} // namespace dr439
+
+// We're checking that p2 was copied from p1, and then was carried over
+// to the comparison without change.
+
+// CHECK-LABEL: define {{.*}} void @dr439::f()()
+// CHECK:         [[P1:%.+]] = alloca ptr, align 8
+// CHECK-NEXT:    [[P2:%.+]] = alloca ptr, align 8
+// CHECK:         [[TEMP0:%.+]] = load ptr, ptr [[P1]]
+// CHECK-NEXT:    store ptr [[TEMP0:%.+]], ptr [[P2]]
+// CHECK-NEXT:    [[TEMP1:%.+]] = load ptr, ptr [[P1]]
+// CHECK-NEXT:    [[TEMP2:%.+]] = load ptr, ptr [[P2]]
+// CHECK-NEXT:    {{.*}} = icmp eq ptr [[TEMP1]], [[TEMP2]]
+// CHECK-LABEL: }
diff --git a/clang/test/CXX/drs/dr441.cpp b/clang/test/CXX/drs/dr441.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6504bba689d2251a1afc177da1aba0f71b96b5fb
--- /dev/null
+++ b/clang/test/CXX/drs/dr441.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+
+namespace dr441 { // dr441: 2.7
+
+struct A {
+  A() {}
+};
+
+A dynamic_init;
+int i;
+int& ir = i;
+int* ip = &i;
+
+} // namespace dr441
+
+// CHECK-DAG:   @dr441::dynamic_init = global %"struct.dr441::A" zeroinitializer
+// CHECK-DAG:   @dr441::i = global i32 0
+// CHECK-DAG:   @dr441::ir = constant ptr @dr441::i
+// CHECK-DAG:   @dr441::ip = global ptr @dr441::i
+// CHECK-DAG:   @llvm.global_ctors = appending global [{{.+}}] [{ {{.+}} } { {{.+}}, ptr @_GLOBAL__sub_I_dr441.cpp, {{.+}} }]
+
+// CHECK-LABEL: define {{.*}} void @__cxx_global_var_init()
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    call void @dr441::A::A()({{.*}} @dr441::dynamic_init)
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
+
+// CHECK-LABEL: define {{.*}} void @_GLOBAL__sub_I_dr441.cpp()
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    call void @__cxx_global_var_init()
+// CHECK-NEXT:    ret void
+// CHECK-NEXT:  }
diff --git a/clang/test/CXX/drs/dr462.cpp b/clang/test/CXX/drs/dr462.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2b268778ea10da049d00d7e65fb47148de25f29a
--- /dev/null
+++ b/clang/test/CXX/drs/dr462.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+
+#if __cplusplus == 199711L
+#define NOTHROW throw()
+#else
+#define NOTHROW noexcept(true)
+#endif
+
+namespace dr462 { // dr462: 2.7
+
+struct A {
+  ~A() NOTHROW {}
+};
+
+extern void full_expr_fence() NOTHROW;
+
+void f() {
+  const A& r = (3, A());
+  full_expr_fence();
+}
+
+} // namespace dr462
+
+// CHECK-LABEL: define {{.*}} void @dr462::f()()
+// CHECK:         call void @dr462::full_expr_fence()()
+// CHECK:         call void @dr462::A::~A()
+// CHECK-LABEL: }
diff --git a/clang/test/CXX/drs/dr492.cpp b/clang/test/CXX/drs/dr492.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f53f1cb54124048ed4684eb220f6558fd1acdfec
--- /dev/null
+++ b/clang/test/CXX/drs/dr492.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+
+#if __cplusplus == 199711L
+#define NOTHROW throw()
+#else
+#define NOTHROW noexcept(true)
+#endif
+
+namespace std {
+struct type_info {
+  const char* name() const NOTHROW;
+}; 
+}
+
+namespace dr492 { // dr492: 2.7
+
+void f() {
+  typeid(int).name();
+  typeid(const int).name();
+  typeid(volatile int).name();
+  typeid(const volatile int).name();
+}
+
+} // namespace dr492
+
+// CHECK-LABEL: define {{.*}} void @dr492::f()()
+// CHECK:         {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int)
+// CHECK-NEXT:    {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int)
+// CHECK-NEXT:    {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int)
+// CHECK-NEXT:    {{.*}} = call {{.*}} @std::type_info::name() const({{.*}} @typeinfo for int)
+// CHECK-LABEL: }
diff --git a/clang/test/CXX/drs/dr4xx.cpp b/clang/test/CXX/drs/dr4xx.cpp
index 612a152aec4c4d22f521d4fbd9692df093407379..343c4ee6f3344ed1bcee63fddbccc7f8692fbec2 100644
--- a/clang/test/CXX/drs/dr4xx.cpp
+++ b/clang/test/CXX/drs/dr4xx.cpp
@@ -698,9 +698,9 @@ namespace dr437 { // dr437: sup 1308
   };
 }
 
-// dr438 FIXME write a codegen test
-// dr439 FIXME write a codegen test
-// dr441 FIXME write a codegen test
+// dr438 is in dr438.cpp
+// dr439 is in dr439.cpp
+// dr441 is in dr441.cpp
 // dr442: sup 348
 // dr443: na
 
@@ -943,7 +943,7 @@ namespace dr460 { // dr460: yes
 }
 
 // dr461: na
-// dr462 FIXME write a codegen test
+// dr462 is in dr462.cpp
 // dr463: na
 // dr464: na
 // dr465: na
@@ -1089,7 +1089,7 @@ namespace dr474 { // dr474: 3.4
   }
 }
 
-// dr475 FIXME write a codegen test
+// dr475 FIXME write a libc++abi test
 
 namespace dr477 { // dr477: 3.5
   struct A {
@@ -1437,7 +1437,7 @@ namespace dr491 { // dr491: dup 413
   // expected-error@-1 {{excess elements in array initializer}}
 }
 
-// dr492 FIXME write a codegen test
+// dr492 is in dr492.cpp
 
 namespace dr493 { // dr493: dup 976
   struct X {
diff --git a/clang/test/CXX/drs/dr519.cpp b/clang/test/CXX/drs/dr519.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..67c01d95ef7c6f89e6a71b3c8c48107985dc915c
--- /dev/null
+++ b/clang/test/CXX/drs/dr519.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+
+namespace dr519 { // dr519: 2.7
+void f() {
+  int *a = 0;
+  void *v = a;
+  bool c1 = v == static_cast(0);
+
+  void *w = 0;
+  int *b = static_cast(w);
+  bool c2 = b == static_cast(0);
+}
+} // namespace dr519
+
+// We're checking that `null`s that were initially stored in `a` and `w`
+// are simply copied over all the way to respective comparisons with `null`.
+
+// CHECK-LABEL: define {{.*}} void @dr519::f()()
+// CHECK:         store ptr null, ptr [[A:%.+]],
+// CHECK-NEXT:    [[TEMP_A:%.+]] = load ptr, ptr [[A]] 
+// CHECK-NEXT:    store ptr [[TEMP_A]], ptr [[V:%.+]],
+// CHECK-NEXT:    [[TEMP_V:%.+]] = load ptr, ptr [[V]]
+// CHECK-NEXT:    {{.+}} = icmp eq ptr [[TEMP_V]], null
+
+// CHECK:         store ptr null, ptr [[W:%.+]],
+// CHECK-NEXT:    [[TEMP_W:%.+]] = load ptr, ptr [[W]] 
+// CHECK-NEXT:    store ptr [[TEMP_W]], ptr [[B:%.+]],
+// CHECK-NEXT:    [[TEMP_B:%.+]] = load ptr, ptr [[B]]
+// CHECK-NEXT:    {{.+}} = icmp eq ptr [[TEMP_B]], null
+// CHECK-LABEL: }
diff --git a/clang/test/CXX/drs/dr571.cpp b/clang/test/CXX/drs/dr571.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..19a85b7ddc3508a7929ae31196de2ae336ee6d3d
--- /dev/null
+++ b/clang/test/CXX/drs/dr571.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
+
+namespace dr571 { // dr571: 2.7
+  typedef int &ir;
+  int n;
+  const ir r = n;
+  // expected-warning@-1 {{'const' qualifier on reference type 'ir' (aka 'int &') has no effect}}
+  ir r2 = n;
+}
+
+// Entities have external linkage by default.
+
+// CHECK: @dr571::r = constant ptr @dr571::n
+// CHECK: @dr571::r2 = constant ptr @dr571::n
diff --git a/clang/test/CXX/drs/dr5xx.cpp b/clang/test/CXX/drs/dr5xx.cpp
index 0e1de342f6706f69dc8feebd47320b6695fe994a..426b368b390ae655ecfcc518f71bc65b3dc6819f 100644
--- a/clang/test/CXX/drs/dr5xx.cpp
+++ b/clang/test/CXX/drs/dr5xx.cpp
@@ -141,15 +141,7 @@ namespace dr518 { // dr518: yes c++11
   // cxx98-error@-1 {{commas at the end of enumerator lists are a C++11 extension}}
 }
 
-namespace dr519 { // dr519: yes
-// FIXME: Add a codegen test.
-#if __cplusplus >= 201103L
-#define fold(x) (__builtin_constant_p(x) ? (x) : (x))
-  int test[fold((int*)(void*)0) ? -1 : 1];
-#undef fold
-#endif
-}
-
+// dr519 is in dr519.cpp
 // dr520: na
 
 // dr521: no
@@ -800,14 +792,7 @@ namespace dr570 { // dr570: dup 633
   //   expected-note@#dr570-r {{previous definition is here}}
 }
 
-namespace dr571 { // dr571 unknown
-  // FIXME: Add a codegen test.
-  typedef int &ir;
-  int n;
-  // FIXME: Test if this has internal linkage.
-  const ir r = n;
-  // expected-warning@-1 {{'const' qualifier on reference type 'ir' (aka 'int &') has no effect}}
-}
+// dr571 is in dr571.cpp
 
 namespace dr572 { // dr572: yes
   enum E { a = 1, b = 2 };
diff --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp
index b35d3051ab554caa1a6d3d023a635429e809703b..190e05784f32be94b33f8a698937e4f110864909 100644
--- a/clang/test/CXX/drs/dr6xx.cpp
+++ b/clang/test/CXX/drs/dr6xx.cpp
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-17,cxx98-14,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
-// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx98-17,cxx11-17,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
-// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx98-17,cxx11-17,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
-// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx98-17,cxx11-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
-// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,cxx98-14,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,cxx98-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx11-20,cxx98-17,cxx11-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
+// RUN: %clang_cc1 -std=c++20 %s -verify=expected,cxx11-20,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
 // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking
 
 namespace dr600 { // dr600: 2.8
@@ -584,8 +584,8 @@ namespace dr647 { // dr647: 3.1
   struct C {
     constexpr C(NonLiteral);
     constexpr C(NonLiteral, int) {}
-    // since-cxx11-error@-1 {{constexpr constructor's 1st parameter type 'NonLiteral' is not a literal type}}
-    //   since-cxx11-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
+    // cxx11-20-error@-1 {{constexpr constructor's 1st parameter type 'NonLiteral' is not a literal type}}
+    //   cxx11-20-note@#dr647-NonLiteral {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors}}
     constexpr C() try {} catch (...) {}
     // cxx11-17-error@-1 {{function try block in constexpr constructor is a C++20 extension}}
     // cxx11-error@-2 {{use of this statement in a constexpr constructor is a C++14 extension}}
@@ -609,15 +609,15 @@ namespace dr647 { // dr647: 3.1
           d(0) {}
 
     constexpr E(int)
-    // since-cxx11-error@-1 {{constexpr constructor never produces a constant expression}}
-    //   since-cxx11-note@#dr647-int-d {{non-constexpr constructor 'D' cannot be used in a constant expression}}
-    //   since-cxx11-note@#dr647-D-float-ctor {{declared here}}
+    // cxx11-20-error@-1 {{constexpr constructor never produces a constant expression}}
+    //   cxx11-20-note@#dr647-int-d {{non-constexpr constructor 'D' cannot be used in a constant expression}}
+    //   cxx11-20-note@#dr647-D-float-ctor {{declared here}}
         : n(0),
           d(0.0f) {} // #dr647-int-d
     constexpr E(float f)
-    // since-cxx11-error@-1 {{never produces a constant expression}}
-    //   since-cxx11-note@#dr647-float-d {{non-constexpr constructor}}
-    //   since-cxx11-note@#dr647-D-float-ctor {{declared here}}
+    // cxx11-20-error@-1 {{never produces a constant expression}}
+    //   cxx11-20-note@#dr647-float-d {{non-constexpr constructor}}
+    //   cxx11-20-note@#dr647-D-float-ctor {{declared here}}
         : n(get()),
           d(D(0) + f) {} // #dr647-float-d
   };
diff --git a/clang/test/CXX/expr/expr.const/p5-26.cpp b/clang/test/CXX/expr/expr.const/p5-26.cpp
index de2afa71b4266955e910849bb067076eb1011ffb..3624b1e5a3e3dfce31ec5ff562fc50f34ae94cc6 100644
--- a/clang/test/CXX/expr/expr.const/p5-26.cpp
+++ b/clang/test/CXX/expr/expr.const/p5-26.cpp
@@ -5,11 +5,11 @@
 struct S {};
 struct T : S {} t;
 
-consteval void test() { // cxx23-error{{consteval function never produces a constant expression}}
+consteval void test() {
     void* a = &t;
     const void* b = &t;
     volatile void* c = &t;
-    (void)static_cast(a); //cxx23-note {{cast from 'void *' is not allowed in a constant expression in C++ standards before C++2c}}
+    (void)static_cast(a);
     (void)static_cast(a);
     (void)static_cast(a);
 
diff --git a/clang/test/CXX/special/class.copy/p13-0x.cpp b/clang/test/CXX/special/class.copy/p13-0x.cpp
index 16c8a4029cbac669dca3dbdac8e82df7e5abaa7d..013d5b56582380c1a9efb272740df7d04deef3de 100644
--- a/clang/test/CXX/special/class.copy/p13-0x.cpp
+++ b/clang/test/CXX/special/class.copy/p13-0x.cpp
@@ -125,7 +125,7 @@ namespace Mutable {
     mutable A a;
   };
   struct C {
-    constexpr C(const C &) = default; // expected-error {{not constexpr}}
+    constexpr C(const C &) = default; // expected-error {{cannot be marked constexpr}}
     A a;
   };
 }
diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp
index 085976b081332b1f583365d258b519384d74e523..974240c514846c31e7429dfe85068bc0d01b88cd 100644
--- a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp
+++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp
@@ -130,6 +130,15 @@ namespace non_ptr_ref_cv_qual {
   int (&test_conv_to_arr_1)[3] = ConvToArr(); // ok
   const int (&test_conv_to_arr_2)[3] = ConvToArr(); // ok, with qualification conversion
 
+  struct ConvToConstArr {
+    template 
+    operator const Arr &() { // expected-note {{candidate}}
+      static_assert(N == 3, "");
+    }
+  };
+  Arr &test_conv_to_const_arr_1 = ConvToConstArr(); // expected-error {{no viable}}
+  const Arr &test_conv_to_const_arr_2 = ConvToConstArr(); // ok
+
 #if __cplusplus >= 201702L
   template using Function = T(U...) noexcept(Noexcept);
   template struct ConvToFunction {
diff --git a/clang/test/CodeGen/LoongArch/intrinsic-la32.c b/clang/test/CodeGen/LoongArch/intrinsic-la32.c
index 93d54f511a9cd271695ec066c483ff87f0a03c09..eb3f8cbe7ac4cc252e715d09cc7e9847173f5035 100644
--- a/clang/test/CodeGen/LoongArch/intrinsic-la32.c
+++ b/clang/test/CodeGen/LoongArch/intrinsic-la32.c
@@ -169,8 +169,8 @@ unsigned int cpucfg(unsigned int a) {
 
 // LA32-LABEL: @rdtime(
 // LA32-NEXT:  entry:
-// LA32-NEXT:    [[TMP0:%.*]] = tail call { i32, i32 } asm sideeffect "rdtimeh.w $0, $1\0A\09", "=&r,=&r"() #[[ATTR1:[0-9]+]], !srcloc !2
-// LA32-NEXT:    [[TMP1:%.*]] = tail call { i32, i32 } asm sideeffect "rdtimel.w $0, $1\0A\09", "=&r,=&r"() #[[ATTR1]], !srcloc !3
+// LA32-NEXT:    [[TMP0:%.*]] = tail call { i32, i32 } asm sideeffect "rdtimeh.w $0, $1\0A\09", "=&r,=&r"() #[[ATTR1:[0-9]+]], !srcloc [[META2:![0-9]+]]
+// LA32-NEXT:    [[TMP1:%.*]] = tail call { i32, i32 } asm sideeffect "rdtimel.w $0, $1\0A\09", "=&r,=&r"() #[[ATTR1]], !srcloc [[META3:![0-9]+]]
 // LA32-NEXT:    ret void
 //
 void rdtime() {
@@ -201,13 +201,28 @@ void loongarch_movgr2fcsr(int a) {
   __builtin_loongarch_movgr2fcsr(1, a);
 }
 
-// CHECK-LABEL: @cacop_w(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    tail call void @llvm.loongarch.cacop.w(i32 1, i32 [[A:%.*]], i32 1024)
-// CHECK-NEXT:    tail call void @llvm.loongarch.cacop.w(i32 1, i32 [[A]], i32 1024)
-// CHECK-NEXT:    ret void
+// LA32-LABEL: @cacop_w(
+// LA32-NEXT:  entry:
+// LA32-NEXT:    tail call void @llvm.loongarch.cacop.w(i32 1, i32 [[A:%.*]], i32 1024)
+// LA32-NEXT:    tail call void @llvm.loongarch.cacop.w(i32 1, i32 [[A]], i32 1024)
+// LA32-NEXT:    ret void
 //
 void cacop_w(unsigned long int a) {
   __cacop_w(1, a, 1024);
   __builtin_loongarch_cacop_w(1, a, 1024);
 }
+
+// LA32-LABEL: @iocsrrd_h_result(
+// LA32-NEXT:  entry:
+// LA32-NEXT:    [[TMP0:%.*]] = tail call i32 @llvm.loongarch.iocsrrd.h(i32 [[A:%.*]])
+// LA32-NEXT:    [[CONV_I:%.*]] = trunc i32 [[TMP0]] to i16
+// LA32-NEXT:    [[TMP1:%.*]] = tail call i32 @llvm.loongarch.iocsrrd.h(i32 [[A]])
+// LA32-NEXT:    [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16
+// LA32-NEXT:    [[CONV3:%.*]] = add i16 [[TMP2]], [[CONV_I]]
+// LA32-NEXT:    ret i16 [[CONV3]]
+//
+unsigned short iocsrrd_h_result(unsigned int a) {
+  unsigned short b = __iocsrrd_h(a);
+  unsigned short c = __builtin_loongarch_iocsrrd_h(a);
+  return b+c;
+}
diff --git a/clang/test/CodeGen/LoongArch/intrinsic-la64.c b/clang/test/CodeGen/LoongArch/intrinsic-la64.c
index a740882eef5411cbb1940ce1538cbea12a672b2e..50ec358f546ec01ff1c08a3f9695ec701fca9ace 100644
--- a/clang/test/CodeGen/LoongArch/intrinsic-la64.c
+++ b/clang/test/CodeGen/LoongArch/intrinsic-la64.c
@@ -387,7 +387,7 @@ unsigned int cpucfg(unsigned int a) {
 
 // CHECK-LABEL: @rdtime_d(
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = tail call { i64, i64 } asm sideeffect "rdtime.d $0, $1\0A\09", "=&r,=&r"() #[[ATTR1:[0-9]+]], !srcloc !2
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call { i64, i64 } asm sideeffect "rdtime.d $0, $1\0A\09", "=&r,=&r"() #[[ATTR1:[0-9]+]], !srcloc [[META2:![0-9]+]]
 // CHECK-NEXT:    ret void
 //
 void rdtime_d() {
@@ -396,8 +396,8 @@ void rdtime_d() {
 
 // CHECK-LABEL: @rdtime(
 // CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = tail call { i32, i32 } asm sideeffect "rdtimeh.w $0, $1\0A\09", "=&r,=&r"() #[[ATTR1]], !srcloc !3
-// CHECK-NEXT:    [[TMP1:%.*]] = tail call { i32, i32 } asm sideeffect "rdtimel.w $0, $1\0A\09", "=&r,=&r"() #[[ATTR1]], !srcloc !4
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call { i32, i32 } asm sideeffect "rdtimeh.w $0, $1\0A\09", "=&r,=&r"() #[[ATTR1]], !srcloc [[META3:![0-9]+]]
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call { i32, i32 } asm sideeffect "rdtimel.w $0, $1\0A\09", "=&r,=&r"() #[[ATTR1]], !srcloc [[META4:![0-9]+]]
 // CHECK-NEXT:    ret void
 //
 void rdtime() {
@@ -427,3 +427,18 @@ void loongarch_movgr2fcsr(int a) {
   __movgr2fcsr(1, a);
   __builtin_loongarch_movgr2fcsr(1, a);
 }
+
+// CHECK-LABEL: @iocsrrd_h_result(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call i32 @llvm.loongarch.iocsrrd.h(i32 [[A:%.*]])
+// CHECK-NEXT:    [[CONV_I:%.*]] = trunc i32 [[TMP0]] to i16
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call i32 @llvm.loongarch.iocsrrd.h(i32 [[A]])
+// CHECK-NEXT:    [[TMP2:%.*]] = trunc i32 [[TMP1]] to i16
+// CHECK-NEXT:    [[CONV3:%.*]] = add i16 [[TMP2]], [[CONV_I]]
+// CHECK-NEXT:    ret i16 [[CONV3]]
+//
+unsigned short iocsrrd_h_result(unsigned int a) {
+  unsigned short b = __iocsrrd_h(a);
+  unsigned short c = __builtin_loongarch_iocsrrd_h(a);
+  return b+c;
+}
diff --git a/clang/test/CodeGen/SystemZ/atomic_fp_load_store.c b/clang/test/CodeGen/SystemZ/atomic_fp_load_store.c
new file mode 100644
index 0000000000000000000000000000000000000000..8a4383e92a1e50699b162ea783bffe4d6f4cad54
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/atomic_fp_load_store.c
@@ -0,0 +1,164 @@
+// RUN: %clang_cc1 -triple s390x-linux-gnu -O1 -emit-llvm %s -o - | FileCheck %s
+//
+// Test that floating point atomic stores and loads do not get casted to/from
+// integer.
+
+#include 
+
+_Atomic float Af;
+_Atomic double Ad;
+_Atomic long double Ald;
+
+//// Atomic stores of floating point values.
+void fun0(float Arg) {
+// CHECK-LABEL: @fun0
+// CHECK:       store atomic float %Arg, ptr @Af seq_cst, align 4
+  Af = Arg;
+}
+
+void fun1(double Arg) {
+// CHECK-LABEL: @fun1
+// CHECK:       store atomic double %Arg, ptr @Ad seq_cst, align 8
+  Ad = Arg;
+}
+
+void fun2(long double Arg) {
+// CHECK-LABEL: @fun2
+// CHECK:       store atomic fp128 %Arg, ptr @Ald seq_cst, align 16
+  Ald = Arg;
+}
+
+void fun3(_Atomic float *Dst, float Arg) {
+// CHECK-LABEL: @fun
+// CHECK:       store atomic float %Arg, ptr %Dst seq_cst, align 4
+  *Dst = Arg;
+}
+
+void fun4(_Atomic double *Dst, double Arg) {
+// CHECK-LABEL: @fun4
+// CHECK:       store atomic double %Arg, ptr %Dst seq_cst, align 8
+  *Dst = Arg;
+}
+
+void fun5(_Atomic long double *Dst, long double Arg) {
+// CHECK-LABEL: @fun5
+// CHECK:       store atomic fp128 %Arg, ptr %Dst seq_cst, align 16
+  *Dst = Arg;
+}
+
+//// Atomic loads of floating point values.
+float fun6() {
+// CHECK-LABEL: @fun6
+// CHECK:       %atomic-load = load atomic float, ptr @Af seq_cst, align 4
+  return Af;
+}
+
+float fun7() {
+// CHECK-LABEL: @fun7
+// CHECK:       %atomic-load = load atomic double, ptr @Ad seq_cst, align 8
+  return Ad;
+}
+
+float fun8() {
+// CHECK-LABEL: @fun8
+// CHECK:       %atomic-load = load atomic fp128, ptr @Ald seq_cst, align 16
+  return Ald;
+}
+
+float fun9(_Atomic float *Src) {
+// CHECK-LABEL: @fun9
+// CHECK:       %atomic-load = load atomic float, ptr %Src seq_cst, align 4
+  return *Src;
+}
+
+double fun10(_Atomic double *Src) {
+// CHECK-LABEL: @fun10
+// CHECK:       %atomic-load = load atomic double, ptr %Src seq_cst, align 8
+  return *Src;
+}
+
+long double fun11(_Atomic long double *Src) {
+// CHECK-LABEL: @fun11
+// CHECK:       %atomic-load = load atomic fp128, ptr %Src seq_cst, align 16
+  return *Src;
+}
+
+//// Same, but with 'volatile' as well:
+
+_Atomic volatile float Af_vol;
+_Atomic volatile double Ad_vol;
+_Atomic volatile long double Ald_vol;
+
+//// Atomic volatile stores of floating point values.
+void fun0_vol(float Arg) {
+// CHECK-LABEL: @fun0_vol
+// CHECK:       store atomic volatile float %Arg, ptr @Af_vol seq_cst, align 4
+  Af_vol = Arg;
+}
+
+void fun1_vol(double Arg) {
+// CHECK-LABEL: @fun1_vol
+// CHECK:       store atomic volatile double %Arg, ptr @Ad_vol seq_cst, align 8
+  Ad_vol = Arg;
+}
+
+void fun2_vol(long double Arg) {
+// CHECK-LABEL: @fun2_vol
+// CHECK:       store atomic volatile fp128 %Arg, ptr @Ald_vol seq_cst, align 16
+  Ald_vol = Arg;
+}
+
+void fun3_vol(_Atomic volatile float *Dst, float Arg) {
+// CHECK-LABEL: @fun3_vol
+// CHECK:       store atomic volatile float %Arg, ptr %Dst seq_cst, align 4
+  *Dst = Arg;
+}
+
+void fun4_vol(_Atomic volatile double *Dst, double Arg) {
+// CHECK-LABEL: @fun4_vol
+// CHECK:       store atomic volatile double %Arg, ptr %Dst seq_cst, align 8
+  *Dst = Arg;
+}
+
+void fun5_vol(_Atomic volatile long double *Dst, long double Arg) {
+// CHECK-LABEL: @fun5_vol
+// CHECK:       store atomic volatile fp128 %Arg, ptr %Dst seq_cst, align 16
+  *Dst = Arg;
+}
+
+//// Atomic volatile loads of floating point values.
+float fun6_vol() {
+// CHECK-LABEL: @fun6_vol
+// CHECK:       %atomic-load = load atomic volatile float, ptr @Af_vol seq_cst, align 4
+  return Af_vol;
+}
+
+float fun7_vol() {
+// CHECK-LABEL: @fun7_vol
+// CHECK:       %atomic-load = load atomic volatile double, ptr @Ad_vol seq_cst, align 8
+  return Ad_vol;
+}
+
+float fun8_vol() {
+// CHECK-LABEL: @fun8_vol
+// CHECK:       %atomic-load = load atomic volatile fp128, ptr @Ald_vol seq_cst, align 16
+  return Ald_vol;
+}
+
+float fun9_vol(_Atomic volatile float *Src) {
+// CHECK-LABEL: @fun9_vol
+// CHECK:       %atomic-load = load atomic volatile float, ptr %Src seq_cst, align 4
+  return *Src;
+}
+
+double fun10_vol(_Atomic volatile double *Src) {
+// CHECK-LABEL: @fun10_vol
+// CHECK:       %atomic-load = load atomic volatile double, ptr %Src seq_cst, align 8
+  return *Src;
+}
+
+long double fun11_vol(_Atomic volatile long double *Src) {
+// CHECK-LABEL: @fun11_vol
+// CHECK:       %atomic-load = load atomic volatile fp128, ptr %Src seq_cst, align 16
+  return *Src;
+}
diff --git a/clang/test/CodeGen/X86/attribute-cmpsd-no-error.c b/clang/test/CodeGen/X86/attribute-cmpsd-no-error.c
new file mode 100644
index 0000000000000000000000000000000000000000..a73d998155d0963c4fb3e987c83272cf78b634fe
--- /dev/null
+++ b/clang/test/CodeGen/X86/attribute-cmpsd-no-error.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown-emit-llvm -o /dev/null -verify
+// RUN: %clang_cc1 %s -ffreestanding -triple=i386-unknown-unknown-emit-llvm -o /dev/null -verify
+
+// expected-no-diagnostics
+
+#include 
+
+__attribute__((target("avx")))
+__m128 test(__m128 a, __m128 b) {
+  return _mm_cmp_ps(a, b, 14);
+}
diff --git a/clang/test/CodeGen/X86/avx-builtins.c b/clang/test/CodeGen/X86/avx-builtins.c
index d50366c3a022ccaf64bbc0eb1186e156e376b689..4bf1213d9fca97a9d59c7ff904631fde2e8f80ff 100644
--- a/clang/test/CodeGen/X86/avx-builtins.c
+++ b/clang/test/CodeGen/X86/avx-builtins.c
@@ -596,54 +596,6 @@ __m256 test_mm256_cmp_ps_true_us(__m256 a, __m256 b) {
   return _mm256_cmp_ps(a, b, _CMP_TRUE_US);
 }
 
-__m128d test_mm_cmp_pd_eq_oq(__m128d a, __m128d b) {
-  // CHECK-LABEL: test_mm_cmp_pd_eq_oq
-  // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}}
-  return _mm_cmp_pd(a, b, _CMP_EQ_OQ);
-}
-
-__m128d test_mm_cmp_pd_lt_os(__m128d a, __m128d b) {
-  // CHECK-LABEL: test_mm_cmp_pd_lt_os
-  // CHECK: fcmp olt <2 x double> %{{.*}}, %{{.*}}
-  return _mm_cmp_pd(a, b, _CMP_LT_OS);
-}
-
-__m128d test_mm_cmp_pd_le_os(__m128d a, __m128d b) {
-  // CHECK-LABEL: test_mm_cmp_pd_le_os
-  // CHECK: fcmp ole <2 x double> %{{.*}}, %{{.*}}
-  return _mm_cmp_pd(a, b, _CMP_LE_OS);
-}
-
-__m128d test_mm_cmp_pd_unord_q(__m128d a, __m128d b) {
-  // CHECK-LABEL: test_mm_cmp_pd_unord_q
-  // CHECK: fcmp uno <2 x double> %{{.*}}, %{{.*}}
-  return _mm_cmp_pd(a, b, _CMP_UNORD_Q);
-}
-
-__m128d test_mm_cmp_pd_neq_uq(__m128d a, __m128d b) {
-  // CHECK-LABEL: test_mm_cmp_pd_neq_uq
-  // CHECK: fcmp une <2 x double> %{{.*}}, %{{.*}}
-  return _mm_cmp_pd(a, b, _CMP_NEQ_UQ);
-}
-
-__m128d test_mm_cmp_pd_nlt_us(__m128d a, __m128d b) {
-  // CHECK-LABEL: test_mm_cmp_pd_nlt_us
-  // CHECK: fcmp uge <2 x double> %{{.*}}, %{{.*}}
-  return _mm_cmp_pd(a, b, _CMP_NLT_US);
-}
-
-__m128d test_mm_cmp_pd_nle_us(__m128d a, __m128d b) {
-  // CHECK-LABEL: test_mm_cmp_pd_nle_us
-  // CHECK: fcmp ugt <2 x double> %{{.*}}, %{{.*}}
-  return _mm_cmp_pd(a, b, _CMP_NLE_US);
-}
-
-__m128d test_mm_cmp_pd_ord_q(__m128d a, __m128d b) {
-  // CHECK-LABEL: test_mm_cmp_pd_ord_q
-  // CHECK: fcmp ord <2 x double> %{{.*}}, %{{.*}}
-  return _mm_cmp_pd(a, b, _CMP_ORD_Q);
-}
-
 __m128d test_mm_cmp_pd_eq_uq(__m128d a, __m128d b) {
   // CHECK-LABEL: test_mm_cmp_pd_eq_uq
   // CHECK: fcmp ueq <2 x double> %{{.*}}, %{{.*}}
@@ -788,54 +740,6 @@ __m128d test_mm_cmp_pd_true_us(__m128d a, __m128d b) {
   return _mm_cmp_pd(a, b, _CMP_TRUE_US);
 }
 
-__m128 test_mm_cmp_ps_eq_oq(__m128 a, __m128 b) {
-  // CHECK-LABEL: test_mm_cmp_ps_eq_oq
-  // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}}
-  return _mm_cmp_ps(a, b, _CMP_EQ_OQ);
-}
-
-__m128 test_mm_cmp_ps_lt_os(__m128 a, __m128 b) {
-  // CHECK-LABEL: test_mm_cmp_ps_lt_os
-  // CHECK: fcmp olt <4 x float> %{{.*}}, %{{.*}}
-  return _mm_cmp_ps(a, b, _CMP_LT_OS);
-}
-
-__m128 test_mm_cmp_ps_le_os(__m128 a, __m128 b) {
-  // CHECK-LABEL: test_mm_cmp_ps_le_os
-  // CHECK: fcmp ole <4 x float> %{{.*}}, %{{.*}}
-  return _mm_cmp_ps(a, b, _CMP_LE_OS);
-}
-
-__m128 test_mm_cmp_ps_unord_q(__m128 a, __m128 b) {
-  // CHECK-LABEL: test_mm_cmp_ps_unord_q
-  // CHECK: fcmp uno <4 x float> %{{.*}}, %{{.*}}
-  return _mm_cmp_ps(a, b, _CMP_UNORD_Q);
-}
-
-__m128 test_mm_cmp_ps_neq_uq(__m128 a, __m128 b) {
-  // CHECK-LABEL: test_mm_cmp_ps_neq_uq
-  // CHECK: fcmp une <4 x float> %{{.*}}, %{{.*}}
-  return _mm_cmp_ps(a, b, _CMP_NEQ_UQ);
-}
-
-__m128 test_mm_cmp_ps_nlt_us(__m128 a, __m128 b) {
-  // CHECK-LABEL: test_mm_cmp_ps_nlt_us
-  // CHECK: fcmp uge <4 x float> %{{.*}}, %{{.*}}
-  return _mm_cmp_ps(a, b, _CMP_NLT_US);
-}
-
-__m128 test_mm_cmp_ps_nle_us(__m128 a, __m128 b) {
-  // CHECK-LABEL: test_mm_cmp_ps_nle_us
-  // CHECK: fcmp ugt <4 x float> %{{.*}}, %{{.*}}
-  return _mm_cmp_ps(a, b, _CMP_NLE_US);
-}
-
-__m128 test_mm_cmp_ps_ord_q(__m128 a, __m128 b) {
-  // CHECK-LABEL: test_mm_cmp_ps_ord_q
-  // CHECK: fcmp ord <4 x float> %{{.*}}, %{{.*}}
-  return _mm_cmp_ps(a, b, _CMP_ORD_Q);
-}
-
 __m128 test_mm_cmp_ps_eq_uq(__m128 a, __m128 b) {
   // CHECK-LABEL: test_mm_cmp_ps_eq_uq
   // CHECK: fcmp ueq <4 x float> %{{.*}}, %{{.*}}
diff --git a/clang/test/CodeGen/X86/cmp-avx-builtins-error.c b/clang/test/CodeGen/X86/cmp-avx-builtins-error.c
new file mode 100644
index 0000000000000000000000000000000000000000..bad2606021b69e6e0f0ad19982d3eee17b517236
--- /dev/null
+++ b/clang/test/CodeGen/X86/cmp-avx-builtins-error.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 %s -ffreestanding -triple=x86_64-unknown-unknown \
+// RUN: -target-feature +avx -emit-llvm -fsyntax-only -verify
+// RUN: %clang_cc1 %s -ffreestanding -triple=i386-unknown-unknown \
+// RUN: -target-feature +avx -emit-llvm -fsyntax-only -verify
+
+#include 
+
+__m128d test_mm_cmp_pd(__m128d a, __m128d b) {
+  return _mm_cmp_pd(a, b, 32);  // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+}
+
+__m128d test_mm_cmp_sd(__m128d a, __m128d b) {
+  return _mm_cmp_sd(a, b, 32);  // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+}
+
+__m128 test_mm_cmp_ps(__m128 a, __m128 b) {
+  return _mm_cmp_ps(a, b, 32);  // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+}
+
+__m128 test_mm_cmp_ss(__m128 a, __m128 b) {
+  return _mm_cmp_ss(a, b, 32);  // expected-error {{argument value 32 is outside the valid range [0, 31]}}
+}
diff --git a/clang/test/CodeGen/X86/sse-builtins.c b/clang/test/CodeGen/X86/sse-builtins.c
index 830081296e52fb839738d9da3079596e9b765aea..aae5cfb8bb1d99376db66102dbe0480b998222d3 100644
--- a/clang/test/CodeGen/X86/sse-builtins.c
+++ b/clang/test/CodeGen/X86/sse-builtins.c
@@ -34,6 +34,60 @@ __m128 test_mm_andnot_ps(__m128 A, __m128 B) {
   return _mm_andnot_ps(A, B);
 }
 
+__m128 test_mm_cmp_ps_eq_oq(__m128 a, __m128 b) {
+  // CHECK-LABEL: test_mm_cmp_ps_eq_oq
+  // CHECK: fcmp oeq <4 x float> %{{.*}}, %{{.*}}
+  return _mm_cmp_ps(a, b, _CMP_EQ_OQ);
+}
+
+__m128 test_mm_cmp_ps_lt_os(__m128 a, __m128 b) {
+  // CHECK-LABEL: test_mm_cmp_ps_lt_os
+  // CHECK: fcmp olt <4 x float> %{{.*}}, %{{.*}}
+  return _mm_cmp_ps(a, b, _CMP_LT_OS);
+}
+
+__m128 test_mm_cmp_ps_le_os(__m128 a, __m128 b) {
+  // CHECK-LABEL: test_mm_cmp_ps_le_os
+  // CHECK: fcmp ole <4 x float> %{{.*}}, %{{.*}}
+  return _mm_cmp_ps(a, b, _CMP_LE_OS);
+}
+
+__m128 test_mm_cmp_ps_unord_q(__m128 a, __m128 b) {
+  // CHECK-LABEL: test_mm_cmp_ps_unord_q
+  // CHECK: fcmp uno <4 x float> %{{.*}}, %{{.*}}
+  return _mm_cmp_ps(a, b, _CMP_UNORD_Q);
+}
+
+__m128 test_mm_cmp_ps_neq_uq(__m128 a, __m128 b) {
+  // CHECK-LABEL: test_mm_cmp_ps_neq_uq
+  // CHECK: fcmp une <4 x float> %{{.*}}, %{{.*}}
+  return _mm_cmp_ps(a, b, _CMP_NEQ_UQ);
+}
+
+__m128 test_mm_cmp_ps_nlt_us(__m128 a, __m128 b) {
+  // CHECK-LABEL: test_mm_cmp_ps_nlt_us
+  // CHECK: fcmp uge <4 x float> %{{.*}}, %{{.*}}
+  return _mm_cmp_ps(a, b, _CMP_NLT_US);
+}
+
+__m128 test_mm_cmp_ps_nle_us(__m128 a, __m128 b) {
+  // CHECK-LABEL: test_mm_cmp_ps_nle_us
+  // CHECK: fcmp ugt <4 x float> %{{.*}}, %{{.*}}
+  return _mm_cmp_ps(a, b, _CMP_NLE_US);
+}
+
+__m128 test_mm_cmp_ps_ord_q(__m128 a, __m128 b) {
+  // CHECK-LABEL: test_mm_cmp_ps_ord_q
+  // CHECK: fcmp ord <4 x float> %{{.*}}, %{{.*}}
+  return _mm_cmp_ps(a, b, _CMP_ORD_Q);
+}
+
+__m128 test_mm_cmp_ss(__m128 A, __m128 B) {
+  // CHECK-LABEL: test_mm_cmp_ss
+  // CHECK: call <4 x float> @llvm.x86.sse.cmp.ss(<4 x float> %{{.*}}, <4 x float> %{{.*}}, i8 7)
+  return _mm_cmp_ss(A, B, _CMP_ORD_Q);
+}
+
 __m128 test_mm_cmpeq_ps(__m128 __a, __m128 __b) {
   // CHECK-LABEL: test_mm_cmpeq_ps
   // CHECK:         [[CMP:%.*]] = fcmp oeq <4 x float>
diff --git a/clang/test/CodeGen/X86/sse2-builtins.c b/clang/test/CodeGen/X86/sse2-builtins.c
index 44b2e485a5bd85eeead9be1e261676c893f93bc1..3ca7777e763359ede47544926149b77e9ec42d0f 100644
--- a/clang/test/CodeGen/X86/sse2-builtins.c
+++ b/clang/test/CodeGen/X86/sse2-builtins.c
@@ -160,6 +160,60 @@ void test_mm_clflush(void* A) {
   _mm_clflush(A);
 }
 
+__m128d test_mm_cmp_pd_eq_oq(__m128d a, __m128d b) {
+  // CHECK-LABEL: test_mm_cmp_pd_eq_oq
+  // CHECK: fcmp oeq <2 x double> %{{.*}}, %{{.*}}
+  return _mm_cmp_pd(a, b, _CMP_EQ_OQ);
+}
+
+__m128d test_mm_cmp_pd_lt_os(__m128d a, __m128d b) {
+  // CHECK-LABEL: test_mm_cmp_pd_lt_os
+  // CHECK: fcmp olt <2 x double> %{{.*}}, %{{.*}}
+  return _mm_cmp_pd(a, b, _CMP_LT_OS);
+}
+
+__m128d test_mm_cmp_pd_le_os(__m128d a, __m128d b) {
+  // CHECK-LABEL: test_mm_cmp_pd_le_os
+  // CHECK: fcmp ole <2 x double> %{{.*}}, %{{.*}}
+  return _mm_cmp_pd(a, b, _CMP_LE_OS);
+}
+
+__m128d test_mm_cmp_pd_unord_q(__m128d a, __m128d b) {
+  // CHECK-LABEL: test_mm_cmp_pd_unord_q
+  // CHECK: fcmp uno <2 x double> %{{.*}}, %{{.*}}
+  return _mm_cmp_pd(a, b, _CMP_UNORD_Q);
+}
+
+__m128d test_mm_cmp_pd_neq_uq(__m128d a, __m128d b) {
+  // CHECK-LABEL: test_mm_cmp_pd_neq_uq
+  // CHECK: fcmp une <2 x double> %{{.*}}, %{{.*}}
+  return _mm_cmp_pd(a, b, _CMP_NEQ_UQ);
+}
+
+__m128d test_mm_cmp_pd_nlt_us(__m128d a, __m128d b) {
+  // CHECK-LABEL: test_mm_cmp_pd_nlt_us
+  // CHECK: fcmp uge <2 x double> %{{.*}}, %{{.*}}
+  return _mm_cmp_pd(a, b, _CMP_NLT_US);
+}
+
+__m128d test_mm_cmp_pd_nle_us(__m128d a, __m128d b) {
+  // CHECK-LABEL: test_mm_cmp_pd_nle_us
+  // CHECK: fcmp ugt <2 x double> %{{.*}}, %{{.*}}
+  return _mm_cmp_pd(a, b, _CMP_NLE_US);
+}
+
+__m128d test_mm_cmp_pd_ord_q(__m128d a, __m128d b) {
+  // CHECK-LABEL: test_mm_cmp_pd_ord_q
+  // CHECK: fcmp ord <2 x double> %{{.*}}, %{{.*}}
+  return _mm_cmp_pd(a, b, _CMP_ORD_Q);
+}
+
+__m128d test_mm_cmp_sd(__m128d A, __m128d B) {
+  // CHECK-LABEL: test_mm_cmp_sd
+  // CHECK: call <2 x double> @llvm.x86.sse2.cmp.sd(<2 x double> %{{.*}}, <2 x double> %{{.*}}, i8 7)
+  return _mm_cmp_sd(A, B, _CMP_ORD_Q);
+}
+
 __m128i test_mm_cmpeq_epi8(__m128i A, __m128i B) {
   // CHECK-LABEL: test_mm_cmpeq_epi8
   // CHECK: icmp eq <16 x i8>
diff --git a/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_dupq.c b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_dupq.c
new file mode 100644
index 0000000000000000000000000000000000000000..587a67aa6b7ca2fa89a29f293256ad7c9c6df75e
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_dupq.c
@@ -0,0 +1,213 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2
+// REQUIRES: aarch64-registered-target
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -target-feature +bf16\
+// RUN:   -S -Werror -emit-llvm -disable-O0-optnone -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -target-feature +bf16\
+// RUN:   -S -Werror -emit-llvm -disable-O0-optnone -o - %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -target-feature +bf16\
+// RUN:   -S -Werror -emit-llvm -disable-O0-optnone -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2p1 -target-feature +bf16\
+// RUN:   -S -Werror -emit-llvm -disable-O0-optnone -o - -x c++ %s | opt -S -p mem2reg,instcombine,tailcallelim | FileCheck %s -check-prefix=CPP-CHECK
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve2p1 -target-feature +bf16 -S -disable-O0-optnone -Werror -Wall -o /dev/null %s
+
+
+#include 
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1, A2_UNUSED) A1
+#else
+#define SVE_ACLE_FUNC(A1, A2) A1##A2
+#endif
+
+// CHECK-LABEL: define dso_local  @test_svdup_laneq_s8
+// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv16i8( [[ZN]], i32 0)
+// CHECK-NEXT:    ret  [[TMP0]]
+//
+// CPP-CHECK-LABEL: define dso_local  @_Z19test_svdup_laneq_s8u10__SVInt8_t
+// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0:[0-9]+]] {
+// CPP-CHECK-NEXT:  entry:
+// CPP-CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv16i8( [[ZN]], i32 0)
+// CPP-CHECK-NEXT:    ret  [[TMP0]]
+//
+svint8_t test_svdup_laneq_s8(svint8_t zn) {
+    return SVE_ACLE_FUNC(svdup_laneq, _s8)(zn, 0);
+}
+
+// CHECK-LABEL: define dso_local  @test_svdup_laneq_u8
+// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv16i8( [[ZN]], i32 15)
+// CHECK-NEXT:    ret  [[TMP0]]
+//
+// CPP-CHECK-LABEL: define dso_local  @_Z19test_svdup_laneq_u8u11__SVUint8_t
+// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT:  entry:
+// CPP-CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv16i8( [[ZN]], i32 15)
+// CPP-CHECK-NEXT:    ret  [[TMP0]]
+//
+svuint8_t test_svdup_laneq_u8(svuint8_t zn) {
+    return SVE_ACLE_FUNC(svdup_laneq, _u8)(zn, 15);
+}
+
+// CHECK-LABEL: define dso_local  @test_svdup_laneq_s16
+// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv8i16( [[ZN]], i32 1)
+// CHECK-NEXT:    ret  [[TMP0]]
+//
+// CPP-CHECK-LABEL: define dso_local  @_Z20test_svdup_laneq_s16u11__SVInt16_t
+// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT:  entry:
+// CPP-CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv8i16( [[ZN]], i32 1)
+// CPP-CHECK-NEXT:    ret  [[TMP0]]
+//
+svint16_t test_svdup_laneq_s16(svint16_t zn) {
+    return SVE_ACLE_FUNC(svdup_laneq, _s16)(zn, 1);
+}
+
+// CHECK-LABEL: define dso_local  @test_svdup_laneq_u16
+// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv8i16( [[ZN]], i32 7)
+// CHECK-NEXT:    ret  [[TMP0]]
+//
+// CPP-CHECK-LABEL: define dso_local  @_Z20test_svdup_laneq_u16u12__SVUint16_t
+// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT:  entry:
+// CPP-CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv8i16( [[ZN]], i32 7)
+// CPP-CHECK-NEXT:    ret  [[TMP0]]
+//
+svuint16_t test_svdup_laneq_u16(svuint16_t zn) {
+    return SVE_ACLE_FUNC(svdup_laneq, _u16)(zn, 7);
+}
+
+// CHECK-LABEL: define dso_local  @test_svdup_laneq_s32
+// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv4i32( [[ZN]], i32 2)
+// CHECK-NEXT:    ret  [[TMP0]]
+//
+// CPP-CHECK-LABEL: define dso_local  @_Z20test_svdup_laneq_s32u11__SVInt32_t
+// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT:  entry:
+// CPP-CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv4i32( [[ZN]], i32 2)
+// CPP-CHECK-NEXT:    ret  [[TMP0]]
+//
+svint32_t test_svdup_laneq_s32(svint32_t zn) {
+    return SVE_ACLE_FUNC(svdup_laneq, _s32)(zn, 2);
+}
+
+// CHECK-LABEL: define dso_local  @test_svdup_laneq_u32
+// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv4i32( [[ZN]], i32 3)
+// CHECK-NEXT:    ret  [[TMP0]]
+//
+// CPP-CHECK-LABEL: define dso_local  @_Z20test_svdup_laneq_u32u12__SVUint32_t
+// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT:  entry:
+// CPP-CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv4i32( [[ZN]], i32 3)
+// CPP-CHECK-NEXT:    ret  [[TMP0]]
+//
+svuint32_t test_svdup_laneq_u32(svuint32_t zn) {
+    return SVE_ACLE_FUNC(svdup_laneq, _u32)(zn, 3);
+}
+
+// CHECK-LABEL: define dso_local  @test_svdup_laneq_s64
+// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv2i64( [[ZN]], i32 0)
+// CHECK-NEXT:    ret  [[TMP0]]
+//
+// CPP-CHECK-LABEL: define dso_local  @_Z20test_svdup_laneq_s64u11__SVInt64_t
+// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT:  entry:
+// CPP-CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv2i64( [[ZN]], i32 0)
+// CPP-CHECK-NEXT:    ret  [[TMP0]]
+//
+svint64_t test_svdup_laneq_s64(svint64_t zn) {
+    return SVE_ACLE_FUNC(svdup_laneq, _s64)(zn, 0);
+}
+
+// CHECK-LABEL: define dso_local  @test_svdup_laneq_u64
+// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv2i64( [[ZN]], i32 1)
+// CHECK-NEXT:    ret  [[TMP0]]
+//
+// CPP-CHECK-LABEL: define dso_local  @_Z20test_svdup_laneq_u64u12__SVUint64_t
+// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT:  entry:
+// CPP-CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv2i64( [[ZN]], i32 1)
+// CPP-CHECK-NEXT:    ret  [[TMP0]]
+//
+svuint64_t test_svdup_laneq_u64(svuint64_t zn) {
+    return SVE_ACLE_FUNC(svdup_laneq, _u64)(zn, 1);
+}
+
+// CHECK-LABEL: define dso_local  @test_svdup_laneq_f16
+// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv8f16( [[ZN]], i32 4)
+// CHECK-NEXT:    ret  [[TMP0]]
+//
+// CPP-CHECK-LABEL: define dso_local  @_Z20test_svdup_laneq_f16u13__SVFloat16_t
+// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT:  entry:
+// CPP-CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv8f16( [[ZN]], i32 4)
+// CPP-CHECK-NEXT:    ret  [[TMP0]]
+//
+svfloat16_t test_svdup_laneq_f16(svfloat16_t zn) {
+    return SVE_ACLE_FUNC(svdup_laneq, _f16)(zn, 4);
+}
+
+// CHECK-LABEL: define dso_local  @test_svdup_laneq_f32
+// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv4f32( [[ZN]], i32 1)
+// CHECK-NEXT:    ret  [[TMP0]]
+//
+// CPP-CHECK-LABEL: define dso_local  @_Z20test_svdup_laneq_f32u13__SVFloat32_t
+// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT:  entry:
+// CPP-CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv4f32( [[ZN]], i32 1)
+// CPP-CHECK-NEXT:    ret  [[TMP0]]
+//
+svfloat32_t test_svdup_laneq_f32(svfloat32_t zn) {
+    return SVE_ACLE_FUNC(svdup_laneq, _f32)(zn, 1);
+}
+
+// CHECK-LABEL: define dso_local  @test_svdup_laneq_f64
+// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv2f64( [[ZN]], i32 1)
+// CHECK-NEXT:    ret  [[TMP0]]
+//
+// CPP-CHECK-LABEL: define dso_local  @_Z20test_svdup_laneq_f64u13__SVFloat64_t
+// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT:  entry:
+// CPP-CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv2f64( [[ZN]], i32 1)
+// CPP-CHECK-NEXT:    ret  [[TMP0]]
+//
+svfloat64_t test_svdup_laneq_f64(svfloat64_t zn) {
+    return SVE_ACLE_FUNC(svdup_laneq, _f64)(zn, 1);
+}
+
+// CHECK-LABEL: define dso_local  @test_svdup_laneq_bf16
+// CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv8bf16( [[ZN]], i32 3)
+// CHECK-NEXT:    ret  [[TMP0]]
+//
+// CPP-CHECK-LABEL: define dso_local  @_Z21test_svdup_laneq_bf16u14__SVBfloat16_t
+// CPP-CHECK-SAME: ( [[ZN:%.*]]) #[[ATTR0]] {
+// CPP-CHECK-NEXT:  entry:
+// CPP-CHECK-NEXT:    [[TMP0:%.*]] = tail call  @llvm.aarch64.sve.dup.laneq.nxv8bf16( [[ZN]], i32 3)
+// CPP-CHECK-NEXT:    ret  [[TMP0]]
+//
+svbfloat16_t test_svdup_laneq_bf16(svbfloat16_t zn) {
+    return SVE_ACLE_FUNC(svdup_laneq, _bf16)(zn, 3);
+}
diff --git a/clang/test/CodeGen/atomic.c b/clang/test/CodeGen/atomic.c
index 9143bedab906160ddc792c1e489c308adc5548d2..af5c056bbfe6e8ad4cb4679a35c70796d5267584 100644
--- a/clang/test/CodeGen/atomic.c
+++ b/clang/test/CodeGen/atomic.c
@@ -145,6 +145,5 @@ void force_global_uses(void) {
   (void)glob_int;
   // CHECK: load atomic i32, ptr @[[GLOB_INT]] seq_cst
   (void)glob_flt;
-  // CHECK: %[[LOCAL_FLT:.+]] = load atomic i32, ptr @[[GLOB_FLT]] seq_cst
-  // CHECK-NEXT: bitcast i32 %[[LOCAL_FLT]] to float
+  // CHECK: load atomic float, ptr @[[GLOB_FLT]] seq_cst
 }
diff --git a/clang/test/CodeGen/attr-availability-visionos.c b/clang/test/CodeGen/attr-availability-visionos.c
new file mode 100644
index 0000000000000000000000000000000000000000..09b98fb4a7d5e3d54fcd11f17c3ae7ba154ab09b
--- /dev/null
+++ b/clang/test/CodeGen/attr-availability-visionos.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple arm64-apple-xros1 -emit-llvm -o - %s 2>&1 | FileCheck %s
+
+__attribute__((availability(visionOS, introduced=1.1)))
+void introduced_1_1();
+
+void use() {
+  if (__builtin_available(visionOS 1.2, *))
+    introduced_1_1();
+  // CHECK: call i32 @__isPlatformVersionAtLeast(i32 11, i32 1, i32 2, i32 0)
+}
diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c
index 56a42499d0a7ca0857e5ff303650b8a79d93a9db..b7112c783da913726d5c8404ebb96d1d3ccdd988 100644
--- a/clang/test/CodeGen/attr-target-version.c
+++ b/clang/test/CodeGen/attr-target-version.c
@@ -94,16 +94,16 @@ int hoo(void) {
 // CHECK: @fmv_one.ifunc = weak_odr alias i32 (), ptr @fmv_one
 // CHECK: @fmv_two.ifunc = weak_odr alias i32 (), ptr @fmv_two
 // CHECK: @fmv_e.ifunc = weak_odr alias i32 (), ptr @fmv_e
+// CHECK: @fmv_c.ifunc = weak_odr alias void (), ptr @fmv_c
 // CHECK: @fmv_inline.ifunc = weak_odr alias i32 (), ptr @fmv_inline
 // CHECK: @fmv_d.ifunc = internal alias i32 (), ptr @fmv_d
-// CHECK: @fmv_c.ifunc = weak_odr alias void (), ptr @fmv_c
 // CHECK: @fmv = weak_odr ifunc i32 (), ptr @fmv.resolver
 // CHECK: @fmv_one = weak_odr ifunc i32 (), ptr @fmv_one.resolver
 // CHECK: @fmv_two = weak_odr ifunc i32 (), ptr @fmv_two.resolver
 // CHECK: @fmv_e = weak_odr ifunc i32 (), ptr @fmv_e.resolver
+// CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver
 // CHECK: @fmv_inline = weak_odr ifunc i32 (), ptr @fmv_inline.resolver
 // CHECK: @fmv_d = internal ifunc i32 (), ptr @fmv_d.resolver
-// CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver
 //.
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv._MflagmMfp16fmlMrng
@@ -238,11 +238,18 @@ int hoo(void) {
 // CHECK-NEXT:    ret i32 111
 //
 //
-// CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs
-// CHECK-SAME: () #[[ATTR2]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    ret void
+// CHECK-LABEL: define {{[^@]+}}@fmv_c.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]], 281474976710656
+// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656
+// 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_c._Mssbs
+// CHECK:       resolver_else:
+// CHECK-NEXT:    ret ptr @fmv_c.default
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
@@ -266,7 +273,7 @@ int hoo(void) {
 // 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._MfcmaMfp16Mfp16MrdmMsme
+// CHECK-NEXT:    ret ptr @fmv_inline._MfcmaMfp16MrdmMsme
 // CHECK:       resolver_else:
 // CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 864726312827224064
@@ -405,20 +412,6 @@ int hoo(void) {
 // CHECK-NEXT:    ret ptr @fmv_d.default
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv_c.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]], 281474976710656
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 281474976710656
-// 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_c._Mssbs
-// CHECK:       resolver_else:
-// CHECK-NEXT:    ret ptr @fmv_c.default
-//
-//
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@recur
 // CHECK-SAME: () #[[ATTR2]] {
@@ -568,6 +561,20 @@ int hoo(void) {
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@fmv_c.default
+// CHECK-SAME: () #[[ATTR2]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    ret void
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@fmv_c._Mssbs
+// CHECK-SAME: () #[[ATTR2]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    ret void
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mf64mmMpmullMsha1
 // CHECK-SAME: () #[[ATTR12:[0-9]+]] {
 // CHECK-NEXT:  entry:
@@ -575,7 +582,7 @@ int hoo(void) {
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfcmaMfp16Mfp16MrdmMsme
+// CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfcmaMfp16MrdmMsme
 // CHECK-SAME: () #[[ATTR13:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 2
@@ -700,13 +707,6 @@ int hoo(void) {
 // CHECK-NEXT:    ret i32 1
 //
 //
-// CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_c.default
-// CHECK-SAME: () #[[ATTR2]] {
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    ret void
-//
-//
 // CHECK-NOFMV: Function Attrs: noinline nounwind optnone
 // CHECK-NOFMV-LABEL: define {{[^@]+}}@fmv
 // CHECK-NOFMV-SAME: () #[[ATTR0:[0-9]+]] {
diff --git a/clang/test/CodeGen/c11atomics-ios.c b/clang/test/CodeGen/c11atomics-ios.c
index bcb6519ab0dc818a622f710aa1ab8f213051d353..811820b67fbdbf23d1073a37f8671fb82294c82a 100644
--- a/clang/test/CodeGen/c11atomics-ios.c
+++ b/clang/test/CodeGen/c11atomics-ios.c
@@ -19,15 +19,13 @@ void testFloat(_Atomic(float) *fp) {
   _Atomic(float) x = 2.0f;
 
 // CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[FP]]
-// CHECK-NEXT: [[T2:%.*]] = load atomic i32, ptr [[T0]] seq_cst, align 4
-// CHECK-NEXT: [[T3:%.*]] = bitcast i32 [[T2]] to float
-// CHECK-NEXT: store float [[T3]], ptr [[F]]
+// CHECK-NEXT: [[T2:%.*]] = load atomic float, ptr [[T0]] seq_cst, align 4
+// CHECK-NEXT: store float [[T2]], ptr [[F]]
   float f = *fp;
 
 // CHECK-NEXT: [[T0:%.*]] = load float, ptr [[F]], align 4
 // CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[FP]], align 4
-// CHECK-NEXT: [[T2:%.*]] = bitcast float [[T0]] to i32
-// CHECK-NEXT: store atomic i32 [[T2]], ptr [[T1]] seq_cst, align 4
+// CHECK-NEXT: store atomic float [[T0]], ptr [[T1]] seq_cst, align 4
   *fp = f;
 
 // CHECK-NEXT: ret void
diff --git a/clang/test/CodeGen/remote-traps.c b/clang/test/CodeGen/remote-traps.c
new file mode 100644
index 0000000000000000000000000000000000000000..6751afb96d25f2572f456c52d3f291b205e8d74e
--- /dev/null
+++ b/clang/test/CodeGen/remote-traps.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -O1 -emit-llvm -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow %s -o - | FileCheck %s 
+// RUN: %clang_cc1 -O1 -emit-llvm -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -mllvm -clang-remove-traps -mllvm -remove-traps-random-rate=1 %s -o - | FileCheck %s --implicit-check-not="call void @llvm.ubsantrap" --check-prefixes=REMOVE
+
+int test(int x) {
+  return x + 123;
+}
+
+// CHECK-LABEL: define {{.*}}i32 @test(
+// CHECK: call { i32, i1 } @llvm.sadd.with.overflow.i32(
+// CHECK: trap:
+// CHECK-NEXT: call void @llvm.ubsantrap(i8 0)
+// CHECK-NEXT: unreachable
+
+// REMOVE-LABEL: define {{.*}}i32 @test(
+// REMOVE: call { i32, i1 } @llvm.sadd.with.overflow.i32(
diff --git a/clang/test/CodeGen/target-features-error-2.c b/clang/test/CodeGen/target-features-error-2.c
index 60586fb57f1c04486ab72032c89bfc21187af12e..1599b0135b747f981da0c4a9c05a2c3e67b51a5d 100644
--- a/clang/test/CodeGen/target-features-error-2.c
+++ b/clang/test/CodeGen/target-features-error-2.c
@@ -15,7 +15,7 @@ int baz(__m256i a) {
 
 #if NEED_AVX_2
 __m128 need_avx(__m128 a, __m128 b) {
-  return _mm_cmp_ps(a, b, 0); // expected-error {{'__builtin_ia32_cmpps' needs target feature avx}}
+  return _mm_cmp_ps(a, b, 8); // expected-error {{'__builtin_ia32_cmpps' needs target feature avx}}
 }
 #endif
 
diff --git a/clang/test/CodeGen/tbaa-struct-relaxed-aliasing-with-tsan.cpp b/clang/test/CodeGen/tbaa-struct-relaxed-aliasing-with-tsan.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ce613b9d6b23f8016a97bb43c3425badf11b2ec7
--- /dev/null
+++ b/clang/test/CodeGen/tbaa-struct-relaxed-aliasing-with-tsan.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - -O1 -relaxed-aliasing -fsanitize=thread -disable-llvm-optzns %s | \
+// RUN:     FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -new-struct-path-tbaa \
+// RUN:     -emit-llvm -o - -O1 -relaxed-aliasing -fsanitize=thread -disable-llvm-optzns %s | \
+// RUN:     FileCheck %s
+//
+// Check that we do not create tbaa for instructions generated for copies.
+
+// CHECK-NOT: !tbaa
+
+struct A {
+  short s;
+  int i;
+  char c;
+  int j;
+};
+
+void copyStruct(A *a1, A *a2) {
+  *a1 = *a2;
+}
+
+void copyInt(int *a, int *b) {
+  *a = *b;
+}
diff --git a/clang/test/CodeGen/tbaa-struct.cpp b/clang/test/CodeGen/tbaa-struct.cpp
index 883c982be26c8f638b20ce0aebd5618e8968be15..9b4b7415142d933be0a89e1a87520dc4d5a726bd 100644
--- a/clang/test/CodeGen/tbaa-struct.cpp
+++ b/clang/test/CodeGen/tbaa-struct.cpp
@@ -151,6 +151,38 @@ void copy10(NamedBitfields3 *a1, NamedBitfields3 *a2) {
   *a1 = *a2;
 }
 
+union U2 {
+  double d;
+  float f;
+};
+
+struct UnionMember1 {
+  U2 u;
+  int p;
+};
+
+void copy11(UnionMember1 *a1, UnionMember1 *a2) {
+// CHECK-LABEL: _Z6copy11P12UnionMember1S0_
+// CHECK:   tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %a1, ptr noundef nonnull align 8 dereferenceable(16) %a2, i64 16, i1 false),
+// CHECK-OLD-SAME: !tbaa.struct [[TS9:!.*]]
+// CHECK-NEW-SAME: !tbaa [[TAG_UnionMember1:!.+]], !tbaa.struct
+  *a1 = *a2;
+}
+
+struct UnionMember2 {
+  int p;
+  U2 u;
+};
+
+void copy12(UnionMember2 *a1, UnionMember2 *a2) {
+// CHECK-LABEL: _Z6copy12P12UnionMember2S0_
+// CHECK:   tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %a1, ptr noundef nonnull align 8 dereferenceable(16) %a2, i64 16, i1 false),
+// CHECK-OLD-SAME: !tbaa.struct [[TS10:!.*]]
+// CHECK-NEW-SAME: !tbaa [[TAG_UnionMember2:!.+]], !tbaa.struct
+
+  *a1 = *a2;
+}
+
 // CHECK-OLD: [[TS]] = !{i64 0, i64 2, !{{.*}}, i64 4, i64 4, !{{.*}}, i64 8, i64 1, !{{.*}}, i64 12, i64 4, !{{.*}}}
 // CHECK-OLD: [[CHAR:!.*]] = !{!"omnipotent char", !{{.*}}}
 // CHECK-OLD: [[TAG_INT:!.*]] = !{[[INT:!.*]], [[INT]], i64 0}
@@ -159,7 +191,7 @@ void copy10(NamedBitfields3 *a1, NamedBitfields3 *a2) {
 // (offset, size) = (0,1) char; (4,2) short; (8,4) int; (12,1) char; (16,4) int; (20,4) int
 // CHECK-OLD: [[TS2]] = !{i64 0, i64 1, !{{.*}}, i64 4, i64 2, !{{.*}}, i64 8, i64 4, !{{.*}}, i64 12, i64 1, !{{.*}}, i64 16, i64 4, {{.*}}, i64 20, i64 4, {{.*}}}
 // (offset, size) = (0,8) char; (0,2) char; (4,8) char
-// CHECK-OLD: [[TS3]] = !{i64 0, i64 8, !{{.*}}, i64 0, i64 2, !{{.*}}, i64 4, i64 8, !{{.*}}}
+// CHECK-OLD: [[TS3]] = !{i64 0, i64 12, [[TAG_CHAR]]}
 // CHECK-OLD: [[TS4]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]]}
 // CHECK-OLD: [[TS5]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 4, i64 1, [[TAG_CHAR]], i64 5, i64 1, [[TAG_CHAR]]}
 // CHECK-OLD: [[TS6]] = !{i64 0, i64 2, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE:!.+]]}
@@ -167,6 +199,8 @@ void copy10(NamedBitfields3 *a1, NamedBitfields3 *a2) {
 // CHECK-OLD  [[DOUBLE]] = !{!"double", [[CHAR]], i64 0}
 // CHECK-OLD: [[TS7]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 3, i64 1, [[TAG_CHAR]], i64 4, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]], i64 16, i64 1, [[TAG_CHAR]]}
 // CHECK-OLD: [[TS8]] = !{i64 0, i64 4, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]]}
+// CHECK-OLD: [[TS9]] = !{i64 0, i64 8, [[TAG_CHAR]], i64 8, i64 4, [[TAG_INT]]}
+// CHECK-OLD: [[TS10]] = !{i64 0, i64 4, [[TAG_INT]], i64 8, i64 8, [[TAG_CHAR]]}
 
 // CHECK-NEW-DAG: [[TYPE_char:!.*]] = !{{{.*}}, i64 1, !"omnipotent char"}
 // CHECK-NEW-DAG: [[TAG_char]] = !{[[TYPE_char]], [[TYPE_char]], i64 0, i64 0}
@@ -188,3 +222,7 @@ void copy10(NamedBitfields3 *a1, NamedBitfields3 *a2) {
 // CHECK-NEW-DAG: [[TYPE_NamedBitfields2]] = !{[[TYPE_char]], i64 24, !"_ZTS15NamedBitfields2", [[TYPE_char]], i64 0, i64 1, [[TYPE_char]], i64 1, i64 1, [[TYPE_char]], i64 2, i64 1, [[TYPE_int]], i64 3, i64 4, [[TYPE_int]], i64 3, i64 4, [[TYPE_char]], i64 4, i64 1, [[TYPE_double]], i64 8, i64 8, [[TYPE_int]], i64 16, i64 4}
 // CHECK-NEW-DAG: [[TAG_NamedBitfields3]] = !{[[TYPE_NamedBitfields3:!.+]], [[TYPE_NamedBitfields3]], i64 0, i64 16}
 // CHECK-NEW-DAG: [[TYPE_NamedBitfields3]] = !{[[TYPE_char]], i64 16, !"_ZTS15NamedBitfields3", [[TYPE_int]], i64 1, i64 4, [[TYPE_int]], i64 2, i64 4, [[TYPE_double]], i64 8, i64 8}
+// CHECK-NEW-DAG: [[TAG_UnionMember1]] = !{[[TYPE_UnionMember1:!.+]], [[TYPE_UnionMember1]], i64 0, i64 16}
+// CHECK-NEW-DAG: [[TYPE_UnionMember1]] = !{[[TYPE_char]], i64 16, !"_ZTS12UnionMember1", [[TYPE_char]], i64 0, i64 8, [[TYPE_int]], i64 8, i64 4}
+// CHECK-NEW-DAG: [[TAG_UnionMember2]] = !{[[TYPE_UnionMember2:!.+]], [[TYPE_UnionMember2]], i64 0, i64 16}
+// CHECK-NEW-DAG: [[TYPE_UnionMember2]] = !{[[TYPE_char]], i64 16, !"_ZTS12UnionMember2", [[TYPE_int]], i64 0, i64 4, [[TYPE_char]], i64 8, i64 8}
diff --git a/clang/test/CodeGenCUDA/amdgpu-code-object-version-linking.cu b/clang/test/CodeGenCUDA/amdgpu-code-object-version-linking.cu
index d33acdf7eb8bed69d61755ff4607b27e19b9915a..cb467886c016c963d2d2023c51baaaad45122be4 100644
--- a/clang/test/CodeGenCUDA/amdgpu-code-object-version-linking.cu
+++ b/clang/test/CodeGenCUDA/amdgpu-code-object-version-linking.cu
@@ -52,7 +52,7 @@
 // LINKED4: [[GEP_4_Z:%.*]] = getelementptr i8, ptr addrspace(4) %{{.*}}, i32 8
 // LINKED4: select i1 false, ptr addrspace(4) [[GEP_5_Z]], ptr addrspace(4) [[GEP_4_Z]]
 // LINKED4: load i16, ptr addrspace(4) %{{.*}}, align 2, !range [[$WS_RANGE:![0-9]*]], !invariant.load{{.*}}, !noundef
-// LINKED4: "amdgpu_code_object_version", i32 400
+// LINKED4: "amdhsa_code_object_version", i32 400
 
 // LINKED5: __oclc_ABI_version = weak_odr hidden local_unnamed_addr addrspace(4) constant i32 500
 // LINKED5-LABEL: bar
@@ -82,7 +82,7 @@
 // LINKED5: [[GEP_4_Z:%.*]] = getelementptr i8, ptr addrspace(4) %{{.*}}, i32 8
 // LINKED5: select i1 true, ptr addrspace(4) [[GEP_5_Z]], ptr addrspace(4) [[GEP_4_Z]]
 // LINKED5: load i16, ptr addrspace(4) %{{.*}}, align 2, !range [[$WS_RANGE:![0-9]*]], !invariant.load{{.*}}, !noundef
-// LINKED5: "amdgpu_code_object_version", i32 500
+// LINKED5: "amdhsa_code_object_version", i32 500
 
 // LINKED6: __oclc_ABI_version = weak_odr hidden local_unnamed_addr addrspace(4) constant i32 600
 // LINKED6-LABEL: bar
@@ -112,7 +112,7 @@
 // LINKED6: [[GEP_4_Z:%.*]] = getelementptr i8, ptr addrspace(4) %{{.*}}, i32 8
 // LINKED6: select i1 true, ptr addrspace(4) [[GEP_5_Z]], ptr addrspace(4) [[GEP_4_Z]]
 // LINKED6: load i16, ptr addrspace(4) %{{.*}}, align 2, !range [[$WS_RANGE:![0-9]*]], !invariant.load{{.*}}, !noundef
-// LINKED6: "amdgpu_code_object_version", i32 600
+// LINKED6: "amdhsa_code_object_version", i32 600
 
 #ifdef DEVICELIB
 __device__ void bar(int *x, int *y, int *z)
diff --git a/clang/test/CodeGenCUDA/amdgpu-code-object-version.cu b/clang/test/CodeGenCUDA/amdgpu-code-object-version.cu
index d3450a105df33c9f3c9a494410c33052daebd78b..ffe12544917f7fb3f5a96361c840367f0f345cf8 100644
--- a/clang/test/CodeGenCUDA/amdgpu-code-object-version.cu
+++ b/clang/test/CodeGenCUDA/amdgpu-code-object-version.cu
@@ -18,8 +18,8 @@
 // RUN: not %clang_cc1 -fcuda-is-device -triple amdgcn-amd-amdhsa -emit-llvm \
 // RUN:   -mcode-object-version=4.1 -o - %s 2>&1| FileCheck %s -check-prefix=INV
 
-// V4: !{{.*}} = !{i32 1, !"amdgpu_code_object_version", i32 400}
-// V5: !{{.*}} = !{i32 1, !"amdgpu_code_object_version", i32 500}
-// V6: !{{.*}} = !{i32 1, !"amdgpu_code_object_version", i32 600}
-// NONE-NOT: !{{.*}} = !{i32 1, !"amdgpu_code_object_version",
+// V4: !{{.*}} = !{i32 1, !"amdhsa_code_object_version", i32 400}
+// V5: !{{.*}} = !{i32 1, !"amdhsa_code_object_version", i32 500}
+// V6: !{{.*}} = !{i32 1, !"amdhsa_code_object_version", i32 600}
+// NONE-NOT: !{{.*}} = !{i32 1, !"amdhsa_code_object_version",
 // INV: error: invalid value '4.1' in '-mcode-object-version=4.1'
diff --git a/clang/test/CodeGenCUDA/host-used-extern.cu b/clang/test/CodeGenCUDA/host-used-extern.cu
index e8f8e12aad47d1cff2621c98bb7d3ad99c9ac46f..1ae644ae981aaf733e165234de7b2684ab62a519 100644
--- a/clang/test/CodeGenCUDA/host-used-extern.cu
+++ b/clang/test/CodeGenCUDA/host-used-extern.cu
@@ -24,6 +24,7 @@
 
 // NEG-NOT: @__clang_gpu_used_external = {{.*}} @_Z7kernel2v
 // NEG-NOT: @__clang_gpu_used_external = {{.*}} @_Z7kernel3v
+// NEG-NOT: @__clang_gpu_used_external = {{.*}} @_Z7kernel5v
 // NEG-NOT: @__clang_gpu_used_external = {{.*}} @var2
 // NEG-NOT: @__clang_gpu_used_external = {{.*}} @var3
 // NEG-NOT: @__clang_gpu_used_external = {{.*}} @ext_shvar
@@ -44,6 +45,10 @@ __global__ void kernel3();
 // kernel4 is marked as used even though it is not called.
 __global__ void kernel4();
 
+// kernel5 is not marked as used since it is called by host function
+// with weak_odr linkage, which may be dropped by linker.
+__global__ void kernel5();
+
 extern __device__ int var1;
 
 __device__ int var2;
@@ -67,3 +72,11 @@ __global__ void test_lambda_using_extern_shared() {
   };
   lambda();
 }
+
+template
+void template_caller() {
+  kernel5<<<1, 1>>>();
+  var1 = 1;
+}
+
+template void template_caller();
diff --git a/clang/test/CodeGenCXX/cxx23-assume.cpp b/clang/test/CodeGenCXX/cxx23-assume.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a1fa6b30b2f0e112298fe0433c3efc2d21260632
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx23-assume.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++23 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++23 -fno-assumptions %s -emit-llvm -o - | FileCheck %s --check-prefix=DISABLED
+
+// DISABLED-NOT: @llvm.assume
+
+bool f();
+
+template 
+void f2() {
+  [[assume(sizeof(T) == sizeof(int))]];
+}
+
+// CHECK: @_Z1gii(i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]])
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32
+// CHECK-NEXT: [[Y_ADDR:%.*]] = alloca i32
+// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]]
+// CHECK-NEXT: store i32 [[Y]], ptr [[Y_ADDR]]
+void g(int x, int y) {
+  // Not emitted because it has side-effects.
+  [[assume(f())]];
+
+  // CHECK-NEXT: call void @llvm.assume(i1 true)
+  [[assume((1, 2))]];
+
+  // CHECK-NEXT: [[X1:%.*]] = load i32, ptr [[X_ADDR]]
+  // CHECK-NEXT: [[CMP1:%.*]] = icmp ne i32 [[X1]], 27
+  // CHECK-NEXT: call void @llvm.assume(i1 [[CMP1]])
+  [[assume(x != 27)]];
+
+  // CHECK-NEXT: [[X2:%.*]] = load i32, ptr [[X_ADDR]]
+  // CHECK-NEXT: [[Y2:%.*]] = load i32, ptr [[Y_ADDR]]
+  // CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[X2]], [[Y2]]
+  // CHECK-NEXT: call void @llvm.assume(i1 [[CMP2]])
+  [[assume(x == y)]];
+
+  // CHECK-NEXT: call void @_Z2f2IiEvv()
+  f2();
+
+  // CHECK-NEXT: call void @_Z2f2IdEvv()
+  f2();
+}
+
+// CHECK: void @_Z2f2IiEvv()
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void @llvm.assume(i1 true)
+
+// CHECK: void @_Z2f2IdEvv()
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void @llvm.assume(i1 false)
diff --git a/clang/test/CodeGenCoroutines/coro-always-inline.cpp b/clang/test/CodeGenCoroutines/coro-always-inline.cpp
index 6e13a62fbd98659f0fb3c940fe2aeeb578a6a0ae..d4f67a73f517268aa810a406148dcc2bd537b041 100644
--- a/clang/test/CodeGenCoroutines/coro-always-inline.cpp
+++ b/clang/test/CodeGenCoroutines/coro-always-inline.cpp
@@ -34,7 +34,7 @@ struct coroutine_traits {
 // CHECK-LABEL: @_Z3foov
 // CHECK-LABEL: entry:
 // CHECK: %ref.tmp.reload.addr = getelementptr
-// CHECK: %ref.tmp4.reload.addr = getelementptr
+// CHECK: %ref.tmp3.reload.addr = getelementptr
 void foo() { co_return; }
 
 // Check that bar is not inlined even it's marked as always_inline.
diff --git a/clang/test/CodeGenCoroutines/coro-await.cpp b/clang/test/CodeGenCoroutines/coro-await.cpp
index dc5a765ccb83d782c10add7d6977b5f756fc5067..75851d8805bb6e37d1308bcf7e6b03c112f87137 100644
--- a/clang/test/CodeGenCoroutines/coro-await.cpp
+++ b/clang/test/CodeGenCoroutines/coro-await.cpp
@@ -71,16 +71,13 @@ extern "C" void f0() {
   // CHECK: [[SUSPEND_BB]]:
   // CHECK: %[[SUSPEND_ID:.+]] = call token @llvm.coro.save(
   // ---------------------------
-  // Build the coroutine handle and pass it to await_suspend
+  // Call coro.await.suspend
   // ---------------------------
-  // CHECK: call ptr @_ZNSt16coroutine_handleINSt16coroutine_traitsIJvEE12promise_typeEE12from_addressEPv(ptr %[[FRAME]])
-  //   ... many lines of code to coerce coroutine_handle into an ptr scalar
-  // CHECK: %[[CH:.+]] = load ptr, ptr %{{.+}}
-  // CHECK: call void @_ZN14suspend_always13await_suspendESt16coroutine_handleIvE(ptr {{[^,]*}} %[[AWAITABLE]], ptr %[[CH]])
+  // CHECK-NEXT: call void @llvm.coro.await.suspend.void(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @__await_suspend_wrapper_f0_await)
   // -------------------------
   // Generate a suspend point:
   // -------------------------
-  // CHECK: %[[OUTCOME:.+]] = call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false)
+  // CHECK-NEXT: %[[OUTCOME:.+]] = call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false)
   // CHECK: switch i8 %[[OUTCOME]], label %[[RET_BB:.+]] [
   // CHECK:   i8 0, label %[[READY_BB]]
   // CHECK:   i8 1, label %[[CLEANUP_BB:.+]]
@@ -101,6 +98,17 @@ extern "C" void f0() {
   // CHECK-NEXT: call zeroext i1 @_ZN10final_susp11await_readyEv(ptr
   // CHECK: %[[FINALSP_ID:.+]] = call token @llvm.coro.save(
   // CHECK: call i8 @llvm.coro.suspend(token %[[FINALSP_ID]], i1 true)
+
+  // Await suspend wrapper
+  // CHECK: define{{.*}} @__await_suspend_wrapper_f0_await(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]])
+  // CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]],
+  // CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]],
+  // CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]]
+  // CHECK: %[[FRAME:.+]] = load ptr, ptr %[[FRAME_TMP]]
+  // CHECK: call ptr @_ZNSt16coroutine_handleINSt16coroutine_traitsIJvEE12promise_typeEE12from_addressEPv(ptr %[[FRAME]])
+  //   ... many lines of code to coerce coroutine_handle into an ptr scalar
+  // CHECK: %[[CH:.+]] = load ptr, ptr %{{.+}}
+  // CHECK: call void @_ZN14suspend_always13await_suspendESt16coroutine_handleIvE(ptr {{[^,]*}} %[[AWAITABLE]], ptr %[[CH]])
 }
 
 struct suspend_maybe {
@@ -131,7 +139,7 @@ extern "C" void f1(int) {
 
   // See if we need to suspend:
   // --------------------------
-  // CHECK: %[[READY:.+]] = call zeroext i1 @_ZN13suspend_maybe11await_readyEv(ptr {{[^,]*}} %[[AWAITABLE]])
+  // CHECK: %[[READY:.+]] = call zeroext i1 @_ZN13suspend_maybe11await_readyEv(ptr {{[^,]*}} %[[AWAITABLE:.+]])
   // CHECK: br i1 %[[READY]], label %[[READY_BB:.+]], label %[[SUSPEND_BB:.+]]
 
   // If we are suspending:
@@ -139,12 +147,9 @@ extern "C" void f1(int) {
   // CHECK: [[SUSPEND_BB]]:
   // CHECK: %[[SUSPEND_ID:.+]] = call token @llvm.coro.save(
   // ---------------------------
-  // Build the coroutine handle and pass it to await_suspend
+  // Call coro.await.suspend
   // ---------------------------
-  // CHECK: call ptr @_ZNSt16coroutine_handleINSt16coroutine_traitsIJviEE12promise_typeEE12from_addressEPv(ptr %[[FRAME]])
-  //   ... many lines of code to coerce coroutine_handle into an ptr scalar
-  // CHECK: %[[CH:.+]] = load ptr, ptr %{{.+}}
-  // CHECK: %[[YES:.+]] = call zeroext i1 @_ZN13suspend_maybe13await_suspendESt16coroutine_handleIvE(ptr {{[^,]*}} %[[AWAITABLE]], ptr %[[CH]])
+  // CHECK-NEXT: %[[YES:.+]] = call i1 @llvm.coro.await.suspend.bool(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @__await_suspend_wrapper_f1_yield)
   // -------------------------------------------
   // See if await_suspend decided not to suspend
   // -------------------------------------------
@@ -155,6 +160,18 @@ extern "C" void f1(int) {
 
   // CHECK: [[READY_BB]]:
   // CHECK:     call void @_ZN13suspend_maybe12await_resumeEv(ptr {{[^,]*}} %[[AWAITABLE]])
+
+  // Await suspend wrapper
+  // CHECK: define {{.*}} i1 @__await_suspend_wrapper_f1_yield(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]])
+  // CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]],
+  // CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]],
+  // CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]]
+  // CHECK: %[[FRAME:.+]] = load ptr, ptr %[[FRAME_TMP]]
+  // CHECK: call ptr @_ZNSt16coroutine_handleINSt16coroutine_traitsIJviEE12promise_typeEE12from_addressEPv(ptr %[[FRAME]])
+  //   ... many lines of code to coerce coroutine_handle into an ptr scalar
+  // CHECK: %[[CH:.+]] = load ptr, ptr %{{.+}}
+  // CHECK: %[[YES:.+]] = call zeroext i1 @_ZN13suspend_maybe13await_suspendESt16coroutine_handleIvE(ptr {{[^,]*}} %[[AWAITABLE]], ptr %[[CH]]) 
+  // CHECK-NEXT: ret i1 %[[YES]]
 }
 
 struct ComplexAwaiter {
@@ -340,11 +357,39 @@ struct TailCallAwait {
 
 // CHECK-LABEL: @TestTailcall(
 extern "C" void TestTailcall() {
+  // CHECK: %[[PROMISE:.+]] = alloca %"struct.std::coroutine_traits::promise_type"
+  // CHECK: %[[FRAME:.+]] = call ptr @llvm.coro.begin(
   co_await TailCallAwait{};
+  // CHECK: %[[READY:.+]] = call zeroext i1 @_ZN13TailCallAwait11await_readyEv(ptr {{[^,]*}} %[[AWAITABLE:.+]])
+  // CHECK: br i1 %[[READY]], label %[[READY_BB:.+]], label %[[SUSPEND_BB:.+]]
 
-  // CHECK: %[[RESULT:.+]] = call ptr @_ZN13TailCallAwait13await_suspendESt16coroutine_handleIvE(ptr
-  // CHECK: %[[COERCE:.+]] = getelementptr inbounds %"struct.std::coroutine_handle", ptr %[[TMP:.+]], i32 0, i32 0
-  // CHECK: store ptr %[[RESULT]], ptr %[[COERCE]]
-  // CHECK: %[[ADDR:.+]] = call ptr @_ZNSt16coroutine_handleIvE7addressEv(ptr {{[^,]*}} %[[TMP]])
-  // CHECK: call void @llvm.coro.resume(ptr %[[ADDR]])
+  // If we are suspending:
+  // ---------------------
+  // CHECK: [[SUSPEND_BB]]:
+  // CHECK: %[[SUSPEND_ID:.+]] = call token @llvm.coro.save(
+  // ---------------------------
+  // Call coro.await.suspend
+  // ---------------------------
+  // CHECK-NEXT: %[[RESUMED:.+]] = call ptr @llvm.coro.await.suspend.handle(ptr %[[AWAITABLE]], ptr %[[FRAME]], ptr @__await_suspend_wrapper_TestTailcall_await)
+  // CHECK-NEXT: call void @llvm.coro.resume(ptr %[[RESUMED]])
+  // CHECK-NEXT: %[[OUTCOME:.+]] = call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false)
+  // CHECK-NEXT: switch i8 %[[OUTCOME]], label %[[RET_BB:.+]] [
+  // CHECK-NEXT:   i8 0, label %[[READY_BB]]
+  // CHECK-NEXT:   i8 1, label %{{.+}}
+  // CHECK-NEXT: ]
+
+  // Await suspend wrapper
+  // CHECK: define {{.*}} ptr @__await_suspend_wrapper_TestTailcall_await(ptr {{[^,]*}} %[[AWAITABLE_ARG:.+]], ptr {{[^,]*}} %[[FRAME_ARG:.+]])
+  // CHECK: store ptr %[[AWAITABLE_ARG]], ptr %[[AWAITABLE_TMP:.+]],
+  // CHECK: store ptr %[[FRAME_ARG]], ptr %[[FRAME_TMP:.+]],
+  // CHECK: %[[AWAITABLE:.+]] = load ptr, ptr %[[AWAITABLE_TMP]]
+  // CHECK: %[[FRAME:.+]] = load ptr, ptr %[[FRAME_TMP]]
+  // CHECK: call ptr  @_ZNSt16coroutine_handleINSt16coroutine_traitsIJvEE12promise_typeEE12from_addressEPv(ptr %[[FRAME]])
+  //   ... many lines of code to coerce coroutine_handle into an ptr scalar
+  // CHECK: %[[CH:.+]] = load ptr, ptr %{{.+}}
+  // CHECK-NEXT: %[[RESULT:.+]] = call ptr @_ZN13TailCallAwait13await_suspendESt16coroutine_handleIvE(ptr {{[^,]*}} %[[AWAITABLE]], ptr %[[CH]]) 
+  // CHECK-NEXT: %[[COERCE:.+]] = getelementptr inbounds %"struct.std::coroutine_handle", ptr %[[TMP:.+]], i32 0, i32 0
+  // CHECK-NEXT: store ptr %[[RESULT]], ptr %[[COERCE]]
+  // CHECK-NEXT: %[[ADDR:.+]] = call ptr @_ZNSt16coroutine_handleIvE7addressEv(ptr {{[^,]*}} %[[TMP]])
+  // CHECK-NEXT: ret ptr %[[ADDR]]
 }
diff --git a/clang/test/CodeGenCoroutines/coro-awaiter-noinline-suspend.cpp b/clang/test/CodeGenCoroutines/coro-awaiter-noinline-suspend.cpp
deleted file mode 100644
index f95286faf46ec8ddc317723e72d104401406e004..0000000000000000000000000000000000000000
--- a/clang/test/CodeGenCoroutines/coro-awaiter-noinline-suspend.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-// Tests that we can mark await-suspend as noinline correctly.
-//
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s \
-// RUN:     -O1 -disable-llvm-passes | FileCheck %s
-
-#include "Inputs/coroutine.h"
-
-struct Task {
-  struct promise_type {
-    struct FinalAwaiter {
-      bool await_ready() const noexcept { return false; }
-      template 
-      std::coroutine_handle<> await_suspend(std::coroutine_handle h) noexcept {
-        return h.promise().continuation;
-      }
-      void await_resume() noexcept {}
-    };
-
-    Task get_return_object() noexcept {
-      return std::coroutine_handle::from_promise(*this);
-    }
-
-    std::suspend_always initial_suspend() noexcept { return {}; }
-    FinalAwaiter final_suspend() noexcept { return {}; }
-    void unhandled_exception() noexcept {}
-    void return_void() noexcept {}
-
-    std::coroutine_handle<> continuation;
-  };
-
-  Task(std::coroutine_handle handle);
-  ~Task();
-
-private:
-  std::coroutine_handle handle;
-};
-
-struct StatefulAwaiter {
-    int value;
-    bool await_ready() const noexcept { return false; }
-    template 
-    void await_suspend(std::coroutine_handle h) noexcept {}
-    void await_resume() noexcept {}
-};
-
-typedef std::suspend_always NoStateAwaiter;
-using AnotherStatefulAwaiter = StatefulAwaiter;
-
-template 
-struct TemplatedAwaiter {
-    T value;
-    bool await_ready() const noexcept { return false; }
-    template 
-    void await_suspend(std::coroutine_handle h) noexcept {}
-    void await_resume() noexcept {}
-};
-
-
-class Awaitable {};
-StatefulAwaiter operator co_await(Awaitable) {
-  return StatefulAwaiter{};
-}
-
-StatefulAwaiter GlobalAwaiter;
-class Awaitable2 {};
-StatefulAwaiter& operator co_await(Awaitable2) {
-  return GlobalAwaiter;
-}
-
-struct AlwaysInlineStatefulAwaiter {
-    void* value;
-    bool await_ready() const noexcept { return false; }
-
-    template 
-    __attribute__((always_inline))
-    void await_suspend(std::coroutine_handle h) noexcept {}
-
-    void await_resume() noexcept {}
-};
-
-Task testing() {
-    co_await std::suspend_always{};
-    co_await StatefulAwaiter{};
-    co_await AnotherStatefulAwaiter{};
-    
-    // Test lvalue case.
-    StatefulAwaiter awaiter;
-    co_await awaiter;
-
-    // The explicit call to await_suspend is not considered suspended.
-    awaiter.await_suspend(std::coroutine_handle::from_address(nullptr));
-
-    co_await TemplatedAwaiter{};
-    TemplatedAwaiter TemplatedAwaiterInstace;
-    co_await TemplatedAwaiterInstace;
-
-    co_await Awaitable{};
-    co_await Awaitable2{};
-
-    co_await AlwaysInlineStatefulAwaiter{};
-}
-
-struct AwaitTransformTask {
-  struct promise_type {
-    struct FinalAwaiter {
-      bool await_ready() const noexcept { return false; }
-      template 
-      std::coroutine_handle<> await_suspend(std::coroutine_handle h) noexcept {
-        return h.promise().continuation;
-      }
-      void await_resume() noexcept {}
-    };
-
-    AwaitTransformTask get_return_object() noexcept {
-      return std::coroutine_handle::from_promise(*this);
-    }
-
-    std::suspend_always initial_suspend() noexcept { return {}; }
-    FinalAwaiter final_suspend() noexcept { return {}; }
-    void unhandled_exception() noexcept {}
-    void return_void() noexcept {}
-
-    template 
-    auto await_transform(Awaitable &&awaitable) {
-      return awaitable;
-    }
-
-    std::coroutine_handle<> continuation;
-  };
-
-  AwaitTransformTask(std::coroutine_handle handle);
-  ~AwaitTransformTask();
-
-private:
-  std::coroutine_handle handle;
-};
-
-struct awaitableWithGetAwaiter {
-  bool await_ready() const noexcept { return false; }
-  template 
-  void await_suspend(std::coroutine_handle h) noexcept {}
-  void await_resume() noexcept {}
-};
-
-AwaitTransformTask testingWithAwaitTransform() {
-  co_await awaitableWithGetAwaiter{};
-}
-
-// CHECK: define{{.*}}@_ZNSt14suspend_always13await_suspendESt16coroutine_handleIvE{{.*}}#[[NORMAL_ATTR:[0-9]+]]
-
-// CHECK: define{{.*}}@_ZN15StatefulAwaiter13await_suspendIN4Task12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[NOINLINE_ATTR:[0-9]+]]
-
-// CHECK: define{{.*}}@_ZN15StatefulAwaiter13await_suspendIvEEvSt16coroutine_handleIT_E{{.*}}#[[NORMAL_ATTR]]
-
-// CHECK: define{{.*}}@_ZN16TemplatedAwaiterIiE13await_suspendIN4Task12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[NOINLINE_ATTR]]
-
-// CHECK: define{{.*}}@_ZN27AlwaysInlineStatefulAwaiter13await_suspendIN4Task12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[ALWAYS_INLINE_ATTR:[0-9]+]]
-
-// CHECK: define{{.*}}@_ZN4Task12promise_type12FinalAwaiter13await_suspendIS0_EESt16coroutine_handleIvES3_IT_E{{.*}}#[[NORMAL_ATTR]]
-
-// CHECK: define{{.*}}@_ZN23awaitableWithGetAwaiter13await_suspendIN18AwaitTransformTask12promise_typeEEEvSt16coroutine_handleIT_E{{.*}}#[[NORMAL_ATTR]]
-
-// CHECK: define{{.*}}@_ZN18AwaitTransformTask12promise_type12FinalAwaiter13await_suspendIS0_EESt16coroutine_handleIvES3_IT_E{{.*}}#[[NORMAL_ATTR]]
-
-// CHECK-NOT: attributes #[[NORMAL_ATTR]] = noinline
-// CHECK: attributes #[[NOINLINE_ATTR]] = {{.*}}noinline
-// CHECK-NOT: attributes #[[ALWAYS_INLINE_ATTR]] = {{.*}}noinline
-// CHECK: attributes #[[ALWAYS_INLINE_ATTR]] = {{.*}}alwaysinline
diff --git a/clang/test/CodeGenCoroutines/coro-dwarf.cpp b/clang/test/CodeGenCoroutines/coro-dwarf.cpp
index 7914babe5483a4597d9c954b9c26759b82ffa45b..2c9c827e6753d68e8a0e71449b896ab2df1ee453 100644
--- a/clang/test/CodeGenCoroutines/coro-dwarf.cpp
+++ b/clang/test/CodeGenCoroutines/coro-dwarf.cpp
@@ -70,3 +70,15 @@ void f_coro(int val, MoveOnly moParam, MoveAndCopy mcParam) {
 // CHECK: !{{[0-9]+}} = !DILocalVariable(name: "moParam", arg: 2, scope: ![[SP]], file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
 // CHECK: !{{[0-9]+}} = !DILocalVariable(name: "mcParam", arg: 3, scope: ![[SP]], file: !{{[0-9]+}}, line: {{[0-9]+}}, type: !{{[0-9]+}})
 // CHECK: !{{[0-9]+}} = !DILocalVariable(name: "__promise",
+
+// CHECK: !{{[0-9]+}} = distinct !DISubprogram(linkageName: "__await_suspend_wrapper__Z6f_coroi8MoveOnly11MoveAndCopy_init"
+// CHECK-NEXT: !{{[0-9]+}} = !DIFile
+// CHECK-NEXT: !{{[0-9]+}} = !DISubroutineType
+// CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 1,
+// CHECK-NEXT: !{{[0-9]+}} = !DILocation
+// CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 2,
+
+// CHECK: !{{[0-9]+}} = distinct !DISubprogram(linkageName: "__await_suspend_wrapper__Z6f_coroi8MoveOnly11MoveAndCopy_final"
+// CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 1,
+// CHECK-NEXT: !{{[0-9]+}} = !DILocation
+// CHECK-NEXT: !{{[0-9]+}} = !DILocalVariable(arg: 2,
diff --git a/clang/test/CodeGenCoroutines/coro-function-try-block.cpp b/clang/test/CodeGenCoroutines/coro-function-try-block.cpp
index f609eb55b8e771ffd64a1629e5c97f03e7f9c2b4..b7a796cc241af4bca3d378d0095843e0463fe281 100644
--- a/clang/test/CodeGenCoroutines/coro-function-try-block.cpp
+++ b/clang/test/CodeGenCoroutines/coro-function-try-block.cpp
@@ -19,5 +19,5 @@ task f() try {
 }
 
 // CHECK-LABEL: define{{.*}} void @_Z1fv(
-// CHECK: call void @_ZNSt13suspend_never13await_suspendESt16coroutine_handleIvE(
+// CHECK: call void @llvm.coro.await.suspend.void(
 // CHECK: call void @_ZN4task12promise_type11return_voidEv(
diff --git a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp
index c0b9e9ee2c55818fcc8189e2611ba91ff4a706d5..da30e12c63cffb2d1e3038969ba03087d633d7d5 100644
--- a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp
+++ b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp
@@ -50,10 +50,5 @@ detached_task foo() {
 // check that the lifetime of the coroutine handle used to obtain the address is contained within single basic block, and hence does not live across suspension points.
 // CHECK-LABEL: final.suspend:
 // CHECK:         %{{.+}} = call token @llvm.coro.save(ptr null)
-// CHECK:         call void @llvm.lifetime.start.p0(i64 8, ptr %[[HDL:.+]])
-// CHECK:         %[[CALL:.+]] = call ptr @_ZN13detached_task12promise_type13final_awaiter13await_suspendESt16coroutine_handleIS0_E(
-// CHECK:         %[[HDL_CAST2:.+]] = getelementptr inbounds %"struct.std::coroutine_handle.0", ptr %[[HDL]], i32 0, i32 0
-// CHECK:         store ptr %[[CALL]], ptr %[[HDL_CAST2]], align 8
-// CHECK:         %[[HDL_TRANSFER:.+]] = call noundef ptr @_ZNKSt16coroutine_handleIvE7addressEv(ptr noundef {{.*}}%[[HDL]])
-// CHECK:         call void @llvm.lifetime.end.p0(i64 8, ptr %[[HDL]])
+// CHECK:         %[[HDL_TRANSFER:.+]] = call ptr @llvm.coro.await.suspend.handle
 // CHECK:         call void @llvm.coro.resume(ptr %[[HDL_TRANSFER]])
diff --git a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp
index 890d55e41de95380c7ad53265d19af2a1de79f4a..ca6cf74115a3b1e434e9c2b95b17be8c856f76fb 100644
--- a/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp
+++ b/clang/test/CodeGenCoroutines/coro-symmetric-transfer-02.cpp
@@ -89,10 +89,8 @@ Task bar() {
 // CHECK:         br i1 %{{.+}}, label %[[CASE1_AWAIT_READY:.+]], label %[[CASE1_AWAIT_SUSPEND:.+]]
 // CHECK:       [[CASE1_AWAIT_SUSPEND]]:
 // CHECK-NEXT:    %{{.+}} = call token @llvm.coro.save(ptr null)
-// CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr %[[TMP1:.+]])
-
-// CHECK:    call void @llvm.lifetime.end.p0(i64 8, ptr %[[TMP1]])
-// CHECK-NEXT:    call void @llvm.coro.resume
+// CHECK-NEXT:    %[[HANDLE1_PTR:.+]] = call ptr @llvm.coro.await.suspend.handle
+// CHECK-NEXT:    call void @llvm.coro.resume(ptr %[[HANDLE1_PTR]])
 // CHECK-NEXT:    %{{.+}} = call i8 @llvm.coro.suspend
 // CHECK-NEXT:    switch i8 %{{.+}}, label %coro.ret [
 // CHECK-NEXT:      i8 0, label %[[CASE1_AWAIT_READY]]
@@ -106,10 +104,8 @@ Task bar() {
 // CHECK:         br i1 %{{.+}}, label %[[CASE2_AWAIT_READY:.+]], label %[[CASE2_AWAIT_SUSPEND:.+]]
 // CHECK:       [[CASE2_AWAIT_SUSPEND]]:
 // CHECK-NEXT:    %{{.+}} = call token @llvm.coro.save(ptr null)
-// CHECK-NEXT:    call void @llvm.lifetime.start.p0(i64 8, ptr %[[TMP2:.+]])
-
-// CHECK:    call void @llvm.lifetime.end.p0(i64 8, ptr %[[TMP2]])
-// CHECK-NEXT:    call void @llvm.coro.resume
+// CHECK-NEXT:    %[[HANDLE2_PTR:.+]] = call ptr @llvm.coro.await.suspend.handle
+// CHECK-NEXT:    call void @llvm.coro.resume(ptr %[[HANDLE2_PTR]])
 // CHECK-NEXT:    %{{.+}} = call i8 @llvm.coro.suspend
 // CHECK-NEXT:    switch i8 %{{.+}}, label %coro.ret [
 // CHECK-NEXT:      i8 0, label %[[CASE2_AWAIT_READY]]
diff --git a/clang/test/CodeGenCoroutines/pr56329.cpp b/clang/test/CodeGenCoroutines/pr56329.cpp
index 31d4849af4e71efd00ccb985d74e09d02d8f2579..ad8b1b990179c949207803ca457fda14d6e313e9 100644
--- a/clang/test/CodeGenCoroutines/pr56329.cpp
+++ b/clang/test/CodeGenCoroutines/pr56329.cpp
@@ -115,5 +115,9 @@ Task Outer() {
 // CHECK-NOT: _exit
 // CHECK: musttail call
 // CHECK: musttail call
+// CHECK: musttail call
 // CHECK-NEXT: ret void
+// CHECK-EMPTY:
+// CHECK-NEXT: unreachable:
+// CHECK-NEXT: unreachable
 // CHECK-NEXT: }
diff --git a/clang/test/CodeGenCoroutines/pr59181.cpp b/clang/test/CodeGenCoroutines/pr59181.cpp
index 80f4634db25214663eb7af7cd8b8bdd9e71252d8..21e784e0031de33d52357982086907514039fcf3 100644
--- a/clang/test/CodeGenCoroutines/pr59181.cpp
+++ b/clang/test/CodeGenCoroutines/pr59181.cpp
@@ -52,9 +52,8 @@ void foo() {
 // CHECK-NEXT: load i8
 // CHECK-NEXT: trunc
 // CHECK-NEXT: store i1 false
-// CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[REF:%ref.tmp[0-9]+]])
 
 // CHECK: await.suspend:{{.*}}
-// CHECK-NOT: call void @llvm.lifetime.start.p0(i64 8, ptr [[REF]])
-// CHECK: call void @_ZZN4Task12promise_type15await_transformES_EN10Suspension13await_suspendESt16coroutine_handleIvE
-// CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[REF]])
+// CHECK-NOT: call void @llvm.lifetime
+// CHECK: call void @llvm.coro.await.suspend.void(
+// CHECK-NEXT: %{{[0-9]+}} = call i8 @llvm.coro.suspend(
diff --git a/clang/test/CodeGenCoroutines/pr65054.cpp b/clang/test/CodeGenCoroutines/pr65054.cpp
index 834b71050f59ffaf66ad7c2967077ee04c20d6bb..7af9c04fca180e725cdf8fe58bf47d60416e1bcf 100644
--- a/clang/test/CodeGenCoroutines/pr65054.cpp
+++ b/clang/test/CodeGenCoroutines/pr65054.cpp
@@ -1,7 +1,3 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 \
-// RUN:      -O0 -disable-llvm-passes -emit-llvm %s -o - \
-// RUN:      | FileCheck %s --check-prefix=FRONTEND
-
 // The output of O0 is highly redundant and hard to test. Also it is not good
 // limit the output of O0. So we test the optimized output from O0. The idea
 // is the optimizations shouldn't change the semantics of the program.
@@ -51,10 +47,7 @@ MyTask FooBar() {
   }
 }
 
-// FRONTEND: define{{.*}}@_ZNKSt16coroutine_handleIvE7addressEv{{.*}}#[[address_attr:[0-9]+]]
-// FRONTEND: attributes #[[address_attr]] = {{.*}}alwaysinline
-
 // CHECK-O0: define{{.*}}@_Z6FooBarv.resume
-// CHECK-O0: call{{.*}}@_ZN7Awaiter13await_suspendESt16coroutine_handleIvE
+// CHECK-O0: call{{.*}}@__await_suspend_wrapper__Z6FooBarv_await(
 // CHECK-O0-NOT: store
 // CHECK-O0: ret void
diff --git a/clang/test/CodeGenHIP/default-attributes.hip b/clang/test/CodeGenHIP/default-attributes.hip
index 9c9ea521271b99bddfaf6d80e3a54e043ed61466..63572bfd242b98da3825fc72c0ca46a70907a60b 100644
--- a/clang/test/CodeGenHIP/default-attributes.hip
+++ b/clang/test/CodeGenHIP/default-attributes.hip
@@ -46,11 +46,11 @@ __global__ void kernel() {
 // OPT: attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
 // OPT: attributes #1 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "amdgpu-flat-work-group-size"="1,1024" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "uniform-work-group-size"="true" }
 //.
-// OPTNONE: !0 = !{i32 1, !"amdgpu_code_object_version", i32 500}
+// OPTNONE: !0 = !{i32 1, !"amdhsa_code_object_version", i32 500}
 // OPTNONE: !1 = !{i32 1, !"amdgpu_printf_kind", !"hostcall"}
 // OPTNONE: !2 = !{i32 1, !"wchar_size", i32 4}
 //.
-// OPT: !0 = !{i32 1, !"amdgpu_code_object_version", i32 500}
+// OPT: !0 = !{i32 1, !"amdhsa_code_object_version", i32 500}
 // OPT: !1 = !{i32 1, !"amdgpu_printf_kind", !"hostcall"}
 // OPT: !2 = !{i32 1, !"wchar_size", i32 4}
 //.
diff --git a/clang/test/CodeGenHLSL/builtins/any.hlsl b/clang/test/CodeGenHLSL/builtins/any.hlsl
new file mode 100644
index 0000000000000000000000000000000000000000..ae348fec756b3ef39d54fead5175449fe94c497b
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/any.hlsl
@@ -0,0 +1,186 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
+
+#ifdef __HLSL_ENABLE_16_BIT
+// NATIVE_HALF: define noundef i1 @
+// NATIVE_HALF: %dx.any = call i1 @llvm.dx.any.i16
+// NATIVE_HALF: ret i1 %dx.any
+bool test_any_int16_t(int16_t p0) { return any(p0); }
+// NATIVE_HALF: define noundef i1 @
+// NATIVE_HALF: %dx.any = call i1 @llvm.dx.any.v2i16
+// NATIVE_HALF: ret i1 %dx.any
+bool test_any_int16_t2(int16_t2 p0) { return any(p0); }
+// NATIVE_HALF: define noundef i1 @
+// NATIVE_HALF: %dx.any = call i1 @llvm.dx.any.v3i16
+// NATIVE_HALF: ret i1 %dx.any
+bool test_any_int16_t3(int16_t3 p0) { return any(p0); }
+// NATIVE_HALF: define noundef i1 @
+// NATIVE_HALF: %dx.any = call i1 @llvm.dx.any.v4i16
+// NATIVE_HALF: ret i1 %dx.any
+bool test_any_int16_t4(int16_t4 p0) { return any(p0); }
+
+// NATIVE_HALF: define noundef i1 @
+// NATIVE_HALF: %dx.any = call i1 @llvm.dx.any.i16
+// NATIVE_HALF: ret i1 %dx.any
+bool test_any_uint16_t(uint16_t p0) { return any(p0); }
+// NATIVE_HALF: define noundef i1 @
+// NATIVE_HALF: %dx.any = call i1 @llvm.dx.any.v2i16
+// NATIVE_HALF: ret i1 %dx.any
+bool test_any_uint16_t2(uint16_t2 p0) { return any(p0); }
+// NATIVE_HALF: define noundef i1 @
+// NATIVE_HALF: %dx.any = call i1 @llvm.dx.any.v3i16
+// NATIVE_HALF: ret i1 %dx.any
+bool test_any_uint16_t3(uint16_t3 p0) { return any(p0); }
+// NATIVE_HALF: define noundef i1 @
+// NATIVE_HALF: %dx.any = call i1 @llvm.dx.any.v4i16
+// NATIVE_HALF: ret i1 %dx.any
+bool test_any_uint16_t4(uint16_t4 p0) { return any(p0); }
+#endif // __HLSL_ENABLE_16_BIT
+
+// CHECK: define noundef i1 @
+// NATIVE_HALF: %dx.any = call i1 @llvm.dx.any.f16
+// NO_HALF: %dx.any = call i1 @llvm.dx.any.f32
+// CHECK: ret i1 %dx.any
+bool test_any_half(half p0) { return any(p0); }
+
+// CHECK: define noundef i1 @
+// NATIVE_HALF: %dx.any = call i1 @llvm.dx.any.v2f16
+// NO_HALF: %dx.any = call i1 @llvm.dx.any.v2f32
+// CHECK: ret i1 %dx.any
+bool test_any_half2(half2 p0) { return any(p0); }
+
+// CHECK: define noundef i1 @
+// NATIVE_HALF: %dx.any = call i1 @llvm.dx.any.v3f16
+// NO_HALF: %dx.any = call i1 @llvm.dx.any.v3f32
+// CHECK: ret i1 %dx.any
+bool test_any_half3(half3 p0) { return any(p0); }
+
+// CHECK: define noundef i1 @
+// NATIVE_HALF: %dx.any = call i1 @llvm.dx.any.v4f16
+// NO_HALF: %dx.any = call i1 @llvm.dx.any.v4f32
+// CHECK: ret i1 %dx.any
+bool test_any_half4(half4 p0) { return any(p0); }
+
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.f32
+// CHECK: ret i1 %dx.any
+bool test_any_float(float p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v2f32
+// CHECK: ret i1 %dx.any
+bool test_any_float2(float2 p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v3f32
+// CHECK: ret i1 %dx.any
+bool test_any_float3(float3 p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v4f32
+// CHECK: ret i1 %dx.any
+bool test_any_float4(float4 p0) { return any(p0); }
+
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.f64
+// CHECK: ret i1 %dx.any
+bool test_any_double(double p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v2f64
+// CHECK: ret i1 %dx.any
+bool test_any_double2(double2 p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v3f64
+// CHECK: ret i1 %dx.any
+bool test_any_double3(double3 p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v4f64
+// CHECK: ret i1 %dx.any
+bool test_any_double4(double4 p0) { return any(p0); }
+
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.i32
+// CHECK: ret i1 %dx.any
+bool test_any_int(int p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v2i32
+// CHECK: ret i1 %dx.any
+bool test_any_int2(int2 p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v3i32
+// CHECK: ret i1 %dx.any
+bool test_any_int3(int3 p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v4i32
+// CHECK: ret i1 %dx.any
+bool test_any_int4(int4 p0) { return any(p0); }
+
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.i32
+// CHECK: ret i1 %dx.any
+bool test_any_uint(uint p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v2i32
+// CHECK: ret i1 %dx.any
+bool test_any_uint2(uint2 p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v3i32
+// CHECK: ret i1 %dx.any
+bool test_any_uint3(uint3 p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v4i32
+// CHECK: ret i1 %dx.any
+bool test_any_uint4(uint4 p0) { return any(p0); }
+
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.i64
+// CHECK: ret i1 %dx.any
+bool test_any_int64_t(int64_t p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v2i64
+// CHECK: ret i1 %dx.any
+bool test_any_int64_t2(int64_t2 p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v3i64
+// CHECK: ret i1 %dx.any
+bool test_any_int64_t3(int64_t3 p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v4i64
+// CHECK: ret i1 %dx.any
+bool test_any_int64_t4(int64_t4 p0) { return any(p0); }
+
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.i64
+// CHECK: ret i1 %dx.any
+bool test_any_uint64_t(uint64_t p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v2i64
+// CHECK: ret i1 %dx.any
+bool test_any_uint64_t2(uint64_t2 p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v3i64
+// CHECK: ret i1 %dx.any
+bool test_any_uint64_t3(uint64_t3 p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v4i64
+// CHECK: ret i1 %dx.any
+bool test_any_uint64_t4(uint64_t4 p0) { return any(p0); }
+
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.i1
+// CHECK: ret i1 %dx.any
+bool test_any_bool(bool p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v2i1
+// CHECK: ret i1 %dx.any
+bool test_any_bool2(bool2 p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v3i1
+// CHECK: ret i1 %dx.any
+bool test_any_bool3(bool3 p0) { return any(p0); }
+// CHECK: define noundef i1 @
+// CHECK: %dx.any = call i1 @llvm.dx.any.v4i1
+// CHECK: ret i1 %dx.any
+bool test_any_bool4(bool4 p0) { return any(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/exp.hlsl b/clang/test/CodeGenHLSL/builtins/exp.hlsl
new file mode 100644
index 0000000000000000000000000000000000000000..773edbe3364fd2bed6ea3dc591634375a86e374e
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/exp.hlsl
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
+
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: %elt.exp = call half @llvm.exp.f16(
+// NATIVE_HALF: ret half %elt.exp
+// NO_HALF: define noundef float @"?test_exp_half@@YA$halff@$halff@@Z"(
+// NO_HALF: %elt.exp = call float @llvm.exp.f32(
+// NO_HALF: ret float %elt.exp
+half test_exp_half(half p0) { return exp(p0); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: %elt.exp = call <2 x half> @llvm.exp.v2f16
+// NATIVE_HALF: ret <2 x half> %elt.exp
+// NO_HALF: define noundef <2 x float> @
+// NO_HALF: %elt.exp = call <2 x float> @llvm.exp.v2f32(
+// NO_HALF: ret <2 x float> %elt.exp
+half2 test_exp_half2(half2 p0) { return exp(p0); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: %elt.exp = call <3 x half> @llvm.exp.v3f16
+// NATIVE_HALF: ret <3 x half> %elt.exp
+// NO_HALF: define noundef <3 x float> @
+// NO_HALF: %elt.exp = call <3 x float> @llvm.exp.v3f32(
+// NO_HALF: ret <3 x float> %elt.exp
+half3 test_exp_half3(half3 p0) { return exp(p0); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: %elt.exp = call <4 x half> @llvm.exp.v4f16
+// NATIVE_HALF: ret <4 x half> %elt.exp
+// NO_HALF: define noundef <4 x float> @
+// NO_HALF: %elt.exp = call <4 x float> @llvm.exp.v4f32(
+// NO_HALF: ret <4 x float> %elt.exp
+half4 test_exp_half4(half4 p0) { return exp(p0); }
+
+// CHECK: define noundef float @
+// CHECK: %elt.exp = call float @llvm.exp.f32(
+// CHECK: ret float %elt.exp
+float test_exp_float(float p0) { return exp(p0); }
+// CHECK: define noundef <2 x float> @
+// CHECK: %elt.exp = call <2 x float> @llvm.exp.v2f32
+// CHECK: ret <2 x float> %elt.exp
+float2 test_exp_float2(float2 p0) { return exp(p0); }
+// CHECK: define noundef <3 x float> @
+// CHECK: %elt.exp = call <3 x float> @llvm.exp.v3f32
+// CHECK: ret <3 x float> %elt.exp
+float3 test_exp_float3(float3 p0) { return exp(p0); }
+// CHECK: define noundef <4 x float> @
+// CHECK: %elt.exp = call <4 x float> @llvm.exp.v4f32
+// CHECK: ret <4 x float> %elt.exp
+float4 test_exp_float4(float4 p0) { return exp(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/exp2.hlsl b/clang/test/CodeGenHLSL/builtins/exp2.hlsl
new file mode 100644
index 0000000000000000000000000000000000000000..f21cdd95774ab6f2797284872655d37602f31b2d
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/exp2.hlsl
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
+
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: %elt.exp2 = call half @llvm.exp2.f16(
+// NATIVE_HALF: ret half %elt.exp2
+// NO_HALF: define noundef float @"?test_exp2_half@@YA$halff@$halff@@Z"(
+// NO_HALF: %elt.exp2 = call float @llvm.exp2.f32(
+// NO_HALF: ret float %elt.exp2
+half test_exp2_half(half p0) { return exp2(p0); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: %elt.exp2 = call <2 x half> @llvm.exp2.v2f16
+// NATIVE_HALF: ret <2 x half> %elt.exp2
+// NO_HALF: define noundef <2 x float> @
+// NO_HALF: %elt.exp2 = call <2 x float> @llvm.exp2.v2f32(
+// NO_HALF: ret <2 x float> %elt.exp2
+half2 test_exp2_half2(half2 p0) { return exp2(p0); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: %elt.exp2 = call <3 x half> @llvm.exp2.v3f16
+// NATIVE_HALF: ret <3 x half> %elt.exp2
+// NO_HALF: define noundef <3 x float> @
+// NO_HALF: %elt.exp2 = call <3 x float> @llvm.exp2.v3f32(
+// NO_HALF: ret <3 x float> %elt.exp2
+half3 test_exp2_half3(half3 p0) { return exp2(p0); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: %elt.exp2 = call <4 x half> @llvm.exp2.v4f16
+// NATIVE_HALF: ret <4 x half> %elt.exp2
+// NO_HALF: define noundef <4 x float> @
+// NO_HALF: %elt.exp2 = call <4 x float> @llvm.exp2.v4f32(
+// NO_HALF: ret <4 x float> %elt.exp2
+half4 test_exp2_half4(half4 p0) { return exp2(p0); }
+
+// CHECK: define noundef float @
+// CHECK: %elt.exp2 = call float @llvm.exp2.f32(
+// CHECK: ret float %elt.exp2
+float test_exp2_float(float p0) { return exp2(p0); }
+// CHECK: define noundef <2 x float> @
+// CHECK: %elt.exp2 = call <2 x float> @llvm.exp2.v2f32
+// CHECK: ret <2 x float> %elt.exp2
+float2 test_exp2_float2(float2 p0) { return exp2(p0); }
+// CHECK: define noundef <3 x float> @
+// CHECK: %elt.exp2 = call <3 x float> @llvm.exp2.v3f32
+// CHECK: ret <3 x float> %elt.exp2
+float3 test_exp2_float3(float3 p0) { return exp2(p0); }
+// CHECK: define noundef <4 x float> @
+// CHECK: %elt.exp2 = call <4 x float> @llvm.exp2.v4f32
+// CHECK: ret <4 x float> %elt.exp2
+float4 test_exp2_float4(float4 p0) { return exp2(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/mad.hlsl b/clang/test/CodeGenHLSL/builtins/mad.hlsl
new file mode 100644
index 0000000000000000000000000000000000000000..749eac6d64736d476ee76b4c12648f08de4de091
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/mad.hlsl
@@ -0,0 +1,191 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
+
+#ifdef __HLSL_ENABLE_16_BIT
+// NATIVE_HALF: %dx.umad = call i16 @llvm.dx.umad.i16(i16 %0, i16 %1, i16 %2)
+// NATIVE_HALF: ret i16 %dx.umad
+uint16_t test_mad_uint16_t(uint16_t p0, uint16_t p1, uint16_t p2) { return mad(p0, p1, p2); }
+
+// NATIVE_HALF: %dx.umad = call <2 x i16>  @llvm.dx.umad.v2i16(<2 x i16> %0, <2 x i16> %1, <2 x i16> %2)
+// NATIVE_HALF: ret <2 x i16> %dx.umad
+uint16_t2 test_mad_uint16_t2(uint16_t2 p0, uint16_t2 p1, uint16_t2 p2) { return mad(p0, p1, p2); }
+
+// NATIVE_HALF: %dx.umad = call <3 x i16>  @llvm.dx.umad.v3i16(<3 x i16> %0, <3 x i16> %1, <3 x i16> %2)
+// NATIVE_HALF: ret <3 x i16> %dx.umad
+uint16_t3 test_mad_uint16_t3(uint16_t3 p0, uint16_t3 p1, uint16_t3 p2) { return mad(p0, p1, p2); }
+
+// NATIVE_HALF: %dx.umad = call <4 x i16>  @llvm.dx.umad.v4i16(<4 x i16> %0, <4 x i16> %1, <4 x i16> %2)
+// NATIVE_HALF: ret <4 x i16> %dx.umad
+uint16_t4 test_mad_uint16_t4(uint16_t4 p0, uint16_t4 p1, uint16_t4 p2) { return mad(p0, p1, p2); }
+
+// NATIVE_HALF: %dx.imad = call i16 @llvm.dx.imad.i16(i16 %0, i16 %1, i16 %2)
+// NATIVE_HALF: ret i16 %dx.imad
+int16_t test_mad_int16_t(int16_t p0, int16_t p1, int16_t p2) { return mad(p0, p1, p2); }
+
+// NATIVE_HALF: %dx.imad = call <2 x i16>  @llvm.dx.imad.v2i16(<2 x i16> %0, <2 x i16> %1, <2 x i16> %2)
+// NATIVE_HALF: ret <2 x i16> %dx.imad
+int16_t2 test_mad_int16_t2(int16_t2 p0, int16_t2 p1, int16_t2 p2) { return mad(p0, p1, p2); }
+
+// NATIVE_HALF: %dx.imad = call <3 x i16>  @llvm.dx.imad.v3i16(<3 x i16> %0, <3 x i16> %1, <3 x i16> %2)
+// NATIVE_HALF: ret <3 x i16> %dx.imad
+int16_t3 test_mad_int16_t3(int16_t3 p0, int16_t3 p1, int16_t3 p2) { return mad(p0, p1, p2); }
+
+// NATIVE_HALF: %dx.imad = call <4 x i16>  @llvm.dx.imad.v4i16(<4 x i16> %0, <4 x i16> %1, <4 x i16> %2)
+// NATIVE_HALF: ret <4 x i16> %dx.imad
+int16_t4 test_mad_int16_t4(int16_t4 p0, int16_t4 p1, int16_t4 p2) { return mad(p0, p1, p2); }
+#endif // __HLSL_ENABLE_16_BIT
+
+// NATIVE_HALF: %dx.fmad = call half @llvm.fmuladd.f16(half %0, half %1, half %2)
+// NATIVE_HALF: ret half %dx.fmad
+// NO_HALF: %dx.fmad = call float @llvm.fmuladd.f32(float %0, float %1, float %2)
+// NO_HALF: ret float %dx.fmad
+half test_mad_half(half p0, half p1, half p2) { return mad(p0, p1, p2); }
+
+// NATIVE_HALF: %dx.fmad = call <2 x half>  @llvm.fmuladd.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2)
+// NATIVE_HALF: ret <2 x half> %dx.fmad
+// NO_HALF: %dx.fmad = call <2 x float>  @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2)
+// NO_HALF: ret <2 x float> %dx.fmad
+half2 test_mad_half2(half2 p0, half2 p1, half2 p2) { return mad(p0, p1, p2); }
+
+// NATIVE_HALF: %dx.fmad = call <3 x half>  @llvm.fmuladd.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2)
+// NATIVE_HALF: ret <3 x half> %dx.fmad
+// NO_HALF: %dx.fmad = call <3 x float>  @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2)
+// NO_HALF: ret <3 x float> %dx.fmad
+half3 test_mad_half3(half3 p0, half3 p1, half3 p2) { return mad(p0, p1, p2); }
+
+// NATIVE_HALF: %dx.fmad = call <4 x half>  @llvm.fmuladd.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2)
+// NATIVE_HALF: ret <4 x half> %dx.fmad
+// NO_HALF: %dx.fmad = call <4 x float>  @llvm.fmuladd.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2)
+// NO_HALF: ret <4 x float> %dx.fmad
+half4 test_mad_half4(half4 p0, half4 p1, half4 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.fmad = call float @llvm.fmuladd.f32(float %0, float %1, float %2)
+// CHECK: ret float %dx.fmad
+float test_mad_float(float p0, float p1, float p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.fmad = call <2 x float>  @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2)
+// CHECK: ret <2 x float> %dx.fmad
+float2 test_mad_float2(float2 p0, float2 p1, float2 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.fmad = call <3 x float>  @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2)
+// CHECK: ret <3 x float> %dx.fmad
+float3 test_mad_float3(float3 p0, float3 p1, float3 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.fmad = call <4 x float>  @llvm.fmuladd.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2)
+// CHECK: ret <4 x float> %dx.fmad
+float4 test_mad_float4(float4 p0, float4 p1, float4 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.fmad = call double @llvm.fmuladd.f64(double %0, double %1, double %2)
+// CHECK: ret double %dx.fmad
+double test_mad_double(double p0, double p1, double p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.fmad = call <2 x double>  @llvm.fmuladd.v2f64(<2 x double> %0, <2 x double> %1, <2 x double> %2)
+// CHECK: ret <2 x double> %dx.fmad
+double2 test_mad_double2(double2 p0, double2 p1, double2 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.fmad = call <3 x double>  @llvm.fmuladd.v3f64(<3 x double> %0, <3 x double> %1, <3 x double> %2)
+// CHECK: ret <3 x double> %dx.fmad
+double3 test_mad_double3(double3 p0, double3 p1, double3 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.fmad = call <4 x double>  @llvm.fmuladd.v4f64(<4 x double> %0, <4 x double> %1, <4 x double> %2)
+// CHECK: ret <4 x double> %dx.fmad
+double4 test_mad_double4(double4 p0, double4 p1, double4 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.imad = call i32 @llvm.dx.imad.i32(i32 %0, i32 %1, i32 %2)
+// CHECK: ret i32 %dx.imad
+int test_mad_int(int p0, int p1, int p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.imad = call <2 x i32>  @llvm.dx.imad.v2i32(<2 x i32> %0, <2 x i32> %1, <2 x i32> %2)
+// CHECK: ret <2 x i32> %dx.imad
+int2 test_mad_int2(int2 p0, int2 p1, int2 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.imad = call <3 x i32>  @llvm.dx.imad.v3i32(<3 x i32> %0, <3 x i32> %1, <3 x i32> %2)
+// CHECK: ret <3 x i32> %dx.imad
+int3 test_mad_int3(int3 p0, int3 p1, int3 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.imad = call <4 x i32>  @llvm.dx.imad.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2)
+// CHECK: ret <4 x i32> %dx.imad
+int4 test_mad_int4(int4 p0, int4 p1, int4 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.imad = call i64 @llvm.dx.imad.i64(i64 %0, i64 %1, i64 %2)
+// CHECK: ret i64 %dx.imad
+int64_t test_mad_int64_t(int64_t p0, int64_t p1, int64_t p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.imad = call <2 x i64>  @llvm.dx.imad.v2i64(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2)
+// CHECK: ret <2 x i64> %dx.imad
+int64_t2 test_mad_int64_t2(int64_t2 p0, int64_t2 p1, int64_t2 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.imad = call <3 x i64>  @llvm.dx.imad.v3i64(<3 x i64> %0, <3 x i64> %1, <3 x i64> %2)
+// CHECK: ret <3 x i64> %dx.imad
+int64_t3 test_mad_int64_t3(int64_t3 p0, int64_t3 p1, int64_t3 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.imad = call <4 x i64>  @llvm.dx.imad.v4i64(<4 x i64> %0, <4 x i64> %1, <4 x i64> %2)
+// CHECK: ret <4 x i64> %dx.imad
+int64_t4 test_mad_int64_t4(int64_t4 p0, int64_t4 p1, int64_t4 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.umad = call i32 @llvm.dx.umad.i32(i32 %0, i32 %1, i32 %2)
+// CHECK: ret i32 %dx.umad
+uint test_mad_uint(uint p0, uint p1, uint p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.umad = call <2 x i32>  @llvm.dx.umad.v2i32(<2 x i32> %0, <2 x i32> %1, <2 x i32> %2)
+// CHECK: ret <2 x i32> %dx.umad
+uint2 test_mad_uint2(uint2 p0, uint2 p1, uint2 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.umad = call <3 x i32>  @llvm.dx.umad.v3i32(<3 x i32> %0, <3 x i32> %1, <3 x i32> %2)
+// CHECK: ret <3 x i32> %dx.umad
+uint3 test_mad_uint3(uint3 p0, uint3 p1, uint3 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.umad = call <4 x i32>  @llvm.dx.umad.v4i32(<4 x i32> %0, <4 x i32> %1, <4 x i32> %2)
+// CHECK: ret <4 x i32> %dx.umad
+uint4 test_mad_uint4(uint4 p0, uint4 p1, uint4 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.umad = call i64 @llvm.dx.umad.i64(i64 %0, i64 %1, i64 %2)
+// CHECK: ret i64 %dx.umad
+uint64_t test_mad_uint64_t(uint64_t p0, uint64_t p1, uint64_t p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.umad = call <2 x i64>  @llvm.dx.umad.v2i64(<2 x i64> %0, <2 x i64> %1, <2 x i64> %2)
+// CHECK: ret <2 x i64> %dx.umad
+uint64_t2 test_mad_uint64_t2(uint64_t2 p0, uint64_t2 p1, uint64_t2 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.umad = call <3 x i64>  @llvm.dx.umad.v3i64(<3 x i64> %0, <3 x i64> %1, <3 x i64> %2)
+// CHECK: ret <3 x i64> %dx.umad
+uint64_t3 test_mad_uint64_t3(uint64_t3 p0, uint64_t3 p1, uint64_t3 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.umad = call <4 x i64>  @llvm.dx.umad.v4i64(<4 x i64> %0, <4 x i64> %1, <4 x i64> %2)
+// CHECK: ret <4 x i64> %dx.umad
+uint64_t4 test_mad_uint64_t4(uint64_t4 p0, uint64_t4 p1, uint64_t4 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.fmad = call <2 x float>  @llvm.fmuladd.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2)
+// CHECK: ret <2 x float> %dx.fmad
+float2 test_mad_float2_splat(float p0, float2 p1, float2 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %dx.fmad = call <3 x float>  @llvm.fmuladd.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2)
+// CHECK: ret <3 x float> %dx.fmad
+float3 test_mad_float3_splat(float p0, float3 p1, float3 p2) { return mad(p0, p1, p2); }
+
+// CHECK:  %dx.fmad = call <4 x float>  @llvm.fmuladd.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2)
+// CHECK:  ret <4 x float> %dx.fmad
+float4 test_mad_float4_splat(float p0, float4 p1, float4 p2) { return mad(p0, p1, p2); }
+
+// CHECK: %conv = sitofp i32 %2 to float
+// CHECK: %splat.splatinsert = insertelement <2 x float> poison, float %conv, i64 0
+// CHECK: %splat.splat = shufflevector <2 x float> %splat.splatinsert, <2 x float> poison, <2 x i32> zeroinitializer
+// CHECK: %dx.fmad = call <2 x float>  @llvm.fmuladd.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat)
+// CHECK: ret <2 x float> %dx.fmad
+float2 test_mad_float2_int_splat(float2 p0, float2 p1, int p2) {
+  return mad(p0, p1, p2);
+}
+
+// CHECK: %conv = sitofp i32 %2 to float
+// CHECK: %splat.splatinsert = insertelement <3 x float> poison, float %conv, i64 0
+// CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer
+// CHECK:  %dx.fmad = call <3 x float>  @llvm.fmuladd.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat)
+// CHECK: ret <3 x float> %dx.fmad
+float3 test_mad_float3_int_splat(float3 p0, float3 p1, int p2) {
+  return mad(p0, p1, p2);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/rcp.hlsl b/clang/test/CodeGenHLSL/builtins/rcp.hlsl
new file mode 100644
index 0000000000000000000000000000000000000000..9b8406e1f0b605231519a61ad1868595457f0573
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/rcp.hlsl
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
+
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: %dx.rcp = call half @llvm.dx.rcp.f16(
+// NATIVE_HALF: ret half %dx.rcp
+// NO_HALF: define noundef float @"?test_rcp_half@@YA$halff@$halff@@Z"(
+// NO_HALF: %dx.rcp = call float @llvm.dx.rcp.f32(
+// NO_HALF: ret float %dx.rcp
+half test_rcp_half(half p0) { return rcp(p0); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: %dx.rcp = call <2 x half> @llvm.dx.rcp.v2f16
+// NATIVE_HALF: ret <2 x half> %dx.rcp
+// NO_HALF: define noundef <2 x float> @
+// NO_HALF: %dx.rcp = call <2 x float> @llvm.dx.rcp.v2f32(
+// NO_HALF: ret <2 x float> %dx.rcp
+half2 test_rcp_half2(half2 p0) { return rcp(p0); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: %dx.rcp = call <3 x half> @llvm.dx.rcp.v3f16
+// NATIVE_HALF: ret <3 x half> %dx.rcp
+// NO_HALF: define noundef <3 x float> @
+// NO_HALF: %dx.rcp = call <3 x float> @llvm.dx.rcp.v3f32(
+// NO_HALF: ret <3 x float> %dx.rcp
+half3 test_rcp_half3(half3 p0) { return rcp(p0); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: %dx.rcp = call <4 x half> @llvm.dx.rcp.v4f16
+// NATIVE_HALF: ret <4 x half> %dx.rcp
+// NO_HALF: define noundef <4 x float> @
+// NO_HALF: %dx.rcp = call <4 x float> @llvm.dx.rcp.v4f32(
+// NO_HALF: ret <4 x float> %dx.rcp
+half4 test_rcp_half4(half4 p0) { return rcp(p0); }
+
+// CHECK: define noundef float @
+// CHECK: %dx.rcp = call float @llvm.dx.rcp.f32(
+// CHECK: ret float %dx.rcp
+float test_rcp_float(float p0) { return rcp(p0); }
+// CHECK: define noundef <2 x float> @
+// CHECK: %dx.rcp = call <2 x float> @llvm.dx.rcp.v2f32
+// CHECK: ret <2 x float> %dx.rcp
+float2 test_rcp_float2(float2 p0) { return rcp(p0); }
+// CHECK: define noundef <3 x float> @
+// CHECK: %dx.rcp = call <3 x float> @llvm.dx.rcp.v3f32
+// CHECK: ret <3 x float> %dx.rcp
+float3 test_rcp_float3(float3 p0) { return rcp(p0); }
+// CHECK: define noundef <4 x float> @
+// CHECK: %dx.rcp = call <4 x float> @llvm.dx.rcp.v4f32
+// CHECK: ret <4 x float> %dx.rcp
+float4 test_rcp_float4(float4 p0) { return rcp(p0); }
diff --git a/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl b/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl
index e285f74a822d5827d4bd5f9b893e236f13dbb27c..3efc36baa35b1a1ffc4116614eb5a5cd43a2b9f3 100644
--- a/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl
+++ b/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl
@@ -1,28 +1,25 @@
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-DXIL
+// RUN: %clang_cc1 -triple spirv-linux-vulkan-library -x hlsl -emit-llvm -finclude-default-header -disable-llvm-passes -o - %s | FileCheck %s --check-prefixes=CHECK,CHECK-SPIRV
 
 // Make sure SV_DispatchThreadID translated into dx.thread.id.
 
-const RWBuffer In;
-RWBuffer Out;
-
-// CHECK: define void @foo()
-// CHECK: %[[ID:[0-9a-zA-Z]+]] = call i32 @llvm.dx.thread.id(i32 0)
-// CHECK: call void @"?foo@@YAXH@Z"(i32 %[[ID]])
+// CHECK:       define void @foo()
+// CHECK-DXIL:  %[[#ID:]] = call i32 @llvm.dx.thread.id(i32 0)
+// CHECK-SPIRV: %[[#ID:]] = call i32 @llvm.spv.thread.id(i32 0)
+// CHECK:       call void @{{.*}}foo{{.*}}(i32 %[[#ID]])
 [shader("compute")]
 [numthreads(8,8,1)]
-void foo(uint Idx : SV_DispatchThreadID) {
-  Out[Idx] = In[Idx];
-}
+void foo(uint Idx : SV_DispatchThreadID) {}
 
-// CHECK: define void @bar()
-// CHECK: %[[ID_X:[0-9a-zA-Z]+]] = call i32 @llvm.dx.thread.id(i32 0)
-// CHECK: %[[ID_X_:[0-9a-zA-Z]+]] = insertelement <2 x i32> poison, i32 %[[ID_X]], i64 0
-// CHECK: %[[ID_Y:[0-9a-zA-Z]+]] = call i32 @llvm.dx.thread.id(i32 1)
-// CHECK: %[[ID_XY:[0-9a-zA-Z]+]] = insertelement <2 x i32> %[[ID_X_]], i32 %[[ID_Y]], i64 1
-// CHECK: call void @"?bar@@YAXT?$__vector@H$01@__clang@@@Z"(<2 x i32> %[[ID_XY]])
+// CHECK:       define void @bar()
+// CHECK-DXIL:  %[[#ID_X:]] = call i32 @llvm.dx.thread.id(i32 0)
+// CHECK-SPIRV: %[[#ID_X:]] = call i32 @llvm.spv.thread.id(i32 0)
+// CHECK:       %[[#ID_X_:]] = insertelement <2 x i32> poison, i32 %[[#ID_X]], i64 0
+// CHECK-DXIL:  %[[#ID_Y:]] = call i32 @llvm.dx.thread.id(i32 1)
+// CHECK-SPIRV: %[[#ID_Y:]] = call i32 @llvm.spv.thread.id(i32 1)
+// CHECK:       %[[#ID_XY:]] = insertelement <2 x i32> %[[#ID_X_]], i32 %[[#ID_Y]], i64 1
+// CHECK-DXIL:  call void @{{.*}}bar{{.*}}(<2 x i32> %[[#ID_XY]])
 [shader("compute")]
 [numthreads(8,8,1)]
-void bar(uint2 Idx : SV_DispatchThreadID) {
-  Out[Idx.y] = In[Idx.x];
-}
+void bar(uint2 Idx : SV_DispatchThreadID) {}
 
diff --git a/clang/test/CodeGenObjC/constant-non-fragile-ivar-offset.m b/clang/test/CodeGenObjC/constant-non-fragile-ivar-offset.m
index 788b3220af30673041f3f951d997ce59631281d2..8d55e6c7d230814f0f1e93bb9b825109a2ae2bc9 100644
--- a/clang/test/CodeGenObjC/constant-non-fragile-ivar-offset.m
+++ b/clang/test/CodeGenObjC/constant-non-fragile-ivar-offset.m
@@ -1,6 +1,13 @@
 // RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 -emit-llvm %s -o - | FileCheck %s
 
 // CHECK: @"OBJC_IVAR_$_StaticLayout.static_layout_ivar" = hidden constant i64 20
+// CHECK: @"OBJC_IVAR_$_SuperClass.superClassIvar" = hidden constant i64 20
+// CHECK: @"OBJC_IVAR_$_SuperClass._superClassProperty" = hidden constant i64 24
+// CHECK: @"OBJC_IVAR_$_IntermediateClass.intermediateClassIvar" = constant i64 32
+// CHECK: @"OBJC_IVAR_$_IntermediateClass.intermediateClassIvar2" = constant i64 40
+// CHECK: @"OBJC_IVAR_$_IntermediateClass._intermediateProperty" = hidden constant i64 48
+// CHECK: @"OBJC_IVAR_$_SubClass.subClassIvar" = constant i64 56
+// CHECK: @"OBJC_IVAR_$_SubClass._subClassProperty" = hidden constant i64 64
 // CHECK: @"OBJC_IVAR_$_NotStaticLayout.not_static_layout_ivar" = hidden global i64 12
 
 @interface NSObject {
@@ -14,12 +21,105 @@
 @implementation StaticLayout {
   int static_layout_ivar;
 }
+
+// CHECK-LABEL: define internal void @"\01-[StaticLayout meth]"
 -(void)meth {
   static_layout_ivar = 0;
   // CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_StaticLayout
+  // CHECK: getelementptr inbounds i8, ptr %0, i64 20
+}
+@end
+
+@interface SuperClass : NSObject
+@property (nonatomic, assign) int superClassProperty;
+@end
+
+@implementation SuperClass {
+  int superClassIvar; // Declare an ivar
+}
+
+// CHECK-LABEL: define internal void @"\01-[SuperClass superClassMethod]"
+- (void)superClassMethod {
+    _superClassProperty = 42;
+    superClassIvar = 10;
+    // CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_SuperClass
+    // CHECK: getelementptr inbounds i8, ptr %1, i64 20
+}
+
+// Implicitly synthesized method here
+// CHECK-LABEL: define internal i32 @"\01-[SuperClass superClassProperty]"
+// CHECK: getelementptr inbounds i8, ptr %0, i64 24
+
+// CHECK-LABEL: define internal void @"\01-[SuperClass setSuperClassProperty:]"
+// CHECK: getelementptr inbounds i8, ptr %1, i64 24
+@end
+
+@interface IntermediateClass : SuperClass {
+    double intermediateClassIvar;
+
+    @protected
+    int intermediateClassIvar2;
+}
+@property (nonatomic, strong) SuperClass *intermediateProperty;
+@end
+
+@implementation IntermediateClass
+@synthesize intermediateProperty = _intermediateProperty;
+
+// CHECK-LABEL: define internal void @"\01-[IntermediateClass intermediateClassMethod]"
+- (void)intermediateClassMethod {
+    intermediateClassIvar = 3.14;
+    // CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_IntermediateClass
+    // CHECK: getelementptr inbounds i8, ptr %0, i64 32
+}
+
+// CHECK-LABEL: define internal void @"\01-[IntermediateClass intermediateClassPropertyMethod]"
+- (void)intermediateClassPropertyMethod {
+    self.intermediateProperty = 0;
+    // CHECK: load ptr, ptr @OBJC_SELECTOR_REFERENCES_
+    // CHECK: call void @objc_msgSend(ptr noundef %0, ptr noundef %1, ptr noundef null)
+}
+
+// CHECK-LABEL: define internal void @"\01-[IntermediateClass intermediateClassPropertyMethodDirect]"
+- (void)intermediateClassPropertyMethodDirect {
+    _intermediateProperty = 0;
+    // CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_IntermediateClass._intermediateProperty"
+    // CHECK: getelementptr inbounds i8, ptr %0, i64 48
 }
 @end
 
+@interface SubClass : IntermediateClass {
+    double subClassIvar;
+}
+@property (nonatomic, assign) SubClass *subClassProperty;
+@end
+
+@implementation SubClass
+
+// CHECK-LABEL: define internal void @"\01-[SubClass subclassVar]"
+- (void)subclassVar {
+    subClassIvar = 6.28;
+    // CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_SubClass
+    // CHECK: getelementptr inbounds i8, ptr %0, i64 56
+}
+
+// CHECK-LABEL: define internal void @"\01-[SubClass intermediateSubclassVar]"
+-(void)intermediateSubclassVar {
+    intermediateClassIvar = 3.14;
+    // CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_IntermediateClass
+    // CHECK: getelementptr inbounds i8, ptr %0, i64 32
+}
+
+// Implicit synthesized method here:
+// CHECK-LABEL: define internal ptr @"\01-[SubClass subClassProperty]"
+// CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_SubClass._subClassProperty"
+// CHECK: getelementptr inbounds i8, ptr %0, i64 64
+
+// CHECK-LABEL: define internal void @"\01-[SubClass setSubClassProperty:]"
+// CHECK-NOT: load i64, ptr @"OBJC_IVAR_$_SubClass._subClassProperty"
+// CHECK: getelementptr inbounds i8, ptr %1, i64 64
+@end
+
 @interface NotNSObject {
   int these, might, change;
 }
@@ -31,6 +131,8 @@
 @implementation NotStaticLayout {
   int not_static_layout_ivar;
 }
+
+// CHECK-LABEL: define internal void @"\01-[NotStaticLayout meth]"
 -(void)meth {
   not_static_layout_ivar = 0;
   // CHECK: load i64, ptr @"OBJC_IVAR_$_NotStaticLayout.not_static_layout_ivar
diff --git a/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl b/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl
index 2cf1286e2b54e8e4f1d99b30b1df83aa31f784a9..a5c9f69bc2de0666c4af21039907f1f21d1e84a5 100644
--- a/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl
+++ b/clang/test/CodeGenOpenCL/amdgpu-enqueue-kernel.cl
@@ -703,7 +703,7 @@ kernel void test_target_features_kernel(global int *i) {
 // GFX900: attributes #8 = { nounwind }
 // GFX900: attributes #9 = { convergent nounwind }
 //.
-// NOCPU: !0 = !{i32 1, !"amdgpu_code_object_version", i32 500}
+// NOCPU: !0 = !{i32 1, !"amdhsa_code_object_version", i32 500}
 // NOCPU: !1 = !{i32 1, !"wchar_size", i32 4}
 // NOCPU: !2 = !{i32 2, i32 0}
 // NOCPU: !3 = !{i32 1, i32 0, i32 1, i32 0}
@@ -721,7 +721,7 @@ kernel void test_target_features_kernel(global int *i) {
 // NOCPU: !15 = !{i32 1}
 // NOCPU: !16 = !{!"int*"}
 //.
-// GFX900: !0 = !{i32 1, !"amdgpu_code_object_version", i32 500}
+// GFX900: !0 = !{i32 1, !"amdhsa_code_object_version", i32 500}
 // GFX900: !1 = !{i32 1, !"wchar_size", i32 4}
 // GFX900: !2 = !{i32 2, i32 0}
 // GFX900: !3 = !{!4, !4, i64 0}
diff --git a/clang/test/CodeGenOpenCL/amdgpu-features.cl b/clang/test/CodeGenOpenCL/amdgpu-features.cl
index 9c8ca0bb96f6125b9f15c146e45c83cfec997ffd..7387f9a22f0dfc11e174f5f6f43d6b27a476ba8e 100644
--- a/clang/test/CodeGenOpenCL/amdgpu-features.cl
+++ b/clang/test/CodeGenOpenCL/amdgpu-features.cl
@@ -100,8 +100,8 @@
 // GFX1103: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
 // GFX1150: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
 // GFX1151: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
-// GFX1200: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot10-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+fp8-conversion-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
-// GFX1201: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot10-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+fp8-conversion-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
+// GFX1200: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot10-insts,+dot11-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+fp8-conversion-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
+// GFX1201: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot10-insts,+dot11-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+fp8-conversion-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
 
 // GFX1103-W64: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize64"
 
diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl
index f5317683d0ff97544b84c7b1f0027bb2b17cdc06..ce36a807a6c0e3487ef9c68dbccdb79ea75cf126 100644
--- a/clang/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl
+++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-dl-insts-err.cl
@@ -50,8 +50,8 @@ kernel void builtins_amdgcn_dl_insts_err(
   iOut[3] = __builtin_amdgcn_sudot8(false, A, true, B, C, false);    // expected-error {{'__builtin_amdgcn_sudot8' needs target feature dot8-insts}}
   iOut[4] = __builtin_amdgcn_sudot8(true, A, false, B, C, true);     // expected-error {{'__builtin_amdgcn_sudot8' needs target feature dot8-insts}}
 
-  fOut[5] = __builtin_amdgcn_dot4_f32_fp8_bf8(uiA, uiB, fC);        // expected-error {{'__builtin_amdgcn_dot4_f32_fp8_bf8' needs target feature gfx12-insts}}
-  fOut[6] = __builtin_amdgcn_dot4_f32_bf8_fp8(uiA, uiB, fC);        // expected-error {{'__builtin_amdgcn_dot4_f32_bf8_fp8' needs target feature gfx12-insts}}
-  fOut[7] = __builtin_amdgcn_dot4_f32_fp8_fp8(uiA, uiB, fC);        // expected-error {{'__builtin_amdgcn_dot4_f32_fp8_fp8' needs target feature gfx12-insts}}
-  fOut[8] = __builtin_amdgcn_dot4_f32_bf8_bf8(uiA, uiB, fC);        // expected-error {{'__builtin_amdgcn_dot4_f32_bf8_bf8' needs target feature gfx12-insts}}
+  fOut[5] = __builtin_amdgcn_dot4_f32_fp8_bf8(uiA, uiB, fC);        // expected-error {{'__builtin_amdgcn_dot4_f32_fp8_bf8' needs target feature dot11-insts}}
+  fOut[6] = __builtin_amdgcn_dot4_f32_bf8_fp8(uiA, uiB, fC);        // expected-error {{'__builtin_amdgcn_dot4_f32_bf8_fp8' needs target feature dot11-insts}}
+  fOut[7] = __builtin_amdgcn_dot4_f32_fp8_fp8(uiA, uiB, fC);        // expected-error {{'__builtin_amdgcn_dot4_f32_fp8_fp8' needs target feature dot11-insts}}
+  fOut[8] = __builtin_amdgcn_dot4_f32_bf8_bf8(uiA, uiB, fC);        // expected-error {{'__builtin_amdgcn_dot4_f32_bf8_bf8' needs target feature dot11-insts}}
 }
diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
index 7d9010ee9067d679f552f9c73818f1d525723ae0..8a4533633706b2478fcf7d943739c93c339b313c 100644
--- a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
+++ b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
@@ -839,6 +839,18 @@ unsigned test_wavefrontsize() {
   return __builtin_amdgcn_wavefrontsize();
 }
 
+// CHECK-LABEL test_get_fpenv(
+unsigned long test_get_fpenv() {
+  // CHECK: call i64 @llvm.get.fpenv.i64()
+  return __builtin_amdgcn_get_fpenv();
+}
+
+// CHECK-LABEL test_set_fpenv(
+void test_set_fpenv(unsigned long env) {
+  // CHECK: call void @llvm.set.fpenv.i64(i64 %[[ENV:.+]])
+  __builtin_amdgcn_set_fpenv(env);
+}
+
 // CHECK-DAG: [[$WI_RANGE]] = !{i32 0, i32 1024}
 // CHECK-DAG: [[$WS_RANGE]] = !{i16 1, i16 1025}
 // CHECK-DAG: attributes #[[$NOUNWIND_READONLY]] = { convergent mustprogress nocallback nofree nounwind willreturn memory(none) }
diff --git a/clang/test/Driver/aarch64-mcpu.c b/clang/test/Driver/aarch64-mcpu.c
index 3e07f3597f34081da428233d902f304e36c285c8..cacfc691058d13709b22de2bf1ebc9be119236d7 100644
--- a/clang/test/Driver/aarch64-mcpu.c
+++ b/clang/test/Driver/aarch64-mcpu.c
@@ -50,6 +50,8 @@
 // CORTEXA78: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a78"
 // RUN: %clang --target=aarch64 -mcpu=cortex-a78c  -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A78C %s
 // CORTEX-A78C: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a78c"
+// RUN: %clang --target=aarch64 -mcpu=cortex-a78ae  -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A78AE %s
+// CORTEX-A78AE: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a78ae"
 // RUN: %clang --target=aarch64 -mcpu=cortex-a715  -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A715 %s
 // CORTEX-A715: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "cortex-a715"
 // RUN: %clang --target=aarch64 -mcpu=cortex-a720  -### -c %s 2>&1 | FileCheck -check-prefix=CORTEX-A720 %s
diff --git a/clang/test/Driver/amdgpu-openmp-toolchain.c b/clang/test/Driver/amdgpu-openmp-toolchain.c
index 4975e2f8a52399c17eacf8ae2542b8ebb2418483..849afb871ddbfc65c8e0e78c43a8c08c8a41efc7 100644
--- a/clang/test/Driver/amdgpu-openmp-toolchain.c
+++ b/clang/test/Driver/amdgpu-openmp-toolchain.c
@@ -11,7 +11,7 @@
 // CHECK: "-cc1" "-triple" "x86_64-unknown-linux-gnu"{{.*}}"-emit-llvm-bc"{{.*}}"-x" "c"
 // CHECK: "-cc1" "-triple" "amdgcn-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu"{{.*}}"-target-cpu" "gfx906"{{.*}}"-fcuda-is-device"{{.*}}
 // CHECK: "-cc1" "-triple" "x86_64-unknown-linux-gnu"{{.*}}"-emit-obj"
-// CHECK: clang-linker-wrapper{{.*}}"--"{{.*}} "-o" "a.out"
+// CHECK: clang-linker-wrapper{{.*}} "-o" "a.out"
 
 // RUN:   %clang -ccc-print-phases --target=x86_64-unknown-linux-gnu -fopenmp -fopenmp-targets=amdgcn-amd-amdhsa -Xopenmp-target=amdgcn-amd-amdhsa -march=gfx906 %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=CHECK-PHASES %s
diff --git a/clang/test/Driver/arm-cortex-cpus-2.c b/clang/test/Driver/arm-cortex-cpus-2.c
index c322303d22786681c25d11b271f273624d5cc2d7..5ce3758655b500ff1cea13c97db1df0ae3c6820f 100644
--- a/clang/test/Driver/arm-cortex-cpus-2.c
+++ b/clang/test/Driver/arm-cortex-cpus-2.c
@@ -537,6 +537,13 @@
 // CHECK-CORTEX-A78C-MFPU: "-target-feature" "+sha2"
 // CHECK-CORTEX-A78C-MFPU: "-target-feature" "+aes"
 
+// RUN: %clang -target armv8a-arm-none-eabi -mcpu=cortex-a78ae -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CORTEX-A78AE %s
+// RUN: %clang -target armv8a-arm-none-eabi -mcpu=cortex-a78ae -mfpu=crypto-neon-fp-armv8 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CORTEX-A78AE-MFPU %s
+// CHECK-CORTEX-A78AE: "-cc1"{{.*}} "-triple" "armv8.2a-{{.*}} "-target-cpu" "cortex-a78ae"
+// CHECK-CORTEX-A78AE-MFPU: "-cc1"{{.*}} "-target-feature" "+fp-armv8"
+// CHECK-CORTEX-A78AE-MFPU: "-target-feature" "+sha2"
+// CHECK-CORTEX-A78AE-MFPU: "-target-feature" "+aes"
+
 // RUN: %clang -target armv8a-arm-none-eabi -mcpu=cortex-a710 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CORTEX-A710 %s
 // RUN: %clang -target armv8a-arm-none-eabi -mcpu=cortex-a710 -mfpu=crypto-neon-fp-armv8 -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-CORTEX-A710-MFPU %s
 // CHECK-CORTEX-A710: "-cc1"{{.*}} "-triple" "armv9a-{{.*}} "-target-cpu" "cortex-a710"
diff --git a/clang/test/Driver/clang-offload-bundler-zlib.c b/clang/test/Driver/clang-offload-bundler-zlib.c
index a57ee6da9a86a6d31ecb1091335a0acbb5ce8929..15b60341a8dbde372d010514a201a01a6fd609eb 100644
--- a/clang/test/Driver/clang-offload-bundler-zlib.c
+++ b/clang/test/Driver/clang-offload-bundler-zlib.c
@@ -1,4 +1,4 @@
-// REQUIRES: zlib
+// REQUIRES: zlib && !zstd
 // REQUIRES: x86-registered-target
 // UNSUPPORTED: target={{.*}}-darwin{{.*}}, target={{.*}}-aix{{.*}}
 
@@ -34,13 +34,28 @@
 // RUN: diff %t.tgt2 %t.res.tgt2
 
 //
-// COMPRESS: Compression method used:
-// DECOMPRESS: Decompression method:
+// COMPRESS: Compression method used: zlib
+// COMPRESS: Compression level: 6
+// DECOMPRESS: Decompression method: zlib
+// DECOMPRESS: Hashes match: Yes
 // NOHOST-NOT: host-
 // NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx900
 // NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx906
 //
 
+// Check -compression-level= option
+
+// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \
+// RUN:   -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip.bundle.bc -compress -verbose -compression-level=9 2>&1 | \
+// RUN:   FileCheck -check-prefix=LEVEL %s
+// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \
+// RUN:   -output=%t.res.tgt1 -output=%t.res.tgt2 -input=%t.hip.bundle.bc -unbundle
+// RUN: diff %t.tgt1 %t.res.tgt1
+// RUN: diff %t.tgt2 %t.res.tgt2
+//
+// LEVEL: Compression method used: zlib
+// LEVEL: Compression level: 9
+
 //
 // Check -bundle-align option.
 //
diff --git a/clang/test/Driver/clang-offload-bundler-zstd.c b/clang/test/Driver/clang-offload-bundler-zstd.c
index 3b577d4d166a3f5e8b6162d67bcb3f981ad4f9ae..4485e57309bbbc5b9489b496d5751b3ed783862a 100644
--- a/clang/test/Driver/clang-offload-bundler-zstd.c
+++ b/clang/test/Driver/clang-offload-bundler-zstd.c
@@ -31,13 +31,28 @@
 // RUN: diff %t.tgt1 %t.res.tgt1
 // RUN: diff %t.tgt2 %t.res.tgt2
 //
-// COMPRESS: Compression method used
-// DECOMPRESS: Decompression method
+// COMPRESS: Compression method used: zstd
+// COMPRESS: Compression level: 3 
+// DECOMPRESS: Decompression method: zstd
+// DECOMPRESS: Hashes match: Yes
 // NOHOST-NOT: host-
 // NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx900
 // NOHOST-DAG: hip-amdgcn-amd-amdhsa--gfx906
 //
 
+// Check -compression-level= option
+
+// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \
+// RUN:   -input=%t.tgt1 -input=%t.tgt2 -output=%t.hip.bundle.bc -compress -verbose -compression-level=9 2>&1 | \
+// RUN:   FileCheck -check-prefix=LEVEL %s
+// RUN: clang-offload-bundler -type=bc -targets=hip-amdgcn-amd-amdhsa--gfx900,hip-amdgcn-amd-amdhsa--gfx906 \
+// RUN:   -output=%t.res.tgt1 -output=%t.res.tgt2 -input=%t.hip.bundle.bc -unbundle
+// RUN: diff %t.tgt1 %t.res.tgt1
+// RUN: diff %t.tgt2 %t.res.tgt2
+//
+// LEVEL: Compression method used: zstd
+// LEVEL: Compression level: 9
+
 //
 // Check -bundle-align option.
 //
diff --git a/clang/test/Driver/clang-offload-bundler.c b/clang/test/Driver/clang-offload-bundler.c
index 9d8b81ee9806ee85e5888ea7acc15a8895249ccd..f3cd2493e052772a75d2e4dd5fbd01d064995554 100644
--- a/clang/test/Driver/clang-offload-bundler.c
+++ b/clang/test/Driver/clang-offload-bundler.c
@@ -13,6 +13,19 @@
 // RUN: obj2yaml %t.o > %t.o.yaml
 // RUN: %clang -O0 -target %itanium_abi_triple %s -emit-ast -o %t.ast
 
+// RUN: echo 'void a() {}' >%t.a.cpp
+// RUN: echo 'void b() {}' >%t.b.cpp
+// RUN: %clang -target %itanium_abi_triple %t.a.cpp -c -o %t.a.o
+// RUN: %clang -target %itanium_abi_triple %t.b.cpp -c -o %t.b.o
+//
+// Remove .llvm_addrsig section since its offset changes after llvm-objcopy
+// removes clang-offload-bundler sections, therefore not good for comparison.
+//
+// RUN: llvm-objcopy --remove-section=.llvm_addrsig %t.a.o
+// RUN: llvm-objcopy --remove-section=.llvm_addrsig %t.b.o
+// RUN: obj2yaml %t.a.o > %t.a.yaml
+// RUN: obj2yaml %t.b.o > %t.b.yaml
+
 //
 // Generate an empty file to help with the checks of empty files.
 //
@@ -414,6 +427,25 @@
 // HIP-AR-906-DAG: hip_bundle1-hip-amdgcn-amd-amdhsa--gfx906
 // HIP-AR-906-DAG: hip_bundle2-hip-amdgcn-amd-amdhsa--gfx906
 
+//
+// Check unbundling archive for host target
+//
+// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,hip-amdgcn-amd-amdhsa--gfx900 \
+// RUN:   -input=%t.a.o -input=%t.tgt1 -output=%t.a.bundled.o
+// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,hip-amdgcn-amd-amdhsa--gfx900 \
+// RUN:   -input=%t.b.o -input=%t.tgt1 -output=%t.b.bundled.o
+// RUN: rm -f %t.bundled.a
+// RUN: llvm-ar cr %t.bundled.a %t.a.bundled.o %t.b.bundled.o
+// RUN: cp %t.bundled.a %t.bundled.a.bak
+// RUN: clang-offload-bundler -unbundle --targets=host-%itanium_abi_triple -type=a -input=%t.bundled.a -output=%t.host.a
+// RUN: rm -f *%itanium_abi_triple*.a.bundled.o *%itanium_abi_triple*.b.bundled.o
+// RUN: llvm-ar -x %t.host.a
+// RUN: diff %t.bundled.a %t.bundled.a.bak
+// RUN: obj2yaml *%itanium_abi_triple*.a.bundled.o > %t.a.unbundled.yaml
+// RUN: diff %t.a.unbundled.yaml %t.a.yaml
+// RUN: obj2yaml *%itanium_abi_triple*.b.bundled.o > %t.b.unbundled.yaml
+// RUN: diff %t.b.unbundled.yaml %t.b.yaml
+//
 // Check clang-offload-bundler reporting an error when trying to unbundle an archive but
 // the input file is not an archive.
 //
diff --git a/clang/test/Driver/cuda-bad-arch.cu b/clang/test/Driver/cuda-bad-arch.cu
index 877b20bc9351bce886b2d8f3cd6f19dd8df9df1c..35a56a8bef0f0d04d29d7ff9998068671d4105de 100644
--- a/clang/test/Driver/cuda-bad-arch.cu
+++ b/clang/test/Driver/cuda-bad-arch.cu
@@ -30,9 +30,9 @@
 // RUN: | FileCheck -check-prefix OK %s
 
 // We don't allow using NVPTX/AMDGCN for host compilation.
-// RUN: not %clang -### --cuda-host-only --target=nvptx-nvidia-cuda -nogpulib -nogpuinc -c %s 2>&1 \
+// RUN: not %clang -### --no-offload-new-driver --cuda-host-only --target=nvptx-nvidia-cuda -nogpulib -nogpuinc -c %s 2>&1 \
 // RUN: | FileCheck -check-prefix HOST_NVPTX %s
-// RUN: not %clang -### --cuda-host-only --target=amdgcn-amd-amdhsa -nogpulib -nogpuinc -c %s 2>&1 \
+// RUN: not %clang -### --no-offload-new-driver --cuda-host-only --target=amdgcn-amd-amdhsa -nogpulib -nogpuinc -c %s 2>&1 \
 // RUN: | FileCheck -check-prefix HOST_AMDGCN %s
 
 // OK-NOT: error: Unsupported CUDA gpu architecture
diff --git a/clang/test/Driver/cuda-detect.cu b/clang/test/Driver/cuda-detect.cu
index 077d555a3128f27a32c040860bdf68fbf6e32599..49e58004e672c3ae79a828b17510e5d99aa6c76d 100644
--- a/clang/test/Driver/cuda-detect.cu
+++ b/clang/test/Driver/cuda-detect.cu
@@ -11,7 +11,6 @@
 // RUN: %clang -v --target=x86_64-apple-macosx \
 // RUN:   --sysroot=%S/no-cuda-there --cuda-path-ignore-env 2>&1 | FileCheck %s -check-prefix NOCUDA
 
-
 // RUN: %clang -v --target=i386-unknown-linux \
 // RUN:   --sysroot=%S/Inputs/CUDA --cuda-path-ignore-env 2>&1 | FileCheck %s
 // RUN: %clang -v --target=i386-apple-macosx \
@@ -146,9 +145,9 @@
 // RUN:     -check-prefix NOCUDAINC
 
 // Verify that C++ include paths are passed for both host and device frontends.
-// RUN: not %clang -### --target=x86_64-linux-gnu %s \
+// RUN: %clang -### --target=x86_64-linux-gnu %s \
 // RUN: --stdlib=libstdc++ --sysroot=%S/Inputs/ubuntu_14.04_multiarch_tree2 \
-// RUN: --gcc-toolchain="" 2>&1 \
+// RUN: -nogpulib -nogpuinc --gcc-toolchain="" 2>&1 \
 // RUN: | FileCheck %s --check-prefix CHECK-CXXINCLUDE
 
 // Verify that CUDA SDK version is propagated to the CC1 compilations.
diff --git a/clang/test/Driver/cuda-external-tools.cu b/clang/test/Driver/cuda-external-tools.cu
index 1aa87cc09982c67751f9abbbfc5984859d3ed44f..946e144fce38fb0ef29f264f60fa54fb12ab354e 100644
--- a/clang/test/Driver/cuda-external-tools.cu
+++ b/clang/test/Driver/cuda-external-tools.cu
@@ -25,7 +25,7 @@
 // RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35,OPT3 %s
 // Generating relocatable device code
 // RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -c %s 2>&1 \
-// RUN:   --offload-arch=sm_35 --cuda-path=%S/Inputs/CUDA/usr/local/cuda \
+// RUN:   --no-offload-new-driver --offload-arch=sm_35 --cuda-path=%S/Inputs/CUDA/usr/local/cuda \
 // RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35,RDC %s
 
 // With debugging enabled, ptxas should be run with with no ptxas optimizations.
@@ -59,7 +59,7 @@
 // RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35 %s
 // Separate compilation targeting sm_35.
 // RUN: %clang -### --target=x86_64-linux-gnu --cuda-gpu-arch=sm_35 -fgpu-rdc -c %s 2>&1 \
-// RUN:   --offload-arch=sm_35 --cuda-path=%S/Inputs/CUDA/usr/local/cuda \
+// RUN:   --no-offload-new-driver --offload-arch=sm_35 --cuda-path=%S/Inputs/CUDA/usr/local/cuda \
 // RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35,RDC %s
 
 // 32-bit compile.
@@ -68,7 +68,7 @@
 // RUN: | FileCheck -check-prefixes=CHECK,ARCH32,SM35 %s
 // 32-bit compile when generating relocatable device code.
 // RUN: %clang -### --target=i386-linux-gnu -fgpu-rdc -c %s 2>&1 \
-// RUN:   --offload-arch=sm_35 --cuda-path=%S/Inputs/CUDA/usr/local/cuda \
+// RUN:   --no-offload-new-driver --offload-arch=sm_35 --cuda-path=%S/Inputs/CUDA/usr/local/cuda \
 // RUN: | FileCheck -check-prefixes=CHECK,ARCH32,SM35,RDC %s
 
 // Compile with -fintegrated-as.  This should still cause us to invoke ptxas.
@@ -77,7 +77,7 @@
 // RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35,OPT0 %s
 // Check that we still pass -c when generating relocatable device code.
 // RUN: %clang -### --target=x86_64-linux-gnu -fintegrated-as -fgpu-rdc -c %s 2>&1 \
-// RUN:   --offload-arch=sm_35 --cuda-path=%S/Inputs/CUDA/usr/local/cuda \
+// RUN:   --no-offload-new-driver --offload-arch=sm_35 --cuda-path=%S/Inputs/CUDA/usr/local/cuda \
 // RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35,RDC %s
 
 // Check -Xcuda-ptxas and -Xcuda-fatbinary
@@ -99,13 +99,13 @@
 
 // Check relocatable device code generation on MacOS.
 // RUN: %clang -### --target=x86_64-apple-macosx -O0 -fgpu-rdc -c %s 2>&1 \
-// RUN:   --offload-arch=sm_35 --cuda-path=%S/Inputs/CUDA/usr/local/cuda \
+// RUN:   --no-offload-new-driver --offload-arch=sm_35 --cuda-path=%S/Inputs/CUDA/usr/local/cuda \
 // RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35,RDC %s
 // RUN: %clang -### --target=x86_64-apple-macosx --cuda-gpu-arch=sm_35 -fgpu-rdc -c %s 2>&1 \
-// RUN:   --offload-arch=sm_35 --cuda-path=%S/Inputs/CUDA/usr/local/cuda \
+// RUN:   --no-offload-new-driver --offload-arch=sm_35 --cuda-path=%S/Inputs/CUDA/usr/local/cuda \
 // RUN: | FileCheck -check-prefixes=CHECK,ARCH64,SM35,RDC %s
 // RUN: %clang -### --target=i386-apple-macosx -fgpu-rdc -c %s 2>&1 \
-// RUN:   --offload-arch=sm_35 --cuda-path=%S/Inputs/CUDA/usr/local/cuda \
+// RUN:   --no-offload-new-driver --offload-arch=sm_35 --cuda-path=%S/Inputs/CUDA/usr/local/cuda \
 // RUN: | FileCheck -check-prefixes=CHECK,ARCH32,SM35,RDC %s
 
 // Check that CLANG forwards the -v flag to PTXAS.
diff --git a/clang/test/Driver/cuda-march.cu b/clang/test/Driver/cuda-march.cu
index 7003e9fd4198c6d52a0508fce116276ded84cb0e..25fd6f3a10f2a2595125a329a5c3e3ed0b1818f3 100644
--- a/clang/test/Driver/cuda-march.cu
+++ b/clang/test/Driver/cuda-march.cu
@@ -5,15 +5,15 @@
 // REQUIRES: x86-registered-target
 // REQUIRES: nvptx-registered-target
 
-// RUN: not %clang -### --target=x86_64-linux-gnu -c \
-// RUN: -march=haswell %s 2>&1 | FileCheck %s
-// RUN: not %clang -### --target=x86_64-linux-gnu -c \
-// RUN: -march=haswell --cuda-gpu-arch=sm_35 %s 2>&1 | FileCheck %s
+// RUN: %clang -### --target=x86_64-linux-gnu -c \
+// RUN: -nogpulib -nogpuinc -march=haswell %s 2>&1 | FileCheck %s
+// RUN: %clang -### --target=x86_64-linux-gnu -c \
+// RUN: -nogpulib -nogpuinc -march=haswell --cuda-gpu-arch=sm_52 %s 2>&1 | FileCheck %s
 
 // CHECK: "-cc1"{{.*}} "-triple" "nvptx
-// CHECK-SAME: "-target-cpu" "sm_35"
+// CHECK-SAME: "-target-cpu" "sm_52"
 
 // CHECK: ptxas
-// CHECK-SAME: "--gpu-name" "sm_35"
+// CHECK-SAME: "--gpu-name" "sm_52"
 
 // CHECK: "-cc1"{{.*}} "-target-cpu" "haswell"
diff --git a/clang/test/Driver/cuda-omp-unsupported-debug-options.cu b/clang/test/Driver/cuda-omp-unsupported-debug-options.cu
index 77cfa6925e387fc82c1a00d3fa001fe8c21ec2f7..8e1bb2e496c749856fc1475c654cbf8b2f43405e 100644
--- a/clang/test/Driver/cuda-omp-unsupported-debug-options.cu
+++ b/clang/test/Driver/cuda-omp-unsupported-debug-options.cu
@@ -2,56 +2,56 @@
 // REQUIRES: nvptx-registered-target
 // REQUIRES: zlib
 
-// RUN: not %clang -### --target=x86_64-linux-gnu -c %s -g -gz 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -c %s -g -gz 2>&1 \
 // RUN: | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -c %s -gdwarf -fdebug-info-for-profiling 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -c %s -gdwarf -fdebug-info-for-profiling 2>&1 \
 // RUN: | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -c %s -gdwarf-2 -gsplit-dwarf 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -c %s -gdwarf-2 -gsplit-dwarf 2>&1 \
 // RUN: | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -c %s -gdwarf-3 -glldb 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -c %s -gdwarf-3 -glldb 2>&1 \
 // RUN: | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -c %s -gdwarf-4 -gcodeview 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -c %s -gdwarf-4 -gcodeview 2>&1 \
 // RUN: | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -c %s -gdwarf-5 -gmodules 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -c %s -gdwarf-5 -gmodules 2>&1 \
 // RUN: | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -c %s -ggdb1 -fdebug-macro 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -c %s -ggdb1 -fdebug-macro 2>&1 \
 // RUN: | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -c %s -ggdb2 -ggnu-pubnames 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -c %s -ggdb2 -ggnu-pubnames 2>&1 \
 // RUN: | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -c %s -ggdb3 -gdwarf-aranges 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -c %s -ggdb3 -gdwarf-aranges 2>&1 \
 // RUN: | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -c %s -g -gcolumn-info -fdebug-types-section 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -c %s -g -gcolumn-info -fdebug-types-section 2>&1 \
 // RUN: | FileCheck %s --check-prefixes WARN,COMMON
 
 // Same tests for OpenMP
-// RUN: not %clang -### --target=x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -fopenmp=libomp -c %s \
 // RUN:   -fgpu-rdc -g -gz 2>&1 | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -fopenmp=libomp -c %s \
 // RUN:   -fgpu-rdc -gdwarf -fdebug-info-for-profiling 2>&1 | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -fopenmp=libomp -c %s \
 // RUN:   -fgpu-rdc -gdwarf-2 -gsplit-dwarf 2>&1 | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -fopenmp=libomp -c %s \
 // RUN:   -fgpu-rdc -gdwarf-3 -glldb 2>&1 | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -fopenmp=libomp -c %s \
 // RUN:   -fgpu-rdc -gdwarf-4 -gcodeview 2>&1 | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -fopenmp=libomp -c %s \
 // RUN:   -fgpu-rdc -gdwarf-5 -gmodules 2>&1 | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -fopenmp=libomp -c %s \
 // RUN:   -fgpu-rdc -ggdb1 -fdebug-macro 2>&1 | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -fopenmp=libomp -c %s \
 // RUN:   -fgpu-rdc -ggdb2 -ggnu-pubnames 2>&1 | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -fopenmp=libomp -c %s \
 // RUN:   -fgpu-rdc -ggdb3 -gdwarf-aranges 2>&1 | FileCheck %s --check-prefixes WARN,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -fopenmp=libomp -c %s \
 // RUN:   -fgpu-rdc -g -gcolumn-info -fdebug-types-section 2>&1 | FileCheck %s --check-prefixes WARN,COMMON
 
-// RUN: not %clang -### --target=x86_64-linux-gnu -c %s -gdwarf-5 -gembed-source 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -c %s -gdwarf-5 -gembed-source 2>&1 \
 // RUN: | FileCheck %s --check-prefixes WARN-GES,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -c %s -ggdb -gembed-source -gdwarf-5 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -c %s -ggdb -gembed-source -gdwarf-5 2>&1 \
 // RUN: | FileCheck %s --check-prefixes WARN-GES,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -fopenmp=libomp -c %s \
 // RUN:   -fgpu-rdc -gdwarf-5 -gembed-source 2>&1 | FileCheck %s --check-prefixes WARN-GES,COMMON
-// RUN: not %clang -### --target=x86_64-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -c %s \
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-arch=sm_52 -nogpulib -nogpuinc -fopenmp=libomp -c %s \
 // RUN:   -fgpu-rdc -ggdb -gembed-source -gdwarf-5 2>&1 | FileCheck %s --check-prefixes WARN-GES,COMMON
 
 // COMMON: warning: debug information option '{{-gz|-fdebug-info-for-profiling|-gsplit-dwarf|-glldb|-gcodeview|-gmodules|-gembed-source|-fdebug-macro|-ggnu-pubnames|-gdwarf-aranges|-fdebug-types-section}}' is not supported
diff --git a/clang/test/Driver/cuda-options.cu b/clang/test/Driver/cuda-options.cu
index ad892b7839b96463ef1bcef73c3e293286af2344..8999a6618fe1fa75fb2745f469d31ad481fef5b1 100644
--- a/clang/test/Driver/cuda-options.cu
+++ b/clang/test/Driver/cuda-options.cu
@@ -4,197 +4,197 @@
 
 // Simple compilation case. Compile device-side to PTX assembly and make sure
 // we use it on the host side.
-// RUN: %clang -### -target x86_64-linux-gnu -c --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
+// RUN: %clang -### -target x86_64-linux-gnu -c -nogpulib -nogpuinc %s 2>&1 \
 // RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \
 // RUN:    -check-prefix HOST -check-prefix INCLUDES-DEVICE \
 // RUN:    -check-prefix NOLINK %s
 
 // Typical compilation + link case.
-// RUN: %clang -### -target x86_64-linux-gnu --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
+// RUN: %clang -### -target x86_64-linux-gnu -nogpulib -nogpuinc %s 2>&1 \
 // RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \
 // RUN:    -check-prefix HOST -check-prefix INCLUDES-DEVICE \
 // RUN:    -check-prefix LINK %s
 
 // Verify that --cuda-host-only disables device-side compilation, but doesn't
 // disable host-side compilation/linking.
-// RUN: %clang -### -target x86_64-linux-gnu --cuda-host-only --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
+// RUN: %clang -### -target x86_64-linux-gnu --cuda-host-only -nogpulib -nogpuinc %s 2>&1 \
 // RUN: | FileCheck -check-prefix NODEVICE -check-prefix HOST \
 // RUN:    -check-prefix NOINCLUDES-DEVICE -check-prefix LINK %s
 
 // Verify that --cuda-device-only disables host-side compilation and linking.
-// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
+// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only -nogpulib -nogpuinc %s 2>&1 \
 // RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \
 // RUN:    -check-prefix NOHOST -check-prefix NOLINK %s
 
 // Check that the last of --cuda-compile-host-device, --cuda-host-only, and
 // --cuda-device-only wins.
 
-// RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only \
-// RUN:    --cuda-host-only --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --cuda-device-only \
+// RUN:    --cuda-host-only -nogpulib -nogpuinc %s 2>&1 \
 // RUN: | FileCheck -check-prefix NODEVICE -check-prefix HOST \
 // RUN:    -check-prefix NOINCLUDES-DEVICE -check-prefix LINK %s
 
-// RUN: %clang -### -target x86_64-linux-gnu --cuda-compile-host-device \
-// RUN:    --cuda-host-only --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --cuda-compile-host-device \
+// RUN:    --cuda-host-only -nogpulib -nogpuinc %s 2>&1 \
 // RUN: | FileCheck -check-prefix NODEVICE -check-prefix HOST \
 // RUN:    -check-prefix NOINCLUDES-DEVICE -check-prefix LINK %s
 
-// RUN: not %clang -### --target=x86_64-linux-gnu --cuda-host-only \
-// RUN:    --cuda-device-only %s 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --cuda-host-only \
+// RUN:    -nogpulib -nogpuinc --cuda-device-only %s 2>&1 \
 // RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \
 // RUN:    -check-prefix NOHOST -check-prefix NOLINK %s
 
-// RUN: not %clang -### --target=x86_64-linux-gnu --cuda-compile-host-device \
-// RUN:    --cuda-device-only %s 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --cuda-compile-host-device \
+// RUN:    -nogpulib -nogpuinc --cuda-device-only %s 2>&1 \
 // RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \
 // RUN:    -check-prefix NOHOST -check-prefix NOLINK %s
 
-// RUN: not %clang -### --target=x86_64-linux-gnu --cuda-host-only \
-// RUN:   --cuda-compile-host-device %s 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --cuda-host-only \
+// RUN:   -nogpulib -nogpuinc --cuda-compile-host-device %s 2>&1 \
 // RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \
 // RUN:    -check-prefix HOST -check-prefix INCLUDES-DEVICE \
 // RUN:    -check-prefix LINK %s
 
-// RUN: not %clang -### --target=x86_64-linux-gnu --cuda-device-only \
-// RUN:   --cuda-compile-host-device %s 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu --cuda-device-only \
+// RUN:   -nogpulib -nogpuinc --cuda-compile-host-device %s 2>&1 \
 // RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \
 // RUN:    -check-prefix HOST -check-prefix INCLUDES-DEVICE \
 // RUN:    -check-prefix LINK %s
 
 // Verify that --cuda-gpu-arch option passes the correct GPU architecture to
 // device compilation.
-// RUN: not %clang -### --target=x86_64-linux-gnu --cuda-gpu-arch=sm_30 -c %s 2>&1 \
+// RUN: %clang -### -nogpulib -nogpuinc --target=x86_64-linux-gnu --cuda-gpu-arch=sm_52 -c %s 2>&1 \
 // RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \
-// RUN:    -check-prefix DEVICE-SM30 -check-prefix HOST \
+// RUN:    -check-prefix DEVICE-SM52 -check-prefix HOST \
 // RUN:    -check-prefix INCLUDES-DEVICE -check-prefix NOLINK %s
 
 // Verify that there is one device-side compilation per --cuda-gpu-arch args
 // and that all results are included on the host side.
-// RUN: not %clang -### --target=x86_64-linux-gnu \
-// RUN:   --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 -c %s 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu \
+// RUN:   -nogpulib -nogpuinc --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_52 -c %s 2>&1 \
 // RUN: | FileCheck -check-prefixes DEVICE,DEVICE-NOSAVE,DEVICE2 \
-// RUN:             -check-prefixes DEVICE-SM30,DEVICE2-SM35 \
+// RUN:             -check-prefixes DEVICE-SM52,DEVICE2-SM60 \
 // RUN:             -check-prefixes INCLUDES-DEVICE,INCLUDES-DEVICE2 \
 // RUN:             -check-prefixes HOST,HOST-NOSAVE,NOLINK %s
 
 // Verify that device-side results are passed to the correct tool when
 // -save-temps is used.
-// RUN: not %clang -### --target=x86_64-linux-gnu -save-temps -c %s 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -nogpuinc -save-temps -c %s 2>&1 \
 // RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-SAVE \
 // RUN:    -check-prefix HOST -check-prefix HOST-SAVE -check-prefix NOLINK %s
 
 // Verify that device-side results are passed to the correct tool when
 // -fno-integrated-as is used.
-// RUN: not %clang -### --target=x86_64-linux-gnu -fno-integrated-as -c %s 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -nogpuinc -fno-integrated-as -c %s 2>&1 \
 // RUN: | FileCheck -check-prefix DEVICE -check-prefix DEVICE-NOSAVE \
 // RUN:    -check-prefix HOST -check-prefix HOST-NOSAVE \
 // RUN:    -check-prefix HOST-AS -check-prefix NOLINK %s
 
 // Verify that --[no-]cuda-gpu-arch arguments are handled correctly.
 // a) --no-cuda-gpu-arch=X negates preceding --cuda-gpu-arch=X
-// RUN: not %clang -### --target=x86_64-linux-gnu --cuda-device-only \
-// RUN:   --cuda-gpu-arch=sm_50 --cuda-gpu-arch=sm_30 \
-// RUN:   --no-cuda-gpu-arch=sm_50 \
+// RUN: %clang -### --target=x86_64-linux-gnu --cuda-device-only \
+// RUN:   -nogpulib -nogpuinc --cuda-gpu-arch=sm_70 --cuda-gpu-arch=sm_52 \
+// RUN:   --no-cuda-gpu-arch=sm_70 \
 // RUN:   -c %s 2>&1 \
-// RUN: | FileCheck -check-prefixes ARCH-SM30,NOARCH-SM35,NOARCH-SM50 %s
+// RUN: | FileCheck -check-prefixes ARCH-SM52,NOARCH-SM60,NOARCH-SM70 %s
 
 // b) --no-cuda-gpu-arch=X negates more than one preceding --cuda-gpu-arch=X
-// RUN: not %clang -### --target=x86_64-linux-gnu --cuda-device-only \
-// RUN:   --cuda-gpu-arch=sm_50 --cuda-gpu-arch=sm_50 --cuda-gpu-arch=sm_30 \
-// RUN:   --no-cuda-gpu-arch=sm_50 \
+// RUN: %clang -### --target=x86_64-linux-gnu --cuda-device-only \
+// RUN:   -nogpulib -nogpuinc --cuda-gpu-arch=sm_70 --cuda-gpu-arch=sm_70 --cuda-gpu-arch=sm_52 \
+// RUN:   --no-cuda-gpu-arch=sm_70 \
 // RUN:   -c %s 2>&1 \
-// RUN: | FileCheck -check-prefixes ARCH-SM30,NOARCH-SM35,NOARCH-SM50 %s
+// RUN: | FileCheck -check-prefixes ARCH-SM52,NOARCH-SM60,NOARCH-SM70 %s
 
 // c) if --no-cuda-gpu-arch=X negates all preceding --cuda-gpu-arch=X
-//    we default to sm_35 -- same as if no --cuda-gpu-arch were passed.
-// RUN: not %clang -### --target=x86_64-linux-gnu --cuda-device-only \
-// RUN:   --cuda-gpu-arch=sm_50 --cuda-gpu-arch=sm_30 \
-// RUN:   --no-cuda-gpu-arch=sm_50 --no-cuda-gpu-arch=sm_30 \
+//    we default to sm_52 -- same as if no --cuda-gpu-arch were passed.
+// RUN: %clang -### --target=x86_64-linux-gnu --cuda-device-only \
+// RUN:   -nogpulib -nogpuinc --cuda-gpu-arch=sm_70 --cuda-gpu-arch=sm_60 \
+// RUN:   --no-cuda-gpu-arch=sm_70 --no-cuda-gpu-arch=sm_60 \
 // RUN:   -c %s 2>&1 \
-// RUN: | FileCheck -check-prefixes NOARCH-SM30,ARCH-SM35,NOARCH-SM50 %s
+// RUN: | FileCheck -check-prefixes ARCH-SM52,NOARCH-SM60,NOARCH-SM70 %s
 
 // d) --no-cuda-gpu-arch=X is a no-op if there's no preceding --cuda-gpu-arch=X
-// RUN: not %clang -### --target=x86_64-linux-gnu --cuda-device-only \
-// RUN:   --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30\
-// RUN:   --no-cuda-gpu-arch=sm_50 \
+// RUN: %clang -### --target=x86_64-linux-gnu --cuda-device-only \
+// RUN:   -nogpulib -nogpuinc --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_52\
+// RUN:   --no-cuda-gpu-arch=sm_70 \
 // RUN:   -c %s 2>&1 \
-// RUN: | FileCheck -check-prefixes ARCH-SM30,ARCH-SM35,NOARCH-SM50 %s
+// RUN: | FileCheck -check-prefixes ARCH-SM52,ARCH-SM60,NOARCH-SM70 %s
 
 // e) --no-cuda-gpu-arch=X does not affect following --cuda-gpu-arch=X
-// RUN: not %clang -### --target=x86_64-linux-gnu --cuda-device-only \
-// RUN:   --no-cuda-gpu-arch=sm_50 --no-cuda-gpu-arch=sm_30 \
-// RUN:   --cuda-gpu-arch=sm_50 --cuda-gpu-arch=sm_30 \
+// RUN: %clang -### --target=x86_64-linux-gnu --cuda-device-only \
+// RUN:   -nogpulib -nogpuinc --no-cuda-gpu-arch=sm_70 --no-cuda-gpu-arch=sm_52 \
+// RUN:   --cuda-gpu-arch=sm_70 --cuda-gpu-arch=sm_52 \
 // RUN:   -c %s 2>&1 \
-// RUN: | FileCheck -check-prefixes ARCH-SM30,NOARCH-SM35,ARCH-SM50 %s
+// RUN: | FileCheck -check-prefixes ARCH-SM52,NOARCH-SM60,ARCH-SM70 %s
 
 // f) --no-cuda-gpu-arch=all negates all preceding --cuda-gpu-arch=X
 // RUN: %clang -### -target x86_64-linux-gnu --cuda-device-only \
-// RUN:   --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
+// RUN:   -nogpulib -nogpuinc --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_52 \
 // RUN:   --no-cuda-gpu-arch=all \
-// RUN:   --cuda-gpu-arch=sm_50 \
-// RUN:   -c --cuda-path=%S/Inputs/CUDA/usr/local/cuda %s 2>&1 \
-// RUN: | FileCheck -check-prefixes NOARCH-SM30,NOARCH-SM35,ARCH-SM50 %s
+// RUN:   --cuda-gpu-arch=sm_70 \
+// RUN:   -c -nogpulib -nogpuinc %s 2>&1 \
+// RUN: | FileCheck -check-prefixes NOARCH-SM52,NOARCH-SM60,ARCH-SM70 %s
 
 // g) There's no --cuda-gpu-arch=all
 // RUN: not %clang -### --target=x86_64-linux-gnu --cuda-device-only \
-// RUN:   --cuda-gpu-arch=all \
+// RUN:   -nogpulib -nogpuinc --cuda-gpu-arch=all \
 // RUN:   -c %s 2>&1 \
 // RUN: | FileCheck -check-prefix ARCHALLERROR %s
 
 
 // Verify that --[no-]cuda-include-ptx arguments are handled correctly.
 // a) by default we're including PTX for all GPUs.
-// RUN: not %clang -### --target=x86_64-linux-gnu \
-// RUN:   --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
+// RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -nogpuinc \
+// RUN:   --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_52 \
 // RUN:   -c %s 2>&1 \
-// RUN: | FileCheck -check-prefixes FATBIN-COMMON,PTX-SM35,PTX-SM30 %s
+// RUN: | FileCheck -check-prefixes FATBIN-COMMON,PTX-SM60,PTX-SM52 %s
 
 // b) --no-cuda-include-ptx=all disables PTX inclusion for all GPUs
-// RUN: not %clang -### --target=x86_64-linux-gnu \
-// RUN:   --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
+// RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -nogpuinc \
+// RUN:   --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_52 \
 // RUN:   --no-cuda-include-ptx=all \
 // RUN:   -c %s 2>&1 \
-// RUN: | FileCheck -check-prefixes FATBIN-COMMON,NOPTX-SM35,NOPTX-SM30 %s
+// RUN: | FileCheck -check-prefixes FATBIN-COMMON,NOPTX-SM60,NOPTX-SM52 %s
 
 // c) --no-cuda-include-ptx=sm_XX disables PTX inclusion for that GPU only.
-// RUN: not %clang -### --target=x86_64-linux-gnu \
-// RUN:   --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
-// RUN:   --no-cuda-include-ptx=sm_35 \
+// RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -nogpuinc \
+// RUN:   --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_52 \
+// RUN:   --no-cuda-include-ptx=sm_60 \
 // RUN:   -c %s 2>&1 \
-// RUN: | FileCheck -check-prefixes FATBIN-COMMON,NOPTX-SM35,PTX-SM30 %s
-// RUN: not %clang -### --target=x86_64-linux-gnu \
-// RUN:   --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
-// RUN:   --no-cuda-include-ptx=sm_30 \
+// RUN: | FileCheck -check-prefixes FATBIN-COMMON,NOPTX-SM60,PTX-SM52 %s
+// RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -nogpuinc \
+// RUN:   --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_52 \
+// RUN:   --no-cuda-include-ptx=sm_52 \
 // RUN:   -c %s 2>&1 \
-// RUN: | FileCheck -check-prefixes FATBIN-COMMON,PTX-SM35,NOPTX-SM30 %s
+// RUN: | FileCheck -check-prefixes FATBIN-COMMON,PTX-SM60,NOPTX-SM52 %s
 
 // d) --cuda-include-ptx=all overrides preceding --no-cuda-include-ptx=all
-// RUN: not %clang -### --target=x86_64-linux-gnu \
-// RUN:   --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
+// RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -nogpuinc \
+// RUN:   --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_52 \
 // RUN:   --no-cuda-include-ptx=all --cuda-include-ptx=all \
 // RUN:   -c %s 2>&1 \
-// RUN: | FileCheck -check-prefixes FATBIN-COMMON,PTX-SM35,PTX-SM30 %s
+// RUN: | FileCheck -check-prefixes FATBIN-COMMON,PTX-SM60,PTX-SM52 %s
 
 // e) --cuda-include-ptx=all overrides preceding --no-cuda-include-ptx=sm_XX
-// RUN: not %clang -### --target=x86_64-linux-gnu \
-// RUN:   --cuda-gpu-arch=sm_35 --cuda-gpu-arch=sm_30 \
-// RUN:   --no-cuda-include-ptx=sm_30 --cuda-include-ptx=all \
+// RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -nogpuinc \
+// RUN:   --cuda-gpu-arch=sm_60 --cuda-gpu-arch=sm_52 \
+// RUN:   --no-cuda-include-ptx=sm_52 --cuda-include-ptx=all \
 // RUN:   -c %s 2>&1 \
-// RUN: | FileCheck -check-prefixes FATBIN-COMMON,PTX-SM35,PTX-SM30 %s
+// RUN: | FileCheck -check-prefixes FATBIN-COMMON,PTX-SM60,PTX-SM52 %s
 
 // Verify -flto=thin -fwhole-program-vtables handling. This should result in
 // both options being passed to the host compilation, with neither passed to
 // the device compilation.
-// RUN: not %clang -### --target=x86_64-linux-gnu -c -flto=thin -fwhole-program-vtables %s 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -nogpuinc -c -flto=thin -fwhole-program-vtables %s 2>&1 \
 // RUN: | FileCheck -check-prefixes DEVICE,DEVICE-NOSAVE,HOST,INCLUDES-DEVICE,NOLINK,THINLTOWPD %s
 // THINLTOWPD-NOT: error: invalid argument '-fwhole-program-vtables' only allowed with '-flto'
 
-// ARCH-SM30: "-cc1"{{.*}}"-target-cpu" "sm_30"
-// NOARCH-SM30-NOT: "-cc1"{{.*}}"-target-cpu" "sm_30"
-// ARCH-SM35: "-cc1"{{.*}}"-target-cpu" "sm_35"
-// NOARCH-SM35-NOT: "-cc1"{{.*}}"-target-cpu" "sm_35"
-// ARCH-SM50: "-cc1"{{.*}}"-target-cpu" "sm_50"
-// NOARCH-SM50-NOT: "-cc1"{{.*}}"-target-cpu" "sm_50"
+// ARCH-SM52: "-cc1"{{.*}}"-target-cpu" "sm_52"
+// NOARCH-SM52-NOT: "-cc1"{{.*}}"-target-cpu" "sm_52"
+// ARCH-SM60: "-cc1"{{.*}}"-target-cpu" "sm_60"
+// NOARCH-SM60-NOT: "-cc1"{{.*}}"-target-cpu" "sm_60"
+// ARCH-SM70: "-cc1"{{.*}}"-target-cpu" "sm_70"
+// NOARCH-SM70-NOT: "-cc1"{{.*}}"-target-cpu" "sm_70"
 // ARCHALLERROR: error: unsupported CUDA gpu architecture: all
 
 // Match device-side preprocessor and compiler phases with -save-temps.
@@ -213,7 +213,7 @@
 // DEVICE-NOSAVE-SAME: "-aux-triple" "x86_64-unknown-linux-gnu"
 // THINLTOWPD-NOT: "-flto=thin"
 // DEVICE-SAME: "-fcuda-is-device"
-// DEVICE-SM30-SAME: "-target-cpu" "sm_30"
+// DEVICE-SM52-SAME: "-target-cpu" "sm_52"
 // THINLTOWPD-NOT: "-fwhole-program-vtables"
 // DEVICE-SAME: "-o" "[[PTXFILE:[^"]*]]"
 // DEVICE-NOSAVE-SAME: "-x" "cuda"
@@ -221,7 +221,7 @@
 
 // Match the call to ptxas (which assembles PTX to SASS).
 // DEVICE:ptxas
-// DEVICE-SM30-DAG: "--gpu-name" "sm_30"
+// DEVICE-SM52-DAG: "--gpu-name" "sm_52"
 // DEVICE-DAG: "--output-file" "[[CUBINFILE:[^"]*]]"
 // DEVICE-DAG: "[[PTXFILE]]"
 
@@ -229,13 +229,13 @@
 // DEVICE2: "-cc1" "-triple" "nvptx64-nvidia-cuda"
 // DEVICE2-SAME: "-aux-triple" "x86_64-unknown-linux-gnu"
 // DEVICE2-SAME: "-fcuda-is-device"
-// DEVICE2-SM35-SAME: "-target-cpu" "sm_35"
+// DEVICE2-SM60-SAME: "-target-cpu" "sm_60"
 // DEVICE2-SAME: "-o" "[[PTXFILE2:[^"]*]]"
 // DEVICE2-SAME: "-x" "cuda"
 
 // Match another call to ptxas.
 // DEVICE2: ptxas
-// DEVICE2-SM35-DAG: "--gpu-name" "sm_35"
+// DEVICE2-SM60-DAG: "--gpu-name" "sm_60"
 // DEVICE2-DAG: "--output-file" "[[CUBINFILE2:[^"]*]]"
 // DEVICE2-DAG: "[[PTXFILE2]]"
 
@@ -290,9 +290,9 @@
 
 // FATBIN-COMMON:fatbinary
 // FATBIN-COMMON: "--create" "[[FATBINARY:[^"]*]]"
-// FATBIN-COMMON: "--image=profile=sm_30,file=
-// PTX-SM30: "--image=profile=compute_30,file=
-// NOPTX-SM30-NOT: "--image=profile=compute_30,file=
-// FATBIN-COMMON: "--image=profile=sm_35,file=
-// PTX-SM35: "--image=profile=compute_35,file=
-// NOPTX-SM35-NOT: "--image=profile=compute_35,file=
+// FATBIN-COMMON: "--image=profile=sm_52,file=
+// PTX-SM52: "--image=profile=compute_52,file=
+// NOPTX-SM52-NOT: "--image=profile=compute_52,file=
+// FATBIN-COMMON: "--image=profile=sm_60,file=
+// PTX-SM60: "--image=profile=compute_60,file=
+// NOPTX-SM60-NOT: "--image=profile=compute_60,file=
diff --git a/clang/test/Driver/cuda-phases.cu b/clang/test/Driver/cuda-phases.cu
index 9a231091de2bdc1acf41aaff29b7bde97edc86e2..85b1a550524d21949ff24d40da251a28290bb1e7 100644
--- a/clang/test/Driver/cuda-phases.cu
+++ b/clang/test/Driver/cuda-phases.cu
@@ -11,7 +11,7 @@
 //
 // Test CUDA NVPTX phases.
 // RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=sm_30 %s 2>&1 \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=sm_30 %s 2>&1 \
 // RUN: | FileCheck -check-prefixes=BIN %s
 //
 // BIN-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (host-[[T]])
@@ -34,7 +34,7 @@
 // Test single gpu architecture up to the assemble phase.
 //
 // RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=sm_30 %s -S 2>&1 \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=sm_30 %s -S 2>&1 \
 // RUN: | FileCheck -check-prefixes=ASM %s
 // ASM-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (device-[[T]], [[ARCH:sm_30]])
 // ASM-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH]])
@@ -50,7 +50,7 @@
 // Test two gpu architectures with complete compilation.
 //
 // RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s 2>&1 \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s 2>&1 \
 // RUN: | FileCheck -check-prefixes=BIN2 %s
 // BIN2-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (host-[[T]])
 // BIN2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
@@ -79,7 +79,7 @@
 // Test two gpu architecturess up to the assemble phase.
 //
 // RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s -S 2>&1 \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s -S 2>&1 \
 // RUN: | FileCheck -check-prefixes=ASM2 %s
 // ASM2-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (device-[[T]], [[ARCH1:sm_30]])
 // ASM2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH1]])
@@ -101,7 +101,7 @@
 // compilation mode.
 //
 // RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=sm_30 %s --cuda-host-only 2>&1 \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=sm_30 %s --cuda-host-only 2>&1 \
 // RUN: | FileCheck -check-prefixes=HBIN %s
 // HBIN-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (host-[[T]])
 // HBIN-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
@@ -115,7 +115,7 @@
 // compilation mode.
 //
 // RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=sm_30 %s --cuda-host-only -S 2>&1 \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=sm_30 %s --cuda-host-only -S 2>&1 \
 // RUN: | FileCheck -check-prefixes=HASM %s
 // HASM-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (host-[[T]])
 // HASM-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
@@ -128,7 +128,7 @@
 // compilation mode.
 //
 // RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-host-only 2>&1 \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-host-only 2>&1 \
 // RUN: | FileCheck -check-prefixes=HBIN2 %s
 // HBIN2-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (host-[[T]])
 // HBIN2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
@@ -143,7 +143,7 @@
 // compilation mode.
 //
 // RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-host-only -S \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-host-only -S \
 // RUN: 2>&1 | FileCheck -check-prefixes=HASM2 %s
 // HASM2-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (host-[[T]])
 // HASM2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
@@ -156,7 +156,7 @@
 // compilation mode.
 //
 // RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=sm_30 %s --cuda-device-only 2>&1 \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=sm_30 %s --cuda-device-only 2>&1 \
 // RUN: | FileCheck -check-prefixes=DBIN %s
 // DBIN-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (device-[[T]], [[ARCH:sm_30]])
 // DBIN-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH]])
@@ -170,7 +170,7 @@
 // compilation mode.
 //
 // RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=sm_30 %s --cuda-device-only -S 2>&1 \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=sm_30 %s --cuda-device-only -S 2>&1 \
 // RUN: | FileCheck -check-prefixes=DASM %s
 // DASM-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (device-[[T]], [[ARCH:sm_30]])
 // DASM-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH]])
@@ -184,7 +184,7 @@
 // compilation mode.
 //
 // RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-device-only 2>&1 \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-device-only 2>&1 \
 // RUN: | FileCheck -check-prefixes=DBIN2 %s
 // DBIN2-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (device-[[T]], [[ARCH:sm_30]])
 // DBIN2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH]])
@@ -204,7 +204,7 @@
 // compilation mode.
 //
 // RUN: %clang -target powerpc64le-ibm-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-device-only -S \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=sm_30 --cuda-gpu-arch=sm_35 %s --cuda-device-only -S \
 // RUN: 2>&1 | FileCheck -check-prefixes=DASM2 %s
 // DASM2-DAG: [[P0:[0-9]+]]: input, "{{.*}}cuda-phases.cu", [[T:cuda]], (device-[[T]], [[ARCH:sm_30]])
 // DASM2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH]])
@@ -244,31 +244,32 @@
 // NEW-DRIVER-RDC-NEXT: 18: assembler, {17}, object, (host-cuda)
 // NEW-DRIVER-RDC-NEXT: 19: clang-linker-wrapper, {18}, image, (host-cuda)
 
-// RUN: %clang -### -target powerpc64le-ibm-linux-gnu -ccc-print-phases --offload-new-driver -fgpu-rdc \
+// RUN: %clang -### -target powerpc64le-ibm-linux-gnu -ccc-print-phases --offload-new-driver \
 // RUN:   --offload-arch=sm_52 --offload-arch=sm_70 %s 2>&1 | FileCheck --check-prefix=NEW-DRIVER %s
-//      NEW-DRIVER: 0: input, "[[INPUT:.+]]", cuda
-// NEW-DRIVER-NEXT: 1: preprocessor, {0}, cuda-cpp-output
-// NEW-DRIVER-NEXT: 2: compiler, {1}, ir
-// NEW-DRIVER-NEXT: 3: input, "[[INPUT]]", cuda, (device-cuda, sm_52)
+//      NEW-DRIVER: 0: input, "[[CUDA:.+]]", cuda, (host-cuda)
+// NEW-DRIVER-NEXT: 1: preprocessor, {0}, cuda-cpp-output, (host-cuda)
+// NEW-DRIVER-NEXT: 2: compiler, {1}, ir, (host-cuda)
+// NEW-DRIVER-NEXT: 3: input, "[[CUDA]]", cuda, (device-cuda, sm_52)
 // NEW-DRIVER-NEXT: 4: preprocessor, {3}, cuda-cpp-output, (device-cuda, sm_52)
 // NEW-DRIVER-NEXT: 5: compiler, {4}, ir, (device-cuda, sm_52)
 // NEW-DRIVER-NEXT: 6: backend, {5}, assembler, (device-cuda, sm_52)
 // NEW-DRIVER-NEXT: 7: assembler, {6}, object, (device-cuda, sm_52)
-// NEW-DRIVER-NEXT: 8: offload, "device-cuda (nvptx64-nvidia-cuda:sm_52)" {7}, object
-// NEW-DRIVER-NEXT: 9: input, "[[INPUT]]", cuda, (device-cuda, sm_70)
+// NEW-DRIVER-NEXT: 8: offload, "device-cuda (nvptx64-nvidia-cuda:sm_52)" {7}, "device-cuda (nvptx64-nvidia-cuda:sm_52)" {6}, object
+// NEW-DRIVER-NEXT: 9: input, "[[CUDA]]", cuda, (device-cuda, sm_70)
 // NEW-DRIVER-NEXT: 10: preprocessor, {9}, cuda-cpp-output, (device-cuda, sm_70)
 // NEW-DRIVER-NEXT: 11: compiler, {10}, ir, (device-cuda, sm_70)
 // NEW-DRIVER-NEXT: 12: backend, {11}, assembler, (device-cuda, sm_70)
 // NEW-DRIVER-NEXT: 13: assembler, {12}, object, (device-cuda, sm_70)
-// NEW-DRIVER-NEXT: 14: offload, "device-cuda (nvptx64-nvidia-cuda:sm_70)" {13}, object
-// NEW-DRIVER-NEXT: 15: clang-offload-packager, {8, 14}, image
-// NEW-DRIVER-NEXT: 16: offload, "host-cuda (powerpc64le-ibm-linux-gnu)" {2}, "device-cuda (powerpc64le-ibm-linux-gnu)" {15}, ir
+// NEW-DRIVER-NEXT: 14: offload, "device-cuda (nvptx64-nvidia-cuda:sm_70)" {13}, "device-cuda (nvptx64-nvidia-cuda:sm_70)" {12}, object
+// NEW-DRIVER-NEXT: 15: linker, {8, 14}, cuda-fatbin, (device-cuda)
+// NEW-DRIVER-NEXT: 16: offload, "host-cuda (powerpc64le-ibm-linux-gnu)" {2}, "device-cuda (nvptx64-nvidia-cuda)" {15}, ir
 // NEW-DRIVER-NEXT: 17: backend, {16}, assembler, (host-cuda)
 // NEW-DRIVER-NEXT: 18: assembler, {17}, object, (host-cuda)
 // NEW-DRIVER-NEXT: 19: clang-linker-wrapper, {18}, image, (host-cuda)
 
 // RUN: %clang -### --target=powerpc64le-ibm-linux-gnu -ccc-print-phases --offload-new-driver \
 // RUN:   --offload-arch=sm_52 --offload-arch=sm_70 %s %S/Inputs/empty.cpp 2>&1 | FileCheck --check-prefix=NON-CUDA-INPUT %s
+
 //      NON-CUDA-INPUT: 0: input, "[[CUDA:.+]]", cuda, (host-cuda)
 // NON-CUDA-INPUT-NEXT: 1: preprocessor, {0}, cuda-cpp-output, (host-cuda)
 // NON-CUDA-INPUT-NEXT: 2: compiler, {1}, ir, (host-cuda)
@@ -277,13 +278,13 @@
 // NON-CUDA-INPUT-NEXT: 5: compiler, {4}, ir, (device-cuda, sm_52)
 // NON-CUDA-INPUT-NEXT: 6: backend, {5}, assembler, (device-cuda, sm_52)
 // NON-CUDA-INPUT-NEXT: 7: assembler, {6}, object, (device-cuda, sm_52)
-// NON-CUDA-INPUT-NEXT: 8: offload, "device-cuda (nvptx64-nvidia-cuda:sm_52)" {7}, object
+// NON-CUDA-INPUT-NEXT: 8: offload, "device-cuda (nvptx64-nvidia-cuda:sm_52)" {7}, "device-cuda (nvptx64-nvidia-cuda:sm_52)" {6}, object
 // NON-CUDA-INPUT-NEXT: 9: input, "[[CUDA]]", cuda, (device-cuda, sm_70)
 // NON-CUDA-INPUT-NEXT: 10: preprocessor, {9}, cuda-cpp-output, (device-cuda, sm_70)
 // NON-CUDA-INPUT-NEXT: 11: compiler, {10}, ir, (device-cuda, sm_70)
 // NON-CUDA-INPUT-NEXT: 12: backend, {11}, assembler, (device-cuda, sm_70)
 // NON-CUDA-INPUT-NEXT: 13: assembler, {12}, object, (device-cuda, sm_70)
-// NON-CUDA-INPUT-NEXT: 14: offload, "device-cuda (nvptx64-nvidia-cuda:sm_70)" {13}, object
+// NON-CUDA-INPUT-NEXT: 14: offload, "device-cuda (nvptx64-nvidia-cuda:sm_70)" {13}, "device-cuda (nvptx64-nvidia-cuda:sm_70)" {12}, object
 // NON-CUDA-INPUT-NEXT: 15: linker, {8, 14}, cuda-fatbin, (device-cuda)
 // NON-CUDA-INPUT-NEXT: 16: offload, "host-cuda (powerpc64le-ibm-linux-gnu)" {2}, "device-cuda (nvptx64-nvidia-cuda)" {15}, ir
 // NON-CUDA-INPUT-NEXT: 17: backend, {16}, assembler, (host-cuda)
diff --git a/clang/test/Driver/cuda-ptxas-path.cu b/clang/test/Driver/cuda-ptxas-path.cu
index 09c6014a91a2edd09ec5cd2ae3b93374ad49df9c..87b19d9d4d6163f0faafd09a8ef3d9b03533ab09 100644
--- a/clang/test/Driver/cuda-ptxas-path.cu
+++ b/clang/test/Driver/cuda-ptxas-path.cu
@@ -8,4 +8,4 @@
 
 // CHECK-NOT: "ptxas"
 // CHECK: "/some/path/to/ptxas"
-// CHECK-SAME: "--gpu-name" "sm_35"
+// CHECK-SAME: "--gpu-name" "sm_52"
diff --git a/clang/test/Driver/dwarf-target-version-clamp.cu b/clang/test/Driver/dwarf-target-version-clamp.cu
index ec0386afbc57eb822cab687b353f16b3c2a24947..d9dbbe62cfb2fbf46f55e1da54b61e6ace585e52 100644
--- a/clang/test/Driver/dwarf-target-version-clamp.cu
+++ b/clang/test/Driver/dwarf-target-version-clamp.cu
@@ -2,9 +2,9 @@
 // REQUIRES: nvptx-registered-target
 
 // Verify that DWARF version is properly clamped for nvptx, but not for the host.
-// RUN: not %clang -### --target=x86_64-linux-gnu -c %s -gdwarf-5 -gembed-source 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -nogpuinc -c %s -gdwarf-5 -gembed-source 2>&1 \
 // RUN: | FileCheck %s --check-prefix=DWARF-CLAMP
-// RUN: not %clang -### --target=x86_64-linux-gnu -c %s -ggdb -gembed-source -gdwarf-5 2>&1 \
+// RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -nogpuinc -c %s -ggdb -gembed-source -gdwarf-5 2>&1 \
 // RUN: | FileCheck %s --check-prefix=DWARF-CLAMP
 
 // DWARF-CLAMP: "-triple" "nvptx64-nvidia-cuda"
diff --git a/clang/test/Driver/freebsd.c b/clang/test/Driver/freebsd.c
index e1ce8889459f974efe38192dc7541365dce2be11..10fe155fee87443eaeba1a16992ea5cd8ea0bf77 100644
--- a/clang/test/Driver/freebsd.c
+++ b/clang/test/Driver/freebsd.c
@@ -203,3 +203,7 @@
 // RELOCATABLE-NOT: "-l
 // RELOCATABLE-NOT: crt{{[^./\\]+}}.o
 
+// Check that the -X and --no-relax flags are passed to the linker on riscv64
+// RUN: %clang --target=riscv64-unknown-freebsd -mno-relax -### %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=RISCV64-FLAGS %s
+// RISCV64-FLAGS: "-X" "--no-relax"
diff --git a/clang/test/Driver/fuchsia.c b/clang/test/Driver/fuchsia.c
index ca53f0d107a005ba1d57fd4384ce4e3c8090c1dc..c67f7f8c005b394c305d5bb4902a41706c434d8e 100644
--- a/clang/test/Driver/fuchsia.c
+++ b/clang/test/Driver/fuchsia.c
@@ -292,3 +292,8 @@
 // RUN:     | FileCheck %s -check-prefix=CHECK-PROFRT-X86_64
 // CHECK-PROFRT-X86_64: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
 // CHECK-PROFRT-X86_64: "[[RESOURCE_DIR]]{{/|\\\\}}lib{{/|\\\\}}x86_64-unknown-fuchsia{{/|\\\\}}libclang_rt.profile.a"
+
+// Check that the -X and --no-relax flags are passed to the linker on riscv64
+// RUN: %clang --target=riscv64-unknown-fuchsia -mno-relax -### %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=RISCV64-FLAGS %s
+// RISCV64-FLAGS: "-X" "--no-relax"
diff --git a/clang/test/Driver/haiku.c b/clang/test/Driver/haiku.c
index e907c34b29b99555f6e74706edcd53b8f054cc51..060a56b3c70e562dc516d2d592fb736009d6926f 100644
--- a/clang/test/Driver/haiku.c
+++ b/clang/test/Driver/haiku.c
@@ -76,6 +76,11 @@
 // RUN:   | FileCheck --check-prefix=CHECK-ARM-CPU %s
 // CHECK-ARM-CPU: "-target-cpu" "arm1176jzf-s"
 
+// Check that the -X and --no-relax flags are passed to the linker on riscv64
+// RUN: %clang --target=riscv64-unknown-haiku -mno-relax -### %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=RISCV64-FLAGS %s
+// RISCV64-FLAGS: "-X" "--no-relax"
+
 // Check passing LTO flags to the linker
 // RUN: %clang --target=x86_64-unknown-haiku -flto -### %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-LTO-FLAGS %s
diff --git a/clang/test/Driver/hip-binding.hip b/clang/test/Driver/hip-binding.hip
index c48397168a60f081ea14bd2c2753b9c236fd31c9..c116ad80a8ad80e53efa939e84f57f0662a62a34 100644
--- a/clang/test/Driver/hip-binding.hip
+++ b/clang/test/Driver/hip-binding.hip
@@ -3,10 +3,10 @@
 
 // RUN: %clang -ccc-print-bindings --target=x86_64-linux-gnu \
 // RUN:   --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s \
-// RUN:   -c 2>&1 | FileCheck -check-prefix=NRDCS %s
+// RUN:   --no-offload-new-driver -c 2>&1 | FileCheck -check-prefix=NRDCS %s
 // RUN: %clang -ccc-print-bindings --target=x86_64-linux-gnu --offload-new-driver \
 // RUN:   --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s \
-// RUN:   -c 2>&1 | FileCheck -check-prefix=NRDCS %s
+// RUN:   --no-offload-new-driver -c 2>&1 | FileCheck -check-prefix=NRDCS %s
 // NRDCS: # "amdgcn-amd-amdhsa" - "clang", inputs: ["[[IN:.*hip-binding.hip]]"], output: "[[OBJ1:.*o]]"
 // NRDCS: # "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[OBJ1]]"], output: "[[IMG1:.*]]"
 // NRDCS: # "amdgcn-amd-amdhsa" - "clang", inputs: ["[[IN:.*hip-binding.hip]]"], output: "[[OBJ2:.*o]]"
@@ -16,7 +16,7 @@
 
 // RUN: %clang -ccc-print-bindings --target=x86_64-linux-gnu \
 // RUN:   --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s \
-// RUN:   -c -fgpu-rdc 2>&1 | FileCheck -check-prefix=RDCS %s
+// RUN:   --no-offload-new-driver -c -fgpu-rdc 2>&1 | FileCheck -check-prefix=RDCS %s
 // RDCS: # "amdgcn-amd-amdhsa" - "clang", inputs: ["[[IN:.*hip-binding.hip]]"], output: "[[BC1:.*bc]]"
 // RDCS: # "amdgcn-amd-amdhsa" - "clang", inputs: ["[[IN:.*hip-binding.hip]]"], output: "[[BC2:.*bc]]"
 // RDCS: # "x86_64-unknown-linux-gnu" - "clang", inputs: ["[[IN]]"], output: "[[HOSTOBJ:.*o]]"
@@ -32,7 +32,7 @@
 
 // RUN: touch %t.o
 // RUN: %clang --hip-link -ccc-print-bindings --target=x86_64-linux-gnu \
-// RUN:   --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 -fgpu-rdc %t.o\
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 -fgpu-rdc %t.o\
 // RUN: 2>&1 | FileCheck %s
 
 // CHECK: # "x86_64-unknown-linux-gnu" - "offload bundler", inputs: ["[[IN:.*o]]"], outputs: ["[[HOSTOBJ:.*o]]", "{{.*o}}", "{{.*o}}"]
@@ -46,7 +46,7 @@
 // CHECK: # "x86_64-unknown-linux-gnu" - "GNU::Linker", inputs: ["[[HOSTOBJ]]", "[[FATBINOBJ]]"], output: "a.out"
 
 // RUN: %clang --hip-link -ccc-print-bindings --target=x86_64-linux-gnu \
-// RUN:   --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t.o\
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t.o\
 // RUN: 2>&1 | FileCheck -check-prefix=NORDC %s
 
 // NORDC-NOT: offload bundler
@@ -65,9 +65,18 @@
 // MULTI-D-ONLY-NEXT: # "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[GFX90a]]"], output: "[[GFX90a_OUT:.+]]"
 //
 // RUN: not %clang -### --target=x86_64-linux-gnu --offload-new-driver -ccc-print-bindings -nogpulib -nogpuinc \
-// RUN:        --offload-arch=gfx90a --offload-arch=gfx908 --offload-device-only -c -o %t %s 2>&1 \
+// RUN:        --no-gpu-bundle-output --offload-arch=gfx90a --offload-arch=gfx908 --offload-device-only -c -o %t %s 2>&1 \
+// RUN: | FileCheck -check-prefix=MULTI-D-ONLY-NO-BUNDLE-O %s
+// MULTI-D-ONLY-NO-BUNDLE-O: error: cannot specify -o when generating multiple output files
+
+// RUN: %clang -### --target=x86_64-linux-gnu --offload-new-driver -ccc-print-bindings -nogpulib -nogpuinc \
+// RUN:        --gpu-bundle-output --offload-arch=gfx90a --offload-arch=gfx908 --offload-device-only -c -o a.out %s 2>&1 \
 // RUN: | FileCheck -check-prefix=MULTI-D-ONLY-O %s
-// MULTI-D-ONLY-O: error: cannot specify -o when generating multiple output files
+//      MULTI-D-ONLY-O: "amdgcn-amd-amdhsa" - "clang", inputs: ["[[INPUT:.+]]"], output: "[[GFX908_OBJ:.+]]"
+// MULTI-D-ONLY-O-NEXT: "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[GFX908_OBJ]]"], output: "[[GFX908:.+]]"
+// MULTI-D-ONLY-O-NEXT: "amdgcn-amd-amdhsa" - "clang", inputs: ["[[INPUT]]"], output: "[[GFX90A_OBJ:.+]]"
+// MULTI-D-ONLY-O-NEXT: "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[GFX90A_OBJ]]"], output: "[[GFX90A:.+]]"
+// MULTI-D-ONLY-O-NEXT: "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[GFX908]]", "[[GFX90A]]"], output: "a.out"
 
 //
 // Check to ensure that we can use '-fsyntax-only' for HIP output with the new
diff --git a/clang/test/Driver/hip-cuid-hash.hip b/clang/test/Driver/hip-cuid-hash.hip
index 1b4d26c471c15d7f634d53a3e6d1ef14f28165bd..ef2a32a69c8f4366a5f0a1896e0de4fd7e123c12 100644
--- a/clang/test/Driver/hip-cuid-hash.hip
+++ b/clang/test/Driver/hip-cuid-hash.hip
@@ -4,11 +4,11 @@
 // Check CUID generated by hash.
 // The same CUID is generated for the same file with the same options.
 
-// RUN: %clang -### -x hip --target=x86_64-unknown-linux-gnu \
+// RUN: %clang -### -x hip --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN:   --offload-arch=gfx906 -c -nogpuinc -nogpulib -fuse-cuid=hash \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu >%t.out 2>&1
 
-// RUN: %clang -### -x hip --target=x86_64-unknown-linux-gnu \
+// RUN: %clang -### -x hip --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN:   --offload-arch=gfx906 -c -nogpuinc -nogpulib -fuse-cuid=hash \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu >>%t.out 2>&1
 
@@ -17,11 +17,11 @@
 // Check CUID generated by hash.
 // Different CUID's are generated for the same file with different options.
 
-// RUN: %clang -### -x hip --target=x86_64-unknown-linux-gnu -DX=1 \
+// RUN: %clang -### -x hip --target=x86_64-unknown-linux-gnu -DX=1 --no-offload-new-driver \
 // RUN:   --offload-arch=gfx906 -c -nogpuinc -nogpulib -fuse-cuid=hash \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu >%t.out 2>&1
 
-// RUN: %clang -### -x hip --target=x86_64-unknown-linux-gnu -DX=2 \
+// RUN: %clang -### -x hip --target=x86_64-unknown-linux-gnu -DX=2 --no-offload-new-driver \
 // RUN:   --offload-arch=gfx906 -c -nogpuinc -nogpulib -fuse-cuid=hash \
 // RUN:   %S/Inputs/../Inputs/hip_multiple_inputs/a.cu >>%t.out 2>&1
 
diff --git a/clang/test/Driver/hip-cuid.hip b/clang/test/Driver/hip-cuid.hip
index 421810b824fd619f28686a092c2bbe89f63ff794..ce3d2de3501e25c0c8bffcdcd4d2c51f60c18b2f 100644
--- a/clang/test/Driver/hip-cuid.hip
+++ b/clang/test/Driver/hip-cuid.hip
@@ -5,6 +5,7 @@
 
 // RUN: not %clang -### -x hip \
 // RUN:   --target=x86_64-unknown-linux-gnu \
+// RUN:   --no-offload-new-driver \
 // RUN:   --offload-arch=gfx900 \
 // RUN:   --offload-arch=gfx906 \
 // RUN:   -c -nogpuinc -nogpulib -fuse-cuid=invalid \
@@ -16,6 +17,7 @@
 
 // RUN: %clang -### -x hip \
 // RUN:   --target=x86_64-unknown-linux-gnu \
+// RUN:   --no-offload-new-driver \
 // RUN:   --offload-arch=gfx900 \
 // RUN:   --offload-arch=gfx906 \
 // RUN:   -c -nogpuinc -nogpulib -fuse-cuid=random \
@@ -27,6 +29,7 @@
 
 // RUN: %clang -### -x hip \
 // RUN:   --target=x86_64-unknown-linux-gnu \
+// RUN:   --no-offload-new-driver \
 // RUN:   --offload-arch=gfx900 \
 // RUN:   --offload-arch=gfx906 \
 // RUN:   -c -nogpuinc -nogpulib -cuid=xyz_123 \
@@ -38,6 +41,7 @@
 
 // RUN: %clang -### -x hip \
 // RUN:   --target=x86_64-unknown-linux-gnu \
+// RUN:   --no-offload-new-driver \
 // RUN:   --offload-arch=gfx900 \
 // RUN:   --offload-arch=gfx906 \
 // RUN:   -c -nogpuinc -nogpulib -fuse-cuid=random -cuid=xyz_123 \
@@ -49,6 +53,7 @@
 
 // RUN: %clang -### -x hip \
 // RUN:   --target=x86_64-unknown-linux-gnu \
+// RUN:   --no-offload-new-driver \
 // RUN:   --offload-arch=gfx900 \
 // RUN:   --offload-arch=gfx906 \
 // RUN:   -c -nogpuinc -nogpulib -fuse-cuid=hash \
diff --git a/clang/test/Driver/hip-dependent-options.hip b/clang/test/Driver/hip-dependent-options.hip
index 405b092d0f834ee2fd022048d523dee764b73056..b0dc7f289e8133076c090bd0a8b2e1a416289c04 100644
--- a/clang/test/Driver/hip-dependent-options.hip
+++ b/clang/test/Driver/hip-dependent-options.hip
@@ -1,4 +1,4 @@
-// RUN: not %clang -### --target=x86_64-linux-gnu \
+// RUN: not %clang -### --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN:   -c -fhip-emit-relocatable -nogpuinc -nogpulib --cuda-device-only -fgpu-rdc \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
@@ -7,7 +7,7 @@
 
 // RELOCRDC: error: option '-fhip-emit-relocatable' cannot be specified with '-fgpu-rdc'
 
-// RUN: not %clang -### --target=x86_64-linux-gnu \
+// RUN: not %clang -### --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN:   -c -fhip-emit-relocatable -nogpuinc -nogpulib \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
diff --git a/clang/test/Driver/hip-device-compile.hip b/clang/test/Driver/hip-device-compile.hip
index 3c3e3878562474851d3b33eea3940861e15d7156..74be9c6cf2ee6d764c71e53d78fc98e2bf673453 100644
--- a/clang/test/Driver/hip-device-compile.hip
+++ b/clang/test/Driver/hip-device-compile.hip
@@ -8,7 +8,7 @@
 // Output unbundled bitcode.
 // RUN: %clang -c -emit-llvm --cuda-device-only -### --target=x86_64-linux-gnu \
 // RUN:   --rocm-path=%S/Inputs/rocm -o a.bc -x hip --cuda-gpu-arch=gfx900 --no-gpu-bundle-output \
-// RUN:   --hip-device-lib=lib1.bc \
+// RUN:   --no-offload-new-driver --hip-device-lib=lib1.bc \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
 // RUN: 2>&1 | FileCheck -check-prefixes=CHECK,BC,NBUN %s
@@ -16,7 +16,7 @@
 // Output bundled bitcode.
 // RUN: %clang -c -emit-llvm --cuda-device-only -### --target=x86_64-linux-gnu \
 // RUN:   --rocm-path=%S/Inputs/rocm -o a.bc -x hip --cuda-gpu-arch=gfx900 --no-gpu-bundle-output \
-// RUN:   --hip-device-lib=lib1.bc \
+// RUN:   --no-offload-new-driver --hip-device-lib=lib1.bc \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu --gpu-bundle-output \
 // RUN: 2>&1 | FileCheck -check-prefixes=CHECK,BCBUN %s
@@ -24,7 +24,7 @@
 // Output unbundled LLVM IR.
 // RUN: %clang -c -S -emit-llvm --cuda-device-only -### --target=x86_64-linux-gnu \
 // RUN:   --rocm-path=%S/Inputs/rocm -o a.ll -x hip --cuda-gpu-arch=gfx900 --no-gpu-bundle-output \
-// RUN:   --hip-device-lib=lib1.bc \
+// RUN:   --no-offload-new-driver --hip-device-lib=lib1.bc \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
 // RUN: 2>&1 | FileCheck -check-prefixes=CHECK,LL,NBUN %s
@@ -32,7 +32,7 @@
 // Output bundled LLVM IR.
 // RUN: %clang -c -S -emit-llvm --cuda-device-only -### --target=x86_64-linux-gnu \
 // RUN:   --rocm-path=%S/Inputs/rocm -o a.ll -x hip --cuda-gpu-arch=gfx900 --no-gpu-bundle-output \
-// RUN:   --hip-device-lib=lib1.bc \
+// RUN:   --no-offload-new-driver --hip-device-lib=lib1.bc \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu --gpu-bundle-output \
 // RUN: 2>&1 | FileCheck -check-prefixes=CHECK,LLBUN %s
@@ -40,7 +40,7 @@
 // Output unbundled assembly.
 // RUN: %clang -c -S --cuda-device-only -### --target=x86_64-linux-gnu \
 // RUN:   --rocm-path=%S/Inputs/rocm -o a.s -x hip --cuda-gpu-arch=gfx900 --no-gpu-bundle-output \
-// RUN:   --hip-device-lib=lib1.bc \
+// RUN:   --no-offload-new-driver --hip-device-lib=lib1.bc \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
 // RUN: 2>&1 | FileCheck -check-prefixes=CHECK,ASM,NBUN %s
@@ -48,7 +48,7 @@
 // Output relocatable.
 // RUN: %clang -c --cuda-device-only -### --target=x86_64-linux-gnu \
 // RUN:   --rocm-path=%S/Inputs/rocm -o a.o -x hip --cuda-gpu-arch=gfx900 -fhip-emit-relocatable \
-// RUN:   --hip-device-lib=lib1.bc \
+// RUN:   --no-offload-new-driver --hip-device-lib=lib1.bc \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
 // RUN: 2>&1 | FileCheck -check-prefixes=CHECK,NBUN,RELOC %s
@@ -56,7 +56,7 @@
 // Output bundled assembly.
 // RUN: %clang -c -S --cuda-device-only -### --target=x86_64-linux-gnu \
 // RUN:   --rocm-path=%S/Inputs/rocm -o a.s -x hip --cuda-gpu-arch=gfx900 --no-gpu-bundle-output \
-// RUN:   --hip-device-lib=lib1.bc \
+// RUN:   --no-offload-new-driver --hip-device-lib=lib1.bc \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu --gpu-bundle-output \
 // RUN: 2>&1 | FileCheck -check-prefixes=CHECK,ASMBUN %s
@@ -96,7 +96,7 @@
 // Output bundled code objects.
 // RUN: %clang -c --cuda-device-only -### --target=x86_64-linux-gnu \
 // RUN:   --rocm-path=%S/Inputs/rocm -o a.o -x hip --cuda-gpu-arch=gfx900 \
-// RUN:   --hip-device-lib=lib1.bc \
+// RUN:   --no-offload-new-driver --hip-device-lib=lib1.bc \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
 // RUN: 2>&1 | FileCheck -check-prefixes=OBJ,OBJ-BUN %s
@@ -104,7 +104,7 @@
 // Output unbundled code objects.
 // RUN: %clang -c --cuda-device-only -### --target=x86_64-linux-gnu \
 // RUN:   --rocm-path=%S/Inputs/rocm -o a.o -x hip --cuda-gpu-arch=gfx900 \
-// RUN:   --hip-device-lib=lib1.bc \
+// RUN:   --no-offload-new-driver --hip-device-lib=lib1.bc \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu --no-gpu-bundle-output \
 // RUN: 2>&1 | FileCheck -check-prefixes=OBJ,OBJ-UBUN %s
@@ -112,7 +112,7 @@
 // Output bundled code objects.
 // RUN: %clang --cuda-device-only -### --target=x86_64-linux-gnu \
 // RUN:   --rocm-path=%S/Inputs/rocm -o a.o -x hip --cuda-gpu-arch=gfx900 \
-// RUN:   --hip-device-lib=lib1.bc \
+// RUN:   --no-offload-new-driver --hip-device-lib=lib1.bc \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
 // RUN: 2>&1 | FileCheck -check-prefixes=OBJ,OBJ-BUN %s
@@ -120,7 +120,7 @@
 // Output unbundled code objects.
 // RUN: %clang --cuda-device-only -### --target=x86_64-linux-gnu \
 // RUN:   --rocm-path=%S/Inputs/rocm -o a.o -x hip --cuda-gpu-arch=gfx900 \
-// RUN:   --hip-device-lib=lib1.bc \
+// RUN:   --no-offload-new-driver --hip-device-lib=lib1.bc \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu --no-gpu-bundle-output \
 // RUN: 2>&1 | FileCheck -check-prefixes=OBJ,OBJ-UBUN %s
diff --git a/clang/test/Driver/hip-link-bc-to-bc.hip b/clang/test/Driver/hip-link-bc-to-bc.hip
index 52eab97bcebb0ee4705e631326320de81dbae160..7b232f2656a93d7b8e0080a9bd29f04331607f5d 100644
--- a/clang/test/Driver/hip-link-bc-to-bc.hip
+++ b/clang/test/Driver/hip-link-bc-to-bc.hip
@@ -7,7 +7,7 @@
 
 // RUN: %clang -### --target=x86_64-unknown-linux-gnu --offload-arch=gfx906 --hip-link \
 // RUN:   -nogpulib -nogpuinc -emit-llvm -fgpu-rdc --cuda-device-only \
-// RUN:   %t/bundle1.bc %t/bundle2.bc \
+// RUN:   --no-offload-new-driver %t/bundle1.bc %t/bundle2.bc \
 // RUN:   2>&1 | FileCheck -check-prefix=BITCODE %s
 
 // BITCODE: "{{.*}}clang-offload-bundler" "-type=bc" "-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa-gfx906" "-input={{.*}}bundle1.bc" "-output=[[B1HOST:.*\.bc]]" "-output=[[B1DEV1:.*\.bc]]" "-unbundle" "-allow-missing-bundles"
@@ -24,7 +24,7 @@
 
 // RUN: %clang -### --target=x86_64-unknown-linux-gnu --offload-arch=gfx906 --hip-link \
 // RUN:   -nogpulib -nogpuinc -emit-llvm -fgpu-rdc --cuda-device-only \
-// RUN:   %t/bundle.bc -L%t -lhipbundle \
+// RUN:   --no-offload-new-driver %t/bundle.bc -L%t -lhipbundle \
 // RUN:   2>&1 | FileCheck -check-prefix=ARCHIVE %s
 
 // ARCHIVE: "{{.*}}clang-offload-bundler" "-type=bc" "-targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa-gfx906" "-input={{.*}}bundle.bc" "-output=[[HOST:.*\.bc]]" "-output=[[DEV1:.*\.bc]]" "-unbundle" "-allow-missing-bundles"
diff --git a/clang/test/Driver/hip-link-bundle-archive.hip b/clang/test/Driver/hip-link-bundle-archive.hip
index dd1d779fe19a87683cd269aef02d90532f21af04..cfbf7137226060860fc47448d4f9533547c2c0f4 100644
--- a/clang/test/Driver/hip-link-bundle-archive.hip
+++ b/clang/test/Driver/hip-link-bundle-archive.hip
@@ -9,23 +9,23 @@
 // RUN: touch %t/dummy.bc
 // RUN: llvm-ar cr %t/libhipBundled.a %t/dummy.bc
 // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \
-// RUN:   --target=x86_64-unknown-linux-gnu \
+// RUN:   --no-offload-new-driver --target=x86_64-unknown-linux-gnu \
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc -L%t -lhipBundled \
 // RUN:   2>&1 | FileCheck -check-prefixes=GNU,GNU1,GNU-L %s
 
 // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 -nogpuinc \
-// RUN:   --target=x86_64-unknown-linux-gnu \
+// RUN:   --no-offload-new-driver --target=x86_64-unknown-linux-gnu \
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc -L%t -l:libhipBundled.a \
 // RUN:   2>&1 | FileCheck -check-prefixes=GNU,GNU1,GNU-LA %s
 
 // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \
-// RUN:   --target=x86_64-unknown-linux-gnu \
+// RUN:   --no-offload-new-driver --target=x86_64-unknown-linux-gnu \
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc %t/libhipBundled.a \
 // RUN:   2>&1 | FileCheck -check-prefixes=GNU,GNU1,GNU-A %s
 
 // RUN: llvm-ar cr %t/libhipBundled.a.5.2 %t/dummy.bc
 // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \
-// RUN:   --target=x86_64-unknown-linux-gnu \
+// RUN:   --no-offload-new-driver --target=x86_64-unknown-linux-gnu \
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc %t/libhipBundled.a.5.2 \
 // RUN:   2>&1 | FileCheck -check-prefixes=GNU,GNU2,GNU-A %s
 
@@ -33,22 +33,22 @@
 
 // RUN: touch %t/libNonArchive.a
 // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \
-// RUN:   --target=x86_64-unknown-linux-gnu \
+// RUN:   --no-offload-new-driver --target=x86_64-unknown-linux-gnu \
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc -L%t -lNonArchive \
 // RUN:   2>&1 | FileCheck -check-prefixes=NONARCHIVE %s
 // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \
-// RUN:   --target=x86_64-unknown-linux-gnu \
+// RUN:   --no-offload-new-driver --target=x86_64-unknown-linux-gnu \
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc -L%t -l:libNonArchive.a \
 // RUN:   2>&1 | FileCheck -check-prefixes=NONARCHIVE %s
 // RUN: not %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \
-// RUN:   --target=x86_64-unknown-linux-gnu \
+// RUN:   --no-offload-new-driver --target=x86_64-unknown-linux-gnu \
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc -L%t libNonArchive.a \
 // RUN:   2>&1 | FileCheck -check-prefixes=NONARCHIVE %s
 
 // Check if a file does not exist, it is not unbundled.
 
 // RUN: not %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \
-// RUN:   --target=x86_64-unknown-linux-gnu \
+// RUN:   --no-offload-new-driver --target=x86_64-unknown-linux-gnu \
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc %t/NoneExist.a \
 // RUN:   2>&1 | FileCheck -check-prefixes=NONE %s
 
@@ -56,17 +56,17 @@
 
 // RUN: llvm-ar cr %t/hipBundled2.lib %t/dummy.bc
 // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \
-// RUN:   --target=x86_64-pc-windows-msvc -fuse-ld= \
+// RUN:   --no-offload-new-driver --target=x86_64-pc-windows-msvc -fuse-ld= \
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc -L%t -lhipBundled2 \
 // RUN:   2>&1 | FileCheck -check-prefix=MSVC %s
 
 // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \
-// RUN:   --target=x86_64-pc-windows-msvc -fuse-ld= \
+// RUN:   --no-offload-new-driver --target=x86_64-pc-windows-msvc -fuse-ld= \
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc -L%t -l:hipBundled2.lib \
 // RUN:   2>&1 | FileCheck -check-prefix=MSVC %s
 
 // RUN: %clang -### --offload-arch=gfx906 --offload-arch=gfx1030 \
-// RUN:   --target=x86_64-pc-windows-msvc -fuse-ld= \
+// RUN:   --no-offload-new-driver --target=x86_64-pc-windows-msvc -fuse-ld= \
 // RUN:   -nogpuinc -nogpulib %s -fgpu-rdc %t/hipBundled2.lib \
 // RUN:   2>&1 | FileCheck -check-prefix=MSVC %s
 
diff --git a/clang/test/Driver/hip-link-save-temps.hip b/clang/test/Driver/hip-link-save-temps.hip
index b8a5dcefb8cf0c373fced450e49dc973738302b5..e54be63c578b872e46ba0577fea7b9b9760ffeb5 100644
--- a/clang/test/Driver/hip-link-save-temps.hip
+++ b/clang/test/Driver/hip-link-save-temps.hip
@@ -7,14 +7,14 @@
 // RUN: touch %t/obj2.o
 // RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -save-temps \
 // RUN:   --hip-link -o executable -fgpu-rdc --cuda-gpu-arch=gfx900 \
-// RUN:   --offload-arch=gfx906  %t/obj1.o %t/obj2.o 2>&1 | \
+// RUN:   --no-offload-new-driver --offload-arch=gfx906  %t/obj1.o %t/obj2.o 2>&1 | \
 // RUN:   FileCheck -check-prefixes=CHECK,OUT %s
 
 // -fgpu-rdc link without output
 // RUN: touch %t/obj1.o
 // RUN: touch %t/obj2.o
 // RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -save-temps \
-// RUN:   --hip-link -fgpu-rdc --cuda-gpu-arch=gfx900 \
+// RUN:   --no-offload-new-driver --hip-link -fgpu-rdc --cuda-gpu-arch=gfx900 \
 // RUN:   --offload-arch=gfx906  %t/obj1.o %t/obj2.o 2>&1 | \
 // RUN:   FileCheck -check-prefixes=CHECK,NOUT %s
 
@@ -23,7 +23,7 @@
 // RUN: touch %t/obj2.o
 // RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -save-temps \
 // RUN:   --hip-link -o libTest.a -fgpu-rdc --cuda-gpu-arch=gfx900 \
-// RUN:   --emit-static-lib \
+// RUN:   --no-offload-new-driver --emit-static-lib \
 // RUN:   --offload-arch=gfx906  %t/obj1.o %t/obj2.o 2>&1 | \
 // RUN:   FileCheck -check-prefixes=CHECK,SLO %s
 
@@ -32,7 +32,7 @@
 // RUN: touch %t/obj2.o
 // RUN: %clang -### --target=x86_64-linux-gnu -nogpulib -save-temps \
 // RUN:   --hip-link -fgpu-rdc --cuda-gpu-arch=gfx900 \
-// RUN:   --emit-static-lib \
+// RUN:   --no-offload-new-driver --emit-static-lib \
 // RUN:   --offload-arch=gfx906  %t/obj1.o %t/obj2.o 2>&1 | \
 // RUN:   FileCheck -check-prefixes=CHECK,SLNO %s
 
diff --git a/clang/test/Driver/hip-link-shared-library.hip b/clang/test/Driver/hip-link-shared-library.hip
index fc1f9f53b9549a07a5dd5fa3376515c298386081..73643682dda8ae57ad86831f94ba56baff975f49 100644
--- a/clang/test/Driver/hip-link-shared-library.hip
+++ b/clang/test/Driver/hip-link-shared-library.hip
@@ -1,7 +1,7 @@
 // RUN: touch %t.o
 // RUN: %clang --hip-link -ccc-print-bindings --target=x86_64-linux-gnu \
 // RUN:   --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t.o %S/Inputs/in.so \
-// RUN:   -fgpu-rdc 2>&1 | FileCheck %s
+// RUN:   --no-offload-new-driver -fgpu-rdc 2>&1 | FileCheck %s
 
 // CHECK: # "x86_64-unknown-linux-gnu" - "offload bundler", inputs: ["[[IN:.*o]]"], outputs: ["[[HOSTOBJ:.*o]]", "{{.*o}}", "{{.*o}}"]
 // CHECK: # "amdgcn-amd-amdhsa" - "offload bundler", inputs: ["[[IN]]"], outputs: ["{{.*o}}", "[[DOBJ1:.*o]]", "[[DOBJ2:.*o]]"]
@@ -12,4 +12,3 @@
 // CHECK: # "amdgcn-amd-amdhsa" - "AMDGCN::Linker", inputs: ["[[IMG1]]", "[[IMG2]]"], output: "[[FATBINOBJ:.*o]]"
 // CHECK-NOT: offload bundler
 // CHECK: # "x86_64-unknown-linux-gnu" - "GNU::Linker", inputs: ["[[HOSTOBJ]]", "{{.*}}/Inputs/in.so", "[[FATBINOBJ]]"], output: "a.out"
-
diff --git a/clang/test/Driver/hip-link-static-library.hip b/clang/test/Driver/hip-link-static-library.hip
index 63675ffd62621c362638f3733274f450a8d5f044..3159b5f3984feeb2133f2a642abcb65ea953c126 100644
--- a/clang/test/Driver/hip-link-static-library.hip
+++ b/clang/test/Driver/hip-link-static-library.hip
@@ -3,7 +3,7 @@
 
 // RUN: touch %t.o
 // RUN: %clang --hip-link -ccc-print-bindings --target=x86_64-linux-gnu \
-// RUN:   --emit-static-lib \
+// RUN:   --no-offload-new-driver --emit-static-lib \
 // RUN:   --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 -fgpu-rdc %t.o\
 // RUN: 2>&1 | FileCheck %s
 
@@ -18,7 +18,7 @@
 // CHECK: # "x86_64-unknown-linux-gnu" - "GNU::StaticLibTool", inputs: ["[[HOSTOBJ]]", "[[FATBINOBJ]]"], output: "a.out"
 
 // RUN: %clang --hip-link -ccc-print-bindings --target=x86_64-linux-gnu \
-// RUN:   --emit-static-lib \
+// RUN:   --no-offload-new-driver --emit-static-lib \
 // RUN:   --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t.o\
 // RUN: 2>&1 | FileCheck -check-prefix=NORDC %s
 
@@ -26,7 +26,7 @@
 // NORDC: # "x86_64-unknown-linux-gnu" - "GNU::StaticLibTool", inputs: ["{{.*o}}"], output: "a.out"
 
 // RUN: %clang --hip-link -### --target=x86_64-linux-gnu \
-// RUN:   --emit-static-lib -lgcc \
+// RUN:   --no-offload-new-driver --emit-static-lib -lgcc \
 // RUN:   -Wl,--enable-new-dtags -Wl,--rpath=/opt \
 // RUN:   --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 -fgpu-rdc %t.o\
 // RUN: 2>&1 | FileCheck -check-prefix=NOFLAG %s
diff --git a/clang/test/Driver/hip-offload-compress-zlib.hip b/clang/test/Driver/hip-offload-compress-zlib.hip
index 7557fdde8786c7bfda882718e98ee7e0b9db3718..c1566c5f192c2d5593e257917667b38ad40f3a4c 100644
--- a/clang/test/Driver/hip-offload-compress-zlib.hip
+++ b/clang/test/Driver/hip-offload-compress-zlib.hip
@@ -1,4 +1,4 @@
-// REQUIRES: zlib
+// REQUIRES: zlib && !zstd
 // REQUIRES: x86-registered-target
 // REQUIRES: amdgpu-registered-target
 
@@ -7,22 +7,23 @@
 // RUN: rm -rf %t.bc
 // RUN: %clang -c -v --target=x86_64-linux-gnu \
 // RUN:   -x hip --offload-arch=gfx1100 --offload-arch=gfx1101 \
-// RUN:   -fgpu-rdc -nogpuinc -nogpulib \
+// RUN:   --no-offload-new-driver -fgpu-rdc -nogpuinc -nogpulib \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
-// RUN:   --offload-compress --offload-device-only --gpu-bundle-output \
+// RUN:   --offload-compress --offload-compression-level=9 \
+// RUN:   --offload-device-only --gpu-bundle-output \
 // RUN:   -o %t.bc \
 // RUN: 2>&1 | FileCheck %s
 
 // CHECK: clang-offload-bundler{{.*}} -type=bc
 // CHECK-SAME: -targets={{.*}}hip-amdgcn-amd-amdhsa-gfx1100,hip-amdgcn-amd-amdhsa-gfx1101
-// CHECK-SAME: -compress -verbose
+// CHECK-SAME: -compress -verbose -compression-level=9
 // CHECK: Compressed bundle format
 
 // Test uncompress of bundled bitcode.
 
 // RUN: %clang --hip-link -### -v --target=x86_64-linux-gnu \
 // RUN:   --offload-arch=gfx1100 --offload-arch=gfx1101 \
-// RUN:   -fgpu-rdc -nogpulib \
+// RUN:   --no-offload-new-driver -fgpu-rdc -nogpulib \
 // RUN:   %t.bc --offload-device-only \
 // RUN: 2>&1 | FileCheck -check-prefix=UNBUNDLE %s
 
@@ -35,7 +36,7 @@
 
 // RUN: %clang -c -### -v --target=x86_64-linux-gnu \
 // RUN:   -x hip --offload-arch=gfx1100 --offload-arch=gfx1101 \
-// RUN:   -nogpuinc -nogpulib \
+// RUN:   --no-offload-new-driver -nogpuinc -nogpulib \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
 // RUN:   --offload-compress \
 // RUN: 2>&1 | FileCheck -check-prefix=CO %s
diff --git a/clang/test/Driver/hip-offload-compress-zstd.hip b/clang/test/Driver/hip-offload-compress-zstd.hip
index 3680ae47974a601f4fc2c017d46a331828a19e63..ede7d59f113c863dc2ecaee922d47fdade1179b7 100644
--- a/clang/test/Driver/hip-offload-compress-zstd.hip
+++ b/clang/test/Driver/hip-offload-compress-zstd.hip
@@ -7,22 +7,23 @@
 // RUN: rm -rf %t.bc
 // RUN: %clang -c -v --target=x86_64-linux-gnu \
 // RUN:   -x hip --offload-arch=gfx1100 --offload-arch=gfx1101 \
-// RUN:   -fgpu-rdc -nogpuinc -nogpulib \
+// RUN:   --no-offload-new-driver -fgpu-rdc -nogpuinc -nogpulib \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
-// RUN:   --offload-compress --offload-device-only --gpu-bundle-output \
+// RUN:   --offload-compress --offload-compression-level=9 \
+// RUN:   --offload-device-only --gpu-bundle-output \
 // RUN:   -o %t.bc \
 // RUN: 2>&1 | FileCheck %s
 
 // CHECK: clang-offload-bundler{{.*}} -type=bc
 // CHECK-SAME: -targets={{.*}}hip-amdgcn-amd-amdhsa-gfx1100,hip-amdgcn-amd-amdhsa-gfx1101
-// CHECK-SAME: -compress -verbose
+// CHECK-SAME: -compress -verbose -compression-level=9
 // CHECK: Compressed bundle format
 
 // Test uncompress of bundled bitcode.
 
 // RUN: %clang --hip-link -### -v --target=x86_64-linux-gnu \
 // RUN:   --offload-arch=gfx1100 --offload-arch=gfx1101 \
-// RUN:   -fgpu-rdc -nogpulib \
+// RUN:   --no-offload-new-driver -fgpu-rdc -nogpulib \
 // RUN:   %t.bc --offload-device-only \
 // RUN: 2>&1 | FileCheck -check-prefix=UNBUNDLE %s
 
@@ -35,7 +36,7 @@
 
 // RUN: %clang -c -### -v --target=x86_64-linux-gnu \
 // RUN:   -x hip --offload-arch=gfx1100 --offload-arch=gfx1101 \
-// RUN:   -nogpuinc -nogpulib \
+// RUN:   --no-offload-new-driver -nogpuinc -nogpulib \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
 // RUN:   --offload-compress \
 // RUN: 2>&1 | FileCheck -check-prefix=CO %s
diff --git a/clang/test/Driver/hip-output-file-name.hip b/clang/test/Driver/hip-output-file-name.hip
index 746678b81e251e7a449e2522c08748caae10a03e..aca64346e0c47592b3f32e60e1a0fd2cdce81c13 100644
--- a/clang/test/Driver/hip-output-file-name.hip
+++ b/clang/test/Driver/hip-output-file-name.hip
@@ -2,7 +2,7 @@
 // REQUIRES: amdgpu-registered-target
 
 // Output bundled code objects for combined compilation.
-// RUN: %clang -### -c --target=x86_64-linux-gnu -fgpu-rdc \
+// RUN: %clang -### -c --target=x86_64-linux-gnu -fgpu-rdc --no-offload-new-driver \
 // RUN:   -nogpulib -nogpuinc --offload-arch=gfx803 --offload-arch=gfx900 %s \
 // RUN: 2>&1 | FileCheck %s
 
@@ -13,42 +13,42 @@
 // is used to bundle the final output.
 
 // Output bundled PPE for one GPU for mixed compliation.
-// RUN: %clang -### -E --target=x86_64-linux-gnu \
+// RUN: %clang -### -E --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -nogpulib -nogpuinc --offload-arch=gfx803 %s \
 // RUN: 2>&1 | FileCheck -check-prefixes=DASH %s
 
 // Output unbundled PPE for one GPU for device only compilation.
 // RUN: %clang -### -E --offload-device-only --target=x86_64-linux-gnu \
-// RUN:   -nogpulib -nogpuinc --offload-arch=gfx803 %s \
+// RUN:   --no-offload-new-driver -nogpulib -nogpuinc --offload-arch=gfx803 %s \
 // RUN: 2>&1 | FileCheck -check-prefixes=CLANG-DASH %s
 
 // Output bundled PPE for two GPUs for mixed compilation.
-// RUN: %clang -### -E --target=x86_64-linux-gnu \
+// RUN: %clang -### -E --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -nogpulib -nogpuinc --offload-arch=gfx803 --offload-arch=gfx900 %s \
 // RUN: 2>&1 | FileCheck -check-prefixes=DASH %s
 
 // Output bundled PPE for two GPUs for mixed compilation with -save-temps.
-// RUN: %clang -### -E -save-temps --target=x86_64-linux-gnu \
+// RUN: %clang -### -E -save-temps --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -nogpulib -nogpuinc --offload-arch=gfx803 --offload-arch=gfx900 %s \
 // RUN: 2>&1 | FileCheck -check-prefixes=DASH %s
 
 // Output unbundled PPE for two GPUs for device only compilation.
-// RUN: %clang -### -E --offload-device-only --target=x86_64-linux-gnu \
+// RUN: %clang -### -E --offload-device-only --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -nogpulib -nogpuinc --offload-arch=gfx803 --offload-arch=gfx900 %s \
 // RUN: 2>&1 | FileCheck -check-prefixes=CLANG-DASH %s
 
 // Output bundled PPE for two GPUs for device only compilation with --gpu-bundle-output.
-// RUN: %clang -### -E --offload-device-only --target=x86_64-linux-gnu \
+// RUN: %clang -### -E --offload-device-only --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -nogpulib -nogpuinc --offload-arch=gfx803 --offload-arch=gfx900 %s --gpu-bundle-output \
 // RUN: 2>&1 | FileCheck -check-prefixes=DASH %s
 
 // Output unbundled PPE for two GPUs for device only compilation with --no-gpu-bundle-output.
-// RUN: %clang -### -E --offload-device-only --target=x86_64-linux-gnu \
+// RUN: %clang -### -E --offload-device-only --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -nogpulib -nogpuinc --offload-arch=gfx803 --offload-arch=gfx900 %s --no-gpu-bundle-output \
 // RUN: 2>&1 | FileCheck -check-prefixes=CLANG-DASH %s
 
 // Output unbundled PPE for host only compilation.
-// RUN: %clang -### -E --offload-host-only --target=x86_64-linux-gnu \
+// RUN: %clang -### -E --offload-host-only --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -nogpulib -nogpuinc --offload-arch=gfx803 --offload-arch=gfx900 %s \
 // RUN: 2>&1 | FileCheck -check-prefixes=CLANG-DASH %s
 
@@ -60,22 +60,22 @@
 // Check -E with -o.
 
 // Output bundled PPE for two GPUs for mixed compilation.
-// RUN: %clang -### -E -o test.cui --target=x86_64-linux-gnu \
+// RUN: %clang -### -E -o test.cui --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -nogpulib -nogpuinc --offload-arch=gfx803 --offload-arch=gfx900 %s \
 // RUN: 2>&1 | FileCheck -check-prefixes=OUT %s
 
 // Output bundled PPE for two GPUs for mixed compilation.
-// RUN: %clang -### -E -o test.cui -save-temps --target=x86_64-linux-gnu \
+// RUN: %clang -### -E -o test.cui -save-temps --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -nogpulib -nogpuinc --offload-arch=gfx803 --offload-arch=gfx900 %s \
 // RUN: 2>&1 | FileCheck -check-prefixes=OUT %s
 
 // Output bundled PPE for two GPUs for device only compilation with --gpu-bundle-output.
-// RUN: %clang -### -E -o test.cui --offload-device-only --target=x86_64-linux-gnu \
+// RUN: %clang -### -E -o test.cui --offload-device-only --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -nogpulib -nogpuinc --offload-arch=gfx803 --offload-arch=gfx900 --gpu-bundle-output %s \
 // RUN: 2>&1 | FileCheck -check-prefixes=OUT %s
 
 // Output unbundled PPE for two GPUs for device only compilation.
-// RUN: %clang -### -E -o test.cui --offload-host-only --target=x86_64-linux-gnu \
+// RUN: %clang -### -E -o test.cui --offload-host-only --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -nogpulib -nogpuinc --offload-arch=gfx803 --offload-arch=gfx900 %s \
 // RUN: 2>&1 | FileCheck -check-prefixes=CLANG-OUT %s
 
diff --git a/clang/test/Driver/hip-partial-link.hip b/clang/test/Driver/hip-partial-link.hip
index a1d31f9a651951c50a76edde8cd8f973d944e6d2..faa185972abc33e52d02c0866dbc8f3af645cbd5 100644
--- a/clang/test/Driver/hip-partial-link.hip
+++ b/clang/test/Driver/hip-partial-link.hip
@@ -1,14 +1,14 @@
 // REQUIRES: x86-registered-target, amdgpu-registered-target, lld, system-linux
 
-// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu \
+// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN:   --offload-arch=gfx906 -c -nostdinc -nogpuinc -nohipwrapperinc \
 // RUN:   -nogpulib -fgpu-rdc -I%S/Inputs %s -o %t.1.o
 
-// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -DLIB \
+// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -DLIB --no-offload-new-driver \
 // RUN:   --offload-arch=gfx906 -c -nostdinc -nogpuinc -nohipwrapperinc \
 // RUN:   -nogpulib -fgpu-rdc -I%S/Inputs %s -o %t.2.o
 
-// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -DMAIN \
+// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -DMAIN --no-offload-new-driver \
 // RUN:   --offload-arch=gfx906 -c -nostdinc -nogpuinc -nohipwrapperinc \
 // RUN:   -nogpulib -fgpu-rdc -I%S/Inputs %s -o %t.main.o
 
@@ -24,7 +24,7 @@
 
 // Link %t.1.o and %t.2.o by -r and then link with %t.main.o
 
-// RUN: %clang -v --target=x86_64-unknown-linux-gnu \
+// RUN: %clang -v --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN:   --hip-link -fgpu-rdc --offload-arch=gfx906 \
 // RUN:   -r -fuse-ld=lld -nostdlib %t.1.o %t.2.o -o %t.lib.o \
 // RUN:   2>&1 | FileCheck -check-prefix=LD-R %s
@@ -46,7 +46,7 @@
 // OBJ:  D __hip_gpubin_handle_[[ID1]]
 // OBJ:  D __hip_gpubin_handle_[[ID2]]
 
-// RUN: %clang -v --target=x86_64-unknown-linux-gnu \
+// RUN: %clang -v --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN:   --hip-link -no-hip-rt -fgpu-rdc --offload-arch=gfx906 \
 // RUN:   -fuse-ld=lld -nostdlib -r %t.main.o %t.lib.o -o %t.final.o \
 // RUN:   2>&1 | FileCheck -check-prefix=LINK-O %s
@@ -54,7 +54,7 @@
 
 // Generate a static lib with %t.1.o and %t.2.o then link with %t.main.o
 
-// RUN: %clang -v --target=x86_64-unknown-linux-gnu \
+// RUN: %clang -v --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN:   --hip-link -fgpu-rdc --offload-arch=gfx906 \
 // RUN:   --emit-static-lib -fuse-ld=lld -nostdlib %t.1.o %t.2.o -o %t.a \
 // RUN:   2>&1 | FileCheck -check-prefix=STATIC %s
@@ -68,7 +68,7 @@
 // STATIC: "{{.*}}/llvm-mc" -triple x86_64-unknown-linux-gnu
 // STATIC: "{{.*}}/llvm-ar"
 
-// RUN: %clang -v --target=x86_64-unknown-linux-gnu \
+// RUN: %clang -v --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN:   --hip-link -no-hip-rt -fgpu-rdc --offload-arch=gfx906 \
 // RUN:   -fuse-ld=lld -nostdlib -r %t.main.o %t.a -o %t.final.o \
 // RUN:   2>&1 | FileCheck -check-prefix=LINK-A %s
diff --git a/clang/test/Driver/hip-phases.hip b/clang/test/Driver/hip-phases.hip
index e976583820ccf7ee36ec5e681337f8265fd14f86..ca63d4304d3959949b0d2976c608d33334c69de2 100644
--- a/clang/test/Driver/hip-phases.hip
+++ b/clang/test/Driver/hip-phases.hip
@@ -10,14 +10,14 @@
 // Test single gpu architecture with complete compilation.
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 %s 2>&1 \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 %s 2>&1 \
 // RUN: | FileCheck -check-prefixes=BIN,NRD,OLD %s
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
 // RUN: --offload-new-driver --cuda-gpu-arch=gfx803 %s 2>&1 \
 // RUN: | FileCheck -check-prefixes=BIN,NRD,NEW %s
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 -fgpu-rdc %s 2>&1 \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 -fgpu-rdc %s 2>&1 \
 // RUN: | FileCheck -check-prefixes=BIN,RDC %s
 //
 // BIN-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (host-[[T]])
@@ -49,7 +49,7 @@
 // Test single gpu architecture up to the assemble phase.
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 %s -S 2>&1 \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 %s -S 2>&1 \
 // RUN: | FileCheck -check-prefixes=ASM %s
 // ASM-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (device-[[T]], [[ARCH:gfx803]])
 // ASM-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH]])
@@ -64,11 +64,11 @@
 // Test two gpu architectures with complete compilation with -fno-gpu-rdc.
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s 2>&1 \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s 2>&1 \
 // RUN: | FileCheck -check-prefixes=NRD2,NCL2 %s
 
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s -c 2>&1 \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s -c 2>&1 \
 // RUN: | FileCheck -check-prefixes=NRD2 %s
 
 // NRD2-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (host-[[T]])
@@ -100,11 +100,11 @@
 // Test two gpu architectures with complete compilation with -fgpu-rdc.
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s -fgpu-rdc 2>&1 \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s -fgpu-rdc 2>&1 \
 // RUN: | FileCheck -check-prefixes=RDC2,RCL2 %s
 
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s -fgpu-rdc -c 2>&1 \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s -fgpu-rdc -c 2>&1 \
 // RUN: | FileCheck -check-prefixes=RDC2,RC2 %s
 
 // RCL2-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (host-[[T]])
@@ -144,7 +144,7 @@
 // Test two gpu architecturess up to the assemble phase.
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s -S 2>&1 \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s -S 2>&1 \
 // RUN: | FileCheck -check-prefixes=ASM2 %s
 // ASM2-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (device-[[T]], [[ARCH1:gfx803]])
 // ASM2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH1]])
@@ -162,7 +162,7 @@
 // compilation mode.
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 %s --cuda-host-only 2>&1 \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 %s --cuda-host-only 2>&1 \
 // RUN: | FileCheck -check-prefixes=HBIN %s
 // HBIN-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (host-[[T]])
 // HBIN-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
@@ -176,7 +176,7 @@
 // compilation mode.
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 %s --cuda-host-only -S 2>&1 \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 %s --cuda-host-only -S 2>&1 \
 // RUN: | FileCheck -check-prefixes=HASM %s
 // HASM-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (host-[[T]])
 // HASM-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
@@ -189,7 +189,7 @@
 // compilation mode.
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s --cuda-host-only 2>&1 \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s --cuda-host-only 2>&1 \
 // RUN: | FileCheck -check-prefixes=HBIN2 %s
 // HBIN2-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (host-[[T]])
 // HBIN2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
@@ -204,7 +204,7 @@
 // compilation mode.
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s --cuda-host-only -S \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s --cuda-host-only -S \
 // RUN: 2>&1 | FileCheck -check-prefixes=HASM2 %s
 // HASM2-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (host-[[T]])
 // HASM2-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (host-[[T]])
@@ -217,14 +217,14 @@
 // compilation mode.
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 %s --cuda-device-only 2>&1 \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 %s --cuda-device-only 2>&1 \
 // RUN: | FileCheck -check-prefixes=DBIN %s
 //
 // Test single gpu architecture with complete compilation in device-only
 // compilation mode with an unused host linker flag.
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
-// RUN: --cuda-gpu-arch=gfx803 %s --cuda-device-only -Wl,--disable-new-dtags 2>&1 \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 %s --cuda-device-only -Wl,--disable-new-dtags 2>&1 \
 // RUN: | FileCheck -check-prefixes=DBIN %s
 
 // DBIN-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (device-[[T]], [[ARCH:gfx803]])
@@ -242,7 +242,7 @@
 // Test single gpu architecture up to the assemble phase in device-only
 // compilation mode.
 //
-// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
+// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases --no-offload-new-driver \
 // RUN: --cuda-gpu-arch=gfx803 %s --cuda-device-only -S --no-gpu-bundle-output 2>&1 \
 // RUN: | FileCheck -check-prefixes=DASM %s
 // DASM-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (device-[[T]], [[ARCH:gfx803]])
@@ -257,11 +257,11 @@
 // Test single gpu architecture with compile to relocatable in device-only
 // compilation mode.
 //
-// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
+// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases --no-offload-new-driver \
 // RUN: --cuda-gpu-arch=gfx803 %s --cuda-device-only -fhip-emit-relocatable 2>&1 \
 // RUN: | FileCheck -check-prefixes=RELOC %s
 //
-// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
+// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases --no-offload-new-driver \
 // RUN: --cuda-gpu-arch=gfx803 %s --cuda-device-only -fhip-emit-relocatable -Wl,--disable-new-dtags \
 // RUN: 2>&1 | FileCheck -check-prefixes=RELOC %s
 //
@@ -278,11 +278,11 @@
 // Test two gpu architectures with compile to relocatable in device-only
 // compilation mode.
 //
-// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
+// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases --no-offload-new-driver \
 // RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s --cuda-device-only -fhip-emit-relocatable 2>&1 \
 // RUN: | FileCheck -check-prefixes=RELOC2 %s
 //
-// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
+// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases --no-offload-new-driver \
 // RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s --cuda-device-only -fhip-emit-relocatable \
 // RUN: -Wl,--disable-new-dtags 2>&1 | FileCheck -check-prefixes=RELOC2 %s
 //
@@ -306,14 +306,14 @@
 // Test two gpu architectures with complete compilation in device-only
 // compilation mode.
 //
-// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
+// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases --no-offload-new-driver \
 // RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s --cuda-device-only \
 // RUN: 2>&1 | FileCheck -check-prefixes=DBIN2 %s
 //
 // Test two gpu architectures with complete compilation in device-only
 // compilation mode with an unused host linker flag.
 //
-// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases \
+// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases --no-offload-new-driver \
 // RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s --cuda-device-only \
 // RUN: -Wl,--disable-new-dtags 2>&1 | FileCheck -check-prefixes=DBIN2 %s
 
@@ -339,19 +339,19 @@
 // Test two gpu architectures up to the assemble phase in device-only
 // compilation mode.
 //
-// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu \
+// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s \
 // RUN: --cuda-device-only -S -o %t.s 2>&1 \
 // RUN: | FileCheck -check-prefixes=DASM2,DASM2-NOBUNDLE %s
-// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu \
+// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s \
 // RUN: --cuda-device-only -S -o %t.s --no-gpu-bundle-output 2>&1 \
 // RUN: | FileCheck -check-prefixes=DASM2,DASM2-NOBUNDLE %s
-// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu \
+// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s \
 // RUN: --cuda-device-only -S 2>&1 \
 // RUN: | FileCheck -check-prefixes=DASM2,DASM2-NOBUNDLE %s
-// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu \
+// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s \
 // RUN: --cuda-device-only -S --gpu-bundle-output 2>&1 \
 // RUN: | FileCheck -check-prefixes=DASM2,DASM2-BUNDLE %s
@@ -376,29 +376,29 @@
 // RUN: touch %t/obj1.o %t/obj2.o
 
 // RUN: %clang --target=x86_64-unknown-linux-gnu -ccc-print-phases --hip-link \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t/obj1.o %t/obj2.o 2>&1 \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t/obj1.o %t/obj2.o 2>&1 \
 // RUN: | FileCheck -check-prefixes=L2,NL2 %s
 //
 // RUN: %clang --target=x86_64-unknown-linux-gnu -ccc-print-phases --hip-link \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t/obj1.o %t/obj2.o \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t/obj1.o %t/obj2.o \
 // RUN: -fgpu-rdc 2>&1 | FileCheck -check-prefixes=L2,RL2,RL2-EM %s
 //
 // RUN: %clang --target=x86_64-unknown-linux-gnu -ccc-print-phases --hip-link \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t/obj1.o %t/obj2.o \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t/obj1.o %t/obj2.o \
 // RUN: -fgpu-rdc --cuda-device-only 2>&1 | FileCheck -check-prefixes=L2,RL2,RL2-DEV %s
 
 // RUN: %clang --target=x86_64-unknown-linux-gnu -ccc-print-phases --hip-link \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t/obj1.o %t/obj2.o \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t/obj1.o %t/obj2.o \
 // RUN: -fgpu-rdc --cuda-device-only -Wl,--disable-new-dtags 2>&1 \
 // RUN: | FileCheck -check-prefixes=L2,RL2,RL2-DEV %s
 
 // RUN: %clang --target=x86_64-unknown-linux-gnu -ccc-print-phases --hip-link \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t/obj1.o %t/obj2.o \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t/obj1.o %t/obj2.o \
 // RUN: -fgpu-rdc --cuda-device-only --no-gpu-bundle-output 2>&1 \
 // RUN: | FileCheck -check-prefixes=L2,RL2,RL2-NB %s
 
 // RUN: %clang --target=x86_64-unknown-linux-gnu -ccc-print-phases --hip-link \
-// RUN: --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t/obj1.o %t/obj2.o \
+// RUN: --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %t/obj1.o %t/obj2.o \
 // RUN: -fgpu-rdc --cuda-device-only --no-gpu-bundle-output -Wl,--disable-new-dtags 2>&1 \
 // RUN: | FileCheck -check-prefixes=L2,RL2,RL2-NB %s
 
@@ -428,12 +428,12 @@
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 %s \
-// RUN: --cuda-device-only -E 2>&1 \
+// RUN: --no-offload-new-driver --cuda-device-only -E 2>&1 \
 // RUN: | FileCheck -check-prefixes=PPE,PPEN %s
 
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 %s \
-// RUN: --cuda-device-only -E --no-gpu-bundle-output 2>&1 \
+// RUN: --no-offload-new-driver --cuda-device-only -E --no-gpu-bundle-output 2>&1 \
 // RUN: | FileCheck -check-prefixes=PPE,PPEN %s
 
 // Test one gpu architectures up to the preprocessor expansion output phase in device-only
@@ -441,7 +441,7 @@
 
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 %s \
-// RUN: --cuda-device-only -E --gpu-bundle-output 2>&1 \
+// RUN: --no-offload-new-driver --cuda-device-only -E --gpu-bundle-output 2>&1 \
 // RUN: | FileCheck -check-prefixes=PPE,PPEB %s
 
 // Test two gpu architectures up to the preprocessor expansion output phase in device-only
@@ -449,12 +449,12 @@
 
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s \
-// RUN: --cuda-device-only -E 2>&1 \
+// RUN: --no-offload-new-driver --cuda-device-only -E 2>&1 \
 // RUN: | FileCheck -check-prefixes=PPE2,PPE2N %s
 
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s \
-// RUN: --cuda-device-only -E --no-gpu-bundle-output 2>&1 \
+// RUN: --no-offload-new-driver --cuda-device-only -E --no-gpu-bundle-output 2>&1 \
 // RUN: | FileCheck -check-prefixes=PPE2,PPE2N %s
 
 // Test two gpu architectures up to the preprocessor expansion output phase in device-only
@@ -462,7 +462,7 @@
 
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s \
-// RUN: --cuda-device-only -E --gpu-bundle-output 2>&1 \
+// RUN: --no-offload-new-driver --cuda-device-only -E --gpu-bundle-output 2>&1 \
 // RUN: | FileCheck -check-prefixes=PPE2,PPE2B %s
 
 // Test one gpu architectures up to the LLVM IR output phase in device-only
@@ -470,7 +470,7 @@
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 %s \
-// RUN: --cuda-device-only -c -emit-llvm 2>&1 \
+// RUN: --no-offload-new-driver --cuda-device-only -c -emit-llvm 2>&1 \
 // RUN: | FileCheck -check-prefixes=LLVM %s
 
 // Test two gpu architectures up to the LLVM IR output phase in device-only
@@ -478,7 +478,7 @@
 //
 // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s \
-// RUN: --cuda-device-only -c -emit-llvm -o %t.bc --gpu-bundle-output 2>&1 \
+// RUN: --no-offload-new-driver --cuda-device-only -c -emit-llvm -o %t.bc --gpu-bundle-output 2>&1 \
 // RUN: | FileCheck -check-prefixes=LLVM2 %s
 
 // Test two gpu architectures up to the LLVM IR output phase in device-only
@@ -486,7 +486,7 @@
 //
 // RUN: %clang -x hip-cpp-output --target=x86_64-unknown-linux-gnu \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 %s \
-// RUN: --cuda-device-only -c -emit-llvm -o %t.bc --gpu-bundle-output 2>&1 \
+// RUN: --no-offload-new-driver --cuda-device-only -c -emit-llvm -o %t.bc --gpu-bundle-output 2>&1 \
 // RUN: | FileCheck -check-prefixes=PPELLVM2 %s
 
 // PPE-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (device-[[T]], [[ARCH:gfx803]])
@@ -541,50 +541,50 @@
 // C++ program should have no offload kind.
 
 // Test compile empty.hip and empty.cpp.
-// RUN: %clang --target=x86_64-unknown-linux-gnu \
+// RUN: %clang --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN: -c %S/Inputs/empty.hip %S/Inputs/empty.cpp 2>&1 | FileCheck -check-prefixes=MIXED %s
-// RUN: %clang --target=x86_64-unknown-linux-gnu \
+// RUN: %clang --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN: -c %S/Inputs/empty.hip %S/Inputs/empty.cpp 2>&1 | FileCheck -check-prefixes=MIXED-NEG %s
 
 // Test compile and link empty.hip and empty.cpp.
-// RUN: %clang --target=x86_64-unknown-linux-gnu \
+// RUN: %clang --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN: %S/Inputs/empty.hip %S/Inputs/empty.cpp 2>&1 | FileCheck -check-prefixes=MIXED %s
-// RUN: %clang --target=x86_64-unknown-linux-gnu \
+// RUN: %clang --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN: %S/Inputs/empty.hip %S/Inputs/empty.cpp 2>&1 | FileCheck -check-prefixes=MIXED-NEG %s
 
 // Test compile and link empty.hip and empty.cpp with --hip-link -fgpu-rdc.
-// RUN: %clang --target=x86_64-unknown-linux-gnu --hip-link -fgpu-rdc \
+// RUN: %clang --target=x86_64-unknown-linux-gnu --hip-link -fgpu-rdc --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN: %S/Inputs/empty.hip %S/Inputs/empty.cpp 2>&1 | FileCheck -check-prefixes=MIXED %s
-// RUN: %clang --target=x86_64-unknown-linux-gnu --hip-link -fgpu-rdc \
+// RUN: %clang --target=x86_64-unknown-linux-gnu --hip-link -fgpu-rdc --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN: %S/Inputs/empty.hip %S/Inputs/empty.cpp 2>&1 | FileCheck -check-prefixes=MIXED-NEG %s
 
 // Test compile and link -x hip empty.hip and -x c++ empty.cpp.
-// RUN: %clang --target=x86_64-unknown-linux-gnu \
+// RUN: %clang --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN: -x hip %S/Inputs/empty.hip -x c++ %S/Inputs/empty.cpp 2>&1 | FileCheck -check-prefixes=MIXED %s
-// RUN: %clang --target=x86_64-unknown-linux-gnu \
+// RUN: %clang --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN: -x hip %S/Inputs/empty.hip -x c++ %S/Inputs/empty.cpp 2>&1 | FileCheck -check-prefixes=MIXED-NEG %s
 
 // Test compile and link -x hip empty.hip and empty.cpp.
-// RUN: %clang --target=x86_64-unknown-linux-gnu \
+// RUN: %clang --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN: -x hip %S/Inputs/empty.hip %S/Inputs/empty.cpp 2>&1 | FileCheck -check-prefixes=MIXED2 %s
-// RUN: %clang --target=x86_64-unknown-linux-gnu \
+// RUN: %clang --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN: -x hip %S/Inputs/empty.hip %S/Inputs/empty.cpp 2>&1 | FileCheck -check-prefixes=MIXED2-NEG %s
 
 // Test compile and link empty.hip and -x hip empty.cpp.
-// RUN: %clang --target=x86_64-unknown-linux-gnu \
+// RUN: %clang --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN: %S/Inputs/empty.hip -x hip %S/Inputs/empty.cpp 2>&1 | FileCheck -check-prefixes=MIXED2 %s
-// RUN: %clang --target=x86_64-unknown-linux-gnu \
+// RUN: %clang --target=x86_64-unknown-linux-gnu --no-offload-new-driver \
 // RUN: -ccc-print-phases --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN: -x hip %S/Inputs/empty.hip %S/Inputs/empty.cpp 2>&1 | FileCheck -check-prefixes=MIXED2-NEG %s
 
@@ -609,7 +609,7 @@
 // RUN: touch %t/bitcodeA.bc
 // RUN: touch %t/bitcodeB.bc
 // RUN: %clang -ccc-print-phases --hip-link -emit-llvm --cuda-device-only \
-// RUN: --offload-arch=gfx906 %t/bitcodeA.bc %t/bitcodeB.bc 2>&1 \
+// RUN: --no-offload-new-driver --offload-arch=gfx906 %t/bitcodeA.bc %t/bitcodeB.bc 2>&1 \
 // RUN: | FileCheck -check-prefixes=CHECK %s
 
 // CHECK: [[A0:[0-9]+]]: input, "{{.*}}bitcodeA.bc", ir
diff --git a/clang/test/Driver/hip-rdc-device-only.hip b/clang/test/Driver/hip-rdc-device-only.hip
index d972927ff7a3480af69cac2d1b56875ea1badedf..d79cc1febf3d42ebccaaf015f002f10780df2c1e 100644
--- a/clang/test/Driver/hip-rdc-device-only.hip
+++ b/clang/test/Driver/hip-rdc-device-only.hip
@@ -1,7 +1,7 @@
 // REQUIRES: x86-registered-target
 // REQUIRES: amdgpu-registered-target
 
-// RUN: %clang -### --target=x86_64-linux-gnu \
+// RUN: %clang -### --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN:   -c -nogpuinc -nogpulib --cuda-device-only -fgpu-rdc \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
@@ -11,7 +11,7 @@
 // With `-emit-llvm`, the output should be the same as the aforementioned line
 // as `-fgpu-rdc` in HIP implies `-emit-llvm`.
 
-// RUN: %clang -### --target=x86_64-linux-gnu \
+// RUN: %clang -### --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN:   -c -emit-llvm -nogpuinc -nogpulib --cuda-device-only -fgpu-rdc \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
@@ -21,14 +21,14 @@
 // With `-fno-hip-emit-relocatable`, the output should be the same as the aforementioned line
 // as `-fgpu-rdc` in HIP implies `-fno-hip-emit-relocatable`.
 
-// RUN: %clang -### --target=x86_64-linux-gnu \
+// RUN: %clang -### --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN:   -c -fno-hip-emit-relocatable -nogpuinc -nogpulib --cuda-device-only -fgpu-rdc \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
 // RUN:   %S/Inputs/hip_multiple_inputs/b.hip --gpu-bundle-output \
 // RUN: 2>&1 | FileCheck -check-prefixes=COMMON,EMITBC %s
 
-// RUN: %clang -### --target=x86_64-linux-gnu \
+// RUN: %clang -### --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN:   -S -nogpuinc -nogpulib --cuda-device-only -fgpu-rdc \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
@@ -38,7 +38,7 @@
 // With `-emit-llvm`, the output should be the same as the aforementioned line
 // as `-fgpu-rdc` in HIP implies `-emit-llvm`.
 
-// RUN: %clang -### --target=x86_64-linux-gnu \
+// RUN: %clang -### --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN:   -S -emit-llvm -nogpuinc -nogpulib --cuda-device-only -fgpu-rdc \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
@@ -49,7 +49,7 @@
 // output, there should 3 steps (preprocessor, compile, and backend) per source
 // and per target, totally 12 steps.
 
-// RUN: %clang -### -save-temps --target=x86_64-linux-gnu \
+// RUN: %clang -### -save-temps --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN:   -S -nogpuinc -nogpulib --cuda-device-only -fgpu-rdc \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
@@ -58,7 +58,7 @@
 
 // Check output one file without bundling cause error.
 
-// RUN: not %clang -### --target=x86_64-linux-gnu \
+// RUN: not %clang -### --target=x86_64-linux-gnu --no-offload-new-driver \
 // RUN:   -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN:   -S -nogpuinc -nogpulib --cuda-device-only -fgpu-rdc \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu -o %t.s --no-gpu-bundle-output \
diff --git a/clang/test/Driver/hip-target-id.hip b/clang/test/Driver/hip-target-id.hip
index 703d6b50be2e3a775cf0ab8a5d47c8268e33022d..e7ba456565c095eba71a870c8524c91472cadafb 100644
--- a/clang/test/Driver/hip-target-id.hip
+++ b/clang/test/Driver/hip-target-id.hip
@@ -5,7 +5,7 @@
 // RUN:   -x hip \
 // RUN:   --offload-arch=gfx908:xnack+:sramecc+ \
 // RUN:   --offload-arch=gfx908:xnack+:sramecc- \
-// RUN:   --rocm-path=%S/Inputs/rocm \
+// RUN:   --no-offload-new-driver --rocm-path=%S/Inputs/rocm \
 // RUN:   %s 2>&1 | FileCheck %s
 
 // RUN: %clang -### --target=x86_64-linux-gnu \
@@ -13,7 +13,7 @@
 // RUN:   --offload-arch=gfx908:xnack+:sramecc+ \
 // RUN:   --offload-arch=gfx908:xnack+:sramecc- \
 // RUN:   --rocm-path=%S/Inputs/rocm \
-// RUN:   -save-temps \
+// RUN:   --no-offload-new-driver -save-temps \
 // RUN:   %s 2>&1 | FileCheck --check-prefixes=CHECK,TMP %s
 
 // RUN: %clang -### --target=x86_64-linux-gnu \
@@ -21,7 +21,7 @@
 // RUN:   --offload-arch=gfx908:xnack+:sramecc+ \
 // RUN:   --offload-arch=gfx908:xnack+:sramecc- \
 // RUN:   --rocm-path=%S/Inputs/rocm \
-// RUN:   -fgpu-rdc \
+// RUN:   --no-offload-new-driver -fgpu-rdc \
 // RUN:   %s 2>&1 | FileCheck --check-prefixes=CHECK %s
 
 // CHECK: [[CLANG:"[^"]*clang[^"]*"]] "-cc1" "-triple" "amdgcn-amd-amdhsa"
@@ -55,7 +55,7 @@
 // RUN:   --offload-arch=fiji \
 // RUN:   --offload-arch=gfx803 \
 // RUN:   --offload-arch=fiji \
-// RUN:   --rocm-path=%S/Inputs/rocm \
+// RUN:   --no-offload-new-driver --rocm-path=%S/Inputs/rocm \
 // RUN:   %s 2>&1 | FileCheck -check-prefix=FIJI %s
 // FIJI: "-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx803"
 
@@ -66,6 +66,6 @@
 // RUN:   --offload-arch=gfx908:sramecc+ \
 // RUN:   --offload-arch=gfx908:sramecc- \
 // RUN:   --offload-arch=gfx906 \
-// RUN:   --rocm-path=%S/Inputs/rocm \
+// RUN:   --no-offload-new-driver --rocm-path=%S/Inputs/rocm \
 // RUN:   %s 2>&1 | FileCheck -check-prefix=MULTI %s
 // MULTI: "-targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx900:xnack+,hipv4-amdgcn-amd-amdhsa--gfx900:xnack-,hipv4-amdgcn-amd-amdhsa--gfx906,hipv4-amdgcn-amd-amdhsa--gfx908:sramecc+,hipv4-amdgcn-amd-amdhsa--gfx908:sramecc-"
diff --git a/clang/test/Driver/hip-toolchain-features.hip b/clang/test/Driver/hip-toolchain-features.hip
index 2e11ce38403ef401d9fad729025cfdd32dd631c6..551d8ef42e02026e42bc8c74f089aec5175aa086 100644
--- a/clang/test/Driver/hip-toolchain-features.hip
+++ b/clang/test/Driver/hip-toolchain-features.hip
@@ -1,10 +1,10 @@
 // REQUIRES: x86-registered-target
 // REQUIRES: amdgpu-registered-target
 
-// RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -nogpulib \
+// RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -nogpulib --no-offload-new-driver \
 // RUN:   -nogpuinc --offload-arch=gfx906:xnack+ --offload-arch=gfx900:xnack+ %s \
 // RUN:   2>&1 | FileCheck %s -check-prefix=XNACK
-// RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -nogpulib \
+// RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -nogpulib --no-offload-new-driver \
 // RUN:   -nogpuinc --offload-arch=gfx906:xnack- --offload-arch=gfx900:xnack- %s \
 // RUN:   2>&1 | FileCheck %s -check-prefix=NOXNACK
 
@@ -14,10 +14,10 @@
 // NOXNACK: {{.*}}lld{{.*}} "-plugin-opt=-mattr=-xnack"
 
 // RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -nogpulib \
-// RUN:   -nogpuinc --offload-arch=gfx908:sramecc+ %s \
+// RUN:   -nogpuinc --offload-arch=gfx908:sramecc+ --no-offload-new-driver %s \
 // RUN:   2>&1 | FileCheck %s -check-prefix=SRAM
 // RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -nogpulib \
-// RUN:   -nogpuinc --offload-arch=gfx908:sramecc- %s \
+// RUN:   -nogpuinc --offload-arch=gfx908:sramecc- --no-offload-new-driver %s \
 // RUN:   2>&1 | FileCheck %s -check-prefix=NOSRAM
 
 // SRAM: {{.*}}clang{{.*}}"-target-feature" "+sramecc"
@@ -26,10 +26,10 @@
 // NOTSRAM: {{.*}}lld{{.*}} "-plugin-opt=-mattr=-sramecc"
 
 // RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -nogpulib \
-// RUN:   -nogpuinc --offload-arch=gfx1010 %s \
+// RUN:   -nogpuinc --offload-arch=gfx1010 --no-offload-new-driver %s \
 // RUN:   -mcumode  2>&1 | FileCheck %s -check-prefix=CUMODE
 // RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -nogpulib \
-// RUN:   -nogpuinc --offload-arch=gfx1010 %s \
+// RUN:   -nogpuinc --offload-arch=gfx1010 --no-offload-new-driver %s \
 // RUN:   -mno-cumode  2>&1 | FileCheck %s -check-prefix=NOTCUMODE
 
 // CUMODE: {{.*}}clang{{.*}}"-target-feature" "+cumode"
@@ -38,20 +38,20 @@
 // NOTCUMODE: {{.*}}lld{{.*}} "-plugin-opt=-mattr=-cumode"
 
 // RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -nogpulib \
-// RUN:   -nogpuinc --offload-arch=gfx908:xnack+:sramecc+ %s \
+// RUN:   -nogpuinc --offload-arch=gfx908:xnack+:sramecc+ --no-offload-new-driver %s \
 // RUN:   2>&1 | FileCheck %s -check-prefix=ALL3
 // RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -nogpulib \
-// RUN:   -nogpuinc --offload-arch=gfx908:xnack-:sramecc- %s \
+// RUN:   -nogpuinc --offload-arch=gfx908:xnack-:sramecc- --no-offload-new-driver %s \
 // RUN:   2>&1 | FileCheck %s -check-prefix=NOALL3
 
 // ALL3: {{.*}}clang{{.*}}"-target-feature" "+sramecc" "-target-feature" "+xnack"
 // NOALL3: {{.*}}clang{{.*}}"-target-feature" "-sramecc" "-target-feature" "-xnack"
 
 // RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -nogpulib \
-// RUN:   -nogpuinc --offload-arch=gfx1010 %s \
+// RUN:   -nogpuinc --offload-arch=gfx1010 --no-offload-new-driver %s \
 // RUN:   -mtgsplit  2>&1 | FileCheck %s -check-prefix=TGSPLIT
 // RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -nogpulib \
-// RUN:   -nogpuinc --offload-arch=gfx1010 %s \
+// RUN:   -nogpuinc --offload-arch=gfx1010 --no-offload-new-driver %s \
 // RUN:   -mno-tgsplit  2>&1 | FileCheck %s -check-prefix=NOTTGSPLIT
 
 // TGSPLIT: {{.*}}clang{{.*}}"-target-feature" "+tgsplit"
@@ -60,7 +60,7 @@
 // NOTTGSPLIT: {{.*}}lld{{.*}} "-plugin-opt=-mattr=-tgsplit"
 
 // RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -nogpulib \
-// RUN:   -nogpuinc --offload-arch=gfx1010 %s \
+// RUN:   -nogpuinc --offload-arch=gfx1010 --no-offload-new-driver %s \
 // RUN:   -mcumode -mcumode -mno-cumode -mwavefrontsize64 -mcumode \
 // RUN:   -mwavefrontsize64 -mno-wavefrontsize64 2>&1 \
 // RUN:   | FileCheck %s -check-prefix=DUP
@@ -71,7 +71,7 @@
 // DUP: {{.*}}lld{{.*}} "-plugin-opt=-mattr=+cumode"
 
 // RUN: %clang -### --target=x86_64-linux-gnu -fgpu-rdc -nogpulib \
-// RUN:   -nogpuinc --offload-arch=gfx1010 %s \
+// RUN:   -nogpuinc --offload-arch=gfx1010 --no-offload-new-driver %s \
 // RUN:   -mno-wavefrontsize64 -mwavefrontsize64 2>&1 \
 // RUN:   | FileCheck %s -check-prefix=WAVE64
 // WAVE64: {{.*}}clang{{.*}} "-target-feature" "+wavefrontsize64"
diff --git a/clang/test/Driver/hip-toolchain-rdc-separate.hip b/clang/test/Driver/hip-toolchain-rdc-separate.hip
index e52184fdeacf36a1dc07e9d77dc4a8e7890681b6..6efca87dc0db208a69011163a9f697ea32ecb0b2 100644
--- a/clang/test/Driver/hip-toolchain-rdc-separate.hip
+++ b/clang/test/Driver/hip-toolchain-rdc-separate.hip
@@ -7,7 +7,7 @@
 // RUN:   --hip-device-lib=lib1.bc --hip-device-lib=lib2.bc \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib2 \
-// RUN:   -fuse-ld=lld -B%S/Inputs/lld -fgpu-rdc -nogpuinc \
+// RUN:   --no-offload-new-driver -fuse-ld=lld -B%S/Inputs/lld -fgpu-rdc -nogpuinc \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
 // RUN:   %S/Inputs/hip_multiple_inputs/b.hip \
 // RUN: 2>&1 | FileCheck %s
@@ -84,19 +84,19 @@
 
 // RUN: touch %t/a.o %t/b.o
 // RUN: %clang --hip-link -### --target=x86_64-linux-gnu \
-// RUN:   --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN:   -fuse-ld=lld -B%S/Inputs/lld -fgpu-rdc -nogpuinc \
 // RUN:   %t/a.o %t/b.o \
 // RUN: 2>&1 | FileCheck -check-prefixes=LINK,LINK-HOST-UNBUNDLE,LLD-TMP,LINK-BUNDLE,LINK-EMBED %s
 
 // RUN: %clang --hip-link -### --target=x86_64-linux-gnu \
-// RUN:   --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN:   -fuse-ld=lld -B%S/Inputs/lld -fgpu-rdc -nogpuinc \
 // RUN:   %t/a.o %t/b.o --cuda-device-only \
 // RUN: 2>&1 | FileCheck -check-prefixes=LINK,LLD-TMP,LINK-BUNDLE,LINK-NOEMBED %s
 
 // RUN: %clang --hip-link -### --target=x86_64-linux-gnu \
-// RUN:   --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
+// RUN:   --no-offload-new-driver --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
 // RUN:   -fuse-ld=lld -B%S/Inputs/lld -fgpu-rdc -nogpuinc \
 // RUN:   %t/a.o %t/b.o --cuda-device-only --no-gpu-bundle-output \
 // RUN: 2>&1 | FileCheck -check-prefixes=LINK,LLD-FIN,LINK-NOBUNDLE,LINK-NOEMBED %s
diff --git a/clang/test/Driver/hip-toolchain-rdc-static-lib.hip b/clang/test/Driver/hip-toolchain-rdc-static-lib.hip
index fd12d48a2b8235c99ec8b98165609fc168acc242..2cfb2485238621789f52224321c626efcb47e129 100644
--- a/clang/test/Driver/hip-toolchain-rdc-static-lib.hip
+++ b/clang/test/Driver/hip-toolchain-rdc-static-lib.hip
@@ -3,7 +3,7 @@
 
 // RUN: %clang -### --target=x86_64-linux-gnu \
 // RUN:   -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \
-// RUN:   --emit-static-lib -nogpulib \
+// RUN:   --no-offload-new-driver --emit-static-lib -nogpulib \
 // RUN:   -fuse-ld=lld -B%S/Inputs/lld -fgpu-rdc -nogpuinc \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
 // RUN:   %S/Inputs/hip_multiple_inputs/b.hip \
diff --git a/clang/test/Driver/hip-toolchain-rdc.hip b/clang/test/Driver/hip-toolchain-rdc.hip
index d19d8ccd6cb29eeb21c65f01838a8ec32ea32ee0..49acc40ec6f9fd9e198570aac34c5c6d86cfcb83 100644
--- a/clang/test/Driver/hip-toolchain-rdc.hip
+++ b/clang/test/Driver/hip-toolchain-rdc.hip
@@ -7,7 +7,7 @@
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib2 \
 // RUN:   -fuse-ld=lld -B%S/Inputs/lld -fgpu-rdc -nogpuinc \
-// RUN:   -fhip-dump-offload-linker-script \
+// RUN:   --no-offload-new-driver -fhip-dump-offload-linker-script \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
 // RUN:   %S/Inputs/hip_multiple_inputs/b.hip \
 // RUN: 2>&1 | FileCheck -check-prefixes=CHECK,LNX %s
@@ -18,7 +18,7 @@
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \
 // RUN:   --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib2 \
 // RUN:   -fuse-ld=lld -B%S/Inputs/lld -fgpu-rdc -nogpuinc \
-// RUN:   -fhip-dump-offload-linker-script \
+// RUN:   --no-offload-new-driver -fhip-dump-offload-linker-script \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
 // RUN:   %S/Inputs/hip_multiple_inputs/b.hip \
 // RUN: 2>&1 | FileCheck -check-prefixes=CHECK,MSVC %s
diff --git a/clang/test/Driver/hip-unbundle-preproc.hipi b/clang/test/Driver/hip-unbundle-preproc.hipi
index fecdfdbe7d143c2ca7a5a73db3ada73b83bd1c1f..6d92d23819739adacef9ec85a32f008e6c86af39 100644
--- a/clang/test/Driver/hip-unbundle-preproc.hipi
+++ b/clang/test/Driver/hip-unbundle-preproc.hipi
@@ -1,11 +1,11 @@
 // REQUIRES: amdgpu-registered-target
 
 // RUN: %clang -### --target=x86_64-unknown-linux-gnu \
-// RUN:   --offload-arch=gfx803 -nogpulib \
+// RUN:   --no-offload-new-driver --offload-arch=gfx803 -nogpulib \
 // RUN:   -x hip-cpp-output %s 2>&1 | FileCheck %s
 
 // RUN: %clang -### --target=x86_64-unknown-linux-gnu \
-// RUN:   --offload-arch=gfx803 -nogpulib \
+// RUN:   --no-offload-new-driver --offload-arch=gfx803 -nogpulib \
 // RUN:   %s 2>&1 | FileCheck %s
 
 // CHECK: {{".*clang-offload-bundler.*"}} {{.*}}"-output=[[HOST_PP:.*hipi]]" "-output=[[DEV_PP:.*hipi]]" "-unbundle"
@@ -16,7 +16,7 @@
 // CHECK: {{".*ld.*"}} {{.*}}"[[HOST_O]]"
 
 // RUN: %clang -### --target=x86_64-unknown-linux-gnu \
-// RUN:   --offload-arch=gfx803 -nogpulib -fgpu-rdc \
+// RUN:   --no-offload-new-driver --offload-arch=gfx803 -nogpulib -fgpu-rdc \
 // RUN:   %s 2>&1 | FileCheck -check-prefix=RDC %s
 
 // RDC: {{".*clang-offload-bundler.*"}} {{.*}}"-output=[[HOST_PP:.*hipi]]" "-output=[[DEV_PP:.*hipi]]" "-unbundle"
diff --git a/clang/test/Driver/hipspv-toolchain-rdc.hip b/clang/test/Driver/hipspv-toolchain-rdc.hip
index 2bfcec977d392dc6a6653b80ad2d4f2833da5d6c..d4e612cc54378f51f693d5549314fce943f9aa98 100644
--- a/clang/test/Driver/hipspv-toolchain-rdc.hip
+++ b/clang/test/Driver/hipspv-toolchain-rdc.hip
@@ -2,7 +2,7 @@
 // UNSUPPORTED: system-windows
 
 // RUN: %clang -### -x hip -target x86_64-linux-gnu --offload=spirv64 \
-// RUN:   -fgpu-rdc --hip-path=%S/Inputs/hipspv -nohipwrapperinc \
+// RUN:   --no-offload-new-driver -fgpu-rdc --hip-path=%S/Inputs/hipspv -nohipwrapperinc \
 // RUN:   %S/Inputs/hip_multiple_inputs/a.cu \
 // RUN:   %S/Inputs/hip_multiple_inputs/b.hip \
 // RUN: 2>&1 | FileCheck %s
diff --git a/clang/test/Driver/hipspv-toolchain.hip b/clang/test/Driver/hipspv-toolchain.hip
index bfae41049ba4dd1a88144488da5a6611f98f9744..4602cd3fc8d68a053cd21f2e85de9a91e5d823d5 100644
--- a/clang/test/Driver/hipspv-toolchain.hip
+++ b/clang/test/Driver/hipspv-toolchain.hip
@@ -2,7 +2,7 @@
 // UNSUPPORTED: system-windows
 
 // RUN: %clang -### -target x86_64-linux-gnu --offload=spirv64 \
-// RUN:   --hip-path=%S/Inputs/hipspv -nohipwrapperinc %s \
+// RUN:   --no-offload-new-driver --hip-path=%S/Inputs/hipspv -nohipwrapperinc %s \
 // RUN: 2>&1 | FileCheck %s
 
 // CHECK: [[CLANG:".*clang.*"]] "-cc1" "-triple" "spirv64"
diff --git a/clang/test/Driver/linker-wrapper-image.c b/clang/test/Driver/linker-wrapper-image.c
index 08f860f6cab0de421da75a5771232b55e3c6869e..7547526413522475e5f47de5b0700b344e4e1230 100644
--- a/clang/test/Driver/linker-wrapper-image.c
+++ b/clang/test/Driver/linker-wrapper-image.c
@@ -8,11 +8,11 @@
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o \
 // RUN:   -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=OPENMP,OPENMP-ELF
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=OPENMP,OPENMP-ELF
 // RUN: clang-linker-wrapper --print-wrapped-module --dry-run -r --host-triple=x86_64-unknown-linux-gnu \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=OPENMP-ELF,OPENMP-REL
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=OPENMP-ELF,OPENMP-REL
 // RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-windows-gnu \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=OPENMP,OPENMP-COFF
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=OPENMP,OPENMP-COFF
 
 //      OPENMP-ELF: @__start_omp_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
 // OPENMP-ELF-NEXT: @__stop_omp_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
@@ -45,11 +45,11 @@
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o \
 // RUN:   -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=CUDA,CUDA-ELF
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=CUDA,CUDA-ELF
 // RUN: clang-linker-wrapper --print-wrapped-module --dry-run -r --host-triple=x86_64-unknown-linux-gnu \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=CUDA,CUDA-ELF
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=CUDA,CUDA-ELF
 // RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-windows-gnu \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=CUDA,CUDA-COFF
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=CUDA,CUDA-COFF
 
 //      CUDA-ELF: @__start_cuda_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
 // CUDA-ELF-NEXT: @__stop_cuda_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
@@ -145,11 +145,11 @@
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o \
 // RUN:   -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=HIP,HIP-ELF
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=HIP,HIP-ELF
 // RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-linux-gnu -r \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=HIP,HIP-ELF
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=HIP,HIP-ELF
 // RUN: clang-linker-wrapper --print-wrapped-module --dry-run --host-triple=x86_64-unknown-windows-gnu \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=HIP,HIP-COFF
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefixes=HIP,HIP-COFF
 
 //      HIP-ELF: @__start_hip_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
 // HIP-ELF-NEXT: @__stop_hip_offloading_entries = external hidden constant [0 x %struct.__tgt_offload_entry]
diff --git a/clang/test/Driver/linker-wrapper-libs.c b/clang/test/Driver/linker-wrapper-libs.c
index 2073092bdbcf9e44069fd8e9f775f74ecaa3180e..9a78200d7d3cfc7dd8deeb984b89e3137a03d23b 100644
--- a/clang/test/Driver/linker-wrapper-libs.c
+++ b/clang/test/Driver/linker-wrapper-libs.c
@@ -43,7 +43,7 @@ int bar() { return weak; }
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o %t.a -o a.out 2>&1 \
+// RUN:   --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \
 // RUN: | FileCheck %s --check-prefix=LIBRARY-RESOLVES
 
 // LIBRARY-RESOLVES: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
@@ -65,7 +65,7 @@ int bar() { return weak; }
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o %t.a -o a.out 2>&1 \
+// RUN:   --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \
 // RUN: | FileCheck %s --check-prefix=LIBRARY-GLOBAL
 
 // LIBRARY-GLOBAL: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
@@ -88,7 +88,7 @@ int bar() { return weak; }
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o %t.a -o a.out 2>&1 \
+// RUN:   --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \
 // RUN: | FileCheck %s --check-prefix=LIBRARY-GLOBAL-NONE
 
 // LIBRARY-GLOBAL-NONE-NOT: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
@@ -109,7 +109,7 @@ int bar() { return weak; }
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o %t.a -o a.out 2>&1 \
+// RUN:   --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \
 // RUN: | FileCheck %s --check-prefix=LIBRARY-WEAK
 
 // LIBRARY-WEAK: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030
@@ -131,7 +131,7 @@ int bar() { return weak; }
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o %t.a -o a.out 2>&1 \
+// RUN:   --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \
 // RUN: | FileCheck %s --check-prefix=LIBRARY-HIDDEN
 
 // LIBRARY-HIDDEN: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030
@@ -154,7 +154,7 @@ int bar() { return weak; }
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o %t.a %t.a -o a.out 2>&1 \
+// RUN:   --linker-path=/usr/bin/ld %t.o %t.a %t.a -o a.out 2>&1 \
 // RUN: | FileCheck %s --check-prefix=LIBRARY-GLOBAL-DEFINED
 
 // LIBRARY-GLOBAL-DEFINED: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
@@ -178,7 +178,7 @@ int bar() { return weak; }
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o --whole-archive %t.a -o a.out 2>&1 \
+// RUN:   --linker-path=/usr/bin/ld %t.o --whole-archive %t.a -o a.out 2>&1 \
 // RUN: | FileCheck %s --check-prefix=LIBRARY-WHOLE-ARCHIVE
 
 // LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
diff --git a/clang/test/Driver/linker-wrapper.c b/clang/test/Driver/linker-wrapper.c
index 83df2b84adefed948916b56312847ad5b814e203..cbf24d4ce3a8245c83204ee6e3eb637dd71169b1 100644
--- a/clang/test/Driver/linker-wrapper.c
+++ b/clang/test/Driver/linker-wrapper.c
@@ -16,10 +16,10 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=NVPTX-LINK
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=NVPTX-LINK
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=NVPTX-LINK
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=NVPTX-LINK
 
 // NVPTX-LINK: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_70 -O2 {{.*}}.o {{.*}}.o
 
@@ -28,7 +28,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run --device-debug -O0 \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=NVPTX-LINK-DEBUG
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=NVPTX-LINK-DEBUG
 
 // NVPTX-LINK-DEBUG: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_70 -O2 {{.*}}.o {{.*}}.o -g 
 
@@ -37,7 +37,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx908
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LINK
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LINK
 
 // AMDGPU-LINK: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx908 -O2 -Wl,--no-undefined {{.*}}.o {{.*}}.o
 
@@ -46,7 +46,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --image=file=%t.amdgpu.bc,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run --save-temps -O2 \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LTO-TEMPS
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LTO-TEMPS
 
 // AMDGPU-LTO-TEMPS: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 -O2 -Wl,--no-undefined {{.*}}.s -save-temps
 
@@ -56,14 +56,14 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: llvm-ar rcs %t.a %t.o
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld.lld -- --whole-archive %t.a --no-whole-archive \
+// RUN:   --linker-path=/usr/bin/ld.lld --whole-archive %t.a --no-whole-archive \
 // RUN:   %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CPU-LINK
 
 // CPU-LINK: clang{{.*}} -o {{.*}}.img --target=x86_64-unknown-linux-gnu -march=native -O2 -Wl,--no-undefined {{.*}}.o {{.*}}.o -Wl,-Bsymbolic -shared -Wl,--whole-archive {{.*}}.a -Wl,--no-whole-archive
 
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o
 // RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu -mllvm -openmp-opt-disable \
-// RUN:   --linker-path=/usr/bin/ld.lld -- -a -b -c %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=HOST-LINK
+// RUN:   --linker-path=/usr/bin/ld.lld -a -b -c %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=HOST-LINK
 
 // HOST-LINK: ld.lld{{.*}}-a -b -c {{.*}}.o -o a.out
 // HOST-LINK-NOT: ld.lld{{.*}}-abc
@@ -77,7 +77,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t-obj.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld -- %t.a %t-obj.o -o a.out 2>&1 | FileCheck %s --check-prefix=STATIC-LIBRARY
+// RUN:   --linker-path=/usr/bin/ld %t.a %t-obj.o -o a.out 2>&1 | FileCheck %s --check-prefix=STATIC-LIBRARY
 
 // STATIC-LIBRARY: clang{{.*}} -march=sm_70
 // STATIC-LIBRARY-NOT: clang{{.*}} -march=sm_50
@@ -89,7 +89,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o \
 // RUN:   -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu \
-// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CUDA
+// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CUDA
 
 // CUDA: clang{{.*}} -o [[IMG_SM52:.+]] --target=nvptx64-nvidia-cuda -march=sm_52
 // CUDA: clang{{.*}} -o [[IMG_SM70:.+]] --target=nvptx64-nvidia-cuda -march=sm_70
@@ -104,7 +104,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o \
 // RUN:   -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu --wrapper-jobs=4 \
-// RUN: --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CUDA-PAR
+// RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CUDA-PAR
 
 // CUDA-PAR: fatbinary{{.*}}-64 --create {{.*}}.fatbin
 
@@ -115,11 +115,12 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o \
 // RUN:   -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=HIP
+// RUN:   --compress --compression-level=6 \
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=HIP
 
 // HIP: clang{{.*}} -o [[IMG_GFX908:.+]] --target=amdgcn-amd-amdhsa -mcpu=gfx908
 // HIP: clang{{.*}} -o [[IMG_GFX90A:.+]] --target=amdgcn-amd-amdhsa -mcpu=gfx90a
-// HIP: clang-offload-bundler{{.*}}-type=o -bundle-align=4096 -targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx90a,hipv4-amdgcn-amd-amdhsa--gfx908 -input=/dev/null -input=[[IMG_GFX90A]] -input=[[IMG_GFX908]] -output={{.*}}.hipfb
+// HIP: clang-offload-bundler{{.*}}-type=o -bundle-align=4096 -compress -compression-level=6 -targets=host-x86_64-unknown-linux,hipv4-amdgcn-amd-amdhsa--gfx90a,hipv4-amdgcn-amd-amdhsa--gfx908 -input=/dev/null -input=[[IMG_GFX90A]] -input=[[IMG_GFX908]] -output={{.*}}.hipfb
 
 // RUN: clang-offload-packager -o %t.out \
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx908 \
@@ -127,14 +128,14 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o \
 // RUN:   -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu \
-// RUN:   --linker-path=/usr/bin/ld --device-linker=a --device-linker=nvptx64-nvidia-cuda=b -- \
+// RUN:   --linker-path=/usr/bin/ld --device-linker=a --device-linker=nvptx64-nvidia-cuda=b \
 // RUN:   %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=LINKER-ARGS
 
 // LINKER-ARGS: clang{{.*}}--target=amdgcn-amd-amdhsa{{.*}}a
 // LINKER-ARGS: clang{{.*}}--target=nvptx64-nvidia-cuda{{.*}}a b
 
 // RUN: not clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu -ldummy \
-// RUN:   --linker-path=/usr/bin/ld --device-linker=a --device-linker=nvptx64-nvidia-cuda=b -- \
+// RUN:   --linker-path=/usr/bin/ld --device-linker=a --device-linker=nvptx64-nvidia-cuda=b \
 // RUN:   -o a.out 2>&1 | FileCheck %s --check-prefix=MISSING-LIBRARY
 
 // MISSING-LIBRARY: error: unable to find library -ldummy
@@ -144,7 +145,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --image=file=%t.amdgpu.bc,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx908
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run --clang-backend \
-// RUN:   --linker-path=/usr/bin/ld -- %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CLANG-BACKEND
+// RUN:   --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CLANG-BACKEND
 
 // CLANG-BACKEND: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx908 -O2 -Wl,--no-undefined {{.*}}.bc
 
@@ -152,7 +153,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70
 // RUN: %clang -cc1 %s -triple x86_64-unknown-windows-msvc -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-windows-msvc --dry-run \
-// RUN:   --linker-path=/usr/bin/lld-link -- %t.o -libpath:./ -out:a.exe 2>&1 | FileCheck %s --check-prefix=COFF
+// RUN:   --linker-path=/usr/bin/lld-link %t.o -libpath:./ -out:a.exe 2>&1 | FileCheck %s --check-prefix=COFF
 
 // COFF: "/usr/bin/lld-link" {{.*}}.o -libpath:./ -out:a.exe {{.*}}openmp.image.wrapper{{.*}}
 
@@ -167,7 +168,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx90a:xnack-
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t-off.o -fembed-offload-object=%t-off.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld -- %t-on.o %t-off.o %t.a -o a.out 2>&1 | FileCheck %s --check-prefix=AMD-TARGET-ID
+// RUN:   --linker-path=/usr/bin/ld %t-on.o %t-off.o %t.a -o a.out 2>&1 | FileCheck %s --check-prefix=AMD-TARGET-ID
 
 // AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack+ -O2 -Wl,--no-undefined {{.*}}.o {{.*}}.o
 // AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack- -O2 -Wl,--no-undefined {{.*}}.o {{.*}}.o
@@ -183,7 +184,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx908
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t2.o -fembed-offload-object=%t2.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld -- %t1.o %t2.o %t.a -o a.out 2>&1 | FileCheck %s --check-prefix=ARCH-ALL
+// RUN:   --linker-path=/usr/bin/ld %t1.o %t2.o %t.a -o a.out 2>&1 | FileCheck %s --check-prefix=ARCH-ALL
 
 // ARCH-ALL: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx908 -O2 -Wl,--no-undefined {{.*}}.o {{.*}}.o
 // ARCH-ALL: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx90a -O2 -Wl,--no-undefined {{.*}}.o {{.*}}.o
@@ -193,7 +194,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld.lld -- -r %t.o \
+// RUN:   --linker-path=/usr/bin/ld.lld -r %t.o \
 // RUN:   %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=RELOCATABLE-LINK
 
 // RELOCATABLE-LINK: clang{{.*}} -o {{.*}}.img --target=x86_64-unknown-linux-gnu
@@ -205,7 +206,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --image=file=%t.elf.o,kind=hip,triple=amdgcn-amd-amdhsa,arch=gfx90a
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld.lld -- -r %t.o \
+// RUN:   --linker-path=/usr/bin/ld.lld -r %t.o \
 // RUN:   %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=RELOCATABLE-LINK-HIP
 
 // RELOCATABLE-LINK-HIP: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa
@@ -218,7 +219,7 @@ __attribute__((visibility("protected"), used)) int x;
 // RUN:   --image=file=%t.elf.o,kind=cuda,triple=nvptx64-nvidia-cuda,arch=sm_89
 // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
 // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
-// RUN:   --linker-path=/usr/bin/ld.lld -- -r %t.o \
+// RUN:   --linker-path=/usr/bin/ld.lld -r %t.o \
 // RUN:   %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=RELOCATABLE-LINK-CUDA
 
 // RELOCATABLE-LINK-CUDA: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda
diff --git a/clang/test/Driver/lto.cu b/clang/test/Driver/lto.cu
index dadf35d8e6c9a917732362aa6478a33fede80ff2..fb8cc5cba3938cd3fd2022d73e0af2a7c3ba6296 100644
--- a/clang/test/Driver/lto.cu
+++ b/clang/test/Driver/lto.cu
@@ -2,14 +2,14 @@
 // REQUIRES: nvptx-registered-target
 
 // -flto causes a switch to llvm-bc object files.
-// RUN: %clangxx --target=x86_64-unknown-linux-gnu -nocudainc -nocudalib -ccc-print-phases -c %s -flto 2> %t
+// RUN: %clangxx --target=x86_64-unknown-linux-gnu --no-offload-new-driver -nocudainc -nocudalib -ccc-print-phases -c %s -flto 2> %t
 // RUN: FileCheck -check-prefix=CHECK-COMPILE-ACTIONS < %t %s
 //
 // CHECK-COMPILE-ACTIONS: 2: compiler, {1}, ir, (host-cuda)
 // CHECK-COMPILE-ACTIONS-NOT: lto-bc
 // CHECK-COMPILE-ACTIONS: 12: backend, {11}, lto-bc, (host-cuda)
 
-// RUN: %clangxx --target=x86_64-unknown-linux-gnu -nocudainc -nocudalib -ccc-print-phases %s -flto 2> %t
+// RUN: %clangxx --target=x86_64-unknown-linux-gnu --no-offload-new-driver -nocudainc -nocudalib -ccc-print-phases %s -flto 2> %t
 // RUN: FileCheck -check-prefix=CHECK-COMPILELINK-ACTIONS < %t %s
 //
 // CHECK-COMPILELINK-ACTIONS: 0: input, "{{.*}}lto.cu", cuda, (host-cuda)
@@ -29,7 +29,7 @@
 
 // llvm-bc and llvm-ll outputs need to match regular suffixes
 // (unfortunately).
-// RUN: %clangxx %s --target=x86_64-unknown-linux-gnu -nocudainc -nocudalib -flto -save-temps --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda -### 2> %t
+// RUN: %clangxx %s --target=x86_64-unknown-linux-gnu --no-offload-new-driver -nocudainc -nocudalib -flto -save-temps --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda -### 2> %t
 // RUN: FileCheck -check-prefix=CHECK-COMPILELINK-SUFFIXES < %t %s
 //
 // CHECK-COMPILELINK-SUFFIXES: "-o" "[[CPP:.*lto-host.*\.cui]]" "-x" "cuda" "{{.*}}lto.cu"
@@ -37,36 +37,36 @@
 // CHECK-COMPILELINK-SUFFIXES: "-o" "[[OBJ:.*lto-host.*\.o]]" {{.*}}[[BC]]"
 // CHECK-COMPILELINK-SUFFIXES: "{{.*}}a.{{(out|exe)}}" {{.*}}[[OBJ]]"
 
-// RUN: %clangxx --target=x86_64-unknown-linux-gnu %s -nocudainc -nocudalib -flto -S -### 2> %t
+// RUN: %clangxx --target=x86_64-unknown-linux-gnu %s --no-offload-new-driver -nocudainc -nocudalib -flto -S -### 2> %t
 // RUN: FileCheck -check-prefix=CHECK-COMPILE-SUFFIXES < %t %s
 //
 // CHECK-COMPILE-SUFFIXES: "-o" "{{.*}}lto.s" "-x" "cuda" "{{.*}}lto.cu"
 
-// RUN: not %clangxx --target=x86_64-unknown-linux-gnu -nocudainc -nocudalib %s -emit-llvm 2>&1 \
+// RUN: not %clangxx --target=x86_64-unknown-linux-gnu --no-offload-new-driver -nocudainc -nocudalib %s -emit-llvm 2>&1 \
 // RUN:    | FileCheck --check-prefix=LLVM-LINK %s
 // LLVM-LINK: -emit-llvm cannot be used when linking
 
 /// With ld.bfd or gold, link against LLVMgold.
 // RUN: %clangxx -nocudainc -nocudalib --target=x86_64-unknown-linux-gnu --offload-arch=sm_52 --sysroot=%S/Inputs/basic_cross_linux_tree %s \
-// RUN:   -fuse-ld=bfd -flto=thin -### 2>&1 | FileCheck --check-prefix=LLVMGOLD %s
+// RUN:   --no-offload-new-driver -fuse-ld=bfd -flto=thin -### 2>&1 | FileCheck --check-prefix=LLVMGOLD %s
 // RUN: %clangxx -nocudainc -nocudalib --target=x86_64-unknown-linux-gnu --offload-arch=sm_52 --sysroot=%S/Inputs/basic_cross_linux_tree %s \
-// RUN:   -fuse-ld=gold -flto=full -### 2>&1 | FileCheck --check-prefix=LLVMGOLD %s
+// RUN:   --no-offload-new-driver -fuse-ld=gold -flto=full -### 2>&1 | FileCheck --check-prefix=LLVMGOLD %s
 //
 // LLVMGOLD: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
 
 /// lld does not need LLVMgold.
 // RUN: %clangxx -nocudainc -nocudalib --target=x86_64-unknown-linux-gnu --offload-arch=sm_52 --sysroot=%S/Inputs/basic_cross_linux_tree %s \
-// RUN:   -fuse-ld=lld -flto=full -### 2>&1 | FileCheck --check-prefix=NO-LLVMGOLD %s
+// RUN:   --no-offload-new-driver -fuse-ld=lld -flto=full -### 2>&1 | FileCheck --check-prefix=NO-LLVMGOLD %s
 // RUN: %clangxx -nocudainc -nocudalib --target=x86_64-unknown-linux-gnu --offload-arch=sm_52 --sysroot=%S/Inputs/basic_cross_linux_tree %s \
-// RUN:   -fuse-ld=gold -flto=full -fno-lto -### 2>&1 | FileCheck --check-prefix=NO-LLVMGOLD %s
+// RUN:   --no-offload-new-driver -fuse-ld=gold -flto=full -fno-lto -### 2>&1 | FileCheck --check-prefix=NO-LLVMGOLD %s
 //
 // NO-LLVMGOLD-NOT: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}"
 
 // -flto passes along an explicit debugger tuning argument.
-// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: %clangxx -nocudainc -nocudalib --no-offload-new-driver \
 // RUN:          --target=x86_64-unknown-linux -### %s -flto -glldb --offload-arch=sm_52 --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda 2> %t
 // RUN: FileCheck -check-prefix=CHECK-TUNING-LLDB < %t %s
-// RUN: %clangxx -nocudainc -nocudalib \
+// RUN: %clangxx -nocudainc -nocudalib --no-offload-new-driver \
 // RUN:          --target=x86_64-unknown-linux -### %s -flto -g --offload-arch=sm_52 --cuda-path=%S/Inputs/CUDA_80/usr/local/cuda 2> %t
 // RUN: FileCheck -check-prefix=CHECK-NO-TUNING < %t %s
 //
diff --git a/clang/test/Driver/modules-print-library-module-manifest-path.cpp b/clang/test/Driver/modules-print-library-module-manifest-path.cpp
deleted file mode 100644
index 95bcc59ae23c2a7539967b7cf71e6ae35d077d3f..0000000000000000000000000000000000000000
--- a/clang/test/Driver/modules-print-library-module-manifest-path.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-// Test that -print-library-module-manifest-path finds the correct file.
-
-// FIXME: Enable on all platforms.
-
-// REQUIRES: x86-registered-target
-
-// RUN: rm -rf %t && split-file %s %t && cd %t
-// RUN: mkdir -p %t/Inputs/usr/lib/x86_64-linux-gnu
-// RUN: touch %t/Inputs/usr/lib/x86_64-linux-gnu/libc++.so
-
-// RUN: %clang -print-library-module-manifest-path \
-// RUN:     -stdlib=libc++ \
-// RUN:     --sysroot=%t/Inputs \
-// RUN:     --target=x86_64-linux-gnu 2>&1 \
-// RUN:   | FileCheck libcxx-no-module-json.cpp
-
-// RUN: touch %t/Inputs/usr/lib/x86_64-linux-gnu/modules.json
-// RUN: %clang -print-library-module-manifest-path \
-// RUN:     -stdlib=libc++ \
-// RUN:     --sysroot=%t/Inputs \
-// RUN:     --target=x86_64-linux-gnu 2>&1 \
-// RUN:   | FileCheck libcxx.cpp
-
-// RUN: %clang -print-library-module-manifest-path \
-// RUN:     -stdlib=libstdc++ \
-// RUN:     --sysroot=%t/Inputs \
-// RUN:     --target=x86_64-linux-gnu 2>&1 \
-// RUN:   | FileCheck libstdcxx.cpp
-
-//--- libcxx-no-module-json.cpp
-
-// CHECK: 
-
-//--- libcxx.cpp
-
-// CHECK: {{.*}}/Inputs/usr/lib/x86_64-linux-gnu{{/|\\}}modules.json
-
-//--- libstdcxx.cpp
-
-// CHECK: 
diff --git a/clang/test/Driver/netbsd.c b/clang/test/Driver/netbsd.c
index 73777e7a3e38fa34915947de6d7873e84567da34..1b7c674e18af6731942c8054647946402b5650dc 100644
--- a/clang/test/Driver/netbsd.c
+++ b/clang/test/Driver/netbsd.c
@@ -342,3 +342,10 @@
 // DRIVER-PASS-INCLUDES:      "-cc1" {{.*}}"-resource-dir" "[[RESOURCE:[^"]+]]"
 // DRIVER-PASS-INCLUDES-SAME: "-internal-isystem" "[[RESOURCE]]{{/|\\\\}}include"
 // DRIVER-PASS-INCLUDES-SAME: {{^}} "-internal-externc-isystem" "{{.*}}/usr/include"
+
+// Check that the -X and --no-relax flags are passed to the linker on riscv
+// RUN: %clang --target=riscv32-unknown-netbsd -mno-relax -### %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=RISCV-FLAGS %s
+// RUN: %clang --target=riscv64-unknown-netbsd -mno-relax -### %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=RISCV-FLAGS %s
+// RISCV-FLAGS: "-X" "--no-relax"
diff --git a/clang/test/Driver/openbsd.c b/clang/test/Driver/openbsd.c
index 68d33c5dd01e227430ff748d18b9577222504e97..672cd3adf44a691552457a102d3aef34f5d48e6a 100644
--- a/clang/test/Driver/openbsd.c
+++ b/clang/test/Driver/openbsd.c
@@ -127,10 +127,10 @@
 // UNWIND-TABLES: "-funwind-tables=2"
 // NO-UNWIND-TABLES-NOT: "-funwind-tables=2"
 
-// Check that the -X flag is passed to the linker on riscv64
-// RUN: %clang --target=riscv64-unknown-openbsd -### %s 2>&1 \
-// RUN:   | FileCheck -check-prefix=CHECK-RISCV64-FLAGS %s
-// CHECK-RISCV64-FLAGS: "-X"
+// Check that the -X and --no-relax flags are passed to the linker on riscv64
+// RUN: %clang --target=riscv64-unknown-openbsd -mno-relax -### %s 2>&1 \
+// RUN:   | FileCheck -check-prefix=RISCV64-FLAGS %s
+// RISCV64-FLAGS: "-X" "--no-relax"
 
 // Check passing LTO flags to the linker
 // RUN: %clang --target=amd64-unknown-openbsd -flto -### %s 2>&1 \
diff --git a/clang/test/Driver/openmp-offload-gpu.c b/clang/test/Driver/openmp-offload-gpu.c
index f7b06c9ec595809435da68f29629f84741226771..d705be44e595d80f07ad32ef8ad09f77362bf2b7 100644
--- a/clang/test/Driver/openmp-offload-gpu.c
+++ b/clang/test/Driver/openmp-offload-gpu.c
@@ -233,7 +233,7 @@
 // CHECK: "-cc1" "-triple" "x86_64-unknown-linux-gnu"{{.*}}"-emit-llvm-bc"{{.*}}"-x" "c"
 // CHECK: "-cc1" "-triple" "nvptx64-nvidia-cuda" "-aux-triple" "x86_64-unknown-linux-gnu"{{.*}}"-target-cpu" "sm_52"
 // CHECK: "-cc1" "-triple" "x86_64-unknown-linux-gnu"{{.*}}"-emit-obj"
-// CHECK: clang-linker-wrapper{{.*}}"--"{{.*}} "-o" "a.out"
+// CHECK: clang-linker-wrapper{{.*}} "-o" "a.out"
 
 // RUN:   %clang -ccc-print-phases --target=x86_64-unknown-linux-gnu -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -Xopenmp-target=nvptx64-nvidia-cuda -march=sm_52 %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=CHECK-PHASES %s
diff --git a/clang/test/Driver/openmp-offload-infer.c b/clang/test/Driver/openmp-offload-infer.c
index 9a949f52e2e97d44e6894e6b8b70b02c64a4776c..50333293eb7dbdd16b39364c633b91f306100480 100644
--- a/clang/test/Driver/openmp-offload-infer.c
+++ b/clang/test/Driver/openmp-offload-infer.c
@@ -13,7 +13,7 @@
 // CHECK: "-cc1" "-triple" "amdgcn-amd-amdhsa" "-aux-triple" "x86_64-unknown-linux-gnu"{{.*}}"-target-cpu" "gfx803"
 // CHECK: "-cc1" "-triple" "nvptx64-nvidia-cuda" "-aux-triple" "x86_64-unknown-linux-gnu"{{.*}}"-target-cpu" "sm_52"
 // CHECK: "-cc1" "-triple" "x86_64-unknown-linux-gnu"{{.*}}"-emit-obj"
-// CHECK: clang-linker-wrapper{{.*}}"--"{{.*}} "-o" "a.out"
+// CHECK: clang-linker-wrapper{{.*}} "-o" "a.out"
 
 // RUN:   %clang -### --target=x86_64-unknown-linux-gnu -ccc-print-bindings -fopenmp=libomp \
 // RUN:     --offload-arch=sm_70 --offload-arch=gfx908:sramecc+:xnack- \
diff --git a/clang/test/Driver/range.c b/clang/test/Driver/range.c
index 49116df2f4480ed002fca71a3ec934814dbcaef9..2d1fd7f9f1a9d53d573b30eed2b275263e704581 100644
--- a/clang/test/Driver/range.c
+++ b/clang/test/Driver/range.c
@@ -12,12 +12,23 @@
 // RUN: %clang -### -target x86_64 -fcx-fortran-rules -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=FRTRN %s
 
+// RUN: %clang -### -target x86_64 -fcx-fortran-rules -c %s 2>&1 \
+// RUN:   -fno-cx-fortran-rules | FileCheck --check-prefix=FULL %s
+
+// RUN: %clang -### -target x86_64 -fcx-fortran-rules -fno-cx-limited-range \
+// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN3 %s
+
 // RUN: %clang -### -target x86_64 -fno-cx-fortran-rules -c %s 2>&1 \
 // RUN:   | FileCheck  %s
 
-// RUN: %clang -### -target x86_64 -fcx-limited-range \
-// RUN: -fcx-fortran-rules -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefix=WARN1 %s
+// RUN: %clang -### -target x86_64 -fcx-limited-range -fcx-fortran-rules \
+// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN1 %s
+
+// RUN: %clang -### -target x86_64 -fcx-limited-range -fno-cx-fortran-rules \
+// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN4 %s
+
+// RUN: %clang -### -target x86_64 -fcx-limited-range -fno-cx-limited-range \
+// RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s
 
 // RUN: %clang -### -target x86_64 -fcx-fortran-rules \
 // RUN: -fcx-limited-range  -c %s 2>&1 \
@@ -32,8 +43,8 @@
 // RUN: %clang -### -target x86_64 -fcx-limited-range -ffast-math -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=LMTD %s
 
-// RUN: %clang -### -target x86_64 -ffast-math -fno-cx-limited-range -c %s 2>&1 \
-// RUN:   | FileCheck --check-prefix=FULL %s
+// RUN: %clang -### -target x86_64 -ffast-math -fno-cx-limited-range \
+// RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s
 
 // RUN: %clang -### -Werror -target x86_64 -fcx-limited-range -c %s 2>&1 \
 // RUN:   | FileCheck --check-prefix=LMTD %s
@@ -50,3 +61,5 @@
 // CHECK-NOT: -complex-range=fortran
 // WARN1: warning: overriding '-fcx-limited-range' option with '-fcx-fortran-rules' [-Woverriding-option]
 // WARN2: warning: overriding '-fcx-fortran-rules' option with '-fcx-limited-range' [-Woverriding-option]
+// WARN3: warning: overriding '-fcx-fortran-rules' option with '-fno-cx-limited-range' [-Woverriding-option]
+// WARN4: warning: overriding '-fcx-limited-range' option with '-fno-cx-fortran-rules' [-Woverriding-option]
diff --git a/clang/test/Driver/riscv-arch.c b/clang/test/Driver/riscv-arch.c
index c9e984e07cbea985ba084410e865484cc7bdfaf4..8399b4e97f86d52fe0d9ba5015677e2b6fd01b09 100644
--- a/clang/test/Driver/riscv-arch.c
+++ b/clang/test/Driver/riscv-arch.c
@@ -306,7 +306,7 @@
 // RUN: not %clang --target=riscv32-unknown-elf -march=rv32ist2p0 -### %s \
 // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-SMINOR0 %s
 // RV32-SMINOR0: error: invalid arch name 'rv32ist2p0',
-// RV32-SMINOR0: unsupported version number 2.0 for extension 'st'
+// RV32-SMINOR0: unsupported standard supervisor-level extension 'st'
 
 // RUN: not %clang --target=riscv32-unknown-elf -march=rv32ixabc_ -### %s \
 // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-XSEP %s
@@ -397,7 +397,7 @@
 
 // RUN: not %clang --target=riscv32-unknown-elf -march=rv32izbb1p0zbs1p0 -menable-experimental-extensions -### %s \
 // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-ZBB-ZBS-UNDERSCORE %s
-// RV32-EXPERIMENTAL-ZBB-ZBS-UNDERSCORE: error: invalid arch name 'rv32izbb1p0zbs1p0', unsupported version number 1.0 for extension 'zbb1p0zbs'
+// RV32-EXPERIMENTAL-ZBB-ZBS-UNDERSCORE: error: invalid arch name 'rv32izbb1p0zbs1p0', unsupported standard user-level extension 'zbb1p0zbs'
 
 // RUN: %clang --target=riscv32-unknown-elf -march=rv32izba1p0 -### %s \
 // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-ZBA %s
diff --git a/clang/test/Driver/split-debug.c b/clang/test/Driver/split-debug.c
index 968f33b4cc035c555b043cbb7aed7a6a343b8bf3..57f3989ed7b5103dbc9aac76741617552f70c919 100644
--- a/clang/test/Driver/split-debug.c
+++ b/clang/test/Driver/split-debug.c
@@ -124,3 +124,13 @@
 // G1_NOSPLIT: "-debug-info-kind=line-tables-only"
 // G1_NOSPLIT-NOT: "-split-dwarf-file"
 // G1_NOSPLIT-NOT: "-split-dwarf-output"
+
+/// Do not generate -ggnu-pubnames for -glldb
+// RUN: %clang -### -c -target x86_64 -gsplit-dwarf -g -glldb %s 2>&1 | FileCheck %s --check-prefixes=GLLDBSPLIT
+
+// GLLDBSPLIT-NOT: "-ggnu-pubnames"
+
+/// Generate -ggnu-pubnames for -glldb when it is explicitly enabled
+// RUN: %clang -### -c -target x86_64 -gsplit-dwarf -g -glldb -ggnu-pubnames %s 2>&1 | FileCheck %s --check-prefixes=GLLDBSPLIT2
+
+// GLLDBSPLIT2: "-ggnu-pubnames"
diff --git a/clang/test/Driver/thinlto.cu b/clang/test/Driver/thinlto.cu
index d4f265baf3708fe509e0717a47b03e1cd88ed441..7c51a5194e0b76be328cfddda56135820f4eacc5 100644
--- a/clang/test/Driver/thinlto.cu
+++ b/clang/test/Driver/thinlto.cu
@@ -2,14 +2,14 @@
 // REQUIRES: nvptx-registered-target
 
 // -flto=thin causes a switch to llvm-bc object files.
-// RUN: %clangxx -ccc-print-phases -nocudainc -nocudalib -c %s -flto=thin 2> %t
+// RUN: %clangxx -ccc-print-phases --no-offload-new-driver -nocudainc -nocudalib -c %s -flto=thin 2> %t
 // RUN: FileCheck -check-prefix=CHECK-COMPILE-ACTIONS < %t %s
 //
 // CHECK-COMPILE-ACTIONS: 2: compiler, {1}, ir, (host-cuda)
 // CHECK-COMPILE-ACTIONS-NOT: lto-bc
 // CHECK-COMPILE-ACTIONS: 12: backend, {11}, lto-bc, (host-cuda)
 
-// RUN: %clangxx -ccc-print-phases -nocudainc -nocudalib %s -flto=thin 2> %t
+// RUN: %clangxx -ccc-print-phases --no-offload-new-driver -nocudainc -nocudalib %s -flto=thin 2> %t
 // RUN: FileCheck -check-prefix=CHECK-COMPILELINK-ACTIONS < %t %s
 //
 // CHECK-COMPILELINK-ACTIONS: 0: input, "{{.*}}thinlto.cu", cuda, (host-cuda)
diff --git a/clang/test/InstallAPI/cpp.test b/clang/test/InstallAPI/cpp.test
new file mode 100644
index 0000000000000000000000000000000000000000..4817899095302b2ca46370abc87d4bb78da3449f
--- /dev/null
+++ b/clang/test/InstallAPI/cpp.test
@@ -0,0 +1,530 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json
+
+// Invoke C++ with no-rtti.
+// RUN: clang-installapi -target arm64-apple-macos13.1 \
+// RUN: -I%t/usr/include -I%t/usr/local/include -x c++ \
+// RUN: -install_name @rpath/lib/libcpp.dylib -fno-rtti \
+// RUN: %t/inputs.json -o %t/no-rtti.tbd 2>&1 | FileCheck %s --allow-empty
+
+// RUN: llvm-readtapi -compare %t/no-rtti.tbd \
+// RUN: %t/expected-no-rtti.tbd 2>&1 | FileCheck %s --allow-empty
+
+// Invoke C++ with rtti.
+// RUN: clang-installapi -target arm64-apple-macos13.1 \
+// RUN: -I%t/usr/include -I%t/usr/local/include -x c++ \
+// RUN: -install_name @rpath/lib/libcpp.dylib -frtti \
+// RUN: %t/inputs.json -o %t/rtti.tbd 2>&1 | FileCheck %s --allow-empty
+// RUN: llvm-readtapi -compare %t/rtti.tbd \
+// RUN: %t/expected-rtti.tbd 2>&1 | FileCheck %s --allow-empty
+
+// CHECK-NOT: error: 
+// CHECK-NOT: warning: 
+
+//--- usr/include/basic.h
+#ifndef CPP_H
+#define CPP_H
+
+inline int foo(int x) { return x + 1; }
+
+extern int bar(int x) { return x + 1; }
+
+inline int baz(int x) {
+  static const int a[] = {1, 2, 3};
+  return a[x];
+}
+
+extern "C" {
+  int cFunc(const char*);
+}
+
+class Bar {
+public:
+  static const int x = 0;
+  static int y;
+
+  inline int func1(int x) { return x + 2; }
+  inline int func2(int x);
+  int func3(int x);
+};
+
+class __attribute__((visibility("hidden"))) BarI {
+  static const int x = 0;
+  static int y;
+
+  inline int func1(int x) { return x + 2; }
+  inline int func2(int x);
+  int func3(int x);
+};
+
+int Bar::func2(int x) { return x + 3; }
+inline int Bar::func3(int x) { return x + 4; }
+
+int BarI::func2(int x) { return x + 3; }
+inline int BarI::func3(int x) { return x + 4; }
+#endif
+
+//--- usr/local/include/vtable.h
+// Simple test class with no virtual functions. There should be no vtable or
+// RTTI.
+namespace test1 {
+class Simple {
+public:
+  void run();
+};
+} // end namespace test1
+
+// Simple test class with virtual function. There should be an external vtable
+// and RTTI.
+namespace test2 {
+class Simple {
+public:
+  virtual void run();
+};
+} // end namespace test2
+
+// Abstract class with no sub classes. There should be no vtable or RTTI.
+namespace test3 {
+class Abstract {
+public:
+  virtual ~Abstract() {}
+  virtual void run() = 0;
+};
+} // end namespace test3
+
+// Abstract base class with a sub class. There should be weak-def RTTI for the
+// abstract base class.
+// The sub-class should have vtable and RTTI.
+namespace test4 {
+class Base {
+public:
+  virtual ~Base() {}
+  virtual void run() = 0;
+};
+
+class Sub : public Base {
+public:
+  void run() override;
+};
+} // end namespace test4
+
+// Abstract base class with a sub class. Same as above, but with a user defined
+// inlined destructor.
+namespace test5 {
+class Base {
+public:
+  virtual ~Base() {}
+  virtual void run() = 0;
+};
+
+class Sub : public Base {
+public:
+  virtual ~Sub() {}
+  void run() override;
+};
+} // end namespace test5
+
+// Abstract base class with a sub class. Same as above, but with a different
+// inlined key method.
+namespace test6 {
+class Base {
+public:
+  virtual ~Base() {}
+  virtual void run() = 0;
+};
+
+class Sub : public Base {
+public:
+  virtual void foo() {}
+  void run() override;
+};
+} // end namespace test6
+
+// Abstract base class with a sub class. Overloaded method is implemented
+// inline. No vtable or RTTI.
+namespace test7 {
+class Base {
+public:
+  virtual ~Base() {}
+  virtual bool run() = 0;
+};
+
+class Sub : public Base {
+public:
+  bool run() override { return true; }
+};
+} // end namespace test7
+
+// Abstract base class with a sub class. Overloaded method has no inline
+// attribute and is recognized as key method,
+// but is later implemented inline. Weak-def RTTI only.
+namespace test8 {
+class Base {
+public:
+  virtual ~Base() {}
+  virtual void run() = 0;
+};
+
+class Sub : public Base {
+public:
+  void run() override;
+};
+
+inline void Sub::run() {}
+} // end namespace test8
+
+namespace test9 {
+class Base {
+public:
+  virtual ~Base() {}
+  virtual void run1() = 0;
+  virtual void run2() = 0;
+};
+
+class Sub : public Base {
+public:
+  void run1() override {}
+  void run2() override;
+};
+
+inline void Sub::run2() {}
+} // end namespace test9
+
+namespace test10 {
+class Base {
+public:
+  virtual ~Base() {}
+  virtual void run1() = 0;
+  virtual void run2() = 0;
+};
+
+class Sub : public Base {
+public:
+  void run1() override {}
+  inline void run2() override;
+};
+
+void Sub::run2() {}
+} // end namespace test10
+
+namespace test11 {
+class Base {
+public:
+  virtual ~Base() {}
+  virtual void run1() = 0;
+  virtual void run2() = 0;
+  virtual void run3() = 0;
+};
+
+class Sub : public Base {
+public:
+  void run1() override {}
+  void run2() override;
+  void run3() override;
+};
+
+inline void Sub::run2() {}
+} // end namespace test11
+
+namespace test12 {
+template  class Simple {
+public:
+  virtual void foo() {}
+};
+extern template class Simple;
+} // end namespace test12
+
+namespace test13 {
+class Base {
+public:
+  virtual ~Base() {}
+  virtual void run1() = 0;
+  virtual void run2() {};
+  virtual void run3(); // key function.
+};
+
+class Sub : public Base {
+public:
+  void run1() override {}
+  void run2() override {}
+};
+
+} // end namespace test13
+
+namespace test14 {
+
+class __attribute__((visibility("hidden"))) Base
+{
+public:
+    Base() {}
+    virtual ~Base(); // keyfunction.
+    virtual void run1() const = 0;
+};
+
+class Sub : public Base
+{
+public:
+    Sub();
+    virtual ~Sub();
+    virtual void run1() const;
+    void run2() const {}
+};
+
+} // end namespace test14
+
+namespace test15 {
+
+class Base {
+public:
+  virtual ~Base() {}
+  virtual void run() {};
+};
+
+class Base1 {
+public:
+  virtual ~Base1() {}
+  virtual void run1() {};
+};
+
+class Sub : public Base, public Base1 {
+public:
+  Sub() {}
+  ~Sub();
+  void run() override;
+  void run1() override;
+};
+
+class Sub1 : public Base, public Base1 {
+public:
+  Sub1() {}
+  ~Sub1() = default;
+  void run() override;
+  void run1() override;
+};
+
+} // end namespace test15
+
+//--- usr/local/include/templates.h
+#ifndef TEMPLATES_H
+#define TEMPLATES_H
+
+namespace templates {
+
+// Full specialization.
+template  int foo1(T a) { return 1; }
+template <> int foo1(int a);
+extern template int foo1(short a);
+
+template  int foo2(T a);
+
+// Partial specialization.
+template  class Partial {
+  static int run(A a, B b) { return a + b; }
+};
+
+template  class Partial {
+  static int run(A a, int b) { return a - b; }
+};
+
+template  class Foo {
+public:
+  Foo();
+  ~Foo();
+};
+
+template  class Bar {
+public:
+  Bar();
+  ~Bar() {}
+
+  inline int bazinga() { return 7; }
+};
+
+extern template class Bar;
+
+class Bazz {
+public:
+  Bazz() {}
+
+  template  int buzz(T a);
+
+  float implicit() const { return foo1(0.0f); }
+};
+
+template  int Bazz::buzz(T a) { return sizeof(T); }
+
+template  struct S { static int x; };
+
+template  int S::x = 0;
+
+} // end namespace templates.
+
+#endif
+
+
+//--- inputs.json.in
+{
+  "headers": [ {
+    "path" : "DSTROOT/usr/include/basic.h",
+    "type" : "public"
+  }, 
+  {
+    "path" : "DSTROOT/usr/local/include/vtable.h",
+    "type" : "private"
+  },
+  {
+    "path" : "DSTROOT/usr/local/include/templates.h",
+    "type" : "private"
+  }
+  ],
+  "version": "3"
+}
+
+//--- expected-no-rtti.tbd
+{
+  "main_library": {
+    "compatibility_versions": [
+      {
+        "version": "0"
+      }
+    ],
+    "current_versions": [
+      {
+        "version": "0"
+      }
+    ],
+    "exported_symbols": [
+      {
+        "data": {
+          "global": [
+            "__ZTVN6test143SubE", "__ZTVN6test113SubE", "__ZTVN5test26SimpleE",
+            "__ZTVN5test53SubE", "__ZTVN6test154Sub1E", "__ZTVN6test153SubE",
+            "__ZN3Bar1yE", "__ZTVN5test43SubE", "__ZTVN5test63SubE",
+            "__ZTVN6test134BaseE"
+          ],
+          "weak": [
+            "__ZTVN6test126SimpleIiEE"
+          ]
+        },
+        "text": {
+          "global": [
+            "__ZN6test153Sub3runEv", "__ZN6test154Sub13runEv",
+            "__Z3bari", "__ZThn8_N6test153SubD1Ev",
+            "__ZNK6test143Sub4run1Ev", "__ZN6test154Sub14run1Ev",
+            "__ZThn8_N6test153Sub4run1Ev", "__ZN6test143SubD1Ev",
+            "__ZN6test134Base4run3Ev", "__ZN5test16Simple3runEv",
+            "__ZN5test43Sub3runEv", "__ZN6test113Sub4run3Ev", "__ZN6test153SubD2Ev",
+            "__ZN5test53Sub3runEv", "__ZN6test153SubD1Ev", "__ZN6test143SubC1Ev",
+            "__ZN9templates4foo1IiEEiT_", "__ZN6test143SubC2Ev", "__ZN5test63Sub3runEv",
+            "__ZN5test26Simple3runEv", "__ZN6test153SubD0Ev",
+            "__ZN6test143SubD2Ev", "__ZN6test153Sub4run1Ev", "__ZN6test143SubD0Ev",
+            "__ZThn8_N6test153SubD0Ev", "__ZThn8_N6test154Sub14run1Ev", "_cFunc"
+          ],
+          "weak": [
+            "__ZN9templates3BarIiED2Ev", "__ZN9templates3BarIiEC2Ev",
+            "__ZN9templates3BarIiEC1Ev", "__ZN9templates3BarIiED1Ev",
+            "__ZN6test126SimpleIiE3fooEv", "__ZN9templates3BarIiE7bazingaEv",
+            "__ZN9templates4foo1IsEEiT_"
+          ]
+        }
+      }
+    ],
+    "flags": [
+      {
+        "attributes": [
+          "not_app_extension_safe"
+        ]
+      }
+    ],
+    "install_names": [
+      {
+        "name": "@rpath/lib/libcpp.dylib"
+      }
+    ],
+    "target_info": [
+      {
+        "min_deployment": "13.1",
+        "target": "arm64-macos"
+      }
+    ]
+  },
+  "tapi_tbd_version": 5
+}
+
+//--- expected-rtti.tbd
+{
+  "main_library": {
+    "compatibility_versions": [
+      {
+        "version": "0"
+      }
+    ],
+    "current_versions": [
+      {
+        "version": "0"
+      }
+    ],
+    "exported_symbols": [
+      {
+        "data": {
+          "global": [
+            "__ZTVN6test143SubE", "__ZTIN5test63SubE", "__ZTSN5test26SimpleE",
+            "__ZTIN6test153SubE", "__ZTVN6test113SubE", "__ZTIN5test43SubE",
+            "__ZTIN6test134BaseE", "__ZTVN5test26SimpleE", "__ZTIN5test26SimpleE",
+            "__ZTSN6test134BaseE", "__ZTVN6test154Sub1E", "__ZTVN5test43SubE",
+            "__ZTVN5test63SubE", "__ZTSN5test43SubE", "__ZTSN6test113SubE",
+            "__ZTIN6test154Sub1E", "__ZTSN6test153SubE", "__ZTSN5test63SubE",
+            "__ZTSN6test154Sub1E", "__ZTIN6test113SubE", "__ZTSN6test143SubE",
+            "__ZTVN5test53SubE", "__ZTIN6test143SubE", "__ZTVN6test153SubE",
+            "__ZTIN5test53SubE", "__ZN3Bar1yE", "__ZTVN6test134BaseE",
+            "__ZTSN5test53SubE"
+          ],
+          "weak": [
+            "__ZTVN6test126SimpleIiEE"
+          ]
+        },
+        "text": {
+          "global": [
+            "__ZN6test154Sub13runEv", "__ZN6test153Sub3runEv", "__ZNK6test143Sub4run1Ev",
+            "__ZN6test134Base4run3Ev", "__ZN5test16Simple3runEv", "__ZN6test153SubD2Ev",
+            "__ZN6test143SubC2Ev", "__ZN5test63Sub3runEv", "__ZN6test153SubD0Ev", 
+            "__ZN6test143SubD2Ev", "__ZThn8_N6test154Sub14run1Ev",
+            "__ZThn8_N6test153SubD0Ev", "__Z3bari", "__ZThn8_N6test153SubD1Ev",
+            "__ZN6test154Sub14run1Ev", "__ZThn8_N6test153Sub4run1Ev",
+            "__ZN6test143SubD1Ev", "__ZN5test43Sub3runEv",
+            "__ZN6test113Sub4run3Ev", "__ZN5test53Sub3runEv", "__ZN6test143SubC1Ev",
+            "__ZN6test153SubD1Ev", "__ZN9templates4foo1IiEEiT_", "__ZN5test26Simple3runEv",
+            "__ZN6test153Sub4run1Ev", "__ZN6test143SubD0Ev", "_cFunc"
+          ],
+          "weak": [
+            "__ZN9templates3BarIiEC2Ev", "__ZN9templates3BarIiEC1Ev",
+            "__ZN9templates3BarIiED1Ev", "__ZN6test126SimpleIiE3fooEv",
+            "__ZN9templates4foo1IsEEiT_", "__ZN9templates3BarIiED2Ev",
+            "__ZN9templates3BarIiE7bazingaEv"
+          ]
+        }
+      }
+    ],
+    "flags": [
+      {
+        "attributes": [
+          "not_app_extension_safe"
+        ]
+      }
+    ],
+    "install_names": [
+      {
+        "name": "@rpath/lib/libcpp.dylib"
+      }
+    ],
+    "target_info": [
+      {
+        "min_deployment": "13.1",
+        "target": "arm64-macos"
+      }
+    ]
+  },
+  "tapi_tbd_version": 5
+}
+
diff --git a/clang/test/InstallAPI/functions.test b/clang/test/InstallAPI/functions.test
new file mode 100644
index 0000000000000000000000000000000000000000..527965303cb351f4a8422e1ced40cf502c401f10
--- /dev/null
+++ b/clang/test/InstallAPI/functions.test
@@ -0,0 +1,78 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s|DSTROOT|%/t|g" %t/inputs.json.in > %t/inputs.json
+
+// RUN: clang-installapi -target arm64-apple-macos13.1 \
+// RUN: -I%t/usr/include -I%t/usr/local/include \
+// RUN: -install_name @rpath/lib/libfunctions.dylib \
+// RUN: %t/inputs.json -o %t/outputs.tbd 2>&1 | FileCheck %s --allow-empty
+// RUN: llvm-readtapi -compare %t/outputs.tbd %t/expected.tbd 2>&1 | FileCheck %s --allow-empty
+
+// CHECK-NOT: error: 
+// CHECK-NOT: warning: 
+
+//--- usr/include/functions.h
+inline int inlined_func(void) { return 1;}
+int public(int a);
+
+//--- usr/local/include/private_functions.h
+__attribute__((visibility("hidden")))
+void hidden(void);
+
+//--- inputs.json.in
+{
+  "headers": [ {
+    "path" : "DSTROOT/usr/include/functions.h",
+    "type" : "public"
+  }, 
+  {
+    "path" : "DSTROOT/usr/local/include/private_functions.h",
+    "type" : "private"
+  }
+  ],
+  "version": "3"
+}
+
+//--- expected.tbd
+{
+  "main_library": {
+    "compatibility_versions": [
+      {
+        "version": "0"
+      }
+    ],
+    "current_versions": [
+      {
+        "version": "0"
+      }
+    ],
+    "exported_symbols": [
+      {
+        "text": {
+          "global": [
+            "_public"
+          ]
+        }
+      }
+    ],
+    "flags": [
+      {
+        "attributes": [
+          "not_app_extension_safe"
+        ]
+      }
+    ],
+    "install_names": [
+      {
+        "name": "@rpath/lib/libfunctions.dylib"
+      }
+    ],
+    "target_info": [
+      {
+        "min_deployment": "13.1",
+        "target": "arm64-macos"
+      }
+    ]
+  },
+  "tapi_tbd_version": 5
+}
diff --git a/clang/test/InstallAPI/objcclasses.test b/clang/test/InstallAPI/objcclasses.test
index d32291c64c472d0556042ec19ecad285926967e3..7b73dffbe9208b357854c18e8e7bd856e8076795 100644
--- a/clang/test/InstallAPI/objcclasses.test
+++ b/clang/test/InstallAPI/objcclasses.test
@@ -20,19 +20,68 @@
 @end
 
 __attribute__((visibility("hidden")))
-@interface Hidden 
+@interface Hidden
+@end
+
+__attribute__((visibility("hidden")))
+@interface HiddenWithIvars {
+@public 
+char _ivar;
+}
 @end
 
 __attribute__((objc_exception))
 @interface Exception 
 @end
 
+@interface PublicClass : Visible  {
+@package 
+  int _internal;
+@protected
+  int _external;
+@private
+  int private;
+@public
+char _public;
+}
+@end
+
+
+//--- Foo.framework/PrivateHeaders/Foo_Private.h
+#import 
+
+@interface ClassWithIvars : Visible  {
+  char _ivar1;
+  char _ivar2;
+@private
+  int _privateIVar;
+@protected
+  int _externalIVar;
+@package 
+  int _internalIVar;
+}
+@end
+
+@interface Exception () {
+@public 
+  char _ivarFromExtension;
+@private 
+  int _privateIvarFromExtension;
+}
+@end
+
+
 //--- inputs.json.in
 {
   "headers": [ {
     "path" : "DSTROOT/Foo.framework/Headers/Foo.h",
     "type" : "public"
-  }],
+  }, 
+  {
+    "path" : "DSTROOT/Foo.framework/PrivateHeaders/Foo_Private.h",
+    "type" : "private"
+  }
+  ],
   "version": "3"
 }
 
@@ -53,11 +102,21 @@ __attribute__((objc_exception))
       {
         "data": {
           "objc_class": [
+            "PublicClass",
             "Exception",
-            "Visible"
+            "Visible",
+            "ClassWithIvars"
           ],
           "objc_eh_type": [
             "Exception"
+          ],
+          "objc_ivar": [
+            "Exception._ivarFromExtension",
+            "ClassWithIvars._ivar2",
+            "PublicClass._external",
+            "ClassWithIvars._ivar1",
+            "ClassWithIvars._externalIVar",
+            "PublicClass._public"
           ]
         }
       }
diff --git a/clang/test/Interpreter/execute-stmts.cpp b/clang/test/Interpreter/execute-stmts.cpp
index 2d4c17e0c91e661a5f622459e9ba775ea8f38bd6..433c6811777dac2289850bf7d78549b22e6d1893 100644
--- a/clang/test/Interpreter/execute-stmts.cpp
+++ b/clang/test/Interpreter/execute-stmts.cpp
@@ -9,7 +9,6 @@
 //CODEGEN-CHECK-COUNT-2: define internal void @__stmts__
 //CODEGEN-CHECK-NOT: define internal void @__stmts__
 
-
 extern "C" int printf(const char*,...);
 
 template  T call() { printf("called\n"); return T(); }
@@ -41,3 +40,26 @@ for (; i > 4; --i) { printf("i = %d\n", i); };
 
 int j = i; printf("j = %d\n", j);
 // CHECK-NEXT: j = 4
+
+{i = 0; printf("i = %d (global scope)\n", i);}
+// CHECK-NEXT: i = 0
+
+while (int i = 1) { printf("i = %d (while condition)\n", i--); break; }
+// CHECK-NEXT: i = 1
+
+if (int i = 2) printf("i = %d (if condition)\n", i);
+// CHECK-NEXT: i = 2
+
+switch (int i = 3) { default: printf("i = %d (switch condition)\n", i); }
+// CHECK-NEXT: i = 3
+
+for (int i = 4; i > 3; --i) printf("i = %d (for-init)\n", i);
+// CHECK-NEXT: i = 4
+
+for (const auto &i : "5") printf("i = %c (range-based for-init)\n", i);
+// CHECK-NEXT: i = 5
+
+int *aa=nullptr;
+if (auto *b=aa) *b += 1;
+while (auto *b=aa) ;
+for (auto *b=aa; b; *b+=1) ;
diff --git a/clang/test/Lexer/cxx-features.cpp b/clang/test/Lexer/cxx-features.cpp
index 2650a3a82252ba257d9bffe164c157d0903a629e..9496746c6fd663e5a43bc8e0215f2c3fc289607a 100644
--- a/clang/test/Lexer/cxx-features.cpp
+++ b/clang/test/Lexer/cxx-features.cpp
@@ -45,7 +45,7 @@
 #endif
 
 
-#if check(implicit_move, 0, 0, 0, 0, 0, 202011, 202011)
+#if check(implicit_move, 0, 0, 0, 0, 0, 202207, 202207)
 #error "wrong value for __cpp_implicit_move"
 #endif
 
diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index 1528388e3298ebcc7b3b5e9f3674de582bb8d174..ec84ebdc6abe7b494931e6f6bf6031170a52cd83 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -19,7 +19,6 @@
 // CHECK-NEXT: ArcWeakrefUnavailable (SubjectMatchRule_objc_interface)
 // CHECK-NEXT: ArmBuiltinAlias (SubjectMatchRule_function)
 // CHECK-NEXT: AssumeAligned (SubjectMatchRule_objc_method, SubjectMatchRule_function)
-// CHECK-NEXT: Assumption (SubjectMatchRule_function, SubjectMatchRule_objc_method)
 // CHECK-NEXT: Availability ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_implementation, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable))
 // CHECK-NEXT: AvailableOnlyInDefaultEvalMethod (SubjectMatchRule_type_alias)
 // CHECK-NEXT: BPFPreserveAccessIndex (SubjectMatchRule_record)
@@ -127,6 +126,7 @@
 // CHECK-NEXT: NoThrow (SubjectMatchRule_hasType_functionType)
 // CHECK-NEXT: NoUwtable (SubjectMatchRule_hasType_functionType)
 // CHECK-NEXT: NotTailCalled (SubjectMatchRule_function)
+// CHECK-NEXT: OMPAssume (SubjectMatchRule_function, SubjectMatchRule_objc_method)
 // CHECK-NEXT: OSConsumed (SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: OSReturnsNotRetained (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_variable_is_parameter)
 // CHECK-NEXT: OSReturnsRetained (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_variable_is_parameter)
diff --git a/clang/test/Misc/target-invalid-cpu-note.c b/clang/test/Misc/target-invalid-cpu-note.c
index ef2c1c0cfd3d296cedca1ebac7cc7c73b3b8c38a..b65a8fb057ee53f51ae1b9f75d20b76d37372d01 100644
--- a/clang/test/Misc/target-invalid-cpu-note.c
+++ b/clang/test/Misc/target-invalid-cpu-note.c
@@ -1,15 +1,15 @@
 // Use CHECK-NEXT instead of multiple CHECK-SAME to ensure we will fail if there is anything extra in the output.
 // RUN: not %clang_cc1 -triple armv5--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix ARM
 // ARM: error: unknown target CPU 'not-a-cpu'
-// ARM-NEXT: note: valid target CPU values are: arm8, arm810, strongarm, strongarm110, strongarm1100, strongarm1110, arm7tdmi, arm7tdmi-s, arm710t, arm720t, arm9, arm9tdmi, arm920, arm920t, arm922t, arm940t, ep9312, arm10tdmi, arm1020t, arm9e, arm946e-s, arm966e-s, arm968e-s, arm10e, arm1020e, arm1022e, arm926ej-s, arm1136j-s, arm1136jf-s, mpcore, mpcorenovfp, arm1176jz-s, arm1176jzf-s, arm1156t2-s, arm1156t2f-s, cortex-m0, cortex-m0plus, cortex-m1, sc000, cortex-a5, cortex-a7, cortex-a8, cortex-a9, cortex-a12, cortex-a15, cortex-a17, krait, cortex-r4, cortex-r4f, cortex-r5, cortex-r7, cortex-r8, cortex-r52, sc300, cortex-m3, cortex-m4, cortex-m7, cortex-m23, cortex-m33, cortex-m35p, cortex-m55, cortex-m85, cortex-m52, cortex-a32, cortex-a35, cortex-a53, cortex-a55, cortex-a57, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78c, cortex-a710, cortex-x1, cortex-x1c, neoverse-n1, neoverse-n2, neoverse-v1, cyclone, exynos-m3, exynos-m4, exynos-m5, kryo, iwmmxt, xscale, swift{{$}}
+// ARM-NEXT: note: valid target CPU values are: arm8, arm810, strongarm, strongarm110, strongarm1100, strongarm1110, arm7tdmi, arm7tdmi-s, arm710t, arm720t, arm9, arm9tdmi, arm920, arm920t, arm922t, arm940t, ep9312, arm10tdmi, arm1020t, arm9e, arm946e-s, arm966e-s, arm968e-s, arm10e, arm1020e, arm1022e, arm926ej-s, arm1136j-s, arm1136jf-s, mpcore, mpcorenovfp, arm1176jz-s, arm1176jzf-s, arm1156t2-s, arm1156t2f-s, cortex-m0, cortex-m0plus, cortex-m1, sc000, cortex-a5, cortex-a7, cortex-a8, cortex-a9, cortex-a12, cortex-a15, cortex-a17, krait, cortex-r4, cortex-r4f, cortex-r5, cortex-r7, cortex-r8, cortex-r52, sc300, cortex-m3, cortex-m4, cortex-m7, cortex-m23, cortex-m33, cortex-m35p, cortex-m55, cortex-m85, cortex-m52, cortex-a32, cortex-a35, cortex-a53, cortex-a55, cortex-a57, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-x1, cortex-x1c, neoverse-n1, neoverse-n2, neoverse-v1, cyclone, exynos-m3, exynos-m4, exynos-m5, kryo, iwmmxt, xscale, swift{{$}}
 
 // RUN: not %clang_cc1 -triple arm64--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix AARCH64
 // AARCH64: error: unknown target CPU 'not-a-cpu'
-// AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}}
+// AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}}
 
 // RUN: not %clang_cc1 -triple arm64--- -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE_AARCH64
 // TUNE_AARCH64: error: unknown target CPU 'not-a-cpu'
-// TUNE_AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}}
+// TUNE_AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-r82, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-512tvb, neoverse-v1, neoverse-v2, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}}
 
 // RUN: not %clang_cc1 -triple i386--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix X86
 // X86: error: unknown target CPU 'not-a-cpu'
diff --git a/clang/test/Misc/warning-wall.c b/clang/test/Misc/warning-wall.c
index 05a82770e26de69595374a64b25a81cea43b6e2c..4909ab034ef30aa3bd005b92032c5a780981889f 100644
--- a/clang/test/Misc/warning-wall.c
+++ b/clang/test/Misc/warning-wall.c
@@ -44,6 +44,7 @@ CHECK-NEXT:      -Wreorder-ctor
 CHECK-NEXT:      -Wreorder-init-list
 CHECK-NEXT:    -Wreturn-type
 CHECK-NEXT:      -Wreturn-type-c-linkage
+CHECK-NEXT:      -Wreturn-mismatch
 CHECK-NEXT:    -Wself-assign
 CHECK-NEXT:      -Wself-assign-overloaded
 CHECK-NEXT:      -Wself-assign-field
diff --git a/clang/test/Modules/InheritDefaultArguments.cppm b/clang/test/Modules/InheritDefaultArguments.cppm
index 0afb46319ff8508f44e7f05b1b5aa45956b79e7d..0ef6390204c4b9fad3ace04c4b38e5a39fbbc358 100644
--- a/clang/test/Modules/InheritDefaultArguments.cppm
+++ b/clang/test/Modules/InheritDefaultArguments.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cppm -verify -fsyntax-only
 
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-reduced-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cppm -verify -fsyntax-only
+
 //--- foo.h
 template 
 class Templ;
diff --git a/clang/test/Modules/Inputs/config.h b/clang/test/Modules/Inputs/config.h
deleted file mode 100644
index 4c124b0bf82b7cba40c99a7dbfc3408fbb148b9a..0000000000000000000000000000000000000000
--- a/clang/test/Modules/Inputs/config.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifdef WANT_FOO
-int* foo(void);
-#endif
-
-#ifdef WANT_BAR
-char *bar(void);
-#endif
diff --git a/clang/test/Modules/Inputs/module.modulemap b/clang/test/Modules/Inputs/module.modulemap
index e7cb4b27bc08b9ed2b96b9a3b50342921bd017f5..47f6c5c1010d7daf2940457f2b4b5a5bc4560172 100644
--- a/clang/test/Modules/Inputs/module.modulemap
+++ b/clang/test/Modules/Inputs/module.modulemap
@@ -260,11 +260,6 @@ module cxx_decls_merged {
   header "cxx-decls-merged.h"
 }
 
-module config {
-  header "config.h"
-  config_macros [exhaustive] WANT_FOO, WANT_BAR
-}
-
 module diag_flags {
   header "diag_flags.h"
 }
diff --git a/clang/test/Modules/Reachability-Private.cpp b/clang/test/Modules/Reachability-Private.cpp
index 9a7c3ba231f179c6a2335c9991f75da793c89664..3ce108dc5c5509340906a0a0454186c67a589ff3 100644
--- a/clang/test/Modules/Reachability-Private.cpp
+++ b/clang/test/Modules/Reachability-Private.cpp
@@ -9,6 +9,16 @@
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp \
 // RUN: -DTEST_BADINLINE -verify -fsyntax-only
 
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/Private.cppm -emit-reduced-module-interface \
+// RUN: -o %t/Private.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp \
+// RUN: -DTEST_BADINLINE -verify -fsyntax-only
+
 //--- Private.cppm
 export module Private;
 #ifdef TEST_BADINLINE
diff --git a/clang/test/Modules/Reachability-func-default-arg.cpp b/clang/test/Modules/Reachability-func-default-arg.cpp
index 0d6d8655d53293e17524670412724ece6a8f7d42..bc0cafdebb7a4e3c7da061b0a693f49d9707b3ad 100644
--- a/clang/test/Modules/Reachability-func-default-arg.cpp
+++ b/clang/test/Modules/Reachability-func-default-arg.cpp
@@ -4,6 +4,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/func_default_arg.cppm -emit-module-interface -o %t/func_default_arg.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+
+// RUN: %clang_cc1 -std=c++20 %t/func_default_arg.cppm -emit-reduced-module-interface -o %t/func_default_arg.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 //
 //--- func_default_arg.cppm
 export module func_default_arg;
diff --git a/clang/test/Modules/Reachability-func-ret.cpp b/clang/test/Modules/Reachability-func-ret.cpp
index ca5bbc68d759f93e95cae3c40db8c5bd6b1317fa..7d34387726f683cb93055be8f5e6eaac7ace7c05 100644
--- a/clang/test/Modules/Reachability-func-ret.cpp
+++ b/clang/test/Modules/Reachability-func-ret.cpp
@@ -4,6 +4,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/func_ret.cppm -emit-module-interface -o %t/func_ret.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+
+// RUN: %clang_cc1 -std=c++20 %t/func_ret.cppm -emit-reduced-module-interface -o %t/func_ret.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 //
 //--- func_ret.cppm
 export module func_ret;
diff --git a/clang/test/Modules/Reachability-template-default-arg.cpp b/clang/test/Modules/Reachability-template-default-arg.cpp
index 6fb109e41fcf0a0705d444dd0a6383faae1a796e..35c647d0d344ba3ef49dba08e867448047dd6adf 100644
--- a/clang/test/Modules/Reachability-template-default-arg.cpp
+++ b/clang/test/Modules/Reachability-template-default-arg.cpp
@@ -4,6 +4,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/template_default_arg.cppm -emit-module-interface -o %t/template_default_arg.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 %t/template_default_arg.cppm -emit-reduced-module-interface -o %t/template_default_arg.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
 //
 //--- template_default_arg.cppm
 export module template_default_arg;
diff --git a/clang/test/Modules/Reachability-template-instantiation.cpp b/clang/test/Modules/Reachability-template-instantiation.cpp
index 2170c7b92a370aa3e8ccd3882387bd24dc818d8f..6f363ed00b6e36626edd63ee2e35ec73fbc13991 100644
--- a/clang/test/Modules/Reachability-template-instantiation.cpp
+++ b/clang/test/Modules/Reachability-template-instantiation.cpp
@@ -5,6 +5,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm
 // RUN: %clang_cc1 -std=c++20 %t/Use.cppm -fprebuilt-module-path=%t -emit-module-interface -o %t/Use.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cpp -verify -fsyntax-only
+
+// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-reduced-module-interface -o %t/Templ.pcm
+// RUN: %clang_cc1 -std=c++20 %t/Use.cppm -fprebuilt-module-path=%t -emit-reduced-module-interface -o %t/Use.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cpp -verify -fsyntax-only
 //
 //--- Templ.h
 #ifndef TEMPL_H
diff --git a/clang/test/Modules/Reachability-using-templates.cpp b/clang/test/Modules/Reachability-using-templates.cpp
index f530e15bd4d2ba454b1f2ec88d149992822e4685..65601c1cfe4e2df8c9df830162d63ad9e5035e8e 100644
--- a/clang/test/Modules/Reachability-using-templates.cpp
+++ b/clang/test/Modules/Reachability-using-templates.cpp
@@ -4,6 +4,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/mod.templates.cppm -emit-module-interface -o %t/mod.templates.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 %t/mod.templates.cppm -emit-reduced-module-interface -o %t/mod.templates.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
 //
 //--- mod.templates.cppm
 export module mod.templates;
diff --git a/clang/test/Modules/Reachability-using.cpp b/clang/test/Modules/Reachability-using.cpp
index 642b97dd8432c3bfd1aca096fc7169976f2b0127..8301bfbedf87045077d21a9fe8253e0dfdccc522 100644
--- a/clang/test/Modules/Reachability-using.cpp
+++ b/clang/test/Modules/Reachability-using.cpp
@@ -4,6 +4,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/mod.cppm -emit-module-interface -o %t/mod.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 %t/mod.cppm -emit-reduced-module-interface -o %t/mod.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
 //
 //--- mod.cppm
 export module mod;
diff --git a/clang/test/Modules/concept.cppm b/clang/test/Modules/concept.cppm
index 0fdb5ea89680859caafb6a3a0a2efad22f265231..4464cf7c0a416cbac6079640633f113a39195514 100644
--- a/clang/test/Modules/concept.cppm
+++ b/clang/test/Modules/concept.cppm
@@ -11,7 +11,6 @@
 // RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf -fprebuilt-module-path=%t -I%t  \
 // RUN:    -DDIFFERENT -DSKIP_ODR_CHECK_IN_GMF %t/B.cppm -verify
 
-
 //--- foo.h
 #ifndef FOO_H
 #define FOO_H
diff --git a/clang/test/Modules/concept_differ.cppm b/clang/test/Modules/concept_differ.cppm
index ccb29d26e53d1340b69a124da20bc56868372ffb..525ee2d4edcc8ec6f71f52917f6e4ad5f321c459 100644
--- a/clang/test/Modules/concept_differ.cppm
+++ b/clang/test/Modules/concept_differ.cppm
@@ -5,6 +5,11 @@
 // RUN: %clang_cc1 -x c++ -std=c++20 %t/A.cppm -I%t -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -x c++ -std=c++20 %t/B.cppm -I%t -emit-module-interface -o %t/B.pcm
 // RUN: %clang_cc1 -x c++ -std=c++20 -fprebuilt-module-path=%t %t/foo.cpp -verify
+//
+// RUN: rm %t/A.pcm %t/B.pcm
+// RUN: %clang_cc1 -x c++ -std=c++20 %t/A.cppm -I%t -emit-reduced-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -x c++ -std=c++20 %t/B.cppm -I%t -emit-reduced-module-interface -o %t/B.pcm
+// RUN: %clang_cc1 -x c++ -std=c++20 -fprebuilt-module-path=%t %t/foo.cpp -verify
 
 //--- foo.h
 template 
diff --git a/clang/test/Modules/config_macros.m b/clang/test/Modules/config_macros.m
index 15e2c16606ba29db7887ead7f44c62e26193a7d3..adb2a8f6e5ce34404454ca5252cb730e46ee71ff 100644
--- a/clang/test/Modules/config_macros.m
+++ b/clang/test/Modules/config_macros.m
@@ -1,3 +1,50 @@
+// This test verifies that config macro warnings are emitted when it looks like
+// the user expected a `#define` to impact the import of a module.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+
+// Prebuild the `config` module so it's in the module cache.
+// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -x objective-c -fmodules-cache-path=%t -DWANT_FOO=1 -emit-module -fmodule-name=config %t/module.modulemap
+
+// Verify that each time the `config` module is imported the current macro state
+// is checked.
+// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %t -DWANT_FOO=1 %t/config.m -verify
+
+// Verify that warnings are emitted before building a module in case the command
+// line macro state causes the module to fail to build.
+// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %t %t/config_error.m -verify
+
+//--- module.modulemap
+
+module config {
+  header "config.h"
+  config_macros [exhaustive] WANT_FOO, WANT_BAR
+}
+
+module config_error {
+  header "config_error.h"
+  config_macros SOME_VALUE
+}
+
+//--- config.h
+
+#ifdef WANT_FOO
+int* foo(void);
+#endif
+
+#ifdef WANT_BAR
+char *bar(void);
+#endif
+
+//--- config_error.h
+
+struct my_thing {
+  char buf[SOME_VALUE];
+};
+
+//--- config.m
+
 @import config;
 
 int *test_foo(void) {
@@ -22,7 +69,8 @@ char *test_bar(void) {
 #define WANT_BAR 1 // expected-note{{macro was defined here}}
 @import config; // expected-warning{{definition of configuration macro 'WANT_BAR' has no effect on the import of 'config'; pass '-DWANT_BAR=...' on the command line to configure the module}}
 
-// RUN: rm -rf %t
-// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -x objective-c -fmodules-cache-path=%t -DWANT_FOO=1 -emit-module -fmodule-name=config %S/Inputs/module.modulemap
-// RUN: %clang_cc1 -std=c99 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs -DWANT_FOO=1 %s -verify
+//--- config_error.m
 
+#define SOME_VALUE 5 // expected-note{{macro was defined here}}
+@import config_error; // expected-error{{could not build module}} \
+                      // expected-warning{{definition of configuration macro 'SOME_VALUE' has no effect on the import of 'config_error';}}
diff --git a/clang/test/Modules/ctor.arg.dep.cppm b/clang/test/Modules/ctor.arg.dep.cppm
index 0e5b1a694f6a5e149c08e7ed25e6a782bd9a2e90..10924bfe0f1bdcec5c20909a9ebf452e77e06e1a 100644
--- a/clang/test/Modules/ctor.arg.dep.cppm
+++ b/clang/test/Modules/ctor.arg.dep.cppm
@@ -5,6 +5,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 //
+// RUN: rm %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -emit-reduced-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+//
 //--- foo.h
 
 namespace ns {
diff --git a/clang/test/Modules/cxx20-10-1-ex1.cpp b/clang/test/Modules/cxx20-10-1-ex1.cpp
index b330e0a6c9a9d88d5114116450dd3b0159cffc75..4445b19ea86cf4af1fb983eb6b55c35b9cb8f044 100644
--- a/clang/test/Modules/cxx20-10-1-ex1.cpp
+++ b/clang/test/Modules/cxx20-10-1-ex1.cpp
@@ -19,6 +19,22 @@
 // RUN:  -fmodule-file=A=%t/A.pcm -fmodule-file=A:Foo=%t/A_Foo.pcm \
 // RUN:  -fmodule-file=A:Internals=%t/A_Internals.pcm -o %t/ex1.o
 
+// RUN: rm %t/A_Internals.pcm %t/A_Foo.pcm %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std10-1-ex1-tu1.cpp \
+// RUN:  -o %t/A_Internals.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std10-1-ex1-tu2.cpp \
+// RUN:  -fmodule-file=A:Internals=%t/A_Internals.pcm -o %t/A_Foo.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std10-1-ex1-tu3.cpp \
+// RUN:     -fmodule-file=A:Internals=%t/A_Internals.pcm \
+// RUN:     -fmodule-file=A:Foo=%t/A_Foo.pcm -o %t/A.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std10-1-ex1-tu4.cpp \
+// RUN:     -fmodule-file=A:Internals=%t/A_Internals.pcm \
+// RUN:     -fmodule-file=A:Foo=%t/A_Foo.pcm \
+// RUN:     -fmodule-file=A=%t/A.pcm -o %t/ex1.o
+
 // expected-no-diagnostics
 
 //--- std10-1-ex1-tu1.cpp
diff --git a/clang/test/Modules/cxx20-10-1-ex2.cpp b/clang/test/Modules/cxx20-10-1-ex2.cpp
index 8b908d5fa2eda61a8fb1fc2d8935c3db3e7443b6..fc61d89926d4488802d30ece97a18bd13a092e12 100644
--- a/clang/test/Modules/cxx20-10-1-ex2.cpp
+++ b/clang/test/Modules/cxx20-10-1-ex2.cpp
@@ -5,26 +5,50 @@
 
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu1.cpp \
 // RUN:  -o %t/B_Y.pcm
-
+//
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu2.cpp \
 // RUN:     -fmodule-file=B:Y=%t/B_Y.pcm -o %t/B.pcm
-
+//
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu3.cpp \
 // RUN:     -o %t/B_X1.pcm -verify
-
+//
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu4.cpp \
 // RUN:     -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm  -o %t/B_X2.pcm
-
+//
 // RUN: %clang_cc1 -std=c++20 -emit-obj %t/std10-1-ex2-tu5.cpp \
 // RUN:     -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm  -o %t/b_tu5.o
-
+//
 // RUN: %clang_cc1 -std=c++20 -S %t/std10-1-ex2-tu6.cpp \
 // RUN:     -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm  -o %t/b_tu6.s -verify
-
+//
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu7.cpp \
 // RUN:     -fmodule-file=B:X2=%t/B_X2.pcm -fmodule-file=B=%t/B.pcm \
 // RUN:     -fmodule-file=B:Y=%t/B_Y.pcm   -o %t/B_X3.pcm -verify
 
+// Test again with reduced BMI.
+// RUN: rm %t/B_X2.pcm %t/B.pcm %t/B_Y.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std10-1-ex2-tu1.cpp \
+// RUN:  -o %t/B_Y.pcm
+//
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std10-1-ex2-tu2.cpp \
+// RUN:     -fmodule-file=B:Y=%t/B_Y.pcm -o %t/B.pcm
+//
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std10-1-ex2-tu3.cpp \
+// RUN:     -o %t/B_X1.pcm -verify
+//
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std10-1-ex2-tu4.cpp \
+// RUN:     -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm  -o %t/B_X2.pcm
+//
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std10-1-ex2-tu5.cpp \
+// RUN:     -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm  -o %t/b_tu5.o
+//
+// RUN: %clang_cc1 -std=c++20 -S %t/std10-1-ex2-tu6.cpp \
+// RUN:     -fmodule-file=B=%t/B.pcm -fmodule-file=B:Y=%t/B_Y.pcm  -o %t/b_tu6.s -verify
+//
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std10-1-ex2-tu7.cpp \
+// RUN:     -fmodule-file=B:X2=%t/B_X2.pcm -fmodule-file=B=%t/B.pcm \
+// RUN:     -fmodule-file=B:Y=%t/B_Y.pcm   -o %t/B_X3.pcm -verify
+
 //--- std10-1-ex2-tu1.cpp
 module B:Y;
 int y();
diff --git a/clang/test/Modules/cxx20-10-2-ex2.cpp b/clang/test/Modules/cxx20-10-2-ex2.cpp
index bc66d6a2ec1a92e2bf13c2b003e058fbf608eed9..b48d96478b9a6523bd797dbdeaac52c0dfb987e1 100644
--- a/clang/test/Modules/cxx20-10-2-ex2.cpp
+++ b/clang/test/Modules/cxx20-10-2-ex2.cpp
@@ -14,6 +14,18 @@
 // RUN: -fmodule-file=%t/std-10-2-ex2-c.pcm -fmodule-file=X=%t/X.pcm \
 // RUN: -pedantic-errors -verify -o  %t/M.pcm
 
+// Test again with reduced BMI.
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -I %t \
+// RUN: -xc++-user-header std-10-2-ex2-c.h -o %t/std-10-2-ex2-c.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std-10-2-ex2-tu1.cpp \
+// RUN:  -o  %t/X.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std-10-2-ex2-tu2.cpp \
+// RUN: -fmodule-file=%t/std-10-2-ex2-c.pcm -fmodule-file=X=%t/X.pcm \
+// RUN: -pedantic-errors -verify -o  %t/M.pcm
+
+
 //--- std-10-2-ex2-b.h
 int f();
 
diff --git a/clang/test/Modules/cxx20-10-2-ex5.cpp b/clang/test/Modules/cxx20-10-2-ex5.cpp
index 49c5934c8f2172d14dc40d76c3ee6ae681df6a4f..f222568072393f949dd0d3fe72ce701143d55bc3 100644
--- a/clang/test/Modules/cxx20-10-2-ex5.cpp
+++ b/clang/test/Modules/cxx20-10-2-ex5.cpp
@@ -13,6 +13,18 @@
 // RUN: %clang_cc1 -std=c++20 -emit-obj %t/std-10-2-ex5-tu3.cpp \
 // RUN:  -fmodule-file=M=%t/M.pcm -verify -o %t/main.o
 
+// Test again with reduced BMI.
+// RUN: rm %t/M.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std-10-2-ex5-tu1.cpp \
+// RUN:  -o  %t/M.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std-10-2-ex5-tu2.cpp \
+// RUN:  -fmodule-file=M=%t/M.pcm -o  %t/tu-2.o
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std-10-2-ex5-tu3.cpp \
+// RUN:  -fmodule-file=M=%t/M.pcm -verify -o %t/main.o
+
+
 //--- std-10-2-ex5-tu1.cpp
 export module M;
 export struct X {
diff --git a/clang/test/Modules/cxx20-10-3-ex1.cpp b/clang/test/Modules/cxx20-10-3-ex1.cpp
index 5d6e2554f753b07d46db6604a33689738f1bc31f..99b88c7e442ffdb01dcf09d7efebc4afe2645406 100644
--- a/clang/test/Modules/cxx20-10-3-ex1.cpp
+++ b/clang/test/Modules/cxx20-10-3-ex1.cpp
@@ -14,6 +14,20 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-3-ex1-tu4.cpp \
 // RUN:  -fmodule-file=M:Part=%t/M_Part.pcm -o %t/M.pcm
 
+// Test again with reduced BMI.
+// RUN: rm %t/M_PartImpl.pcm %t/M.pcm %t/M_Part.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std10-3-ex1-tu1.cpp \
+// RUN:  -o %t/M_PartImpl.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std10-3-ex1-tu2.cpp \
+// RUN:  -fmodule-file=M:PartImpl=%t/M_PartImpl.pcm -o %t/M.pcm -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std10-3-ex1-tu3.cpp \
+// RUN:  -o %t/M_Part.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std10-3-ex1-tu4.cpp \
+// RUN:  -fmodule-file=M:Part=%t/M_Part.pcm -o %t/M.pcm
+
 //--- std10-3-ex1-tu1.cpp
 module M:PartImpl;
 
diff --git a/clang/test/Modules/cxx20-10-3-ex2.cpp b/clang/test/Modules/cxx20-10-3-ex2.cpp
index b1d6d669c0a0e60fedfb0348433fa4ff60589d8d..40566c00f578c2b5bc135635e4193933c211d143 100644
--- a/clang/test/Modules/cxx20-10-3-ex2.cpp
+++ b/clang/test/Modules/cxx20-10-3-ex2.cpp
@@ -11,6 +11,16 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-3-ex2-tu3.cpp \
 // RUN:  -o %t/M.pcm -verify
 
+// Test again with reduced BMI.
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std10-3-ex2-tu1.cpp \
+// RUN:  -o %t/M.pcm
+
+// RUN: %clang_cc1 -std=c++20 -S %t/std10-3-ex2-tu2.cpp \
+// RUN:  -fmodule-file=M=%t/M.pcm -o %t/tu_8.s -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/std10-3-ex2-tu3.cpp \
+// RUN:  -o %t/M.pcm -verify
+
 //--- std10-3-ex2-tu1.cpp
 export module M;
 
diff --git a/clang/test/Modules/cxx20-10-5-ex1.cpp b/clang/test/Modules/cxx20-10-5-ex1.cpp
index a83162c5c1501719f3a3c933e87dc5e61b5e2460..0435b3a64c075d344e73a9805220c00307043226 100644
--- a/clang/test/Modules/cxx20-10-5-ex1.cpp
+++ b/clang/test/Modules/cxx20-10-5-ex1.cpp
@@ -11,6 +11,18 @@
 // RUN: %clang_cc1 -std=c++20 std-10-5-ex1-use.cpp  -fmodule-file=A=A.pcm \
 // RUN:    -fsyntax-only -verify
 
+// Test again with reduced BMI.
+// RUN: rm A.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface std-10-5-ex1-interface.cpp \
+// RUN: -DBAD_FWD_DECL  -fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface std-10-5-ex1-interface.cpp \
+// RUN: -o A.pcm
+
+// RUN: %clang_cc1 -std=c++20 std-10-5-ex1-use.cpp  -fmodule-file=A=A.pcm \
+// RUN:    -fsyntax-only -verify
+
+
 //--- std-10-5-ex1-interface.cpp
 
 export module A;
diff --git a/clang/test/Modules/cxx20-import-diagnostics-a.cpp b/clang/test/Modules/cxx20-import-diagnostics-a.cpp
index a5cf44ed82d5ff307fc9143fd62b8a797f510695..1b38259e0358c0fd69fb2b08ce18acdf752c9c37 100644
--- a/clang/test/Modules/cxx20-import-diagnostics-a.cpp
+++ b/clang/test/Modules/cxx20-import-diagnostics-a.cpp
@@ -36,6 +36,45 @@
 // RUN: %clang_cc1 -std=c++20 -emit-obj %t/import-diags-tu11.cpp \
 // RUN:  -fmodule-file=C=%t/C.pcm  -o %t/impl.o
 
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/import-diags-tu1.cpp \
+// RUN:  -o %t/B.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/import-diags-tu2.cpp \
+// RUN:  -o %t/C.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/import-diags-tu3.cpp \
+// RUN:  -fmodule-file=B=%t/B.pcm -fmodule-file=C=%t/C.pcm -o %t/AOK1.pcm
+
+// RUN: %clang_cc1 -std=c++20 -S %t/import-diags-tu4.cpp \
+// RUN:  -fmodule-file=AOK1=%t/AOK1.pcm -fmodule-file=B=%t/B.pcm \
+// RUN:  -fmodule-file=C=%t/C.pcm -o %t/tu_3.s -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/import-diags-tu5.cpp \
+// RUN:  -fmodule-file=B=%t/B.pcm -fmodule-file=C=%t/C.pcm -o %t/BC.pcm -verify
+
+// RUN: %clang_cc1 -std=c++20 -S %t/import-diags-tu6.cpp \
+// RUN:  -fmodule-file=B=%t/B.pcm -fmodule-file=C=%t/C.pcm -o %t/tu_5.s -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/import-diags-tu7.cpp \
+// RUN:  -fmodule-file=B=%t/B.pcm -o %t/D.pcm -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/import-diags-tu8.cpp \
+// RUN:  -fmodule-file=B=%t/B.pcm -o %t/D.pcm -verify
+
+// RUN: %clang_cc1 -std=c++20 -S %t/import-diags-tu9.cpp \
+// RUN:  -fmodule-file=B=%t/B.pcm -o %t/tu_8.s -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/import-diags-tu10.cpp \
+// RUN:  -o %t/B.pcm -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/import-diags-tu11.cpp \
+// RUN:  -fmodule-file=C=%t/C.pcm  -o %t/impl.o
+
 // Test diagnostics for incorrect module import sequences.
 
 //--- import-diags-tu1.cpp
diff --git a/clang/test/Modules/cxx20-import-diagnostics-b.cpp b/clang/test/Modules/cxx20-import-diagnostics-b.cpp
index 7d432633552a25a0cc401101ce088237119a7115..db522d7babd3ae0832b21624cd816547b5a49fda 100644
--- a/clang/test/Modules/cxx20-import-diagnostics-b.cpp
+++ b/clang/test/Modules/cxx20-import-diagnostics-b.cpp
@@ -22,6 +22,31 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface  %t/g.cpp \
 // RUN: -fmodule-file=a=%t/a.pcm -o %t/g.pcm -verify
 
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface  %t/a.cpp -o %t/a.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface  %t/c.cpp \
+// RUN: -fmodule-file=a=%t/a.pcm -o %t/c.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface  %t/d.cpp \
+// RUN: -fmodule-file=a=%t/a.pcm -o %t/d.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface  %t/e.cpp \
+// RUN: -fmodule-file=a=%t/a.pcm -o %t/e.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface  %t/a-part.cpp \
+// RUN: -o %t/a-part.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface  %t/f.cpp \
+// RUN: -fmodule-file=a=%t/a.pcm -o %t/f.pcm -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface  %t/g.cpp \
+// RUN: -fmodule-file=a=%t/a.pcm -o %t/g.pcm -verify
+
 //--- a.cpp
 export module a;
 
diff --git a/clang/test/Modules/cxx20-module-file-info-macros.cpp b/clang/test/Modules/cxx20-module-file-info-macros.cpp
index bc7df1c9f50b59747ccc1690558a248313668c4d..3b67e9b9acd4107cb62e043102feab215e1a23a5 100644
--- a/clang/test/Modules/cxx20-module-file-info-macros.cpp
+++ b/clang/test/Modules/cxx20-module-file-info-macros.cpp
@@ -17,6 +17,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/named_module.cppm -emit-module-interface -o %t/M.pcm
 // RUN: %clang_cc1 -module-file-info %t/M.pcm | FileCheck %t/named_module.cppm
 
+// RUN: %clang_cc1 -std=c++20 %t/named_module.cppm -emit-reduced-module-interface -o %t/M.pcm
+// RUN: %clang_cc1 -module-file-info %t/M.pcm | FileCheck %t/named_module.cppm
+
 //--- foo.h
 #pragma once
 #define FOO
diff --git a/clang/test/Modules/deduction-guide.cppm b/clang/test/Modules/deduction-guide.cppm
index 9c959a71365dac973b0dc3f095770c07f4fefb61..02ac2c0053cff53515f5bf6be12fd1646fd5c8d9 100644
--- a/clang/test/Modules/deduction-guide.cppm
+++ b/clang/test/Modules/deduction-guide.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 
+// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-reduced-module-interface -o %t/Templ.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+
 //--- foo.h
 template 
 class Templ {
diff --git a/clang/test/Modules/deduction-guide2.cppm b/clang/test/Modules/deduction-guide2.cppm
index a163c3656831019008a00261badf7c8ae1c5ec40..889670b973f0d3a3d11e6ca530aac0c396567024 100644
--- a/clang/test/Modules/deduction-guide2.cppm
+++ b/clang/test/Modules/deduction-guide2.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 
+// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-reduced-module-interface -o %t/Templ.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+
 //--- Templ.cppm
 export module Templ;
 export template 
diff --git a/clang/test/Modules/deduction-guide3.cppm b/clang/test/Modules/deduction-guide3.cppm
index 8fa08a0625d7c89190fb50c1db30fde54f8d239b..1165dd40bcfb8c9267132506f69ac831cc0176e0 100644
--- a/clang/test/Modules/deduction-guide3.cppm
+++ b/clang/test/Modules/deduction-guide3.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o %t/Templ.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 
+// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-reduced-module-interface -o %t/Templ.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+
 //--- Templ.cppm
 export module Templ;
 template 
diff --git a/clang/test/Modules/derived_class.cpp b/clang/test/Modules/derived_class.cpp
index ee9e0ae4637ec725aa5502656a1917d9eedb8533..e0c5a652eba4eaf5b154a43e571108b6b5c106ee 100644
--- a/clang/test/Modules/derived_class.cpp
+++ b/clang/test/Modules/derived_class.cpp
@@ -4,6 +4,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/foo.cppm -emit-module-interface -o %t/foo.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 %t/foo.cppm -emit-reduced-module-interface -o %t/foo.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
 //
 //--- bar.h
 struct bar_base {
diff --git a/clang/test/Modules/duplicated-module-file-eq-module-name.cppm b/clang/test/Modules/duplicated-module-file-eq-module-name.cppm
index e86dbe2b941ef88c453e8eecd48fe5cbc679c8e3..57ffb560ab540a86d21ab7f759797762b45f26f3 100644
--- a/clang/test/Modules/duplicated-module-file-eq-module-name.cppm
+++ b/clang/test/Modules/duplicated-module-file-eq-module-name.cppm
@@ -8,6 +8,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm
 // RUN: %clang_cc1 -std=c++20 %t/u.cpp -fmodule-file=a=%t/unexist.pcm \
 // RUN:      -fmodule-file=a=%t/a.pcm -verify -fsyntax-only
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/u.cpp -fmodule-file=a=%t/unexist.pcm \
+// RUN:      -fmodule-file=a=%t/a.pcm -verify -fsyntax-only
 
 //--- a.cppm
 export module a;
diff --git a/clang/test/Modules/enum-class.cppm b/clang/test/Modules/enum-class.cppm
index 01ae8c0d8814da5132d489299f6adcc13b7e1dc4..992eb9d5e55100be1647bc6775d9fd25f259420b 100644
--- a/clang/test/Modules/enum-class.cppm
+++ b/clang/test/Modules/enum-class.cppm
@@ -6,6 +6,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-reduced-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 
 //--- foo.h
 enum class foo {
diff --git a/clang/test/Modules/explicitly-specialized-template.cpp b/clang/test/Modules/explicitly-specialized-template.cpp
index 89677254ea739ac7c662360592e476acd9204ab7..2450bbe31bd9b76e178869aa768a78d11c785770 100644
--- a/clang/test/Modules/explicitly-specialized-template.cpp
+++ b/clang/test/Modules/explicitly-specialized-template.cpp
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/X.cppm -emit-module-interface -o %t/X.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
 //
+// RUN: %clang_cc1 -std=c++20 %t/X.cppm -emit-reduced-module-interface -o %t/X.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
+//
 //--- foo.h
 #ifndef FOO_H
 #define FOO_H
diff --git a/clang/test/Modules/export-language-linkage.cppm b/clang/test/Modules/export-language-linkage.cppm
index 462b28d36cb44b5d43100601b6c2ea42c8153032..f389d9604ef3a84567611fbe0e18ab52f22f5790 100644
--- a/clang/test/Modules/export-language-linkage.cppm
+++ b/clang/test/Modules/export-language-linkage.cppm
@@ -8,6 +8,11 @@
 // RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-module-interface -o %t/c.pcm
 // RUN: %clang_cc1 -std=c++20 %t/d.cpp -fsyntax-only -verify -fmodule-file=c=%t/c.pcm
 
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cpp -fmodule-file=a=%t/a.pcm -fsyntax-only -verify
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -fsyntax-only -verify
+// RUN: %clang_cc1 -module-file-info %t/a.pcm | FileCheck %t/a.cppm
+
 //--- a.cppm
 export module a;
 export extern "C++" int foo() { return 43; }
@@ -43,6 +48,7 @@ int use() {
 }
 
 //--- c.cppm
+// expected-no-diagnostics
 export module c;
 extern "C++" {
     export int f();
@@ -59,5 +65,5 @@ int use() {
 
 int use_of_nonexported() {
     return h(); // expected-error {{declaration of 'h' must be imported from module 'c' before it is required}}
-                // expected-note@c.cppm:4 {{declaration here is not visible}}
+                // expected-note@c.cppm:5 {{declaration here is not visible}}
 }
diff --git a/clang/test/Modules/ftime-trace.cppm b/clang/test/Modules/ftime-trace.cppm
index 48cd4113ec7826cf751b26a50b2f1e957e360358..8882e85be151563bfd134daf3b8a4fc132eb76f2 100644
--- a/clang/test/Modules/ftime-trace.cppm
+++ b/clang/test/Modules/ftime-trace.cppm
@@ -9,5 +9,14 @@
 // RUN: %clang_cc1 -std=c++20 %t/a.pcm -ftime-trace=%t/a.json -o -
 // RUN: ls %t | grep "a.json"
 
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/a.pcm -ftime-trace=%t/a.json -o -
+// RUN: ls %t | grep "a.json"
+
 //--- a.cppm
 export module a;
diff --git a/clang/test/Modules/hashing-decls-in-exprs-from-gmf.cppm b/clang/test/Modules/hashing-decls-in-exprs-from-gmf.cppm
new file mode 100644
index 0000000000000000000000000000000000000000..8db53c0ace8796971b763d9ceebd11e2fee62936
--- /dev/null
+++ b/clang/test/Modules/hashing-decls-in-exprs-from-gmf.cppm
@@ -0,0 +1,67 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/A.cppm -emit-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/B.cppm -emit-module-interface -o %t/B.pcm
+// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/test.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+
+//--- header.h
+#pragma once
+template 
+class Optional {};
+
+template 
+concept C = requires(const _Tp& __t) {
+    [](const Optional<_Up>&) {}(__t);
+};
+
+//--- func.h
+#include "header.h"
+template 
+void func() {}
+
+//--- duplicated_func.h
+#include "header.h"
+template 
+void duplicated_func() {}
+
+//--- test_func.h
+#include "func.h"
+
+void test_func() {
+    func>();
+}
+
+//--- test_duplicated_func.h
+#include "duplicated_func.h"
+
+void test_duplicated_func() {
+    duplicated_func>();
+}
+
+//--- A.cppm
+module;
+#include "header.h"
+#include "test_duplicated_func.h"
+export module A;
+export using ::test_duplicated_func;
+
+//--- B.cppm
+module;
+#include "header.h"
+#include "test_func.h"
+#include "test_duplicated_func.h"
+export module B;
+export using ::test_func;
+export using ::test_duplicated_func;
+
+//--- test.cpp
+// expected-no-diagnostics
+import A;
+import B;
+
+void test() {
+    test_func();
+    test_duplicated_func();
+}
diff --git a/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm b/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm
index abcbec07f97de064025ab0809718f4d824250a3b..3991e47ce215133fb016f8ce777c3ac8b9075f0c 100644
--- a/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm
+++ b/clang/test/Modules/inconsistent-deduction-guide-linkage.cppm
@@ -8,6 +8,12 @@
 // RUN: %clang_cc1 -std=c++20 %t/D.cppm -I%t -emit-module-interface -o %t/D.pcm
 // RUN: %clang_cc1 -std=c++20 -fsyntax-only %t/D-part.cppm -I%t -fprebuilt-module-path=%t -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -I%t -emit-reduced-module-interface -o %t/B.pcm
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only %t/A.cppm -I%t -fprebuilt-module-path=%t -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/D.cppm -I%t -emit-reduced-module-interface -o %t/D.pcm
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only %t/D-part.cppm -I%t -fprebuilt-module-path=%t -verify
+
 //--- A.cppm
 module;
 export module baz:A;
diff --git a/clang/test/Modules/inconsistent-export.cppm b/clang/test/Modules/inconsistent-export.cppm
index 5e94d2b37b75785424e2ead4e88171a7efd303da..0c74ba9037702a4b14e2c8a7ed811ecee0d5b662 100644
--- a/clang/test/Modules/inconsistent-export.cppm
+++ b/clang/test/Modules/inconsistent-export.cppm
@@ -9,6 +9,19 @@
 // RUN:     -fprebuilt-module-path=%t
 // RUN: %clang_cc1 -std=c++20 %t/use.cppm -fprebuilt-module-path=%t -emit-obj
 
+// Test again with reduced BMI.
+// RUN: rm -fr %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/m-a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-reduced-module-interface -o %t/m-b.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/m.cppm -emit-reduced-module-interface -o %t/m.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/use.cppm -fprebuilt-module-path=%t -emit-obj
+
+
 //--- a.cppm
 export module m:a;
 namespace n {
diff --git a/clang/test/Modules/inherited_arg.cppm b/clang/test/Modules/inherited_arg.cppm
index eb66b70cdce3360a5a8f7124c7b67e206537621c..a9b6efabb1e6f7d5bf5fc227c6a26eb6f4600895 100644
--- a/clang/test/Modules/inherited_arg.cppm
+++ b/clang/test/Modules/inherited_arg.cppm
@@ -7,6 +7,14 @@
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -fprebuilt-module-path=%t -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 
+// Test again with reduced BMI.
+//
+// RUN: %clang_cc1 -std=c++20 %t/A-B.cppm -I%t -emit-reduced-module-interface -o %t/A-B.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A-C.cppm -I%t -emit-reduced-module-interface -o %t/A-C.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-reduced-module-interface -fprebuilt-module-path=%t -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+
+
 //--- foo.h
 template 
 class pair {};
diff --git a/clang/test/Modules/instantiation-argdep-lookup.cppm b/clang/test/Modules/instantiation-argdep-lookup.cppm
index fc9009a5bc13d5a28af7184205a81cd26b1c4879..62dabfb6efddcfa40561cbe95855fa9ae71fda4f 100644
--- a/clang/test/Modules/instantiation-argdep-lookup.cppm
+++ b/clang/test/Modules/instantiation-argdep-lookup.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
 //
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -I%t -emit-reduced-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+//
 //--- foo.h
 
 namespace ns {
diff --git a/clang/test/Modules/lambdas.cppm b/clang/test/Modules/lambdas.cppm
index 7f00cf6f8682ac4963f4dbc947793380098e16cc..be614b0519161af648ffd321f3128834d64c2bd2 100644
--- a/clang/test/Modules/lambdas.cppm
+++ b/clang/test/Modules/lambdas.cppm
@@ -11,6 +11,21 @@
 // RUN:    -o %t/lambdas2.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \
 // RUN:    -verify -DUSE_LAMBDA2
+//
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/lambdas.cppm -emit-reduced-module-interface \
+// RUN:    -o %t/lambdas.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \
+// RUN:    -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/lambdas2.cppm -emit-reduced-module-interface \
+// RUN:    -o %t/lambdas2.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \
+// RUN:    -verify -DUSE_LAMBDA2
 
 //--- lambdas.h
 auto l1 = []() constexpr -> int {
diff --git a/clang/test/Modules/merge-concepts-cxx-modules.cpp b/clang/test/Modules/merge-concepts-cxx-modules.cpp
index 3d4f8435531a88cfed9cc58c06195e303f7073cd..0127e8baad6b94a230c3154353e9777de6a6f182 100644
--- a/clang/test/Modules/merge-concepts-cxx-modules.cpp
+++ b/clang/test/Modules/merge-concepts-cxx-modules.cpp
@@ -8,6 +8,18 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/conflicting.cppm -o %t/conflicting.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cppm -fsyntax-only -verify
 
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/same_as.cppm -o %t/same_as.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface -fprebuilt-module-path=%t %t/concepts.cppm -o %t/concepts.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface -fprebuilt-module-path=%t %t/format.cppm -o %t/format.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/conflicting.cppm -o %t/conflicting.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cppm -fsyntax-only -verify
+
+
 //--- same_as.cppm
 export module same_as;
 export template 
diff --git a/clang/test/Modules/merge-constrained-friends.cpp b/clang/test/Modules/merge-constrained-friends.cpp
index 8f0e9ed83cf2962b91df6042b79356d0d3beddc9..d0317b99801e970ce10d1a997b5062f40d2838f7 100644
--- a/clang/test/Modules/merge-constrained-friends.cpp
+++ b/clang/test/Modules/merge-constrained-friends.cpp
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++23 %t/A.cppm -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++23 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++23 %t/A.cppm -emit-reduced-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++23 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+
 //--- A.cppm
 module;
 export module A;
diff --git a/clang/test/Modules/merge-lambdas.cppm b/clang/test/Modules/merge-lambdas.cppm
index a1d04ab4e234dd32b4581ec1e43afcc11aeebeb4..4363e452c2bcd3857aa2a31a7f1bf545464cfb7a 100644
--- a/clang/test/Modules/merge-lambdas.cppm
+++ b/clang/test/Modules/merge-lambdas.cppm
@@ -6,6 +6,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-module-interface -o %t/B.pcm
 // RUN: %clang_cc1 -std=c++20 %t/use.cppm -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-reduced-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-reduced-module-interface -o %t/B.pcm
+// RUN: %clang_cc1 -std=c++20 %t/use.cppm -fprebuilt-module-path=%t -fsyntax-only -verify
+
 //--- lambda.h
 inline auto cmp = [](auto l, auto r) {
   return l < r;
diff --git a/clang/test/Modules/merge-requires-with-lambdas.cppm b/clang/test/Modules/merge-requires-with-lambdas.cppm
index 5767492047684b90ef1090636a0a8607b8c7a328..c4d6e0539f41ea300419e64d237145807bce4eda 100644
--- a/clang/test/Modules/merge-requires-with-lambdas.cppm
+++ b/clang/test/Modules/merge-requires-with-lambdas.cppm
@@ -17,6 +17,25 @@
 // RUN: %clang_cc1 -std=c++20 %t/A3.cppm -emit-module-interface -o %t/A3.pcm
 // RUN: %clang_cc1 -std=c++20 %t/TestA3.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-reduced-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A0.cppm -emit-reduced-module-interface -o %t/A0.pcm
+// RUN: %clang_cc1 -std=c++20 %t/TestA.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/A1.cppm -emit-reduced-module-interface -o %t/A1.pcm
+// RUN: %clang_cc1 -std=c++20 %t/TestA1.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/A2.cppm -emit-reduced-module-interface -o %t/A2.pcm
+// RUN: %clang_cc1 -std=c++20 %t/TestA2.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/A3.cppm -emit-reduced-module-interface -o %t/A3.pcm
+// RUN: %clang_cc1 -std=c++20 %t/TestA3.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+
+
 //--- A.h
 template 
 concept A = requires(const _Tp& __t) { [](const __Up&) {}(__t); };
diff --git a/clang/test/Modules/merge-var-template-spec-cxx-modules.cppm b/clang/test/Modules/merge-var-template-spec-cxx-modules.cppm
index a451bfe7804d3322893d11d2aa73e4b22ed04b09..db3f4cd5187169449bf89ac6f01735bf026dcb90 100644
--- a/clang/test/Modules/merge-var-template-spec-cxx-modules.cppm
+++ b/clang/test/Modules/merge-var-template-spec-cxx-modules.cppm
@@ -7,6 +7,11 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface -fprebuilt-module-path=%t %t/reexport2.cppm -o %t/reexport2.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/use.cppm -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/var_def.cppm -o %t/var_def.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface -fprebuilt-module-path=%t %t/reexport1.cppm -o %t/reexport1.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface -fprebuilt-module-path=%t %t/reexport2.cppm -o %t/reexport2.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/use.cppm -fsyntax-only -verify
+
 //--- use.cppm
 import reexport1;
 import reexport2;
diff --git a/clang/test/Modules/mismatch-diagnostics.cpp b/clang/test/Modules/mismatch-diagnostics.cpp
index f8ce987cfba57276eb3dff214225f02815fce48a..5a026aa1f6c020f44e9e6b3d6f3281378ab2e77b 100644
--- a/clang/test/Modules/mismatch-diagnostics.cpp
+++ b/clang/test/Modules/mismatch-diagnostics.cpp
@@ -13,6 +13,17 @@
 // RUN:     -fprebuilt-module-path=%t/prebuilt_modules -DCHECK_MISMATCH \
 // RUN:     %t/use.cpp 2>&1 | FileCheck %s
 
+// Test again with reduced BMI.
+// RUN: %clang_cc1 -triple %itanium_abi_triple                          \
+// RUN:     -std=c++20 -fprebuilt-module-path=%t/prebuilt-modules       \
+// RUN:     -emit-reduced-module-interface -pthread -DBUILD_MODULE              \
+// RUN:     %t/mismatching_module.cppm -o                               \
+// RUN:     %t/prebuilt_modules/mismatching_module.pcm
+//
+// RUN: not %clang_cc1 -triple %itanium_abi_triple -std=c++20           \
+// RUN:     -fprebuilt-module-path=%t/prebuilt_modules -DCHECK_MISMATCH \
+// RUN:     %t/use.cpp 2>&1 | FileCheck %s
+
 //--- mismatching_module.cppm
 export module mismatching_module;
 
diff --git a/clang/test/Modules/module-init-duplicated-import.cppm b/clang/test/Modules/module-init-duplicated-import.cppm
index 7adce11779566e1f784cdda853bb38721b1f88e4..1326402bb4ded39a0cc925351177f5c0e94d3f07 100644
--- a/clang/test/Modules/module-init-duplicated-import.cppm
+++ b/clang/test/Modules/module-init-duplicated-import.cppm
@@ -9,6 +9,17 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm  \
 // RUN:      -fmodule-file=a=%t/a.pcm -S -emit-llvm -o - | FileCheck %t/m.cppm
 
+// Test again with reduced BMI.
+// Note that we can't use reduced BMI here for m.cppm since it is required
+// to generate the backend code.
+// RUN: rm %t/a.pcm %t/m.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/a.cppm \
+// RUN:      -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.cppm \
+// RUN:      -emit-module-interface -fmodule-file=a=%t/a.pcm -o %t/m.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm  \
+// RUN:      -fmodule-file=a=%t/a.pcm -S -emit-llvm -o - | FileCheck %t/m.cppm
+
 //--- a.cppm
 export module a;
 export struct A {
diff --git a/clang/test/Modules/named-modules-adl-2.cppm b/clang/test/Modules/named-modules-adl-2.cppm
index 655acfcd93f69ab8db0f7d75d76f0da757cfbcd8..a14b9a68d74e41cfc5427d4efb32d779bfdd4a80 100644
--- a/clang/test/Modules/named-modules-adl-2.cppm
+++ b/clang/test/Modules/named-modules-adl-2.cppm
@@ -6,6 +6,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -emit-module-interface -o %t/b.pcm
 // RUN: %clang_cc1 -std=c++20 %t/c.cppm -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -emit-reduced-module-interface -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm -fsyntax-only -verify
+
 //--- a.cppm
 export module a;
 
diff --git a/clang/test/Modules/named-modules-adl-3.cppm b/clang/test/Modules/named-modules-adl-3.cppm
index 2fc2962c926b1b699ec804db7c68561a49c5ce83..d70946fa068b3ad87fbe643653a95307314e7720 100644
--- a/clang/test/Modules/named-modules-adl-3.cppm
+++ b/clang/test/Modules/named-modules-adl-3.cppm
@@ -14,6 +14,20 @@
 // RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/c.cppm -fmodule-file=a=%t/a.pcm \
 // RUN:     -fmodule-file=b=%t/b.pcm -fsyntax-only -verify
 
+// Test again with reduced BMI.
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm  -emit-reduced-module-interface \
+// RUN:     -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -fmodule-file=a=%t/a.pcm -fmodule-file=b=%t/b.pcm \
+// RUN:     -fsyntax-only -verify
+//
+// RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/b.cppm -fmodule-file=a=%t/a.pcm  \
+// RUN:     -emit-reduced-module-interface -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 -DEXPORT_OPERATOR %t/c.cppm -fmodule-file=a=%t/a.pcm \
+// RUN:     -fmodule-file=b=%t/b.pcm -fsyntax-only -verify
+
 //--- foo.h
 namespace n {
 
diff --git a/clang/test/Modules/named-modules-adl.cppm b/clang/test/Modules/named-modules-adl.cppm
index d5133ef367265a897299762b43353840067b113d..ef250023f91e75c2d59ac5134748e5355f3c0536 100644
--- a/clang/test/Modules/named-modules-adl.cppm
+++ b/clang/test/Modules/named-modules-adl.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm
 // RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fmodule-file=a=%t/a.pcm -fsyntax-only -verify
+
 //--- a.h
 namespace n {
 
diff --git a/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm b/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm
index a743b64cb18d6e21c44bdea6f22d6e12c2461be0..36a2d8bc8c95ce534baa2a6185a7a56b77f0dce9 100644
--- a/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm
+++ b/clang/test/Modules/no-duplicate-codegen-in-GMF.cppm
@@ -10,6 +10,16 @@
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/B.pcm -S -emit-llvm -o - \
 // RUN:     -fprebuilt-module-path=%t | FileCheck %t/B.cppm
 
+// Test again with reduced BMI. Note that we need to generate full BMI for B.cppm
+// since it is required to generate backend codes.
+// RUN: rm %t/A.pcm %t/B.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/A.cppm -emit-reduced-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/B.cppm -emit-module-interface -o %t/B.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/B.pcm -S -emit-llvm -o - \
+// RUN:     -fprebuilt-module-path=%t | FileCheck %t/B.cppm
+
+
 //--- foo.h
 
 template 
diff --git a/clang/test/Modules/pair-unambiguous-ctor.cppm b/clang/test/Modules/pair-unambiguous-ctor.cppm
index eb242244260cbdf64792c0ce2b4bdf9eb99ad693..24fb15959577b0f79b35f270346065c37f888c68 100644
--- a/clang/test/Modules/pair-unambiguous-ctor.cppm
+++ b/clang/test/Modules/pair-unambiguous-ctor.cppm
@@ -10,6 +10,15 @@
 // RUN: %clang_cc1 -std=c++20 %t/algorithm.cppm -I%t -emit-module-interface -o %t/std-algorithm.pcm
 // RUN: %clang_cc1 -std=c++20 %t/Use.cppm -I%t -fprebuilt-module-path=%t -emit-module-interface -verify -o %t/Use.pcm
 
+// Test again with reduced BMI.
+// RUN: rm -fr %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/string.cppm -I%t -emit-reduced-module-interface -o %t/std-string.pcm
+// RUN: %clang_cc1 -std=c++20 %t/algorithm.cppm -I%t -emit-reduced-module-interface -o %t/std-algorithm.pcm
+// RUN: %clang_cc1 -std=c++20 %t/Use.cppm -I%t -fprebuilt-module-path=%t -emit-reduced-module-interface -verify -o %t/Use.pcm
+
 //--- Use.cppm
 // expected-no-diagnostics
 module;
diff --git a/clang/test/Modules/partial_specialization.cppm b/clang/test/Modules/partial_specialization.cppm
index 3a01857172112e1796c7f08242f686f32a362524..1d65a375643a28bf4d956f6d0728541bec8696fe 100644
--- a/clang/test/Modules/partial_specialization.cppm
+++ b/clang/test/Modules/partial_specialization.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/A.cppm -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
 //
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/A.cppm -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
+//
 //--- foo.h
 template
 inline constexpr bool IsSame = false;
diff --git a/clang/test/Modules/placement-new-reachable.cpp b/clang/test/Modules/placement-new-reachable.cpp
index 29263173d78f458e070f41c80f7c22235a324b22..6b495a60306bc1b0887d39299bd9e6f96c3dca9a 100644
--- a/clang/test/Modules/placement-new-reachable.cpp
+++ b/clang/test/Modules/placement-new-reachable.cpp
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-reduced-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+
 //--- placement.h
 namespace std {
   using size_t = decltype(sizeof(0));
diff --git a/clang/test/Modules/polluted-operator.cppm b/clang/test/Modules/polluted-operator.cppm
index 721ca061c939f4b45dae1ad38579dab501bded03..2179fa098064ae430d9b68717f0c48035ca97121 100644
--- a/clang/test/Modules/polluted-operator.cppm
+++ b/clang/test/Modules/polluted-operator.cppm
@@ -11,6 +11,9 @@
 // RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf  %t/b.cppm -fprebuilt-module-path=%t \
 // RUN:   -emit-module-interface -DSKIP_ODR_CHECK_IN_GMF -o %t/b.pcm -verify
 
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/a.cppm -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t -emit-reduced-module-interface -o %t/b.pcm -verify
+
 //--- foo.h
 
 namespace std
diff --git a/clang/test/Modules/pr54457.cppm b/clang/test/Modules/pr54457.cppm
index ed67ec1065376ef42752b18196b181715b26effb..d55bdfbf3b7582c85f8e5942ef979275c2035647 100644
--- a/clang/test/Modules/pr54457.cppm
+++ b/clang/test/Modules/pr54457.cppm
@@ -9,6 +9,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/C.cppm -emit-module-interface -o %t/C.pcm
 // RUN: %clang_cc1 -std=c++20 %t/UseC.cppm -fprebuilt-module-path=%t -verify -S -o -
 
+// RUN: %clang_cc1 -std=c++20 %t/C.cppm -emit-reduced-module-interface -o %t/C.pcm
+// RUN: %clang_cc1 -std=c++20 %t/UseC.cppm -fprebuilt-module-path=%t -verify -S -o -
+
 //--- A.cppm
 // expected-no-diagnostics
 export module A;
diff --git a/clang/test/Modules/pr56916.cppm b/clang/test/Modules/pr56916.cppm
index a435b06d5cf1523ae8db7ec9b7bda096d91ad5e6..09cea6720427b3d325f4dddb71b27c525cf39b6d 100644
--- a/clang/test/Modules/pr56916.cppm
+++ b/clang/test/Modules/pr56916.cppm
@@ -8,6 +8,18 @@
 // RUN:     -fprebuilt-module-path=%t
 // RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fsyntax-only -fprebuilt-module-path=%t -verify
 
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-reduced-module-interface -o %t/M-A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-reduced-module-interface -o %t/M-B.pcm
+// RUN: %clang_cc1 -std=c++20 %t/M.cppm -emit-reduced-module-interface -o %t/M.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fsyntax-only -fprebuilt-module-path=%t -verify
+
+
 //--- foo.h
 template 
 class Templ {
diff --git a/clang/test/Modules/pr58532.cppm b/clang/test/Modules/pr58532.cppm
index cf530b4ac2ccce55f465444b7a45244abc275c0b..35bebb41431e7b5279616414dcf43cc1bfaf0741 100644
--- a/clang/test/Modules/pr58532.cppm
+++ b/clang/test/Modules/pr58532.cppm
@@ -7,6 +7,12 @@
 // RUN: %clang_cc1 -std=c++20 %t/implementation.cpp -fmodule-file=m=%t/m.pcm \
 // RUN:     -fsyntax-only -verify
 
+// Test again with reduced BMI.
+// RUN: %clang_cc1 -std=c++20 %t/interface.cppm -emit-reduced-module-interface \
+// RUN:     -o %t/m.pcm
+// RUN: %clang_cc1 -std=c++20 %t/implementation.cpp -fmodule-file=m=%t/m.pcm \
+// RUN:     -fsyntax-only -verify
+
 //--- invisible.h
 #pragma once // This breaks things.
 const int kInvisibleSymbol = 0;
diff --git a/clang/test/Modules/pr58716.cppm b/clang/test/Modules/pr58716.cppm
index 3f97fca7d5e8a325a85eda1f08247639eae82e63..177802fe3afcb8942b6e3acdeb7e50ebe3df2584 100644
--- a/clang/test/Modules/pr58716.cppm
+++ b/clang/test/Modules/pr58716.cppm
@@ -8,7 +8,7 @@
 //
 // RUN: %clang_cc1 -triple=x86_64-linux-gnu -std=c++20 -emit-module-interface %t/m.cppm -o %t/m.pcm
 // RUN: %clang_cc1 -triple=x86_64-linux-gnu -std=c++20 %t/m.pcm -S -emit-llvm -o - | FileCheck %t/m.cppm
-//
+
 //--- m.cppm
 module;
 #include "fail.h"
diff --git a/clang/test/Modules/pr59719.cppm b/clang/test/Modules/pr59719.cppm
index 5aea8992a0ca85bfcaebde7a56390042d839a239..5a600c8e36a4b6c68bdc3fbf9f5f8488d8eb9a96 100644
--- a/clang/test/Modules/pr59719.cppm
+++ b/clang/test/Modules/pr59719.cppm
@@ -7,6 +7,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/data.cppm -emit-module-interface -o %t/data.pcm
 // RUN: %clang_cc1 -std=c++20 %t/main.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/data.cppm -emit-reduced-module-interface -o %t/data.pcm
+// RUN: %clang_cc1 -std=c++20 %t/main.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+
 //--- foo.h
 namespace std {
 
diff --git a/clang/test/Modules/pr59780.cppm b/clang/test/Modules/pr59780.cppm
index d4bbd52c13f1a4ad16f093903fcce6f1aa2f51f6..ee81ca575d7bf663eb590b93e8e2ecab725e7cb4 100644
--- a/clang/test/Modules/pr59780.cppm
+++ b/clang/test/Modules/pr59780.cppm
@@ -9,6 +9,16 @@
 // RUN:     -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/use.cpp
 // RUN: %clang_cc1 -std=c++20 %t/a.pcm -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/a.cppm
 
+// Test again with reduced BMI.
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -triple %itanium_abi_triple -emit-module-interface \
+// RUN:     -o %t/a.full.pcm
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -triple %itanium_abi_triple -emit-reduced-module-interface \
+// RUN:     -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t -S \
+// RUN:     -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/use.cpp
+// RUN: %clang_cc1 -std=c++20 %t/a.full.pcm -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %t/a.cppm
+
+
 //--- a.cppm
 export module a;
 
diff --git a/clang/test/Modules/pr59999.cppm b/clang/test/Modules/pr59999.cppm
index 23710de9fe1c55961a307775baf0f8a5e04e6cc0..54452c26de4710f3f3e4f30495de37b1c9ba55ad 100644
--- a/clang/test/Modules/pr59999.cppm
+++ b/clang/test/Modules/pr59999.cppm
@@ -11,6 +11,19 @@
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Object.pcm \
 // RUN:     -fmodule-file=Module=%t/Module.pcm -S -emit-llvm -o - | FileCheck %t/Object.cppm
 
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Module.cppm \
+// RUN:     -emit-reduced-module-interface -o %t/Module.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Object.cppm \
+// RUN:     -fmodule-file=Module=%t/Module.pcm -emit-module-interface -o %t/Object.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/Object.pcm \
+// RUN:     -fmodule-file=Module=%t/Module.pcm -S -emit-llvm -o - | FileCheck %t/Object.cppm
+
+
 //--- Module.cppm
 export module Module;
 
diff --git a/clang/test/Modules/pr60036.cppm b/clang/test/Modules/pr60036.cppm
index 297132cfde60bdb0741a9ce61941f6183b7061d9..ffbc5fd56c2730775f7060110231348befb24272 100644
--- a/clang/test/Modules/pr60036.cppm
+++ b/clang/test/Modules/pr60036.cppm
@@ -24,6 +24,20 @@
 // RUN:		-fmodule-file=c=%t/c.pcm -fmodule-file=d=%t/d.pcm -fmodule-file=e=%t/e.pcm \
 // RUN:		-fmodule-file=f=%t/f.pcm -verify -fsyntax-only 
 
+// Test again with reduced BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-reduced-module-interface -fprebuilt-module-path=%t -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-reduced-module-interface -fprebuilt-module-path=%t -o %t/c.pcm
+// RUN: %clang_cc1 -std=c++20 %t/d.cppm -emit-reduced-module-interface -fprebuilt-module-path=%t -o %t/d.pcm
+// RUN: %clang_cc1 -std=c++20 %t/e.cppm -emit-reduced-module-interface -fprebuilt-module-path=%t -o %t/e.pcm
+// RUN: %clang_cc1 -std=c++20 %t/f.cppm -emit-reduced-module-interface -fprebuilt-module-path=%t -o %t/f.pcm
+// RUN: %clang_cc1 -std=c++20 %t/g.cppm -fprebuilt-module-path=%t -verify -fsyntax-only 
+
+
 //--- a.cppm
 export module a;
 
diff --git a/clang/test/Modules/pr60085.cppm b/clang/test/Modules/pr60085.cppm
index fd6fd914a543c3f1b44d023333ec2a40c6511f5a..37d8b09350b42b96f5ffd93ad8b354db1a30f4e6 100644
--- a/clang/test/Modules/pr60085.cppm
+++ b/clang/test/Modules/pr60085.cppm
@@ -14,6 +14,23 @@
 // RUN:     -S -emit-llvm -disable-llvm-passes -o - -fprebuilt-module-path=%t \
 // RUN:     | FileCheck %t/a.cppm
 
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/d.cppm \
+// RUN:     -emit-reduced-module-interface -o %t/d.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.cppm \
+// RUN:     -emit-reduced-module-interface -o %t/c.pcm -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cppm \
+// RUN:     -emit-reduced-module-interface -o %t/b.pcm -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm \
+// RUN:     -emit-module-interface -o %t/a.pcm -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.pcm \
+// RUN:     -S -emit-llvm -disable-llvm-passes -o - -fprebuilt-module-path=%t \
+// RUN:		| FileCheck %t/a.cppm
+
 //--- d.cppm
 export module d;
 
diff --git a/clang/test/Modules/pr60275.cppm b/clang/test/Modules/pr60275.cppm
index 57b31c6952bea94df97be6de1287f761977ea963..eb1ebc0e4330aca7cf5c28292651c930ccae1234 100644
--- a/clang/test/Modules/pr60275.cppm
+++ b/clang/test/Modules/pr60275.cppm
@@ -5,7 +5,12 @@
 // RUN: split-file %s %t
 //
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -emit-module-interface %t/a.cppm -o %t/a.pcm
-// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cpp -fmodule-file=%t/a.pcm -emit-llvm -o - | FileCheck %t/b.cpp
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cpp -fmodule-file=a=%t/a.pcm -emit-llvm -o - | FileCheck %t/b.cpp
+
+// Test again with reduced BMI
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -emit-reduced-module-interface %t/a.cppm -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cpp -fmodule-file=a=%t/a.pcm -emit-llvm -o - | FileCheck %t/b.cpp
+
 //--- foo.h
 
 consteval void global() {}
diff --git a/clang/test/Modules/pr60486.cppm b/clang/test/Modules/pr60486.cppm
index 13802a4917e6e7f13a979af39606064eb1cca08c..1100662c43211ee068a2ba461ffadde796f7d2d0 100644
--- a/clang/test/Modules/pr60486.cppm
+++ b/clang/test/Modules/pr60486.cppm
@@ -7,6 +7,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm
 // RUN: %clang_cc1 -std=c++20 -fmodule-file=a=%t/a.pcm %t/b.cppm -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -fmodule-file=a=%t/a.pcm %t/b.cppm -fsyntax-only -verify
+
 //--- foo.h
 template
 struct s {
diff --git a/clang/test/Modules/pr60693.cppm b/clang/test/Modules/pr60693.cppm
index c50791083a5beae6f8ab27c5a6a05933ee66b23c..6fb3de60e59b0873fd3a6f5792bf266ee4f66a4a 100644
--- a/clang/test/Modules/pr60693.cppm
+++ b/clang/test/Modules/pr60693.cppm
@@ -7,6 +7,10 @@
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm -emit-module-interface -o %t/a.pcm
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -fmodule-file=a=%t/a.pcm %t/c.cpp -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cpp
 
+// Test again with reduced BMI
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -fmodule-file=a=%t/a.pcm %t/c.cpp -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cpp
+
 //--- a.cppm
 export module a;
 
diff --git a/clang/test/Modules/pr60775.cppm b/clang/test/Modules/pr60775.cppm
index 4db027ba3600a98fe8032668545c63c1edd73c53..35eb92512f42774f5b9e38924adeade58039ccc7 100644
--- a/clang/test/Modules/pr60775.cppm
+++ b/clang/test/Modules/pr60775.cppm
@@ -12,6 +12,19 @@
 // RUN: %clang_cc1 -std=c++20 %t/f.cppm -emit-module-interface -fmodule-file=c=%t/c.pcm -o %t/f.pcm
 // RUN: %clang_cc1 -std=c++20 %t/g.cpp -fmodule-file=f=%t/f.pcm -fmodule-file=c=%t/c.pcm  -verify -fsyntax-only
 
+// Test again with reduced BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -I%t -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cpp -fmodule-file=a=%t/a.pcm -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -I%t -emit-reduced-module-interface -o %t/c.pcm
+// RUN: %clang_cc1 -std=c++20 %t/d.cppm -emit-reduced-module-interface -fmodule-file=c=%t/c.pcm -o %t/d.pcm
+// RUN: %clang_cc1 -std=c++20 %t/e.cpp -fmodule-file=d=%t/d.pcm -fmodule-file=c=%t/c.pcm -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 %t/f.cppm -emit-reduced-module-interface -fmodule-file=c=%t/c.pcm -o %t/f.pcm
+// RUN: %clang_cc1 -std=c++20 %t/g.cpp -fmodule-file=f=%t/f.pcm -fmodule-file=c=%t/c.pcm  -verify -fsyntax-only
+
 //--- initializer_list.h
 namespace std {
   typedef decltype(sizeof(int)) size_t;
diff --git a/clang/test/Modules/pr60890.cppm b/clang/test/Modules/pr60890.cppm
index 2560bec5b43351a4ab9560d436c0e5a992766c3e..488b512aaac2934c939b62b70b6ca2c586c4e5b1 100644
--- a/clang/test/Modules/pr60890.cppm
+++ b/clang/test/Modules/pr60890.cppm
@@ -9,6 +9,12 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/c.cppm -fprebuilt-module-path=%t -o %t/c.pcm
 // RUN: %clang_cc1 -std=c++20 %t/d.cpp -fprebuilt-module-path=%t -S -emit-llvm -o -
 
+// Test again with reduced BMI
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/a.cppm -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/b.cppm -fprebuilt-module-path=%t -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/c.cppm -fprebuilt-module-path=%t -o %t/c.pcm
+// RUN: %clang_cc1 -std=c++20 %t/d.cpp -fprebuilt-module-path=%t -S -emit-llvm -o -
+
 //--- a.cppm
 export module a;
  
diff --git a/clang/test/Modules/pr61065.cppm b/clang/test/Modules/pr61065.cppm
index cf6fcdda78cd446999a9b2fa11cf2737ee9f1314..c79d7ac4457a1144a89e43d3093c135a98b5c152 100644
--- a/clang/test/Modules/pr61065.cppm
+++ b/clang/test/Modules/pr61065.cppm
@@ -10,6 +10,19 @@
 // DISABLED:     -fprebuilt-module-path=%t
 // DISABLED: %clang_cc1 -std=c++20 %t/d.cpp -fsyntax-only -verify -fprebuilt-module-path=%t
 
+// Test again with reduced BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-reduced-module-interface -o %t/b.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// DISABLED: %clang_cc1 -std=c++20 %t/c.cppm -emit-reduced-module-interface -o %t/c.pcm \
+// DISABLED:     -fprebuilt-module-path=%t
+// DISABLED: %clang_cc1 -std=c++20 %t/d.cpp -fsyntax-only -verify -fprebuilt-module-path=%t
+
+
 //--- a.cppm
 export module a;
 
diff --git a/clang/test/Modules/pr61065_2.cppm b/clang/test/Modules/pr61065_2.cppm
index 10cc1a06b7e450a5c53b90285b2caa7e9234f66d..e898f4086af1de56c928b71e2f3f192f17d58007 100644
--- a/clang/test/Modules/pr61065_2.cppm
+++ b/clang/test/Modules/pr61065_2.cppm
@@ -11,6 +11,21 @@
 // RUN:     -fprebuilt-module-path=%t
 // RUN: %clang_cc1 -std=c++20 %t/e.cpp -fsyntax-only -verify -fprebuilt-module-path=%t
 
+// Test again with reduced BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-reduced-module-interface -o %t/b.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-reduced-module-interface -o %t/c.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/d.cppm -emit-reduced-module-interface -o %t/d.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/e.cpp -fsyntax-only -verify -fprebuilt-module-path=%t
+
+
 //--- a.cppm
 export module a;
 
diff --git a/clang/test/Modules/pr61067.cppm b/clang/test/Modules/pr61067.cppm
index baee4b83de5660d658941dd96111d8355df944a8..b7f9d22e253854c5354eca2cf52266863078dabd 100644
--- a/clang/test/Modules/pr61067.cppm
+++ b/clang/test/Modules/pr61067.cppm
@@ -12,6 +12,20 @@
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.cpp -fmodule-file=a=%t/a.pcm \
 // RUN:     -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cpp
 
+// Test again with reduced BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm \
+// RUN:     -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cppm \
+// RUN:     -emit-module-interface -fmodule-file=a=%t/a.pcm -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.pcm -S \
+// RUN:     -emit-llvm -fmodule-file=a=%t/a.pcm -disable-llvm-passes -o - | FileCheck %t/b.cppm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.cpp -fmodule-file=a=%t/a.pcm \
+// RUN:     -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cpp
+
 //--- a.cppm
 export module a;
 
diff --git a/clang/test/Modules/pr61317.cppm b/clang/test/Modules/pr61317.cppm
index 4b54d26dc5a63bb05fcb11b04ef37fee0bd9c89b..9ed20e7947062f03a74ce634b7a9125b81624d48 100644
--- a/clang/test/Modules/pr61317.cppm
+++ b/clang/test/Modules/pr61317.cppm
@@ -8,6 +8,15 @@
 // RUN:     -fprebuilt-module-path=%t
 // RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-reduced-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-reduced-module-interface -o %t/B.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+
 //--- foo.h
 #ifndef _FOO
 #define _FOO
diff --git a/clang/test/Modules/pr61783.cppm b/clang/test/Modules/pr61783.cppm
index 9cf773b0b282baae4455fb4ec237fde01f87c251..c3bc853d2dee8ef880848cf454db133311e3f9a7 100644
--- a/clang/test/Modules/pr61783.cppm
+++ b/clang/test/Modules/pr61783.cppm
@@ -9,6 +9,14 @@
 // RUN: %clang_cc1 -std=c++20 -triple x86_64-pc-windows-msvc19.11.0 -fms-extensions %t/user.cpp -fmodule-file=mod=%t/mod.pcm \
 // RUN:     -S -emit-llvm -o - | FileCheck %t/user.cpp
 
+// Test again with reduced BMI
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-pc-windows-msvc19.11.0 -fms-extensions %t/mod.cppm -emit-reduced-module-interface \
+// RUN:     -o %t/mod.pcm
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-pc-windows-msvc19.11.0 -fms-extensions %t/mod.pcm -S -emit-llvm -o - | \
+// RUN:     FileCheck %t/mod.cppm
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-pc-windows-msvc19.11.0 -fms-extensions %t/user.cpp -fmodule-file=mod=%t/mod.pcm \
+// RUN:     -S -emit-llvm -o - | FileCheck %t/user.cpp
+
 //--- mod.cppm
 module;
 
diff --git a/clang/test/Modules/pr61892.cppm b/clang/test/Modules/pr61892.cppm
index 99d02f36b2b54b3785fb95f05379e02210b4fbdd..7b8905036cd449f0dd2b6131fe64bbf2a16aa748 100644
--- a/clang/test/Modules/pr61892.cppm
+++ b/clang/test/Modules/pr61892.cppm
@@ -2,11 +2,25 @@
 // RUN: mkdir -p %t
 // RUN: split-file %s %t
 //
+// RUNX: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \
+// RUNX:     -emit-module-interface %t/a.cppm -o %t/a.pcm
+// RUNX: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \
+// RUNX:     %t/b.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \
+// RUNX:     -emit-llvm -o - | FileCheck %t/b.cpp
+// RUNX: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \
+// RUNX:     %t/c.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \
+// RUNX:     -emit-llvm -o - | FileCheck %t/c.cpp
+
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \
-// RUN:     -emit-module-interface %t/a.cppm -o %t/a.pcm
-// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \
-// RUN:     %t/b.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \
-// RUN:     -emit-llvm -o - | FileCheck %t/b.cpp
+// RUN:     -emit-reduced-module-interface %t/a.cppm -o %t/a.pcm
+// RUNX: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \
+// RUNX:     %t/b.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \
+// RUNX:     -emit-llvm -o - | FileCheck %t/b.cpp
 // RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple \
 // RUN:     %t/c.cpp -fmodule-file=a=%t/a.pcm -disable-llvm-passes \
 // RUN:     -emit-llvm -o - | FileCheck %t/c.cpp
@@ -23,20 +37,10 @@ struct integer {
 export template
 int a = static_cast(integer());
 
-struct s {
-    ~s();
-    operator int() const;
-};
-
-export template
-auto d = s();
-
 int aa() {
-	return a + d;
+	return a;
 }
 
-int dynamic_func();
-export inline int dynamic_var = dynamic_func();
 
 //--- b.cpp
 import a;
@@ -53,13 +57,9 @@ void b() {}
 //--- c.cpp
 import a;
 int c() {
-    return a + d + dynamic_var;
+    return a;
 }
 
 // The used variables are generated normally
 // CHECK-DAG: @_ZW1a1aIvE =
-// CHECK-DAG: @_ZW1a1dIvE =
-// CHECK-DAG: @_ZW1a11dynamic_var = linkonce_odr
 // CHECK-DAG: @_ZGVW1a1aIvE =
-// CHECk-DAG: @_ZGVW1a1dIvE =
-// CHECK-DAG: @_ZGVW1a11dynamic_var = linkonce_odr
diff --git a/clang/test/Modules/pr62158.cppm b/clang/test/Modules/pr62158.cppm
index 7a0761df77158079c6e2e6f501aff665fa0f6246..bb488fff108f2826f199b35021dfcf89f91caece 100644
--- a/clang/test/Modules/pr62158.cppm
+++ b/clang/test/Modules/pr62158.cppm
@@ -6,6 +6,15 @@
 // RUN: %clang_cc1 -std=c++20 %t/main.cpp -fmodule-file=lib=%t/lib.pcm \
 // RUN:     -verify -fsyntax-only
 
+// Test again with reduced BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/lib.cppm -o %t/lib.pcm
+// RUN: %clang_cc1 -std=c++20 %t/main.cpp -fmodule-file=lib=%t/lib.pcm \
+// RUN:     -verify -fsyntax-only
+
 //--- header.h
 namespace lib::inline __1 {
 template 
diff --git a/clang/test/Modules/pr62359.cppm b/clang/test/Modules/pr62359.cppm
index 4632457e57f189e011af1302acedb8c85b6e2336..69acc3ce303a57481e03ba94bef831d0807bc9bc 100644
--- a/clang/test/Modules/pr62359.cppm
+++ b/clang/test/Modules/pr62359.cppm
@@ -12,6 +12,22 @@
 // RUN: %clang_cc1 -std=c++20 -fopenmp %t/use.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only -verify
 // RUN: %clang_cc1 -std=c++20 -fopenmp %t/use2.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only -verify
 
+// Test again with reduced BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/Hello.cppm -o %t/Hello.pcm
+// RUN: not %clang_cc1 -std=c++20 -fopenmp %t/use.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only \
+// RUN:     2>&1 | FileCheck %t/use.cpp
+// RUN: not %clang_cc1 -std=c++20 -fopenmp %t/use2.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only \
+// RUN:     2>&1 | FileCheck %t/use2.cpp
+//
+// RUN: %clang_cc1 -std=c++20 -fopenmp -emit-reduced-module-interface %t/Hello.cppm -o %t/Hello.pcm
+// RUN: %clang_cc1 -std=c++20 -fopenmp %t/use.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only -verify
+// RUN: %clang_cc1 -std=c++20 -fopenmp %t/use2.cpp -fmodule-file=hello=%t/Hello.pcm -fsyntax-only -verify
+
+
 //--- Hello.cppm
 export module hello;
 export void hello() {
diff --git a/clang/test/Modules/pr62589.cppm b/clang/test/Modules/pr62589.cppm
index 4164c3405ac0e3b2ae08df6e3771b407bad936b0..c5aec3ed81846f0523fc4e9b14ef5bbd568e6344 100644
--- a/clang/test/Modules/pr62589.cppm
+++ b/clang/test/Modules/pr62589.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++23 -emit-module-interface %t/a.cppm -o %t/a.pcm
 // RUN: %clang_cc1 -std=c++23 %t/b.cpp -fmodule-file=a=%t/a.pcm -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++23 -emit-reduced-module-interface %t/a.cppm -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++23 %t/b.cpp -fmodule-file=a=%t/a.pcm -fsyntax-only -verify
+
 //--- foo.h
 class TypeA {};
 
diff --git a/clang/test/Modules/pr62705.cppm b/clang/test/Modules/pr62705.cppm
index 00769d2277f4f101d6abfd23af1a1c0596b30683..9d996ae297d7af4046b428466fa3095b6a6f0dd7 100644
--- a/clang/test/Modules/pr62705.cppm
+++ b/clang/test/Modules/pr62705.cppm
@@ -10,6 +10,14 @@
 // RUN: %clang_cc1 %t/b.pcm -std=c++20 -triple %itanium_abi_triple \
 // RUN:     -fmodule-file=a=%t/a.pcm -emit-llvm -o - | FileCheck %t/b.cppm
 
+// RUN: %clang_cc1 %t/a.cppm -std=c++20 -triple %itanium_abi_triple \
+// RUN:     -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 %t/b.cppm -std=c++20 -triple %itanium_abi_triple \
+// RUN:     -emit-module-interface -o %t/b.pcm \
+// RUN:     -fmodule-file=a=%t/a.pcm
+// RUN: %clang_cc1 %t/b.pcm -std=c++20 -triple %itanium_abi_triple \
+// RUN:     -fmodule-file=a=%t/a.pcm -emit-llvm -o - | FileCheck %t/b.cppm
+
 //--- foo.h
 namespace n {
 
diff --git a/clang/test/Modules/pr62796.cppm b/clang/test/Modules/pr62796.cppm
index f96e54bc6adedec4b4a5183d0ef348fdc4139fbc..58b72164e88bfcd04d73dc1cec505cbf764842ce 100644
--- a/clang/test/Modules/pr62796.cppm
+++ b/clang/test/Modules/pr62796.cppm
@@ -6,6 +6,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fmodule-file=Fibonacci.Cache=%t/Cache.pcm \
 // RUN:     -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/Cache.cppm -o %t/Cache.pcm
+// RUN: %clang_cc1 -std=c++20 %t/Use.cpp -fmodule-file=Fibonacci.Cache=%t/Cache.pcm \
+// RUN:     -fsyntax-only -verify
+
 //--- Cache.cppm
 export module Fibonacci.Cache;
 
diff --git a/clang/test/Modules/pr62943.cppm b/clang/test/Modules/pr62943.cppm
index 27868b78220f5c92006a059d9dd8d77fbadb5296..c3a373814a439873fb14fe4354e838a5387c8a0d 100644
--- a/clang/test/Modules/pr62943.cppm
+++ b/clang/test/Modules/pr62943.cppm
@@ -9,6 +9,18 @@
 // RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t \
 // RUN:     -fsyntax-only -verify
 
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-reduced-module-interface -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-reduced-module-interface \
+// RUN:     -fprebuilt-module-path=%t -o %t/c.pcm
+// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t \
+// RUN:     -fsyntax-only -verify
+
 //--- foo.h
 #ifndef FOO_H
 #define FOO_H
diff --git a/clang/test/Modules/pr63544.cppm b/clang/test/Modules/pr63544.cppm
index 16224cfd0109491a3f1c429ff841b29d1e4802f1..f079abaed09df8d735fde5123807201f9e9198d2 100644
--- a/clang/test/Modules/pr63544.cppm
+++ b/clang/test/Modules/pr63544.cppm
@@ -8,6 +8,18 @@
 // RUN:     -fprebuilt-module-path=%t
 // RUN: %clang_cc1 -std=c++23 %t/pr63544.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++23 %t/a.cppm -emit-reduced-module-interface -o %t/m-a.pcm
+// RUN: %clang_cc1 -std=c++23 %t/b.cppm -emit-reduced-module-interface -o %t/m-b.pcm
+// RUN: %clang_cc1 -std=c++23 %t/m.cppm -emit-reduced-module-interface -o %t/m.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++23 %t/pr63544.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+
+
 //--- foo.h
 
 namespace std {
diff --git a/clang/test/Modules/pr63595.cppm b/clang/test/Modules/pr63595.cppm
index 13a5f84a3e71f22133b2a95a25ba3bdf36623070..7c5395e065de540d1a4648d30ae67badd6827417 100644
--- a/clang/test/Modules/pr63595.cppm
+++ b/clang/test/Modules/pr63595.cppm
@@ -6,6 +6,16 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface -I%t %t/module2.cppm -o %t/module2.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/merge.cpp -verify -fsyntax-only
 
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface -I%t %t/module1.cppm -o %t/module1.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface -I%t %t/module2.cppm -o %t/module2.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/merge.cpp -verify -fsyntax-only
+
+
 //--- header.h
 namespace NS {
 template 
diff --git a/clang/test/Modules/pr67627.cppm b/clang/test/Modules/pr67627.cppm
index 3d4410229080a983fa16b04c42b09329780b20a8..d3f8496c47c2a73932302136dd6d156de85cd9bb 100644
--- a/clang/test/Modules/pr67627.cppm
+++ b/clang/test/Modules/pr67627.cppm
@@ -5,6 +5,10 @@
 // RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
 // RUN: %clang_cc1 -std=c++20 %t/B.cppm -fmodule-file=A=%t/A.pcm -fsyntax-only -verify
 
+// RUN: rm %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-reduced-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -fmodule-file=A=%t/A.pcm -fsyntax-only -verify
+
 //--- A.cppm
 export module A;
 
diff --git a/clang/test/Modules/pr67893.cppm b/clang/test/Modules/pr67893.cppm
index 00b024ecc2eb11f6132d6dedb9ccae8b7e5c5550..58990cec01d6666a92e545bd7d539d0d2648ba0e 100644
--- a/clang/test/Modules/pr67893.cppm
+++ b/clang/test/Modules/pr67893.cppm
@@ -9,6 +9,15 @@
 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm  \
 // RUN:      -fprebuilt-module-path=%t -S -emit-llvm -o - | FileCheck %t/m.cppm
 
+// Test again with reduced BMI
+//
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/a.cppm \
+// RUN:      -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.cppm \
+// RUN:      -emit-reduced-module-interface -fprebuilt-module-path=%t -o %t/m.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %t/m.pcm  \
+// RUN:      -fprebuilt-module-path=%t -S -emit-llvm -o - | FileCheck %t/m.cppm
+
 //--- a.cppm
 export module a;
 export struct A {
diff --git a/clang/test/Modules/predefined.cpp b/clang/test/Modules/predefined.cpp
index fbe0c4e23ca59cf323a724e5fd23430eab6944e4..8f897f5ace938f33c0213eb7d9e665f44027fee6 100644
--- a/clang/test/Modules/predefined.cpp
+++ b/clang/test/Modules/predefined.cpp
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -x c++ -std=c++20 -emit-module-interface a.h -o a.pcm -fms-extensions -verify
 // RUN: %clang_cc1 -std=c++20 a.cpp -fmodule-file=A=a.pcm -fms-extensions -fsyntax-only -verify
 
+// RUN: %clang_cc1 -x c++ -std=c++20 -emit-reduced-module-interface a.h -o a.pcm -fms-extensions -verify
+// RUN: %clang_cc1 -std=c++20 a.cpp -fmodule-file=A=a.pcm -fms-extensions -fsyntax-only -verify
+
 //--- a.h
 
 // expected-no-diagnostics
diff --git a/clang/test/Modules/preferred_name.cppm b/clang/test/Modules/preferred_name.cppm
index 46ad96cb1abc33cac1650f9708416ecfa626455d..2f17058678455c454f178e826079f970604779b8 100644
--- a/clang/test/Modules/preferred_name.cppm
+++ b/clang/test/Modules/preferred_name.cppm
@@ -8,6 +8,16 @@
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cppm -verify -fsyntax-only
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use1.cpp -verify -fsyntax-only
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use2.cpp -verify -fsyntax-only
+
+// Test again with reduced BMI.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-reduced-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use.cppm -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use1.cpp -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/Use2.cpp -verify -fsyntax-only
 //
 //--- foo.h
 template
diff --git a/clang/test/Modules/redefinition-merges.cppm b/clang/test/Modules/redefinition-merges.cppm
index 9ab4006f985fa941909ffe8b7b5b50bbba023f9a..13032b22ee60e43207d9fd27befe0f373d96d82b 100644
--- a/clang/test/Modules/redefinition-merges.cppm
+++ b/clang/test/Modules/redefinition-merges.cppm
@@ -12,6 +12,12 @@
 // RUN: %clang_cc1 -std=c++20 -I%t %t/M.cppm -emit-module-interface -o %t/M.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use1.cpp -verify -fsyntax-only
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use2.cpp -verify -fsyntax-only
+
+// / Test again with reduced BMI.
+// RUN: %clang_cc1 -std=c++20 -I%t %t/M.cppm -emit-reduced-module-interface -o %t/M.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use1.cpp -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use2.cpp -verify -fsyntax-only
+
 //
 //--- foo.h
 #ifndef FOO
diff --git a/clang/test/Modules/redundant-template-default-arg.cpp b/clang/test/Modules/redundant-template-default-arg.cpp
index 6807b45e513954c9daf93955b1f3bbfb4055a1c8..20a806c4c818ab837bbd7d559feaca1e1da954ac 100644
--- a/clang/test/Modules/redundant-template-default-arg.cpp
+++ b/clang/test/Modules/redundant-template-default-arg.cpp
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1  -std=c++20 %t/foo.cppm -I%t -emit-module-interface -o %t/foo.pcm
 // RUN: %clang_cc1  -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -I%t -fsyntax-only -verify
 
+// RUN: %clang_cc1  -std=c++20 %t/foo.cppm -I%t -emit-reduced-module-interface -o %t/foo.pcm
+// RUN: %clang_cc1  -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -I%t -fsyntax-only -verify
+
 //--- foo.h
 template 
 T u;
diff --git a/clang/test/Modules/redundant-template-default-arg2.cpp b/clang/test/Modules/redundant-template-default-arg2.cpp
index 41deb112cfa6eaef6d990318770698c51eb913ed..ae1f0c7e69cc06ece8ab6e0cb47d725bf1d18617 100644
--- a/clang/test/Modules/redundant-template-default-arg2.cpp
+++ b/clang/test/Modules/redundant-template-default-arg2.cpp
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/foo.cppm -I%t -emit-module-interface -o %t/foo.pcm
 // RUN: %clang_cc1 -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 %t/foo.cppm -I%t -emit-reduced-module-interface -o %t/foo.pcm
+// RUN: %clang_cc1 -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -fsyntax-only -verify
+
 //--- foo.cppm
 export module foo;
 export template 
diff --git a/clang/test/Modules/redundant-template-default-arg3.cpp b/clang/test/Modules/redundant-template-default-arg3.cpp
index 8bb222ac91ffce1f491c7cba55c3eab3bbe96c29..e4464c40e976874ced3c93120dc2e92b9329fe78 100644
--- a/clang/test/Modules/redundant-template-default-arg3.cpp
+++ b/clang/test/Modules/redundant-template-default-arg3.cpp
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1  -std=c++20 %t/foo.cppm -I%t -emit-module-interface -o %t/foo.pcm
 // RUN: %clang_cc1  -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -I%t/. -fsyntax-only -verify
 
+// RUN: %clang_cc1  -std=c++20 %t/foo.cppm -I%t -emit-reduced-module-interface -o %t/foo.pcm
+// RUN: %clang_cc1  -fprebuilt-module-path=%t -std=c++20 %t/use.cpp -I%t/. -fsyntax-only -verify
+
 //--- foo.h
 template 
 T v;
diff --git a/clang/test/Modules/search-partitions.cpp b/clang/test/Modules/search-partitions.cpp
index 571160def7e9b7bc2b3b4df358e2266c74f2b32d..92732958db94e6ffcb00de25784797a8a0037bc6 100644
--- a/clang/test/Modules/search-partitions.cpp
+++ b/clang/test/Modules/search-partitions.cpp
@@ -14,6 +14,22 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/moduleA.cpp \
 // RUN:  -fprebuilt-module-path=%t
 
+// Test again with reduced BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/partition1.cpp \
+// RUN:  -o %t/A-Part1.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/partition2.cpp \
+// RUN:  -o %t/A-Part2.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/partition3.cpp \
+// RUN:  -o %t/A-Part3.pcm
+
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only %t/moduleA.cpp -fprebuilt-module-path=%t 
+
 // expected-no-diagnostics
 
 //--- partition1.cpp
diff --git a/clang/test/Modules/seperated-member-function-definition-for-template-class.cppm b/clang/test/Modules/seperated-member-function-definition-for-template-class.cppm
index e32da39d9df1af4edb007a4f30dbf4542e5bb2d5..1465c33c3625c862d0f0e3a6bf6a1b3aedf48ec6 100644
--- a/clang/test/Modules/seperated-member-function-definition-for-template-class.cppm
+++ b/clang/test/Modules/seperated-member-function-definition-for-template-class.cppm
@@ -12,6 +12,18 @@
 // RUN:     -fprebuilt-module-path=%t
 // RUN: %clang_cc1 -std=c++20 %t/use.cpp -fsyntax-only -verify -fprebuilt-module-path=%t
 
+// Test again with reduced BMI
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/base.cppm -emit-reduced-module-interface -o %t/package-base.pcm
+// RUN: %clang_cc1 -std=c++20 %t/child.cppm -emit-reduced-module-interface -o %t/package-child.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/package.cppm -emit-reduced-module-interface -o %t/package.pcm \
+// RUN:     -fprebuilt-module-path=%t
+// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fsyntax-only -verify -fprebuilt-module-path=%t
+
 //--- base.cppm
 export module package:base;
 
diff --git a/clang/test/Modules/template-function-specialization.cpp b/clang/test/Modules/template-function-specialization.cpp
index 3eac92e7edb94c917c00c32baf1f50ea8e514f55..1b6bf2de6ba1d9b4e76ade401e55fd7a4bf78b8e 100644
--- a/clang/test/Modules/template-function-specialization.cpp
+++ b/clang/test/Modules/template-function-specialization.cpp
@@ -4,7 +4,10 @@
 //
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/foo.cppm -o %t/foo.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
-//
+
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/foo.cppm -o %t/foo.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+
 //--- foo.cppm
 module;
 # 3 __FILE__ 1 // use the next physical line number here (and below)
diff --git a/clang/test/Modules/template-lambdas.cppm b/clang/test/Modules/template-lambdas.cppm
index 69117a1a04fc7b6c101e532fc6bb62caa20754d7..e82cb1f3ad85ac83f869ee4cbc6f895239ed2024 100644
--- a/clang/test/Modules/template-lambdas.cppm
+++ b/clang/test/Modules/template-lambdas.cppm
@@ -12,6 +12,21 @@
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \
 // RUN:    -verify -DUSE_LAMBDA2
 
+// Test again with reduced BMI
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/template_lambdas.cppm -emit-reduced-module-interface \
+// RUN:    -o %t/lambdas.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \
+// RUN:    -verify
+//
+// RUN: %clang_cc1 -std=c++20 %t/template_lambdas2.cppm -emit-reduced-module-interface \
+// RUN:    -o %t/lambdas2.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only \
+// RUN:    -verify -DUSE_LAMBDA2
+
 //--- lambdas.h
 auto l1 = []() constexpr -> int {
     return I;
diff --git a/clang/test/Modules/template-pack.cppm b/clang/test/Modules/template-pack.cppm
index eca17f31f015e5ef13bcbdcc29efa1647a783675..278c1c2d54ccf536f914a1bba9bf629c43e65623 100644
--- a/clang/test/Modules/template-pack.cppm
+++ b/clang/test/Modules/template-pack.cppm
@@ -5,6 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/a.cppm -o %t/a.pcm
 // RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t -fsyntax-only -verify
 
+// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/a.cppm -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -fprebuilt-module-path=%t -fsyntax-only -verify
+
 //--- foo.h
 
 namespace std
diff --git a/clang/test/Modules/template_default_argument.cpp b/clang/test/Modules/template_default_argument.cpp
index 5a7d1c04cf1817508195e44f743281c0e728380b..202f8dd40d7a94785a4024fdb73e40763322787f 100644
--- a/clang/test/Modules/template_default_argument.cpp
+++ b/clang/test/Modules/template_default_argument.cpp
@@ -4,6 +4,9 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-module-interface -o %t/B.pcm
 // RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 %t/B.cppm -emit-reduced-module-interface -o %t/B.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -fsyntax-only -verify
 //
 //--- templ.h
 template 
diff --git a/clang/test/Modules/transitive-import.cppm b/clang/test/Modules/transitive-import.cppm
new file mode 100644
index 0000000000000000000000000000000000000000..0eed8cfe2f0aeb9c867445cb8c01f09ab4cbc8fe
--- /dev/null
+++ b/clang/test/Modules/transitive-import.cppm
@@ -0,0 +1,109 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/Invisible.cppm -emit-module-interface -o %t/Invisible.pcm
+// RUN: %clang_cc1 -std=c++20 %t/Other.cppm -emit-module-interface -fprebuilt-module-path=%t \
+// RUN:     -o %t/Other.pcm
+// RUN: %clang_cc1 -std=c++20 %t/Another.cppm -emit-module-interface -o %t/Another.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A-interface.cppm -emit-module-interface \
+// RUN:     -fprebuilt-module-path=%t -o %t/A-interface.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A-interface2.cppm -emit-module-interface \
+// RUN:     -fprebuilt-module-path=%t -o %t/A-interface2.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A-interface3.cppm -emit-module-interface \
+// RUN:     -fprebuilt-module-path=%t -o %t/A-interface3.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface \
+// RUN:     -fprebuilt-module-path=%t -o %t/A.pcm
+
+// RUN: %clang_cc1 -std=c++20 %t/A.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+// RUN: %clang_cc1 -std=c++20 %t/A-impl.cppm -fprebuilt-module-path=%t -fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 %t/A-impl2.cppm -fprebuilt-module-path=%t -fsyntax-only -verify
+
+//--- Invisible.cppm
+export module Invisible;
+export void invisible() {}
+
+//--- Other.cppm
+export module Other;
+import Invisible;
+export void other() {}
+
+//--- Another.cppm
+export module Another;
+export void another() {}
+
+//--- A-interface.cppm
+export module A:interface;
+import Other;
+export void a_interface() {}
+
+//--- A-interface2.cppm
+export module A:interface2;
+import Another;
+export void a_interface2() {}
+
+//--- A-interface3.cppm
+export module A:interface3;
+import :interface;
+import :interface2;
+export void a_interface3() {}
+
+//--- A.cppm
+export module A;
+import Another;
+import :interface;
+import :interface2;
+import :interface3;
+
+export void a() {}
+export void impl();
+
+//--- A.cpp
+module A;
+void impl() {
+    a_interface();
+    a_interface2();
+    a_interface3();
+
+    other();
+    another();
+
+    invisible(); // expected-error {{declaration of 'invisible' must be imported from module 'Invisible' before it is required}}
+                 // expected-note@* {{declaration here is not visible}}
+}
+
+//--- A-impl.cppm
+module A:impl;
+import :interface3;
+
+void impl_part() {
+    a_interface();
+    a_interface2();
+    a_interface3();
+
+    other();
+    another();
+
+    invisible(); // expected-error {{declaration of 'invisible' must be imported from module 'Invisible' before it is required}}
+                 // expected-note@* {{declaration here is not visible}}
+}
+
+//--- A-impl2.cppm
+module A:impl2;
+import A;
+
+void impl_part2() {
+    a();
+    impl();
+
+    a_interface();
+    a_interface2();
+    a_interface3();
+
+    other();
+    another();
+
+    invisible(); // expected-error {{declaration of 'invisible' must be imported from module 'Invisible' before it is required}}
+                 // expected-note@* {{declaration here is not visible}}
+}
diff --git a/clang/test/OpenMP/amdgcn_target_device_vla.cpp b/clang/test/OpenMP/amdgcn_target_device_vla.cpp
index de150a0fcb4afd23854ac78630b72d5b9c864bb9..58fef517a9e72d2eaeb8aff57355697b9af2f458 100644
--- a/clang/test/OpenMP/amdgcn_target_device_vla.cpp
+++ b/clang/test/OpenMP/amdgcn_target_device_vla.cpp
@@ -539,7 +539,7 @@ int main() {
 // CHECK:       omp.loop.exit:
 // CHECK-NEXT:    [[TMP34:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR_ASCAST]], align 8
 // CHECK-NEXT:    [[TMP35:%.*]] = load i32, ptr [[TMP34]], align 4
-// CHECK-NEXT:    call void @__kmpc_distribute_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB2]] to ptr), i32 [[TMP35]])
+// CHECK-NEXT:    call void @__kmpc_for_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB3]] to ptr), i32 [[TMP35]])
 // CHECK-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK:       omp.precond.end:
 // CHECK-NEXT:    ret void
diff --git a/clang/test/OpenMP/amdgpu_target_with_aligned_attribute.c b/clang/test/OpenMP/amdgpu_target_with_aligned_attribute.c
index dd33e8405c34247ee1eb17e3284626e56f789ba5..cc0cc0def48b8111fbb4437e6dac8fd44d59f824 100644
--- a/clang/test/OpenMP/amdgpu_target_with_aligned_attribute.c
+++ b/clang/test/OpenMP/amdgpu_target_with_aligned_attribute.c
@@ -301,7 +301,7 @@ void write_to_aligned_array(int *a, int N) {
 // CHECK-AMD:       omp.loop.exit:
 // CHECK-AMD-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR_ASCAST]], align 8
 // CHECK-AMD-NEXT:    [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
-// CHECK-AMD-NEXT:    call void @__kmpc_distribute_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB2]] to ptr), i32 [[TMP18]])
+// CHECK-AMD-NEXT:    call void @__kmpc_for_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB3]] to ptr), i32 [[TMP18]])
 // CHECK-AMD-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK-AMD:       omp.precond.end:
 // CHECK-AMD-NEXT:    ret void
diff --git a/clang/test/OpenMP/atomic_read_codegen.c b/clang/test/OpenMP/atomic_read_codegen.c
index b60e1686d4dab0b05d340c8dce078e4de44168cc..0a68c8e2c35a5636f4ccb80be25fd6bd21394a8d 100644
--- a/clang/test/OpenMP/atomic_read_codegen.c
+++ b/clang/test/OpenMP/atomic_read_codegen.c
@@ -128,13 +128,11 @@ int main(void) {
 // CHECK: store i64
 #pragma omp atomic read
   ullv = ullx;
-// CHECK: load atomic i32, ptr {{.*}} monotonic, align 4
-// CHECK: bitcast i32 {{.*}} to float
+// CHECK: load atomic float, ptr {{.*}} monotonic, align 4
 // CHECK: store float
 #pragma omp atomic read
   fv = fx;
-// CHECK: load atomic i64, ptr {{.*}} monotonic, align 8
-// CHECK: bitcast i64 {{.*}} to double
+// CHECK: load atomic double, ptr {{.*}} monotonic, align 8
 // CHECK: store double
 #pragma omp atomic read
   dv = dx;
@@ -194,11 +192,11 @@ int main(void) {
 // CHECK: store i64
 #pragma omp atomic read
   lv = cix;
-// CHECK: load atomic i32, ptr {{.*}} monotonic, align 4
+// CHECK: load atomic float, ptr {{.*}} monotonic, align 4
 // CHECK: store i64
 #pragma omp atomic read
   ulv = fx;
-// CHECK: load atomic i64, ptr {{.*}} monotonic, align 8
+// CHECK: load atomic double, ptr {{.*}} monotonic, align 8
 // CHECK: store i64
 #pragma omp atomic read
   llv = dx;
diff --git a/clang/test/OpenMP/atomic_write_codegen.c b/clang/test/OpenMP/atomic_write_codegen.c
index 24dfbf9c0e8fc78d8e16219ccbc3c1538bd0570c..afe8737d30b06584fe1ac28eab8914be184698d3 100644
--- a/clang/test/OpenMP/atomic_write_codegen.c
+++ b/clang/test/OpenMP/atomic_write_codegen.c
@@ -131,13 +131,11 @@ int main(void) {
 #pragma omp atomic write
   ullx = ullv;
 // CHECK: load float, ptr
-// CHECK: bitcast float {{.*}} to i32
-// CHECK: store atomic i32 {{.*}}, ptr {{.*}} monotonic, align 4
+// CHECK: store atomic float {{.*}}, ptr {{.*}} monotonic, align 4
 #pragma omp atomic write
   fx = fv;
 // CHECK: load double, ptr
-// CHECK: bitcast double {{.*}} to i64
-// CHECK: store atomic i64 {{.*}}, ptr {{.*}} monotonic, align 8
+// CHECK: store atomic double {{.*}}, ptr {{.*}} monotonic, align 8
 #pragma omp atomic write
   dx = dv;
 // CHECK: [[LD:%.+]] = load x86_fp80, ptr
@@ -215,11 +213,11 @@ int main(void) {
 #pragma omp atomic write
   cix = lv;
 // CHECK: load i64, ptr
-// CHECK: store atomic i32 %{{.+}}, ptr {{.*}} monotonic, align 4
+// CHECK: store atomic float %{{.+}}, ptr {{.*}} monotonic, align 4
 #pragma omp atomic write
   fx = ulv;
 // CHECK: load i64, ptr
-// CHECK: store atomic i64 %{{.+}}, ptr {{.*}} monotonic, align 8
+// CHECK: store atomic double %{{.+}}, ptr {{.*}} monotonic, align 8
 #pragma omp atomic write
   dx = llv;
 // CHECK: load i64, ptr
@@ -491,8 +489,7 @@ int main(void) {
   float2x.x = ulv;
 // CHECK: call i32 @llvm.read_register.i32(
 // CHECK: sitofp i32 %{{.+}} to double
-// CHECK: bitcast double %{{.+}} to i64
-// CHECK: store atomic i64 %{{.+}}, ptr @{{.+}} seq_cst, align 8
+// CHECK: store atomic double %{{.+}}, ptr @{{.+}} seq_cst, align 8
 // CHECK: call{{.*}} @__kmpc_flush(
 #pragma omp atomic write seq_cst
   dv = rix;
diff --git a/clang/test/OpenMP/attr-assume.cpp b/clang/test/OpenMP/attr-assume.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..09c22f98d1e299ab3220d2e75d8d2b489a25b1e1
--- /dev/null
+++ b/clang/test/OpenMP/attr-assume.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
+[[omp::assume(3)]] void f1(); // expected-error {{expected string literal as argument of 'assume' attribute}}
+[[omp::assume(int)]] void f2(); // expected-error {{expected string literal as argument of 'assume' attribute}}
+[[omp::assume(for)]] void f3(); // expected-error {{expected string literal as argument of 'assume' attribute}}
+[[omp::assume("QQQQ")]] void f4(); // expected-warning {{unknown assumption string 'QQQQ'; attribute is potentially ignored}}
+[[omp::assume("omp_no_openmp")]] void f5();
+[[omp::assume("omp_noopenmp")]] void f6(); // expected-warning {{unknown assumption string 'omp_noopenmp' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp'?}}
+[[omp::assume("omp_no_openmp_routine")]] void f7(); // expected-warning {{unknown assumption string 'omp_no_openmp_routine' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp_routines'?}}
+[[omp::assume("omp_no_openmp1")]] void f8(); // expected-warning {{unknown assumption string 'omp_no_openmp1' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp'?}}
+[[omp::assume("omp_no_openmp", "omp_no_openmp")]] void f9(); // expected-error {{'assume' attribute takes one argument}}
+
+[[omp::assume(3)]] int g1; // expected-error {{expected string literal as argument of 'assume' attribute}}
+[[omp::assume("omp_no_openmp")]] int g2; // expected-warning {{'assume' attribute only applies to functions and Objective-C methods}}
diff --git a/clang/test/OpenMP/bug60602.cpp b/clang/test/OpenMP/bug60602.cpp
index 3ecc70cab778a1823905283e0acab8e363d017ae..48dc341a08224ec9d0483262536e2e564f824e7a 100644
--- a/clang/test/OpenMP/bug60602.cpp
+++ b/clang/test/OpenMP/bug60602.cpp
@@ -564,7 +564,7 @@ int kernel_within_loop(int *a, int *b, int N, int num_iters) {
 // CHECK:       omp.loop.exit:
 // CHECK-NEXT:    [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK-NEXT:    [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
-// CHECK-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP23]])
+// CHECK-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP23]])
 // CHECK-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK:       omp.precond.end:
 // CHECK-NEXT:    ret void
diff --git a/clang/test/OpenMP/declare_target_ast_print.cpp b/clang/test/OpenMP/declare_target_ast_print.cpp
index 40c5dd299abd9644df1fd72fd384b2382e87bca5..43cccf763e97c3af98f5bf2b6b2a6ded590065ca 100644
--- a/clang/test/OpenMP/declare_target_ast_print.cpp
+++ b/clang/test/OpenMP/declare_target_ast_print.cpp
@@ -360,6 +360,17 @@ int inner_link;
 // CHECK-NEXT: int inner_link;
 // CHECK-NEXT: #pragma omp end declare target
 
+void foo2() { return ;}
+// CHECK: #pragma omp declare target
+// CHECK-NEXT: void foo2() {
+// CHECK-NEXT: return;
+// CHECK-NEXT: }
+
+int x;
+// CHECK: #pragma omp declare target link
+// CHECK-NEXT: int x;
+// CHECK-NEXT: #pragma omp end declare target
+
 int main (int argc, char **argv) {
   foo();
   foo_c();
@@ -367,6 +378,14 @@ int main (int argc, char **argv) {
   test1();
   baz();
   baz();
+
+#if _OPENMP == 202111
+#pragma omp declare target enter(foo2)
+#else
+#pragma omp declare target to (foo2)
+#endif
+
+  #pragma omp declare target link(x)
   return (0);
 }
 
diff --git a/clang/test/OpenMP/declare_target_messages.cpp b/clang/test/OpenMP/declare_target_messages.cpp
index cf034aca7c9136f251932887a04775973755f555..de831f8575ee5f3551091683b2121ede4c37af6f 100644
--- a/clang/test/OpenMP/declare_target_messages.cpp
+++ b/clang/test/OpenMP/declare_target_messages.cpp
@@ -182,11 +182,20 @@ struct S {
 #pragma omp end declare target
 };
 
+void foo3() {
+  return;
+}
+
+int *y;
+int **w = &y;
 int main (int argc, char **argv) {
+  int a = 2;
 #pragma omp declare target // expected-error {{unexpected OpenMP directive '#pragma omp declare target'}}
   int v;
 #pragma omp end declare target // expected-error {{unexpected OpenMP directive '#pragma omp end declare target'}}
   foo(v);
+#pragma omp declare target to(foo3) link(w) // omp52-error {{unexpected 'to' clause, use 'enter' instead}} omp52-error {{expected at least one 'enter', 'link' or 'indirect' clause}}
+#pragma omp declare target to(a) //omp45-error {{local variable 'a' should not be used in 'declare target' directive}} omp5-error {{local variable 'a' should not be used in 'declare target' directive}} omp51-error {{local variable 'a' should not be used in 'declare target' directive}} omp52-error {{unexpected 'to' clause, use 'enter' instead}} omp52-error {{expected at least one 'enter', 'link' or 'indirect' clause}}
   return (0);
 }
 
diff --git a/clang/test/OpenMP/distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_codegen.cpp
index 95adefa8020f6267ce6210bab6491f60ddbddbf2..9cb0a15530651b4a2f0c5043a431a2023e93b1d8 100644
--- a/clang/test/OpenMP/distribute_parallel_for_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_codegen.cpp
@@ -1027,7 +1027,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -1266,7 +1266,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -1535,7 +1535,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -1774,7 +1774,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -2047,7 +2047,7 @@ int main() {
 // CHECK1:       omp.dispatch.end:
 // CHECK1-NEXT:    [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP41]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP41]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -2791,7 +2791,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    ret void
@@ -3023,7 +3023,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    ret void
@@ -3285,7 +3285,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    ret void
@@ -3517,7 +3517,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    ret void
@@ -3781,7 +3781,7 @@ int main() {
 // CHECK3:       omp.dispatch.end:
 // CHECK3-NEXT:    [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP41]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP41]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    ret void
@@ -5108,7 +5108,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -5337,7 +5337,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -5596,7 +5596,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -5825,7 +5825,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -6088,7 +6088,7 @@ int main() {
 // CHECK9:       omp.dispatch.end:
 // CHECK9-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -7414,12 +7414,12 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       cancel.exit:
 // CHECK9-NEXT:    [[TMP35:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP36:%.*]] = load i32, ptr [[TMP35]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP36]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP36]])
 // CHECK9-NEXT:    br label [[CANCEL_CONT:%.*]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    br label [[CANCEL_CONT]]
@@ -7650,7 +7650,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -7909,7 +7909,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -8138,7 +8138,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -8401,7 +8401,7 @@ int main() {
 // CHECK9:       omp.dispatch.end:
 // CHECK9-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -9715,7 +9715,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -9937,7 +9937,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -10189,7 +10189,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -10411,7 +10411,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -10665,7 +10665,7 @@ int main() {
 // CHECK11:       omp.dispatch.end:
 // CHECK11-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -11970,12 +11970,12 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       cancel.exit:
 // CHECK11-NEXT:    [[TMP35:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP36:%.*]] = load i32, ptr [[TMP35]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP36]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP36]])
 // CHECK11-NEXT:    br label [[CANCEL_CONT:%.*]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    br label [[CANCEL_CONT]]
@@ -12199,7 +12199,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -12451,7 +12451,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -12673,7 +12673,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -12927,7 +12927,7 @@ int main() {
 // CHECK11:       omp.dispatch.end:
 // CHECK11-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
diff --git a/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp
index 46c115e40e4356fa6a3de92441cdf3684754de7a..6084a9a6cf931457adf3a907d3e46a2fcdde62a2 100644
--- a/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_firstprivate_codegen.cpp
@@ -500,7 +500,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -748,7 +748,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -1167,7 +1167,7 @@ int main() {
 // CHECK8:       omp.loop.exit:
 // CHECK8-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK8-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK8-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK8-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK8-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]]) #[[ATTR4]]
 // CHECK8-NEXT:    [[ARRAY_BEGIN12:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR4]], i32 0, i32 0
 // CHECK8-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN12]], i64 2
@@ -1612,7 +1612,7 @@ int main() {
 // CHECK8:       omp.loop.exit:
 // CHECK8-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK8-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK8-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK8-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK8-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]]) #[[ATTR4]]
 // CHECK8-NEXT:    [[ARRAY_BEGIN12:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i32 0, i32 0
 // CHECK8-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN12]], i64 2
@@ -2080,7 +2080,7 @@ int main() {
 // CHECK10:       omp.loop.exit:
 // CHECK10-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK10-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK10-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR4]]
 // CHECK10-NEXT:    [[ARRAY_BEGIN10:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR3]], i32 0, i32 0
 // CHECK10-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN10]], i32 2
@@ -2519,7 +2519,7 @@ int main() {
 // CHECK10:       omp.loop.exit:
 // CHECK10-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK10-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK10-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR4]]
 // CHECK10-NEXT:    [[ARRAY_BEGIN10:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i32 0, i32 0
 // CHECK10-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN10]], i32 2
diff --git a/clang/test/OpenMP/distribute_parallel_for_if_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_if_codegen.cpp
index 846e7beb5d92ffe476373a37082ebb7a0644b618..d3b6654e57e2c99e76564e487d0ef5ce2d618eba 100644
--- a/clang/test/OpenMP/distribute_parallel_for_if_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_if_codegen.cpp
@@ -329,7 +329,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -472,7 +472,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -740,7 +740,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -883,7 +883,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1040,7 +1040,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1306,7 +1306,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1449,7 +1449,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1606,6 +1606,6 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
diff --git a/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp
index aa981f606cc876200d170967622dec73704e76f4..1f069c4070aecfa81c4a4ff68cca35117a3ec905 100644
--- a/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_lastprivate_codegen.cpp
@@ -443,7 +443,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]])
 // CHECK1-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK1-NEXT:    br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -708,7 +708,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]])
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK3-NEXT:    br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -1153,7 +1153,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK9-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK9-NEXT:    br i1 [[TMP24]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -1636,7 +1636,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK9-NEXT:    br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -2139,7 +2139,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK11-NEXT:    br i1 [[TMP24]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -2616,7 +2616,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK11-NEXT:    br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
diff --git a/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp
index 5d9244268d5546bf3a2e23507a8fef56a1d36bc0..b6ae783b74d049cf833e4849bcab1ae5096046ef 100644
--- a/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp
@@ -386,7 +386,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 // CHECK1:       terminate.lpad:
 // CHECK1-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -547,7 +547,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 // CHECK1:       terminate.lpad:
 // CHECK1-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -879,7 +879,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 // CHECK1:       terminate.lpad:
 // CHECK1-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -1026,7 +1026,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 // CHECK1:       terminate.lpad:
 // CHECK1-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -1173,7 +1173,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 // CHECK1:       terminate.lpad:
 // CHECK1-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -1335,7 +1335,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 // CHECK1:       terminate.lpad:
 // CHECK1-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -1638,7 +1638,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    ret void
 // CHECK5:       terminate.lpad:
 // CHECK5-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -1799,7 +1799,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    ret void
 // CHECK5:       terminate.lpad:
 // CHECK5-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -2122,7 +2122,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    ret void
 // CHECK5:       terminate.lpad:
 // CHECK5-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -2269,7 +2269,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    ret void
 // CHECK5:       terminate.lpad:
 // CHECK5-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -2416,7 +2416,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    ret void
 // CHECK5:       terminate.lpad:
 // CHECK5-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -2578,7 +2578,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    ret void
 // CHECK5:       terminate.lpad:
 // CHECK5-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -2890,7 +2890,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    ret void
 // CHECK9:       terminate.lpad:
 // CHECK9-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -3051,7 +3051,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    ret void
 // CHECK9:       terminate.lpad:
 // CHECK9-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -3383,7 +3383,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    ret void
 // CHECK9:       terminate.lpad:
 // CHECK9-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -3530,7 +3530,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    ret void
 // CHECK9:       terminate.lpad:
 // CHECK9-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -3677,7 +3677,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    ret void
 // CHECK9:       terminate.lpad:
 // CHECK9-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -3839,7 +3839,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    ret void
 // CHECK9:       terminate.lpad:
 // CHECK9-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -4142,7 +4142,7 @@ int main() {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK13-NEXT:    ret void
 // CHECK13:       terminate.lpad:
 // CHECK13-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -4303,7 +4303,7 @@ int main() {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK13-NEXT:    ret void
 // CHECK13:       terminate.lpad:
 // CHECK13-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -4626,7 +4626,7 @@ int main() {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK13-NEXT:    ret void
 // CHECK13:       terminate.lpad:
 // CHECK13-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -4773,7 +4773,7 @@ int main() {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK13-NEXT:    ret void
 // CHECK13:       terminate.lpad:
 // CHECK13-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -4920,7 +4920,7 @@ int main() {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK13-NEXT:    ret void
 // CHECK13:       terminate.lpad:
 // CHECK13-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -5082,7 +5082,7 @@ int main() {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK13-NEXT:    ret void
 // CHECK13:       terminate.lpad:
 // CHECK13-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
diff --git a/clang/test/OpenMP/distribute_parallel_for_private_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_private_codegen.cpp
index 249609c7d831c548a30304bc75d5d21ec909deb0..e2b0d64093ebc0313e4502f4af5cdb4cb959bd0d 100644
--- a/clang/test/OpenMP/distribute_parallel_for_private_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_private_codegen.cpp
@@ -313,7 +313,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -491,7 +491,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -795,7 +795,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK9-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR4]]
 // CHECK9-NEXT:    [[ARRAY_BEGIN8:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0
 // CHECK9-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN8]], i64 2
@@ -1147,7 +1147,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK9-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR4]]
 // CHECK9-NEXT:    [[ARRAY_BEGIN8:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0
 // CHECK9-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN8]], i64 2
@@ -1500,7 +1500,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK11-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR4]]
 // CHECK11-NEXT:    [[ARRAY_BEGIN6:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0
 // CHECK11-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN6]], i32 2
@@ -1846,7 +1846,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK11-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR4]]
 // CHECK11-NEXT:    [[ARRAY_BEGIN6:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0
 // CHECK11-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN6]], i32 2
diff --git a/clang/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp
index 8784611d8399ed40eb088a14e5e2e19308729195..040f90b9ef78bd269355e1ac757e5b4498472b20 100644
--- a/clang/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_proc_bind_codegen.cpp
@@ -266,7 +266,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -404,7 +404,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -583,6 +583,6 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
diff --git a/clang/test/OpenMP/distribute_parallel_for_reduction_task_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_reduction_task_codegen.cpp
index 7caca83c25d647952e3a2a1d1ceca601a11210df..a019f09c14cb87fe31e5d5c4fffc937c247ac69e 100644
--- a/clang/test/OpenMP/distribute_parallel_for_reduction_task_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_reduction_task_codegen.cpp
@@ -328,7 +328,7 @@ int main(int argc, char **argv) {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP78:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP79:%.*]] = load i32, ptr [[TMP78]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP79]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP79]])
 // CHECK1-NEXT:    [[TMP80:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP81:%.*]] = load i32, ptr [[TMP80]], align 4
 // CHECK1-NEXT:    call void @__kmpc_task_reduction_modifier_fini(ptr @[[GLOB2]], i32 [[TMP81]], i32 1)
@@ -343,8 +343,8 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    [[TMP87:%.*]] = load i32, ptr [[TMP86]], align 4
 // CHECK1-NEXT:    [[TMP88:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB4:[0-9]+]], i32 [[TMP87]], i32 2, i64 24, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l14.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
 // CHECK1-NEXT:    switch i32 [[TMP88]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
-// CHECK1-NEXT:    i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
-// CHECK1-NEXT:    i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
+// CHECK1-NEXT:      i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
+// CHECK1-NEXT:      i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
 // CHECK1-NEXT:    ]
 // CHECK1:       .omp.reduction.case1:
 // CHECK1-NEXT:    [[TMP89:%.*]] = load i32, ptr [[TMP0]], align 4
@@ -536,21 +536,21 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]])
 // CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META8:![0-9]+]])
 // CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META10:![0-9]+]])
-// CHECK1-NEXT:    store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !12
+// CHECK1-NEXT:    store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META12:![0-9]+]]
+// CHECK1-NEXT:    store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META12]]
 // CHECK1-NEXT:    call void [[TMP10]](ptr [[TMP11]], ptr [[DOTFIRSTPRIV_PTR_ADDR_I]]) #[[ATTR2]]
-// CHECK1-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias !12
+// CHECK1-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias [[META12]]
 // CHECK1-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[TMP9]], i32 0, i32 1
 // CHECK1-NEXT:    [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8
 // CHECK1-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[TMP12]], align 8
-// CHECK1-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !12
+// CHECK1-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META12]]
 // CHECK1-NEXT:    [[TMP17:%.*]] = call ptr @__kmpc_task_reduction_get_th_data(i32 [[TMP16]], ptr [[TMP15]], ptr [[TMP14]])
 // CHECK1-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2
 // CHECK1-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[TMP18]], align 8
@@ -570,7 +570,7 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    [[TMP30:%.*]] = sub i64 [[TMP28]], [[TMP29]]
 // CHECK1-NEXT:    [[TMP31:%.*]] = add nuw i64 [[TMP30]], 1
 // CHECK1-NEXT:    [[TMP32:%.*]] = mul nuw i64 [[TMP31]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK1-NEXT:    store i64 [[TMP31]], ptr @{{reduction_size[.].+[.]}}, align 8, !noalias !12
+// CHECK1-NEXT:    store i64 [[TMP31]], ptr @{{reduction_size[.].+[.]}}, align 8, !noalias [[META12]]
 // CHECK1-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[TMP12]], align 8
 // CHECK1-NEXT:    [[TMP34:%.*]] = call ptr @__kmpc_task_reduction_get_th_data(i32 [[TMP16]], ptr [[TMP33]], ptr [[TMP20]])
 // CHECK1-NEXT:    [[TMP35:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2
@@ -580,8 +580,8 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    [[TMP39:%.*]] = ptrtoint ptr [[TMP20]] to i64
 // CHECK1-NEXT:    [[TMP40:%.*]] = sub i64 [[TMP38]], [[TMP39]]
 // CHECK1-NEXT:    [[TMP41:%.*]] = getelementptr i8, ptr [[TMP34]], i64 [[TMP40]]
-// CHECK1-NEXT:    store ptr [[TMP4_I]], ptr [[TMP_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP41]], ptr [[TMP4_I]], align 8, !noalias !12
+// CHECK1-NEXT:    store ptr [[TMP4_I]], ptr [[TMP_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr [[TMP41]], ptr [[TMP4_I]], align 8, !noalias [[META12]]
 // CHECK1-NEXT:    ret i32 0
 //
 //
diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_codegen.cpp
index e0618cb9924596e65d550595f58b949f80b16245..77336877e2be0427f853f0572766a4ee7dc8e551 100644
--- a/clang/test/OpenMP/distribute_parallel_for_simd_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_simd_codegen.cpp
@@ -1039,7 +1039,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK1-NEXT:    [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0
 // CHECK1-NEXT:    br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1302,7 +1302,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK1-NEXT:    [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0
 // CHECK1-NEXT:    br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1595,7 +1595,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK1-NEXT:    [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0
 // CHECK1-NEXT:    br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1858,7 +1858,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK1-NEXT:    [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0
 // CHECK1-NEXT:    br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2155,7 +2155,7 @@ int main() {
 // CHECK1:       omp.dispatch.end:
 // CHECK1-NEXT:    [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP41]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP41]])
 // CHECK1-NEXT:    [[TMP42:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP43:%.*]] = icmp ne i32 [[TMP42]], 0
 // CHECK1-NEXT:    br i1 [[TMP43]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2971,7 +2971,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK3-NEXT:    [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0
 // CHECK3-NEXT:    br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3227,7 +3227,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK3-NEXT:    [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0
 // CHECK3-NEXT:    br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3513,7 +3513,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK3-NEXT:    [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0
 // CHECK3-NEXT:    br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3769,7 +3769,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK3-NEXT:    [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0
 // CHECK3-NEXT:    br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4057,7 +4057,7 @@ int main() {
 // CHECK3:       omp.dispatch.end:
 // CHECK3-NEXT:    [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP41]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP41]])
 // CHECK3-NEXT:    [[TMP42:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP43:%.*]] = icmp ne i32 [[TMP42]], 0
 // CHECK3-NEXT:    br i1 [[TMP43]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5510,7 +5510,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK9-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5763,7 +5763,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK9-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6046,7 +6046,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK9-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6299,7 +6299,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK9-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6586,7 +6586,7 @@ int main() {
 // CHECK9:       omp.dispatch.end:
 // CHECK9-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]])
 // CHECK9-NEXT:    [[TMP38:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP39:%.*]] = icmp ne i32 [[TMP38]], 0
 // CHECK9-NEXT:    br i1 [[TMP39]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7976,7 +7976,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK9-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -8229,7 +8229,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK9-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -8512,7 +8512,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK9-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -8765,7 +8765,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK9-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK9-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -9052,7 +9052,7 @@ int main() {
 // CHECK9:       omp.dispatch.end:
 // CHECK9-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]])
 // CHECK9-NEXT:    [[TMP38:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP39:%.*]] = icmp ne i32 [[TMP38]], 0
 // CHECK9-NEXT:    br i1 [[TMP39]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -10438,7 +10438,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK11-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -10684,7 +10684,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK11-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -10960,7 +10960,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK11-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -11206,7 +11206,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK11-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -11484,7 +11484,7 @@ int main() {
 // CHECK11:       omp.dispatch.end:
 // CHECK11-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]])
 // CHECK11-NEXT:    [[TMP38:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP39:%.*]] = icmp ne i32 [[TMP38]], 0
 // CHECK11-NEXT:    br i1 [[TMP39]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -12853,7 +12853,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK11-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -13099,7 +13099,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK11-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -13375,7 +13375,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK11-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -13621,7 +13621,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK11-NEXT:    [[TMP31:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP32:%.*]] = icmp ne i32 [[TMP31]], 0
 // CHECK11-NEXT:    br i1 [[TMP32]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -13899,7 +13899,7 @@ int main() {
 // CHECK11:       omp.dispatch.end:
 // CHECK11-NEXT:    [[TMP36:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP37:%.*]] = load i32, ptr [[TMP36]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP37]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP37]])
 // CHECK11-NEXT:    [[TMP38:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP39:%.*]] = icmp ne i32 [[TMP38]], 0
 // CHECK11-NEXT:    br i1 [[TMP39]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp
index 5c9b2aa1f47fb668f97679b83ce7e9d3e29126b4..f47b64b1e299d597f722b779b649e6f8dde3ce0b 100644
--- a/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_codegen.cpp
@@ -506,7 +506,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0
 // CHECK1-NEXT:    br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -768,7 +768,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK3-NEXT:    [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0
 // CHECK3-NEXT:    br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1237,7 +1237,7 @@ int main() {
 // CHECK8:       omp.loop.exit:
 // CHECK8-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK8-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK8-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK8-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK8-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK8-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK8-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1696,7 +1696,7 @@ int main() {
 // CHECK8:       omp.loop.exit:
 // CHECK8-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK8-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK8-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK8-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK8-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK8-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK8-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2178,7 +2178,7 @@ int main() {
 // CHECK10:       omp.loop.exit:
 // CHECK10-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK10-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK10-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK10-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK10-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2631,7 +2631,7 @@ int main() {
 // CHECK10:       omp.loop.exit:
 // CHECK10-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK10-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK10-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK10-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK10-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp
index 67384abc7751eef8624099a1dc1019c32240525a..b3e964fddcf0d7afa4ab343a766069974c5919cf 100644
--- a/clang/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_simd_if_codegen.cpp
@@ -333,7 +333,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -490,7 +490,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -772,7 +772,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -929,7 +929,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1100,7 +1100,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1380,7 +1380,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1537,7 +1537,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1708,7 +1708,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1935,7 +1935,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2092,7 +2092,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2374,7 +2374,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2531,7 +2531,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2810,7 +2810,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK3-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK3-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2937,7 +2937,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK3-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK3-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3217,7 +3217,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3374,7 +3374,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3545,7 +3545,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4348,7 +4348,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4505,7 +4505,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4787,7 +4787,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4944,7 +4944,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5115,7 +5115,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5395,7 +5395,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5552,7 +5552,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5723,7 +5723,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5950,7 +5950,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6107,7 +6107,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6389,7 +6389,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6546,7 +6546,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6825,7 +6825,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK11-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6952,7 +6952,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK11-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7232,7 +7232,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7389,7 +7389,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7560,7 +7560,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp
index adef55eee1cd5f9a58f7b1102cfdca6f223131ad..7656fb7bc2c519dc68b62a97ee344c76052e2b60 100644
--- a/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_simd_lastprivate_codegen.cpp
@@ -453,7 +453,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]])
 // CHECK1-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK1-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -732,7 +732,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]])
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK3-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1227,7 +1227,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK9-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK9-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1724,7 +1724,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK9-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2241,7 +2241,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK11-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2732,7 +2732,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK11-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp
index 0a0ed699acb1a2a2e160345fc1d803001c799b05..9f4fffbea63d16e3357eafe2fdab8fa0af5e8486 100644
--- a/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp
@@ -393,7 +393,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -568,7 +568,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -914,7 +914,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1075,7 +1075,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1236,7 +1236,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1412,7 +1412,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2068,7 +2068,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK5-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2243,7 +2243,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK5-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2580,7 +2580,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK5-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2741,7 +2741,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK5-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2902,7 +2902,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK5-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3078,7 +3078,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK5-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3404,7 +3404,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3579,7 +3579,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3925,7 +3925,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4086,7 +4086,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4247,7 +4247,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4423,7 +4423,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5079,7 +5079,7 @@ int main() {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK13-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK13-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5254,7 +5254,7 @@ int main() {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK13-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK13-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5591,7 +5591,7 @@ int main() {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK13-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK13-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5752,7 +5752,7 @@ int main() {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK13-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK13-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5913,7 +5913,7 @@ int main() {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK13-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK13-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6089,7 +6089,7 @@ int main() {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK13-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK13-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp
index 22208e2e2c1dc9526a62cc3bb45c19618a22d867..61f35d8b456cea954a88940053a19d7f58634731 100644
--- a/clang/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_simd_private_codegen.cpp
@@ -320,7 +320,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0
 // CHECK1-NEXT:    br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -512,7 +512,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0
 // CHECK3-NEXT:    br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -856,7 +856,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK9-NEXT:    [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0
 // CHECK9-NEXT:    br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1222,7 +1222,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK9-NEXT:    [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0
 // CHECK9-NEXT:    br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1589,7 +1589,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK11-NEXT:    [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0
 // CHECK11-NEXT:    br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1949,7 +1949,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK11-NEXT:    [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0
 // CHECK11-NEXT:    br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp
index d452ac3bed485b70bb6b66130da90e8ee07bbb6c..334965f59a826dba4ab7cc2cd59f4b1af33e1d1a 100644
--- a/clang/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_simd_proc_bind_codegen.cpp
@@ -273,7 +273,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -425,7 +425,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -618,7 +618,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/metadirective_device_arch_codegen.cpp b/clang/test/OpenMP/metadirective_device_arch_codegen.cpp
index 6150b7c07c167a2bd93430768ef635837a7a54d9..eecae310d0a77838d14b8a60eb06ae045f56ee75 100644
--- a/clang/test/OpenMP/metadirective_device_arch_codegen.cpp
+++ b/clang/test/OpenMP/metadirective_device_arch_codegen.cpp
@@ -60,6 +60,6 @@ int metadirective1() {
 // CHECK: omp.inner.for.body:
 // CHECK: store atomic {{.*}} monotonic
 // CHECK: omp.loop.exit:
-// CHECK-NEXT: call void @__kmpc_distribute_static_fini
+// CHECK-NEXT: call void @__kmpc_for_static_fini
 // CHECK-NEXT: ret void
 
diff --git a/clang/test/OpenMP/nvptx_SPMD_codegen.cpp b/clang/test/OpenMP/nvptx_SPMD_codegen.cpp
index 1ac5454994277b9da61c0d7090355536e9505f3c..d47025cd1acaa76cb0494ad76b6063ab88fe085b 100644
--- a/clang/test/OpenMP/nvptx_SPMD_codegen.cpp
+++ b/clang/test/OpenMP/nvptx_SPMD_codegen.cpp
@@ -573,7 +573,7 @@ int a;
 // CHECK-64:       omp.loop.exit:
 // CHECK-64-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK-64-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]])
 // CHECK-64-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-64-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK-64-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -680,7 +680,7 @@ int a;
 // CHECK-64:       omp.loop.exit:
 // CHECK-64-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK-64-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]])
 // CHECK-64-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-64-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK-64-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -873,7 +873,7 @@ int a;
 // CHECK-64:       omp.inner.for.end:
 // CHECK-64-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-64:       omp.loop.exit:
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-64-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-64-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK-64-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1057,7 +1057,7 @@ int a;
 // CHECK-64:       omp.inner.for.end:
 // CHECK-64-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-64:       omp.loop.exit:
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-64-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-64-NEXT:    [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0
 // CHECK-64-NEXT:    br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2028,7 +2028,7 @@ int a;
 // CHECK-64:       omp.inner.for.end:
 // CHECK-64-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-64:       omp.loop.exit:
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-64-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-64-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK-64-NEXT:    br i1 [[TMP12]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -2215,7 +2215,7 @@ int a;
 // CHECK-64:       omp.inner.for.end:
 // CHECK-64-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-64:       omp.loop.exit:
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-64-NEXT:    ret void
 //
 //
@@ -2385,7 +2385,7 @@ int a;
 // CHECK-64:       omp.inner.for.end:
 // CHECK-64-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-64:       omp.loop.exit:
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-64-NEXT:    ret void
 //
 //
@@ -3271,7 +3271,7 @@ int a;
 // CHECK-64:       omp.inner.for.end:
 // CHECK-64-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-64:       omp.loop.exit:
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-64-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-64-NEXT:    [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0
 // CHECK-64-NEXT:    br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3466,7 +3466,7 @@ int a;
 // CHECK-64:       omp.inner.for.end:
 // CHECK-64-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-64:       omp.loop.exit:
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-64-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-64-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK-64-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3634,7 +3634,7 @@ int a;
 // CHECK-64:       omp.inner.for.end:
 // CHECK-64-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-64:       omp.loop.exit:
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-64-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-64-NEXT:    [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0
 // CHECK-64-NEXT:    br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4595,7 +4595,7 @@ int a;
 // CHECK-64:       omp.inner.for.end:
 // CHECK-64-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-64:       omp.loop.exit:
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-64-NEXT:    ret void
 //
 //
@@ -4774,7 +4774,7 @@ int a;
 // CHECK-64:       omp.inner.for.end:
 // CHECK-64-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-64:       omp.loop.exit:
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-64-NEXT:    ret void
 //
 //
@@ -4944,7 +4944,7 @@ int a;
 // CHECK-64:       omp.inner.for.end:
 // CHECK-64-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-64:       omp.loop.exit:
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-64-NEXT:    ret void
 //
 //
@@ -5822,7 +5822,7 @@ int a;
 // CHECK-64:       omp.inner.for.end:
 // CHECK-64-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-64:       omp.loop.exit:
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-64-NEXT:    ret void
 //
 //
@@ -6001,7 +6001,7 @@ int a;
 // CHECK-64:       omp.inner.for.end:
 // CHECK-64-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-64:       omp.loop.exit:
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-64-NEXT:    ret void
 //
 //
@@ -6171,7 +6171,7 @@ int a;
 // CHECK-64:       omp.inner.for.end:
 // CHECK-64-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-64:       omp.loop.exit:
-// CHECK-64-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-64-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-64-NEXT:    ret void
 //
 //
@@ -9534,7 +9534,7 @@ int a;
 // CHECK-32:       omp.loop.exit:
 // CHECK-32-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK-32-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]])
 // CHECK-32-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK-32-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -9637,7 +9637,7 @@ int a;
 // CHECK-32:       omp.loop.exit:
 // CHECK-32-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK-32-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]])
 // CHECK-32-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK-32-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -9826,7 +9826,7 @@ int a;
 // CHECK-32:       omp.inner.for.end:
 // CHECK-32-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32:       omp.loop.exit:
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK-32-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -10005,7 +10005,7 @@ int a;
 // CHECK-32:       omp.inner.for.end:
 // CHECK-32-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32:       omp.loop.exit:
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-NEXT:    [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0
 // CHECK-32-NEXT:    br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -10955,7 +10955,7 @@ int a;
 // CHECK-32:       omp.inner.for.end:
 // CHECK-32-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32:       omp.loop.exit:
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK-32-NEXT:    br i1 [[TMP12]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -11138,7 +11138,7 @@ int a;
 // CHECK-32:       omp.inner.for.end:
 // CHECK-32-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32:       omp.loop.exit:
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-NEXT:    ret void
 //
 //
@@ -11303,7 +11303,7 @@ int a;
 // CHECK-32:       omp.inner.for.end:
 // CHECK-32-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32:       omp.loop.exit:
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-NEXT:    ret void
 //
 //
@@ -12168,7 +12168,7 @@ int a;
 // CHECK-32:       omp.inner.for.end:
 // CHECK-32-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32:       omp.loop.exit:
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-NEXT:    [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0
 // CHECK-32-NEXT:    br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -12359,7 +12359,7 @@ int a;
 // CHECK-32:       omp.inner.for.end:
 // CHECK-32-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32:       omp.loop.exit:
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK-32-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -12522,7 +12522,7 @@ int a;
 // CHECK-32:       omp.inner.for.end:
 // CHECK-32-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32:       omp.loop.exit:
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-NEXT:    [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0
 // CHECK-32-NEXT:    br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -13462,7 +13462,7 @@ int a;
 // CHECK-32:       omp.inner.for.end:
 // CHECK-32-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32:       omp.loop.exit:
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-NEXT:    ret void
 //
 //
@@ -13637,7 +13637,7 @@ int a;
 // CHECK-32:       omp.inner.for.end:
 // CHECK-32-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32:       omp.loop.exit:
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-NEXT:    ret void
 //
 //
@@ -13802,7 +13802,7 @@ int a;
 // CHECK-32:       omp.inner.for.end:
 // CHECK-32-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32:       omp.loop.exit:
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-NEXT:    ret void
 //
 //
@@ -14659,7 +14659,7 @@ int a;
 // CHECK-32:       omp.inner.for.end:
 // CHECK-32-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32:       omp.loop.exit:
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-NEXT:    ret void
 //
 //
@@ -14834,7 +14834,7 @@ int a;
 // CHECK-32:       omp.inner.for.end:
 // CHECK-32-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32:       omp.loop.exit:
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-NEXT:    ret void
 //
 //
@@ -14999,7 +14999,7 @@ int a;
 // CHECK-32:       omp.inner.for.end:
 // CHECK-32-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32:       omp.loop.exit:
-// CHECK-32-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-NEXT:    ret void
 //
 //
@@ -18346,7 +18346,7 @@ int a;
 // CHECK-32-EX:       omp.loop.exit:
 // CHECK-32-EX-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK-32-EX-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]])
 // CHECK-32-EX-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-EX-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK-32-EX-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -18449,7 +18449,7 @@ int a;
 // CHECK-32-EX:       omp.loop.exit:
 // CHECK-32-EX-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK-32-EX-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]])
 // CHECK-32-EX-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-EX-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK-32-EX-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -18638,7 +18638,7 @@ int a;
 // CHECK-32-EX:       omp.inner.for.end:
 // CHECK-32-EX-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32-EX:       omp.loop.exit:
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-EX-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-EX-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK-32-EX-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -18817,7 +18817,7 @@ int a;
 // CHECK-32-EX:       omp.inner.for.end:
 // CHECK-32-EX-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32-EX:       omp.loop.exit:
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-EX-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-EX-NEXT:    [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0
 // CHECK-32-EX-NEXT:    br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -19767,7 +19767,7 @@ int a;
 // CHECK-32-EX:       omp.inner.for.end:
 // CHECK-32-EX-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32-EX:       omp.loop.exit:
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-EX-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-EX-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK-32-EX-NEXT:    br i1 [[TMP12]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -19950,7 +19950,7 @@ int a;
 // CHECK-32-EX:       omp.inner.for.end:
 // CHECK-32-EX-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32-EX:       omp.loop.exit:
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-EX-NEXT:    ret void
 //
 //
@@ -20115,7 +20115,7 @@ int a;
 // CHECK-32-EX:       omp.inner.for.end:
 // CHECK-32-EX-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32-EX:       omp.loop.exit:
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-EX-NEXT:    ret void
 //
 //
@@ -20980,7 +20980,7 @@ int a;
 // CHECK-32-EX:       omp.inner.for.end:
 // CHECK-32-EX-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32-EX:       omp.loop.exit:
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-EX-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-EX-NEXT:    [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0
 // CHECK-32-EX-NEXT:    br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -21171,7 +21171,7 @@ int a;
 // CHECK-32-EX:       omp.inner.for.end:
 // CHECK-32-EX-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32-EX:       omp.loop.exit:
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-EX-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-EX-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK-32-EX-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -21334,7 +21334,7 @@ int a;
 // CHECK-32-EX:       omp.inner.for.end:
 // CHECK-32-EX-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32-EX:       omp.loop.exit:
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-EX-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-32-EX-NEXT:    [[TMP11:%.*]] = icmp ne i32 [[TMP10]], 0
 // CHECK-32-EX-NEXT:    br i1 [[TMP11]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -22274,7 +22274,7 @@ int a;
 // CHECK-32-EX:       omp.inner.for.end:
 // CHECK-32-EX-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32-EX:       omp.loop.exit:
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-EX-NEXT:    ret void
 //
 //
@@ -22449,7 +22449,7 @@ int a;
 // CHECK-32-EX:       omp.inner.for.end:
 // CHECK-32-EX-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32-EX:       omp.loop.exit:
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-EX-NEXT:    ret void
 //
 //
@@ -22614,7 +22614,7 @@ int a;
 // CHECK-32-EX:       omp.inner.for.end:
 // CHECK-32-EX-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32-EX:       omp.loop.exit:
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-EX-NEXT:    ret void
 //
 //
@@ -23471,7 +23471,7 @@ int a;
 // CHECK-32-EX:       omp.inner.for.end:
 // CHECK-32-EX-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32-EX:       omp.loop.exit:
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-EX-NEXT:    ret void
 //
 //
@@ -23646,7 +23646,7 @@ int a;
 // CHECK-32-EX:       omp.inner.for.end:
 // CHECK-32-EX-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32-EX:       omp.loop.exit:
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-EX-NEXT:    ret void
 //
 //
@@ -23811,7 +23811,7 @@ int a;
 // CHECK-32-EX:       omp.inner.for.end:
 // CHECK-32-EX-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK-32-EX:       omp.loop.exit:
-// CHECK-32-EX-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
+// CHECK-32-EX-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP3]])
 // CHECK-32-EX-NEXT:    ret void
 //
 //
diff --git a/clang/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp b/clang/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp
index 7402698af3e4c00997d274b777d15b1a2d90a214..986aeadaf998c3bb8673b3f480615d518c18c06b 100644
--- a/clang/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp
+++ b/clang/test/OpenMP/nvptx_distribute_parallel_generic_mode_codegen.cpp
@@ -329,7 +329,7 @@ int main(int argc, char **argv) {
 // CHECK4:       omp.loop.exit:
 // CHECK4-NEXT:    [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK4-NEXT:    [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
-// CHECK4-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP23]])
+// CHECK4-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP23]])
 // CHECK4-NEXT:    [[TMP24:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK4-NEXT:    [[TMP25:%.*]] = icmp ne i32 [[TMP24]], 0
 // CHECK4-NEXT:    br i1 [[TMP25]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -639,7 +639,7 @@ int main(int argc, char **argv) {
 // CHECK5:       omp.loop.exit:
 // CHECK5-NEXT:    [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK5-NEXT:    [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
-// CHECK5-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP23]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP23]])
 // CHECK5-NEXT:    [[TMP24:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP25:%.*]] = icmp ne i32 [[TMP24]], 0
 // CHECK5-NEXT:    br i1 [[TMP25]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
diff --git a/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp
index 4d6982d10616eca5438aba26467ca0996f417edf..8397b93cbeedb56e33d8d586e7e9e26cae840753 100644
--- a/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp
+++ b/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_codegen.cpp
@@ -371,7 +371,7 @@ int bar(int n){
 // CHECK1:       omp.dispatch.end:
 // CHECK1-NEXT:    [[TMP26:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4
-// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP27]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP27]])
 // CHECK1-NEXT:    [[TMP28:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP29:%.*]] = icmp ne i32 [[TMP28]], 0
 // CHECK1-NEXT:    br i1 [[TMP29]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -633,7 +633,7 @@ int bar(int n){
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
-// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP18]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP18]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -822,7 +822,7 @@ int bar(int n){
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1050,7 +1050,7 @@ int bar(int n){
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1360,7 +1360,7 @@ int bar(int n){
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP27:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP28:%.*]] = load i32, ptr [[TMP27]], align 4
-// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP28]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP28]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -1625,7 +1625,7 @@ int bar(int n){
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -1931,7 +1931,7 @@ int bar(int n){
 // CHECK2:       omp.dispatch.end:
 // CHECK2-NEXT:    [[TMP26:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK2-NEXT:    [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4
-// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP27]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP27]])
 // CHECK2-NEXT:    [[TMP28:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK2-NEXT:    [[TMP29:%.*]] = icmp ne i32 [[TMP28]], 0
 // CHECK2-NEXT:    br i1 [[TMP29]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -2193,7 +2193,7 @@ int bar(int n){
 // CHECK2:       omp.loop.exit:
 // CHECK2-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK2-NEXT:    [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
-// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP18]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP18]])
 // CHECK2-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK2:       omp.precond.end:
 // CHECK2-NEXT:    ret void
@@ -2382,7 +2382,7 @@ int bar(int n){
 // CHECK2:       omp.inner.for.end:
 // CHECK2-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK2:       omp.loop.exit:
-// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK2-NEXT:    ret void
 //
 //
@@ -2610,7 +2610,7 @@ int bar(int n){
 // CHECK2:       omp.inner.for.end:
 // CHECK2-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK2:       omp.loop.exit:
-// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK2-NEXT:    ret void
 //
 //
@@ -2915,7 +2915,7 @@ int bar(int n){
 // CHECK2:       omp.loop.exit:
 // CHECK2-NEXT:    [[TMP27:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK2-NEXT:    [[TMP28:%.*]] = load i32, ptr [[TMP27]], align 4
-// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP28]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP28]])
 // CHECK2-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK2:       omp.precond.end:
 // CHECK2-NEXT:    ret void
@@ -3180,7 +3180,7 @@ int bar(int n){
 // CHECK2:       omp.loop.exit:
 // CHECK2-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK2-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]])
 // CHECK2-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK2:       omp.precond.end:
 // CHECK2-NEXT:    ret void
@@ -3479,7 +3479,7 @@ int bar(int n){
 // CHECK3:       omp.dispatch.end:
 // CHECK3-NEXT:    [[TMP26:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4
-// CHECK3-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP27]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP27]])
 // CHECK3-NEXT:    [[TMP28:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP29:%.*]] = icmp ne i32 [[TMP28]], 0
 // CHECK3-NEXT:    br i1 [[TMP29]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -3735,7 +3735,7 @@ int bar(int n){
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
-// CHECK3-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP18]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP18]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    ret void
@@ -3918,7 +3918,7 @@ int bar(int n){
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -4139,7 +4139,7 @@ int bar(int n){
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -4452,7 +4452,7 @@ int bar(int n){
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP27:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP28:%.*]] = load i32, ptr [[TMP27]], align 4
-// CHECK3-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP28]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP28]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    ret void
@@ -4710,7 +4710,7 @@ int bar(int n){
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK3-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP20]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    ret void
diff --git a/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp b/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp
index 045cd39b07b7369c7dcc8f2942c122e36b346217..e687a537ecf1eaab1ba872f3757fcda0265eb63f 100644
--- a/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp
+++ b/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_generic_mode_codegen.cpp
@@ -323,7 +323,7 @@ int main(int argc, char **argv) {
 // CHECK1:       omp.dispatch.end:
 // CHECK1-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4
-// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP26]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP26]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -617,7 +617,7 @@ int main(int argc, char **argv) {
 // CHECK2:       omp.dispatch.end:
 // CHECK2-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK2-NEXT:    [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4
-// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP26]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP26]])
 // CHECK2-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK2:       omp.precond.end:
 // CHECK2-NEXT:    ret void
diff --git a/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp
index 2520713da50e5605226cea39783856db55996c71..9aee4bd09282a46ef7cd563fedc7e3cfb2ea15fd 100644
--- a/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp
+++ b/clang/test/OpenMP/nvptx_target_teams_distribute_parallel_for_simd_codegen.cpp
@@ -371,7 +371,7 @@ int bar(int n){
 // CHECK1:       omp.dispatch.end:
 // CHECK1-NEXT:    [[TMP26:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4
-// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP27]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP27]])
 // CHECK1-NEXT:    [[TMP28:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP29:%.*]] = icmp ne i32 [[TMP28]], 0
 // CHECK1-NEXT:    br i1 [[TMP29]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -657,7 +657,7 @@ int bar(int n){
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
-// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP18]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP18]])
 // CHECK1-NEXT:    [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0
 // CHECK1-NEXT:    br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -865,7 +865,7 @@ int bar(int n){
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK1-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1108,7 +1108,7 @@ int bar(int n){
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0
 // CHECK1-NEXT:    br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1425,7 +1425,7 @@ int bar(int n){
 // CHECK2:       omp.dispatch.end:
 // CHECK2-NEXT:    [[TMP26:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK2-NEXT:    [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4
-// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP27]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP27]])
 // CHECK2-NEXT:    [[TMP28:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK2-NEXT:    [[TMP29:%.*]] = icmp ne i32 [[TMP28]], 0
 // CHECK2-NEXT:    br i1 [[TMP29]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1705,7 +1705,7 @@ int bar(int n){
 // CHECK2:       omp.loop.exit:
 // CHECK2-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK2-NEXT:    [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
-// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP18]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP18]])
 // CHECK2-NEXT:    [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK2-NEXT:    [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0
 // CHECK2-NEXT:    br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1907,7 +1907,7 @@ int bar(int n){
 // CHECK2:       omp.inner.for.end:
 // CHECK2-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK2:       omp.loop.exit:
-// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK2-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK2-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK2-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2143,7 +2143,7 @@ int bar(int n){
 // CHECK2:       omp.inner.for.end:
 // CHECK2-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK2:       omp.loop.exit:
-// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK2-NEXT:    [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK2-NEXT:    [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0
 // CHECK2-NEXT:    br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/nvptx_target_teams_generic_loop_codegen.cpp b/clang/test/OpenMP/nvptx_target_teams_generic_loop_codegen.cpp
index fc83500a09f9846e4d9eace415325626dce2932d..5226b7498e4ce7321fa300b9796ca7fd3fa51bd7 100644
--- a/clang/test/OpenMP/nvptx_target_teams_generic_loop_codegen.cpp
+++ b/clang/test/OpenMP/nvptx_target_teams_generic_loop_codegen.cpp
@@ -219,7 +219,7 @@ int bar(int n){
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3:[0-9]+]], i32 [[TMP41]])
+// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP41]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -276,7 +276,7 @@ int bar(int n){
 // CHECK1-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB3]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB3:[0-9]+]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK1-NEXT:    [[TMP9:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4
 // CHECK1-NEXT:    store i32 [[TMP9]], ptr [[DOTOMP_IV]], align 4
 // CHECK1-NEXT:    br label [[OMP_INNER_FOR_COND:%.*]]
@@ -432,7 +432,7 @@ int bar(int n){
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP2]])
+// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP2]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -637,7 +637,7 @@ int bar(int n){
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP2]])
+// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP2]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -904,7 +904,7 @@ int bar(int n){
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP41:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP42:%.*]] = load i32, ptr [[TMP41]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP42]])
+// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP42]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -1208,7 +1208,7 @@ int bar(int n){
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP42:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP43:%.*]] = load i32, ptr [[TMP42]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP43]])
+// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP43]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -1465,7 +1465,7 @@ int bar(int n){
 // CHECK2:       omp.loop.exit:
 // CHECK2-NEXT:    [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK2-NEXT:    [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3:[0-9]+]], i32 [[TMP41]])
+// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP41]])
 // CHECK2-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK2:       omp.precond.end:
 // CHECK2-NEXT:    ret void
@@ -1522,7 +1522,7 @@ int bar(int n){
 // CHECK2-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK2-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK2-NEXT:    [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
-// CHECK2-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB3]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK2-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB3:[0-9]+]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK2-NEXT:    [[TMP9:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4
 // CHECK2-NEXT:    store i32 [[TMP9]], ptr [[DOTOMP_IV]], align 4
 // CHECK2-NEXT:    br label [[OMP_INNER_FOR_COND:%.*]]
@@ -1678,7 +1678,7 @@ int bar(int n){
 // CHECK2:       omp.inner.for.end:
 // CHECK2-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK2:       omp.loop.exit:
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP2]])
+// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP2]])
 // CHECK2-NEXT:    ret void
 //
 //
@@ -1883,7 +1883,7 @@ int bar(int n){
 // CHECK2:       omp.inner.for.end:
 // CHECK2-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK2:       omp.loop.exit:
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP2]])
+// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP2]])
 // CHECK2-NEXT:    ret void
 //
 //
@@ -2149,7 +2149,7 @@ int bar(int n){
 // CHECK2:       omp.loop.exit:
 // CHECK2-NEXT:    [[TMP43:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK2-NEXT:    [[TMP44:%.*]] = load i32, ptr [[TMP43]], align 4
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP44]])
+// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP44]])
 // CHECK2-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK2:       omp.precond.end:
 // CHECK2-NEXT:    ret void
@@ -2449,7 +2449,7 @@ int bar(int n){
 // CHECK2:       omp.loop.exit:
 // CHECK2-NEXT:    [[TMP42:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK2-NEXT:    [[TMP43:%.*]] = load i32, ptr [[TMP42]], align 4
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP43]])
+// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP43]])
 // CHECK2-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK2:       omp.precond.end:
 // CHECK2-NEXT:    ret void
@@ -2704,7 +2704,7 @@ int bar(int n){
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP38:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP39:%.*]] = load i32, ptr [[TMP38]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3:[0-9]+]], i32 [[TMP39]])
+// CHECK3-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP39]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    ret void
@@ -2759,7 +2759,7 @@ int bar(int n){
 // CHECK3-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB3]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK3-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB3:[0-9]+]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK3-NEXT:    [[TMP9:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4
 // CHECK3-NEXT:    store i32 [[TMP9]], ptr [[DOTOMP_IV]], align 4
 // CHECK3-NEXT:    br label [[OMP_INNER_FOR_COND:%.*]]
@@ -2911,7 +2911,7 @@ int bar(int n){
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP2]])
+// CHECK3-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP2]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -3110,7 +3110,7 @@ int bar(int n){
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP2]])
+// CHECK3-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP2]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -3374,7 +3374,7 @@ int bar(int n){
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP43:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP44:%.*]] = load i32, ptr [[TMP43]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP44]])
+// CHECK3-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP44]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    ret void
@@ -3677,7 +3677,7 @@ int bar(int n){
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP41]])
+// CHECK3-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP41]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    ret void
diff --git a/clang/test/OpenMP/nvptx_target_teams_generic_loop_generic_mode_codegen.cpp b/clang/test/OpenMP/nvptx_target_teams_generic_loop_generic_mode_codegen.cpp
index ef26c9b1003ac55d948b3898d02715a69932fd4c..ca2670f0cd643fc110bde6595ea36f55989217d4 100644
--- a/clang/test/OpenMP/nvptx_target_teams_generic_loop_generic_mode_codegen.cpp
+++ b/clang/test/OpenMP/nvptx_target_teams_generic_loop_generic_mode_codegen.cpp
@@ -183,7 +183,7 @@ int main(int argc, char **argv) {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP40:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP41:%.*]] = load i32, ptr [[TMP40]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3:[0-9]+]], i32 [[TMP41]])
+// CHECK1-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP41]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -240,7 +240,7 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB3]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB3:[0-9]+]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK1-NEXT:    [[TMP9:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4
 // CHECK1-NEXT:    store i32 [[TMP9]], ptr [[DOTOMP_IV]], align 4
 // CHECK1-NEXT:    br label [[OMP_INNER_FOR_COND:%.*]]
@@ -433,7 +433,7 @@ int main(int argc, char **argv) {
 // CHECK2:       omp.loop.exit:
 // CHECK2-NEXT:    [[TMP38:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK2-NEXT:    [[TMP39:%.*]] = load i32, ptr [[TMP38]], align 4
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3:[0-9]+]], i32 [[TMP39]])
+// CHECK2-NEXT:    call void @__kmpc_distribute_static_fini(ptr @[[GLOB2]], i32 [[TMP39]])
 // CHECK2-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK2:       omp.precond.end:
 // CHECK2-NEXT:    ret void
@@ -488,7 +488,7 @@ int main(int argc, char **argv) {
 // CHECK2-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK2-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK2-NEXT:    [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
-// CHECK2-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB3]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK2-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB3:[0-9]+]], i32 [[TMP8]], i32 33, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK2-NEXT:    [[TMP9:%.*]] = load i32, ptr [[DOTOMP_LB]], align 4
 // CHECK2-NEXT:    store i32 [[TMP9]], ptr [[DOTOMP_IV]], align 4
 // CHECK2-NEXT:    br label [[OMP_INNER_FOR_COND:%.*]]
diff --git a/clang/test/OpenMP/reduction_implicit_map.cpp b/clang/test/OpenMP/reduction_implicit_map.cpp
index d47c6ec7214df6a8d516756d999bcb91fae41c08..7305c56289e01b68464427ba1660125ca645a0de 100644
--- a/clang/test/OpenMP/reduction_implicit_map.cpp
+++ b/clang/test/OpenMP/reduction_implicit_map.cpp
@@ -1365,7 +1365,7 @@ int main()
 // CHECK2:       omp.loop.exit:
 // CHECK2-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK2-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP30]])
 // CHECK2-NEXT:    [[TMP31:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0
 // CHECK2-NEXT:    store ptr [[OUTPUT3]], ptr [[TMP31]], align 4
 // CHECK2-NEXT:    [[TMP32:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
@@ -1735,7 +1735,7 @@ int main()
 // CHECK2:       omp.loop.exit:
 // CHECK2-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK2-NEXT:    [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP32]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP32]])
 // CHECK2-NEXT:    [[TMP33:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0
 // CHECK2-NEXT:    store ptr [[OUTPUT4]], ptr [[TMP33]], align 4
 // CHECK2-NEXT:    [[TMP34:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
diff --git a/clang/test/OpenMP/target_ompx_dyn_cgroup_mem_codegen.cpp b/clang/test/OpenMP/target_ompx_dyn_cgroup_mem_codegen.cpp
index a8b241c17d248216d71df9447d3ec0e9a6210862..e8b074a9d5f8be980b00ba24d776e1e3bbd4bbd6 100644
--- a/clang/test/OpenMP/target_ompx_dyn_cgroup_mem_codegen.cpp
+++ b/clang/test/OpenMP/target_ompx_dyn_cgroup_mem_codegen.cpp
@@ -854,7 +854,7 @@ int bar(int n){
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP18]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP18]])
 // CHECK1-NEXT:    [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0
 // CHECK1-NEXT:    br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1732,7 +1732,7 @@ int bar(int n){
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP18]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP18]])
 // CHECK3-NEXT:    [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0
 // CHECK3-NEXT:    br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2145,7 +2145,7 @@ int bar(int n){
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP18]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP18]])
 // CHECK9-NEXT:    [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0
 // CHECK9-NEXT:    br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2508,7 +2508,7 @@ int bar(int n){
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP18]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP18]])
 // CHECK11-NEXT:    [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0
 // CHECK11-NEXT:    br i1 [[TMP20]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp
index 9e12880be298d80fcadffb6a696e673fb86c2028..7e06d8c16169f74d14cad7613054d35555923e37 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp
@@ -333,12 +333,12 @@ int target_teams_fun(int *g){
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       cancel.exit:
 // CHECK1-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP26]])
 // CHECK1-NEXT:    br label [[CANCEL_CONT:%.*]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    br label [[CANCEL_CONT]]
@@ -559,7 +559,7 @@ int target_teams_fun(int *g){
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -975,12 +975,12 @@ int target_teams_fun(int *g){
 // CHECK2:       omp.loop.exit:
 // CHECK2-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK2-NEXT:    [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]])
 // CHECK2-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK2:       cancel.exit:
 // CHECK2-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK2-NEXT:    [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP26]])
 // CHECK2-NEXT:    br label [[CANCEL_CONT:%.*]]
 // CHECK2:       omp.precond.end:
 // CHECK2-NEXT:    br label [[CANCEL_CONT]]
@@ -1201,7 +1201,7 @@ int target_teams_fun(int *g){
 // CHECK2:       omp.loop.exit:
 // CHECK2-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK2-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK2-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK2:       omp.precond.end:
 // CHECK2-NEXT:    ret void
@@ -1612,12 +1612,12 @@ int target_teams_fun(int *g){
 // CHECK4:       omp.loop.exit:
 // CHECK4-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK4-NEXT:    [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4
-// CHECK4-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]])
+// CHECK4-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]])
 // CHECK4-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK4:       cancel.exit:
 // CHECK4-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK4-NEXT:    [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4
-// CHECK4-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]])
+// CHECK4-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP26]])
 // CHECK4-NEXT:    br label [[CANCEL_CONT:%.*]]
 // CHECK4:       omp.precond.end:
 // CHECK4-NEXT:    br label [[CANCEL_CONT]]
@@ -1833,7 +1833,7 @@ int target_teams_fun(int *g){
 // CHECK4:       omp.loop.exit:
 // CHECK4-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK4-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK4-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK4-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK4-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK4:       omp.precond.end:
 // CHECK4-NEXT:    ret void
@@ -2059,12 +2059,12 @@ int target_teams_fun(int *g){
 // CHECK10:       omp.loop.exit:
 // CHECK10-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK10-NEXT:    [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4
-// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]])
+// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]])
 // CHECK10-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK10:       cancel.exit:
 // CHECK10-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK10-NEXT:    [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4
-// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]])
+// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP26]])
 // CHECK10-NEXT:    br label [[CANCEL_CONT:%.*]]
 // CHECK10:       omp.precond.end:
 // CHECK10-NEXT:    br label [[CANCEL_CONT]]
@@ -2287,7 +2287,7 @@ int target_teams_fun(int *g){
 // CHECK10:       omp.loop.exit:
 // CHECK10-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK10-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK10-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK10:       omp.precond.end:
 // CHECK10-NEXT:    ret void
@@ -2508,12 +2508,12 @@ int target_teams_fun(int *g){
 // CHECK12:       omp.loop.exit:
 // CHECK12-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK12-NEXT:    [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4
-// CHECK12-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]])
+// CHECK12-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]])
 // CHECK12-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK12:       cancel.exit:
 // CHECK12-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK12-NEXT:    [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4
-// CHECK12-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]])
+// CHECK12-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP26]])
 // CHECK12-NEXT:    br label [[CANCEL_CONT:%.*]]
 // CHECK12:       omp.precond.end:
 // CHECK12-NEXT:    br label [[CANCEL_CONT]]
@@ -2731,7 +2731,7 @@ int target_teams_fun(int *g){
 // CHECK12:       omp.loop.exit:
 // CHECK12-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK12-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK12-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK12-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK12-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK12:       omp.precond.end:
 // CHECK12-NEXT:    ret void
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp
index d13920ba956f1bbf094cd4ced7dd9ec506f3d80f..b812011ea4ca0413522eebf21a2d00de1a969a19 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_collapse_codegen.cpp
@@ -331,7 +331,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -561,7 +561,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -1000,7 +1000,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP32]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP32]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -1224,7 +1224,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    ret void
 //
 //
@@ -1664,7 +1664,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP32]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP32]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -1882,6 +1882,6 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    ret void
 //
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp
index 517ea936a1d680e1260351cc8ffd901d137f2f70..0aa75952a3c2b90f0a8087864944df87816a5773 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_codegen.cpp
@@ -442,7 +442,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -593,7 +593,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -764,7 +764,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1071,7 +1071,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -1217,7 +1217,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -1383,7 +1383,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -1881,7 +1881,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -2098,7 +2098,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -2354,7 +2354,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -2668,7 +2668,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    ret void
 //
 //
@@ -2818,7 +2818,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    ret void
 //
 //
@@ -3003,7 +3003,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    ret void
 //
 //
@@ -3498,7 +3498,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -3710,7 +3710,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -3961,7 +3961,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -4270,7 +4270,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    ret void
 //
 //
@@ -4415,7 +4415,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    ret void
 //
 //
@@ -4595,6 +4595,6 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    ret void
 //
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp
index 9f11929ec372df3c793482154191465680f9d1c6..375279d9636080c2d2656afd91596d8379388853 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_firstprivate_codegen.cpp
@@ -703,7 +703,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK1-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR2]]
 // CHECK1-NEXT:    [[ARRAY_BEGIN12:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR3]], i32 0, i32 0
 // CHECK1-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN12]], i64 2
@@ -1170,7 +1170,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK1-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]]) #[[ATTR2]]
 // CHECK1-NEXT:    [[ARRAY_BEGIN13:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i32 0, i32 0
 // CHECK1-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN13]], i64 2
@@ -1759,7 +1759,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK3-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR4]]) #[[ATTR2]]
 // CHECK3-NEXT:    [[ARRAY_BEGIN10:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR2]], i32 0, i32 0
 // CHECK3-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN10]], i32 2
@@ -2220,7 +2220,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK3-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR2]]
 // CHECK3-NEXT:    [[ARRAY_BEGIN11:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i32 0, i32 0
 // CHECK3-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN11]], i32 2
@@ -2631,7 +2631,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    ret void
 //
 //
@@ -2949,7 +2949,7 @@ int main() {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK13-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR5]]
 // CHECK13-NEXT:    [[ARRAY_BEGIN12:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR3]], i32 0, i32 0
 // CHECK13-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN12]], i64 2
@@ -3256,7 +3256,7 @@ int main() {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK13-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]]) #[[ATTR5]]
 // CHECK13-NEXT:    [[ARRAY_BEGIN13:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i32 0, i32 0
 // CHECK13-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN13]], i64 2
@@ -3663,7 +3663,7 @@ int main() {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK15-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR4]]) #[[ATTR5]]
 // CHECK15-NEXT:    [[ARRAY_BEGIN10:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR2]], i32 0, i32 0
 // CHECK15-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN10]], i32 2
@@ -3964,7 +3964,7 @@ int main() {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK15-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR5]]
 // CHECK15-NEXT:    [[ARRAY_BEGIN11:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i32 0, i32 0
 // CHECK15-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN11]], i32 2
@@ -4270,6 +4270,6 @@ int main() {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK17-NEXT:    ret void
 //
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp
index fe2088aace15efc0141070aacfb0240af73d5eb8..9baf13385bef5bbf184d0e0990c136bed97b9e97 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp
@@ -314,7 +314,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -457,7 +457,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -711,7 +711,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -854,7 +854,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1016,7 +1016,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1259,7 +1259,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1402,7 +1402,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1564,6 +1564,6 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp
index e2181e5088cc98f58a3082008c64e26ba7771932..e54c230eea7eefd96af9b8c30f2ae684a928ee22 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_lastprivate_codegen.cpp
@@ -428,7 +428,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0
 // CHECK1-NEXT:    br i1 [[TMP19]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -692,7 +692,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP6]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP6]])
 // CHECK3-NEXT:    [[TMP20:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP21:%.*]] = icmp ne i32 [[TMP20]], 0
 // CHECK3-NEXT:    br i1 [[TMP21]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -1144,7 +1144,7 @@ int main() {
 // CHECK5:       omp.loop.exit:
 // CHECK5-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK5-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
 // CHECK5-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK5-NEXT:    br i1 [[TMP22]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -1628,7 +1628,7 @@ int main() {
 // CHECK5:       omp.loop.exit:
 // CHECK5-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK5-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
 // CHECK5-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK5-NEXT:    br i1 [[TMP22]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -2138,7 +2138,7 @@ int main() {
 // CHECK7:       omp.loop.exit:
 // CHECK7-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK7-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]])
+// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
 // CHECK7-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK7-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK7-NEXT:    br i1 [[TMP22]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -2616,7 +2616,7 @@ int main() {
 // CHECK7:       omp.loop.exit:
 // CHECK7-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK7-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]])
+// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
 // CHECK7-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK7-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK7-NEXT:    br i1 [[TMP22]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp
index 74dee0399f58e83539bbb63a35d2c54de97f1892..feab9cdc948bcba8fb8552ad79b83b34021a4d00 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp
@@ -195,6 +195,6 @@ void gtid_test() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp
index 82f29fa1d3ef421875f1c461414f5f50c59c6b24..066d926e5abcbf2ec545ffbdb2cba6f61795f175 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_private_codegen.cpp
@@ -534,7 +534,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]])
 // CHECK1-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK1-NEXT:    [[ARRAY_BEGIN7:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0
 // CHECK1-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN7]], i64 2
@@ -842,7 +842,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK1-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK1-NEXT:    [[ARRAY_BEGIN8:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0
 // CHECK1-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN8]], i64 2
@@ -1261,7 +1261,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]])
 // CHECK3-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK3-NEXT:    [[ARRAY_BEGIN5:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0
 // CHECK3-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN5]], i32 2
@@ -1563,7 +1563,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK3-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK3-NEXT:    [[ARRAY_BEGIN6:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0
 // CHECK3-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN6]], i32 2
@@ -1917,7 +1917,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    ret void
 //
 //
@@ -2139,7 +2139,7 @@ int main() {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]])
 // CHECK13-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5]]
 // CHECK13-NEXT:    [[ARRAY_BEGIN7:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0
 // CHECK13-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN7]], i64 2
@@ -2376,7 +2376,7 @@ int main() {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK13-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5]]
 // CHECK13-NEXT:    [[ARRAY_BEGIN8:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0
 // CHECK13-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN8]], i64 2
@@ -2647,7 +2647,7 @@ int main() {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]])
 // CHECK15-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5]]
 // CHECK15-NEXT:    [[ARRAY_BEGIN5:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0
 // CHECK15-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN5]], i32 2
@@ -2878,7 +2878,7 @@ int main() {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK15-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5]]
 // CHECK15-NEXT:    [[ARRAY_BEGIN6:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0
 // CHECK15-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN6]], i32 2
@@ -3108,6 +3108,6 @@ int main() {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK17-NEXT:    ret void
 //
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp
index 6d22bc22e47960b9d5655cd82767ea7635f8303f..9f3e50fe20a62a08f035cf5a2ad6a4e8b069025d 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_proc_bind_codegen.cpp
@@ -261,7 +261,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -399,7 +399,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -578,6 +578,6 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp
index bfa00ee7a0f4ba0395c1396b44ad40441969acf1..1036ffd195de00e8544c669ee18c5580a14e2455 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_codegen.cpp
@@ -316,7 +316,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
 // CHECK1-NEXT:    store ptr [[SIVAR2]], ptr [[TMP14]], align 8
 // CHECK1-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l66.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -606,7 +606,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
 // CHECK1-NEXT:    store ptr [[T_VAR2]], ptr [[TMP14]], align 8
 // CHECK1-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -891,7 +891,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0
 // CHECK3-NEXT:    store ptr [[SIVAR1]], ptr [[TMP14]], align 4
 // CHECK3-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l66.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -1177,7 +1177,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0
 // CHECK3-NEXT:    store ptr [[T_VAR1]], ptr [[TMP14]], align 4
 // CHECK3-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -1425,7 +1425,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
 // CHECK5-NEXT:    store ptr [[SIVAR2]], ptr [[TMP15]], align 8
 // CHECK5-NEXT:    [[TMP16:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_task_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_task_codegen.cpp
index fea36e882b7ae2af3a8edbe222f589173041ed3f..6f1cc4d308a62fdc57058ae154061401828ba1f5 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_task_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_reduction_task_codegen.cpp
@@ -239,8 +239,8 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    [[TMP72:%.*]] = load i32, ptr [[TMP71]], align 4
 // CHECK1-NEXT:    [[TMP73:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB4:[0-9]+]], i32 [[TMP72]], i32 2, i64 24, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l14.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
 // CHECK1-NEXT:    switch i32 [[TMP73]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
-// CHECK1-NEXT:    i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
-// CHECK1-NEXT:    i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
+// CHECK1-NEXT:      i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
+// CHECK1-NEXT:      i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
 // CHECK1-NEXT:    ]
 // CHECK1:       .omp.reduction.case1:
 // CHECK1-NEXT:    [[TMP74:%.*]] = load i32, ptr [[TMP0]], align 4
@@ -588,7 +588,7 @@ int main(int argc, char **argv) {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP78:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP79:%.*]] = load i32, ptr [[TMP78]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP79]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP79]])
 // CHECK1-NEXT:    [[TMP80:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP81:%.*]] = load i32, ptr [[TMP80]], align 4
 // CHECK1-NEXT:    call void @__kmpc_task_reduction_modifier_fini(ptr @[[GLOB1]], i32 [[TMP81]], i32 1)
@@ -603,8 +603,8 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    [[TMP87:%.*]] = load i32, ptr [[TMP86]], align 4
 // CHECK1-NEXT:    [[TMP88:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB4]], i32 [[TMP87]], i32 2, i64 24, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l14.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
 // CHECK1-NEXT:    switch i32 [[TMP88]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
-// CHECK1-NEXT:    i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
-// CHECK1-NEXT:    i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
+// CHECK1-NEXT:      i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
+// CHECK1-NEXT:      i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
 // CHECK1-NEXT:    ]
 // CHECK1:       .omp.reduction.case1:
 // CHECK1-NEXT:    [[TMP89:%.*]] = load i32, ptr [[TMP0]], align 4
@@ -796,21 +796,21 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]])
 // CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META8:![0-9]+]])
 // CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META10:![0-9]+]])
-// CHECK1-NEXT:    store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !12
+// CHECK1-NEXT:    store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META12:![0-9]+]]
+// CHECK1-NEXT:    store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META12]]
 // CHECK1-NEXT:    call void [[TMP10]](ptr [[TMP11]], ptr [[DOTFIRSTPRIV_PTR_ADDR_I]]) #[[ATTR6]]
-// CHECK1-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias !12
+// CHECK1-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias [[META12]]
 // CHECK1-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[TMP9]], i32 0, i32 1
 // CHECK1-NEXT:    [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8
 // CHECK1-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[TMP12]], align 8
-// CHECK1-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !12
+// CHECK1-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META12]]
 // CHECK1-NEXT:    [[TMP17:%.*]] = call ptr @__kmpc_task_reduction_get_th_data(i32 [[TMP16]], ptr [[TMP15]], ptr [[TMP14]])
 // CHECK1-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2
 // CHECK1-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[TMP18]], align 8
@@ -830,7 +830,7 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    [[TMP30:%.*]] = sub i64 [[TMP28]], [[TMP29]]
 // CHECK1-NEXT:    [[TMP31:%.*]] = add nuw i64 [[TMP30]], 1
 // CHECK1-NEXT:    [[TMP32:%.*]] = mul nuw i64 [[TMP31]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK1-NEXT:    store i64 [[TMP31]], ptr @{{reduction_size[.].+[.]}}, align 8, !noalias !12
+// CHECK1-NEXT:    store i64 [[TMP31]], ptr @{{reduction_size[.].+[.]}}, align 8, !noalias [[META12]]
 // CHECK1-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[TMP12]], align 8
 // CHECK1-NEXT:    [[TMP34:%.*]] = call ptr @__kmpc_task_reduction_get_th_data(i32 [[TMP16]], ptr [[TMP33]], ptr [[TMP20]])
 // CHECK1-NEXT:    [[TMP35:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2
@@ -840,8 +840,8 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    [[TMP39:%.*]] = ptrtoint ptr [[TMP20]] to i64
 // CHECK1-NEXT:    [[TMP40:%.*]] = sub i64 [[TMP38]], [[TMP39]]
 // CHECK1-NEXT:    [[TMP41:%.*]] = getelementptr i8, ptr [[TMP34]], i64 [[TMP40]]
-// CHECK1-NEXT:    store ptr [[TMP4_I]], ptr [[TMP_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP41]], ptr [[TMP4_I]], align 8, !noalias !12
+// CHECK1-NEXT:    store ptr [[TMP4_I]], ptr [[TMP_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr [[TMP41]], ptr [[TMP4_I]], align 8, !noalias [[META12]]
 // CHECK1-NEXT:    ret i32 0
 //
 //
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp
index f71a5ca734377d6dcc7169055b4afd14b0697057..3d031e09aa07d698c637a51632c621cf1c1fc26e 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_schedule_codegen.cpp
@@ -596,7 +596,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -747,7 +747,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -919,7 +919,7 @@ int main (int argc, char **argv) {
 // CHECK1-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK1-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK1:       omp.dispatch.end:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1618,7 +1618,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -1764,7 +1764,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -1929,7 +1929,7 @@ int main (int argc, char **argv) {
 // CHECK3-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK3-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK3:       omp.dispatch.end:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -2623,7 +2623,7 @@ int main (int argc, char **argv) {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    ret void
 //
 //
@@ -2774,7 +2774,7 @@ int main (int argc, char **argv) {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    ret void
 //
 //
@@ -2946,7 +2946,7 @@ int main (int argc, char **argv) {
 // CHECK5-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK5-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK5:       omp.dispatch.end:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    ret void
 //
 //
@@ -3645,7 +3645,7 @@ int main (int argc, char **argv) {
 // CHECK7:       omp.inner.for.end:
 // CHECK7-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK7:       omp.loop.exit:
-// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK7-NEXT:    ret void
 //
 //
@@ -3791,7 +3791,7 @@ int main (int argc, char **argv) {
 // CHECK7:       omp.inner.for.end:
 // CHECK7-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK7:       omp.loop.exit:
-// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK7-NEXT:    ret void
 //
 //
@@ -3956,7 +3956,7 @@ int main (int argc, char **argv) {
 // CHECK7-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK7-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK7:       omp.dispatch.end:
-// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK7-NEXT:    ret void
 //
 //
@@ -4915,7 +4915,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK13-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK13:       omp.precond.end:
 // CHECK13-NEXT:    ret void
@@ -5132,7 +5132,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK13-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK13:       omp.precond.end:
 // CHECK13-NEXT:    ret void
@@ -5388,7 +5388,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK13-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK13:       omp.precond.end:
 // CHECK13-NEXT:    ret void
@@ -6248,7 +6248,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK13-NEXT:    ret void
 //
 //
@@ -6398,7 +6398,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK13-NEXT:    ret void
 //
 //
@@ -6584,7 +6584,7 @@ int main (int argc, char **argv) {
 // CHECK13-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK13-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK13:       omp.dispatch.end:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK13-NEXT:    ret void
 //
 //
@@ -7565,7 +7565,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK15-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK15:       omp.precond.end:
 // CHECK15-NEXT:    ret void
@@ -7777,7 +7777,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK15-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK15:       omp.precond.end:
 // CHECK15-NEXT:    ret void
@@ -8028,7 +8028,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK15-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK15:       omp.precond.end:
 // CHECK15-NEXT:    ret void
@@ -8873,7 +8873,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.inner.for.end:
 // CHECK15-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK15:       omp.loop.exit:
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK15-NEXT:    ret void
 //
 //
@@ -9018,7 +9018,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.inner.for.end:
 // CHECK15-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK15:       omp.loop.exit:
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK15-NEXT:    ret void
 //
 //
@@ -9197,7 +9197,7 @@ int main (int argc, char **argv) {
 // CHECK15-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK15-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK15:       omp.dispatch.end:
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK15-NEXT:    ret void
 //
 //
@@ -10169,7 +10169,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.loop.exit:
 // CHECK17-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK17-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK17-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK17:       omp.precond.end:
 // CHECK17-NEXT:    ret void
@@ -10386,7 +10386,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.loop.exit:
 // CHECK17-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK17-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK17-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK17:       omp.precond.end:
 // CHECK17-NEXT:    ret void
@@ -10642,7 +10642,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.loop.exit:
 // CHECK17-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK17-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK17-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK17:       omp.precond.end:
 // CHECK17-NEXT:    ret void
@@ -11502,7 +11502,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK17-NEXT:    ret void
 //
 //
@@ -11652,7 +11652,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK17-NEXT:    ret void
 //
 //
@@ -11838,7 +11838,7 @@ int main (int argc, char **argv) {
 // CHECK17-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK17-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK17:       omp.dispatch.end:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK17-NEXT:    ret void
 //
 //
@@ -12819,7 +12819,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.loop.exit:
 // CHECK19-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK19-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK19-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK19:       omp.precond.end:
 // CHECK19-NEXT:    ret void
@@ -13031,7 +13031,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.loop.exit:
 // CHECK19-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK19-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK19-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK19:       omp.precond.end:
 // CHECK19-NEXT:    ret void
@@ -13282,7 +13282,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.loop.exit:
 // CHECK19-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK19-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK19-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK19:       omp.precond.end:
 // CHECK19-NEXT:    ret void
@@ -14127,7 +14127,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.inner.for.end:
 // CHECK19-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK19:       omp.loop.exit:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK19-NEXT:    ret void
 //
 //
@@ -14272,7 +14272,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.inner.for.end:
 // CHECK19-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK19:       omp.loop.exit:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK19-NEXT:    ret void
 //
 //
@@ -14451,7 +14451,7 @@ int main (int argc, char **argv) {
 // CHECK19-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK19-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK19:       omp.dispatch.end:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK19-NEXT:    ret void
 //
 //
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp
index 5294f0d65eb6de0485036b58d47327fff2684487..109063c623a11da7de177058c66963289e71f9cb 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp
@@ -535,7 +535,7 @@ void test_target_teams_atomic() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP24]])
 // CHECK1-NEXT:    [[TMP25:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP26:%.*]] = icmp ne i32 [[TMP25]], 0
 // CHECK1-NEXT:    br i1 [[TMP26]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -784,7 +784,7 @@ void test_target_teams_atomic() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP22]])
 // CHECK1-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK1-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1006,7 +1006,7 @@ void test_target_teams_atomic() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK1-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1465,7 +1465,7 @@ void test_target_teams_atomic() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP24]])
 // CHECK3-NEXT:    [[TMP25:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP26:%.*]] = icmp ne i32 [[TMP25]], 0
 // CHECK3-NEXT:    br i1 [[TMP26]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1709,7 +1709,7 @@ void test_target_teams_atomic() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP22]])
 // CHECK3-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK3-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1927,7 +1927,7 @@ void test_target_teams_atomic() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK3-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2574,7 +2574,7 @@ void test_target_teams_atomic() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP24]])
 // CHECK9-NEXT:    [[TMP25:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP26:%.*]] = icmp ne i32 [[TMP25]], 0
 // CHECK9-NEXT:    br i1 [[TMP26]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2825,7 +2825,7 @@ void test_target_teams_atomic() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP22]])
 // CHECK9-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK9-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2995,7 +2995,7 @@ void test_target_teams_atomic() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK9-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK9-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3253,7 +3253,7 @@ void test_target_teams_atomic() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP24]])
 // CHECK11-NEXT:    [[TMP25:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP26:%.*]] = icmp ne i32 [[TMP25]], 0
 // CHECK11-NEXT:    br i1 [[TMP26]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3499,7 +3499,7 @@ void test_target_teams_atomic() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP22]])
 // CHECK11-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK11-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3665,7 +3665,7 @@ void test_target_teams_atomic() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK11-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK11-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp
index 2b4d31d14524083ca935887270f10e3bd5e24663..306ec1db2ab2158a7ffdf3f5a60f44913842ba75 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_collapse_codegen.cpp
@@ -339,7 +339,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0
 // CHECK1-NEXT:    br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -585,7 +585,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0
 // CHECK3-NEXT:    br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1190,7 +1190,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP32]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP32]])
 // CHECK9-NEXT:    [[TMP33:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP34:%.*]] = icmp ne i32 [[TMP33]], 0
 // CHECK9-NEXT:    br i1 [[TMP34]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1440,7 +1440,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0
 // CHECK9-NEXT:    br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1906,7 +1906,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP31:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP32:%.*]] = load i32, ptr [[TMP31]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP32]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP32]])
 // CHECK11-NEXT:    [[TMP33:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP34:%.*]] = icmp ne i32 [[TMP33]], 0
 // CHECK11-NEXT:    br i1 [[TMP34]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2150,7 +2150,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0
 // CHECK11-NEXT:    br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp
index 90fa290370b45b154a8ccf412658dd82f3cae602..c265c1c616b14a4423b092f99fd5336ddbef8a14 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp
@@ -449,7 +449,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK1-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -614,7 +614,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK1-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -799,7 +799,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK1-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1120,7 +1120,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK3-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1280,7 +1280,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK3-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1460,7 +1460,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK3-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2224,7 +2224,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK9-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2465,7 +2465,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK9-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2745,7 +2745,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK9-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3078,7 +3078,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK9-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3242,7 +3242,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK9-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3441,7 +3441,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK9-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3955,7 +3955,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK11-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4191,7 +4191,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK11-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4466,7 +4466,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK11-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4794,7 +4794,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK11-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4953,7 +4953,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK11-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5147,7 +5147,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK11-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp
index bf79fe669d83a23cd633a312956f8d9e066153e0..37c1f428ef9a3010b934c0cc1bd2cc6975cb1592 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_firstprivate_codegen.cpp
@@ -708,7 +708,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK1-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK1-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1189,7 +1189,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK1-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK1-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1792,7 +1792,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK3-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2267,7 +2267,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK3-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2692,7 +2692,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0
 // CHECK5-NEXT:    br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3798,7 +3798,7 @@ int main() {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK13-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK13-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4119,7 +4119,7 @@ int main() {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK13-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK13-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4540,7 +4540,7 @@ int main() {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK15-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK15-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK15-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4855,7 +4855,7 @@ int main() {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK15-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK15-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK15-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5175,7 +5175,7 @@ int main() {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK17-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0
 // CHECK17-NEXT:    br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp
index 329cd788c8bab8b4252c6382624d56ba1230c221..df5dd7ba680523cc1fe9583627f5980021b39696 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp
@@ -353,7 +353,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -510,7 +510,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -778,7 +778,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -935,7 +935,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1111,7 +1111,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1368,7 +1368,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1525,7 +1525,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1701,7 +1701,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1958,7 +1958,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2115,7 +2115,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2383,7 +2383,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2540,7 +2540,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2819,7 +2819,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK3-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK3-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2946,7 +2946,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK3-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK3-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3203,7 +3203,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3360,7 +3360,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3536,7 +3536,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4386,7 +4386,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4543,7 +4543,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4811,7 +4811,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4968,7 +4968,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5144,7 +5144,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5401,7 +5401,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5558,7 +5558,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5734,7 +5734,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5991,7 +5991,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6148,7 +6148,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6416,7 +6416,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6573,7 +6573,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6852,7 +6852,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK11-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6979,7 +6979,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK11-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7236,7 +7236,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7393,7 +7393,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7569,7 +7569,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp
index 903ecb865a2507becf67d743f7c2ae7b164180b7..3fdc0c482541084b9a5245d7692f8e4167b6f6e7 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_lastprivate_codegen.cpp
@@ -435,7 +435,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0
 // CHECK1-NEXT:    br i1 [[TMP19]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -713,7 +713,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP6]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP6]])
 // CHECK3-NEXT:    [[TMP20:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP21:%.*]] = icmp ne i32 [[TMP20]], 0
 // CHECK3-NEXT:    br i1 [[TMP21]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1179,7 +1179,7 @@ int main() {
 // CHECK5:       omp.loop.exit:
 // CHECK5-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK5-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
 // CHECK5-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK5-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1677,7 +1677,7 @@ int main() {
 // CHECK5:       omp.loop.exit:
 // CHECK5-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK5-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
 // CHECK5-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK5-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2201,7 +2201,7 @@ int main() {
 // CHECK7:       omp.loop.exit:
 // CHECK7-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK7-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]])
+// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
 // CHECK7-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK7-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK7-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2693,7 +2693,7 @@ int main() {
 // CHECK7:       omp.loop.exit:
 // CHECK7-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK7-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]])
+// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
 // CHECK7-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK7-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK7-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp
index 7a211b4cd06b22931ecfc2a59896d7aac77177db..bba97a750adc6294190ae92cf4c83bb05b55a953 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_private_codegen.cpp
@@ -541,7 +541,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]])
 // CHECK1-NEXT:    [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0
 // CHECK1-NEXT:    br i1 [[TMP19]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -863,7 +863,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK1-NEXT:    [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0
 // CHECK1-NEXT:    br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1296,7 +1296,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]])
 // CHECK3-NEXT:    [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0
 // CHECK3-NEXT:    br i1 [[TMP19]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1612,7 +1612,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK3-NEXT:    [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0
 // CHECK3-NEXT:    br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1980,7 +1980,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0
 // CHECK5-NEXT:    br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3100,7 +3100,7 @@ int main() {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]])
 // CHECK13-NEXT:    [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0
 // CHECK13-NEXT:    br i1 [[TMP19]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3351,7 +3351,7 @@ int main() {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK13-NEXT:    [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0
 // CHECK13-NEXT:    br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3636,7 +3636,7 @@ int main() {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]])
 // CHECK15-NEXT:    [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK15-NEXT:    [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0
 // CHECK15-NEXT:    br i1 [[TMP19]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3881,7 +3881,7 @@ int main() {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK15-NEXT:    [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK15-NEXT:    [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0
 // CHECK15-NEXT:    br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4125,7 +4125,7 @@ int main() {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK17-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0
 // CHECK17-NEXT:    br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
index 31941b48f92dff1f5452f2849ccb608d55f245c9..c347743bd4fdd7efb5c01593c2835fd0d0d4f4ab 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
@@ -268,7 +268,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -420,7 +420,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -613,7 +613,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp
index f255c3f084dbf9d38d7ae8a7b542d528434d36ae..52430d51cde1b5866a75a746d2fbe2a6d32cb863 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_reduction_codegen.cpp
@@ -323,7 +323,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0
 // CHECK1-NEXT:    br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -627,7 +627,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0
 // CHECK1-NEXT:    br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -926,7 +926,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0
 // CHECK3-NEXT:    br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1226,7 +1226,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0
 // CHECK3-NEXT:    br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1488,7 +1488,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    [[TMP15:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP16:%.*]] = icmp ne i32 [[TMP15]], 0
 // CHECK5-NEXT:    br i1 [[TMP16]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp
index b41571eb415d989ef9155f7870601ad62ab5d2dd..f7c0666d58b66183ad6ecb1a52244609b8ebf49b 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_schedule_codegen.cpp
@@ -603,7 +603,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK1-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -768,7 +768,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK1-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -954,7 +954,7 @@ int main (int argc, char **argv) {
 // CHECK1-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK1-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK1:       omp.dispatch.end:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK1-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1695,7 +1695,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK3-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1855,7 +1855,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK3-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2034,7 +2034,7 @@ int main (int argc, char **argv) {
 // CHECK3-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK3-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK3:       omp.dispatch.end:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK3-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2770,7 +2770,7 @@ int main (int argc, char **argv) {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK5-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2935,7 +2935,7 @@ int main (int argc, char **argv) {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK5-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3121,7 +3121,7 @@ int main (int argc, char **argv) {
 // CHECK5-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK5-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK5:       omp.dispatch.end:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK5-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3862,7 +3862,7 @@ int main (int argc, char **argv) {
 // CHECK7:       omp.inner.for.end:
 // CHECK7-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK7:       omp.loop.exit:
-// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK7-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK7-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK7-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4022,7 +4022,7 @@ int main (int argc, char **argv) {
 // CHECK7:       omp.inner.for.end:
 // CHECK7-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK7:       omp.loop.exit:
-// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK7-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK7-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK7-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4201,7 +4201,7 @@ int main (int argc, char **argv) {
 // CHECK7-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK7-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK7:       omp.dispatch.end:
-// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK7-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK7-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK7-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5592,7 +5592,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK13-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK13-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5833,7 +5833,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK13-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK13-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6113,7 +6113,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK13-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK13-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7040,7 +7040,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK13-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK13-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7204,7 +7204,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK13-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK13-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7404,7 +7404,7 @@ int main (int argc, char **argv) {
 // CHECK13-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK13-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK13:       omp.dispatch.end:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK13-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK13-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -8432,7 +8432,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK15-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK15-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK15-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -8668,7 +8668,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK15-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK15-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK15-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -8943,7 +8943,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK15-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK15-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK15-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -9855,7 +9855,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.inner.for.end:
 // CHECK15-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK15:       omp.loop.exit:
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK15-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK15-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK15-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -10014,7 +10014,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.inner.for.end:
 // CHECK15-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK15:       omp.loop.exit:
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK15-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK15-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK15-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -10207,7 +10207,7 @@ int main (int argc, char **argv) {
 // CHECK15-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK15-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK15:       omp.dispatch.end:
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK15-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK15-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK15-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -11226,7 +11226,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.loop.exit:
 // CHECK17-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK17-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK17-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK17-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -11467,7 +11467,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.loop.exit:
 // CHECK17-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK17-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK17-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK17-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -11747,7 +11747,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.loop.exit:
 // CHECK17-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK17-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK17-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK17-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -12674,7 +12674,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK17-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK17-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -12838,7 +12838,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK17-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK17-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -13038,7 +13038,7 @@ int main (int argc, char **argv) {
 // CHECK17-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK17-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK17:       omp.dispatch.end:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK17-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK17-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -14066,7 +14066,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.loop.exit:
 // CHECK19-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK19-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK19-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK19-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK19-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -14302,7 +14302,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.loop.exit:
 // CHECK19-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK19-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK19-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK19-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK19-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -14577,7 +14577,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.loop.exit:
 // CHECK19-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK19-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK19-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK19-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK19-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -15489,7 +15489,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.inner.for.end:
 // CHECK19-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK19:       omp.loop.exit:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK19-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK19-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK19-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -15648,7 +15648,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.inner.for.end:
 // CHECK19-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK19:       omp.loop.exit:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK19-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK19-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK19-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -15841,7 +15841,7 @@ int main (int argc, char **argv) {
 // CHECK19-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK19-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK19:       omp.dispatch.end:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK19-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK19-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK19-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_generic_loop_codegen-1.cpp b/clang/test/OpenMP/target_teams_generic_loop_codegen-1.cpp
index 26c9e4713f3e63d5eb1d55c6567d414dee23e7f4..190ea17e96070455c1955b4414679be029870d00 100644
--- a/clang/test/OpenMP/target_teams_generic_loop_codegen-1.cpp
+++ b/clang/test/OpenMP/target_teams_generic_loop_codegen-1.cpp
@@ -223,7 +223,7 @@ int target_teams_fun(int *g){
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP23]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP23]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -280,7 +280,7 @@ int target_teams_fun(int *g){
 // CHECK1-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK1-NEXT:    [[TMP9:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK1-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4
 // CHECK1-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]]
@@ -437,7 +437,7 @@ int target_teams_fun(int *g){
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -848,7 +848,7 @@ int target_teams_fun(int *g){
 // CHECK2:       omp.loop.exit:
 // CHECK2-NEXT:    [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK2-NEXT:    [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP23]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP23]])
 // CHECK2-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK2:       omp.precond.end:
 // CHECK2-NEXT:    ret void
@@ -905,7 +905,7 @@ int target_teams_fun(int *g){
 // CHECK2-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK2-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK2-NEXT:    [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
-// CHECK2-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK2-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK2-NEXT:    [[TMP9:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK2-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4
 // CHECK2-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]]
@@ -1062,7 +1062,7 @@ int target_teams_fun(int *g){
 // CHECK2:       omp.loop.exit:
 // CHECK2-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK2-NEXT:    [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]])
 // CHECK2-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK2:       omp.precond.end:
 // CHECK2-NEXT:    ret void
@@ -1471,7 +1471,7 @@ int target_teams_fun(int *g){
 // CHECK4:       omp.loop.exit:
 // CHECK4-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK4-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK4-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP21]])
+// CHECK4-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
 // CHECK4-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK4:       omp.precond.end:
 // CHECK4-NEXT:    ret void
@@ -1526,7 +1526,7 @@ int target_teams_fun(int *g){
 // CHECK4-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK4-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK4-NEXT:    [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
-// CHECK4-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK4-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK4-NEXT:    [[TMP9:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK4-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4
 // CHECK4-NEXT:    [[CMP4:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]]
@@ -1680,7 +1680,7 @@ int target_teams_fun(int *g){
 // CHECK4:       omp.loop.exit:
 // CHECK4-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK4-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK4-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
+// CHECK4-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
 // CHECK4-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK4:       omp.precond.end:
 // CHECK4-NEXT:    ret void
@@ -1900,7 +1900,7 @@ int target_teams_fun(int *g){
 // CHECK10:       omp.loop.exit:
 // CHECK10-NEXT:    [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK10-NEXT:    [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
-// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP23]])
+// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP23]])
 // CHECK10-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK10:       omp.precond.end:
 // CHECK10-NEXT:    ret void
@@ -1957,7 +1957,7 @@ int target_teams_fun(int *g){
 // CHECK10-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK10-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK10-NEXT:    [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
-// CHECK10-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK10-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK10-NEXT:    [[TMP9:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK10-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4
 // CHECK10-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]]
@@ -2116,7 +2116,7 @@ int target_teams_fun(int *g){
 // CHECK10:       omp.loop.exit:
 // CHECK10-NEXT:    [[TMP23:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK10-NEXT:    [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4
-// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP24]])
+// CHECK10-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP24]])
 // CHECK10-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK10:       omp.precond.end:
 // CHECK10-NEXT:    ret void
@@ -2337,7 +2337,7 @@ int target_teams_fun(int *g){
 // CHECK12:       omp.loop.exit:
 // CHECK12-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK12-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK12-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP21]])
+// CHECK12-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
 // CHECK12-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK12:       omp.precond.end:
 // CHECK12-NEXT:    ret void
@@ -2392,7 +2392,7 @@ int target_teams_fun(int *g){
 // CHECK12-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK12-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK12-NEXT:    [[TMP8:%.*]] = load i32, ptr [[TMP7]], align 4
-// CHECK12-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK12-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP8]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK12-NEXT:    [[TMP9:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK12-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4
 // CHECK12-NEXT:    [[CMP4:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]]
@@ -2548,7 +2548,7 @@ int target_teams_fun(int *g){
 // CHECK12:       omp.loop.exit:
 // CHECK12-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK12-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK12-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
+// CHECK12-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
 // CHECK12-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK12:       omp.precond.end:
 // CHECK12-NEXT:    ret void
diff --git a/clang/test/OpenMP/target_teams_generic_loop_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_codegen.cpp
index 3b1af7618794db6d4451be873bd68f5db3c5336d..22cf534bf0ba27933ce268956a5602f278505cfb 100644
--- a/clang/test/OpenMP/target_teams_generic_loop_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_generic_loop_codegen.cpp
@@ -1312,7 +1312,7 @@ int foo() {
 // IR-GPU:       omp.loop.exit:
 // IR-GPU-NEXT:    [[TMP32:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR_ASCAST]], align 8
 // IR-GPU-NEXT:    [[TMP33:%.*]] = load i32, ptr [[TMP32]], align 4
-// IR-GPU-NEXT:    call void @__kmpc_for_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB3:[0-9]+]] to ptr), i32 [[TMP33]])
+// IR-GPU-NEXT:    call void @__kmpc_distribute_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB2]] to ptr), i32 [[TMP33]])
 // IR-GPU-NEXT:    [[TMP34:%.*]] = load i32, ptr [[DOTOMP_IS_LAST_ASCAST]], align 4
 // IR-GPU-NEXT:    [[TMP35:%.*]] = icmp ne i32 [[TMP34]], 0
 // IR-GPU-NEXT:    br i1 [[TMP35]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -1418,7 +1418,7 @@ int foo() {
 // IR-GPU:       omp.arrayinit.done:
 // IR-GPU-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR_ASCAST]], align 8
 // IR-GPU-NEXT:    [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
-// IR-GPU-NEXT:    call void @__kmpc_for_static_init_4(ptr addrspacecast (ptr addrspace(1) @[[GLOB3]] to ptr), i32 [[TMP5]], i32 33, ptr [[DOTOMP_IS_LAST_ASCAST]], ptr [[DOTOMP_LB_ASCAST]], ptr [[DOTOMP_UB_ASCAST]], ptr [[DOTOMP_STRIDE_ASCAST]], i32 1, i32 1)
+// IR-GPU-NEXT:    call void @__kmpc_for_static_init_4(ptr addrspacecast (ptr addrspace(1) @[[GLOB3:[0-9]+]] to ptr), i32 [[TMP5]], i32 33, ptr [[DOTOMP_IS_LAST_ASCAST]], ptr [[DOTOMP_LB_ASCAST]], ptr [[DOTOMP_UB_ASCAST]], ptr [[DOTOMP_STRIDE_ASCAST]], i32 1, i32 1)
 // IR-GPU-NEXT:    [[TMP6:%.*]] = load i32, ptr [[DOTOMP_LB_ASCAST]], align 4
 // IR-GPU-NEXT:    store i32 [[TMP6]], ptr [[DOTOMP_IV_ASCAST]], align 4
 // IR-GPU-NEXT:    br label [[OMP_INNER_FOR_COND:%.*]]
@@ -2001,7 +2001,7 @@ int foo() {
 // IR:       omp.loop.exit:
 // IR-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // IR-NEXT:    [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
-// IR-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP18]])
+// IR-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP18]])
 // IR-NEXT:    [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // IR-NEXT:    [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0
 // IR-NEXT:    br i1 [[TMP20]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -2109,7 +2109,7 @@ int foo() {
 // IR:       omp.arrayinit.done:
 // IR-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // IR-NEXT:    [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
-// IR-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP5]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// IR-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP5]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // IR-NEXT:    [[TMP6:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // IR-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP6]], 99
 // IR-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -2398,7 +2398,7 @@ int foo() {
 // IR-PCH:       omp.loop.exit:
 // IR-PCH-NEXT:    [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // IR-PCH-NEXT:    [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
-// IR-PCH-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP18]])
+// IR-PCH-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP18]])
 // IR-PCH-NEXT:    [[TMP19:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // IR-PCH-NEXT:    [[TMP20:%.*]] = icmp ne i32 [[TMP19]], 0
 // IR-PCH-NEXT:    br i1 [[TMP20]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -2506,7 +2506,7 @@ int foo() {
 // IR-PCH:       omp.arrayinit.done:
 // IR-PCH-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // IR-PCH-NEXT:    [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4
-// IR-PCH-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP5]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// IR-PCH-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP5]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // IR-PCH-NEXT:    [[TMP6:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // IR-PCH-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP6]], 99
 // IR-PCH-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_generic_loop_collapse_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_collapse_codegen.cpp
index 6a30ef7f6eb8fa8061cbf87281e60ba343932912..82ad43373327af7f7e7cedc394c55d7e1430e2bf 100644
--- a/clang/test/OpenMP/target_teams_generic_loop_collapse_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_generic_loop_collapse_codegen.cpp
@@ -239,7 +239,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -278,7 +278,7 @@ int main (int argc, char **argv) {
 // CHECK1-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK1-NEXT:    [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK1-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 56087
 // CHECK1-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -473,7 +473,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -510,7 +510,7 @@ int main (int argc, char **argv) {
 // CHECK3-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK3-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK3-NEXT:    [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK3-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 56087
 // CHECK3-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -846,7 +846,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP27:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP28:%.*]] = load i32, ptr [[TMP27]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP28]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP28]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -926,7 +926,7 @@ int main (int argc, char **argv) {
 // CHECK9-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP13:%.*]] = load i32, ptr [[TMP12]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_init_8(ptr @[[GLOB2]], i32 [[TMP13]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1)
+// CHECK9-NEXT:    call void @__kmpc_for_static_init_8(ptr @[[GLOB2:[0-9]+]], i32 [[TMP13]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1)
 // CHECK9-NEXT:    [[TMP14:%.*]] = load i64, ptr [[DOTOMP_UB]], align 8
 // CHECK9-NEXT:    [[TMP15:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_5]], align 8
 // CHECK9-NEXT:    [[CMP13:%.*]] = icmp sgt i64 [[TMP14]], [[TMP15]]
@@ -1133,7 +1133,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK9-NEXT:    ret void
 //
 //
@@ -1510,7 +1510,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP29:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP30:%.*]] = load i32, ptr [[TMP29]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP30]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP30]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -1592,7 +1592,7 @@ int main (int argc, char **argv) {
 // CHECK11-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP13:%.*]] = load i32, ptr [[TMP12]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_init_8(ptr @[[GLOB2]], i32 [[TMP13]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1)
+// CHECK11-NEXT:    call void @__kmpc_for_static_init_8(ptr @[[GLOB2:[0-9]+]], i32 [[TMP13]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1)
 // CHECK11-NEXT:    [[TMP14:%.*]] = load i64, ptr [[DOTOMP_UB]], align 8
 // CHECK11-NEXT:    [[TMP15:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_5]], align 8
 // CHECK11-NEXT:    [[CMP15:%.*]] = icmp sgt i64 [[TMP14]], [[TMP15]]
@@ -1795,7 +1795,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK11-NEXT:    ret void
 //
 //
diff --git a/clang/test/OpenMP/target_teams_generic_loop_if_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_if_codegen.cpp
index c19323c35b4e182da024e0ef05882260cccaf4f3..b2ff4c20db7a12ad70cdb887ae4c76396f0fbf50 100644
--- a/clang/test/OpenMP/target_teams_generic_loop_if_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_generic_loop_if_codegen.cpp
@@ -210,7 +210,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP1]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -244,7 +244,7 @@ int main() {
 // CHECK1-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK1-NEXT:    [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK1-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 99
 // CHECK1-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -347,7 +347,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -601,7 +601,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -744,7 +744,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -906,7 +906,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1132,7 +1132,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1275,7 +1275,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1413,7 +1413,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]])
 // CHECK1-NEXT:    ret void
 //
 //
diff --git a/clang/test/OpenMP/target_teams_generic_loop_order_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_order_codegen.cpp
index 195989692dc3902e553fac23f69286e1c06a986b..85f6a85a11bd815bfd797bfbdce332dde8c08a1c 100644
--- a/clang/test/OpenMP/target_teams_generic_loop_order_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_generic_loop_order_codegen.cpp
@@ -125,7 +125,7 @@ void gtid_test() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP1]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -159,7 +159,7 @@ void gtid_test() {
 // CHECK1-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK1-NEXT:    [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK1-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 99
 // CHECK1-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_generic_loop_private_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_private_codegen.cpp
index 987c12adc6f66b462f574a4a47371d35a7e4154e..7503b69b92aa91005cdd4153b1ab58f2e1321cc5 100644
--- a/clang/test/OpenMP/target_teams_generic_loop_private_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_generic_loop_private_codegen.cpp
@@ -420,7 +420,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP13:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP14]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP14]])
 // CHECK1-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK1-NEXT:    [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0
 // CHECK1-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN2]], i64 2
@@ -481,7 +481,7 @@ int main() {
 // CHECK1-NEXT:    call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]])
 // CHECK1-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK1-NEXT:    [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK1-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1
 // CHECK1-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -728,7 +728,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP13:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP14]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP14]])
 // CHECK1-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK1-NEXT:    [[ARRAY_BEGIN4:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0
 // CHECK1-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN4]], i64 2
@@ -1151,7 +1151,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP12]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP12]])
 // CHECK3-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK3-NEXT:    [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0
 // CHECK3-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN2]], i32 2
@@ -1210,7 +1210,7 @@ int main() {
 // CHECK3-NEXT:    call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]])
 // CHECK3-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK3-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK3-NEXT:    [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK3-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1
 // CHECK3-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -1453,7 +1453,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP12]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP12]])
 // CHECK3-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK3-NEXT:    [[ARRAY_BEGIN4:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0
 // CHECK3-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN4]], i32 2
@@ -1827,7 +1827,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP1]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]])
 // CHECK5-NEXT:    ret void
 //
 //
@@ -1869,7 +1869,7 @@ int main() {
 // CHECK5-NEXT:    store ptr [[G1]], ptr [[_TMP3]], align 8
 // CHECK5-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK5-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
-// CHECK5-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK5-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK5-NEXT:    [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK5-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1
 // CHECK5-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -2015,7 +2015,7 @@ int main() {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP13:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP14]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP14]])
 // CHECK13-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5:[0-9]+]]
 // CHECK13-NEXT:    [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0
 // CHECK13-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN2]], i64 2
@@ -2086,7 +2086,7 @@ int main() {
 // CHECK13-NEXT:    call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR4]]
 // CHECK13-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK13-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK13-NEXT:    [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK13-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1
 // CHECK13-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -2252,7 +2252,7 @@ int main() {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP13:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP14]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP14]])
 // CHECK13-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5]]
 // CHECK13-NEXT:    [[ARRAY_BEGIN4:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0
 // CHECK13-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN4]], i64 2
@@ -2527,7 +2527,7 @@ int main() {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP12]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP12]])
 // CHECK15-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5:[0-9]+]]
 // CHECK15-NEXT:    [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0
 // CHECK15-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN2]], i32 2
@@ -2596,7 +2596,7 @@ int main() {
 // CHECK15-NEXT:    call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR4]]
 // CHECK15-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK15-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK15-NEXT:    [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK15-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1
 // CHECK15-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -2758,7 +2758,7 @@ int main() {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP12]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP12]])
 // CHECK15-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR5]]
 // CHECK15-NEXT:    [[ARRAY_BEGIN4:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0
 // CHECK15-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN4]], i32 2
@@ -3018,7 +3018,7 @@ int main() {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP1]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]])
 // CHECK17-NEXT:    ret void
 //
 //
@@ -3060,7 +3060,7 @@ int main() {
 // CHECK17-NEXT:    store ptr [[G1]], ptr [[_TMP3]], align 8
 // CHECK17-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK17-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
-// CHECK17-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK17-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK17-NEXT:    [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK17-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1
 // CHECK17-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
diff --git a/clang/test/OpenMP/target_teams_generic_loop_reduction_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_reduction_codegen.cpp
index bfa00ee7a0f4ba0395c1396b44ad40441969acf1..1036ffd195de00e8544c669ee18c5580a14e2455 100644
--- a/clang/test/OpenMP/target_teams_generic_loop_reduction_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_generic_loop_reduction_codegen.cpp
@@ -316,7 +316,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
 // CHECK1-NEXT:    store ptr [[SIVAR2]], ptr [[TMP14]], align 8
 // CHECK1-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l66.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -606,7 +606,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
 // CHECK1-NEXT:    store ptr [[T_VAR2]], ptr [[TMP14]], align 8
 // CHECK1-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -891,7 +891,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0
 // CHECK3-NEXT:    store ptr [[SIVAR1]], ptr [[TMP14]], align 4
 // CHECK3-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l66.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -1177,7 +1177,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0
 // CHECK3-NEXT:    store ptr [[T_VAR1]], ptr [[TMP14]], align 4
 // CHECK3-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -1425,7 +1425,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
 // CHECK5-NEXT:    store ptr [[SIVAR2]], ptr [[TMP15]], align 8
 // CHECK5-NEXT:    [[TMP16:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l44.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
diff --git a/clang/test/OpenMP/target_teams_generic_loop_uses_allocators_codegen.cpp b/clang/test/OpenMP/target_teams_generic_loop_uses_allocators_codegen.cpp
index f945dc9b21d4eb39e560586d75787832d80e5d00..0dc2c95641e286d20a5a9ea38d8ee2cf83e82d94 100644
--- a/clang/test/OpenMP/target_teams_generic_loop_uses_allocators_codegen.cpp
+++ b/clang/test/OpenMP/target_teams_generic_loop_uses_allocators_codegen.cpp
@@ -400,7 +400,7 @@ void foo() {
 // CHECK:       omp.inner.for.end:
 // CHECK-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK:       omp.loop.exit:
-// CHECK-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3:[0-9]+]], i32 [[TMP1]])
+// CHECK-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP1]])
 // CHECK-NEXT:    ret void
 //
 //
@@ -434,7 +434,7 @@ void foo() {
 // CHECK-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
-// CHECK-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB3]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB3:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 9
 // CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp
index 6dcfa4f6f2abc66b842b8a9e674c07698ccd4a6e..a13b565cb38d854ad66237cef295bda78948889c 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp
@@ -562,12 +562,12 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP24:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP25:%.*]] = load i32, ptr [[TMP24]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP25]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP25]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       cancel.exit:
 // CHECK1-NEXT:    [[TMP26:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP27]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP27]])
 // CHECK1-NEXT:    br label [[CANCEL_CONT:%.*]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    br label [[CANCEL_CONT]]
@@ -771,7 +771,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -1159,12 +1159,12 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP24:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP25:%.*]] = load i32, ptr [[TMP24]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP25]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP25]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       cancel.exit:
 // CHECK3-NEXT:    [[TMP26:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP27:%.*]] = load i32, ptr [[TMP26]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP27]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP27]])
 // CHECK3-NEXT:    br label [[CANCEL_CONT:%.*]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    br label [[CANCEL_CONT]]
@@ -1363,7 +1363,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    ret void
@@ -1674,7 +1674,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -1980,7 +1980,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -2200,7 +2200,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK17-NEXT:    ret void
 //
 //
@@ -2413,7 +2413,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.inner.for.end:
 // CHECK19-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK19:       omp.loop.exit:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK19-NEXT:    ret void
 //
 //
@@ -2730,7 +2730,7 @@ int main (int argc, char **argv) {
 // CHECK25:       omp.loop.exit:
 // CHECK25-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK25-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK25-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK25-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK25-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK25:       omp.precond.end:
 // CHECK25-NEXT:    ret void
@@ -2973,7 +2973,7 @@ int main (int argc, char **argv) {
 // CHECK25:       omp.inner.for.end:
 // CHECK25-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK25:       omp.loop.exit:
-// CHECK25-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK25-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK25-NEXT:    ret void
 //
 //
@@ -3285,7 +3285,7 @@ int main (int argc, char **argv) {
 // CHECK27:       omp.loop.exit:
 // CHECK27-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK27-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK27-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK27-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK27-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK27:       omp.precond.end:
 // CHECK27-NEXT:    ret void
@@ -3523,6 +3523,6 @@ int main (int argc, char **argv) {
 // CHECK27:       omp.inner.for.end:
 // CHECK27-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK27:       omp.loop.exit:
-// CHECK27-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK27-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK27-NEXT:    ret void
 //
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp
index 60c54f7bc0b432881a432b1e4508137f8982a81e..64ee660b706ccf1c5f3ee54c24a581ae11164798 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_collapse_codegen.cpp
@@ -334,7 +334,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -564,7 +564,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -991,7 +991,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -1215,7 +1215,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    ret void
 //
 //
@@ -1643,7 +1643,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -1861,6 +1861,6 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    ret void
 //
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp
index 3455597f90900d3596535b7f970fd6069912b65e..37d19f86a9509ba7db7d99ae332f63dae029232e 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_copyin_codegen.cpp
@@ -314,7 +314,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -537,7 +537,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -764,7 +764,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -982,7 +982,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -1168,7 +1168,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK9-NEXT:    ret void
 //
 //
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp
index f324d2c7ac90c834f87788dccf7efe29401cde08..eb3d2fc84568ab92ebcd9eb7781c9ad6e2a596d5 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_codegen.cpp
@@ -451,7 +451,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -602,7 +602,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -773,7 +773,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1080,7 +1080,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -1226,7 +1226,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -1392,7 +1392,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -1881,7 +1881,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -2092,7 +2092,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -2345,7 +2345,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -2656,7 +2656,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    ret void
 //
 //
@@ -2806,7 +2806,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    ret void
 //
 //
@@ -2994,7 +2994,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    ret void
 //
 //
@@ -3480,7 +3480,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -3686,7 +3686,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -3934,7 +3934,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -4240,7 +4240,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    ret void
 //
 //
@@ -4385,7 +4385,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    ret void
 //
 //
@@ -4568,6 +4568,6 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    ret void
 //
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp
index 24c3bc4adfefd2bef9a947a3f40f4a7ccc5d6b2b..904e6a1c1ce7bb045a58ae3c7ad42c164e77cbae 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_firstprivate_codegen.cpp
@@ -679,7 +679,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK1-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR2]]
 // CHECK1-NEXT:    [[ARRAY_BEGIN12:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR3]], i32 0, i32 0
 // CHECK1-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN12]], i64 2
@@ -1148,7 +1148,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK1-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]]) #[[ATTR2]]
 // CHECK1-NEXT:    [[ARRAY_BEGIN13:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i32 0, i32 0
 // CHECK1-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN13]], i64 2
@@ -1737,7 +1737,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK3-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR4]]) #[[ATTR2]]
 // CHECK3-NEXT:    [[ARRAY_BEGIN10:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR2]], i32 0, i32 0
 // CHECK3-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN10]], i32 2
@@ -2200,7 +2200,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK3-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR2]]
 // CHECK3-NEXT:    [[ARRAY_BEGIN11:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i32 0, i32 0
 // CHECK3-NEXT:    [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN11]], i32 2
@@ -2611,7 +2611,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    ret void
 //
 //
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp
index 31367697db2352653dcba4e1ed98140896375acc..49ff6a5d08beed513035186f560fb30c700d3f73 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_if_codegen.cpp
@@ -322,7 +322,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -465,7 +465,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -742,7 +742,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -885,7 +885,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1052,7 +1052,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1327,7 +1327,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1470,7 +1470,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1637,6 +1637,6 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp
index 45197d5e296de5b218752e4426c23c4ef9ec760e..7b8df7367b828ff62e6ae478d8474c6a2b6c4279 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_lastprivate_codegen.cpp
@@ -411,7 +411,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]])
 // CHECK1-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK1-NEXT:    br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -673,7 +673,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]])
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK3-NEXT:    br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -1115,7 +1115,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK9-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK9-NEXT:    br i1 [[TMP24]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -1595,7 +1595,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK9-NEXT:    br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -2095,7 +2095,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK11-NEXT:    br i1 [[TMP24]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -2569,7 +2569,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK11-NEXT:    br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
index c805d739cf9c23adeb5de447d090970267be2e61..a7b1f6eb309ee9e4891fc5c89c1329e814a37d59 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
@@ -371,7 +371,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 // CHECK1:       terminate.lpad:
 // CHECK1-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -538,7 +538,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 // CHECK1:       terminate.lpad:
 // CHECK1-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -887,7 +887,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 // CHECK1:       terminate.lpad:
 // CHECK1-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -1034,7 +1034,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 // CHECK1:       terminate.lpad:
 // CHECK1-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -1181,7 +1181,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 // CHECK1:       terminate.lpad:
 // CHECK1-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -1350,7 +1350,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 // CHECK1:       terminate.lpad:
 // CHECK1-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -1658,7 +1658,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    ret void
 // CHECK5:       terminate.lpad:
 // CHECK5-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -1825,7 +1825,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    ret void
 // CHECK5:       terminate.lpad:
 // CHECK5-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -2165,7 +2165,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    ret void
 // CHECK5:       terminate.lpad:
 // CHECK5-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -2312,7 +2312,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    ret void
 // CHECK5:       terminate.lpad:
 // CHECK5-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -2459,7 +2459,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    ret void
 // CHECK5:       terminate.lpad:
 // CHECK5-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
@@ -2628,7 +2628,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    ret void
 // CHECK5:       terminate.lpad:
 // CHECK5-NEXT:    [[TMP11:%.*]] = landingpad { ptr, i32 }
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp
index fe537dc743d4e738b826699b67e402d45371d372..dc430fc55787c11f370ef715316199196ff2256f 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_private_codegen.cpp
@@ -496,7 +496,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]])
 // CHECK1-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK1-NEXT:    [[ARRAY_BEGIN7:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0
 // CHECK1-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN7]], i64 2
@@ -804,7 +804,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK1-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK1-NEXT:    [[ARRAY_BEGIN8:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0
 // CHECK1-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN8]], i64 2
@@ -1223,7 +1223,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]])
 // CHECK3-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK3-NEXT:    [[ARRAY_BEGIN5:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0
 // CHECK3-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN5]], i32 2
@@ -1525,7 +1525,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK3-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK3-NEXT:    [[ARRAY_BEGIN6:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0
 // CHECK3-NEXT:    [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN6]], i32 2
@@ -1883,7 +1883,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    ret void
 //
 //
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp
index cbd426aabb9c7c62f38d5923785ed19d720af41e..386e772b78970f8843ea19d17def0ad5eca3241c 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_proc_bind_codegen.cpp
@@ -263,7 +263,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -401,7 +401,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -580,6 +580,6 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    ret void
 //
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp
index a003b9f203a4775f48693c4feb6de03868952cc0..7ac42579e91b95e7fba950f92ed8d9a06d4be59d 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_reduction_codegen.cpp
@@ -322,7 +322,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
 // CHECK1-NEXT:    store ptr [[SIVAR2]], ptr [[TMP14]], align 8
 // CHECK1-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l68.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -615,7 +615,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
 // CHECK1-NEXT:    store ptr [[T_VAR2]], ptr [[TMP14]], align 8
 // CHECK1-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -903,7 +903,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0
 // CHECK3-NEXT:    store ptr [[SIVAR1]], ptr [[TMP14]], align 4
 // CHECK3-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l68.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -1192,7 +1192,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0
 // CHECK3-NEXT:    store ptr [[T_VAR1]], ptr [[TMP14]], align 4
 // CHECK3-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -1439,7 +1439,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
 // CHECK9-NEXT:    store ptr [[SIVAR2]], ptr [[TMP15]], align 8
 // CHECK9-NEXT:    [[TMP16:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP4]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l45.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_reduction_task_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_reduction_task_codegen.cpp
index b583fcad2d3731c95d402d1d3a6218b1c31987c3..f58c848f4caec644dba0b8995f8bbfbe449d4da7 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_reduction_task_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_reduction_task_codegen.cpp
@@ -248,8 +248,8 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    [[TMP72:%.*]] = load i32, ptr [[TMP71]], align 4
 // CHECK1-NEXT:    [[TMP73:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB4:[0-9]+]], i32 [[TMP72]], i32 2, i64 24, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l16.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
 // CHECK1-NEXT:    switch i32 [[TMP73]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
-// CHECK1-NEXT:    i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
-// CHECK1-NEXT:    i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
+// CHECK1-NEXT:      i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
+// CHECK1-NEXT:      i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
 // CHECK1-NEXT:    ]
 // CHECK1:       .omp.reduction.case1:
 // CHECK1-NEXT:    [[TMP74:%.*]] = load i32, ptr [[TMP0]], align 4
@@ -597,7 +597,7 @@ int main(int argc, char **argv) {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP78:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP79:%.*]] = load i32, ptr [[TMP78]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP79]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP79]])
 // CHECK1-NEXT:    [[TMP80:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP81:%.*]] = load i32, ptr [[TMP80]], align 4
 // CHECK1-NEXT:    call void @__kmpc_task_reduction_modifier_fini(ptr @[[GLOB1]], i32 [[TMP81]], i32 1)
@@ -612,8 +612,8 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    [[TMP87:%.*]] = load i32, ptr [[TMP86]], align 4
 // CHECK1-NEXT:    [[TMP88:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB4]], i32 [[TMP87]], i32 2, i64 24, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l16.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
 // CHECK1-NEXT:    switch i32 [[TMP88]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
-// CHECK1-NEXT:    i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
-// CHECK1-NEXT:    i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
+// CHECK1-NEXT:      i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
+// CHECK1-NEXT:      i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
 // CHECK1-NEXT:    ]
 // CHECK1:       .omp.reduction.case1:
 // CHECK1-NEXT:    [[TMP89:%.*]] = load i32, ptr [[TMP0]], align 4
@@ -805,21 +805,21 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META6:![0-9]+]])
 // CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META8:![0-9]+]])
 // CHECK1-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata [[META10:![0-9]+]])
-// CHECK1-NEXT:    store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias !12
-// CHECK1-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias !12
+// CHECK1-NEXT:    store i32 [[TMP2]], ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META12:![0-9]+]]
+// CHECK1-NEXT:    store ptr [[TMP5]], ptr [[DOTPART_ID__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr [[TMP8]], ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr @.omp_task_privates_map., ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr [[TMP3]], ptr [[DOTTASK_T__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr [[TMP7]], ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[__CONTEXT_ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    [[TMP10:%.*]] = load ptr, ptr [[DOTCOPY_FN__ADDR_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTPRIVATES__ADDR_I]], align 8, !noalias [[META12]]
 // CHECK1-NEXT:    call void [[TMP10]](ptr [[TMP11]], ptr [[DOTFIRSTPRIV_PTR_ADDR_I]]) #[[ATTR6]]
-// CHECK1-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias !12
+// CHECK1-NEXT:    [[TMP12:%.*]] = load ptr, ptr [[DOTFIRSTPRIV_PTR_ADDR_I]], align 8, !noalias [[META12]]
 // CHECK1-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], ptr [[TMP9]], i32 0, i32 1
 // CHECK1-NEXT:    [[TMP14:%.*]] = load ptr, ptr [[TMP13]], align 8
 // CHECK1-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[TMP12]], align 8
-// CHECK1-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias !12
+// CHECK1-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTGLOBAL_TID__ADDR_I]], align 4, !noalias [[META12]]
 // CHECK1-NEXT:    [[TMP17:%.*]] = call ptr @__kmpc_task_reduction_get_th_data(i32 [[TMP16]], ptr [[TMP15]], ptr [[TMP14]])
 // CHECK1-NEXT:    [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2
 // CHECK1-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[TMP18]], align 8
@@ -839,7 +839,7 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    [[TMP30:%.*]] = sub i64 [[TMP28]], [[TMP29]]
 // CHECK1-NEXT:    [[TMP31:%.*]] = add nuw i64 [[TMP30]], 1
 // CHECK1-NEXT:    [[TMP32:%.*]] = mul nuw i64 [[TMP31]], ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64)
-// CHECK1-NEXT:    store i64 [[TMP31]], ptr @{{reduction_size[.].+[.]}}, align 8, !noalias !12
+// CHECK1-NEXT:    store i64 [[TMP31]], ptr @{{reduction_size[.].+[.]}}, align 8, !noalias [[META12]]
 // CHECK1-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[TMP12]], align 8
 // CHECK1-NEXT:    [[TMP34:%.*]] = call ptr @__kmpc_task_reduction_get_th_data(i32 [[TMP16]], ptr [[TMP33]], ptr [[TMP20]])
 // CHECK1-NEXT:    [[TMP35:%.*]] = getelementptr inbounds [[STRUCT_ANON]], ptr [[TMP9]], i32 0, i32 2
@@ -849,8 +849,8 @@ int main(int argc, char **argv) {
 // CHECK1-NEXT:    [[TMP39:%.*]] = ptrtoint ptr [[TMP20]] to i64
 // CHECK1-NEXT:    [[TMP40:%.*]] = sub i64 [[TMP38]], [[TMP39]]
 // CHECK1-NEXT:    [[TMP41:%.*]] = getelementptr i8, ptr [[TMP34]], i64 [[TMP40]]
-// CHECK1-NEXT:    store ptr [[TMP4_I]], ptr [[TMP_I]], align 8, !noalias !12
-// CHECK1-NEXT:    store ptr [[TMP41]], ptr [[TMP4_I]], align 8, !noalias !12
+// CHECK1-NEXT:    store ptr [[TMP4_I]], ptr [[TMP_I]], align 8, !noalias [[META12]]
+// CHECK1-NEXT:    store ptr [[TMP41]], ptr [[TMP4_I]], align 8, !noalias [[META12]]
 // CHECK1-NEXT:    ret i32 0
 //
 //
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp
index ab0e08259efe0d847d34cf2ee298d5a6050a7e94..7518179f477655773bbf95eafa4cbdbede186af8 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_schedule_codegen.cpp
@@ -610,7 +610,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -761,7 +761,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -933,7 +933,7 @@ int main (int argc, char **argv) {
 // CHECK1-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK1-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK1:       omp.dispatch.end:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -1632,7 +1632,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -1778,7 +1778,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -1943,7 +1943,7 @@ int main (int argc, char **argv) {
 // CHECK3-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK3-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK3:       omp.dispatch.end:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -2637,7 +2637,7 @@ int main (int argc, char **argv) {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    ret void
 //
 //
@@ -2788,7 +2788,7 @@ int main (int argc, char **argv) {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    ret void
 //
 //
@@ -2960,7 +2960,7 @@ int main (int argc, char **argv) {
 // CHECK5-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK5-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK5:       omp.dispatch.end:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    ret void
 //
 //
@@ -3659,7 +3659,7 @@ int main (int argc, char **argv) {
 // CHECK7:       omp.inner.for.end:
 // CHECK7-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK7:       omp.loop.exit:
-// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK7-NEXT:    ret void
 //
 //
@@ -3805,7 +3805,7 @@ int main (int argc, char **argv) {
 // CHECK7:       omp.inner.for.end:
 // CHECK7-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK7:       omp.loop.exit:
-// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK7-NEXT:    ret void
 //
 //
@@ -3970,7 +3970,7 @@ int main (int argc, char **argv) {
 // CHECK7-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK7-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK7:       omp.dispatch.end:
-// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK7-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK7-NEXT:    ret void
 //
 //
@@ -4917,7 +4917,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK13-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK13:       omp.precond.end:
 // CHECK13-NEXT:    ret void
@@ -5128,7 +5128,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK13-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK13:       omp.precond.end:
 // CHECK13-NEXT:    ret void
@@ -5381,7 +5381,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK13-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK13:       omp.precond.end:
 // CHECK13-NEXT:    ret void
@@ -6226,7 +6226,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK13-NEXT:    ret void
 //
 //
@@ -6376,7 +6376,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK13-NEXT:    ret void
 //
 //
@@ -6565,7 +6565,7 @@ int main (int argc, char **argv) {
 // CHECK13-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK13-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK13:       omp.dispatch.end:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK13-NEXT:    ret void
 //
 //
@@ -7537,7 +7537,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK15-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK15:       omp.precond.end:
 // CHECK15-NEXT:    ret void
@@ -7743,7 +7743,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK15-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK15:       omp.precond.end:
 // CHECK15-NEXT:    ret void
@@ -7991,7 +7991,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.loop.exit:
 // CHECK15-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK15-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK15-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK15:       omp.precond.end:
 // CHECK15-NEXT:    ret void
@@ -8821,7 +8821,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.inner.for.end:
 // CHECK15-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK15:       omp.loop.exit:
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK15-NEXT:    ret void
 //
 //
@@ -8966,7 +8966,7 @@ int main (int argc, char **argv) {
 // CHECK15:       omp.inner.for.end:
 // CHECK15-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK15:       omp.loop.exit:
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK15-NEXT:    ret void
 //
 //
@@ -9148,7 +9148,7 @@ int main (int argc, char **argv) {
 // CHECK15-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK15-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK15:       omp.dispatch.end:
-// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK15-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK15-NEXT:    ret void
 //
 //
@@ -10111,7 +10111,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.loop.exit:
 // CHECK17-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK17-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK17-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK17:       omp.precond.end:
 // CHECK17-NEXT:    ret void
@@ -10322,7 +10322,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.loop.exit:
 // CHECK17-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK17-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK17-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK17:       omp.precond.end:
 // CHECK17-NEXT:    ret void
@@ -10575,7 +10575,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.loop.exit:
 // CHECK17-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK17-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK17-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK17:       omp.precond.end:
 // CHECK17-NEXT:    ret void
@@ -11420,7 +11420,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK17-NEXT:    ret void
 //
 //
@@ -11570,7 +11570,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK17-NEXT:    ret void
 //
 //
@@ -11759,7 +11759,7 @@ int main (int argc, char **argv) {
 // CHECK17-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK17-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK17:       omp.dispatch.end:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK17-NEXT:    ret void
 //
 //
@@ -12731,7 +12731,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.loop.exit:
 // CHECK19-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK19-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK19-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK19:       omp.precond.end:
 // CHECK19-NEXT:    ret void
@@ -12937,7 +12937,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.loop.exit:
 // CHECK19-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK19-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK19-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK19:       omp.precond.end:
 // CHECK19-NEXT:    ret void
@@ -13185,7 +13185,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.loop.exit:
 // CHECK19-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK19-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK19-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK19:       omp.precond.end:
 // CHECK19-NEXT:    ret void
@@ -14015,7 +14015,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.inner.for.end:
 // CHECK19-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK19:       omp.loop.exit:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK19-NEXT:    ret void
 //
 //
@@ -14160,7 +14160,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.inner.for.end:
 // CHECK19-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK19:       omp.loop.exit:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK19-NEXT:    ret void
 //
 //
@@ -14342,7 +14342,7 @@ int main (int argc, char **argv) {
 // CHECK19-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK19-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK19:       omp.dispatch.end:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK19-NEXT:    ret void
 //
 //
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp
index 96439c053ea89740a20c9b5ebe1c5420a8436012..854afe3b9bbc827e217ee9eed8992092e21c8e4c 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp
@@ -583,7 +583,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK1-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK1-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -828,7 +828,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP24:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP25:%.*]] = load i32, ptr [[TMP24]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP25]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP25]])
 // CHECK1-NEXT:    [[TMP26:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP27:%.*]] = icmp ne i32 [[TMP26]], 0
 // CHECK1-NEXT:    br i1 [[TMP27]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1249,7 +1249,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK3-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1489,7 +1489,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP24:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP25:%.*]] = load i32, ptr [[TMP24]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP25]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP25]])
 // CHECK3-NEXT:    [[TMP26:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP27:%.*]] = icmp ne i32 [[TMP26]], 0
 // CHECK3-NEXT:    br i1 [[TMP27]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2126,7 +2126,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP26]])
 // CHECK9-NEXT:    [[TMP27:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP28:%.*]] = icmp ne i32 [[TMP27]], 0
 // CHECK9-NEXT:    br i1 [[TMP28]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2490,7 +2490,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP26]])
 // CHECK11-NEXT:    [[TMP27:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP28:%.*]] = icmp ne i32 [[TMP27]], 0
 // CHECK11-NEXT:    br i1 [[TMP28]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2929,7 +2929,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP6]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP6]])
 // CHECK17-NEXT:    [[TMP15:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP16:%.*]] = icmp ne i32 [[TMP15]], 0
 // CHECK17-NEXT:    br i1 [[TMP16]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3192,7 +3192,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.inner.for.end:
 // CHECK19-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK19:       omp.loop.exit:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP6]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP6]])
 // CHECK19-NEXT:    [[TMP15:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK19-NEXT:    [[TMP16:%.*]] = icmp ne i32 [[TMP15]], 0
 // CHECK19-NEXT:    br i1 [[TMP16]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3687,7 +3687,7 @@ int main (int argc, char **argv) {
 // CHECK25:       omp.loop.exit:
 // CHECK25-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK25-NEXT:    [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4
-// CHECK25-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]])
+// CHECK25-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP26]])
 // CHECK25-NEXT:    [[TMP27:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK25-NEXT:    [[TMP28:%.*]] = icmp ne i32 [[TMP27]], 0
 // CHECK25-NEXT:    br i1 [[TMP28]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3955,7 +3955,7 @@ int main (int argc, char **argv) {
 // CHECK25:       omp.inner.for.end:
 // CHECK25-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK25:       omp.loop.exit:
-// CHECK25-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK25-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK25-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK25-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK25-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4314,7 +4314,7 @@ int main (int argc, char **argv) {
 // CHECK27:       omp.loop.exit:
 // CHECK27-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK27-NEXT:    [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4
-// CHECK27-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]])
+// CHECK27-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP26]])
 // CHECK27-NEXT:    [[TMP27:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK27-NEXT:    [[TMP28:%.*]] = icmp ne i32 [[TMP27]], 0
 // CHECK27-NEXT:    br i1 [[TMP28]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4577,7 +4577,7 @@ int main (int argc, char **argv) {
 // CHECK27:       omp.inner.for.end:
 // CHECK27-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK27:       omp.loop.exit:
-// CHECK27-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK27-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP4]])
 // CHECK27-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK27-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK27-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp
index e68bd591519b73cee9af3e711c3e2851cd454993..e7b9978dd43cd81d2298a03927affddc2a861357 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_collapse_codegen.cpp
@@ -347,7 +347,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0
 // CHECK1-NEXT:    br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -593,7 +593,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0
 // CHECK3-NEXT:    br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1186,7 +1186,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK9-NEXT:    [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0
 // CHECK9-NEXT:    br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1436,7 +1436,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0
 // CHECK9-NEXT:    br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1890,7 +1890,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP33:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP34:%.*]] = load i32, ptr [[TMP33]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP34]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP34]])
 // CHECK11-NEXT:    [[TMP35:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP36:%.*]] = icmp ne i32 [[TMP35]], 0
 // CHECK11-NEXT:    br i1 [[TMP36]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2134,7 +2134,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0
 // CHECK11-NEXT:    br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp
index c2226bc9e75d7c99ac9f9d9d3af2c9fcd5c78254..d3777e81047ca0bdfae179d438146458532745a2 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_codegen.cpp
@@ -461,7 +461,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK1-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -626,7 +626,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK1-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -811,7 +811,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK1-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1132,7 +1132,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK3-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1292,7 +1292,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK3-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1472,7 +1472,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK3-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2227,7 +2227,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK9-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK9-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2462,7 +2462,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK9-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK9-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2739,7 +2739,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK9-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK9-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3069,7 +3069,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK9-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3233,7 +3233,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK9-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3435,7 +3435,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK9-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3940,7 +3940,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK11-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4170,7 +4170,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK11-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4442,7 +4442,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK11-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4767,7 +4767,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK11-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4926,7 +4926,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK11-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5123,7 +5123,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK11-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK11-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp
index 4c9299e6cb9d282ded23b9a7e801d39dd93ec3bd..4f87d40e58f683f1a572d61289d7052fff795d3a 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_firstprivate_codegen.cpp
@@ -689,7 +689,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK1-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK1-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1172,7 +1172,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK1-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK1-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1775,7 +1775,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK3-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2252,7 +2252,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK3-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3323,7 +3323,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0
 // CHECK9-NEXT:    br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp
index 275058b195e375bd2c37428c1e2f8758dcbdd8c2..7c86b180ec674bd347fc090086ee42536fe8cf7f 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_codegen.cpp
@@ -326,7 +326,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -483,7 +483,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -774,7 +774,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -931,7 +931,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1112,7 +1112,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1401,7 +1401,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1558,7 +1558,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1739,7 +1739,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1966,7 +1966,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2123,7 +2123,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2414,7 +2414,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2571,7 +2571,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2855,7 +2855,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK3-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK3-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2982,7 +2982,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK3-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK3-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3271,7 +3271,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3428,7 +3428,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3609,7 +3609,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK3-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4427,7 +4427,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4584,7 +4584,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4875,7 +4875,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5032,7 +5032,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5213,7 +5213,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5502,7 +5502,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5659,7 +5659,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5840,7 +5840,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK9-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6067,7 +6067,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6224,7 +6224,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6515,7 +6515,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6672,7 +6672,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6956,7 +6956,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK11-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7083,7 +7083,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK11-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7372,7 +7372,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7529,7 +7529,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7710,7 +7710,7 @@ int main() {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK11-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp
index fe2001842c26858eb799f3c684b8295d9a59123e..268298c14801cdd6ab3b2e78f4fb9339a3533a0a 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_lastprivate_codegen.cpp
@@ -427,7 +427,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]])
 // CHECK1-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK1-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -703,7 +703,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]])
 // CHECK3-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK3-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1195,7 +1195,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK9-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK9-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1689,7 +1689,7 @@ int main() {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK9-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK9-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2203,7 +2203,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK11-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK11-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2691,7 +2691,7 @@ int main() {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
 // CHECK11-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK11-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
index 49f57a000d3ff58e596c432b40fc8158d49c12b3..fa8bcf65b8fb63d87dd582a92d43c8c714a1f271 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
@@ -380,7 +380,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -561,7 +561,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -924,7 +924,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1085,7 +1085,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1246,7 +1246,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1429,7 +1429,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2100,7 +2100,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK5-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2281,7 +2281,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK5-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2635,7 +2635,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK5-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2796,7 +2796,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK5-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2957,7 +2957,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK5-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3140,7 +3140,7 @@ int main() {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK5-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK5-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp
index 7721daf4aa32bf87547e125b8d646855b514b7a2..03bee1dbb63c099b9374580b580eb3cf07705807 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_private_codegen.cpp
@@ -505,7 +505,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]])
 // CHECK1-NEXT:    [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0
 // CHECK1-NEXT:    br i1 [[TMP19]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -827,7 +827,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK1-NEXT:    [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0
 // CHECK1-NEXT:    br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1260,7 +1260,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP17]])
 // CHECK3-NEXT:    [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0
 // CHECK3-NEXT:    br i1 [[TMP19]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1576,7 +1576,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP15:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP16:%.*]] = load i32, ptr [[TMP15]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP16]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP16]])
 // CHECK3-NEXT:    [[TMP17:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP18:%.*]] = icmp ne i32 [[TMP17]], 0
 // CHECK3-NEXT:    br i1 [[TMP18]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2700,7 +2700,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK9-NEXT:    [[TMP16:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP17:%.*]] = icmp ne i32 [[TMP16]], 0
 // CHECK9-NEXT:    br i1 [[TMP17]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
index 2a3abf176929bb11ae92db11d5a4ce6b4508db09..7d35ea305f92b57c9d323223780c46baaf2a6c28 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_proc_bind_codegen.cpp
@@ -272,7 +272,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -424,7 +424,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -617,7 +617,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP12:%.*]] = icmp ne i32 [[TMP11]], 0
 // CHECK1-NEXT:    br i1 [[TMP12]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp
index 8745dd9710f64696932dc67a75e24abfaa7a56c0..2dd1db48f0306bee4bc912e3d2e1115152eed1b2 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_reduction_codegen.cpp
@@ -333,7 +333,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0
 // CHECK1-NEXT:    br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -640,7 +640,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0
 // CHECK1-NEXT:    br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -942,7 +942,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0
 // CHECK3-NEXT:    br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1245,7 +1245,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK3-NEXT:    [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP15:%.*]] = icmp ne i32 [[TMP14]], 0
 // CHECK3-NEXT:    br i1 [[TMP15]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1704,7 +1704,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK9-NEXT:    [[TMP15:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP16:%.*]] = icmp ne i32 [[TMP15]], 0
 // CHECK9-NEXT:    br i1 [[TMP16]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp
index 0c0945a23d482bade7756fb6af729a3d93e0fcc7..ff70e71e0126739ce20d354fef168413432c623e 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_schedule_codegen.cpp
@@ -627,7 +627,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK1-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -792,7 +792,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK1-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -978,7 +978,7 @@ int main (int argc, char **argv) {
 // CHECK1-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK1-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK1:       omp.dispatch.end:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK1-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK1-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1724,7 +1724,7 @@ int main (int argc, char **argv) {
 // CHECK2:       omp.inner.for.end:
 // CHECK2-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK2:       omp.loop.exit:
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK2-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK2-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK2-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -1889,7 +1889,7 @@ int main (int argc, char **argv) {
 // CHECK2:       omp.inner.for.end:
 // CHECK2-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK2:       omp.loop.exit:
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK2-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK2-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK2-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2075,7 +2075,7 @@ int main (int argc, char **argv) {
 // CHECK2-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK2-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK2:       omp.dispatch.end:
-// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK2-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK2-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK2-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK2-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2816,7 +2816,7 @@ int main (int argc, char **argv) {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK5-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -2976,7 +2976,7 @@ int main (int argc, char **argv) {
 // CHECK5:       omp.inner.for.end:
 // CHECK5-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK5:       omp.loop.exit:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK5-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3155,7 +3155,7 @@ int main (int argc, char **argv) {
 // CHECK5-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK5-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK5:       omp.dispatch.end:
-// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK5-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK5-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK5-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK5-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -3886,7 +3886,7 @@ int main (int argc, char **argv) {
 // CHECK6:       omp.inner.for.end:
 // CHECK6-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK6:       omp.loop.exit:
-// CHECK6-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK6-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK6-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK6-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK6-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4046,7 +4046,7 @@ int main (int argc, char **argv) {
 // CHECK6:       omp.inner.for.end:
 // CHECK6-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK6:       omp.loop.exit:
-// CHECK6-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK6-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK6-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK6-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK6-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -4225,7 +4225,7 @@ int main (int argc, char **argv) {
 // CHECK6-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK6-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK6:       omp.dispatch.end:
-// CHECK6-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK6-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK6-NEXT:    [[TMP21:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK6-NEXT:    [[TMP22:%.*]] = icmp ne i32 [[TMP21]], 0
 // CHECK6-NEXT:    br i1 [[TMP22]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5604,7 +5604,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK13-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK13-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -5839,7 +5839,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK13-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK13-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -6116,7 +6116,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.loop.exit:
 // CHECK13-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK13-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK13-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK13-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7028,7 +7028,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK13-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK13-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7192,7 +7192,7 @@ int main (int argc, char **argv) {
 // CHECK13:       omp.inner.for.end:
 // CHECK13-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK13:       omp.loop.exit:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK13-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK13-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -7395,7 +7395,7 @@ int main (int argc, char **argv) {
 // CHECK13-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK13-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK13:       omp.dispatch.end:
-// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK13-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK13-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK13-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK13-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -8415,7 +8415,7 @@ int main (int argc, char **argv) {
 // CHECK14:       omp.loop.exit:
 // CHECK14-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK14-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK14-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK14-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK14-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK14-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK14-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -8650,7 +8650,7 @@ int main (int argc, char **argv) {
 // CHECK14:       omp.loop.exit:
 // CHECK14-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK14-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK14-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK14-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK14-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK14-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK14-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -8927,7 +8927,7 @@ int main (int argc, char **argv) {
 // CHECK14:       omp.loop.exit:
 // CHECK14-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK14-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK14-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK14-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK14-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK14-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK14-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -9839,7 +9839,7 @@ int main (int argc, char **argv) {
 // CHECK14:       omp.inner.for.end:
 // CHECK14-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK14:       omp.loop.exit:
-// CHECK14-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK14-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK14-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK14-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK14-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -10003,7 +10003,7 @@ int main (int argc, char **argv) {
 // CHECK14:       omp.inner.for.end:
 // CHECK14-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK14:       omp.loop.exit:
-// CHECK14-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK14-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK14-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK14-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK14-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -10206,7 +10206,7 @@ int main (int argc, char **argv) {
 // CHECK14-NEXT:    store i32 [[ADD8]], ptr [[DOTOMP_UB]], align 4
 // CHECK14-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK14:       omp.dispatch.end:
-// CHECK14-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK14-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK14-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK14-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK14-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -11225,7 +11225,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.loop.exit:
 // CHECK17-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK17-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK17-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK17-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -11455,7 +11455,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.loop.exit:
 // CHECK17-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK17-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK17-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK17-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -11727,7 +11727,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.loop.exit:
 // CHECK17-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK17-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK17-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK17-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -12624,7 +12624,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK17-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK17-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -12783,7 +12783,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK17-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK17-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -12979,7 +12979,7 @@ int main (int argc, char **argv) {
 // CHECK17-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK17-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK17:       omp.dispatch.end:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK17-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK17-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -13988,7 +13988,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.loop.exit:
 // CHECK19-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK19-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK19-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK19-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK19-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -14218,7 +14218,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.loop.exit:
 // CHECK19-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK19-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK19-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK19-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK19-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -14490,7 +14490,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.loop.exit:
 // CHECK19-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK19-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
 // CHECK19-NEXT:    [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK19-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
 // CHECK19-NEXT:    br i1 [[TMP24]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -15387,7 +15387,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.inner.for.end:
 // CHECK19-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK19:       omp.loop.exit:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK19-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK19-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK19-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -15546,7 +15546,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.inner.for.end:
 // CHECK19-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK19:       omp.loop.exit:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP4]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP4]])
 // CHECK19-NEXT:    [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK19-NEXT:    [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
 // CHECK19-NEXT:    br i1 [[TMP14]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
@@ -15742,7 +15742,7 @@ int main (int argc, char **argv) {
 // CHECK19-NEXT:    store i32 [[ADD5]], ptr [[DOTOMP_UB]], align 4
 // CHECK19-NEXT:    br label [[OMP_DISPATCH_COND]]
 // CHECK19:       omp.dispatch.end:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
 // CHECK19-NEXT:    [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK19-NEXT:    [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
 // CHECK19-NEXT:    br i1 [[TMP23]], label [[DOTOMP_FINAL_THEN:%.*]], label [[DOTOMP_FINAL_DONE:%.*]]
diff --git a/clang/test/OpenMP/teams_generic_loop_codegen-1.cpp b/clang/test/OpenMP/teams_generic_loop_codegen-1.cpp
index 041a28bd87e7c2707278177fcca03c4327f0fb2b..85a4dfea91a21aa5ba251d36fd9ae71d8555899b 100644
--- a/clang/test/OpenMP/teams_generic_loop_codegen-1.cpp
+++ b/clang/test/OpenMP/teams_generic_loop_codegen-1.cpp
@@ -451,7 +451,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP22]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -509,7 +509,7 @@ int main (int argc, char **argv) {
 // CHECK1-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP8:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP9]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP9]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK1-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK1-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4
 // CHECK1-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[TMP10]], [[TMP11]]
@@ -653,7 +653,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
 // CHECK1-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK1:       omp.precond.end:
 // CHECK1-NEXT:    ret void
@@ -1036,7 +1036,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP20]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    ret void
@@ -1092,7 +1092,7 @@ int main (int argc, char **argv) {
 // CHECK3-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP8:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP9:%.*]] = load i32, ptr [[TMP8]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP9]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK3-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP9]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK3-NEXT:    [[TMP10:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK3-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4
 // CHECK3-NEXT:    [[CMP4:%.*]] = icmp sgt i32 [[TMP10]], [[TMP11]]
@@ -1233,7 +1233,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP19:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP20:%.*]] = load i32, ptr [[TMP19]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP20]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP20]])
 // CHECK3-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK3:       omp.precond.end:
 // CHECK3-NEXT:    ret void
@@ -1538,7 +1538,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP23]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP23]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -1599,7 +1599,7 @@ int main (int argc, char **argv) {
 // CHECK9-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP10:%.*]] = load i32, ptr [[TMP9]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK9-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK9-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK9-NEXT:    [[TMP12:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4
 // CHECK9-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[TMP11]], [[TMP12]]
@@ -1847,7 +1847,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP21]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -1906,7 +1906,7 @@ int main (int argc, char **argv) {
 // CHECK11-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP10:%.*]] = load i32, ptr [[TMP9]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK11-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK11-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK11-NEXT:    [[TMP12:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4
 // CHECK11-NEXT:    [[CMP4:%.*]] = icmp sgt i32 [[TMP11]], [[TMP12]]
@@ -2091,7 +2091,7 @@ int main (int argc, char **argv) {
 // CHECK17:       omp.inner.for.end:
 // CHECK17-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK17:       omp.loop.exit:
-// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]])
+// CHECK17-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK17-NEXT:    ret void
 //
 //
@@ -2128,7 +2128,7 @@ int main (int argc, char **argv) {
 // CHECK17-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK17-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK17-NEXT:    [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
-// CHECK17-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK17-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK17-NEXT:    [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK17-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 122
 // CHECK17-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -2307,7 +2307,7 @@ int main (int argc, char **argv) {
 // CHECK19:       omp.inner.for.end:
 // CHECK19-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK19:       omp.loop.exit:
-// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]])
+// CHECK19-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK19-NEXT:    ret void
 //
 //
@@ -2342,7 +2342,7 @@ int main (int argc, char **argv) {
 // CHECK19-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK19-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK19-NEXT:    [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
-// CHECK19-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK19-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK19-NEXT:    [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK19-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 122
 // CHECK19-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -2594,7 +2594,7 @@ int main (int argc, char **argv) {
 // CHECK25:       omp.loop.exit:
 // CHECK25-NEXT:    [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK25-NEXT:    [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
-// CHECK25-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP23]])
+// CHECK25-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP23]])
 // CHECK25-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK25:       omp.precond.end:
 // CHECK25-NEXT:    ret void
@@ -2655,7 +2655,7 @@ int main (int argc, char **argv) {
 // CHECK25-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK25-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK25-NEXT:    [[TMP10:%.*]] = load i32, ptr [[TMP9]], align 4
-// CHECK25-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK25-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK25-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK25-NEXT:    [[TMP12:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4
 // CHECK25-NEXT:    [[CMP5:%.*]] = icmp sgt i32 [[TMP11]], [[TMP12]]
@@ -2865,7 +2865,7 @@ int main (int argc, char **argv) {
 // CHECK25:       omp.inner.for.end:
 // CHECK25-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK25:       omp.loop.exit:
-// CHECK25-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]])
+// CHECK25-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK25-NEXT:    ret void
 //
 //
@@ -3152,7 +3152,7 @@ int main (int argc, char **argv) {
 // CHECK27:       omp.loop.exit:
 // CHECK27-NEXT:    [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK27-NEXT:    [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
-// CHECK27-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP21]])
+// CHECK27-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
 // CHECK27-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK27:       omp.precond.end:
 // CHECK27-NEXT:    ret void
@@ -3211,7 +3211,7 @@ int main (int argc, char **argv) {
 // CHECK27-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK27-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK27-NEXT:    [[TMP10:%.*]] = load i32, ptr [[TMP9]], align 4
-// CHECK27-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK27-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP10]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK27-NEXT:    [[TMP11:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK27-NEXT:    [[TMP12:%.*]] = load i32, ptr [[DOTCAPTURE_EXPR_1]], align 4
 // CHECK27-NEXT:    [[CMP4:%.*]] = icmp sgt i32 [[TMP11]], [[TMP12]]
@@ -3418,7 +3418,7 @@ int main (int argc, char **argv) {
 // CHECK27:       omp.inner.for.end:
 // CHECK27-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK27:       omp.loop.exit:
-// CHECK27-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]])
+// CHECK27-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK27-NEXT:    ret void
 //
 //
diff --git a/clang/test/OpenMP/teams_generic_loop_codegen.cpp b/clang/test/OpenMP/teams_generic_loop_codegen.cpp
index 2f3e70b1de582932aebf1e84bcd9cbe656a039ea..2499fbb6811c93b0e71035dbd3820e406e996840 100644
--- a/clang/test/OpenMP/teams_generic_loop_codegen.cpp
+++ b/clang/test/OpenMP/teams_generic_loop_codegen.cpp
@@ -113,7 +113,7 @@ int foo() {
 // IR:       omp.loop.exit:
 // IR-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // IR-NEXT:    [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
-// IR-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP17]])
+// IR-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]])
 // IR-NEXT:    [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // IR-NEXT:    [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0
 // IR-NEXT:    br i1 [[TMP19]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -129,8 +129,8 @@ int foo() {
 // IR-NEXT:    [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
 // IR-NEXT:    [[TMP24:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3:[0-9]+]], i32 [[TMP23]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_Z3foov.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
 // IR-NEXT:    switch i32 [[TMP24]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
-// IR-NEXT:    i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
-// IR-NEXT:    i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
+// IR-NEXT:      i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
+// IR-NEXT:      i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
 // IR-NEXT:    ]
 // IR:       .omp.reduction.case1:
 // IR-NEXT:    [[TMP25:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100
@@ -221,7 +221,7 @@ int foo() {
 // IR:       omp.arrayinit.done:
 // IR-NEXT:    [[TMP5:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // IR-NEXT:    [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 4
-// IR-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP6]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// IR-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP6]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // IR-NEXT:    [[TMP7:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // IR-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP7]], 99
 // IR-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -285,8 +285,8 @@ int foo() {
 // IR-NEXT:    [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4
 // IR-NEXT:    [[TMP25:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP24]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_Z3foov.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
 // IR-NEXT:    switch i32 [[TMP25]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
-// IR-NEXT:    i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
-// IR-NEXT:    i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
+// IR-NEXT:      i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
+// IR-NEXT:      i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
 // IR-NEXT:    ]
 // IR:       .omp.reduction.case1:
 // IR-NEXT:    [[TMP26:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100
@@ -486,7 +486,7 @@ int foo() {
 // IR-PCH:       omp.loop.exit:
 // IR-PCH-NEXT:    [[TMP16:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // IR-PCH-NEXT:    [[TMP17:%.*]] = load i32, ptr [[TMP16]], align 4
-// IR-PCH-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP17]])
+// IR-PCH-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP17]])
 // IR-PCH-NEXT:    [[TMP18:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
 // IR-PCH-NEXT:    [[TMP19:%.*]] = icmp ne i32 [[TMP18]], 0
 // IR-PCH-NEXT:    br i1 [[TMP19]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
@@ -502,8 +502,8 @@ int foo() {
 // IR-PCH-NEXT:    [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
 // IR-PCH-NEXT:    [[TMP24:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3:[0-9]+]], i32 [[TMP23]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_Z3foov.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
 // IR-PCH-NEXT:    switch i32 [[TMP24]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
-// IR-PCH-NEXT:    i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
-// IR-PCH-NEXT:    i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
+// IR-PCH-NEXT:      i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
+// IR-PCH-NEXT:      i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
 // IR-PCH-NEXT:    ]
 // IR-PCH:       .omp.reduction.case1:
 // IR-PCH-NEXT:    [[TMP25:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100
@@ -594,7 +594,7 @@ int foo() {
 // IR-PCH:       omp.arrayinit.done:
 // IR-PCH-NEXT:    [[TMP5:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // IR-PCH-NEXT:    [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 4
-// IR-PCH-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP6]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// IR-PCH-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP6]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // IR-PCH-NEXT:    [[TMP7:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // IR-PCH-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP7]], 99
 // IR-PCH-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -658,8 +658,8 @@ int foo() {
 // IR-PCH-NEXT:    [[TMP24:%.*]] = load i32, ptr [[TMP23]], align 4
 // IR-PCH-NEXT:    [[TMP25:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP24]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @_Z3foov.omp_outlined.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
 // IR-PCH-NEXT:    switch i32 [[TMP25]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [
-// IR-PCH-NEXT:    i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
-// IR-PCH-NEXT:    i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
+// IR-PCH-NEXT:      i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]]
+// IR-PCH-NEXT:      i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]]
 // IR-PCH-NEXT:    ]
 // IR-PCH:       .omp.reduction.case1:
 // IR-PCH-NEXT:    [[TMP26:%.*]] = getelementptr i32, ptr [[TMP1]], i64 100
diff --git a/clang/test/OpenMP/teams_generic_loop_collapse_codegen.cpp b/clang/test/OpenMP/teams_generic_loop_collapse_codegen.cpp
index 4cf8f88b4c084a43cc5baf460f24c83e1eac86ea..49df83c9c765cfad07207ea1f799fbb602359ef7 100644
--- a/clang/test/OpenMP/teams_generic_loop_collapse_codegen.cpp
+++ b/clang/test/OpenMP/teams_generic_loop_collapse_codegen.cpp
@@ -242,7 +242,7 @@ int main (int argc, char **argv) {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK1-NEXT:    ret void
 //
 //
@@ -281,7 +281,7 @@ int main (int argc, char **argv) {
 // CHECK1-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK1-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK1-NEXT:    [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK1-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 56087
 // CHECK1-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -476,7 +476,7 @@ int main (int argc, char **argv) {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK3-NEXT:    ret void
 //
 //
@@ -513,7 +513,7 @@ int main (int argc, char **argv) {
 // CHECK3-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK3-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK3-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK3-NEXT:    [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK3-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 56087
 // CHECK3-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -835,7 +835,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.loop.exit:
 // CHECK9-NEXT:    [[TMP25:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP26:%.*]] = load i32, ptr [[TMP25]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP26]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP26]])
 // CHECK9-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK9:       omp.precond.end:
 // CHECK9-NEXT:    ret void
@@ -917,7 +917,7 @@ int main (int argc, char **argv) {
 // CHECK9-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK9-NEXT:    [[TMP14:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP15:%.*]] = load i32, ptr [[TMP14]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_init_8(ptr @[[GLOB2]], i32 [[TMP15]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1)
+// CHECK9-NEXT:    call void @__kmpc_for_static_init_8(ptr @[[GLOB2:[0-9]+]], i32 [[TMP15]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1)
 // CHECK9-NEXT:    [[TMP16:%.*]] = load i64, ptr [[DOTOMP_UB]], align 8
 // CHECK9-NEXT:    [[TMP17:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_5]], align 8
 // CHECK9-NEXT:    [[CMP13:%.*]] = icmp sgt i64 [[TMP16]], [[TMP17]]
@@ -1124,7 +1124,7 @@ int main (int argc, char **argv) {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK9-NEXT:    ret void
 //
 //
@@ -1487,7 +1487,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.loop.exit:
 // CHECK11-NEXT:    [[TMP27:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP28:%.*]] = load i32, ptr [[TMP27]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP28]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP28]])
 // CHECK11-NEXT:    br label [[OMP_PRECOND_END]]
 // CHECK11:       omp.precond.end:
 // CHECK11-NEXT:    ret void
@@ -1571,7 +1571,7 @@ int main (int argc, char **argv) {
 // CHECK11-NEXT:    store i32 0, ptr [[DOTOMP_IS_LAST]], align 4
 // CHECK11-NEXT:    [[TMP14:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK11-NEXT:    [[TMP15:%.*]] = load i32, ptr [[TMP14]], align 4
-// CHECK11-NEXT:    call void @__kmpc_for_static_init_8(ptr @[[GLOB2]], i32 [[TMP15]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1)
+// CHECK11-NEXT:    call void @__kmpc_for_static_init_8(ptr @[[GLOB2:[0-9]+]], i32 [[TMP15]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i64 1, i64 1)
 // CHECK11-NEXT:    [[TMP16:%.*]] = load i64, ptr [[DOTOMP_UB]], align 8
 // CHECK11-NEXT:    [[TMP17:%.*]] = load i64, ptr [[DOTCAPTURE_EXPR_5]], align 8
 // CHECK11-NEXT:    [[CMP15:%.*]] = icmp sgt i64 [[TMP16]], [[TMP17]]
@@ -1774,7 +1774,7 @@ int main (int argc, char **argv) {
 // CHECK11:       omp.inner.for.end:
 // CHECK11-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK11:       omp.loop.exit:
-// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]])
+// CHECK11-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK11-NEXT:    ret void
 //
 //
diff --git a/clang/test/OpenMP/teams_generic_loop_private_codegen.cpp b/clang/test/OpenMP/teams_generic_loop_private_codegen.cpp
index ab5cbdf1b8c9e415ddcfa09ff5da854d86000a2a..5ef729f044e09708a860fe1d49c3cb96d425b4fb 100644
--- a/clang/test/OpenMP/teams_generic_loop_private_codegen.cpp
+++ b/clang/test/OpenMP/teams_generic_loop_private_codegen.cpp
@@ -382,7 +382,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP13:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP14]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP14]])
 // CHECK1-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK1-NEXT:    [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0
 // CHECK1-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN2]], i64 2
@@ -443,7 +443,7 @@ int main() {
 // CHECK1-NEXT:    call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]])
 // CHECK1-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK1-NEXT:    [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK1-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1
 // CHECK1-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -690,7 +690,7 @@ int main() {
 // CHECK1:       omp.loop.exit:
 // CHECK1-NEXT:    [[TMP13:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP14:%.*]] = load i32, ptr [[TMP13]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP14]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP14]])
 // CHECK1-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK1-NEXT:    [[ARRAY_BEGIN4:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0
 // CHECK1-NEXT:    [[TMP15:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN4]], i64 2
@@ -1113,7 +1113,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP12]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP12]])
 // CHECK3-NEXT:    call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK3-NEXT:    [[ARRAY_BEGIN2:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR]], i32 0, i32 0
 // CHECK3-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN2]], i32 2
@@ -1172,7 +1172,7 @@ int main() {
 // CHECK3-NEXT:    call void @_ZN1SIfEC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]])
 // CHECK3-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK3-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK3-NEXT:    [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK3-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1
 // CHECK3-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -1415,7 +1415,7 @@ int main() {
 // CHECK3:       omp.loop.exit:
 // CHECK3-NEXT:    [[TMP11:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP12:%.*]] = load i32, ptr [[TMP11]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP12]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP12]])
 // CHECK3-NEXT:    call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR]]) #[[ATTR2]]
 // CHECK3-NEXT:    [[ARRAY_BEGIN4:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR]], i32 0, i32 0
 // CHECK3-NEXT:    [[TMP13:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN4]], i32 2
@@ -1793,7 +1793,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP1]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP1]])
 // CHECK9-NEXT:    ret void
 //
 //
@@ -1835,7 +1835,7 @@ int main() {
 // CHECK9-NEXT:    store ptr [[G1]], ptr [[_TMP3]], align 8
 // CHECK9-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP3:%.*]] = load i32, ptr [[TMP2]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK9-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP3]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK9-NEXT:    [[TMP4:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK9-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP4]], 1
 // CHECK9-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
diff --git a/clang/test/OpenMP/teams_generic_loop_reduction_codegen.cpp b/clang/test/OpenMP/teams_generic_loop_reduction_codegen.cpp
index f91ee759cddf0d3712e135450a2e8f95133d8f9a..4da49eed32efd2dfcd9b6bb0b8e0c0f7db51d4b4 100644
--- a/clang/test/OpenMP/teams_generic_loop_reduction_codegen.cpp
+++ b/clang/test/OpenMP/teams_generic_loop_reduction_codegen.cpp
@@ -223,7 +223,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK1-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
 // CHECK1-NEXT:    store ptr [[SIVAR1]], ptr [[TMP14]], align 8
 // CHECK1-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3:[0-9]+]], i32 [[TMP2]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l68.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -282,7 +282,7 @@ int main() {
 // CHECK1-NEXT:    store i32 0, ptr [[SIVAR2]], align 4
 // CHECK1-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK1-NEXT:    [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
-// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK1-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK1-NEXT:    [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK1-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 1
 // CHECK1-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -516,7 +516,7 @@ int main() {
 // CHECK1:       omp.inner.for.end:
 // CHECK1-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK1:       omp.loop.exit:
-// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]])
+// CHECK1-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK1-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
 // CHECK1-NEXT:    store ptr [[T_VAR1]], ptr [[TMP14]], align 8
 // CHECK1-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP2]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -806,7 +806,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK3-NEXT:    [[TMP12:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0
 // CHECK3-NEXT:    store ptr [[SIVAR1]], ptr [[TMP12]], align 4
 // CHECK3-NEXT:    [[TMP13:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3:[0-9]+]], i32 [[TMP2]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l68.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -863,7 +863,7 @@ int main() {
 // CHECK3-NEXT:    store i32 0, ptr [[SIVAR1]], align 4
 // CHECK3-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
 // CHECK3-NEXT:    [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
-// CHECK3-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK3-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK3-NEXT:    [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK3-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 1
 // CHECK3-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
@@ -1095,7 +1095,7 @@ int main() {
 // CHECK3:       omp.inner.for.end:
 // CHECK3-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK3:       omp.loop.exit:
-// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP2]])
+// CHECK3-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK3-NEXT:    [[TMP12:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i32 0, i32 0
 // CHECK3-NEXT:    store ptr [[T_VAR1]], ptr [[TMP12]], align 4
 // CHECK3-NEXT:    [[TMP13:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3]], i32 [[TMP2]], i32 1, i32 4, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}__Z5tmainIiET_v_l32.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -1336,7 +1336,7 @@ int main() {
 // CHECK9:       omp.inner.for.end:
 // CHECK9-NEXT:    br label [[OMP_LOOP_EXIT:%.*]]
 // CHECK9:       omp.loop.exit:
-// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB2:[0-9]+]], i32 [[TMP2]])
+// CHECK9-NEXT:    call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP2]])
 // CHECK9-NEXT:    [[TMP14:%.*]] = getelementptr inbounds [1 x ptr], ptr [[DOTOMP_REDUCTION_RED_LIST]], i64 0, i64 0
 // CHECK9-NEXT:    store ptr [[SIVAR1]], ptr [[TMP14]], align 8
 // CHECK9-NEXT:    [[TMP15:%.*]] = call i32 @__kmpc_reduce_nowait(ptr @[[GLOB3:[0-9]+]], i32 [[TMP2]], i32 1, i64 8, ptr [[DOTOMP_REDUCTION_RED_LIST]], ptr @{{__omp_offloading_[0-9a-z]+_[0-9a-z]+}}_main_l45.omp_outlined.omp.reduction.reduction_func, ptr @.gomp_critical_user_.reduction.var)
@@ -1396,7 +1396,7 @@ int main() {
 // CHECK9-NEXT:    store i32 0, ptr [[SIVAR2]], align 4
 // CHECK9-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
 // CHECK9-NEXT:    [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
-// CHECK9-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK9-NEXT:    call void @__kmpc_for_static_init_4(ptr @[[GLOB2:[0-9]+]], i32 [[TMP4]], i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
 // CHECK9-NEXT:    [[TMP5:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
 // CHECK9-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[TMP5]], 1
 // CHECK9-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
diff --git a/clang/test/Parser/c23-constexpr.c b/clang/test/Parser/c23-constexpr.c
new file mode 100644
index 0000000000000000000000000000000000000000..156128fa0745cd2c995fa22ec9c9c142b734bf9f
--- /dev/null
+++ b/clang/test/Parser/c23-constexpr.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify=c23 -std=c23 %s -Wpre-c2x-compat
+// RUN: %clang_cc1 -fsyntax-only -verify=c17 -std=c17 %s
+
+constexpr int a = 0; // c17-error {{unknown type name 'constexpr'}} \
+                        c23-warning {{'constexpr' is incompatible with C standards before C23}}
+
+void func(int array[constexpr]); // c23-error {{expected expression}} \
+                                 // c17-error {{use of undeclared}}
+
+_Atomic constexpr int b = 0; // c23-error {{constexpr variable cannot have type 'const _Atomic(int)'}} \
+                             // c23-warning {{'constexpr' is incompatible with C standards before C23}} \
+                             // c17-error {{unknown type name 'constexpr'}}
+
+int static constexpr c = 1; // c17-error {{expected ';' after top level declarator}} \
+                            // c23-warning {{'constexpr' is incompatible with C standards before C23}}
diff --git a/clang/test/Parser/cxx-declarator-attribute-crash.cpp b/clang/test/Parser/cxx-declarator-attribute-crash.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3b989a659db5691e8d0f639efad5b98db84d4ef5
--- /dev/null
+++ b/clang/test/Parser/cxx-declarator-attribute-crash.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// expected-error@+5{{brackets are not allowed here}}
+// expected-error@+4{{a type specifier is required for all declarations}}
+// expected-warning@+3{{unknown attribute 'h' ignored}}
+// expected-error@+2{{definition of variable with array type}}
+// expected-error@+1{{expected ';'}}
+[][[h]]l
diff --git a/clang/test/Parser/cxx23-assume.cpp b/clang/test/Parser/cxx23-assume.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..269fb7e599443e188b6e285cea9bfadf38cb8e0a
--- /dev/null
+++ b/clang/test/Parser/cxx23-assume.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++23 -x c++ %s -verify
+
+void f(int x, int y) {
+  [[assume(true)]];
+  [[assume(1)]];
+  [[assume(1.0)]];
+  [[assume(1 + 2 == 3)]];
+  [[assume(x ? 1 : 2)]];
+  [[assume(x && y)]];
+  [[assume(true)]] [[assume(true)]];
+
+  [[assume]]; // expected-error {{takes one argument}}
+  [[assume(]]; // expected-error {{expected expression}}
+  [[assume()]]; // expected-error {{expected expression}}
+  [[assume(2]]; // expected-error {{expected ')'}} expected-note {{to match this '('}}
+  [[assume(x = 2)]]; // expected-error {{requires parentheses}}
+  [[assume(2, 3)]]; // expected-error {{requires parentheses}} expected-warning {{has no effect}}
+}
diff --git a/clang/test/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c
index fb2f51890d7d7f97a5a678f50f3e01bbd7bf5329..a82c3662f2ad9e129303b1963f1db29df45f1c12 100644
--- a/clang/test/ParserOpenACC/parse-clauses.c
+++ b/clang/test/ParserOpenACC/parse-clauses.c
@@ -60,12 +60,14 @@ void func() {
   // expected-warning@+2{{OpenACC clause 'auto' not yet implemented, clause ignored}}
   // expected-warning@+1{{OpenACC construct 'kernels loop' not yet implemented, pragma ignored}}
 #pragma acc kernels loop seq independent auto
+  for(;;){}
 
   // expected-warning@+4{{OpenACC clause 'seq' not yet implemented, clause ignored}}
   // expected-warning@+3{{OpenACC clause 'independent' not yet implemented, clause ignored}}
   // expected-warning@+2{{OpenACC clause 'auto' not yet implemented, clause ignored}}
   // expected-warning@+1{{OpenACC construct 'serial loop' not yet implemented, pragma ignored}}
 #pragma acc serial loop seq, independent auto
+  {}
 
   // expected-warning@+4{{OpenACC clause 'seq' not yet implemented, clause ignored}}
   // expected-warning@+3{{OpenACC clause 'independent' not yet implemented, clause ignored}}
@@ -140,105 +142,90 @@ void DefaultClause() {
 #pragma acc serial loop default
   for(;;){}
 
-  // expected-error@+3{{expected '('}}
-  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+2{{expected '('}}
+  // expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
 #pragma acc serial default seq
   for(;;){}
 
-  // expected-error@+4{{expected '('}}
-  // expected-warning@+3{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected '('}}
+  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial default, seq
   for(;;){}
 
-  // expected-error@+5{{expected identifier}}
-  // expected-error@+4{{expected ')'}}
-  // expected-note@+3{{to match this '('}}
-  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+4{{expected identifier}}
+  // expected-error@+3{{expected ')'}}
+  // expected-note@+2{{to match this '('}}
+  // expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
 #pragma acc serial default(
   for(;;){}
 
-  // expected-error@+5{{invalid value for 'default' clause; expected 'present' or 'none'}}
-  // expected-error@+4{{expected ')'}}
-  // expected-note@+3{{to match this '('}}
-  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+4{{invalid value for 'default' clause; expected 'present' or 'none'}}
+  // expected-error@+3{{expected ')'}}
+  // expected-note@+2{{to match this '('}}
+  // expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
 #pragma acc serial default( seq
   for(;;){}
 
-  // expected-error@+5{{expected identifier}}
-  // expected-error@+4{{expected ')'}}
-  // expected-note@+3{{to match this '('}}
-  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+4{{expected identifier}}
+  // expected-error@+3{{expected ')'}}
+  // expected-note@+2{{to match this '('}}
+  // expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
 #pragma acc serial default(, seq
   for(;;){}
 
-  // expected-error@+4{{expected '('}}
-  // expected-error@+3{{expected identifier}}
-  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected '('}}
+  // expected-error@+2{{expected identifier}}
+  // expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
 #pragma acc serial default)
   for(;;){}
 
-  // expected-error@+4{{expected '('}}
-  // expected-error@+3{{expected identifier}}
-  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected '('}}
+  // expected-error@+2{{expected identifier}}
+  // expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
 #pragma acc serial default), seq
   for(;;){}
 
-  // expected-error@+3{{expected identifier}}
-  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+2{{expected identifier}}
+  // expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
 #pragma acc serial default()
   for(;;){}
 
-  // expected-error@+4{{expected identifier}}
-  // expected-warning@+3{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected identifier}}
+  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial default() seq
   for(;;){}
 
-  // expected-error@+4{{expected identifier}}
-  // expected-warning@+3{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected identifier}}
+  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial default(), seq
   for(;;){}
 
-  // expected-error@+3{{invalid value for 'default' clause; expected 'present' or 'none'}}
-  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+2{{invalid value for 'default' clause; expected 'present' or 'none'}}
+  // expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
 #pragma acc serial default(invalid)
   for(;;){}
 
-  // expected-error@+4{{invalid value for 'default' clause; expected 'present' or 'none'}}
-  // expected-warning@+3{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{invalid value for 'default' clause; expected 'present' or 'none'}}
+  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial default(auto) seq
   for(;;){}
 
-  // expected-error@+4{{invalid value for 'default' clause; expected 'present' or 'none'}}
-  // expected-warning@+3{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{invalid value for 'default' clause; expected 'present' or 'none'}}
+  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial default(invalid), seq
   for(;;){}
 
-  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+1{{OpenACC clause 'default' not yet implemented, clause ignored}}
 #pragma acc serial default(none)
   for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'default' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'default' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial default(present), seq
   for(;;){}
 }
@@ -250,108 +237,93 @@ void IfClause() {
 #pragma acc serial loop if
   for(;;){}
 
-  // expected-error@+3{{expected '('}}
-  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+2{{expected '('}}
+  // expected-warning@+1{{OpenACC clause 'if' not yet implemented, clause ignored}}
 #pragma acc serial if seq
   for(;;){}
 
-  // expected-error@+4{{expected '('}}
-  // expected-warning@+3{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected '('}}
+  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial if, seq
   for(;;){}
 
-  // expected-error@+5{{expected expression}}
-  // expected-error@+4{{expected ')'}}
-  // expected-note@+3{{to match this '('}}
-  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+4{{expected expression}}
+  // expected-error@+3{{expected ')'}}
+  // expected-note@+2{{to match this '('}}
+  // expected-warning@+1{{OpenACC clause 'if' not yet implemented, clause ignored}}
 #pragma acc serial if(
   for(;;){}
 
-  // expected-error@+5{{use of undeclared identifier 'seq'}}
-  // expected-error@+4{{expected ')'}}
-  // expected-note@+3{{to match this '('}}
-  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+4{{use of undeclared identifier 'seq'}}
+  // expected-error@+3{{expected ')'}}
+  // expected-note@+2{{to match this '('}}
+  // expected-warning@+1{{OpenACC clause 'if' not yet implemented, clause ignored}}
 #pragma acc serial if( seq
   for(;;){}
 
-  // expected-error@+6{{expected expression}}
-  // expected-error@+5{{use of undeclared identifier 'seq'}}
-  // expected-error@+4{{expected ')'}}
-  // expected-note@+3{{to match this '('}}
-  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+5{{expected expression}}
+  // expected-error@+4{{use of undeclared identifier 'seq'}}
+  // expected-error@+3{{expected ')'}}
+  // expected-note@+2{{to match this '('}}
+  // expected-warning@+1{{OpenACC clause 'if' not yet implemented, clause ignored}}
 #pragma acc serial if(, seq
   for(;;){}
 
-  // expected-error@+4{{expected '('}}
-  // expected-error@+3{{expected identifier}}
-  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected '('}}
+  // expected-error@+2{{expected identifier}}
+  // expected-warning@+1{{OpenACC clause 'if' not yet implemented, clause ignored}}
 #pragma acc serial if)
   for(;;){}
 
-  // expected-error@+4{{expected '('}}
-  // expected-error@+3{{expected identifier}}
-  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected '('}}
+  // expected-error@+2{{expected identifier}}
+  // expected-warning@+1{{OpenACC clause 'if' not yet implemented, clause ignored}}
 #pragma acc serial if) seq
   for(;;){}
 
-  // expected-error@+4{{expected '('}}
-  // expected-error@+3{{expected identifier}}
-  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected '('}}
+  // expected-error@+2{{expected identifier}}
+  // expected-warning@+1{{OpenACC clause 'if' not yet implemented, clause ignored}}
 #pragma acc serial if), seq
   for(;;){}
 
-  // expected-error@+3{{expected expression}}
-  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+2{{expected expression}}
+  // expected-warning@+1{{OpenACC clause 'if' not yet implemented, clause ignored}}
 #pragma acc serial if()
   for(;;){}
 
-  // expected-error@+4{{expected expression}}
-  // expected-warning@+3{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected expression}}
+  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial if() seq
   for(;;){}
 
-  // expected-error@+4{{expected expression}}
-  // expected-warning@+3{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected expression}}
+  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial if(), seq
   for(;;){}
 
-  // expected-error@+3{{use of undeclared identifier 'invalid_expr'}}
-  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+2{{use of undeclared identifier 'invalid_expr'}}
+  // expected-warning@+1{{OpenACC clause 'if' not yet implemented, clause ignored}}
 #pragma acc serial if(invalid_expr)
   for(;;){}
 
-  // expected-error@+4{{expected expression}}
-  // expected-warning@+3{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected expression}}
+  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial if() seq
   for(;;){}
 
   int i, j;
 
-  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+1{{OpenACC clause 'if' not yet implemented, clause ignored}}
 #pragma acc serial if(i > j)
   for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'if' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'if' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial if(1+5>3), seq
   for(;;){}
 }
@@ -436,35 +408,30 @@ void SelfClause() {
 
   int i, j;
 
-  // expected-error@+4{{expected ')'}}
-  // expected-note@+3{{to match this '('}}
-  // expected-warning@+2{{OpenACC clause 'self' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ')'}}
+  // expected-note@+2{{to match this '('}}
+  // expected-warning@+1{{OpenACC clause 'self' not yet implemented, clause ignored}}
 #pragma acc serial self(i > j
   for(;;){}
 
-  // expected-error@+5{{use of undeclared identifier 'seq'}}
-  // expected-error@+4{{expected ')'}}
-  // expected-note@+3{{to match this '('}}
-  // expected-warning@+2{{OpenACC clause 'self' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+4{{use of undeclared identifier 'seq'}}
+  // expected-error@+3{{expected ')'}}
+  // expected-note@+2{{to match this '('}}
+  // expected-warning@+1{{OpenACC clause 'self' not yet implemented, clause ignored}}
 #pragma acc serial self(i > j, seq
   for(;;){}
 
-  // expected-warning@+3{{left operand of comma operator has no effect}}
-  // expected-warning@+2{{OpenACC clause 'self' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{left operand of comma operator has no effect}}
+  // expected-warning@+1{{OpenACC clause 'self' not yet implemented, clause ignored}}
 #pragma acc serial self(i, j)
   for(;;){}
 
-  // expected-warning@+2{{OpenACC clause 'self' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+1{{OpenACC clause 'self' not yet implemented, clause ignored}}
 #pragma acc serial self(i > j)
   for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'self' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'self' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial self(1+5>3), seq
   for(;;){}
 }
@@ -502,478 +469,478 @@ void SelfUpdate() {
 }
 
 void VarListClauses() {
-  // expected-error@+3{{expected '('}}
-  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+2{{expected '('}}
+  // expected-warning@+1{{OpenACC clause 'copy' not yet implemented, clause ignored}}
 #pragma acc serial copy
+  for(;;){}
 
-  // expected-error@+4{{expected '('}}
-  // expected-warning@+3{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected '('}}
+  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy, seq
+  for(;;){}
 
-  // expected-error@+4{{expected '('}}
-  // expected-error@+3{{expected identifier}}
-  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected '('}}
+  // expected-error@+2{{expected identifier}}
+  // expected-warning@+1{{OpenACC clause 'copy' not yet implemented, clause ignored}}
 #pragma acc serial copy)
+  for(;;){}
 
-  // expected-error@+4{{expected '('}}
-  // expected-error@+3{{expected identifier}}
-  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected '('}}
+  // expected-error@+2{{expected identifier}}
+  // expected-warning@+1{{OpenACC clause 'copy' not yet implemented, clause ignored}}
 #pragma acc serial copy), seq
+  for(;;){}
 
-  // expected-error@+5{{expected expression}}
-  // expected-error@+4{{expected ')'}}
-  // expected-note@+3{{to match this '('}}
-  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+4{{expected expression}}
+  // expected-error@+3{{expected ')'}}
+  // expected-note@+2{{to match this '('}}
+  // expected-warning@+1{{OpenACC clause 'copy' not yet implemented, clause ignored}}
 #pragma acc serial copy(
+  for(;;){}
 
-  // expected-error@+5{{expected expression}}
-  // expected-error@+4{{expected ')'}}
-  // expected-note@+3{{to match this '('}}
-  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+4{{expected expression}}
+  // expected-error@+3{{expected ')'}}
+  // expected-note@+2{{to match this '('}}
+  // expected-warning@+1{{OpenACC clause 'copy' not yet implemented, clause ignored}}
 #pragma acc serial copy(, seq
+  for(;;){}
 
-  // expected-error@+3{{expected expression}}
-  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+2{{expected expression}}
+  // expected-warning@+1{{OpenACC clause 'copy' not yet implemented, clause ignored}}
 #pragma acc serial copy()
+  for(;;){}
 
-  // expected-error@+4{{expected expression}}
-  // expected-warning@+3{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected expression}}
+  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(), seq
+  for(;;){}
 
   struct Members s;
   struct HasMembersArray HasMem;
 
-  // expected-warning@+3{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(s.array[s.value]), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(s.array[s.value], s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(HasMem.MemArr[3].array[1]), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(HasMem.MemArr[3].array[1:4]), seq
+  for(;;){}
 
-  // expected-error@+4{{OpenMP array section is not allowed here}}
-  // expected-warning@+3{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{OpenMP array section is not allowed here}}
+  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(HasMem.MemArr[1:3].array[1]), seq
+  for(;;){}
 
-  // expected-error@+4{{OpenMP array section is not allowed here}}
-  // expected-warning@+3{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{OpenMP array section is not allowed here}}
+  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(HasMem.MemArr[1:3].array[1:2]), seq
+  for(;;){}
 
-  // expected-error@+4{{expected expression}}
-  // expected-warning@+3{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected expression}}
+  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(HasMem.MemArr[:]), seq
+  for(;;){}
 
-  // expected-error@+4{{expected expression}}
-  // expected-warning@+3{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected expression}}
+  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(HasMem.MemArr[::]), seq
+  for(;;){}
 
-  // expected-error@+6{{expected expression}}
-  // expected-error@+5{{expected ']'}}
-  // expected-note@+4{{to match this '['}}
-  // expected-warning@+3{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+5{{expected expression}}
+  // expected-error@+4{{expected ']'}}
+  // expected-note@+3{{to match this '['}}
+  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(HasMem.MemArr[: :]), seq
+  for(;;){}
 
-  // expected-error@+4{{expected expression}}
-  // expected-warning@+3{{OpenACC clause 'copy' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected expression}}
+  // expected-warning@+2{{OpenACC clause 'copy' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copy(HasMem.MemArr[3:]), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'use_device' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'use_device' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial use_device(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'use_device' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'use_device' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial use_device(s.array[s.value : 5]), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'no_create' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'no_create' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial no_create(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'no_create' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'no_create' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial no_create(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'present' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'present' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial present(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'present' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'present' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial present(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'deviceptr' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'deviceptr' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial deviceptr(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'deviceptr' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'deviceptr' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial deviceptr(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'attach' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'attach' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial attach(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'attach' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'attach' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial attach(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'detach' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'detach' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial detach(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'detach' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'detach' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial detach(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'private' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'private' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial private(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'private' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'private' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial private(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'firstprivate' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'firstprivate' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial firstprivate(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'firstprivate' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'firstprivate' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial firstprivate(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'delete' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'delete' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial delete(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'delete' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'delete' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial delete(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'use_device' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'use_device' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial use_device(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'use_device' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'use_device' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial use_device(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'device_resident' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'device_resident' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial device_resident(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'device_resident' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'device_resident' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial device_resident(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'link' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'link' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial link(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'link' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'link' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial link(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'host' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'host' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial host(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'host' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'host' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial host(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'device' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'device' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial device(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'device' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'device' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial device(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyout(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyout(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyout(zero:s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyout(zero : s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{use of undeclared identifier 'zero'}}
-  // expected-warning@+3{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{use of undeclared identifier 'zero'}}
+  // expected-warning@+2{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyout(zero s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{invalid tag 'readonly' on 'copyout' clause}}
-  // expected-warning@+3{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{invalid tag 'readonly' on 'copyout' clause}}
+  // expected-warning@+2{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyout(readonly:s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{invalid tag 'invalid' on 'copyout' clause}}
-  // expected-warning@+3{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{invalid tag 'invalid' on 'copyout' clause}}
+  // expected-warning@+2{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyout(invalid:s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{invalid tag 'invalid' on 'copyout' clause}}
-  // expected-warning@+3{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{invalid tag 'invalid' on 'copyout' clause}}
+  // expected-warning@+2{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyout(invalid:s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{use of undeclared identifier 'invalid'}}
-  // expected-warning@+3{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{use of undeclared identifier 'invalid'}}
+  // expected-warning@+2{{OpenACC clause 'copyout' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyout(invalid s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'create' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'create' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial create(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'create' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'create' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial create(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'create' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'create' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial create(zero:s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'create' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'create' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial create(zero : s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{use of undeclared identifier 'zero'}}
-  // expected-warning@+3{{OpenACC clause 'create' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{use of undeclared identifier 'zero'}}
+  // expected-warning@+2{{OpenACC clause 'create' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial create(zero s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{invalid tag 'readonly' on 'create' clause}}
-  // expected-warning@+3{{OpenACC clause 'create' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{invalid tag 'readonly' on 'create' clause}}
+  // expected-warning@+2{{OpenACC clause 'create' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial create(readonly:s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{invalid tag 'invalid' on 'create' clause}}
-  // expected-warning@+3{{OpenACC clause 'create' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{invalid tag 'invalid' on 'create' clause}}
+  // expected-warning@+2{{OpenACC clause 'create' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial create(invalid:s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{invalid tag 'invalid' on 'create' clause}}
-  // expected-warning@+3{{OpenACC clause 'create' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{invalid tag 'invalid' on 'create' clause}}
+  // expected-warning@+2{{OpenACC clause 'create' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial create(invalid:s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{use of undeclared identifier 'invalid'}}
-  // expected-warning@+3{{OpenACC clause 'create' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{use of undeclared identifier 'invalid'}}
+  // expected-warning@+2{{OpenACC clause 'create' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial create(invalid s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{expected ','}}
-  // expected-warning@+3{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected ','}}
+  // expected-warning@+2{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyin(s.array[s.value] s.array[s.value :5] ), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyin(s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyin(readonly:s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-warning@+3{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+2{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyin(readonly : s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{use of undeclared identifier 'readonly'}}
-  // expected-warning@+3{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{use of undeclared identifier 'readonly'}}
+  // expected-warning@+2{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyin(readonly s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{invalid tag 'zero' on 'copyin' clause}}
-  // expected-warning@+3{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{invalid tag 'zero' on 'copyin' clause}}
+  // expected-warning@+2{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyin(zero :s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{invalid tag 'invalid' on 'copyin' clause}}
-  // expected-warning@+3{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{invalid tag 'invalid' on 'copyin' clause}}
+  // expected-warning@+2{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyin(invalid:s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{invalid tag 'invalid' on 'copyin' clause}}
-  // expected-warning@+3{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{invalid tag 'invalid' on 'copyin' clause}}
+  // expected-warning@+2{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyin(invalid:s.array[s.value : 5], s.value), seq
+  for(;;){}
 
-  // expected-error@+4{{use of undeclared identifier 'invalid'}}
-  // expected-warning@+3{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{use of undeclared identifier 'invalid'}}
+  // expected-warning@+2{{OpenACC clause 'copyin' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial copyin(invalid s.array[s.value : 5], s.value), seq
+  for(;;){}
 }
 
 void ReductionClauseParsing() {
   char *Begin, *End;
-  // expected-error@+3{{expected '('}}
-  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+2{{expected '('}}
+  // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
 #pragma acc serial reduction
-  // expected-error@+4{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
-  // expected-error@+3{{expected expression}}
-  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
-#pragma acc serial reduction()
+  for(;;){}
   // expected-error@+3{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
-  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+2{{expected expression}}
+  // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
+#pragma acc serial reduction()
+  for(;;){}
+  // expected-error@+2{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
+  // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
 #pragma acc serial reduction(Begin)
-  // expected-error@+3{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
-  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  for(;;){}
+  // expected-error@+2{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
+  // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
 #pragma acc serial reduction(Begin, End)
-  // expected-error@+3{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
-  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  for(;;){}
+  // expected-error@+2{{missing reduction operator, expected '+', '*', 'max', 'min', '&', '|', '^', '&&', or '||', follwed by a ':'}}
+  // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
 #pragma acc serial reduction(Begin, End)
-  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  for(;;){}
+  // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
 #pragma acc serial reduction(+:Begin)
-  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  for(;;){}
+  // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
 #pragma acc serial reduction(+:Begin, End)
-  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  for(;;){}
+  // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
 #pragma acc serial reduction(*: Begin, End)
-  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  for(;;){}
+  // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
 #pragma acc serial reduction(max : Begin, End)
-  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  for(;;){}
+  // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
 #pragma acc serial reduction(min: Begin, End)
-  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  for(;;){}
+  // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
 #pragma acc serial reduction(&: Begin, End)
-  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  for(;;){}
+  // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
 #pragma acc serial reduction(|: Begin, End)
-  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  for(;;){}
+  // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
 #pragma acc serial reduction(^: Begin, End)
-  // expected-warning@+3{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
-#pragma acc serial seq, reduction(&&: Begin, End)
-  // expected-warning@+3{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
+  for(;;){}
   // expected-warning@+2{{OpenACC clause 'seq' not yet implemented, clause ignored}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-warning@+1{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
+#pragma acc serial seq, reduction(&&: Begin, End)
+  for(;;){}
+  // expected-warning@+2{{OpenACC clause 'reduction' not yet implemented, clause ignored}}
+  // expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
 #pragma acc serial reduction(||: Begin, End), seq
+  for(;;){}
 }
 
 int returns_int();
diff --git a/clang/test/ParserOpenACC/parse-constructs.c b/clang/test/ParserOpenACC/parse-constructs.c
index adb5e3c7c7552736f7a6815bcf792a5e74a9bf5a..ecedfd9e9e6d6a48314b9b07b008b71d0d94fa3a 100644
--- a/clang/test/ParserOpenACC/parse-constructs.c
+++ b/clang/test/ParserOpenACC/parse-constructs.c
@@ -39,23 +39,19 @@ void func() {
   // expected-note@+1{{to match this '('}}
 #pragma acc parallel( clause list
   for(;;){}
-  // expected-error@+3{{expected clause-list or newline in OpenACC directive}}
-  // expected-error@+2{{invalid OpenACC clause 'clause'}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+2{{expected clause-list or newline in OpenACC directive}}
+  // expected-error@+1{{invalid OpenACC clause 'clause'}}
 #pragma acc serial() clause list
   for(;;){}
-  // expected-error@+4{{expected clause-list or newline in OpenACC directive}}
-  // expected-error@+3{{expected ')'}}
-  // expected-note@+2{{to match this '('}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+3{{expected clause-list or newline in OpenACC directive}}
+  // expected-error@+2{{expected ')'}}
+  // expected-note@+1{{to match this '('}}
 #pragma acc serial( clause list
   for(;;){}
-  // expected-error@+2{{invalid OpenACC clause 'clause'}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+1{{invalid OpenACC clause 'clause'}}
 #pragma acc serial clause list
   for(;;){}
-  // expected-error@+2{{invalid OpenACC clause 'clause'}}
-  // expected-warning@+1{{OpenACC construct 'kernels' not yet implemented, pragma ignored}}
+  // expected-error@+1{{invalid OpenACC clause 'clause'}}
 #pragma acc kernels clause list
   for(;;){}
   // expected-error@+2{{invalid OpenACC clause 'clause'}}
@@ -93,8 +89,7 @@ void func() {
   // expected-error@+1{{invalid OpenACC clause 'invalid'}}
 #pragma acc parallel invalid clause list
   for(;;){}
-  // expected-error@+2{{invalid OpenACC clause 'invalid'}}
-  // expected-warning@+1{{OpenACC construct 'serial' not yet implemented, pragma ignored}}
+  // expected-error@+1{{invalid OpenACC clause 'invalid'}}
 #pragma acc serial invalid clause list
   for(;;){}
   // expected-error@+2{{invalid OpenACC clause 'clause'}}
diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c
index 664279cb123949c23161e68435c73afb5ae853e5..1a15be1c6e4dc13642db0a4b315f688fc2d8eac1 100644
--- a/clang/test/Preprocessor/riscv-target-features.c
+++ b/clang/test/Preprocessor/riscv-target-features.c
@@ -29,6 +29,7 @@
 // CHECK-NOT: __riscv_smepmp {{.*$}}
 // CHECK-NOT: __riscv_ssaia {{.*$}}
 // CHECK-NOT: __riscv_ssccptr {{.*$}}
+// CHECK-NOT: __riscv_sscofpmf {{.*$}}
 // CHECK-NOT: __riscv_sscounterenw {{.*$}}
 // CHECK-NOT: __riscv_ssstateen {{.*$}}
 // CHECK-NOT: __riscv_ssstrict {{.*$}}
@@ -351,6 +352,14 @@
 // RUN:   -o - | FileCheck --check-prefix=CHECK-SSCCPTR-EXT %s
 // CHECK-SSCCPTR-EXT: __riscv_ssccptr 1000000{{$}}
 
+// RUN: %clang --target=riscv32-unknown-linux-gnu \
+// RUN:   -march=rv32isscofpmf -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-SSCOFPMF-EXT %s
+// RUN: %clang --target=riscv64-unknown-linux-gnu \
+// RUN:   -march=rv64isscofpmf -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-SSCOFPMF-EXT %s
+// CHECK-SSCOFPMF-EXT: __riscv_sscofpmf 1000000{{$}}
+
 // RUN: %clang --target=riscv32-unknown-linux-gnu \
 // RUN:   -march=rv32isscounterenw -E -dM %s \
 // RUN:   -o - | FileCheck --check-prefix=CHECK-SSCOUNTERENW-EXT %s
diff --git a/clang/test/Rewriter/rewrite-modern-class.mm b/clang/test/Rewriter/rewrite-modern-class.mm
index cf2143e86463b7d625304238e9b6007f34e62156..7d75a51502cd99790bb7e7b565373d1eed44a91b 100644
--- a/clang/test/Rewriter/rewrite-modern-class.mm
+++ b/clang/test/Rewriter/rewrite-modern-class.mm
@@ -44,7 +44,7 @@
 
 @implementation class_has_no_ivar @end
 
-//============================class needs to be synthesized here=====================
+//===================== class needs to be synthesized here =====================
 @interface SUPER  {
 @public
   double divar;
diff --git a/clang/test/Sema/aarch64-sve2p1-intrinsics/acle_sve2p1_imm.cpp b/clang/test/Sema/aarch64-sve2p1-intrinsics/acle_sve2p1_imm.cpp
index d857608d4415576ac80d386dab5e93d10b70833f..a6ec5150f0aabbc84eaaea90ac750d066d99435c 100644
--- a/clang/test/Sema/aarch64-sve2p1-intrinsics/acle_sve2p1_imm.cpp
+++ b/clang/test/Sema/aarch64-sve2p1-intrinsics/acle_sve2p1_imm.cpp
@@ -188,3 +188,32 @@ void test_svget_svset_b(uint64_t idx, svboolx2_t tuple2, svboolx4_t tuple4, svbo
   svget2_b(tuple2, idx); // expected-error {{argument to 'svget2_b' must be a constant integer}}
   svget4_b(tuple4, idx); // expected-error {{argument to 'svget4_b' must be a constant integer}}
 }
+
+__attribute__((target("+sve2p1")))
+void test_svdup_laneq(){  
+  svuint8_t zn_u8;
+  svuint16_t zn_u16;
+  svuint32_t zn_u32;
+  svuint64_t zn_u64;
+  svint8_t zn_s8;
+  svint16_t zn_s16;
+  svint32_t zn_s32;
+  svint64_t zn_s64;
+  svfloat16_t zn_f16;
+  svfloat32_t zn_f32;
+  svfloat64_t zn_f64;
+  svbfloat16_t zn_bf16;
+
+  svdup_laneq_u8(zn_u8,-1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 15]}}
+  svdup_laneq_u16(zn_u16,-1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 7]}}
+  svdup_laneq_u32(zn_u32,-1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 3]}}
+  svdup_laneq_u64(zn_u64,-1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 1]}}
+  svdup_laneq_s8(zn_s8,-1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 15]}}
+  svdup_laneq_s16(zn_s16,-1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 7]}}
+  svdup_laneq_s32(zn_s32,-1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 3]}}
+  svdup_laneq_s64(zn_s64,-1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 1]}}
+  svdup_laneq_f16(zn_f16,-1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 7]}}
+  svdup_laneq_f32(zn_f32,-1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 3]}}
+  svdup_laneq_f64(zn_f64,-1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 1]}}
+  svdup_laneq_bf16(zn_bf16,-1); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 7]}}
+}
\ No newline at end of file
diff --git a/clang/test/Sema/attr-availability-visionos.c b/clang/test/Sema/attr-availability-visionos.c
new file mode 100644
index 0000000000000000000000000000000000000000..2c388c5d529073b6ff6fdc969d15fc5405e92a92
--- /dev/null
+++ b/clang/test/Sema/attr-availability-visionos.c
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple arm64-apple-xros1 -fapplication-extension -verify=visionos %s 2>&1
+
+__attribute__((availability(xros, unavailable))) // visionos-warning {{unknown platform 'xros' in availability macro}}
+void xros_unavail(); // visionos-note {{}}
+
+__attribute__((availability(xros_app_extension, unavailable))) // visionos-warning {{unknown platform 'xros_app_extension' in availability macro}}
+void xros_ext_unavail(); // visionos-note {{}}
+
+__attribute__((availability(visionOSApplicationExtension, unavailable)))
+void visionos_ext_unavail(); // visionos-note {{}}
+
+void use() {
+  xros_unavail(); // visionos-error {{'xros_unavail' is unavailable: not available on visionOS}}
+  xros_ext_unavail(); // visionos-error {{'xros_ext_unavail' is unavailable: not available on visionOS}}
+  visionos_ext_unavail(); // visionos-error {{'visionos_ext_unavail' is unavailable: not available on visionOS}}
+}
+
+__attribute__((availability(visionOS, introduced=1.0)))
+void visionos_introduced_1();
+
+__attribute__((availability(visionos, introduced=1.1)))
+void visionos_introduced_1_1(); // visionos-note 4 {{'visionos_introduced_1_1' has been marked as being introduced in visionOS 1.1 here, but the deployment target is visionOS 1}}
+
+void use2() {
+  if (__builtin_available(iOS 16.1, *))
+    visionos_introduced_1_1(); // visionos-warning {{'visionos_introduced_1_1' is only available on visionOS 1.1 or newer}} visionos-note {{enclose}}
+                              
+  if (__builtin_available(xrOS 1.1, *)) // visionos-error {{unrecognized platform name xrOS}}
+    visionos_introduced_1_1(); // visionos-warning {{'visionos_introduced_1_1' is only available on visionOS 1.1 or newer}} visionos-note {{enclose}}
+  
+  if (__builtin_available(xros_app_extension 1, *)) // visionos-error {{unrecognized platform name xros_app_extension}}
+    visionos_introduced_1_1(); // visionos-warning {{'visionos_introduced_1_1' is only available on visionOS 1.1 or newer}} visionos-note {{enclose}}
+
+  if (__builtin_available(visionOS 1.1, *))
+    visionos_introduced_1_1();
+
+  visionos_introduced_1();
+  visionos_introduced_1_1(); // visionos-warning {{'visionos_introduced_1_1' is only available on visionOS 1.1 or newer}} visionos-note {{enclose}}
+}
diff --git a/clang/test/Sema/attr-target-version.c b/clang/test/Sema/attr-target-version.c
index 587c721de5e3226948bab09e7892b542251e0769..e2940c434c2ff5f2528a1eb1947efecb73022b33 100644
--- a/clang/test/Sema/attr-target-version.c
+++ b/clang/test/Sema/attr-target-version.c
@@ -42,12 +42,25 @@ void __attribute__((target_version("ssbs+fp16fml"))) two(void) {}
 //expected-error@+1 {{'main' cannot be a multiversioned function}}
 int __attribute__((target_version("lse"))) main(void) { return 1; }
 
-//expected-note@+1 {{previous definition is here}}
-int hoo(void) { return 1; }
-//expected-note@-1 {{previous definition is here}}
-//expected-warning@+2 {{attribute declaration must precede definition}}
-//expected-error@+1 {{redefinition of 'hoo'}}
-int __attribute__((target_version("dit"))) hoo(void) { return 2; }
+// It is ok for the default version to appear first.
+int default_first(void) { return 1; }
+int __attribute__((target_version("dit"))) default_first(void) { return 2; }
+int __attribute__((target_version("mops"))) default_first(void) { return 3; }
+
+// It is ok if the default version is between other versions.
+int __attribute__((target_version("simd"))) default_middle(void) {return 0; }
+int __attribute__((target_version("default"))) default_middle(void) { return 1; }
+int __attribute__((target_version("aes"))) default_middle(void) { return 2; }
+
+// It is ok for the default version to be the last one.
+int __attribute__((target_version("rdm"))) default_last(void) {return 0; }
+int __attribute__((target_version("lse+aes"))) default_last(void) { return 1; }
+int __attribute__((target_version("default"))) default_last(void) { return 2; }
+
+// It is also ok to forward declare the default.
+int __attribute__((target_version("default"))) default_fwd_declare(void);
+int __attribute__((target_version("sve"))) default_fwd_declare(void) { return 0; }
+int default_fwd_declare(void) { return 1; }
 
 //expected-warning@+1 {{unsupported '' in the 'target_version' attribute string; 'target_version' attribute ignored}}
 int __attribute__((target_version(""))) unsup1(void) { return 1; }
diff --git a/clang/test/Sema/constant-builtins-2.c b/clang/test/Sema/constant-builtins-2.c
index 2bdd7b06daabfea1c1c061bf64ac0973e9115c66..6dd1d88759c751837e536549068279f6aab2234a 100644
--- a/clang/test/Sema/constant-builtins-2.c
+++ b/clang/test/Sema/constant-builtins-2.c
@@ -237,6 +237,15 @@ char popcount7[__builtin_popcountl(~0L) == BITSIZE(long) ? 1 : -1];
 char popcount8[__builtin_popcountll(0LL) == 0 ? 1 : -1];
 char popcount9[__builtin_popcountll(0xF0F0LL) == 8 ? 1 : -1];
 char popcount10[__builtin_popcountll(~0LL) == BITSIZE(long long) ? 1 : -1];
+char popcount11[__builtin_popcountg(0U) == 0 ? 1 : -1];
+char popcount12[__builtin_popcountg(0xF0F0U) == 8 ? 1 : -1];
+char popcount13[__builtin_popcountg(~0U) == BITSIZE(int) ? 1 : -1];
+char popcount14[__builtin_popcountg(~0UL) == BITSIZE(long) ? 1 : -1];
+char popcount15[__builtin_popcountg(~0ULL) == BITSIZE(long long) ? 1 : -1];
+#ifdef __SIZEOF_INT128__
+char popcount16[__builtin_popcountg(~(unsigned __int128)0) == BITSIZE(__int128) ? 1 : -1];
+#endif
+char popcount17[__builtin_popcountg(~(unsigned _BitInt(128))0) == BITSIZE(_BitInt(128)) ? 1 : -1];
 
 char parity1[__builtin_parity(0) == 0 ? 1 : -1];
 char parity2[__builtin_parity(0xb821) == 0 ? 1 : -1];
diff --git a/clang/test/Sema/constexpr.c b/clang/test/Sema/constexpr.c
new file mode 100644
index 0000000000000000000000000000000000000000..8286cd2107d2f2b842684c5daf7dff7d8b915142
--- /dev/null
+++ b/clang/test/Sema/constexpr.c
@@ -0,0 +1,359 @@
+// RUN: %clang_cc1 -std=c23 -verify -triple x86_64 -pedantic -Wno-conversion -Wno-constant-conversion -Wno-div-by-zero %s
+
+// Check that constexpr only applies to variables.
+constexpr void f0() {} // expected-error {{'constexpr' can only be used in variable declarations}}
+constexpr const int f1() { return 0; } // expected-error {{'constexpr' can only be used in variable declarations}}
+
+constexpr struct S1 { int f; }; //expected-error {{struct cannot be marked constexpr}}
+constexpr struct S2 ; // expected-error {{struct cannot be marked constexpr}}
+constexpr union U1; // expected-error {{union cannot be marked constexpr}}
+constexpr union U2 {int a; float b;}; // expected-error {{union cannot be marked constexpr}}
+constexpr enum E1 {A = 1, B = 2} ; // expected-error {{enum cannot be marked constexpr}}
+struct S3 {
+  static constexpr int f = 0; // expected-error {{type name does not allow storage class}}
+  // expected-error@-1 {{type name does not allow constexpr}}
+  // expected-error@-2 {{expected ';' at end}}
+  constexpr int f1 = 0;
+  // expected-error@-1 {{type name does not allow constexpr}}
+  // expected-error@-2 {{expected ';' at end}}
+};
+
+constexpr; // expected-error {{'constexpr' can only be used in variable declarations}}
+constexpr int V1 = 3;
+constexpr float V2 = 7.0;
+int V3 = (constexpr)3; // expected-error {{expected expression}}
+
+void f2() {
+  constexpr int a = 0;
+  constexpr float b = 1.7f;
+}
+
+// Check how constexpr works with other storage-class specifiers.
+constexpr auto V4 = 1;
+constexpr static auto V5 = 1;
+constexpr static const auto V6 = 1;
+constexpr static const int V7 = 1;
+constexpr static int V8 = 1;
+constexpr auto Ulong = 1L;
+constexpr auto CompoundLiteral = (int){13};
+constexpr auto DoubleCast = (double)(1 / 3);
+constexpr auto String = "this is a string"; // expected-error {{constexpr pointer initializer is not null}}
+constexpr signed auto Long = 1L; // expected-error {{'auto' cannot be signed or unsigned}}
+_Static_assert(_Generic(Ulong, long : 1));
+_Static_assert(_Generic(CompoundLiteral, int : 1));
+_Static_assert(_Generic(DoubleCast, double : 1));
+_Static_assert(_Generic(String, char* : 1));
+
+typedef constexpr int Foo; // expected-error {{typedef cannot be constexpr}}
+constexpr typedef int Bar; // expected-error {{typedef cannot be constexpr}}
+
+void f3(constexpr register int P1) { // expected-error {{function parameter cannot be constexpr}}
+  constexpr register int V9 = 0;
+  constexpr register auto V10 = 0.0;
+}
+
+constexpr thread_local int V11 = 38; // expected-error {{cannot combine with previous '_Thread_local' declaration specifier}}
+constexpr static thread_local double V12 = 38; // expected-error {{cannot combine with previous '_Thread_local' declaration specifier}}
+constexpr extern thread_local char V13; // expected-error {{cannot combine with previous '_Thread_local' declaration specifier}}
+// expected-error@-1 {{cannot combine with previous 'extern' declaration specifier}}
+// expected-error@-2 {{constexpr variable declaration must be a definition}}
+constexpr thread_local short V14 = 38; // expected-error {{cannot combine with previous '_Thread_local' declaration specifier}}
+
+// Check how constexpr works with qualifiers.
+constexpr _Atomic int V15 = 0; // expected-error {{constexpr variable cannot have type 'const _Atomic(int)'}}
+constexpr _Atomic(int) V16 = 0; // expected-error {{constexpr variable cannot have type 'const _Atomic(int)'}}
+
+constexpr volatile int V17 = 0; // expected-error {{constexpr variable cannot have type 'const volatile int'}}
+
+constexpr int * restrict V18 = 0; // expected-error {{constexpr variable cannot have type 'int *const restrict'}}
+
+constexpr extern char Oops = 1; // expected-error {{cannot combine with previous 'extern' declaration specifier}} \
+                                // expected-warning {{'extern' variable has an initializer}}
+
+constexpr int * restrict * Oops1 = 0;
+
+typedef _Atomic(int) TheA;
+typedef volatile short TheV;
+typedef float * restrict TheR;
+
+constexpr TheA V19[3] = {};
+// expected-error@-1 {{constexpr variable cannot have type 'const TheA[3]' (aka 'const _Atomic(int)[3]')}}
+constexpr TheV V20[3] = {};
+// expected-error@-1 {{constexpr variable cannot have type 'const TheV[3]' (aka 'const volatile short[3]')}}
+constexpr TheR V21[3] = {};
+// expected-error@-1 {{constexpr variable cannot have type 'const TheR[3]' (aka 'float *restrict const[3]')}}
+
+struct HasA {
+  TheA f;
+  int b;
+};
+
+struct HasV {
+  float b;
+  TheV f;
+};
+
+struct HasR {
+  short b;
+  int a;
+  TheR f;
+};
+
+constexpr struct HasA V22[2] = {};
+// expected-error@-1 {{constexpr variable cannot have type 'TheA' (aka '_Atomic(int)')}}
+constexpr struct HasV V23[2] = {};
+// expected-error@-1 {{constexpr variable cannot have type 'TheV' (aka 'volatile short')}}
+constexpr struct HasR V24[2] = {};
+// expected-error@-1 {{constexpr variable cannot have type 'TheR' (aka 'float *restrict')}}
+
+union U3 {
+  float a;
+  union {
+    struct HasA f;
+    struct HasR f1;
+  };
+};
+
+constexpr union U3 V25 = {};
+// expected-error@-1 {{constexpr variable cannot have type 'TheA' (aka '_Atomic(int)')}}
+constexpr union U3 V26[8] = {};
+// expected-error@-1 {{constexpr variable cannot have type 'TheA' (aka '_Atomic(int)')}}
+
+struct S4 {
+  union U3 f[3];
+};
+
+constexpr struct S4 V27 = {};
+// expected-error@-1 {{constexpr variable cannot have type 'TheA' (aka '_Atomic(int)')}}
+constexpr const int V28 = 28;
+
+struct S {
+  union {
+    volatile int i;
+  };
+  int j;
+};
+
+constexpr struct S s = {}; // expected-error {{constexpr variable cannot have type 'volatile int'}}
+
+// Check that constexpr variable must have a valid initializer which is a
+// constant expression.
+constexpr int V29;
+// expected-error@-1 {{constexpr variable 'V29' must be initialized by a constant expression}}
+
+struct S5 {
+  int f;
+};
+
+constexpr struct S5 V30;
+// expected-error@-1 {{constexpr variable 'V30' must be initialized by a constant expression}}
+constexpr struct S5 V31 = {};
+
+int randomFoo() { return 7; }
+
+constexpr float V32 = randomFoo();
+// expected-error@-1 {{constexpr variable 'V32' must be initialized by a constant expression}}
+
+const int V33 = 4;
+const int V34 = 0;
+const int V35 = 2;
+
+constexpr int V36 = V33 / V34;
+// expected-error@-1 {{constexpr variable 'V36' must be initialized by a constant expression}}
+constexpr int V37 = V33 / V35;
+// expected-error@-1 {{constexpr variable 'V37' must be initialized by a constant expression}}
+constexpr int V38 = 3;
+constexpr int V39 = V38 / V38;
+constexpr int V40 = V38 / 2;
+constexpr int V41 = V38 / 0;
+// expected-error@-1 {{constexpr variable 'V41' must be initialized by a constant expression}}
+// expected-note@-2 {{division by zero}}
+constexpr int V42 = V38 & 0;
+
+constexpr struct S5 V43 = { randomFoo() };
+// expected-error@-1 {{constexpr variable 'V43' must be initialized by a constant expression}}
+constexpr struct S5 V44 = { 0 };
+constexpr struct S5 V45 = { V38 / 0 };
+// expected-error@-1 {{constexpr variable 'V45' must be initialized by a constant expression}}
+// expected-note@-2 {{division by zero}}
+
+constexpr float V46[3] = {randomFoo() };
+// expected-error@-1 {{constexpr variable 'V46' must be initialized by a constant expression}}
+constexpr struct S5 V47[3] = {randomFoo() };
+// expected-error@-1 {{constexpr variable 'V47' must be initialized by a constant expression}}
+
+const static int V48 = V38;
+constexpr static int V49 = V48;
+// expected-error@-1 {{constexpr variable 'V49' must be initialized by a constant expression}}
+
+void f4(const int P1) {
+  constexpr int V = P1;
+// expected-error@-1 {{constexpr variable 'V' must be initialized by a constant expression}}
+
+  constexpr int V1 = 12;
+  constexpr const int *V2 = &V1;
+// expected-error@-1 {{constexpr variable 'V2' must be initialized by a constant expression}}
+}
+
+// Check that initializer for constexpr variable should match the type of the
+// variable and is exactly representable int the variable's type.
+
+struct S6 {
+  unsigned char a;
+};
+
+struct S7 {
+  union {
+    float a;
+  };
+  unsigned int b;
+};
+
+struct S8 {
+  unsigned char a[3];
+  unsigned int b[3];
+};
+
+constexpr struct S8 DesigInit = {.b = {299, 7, 8}, .a = {-1, 7, 8}};
+// expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'unsigned char'}}
+
+void f5() {
+  constexpr char V50 = 300;
+  // expected-error@-1 {{constexpr initializer evaluates to 300 which is not exactly representable in type 'const char'}}
+  constexpr float V51 = 1.0 / 3.0;
+  // expected-error@-1 {{constexpr initializer evaluates to 3.333333e-01 which is not exactly representable in type 'const float'}}
+  constexpr float V52 = 0.7;
+  // expected-error@-1 {{constexpr initializer evaluates to 7.000000e-01 which is not exactly representable in type 'const float'}}
+  constexpr float V53 = 1.0f / 3.0f;
+  constexpr float V54 = 432000000000;
+  // expected-error@-1 {{constexpr initializer evaluates to 432000000000 which is not exactly representable in type 'const float'}}
+  constexpr unsigned char V55[] = {
+      "\xAF",
+  // expected-error@-1 {{constexpr initializer evaluates to -81 which is not exactly representable in type 'const unsigned char'}}
+  };
+
+  constexpr unsigned char V56[] = {
+      u8"\xAF",
+  };
+  constexpr struct S6 V57 = {299};
+  // expected-error@-1 {{constexpr initializer evaluates to 299 which is not exactly representable in type 'unsigned char'}}
+  constexpr struct S6 V58 = {-299};
+  // expected-error@-1 {{constexpr initializer evaluates to -299 which is not exactly representable in type 'unsigned char'}}
+  constexpr double V59 = 0.5;
+  constexpr double V60 = 1.0;
+  constexpr float V61 = V59 / V60;
+  constexpr double V62 = 1.7;
+  constexpr float V63 = V59 / V62;
+  // expected-error@-1 {{constexpr initializer evaluates to 2.941176e-01 which is not exactly representable in type 'const float'}}
+
+  constexpr unsigned char V64 = '\xAF';
+  // expected-error@-1 {{constexpr initializer evaluates to -81 which is not exactly representable in type 'const unsigned char'}}
+  constexpr unsigned char V65 = u8'\xAF';
+
+  constexpr char V66[3] = {300};
+  // expected-error@-1 {{constexpr initializer evaluates to 300 which is not exactly representable in type 'const char'}}
+  constexpr struct S6 V67[3] = {300};
+  // expected-error@-1 {{constexpr initializer evaluates to 300 which is not exactly representable in type 'unsigned char'}}
+
+  constexpr struct S7 V68 = {0.3, -1 };
+  // expected-error@-1 {{constexpr initializer evaluates to 3.000000e-01 which is not exactly representable in type 'float'}}
+  // expected-error@-2 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'unsigned int'}}
+  constexpr struct S7 V69 = {0.5, -1 };
+  // expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'unsigned int'}}
+  constexpr struct S7 V70[3] = {{123456789}};
+  // expected-error@-1 {{constexpr initializer evaluates to 123456789 which is not exactly representable in type 'float'}}
+
+  constexpr int V71 = 0.3;
+  // expected-error@-1 {{constexpr initializer for type 'const int' is of type 'double'}}
+  constexpr int V72 = V59;
+  // expected-error@-1 {{constexpr initializer for type 'const int' is of type 'const double'}}
+  constexpr struct S6 V73 = {V59};
+  // expected-error@-1 {{constexpr initializer for type 'unsigned char' is of type 'const double'}}
+
+  constexpr float V74 = 1;
+  constexpr float V75 = V59;
+  constexpr unsigned int V76[3] = {0.5};
+  // expected-error@-1 {{constexpr initializer for type 'const unsigned int' is of type 'double'}}
+
+  constexpr _Complex float V77 = 0;
+  constexpr float V78 = V77;
+  // expected-error@-1 {{constexpr initializer for type 'const float' is of type 'const _Complex float'}}
+  constexpr int V79 = V77;
+  // expected-error@-1 {{constexpr initializer for type 'const int' is of type 'const _Complex float'}}
+
+}
+
+constexpr char string[] = "test""ing this out\xFF";
+constexpr unsigned char ustring[] = "test""ing this out\xFF";
+// expected-error@-1 {{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned char'}}
+constexpr char u8string[] = u8"test"u8"ing this out\xFF";
+// expected-error@-1 {{constexpr initializer evaluates to 255 which is not exactly representable in type 'const char'}}
+constexpr unsigned char u8ustring[] = u8"test"u8"ing this out\xFF";
+constexpr unsigned short uustring[] = u"test"u"ing this out\xFF";
+constexpr unsigned int Ustring[] = U"test"U"ing this out\xFF";
+constexpr unsigned char Arr2[6][6] = {
+  {"ek\xFF"}, {"ek\xFF"}
+// expected-error@-1 2{{constexpr initializer evaluates to -1 which is not exactly representable in type 'const unsigned char'}}
+};
+
+constexpr int i = (12);
+constexpr int j = (i);
+constexpr unsigned jneg = (-i);
+// expected-error@-1 {{constexpr initializer evaluates to -12 which is not exactly representable in type 'const unsigned int'}}
+
+// Check that initializer for pointer constexpr variable should be null.
+constexpr int V80 = 3;
+constexpr const int *V81 = &V80;
+// expected-error@-1 {{constexpr pointer initializer is not null}}
+constexpr int *V82 = 0;
+constexpr int *V83 = V82;
+constexpr int *V84 = 42;
+// expected-error@-1 {{constexpr variable 'V84' must be initialized by a constant expression}}
+// expected-note@-2 {{this conversion is not allowed in a constant expression}}
+// expected-error@-3 {{constexpr pointer initializer is not null}}
+constexpr int *V85 = nullptr;
+
+// Check that constexpr variables should not be VLAs.
+void f6(const int P1) {
+  constexpr int V86[P1] = {};
+// expected-error@-1 {{constexpr variable cannot have type 'const int[P1]'}}
+  const int V87 = 3;
+  constexpr int V88[V87] = {};
+// expected-warning@-1 {{variable length array folded to constant array as an extension}}
+  int V89 = 7;
+  constexpr int V90[V89] = {};
+// expected-error@-1 {{constexpr variable cannot have type 'const int[V89]'}}
+}
+
+void f7(int n, int array[n]) {
+  constexpr typeof(array) foo = 0; // Accepted because array is a pointer type, not a VLA type
+  int (*(*fp)(int n))[n];
+  constexpr typeof(fp) bar = 0; // expected-error {{constexpr variable cannot have type 'const typeof (fp)' (aka 'int (*(*const)(int))[n]')}}
+}
+
+// Check how constexpr works with NaNs and infinities.
+#define FLT_NAN __builtin_nanf("1")
+#define DBL_NAN __builtin_nan("1")
+#define LD_NAN __builtin_nanf("1")
+#define FLT_SNAN __builtin_nansf("1")
+#define DBL_SNAN __builtin_nans("1")
+#define LD_SNAN __builtin_nansl("1")
+#define INF __builtin_inf()
+void infsNaNs() {
+  // Inf and quiet NaN is always fine, signaling NaN must have the same type.
+  constexpr float fl0 = INF;
+  constexpr float fl1 = (long double)INF;
+  constexpr float fl2 = (long double)FLT_NAN;
+  constexpr float fl3 = FLT_NAN;
+  constexpr float fl5 = DBL_NAN;
+  constexpr float fl6 = LD_NAN;
+  constexpr float fl7 = DBL_SNAN; // expected-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const float'}}
+  constexpr float fl8 = LD_SNAN; // expected-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const float'}}
+
+  constexpr double db0 = FLT_NAN;
+  constexpr double db2 = DBL_NAN;
+  constexpr double db3 = DBL_SNAN;
+  constexpr double db4 = FLT_SNAN; // expected-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const double'}}
+  constexpr double db5 = LD_SNAN; // expected-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const double'}}
+  constexpr double db6 = INF;
+}
diff --git a/clang/test/Sema/integer-overflow.c b/clang/test/Sema/integer-overflow.c
index cf822f346e8b295f6b180b9c481f0687bb29636e..220fc1bed515a1ba07c252b60be85bdf884abc18 100644
--- a/clang/test/Sema/integer-overflow.c
+++ b/clang/test/Sema/integer-overflow.c
@@ -11,169 +11,169 @@ uint64_t f0(uint64_t);
 uint64_t f1(uint64_t, uint32_t);
 uint64_t f2(uint64_t, ...);
 
-static const uint64_t overflow = 1 * 4608 * 1024 * 1024; // expected-warning {{overflow in expression; result is 536870912 with type 'int'}}
+static const uint64_t overflow = 1 * 4608 * 1024 * 1024; // expected-warning {{overflow in expression; result is 536'870'912 with type 'int'}}
 
 uint64_t check_integer_overflows(int i) {
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   uint64_t overflow = 4608 * 1024 * 1024,
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
            overflow2 = (uint64_t)(4608 * 1024 * 1024),
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
            overflow3 = (uint64_t)(4608 * 1024 * 1024 * i),
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
            overflow4 =  (1ULL * ((4608) * ((1024) * (1024))) + 2ULL),
-// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
            multi_overflow = (uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow += overflow2 = overflow3 = (uint64_t)(4608 * 1024 * 1024);
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow += overflow2 = overflow3 = 4608 * 1024 * 1024;
 
   uint64_t not_overflow = 4608 * 1024 * 1024ULL;
   uint64_t not_overflow2 = (1ULL * ((uint64_t)(4608) * (1024 * 1024)) + 2ULL);
 
-// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow = 4608 * 1024 * 1024 ?  4608 * 1024 * 1024 : 0;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow =  0 ? 0 : 4608 * 1024 * 1024;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if (4608 * 1024 * 1024)
     return 0;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((uint64_t)(4608 * 1024 * 1024))
     return 1;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((uint64_t)(4608 * 1024 * 1024))
     return 2;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((uint64_t)(4608 * 1024 * 1024 * i))
     return 3;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL))
     return 4;
 
-// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024)))
     return 5;
 
   switch (i) {
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   case 4608 * 1024 * 1024:
     return 6;
-// expected-warning@+1 {{overflow in expression; result is 537919488 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 537'919'488 with type 'int'}}
   case (uint64_t)(4609 * 1024 * 1024):
     return 7;
 // expected-error@+1 {{expression is not an integer constant expression}}
   case ((uint64_t)(4608 * 1024 * 1024 * i)):
     return 8;
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   case ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL)):
     return 9;
-// expected-warning@+2 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+2 2{{overflow in expression; result is 536'870'912 with type 'int'}}
 // expected-warning@+1 {{overflow converting case value to switch condition type (288230376151711744 to 0)}}
   case ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024))):
     return 10;
   }
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while (4608 * 1024 * 1024);
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((uint64_t)(4608 * 1024 * 1024 * i));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL));
 
-// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024)));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while (4608 * 1024 * 1024);
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((uint64_t)(4608 * 1024 * 1024 * i));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL));
 
-// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024)));
 
-// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}}
   for (uint64_t i = 4608 * 1024 * 1024;
        (uint64_t)(4608 * 1024 * 1024);
        i += (uint64_t)(4608 * 1024 * 1024 * i));
 
-// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning@+3 2{{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning@+3 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning@+3 2{{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning@+3 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   for (uint64_t i = (1ULL * ((4608) * ((1024) * (1024))) + 2ULL);
        ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024)));
        i = ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024))));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   _Complex long long x = 4608 * 1024 * 1024;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (__real__ x) = 4608 * 1024 * 1024;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (__imag__ x) = 4608 * 1024 * 1024;
 
-// expected-warning@+4 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+4 {{overflow in expression; result is 536'870'912 with type 'int'}}
 // expected-warning@+3 {{array index 536870912 is past the end of the array (that has type 'uint64_t[10]' (aka 'unsigned long long[10]'))}}
 // expected-note@+1 {{array 'a' declared here}}
   uint64_t a[10];
   a[4608 * 1024 * 1024] = 1i;
 
-// expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+2 {{overflow in expression; result is 536'870'912 with type 'int'}}
   uint64_t *b;
   uint64_t b2 = b[4608 * 1024 * 1024] + 1;
 
-// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   (void)((i ? (4608 * 1024 * 1024) : (4608 * 1024 * 1024)) + 1);
 
-// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   return ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024)));
 }
 
 void check_integer_overflows_in_function_calls(void) {
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (void)f0(4608 * 1024 * 1024);
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   uint64_t x = f0(4608 * 1024 * 1024);
 
-// expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+2 {{overflow in expression; result is 536'870'912 with type 'int'}}
   uint64_t (*f0_ptr)(uint64_t) = &f0;
   (void)(*f0_ptr)(4608 * 1024 * 1024);
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (void)f2(0, f0(4608 * 1024 * 1024));
 }
 void check_integer_overflows_in_array_size(void) {
-  int arr[4608 * 1024 * 1024]; // expected-warning {{overflow in expression; result is 536870912 with type 'int'}}
+  int arr[4608 * 1024 * 1024]; // expected-warning {{overflow in expression; result is 536'870'912 with type 'int'}}
 }
 
 struct s {
diff --git a/clang/test/Sema/return-type-mismatch.c b/clang/test/Sema/return-type-mismatch.c
new file mode 100644
index 0000000000000000000000000000000000000000..79a625d7df1f54e83853f0d8c1e40fabb907bd05
--- /dev/null
+++ b/clang/test/Sema/return-type-mismatch.c
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -Wreturn-type -Wno-return-mismatch -fsyntax-only -verify=return-type %s
+// RUN: %clang_cc1 -Wno-return-type -Wreturn-mismatch -fsyntax-only -verify=return-mismatch %s
+
+int foo(void) __attribute__((noreturn));
+int bar(void);
+
+void test1(void) {
+  return 1; // return-mismatch-warning{{void function 'test1' should not return a value}}
+}
+
+int test2(void) { 
+    return; // return-mismatch-warning{{non-void function 'test2' should return a value}}
+} 
+
+int test3(void) { 
+    // return-type-warning@+1 {{non-void function does not return a value}}
+} 
+
+int test4(void) {
+    (void)(bar() || foo()); // return-type-warning@+1 {{non-void function does not return a value in all control paths}}
+} 
+
+void test5(void) {
+} // no-warning
+
+int test6(void) {
+  return 0; // no-warning
+}
+
+int test7(void) {
+  foo(); // no warning
+}
+
+int test8(void) {
+  bar(); // return-type-warning@+1 {{non-void function does not return a value}}
+}
diff --git a/clang/test/Sema/riscv-vector-float64-check.c b/clang/test/Sema/riscv-vector-float64-check.c
index ee7db32663959e39beb4c250f3f0ffa1adb7cf8c..f21ae5c0c704057c19ebaa0fecfaa64de401ac9d 100644
--- a/clang/test/Sema/riscv-vector-float64-check.c
+++ b/clang/test/Sema/riscv-vector-float64-check.c
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d \
-// RUN:   -target-feature +zve64f -target-feature +zfh \
+// RUN: %clang_cc1 -triple riscv64 -target-feature +zve32x \
 // RUN:   -disable-O0-optnone -o - -fsyntax-only %s -verify 
 // REQUIRES: riscv-registered-target
 #include 
diff --git a/clang/test/Sema/static-assert.c b/clang/test/Sema/static-assert.c
index 4e9e6b7ee558bdb0331df20a1f41c66089a0bc0b..ae5e8076e0bedab8c2cfcfd447f364c307f954ae 100644
--- a/clang/test/Sema/static-assert.c
+++ b/clang/test/Sema/static-assert.c
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -std=c11 -Wgnu-folding-constant -fsyntax-only -verify %s
-// RUN: %clang_cc1 -fms-compatibility -Wgnu-folding-constant -DMS -fsyntax-only -verify=expected,ms %s
-// RUN: %clang_cc1 -std=c99 -pedantic -Wgnu-folding-constant -fsyntax-only -verify=expected,ext %s
+// RUN: %clang_cc1 -std=c11 -Wgnu-folding-constant -fsyntax-only -verify=expected,c %s
+// RUN: %clang_cc1 -fms-compatibility -Wgnu-folding-constant -DMS -fsyntax-only -verify=expected,ms,c %s
+// RUN: %clang_cc1 -std=c99 -pedantic -Wgnu-folding-constant -fsyntax-only -verify=expected,ext,c %s
 // RUN: %clang_cc1 -xc++ -std=c++11 -pedantic -fsyntax-only -verify=expected,ext,cxx %s
 
 _Static_assert("foo", "string is nonzero"); // ext-warning {{'_Static_assert' is a C11 extension}}
@@ -57,7 +57,8 @@ UNION(char[2], short) u2 = { .one = { 'a', 'b' } }; // ext-warning 3 {{'_Static_
 typedef UNION(char, short) U3; // expected-error {{static assertion failed due to requirement 'sizeof(char) == sizeof(short)': type size mismatch}} \
                                // expected-note{{evaluates to '1 == 2'}} \
                                // ext-warning 3 {{'_Static_assert' is a C11 extension}}
-typedef UNION(float, 0.5f) U4; // expected-error {{expected a type}} \
+typedef UNION(float, 0.5f) U4; // c-error {{expected a type}} \
+                               // cxx-error {{type name requires a specifier or qualifier}} \
                                // ext-warning 3 {{'_Static_assert' is a C11 extension}}
 
 // After defining the assert macro in MS-compatibility mode, we should
diff --git a/clang/test/Sema/switch-1.c b/clang/test/Sema/switch-1.c
index 95e64748fb1fbfdd4d4321ce377c903523db71a1..09221990ac11d32a711105709ded8629c82b164c 100644
--- a/clang/test/Sema/switch-1.c
+++ b/clang/test/Sema/switch-1.c
@@ -7,7 +7,7 @@ int f(int i) {
   switch (i) {
     case 2147483647 + 2:
 #if (__cplusplus <= 199711L) // C or C++03 or earlier modes
-    // expected-warning@-2 {{overflow in expression; result is -2147483647 with type 'int'}}
+    // expected-warning@-2 {{overflow in expression; result is -2'147'483'647 with type 'int'}}
 #else
     // expected-error@-4 {{case value is not a constant expression}} \
     // expected-note@-4 {{value 2147483649 is outside the range of representable values of type 'int'}}
@@ -23,7 +23,7 @@ int f(int i) {
       return 2;
     case (123456 *789012) + 1:
 #if (__cplusplus <= 199711L)
-    // expected-warning@-2 {{overflow in expression; result is -1375982336 with type 'int'}}
+    // expected-warning@-2 {{overflow in expression; result is -1'375'982'336 with type 'int'}}
 #else
     // expected-error@-4 {{case value is not a constant expression}} \
     // expected-note@-4 {{value 97408265472 is outside the range of representable values of type 'int'}}
@@ -47,7 +47,7 @@ int f(int i) {
     case 2147483647:
       return 0;
   }
-  return (i, 65537) * 65537; // expected-warning {{overflow in expression; result is 131073 with type 'int'}} \
+  return (i, 65537) * 65537; // expected-warning {{overflow in expression; result is 131'073 with type 'int'}} \
 			     // expected-warning {{left operand of comma operator has no effect}}
 }
 
diff --git a/clang/test/SemaCUDA/float128.cu b/clang/test/SemaCUDA/float128.cu
new file mode 100644
index 0000000000000000000000000000000000000000..f8f20cb1588d7648d38cb5ecfb07210591c98214
--- /dev/null
+++ b/clang/test/SemaCUDA/float128.cu
@@ -0,0 +1,18 @@
+// CPU-side compilation on x86 (no errors expected).
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -aux-triple nvptx64 -x cuda -fsyntax-only -verify=cpu %s
+
+// GPU-side compilation on x86 (no errors expected)
+// RUN: %clang_cc1 -triple nvptx64 -aux-triple x86_64-unknown-linux-gnu -fcuda-is-device -x cuda -fsyntax-only -verify=gpu %s
+
+// cpu-no-diagnostics
+typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
+typedef __float128 _Float128;
+
+// gpu-note@+1 {{'a' defined here}}
+__attribute__((device)) __float128 f(__float128 a, float b) {
+    // gpu-note@+1 {{'c' defined here}}
+  __float128 c = b + 1.0;
+  // gpu-error@+2 {{'a' requires 128 bit size '__float128' type support, but target 'nvptx64' does not support it}}
+  // gpu-error@+1 {{'c' requires 128 bit size '__float128' type support, but target 'nvptx64' does not support it}}
+  return a + c;
+}
\ No newline at end of file
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 9e2ae07cbe4c9c0df443bb105a25a920e61ca55e..efb391ba0922d818e1544680098b5b5770b81477 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1273,8 +1273,8 @@ namespace PR11595 {
   struct B { B(); A& x; };
   static_assert(B().x == 3, "");  // expected-error {{constant expression}} expected-note {{non-literal type 'B' cannot be used in a constant expression}}
 
-  constexpr bool f(int k) { // expected-error {{constexpr function never produces a constant expression}}
-    return B().x == k; // expected-note {{non-literal type 'B' cannot be used in a constant expression}}
+  constexpr bool f(int k) { // cxx11_20-error {{constexpr function never produces a constant expression}}
+    return B().x == k; // cxx11_20-note {{non-literal type 'B' cannot be used in a constant expression}}
   }
 }
 
@@ -1326,8 +1326,8 @@ namespace ExternConstexpr {
   constexpr int g() { return q; } // expected-note {{outside its lifetime}}
   constexpr int q = g(); // expected-error {{constant expression}} expected-note {{in call}}
 
-  extern int r; // expected-note {{here}}
-  constexpr int h() { return r; } // expected-error {{never produces a constant}} expected-note {{read of non-const}}
+  extern int r; // cxx11_20-note {{here}}
+  constexpr int h() { return r; } // cxx11_20-error {{never produces a constant}} cxx11_20-note {{read of non-const}}
 
   struct S { int n; };
   extern const S s;
@@ -1678,7 +1678,7 @@ namespace ImplicitConstexpr {
   struct R { constexpr R() noexcept; constexpr R(const R&) noexcept; constexpr R(R&&) noexcept; ~R() noexcept; };
   struct S { R r; }; // expected-note 3{{here}}
   struct T { T(const T&) noexcept; T(T &&) noexcept; ~T() noexcept; };
-  struct U { T t; }; // expected-note 3{{here}}
+  struct U { T t; }; // cxx11_20-note 3{{here}}
   static_assert(!__is_literal_type(Q), "");
   static_assert(!__is_literal_type(R), "");
   static_assert(!__is_literal_type(S), "");
@@ -1691,9 +1691,9 @@ namespace ImplicitConstexpr {
     friend S::S() noexcept; // expected-error {{follows constexpr}}
     friend S::S(S&&) noexcept; // expected-error {{follows constexpr}}
     friend S::S(const S&) noexcept; // expected-error {{follows constexpr}}
-    friend constexpr U::U() noexcept; // expected-error {{follows non-constexpr}}
-    friend constexpr U::U(U&&) noexcept; // expected-error {{follows non-constexpr}}
-    friend constexpr U::U(const U&) noexcept; // expected-error {{follows non-constexpr}}
+    friend constexpr U::U() noexcept; // cxx11_20-error {{follows non-constexpr}}
+    friend constexpr U::U(U&&) noexcept; // cxx11_20-error {{follows non-constexpr}}
+    friend constexpr U::U(const U&) noexcept; // cxx11_20-error {{follows non-constexpr}}
   };
 }
 
@@ -1906,9 +1906,9 @@ namespace StmtExpr {
     });
   }
   static_assert(g(123) == 15129, "");
-  constexpr int h() { // expected-error {{never produces a constant}}
+  constexpr int h() { // cxx11_20-error {{never produces a constant}}
     return ({ // expected-warning {{extension}}
-      return 0; // expected-note {{not supported}}
+      return 0; // cxx11_20-note {{not supported}}
       1;
     });
   }
@@ -2093,8 +2093,8 @@ namespace ZeroSizeTypes {
   // expected-note@-2 {{subtraction of pointers to type 'int[0]' of zero size}}
 
   int arr[5][0];
-  constexpr int f() { // expected-error {{never produces a constant expression}}
-    return &arr[3] - &arr[0]; // expected-note {{subtraction of pointers to type 'int[0]' of zero size}}
+  constexpr int f() { // cxx11_20-error {{never produces a constant expression}}
+    return &arr[3] - &arr[0]; // cxx11_20-note {{subtraction of pointers to type 'int[0]' of zero size}}
   }
 }
 
@@ -2118,8 +2118,8 @@ namespace NeverConstantTwoWays {
   // If we see something non-constant but foldable followed by something
   // non-constant and not foldable, we want the first diagnostic, not the
   // second.
-  constexpr int f(int n) { // expected-error {{never produces a constant expression}}
-    return (int *)(long)&n == &n ? // expected-note {{reinterpret_cast}}
+  constexpr int f(int n) { // cxx11_20-error {{never produces a constant expression}}
+    return (int *)(long)&n == &n ? // cxx11_20-note {{reinterpret_cast}}
         1 / 0 : // expected-warning {{division by zero}}
         0;
   }
@@ -2277,7 +2277,8 @@ namespace InheritedCtor {
   struct A { constexpr A(int) {} };
 
   struct B : A { int n; using A::A; }; // expected-note {{here}}
-  constexpr B b(0); // expected-error {{constant expression}} expected-note {{derived class}}
+  constexpr B b(0); // expected-error {{constant expression}} cxx11_20-note {{derived class}}\
+                    // cxx23-note {{not initialized}}
 
   struct C : A { using A::A; struct { union { int n, m = 0; }; union { int a = 0; }; int k = 0; }; struct {}; union {}; }; // expected-warning 6{{}}
   constexpr C c(0);
@@ -2316,10 +2317,11 @@ namespace InheritedCtor {
 namespace PR28366 {
 namespace ns1 {
 
-void f(char c) { //expected-note2{{declared here}}
+void f(char c) { //expected-note{{declared here}}
+  //cxx11_20-note@-1{{declared here}}
   struct X {
-    static constexpr char f() { //expected-error{{never produces a constant expression}}
-      return c; //expected-error{{reference to local}} expected-note{{function parameter}}
+    static constexpr char f() { // cxx11_20-error {{never produces a constant expression}}
+      return c; //expected-error{{reference to local}} cxx11_20-note{{function parameter}}
     }
   };
   int I = X::f();
diff --git a/clang/test/SemaCXX/constant-expression-cxx14.cpp b/clang/test/SemaCXX/constant-expression-cxx14.cpp
index 273d7ff3a208e290824fd84343d6e7a07684faa8..80a7a2dd31531c4fbd933745be3390b36a7af8dc 100644
--- a/clang/test/SemaCXX/constant-expression-cxx14.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp
@@ -44,13 +44,13 @@ constexpr int g(int k) {
   return 3 * k3 + 5 * k2 + n * k - 20;
 }
 static_assert(g(2) == 42, "");
-constexpr int h(int n) {  // expected-error {{constexpr function never produces a constant expression}}
-  static const int m = n; // expected-note {{control flows through the definition of a static variable}} \
+constexpr int h(int n) {  // cxx14_20-error {{constexpr function never produces a constant expression}}
+  static const int m = n; // cxx14_20-note {{control flows through the definition of a static variable}} \
                           // cxx14_20-warning {{definition of a static variable in a constexpr function is a C++23 extension}}
   return m;
 }
-constexpr int i(int n) {        // expected-error {{constexpr function never produces a constant expression}}
-  thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \
+constexpr int i(int n) {        // cxx14_20-error {{constexpr function never produces a constant expression}}
+  thread_local const int m = n; // cxx14_20-note {{control flows through the definition of a thread_local variable}} \
                                 // cxx14_20-warning {{definition of a thread_local variable in a constexpr function is a C++23 extension}}
   return m;
 }
@@ -68,6 +68,7 @@ constexpr int j(int k) {
     }
   }
 } // expected-note 2{{control reached end of constexpr function}}
+  // cxx23-warning@-1 {{does not return a value in all control paths}}
 static_assert(j(0) == -3, "");
 static_assert(j(1) == 5, "");
 static_assert(j(2), ""); // expected-error {{constant expression}} expected-note {{in call to 'j(2)'}}
@@ -104,10 +105,10 @@ static_assert(l(false) == 5, "");
 static_assert(l(true), ""); // expected-error {{constant expression}} expected-note {{in call to 'l(true)'}}
 
 // Potential constant expression checking is still applied where possible.
-constexpr int htonl(int x) { // expected-error {{never produces a constant expression}}
+constexpr int htonl(int x) { // cxx14_20-error {{never produces a constant expression}}
   typedef unsigned char uchar;
   uchar arr[4] = { uchar(x >> 24), uchar(x >> 16), uchar(x >> 8), uchar(x) };
-  return *reinterpret_cast(arr); // expected-note {{reinterpret_cast is not allowed in a constant expression}}
+  return *reinterpret_cast(arr); // cxx14_20-note {{reinterpret_cast is not allowed in a constant expression}}
 }
 
 constexpr int maybe_htonl(bool isBigEndian, int x) {
@@ -183,7 +184,7 @@ namespace string_assign {
   static_assert(!test1(100), "");
   static_assert(!test1(101), ""); // expected-error {{constant expression}} expected-note {{in call to 'test1(101)'}}
 
-  constexpr void f() { // expected-error{{constexpr function never produces a constant expression}} expected-note@+2{{assignment to dereferenced one-past-the-end pointer is not allowed in a constant expression}}
+  constexpr void f() { // cxx14_20-error{{constexpr function never produces a constant expression}} cxx14_20-note@+2{{assignment to dereferenced one-past-the-end pointer is not allowed in a constant expression}}
     char foo[10] = { "z" }; // expected-note {{here}}
     foo[10] = 'x'; // expected-warning {{past the end}}
   }
@@ -207,14 +208,14 @@ namespace array_resize {
 namespace potential_const_expr {
   constexpr void set(int &n) { n = 1; }
   constexpr int div_zero_1() { int z = 0; set(z); return 100 / z; } // no error
-  constexpr int div_zero_2() { // expected-error {{never produces a constant expression}}
+  constexpr int div_zero_2() { // cxx14_20-error {{never produces a constant expression}}
     int z = 0;
-    return 100 / (set(z), 0); // expected-note {{division by zero}}
+    return 100 / (set(z), 0); // cxx14_20-note {{division by zero}}
   }
-  int n; // expected-note {{declared here}}
-  constexpr int ref() { // expected-error {{never produces a constant expression}}
+  int n; // cxx14_20-note {{declared here}}
+  constexpr int ref() { // cxx14_20-error {{never produces a constant expression}}
     int &r = n;
-    return r; // expected-note {{read of non-const variable 'n'}}
+    return r; // cxx14_20-note {{read of non-const variable 'n'}}
   }
 }
 
@@ -846,8 +847,8 @@ namespace StmtExpr {
   static_assert(g() == 0, ""); // expected-error {{constant expression}} expected-note {{in call}}
 
   // FIXME: We should handle the void statement expression case.
-  constexpr int h() { // expected-error {{never produces a constant}}
-    ({ if (true) {} }); // expected-note {{not supported}}
+  constexpr int h() { // cxx14_20-error {{never produces a constant}}
+    ({ if (true) {} }); // cxx14_20-note {{not supported}}
     return 0;
   }
 }
@@ -1043,9 +1044,9 @@ static_assert(sum(Cs) == 'a' + 'b', ""); // expected-error{{not an integral cons
 constexpr int S = sum(Cs); // expected-error{{must be initialized by a constant expression}} expected-note{{in call}}
 }
 
-constexpr void PR28739(int n) { // expected-error {{never produces a constant}}
+constexpr void PR28739(int n) { // cxx14_20-error {{never produces a constant}}
   int *p = &n;                  // expected-note {{array 'p' declared here}}
-  p += (__int128)(unsigned long)-1; // expected-note {{cannot refer to element 18446744073709551615 of non-array object in a constant expression}}
+  p += (__int128)(unsigned long)-1; // cxx14_20-note {{cannot refer to element 18446744073709551615 of non-array object in a constant expression}}
   // expected-warning@-1 {{the pointer incremented by 18446744073709551615 refers past the last possible element for an array in 64-bit address space containing 32-bit (4-byte) elements (max possible 4611686018427387904 elements)}}
 }
 
diff --git a/clang/test/SemaCXX/constant-expression-cxx2b.cpp b/clang/test/SemaCXX/constant-expression-cxx2b.cpp
index 2ee1d48d1cd697da07d2971958c1815e7b49a93f..2519839b7ac57821094987ba1fdbadd5cfe0c500 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2b.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2b.cpp
@@ -10,36 +10,36 @@ struct Constexpr{};
 
 #if __cplusplus > 202002L
 
-constexpr int f(int n) {  // expected-error {{constexpr function never produces a constant expression}}
-  static const int m = n; // expected-note {{control flows through the definition of a static variable}} \
+constexpr int f(int n) {  // cxx2a-error {{constexpr function never produces a constant expression}}
+  static const int m = n; // cxx2a-note {{control flows through the definition of a static variable}} \
                           // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}}
   return m;
 }
-constexpr int g(int n) {        // expected-error {{constexpr function never produces a constant expression}}
-  thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \
+constexpr int g(int n) {        // cxx2a-error {{constexpr function never produces a constant expression}}
+  thread_local const int m = n; // cxx2a-note {{control flows through the definition of a thread_local variable}} \
                                 // cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}}
   return m;
 }
 
-constexpr int c_thread_local(int n) { // expected-error {{constexpr function never produces a constant expression}}
-  static _Thread_local int m = 0;     // expected-note {{control flows through the definition of a thread_local variable}} \
+constexpr int c_thread_local(int n) { // cxx2a-error {{constexpr function never produces a constant expression}}
+  static _Thread_local int m = 0;     // cxx2a-note {{control flows through the definition of a thread_local variable}} \
                                       // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}}
   return m;
 }
 
-constexpr int gnu_thread_local(int n) { // expected-error {{constexpr function never produces a constant expression}}
-  static __thread int m = 0;            // expected-note {{control flows through the definition of a thread_local variable}} \
+constexpr int gnu_thread_local(int n) { // cxx2a-error {{constexpr function never produces a constant expression}}
+  static __thread int m = 0;            // cxx2a-note {{control flows through the definition of a thread_local variable}} \
                                         // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}}
   return m;
 }
 
-constexpr int h(int n) {  // expected-error {{constexpr function never produces a constant expression}}
-  static const int m = n; // expected-note {{control flows through the definition of a static variable}} \
+constexpr int h(int n) {  // cxx2a-error {{constexpr function never produces a constant expression}}
+  static const int m = n; // cxx2a-note {{control flows through the definition of a static variable}} \
                           // cxx23-warning {{definition of a static variable in a constexpr function is incompatible with C++ standards before C++23}}
   return &m - &m;
 }
-constexpr int i(int n) {        // expected-error {{constexpr function never produces a constant expression}}
-  thread_local const int m = n; // expected-note {{control flows through the definition of a thread_local variable}} \
+constexpr int i(int n) {        // cxx2a-error {{constexpr function never produces a constant expression}}
+  thread_local const int m = n; // cxx2a-note {{control flows through the definition of a thread_local variable}} \
                                  // cxx23-warning {{definition of a thread_local variable in a constexpr function is incompatible with C++ standards before C++23}}
   return &m - &m;
 }
diff --git a/clang/test/SemaCXX/cxx17-compat.cpp b/clang/test/SemaCXX/cxx17-compat.cpp
index d53d80f0d42ca9f17686b4eb18d5ef6854007572..54ea3384022d42dcc92db141037a1ca08ccd6307 100644
--- a/clang/test/SemaCXX/cxx17-compat.cpp
+++ b/clang/test/SemaCXX/cxx17-compat.cpp
@@ -131,3 +131,14 @@ namespace NTTP {
   // expected-warning@-4 {{non-type template parameter of type 'A' is incompatible with C++ standards before C++20}}
 #endif
 }
+
+namespace CTADForAliasTemplate {
+template struct A { A(T); };
+template using B = A;
+B b = {1};
+#if __cplusplus <= 201703L
+  // FIXME: diagnose as well
+#else
+  // expected-warning@-4 {{class template argument deduction for alias templates is incompatible with C++ standards before C++20}}
+#endif
+}
diff --git a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
index 33ed4295c2e48c80dbd0ca0c4b30ea8cbdb22817..2f067ea53a502900a62d3837b47bd4aa57c71612 100644
--- a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -101,13 +101,13 @@ namespace dependent {
   struct B {
     template struct X { X(T); };
     X(int) -> X;
-    template using Y = X; // expected-note {{template}}
+    template using Y = X;
   };
   template void f() {
     typename T::X tx = 0;
-    typename T::Y ty = 0; // expected-error {{alias template 'Y' requires template arguments; argument deduction only allowed for class templates}}
+    typename T::Y ty = 0;
   }
-  template void f(); // expected-note {{in instantiation of}}
+  template void f();
 
   template struct C { C(T); };
   template C(T) -> C;
diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..794496ed418489ecb3440a2246a61f6f926fb51f
--- /dev/null
+++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
@@ -0,0 +1,232 @@
+// RUN: %clang_cc1 -fsyntax-only -Wno-c++11-narrowing -Wno-literal-conversion -std=c++20 -verify %s
+
+namespace test1 {
+template 
+struct Foo { T t; };
+template 
+using Bar = Foo;
+
+Bar s = {1};
+}  // namespace test1
+
+namespace test2 {
+template 
+struct XYpair {
+  X x;
+  Y y;
+};
+// A tricky explicit deduction guide that swapping X and Y.
+template 
+XYpair(X, Y) -> XYpair;
+template 
+using AliasXYpair = XYpair;
+
+AliasXYpair xy = {1.1, 2};  // XYpair
+static_assert(__is_same(decltype(xy.x), int));
+static_assert(__is_same(decltype(xy.y), double));
+}  // namespace test2
+
+namespace test3 {
+template 
+struct container {
+  // test with default arguments.
+  container(T a, T b = T());
+};
+
+template 
+using vector = container;
+vector v(0, 0);
+}  // namespace test3
+
+namespace test4 {
+// Explicit deduction guide.
+template 
+struct X {
+  T t;
+  X(T);
+};
+
+template 
+X(T) -> X;
+
+template 
+using AX = X;
+
+AX s = {1};
+static_assert(__is_same(decltype(s.t), double)); // explicit one is picked.
+}  // namespace test4
+
+namespace test5 {
+template 
+struct Foo {};
+// Template parameter pack
+template 
+using AF = Foo<1>;
+auto a = AF{};
+}  // namespace test5
+
+namespace test6 {
+// non-type template argument.
+template 
+struct Foo {
+  Foo(T);
+};
+template 
+using AF = Foo;
+
+AF b{0}; 
+}  // namespace test6
+
+namespace test7 {
+template 
+struct Foo {
+  Foo(T);
+};
+// using alias chain.
+template 
+using AF1 = Foo;
+template 
+using AF2 = AF1;  
+AF2 b = 1;  
+}  // namespace test7
+
+namespace test8 {
+template 
+struct Foo {
+  Foo(T const (&)[N]);
+};
+
+template 
+using Bar = Foo;
+
+Bar s = {{1}};
+}  // namespace test8
+
+namespace test9 {
+template 
+struct Foo {
+  Foo(T const (&)[N]);
+};
+
+template 
+using Bar = Foo;
+
+// FIXME: we should reject this case? GCC rejects it, MSVC accepts it.
+Bar s = {{1}};
+}  // namespace test9
+
+namespace test10 {
+template 
+struct Foo {
+  template 
+  Foo(U);
+};
+
+template 
+Foo(U) -> Foo;
+
+template 
+using A = Foo;
+A a(2);  // Foo
+}  // namespace test10
+
+namespace test11 {
+struct A {};
+template struct Foo { T c; };
+template using AFoo = Foo;
+
+AFoo s = {1};
+} // namespace test11
+
+namespace test12 {
+// no crash on null access attribute
+template
+struct Foo {
+  template
+  struct Bar { 
+    Bar(K);
+  };
+
+  template
+  using ABar = Bar;
+  void test() { ABar k = 2; }
+};
+
+void func(Foo s) {
+  s.test();
+}
+} // namespace test12
+
+namespace test13 {
+template 
+struct Foo {
+  Foo(Ts...);
+};
+
+template 
+using AFoo = Foo;
+
+auto b = AFoo{};
+} // namespace test13
+
+namespace test14 {
+template
+concept IsInt = __is_same(decltype(T()), int);
+
+template
+struct Foo {
+  Foo(T const (&)[N]);
+};
+
+template 
+using Bar = Foo; // expected-note {{constraints not satisfied for class template 'Foo'}}
+// expected-note@-1 {{candidate template ignored: could not match}}
+double abc[3];
+Bar s2 = {abc}; // expected-error {{no viable constructor or deduction guide for deduction }}
+} // namespace test14
+
+namespace test15 {
+template  struct Foo { Foo(T); };
+
+template using AFoo = Foo;
+template concept False = false;
+template using BFoo = AFoo;
+int i = 0;
+AFoo a1(&i); // OK, deduce Foo
+
+// FIXME: we should reject this case as the W is not deduced from the deduced
+// type Foo.
+BFoo b2(&i); 
+} // namespace test15
+
+namespace test16 {
+struct X { X(int); X(const X&); };
+template
+struct Foo {
+  T t;
+  Foo(T t) : t(t) {}
+};
+template
+using AFoo = Foo;
+int i = 0;
+AFoo s{i};
+static_assert(__is_same(decltype(s.t), int));
+
+// explicit deduction guide.
+Foo(int) -> Foo;
+AFoo s2{i};
+// FIXME: the type should be X because of the above explicit deduction guide.
+static_assert(__is_same(decltype(s2.t), int));
+} // namespace test16
+
+namespace test17 {
+template 
+struct Foo { T t; };
+
+// CTAD for alias templates only works for the RHS of the alias of form of
+//  [typename] [nested-name-specifier] [template] simple-template-id
+template 
+using AFoo = Foo*; // expected-note {{template is declared here}}
+
+AFoo s = {1}; // expected-error {{alias template 'AFoo' requires template arguments; argument deduction only allowed for}}
+} // namespace test17
diff --git a/clang/test/SemaCXX/cxx23-assume-disabled.cpp b/clang/test/SemaCXX/cxx23-assume-disabled.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4233a2f7f433840244a6bf75c92ff4dc1cd50db4
--- /dev/null
+++ b/clang/test/SemaCXX/cxx23-assume-disabled.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -std=c++23 -x c++ %s -fno-assumptions -verify
+// RUN: %clang_cc1 -std=c++23 -x c++ %s -fms-compatibility -verify
+// expected-no-diagnostics
+
+// We don't check assumptions at compile time if '-fno-assumptions' is passed,
+// or if we're in MSVCCompat mode
+
+constexpr bool f(bool x) {
+  [[assume(x)]];
+  return true;
+}
+
+static_assert(f(false));
+
diff --git a/clang/test/SemaCXX/cxx23-assume-print.cpp b/clang/test/SemaCXX/cxx23-assume-print.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..37db015fcc39095a58500c43e586d1efb02fc447
--- /dev/null
+++ b/clang/test/SemaCXX/cxx23-assume-print.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++23 -ast-print %s | FileCheck %s
+
+// CHECK: void f(int x, int y) {
+void f(int x, int y) {
+  // CHECK-NEXT: {{\[}}[assume(true)]]
+  [[assume(true)]];
+
+  // CHECK-NEXT: {{\[}}[assume(2 + 4)]]
+  [[assume(2 + 4)]];
+
+  // CHECK-NEXT: {{\[}}[assume(x == y)]]
+  [[assume(x == y)]];
+}
diff --git a/clang/test/SemaCXX/cxx23-assume.cpp b/clang/test/SemaCXX/cxx23-assume.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2d7c9b174d901934fb38d45ce120c003f4ec72ea
--- /dev/null
+++ b/clang/test/SemaCXX/cxx23-assume.cpp
@@ -0,0 +1,128 @@
+// RUN: %clang_cc1 -std=c++23  -x c++ %s -verify
+// RUN: %clang_cc1 -std=c++20 -pedantic -x c++ %s -verify=ext,expected
+
+struct A{};
+struct B{ explicit operator bool() { return true; } };
+
+template 
+void f() {
+  [[assume(cond)]]; // ext-warning {{C++23 extension}}
+}
+
+template 
+struct S {
+  void f() {
+    [[assume(cond)]]; // ext-warning {{C++23 extension}}
+  }
+
+  template 
+  constexpr bool g() {
+    [[assume(cond == sizeof(T))]]; // expected-note {{assumption evaluated to false}} ext-warning {{C++23 extension}}
+    return true;
+  }
+};
+
+bool f2();
+
+template 
+constexpr void f3() {
+  [[assume(T{})]]; // expected-error {{not contextually convertible to 'bool'}} expected-warning {{has side effects that will be discarded}} ext-warning {{C++23 extension}}
+}
+
+void g(int x) {
+  f();
+  f();
+  S{}.f();
+  S{}.f();
+  S{}.g();
+  S{}.g();
+  [[assume(f2())]]; // expected-warning {{side effects that will be discarded}} ext-warning {{C++23 extension}}
+
+  [[assume((x = 3))]]; // expected-warning {{has side effects that will be discarded}} // ext-warning {{C++23 extension}}
+  [[assume(x++)]]; // expected-warning {{has side effects that will be discarded}} // ext-warning {{C++23 extension}}
+  [[assume(++x)]]; // expected-warning {{has side effects that will be discarded}} // ext-warning {{C++23 extension}}
+  [[assume([]{ return true; }())]]; // expected-warning {{has side effects that will be discarded}} // ext-warning {{C++23 extension}}
+  [[assume(B{})]]; // expected-warning {{has side effects that will be discarded}} // ext-warning {{C++23 extension}}
+  [[assume((1, 2))]]; // expected-warning {{has no effect}} // ext-warning {{C++23 extension}}
+
+  f3(); // expected-note {{in instantiation of}}
+  f3(); // expected-note {{in instantiation of}}
+  [[assume]]; // expected-error {{takes one argument}}
+  [[assume(z)]]; // expected-error {{undeclared identifier}}
+  [[assume(A{})]]; // expected-error {{not contextually convertible to 'bool'}}
+  [[assume(true)]] if (true) {} // expected-error {{only applies to empty statements}}
+  [[assume(true)]] {} // expected-error {{only applies to empty statements}}
+  [[assume(true)]] for (;false;) {} // expected-error {{only applies to empty statements}}
+  [[assume(true)]] while (false) {} // expected-error {{only applies to empty statements}}
+  [[assume(true)]] label:; // expected-error {{cannot be applied to a declaration}}
+  [[assume(true)]] goto label; // expected-error {{only applies to empty statements}}
+}
+
+// Check that 'x' is ODR-used here.
+constexpr int h(int x) { return sizeof([=] { [[assume(x)]]; }); } // ext-warning {{C++23 extension}}
+static_assert(h(4) == sizeof(int));
+
+static_assert(__has_cpp_attribute(assume) == 202207L);
+static_assert(__has_attribute(assume));
+
+constexpr bool i() { // ext-error {{never produces a constant expression}}
+  [[assume(false)]]; // ext-note {{assumption evaluated to false}} expected-note {{assumption evaluated to false}} ext-warning {{C++23 extension}}
+  return true;
+}
+
+constexpr bool j(bool b) {
+  [[assume(b)]]; // expected-note {{assumption evaluated to false}} ext-warning {{C++23 extension}}
+  return true;
+}
+
+static_assert(i()); // expected-error {{not an integral constant expression}} expected-note {{in call to}}
+static_assert(j(true));
+static_assert(j(false)); // expected-error {{not an integral constant expression}} expected-note {{in call to}}
+static_assert(S{}.g());
+static_assert(S{}.g()); // expected-error {{not an integral constant expression}} expected-note {{in call to}}
+
+
+template 
+constexpr bool f4() {
+  [[assume(!T{})]]; // expected-error {{invalid argument type 'D'}} // expected-warning 2 {{side effects}} ext-warning {{C++23 extension}}
+  return sizeof(T) == sizeof(int);
+}
+
+template 
+concept C = f4(); // expected-note 3 {{in instantiation of}}
+                     // expected-note@-1 3 {{while substituting}}
+                     // expected-error@-2 2 {{resulted in a non-constant expression}}
+
+struct D {
+  int x;
+};
+
+struct E {
+  int x;
+  constexpr explicit operator bool() { return false; }
+};
+
+struct F {
+  int x;
+  int y;
+  constexpr explicit operator bool() { return false; }
+};
+
+template 
+constexpr int f5() requires C { return 1; } // expected-note {{while checking the satisfaction}}
+                                               // expected-note@-1 {{while substituting template arguments}}
+                                               // expected-note@-2 {{candidate template ignored}}
+
+template 
+constexpr int f5() requires (!C) { return 2; } // expected-note 4 {{while checking the satisfaction}}
+                                                  // expected-note@-1 4 {{while substituting template arguments}}
+                                                  // expected-note@-2 {{candidate template ignored}}
+
+static_assert(f5() == 1);
+static_assert(f5() == 1); // expected-note 3 {{while checking constraint satisfaction}}
+                             // 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 {{in instantiation of}}
+static_assert(f5() == 2); // expected-note {{while checking constraint satisfaction}} expected-note {{in instantiation of}}
diff --git a/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4dc16c59d8058dcb8439c9dac2611a4e6a3e1fe4
--- /dev/null
+++ b/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
@@ -0,0 +1,159 @@
+// RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++23 %s
+
+// This test covers modifications made by P2448R2.
+
+// Check that there is no error when a constexpr function that never produces a
+// constant expression, but still an error if such function is called from
+// constexpr context.
+constexpr int F(int N) {
+  double D = 2.0 / 0.0; // expected-note {{division by zero}}
+  return 1;
+}
+
+constexpr int F0(int N) {
+  if (N == 0)
+    double d2 = 2.0 / 0.0; // expected-note {{division by zero}}
+  return 1;
+}
+
+template 
+constexpr int FT(T N) {
+  double D = 2.0 / 0.0; // expected-note {{division by zero}}
+  return 1;
+}
+
+class NonLiteral { // expected-note {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors}}
+public:
+  NonLiteral() {}
+  ~NonLiteral() {}
+};
+
+constexpr NonLiteral F1() {
+  return NonLiteral{};
+}
+
+constexpr int F2(NonLiteral N) {
+  return 8;
+}
+
+class Derived : public NonLiteral {
+  constexpr ~Derived() {};
+};
+
+class Derived1 : public NonLiteral {
+  constexpr Derived1() : NonLiteral () {}
+};
+
+
+struct X {
+  X();
+  X(const X&);
+  X(X&&);
+  X& operator=(X&);
+  X& operator=(X&& other);
+  bool operator==(X const&) const;
+};
+
+template 
+struct Wrapper {
+  constexpr Wrapper() = default;
+  constexpr Wrapper(Wrapper const&) = default;
+  constexpr Wrapper(T const& t) : t(t) { }
+  constexpr Wrapper(Wrapper &&) = default;
+  constexpr X get() const { return t; }
+  constexpr bool operator==(Wrapper const&) const = default;
+  private:
+  T t;
+};
+
+struct WrapperNonT {
+  constexpr WrapperNonT() = default;
+  constexpr WrapperNonT(WrapperNonT const&) = default;
+  constexpr WrapperNonT(X const& t) : t(t) { }
+  constexpr WrapperNonT(WrapperNonT &&) = default;
+  constexpr WrapperNonT& operator=(WrapperNonT &) = default;
+  constexpr WrapperNonT& operator=(WrapperNonT&& other) = default;
+  constexpr X get() const { return t; }
+  constexpr bool operator==(WrapperNonT const&) const = default;
+  private:
+  X t;
+};
+
+struct NonDefaultMembers {
+  constexpr NonDefaultMembers() {}; // expected-note {{non-literal type 'X' cannot be used in a constant expression}}
+  constexpr NonDefaultMembers(NonDefaultMembers const&) {};
+  constexpr NonDefaultMembers(NonDefaultMembers &&) {};
+  constexpr NonDefaultMembers& operator=(NonDefaultMembers &other) {this->t = other.t; return *this;}
+  constexpr NonDefaultMembers& operator=(NonDefaultMembers&& other) {this->t = other.t; return *this;}
+  constexpr bool operator==(NonDefaultMembers const& other) const {return this->t == other.t;}
+  X t;
+};
+
+int Glob = 0;
+class C1 {
+public:
+  constexpr C1() : D(Glob) {};
+private:
+  int D;
+};
+
+void test() {
+
+  constexpr int A = F(3); // expected-error {{constexpr variable 'A' must be initialized by a constant expression}}
+                          // expected-note@-1 {{in call}}
+  F(3);
+  constexpr int B = F0(0); // expected-error {{constexpr variable 'B' must be initialized by a constant expression}}
+                           // expected-note@-1 {{in call}}
+  F0(0);
+  constexpr auto C = F1(); // expected-error {{constexpr variable cannot have non-literal type 'const NonLiteral'}}
+  F1();
+  NonLiteral L;
+  constexpr auto D = F2(L); // expected-error {{constexpr variable 'D' must be initialized by a constant expression}}
+                            // expected-note@-1 {{non-literal type 'NonLiteral' cannot be used in a constant expression}}
+
+  constexpr auto E = FT(1); // expected-error {{constexpr variable 'E' must be initialized by a constant expression}}
+                            // expected-note@-1 {{in call}}
+  F2(L);
+
+  Wrapper x;
+  WrapperNonT x1;
+  NonDefaultMembers x2;
+
+  // TODO these produce notes with an invalid source location.
+  // static_assert((Wrapper(), true));
+  // static_assert((WrapperNonT(), true),"");
+
+  static_assert((NonDefaultMembers(), true),""); // expected-error{{expression is not an integral constant expression}} \
+                                                 // expected-note {{in call to}}
+  constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error{{must be initialized by a constant expression}} \
+                                                                     // expected-note{{non-literal}}
+}
+
+struct A {
+  A ();
+  ~A();
+};
+
+template 
+struct opt
+{
+  union {
+    char c;
+    T data;
+  };
+
+  constexpr opt() {}
+
+  constexpr ~opt()  {
+   if (engaged)
+     data.~T();
+ }
+
+  bool engaged = false;
+};
+
+consteval void foo() {
+  opt a;
+}
+
+void bar() { foo(); }
diff --git a/clang/test/SemaCXX/cxx2a-consteval-default-params.cpp b/clang/test/SemaCXX/cxx2a-consteval-default-params.cpp
index be8f7cc788589fde7b09d344d128330e23bd5612..e4b13725b2dacd42452e358b479d57ecbcf51aaa 100644
--- a/clang/test/SemaCXX/cxx2a-consteval-default-params.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval-default-params.cpp
@@ -82,3 +82,18 @@ namespace GH62224 {
   C<> Val; // No error since fwd is defined already.
   static_assert(Val.get() == 42);
 }
+
+namespace GH80630 {
+
+consteval const char* ce() { return "Hello"; }
+
+auto f2(const char* loc = []( char const* fn )
+    { return fn; }  ( ce() ) ) {
+    return loc;
+}
+
+auto g() {
+    return f2();
+}
+
+}
diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index d8482ec53f0ed4f60dd4f29ecfdf46c9b76b3b0b..192621225a543c694784aa6ba4737fc252d94f98 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -54,7 +54,7 @@ struct C {
 
 struct D {
   C c;
-  consteval D() = default; // expected-error {{cannot be consteval}}
+  consteval D() = default; // expected-error {{cannot be marked consteval}}
   consteval ~D() = default; // expected-error {{destructor cannot be declared consteval}}
 };
 
diff --git a/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp b/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
index 510ace58c35a6aaaf5a308013f121d532f495156..1e9c5fa082d0779396811c2cf0a100948d47ea14 100644
--- a/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
+++ b/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
@@ -4,7 +4,8 @@
 // RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected,reorder -Wno-c99-designator -Werror=reorder-init-list -Wno-initializer-overrides
 // RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected,override -Wno-c99-designator -Wno-reorder-init-list -Werror=initializer-overrides
 // RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected -Wno-c99-designator -Wno-reorder-init-list -Wno-initializer-overrides
-// RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected,wmissing -Wmissing-field-initializers -Wno-c99-designator -Wno-reorder-init-list -Wno-initializer-overrides
+// RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected,wmissing,wmissing-designated -Wmissing-field-initializers -Wno-c99-designator -Wno-reorder-init-list -Wno-initializer-overrides
+// RUN: %clang_cc1 -std=c++20 %s -verify=cxx20,expected,wmissing -Wmissing-field-initializers -Wno-missing-designated-field-initializers -Wno-c99-designator -Wno-reorder-init-list -Wno-initializer-overrides
 
 
 namespace class_with_ctor {
@@ -50,11 +51,11 @@ A a3 = {
 A a4 = {
   .x = 1, // override-note {{previous}}
   .x = 1 // override-error {{overrides prior initialization}}
-}; // wmissing-warning {{missing field 'y' initializer}}
+}; // wmissing-designated-warning {{missing field 'y' initializer}}
 A a5 = {
   .y = 1, // override-note {{previous}}
   .y = 1 // override-error {{overrides prior initialization}}
-}; // wmissing-warning {{missing field 'x' initializer}}
+}; // wmissing-designated-warning {{missing field 'x' initializer}}
 B b2 = {.a = 1}; // pedantic-error {{brace elision for designated initializer is a C99 extension}}
                  // wmissing-warning@-1 {{missing field 'y' initializer}}
 B b3 = {.a = 1, 2}; // pedantic-error {{mixture of designated and non-designated}} pedantic-note {{first non-designated}} pedantic-error {{brace elision}}
@@ -74,8 +75,8 @@ C c = {
 struct Foo { int a, b; };
 
 struct Foo foo0 = { 1 }; // wmissing-warning {{missing field 'b' initializer}}
-struct Foo foo1 = { .a = 1 }; // wmissing-warning {{missing field 'b' initializer}}
-struct Foo foo2 = { .b = 1 }; // wmissing-warning {{missing field 'a' initializer}}
+struct Foo foo1 = { .a = 1 }; // wmissing-designated-warning {{missing field 'b' initializer}}
+struct Foo foo2 = { .b = 1 }; // wmissing-designated-warning {{missing field 'a' initializer}}
 
 }
 
diff --git a/clang/test/SemaCXX/cxx2b-p2266-disable-with-msvc-compat.cpp b/clang/test/SemaCXX/cxx2b-p2266-disable-with-msvc-compat.cpp
index d40491834d398881a132addc4f2efca86356f363..9323dea24bd75b90270cd5acd95c74780f2304bb 100644
--- a/clang/test/SemaCXX/cxx2b-p2266-disable-with-msvc-compat.cpp
+++ b/clang/test/SemaCXX/cxx2b-p2266-disable-with-msvc-compat.cpp
@@ -9,7 +9,7 @@
 
 #if __INCLUDE_LEVEL__ == 0
 
-#if __cpluscplus > 202002L && __cpp_implicit_move < 202011L
+#if __cpluscplus > 202002L && __cpp_implicit_move < 202207L
 #error "__cpp_implicit_move not defined correctly"
 #endif
 
diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
index 415bbbf1a0bc5093cb9b1090e443ab5acac0b906..431d77ca785b8e930b5090d64ac6a2bd4da7dae1 100644
--- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx20_23,cxx23    %s
 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx20_23,cxx23    %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
 
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s
-// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
 
 // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,since-cxx14,cxx14_20,cxx14    %s
 // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,since-cxx14,cxx14_20,cxx14    %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
@@ -299,8 +299,8 @@ namespace Constexpr {
     constexpr int q = Y().f(); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Y().f()'}}
   }
   struct NonLiteral { ~NonLiteral(); } nl; // cxx14-note {{user-provided destructor}}
-  // cxx20_23-note@-1 {{'NonLiteral' is not literal because its destructor is not constexpr}}
-  constexpr auto f2(int n) { return nl; } // expected-error {{return type 'struct NonLiteral' is not a literal type}}
+  // cxx20-note@-1 {{'NonLiteral' is not literal because its destructor is not constexpr}}
+  constexpr auto f2(int n) { return nl; } // cxx14_20-error {{constexpr function's return type 'struct NonLiteral' is not a literal type}}
 }
 
 // It's not really clear whether these are valid, but this matches g++.
diff --git a/clang/test/SemaCXX/enum.cpp b/clang/test/SemaCXX/enum.cpp
index fc65fd16f8c302d139aff54c7e20bab5f8cc1fec..c482b3c571ab4ad2ea6b14332d91bda0e38b81e4 100644
--- a/clang/test/SemaCXX/enum.cpp
+++ b/clang/test/SemaCXX/enum.cpp
@@ -103,7 +103,7 @@ enum { overflow = 123456 * 234567 };
 // expected-warning@-2 {{not an integral constant expression}}
 // expected-note@-3 {{value 28958703552 is outside the range of representable values}}
 #else 
-// expected-warning@-5 {{overflow in expression; result is -1106067520 with type 'int'}}
+// expected-warning@-5 {{overflow in expression; result is -1'106'067'520 with type 'int'}}
 #endif
 
 // FIXME: This is not consistent with the above case.
@@ -112,7 +112,7 @@ enum NoFold : int { overflow2 = 123456 * 234567 };
 // expected-error@-2 {{enumerator value is not a constant expression}}
 // expected-note@-3 {{value 28958703552 is outside the range of representable values}}
 #else
-// expected-warning@-5 {{overflow in expression; result is -1106067520 with type 'int'}}
+// expected-warning@-5 {{overflow in expression; result is -1'106'067'520 with type 'int'}}
 // expected-warning@-6 {{extension}}
 #endif
 
diff --git a/clang/test/SemaCXX/integer-overflow.cpp b/clang/test/SemaCXX/integer-overflow.cpp
index 0e8ad050aa14d82d968c58c7782252a6c9b15840..6049458b93bbd094a10eb60e5d13ca398d706c04 100644
--- a/clang/test/SemaCXX/integer-overflow.cpp
+++ b/clang/test/SemaCXX/integer-overflow.cpp
@@ -13,157 +13,157 @@ uint64_t f0(uint64_t);
 uint64_t f1(uint64_t, uint32_t);
 uint64_t f2(uint64_t, ...);
 
-static const uint64_t overflow = 1 * 4608 * 1024 * 1024; // expected-warning {{overflow in expression; result is 536870912 with type 'int'}}
+static const uint64_t overflow = 1 * 4608 * 1024 * 1024; // expected-warning {{overflow in expression; result is 536'870'912 with type 'int'}}
 
 uint64_t check_integer_overflows(int i) { //expected-note 0+{{declared here}}
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   uint64_t overflow = 4608 * 1024 * 1024,
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
            overflow2 = (uint64_t)(4608 * 1024 * 1024),
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
            overflow3 = (uint64_t)(4608 * 1024 * 1024 * i),
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
            overflow4 =  (1ULL * ((4608) * ((1024) * (1024))) + 2ULL),
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
            overflow5 = static_cast(4608 * 1024 * 1024),
-// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
            multi_overflow = (uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow += overflow2 = overflow3 = (uint64_t)(4608 * 1024 * 1024);
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow += overflow2 = overflow3 = 4608 * 1024 * 1024;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow += overflow2 = overflow3 = static_cast(4608 * 1024 * 1024);
 
   uint64_t not_overflow = 4608 * 1024 * 1024ULL;
   uint64_t not_overflow2 = (1ULL * ((uint64_t)(4608) * (1024 * 1024)) + 2ULL);
 
-// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow = 4608 * 1024 * 1024 ?  4608 * 1024 * 1024 : 0;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   overflow =  0 ? 0 : 4608 * 1024 * 1024;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if (4608 * 1024 * 1024)
     return 0;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((uint64_t)(4608 * 1024 * 1024))
     return 1;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if (static_cast(4608 * 1024 * 1024))
     return 1;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((uint64_t)(4608 * 1024 * 1024))
     return 2;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((uint64_t)(4608 * 1024 * 1024 * i))
     return 3;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL))
     return 4;
 
-// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   if ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024)))
     return 5;
 
 #if __cplusplus < 201103L
   switch (i) {
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   case 4608 * 1024 * 1024:
     return 6;
-// expected-warning@+1 {{overflow in expression; result is 537919488 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 537'919'488 with type 'int'}}
   case (uint64_t)(4609 * 1024 * 1024):
     return 7;
-// expected-warning@+1 {{overflow in expression; result is 537919488 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 537'919'488 with type 'int'}}
   case 1 + static_cast(4609 * 1024 * 1024):
     return 7;
 // expected-error@+1 {{expression is not an integral constant expression}}
   case ((uint64_t)(4608 * 1024 * 1024 * i)):
     return 8;
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   case ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL)):
     return 9;
-// expected-warning@+2 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+2 2{{overflow in expression; result is 536'870'912 with type 'int'}}
 // expected-warning@+1 {{overflow converting case value to switch condition type (288230376151711744 to 0)}}
   case ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024))):
     return 10;
   }
 #endif
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while (4608 * 1024 * 1024);
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while (static_cast(4608 * 1024 * 1024));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((uint64_t)(4608 * 1024 * 1024 * i));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL));
 
-// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   while ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024)));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while (4608 * 1024 * 1024);
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while (static_cast(4608 * 1024 * 1024));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((uint64_t)(4608 * 1024 * 1024));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((uint64_t)(4608 * 1024 * 1024 * i));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((1ULL * ((4608) * ((1024) * (1024))) + 2ULL));
 
-// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   do { } while ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024)));
 
-// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}}
   for (uint64_t i = 4608 * 1024 * 1024;
        (uint64_t)(4608 * 1024 * 1024);
        i += (uint64_t)(4608 * 1024 * 1024 * i));
 
-// expected-warning@+3 {{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning@+3 2{{overflow in expression; result is 536870912 with type 'int'}}
-// expected-warning@+3 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+3 {{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning@+3 2{{overflow in expression; result is 536'870'912 with type 'int'}}
+// expected-warning@+3 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   for (uint64_t i = (1ULL * ((4608) * ((1024) * (1024))) + 2ULL);
        ((uint64_t)((uint64_t)(4608 * 1024 * 1024) * (uint64_t)(4608 * 1024 * 1024)));
        i = ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024))));
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   _Complex long long x = 4608 * 1024 * 1024;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (__real__ x) = 4608 * 1024 * 1024;
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (__imag__ x) = 4608 * 1024 * 1024;
 
-// expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+2 {{overflow in expression; result is 536'870'912 with type 'int'}}
   uint64_t a[10];
   a[4608 * 1024 * 1024] = 1;
 #if __cplusplus < 201103L
@@ -171,22 +171,22 @@ uint64_t check_integer_overflows(int i) { //expected-note 0+{{declared here}}
 // expected-note@-4 {{array 'a' declared here}}
 #endif
 
-// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 2{{overflow in expression; result is 536'870'912 with type 'int'}}
   return ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024)));
 }
 
 void check_integer_overflows_in_function_calls() {
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (void)f0(4608 * 1024 * 1024);
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   uint64_t x = f0(4608 * 1024 * 1024);
 
-// expected-warning@+2 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+2 {{overflow in expression; result is 536'870'912 with type 'int'}}
   uint64_t (*f0_ptr)(uint64_t) = &f0;
   (void)(*f0_ptr)(4608 * 1024 * 1024);
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (void)f2(0, f0(4608 * 1024 * 1024));
 }
 
@@ -211,7 +211,7 @@ namespace EvaluationCrashes {
 
 namespace GH31643 {
 void f() {
-  int a = -(1<<31); // expected-warning {{overflow in expression; result is -2147483648 with type 'int'}}
+  int a = -(1<<31); // expected-warning {{overflow in expression; result is -2'147'483'648 with type 'int'}}
 }
 }
 
@@ -237,8 +237,8 @@ u_ptr Wrap(int64_t x) {
 int64_t Pass(int64_t x) { return x; }
 
 int m() {
-    int64_t x = Pass(30 * 24 * 60 * 59 * 1000);  // expected-warning {{overflow in expression; result is -1746167296 with type 'int'}}
-    auto r = Wrap(Pass(30 * 24 * 60 * 59 * 1000));  // expected-warning {{overflow in expression; result is -1746167296 with type 'int'}}
+    int64_t x = Pass(30 * 24 * 60 * 59 * 1000);  // expected-warning {{overflow in expression; result is -1'746'167'296 with type 'int'}}
+    auto r = Wrap(Pass(30 * 24 * 60 * 59 * 1000));  // expected-warning {{overflow in expression; result is -1'746'167'296 with type 'int'}}
     return 0;
 }
 }
diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp
index 41cf5a46c38922adb1bfdf1d338144979f6b4035..0516a5da31ae9a94f7c2da454f15189daf2a8b6f 100644
--- a/clang/test/SemaCXX/lambda-expressions.cpp
+++ b/clang/test/SemaCXX/lambda-expressions.cpp
@@ -732,3 +732,18 @@ void GH67492() {
   constexpr auto test = 42;
   auto lambda = (test, []() noexcept(true) {});
 }
+
+namespace GH83267 {
+auto l = [](auto a) { return 1; };
+using type = decltype(l);
+
+template<>
+auto type::operator()(int a) const { // expected-error{{lambda call operator should not be explicitly specialized or instantiated}}
+  return c; // expected-error {{use of undeclared identifier 'c'}}
+}
+
+auto ll = [](auto a) { return 1; }; // expected-error{{lambda call operator should not be explicitly specialized or instantiated}}
+using t = decltype(ll);
+template auto t::operator()(int a) const; // expected-note {{in instantiation}}
+
+}
diff --git a/clang/test/SemaCXX/overload-bitint.cpp b/clang/test/SemaCXX/overload-bitint.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b834a3b01fede6c84fc673f51ac9c1c37496fc52
--- /dev/null
+++ b/clang/test/SemaCXX/overload-bitint.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -std=c++20 %s -verify
+// expected-no-diagnostics
+
+#include "Inputs/std-compare.h"
+
+struct S {
+  _BitInt(12) a;
+
+  constexpr operator _BitInt(12)() const { return a; }
+};
+
+// None of these used to compile because we weren't adding _BitInt types to the
+// overload set for builtin operators. See GH82998.
+static_assert(S{10} < 11);
+static_assert(S{10} <= 11);
+static_assert(S{12} > 11);
+static_assert(S{12} >= 11);
+static_assert(S{10} == 10);
+static_assert((S{10} <=> 10) == 0);
+static_assert(S{10} != 11);
+static_assert(S{10} + 0 == 10);
+static_assert(S{10} - 0 == 10);
+static_assert(S{10} * 1 == 10);
+static_assert(S{10} / 1 == 10);
+static_assert(S{10} % 1 == 0);
+static_assert(S{10} << 0 == 10);
+static_assert(S{10} >> 0 == 10);
+static_assert((S{10} | 0) == 10);
+static_assert((S{10} & 10) == 10);
+static_assert((S{10} ^ 0) == 10);
+static_assert(-S{10} == -10);
+static_assert(+S{10} == +10);
+static_assert(~S{10} == ~10);
+
+struct A {
+  _BitInt(12) a;
+
+  bool operator==(const A&) const = default;
+  bool operator!=(const A&) const = default;
+  std::strong_ordering operator<=>(const A&) const = default;
+};
+
diff --git a/clang/test/SemaCXX/overload-template.cpp b/clang/test/SemaCXX/overload-template.cpp
index 0a23788ef3da6aca538454d154bc65926517aafa..0fe13c479cce222ea602fc003728814c63b8de40 100644
--- a/clang/test/SemaCXX/overload-template.cpp
+++ b/clang/test/SemaCXX/overload-template.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++23 -verify -fsyntax-only %s
 
 enum copy_traits { movable = 1 };
 
@@ -33,3 +34,27 @@ void ReproducesBugSimply() {
   InsertRow(3, B{}); // expected-error {{no matching function for call to 'InsertRow'}}
 }
 
+#if __cplusplus >= 202302L
+namespace overloadCheck{
+  template
+  concept AlwaysTrue = true;
+
+  struct S {
+    int f(AlwaysTrue auto) { return 1; }
+    void f(this S&&, auto) {}
+
+    void g(auto) {}
+    int g(this S&&,AlwaysTrue auto) {return 1;}
+
+    int h(AlwaysTrue auto) { return 1; } //expected-note {{previous definition is here}}
+    int h(this S&&,AlwaysTrue auto) { // expected-error {{class member cannot be redeclared}} 
+      return 1;
+    }
+  };
+
+  int main() {
+    int x = S{}.f(0);
+    int y = S{}.g(0);
+  }
+}
+#endif
diff --git a/clang/test/SemaCXX/overloaded-operator.cpp b/clang/test/SemaCXX/overloaded-operator.cpp
index 887848c29b83c52d8036c69ce437ced51d1517fe..49311625d7ab2d72e89bf34d6fbe831f6cacd67b 100644
--- a/clang/test/SemaCXX/overloaded-operator.cpp
+++ b/clang/test/SemaCXX/overloaded-operator.cpp
@@ -645,3 +645,40 @@ class b {
 
 
 }
+
+#if __cplusplus >= 202002L
+namespace nw{
+  template
+  concept AlwaysTrue=true;
+
+  struct S{
+    template
+    void operator+(const T&)const{}
+
+    template
+    int operator-(const T&)const{return 0;}
+
+    template
+    int operator*(const T&)const{ // expected-note {{candidate function}}
+      return 0;
+    }
+  };
+
+  template
+  int operator+(const S&, const T&){return 0;}
+
+  template
+  void operator-(const S&, const T&){}
+
+  template
+  int operator*(const S&, const T&){ // expected-note {{candidate function}}
+    return 0;
+  }
+
+  void foo(){
+    int a = S{} + 1;
+    int b = S{} - 1;
+    int c = S{} * 1; // expected-error {{use of overloaded operator '*' is ambiguous (with operand types 'S' and 'int')}}
+  }
+}
+#endif
diff --git a/clang/test/SemaCXX/source_location.cpp b/clang/test/SemaCXX/source_location.cpp
index 7414fbce7828d15c66b761838bfcbbc87e14f308..b151fc45fdad62b79c1a79b64e973478e60b702e 100644
--- a/clang/test/SemaCXX/source_location.cpp
+++ b/clang/test/SemaCXX/source_location.cpp
@@ -832,3 +832,21 @@ void test() {
 }
 
 }
+
+namespace GH80630 {
+
+#define GH80630_LAMBDA \
+    []( char const* fn ) { \
+        static constexpr std::source_location loc = std::source_location::current(); \
+        return &loc; \
+    }( std::source_location::current().function() )
+
+auto f( std::source_location const* loc = GH80630_LAMBDA ) {
+    return loc;
+}
+
+auto g() {
+    return f();
+}
+
+}
diff --git a/clang/test/SemaCXX/type-traits-nonobject.cpp b/clang/test/SemaCXX/type-traits-nonobject.cpp
index c9e3c30e5533d48e58993d53a2f2f35253ba3314..5f7c20cc2e11c3622cd886ba3247ab628cd84645 100644
--- a/clang/test/SemaCXX/type-traits-nonobject.cpp
+++ b/clang/test/SemaCXX/type-traits-nonobject.cpp
@@ -6,11 +6,14 @@
 static_assert(!__is_pod(void), "");
 static_assert(!__is_pod(int&), "");
 static_assert(!__is_pod(int()), "");
+static_assert(!__is_pod(int()&), "");
 
 static_assert(!__is_trivially_copyable(void), "");
 static_assert(!__is_trivially_copyable(int&), "");
 static_assert(!__is_trivially_copyable(int()), "");
+static_assert(!__is_trivially_copyable(int()&), "");
 
 static_assert(!__is_trivially_relocatable(void), "");
 static_assert(!__is_trivially_relocatable(int&), "");
 static_assert(!__is_trivially_relocatable(int()), "");
+static_assert(!__is_trivially_relocatable(int()&), "");
diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp
index 23c339ebdf0826fc292c7256ba354a7c0d074f92..14ec17989ec7c75a4c2edf6b823646a8bf63309c 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1,10 +1,8 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 -fblocks -Wno-deprecated-builtins -Wno-defaulted-function-deleted %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++14 -fblocks -Wno-deprecated-builtins -Wno-defaulted-function-deleted %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++17 -fblocks -Wno-deprecated-builtins -Wno-defaulted-function-deleted %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++20 -fblocks -Wno-deprecated-builtins -Wno-defaulted-function-deleted %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 -fblocks -Wno-deprecated-builtins -Wno-defaulted-function-deleted -Wno-c++17-extensions  %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++14 -fblocks -Wno-deprecated-builtins -Wno-defaulted-function-deleted -Wno-c++17-extensions  %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++17 -fblocks -Wno-deprecated-builtins -Wno-defaulted-function-deleted  %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++20 -fblocks -Wno-deprecated-builtins -Wno-defaulted-function-deleted  %s
 
-#define T(b) (b) ? 1 : -1
-#define F(b) (b) ? -1 : 1
 
 struct NonPOD { NonPOD(int); };
 typedef NonPOD NonPODAr[10];
@@ -214,56 +212,56 @@ struct HasVirtBase : virtual ACompleteType {};
 
 void is_pod()
 {
-  { int arr[T(__is_pod(int))]; }
-  { int arr[T(__is_pod(Enum))]; }
-  { int arr[T(__is_pod(POD))]; }
-  { int arr[T(__is_pod(Int))]; }
-  { int arr[T(__is_pod(IntAr))]; }
-  { int arr[T(__is_pod(Statics))]; }
-  { int arr[T(__is_pod(Empty))]; }
-  { int arr[T(__is_pod(EmptyUnion))]; }
-  { int arr[T(__is_pod(Union))]; }
-  { int arr[T(__is_pod(HasFunc))]; }
-  { int arr[T(__is_pod(HasOp))]; }
-  { int arr[T(__is_pod(HasConv))]; }
-  { int arr[T(__is_pod(HasAssign))]; }
-  { int arr[T(__is_pod(IntArNB))]; }
-  { int arr[T(__is_pod(HasAnonymousUnion))]; }
-  { int arr[T(__is_pod(Vector))]; }
-  { int arr[T(__is_pod(VectorExt))]; }
-  { int arr[T(__is_pod(Derives))]; }
-  { int arr[T(__is_pod(DerivesAr))]; }
-  { int arr[T(__is_pod(DerivesArNB))]; }
-  { int arr[T(__is_pod(DerivesEmpty))]; }
-  { int arr[T(__is_pod(HasPriv))]; }
-  { int arr[T(__is_pod(HasProt))]; }
-  { int arr[T(__is_pod(DerivesHasPriv))]; }
-  { int arr[T(__is_pod(DerivesHasProt))]; }
-
-  { int arr[F(__is_pod(HasCons))]; }
-  { int arr[F(__is_pod(HasCopyAssign))]; }
-  { int arr[F(__is_pod(HasMoveAssign))]; }
-  { int arr[F(__is_pod(HasDest))]; }
-  { int arr[F(__is_pod(HasRef))]; }
-  { int arr[F(__is_pod(HasVirt))]; }
-  { int arr[F(__is_pod(DerivesHasCons))]; }
-  { int arr[F(__is_pod(DerivesHasCopyAssign))]; }
-  { int arr[F(__is_pod(DerivesHasMoveAssign))]; }
-  { int arr[F(__is_pod(DerivesHasDest))]; }
-  { int arr[F(__is_pod(DerivesHasRef))]; }
-  { int arr[F(__is_pod(DerivesHasVirt))]; }
-  { int arr[F(__is_pod(NonPOD))]; }
-  { int arr[F(__is_pod(HasNonPOD))]; }
-  { int arr[F(__is_pod(NonPODAr))]; }
-  { int arr[F(__is_pod(NonPODArNB))]; }
-  { int arr[F(__is_pod(void))]; }
-  { int arr[F(__is_pod(cvoid))]; }
-// { int arr[F(__is_pod(NonPODUnion))]; }
-
-  { int arr[T(__is_pod(ACompleteType))]; }
-  { int arr[F(__is_pod(AnIncompleteType))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_pod(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_pod(AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
+  static_assert(__is_pod(int));
+  static_assert(__is_pod(Enum));
+  static_assert(__is_pod(POD));
+  static_assert(__is_pod(Int));
+  static_assert(__is_pod(IntAr));
+  static_assert(__is_pod(Statics));
+  static_assert(__is_pod(Empty));
+  static_assert(__is_pod(EmptyUnion));
+  static_assert(__is_pod(Union));
+  static_assert(__is_pod(HasFunc));
+  static_assert(__is_pod(HasOp));
+  static_assert(__is_pod(HasConv));
+  static_assert(__is_pod(HasAssign));
+  static_assert(__is_pod(IntArNB));
+  static_assert(__is_pod(HasAnonymousUnion));
+  static_assert(__is_pod(Vector));
+  static_assert(__is_pod(VectorExt));
+  static_assert(__is_pod(Derives));
+  static_assert(__is_pod(DerivesAr));
+  static_assert(__is_pod(DerivesArNB));
+  static_assert(__is_pod(DerivesEmpty));
+  static_assert(__is_pod(HasPriv));
+  static_assert(__is_pod(HasProt));
+  static_assert(__is_pod(DerivesHasPriv));
+  static_assert(__is_pod(DerivesHasProt));
+
+  static_assert(!__is_pod(HasCons));
+  static_assert(!__is_pod(HasCopyAssign));
+  static_assert(!__is_pod(HasMoveAssign));
+  static_assert(!__is_pod(HasDest));
+  static_assert(!__is_pod(HasRef));
+  static_assert(!__is_pod(HasVirt));
+  static_assert(!__is_pod(DerivesHasCons));
+  static_assert(!__is_pod(DerivesHasCopyAssign));
+  static_assert(!__is_pod(DerivesHasMoveAssign));
+  static_assert(!__is_pod(DerivesHasDest));
+  static_assert(!__is_pod(DerivesHasRef));
+  static_assert(!__is_pod(DerivesHasVirt));
+  static_assert(!__is_pod(NonPOD));
+  static_assert(!__is_pod(HasNonPOD));
+  static_assert(!__is_pod(NonPODAr));
+  static_assert(!__is_pod(NonPODArNB));
+  static_assert(!__is_pod(void));
+  static_assert(!__is_pod(cvoid));
+// static_assert(!__is_pod(NonPODUnion));
+
+  static_assert(__is_pod(ACompleteType));
+  static_assert(!__is_pod(AnIncompleteType)); // expected-error {{incomplete type}}
+  static_assert(!__is_pod(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(!__is_pod(AnIncompleteType[1])); // expected-error {{incomplete type}}
 }
 
 typedef Empty EmptyAr[10];
@@ -275,56 +273,56 @@ struct DerivesVirt : virtual POD {};
 
 void is_empty()
 {
-  { int arr[T(__is_empty(Empty))]; }
-  { int arr[T(__is_empty(DerivesEmpty))]; }
-  { int arr[T(__is_empty(HasCons))]; }
-  { int arr[T(__is_empty(HasCopyAssign))]; }
-  { int arr[T(__is_empty(HasMoveAssign))]; }
-  { int arr[T(__is_empty(HasDest))]; }
-  { int arr[T(__is_empty(HasFunc))]; }
-  { int arr[T(__is_empty(HasOp))]; }
-  { int arr[T(__is_empty(HasConv))]; }
-  { int arr[T(__is_empty(HasAssign))]; }
-  { int arr[T(__is_empty(Bit0))]; }
-  { int arr[T(__is_empty(Bit0Cons))]; }
-
-  { int arr[F(__is_empty(Int))]; }
-  { int arr[F(__is_empty(POD))]; }
-  { int arr[F(__is_empty(EmptyUnion))]; }
-  { int arr[F(__is_empty(IncompleteUnion))]; }
-  { int arr[F(__is_empty(EmptyAr))]; }
-  { int arr[F(__is_empty(HasRef))]; }
-  { int arr[F(__is_empty(HasVirt))]; }
-  { int arr[F(__is_empty(AnonBitOnly))]; }
-  { int arr[F(__is_empty(BitOnly))]; }
-  { int arr[F(__is_empty(void))]; }
-  { int arr[F(__is_empty(IntArNB))]; }
-  { int arr[F(__is_empty(HasAnonymousUnion))]; }
-//  { int arr[F(__is_empty(DerivesVirt))]; }
-
-  { int arr[T(__is_empty(ACompleteType))]; }
-  { int arr[F(__is_empty(AnIncompleteType))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_empty(AnIncompleteType[]))]; }
-  { int arr[F(__is_empty(AnIncompleteType[1]))]; }
+  static_assert(__is_empty(Empty));
+  static_assert(__is_empty(DerivesEmpty));
+  static_assert(__is_empty(HasCons));
+  static_assert(__is_empty(HasCopyAssign));
+  static_assert(__is_empty(HasMoveAssign));
+  static_assert(__is_empty(HasDest));
+  static_assert(__is_empty(HasFunc));
+  static_assert(__is_empty(HasOp));
+  static_assert(__is_empty(HasConv));
+  static_assert(__is_empty(HasAssign));
+  static_assert(__is_empty(Bit0));
+  static_assert(__is_empty(Bit0Cons));
+
+  static_assert(!__is_empty(Int));
+  static_assert(!__is_empty(POD));
+  static_assert(!__is_empty(EmptyUnion));
+  static_assert(!__is_empty(IncompleteUnion));
+  static_assert(!__is_empty(EmptyAr));
+  static_assert(!__is_empty(HasRef));
+  static_assert(!__is_empty(HasVirt));
+  static_assert(!__is_empty(AnonBitOnly));
+  static_assert(!__is_empty(BitOnly));
+  static_assert(!__is_empty(void));
+  static_assert(!__is_empty(IntArNB));
+  static_assert(!__is_empty(HasAnonymousUnion));
+//  static_assert(!__is_empty(DerivesVirt));
+
+  static_assert(__is_empty(ACompleteType));
+  static_assert(!__is_empty(AnIncompleteType)); // expected-error {{incomplete type}}
+  static_assert(!__is_empty(AnIncompleteType[]));
+  static_assert(!__is_empty(AnIncompleteType[1]));
 }
 
 typedef Derives ClassType;
 
 void is_class()
 {
-  { int arr[T(__is_class(Derives))]; }
-  { int arr[T(__is_class(HasPriv))]; }
-  { int arr[T(__is_class(ClassType))]; }
-  { int arr[T(__is_class(HasAnonymousUnion))]; }
-
-  { int arr[F(__is_class(int))]; }
-  { int arr[F(__is_class(Enum))]; }
-  { int arr[F(__is_class(Int))]; }
-  { int arr[F(__is_class(IntAr))]; }
-  { int arr[F(__is_class(DerivesAr))]; }
-  { int arr[F(__is_class(Union))]; }
-  { int arr[F(__is_class(cvoid))]; }
-  { int arr[F(__is_class(IntArNB))]; }
+  static_assert(__is_class(Derives));
+  static_assert(__is_class(HasPriv));
+  static_assert(__is_class(ClassType));
+  static_assert(__is_class(HasAnonymousUnion));
+
+  static_assert(!__is_class(int));
+  static_assert(!__is_class(Enum));
+  static_assert(!__is_class(Int));
+  static_assert(!__is_class(IntAr));
+  static_assert(!__is_class(DerivesAr));
+  static_assert(!__is_class(Union));
+  static_assert(!__is_class(cvoid));
+  static_assert(!__is_class(IntArNB));
 }
 
 typedef Union UnionAr[10];
@@ -332,17 +330,17 @@ typedef Union UnionType;
 
 void is_union()
 {
-  { int arr[T(__is_union(Union))]; }
-  { int arr[T(__is_union(UnionType))]; }
-
-  { int arr[F(__is_union(int))]; }
-  { int arr[F(__is_union(Enum))]; }
-  { int arr[F(__is_union(Int))]; }
-  { int arr[F(__is_union(IntAr))]; }
-  { int arr[F(__is_union(UnionAr))]; }
-  { int arr[F(__is_union(cvoid))]; }
-  { int arr[F(__is_union(IntArNB))]; }
-  { int arr[F(__is_union(HasAnonymousUnion))]; }
+  static_assert(__is_union(Union));
+  static_assert(__is_union(UnionType));
+
+  static_assert(!__is_union(int));
+  static_assert(!__is_union(Enum));
+  static_assert(!__is_union(Int));
+  static_assert(!__is_union(IntAr));
+  static_assert(!__is_union(UnionAr));
+  static_assert(!__is_union(cvoid));
+  static_assert(!__is_union(IntArNB));
+  static_assert(!__is_union(HasAnonymousUnion));
 }
 
 typedef Enum EnumType;
@@ -350,57 +348,57 @@ typedef EnumClass EnumClassType;
 
 void is_enum()
 {
-  { int arr[T(__is_enum(Enum))]; }
-  { int arr[T(__is_enum(EnumType))]; }
-  { int arr[T(__is_enum(SignedEnum))]; }
-  { int arr[T(__is_enum(UnsignedEnum))]; }
-
-  { int arr[T(__is_enum(EnumClass))]; }
-  { int arr[T(__is_enum(EnumClassType))]; }
-  { int arr[T(__is_enum(SignedEnumClass))]; }
-  { int arr[T(__is_enum(UnsignedEnumClass))]; }
-
-  { int arr[F(__is_enum(int))]; }
-  { int arr[F(__is_enum(Union))]; }
-  { int arr[F(__is_enum(Int))]; }
-  { int arr[F(__is_enum(IntAr))]; }
-  { int arr[F(__is_enum(UnionAr))]; }
-  { int arr[F(__is_enum(Derives))]; }
-  { int arr[F(__is_enum(ClassType))]; }
-  { int arr[F(__is_enum(cvoid))]; }
-  { int arr[F(__is_enum(IntArNB))]; }
-  { int arr[F(__is_enum(HasAnonymousUnion))]; }
-  { int arr[F(__is_enum(AnIncompleteType))]; }
-  { int arr[F(__is_enum(AnIncompleteTypeAr))]; }
-  { int arr[F(__is_enum(AnIncompleteTypeArMB))]; }
-  { int arr[F(__is_enum(AnIncompleteTypeArNB))]; }
+  static_assert(__is_enum(Enum));
+  static_assert(__is_enum(EnumType));
+  static_assert(__is_enum(SignedEnum));
+  static_assert(__is_enum(UnsignedEnum));
+
+  static_assert(__is_enum(EnumClass));
+  static_assert(__is_enum(EnumClassType));
+  static_assert(__is_enum(SignedEnumClass));
+  static_assert(__is_enum(UnsignedEnumClass));
+
+  static_assert(!__is_enum(int));
+  static_assert(!__is_enum(Union));
+  static_assert(!__is_enum(Int));
+  static_assert(!__is_enum(IntAr));
+  static_assert(!__is_enum(UnionAr));
+  static_assert(!__is_enum(Derives));
+  static_assert(!__is_enum(ClassType));
+  static_assert(!__is_enum(cvoid));
+  static_assert(!__is_enum(IntArNB));
+  static_assert(!__is_enum(HasAnonymousUnion));
+  static_assert(!__is_enum(AnIncompleteType));
+  static_assert(!__is_enum(AnIncompleteTypeAr));
+  static_assert(!__is_enum(AnIncompleteTypeArMB));
+  static_assert(!__is_enum(AnIncompleteTypeArNB));
 }
 
 void is_scoped_enum() {
-  static_assert(!__is_scoped_enum(Enum), "");
-  static_assert(!__is_scoped_enum(EnumType), "");
-  static_assert(!__is_scoped_enum(SignedEnum), "");
-  static_assert(!__is_scoped_enum(UnsignedEnum), "");
-
-  static_assert(__is_scoped_enum(EnumClass), "");
-  static_assert(__is_scoped_enum(EnumClassType), "");
-  static_assert(__is_scoped_enum(SignedEnumClass), "");
-  static_assert(__is_scoped_enum(UnsignedEnumClass), "");
-
-  static_assert(!__is_scoped_enum(int), "");
-  static_assert(!__is_scoped_enum(Union), "");
-  static_assert(!__is_scoped_enum(Int), "");
-  static_assert(!__is_scoped_enum(IntAr), "");
-  static_assert(!__is_scoped_enum(UnionAr), "");
-  static_assert(!__is_scoped_enum(Derives), "");
-  static_assert(!__is_scoped_enum(ClassType), "");
-  static_assert(!__is_scoped_enum(cvoid), "");
-  static_assert(!__is_scoped_enum(IntArNB), "");
-  static_assert(!__is_scoped_enum(HasAnonymousUnion), "");
-  static_assert(!__is_scoped_enum(AnIncompleteType), "");
-  static_assert(!__is_scoped_enum(AnIncompleteTypeAr), "");
-  static_assert(!__is_scoped_enum(AnIncompleteTypeArMB), "");
-  static_assert(!__is_scoped_enum(AnIncompleteTypeArNB), "");
+  static_assert(!__is_scoped_enum(Enum));
+  static_assert(!__is_scoped_enum(EnumType));
+  static_assert(!__is_scoped_enum(SignedEnum));
+  static_assert(!__is_scoped_enum(UnsignedEnum));
+
+  static_assert(__is_scoped_enum(EnumClass));
+  static_assert(__is_scoped_enum(EnumClassType));
+  static_assert(__is_scoped_enum(SignedEnumClass));
+  static_assert(__is_scoped_enum(UnsignedEnumClass));
+
+  static_assert(!__is_scoped_enum(int));
+  static_assert(!__is_scoped_enum(Union));
+  static_assert(!__is_scoped_enum(Int));
+  static_assert(!__is_scoped_enum(IntAr));
+  static_assert(!__is_scoped_enum(UnionAr));
+  static_assert(!__is_scoped_enum(Derives));
+  static_assert(!__is_scoped_enum(ClassType));
+  static_assert(!__is_scoped_enum(cvoid));
+  static_assert(!__is_scoped_enum(IntArNB));
+  static_assert(!__is_scoped_enum(HasAnonymousUnion));
+  static_assert(!__is_scoped_enum(AnIncompleteType));
+  static_assert(!__is_scoped_enum(AnIncompleteTypeAr));
+  static_assert(!__is_scoped_enum(AnIncompleteTypeArMB));
+  static_assert(!__is_scoped_enum(AnIncompleteTypeArNB));
 }
 
 struct FinalClass final {
@@ -421,20 +419,20 @@ struct PotentiallyFinal final { };
 
 void is_final()
 {
-	{ int arr[T(__is_final(FinalClass))]; }
-	{ int arr[T(__is_final(PotentiallyFinal))]; }
-	{ int arr[T(__is_final(PotentiallyFinal))]; }
-
-	{ int arr[F(__is_final(int))]; }
-	{ int arr[F(__is_final(Union))]; }
-	{ int arr[F(__is_final(Int))]; }
-	{ int arr[F(__is_final(IntAr))]; }
-	{ int arr[F(__is_final(UnionAr))]; }
-	{ int arr[F(__is_final(Derives))]; }
-	{ int arr[F(__is_final(ClassType))]; }
-	{ int arr[F(__is_final(cvoid))]; }
-	{ int arr[F(__is_final(IntArNB))]; }
-	{ int arr[F(__is_final(HasAnonymousUnion))]; }
+	static_assert(__is_final(FinalClass));
+	static_assert(__is_final(PotentiallyFinal));
+	static_assert(__is_final(PotentiallyFinal));
+
+	static_assert(!__is_final(int));
+	static_assert(!__is_final(Union));
+	static_assert(!__is_final(Int));
+	static_assert(!__is_final(IntAr));
+	static_assert(!__is_final(UnionAr));
+	static_assert(!__is_final(Derives));
+	static_assert(!__is_final(ClassType));
+	static_assert(!__is_final(cvoid));
+	static_assert(!__is_final(IntArNB));
+	static_assert(!__is_final(HasAnonymousUnion));
 }
 
 
@@ -443,78 +441,78 @@ struct InheritPolymorph : Polymorph {};
 
 void is_polymorphic()
 {
-  { int arr[T(__is_polymorphic(Polymorph))]; }
-  { int arr[T(__is_polymorphic(InheritPolymorph))]; }
-
-  { int arr[F(__is_polymorphic(int))]; }
-  { int arr[F(__is_polymorphic(Union))]; }
-  { int arr[F(__is_polymorphic(IncompleteUnion))]; }
-  { int arr[F(__is_polymorphic(Int))]; }
-  { int arr[F(__is_polymorphic(IntAr))]; }
-  { int arr[F(__is_polymorphic(UnionAr))]; }
-  { int arr[F(__is_polymorphic(Derives))]; }
-  { int arr[F(__is_polymorphic(ClassType))]; }
-  { int arr[F(__is_polymorphic(Enum))]; }
-  { int arr[F(__is_polymorphic(cvoid))]; }
-  { int arr[F(__is_polymorphic(IntArNB))]; }
+  static_assert(__is_polymorphic(Polymorph));
+  static_assert(__is_polymorphic(InheritPolymorph));
+
+  static_assert(!__is_polymorphic(int));
+  static_assert(!__is_polymorphic(Union));
+  static_assert(!__is_polymorphic(IncompleteUnion));
+  static_assert(!__is_polymorphic(Int));
+  static_assert(!__is_polymorphic(IntAr));
+  static_assert(!__is_polymorphic(UnionAr));
+  static_assert(!__is_polymorphic(Derives));
+  static_assert(!__is_polymorphic(ClassType));
+  static_assert(!__is_polymorphic(Enum));
+  static_assert(!__is_polymorphic(cvoid));
+  static_assert(!__is_polymorphic(IntArNB));
 }
 
 void is_integral()
 {
-  int t01[T(__is_integral(bool))];
-  int t02[T(__is_integral(char))];
-  int t03[T(__is_integral(signed char))];
-  int t04[T(__is_integral(unsigned char))];
-  //int t05[T(__is_integral(char16_t))];
-  //int t06[T(__is_integral(char32_t))];
-  int t07[T(__is_integral(wchar_t))];
-  int t08[T(__is_integral(short))];
-  int t09[T(__is_integral(unsigned short))];
-  int t10[T(__is_integral(int))];
-  int t11[T(__is_integral(unsigned int))];
-  int t12[T(__is_integral(long))];
-  int t13[T(__is_integral(unsigned long))];
-
-  int t21[F(__is_integral(float))];
-  int t22[F(__is_integral(double))];
-  int t23[F(__is_integral(long double))];
-  int t24[F(__is_integral(Union))];
-  int t25[F(__is_integral(UnionAr))];
-  int t26[F(__is_integral(Derives))];
-  int t27[F(__is_integral(ClassType))];
-  int t28[F(__is_integral(Enum))];
-  int t29[F(__is_integral(void))];
-  int t30[F(__is_integral(cvoid))];
-  int t31[F(__is_integral(IntArNB))];
+  static_assert(__is_integral(bool));
+  static_assert(__is_integral(char));
+  static_assert(__is_integral(signed char));
+  static_assert(__is_integral(unsigned char));
+  //static_assert(__is_integral(char16_t));
+  //static_assert(__is_integral(char32_t));
+  static_assert(__is_integral(wchar_t));
+  static_assert(__is_integral(short));
+  static_assert(__is_integral(unsigned short));
+  static_assert(__is_integral(int));
+  static_assert(__is_integral(unsigned int));
+  static_assert(__is_integral(long));
+  static_assert(__is_integral(unsigned long));
+
+  static_assert(!__is_integral(float));
+  static_assert(!__is_integral(double));
+  static_assert(!__is_integral(long double));
+  static_assert(!__is_integral(Union));
+  static_assert(!__is_integral(UnionAr));
+  static_assert(!__is_integral(Derives));
+  static_assert(!__is_integral(ClassType));
+  static_assert(!__is_integral(Enum));
+  static_assert(!__is_integral(void));
+  static_assert(!__is_integral(cvoid));
+  static_assert(!__is_integral(IntArNB));
 }
 
 void is_floating_point()
 {
-  int t01[T(__is_floating_point(float))];
-  int t02[T(__is_floating_point(double))];
-  int t03[T(__is_floating_point(long double))];
-
-  int t11[F(__is_floating_point(bool))];
-  int t12[F(__is_floating_point(char))];
-  int t13[F(__is_floating_point(signed char))];
-  int t14[F(__is_floating_point(unsigned char))];
-  //int t15[F(__is_floating_point(char16_t))];
-  //int t16[F(__is_floating_point(char32_t))];
-  int t17[F(__is_floating_point(wchar_t))];
-  int t18[F(__is_floating_point(short))];
-  int t19[F(__is_floating_point(unsigned short))];
-  int t20[F(__is_floating_point(int))];
-  int t21[F(__is_floating_point(unsigned int))];
-  int t22[F(__is_floating_point(long))];
-  int t23[F(__is_floating_point(unsigned long))];
-  int t24[F(__is_floating_point(Union))];
-  int t25[F(__is_floating_point(UnionAr))];
-  int t26[F(__is_floating_point(Derives))];
-  int t27[F(__is_floating_point(ClassType))];
-  int t28[F(__is_floating_point(Enum))];
-  int t29[F(__is_floating_point(void))];
-  int t30[F(__is_floating_point(cvoid))];
-  int t31[F(__is_floating_point(IntArNB))];
+  static_assert(__is_floating_point(float));
+  static_assert(__is_floating_point(double));
+  static_assert(__is_floating_point(long double));
+
+  static_assert(!__is_floating_point(bool));
+  static_assert(!__is_floating_point(char));
+  static_assert(!__is_floating_point(signed char));
+  static_assert(!__is_floating_point(unsigned char));
+  //static_assert(!__is_floating_point(char16_t));
+  //static_assert(!__is_floating_point(char32_t));
+  static_assert(!__is_floating_point(wchar_t));
+  static_assert(!__is_floating_point(short));
+  static_assert(!__is_floating_point(unsigned short));
+  static_assert(!__is_floating_point(int));
+  static_assert(!__is_floating_point(unsigned int));
+  static_assert(!__is_floating_point(long));
+  static_assert(!__is_floating_point(unsigned long));
+  static_assert(!__is_floating_point(Union));
+  static_assert(!__is_floating_point(UnionAr));
+  static_assert(!__is_floating_point(Derives));
+  static_assert(!__is_floating_point(ClassType));
+  static_assert(!__is_floating_point(Enum));
+  static_assert(!__is_floating_point(void));
+  static_assert(!__is_floating_point(cvoid));
+  static_assert(!__is_floating_point(IntArNB));
 }
 
 template 
@@ -537,274 +535,274 @@ void is_aggregate()
   __is_aggregate(IncompleteUnion); // expected-error {{incomplete type}}
 
   // Valid since LWG3823
-  static_assert(__is_aggregate(AnIncompleteType[]), "");
-  static_assert(__is_aggregate(AnIncompleteType[1]), "");
-  static_assert(__is_aggregate(AnIncompleteTypeAr), "");
-  static_assert(__is_aggregate(AnIncompleteTypeArNB), "");
-  static_assert(__is_aggregate(AnIncompleteTypeArMB), "");
-
-  static_assert(!__is_aggregate(NonPOD), "");
-  static_assert(__is_aggregate(NonPODAr), "");
-  static_assert(__is_aggregate(NonPODArNB), "");
-  static_assert(__is_aggregate(NonPODArMB), "");
-
-  static_assert(!__is_aggregate(Enum), "");
-  static_assert(__is_aggregate(POD), "");
-  static_assert(__is_aggregate(Empty), "");
-  static_assert(__is_aggregate(EmptyAr), "");
-  static_assert(__is_aggregate(EmptyArNB), "");
-  static_assert(__is_aggregate(EmptyArMB), "");
-  static_assert(!__is_aggregate(void), "");
-  static_assert(!__is_aggregate(const volatile void), "");
-  static_assert(!__is_aggregate(int), "");
-  static_assert(__is_aggregate(IntAr), "");
-  static_assert(__is_aggregate(IntArNB), "");
-  static_assert(__is_aggregate(EmptyUnion), "");
-  static_assert(__is_aggregate(Union), "");
-  static_assert(__is_aggregate(Statics), "");
-  static_assert(__is_aggregate(HasFunc), "");
-  static_assert(__is_aggregate(HasOp), "");
-  static_assert(__is_aggregate(HasAssign), "");
-  static_assert(__is_aggregate(HasAnonymousUnion), "");
-
-  static_assert(__is_aggregate(Derives) == TrueAfterCpp14, "");
-  static_assert(__is_aggregate(DerivesAr), "");
-  static_assert(__is_aggregate(DerivesArNB), "");
-  static_assert(!__is_aggregate(HasCons), "");
+  static_assert(__is_aggregate(AnIncompleteType[]));
+  static_assert(__is_aggregate(AnIncompleteType[1]));
+  static_assert(__is_aggregate(AnIncompleteTypeAr));
+  static_assert(__is_aggregate(AnIncompleteTypeArNB));
+  static_assert(__is_aggregate(AnIncompleteTypeArMB));
+
+  static_assert(!__is_aggregate(NonPOD));
+  static_assert(__is_aggregate(NonPODAr));
+  static_assert(__is_aggregate(NonPODArNB));
+  static_assert(__is_aggregate(NonPODArMB));
+
+  static_assert(!__is_aggregate(Enum));
+  static_assert(__is_aggregate(POD));
+  static_assert(__is_aggregate(Empty));
+  static_assert(__is_aggregate(EmptyAr));
+  static_assert(__is_aggregate(EmptyArNB));
+  static_assert(__is_aggregate(EmptyArMB));
+  static_assert(!__is_aggregate(void));
+  static_assert(!__is_aggregate(const volatile void));
+  static_assert(!__is_aggregate(int));
+  static_assert(__is_aggregate(IntAr));
+  static_assert(__is_aggregate(IntArNB));
+  static_assert(__is_aggregate(EmptyUnion));
+  static_assert(__is_aggregate(Union));
+  static_assert(__is_aggregate(Statics));
+  static_assert(__is_aggregate(HasFunc));
+  static_assert(__is_aggregate(HasOp));
+  static_assert(__is_aggregate(HasAssign));
+  static_assert(__is_aggregate(HasAnonymousUnion));
+
+  static_assert(__is_aggregate(Derives) == TrueAfterCpp14);
+  static_assert(__is_aggregate(DerivesAr));
+  static_assert(__is_aggregate(DerivesArNB));
+  static_assert(!__is_aggregate(HasCons));
 #if __cplusplus >= 202002L
-  static_assert(!__is_aggregate(HasDefaultCons), "");
+  static_assert(!__is_aggregate(HasDefaultCons));
 #else
-  static_assert(__is_aggregate(HasDefaultCons), "");
+  static_assert(__is_aggregate(HasDefaultCons));
 #endif
-  static_assert(!__is_aggregate(HasExplicitDefaultCons), "");
-  static_assert(!__is_aggregate(HasInheritedCons), "");
-  static_assert(__is_aggregate(HasNoInheritedCons) == TrueAfterCpp14, "");
-  static_assert(__is_aggregate(HasCopyAssign), "");
-  static_assert(!__is_aggregate(NonTrivialDefault), "");
-  static_assert(__is_aggregate(HasDest), "");
-  static_assert(!__is_aggregate(HasPriv), "");
-  static_assert(!__is_aggregate(HasProt), "");
-  static_assert(__is_aggregate(HasRefAggregate), "");
-  static_assert(__is_aggregate(HasNonPOD), "");
-  static_assert(!__is_aggregate(HasVirt), "");
-  static_assert(__is_aggregate(VirtAr), "");
-  static_assert(__is_aggregate(HasInClassInit) == TrueAfterCpp11, "");
-  static_assert(!__is_aggregate(HasPrivateBase), "");
-  static_assert(!__is_aggregate(HasProtectedBase), "");
-  static_assert(!__is_aggregate(HasVirtBase), "");
-
-  static_assert(__is_aggregate(AggregateTemplate), "");
-  static_assert(!__is_aggregate(NonAggregateTemplate), "");
-
-  static_assert(__is_aggregate(Vector), ""); // Extension supported by GCC and Clang
-  static_assert(__is_aggregate(VectorExt), "");
-  static_assert(__is_aggregate(ComplexInt), "");
-  static_assert(__is_aggregate(ComplexFloat), "");
+  static_assert(!__is_aggregate(HasExplicitDefaultCons));
+  static_assert(!__is_aggregate(HasInheritedCons));
+  static_assert(__is_aggregate(HasNoInheritedCons) == TrueAfterCpp14);
+  static_assert(__is_aggregate(HasCopyAssign));
+  static_assert(!__is_aggregate(NonTrivialDefault));
+  static_assert(__is_aggregate(HasDest));
+  static_assert(!__is_aggregate(HasPriv));
+  static_assert(!__is_aggregate(HasProt));
+  static_assert(__is_aggregate(HasRefAggregate));
+  static_assert(__is_aggregate(HasNonPOD));
+  static_assert(!__is_aggregate(HasVirt));
+  static_assert(__is_aggregate(VirtAr));
+  static_assert(__is_aggregate(HasInClassInit) == TrueAfterCpp11);
+  static_assert(!__is_aggregate(HasPrivateBase));
+  static_assert(!__is_aggregate(HasProtectedBase));
+  static_assert(!__is_aggregate(HasVirtBase));
+
+  static_assert(__is_aggregate(AggregateTemplate));
+  static_assert(!__is_aggregate(NonAggregateTemplate));
+
+  static_assert(__is_aggregate(Vector)); // Extension supported by GCC and Clang
+  static_assert(__is_aggregate(VectorExt));
+  static_assert(__is_aggregate(ComplexInt));
+  static_assert(__is_aggregate(ComplexFloat));
 }
 
 void is_arithmetic()
 {
-  int t01[T(__is_arithmetic(float))];
-  int t02[T(__is_arithmetic(double))];
-  int t03[T(__is_arithmetic(long double))];
-  int t11[T(__is_arithmetic(bool))];
-  int t12[T(__is_arithmetic(char))];
-  int t13[T(__is_arithmetic(signed char))];
-  int t14[T(__is_arithmetic(unsigned char))];
-  //int t15[T(__is_arithmetic(char16_t))];
-  //int t16[T(__is_arithmetic(char32_t))];
-  int t17[T(__is_arithmetic(wchar_t))];
-  int t18[T(__is_arithmetic(short))];
-  int t19[T(__is_arithmetic(unsigned short))];
-  int t20[T(__is_arithmetic(int))];
-  int t21[T(__is_arithmetic(unsigned int))];
-  int t22[T(__is_arithmetic(long))];
-  int t23[T(__is_arithmetic(unsigned long))];
-
-  int t24[F(__is_arithmetic(Union))];
-  int t25[F(__is_arithmetic(UnionAr))];
-  int t26[F(__is_arithmetic(Derives))];
-  int t27[F(__is_arithmetic(ClassType))];
-  int t28[F(__is_arithmetic(Enum))];
-  int t29[F(__is_arithmetic(void))];
-  int t30[F(__is_arithmetic(cvoid))];
-  int t31[F(__is_arithmetic(IntArNB))];
+  static_assert(__is_arithmetic(float));
+  static_assert(__is_arithmetic(double));
+  static_assert(__is_arithmetic(long double));
+  static_assert(__is_arithmetic(bool));
+  static_assert(__is_arithmetic(char));
+  static_assert(__is_arithmetic(signed char));
+  static_assert(__is_arithmetic(unsigned char));
+  //static_assert(__is_arithmetic(char16_t));
+  //static_assert(__is_arithmetic(char32_t));
+  static_assert(__is_arithmetic(wchar_t));
+  static_assert(__is_arithmetic(short));
+  static_assert(__is_arithmetic(unsigned short));
+  static_assert(__is_arithmetic(int));
+  static_assert(__is_arithmetic(unsigned int));
+  static_assert(__is_arithmetic(long));
+  static_assert(__is_arithmetic(unsigned long));
+
+  static_assert(!__is_arithmetic(Union));
+  static_assert(!__is_arithmetic(UnionAr));
+  static_assert(!__is_arithmetic(Derives));
+  static_assert(!__is_arithmetic(ClassType));
+  static_assert(!__is_arithmetic(Enum));
+  static_assert(!__is_arithmetic(void));
+  static_assert(!__is_arithmetic(cvoid));
+  static_assert(!__is_arithmetic(IntArNB));
 }
 
 void is_complete_type()
 {
-  int t01[T(__is_complete_type(float))];
-  int t02[T(__is_complete_type(double))];
-  int t03[T(__is_complete_type(long double))];
-  int t11[T(__is_complete_type(bool))];
-  int t12[T(__is_complete_type(char))];
-  int t13[T(__is_complete_type(signed char))];
-  int t14[T(__is_complete_type(unsigned char))];
-  //int t15[T(__is_complete_type(char16_t))];
-  //int t16[T(__is_complete_type(char32_t))];
-  int t17[T(__is_complete_type(wchar_t))];
-  int t18[T(__is_complete_type(short))];
-  int t19[T(__is_complete_type(unsigned short))];
-  int t20[T(__is_complete_type(int))];
-  int t21[T(__is_complete_type(unsigned int))];
-  int t22[T(__is_complete_type(long))];
-  int t23[T(__is_complete_type(unsigned long))];
-  int t24[T(__is_complete_type(ACompleteType))];
-
-  int t30[F(__is_complete_type(AnIncompleteType))];
+  static_assert(__is_complete_type(float));
+  static_assert(__is_complete_type(double));
+  static_assert(__is_complete_type(long double));
+  static_assert(__is_complete_type(bool));
+  static_assert(__is_complete_type(char));
+  static_assert(__is_complete_type(signed char));
+  static_assert(__is_complete_type(unsigned char));
+  //static_assert(__is_complete_type(char16_t));
+  //static_assert(__is_complete_type(char32_t));
+  static_assert(__is_complete_type(wchar_t));
+  static_assert(__is_complete_type(short));
+  static_assert(__is_complete_type(unsigned short));
+  static_assert(__is_complete_type(int));
+  static_assert(__is_complete_type(unsigned int));
+  static_assert(__is_complete_type(long));
+  static_assert(__is_complete_type(unsigned long));
+  static_assert(__is_complete_type(ACompleteType));
+
+  static_assert(!__is_complete_type(AnIncompleteType));
 }
 
 void is_void()
 {
-  int t01[T(__is_void(void))];
-  int t02[T(__is_void(cvoid))];
-
-  int t10[F(__is_void(float))];
-  int t11[F(__is_void(double))];
-  int t12[F(__is_void(long double))];
-  int t13[F(__is_void(bool))];
-  int t14[F(__is_void(char))];
-  int t15[F(__is_void(signed char))];
-  int t16[F(__is_void(unsigned char))];
-  int t17[F(__is_void(wchar_t))];
-  int t18[F(__is_void(short))];
-  int t19[F(__is_void(unsigned short))];
-  int t20[F(__is_void(int))];
-  int t21[F(__is_void(unsigned int))];
-  int t22[F(__is_void(long))];
-  int t23[F(__is_void(unsigned long))];
-  int t24[F(__is_void(Union))];
-  int t25[F(__is_void(UnionAr))];
-  int t26[F(__is_void(Derives))];
-  int t27[F(__is_void(ClassType))];
-  int t28[F(__is_void(Enum))];
-  int t29[F(__is_void(IntArNB))];
-  int t30[F(__is_void(void*))];
-  int t31[F(__is_void(cvoid*))];
+  static_assert(__is_void(void));
+  static_assert(__is_void(cvoid));
+
+  static_assert(!__is_void(float));
+  static_assert(!__is_void(double));
+  static_assert(!__is_void(long double));
+  static_assert(!__is_void(bool));
+  static_assert(!__is_void(char));
+  static_assert(!__is_void(signed char));
+  static_assert(!__is_void(unsigned char));
+  static_assert(!__is_void(wchar_t));
+  static_assert(!__is_void(short));
+  static_assert(!__is_void(unsigned short));
+  static_assert(!__is_void(int));
+  static_assert(!__is_void(unsigned int));
+  static_assert(!__is_void(long));
+  static_assert(!__is_void(unsigned long));
+  static_assert(!__is_void(Union));
+  static_assert(!__is_void(UnionAr));
+  static_assert(!__is_void(Derives));
+  static_assert(!__is_void(ClassType));
+  static_assert(!__is_void(Enum));
+  static_assert(!__is_void(IntArNB));
+  static_assert(!__is_void(void*));
+  static_assert(!__is_void(cvoid*));
 }
 
 void is_array()
 {
-  int t01[T(__is_array(IntAr))];
-  int t02[T(__is_array(IntArNB))];
-  int t03[T(__is_array(UnionAr))];
-
-  int t10[F(__is_array(void))];
-  int t11[F(__is_array(cvoid))];
-  int t12[F(__is_array(float))];
-  int t13[F(__is_array(double))];
-  int t14[F(__is_array(long double))];
-  int t15[F(__is_array(bool))];
-  int t16[F(__is_array(char))];
-  int t17[F(__is_array(signed char))];
-  int t18[F(__is_array(unsigned char))];
-  int t19[F(__is_array(wchar_t))];
-  int t20[F(__is_array(short))];
-  int t21[F(__is_array(unsigned short))];
-  int t22[F(__is_array(int))];
-  int t23[F(__is_array(unsigned int))];
-  int t24[F(__is_array(long))];
-  int t25[F(__is_array(unsigned long))];
-  int t26[F(__is_array(Union))];
-  int t27[F(__is_array(Derives))];
-  int t28[F(__is_array(ClassType))];
-  int t29[F(__is_array(Enum))];
-  int t30[F(__is_array(void*))];
-  int t31[F(__is_array(cvoid*))];
+  static_assert(__is_array(IntAr));
+  static_assert(__is_array(IntArNB));
+  static_assert(__is_array(UnionAr));
+
+  static_assert(!__is_array(void));
+  static_assert(!__is_array(cvoid));
+  static_assert(!__is_array(float));
+  static_assert(!__is_array(double));
+  static_assert(!__is_array(long double));
+  static_assert(!__is_array(bool));
+  static_assert(!__is_array(char));
+  static_assert(!__is_array(signed char));
+  static_assert(!__is_array(unsigned char));
+  static_assert(!__is_array(wchar_t));
+  static_assert(!__is_array(short));
+  static_assert(!__is_array(unsigned short));
+  static_assert(!__is_array(int));
+  static_assert(!__is_array(unsigned int));
+  static_assert(!__is_array(long));
+  static_assert(!__is_array(unsigned long));
+  static_assert(!__is_array(Union));
+  static_assert(!__is_array(Derives));
+  static_assert(!__is_array(ClassType));
+  static_assert(!__is_array(Enum));
+  static_assert(!__is_array(void*));
+  static_assert(!__is_array(cvoid*));
 }
 
 void is_bounded_array(int n) {
-  static_assert(__is_bounded_array(IntAr), "");
-  static_assert(!__is_bounded_array(IntArNB), "");
-  static_assert(__is_bounded_array(UnionAr), "");
-
-  static_assert(!__is_bounded_array(void), "");
-  static_assert(!__is_bounded_array(cvoid), "");
-  static_assert(!__is_bounded_array(float), "");
-  static_assert(!__is_bounded_array(double), "");
-  static_assert(!__is_bounded_array(long double), "");
-  static_assert(!__is_bounded_array(bool), "");
-  static_assert(!__is_bounded_array(char), "");
-  static_assert(!__is_bounded_array(signed char), "");
-  static_assert(!__is_bounded_array(unsigned char), "");
-  static_assert(!__is_bounded_array(wchar_t), "");
-  static_assert(!__is_bounded_array(short), "");
-  static_assert(!__is_bounded_array(unsigned short), "");
-  static_assert(!__is_bounded_array(int), "");
-  static_assert(!__is_bounded_array(unsigned int), "");
-  static_assert(!__is_bounded_array(long), "");
-  static_assert(!__is_bounded_array(unsigned long), "");
-  static_assert(!__is_bounded_array(Union), "");
-  static_assert(!__is_bounded_array(Derives), "");
-  static_assert(!__is_bounded_array(ClassType), "");
-  static_assert(!__is_bounded_array(Enum), "");
-  static_assert(!__is_bounded_array(void *), "");
-  static_assert(!__is_bounded_array(cvoid *), "");
+  static_assert(__is_bounded_array(IntAr));
+  static_assert(!__is_bounded_array(IntArNB));
+  static_assert(__is_bounded_array(UnionAr));
+
+  static_assert(!__is_bounded_array(void));
+  static_assert(!__is_bounded_array(cvoid));
+  static_assert(!__is_bounded_array(float));
+  static_assert(!__is_bounded_array(double));
+  static_assert(!__is_bounded_array(long double));
+  static_assert(!__is_bounded_array(bool));
+  static_assert(!__is_bounded_array(char));
+  static_assert(!__is_bounded_array(signed char));
+  static_assert(!__is_bounded_array(unsigned char));
+  static_assert(!__is_bounded_array(wchar_t));
+  static_assert(!__is_bounded_array(short));
+  static_assert(!__is_bounded_array(unsigned short));
+  static_assert(!__is_bounded_array(int));
+  static_assert(!__is_bounded_array(unsigned int));
+  static_assert(!__is_bounded_array(long));
+  static_assert(!__is_bounded_array(unsigned long));
+  static_assert(!__is_bounded_array(Union));
+  static_assert(!__is_bounded_array(Derives));
+  static_assert(!__is_bounded_array(ClassType));
+  static_assert(!__is_bounded_array(Enum));
+  static_assert(!__is_bounded_array(void *));
+  static_assert(!__is_bounded_array(cvoid *));
 
   int t32[n];
   (void)__is_bounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_bounded_array'}}
 }
 
 void is_unbounded_array(int n) {
-  static_assert(!__is_unbounded_array(IntAr), "");
-  static_assert(__is_unbounded_array(IntArNB), "");
-  static_assert(!__is_unbounded_array(UnionAr), "");
-
-  static_assert(!__is_unbounded_array(void), "");
-  static_assert(!__is_unbounded_array(cvoid), "");
-  static_assert(!__is_unbounded_array(float), "");
-  static_assert(!__is_unbounded_array(double), "");
-  static_assert(!__is_unbounded_array(long double), "");
-  static_assert(!__is_unbounded_array(bool), "");
-  static_assert(!__is_unbounded_array(char), "");
-  static_assert(!__is_unbounded_array(signed char), "");
-  static_assert(!__is_unbounded_array(unsigned char), "");
-  static_assert(!__is_unbounded_array(wchar_t), "");
-  static_assert(!__is_unbounded_array(short), "");
-  static_assert(!__is_unbounded_array(unsigned short), "");
-  static_assert(!__is_unbounded_array(int), "");
-  static_assert(!__is_unbounded_array(unsigned int), "");
-  static_assert(!__is_unbounded_array(long), "");
-  static_assert(!__is_unbounded_array(unsigned long), "");
-  static_assert(!__is_unbounded_array(Union), "");
-  static_assert(!__is_unbounded_array(Derives), "");
-  static_assert(!__is_unbounded_array(ClassType), "");
-  static_assert(!__is_unbounded_array(Enum), "");
-  static_assert(!__is_unbounded_array(void *), "");
-  static_assert(!__is_unbounded_array(cvoid *), "");
+  static_assert(!__is_unbounded_array(IntAr));
+  static_assert(__is_unbounded_array(IntArNB));
+  static_assert(!__is_unbounded_array(UnionAr));
+
+  static_assert(!__is_unbounded_array(void));
+  static_assert(!__is_unbounded_array(cvoid));
+  static_assert(!__is_unbounded_array(float));
+  static_assert(!__is_unbounded_array(double));
+  static_assert(!__is_unbounded_array(long double));
+  static_assert(!__is_unbounded_array(bool));
+  static_assert(!__is_unbounded_array(char));
+  static_assert(!__is_unbounded_array(signed char));
+  static_assert(!__is_unbounded_array(unsigned char));
+  static_assert(!__is_unbounded_array(wchar_t));
+  static_assert(!__is_unbounded_array(short));
+  static_assert(!__is_unbounded_array(unsigned short));
+  static_assert(!__is_unbounded_array(int));
+  static_assert(!__is_unbounded_array(unsigned int));
+  static_assert(!__is_unbounded_array(long));
+  static_assert(!__is_unbounded_array(unsigned long));
+  static_assert(!__is_unbounded_array(Union));
+  static_assert(!__is_unbounded_array(Derives));
+  static_assert(!__is_unbounded_array(ClassType));
+  static_assert(!__is_unbounded_array(Enum));
+  static_assert(!__is_unbounded_array(void *));
+  static_assert(!__is_unbounded_array(cvoid *));
 
   int t32[n];
   (void)__is_unbounded_array(decltype(t32)); // expected-error{{variable length arrays are not supported for '__is_unbounded_array'}}
 }
 
 void is_referenceable() {
-  static_assert(__is_referenceable(int), "");
-  static_assert(__is_referenceable(const int), "");
-  static_assert(__is_referenceable(volatile int), "");
-  static_assert(__is_referenceable(const volatile int), "");
-  static_assert(__is_referenceable(int *), "");
-  static_assert(__is_referenceable(int &), "");
-  static_assert(__is_referenceable(int &&), "");
-  static_assert(__is_referenceable(int (*)()), "");
-  static_assert(__is_referenceable(int (&)()), "");
-  static_assert(__is_referenceable(int(&&)()), "");
-  static_assert(__is_referenceable(IntAr), "");
-  static_assert(__is_referenceable(IntArNB), "");
-  static_assert(__is_referenceable(decltype(nullptr)), "");
-  static_assert(__is_referenceable(Empty), "");
-  static_assert(__is_referenceable(Union), "");
-  static_assert(__is_referenceable(Derives), "");
-  static_assert(__is_referenceable(Enum), "");
-  static_assert(__is_referenceable(EnumClass), "");
-  static_assert(__is_referenceable(int Empty::*), "");
-  static_assert(__is_referenceable(int(Empty::*)()), "");
-  static_assert(__is_referenceable(AnIncompleteType), "");
-  static_assert(__is_referenceable(struct AnIncompleteType), "");
+  static_assert(__is_referenceable(int));
+  static_assert(__is_referenceable(const int));
+  static_assert(__is_referenceable(volatile int));
+  static_assert(__is_referenceable(const volatile int));
+  static_assert(__is_referenceable(int *));
+  static_assert(__is_referenceable(int &));
+  static_assert(__is_referenceable(int &&));
+  static_assert(__is_referenceable(int (*)()));
+  static_assert(__is_referenceable(int (&)()));
+  static_assert(__is_referenceable(int(&&)()));
+  static_assert(__is_referenceable(IntAr));
+  static_assert(__is_referenceable(IntArNB));
+  static_assert(__is_referenceable(decltype(nullptr)));
+  static_assert(__is_referenceable(Empty));
+  static_assert(__is_referenceable(Union));
+  static_assert(__is_referenceable(Derives));
+  static_assert(__is_referenceable(Enum));
+  static_assert(__is_referenceable(EnumClass));
+  static_assert(__is_referenceable(int Empty::*));
+  static_assert(__is_referenceable(int(Empty::*)()));
+  static_assert(__is_referenceable(AnIncompleteType));
+  static_assert(__is_referenceable(struct AnIncompleteType));
 
   using function_type = void(int);
-  static_assert(__is_referenceable(function_type), "");
+  static_assert(__is_referenceable(function_type));
 
-  static_assert(!__is_referenceable(void), "");
+  static_assert(!__is_referenceable(void));
 }
 
 template  void tmpl_func(T&) {}
@@ -817,152 +815,152 @@ template  struct type_wrapper {
 
 void is_function()
 {
-  int t01[T(__is_function(type_wrapper::type))];
-  int t02[T(__is_function(typeof(tmpl_func)))];
+  static_assert(__is_function(type_wrapper::type));
+  static_assert(__is_function(typeof(tmpl_func)));
 
   typedef void (*ptr_to_func_type)(void);
 
-  int t10[F(__is_function(void))];
-  int t11[F(__is_function(cvoid))];
-  int t12[F(__is_function(float))];
-  int t13[F(__is_function(double))];
-  int t14[F(__is_function(long double))];
-  int t15[F(__is_function(bool))];
-  int t16[F(__is_function(char))];
-  int t17[F(__is_function(signed char))];
-  int t18[F(__is_function(unsigned char))];
-  int t19[F(__is_function(wchar_t))];
-  int t20[F(__is_function(short))];
-  int t21[F(__is_function(unsigned short))];
-  int t22[F(__is_function(int))];
-  int t23[F(__is_function(unsigned int))];
-  int t24[F(__is_function(long))];
-  int t25[F(__is_function(unsigned long))];
-  int t26[F(__is_function(Union))];
-  int t27[F(__is_function(Derives))];
-  int t28[F(__is_function(ClassType))];
-  int t29[F(__is_function(Enum))];
-  int t30[F(__is_function(void*))];
-  int t31[F(__is_function(cvoid*))];
-  int t32[F(__is_function(void(*)()))];
-  int t33[F(__is_function(ptr_to_func_type))];
-  int t34[F(__is_function(type_wrapper::ptrtype))];
-  int t35[F(__is_function(type_wrapper::reftype))];
+  static_assert(!__is_function(void));
+  static_assert(!__is_function(cvoid));
+  static_assert(!__is_function(float));
+  static_assert(!__is_function(double));
+  static_assert(!__is_function(long double));
+  static_assert(!__is_function(bool));
+  static_assert(!__is_function(char));
+  static_assert(!__is_function(signed char));
+  static_assert(!__is_function(unsigned char));
+  static_assert(!__is_function(wchar_t));
+  static_assert(!__is_function(short));
+  static_assert(!__is_function(unsigned short));
+  static_assert(!__is_function(int));
+  static_assert(!__is_function(unsigned int));
+  static_assert(!__is_function(long));
+  static_assert(!__is_function(unsigned long));
+  static_assert(!__is_function(Union));
+  static_assert(!__is_function(Derives));
+  static_assert(!__is_function(ClassType));
+  static_assert(!__is_function(Enum));
+  static_assert(!__is_function(void*));
+  static_assert(!__is_function(cvoid*));
+  static_assert(!__is_function(void(*)()));
+  static_assert(!__is_function(ptr_to_func_type));
+  static_assert(!__is_function(type_wrapper::ptrtype));
+  static_assert(!__is_function(type_wrapper::reftype));
 }
 
 void is_reference()
 {
-  int t01[T(__is_reference(int&))];
-  int t02[T(__is_reference(const int&))];
-  int t03[T(__is_reference(void *&))];
+  static_assert(__is_reference(int&));
+  static_assert(__is_reference(const int&));
+  static_assert(__is_reference(void *&));
 
-  int t10[F(__is_reference(int))];
-  int t11[F(__is_reference(const int))];
-  int t12[F(__is_reference(void *))];
+  static_assert(!__is_reference(int));
+  static_assert(!__is_reference(const int));
+  static_assert(!__is_reference(void *));
 }
 
 void is_lvalue_reference()
 {
-  int t01[T(__is_lvalue_reference(int&))];
-  int t02[T(__is_lvalue_reference(void *&))];
-  int t03[T(__is_lvalue_reference(const int&))];
-  int t04[T(__is_lvalue_reference(void * const &))];
-
-  int t10[F(__is_lvalue_reference(int))];
-  int t11[F(__is_lvalue_reference(const int))];
-  int t12[F(__is_lvalue_reference(void *))];
+  static_assert(__is_lvalue_reference(int&));
+  static_assert(__is_lvalue_reference(void *&));
+  static_assert(__is_lvalue_reference(const int&));
+  static_assert(__is_lvalue_reference(void * const &));
+
+  static_assert(!__is_lvalue_reference(int));
+  static_assert(!__is_lvalue_reference(const int));
+  static_assert(!__is_lvalue_reference(void *));
 }
 
 #if __has_feature(cxx_rvalue_references)
 
 void is_rvalue_reference()
 {
-  int t01[T(__is_rvalue_reference(const int&&))];
-  int t02[T(__is_rvalue_reference(void * const &&))];
-
-  int t10[F(__is_rvalue_reference(int&))];
-  int t11[F(__is_rvalue_reference(void *&))];
-  int t12[F(__is_rvalue_reference(const int&))];
-  int t13[F(__is_rvalue_reference(void * const &))];
-  int t14[F(__is_rvalue_reference(int))];
-  int t15[F(__is_rvalue_reference(const int))];
-  int t16[F(__is_rvalue_reference(void *))];
+  static_assert(__is_rvalue_reference(const int&&));
+  static_assert(__is_rvalue_reference(void * const &&));
+
+  static_assert(!__is_rvalue_reference(int&));
+  static_assert(!__is_rvalue_reference(void *&));
+  static_assert(!__is_rvalue_reference(const int&));
+  static_assert(!__is_rvalue_reference(void * const &));
+  static_assert(!__is_rvalue_reference(int));
+  static_assert(!__is_rvalue_reference(const int));
+  static_assert(!__is_rvalue_reference(void *));
 }
 
 #endif
 
 void is_fundamental()
 {
-  int t01[T(__is_fundamental(float))];
-  int t02[T(__is_fundamental(double))];
-  int t03[T(__is_fundamental(long double))];
-  int t11[T(__is_fundamental(bool))];
-  int t12[T(__is_fundamental(char))];
-  int t13[T(__is_fundamental(signed char))];
-  int t14[T(__is_fundamental(unsigned char))];
-  //int t15[T(__is_fundamental(char16_t))];
-  //int t16[T(__is_fundamental(char32_t))];
-  int t17[T(__is_fundamental(wchar_t))];
-  int t18[T(__is_fundamental(short))];
-  int t19[T(__is_fundamental(unsigned short))];
-  int t20[T(__is_fundamental(int))];
-  int t21[T(__is_fundamental(unsigned int))];
-  int t22[T(__is_fundamental(long))];
-  int t23[T(__is_fundamental(unsigned long))];
-  int t24[T(__is_fundamental(void))];
-  int t25[T(__is_fundamental(cvoid))];
-  int t26[T(__is_fundamental(decltype(nullptr)))];
-
-  int t30[F(__is_fundamental(Union))];
-  int t31[F(__is_fundamental(UnionAr))];
-  int t32[F(__is_fundamental(Derives))];
-  int t33[F(__is_fundamental(ClassType))];
-  int t34[F(__is_fundamental(Enum))];
-  int t35[F(__is_fundamental(IntArNB))];
+  static_assert(__is_fundamental(float));
+  static_assert(__is_fundamental(double));
+  static_assert(__is_fundamental(long double));
+  static_assert(__is_fundamental(bool));
+  static_assert(__is_fundamental(char));
+  static_assert(__is_fundamental(signed char));
+  static_assert(__is_fundamental(unsigned char));
+  //static_assert(__is_fundamental(char16_t));
+  //static_assert(__is_fundamental(char32_t));
+  static_assert(__is_fundamental(wchar_t));
+  static_assert(__is_fundamental(short));
+  static_assert(__is_fundamental(unsigned short));
+  static_assert(__is_fundamental(int));
+  static_assert(__is_fundamental(unsigned int));
+  static_assert(__is_fundamental(long));
+  static_assert(__is_fundamental(unsigned long));
+  static_assert(__is_fundamental(void));
+  static_assert(__is_fundamental(cvoid));
+  static_assert(__is_fundamental(decltype(nullptr)));
+
+  static_assert(!__is_fundamental(Union));
+  static_assert(!__is_fundamental(UnionAr));
+  static_assert(!__is_fundamental(Derives));
+  static_assert(!__is_fundamental(ClassType));
+  static_assert(!__is_fundamental(Enum));
+  static_assert(!__is_fundamental(IntArNB));
 }
 
 void is_object()
 {
-  int t01[T(__is_object(int))];
-  int t02[T(__is_object(int *))];
-  int t03[T(__is_object(void *))];
-  int t04[T(__is_object(Union))];
-  int t05[T(__is_object(UnionAr))];
-  int t06[T(__is_object(ClassType))];
-  int t07[T(__is_object(Enum))];
-
-  int t10[F(__is_object(type_wrapper::type))];
-  int t11[F(__is_object(int&))];
-  int t12[F(__is_object(void))];
+  static_assert(__is_object(int));
+  static_assert(__is_object(int *));
+  static_assert(__is_object(void *));
+  static_assert(__is_object(Union));
+  static_assert(__is_object(UnionAr));
+  static_assert(__is_object(ClassType));
+  static_assert(__is_object(Enum));
+
+  static_assert(!__is_object(type_wrapper::type));
+  static_assert(!__is_object(int&));
+  static_assert(!__is_object(void));
 }
 
 void is_scalar()
 {
-  int t01[T(__is_scalar(float))];
-  int t02[T(__is_scalar(double))];
-  int t03[T(__is_scalar(long double))];
-  int t04[T(__is_scalar(bool))];
-  int t05[T(__is_scalar(char))];
-  int t06[T(__is_scalar(signed char))];
-  int t07[T(__is_scalar(unsigned char))];
-  int t08[T(__is_scalar(wchar_t))];
-  int t09[T(__is_scalar(short))];
-  int t10[T(__is_scalar(unsigned short))];
-  int t11[T(__is_scalar(int))];
-  int t12[T(__is_scalar(unsigned int))];
-  int t13[T(__is_scalar(long))];
-  int t14[T(__is_scalar(unsigned long))];
-  int t15[T(__is_scalar(Enum))];
-  int t16[T(__is_scalar(void*))];
-  int t17[T(__is_scalar(cvoid*))];
-
-  int t20[F(__is_scalar(void))];
-  int t21[F(__is_scalar(cvoid))];
-  int t22[F(__is_scalar(Union))];
-  int t23[F(__is_scalar(UnionAr))];
-  int t24[F(__is_scalar(Derives))];
-  int t25[F(__is_scalar(ClassType))];
-  int t26[F(__is_scalar(IntArNB))];
+  static_assert(__is_scalar(float));
+  static_assert(__is_scalar(double));
+  static_assert(__is_scalar(long double));
+  static_assert(__is_scalar(bool));
+  static_assert(__is_scalar(char));
+  static_assert(__is_scalar(signed char));
+  static_assert(__is_scalar(unsigned char));
+  static_assert(__is_scalar(wchar_t));
+  static_assert(__is_scalar(short));
+  static_assert(__is_scalar(unsigned short));
+  static_assert(__is_scalar(int));
+  static_assert(__is_scalar(unsigned int));
+  static_assert(__is_scalar(long));
+  static_assert(__is_scalar(unsigned long));
+  static_assert(__is_scalar(Enum));
+  static_assert(__is_scalar(void*));
+  static_assert(__is_scalar(cvoid*));
+
+  static_assert(!__is_scalar(void));
+  static_assert(!__is_scalar(cvoid));
+  static_assert(!__is_scalar(Union));
+  static_assert(!__is_scalar(UnionAr));
+  static_assert(!__is_scalar(Derives));
+  static_assert(!__is_scalar(ClassType));
+  static_assert(!__is_scalar(IntArNB));
 }
 
 struct StructWithMembers {
@@ -972,314 +970,314 @@ struct StructWithMembers {
 
 void is_compound()
 {
-  int t01[T(__is_compound(void*))];
-  int t02[T(__is_compound(cvoid*))];
-  int t03[T(__is_compound(void (*)()))];
-  int t04[T(__is_compound(int StructWithMembers::*))];
-  int t05[T(__is_compound(void (StructWithMembers::*)()))];
-  int t06[T(__is_compound(int&))];
-  int t07[T(__is_compound(Union))];
-  int t08[T(__is_compound(UnionAr))];
-  int t09[T(__is_compound(Derives))];
-  int t10[T(__is_compound(ClassType))];
-  int t11[T(__is_compound(IntArNB))];
-  int t12[T(__is_compound(Enum))];
-
-  int t20[F(__is_compound(float))];
-  int t21[F(__is_compound(double))];
-  int t22[F(__is_compound(long double))];
-  int t23[F(__is_compound(bool))];
-  int t24[F(__is_compound(char))];
-  int t25[F(__is_compound(signed char))];
-  int t26[F(__is_compound(unsigned char))];
-  int t27[F(__is_compound(wchar_t))];
-  int t28[F(__is_compound(short))];
-  int t29[F(__is_compound(unsigned short))];
-  int t30[F(__is_compound(int))];
-  int t31[F(__is_compound(unsigned int))];
-  int t32[F(__is_compound(long))];
-  int t33[F(__is_compound(unsigned long))];
-  int t34[F(__is_compound(void))];
-  int t35[F(__is_compound(cvoid))];
+  static_assert(__is_compound(void*));
+  static_assert(__is_compound(cvoid*));
+  static_assert(__is_compound(void (*)()));
+  static_assert(__is_compound(int StructWithMembers::*));
+  static_assert(__is_compound(void (StructWithMembers::*)()));
+  static_assert(__is_compound(int&));
+  static_assert(__is_compound(Union));
+  static_assert(__is_compound(UnionAr));
+  static_assert(__is_compound(Derives));
+  static_assert(__is_compound(ClassType));
+  static_assert(__is_compound(IntArNB));
+  static_assert(__is_compound(Enum));
+
+  static_assert(!__is_compound(float));
+  static_assert(!__is_compound(double));
+  static_assert(!__is_compound(long double));
+  static_assert(!__is_compound(bool));
+  static_assert(!__is_compound(char));
+  static_assert(!__is_compound(signed char));
+  static_assert(!__is_compound(unsigned char));
+  static_assert(!__is_compound(wchar_t));
+  static_assert(!__is_compound(short));
+  static_assert(!__is_compound(unsigned short));
+  static_assert(!__is_compound(int));
+  static_assert(!__is_compound(unsigned int));
+  static_assert(!__is_compound(long));
+  static_assert(!__is_compound(unsigned long));
+  static_assert(!__is_compound(void));
+  static_assert(!__is_compound(cvoid));
 }
 
 void is_pointer()
 {
   StructWithMembers x;
 
-  int t01[T(__is_pointer(void*))];
-  int t02[T(__is_pointer(cvoid*))];
-  int t03[T(__is_pointer(cvoid*))];
-  int t04[T(__is_pointer(char*))];
-  int t05[T(__is_pointer(int*))];
-  int t06[T(__is_pointer(int**))];
-  int t07[T(__is_pointer(ClassType*))];
-  int t08[T(__is_pointer(Derives*))];
-  int t09[T(__is_pointer(Enum*))];
-  int t10[T(__is_pointer(IntArNB*))];
-  int t11[T(__is_pointer(Union*))];
-  int t12[T(__is_pointer(UnionAr*))];
-  int t13[T(__is_pointer(StructWithMembers*))];
-  int t14[T(__is_pointer(void (*)()))];
-
-  int t20[F(__is_pointer(void))];
-  int t21[F(__is_pointer(cvoid))];
-  int t22[F(__is_pointer(cvoid))];
-  int t23[F(__is_pointer(char))];
-  int t24[F(__is_pointer(int))];
-  int t25[F(__is_pointer(int))];
-  int t26[F(__is_pointer(ClassType))];
-  int t27[F(__is_pointer(Derives))];
-  int t28[F(__is_pointer(Enum))];
-  int t29[F(__is_pointer(IntArNB))];
-  int t30[F(__is_pointer(Union))];
-  int t31[F(__is_pointer(UnionAr))];
-  int t32[F(__is_pointer(StructWithMembers))];
-  int t33[F(__is_pointer(int StructWithMembers::*))];
-  int t34[F(__is_pointer(void (StructWithMembers::*) ()))];
+  static_assert(__is_pointer(void*));
+  static_assert(__is_pointer(cvoid*));
+  static_assert(__is_pointer(cvoid*));
+  static_assert(__is_pointer(char*));
+  static_assert(__is_pointer(int*));
+  static_assert(__is_pointer(int**));
+  static_assert(__is_pointer(ClassType*));
+  static_assert(__is_pointer(Derives*));
+  static_assert(__is_pointer(Enum*));
+  static_assert(__is_pointer(IntArNB*));
+  static_assert(__is_pointer(Union*));
+  static_assert(__is_pointer(UnionAr*));
+  static_assert(__is_pointer(StructWithMembers*));
+  static_assert(__is_pointer(void (*)()));
+
+  static_assert(!__is_pointer(void));
+  static_assert(!__is_pointer(cvoid));
+  static_assert(!__is_pointer(cvoid));
+  static_assert(!__is_pointer(char));
+  static_assert(!__is_pointer(int));
+  static_assert(!__is_pointer(int));
+  static_assert(!__is_pointer(ClassType));
+  static_assert(!__is_pointer(Derives));
+  static_assert(!__is_pointer(Enum));
+  static_assert(!__is_pointer(IntArNB));
+  static_assert(!__is_pointer(Union));
+  static_assert(!__is_pointer(UnionAr));
+  static_assert(!__is_pointer(StructWithMembers));
+  static_assert(!__is_pointer(int StructWithMembers::*));
+  static_assert(!__is_pointer(void (StructWithMembers::*) ()));
 }
 
 void is_null_pointer() {
   StructWithMembers x;
 
-  static_assert(__is_nullptr(decltype(nullptr)), "");
-  static_assert(!__is_nullptr(void *), "");
-  static_assert(!__is_nullptr(cvoid *), "");
-  static_assert(!__is_nullptr(cvoid *), "");
-  static_assert(!__is_nullptr(char *), "");
-  static_assert(!__is_nullptr(int *), "");
-  static_assert(!__is_nullptr(int **), "");
-  static_assert(!__is_nullptr(ClassType *), "");
-  static_assert(!__is_nullptr(Derives *), "");
-  static_assert(!__is_nullptr(Enum *), "");
-  static_assert(!__is_nullptr(IntArNB *), "");
-  static_assert(!__is_nullptr(Union *), "");
-  static_assert(!__is_nullptr(UnionAr *), "");
-  static_assert(!__is_nullptr(StructWithMembers *), "");
-  static_assert(!__is_nullptr(void (*)()), "");
-
-  static_assert(!__is_nullptr(void), "");
-  static_assert(!__is_nullptr(cvoid), "");
-  static_assert(!__is_nullptr(cvoid), "");
-  static_assert(!__is_nullptr(char), "");
-  static_assert(!__is_nullptr(int), "");
-  static_assert(!__is_nullptr(int), "");
-  static_assert(!__is_nullptr(ClassType), "");
-  static_assert(!__is_nullptr(Derives), "");
-  static_assert(!__is_nullptr(Enum), "");
-  static_assert(!__is_nullptr(IntArNB), "");
-  static_assert(!__is_nullptr(Union), "");
-  static_assert(!__is_nullptr(UnionAr), "");
-  static_assert(!__is_nullptr(StructWithMembers), "");
-  static_assert(!__is_nullptr(int StructWithMembers::*), "");
-  static_assert(!__is_nullptr(void(StructWithMembers::*)()), "");
+  static_assert(__is_nullptr(decltype(nullptr)));
+  static_assert(!__is_nullptr(void *));
+  static_assert(!__is_nullptr(cvoid *));
+  static_assert(!__is_nullptr(cvoid *));
+  static_assert(!__is_nullptr(char *));
+  static_assert(!__is_nullptr(int *));
+  static_assert(!__is_nullptr(int **));
+  static_assert(!__is_nullptr(ClassType *));
+  static_assert(!__is_nullptr(Derives *));
+  static_assert(!__is_nullptr(Enum *));
+  static_assert(!__is_nullptr(IntArNB *));
+  static_assert(!__is_nullptr(Union *));
+  static_assert(!__is_nullptr(UnionAr *));
+  static_assert(!__is_nullptr(StructWithMembers *));
+  static_assert(!__is_nullptr(void (*)()));
+
+  static_assert(!__is_nullptr(void));
+  static_assert(!__is_nullptr(cvoid));
+  static_assert(!__is_nullptr(cvoid));
+  static_assert(!__is_nullptr(char));
+  static_assert(!__is_nullptr(int));
+  static_assert(!__is_nullptr(int));
+  static_assert(!__is_nullptr(ClassType));
+  static_assert(!__is_nullptr(Derives));
+  static_assert(!__is_nullptr(Enum));
+  static_assert(!__is_nullptr(IntArNB));
+  static_assert(!__is_nullptr(Union));
+  static_assert(!__is_nullptr(UnionAr));
+  static_assert(!__is_nullptr(StructWithMembers));
+  static_assert(!__is_nullptr(int StructWithMembers::*));
+  static_assert(!__is_nullptr(void(StructWithMembers::*)()));
 }
 
 void is_member_object_pointer()
 {
   StructWithMembers x;
 
-  int t01[T(__is_member_object_pointer(int StructWithMembers::*))];
-
-  int t10[F(__is_member_object_pointer(void (StructWithMembers::*) ()))];
-  int t11[F(__is_member_object_pointer(void*))];
-  int t12[F(__is_member_object_pointer(cvoid*))];
-  int t13[F(__is_member_object_pointer(cvoid*))];
-  int t14[F(__is_member_object_pointer(char*))];
-  int t15[F(__is_member_object_pointer(int*))];
-  int t16[F(__is_member_object_pointer(int**))];
-  int t17[F(__is_member_object_pointer(ClassType*))];
-  int t18[F(__is_member_object_pointer(Derives*))];
-  int t19[F(__is_member_object_pointer(Enum*))];
-  int t20[F(__is_member_object_pointer(IntArNB*))];
-  int t21[F(__is_member_object_pointer(Union*))];
-  int t22[F(__is_member_object_pointer(UnionAr*))];
-  int t23[F(__is_member_object_pointer(StructWithMembers*))];
-  int t24[F(__is_member_object_pointer(void))];
-  int t25[F(__is_member_object_pointer(cvoid))];
-  int t26[F(__is_member_object_pointer(cvoid))];
-  int t27[F(__is_member_object_pointer(char))];
-  int t28[F(__is_member_object_pointer(int))];
-  int t29[F(__is_member_object_pointer(int))];
-  int t30[F(__is_member_object_pointer(ClassType))];
-  int t31[F(__is_member_object_pointer(Derives))];
-  int t32[F(__is_member_object_pointer(Enum))];
-  int t33[F(__is_member_object_pointer(IntArNB))];
-  int t34[F(__is_member_object_pointer(Union))];
-  int t35[F(__is_member_object_pointer(UnionAr))];
-  int t36[F(__is_member_object_pointer(StructWithMembers))];
-  int t37[F(__is_member_object_pointer(void (*)()))];
+  static_assert(__is_member_object_pointer(int StructWithMembers::*));
+
+  static_assert(!__is_member_object_pointer(void (StructWithMembers::*) ()));
+  static_assert(!__is_member_object_pointer(void*));
+  static_assert(!__is_member_object_pointer(cvoid*));
+  static_assert(!__is_member_object_pointer(cvoid*));
+  static_assert(!__is_member_object_pointer(char*));
+  static_assert(!__is_member_object_pointer(int*));
+  static_assert(!__is_member_object_pointer(int**));
+  static_assert(!__is_member_object_pointer(ClassType*));
+  static_assert(!__is_member_object_pointer(Derives*));
+  static_assert(!__is_member_object_pointer(Enum*));
+  static_assert(!__is_member_object_pointer(IntArNB*));
+  static_assert(!__is_member_object_pointer(Union*));
+  static_assert(!__is_member_object_pointer(UnionAr*));
+  static_assert(!__is_member_object_pointer(StructWithMembers*));
+  static_assert(!__is_member_object_pointer(void));
+  static_assert(!__is_member_object_pointer(cvoid));
+  static_assert(!__is_member_object_pointer(cvoid));
+  static_assert(!__is_member_object_pointer(char));
+  static_assert(!__is_member_object_pointer(int));
+  static_assert(!__is_member_object_pointer(int));
+  static_assert(!__is_member_object_pointer(ClassType));
+  static_assert(!__is_member_object_pointer(Derives));
+  static_assert(!__is_member_object_pointer(Enum));
+  static_assert(!__is_member_object_pointer(IntArNB));
+  static_assert(!__is_member_object_pointer(Union));
+  static_assert(!__is_member_object_pointer(UnionAr));
+  static_assert(!__is_member_object_pointer(StructWithMembers));
+  static_assert(!__is_member_object_pointer(void (*)()));
 }
 
 void is_member_function_pointer()
 {
   StructWithMembers x;
 
-  int t01[T(__is_member_function_pointer(void (StructWithMembers::*) ()))];
-
-  int t10[F(__is_member_function_pointer(int StructWithMembers::*))];
-  int t11[F(__is_member_function_pointer(void*))];
-  int t12[F(__is_member_function_pointer(cvoid*))];
-  int t13[F(__is_member_function_pointer(cvoid*))];
-  int t14[F(__is_member_function_pointer(char*))];
-  int t15[F(__is_member_function_pointer(int*))];
-  int t16[F(__is_member_function_pointer(int**))];
-  int t17[F(__is_member_function_pointer(ClassType*))];
-  int t18[F(__is_member_function_pointer(Derives*))];
-  int t19[F(__is_member_function_pointer(Enum*))];
-  int t20[F(__is_member_function_pointer(IntArNB*))];
-  int t21[F(__is_member_function_pointer(Union*))];
-  int t22[F(__is_member_function_pointer(UnionAr*))];
-  int t23[F(__is_member_function_pointer(StructWithMembers*))];
-  int t24[F(__is_member_function_pointer(void))];
-  int t25[F(__is_member_function_pointer(cvoid))];
-  int t26[F(__is_member_function_pointer(cvoid))];
-  int t27[F(__is_member_function_pointer(char))];
-  int t28[F(__is_member_function_pointer(int))];
-  int t29[F(__is_member_function_pointer(int))];
-  int t30[F(__is_member_function_pointer(ClassType))];
-  int t31[F(__is_member_function_pointer(Derives))];
-  int t32[F(__is_member_function_pointer(Enum))];
-  int t33[F(__is_member_function_pointer(IntArNB))];
-  int t34[F(__is_member_function_pointer(Union))];
-  int t35[F(__is_member_function_pointer(UnionAr))];
-  int t36[F(__is_member_function_pointer(StructWithMembers))];
-  int t37[F(__is_member_function_pointer(void (*)()))];
+  static_assert(__is_member_function_pointer(void (StructWithMembers::*) ()));
+
+  static_assert(!__is_member_function_pointer(int StructWithMembers::*));
+  static_assert(!__is_member_function_pointer(void*));
+  static_assert(!__is_member_function_pointer(cvoid*));
+  static_assert(!__is_member_function_pointer(cvoid*));
+  static_assert(!__is_member_function_pointer(char*));
+  static_assert(!__is_member_function_pointer(int*));
+  static_assert(!__is_member_function_pointer(int**));
+  static_assert(!__is_member_function_pointer(ClassType*));
+  static_assert(!__is_member_function_pointer(Derives*));
+  static_assert(!__is_member_function_pointer(Enum*));
+  static_assert(!__is_member_function_pointer(IntArNB*));
+  static_assert(!__is_member_function_pointer(Union*));
+  static_assert(!__is_member_function_pointer(UnionAr*));
+  static_assert(!__is_member_function_pointer(StructWithMembers*));
+  static_assert(!__is_member_function_pointer(void));
+  static_assert(!__is_member_function_pointer(cvoid));
+  static_assert(!__is_member_function_pointer(cvoid));
+  static_assert(!__is_member_function_pointer(char));
+  static_assert(!__is_member_function_pointer(int));
+  static_assert(!__is_member_function_pointer(int));
+  static_assert(!__is_member_function_pointer(ClassType));
+  static_assert(!__is_member_function_pointer(Derives));
+  static_assert(!__is_member_function_pointer(Enum));
+  static_assert(!__is_member_function_pointer(IntArNB));
+  static_assert(!__is_member_function_pointer(Union));
+  static_assert(!__is_member_function_pointer(UnionAr));
+  static_assert(!__is_member_function_pointer(StructWithMembers));
+  static_assert(!__is_member_function_pointer(void (*)()));
 }
 
 void is_member_pointer()
 {
   StructWithMembers x;
 
-  int t01[T(__is_member_pointer(int StructWithMembers::*))];
-  int t02[T(__is_member_pointer(void (StructWithMembers::*) ()))];
-
-  int t10[F(__is_member_pointer(void*))];
-  int t11[F(__is_member_pointer(cvoid*))];
-  int t12[F(__is_member_pointer(cvoid*))];
-  int t13[F(__is_member_pointer(char*))];
-  int t14[F(__is_member_pointer(int*))];
-  int t15[F(__is_member_pointer(int**))];
-  int t16[F(__is_member_pointer(ClassType*))];
-  int t17[F(__is_member_pointer(Derives*))];
-  int t18[F(__is_member_pointer(Enum*))];
-  int t19[F(__is_member_pointer(IntArNB*))];
-  int t20[F(__is_member_pointer(Union*))];
-  int t21[F(__is_member_pointer(UnionAr*))];
-  int t22[F(__is_member_pointer(StructWithMembers*))];
-  int t23[F(__is_member_pointer(void))];
-  int t24[F(__is_member_pointer(cvoid))];
-  int t25[F(__is_member_pointer(cvoid))];
-  int t26[F(__is_member_pointer(char))];
-  int t27[F(__is_member_pointer(int))];
-  int t28[F(__is_member_pointer(int))];
-  int t29[F(__is_member_pointer(ClassType))];
-  int t30[F(__is_member_pointer(Derives))];
-  int t31[F(__is_member_pointer(Enum))];
-  int t32[F(__is_member_pointer(IntArNB))];
-  int t33[F(__is_member_pointer(Union))];
-  int t34[F(__is_member_pointer(UnionAr))];
-  int t35[F(__is_member_pointer(StructWithMembers))];
-  int t36[F(__is_member_pointer(void (*)()))];
+  static_assert(__is_member_pointer(int StructWithMembers::*));
+  static_assert(__is_member_pointer(void (StructWithMembers::*) ()));
+
+  static_assert(!__is_member_pointer(void*));
+  static_assert(!__is_member_pointer(cvoid*));
+  static_assert(!__is_member_pointer(cvoid*));
+  static_assert(!__is_member_pointer(char*));
+  static_assert(!__is_member_pointer(int*));
+  static_assert(!__is_member_pointer(int**));
+  static_assert(!__is_member_pointer(ClassType*));
+  static_assert(!__is_member_pointer(Derives*));
+  static_assert(!__is_member_pointer(Enum*));
+  static_assert(!__is_member_pointer(IntArNB*));
+  static_assert(!__is_member_pointer(Union*));
+  static_assert(!__is_member_pointer(UnionAr*));
+  static_assert(!__is_member_pointer(StructWithMembers*));
+  static_assert(!__is_member_pointer(void));
+  static_assert(!__is_member_pointer(cvoid));
+  static_assert(!__is_member_pointer(cvoid));
+  static_assert(!__is_member_pointer(char));
+  static_assert(!__is_member_pointer(int));
+  static_assert(!__is_member_pointer(int));
+  static_assert(!__is_member_pointer(ClassType));
+  static_assert(!__is_member_pointer(Derives));
+  static_assert(!__is_member_pointer(Enum));
+  static_assert(!__is_member_pointer(IntArNB));
+  static_assert(!__is_member_pointer(Union));
+  static_assert(!__is_member_pointer(UnionAr));
+  static_assert(!__is_member_pointer(StructWithMembers));
+  static_assert(!__is_member_pointer(void (*)()));
 }
 
 void is_const()
 {
-  int t01[T(__is_const(cvoid))];
-  int t02[T(__is_const(const char))];
-  int t03[T(__is_const(const int))];
-  int t04[T(__is_const(const long))];
-  int t05[T(__is_const(const short))];
-  int t06[T(__is_const(const signed char))];
-  int t07[T(__is_const(const wchar_t))];
-  int t08[T(__is_const(const bool))];
-  int t09[T(__is_const(const float))];
-  int t10[T(__is_const(const double))];
-  int t11[T(__is_const(const long double))];
-  int t12[T(__is_const(const unsigned char))];
-  int t13[T(__is_const(const unsigned int))];
-  int t14[T(__is_const(const unsigned long long))];
-  int t15[T(__is_const(const unsigned long))];
-  int t16[T(__is_const(const unsigned short))];
-  int t17[T(__is_const(const void))];
-  int t18[T(__is_const(const ClassType))];
-  int t19[T(__is_const(const Derives))];
-  int t20[T(__is_const(const Enum))];
-  int t21[T(__is_const(const IntArNB))];
-  int t22[T(__is_const(const Union))];
-  int t23[T(__is_const(const UnionAr))];
-
-  int t30[F(__is_const(char))];
-  int t31[F(__is_const(int))];
-  int t32[F(__is_const(long))];
-  int t33[F(__is_const(short))];
-  int t34[F(__is_const(signed char))];
-  int t35[F(__is_const(wchar_t))];
-  int t36[F(__is_const(bool))];
-  int t37[F(__is_const(float))];
-  int t38[F(__is_const(double))];
-  int t39[F(__is_const(long double))];
-  int t40[F(__is_const(unsigned char))];
-  int t41[F(__is_const(unsigned int))];
-  int t42[F(__is_const(unsigned long long))];
-  int t43[F(__is_const(unsigned long))];
-  int t44[F(__is_const(unsigned short))];
-  int t45[F(__is_const(void))];
-  int t46[F(__is_const(ClassType))];
-  int t47[F(__is_const(Derives))];
-  int t48[F(__is_const(Enum))];
-  int t49[F(__is_const(IntArNB))];
-  int t50[F(__is_const(Union))];
-  int t51[F(__is_const(UnionAr))];
+  static_assert(__is_const(cvoid));
+  static_assert(__is_const(const char));
+  static_assert(__is_const(const int));
+  static_assert(__is_const(const long));
+  static_assert(__is_const(const short));
+  static_assert(__is_const(const signed char));
+  static_assert(__is_const(const wchar_t));
+  static_assert(__is_const(const bool));
+  static_assert(__is_const(const float));
+  static_assert(__is_const(const double));
+  static_assert(__is_const(const long double));
+  static_assert(__is_const(const unsigned char));
+  static_assert(__is_const(const unsigned int));
+  static_assert(__is_const(const unsigned long long));
+  static_assert(__is_const(const unsigned long));
+  static_assert(__is_const(const unsigned short));
+  static_assert(__is_const(const void));
+  static_assert(__is_const(const ClassType));
+  static_assert(__is_const(const Derives));
+  static_assert(__is_const(const Enum));
+  static_assert(__is_const(const IntArNB));
+  static_assert(__is_const(const Union));
+  static_assert(__is_const(const UnionAr));
+
+  static_assert(!__is_const(char));
+  static_assert(!__is_const(int));
+  static_assert(!__is_const(long));
+  static_assert(!__is_const(short));
+  static_assert(!__is_const(signed char));
+  static_assert(!__is_const(wchar_t));
+  static_assert(!__is_const(bool));
+  static_assert(!__is_const(float));
+  static_assert(!__is_const(double));
+  static_assert(!__is_const(long double));
+  static_assert(!__is_const(unsigned char));
+  static_assert(!__is_const(unsigned int));
+  static_assert(!__is_const(unsigned long long));
+  static_assert(!__is_const(unsigned long));
+  static_assert(!__is_const(unsigned short));
+  static_assert(!__is_const(void));
+  static_assert(!__is_const(ClassType));
+  static_assert(!__is_const(Derives));
+  static_assert(!__is_const(Enum));
+  static_assert(!__is_const(IntArNB));
+  static_assert(!__is_const(Union));
+  static_assert(!__is_const(UnionAr));
 }
 
 void is_volatile()
 {
-  int t02[T(__is_volatile(volatile char))];
-  int t03[T(__is_volatile(volatile int))];
-  int t04[T(__is_volatile(volatile long))];
-  int t05[T(__is_volatile(volatile short))];
-  int t06[T(__is_volatile(volatile signed char))];
-  int t07[T(__is_volatile(volatile wchar_t))];
-  int t08[T(__is_volatile(volatile bool))];
-  int t09[T(__is_volatile(volatile float))];
-  int t10[T(__is_volatile(volatile double))];
-  int t11[T(__is_volatile(volatile long double))];
-  int t12[T(__is_volatile(volatile unsigned char))];
-  int t13[T(__is_volatile(volatile unsigned int))];
-  int t14[T(__is_volatile(volatile unsigned long long))];
-  int t15[T(__is_volatile(volatile unsigned long))];
-  int t16[T(__is_volatile(volatile unsigned short))];
-  int t17[T(__is_volatile(volatile void))];
-  int t18[T(__is_volatile(volatile ClassType))];
-  int t19[T(__is_volatile(volatile Derives))];
-  int t20[T(__is_volatile(volatile Enum))];
-  int t21[T(__is_volatile(volatile IntArNB))];
-  int t22[T(__is_volatile(volatile Union))];
-  int t23[T(__is_volatile(volatile UnionAr))];
-
-  int t30[F(__is_volatile(char))];
-  int t31[F(__is_volatile(int))];
-  int t32[F(__is_volatile(long))];
-  int t33[F(__is_volatile(short))];
-  int t34[F(__is_volatile(signed char))];
-  int t35[F(__is_volatile(wchar_t))];
-  int t36[F(__is_volatile(bool))];
-  int t37[F(__is_volatile(float))];
-  int t38[F(__is_volatile(double))];
-  int t39[F(__is_volatile(long double))];
-  int t40[F(__is_volatile(unsigned char))];
-  int t41[F(__is_volatile(unsigned int))];
-  int t42[F(__is_volatile(unsigned long long))];
-  int t43[F(__is_volatile(unsigned long))];
-  int t44[F(__is_volatile(unsigned short))];
-  int t45[F(__is_volatile(void))];
-  int t46[F(__is_volatile(ClassType))];
-  int t47[F(__is_volatile(Derives))];
-  int t48[F(__is_volatile(Enum))];
-  int t49[F(__is_volatile(IntArNB))];
-  int t50[F(__is_volatile(Union))];
-  int t51[F(__is_volatile(UnionAr))];
+  static_assert(__is_volatile(volatile char));
+  static_assert(__is_volatile(volatile int));
+  static_assert(__is_volatile(volatile long));
+  static_assert(__is_volatile(volatile short));
+  static_assert(__is_volatile(volatile signed char));
+  static_assert(__is_volatile(volatile wchar_t));
+  static_assert(__is_volatile(volatile bool));
+  static_assert(__is_volatile(volatile float));
+  static_assert(__is_volatile(volatile double));
+  static_assert(__is_volatile(volatile long double));
+  static_assert(__is_volatile(volatile unsigned char));
+  static_assert(__is_volatile(volatile unsigned int));
+  static_assert(__is_volatile(volatile unsigned long long));
+  static_assert(__is_volatile(volatile unsigned long));
+  static_assert(__is_volatile(volatile unsigned short));
+  static_assert(__is_volatile(volatile void));
+  static_assert(__is_volatile(volatile ClassType));
+  static_assert(__is_volatile(volatile Derives));
+  static_assert(__is_volatile(volatile Enum));
+  static_assert(__is_volatile(volatile IntArNB));
+  static_assert(__is_volatile(volatile Union));
+  static_assert(__is_volatile(volatile UnionAr));
+
+  static_assert(!__is_volatile(char));
+  static_assert(!__is_volatile(int));
+  static_assert(!__is_volatile(long));
+  static_assert(!__is_volatile(short));
+  static_assert(!__is_volatile(signed char));
+  static_assert(!__is_volatile(wchar_t));
+  static_assert(!__is_volatile(bool));
+  static_assert(!__is_volatile(float));
+  static_assert(!__is_volatile(double));
+  static_assert(!__is_volatile(long double));
+  static_assert(!__is_volatile(unsigned char));
+  static_assert(!__is_volatile(unsigned int));
+  static_assert(!__is_volatile(unsigned long long));
+  static_assert(!__is_volatile(unsigned long));
+  static_assert(!__is_volatile(unsigned short));
+  static_assert(!__is_volatile(void));
+  static_assert(!__is_volatile(ClassType));
+  static_assert(!__is_volatile(Derives));
+  static_assert(!__is_volatile(Enum));
+  static_assert(!__is_volatile(IntArNB));
+  static_assert(!__is_volatile(Union));
+  static_assert(!__is_volatile(UnionAr));
 }
 
 struct TrivialStruct {
@@ -1352,87 +1350,87 @@ ExtDefaulted::~ExtDefaulted() = default;
 
 void is_trivial2()
 {
-  int t01[T(__is_trivial(char))];
-  int t02[T(__is_trivial(int))];
-  int t03[T(__is_trivial(long))];
-  int t04[T(__is_trivial(short))];
-  int t05[T(__is_trivial(signed char))];
-  int t06[T(__is_trivial(wchar_t))];
-  int t07[T(__is_trivial(bool))];
-  int t08[T(__is_trivial(float))];
-  int t09[T(__is_trivial(double))];
-  int t10[T(__is_trivial(long double))];
-  int t11[T(__is_trivial(unsigned char))];
-  int t12[T(__is_trivial(unsigned int))];
-  int t13[T(__is_trivial(unsigned long long))];
-  int t14[T(__is_trivial(unsigned long))];
-  int t15[T(__is_trivial(unsigned short))];
-  int t16[T(__is_trivial(ClassType))];
-  int t17[T(__is_trivial(Derives))];
-  int t18[T(__is_trivial(Enum))];
-  int t19[T(__is_trivial(IntAr))];
-  int t20[T(__is_trivial(Union))];
-  int t21[T(__is_trivial(UnionAr))];
-  int t22[T(__is_trivial(TrivialStruct))];
-  int t23[T(__is_trivial(AllDefaulted))];
-  int t24[T(__is_trivial(AllDeleted))];
-
-  int t30[F(__is_trivial(void))];
-  int t31[F(__is_trivial(NonTrivialStruct))];
-  int t32[F(__is_trivial(SuperNonTrivialStruct))];
-  int t33[F(__is_trivial(NonTCStruct))];
-  int t34[F(__is_trivial(ExtDefaulted))];
-
-  int t40[T(__is_trivial(ACompleteType))];
-  int t41[F(__is_trivial(AnIncompleteType))]; // expected-error {{incomplete type}}
-  int t42[F(__is_trivial(AnIncompleteType[]))]; // expected-error {{incomplete type}}
-  int t43[F(__is_trivial(AnIncompleteType[1]))]; // expected-error {{incomplete type}}
-  int t44[F(__is_trivial(void))];
-  int t45[F(__is_trivial(const volatile void))];
+  static_assert(__is_trivial(char));
+  static_assert(__is_trivial(int));
+  static_assert(__is_trivial(long));
+  static_assert(__is_trivial(short));
+  static_assert(__is_trivial(signed char));
+  static_assert(__is_trivial(wchar_t));
+  static_assert(__is_trivial(bool));
+  static_assert(__is_trivial(float));
+  static_assert(__is_trivial(double));
+  static_assert(__is_trivial(long double));
+  static_assert(__is_trivial(unsigned char));
+  static_assert(__is_trivial(unsigned int));
+  static_assert(__is_trivial(unsigned long long));
+  static_assert(__is_trivial(unsigned long));
+  static_assert(__is_trivial(unsigned short));
+  static_assert(__is_trivial(ClassType));
+  static_assert(__is_trivial(Derives));
+  static_assert(__is_trivial(Enum));
+  static_assert(__is_trivial(IntAr));
+  static_assert(__is_trivial(Union));
+  static_assert(__is_trivial(UnionAr));
+  static_assert(__is_trivial(TrivialStruct));
+  static_assert(__is_trivial(AllDefaulted));
+  static_assert(__is_trivial(AllDeleted));
+
+  static_assert(!__is_trivial(void));
+  static_assert(!__is_trivial(NonTrivialStruct));
+  static_assert(!__is_trivial(SuperNonTrivialStruct));
+  static_assert(!__is_trivial(NonTCStruct));
+  static_assert(!__is_trivial(ExtDefaulted));
+
+  static_assert(__is_trivial(ACompleteType));
+  static_assert(!__is_trivial(AnIncompleteType)); // expected-error {{incomplete type}}
+  static_assert(!__is_trivial(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(!__is_trivial(AnIncompleteType[1])); // expected-error {{incomplete type}}
+  static_assert(!__is_trivial(void));
+  static_assert(!__is_trivial(const volatile void));
 }
 
 void is_trivially_copyable2()
 {
-  int t01[T(__is_trivially_copyable(char))];
-  int t02[T(__is_trivially_copyable(int))];
-  int t03[T(__is_trivially_copyable(long))];
-  int t04[T(__is_trivially_copyable(short))];
-  int t05[T(__is_trivially_copyable(signed char))];
-  int t06[T(__is_trivially_copyable(wchar_t))];
-  int t07[T(__is_trivially_copyable(bool))];
-  int t08[T(__is_trivially_copyable(float))];
-  int t09[T(__is_trivially_copyable(double))];
-  int t10[T(__is_trivially_copyable(long double))];
-  int t11[T(__is_trivially_copyable(unsigned char))];
-  int t12[T(__is_trivially_copyable(unsigned int))];
-  int t13[T(__is_trivially_copyable(unsigned long long))];
-  int t14[T(__is_trivially_copyable(unsigned long))];
-  int t15[T(__is_trivially_copyable(unsigned short))];
-  int t16[T(__is_trivially_copyable(ClassType))];
-  int t17[T(__is_trivially_copyable(Derives))];
-  int t18[T(__is_trivially_copyable(Enum))];
-  int t19[T(__is_trivially_copyable(IntAr))];
-  int t20[T(__is_trivially_copyable(Union))];
-  int t21[T(__is_trivially_copyable(UnionAr))];
-  int t22[T(__is_trivially_copyable(TrivialStruct))];
-  int t23[T(__is_trivially_copyable(NonTrivialStruct))];
-  int t24[T(__is_trivially_copyable(AllDefaulted))];
-  int t25[T(__is_trivially_copyable(AllDeleted))];
-
-  int t30[F(__is_trivially_copyable(void))];
-  int t31[F(__is_trivially_copyable(SuperNonTrivialStruct))];
-  int t32[F(__is_trivially_copyable(NonTCStruct))];
-  int t33[F(__is_trivially_copyable(ExtDefaulted))];
-
-  int t34[T(__is_trivially_copyable(const int))];
-  int t35[T(__is_trivially_copyable(volatile int))];
-
-  int t40[T(__is_trivially_copyable(ACompleteType))];
-  int t41[F(__is_trivially_copyable(AnIncompleteType))]; // expected-error {{incomplete type}}
-  int t42[F(__is_trivially_copyable(AnIncompleteType[]))]; // expected-error {{incomplete type}}
-  int t43[F(__is_trivially_copyable(AnIncompleteType[1]))]; // expected-error {{incomplete type}}
-  int t44[F(__is_trivially_copyable(void))];
-  int t45[F(__is_trivially_copyable(const volatile void))];
+  static_assert(__is_trivially_copyable(char));
+  static_assert(__is_trivially_copyable(int));
+  static_assert(__is_trivially_copyable(long));
+  static_assert(__is_trivially_copyable(short));
+  static_assert(__is_trivially_copyable(signed char));
+  static_assert(__is_trivially_copyable(wchar_t));
+  static_assert(__is_trivially_copyable(bool));
+  static_assert(__is_trivially_copyable(float));
+  static_assert(__is_trivially_copyable(double));
+  static_assert(__is_trivially_copyable(long double));
+  static_assert(__is_trivially_copyable(unsigned char));
+  static_assert(__is_trivially_copyable(unsigned int));
+  static_assert(__is_trivially_copyable(unsigned long long));
+  static_assert(__is_trivially_copyable(unsigned long));
+  static_assert(__is_trivially_copyable(unsigned short));
+  static_assert(__is_trivially_copyable(ClassType));
+  static_assert(__is_trivially_copyable(Derives));
+  static_assert(__is_trivially_copyable(Enum));
+  static_assert(__is_trivially_copyable(IntAr));
+  static_assert(__is_trivially_copyable(Union));
+  static_assert(__is_trivially_copyable(UnionAr));
+  static_assert(__is_trivially_copyable(TrivialStruct));
+  static_assert(__is_trivially_copyable(NonTrivialStruct));
+  static_assert(__is_trivially_copyable(AllDefaulted));
+  static_assert(__is_trivially_copyable(AllDeleted));
+
+  static_assert(!__is_trivially_copyable(void));
+  static_assert(!__is_trivially_copyable(SuperNonTrivialStruct));
+  static_assert(!__is_trivially_copyable(NonTCStruct));
+  static_assert(!__is_trivially_copyable(ExtDefaulted));
+
+  static_assert(__is_trivially_copyable(const int));
+  static_assert(__is_trivially_copyable(volatile int));
+
+  static_assert(__is_trivially_copyable(ACompleteType));
+  static_assert(!__is_trivially_copyable(AnIncompleteType)); // expected-error {{incomplete type}}
+  static_assert(!__is_trivially_copyable(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(!__is_trivially_copyable(AnIncompleteType[1])); // expected-error {{incomplete type}}
+  static_assert(!__is_trivially_copyable(void));
+  static_assert(!__is_trivially_copyable(const volatile void));
 }
 
 struct CStruct {
@@ -1477,32 +1475,32 @@ void is_standard_layout()
   typedef ConstInt ConstIntAr[4];
   typedef CppStructStandard CppStructStandardAr[4];
 
-  int t01[T(__is_standard_layout(int))];
-  int t02[T(__is_standard_layout(ConstInt))];
-  int t03[T(__is_standard_layout(ConstIntAr))];
-  int t04[T(__is_standard_layout(CStruct))];
-  int t05[T(__is_standard_layout(CppStructStandard))];
-  int t06[T(__is_standard_layout(CppStructStandardAr))];
-  int t07[T(__is_standard_layout(Vector))];
-  int t08[T(__is_standard_layout(VectorExt))];
+  static_assert(__is_standard_layout(int));
+  static_assert(__is_standard_layout(ConstInt));
+  static_assert(__is_standard_layout(ConstIntAr));
+  static_assert(__is_standard_layout(CStruct));
+  static_assert(__is_standard_layout(CppStructStandard));
+  static_assert(__is_standard_layout(CppStructStandardAr));
+  static_assert(__is_standard_layout(Vector));
+  static_assert(__is_standard_layout(VectorExt));
 
   typedef CppStructNonStandardByBase CppStructNonStandardByBaseAr[4];
 
-  int t10[F(__is_standard_layout(CppStructNonStandardByVirt))];
-  int t11[F(__is_standard_layout(CppStructNonStandardByMemb))];
-  int t12[F(__is_standard_layout(CppStructNonStandardByProt))];
-  int t13[F(__is_standard_layout(CppStructNonStandardByVirtBase))];
-  int t14[F(__is_standard_layout(CppStructNonStandardByBase))];
-  int t15[F(__is_standard_layout(CppStructNonStandardByBaseAr))];
-  int t16[F(__is_standard_layout(CppStructNonStandardBySameBase))];
-  int t17[F(__is_standard_layout(CppStructNonStandardBy2ndVirtBase))];
-
-  int t40[T(__is_standard_layout(ACompleteType))];
-  int t41[F(__is_standard_layout(AnIncompleteType))]; // expected-error {{incomplete type}}
-  int t42[F(__is_standard_layout(AnIncompleteType[]))]; // expected-error {{incomplete type}}
-  int t43[F(__is_standard_layout(AnIncompleteType[1]))]; // expected-error {{incomplete type}}
-  int t44[F(__is_standard_layout(void))];
-  int t45[F(__is_standard_layout(const volatile void))];
+  static_assert(!__is_standard_layout(CppStructNonStandardByVirt));
+  static_assert(!__is_standard_layout(CppStructNonStandardByMemb));
+  static_assert(!__is_standard_layout(CppStructNonStandardByProt));
+  static_assert(!__is_standard_layout(CppStructNonStandardByVirtBase));
+  static_assert(!__is_standard_layout(CppStructNonStandardByBase));
+  static_assert(!__is_standard_layout(CppStructNonStandardByBaseAr));
+  static_assert(!__is_standard_layout(CppStructNonStandardBySameBase));
+  static_assert(!__is_standard_layout(CppStructNonStandardBy2ndVirtBase));
+
+  static_assert(__is_standard_layout(ACompleteType));
+  static_assert(!__is_standard_layout(AnIncompleteType)); // expected-error {{incomplete type}}
+  static_assert(!__is_standard_layout(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(!__is_standard_layout(AnIncompleteType[1])); // expected-error {{incomplete type}}
+  static_assert(!__is_standard_layout(void));
+  static_assert(!__is_standard_layout(const volatile void));
 
   struct HasAnonEmptyBitfield { int : 0; };
   struct HasAnonBitfield { int : 4; };
@@ -1510,11 +1508,11 @@ void is_standard_layout()
   struct DerivesFromBitfieldWithBitfield : HasAnonBitfield { int : 5; };
   struct DerivesFromBitfieldTwice : DerivesFromBitfield, HasAnonEmptyBitfield {};
 
-  int t50[T(__is_standard_layout(HasAnonEmptyBitfield))];
-  int t51[T(__is_standard_layout(HasAnonBitfield))];
-  int t52[T(__is_standard_layout(DerivesFromBitfield))];
-  int t53[F(__is_standard_layout(DerivesFromBitfieldWithBitfield))];
-  int t54[F(__is_standard_layout(DerivesFromBitfieldTwice))];
+  static_assert(__is_standard_layout(HasAnonEmptyBitfield));
+  static_assert(__is_standard_layout(HasAnonBitfield));
+  static_assert(__is_standard_layout(DerivesFromBitfield));
+  static_assert(!__is_standard_layout(DerivesFromBitfieldWithBitfield));
+  static_assert(!__is_standard_layout(DerivesFromBitfieldTwice));
 
   struct Empty {};
   struct HasEmptyBase : Empty {};
@@ -1528,16 +1526,16 @@ void is_standard_layout()
   struct HasEmptyIndirectBaseAsSecondMember : HasEmptyBase { int n; Empty e; };
   struct HasEmptyIndirectBaseAfterBitfield : HasEmptyBase { int : 4; Empty e; };
 
-  int t60[T(__is_standard_layout(Empty))];
-  int t61[T(__is_standard_layout(HasEmptyBase))];
-  int t62[F(__is_standard_layout(HasRepeatedEmptyBase))];
-  int t63[F(__is_standard_layout(HasEmptyBaseAsMember))];
-  int t64[F(__is_standard_layout(HasEmptyBaseAsSubobjectOfMember1))];
-  int t65[T(__is_standard_layout(HasEmptyBaseAsSubobjectOfMember2))]; // FIXME: standard bug?
-  int t66[F(__is_standard_layout(HasEmptyBaseAsSubobjectOfMember3))];
-  int t67[F(__is_standard_layout(HasEmptyIndirectBaseAsMember))];
-  int t68[T(__is_standard_layout(HasEmptyIndirectBaseAsSecondMember))];
-  int t69[F(__is_standard_layout(HasEmptyIndirectBaseAfterBitfield))]; // FIXME: standard bug?
+  static_assert(__is_standard_layout(Empty));
+  static_assert(__is_standard_layout(HasEmptyBase));
+  static_assert(!__is_standard_layout(HasRepeatedEmptyBase));
+  static_assert(!__is_standard_layout(HasEmptyBaseAsMember));
+  static_assert(!__is_standard_layout(HasEmptyBaseAsSubobjectOfMember1));
+  static_assert(__is_standard_layout(HasEmptyBaseAsSubobjectOfMember2)); // FIXME: standard bug?
+  static_assert(!__is_standard_layout(HasEmptyBaseAsSubobjectOfMember3));
+  static_assert(!__is_standard_layout(HasEmptyIndirectBaseAsMember));
+  static_assert(__is_standard_layout(HasEmptyIndirectBaseAsSecondMember));
+  static_assert(!__is_standard_layout(HasEmptyIndirectBaseAfterBitfield)); // FIXME: standard bug?
 
   struct StructWithEmptyFields {
     int n;
@@ -1554,8 +1552,8 @@ void is_standard_layout()
     UnionWithEmptyFields u;
   };
 
-  int t70[T(__is_standard_layout(HasEmptyIndirectBaseAsSecondStructMember))];
-  int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
+  static_assert(__is_standard_layout(HasEmptyIndirectBaseAsSecondStructMember));
+  static_assert(!__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember));
 }
 
 struct CStruct2 {
@@ -1681,6 +1679,16 @@ union UnionLayout3 {
   [[no_unique_address]] CEmptyStruct d;
 };
 
+union UnionNoOveralignedMembers {
+  int a;
+  double b;
+};
+
+union UnionWithOveralignedMembers {
+  int a;
+  alignas(16) double b;
+};
+
 struct StructWithAnonUnion {
   union {
     int a;
@@ -1714,150 +1722,151 @@ struct StructWithAnonUnion3 {
 
 void is_layout_compatible(int n)
 {
-  static_assert(__is_layout_compatible(void, void), "");
-  static_assert(!__is_layout_compatible(void, int), "");
-  static_assert(__is_layout_compatible(void, const void), "");
-  static_assert(__is_layout_compatible(void, volatile void), "");
-  static_assert(__is_layout_compatible(const int, volatile int), "");
-  static_assert(__is_layout_compatible(int, int), "");
-  static_assert(__is_layout_compatible(int, const int), "");
-  static_assert(__is_layout_compatible(int, volatile int), "");
-  static_assert(__is_layout_compatible(const int, volatile int), "");
-  static_assert(__is_layout_compatible(int *, int * __restrict), "");
+  static_assert(__is_layout_compatible(void, void));
+  static_assert(!__is_layout_compatible(void, int));
+  static_assert(__is_layout_compatible(void, const void));
+  static_assert(__is_layout_compatible(void, volatile void));
+  static_assert(__is_layout_compatible(const int, volatile int));
+  static_assert(__is_layout_compatible(int, int));
+  static_assert(__is_layout_compatible(int, const int));
+  static_assert(__is_layout_compatible(int, volatile int));
+  static_assert(__is_layout_compatible(const int, volatile int));
+  static_assert(__is_layout_compatible(int *, int * __restrict));
   // Note: atomic qualification matters for layout compatibility.
-  static_assert(!__is_layout_compatible(int, _Atomic int), "");
-  static_assert(__is_layout_compatible(_Atomic(int), _Atomic int), "");
-  static_assert(!__is_layout_compatible(int, unsigned int), "");
-  static_assert(!__is_layout_compatible(char, unsigned char), "");
-  static_assert(!__is_layout_compatible(char, signed char), "");
-  static_assert(!__is_layout_compatible(unsigned char, signed char), "");
-  static_assert(__is_layout_compatible(int[], int[]), "");
-  static_assert(__is_layout_compatible(int[2], int[2]), "");
-  static_assert(!__is_layout_compatible(int[n], int[2]), ""); // FIXME: VLAs should be rejected
-  static_assert(!__is_layout_compatible(int[n], int[n]), ""); // FIXME: VLAs should be rejected
-  static_assert(__is_layout_compatible(int&, int&), "");
-  static_assert(!__is_layout_compatible(int&, char&), "");
-  static_assert(__is_layout_compatible(void(int), void(int)), "");
-  static_assert(!__is_layout_compatible(void(int), void(char)), "");
-  static_assert(__is_layout_compatible(void(&)(int), void(&)(int)), "");
-  static_assert(!__is_layout_compatible(void(&)(int), void(&)(char)), "");
-  static_assert(__is_layout_compatible(void(*)(int), void(*)(int)), "");
-  static_assert(!__is_layout_compatible(void(*)(int), void(*)(char)), "");
+  static_assert(!__is_layout_compatible(int, _Atomic int));
+  static_assert(__is_layout_compatible(_Atomic(int), _Atomic int));
+  static_assert(!__is_layout_compatible(int, unsigned int));
+  static_assert(!__is_layout_compatible(char, unsigned char));
+  static_assert(!__is_layout_compatible(char, signed char));
+  static_assert(!__is_layout_compatible(unsigned char, signed char));
+  static_assert(__is_layout_compatible(int[], int[]));
+  static_assert(__is_layout_compatible(int[2], int[2]));
+  static_assert(!__is_layout_compatible(int[n], int[2])); // FIXME: VLAs should be rejected
+  static_assert(!__is_layout_compatible(int[n], int[n])); // FIXME: VLAs should be rejected
+  static_assert(__is_layout_compatible(int&, int&));
+  static_assert(!__is_layout_compatible(int&, char&));
+  static_assert(__is_layout_compatible(void(int), void(int)));
+  static_assert(!__is_layout_compatible(void(int), void(char)));
+  static_assert(__is_layout_compatible(void(&)(int), void(&)(int)));
+  static_assert(!__is_layout_compatible(void(&)(int), void(&)(char)));
+  static_assert(__is_layout_compatible(void(*)(int), void(*)(int)));
+  static_assert(!__is_layout_compatible(void(*)(int), void(*)(char)));
   using function_type = void();
   using function_type2 = void(char);
-  static_assert(__is_layout_compatible(const function_type, const function_type), "");
+  static_assert(__is_layout_compatible(const function_type, const function_type));
   // expected-warning@-1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}}
   // expected-warning@-2 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}}
-  static_assert(__is_layout_compatible(function_type, const function_type), "");
+  static_assert(__is_layout_compatible(function_type, const function_type));
   // expected-warning@-1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}}
-  static_assert(!__is_layout_compatible(const function_type, const function_type2), "");
+  static_assert(!__is_layout_compatible(const function_type, const function_type2));
   // expected-warning@-1 {{'const' qualifier on function type 'function_type' (aka 'void ()') has no effect}}
   // expected-warning@-2 {{'const' qualifier on function type 'function_type2' (aka 'void (char)') has no effect}}
-  static_assert(__is_layout_compatible(CStruct, CStruct2), "");
-  static_assert(__is_layout_compatible(CStruct, const CStruct2), "");
-  static_assert(__is_layout_compatible(CStruct, volatile CStruct2), "");
-  static_assert(__is_layout_compatible(const CStruct, volatile CStruct2), "");
-  static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2), "");
-  static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2), "");
-  static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2), "");
-  static_assert(!__is_layout_compatible(CppStructNonStandardByBase, CppStructNonStandardByBase2), "");
-  static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, CppStructNonStandardByVirt2), "");
-  static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, CppStructNonStandardByMemb2), "");
-  static_assert(!__is_layout_compatible(CppStructNonStandardByProt, CppStructNonStandardByProt2), "");
-  static_assert(!__is_layout_compatible(CppStructNonStandardByVirtBase, CppStructNonStandardByVirtBase2), "");
-  static_assert(!__is_layout_compatible(CppStructNonStandardBySameBase, CppStructNonStandardBySameBase2), "");
-  static_assert(!__is_layout_compatible(CppStructNonStandardBy2ndVirtBase, CppStructNonStandardBy2ndVirtBase2), "");
-  static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers), "");
-  static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) != bool(__has_cpp_attribute(no_unique_address)), "");
-  static_assert(__is_layout_compatible(CStructNoUniqueAddress, CStructNoUniqueAddress2) != bool(__has_cpp_attribute(no_unique_address)), "");
-  static_assert(__is_layout_compatible(CStruct, CStructAlignment), "");
-  static_assert(__is_layout_compatible(CStruct, CStructAlignedMembers), ""); // FIXME: alignment of members impact common initial sequence
-  static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds), "");
-  static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds2), "");
-  static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds3), "");
-  static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds4), "");
-  static_assert(__is_layout_compatible(int CStruct2::*, int CStruct2::*), "");
-  static_assert(!__is_layout_compatible(int CStruct2::*, char CStruct2::*), "");
-  static_assert(__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(int)), "");
-  static_assert(!__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(char)), "");
-  static_assert(__is_layout_compatible(CStructNested, CStructNested2), "");
-  static_assert(__is_layout_compatible(UnionLayout, UnionLayout), "");
-  static_assert(!__is_layout_compatible(UnionLayout, UnionLayout2), "");
-  static_assert(!__is_layout_compatible(UnionLayout, UnionLayout3), "");
-  static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion2), "");
-  static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3), "");
-  static_assert(__is_layout_compatible(EnumLayout, EnumClassLayout), "");
-  static_assert(__is_layout_compatible(EnumForward, EnumForward), "");
-  static_assert(__is_layout_compatible(EnumForward, EnumClassForward), "");
+  static_assert(__is_layout_compatible(CStruct, CStruct2));
+  static_assert(__is_layout_compatible(CStruct, const CStruct2));
+  static_assert(__is_layout_compatible(CStruct, volatile CStruct2));
+  static_assert(__is_layout_compatible(const CStruct, volatile CStruct2));
+  static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2));
+  static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2));
+  static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2));
+  static_assert(!__is_layout_compatible(CppStructNonStandardByBase, CppStructNonStandardByBase2));
+  static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, CppStructNonStandardByVirt2));
+  static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, CppStructNonStandardByMemb2));
+  static_assert(!__is_layout_compatible(CppStructNonStandardByProt, CppStructNonStandardByProt2));
+  static_assert(!__is_layout_compatible(CppStructNonStandardByVirtBase, CppStructNonStandardByVirtBase2));
+  static_assert(!__is_layout_compatible(CppStructNonStandardBySameBase, CppStructNonStandardBySameBase2));
+  static_assert(!__is_layout_compatible(CppStructNonStandardBy2ndVirtBase, CppStructNonStandardBy2ndVirtBase2));
+  static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers));
+  static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) != bool(__has_cpp_attribute(no_unique_address)));
+  static_assert(__is_layout_compatible(CStructNoUniqueAddress, CStructNoUniqueAddress2) != bool(__has_cpp_attribute(no_unique_address)));
+  static_assert(__is_layout_compatible(CStruct, CStructAlignment));
+  static_assert(!__is_layout_compatible(CStruct, CStructAlignedMembers));
+  static_assert(__is_layout_compatible(UnionNoOveralignedMembers, UnionWithOveralignedMembers));
+  static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds));
+  static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds2));
+  static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds3));
+  static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds4));
+  static_assert(__is_layout_compatible(int CStruct2::*, int CStruct2::*));
+  static_assert(!__is_layout_compatible(int CStruct2::*, char CStruct2::*));
+  static_assert(__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(int)));
+  static_assert(!__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(char)));
+  static_assert(__is_layout_compatible(CStructNested, CStructNested2));
+  static_assert(__is_layout_compatible(UnionLayout, UnionLayout));
+  static_assert(!__is_layout_compatible(UnionLayout, UnionLayout2));
+  static_assert(!__is_layout_compatible(UnionLayout, UnionLayout3));
+  static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion2));
+  static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3));
+  static_assert(__is_layout_compatible(EnumLayout, EnumClassLayout));
+  static_assert(__is_layout_compatible(EnumForward, EnumForward));
+  static_assert(__is_layout_compatible(EnumForward, EnumClassForward));
   // Layout compatibility for enums might be relaxed in the future. See https://github.com/cplusplus/CWG/issues/39#issuecomment-1184791364
-  static_assert(!__is_layout_compatible(EnumLayout, int), "");
-  static_assert(!__is_layout_compatible(EnumClassLayout, int), "");
-  static_assert(!__is_layout_compatible(EnumForward, int), "");
-  static_assert(!__is_layout_compatible(EnumClassForward, int), "");
+  static_assert(!__is_layout_compatible(EnumLayout, int));
+  static_assert(!__is_layout_compatible(EnumClassLayout, int));
+  static_assert(!__is_layout_compatible(EnumForward, int));
+  static_assert(!__is_layout_compatible(EnumClassForward, int));
   // FIXME: the following should be rejected (array of unknown bound and void are the only allowed incomplete types)
-  static_assert(__is_layout_compatible(CStructIncomplete, CStructIncomplete), ""); 
-  static_assert(!__is_layout_compatible(CStruct, CStructIncomplete), "");
-  static_assert(__is_layout_compatible(CStructIncomplete[2], CStructIncomplete[2]), "");
+  static_assert(__is_layout_compatible(CStructIncomplete, CStructIncomplete)); 
+  static_assert(!__is_layout_compatible(CStruct, CStructIncomplete));
+  static_assert(__is_layout_compatible(CStructIncomplete[2], CStructIncomplete[2]));
 }
 
 void is_signed()
 {
-  //int t01[T(__is_signed(char))];
-  int t02[T(__is_signed(int))];
-  int t03[T(__is_signed(long))];
-  int t04[T(__is_signed(short))];
-  int t05[T(__is_signed(signed char))];
-  int t06[T(__is_signed(wchar_t))];
-  int t07[T(__is_signed(float))];
-  int t08[T(__is_signed(double))];
-  int t09[T(__is_signed(long double))];
-
-  int t13[F(__is_signed(bool))];
-  int t14[F(__is_signed(cvoid))];
-  int t15[F(__is_signed(unsigned char))];
-  int t16[F(__is_signed(unsigned int))];
-  int t17[F(__is_signed(unsigned long long))];
-  int t18[F(__is_signed(unsigned long))];
-  int t19[F(__is_signed(unsigned short))];
-  int t20[F(__is_signed(void))];
-  int t21[F(__is_signed(ClassType))];
-  int t22[F(__is_signed(Derives))];
-  int t23[F(__is_signed(Enum))];
-  int t24[F(__is_signed(SignedEnum))];
-  int t25[F(__is_signed(IntArNB))];
-  int t26[F(__is_signed(Union))];
-  int t27[F(__is_signed(UnionAr))];
-  int t28[F(__is_signed(UnsignedEnum))];
+  //static_assert(__is_signed(char));
+  static_assert(__is_signed(int));
+  static_assert(__is_signed(long));
+  static_assert(__is_signed(short));
+  static_assert(__is_signed(signed char));
+  static_assert(__is_signed(wchar_t));
+  static_assert(__is_signed(float));
+  static_assert(__is_signed(double));
+  static_assert(__is_signed(long double));
+
+  static_assert(!__is_signed(bool));
+  static_assert(!__is_signed(cvoid));
+  static_assert(!__is_signed(unsigned char));
+  static_assert(!__is_signed(unsigned int));
+  static_assert(!__is_signed(unsigned long long));
+  static_assert(!__is_signed(unsigned long));
+  static_assert(!__is_signed(unsigned short));
+  static_assert(!__is_signed(void));
+  static_assert(!__is_signed(ClassType));
+  static_assert(!__is_signed(Derives));
+  static_assert(!__is_signed(Enum));
+  static_assert(!__is_signed(SignedEnum));
+  static_assert(!__is_signed(IntArNB));
+  static_assert(!__is_signed(Union));
+  static_assert(!__is_signed(UnionAr));
+  static_assert(!__is_signed(UnsignedEnum));
 }
 
 void is_unsigned()
 {
-  int t01[T(__is_unsigned(bool))];
-  int t02[T(__is_unsigned(unsigned char))];
-  int t03[T(__is_unsigned(unsigned short))];
-  int t04[T(__is_unsigned(unsigned int))];
-  int t05[T(__is_unsigned(unsigned long))];
-  int t06[T(__is_unsigned(unsigned long long))];
-
-  int t10[F(__is_unsigned(void))];
-  int t11[F(__is_unsigned(cvoid))];
-  int t12[F(__is_unsigned(float))];
-  int t13[F(__is_unsigned(double))];
-  int t14[F(__is_unsigned(long double))];
-  int t16[F(__is_unsigned(char))];
-  int t17[F(__is_unsigned(signed char))];
-  int t18[F(__is_unsigned(wchar_t))];
-  int t19[F(__is_unsigned(short))];
-  int t20[F(__is_unsigned(int))];
-  int t21[F(__is_unsigned(long))];
-  int t22[F(__is_unsigned(Union))];
-  int t23[F(__is_unsigned(UnionAr))];
-  int t24[F(__is_unsigned(Derives))];
-  int t25[F(__is_unsigned(ClassType))];
-  int t26[F(__is_unsigned(IntArNB))];
-  int t27[F(__is_unsigned(Enum))];
-  int t28[F(__is_unsigned(UnsignedEnum))];
-  int t29[F(__is_unsigned(SignedEnum))];
+  static_assert(__is_unsigned(bool));
+  static_assert(__is_unsigned(unsigned char));
+  static_assert(__is_unsigned(unsigned short));
+  static_assert(__is_unsigned(unsigned int));
+  static_assert(__is_unsigned(unsigned long));
+  static_assert(__is_unsigned(unsigned long long));
+
+  static_assert(!__is_unsigned(void));
+  static_assert(!__is_unsigned(cvoid));
+  static_assert(!__is_unsigned(float));
+  static_assert(!__is_unsigned(double));
+  static_assert(!__is_unsigned(long double));
+  static_assert(!__is_unsigned(char));
+  static_assert(!__is_unsigned(signed char));
+  static_assert(!__is_unsigned(wchar_t));
+  static_assert(!__is_unsigned(short));
+  static_assert(!__is_unsigned(int));
+  static_assert(!__is_unsigned(long));
+  static_assert(!__is_unsigned(Union));
+  static_assert(!__is_unsigned(UnionAr));
+  static_assert(!__is_unsigned(Derives));
+  static_assert(!__is_unsigned(ClassType));
+  static_assert(!__is_unsigned(IntArNB));
+  static_assert(!__is_unsigned(Enum));
+  static_assert(!__is_unsigned(UnsignedEnum));
+  static_assert(!__is_unsigned(SignedEnum));
 }
 
 typedef Int& IntRef;
@@ -1880,35 +1889,35 @@ struct HasTemplateCons {
 };
 
 void has_trivial_default_constructor() {
-  { int arr[T(__has_trivial_constructor(Int))]; }
-  { int arr[T(__has_trivial_constructor(IntAr))]; }
-  { int arr[T(__has_trivial_constructor(Union))]; }
-  { int arr[T(__has_trivial_constructor(UnionAr))]; }
-  { int arr[T(__has_trivial_constructor(POD))]; }
-  { int arr[T(__has_trivial_constructor(Derives))]; }
-  { int arr[T(__has_trivial_constructor(DerivesAr))]; }
-  { int arr[T(__has_trivial_constructor(ConstIntAr))]; }
-  { int arr[T(__has_trivial_constructor(ConstIntArAr))]; }
-  { int arr[T(__has_trivial_constructor(HasDest))]; }
-  { int arr[T(__has_trivial_constructor(HasPriv))]; }
-  { int arr[T(__has_trivial_constructor(HasCopyAssign))]; }
-  { int arr[T(__has_trivial_constructor(HasMoveAssign))]; }
-  { int arr[T(__has_trivial_constructor(const Int))]; }
-  { int arr[T(__has_trivial_constructor(AllDefaulted))]; }
-  { int arr[T(__has_trivial_constructor(AllDeleted))]; }
-  { int arr[T(__has_trivial_constructor(ACompleteType[]))]; }
-
-  { int arr[F(__has_trivial_constructor(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__has_trivial_constructor(HasCons))]; }
-  { int arr[F(__has_trivial_constructor(HasRef))]; }
-  { int arr[F(__has_trivial_constructor(HasCopy))]; }
-  { int arr[F(__has_trivial_constructor(IntRef))]; }
-  { int arr[F(__has_trivial_constructor(VirtAr))]; }
-  { int arr[F(__has_trivial_constructor(void))]; }
-  { int arr[F(__has_trivial_constructor(cvoid))]; }
-  { int arr[F(__has_trivial_constructor(HasTemplateCons))]; }
-  { int arr[F(__has_trivial_constructor(AllPrivate))]; }
-  { int arr[F(__has_trivial_constructor(ExtDefaulted))]; }
+  static_assert(__has_trivial_constructor(Int));
+  static_assert(__has_trivial_constructor(IntAr));
+  static_assert(__has_trivial_constructor(Union));
+  static_assert(__has_trivial_constructor(UnionAr));
+  static_assert(__has_trivial_constructor(POD));
+  static_assert(__has_trivial_constructor(Derives));
+  static_assert(__has_trivial_constructor(DerivesAr));
+  static_assert(__has_trivial_constructor(ConstIntAr));
+  static_assert(__has_trivial_constructor(ConstIntArAr));
+  static_assert(__has_trivial_constructor(HasDest));
+  static_assert(__has_trivial_constructor(HasPriv));
+  static_assert(__has_trivial_constructor(HasCopyAssign));
+  static_assert(__has_trivial_constructor(HasMoveAssign));
+  static_assert(__has_trivial_constructor(const Int));
+  static_assert(__has_trivial_constructor(AllDefaulted));
+  static_assert(__has_trivial_constructor(AllDeleted));
+  static_assert(__has_trivial_constructor(ACompleteType[]));
+
+  static_assert(!__has_trivial_constructor(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(!__has_trivial_constructor(HasCons));
+  static_assert(!__has_trivial_constructor(HasRef));
+  static_assert(!__has_trivial_constructor(HasCopy));
+  static_assert(!__has_trivial_constructor(IntRef));
+  static_assert(!__has_trivial_constructor(VirtAr));
+  static_assert(!__has_trivial_constructor(void));
+  static_assert(!__has_trivial_constructor(cvoid));
+  static_assert(!__has_trivial_constructor(HasTemplateCons));
+  static_assert(!__has_trivial_constructor(AllPrivate));
+  static_assert(!__has_trivial_constructor(ExtDefaulted));
 }
 
 void has_trivial_move_constructor() {
@@ -1924,127 +1933,127 @@ void has_trivial_move_constructor() {
   //     type (or array thereof), the constructor selected
   //     to copy/move that member is trivial;
   // otherwise the copy/move constructor is non-trivial.
-  { int arr[T(__has_trivial_move_constructor(POD))]; }
-  { int arr[T(__has_trivial_move_constructor(Union))]; }
-  { int arr[T(__has_trivial_move_constructor(HasCons))]; }
-  { int arr[T(__has_trivial_move_constructor(HasStaticMemberMoveCtor))]; }
-  { int arr[T(__has_trivial_move_constructor(AllDeleted))]; }
-  { int arr[T(__has_trivial_move_constructor(ACompleteType[]))]; }
-
-  { int arr[F(__has_trivial_move_constructor(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__has_trivial_move_constructor(HasVirt))]; }
-  { int arr[F(__has_trivial_move_constructor(DerivesVirt))]; }
-  { int arr[F(__has_trivial_move_constructor(HasMoveCtor))]; }
-  { int arr[F(__has_trivial_move_constructor(DerivesHasMoveCtor))]; }
-  { int arr[F(__has_trivial_move_constructor(HasMemberMoveCtor))]; }
+  static_assert(__has_trivial_move_constructor(POD));
+  static_assert(__has_trivial_move_constructor(Union));
+  static_assert(__has_trivial_move_constructor(HasCons));
+  static_assert(__has_trivial_move_constructor(HasStaticMemberMoveCtor));
+  static_assert(__has_trivial_move_constructor(AllDeleted));
+  static_assert(__has_trivial_move_constructor(ACompleteType[]));
+
+  static_assert(!__has_trivial_move_constructor(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(!__has_trivial_move_constructor(HasVirt));
+  static_assert(!__has_trivial_move_constructor(DerivesVirt));
+  static_assert(!__has_trivial_move_constructor(HasMoveCtor));
+  static_assert(!__has_trivial_move_constructor(DerivesHasMoveCtor));
+  static_assert(!__has_trivial_move_constructor(HasMemberMoveCtor));
 }
 
 void has_trivial_copy_constructor() {
-  { int arr[T(__has_trivial_copy(Int))]; }
-  { int arr[T(__has_trivial_copy(IntAr))]; }
-  { int arr[T(__has_trivial_copy(Union))]; }
-  { int arr[T(__has_trivial_copy(UnionAr))]; }
-  { int arr[T(__has_trivial_copy(POD))]; }
-  { int arr[T(__has_trivial_copy(Derives))]; }
-  { int arr[T(__has_trivial_copy(ConstIntAr))]; }
-  { int arr[T(__has_trivial_copy(ConstIntArAr))]; }
-  { int arr[T(__has_trivial_copy(HasDest))]; }
-  { int arr[T(__has_trivial_copy(HasPriv))]; }
-  { int arr[T(__has_trivial_copy(HasCons))]; }
-  { int arr[T(__has_trivial_copy(HasRef))]; }
-  { int arr[T(__has_trivial_copy(HasMove))]; }
-  { int arr[T(__has_trivial_copy(IntRef))]; }
-  { int arr[T(__has_trivial_copy(HasCopyAssign))]; }
-  { int arr[T(__has_trivial_copy(HasMoveAssign))]; }
-  { int arr[T(__has_trivial_copy(const Int))]; }
-  { int arr[T(__has_trivial_copy(AllDefaulted))]; }
-  { int arr[T(__has_trivial_copy(AllDeleted))]; }
-  { int arr[T(__has_trivial_copy(DerivesAr))]; }
-  { int arr[T(__has_trivial_copy(DerivesHasRef))]; }
-  { int arr[T(__has_trivial_copy(ACompleteType[]))]; }
-
-  { int arr[F(__has_trivial_copy(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__has_trivial_copy(HasCopy))]; }
-  { int arr[F(__has_trivial_copy(HasTemplateCons))]; }
-  { int arr[F(__has_trivial_copy(VirtAr))]; }
-  { int arr[F(__has_trivial_copy(void))]; }
-  { int arr[F(__has_trivial_copy(cvoid))]; }
-  { int arr[F(__has_trivial_copy(AllPrivate))]; }
-  { int arr[F(__has_trivial_copy(ExtDefaulted))]; }
+  static_assert(__has_trivial_copy(Int));
+  static_assert(__has_trivial_copy(IntAr));
+  static_assert(__has_trivial_copy(Union));
+  static_assert(__has_trivial_copy(UnionAr));
+  static_assert(__has_trivial_copy(POD));
+  static_assert(__has_trivial_copy(Derives));
+  static_assert(__has_trivial_copy(ConstIntAr));
+  static_assert(__has_trivial_copy(ConstIntArAr));
+  static_assert(__has_trivial_copy(HasDest));
+  static_assert(__has_trivial_copy(HasPriv));
+  static_assert(__has_trivial_copy(HasCons));
+  static_assert(__has_trivial_copy(HasRef));
+  static_assert(__has_trivial_copy(HasMove));
+  static_assert(__has_trivial_copy(IntRef));
+  static_assert(__has_trivial_copy(HasCopyAssign));
+  static_assert(__has_trivial_copy(HasMoveAssign));
+  static_assert(__has_trivial_copy(const Int));
+  static_assert(__has_trivial_copy(AllDefaulted));
+  static_assert(__has_trivial_copy(AllDeleted));
+  static_assert(__has_trivial_copy(DerivesAr));
+  static_assert(__has_trivial_copy(DerivesHasRef));
+  static_assert(__has_trivial_copy(ACompleteType[]));
+
+  static_assert(!__has_trivial_copy(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(!__has_trivial_copy(HasCopy));
+  static_assert(!__has_trivial_copy(HasTemplateCons));
+  static_assert(!__has_trivial_copy(VirtAr));
+  static_assert(!__has_trivial_copy(void));
+  static_assert(!__has_trivial_copy(cvoid));
+  static_assert(!__has_trivial_copy(AllPrivate));
+  static_assert(!__has_trivial_copy(ExtDefaulted));
 }
 
 void has_trivial_copy_assignment() {
-  { int arr[T(__has_trivial_assign(Int))]; }
-  { int arr[T(__has_trivial_assign(IntAr))]; }
-  { int arr[T(__has_trivial_assign(Union))]; }
-  { int arr[T(__has_trivial_assign(UnionAr))]; }
-  { int arr[T(__has_trivial_assign(POD))]; }
-  { int arr[T(__has_trivial_assign(Derives))]; }
-  { int arr[T(__has_trivial_assign(HasDest))]; }
-  { int arr[T(__has_trivial_assign(HasPriv))]; }
-  { int arr[T(__has_trivial_assign(HasCons))]; }
-  { int arr[T(__has_trivial_assign(HasRef))]; }
-  { int arr[T(__has_trivial_assign(HasCopy))]; }
-  { int arr[T(__has_trivial_assign(HasMove))]; }
-  { int arr[T(__has_trivial_assign(HasMoveAssign))]; }
-  { int arr[T(__has_trivial_assign(AllDefaulted))]; }
-  { int arr[T(__has_trivial_assign(AllDeleted))]; }
-  { int arr[T(__has_trivial_assign(DerivesAr))]; }
-  { int arr[T(__has_trivial_assign(DerivesHasRef))]; }
-  { int arr[T(__has_trivial_assign(ACompleteType[]))]; }
-
-  { int arr[F(__has_trivial_assign(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__has_trivial_assign(IntRef))]; }
-  { int arr[F(__has_trivial_assign(HasCopyAssign))]; }
-  { int arr[F(__has_trivial_assign(const Int))]; }
-  { int arr[F(__has_trivial_assign(ConstIntAr))]; }
-  { int arr[F(__has_trivial_assign(ConstIntArAr))]; }
-  { int arr[F(__has_trivial_assign(VirtAr))]; }
-  { int arr[F(__has_trivial_assign(void))]; }
-  { int arr[F(__has_trivial_assign(cvoid))]; }
-  { int arr[F(__has_trivial_assign(AllPrivate))]; }
-  { int arr[F(__has_trivial_assign(ExtDefaulted))]; }
+  static_assert(__has_trivial_assign(Int));
+  static_assert(__has_trivial_assign(IntAr));
+  static_assert(__has_trivial_assign(Union));
+  static_assert(__has_trivial_assign(UnionAr));
+  static_assert(__has_trivial_assign(POD));
+  static_assert(__has_trivial_assign(Derives));
+  static_assert(__has_trivial_assign(HasDest));
+  static_assert(__has_trivial_assign(HasPriv));
+  static_assert(__has_trivial_assign(HasCons));
+  static_assert(__has_trivial_assign(HasRef));
+  static_assert(__has_trivial_assign(HasCopy));
+  static_assert(__has_trivial_assign(HasMove));
+  static_assert(__has_trivial_assign(HasMoveAssign));
+  static_assert(__has_trivial_assign(AllDefaulted));
+  static_assert(__has_trivial_assign(AllDeleted));
+  static_assert(__has_trivial_assign(DerivesAr));
+  static_assert(__has_trivial_assign(DerivesHasRef));
+  static_assert(__has_trivial_assign(ACompleteType[]));
+
+  static_assert(!__has_trivial_assign(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(!__has_trivial_assign(IntRef));
+  static_assert(!__has_trivial_assign(HasCopyAssign));
+  static_assert(!__has_trivial_assign(const Int));
+  static_assert(!__has_trivial_assign(ConstIntAr));
+  static_assert(!__has_trivial_assign(ConstIntArAr));
+  static_assert(!__has_trivial_assign(VirtAr));
+  static_assert(!__has_trivial_assign(void));
+  static_assert(!__has_trivial_assign(cvoid));
+  static_assert(!__has_trivial_assign(AllPrivate));
+  static_assert(!__has_trivial_assign(ExtDefaulted));
 }
 
 void has_trivial_destructor() {
-  { int arr[T(__has_trivial_destructor(Int))]; }
-  { int arr[T(__has_trivial_destructor(IntAr))]; }
-  { int arr[T(__has_trivial_destructor(Union))]; }
-  { int arr[T(__has_trivial_destructor(UnionAr))]; }
-  { int arr[T(__has_trivial_destructor(POD))]; }
-  { int arr[T(__has_trivial_destructor(Derives))]; }
-  { int arr[T(__has_trivial_destructor(ConstIntAr))]; }
-  { int arr[T(__has_trivial_destructor(ConstIntArAr))]; }
-  { int arr[T(__has_trivial_destructor(HasPriv))]; }
-  { int arr[T(__has_trivial_destructor(HasCons))]; }
-  { int arr[T(__has_trivial_destructor(HasRef))]; }
-  { int arr[T(__has_trivial_destructor(HasCopy))]; }
-  { int arr[T(__has_trivial_destructor(HasMove))]; }
-  { int arr[T(__has_trivial_destructor(IntRef))]; }
-  { int arr[T(__has_trivial_destructor(HasCopyAssign))]; }
-  { int arr[T(__has_trivial_destructor(HasMoveAssign))]; }
-  { int arr[T(__has_trivial_destructor(const Int))]; }
-  { int arr[T(__has_trivial_destructor(DerivesAr))]; }
-  { int arr[T(__has_trivial_destructor(VirtAr))]; }
-  { int arr[T(__has_trivial_destructor(AllDefaulted))]; }
-  { int arr[T(__has_trivial_destructor(AllDeleted))]; }
-  { int arr[T(__has_trivial_destructor(DerivesHasRef))]; }
-  { int arr[T(__has_trivial_destructor(ACompleteType[]))]; }
-
-  { int arr[F(__has_trivial_destructor(HasDest))]; }
-  { int arr[F(__has_trivial_destructor(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__has_trivial_destructor(void))]; }
-  { int arr[F(__has_trivial_destructor(cvoid))]; }
-  { int arr[F(__has_trivial_destructor(AllPrivate))]; }
-  { int arr[F(__has_trivial_destructor(ExtDefaulted))]; }
+  static_assert(__has_trivial_destructor(Int));
+  static_assert(__has_trivial_destructor(IntAr));
+  static_assert(__has_trivial_destructor(Union));
+  static_assert(__has_trivial_destructor(UnionAr));
+  static_assert(__has_trivial_destructor(POD));
+  static_assert(__has_trivial_destructor(Derives));
+  static_assert(__has_trivial_destructor(ConstIntAr));
+  static_assert(__has_trivial_destructor(ConstIntArAr));
+  static_assert(__has_trivial_destructor(HasPriv));
+  static_assert(__has_trivial_destructor(HasCons));
+  static_assert(__has_trivial_destructor(HasRef));
+  static_assert(__has_trivial_destructor(HasCopy));
+  static_assert(__has_trivial_destructor(HasMove));
+  static_assert(__has_trivial_destructor(IntRef));
+  static_assert(__has_trivial_destructor(HasCopyAssign));
+  static_assert(__has_trivial_destructor(HasMoveAssign));
+  static_assert(__has_trivial_destructor(const Int));
+  static_assert(__has_trivial_destructor(DerivesAr));
+  static_assert(__has_trivial_destructor(VirtAr));
+  static_assert(__has_trivial_destructor(AllDefaulted));
+  static_assert(__has_trivial_destructor(AllDeleted));
+  static_assert(__has_trivial_destructor(DerivesHasRef));
+  static_assert(__has_trivial_destructor(ACompleteType[]));
+
+  static_assert(!__has_trivial_destructor(HasDest));
+  static_assert(!__has_trivial_destructor(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(!__has_trivial_destructor(void));
+  static_assert(!__has_trivial_destructor(cvoid));
+  static_assert(!__has_trivial_destructor(AllPrivate));
+  static_assert(!__has_trivial_destructor(ExtDefaulted));
 }
 
 struct A { ~A() {} };
 template struct B : A { };
 
 void f() {
-  { int arr[F(__has_trivial_destructor(A))]; }
-  { int arr[F(__has_trivial_destructor(B))]; }
+  static_assert(!__has_trivial_destructor(A));
+  static_assert(!__has_trivial_destructor(B));
 }
 
 class PR11110 {
@@ -2065,69 +2074,69 @@ public:
 };
 
 void has_nothrow_assign() {
-  { int arr[T(__has_nothrow_assign(Int))]; }
-  { int arr[T(__has_nothrow_assign(IntAr))]; }
-  { int arr[T(__has_nothrow_assign(Union))]; }
-  { int arr[T(__has_nothrow_assign(UnionAr))]; }
-  { int arr[T(__has_nothrow_assign(POD))]; }
-  { int arr[T(__has_nothrow_assign(Derives))]; }
-  { int arr[T(__has_nothrow_assign(HasDest))]; }
-  { int arr[T(__has_nothrow_assign(HasPriv))]; }
-  { int arr[T(__has_nothrow_assign(HasCons))]; }
-  { int arr[T(__has_nothrow_assign(HasRef))]; }
-  { int arr[T(__has_nothrow_assign(HasCopy))]; }
-  { int arr[T(__has_nothrow_assign(HasMove))]; }
-  { int arr[T(__has_nothrow_assign(HasMoveAssign))]; }
-  { int arr[T(__has_nothrow_assign(HasNoThrowCopyAssign))]; }
-  { int arr[T(__has_nothrow_assign(HasMultipleNoThrowCopyAssign))]; }
-  { int arr[T(__has_nothrow_assign(HasVirtDest))]; }
-  { int arr[T(__has_nothrow_assign(AllPrivate))]; }
-  { int arr[T(__has_nothrow_assign(UsingAssign))]; }
-  { int arr[T(__has_nothrow_assign(DerivesAr))]; }
-  { int arr[T(__has_nothrow_assign(ACompleteType[]))]; }
-
-  { int arr[F(__has_nothrow_assign(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__has_nothrow_assign(IntRef))]; }
-  { int arr[F(__has_nothrow_assign(HasCopyAssign))]; }
-  { int arr[F(__has_nothrow_assign(HasMultipleCopyAssign))]; }
-  { int arr[F(__has_nothrow_assign(const Int))]; }
-  { int arr[F(__has_nothrow_assign(ConstIntAr))]; }
-  { int arr[F(__has_nothrow_assign(ConstIntArAr))]; }
-  { int arr[F(__has_nothrow_assign(VirtAr))]; }
-  { int arr[F(__has_nothrow_assign(void))]; }
-  { int arr[F(__has_nothrow_assign(cvoid))]; }
-  { int arr[F(__has_nothrow_assign(PR11110))]; }
+  static_assert(__has_nothrow_assign(Int));
+  static_assert(__has_nothrow_assign(IntAr));
+  static_assert(__has_nothrow_assign(Union));
+  static_assert(__has_nothrow_assign(UnionAr));
+  static_assert(__has_nothrow_assign(POD));
+  static_assert(__has_nothrow_assign(Derives));
+  static_assert(__has_nothrow_assign(HasDest));
+  static_assert(__has_nothrow_assign(HasPriv));
+  static_assert(__has_nothrow_assign(HasCons));
+  static_assert(__has_nothrow_assign(HasRef));
+  static_assert(__has_nothrow_assign(HasCopy));
+  static_assert(__has_nothrow_assign(HasMove));
+  static_assert(__has_nothrow_assign(HasMoveAssign));
+  static_assert(__has_nothrow_assign(HasNoThrowCopyAssign));
+  static_assert(__has_nothrow_assign(HasMultipleNoThrowCopyAssign));
+  static_assert(__has_nothrow_assign(HasVirtDest));
+  static_assert(__has_nothrow_assign(AllPrivate));
+  static_assert(__has_nothrow_assign(UsingAssign));
+  static_assert(__has_nothrow_assign(DerivesAr));
+  static_assert(__has_nothrow_assign(ACompleteType[]));
+
+  static_assert(!__has_nothrow_assign(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(!__has_nothrow_assign(IntRef));
+  static_assert(!__has_nothrow_assign(HasCopyAssign));
+  static_assert(!__has_nothrow_assign(HasMultipleCopyAssign));
+  static_assert(!__has_nothrow_assign(const Int));
+  static_assert(!__has_nothrow_assign(ConstIntAr));
+  static_assert(!__has_nothrow_assign(ConstIntArAr));
+  static_assert(!__has_nothrow_assign(VirtAr));
+  static_assert(!__has_nothrow_assign(void));
+  static_assert(!__has_nothrow_assign(cvoid));
+  static_assert(!__has_nothrow_assign(PR11110));
 }
 
 void has_nothrow_move_assign() {
-  { int arr[T(__has_nothrow_move_assign(Int))]; }
-  { int arr[T(__has_nothrow_move_assign(Enum))]; }
-  { int arr[T(__has_nothrow_move_assign(Int*))]; }
-  { int arr[T(__has_nothrow_move_assign(Enum POD::*))]; }
-  { int arr[T(__has_nothrow_move_assign(POD))]; }
-  { int arr[T(__has_nothrow_move_assign(HasPriv))]; }
-  { int arr[T(__has_nothrow_move_assign(HasNoThrowMoveAssign))]; }
-  { int arr[T(__has_nothrow_move_assign(HasNoExceptNoThrowMoveAssign))]; }
-  { int arr[T(__has_nothrow_move_assign(HasMemberNoThrowMoveAssign))]; }
-  { int arr[T(__has_nothrow_move_assign(HasMemberNoExceptNoThrowMoveAssign))]; }
-  { int arr[T(__has_nothrow_move_assign(AllDeleted))]; }
-  { int arr[T(__has_nothrow_move_assign(ACompleteType[]))]; }
-
-  { int arr[F(__has_nothrow_move_assign(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__has_nothrow_move_assign(HasThrowMoveAssign))]; }
-  { int arr[F(__has_nothrow_move_assign(HasNoExceptFalseMoveAssign))]; }
-  { int arr[F(__has_nothrow_move_assign(HasMemberThrowMoveAssign))]; }
-  { int arr[F(__has_nothrow_move_assign(HasMemberNoExceptFalseMoveAssign))]; }
-  { int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyCtor))]; }
-  { int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyAssign))]; }
-  { int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToDtor))]; }
-
-
-  { int arr[T(__is_nothrow_assignable(HasNoThrowMoveAssign, HasNoThrowMoveAssign))]; }
-  { int arr[F(__is_nothrow_assignable(HasThrowMoveAssign, HasThrowMoveAssign))]; }
-
-  { int arr[T(__is_assignable(HasNoThrowMoveAssign, HasNoThrowMoveAssign))]; }
-  { int arr[T(__is_assignable(HasThrowMoveAssign, HasThrowMoveAssign))]; }
+  static_assert(__has_nothrow_move_assign(Int));
+  static_assert(__has_nothrow_move_assign(Enum));
+  static_assert(__has_nothrow_move_assign(Int*));
+  static_assert(__has_nothrow_move_assign(Enum POD::*));
+  static_assert(__has_nothrow_move_assign(POD));
+  static_assert(__has_nothrow_move_assign(HasPriv));
+  static_assert(__has_nothrow_move_assign(HasNoThrowMoveAssign));
+  static_assert(__has_nothrow_move_assign(HasNoExceptNoThrowMoveAssign));
+  static_assert(__has_nothrow_move_assign(HasMemberNoThrowMoveAssign));
+  static_assert(__has_nothrow_move_assign(HasMemberNoExceptNoThrowMoveAssign));
+  static_assert(__has_nothrow_move_assign(AllDeleted));
+  static_assert(__has_nothrow_move_assign(ACompleteType[]));
+
+  static_assert(!__has_nothrow_move_assign(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(!__has_nothrow_move_assign(HasThrowMoveAssign));
+  static_assert(!__has_nothrow_move_assign(HasNoExceptFalseMoveAssign));
+  static_assert(!__has_nothrow_move_assign(HasMemberThrowMoveAssign));
+  static_assert(!__has_nothrow_move_assign(HasMemberNoExceptFalseMoveAssign));
+  static_assert(!__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyCtor));
+  static_assert(!__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyAssign));
+  static_assert(!__has_nothrow_move_assign(NoDefaultMoveAssignDueToDtor));
+
+
+  static_assert(__is_nothrow_assignable(HasNoThrowMoveAssign, HasNoThrowMoveAssign));
+  static_assert(!__is_nothrow_assignable(HasThrowMoveAssign, HasThrowMoveAssign));
+
+  static_assert(__is_assignable(HasNoThrowMoveAssign, HasNoThrowMoveAssign));
+  static_assert(__is_assignable(HasThrowMoveAssign, HasThrowMoveAssign));
 }
 
 void has_trivial_move_assign() {
@@ -2142,120 +2151,120 @@ void has_trivial_move_assign() {
   //  - for each non-static data member of X that is of class type
   //    (or array thereof), the assignment operator
   //    selected to copy/move that member is trivial;
-  { int arr[T(__has_trivial_move_assign(Int))]; }
-  { int arr[T(__has_trivial_move_assign(HasStaticMemberMoveAssign))]; }
-  { int arr[T(__has_trivial_move_assign(AllDeleted))]; }
-  { int arr[T(__has_trivial_move_assign(ACompleteType[]))]; }
-
-  { int arr[F(__has_trivial_move_assign(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__has_trivial_move_assign(HasVirt))]; }
-  { int arr[F(__has_trivial_move_assign(DerivesVirt))]; }
-  { int arr[F(__has_trivial_move_assign(HasMoveAssign))]; }
-  { int arr[F(__has_trivial_move_assign(DerivesHasMoveAssign))]; }
-  { int arr[F(__has_trivial_move_assign(HasMemberMoveAssign))]; }
-  { int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyCtor))]; }
-  { int arr[F(__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyAssign))]; }
+  static_assert(__has_trivial_move_assign(Int));
+  static_assert(__has_trivial_move_assign(HasStaticMemberMoveAssign));
+  static_assert(__has_trivial_move_assign(AllDeleted));
+  static_assert(__has_trivial_move_assign(ACompleteType[]));
+
+  static_assert(!__has_trivial_move_assign(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(!__has_trivial_move_assign(HasVirt));
+  static_assert(!__has_trivial_move_assign(DerivesVirt));
+  static_assert(!__has_trivial_move_assign(HasMoveAssign));
+  static_assert(!__has_trivial_move_assign(DerivesHasMoveAssign));
+  static_assert(!__has_trivial_move_assign(HasMemberMoveAssign));
+  static_assert(!__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyCtor));
+  static_assert(!__has_nothrow_move_assign(NoDefaultMoveAssignDueToUDCopyAssign));
 }
 
 void has_nothrow_copy() {
-  { int arr[T(__has_nothrow_copy(Int))]; }
-  { int arr[T(__has_nothrow_copy(IntAr))]; }
-  { int arr[T(__has_nothrow_copy(Union))]; }
-  { int arr[T(__has_nothrow_copy(UnionAr))]; }
-  { int arr[T(__has_nothrow_copy(POD))]; }
-  { int arr[T(__has_nothrow_copy(const Int))]; }
-  { int arr[T(__has_nothrow_copy(ConstIntAr))]; }
-  { int arr[T(__has_nothrow_copy(ConstIntArAr))]; }
-  { int arr[T(__has_nothrow_copy(Derives))]; }
-  { int arr[T(__has_nothrow_copy(IntRef))]; }
-  { int arr[T(__has_nothrow_copy(HasDest))]; }
-  { int arr[T(__has_nothrow_copy(HasPriv))]; }
-  { int arr[T(__has_nothrow_copy(HasCons))]; }
-  { int arr[T(__has_nothrow_copy(HasRef))]; }
-  { int arr[T(__has_nothrow_copy(HasMove))]; }
-  { int arr[T(__has_nothrow_copy(HasCopyAssign))]; }
-  { int arr[T(__has_nothrow_copy(HasMoveAssign))]; }
-  { int arr[T(__has_nothrow_copy(HasNoThrowCopy))]; }
-  { int arr[T(__has_nothrow_copy(HasMultipleNoThrowCopy))]; }
-  { int arr[T(__has_nothrow_copy(HasVirtDest))]; }
-  { int arr[T(__has_nothrow_copy(HasTemplateCons))]; }
-  { int arr[T(__has_nothrow_copy(AllPrivate))]; }
-  { int arr[T(__has_nothrow_copy(DerivesAr))]; }
-  { int arr[T(__has_nothrow_copy(ACompleteType[]))]; }
-
-  { int arr[F(__has_nothrow_copy(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__has_nothrow_copy(HasCopy))]; }
-  { int arr[F(__has_nothrow_copy(HasMultipleCopy))]; }
-  { int arr[F(__has_nothrow_copy(VirtAr))]; }
-  { int arr[F(__has_nothrow_copy(void))]; }
-  { int arr[F(__has_nothrow_copy(cvoid))]; }
+  static_assert(__has_nothrow_copy(Int));
+  static_assert(__has_nothrow_copy(IntAr));
+  static_assert(__has_nothrow_copy(Union));
+  static_assert(__has_nothrow_copy(UnionAr));
+  static_assert(__has_nothrow_copy(POD));
+  static_assert(__has_nothrow_copy(const Int));
+  static_assert(__has_nothrow_copy(ConstIntAr));
+  static_assert(__has_nothrow_copy(ConstIntArAr));
+  static_assert(__has_nothrow_copy(Derives));
+  static_assert(__has_nothrow_copy(IntRef));
+  static_assert(__has_nothrow_copy(HasDest));
+  static_assert(__has_nothrow_copy(HasPriv));
+  static_assert(__has_nothrow_copy(HasCons));
+  static_assert(__has_nothrow_copy(HasRef));
+  static_assert(__has_nothrow_copy(HasMove));
+  static_assert(__has_nothrow_copy(HasCopyAssign));
+  static_assert(__has_nothrow_copy(HasMoveAssign));
+  static_assert(__has_nothrow_copy(HasNoThrowCopy));
+  static_assert(__has_nothrow_copy(HasMultipleNoThrowCopy));
+  static_assert(__has_nothrow_copy(HasVirtDest));
+  static_assert(__has_nothrow_copy(HasTemplateCons));
+  static_assert(__has_nothrow_copy(AllPrivate));
+  static_assert(__has_nothrow_copy(DerivesAr));
+  static_assert(__has_nothrow_copy(ACompleteType[]));
+
+  static_assert(!__has_nothrow_copy(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(!__has_nothrow_copy(HasCopy));
+  static_assert(!__has_nothrow_copy(HasMultipleCopy));
+  static_assert(!__has_nothrow_copy(VirtAr));
+  static_assert(!__has_nothrow_copy(void));
+  static_assert(!__has_nothrow_copy(cvoid));
 }
 
 void has_nothrow_constructor() {
-  { int arr[T(__has_nothrow_constructor(Int))]; }
-  { int arr[T(__has_nothrow_constructor(IntAr))]; }
-  { int arr[T(__has_nothrow_constructor(Union))]; }
-  { int arr[T(__has_nothrow_constructor(UnionAr))]; }
-  { int arr[T(__has_nothrow_constructor(POD))]; }
-  { int arr[T(__has_nothrow_constructor(Derives))]; }
-  { int arr[T(__has_nothrow_constructor(DerivesAr))]; }
-  { int arr[T(__has_nothrow_constructor(ConstIntAr))]; }
-  { int arr[T(__has_nothrow_constructor(ConstIntArAr))]; }
-  { int arr[T(__has_nothrow_constructor(HasDest))]; }
-  { int arr[T(__has_nothrow_constructor(HasPriv))]; }
-  { int arr[T(__has_nothrow_constructor(HasCopyAssign))]; }
-  { int arr[T(__has_nothrow_constructor(const Int))]; }
-  { int arr[T(__has_nothrow_constructor(HasNoThrowConstructor))]; }
-  { int arr[T(__has_nothrow_constructor(HasVirtDest))]; }
-  // { int arr[T(__has_nothrow_constructor(VirtAr))]; } // not implemented
-  { int arr[T(__has_nothrow_constructor(AllPrivate))]; }
-  { int arr[T(__has_nothrow_constructor(ACompleteType[]))]; }
-
-  { int arr[F(__has_nothrow_constructor(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__has_nothrow_constructor(HasCons))]; }
-  { int arr[F(__has_nothrow_constructor(HasRef))]; }
-  { int arr[F(__has_nothrow_constructor(HasCopy))]; }
-  { int arr[F(__has_nothrow_constructor(HasMove))]; }
-  { int arr[F(__has_nothrow_constructor(HasNoThrowConstructorWithArgs))]; }
-  { int arr[F(__has_nothrow_constructor(IntRef))]; }
-  { int arr[F(__has_nothrow_constructor(void))]; }
-  { int arr[F(__has_nothrow_constructor(cvoid))]; }
-  { int arr[F(__has_nothrow_constructor(HasTemplateCons))]; }
-
-  { int arr[F(__has_nothrow_constructor(HasMultipleDefaultConstructor1))]; }
-  { int arr[F(__has_nothrow_constructor(HasMultipleDefaultConstructor2))]; }
+  static_assert(__has_nothrow_constructor(Int));
+  static_assert(__has_nothrow_constructor(IntAr));
+  static_assert(__has_nothrow_constructor(Union));
+  static_assert(__has_nothrow_constructor(UnionAr));
+  static_assert(__has_nothrow_constructor(POD));
+  static_assert(__has_nothrow_constructor(Derives));
+  static_assert(__has_nothrow_constructor(DerivesAr));
+  static_assert(__has_nothrow_constructor(ConstIntAr));
+  static_assert(__has_nothrow_constructor(ConstIntArAr));
+  static_assert(__has_nothrow_constructor(HasDest));
+  static_assert(__has_nothrow_constructor(HasPriv));
+  static_assert(__has_nothrow_constructor(HasCopyAssign));
+  static_assert(__has_nothrow_constructor(const Int));
+  static_assert(__has_nothrow_constructor(HasNoThrowConstructor));
+  static_assert(__has_nothrow_constructor(HasVirtDest));
+  // static_assert(__has_nothrow_constructor(VirtAr)); // not implemented
+  static_assert(__has_nothrow_constructor(AllPrivate));
+  static_assert(__has_nothrow_constructor(ACompleteType[]));
+
+  static_assert(!__has_nothrow_constructor(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(!__has_nothrow_constructor(HasCons));
+  static_assert(!__has_nothrow_constructor(HasRef));
+  static_assert(!__has_nothrow_constructor(HasCopy));
+  static_assert(!__has_nothrow_constructor(HasMove));
+  static_assert(!__has_nothrow_constructor(HasNoThrowConstructorWithArgs));
+  static_assert(!__has_nothrow_constructor(IntRef));
+  static_assert(!__has_nothrow_constructor(void));
+  static_assert(!__has_nothrow_constructor(cvoid));
+  static_assert(!__has_nothrow_constructor(HasTemplateCons));
+
+  static_assert(!__has_nothrow_constructor(HasMultipleDefaultConstructor1));
+  static_assert(!__has_nothrow_constructor(HasMultipleDefaultConstructor2));
 }
 
 void has_virtual_destructor() {
-  { int arr[F(__has_virtual_destructor(Int))]; }
-  { int arr[F(__has_virtual_destructor(IntAr))]; }
-  { int arr[F(__has_virtual_destructor(Union))]; }
-  { int arr[F(__has_virtual_destructor(UnionAr))]; }
-  { int arr[F(__has_virtual_destructor(POD))]; }
-  { int arr[F(__has_virtual_destructor(Derives))]; }
-  { int arr[F(__has_virtual_destructor(DerivesAr))]; }
-  { int arr[F(__has_virtual_destructor(const Int))]; }
-  { int arr[F(__has_virtual_destructor(ConstIntAr))]; }
-  { int arr[F(__has_virtual_destructor(ConstIntArAr))]; }
-  { int arr[F(__has_virtual_destructor(HasDest))]; }
-  { int arr[F(__has_virtual_destructor(HasPriv))]; }
-  { int arr[F(__has_virtual_destructor(HasCons))]; }
-  { int arr[F(__has_virtual_destructor(HasRef))]; }
-  { int arr[F(__has_virtual_destructor(HasCopy))]; }
-  { int arr[F(__has_virtual_destructor(HasMove))]; }
-  { int arr[F(__has_virtual_destructor(HasCopyAssign))]; }
-  { int arr[F(__has_virtual_destructor(HasMoveAssign))]; }
-  { int arr[F(__has_virtual_destructor(IntRef))]; }
-  { int arr[F(__has_virtual_destructor(VirtAr))]; }
-  { int arr[F(__has_virtual_destructor(ACompleteType[]))]; }
-
-  { int arr[F(__has_virtual_destructor(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
-  { int arr[T(__has_virtual_destructor(HasVirtDest))]; }
-  { int arr[T(__has_virtual_destructor(DerivedVirtDest))]; }
-  { int arr[F(__has_virtual_destructor(VirtDestAr))]; }
-  { int arr[F(__has_virtual_destructor(void))]; }
-  { int arr[F(__has_virtual_destructor(cvoid))]; }
-  { int arr[F(__has_virtual_destructor(AllPrivate))]; }
+  static_assert(!__has_virtual_destructor(Int));
+  static_assert(!__has_virtual_destructor(IntAr));
+  static_assert(!__has_virtual_destructor(Union));
+  static_assert(!__has_virtual_destructor(UnionAr));
+  static_assert(!__has_virtual_destructor(POD));
+  static_assert(!__has_virtual_destructor(Derives));
+  static_assert(!__has_virtual_destructor(DerivesAr));
+  static_assert(!__has_virtual_destructor(const Int));
+  static_assert(!__has_virtual_destructor(ConstIntAr));
+  static_assert(!__has_virtual_destructor(ConstIntArAr));
+  static_assert(!__has_virtual_destructor(HasDest));
+  static_assert(!__has_virtual_destructor(HasPriv));
+  static_assert(!__has_virtual_destructor(HasCons));
+  static_assert(!__has_virtual_destructor(HasRef));
+  static_assert(!__has_virtual_destructor(HasCopy));
+  static_assert(!__has_virtual_destructor(HasMove));
+  static_assert(!__has_virtual_destructor(HasCopyAssign));
+  static_assert(!__has_virtual_destructor(HasMoveAssign));
+  static_assert(!__has_virtual_destructor(IntRef));
+  static_assert(!__has_virtual_destructor(VirtAr));
+  static_assert(!__has_virtual_destructor(ACompleteType[]));
+
+  static_assert(!__has_virtual_destructor(AnIncompleteType[])); // expected-error {{incomplete type}}
+  static_assert(__has_virtual_destructor(HasVirtDest));
+  static_assert(__has_virtual_destructor(DerivedVirtDest));
+  static_assert(!__has_virtual_destructor(VirtDestAr));
+  static_assert(!__has_virtual_destructor(void));
+  static_assert(!__has_virtual_destructor(cvoid));
+  static_assert(!__has_virtual_destructor(AllPrivate));
 }
 
 
@@ -2271,66 +2280,57 @@ template struct CrazyDerived : T { };
 
 class class_forward; // expected-note 2 {{forward declaration of 'class_forward'}}
 
-template 
-void isBaseOfT() {
-  int t[T(__is_base_of(Base, Derived))];
-};
-template 
-void isBaseOfF() {
-  int t[F(__is_base_of(Base, Derived))];
-};
-
 template  class DerivedTemp : Base {};
 template  class NonderivedTemp {};
 template  class UndefinedTemp; // expected-note {{declared here}}
 
 void is_base_of() {
-  { int arr[T(__is_base_of(Base, Derived))]; }
-  { int arr[T(__is_base_of(const Base, Derived))]; }
-  { int arr[F(__is_base_of(Derived, Base))]; }
-  { int arr[F(__is_base_of(Derived, int))]; }
-  { int arr[T(__is_base_of(Base, Base))]; }
-  { int arr[T(__is_base_of(Base, Derived3))]; }
-  { int arr[T(__is_base_of(Derived, Derived3))]; }
-  { int arr[T(__is_base_of(Derived2b, Derived3))]; }
-  { int arr[T(__is_base_of(Derived2a, Derived3))]; }
-  { int arr[T(__is_base_of(BaseA, DerivedB))]; }
-  { int arr[F(__is_base_of(DerivedB, BaseA))]; }
-  { int arr[T(__is_base_of(Base, CrazyDerived))]; }
-  { int arr[F(__is_base_of(Union, Union))]; }
-  { int arr[T(__is_base_of(Empty, Empty))]; }
-  { int arr[T(__is_base_of(class_forward, class_forward))]; }
-  { int arr[F(__is_base_of(Empty, class_forward))]; } // expected-error {{incomplete type 'class_forward' used in type trait expression}}
-  { int arr[F(__is_base_of(Base&, Derived&))]; }
-  int t18[F(__is_base_of(Base[10], Derived[10]))];
-  { int arr[F(__is_base_of(int, int))]; }
-  { int arr[F(__is_base_of(long, int))]; }
-  { int arr[T(__is_base_of(Base, DerivedTemp))]; }
-  { int arr[F(__is_base_of(Base, NonderivedTemp))]; }
-  { int arr[F(__is_base_of(Base, UndefinedTemp))]; } // expected-error {{implicit instantiation of undefined template 'UndefinedTemp'}}
-
-  { int arr[F(__is_base_of(IncompleteUnion, IncompleteUnion))]; }
-  { int arr[F(__is_base_of(Union, IncompleteUnion))]; }
-  { int arr[F(__is_base_of(IncompleteUnion, Union))]; }
-  { int arr[F(__is_base_of(IncompleteStruct, IncompleteUnion))]; }
-  { int arr[F(__is_base_of(IncompleteUnion, IncompleteStruct))]; }
-  { int arr[F(__is_base_of(Empty, IncompleteUnion))]; }
-  { int arr[F(__is_base_of(IncompleteUnion, Empty))]; }
-  { int arr[F(__is_base_of(int, IncompleteUnion))]; }
-  { int arr[F(__is_base_of(IncompleteUnion, int))]; }
-  { int arr[F(__is_base_of(Empty, Union))]; }
-  { int arr[F(__is_base_of(Union, Empty))]; }
-  { int arr[F(__is_base_of(int, Empty))]; }
-  { int arr[F(__is_base_of(Union, int))]; }
-
-  isBaseOfT();
-  isBaseOfF();
-
-  isBaseOfT >();
-  isBaseOfF, Base>();
-
-  isBaseOfT, DerivedB >();
-  isBaseOfF, BaseA >();
+  static_assert(__is_base_of(Base, Derived));
+  static_assert(__is_base_of(const Base, Derived));
+  static_assert(!__is_base_of(Derived, Base));
+  static_assert(!__is_base_of(Derived, int));
+  static_assert(__is_base_of(Base, Base));
+  static_assert(__is_base_of(Base, Derived3));
+  static_assert(__is_base_of(Derived, Derived3));
+  static_assert(__is_base_of(Derived2b, Derived3));
+  static_assert(__is_base_of(Derived2a, Derived3));
+  static_assert(__is_base_of(BaseA, DerivedB));
+  static_assert(!__is_base_of(DerivedB, BaseA));
+  static_assert(__is_base_of(Base, CrazyDerived));
+  static_assert(!__is_base_of(Union, Union));
+  static_assert(__is_base_of(Empty, Empty));
+  static_assert(__is_base_of(class_forward, class_forward));
+  static_assert(!__is_base_of(Empty, class_forward)); // expected-error {{incomplete type 'class_forward' used in type trait expression}}
+  static_assert(!__is_base_of(Base&, Derived&));
+  static_assert(!__is_base_of(Base[10], Derived[10]));
+  static_assert(!__is_base_of(int, int));
+  static_assert(!__is_base_of(long, int));
+  static_assert(__is_base_of(Base, DerivedTemp));
+  static_assert(!__is_base_of(Base, NonderivedTemp));
+  static_assert(!__is_base_of(Base, UndefinedTemp)); // expected-error {{implicit instantiation of undefined template 'UndefinedTemp'}}
+
+  static_assert(!__is_base_of(IncompleteUnion, IncompleteUnion));
+  static_assert(!__is_base_of(Union, IncompleteUnion));
+  static_assert(!__is_base_of(IncompleteUnion, Union));
+  static_assert(!__is_base_of(IncompleteStruct, IncompleteUnion));
+  static_assert(!__is_base_of(IncompleteUnion, IncompleteStruct));
+  static_assert(!__is_base_of(Empty, IncompleteUnion));
+  static_assert(!__is_base_of(IncompleteUnion, Empty));
+  static_assert(!__is_base_of(int, IncompleteUnion));
+  static_assert(!__is_base_of(IncompleteUnion, int));
+  static_assert(!__is_base_of(Empty, Union));
+  static_assert(!__is_base_of(Union, Empty));
+  static_assert(!__is_base_of(int, Empty));
+  static_assert(!__is_base_of(Union, int));
+
+  static_assert(__is_base_of(Base, Derived));
+  static_assert(!__is_base_of(Derived, Base));
+
+  static_assert(__is_base_of(Base, CrazyDerived));
+  static_assert(!__is_base_of(CrazyDerived, Base));
+
+  static_assert(__is_base_of(BaseA, DerivedB));
+  static_assert(!__is_base_of(DerivedB, BaseA));
 }
 
 template
@@ -2343,17 +2343,17 @@ typedef class Base BaseTypedef;
 
 void is_same()
 {
-  int t01[T(__is_same(Base, Base))];
-  int t02[T(__is_same(Base, BaseTypedef))];
-  int t03[T(__is_same(TemplateClass, TemplateAlias))];
+  static_assert(__is_same(Base, Base));
+  static_assert(__is_same(Base, BaseTypedef));
+  static_assert(__is_same(TemplateClass, TemplateAlias));
 
-  int t10[F(__is_same(Base, const Base))];
-  int t11[F(__is_same(Base, Base&))];
-  int t12[F(__is_same(Base, Derived))];
+  static_assert(!__is_same(Base, const Base));
+  static_assert(!__is_same(Base, Base&));
+  static_assert(!__is_same(Base, Derived));
 
   // __is_same_as is a GCC compatibility synonym for __is_same.
-  int t20[T(__is_same_as(int, int))];
-  int t21[F(__is_same_as(int, float))];
+  static_assert(__is_same_as(int, int));
+  static_assert(!__is_same_as(int, float));
 }
 
 struct IntWrapper
@@ -2381,26 +2381,26 @@ struct FloatWrapper
 
 void is_convertible()
 {
-  int t01[T(__is_convertible(IntWrapper, IntWrapper))];
-  int t02[T(__is_convertible(IntWrapper, const IntWrapper))];
-  int t03[T(__is_convertible(IntWrapper, int))];
-  int t04[T(__is_convertible(int, IntWrapper))];
-  int t05[T(__is_convertible(IntWrapper, FloatWrapper))];
-  int t06[T(__is_convertible(FloatWrapper, IntWrapper))];
-  int t07[T(__is_convertible(FloatWrapper, float))];
-  int t08[T(__is_convertible(float, FloatWrapper))];
+  static_assert(__is_convertible(IntWrapper, IntWrapper));
+  static_assert(__is_convertible(IntWrapper, const IntWrapper));
+  static_assert(__is_convertible(IntWrapper, int));
+  static_assert(__is_convertible(int, IntWrapper));
+  static_assert(__is_convertible(IntWrapper, FloatWrapper));
+  static_assert(__is_convertible(FloatWrapper, IntWrapper));
+  static_assert(__is_convertible(FloatWrapper, float));
+  static_assert(__is_convertible(float, FloatWrapper));
 }
 
 void is_nothrow_convertible()
 {
-  int t01[T(__is_nothrow_convertible(IntWrapper, IntWrapper))];
-  int t02[T(__is_nothrow_convertible(IntWrapper, const IntWrapper))];
-  int t03[T(__is_nothrow_convertible(IntWrapper, int))];
-  int t04[F(__is_nothrow_convertible(int, IntWrapper))];
-  int t05[F(__is_nothrow_convertible(IntWrapper, FloatWrapper))];
-  int t06[F(__is_nothrow_convertible(FloatWrapper, IntWrapper))];
-  int t07[F(__is_nothrow_convertible(FloatWrapper, float))];
-  int t08[T(__is_nothrow_convertible(float, FloatWrapper))];
+  static_assert(__is_nothrow_convertible(IntWrapper, IntWrapper));
+  static_assert(__is_nothrow_convertible(IntWrapper, const IntWrapper));
+  static_assert(__is_nothrow_convertible(IntWrapper, int));
+  static_assert(!__is_nothrow_convertible(int, IntWrapper));
+  static_assert(!__is_nothrow_convertible(IntWrapper, FloatWrapper));
+  static_assert(!__is_nothrow_convertible(FloatWrapper, IntWrapper));
+  static_assert(!__is_nothrow_convertible(FloatWrapper, float));
+  static_assert(__is_nothrow_convertible(float, FloatWrapper));
 }
 
 struct FromInt { FromInt(int); };
@@ -2421,30 +2421,30 @@ struct X0 {
 struct Abstract { virtual void f() = 0; };
 
 void is_convertible_to() {
-  { int arr[T(__is_convertible_to(Int, Int))]; }
-  { int arr[F(__is_convertible_to(Int, IntAr))]; }
-  { int arr[F(__is_convertible_to(IntAr, IntAr))]; }
-  { int arr[T(__is_convertible_to(void, void))]; }
-  { int arr[T(__is_convertible_to(cvoid, void))]; }
-  { int arr[T(__is_convertible_to(void, cvoid))]; }
-  { int arr[T(__is_convertible_to(cvoid, cvoid))]; }
-  { int arr[T(__is_convertible_to(int, FromInt))]; }
-  { int arr[T(__is_convertible_to(long, FromInt))]; }
-  { int arr[T(__is_convertible_to(double, FromInt))]; }
-  { int arr[T(__is_convertible_to(const int, FromInt))]; }
-  { int arr[T(__is_convertible_to(const int&, FromInt))]; }
-  { int arr[T(__is_convertible_to(ToInt, int))]; }
-  { int arr[T(__is_convertible_to(ToInt, const int&))]; }
-  { int arr[T(__is_convertible_to(ToInt, long))]; }
-  { int arr[F(__is_convertible_to(ToInt, int&))]; }
-  { int arr[F(__is_convertible_to(ToInt, FromInt))]; }
-  { int arr[T(__is_convertible_to(IntAr&, IntAr&))]; }
-  { int arr[T(__is_convertible_to(IntAr&, const IntAr&))]; }
-  { int arr[F(__is_convertible_to(const IntAr&, IntAr&))]; }
-  { int arr[F(__is_convertible_to(Function, Function))]; }
-  { int arr[F(__is_convertible_to(PrivateCopy, PrivateCopy))]; }
-  { int arr[T(__is_convertible_to(X0, X0))]; }
-  { int arr[F(__is_convertible_to(Abstract, Abstract))]; }
+  static_assert(__is_convertible_to(Int, Int));
+  static_assert(!__is_convertible_to(Int, IntAr));
+  static_assert(!__is_convertible_to(IntAr, IntAr));
+  static_assert(__is_convertible_to(void, void));
+  static_assert(__is_convertible_to(cvoid, void));
+  static_assert(__is_convertible_to(void, cvoid));
+  static_assert(__is_convertible_to(cvoid, cvoid));
+  static_assert(__is_convertible_to(int, FromInt));
+  static_assert(__is_convertible_to(long, FromInt));
+  static_assert(__is_convertible_to(double, FromInt));
+  static_assert(__is_convertible_to(const int, FromInt));
+  static_assert(__is_convertible_to(const int&, FromInt));
+  static_assert(__is_convertible_to(ToInt, int));
+  static_assert(__is_convertible_to(ToInt, const int&));
+  static_assert(__is_convertible_to(ToInt, long));
+  static_assert(!__is_convertible_to(ToInt, int&));
+  static_assert(!__is_convertible_to(ToInt, FromInt));
+  static_assert(__is_convertible_to(IntAr&, IntAr&));
+  static_assert(__is_convertible_to(IntAr&, const IntAr&));
+  static_assert(!__is_convertible_to(const IntAr&, IntAr&));
+  static_assert(!__is_convertible_to(Function, Function));
+  static_assert(!__is_convertible_to(PrivateCopy, PrivateCopy));
+  static_assert(__is_convertible_to(X0, X0));
+  static_assert(!__is_convertible_to(Abstract, Abstract));
 }
 
 namespace is_convertible_to_instantiate {
@@ -2455,269 +2455,269 @@ namespace is_convertible_to_instantiate {
 
 void is_trivial()
 {
-  { int arr[T(__is_trivial(int))]; }
-  { int arr[T(__is_trivial(Enum))]; }
-  { int arr[T(__is_trivial(POD))]; }
-  { int arr[T(__is_trivial(Int))]; }
-  { int arr[T(__is_trivial(IntAr))]; }
-  { int arr[T(__is_trivial(IntArNB))]; }
-  { int arr[T(__is_trivial(Statics))]; }
-  { int arr[T(__is_trivial(Empty))]; }
-  { int arr[T(__is_trivial(EmptyUnion))]; }
-  { int arr[T(__is_trivial(Union))]; }
-  { int arr[T(__is_trivial(Derives))]; }
-  { int arr[T(__is_trivial(DerivesAr))]; }
-  { int arr[T(__is_trivial(DerivesArNB))]; }
-  { int arr[T(__is_trivial(DerivesEmpty))]; }
-  { int arr[T(__is_trivial(HasFunc))]; }
-  { int arr[T(__is_trivial(HasOp))]; }
-  { int arr[T(__is_trivial(HasConv))]; }
-  { int arr[T(__is_trivial(HasAssign))]; }
-  { int arr[T(__is_trivial(HasAnonymousUnion))]; }
-  { int arr[T(__is_trivial(HasPriv))]; }
-  { int arr[T(__is_trivial(HasProt))]; }
-  { int arr[T(__is_trivial(DerivesHasPriv))]; }
-  { int arr[T(__is_trivial(DerivesHasProt))]; }
-  { int arr[T(__is_trivial(Vector))]; }
-  { int arr[T(__is_trivial(VectorExt))]; }
-
-  { int arr[F(__is_trivial(HasCons))]; }
-  { int arr[F(__is_trivial(HasCopyAssign))]; }
-  { int arr[F(__is_trivial(HasMoveAssign))]; }
-  { int arr[F(__is_trivial(HasDest))]; }
-  { int arr[F(__is_trivial(HasRef))]; }
-  { int arr[F(__is_trivial(HasNonPOD))]; }
-  { int arr[F(__is_trivial(HasVirt))]; }
-  { int arr[F(__is_trivial(DerivesHasCons))]; }
-  { int arr[F(__is_trivial(DerivesHasCopyAssign))]; }
-  { int arr[F(__is_trivial(DerivesHasMoveAssign))]; }
-  { int arr[F(__is_trivial(DerivesHasDest))]; }
-  { int arr[F(__is_trivial(DerivesHasRef))]; }
-  { int arr[F(__is_trivial(DerivesHasVirt))]; }
-  { int arr[F(__is_trivial(void))]; }
-  { int arr[F(__is_trivial(cvoid))]; }
+  static_assert(__is_trivial(int));
+  static_assert(__is_trivial(Enum));
+  static_assert(__is_trivial(POD));
+  static_assert(__is_trivial(Int));
+  static_assert(__is_trivial(IntAr));
+  static_assert(__is_trivial(IntArNB));
+  static_assert(__is_trivial(Statics));
+  static_assert(__is_trivial(Empty));
+  static_assert(__is_trivial(EmptyUnion));
+  static_assert(__is_trivial(Union));
+  static_assert(__is_trivial(Derives));
+  static_assert(__is_trivial(DerivesAr));
+  static_assert(__is_trivial(DerivesArNB));
+  static_assert(__is_trivial(DerivesEmpty));
+  static_assert(__is_trivial(HasFunc));
+  static_assert(__is_trivial(HasOp));
+  static_assert(__is_trivial(HasConv));
+  static_assert(__is_trivial(HasAssign));
+  static_assert(__is_trivial(HasAnonymousUnion));
+  static_assert(__is_trivial(HasPriv));
+  static_assert(__is_trivial(HasProt));
+  static_assert(__is_trivial(DerivesHasPriv));
+  static_assert(__is_trivial(DerivesHasProt));
+  static_assert(__is_trivial(Vector));
+  static_assert(__is_trivial(VectorExt));
+
+  static_assert(!__is_trivial(HasCons));
+  static_assert(!__is_trivial(HasCopyAssign));
+  static_assert(!__is_trivial(HasMoveAssign));
+  static_assert(!__is_trivial(HasDest));
+  static_assert(!__is_trivial(HasRef));
+  static_assert(!__is_trivial(HasNonPOD));
+  static_assert(!__is_trivial(HasVirt));
+  static_assert(!__is_trivial(DerivesHasCons));
+  static_assert(!__is_trivial(DerivesHasCopyAssign));
+  static_assert(!__is_trivial(DerivesHasMoveAssign));
+  static_assert(!__is_trivial(DerivesHasDest));
+  static_assert(!__is_trivial(DerivesHasRef));
+  static_assert(!__is_trivial(DerivesHasVirt));
+  static_assert(!__is_trivial(void));
+  static_assert(!__is_trivial(cvoid));
 }
 
 template struct TriviallyConstructibleTemplate {};
 
 void trivial_checks()
 {
-  { int arr[T(__is_trivially_copyable(int))]; }
-  { int arr[T(__is_trivially_copyable(Enum))]; }
-  { int arr[T(__is_trivially_copyable(POD))]; }
-  { int arr[T(__is_trivially_copyable(Int))]; }
-  { int arr[T(__is_trivially_copyable(IntAr))]; }
-  { int arr[T(__is_trivially_copyable(IntArNB))]; }
-  { int arr[T(__is_trivially_copyable(Statics))]; }
-  { int arr[T(__is_trivially_copyable(Empty))]; }
-  { int arr[T(__is_trivially_copyable(EmptyUnion))]; }
-  { int arr[T(__is_trivially_copyable(Union))]; }
-  { int arr[T(__is_trivially_copyable(Derives))]; }
-  { int arr[T(__is_trivially_copyable(DerivesAr))]; }
-  { int arr[T(__is_trivially_copyable(DerivesArNB))]; }
-  { int arr[T(__is_trivially_copyable(DerivesEmpty))]; }
-  { int arr[T(__is_trivially_copyable(HasFunc))]; }
-  { int arr[T(__is_trivially_copyable(HasOp))]; }
-  { int arr[T(__is_trivially_copyable(HasConv))]; }
-  { int arr[T(__is_trivially_copyable(HasAssign))]; }
-  { int arr[T(__is_trivially_copyable(HasAnonymousUnion))]; }
-  { int arr[T(__is_trivially_copyable(HasPriv))]; }
-  { int arr[T(__is_trivially_copyable(HasProt))]; }
-  { int arr[T(__is_trivially_copyable(DerivesHasPriv))]; }
-  { int arr[T(__is_trivially_copyable(DerivesHasProt))]; }
-  { int arr[T(__is_trivially_copyable(Vector))]; }
-  { int arr[T(__is_trivially_copyable(VectorExt))]; }
-  { int arr[T(__is_trivially_copyable(HasCons))]; }
-  { int arr[T(__is_trivially_copyable(HasRef))]; }
-  { int arr[T(__is_trivially_copyable(HasNonPOD))]; }
-  { int arr[T(__is_trivially_copyable(DerivesHasCons))]; }
-  { int arr[T(__is_trivially_copyable(DerivesHasRef))]; }
-  { int arr[T(__is_trivially_copyable(NonTrivialDefault))]; }
-  { int arr[T(__is_trivially_copyable(NonTrivialDefault[]))]; }
-  { int arr[T(__is_trivially_copyable(NonTrivialDefault[3]))]; }
-
-  { int arr[F(__is_trivially_copyable(HasCopyAssign))]; }
-  { int arr[F(__is_trivially_copyable(HasMoveAssign))]; }
-  { int arr[F(__is_trivially_copyable(HasDest))]; }
-  { int arr[F(__is_trivially_copyable(HasVirt))]; }
-  { int arr[F(__is_trivially_copyable(DerivesHasCopyAssign))]; }
-  { int arr[F(__is_trivially_copyable(DerivesHasMoveAssign))]; }
-  { int arr[F(__is_trivially_copyable(DerivesHasDest))]; }
-  { int arr[F(__is_trivially_copyable(DerivesHasVirt))]; }
-  { int arr[F(__is_trivially_copyable(void))]; }
-  { int arr[F(__is_trivially_copyable(cvoid))]; }
-
-  { int arr[T((__is_trivially_constructible(int)))]; }
-  { int arr[T((__is_trivially_constructible(int, int)))]; }
-  { int arr[T((__is_trivially_constructible(int, float)))]; }
-  { int arr[T((__is_trivially_constructible(int, int&)))]; }
-  { int arr[T((__is_trivially_constructible(int, const int&)))]; }
-  { int arr[T((__is_trivially_constructible(int, int)))]; }
-  { int arr[T((__is_trivially_constructible(HasCopyAssign, HasCopyAssign)))]; }
-  { int arr[T((__is_trivially_constructible(HasCopyAssign, const HasCopyAssign&)))]; }
-  { int arr[T((__is_trivially_constructible(HasCopyAssign, HasCopyAssign&&)))]; }
-  { int arr[T((__is_trivially_constructible(HasCopyAssign)))]; }
-  { int arr[T((__is_trivially_constructible(NonTrivialDefault,
-                                            const NonTrivialDefault&)))]; }
-  { int arr[T((__is_trivially_constructible(NonTrivialDefault,
-                                            NonTrivialDefault&&)))]; }
-  { int arr[T((__is_trivially_constructible(AllDefaulted)))]; }
-  { int arr[T((__is_trivially_constructible(AllDefaulted,
-                                            const AllDefaulted &)))]; }
-  { int arr[T((__is_trivially_constructible(AllDefaulted,
-                                            AllDefaulted &&)))]; }
-
-  { int arr[F((__is_trivially_constructible(int, int*)))]; }
-  { int arr[F((__is_trivially_constructible(NonTrivialDefault)))]; }
-  { int arr[F((__is_trivially_constructible(ThreeArgCtor, int*, char*, int&)))]; }
-  { int arr[F((__is_trivially_constructible(AllDeleted)))]; }
-  { int arr[F((__is_trivially_constructible(AllDeleted,
-                                            const AllDeleted &)))]; }
-  { int arr[F((__is_trivially_constructible(AllDeleted,
-                                            AllDeleted &&)))]; }
-  { int arr[F((__is_trivially_constructible(ExtDefaulted)))]; }
-  { int arr[F((__is_trivially_constructible(ExtDefaulted,
-                                            const ExtDefaulted &)))]; }
-  { int arr[F((__is_trivially_constructible(ExtDefaulted,
-                                            ExtDefaulted &&)))]; }
-
-  { int arr[T((__is_trivially_constructible(TriviallyConstructibleTemplate)))]; }
-  { int arr[F((__is_trivially_constructible(class_forward)))]; } // expected-error {{incomplete type 'class_forward' used in type trait expression}}
-  { int arr[F((__is_trivially_constructible(class_forward[])))]; }
-  { int arr[F((__is_trivially_constructible(void)))]; }
-
-  { int arr[T((__is_trivially_assignable(int&, int)))]; }
-  { int arr[T((__is_trivially_assignable(int&, int&)))]; }
-  { int arr[T((__is_trivially_assignable(int&, int&&)))]; }
-  { int arr[T((__is_trivially_assignable(int&, const int&)))]; }
-  { int arr[T((__is_trivially_assignable(POD&, POD)))]; }
-  { int arr[T((__is_trivially_assignable(POD&, POD&)))]; }
-  { int arr[T((__is_trivially_assignable(POD&, POD&&)))]; }
-  { int arr[T((__is_trivially_assignable(POD&, const POD&)))]; }
-  { int arr[T((__is_trivially_assignable(int*&, int*)))]; }
-  { int arr[T((__is_trivially_assignable(AllDefaulted,
-                                         const AllDefaulted &)))]; }
-  { int arr[T((__is_trivially_assignable(AllDefaulted,
-                                         AllDefaulted &&)))]; }
-
-  { int arr[F((__is_trivially_assignable(int*&, float*)))]; }
-  { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign)))]; }
-  { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign&)))]; }
-  { int arr[F((__is_trivially_assignable(HasCopyAssign&, const HasCopyAssign&)))]; }
-  { int arr[F((__is_trivially_assignable(HasCopyAssign&, HasCopyAssign&&)))]; }
-  { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&,
-                                        TrivialMoveButNotCopy&)))]; }
-  { int arr[F((__is_trivially_assignable(TrivialMoveButNotCopy&,
-                                        const TrivialMoveButNotCopy&)))]; }
-  { int arr[F((__is_trivially_assignable(AllDeleted,
-                                         const AllDeleted &)))]; }
-  { int arr[F((__is_trivially_assignable(AllDeleted,
-                                         AllDeleted &&)))]; }
-  { int arr[F((__is_trivially_assignable(ExtDefaulted,
-                                         const ExtDefaulted &)))]; }
-  { int arr[F((__is_trivially_assignable(ExtDefaulted,
-                                         ExtDefaulted &&)))]; }
-
-  { int arr[T((__is_trivially_assignable(HasDefaultTrivialCopyAssign&,
-                                         HasDefaultTrivialCopyAssign&)))]; }
-  { int arr[T((__is_trivially_assignable(HasDefaultTrivialCopyAssign&,
-                                       const HasDefaultTrivialCopyAssign&)))]; }
-  { int arr[T((__is_trivially_assignable(TrivialMoveButNotCopy&,
-                                         TrivialMoveButNotCopy)))]; }
-  { int arr[T((__is_trivially_assignable(TrivialMoveButNotCopy&,
-                                         TrivialMoveButNotCopy&&)))]; }
-  { int arr[T((__is_trivially_assignable(int&, int)))]; }
-  { int arr[T((__is_trivially_assignable(int&, int&)))]; }
-  { int arr[T((__is_trivially_assignable(int&, int&&)))]; }
-  { int arr[T((__is_trivially_assignable(int&, const int&)))]; }
-  { int arr[T((__is_trivially_assignable(POD&, POD)))]; }
-  { int arr[T((__is_trivially_assignable(POD&, POD&)))]; }
-  { int arr[T((__is_trivially_assignable(POD&, POD&&)))]; }
-  { int arr[T((__is_trivially_assignable(POD&, const POD&)))]; }
-  { int arr[T((__is_trivially_assignable(int*&, int*)))]; }
-  { int arr[T((__is_trivially_assignable(AllDefaulted,
-                                         const AllDefaulted &)))]; }
-  { int arr[T((__is_trivially_assignable(AllDefaulted,
-                                         AllDefaulted &&)))]; }
-
-  { int arr[F((__is_assignable(int *&, float *)))]; }
-  { int arr[T((__is_assignable(HasCopyAssign &, HasCopyAssign)))]; }
-  { int arr[T((__is_assignable(HasCopyAssign &, HasCopyAssign &)))]; }
-  { int arr[T((__is_assignable(HasCopyAssign &, const HasCopyAssign &)))]; }
-  { int arr[T((__is_assignable(HasCopyAssign &, HasCopyAssign &&)))]; }
-  { int arr[T((__is_assignable(TrivialMoveButNotCopy &,
-                               TrivialMoveButNotCopy &)))]; }
-  { int arr[T((__is_assignable(TrivialMoveButNotCopy &,
-                               const TrivialMoveButNotCopy &)))]; }
-  { int arr[F((__is_assignable(AllDeleted,
-                               const AllDeleted &)))]; }
-  { int arr[F((__is_assignable(AllDeleted,
-                               AllDeleted &&)))]; }
-  { int arr[T((__is_assignable(ExtDefaulted,
-                               const ExtDefaulted &)))]; }
-  { int arr[T((__is_assignable(ExtDefaulted,
-                               ExtDefaulted &&)))]; }
-
-  { int arr[T((__is_assignable(HasDefaultTrivialCopyAssign &,
-                               HasDefaultTrivialCopyAssign &)))]; }
-  { int arr[T((__is_assignable(HasDefaultTrivialCopyAssign &,
-                               const HasDefaultTrivialCopyAssign &)))]; }
-  { int arr[T((__is_assignable(TrivialMoveButNotCopy &,
-                               TrivialMoveButNotCopy)))]; }
-  { int arr[T((__is_assignable(TrivialMoveButNotCopy &,
-                               TrivialMoveButNotCopy &&)))]; }
-
-  { int arr[T(__is_assignable(ACompleteType, ACompleteType))]; }
-  { int arr[F(__is_assignable(AnIncompleteType, AnIncompleteType))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_assignable(AnIncompleteType[], AnIncompleteType[]))]; }
-  { int arr[F(__is_assignable(AnIncompleteType[1], AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_assignable(void, void))]; }
-  { int arr[F(__is_assignable(const volatile void, const volatile void))]; }
+  static_assert(__is_trivially_copyable(int));
+  static_assert(__is_trivially_copyable(Enum));
+  static_assert(__is_trivially_copyable(POD));
+  static_assert(__is_trivially_copyable(Int));
+  static_assert(__is_trivially_copyable(IntAr));
+  static_assert(__is_trivially_copyable(IntArNB));
+  static_assert(__is_trivially_copyable(Statics));
+  static_assert(__is_trivially_copyable(Empty));
+  static_assert(__is_trivially_copyable(EmptyUnion));
+  static_assert(__is_trivially_copyable(Union));
+  static_assert(__is_trivially_copyable(Derives));
+  static_assert(__is_trivially_copyable(DerivesAr));
+  static_assert(__is_trivially_copyable(DerivesArNB));
+  static_assert(__is_trivially_copyable(DerivesEmpty));
+  static_assert(__is_trivially_copyable(HasFunc));
+  static_assert(__is_trivially_copyable(HasOp));
+  static_assert(__is_trivially_copyable(HasConv));
+  static_assert(__is_trivially_copyable(HasAssign));
+  static_assert(__is_trivially_copyable(HasAnonymousUnion));
+  static_assert(__is_trivially_copyable(HasPriv));
+  static_assert(__is_trivially_copyable(HasProt));
+  static_assert(__is_trivially_copyable(DerivesHasPriv));
+  static_assert(__is_trivially_copyable(DerivesHasProt));
+  static_assert(__is_trivially_copyable(Vector));
+  static_assert(__is_trivially_copyable(VectorExt));
+  static_assert(__is_trivially_copyable(HasCons));
+  static_assert(__is_trivially_copyable(HasRef));
+  static_assert(__is_trivially_copyable(HasNonPOD));
+  static_assert(__is_trivially_copyable(DerivesHasCons));
+  static_assert(__is_trivially_copyable(DerivesHasRef));
+  static_assert(__is_trivially_copyable(NonTrivialDefault));
+  static_assert(__is_trivially_copyable(NonTrivialDefault[]));
+  static_assert(__is_trivially_copyable(NonTrivialDefault[3]));
+
+  static_assert(!__is_trivially_copyable(HasCopyAssign));
+  static_assert(!__is_trivially_copyable(HasMoveAssign));
+  static_assert(!__is_trivially_copyable(HasDest));
+  static_assert(!__is_trivially_copyable(HasVirt));
+  static_assert(!__is_trivially_copyable(DerivesHasCopyAssign));
+  static_assert(!__is_trivially_copyable(DerivesHasMoveAssign));
+  static_assert(!__is_trivially_copyable(DerivesHasDest));
+  static_assert(!__is_trivially_copyable(DerivesHasVirt));
+  static_assert(!__is_trivially_copyable(void));
+  static_assert(!__is_trivially_copyable(cvoid));
+
+  static_assert((__is_trivially_constructible(int)));
+  static_assert((__is_trivially_constructible(int, int)));
+  static_assert((__is_trivially_constructible(int, float)));
+  static_assert((__is_trivially_constructible(int, int&)));
+  static_assert((__is_trivially_constructible(int, const int&)));
+  static_assert((__is_trivially_constructible(int, int)));
+  static_assert((__is_trivially_constructible(HasCopyAssign, HasCopyAssign)));
+  static_assert((__is_trivially_constructible(HasCopyAssign, const HasCopyAssign&)));
+  static_assert((__is_trivially_constructible(HasCopyAssign, HasCopyAssign&&)));
+  static_assert((__is_trivially_constructible(HasCopyAssign)));
+  static_assert((__is_trivially_constructible(NonTrivialDefault,
+                                            const NonTrivialDefault&)));
+  static_assert((__is_trivially_constructible(NonTrivialDefault,
+                                            NonTrivialDefault&&)));
+  static_assert((__is_trivially_constructible(AllDefaulted)));
+  static_assert((__is_trivially_constructible(AllDefaulted,
+                                            const AllDefaulted &)));
+  static_assert((__is_trivially_constructible(AllDefaulted,
+                                            AllDefaulted &&)));
+
+  static_assert(!(__is_trivially_constructible(int, int*)));
+  static_assert(!(__is_trivially_constructible(NonTrivialDefault)));
+  static_assert(!(__is_trivially_constructible(ThreeArgCtor, int*, char*, int&)));
+  static_assert(!(__is_trivially_constructible(AllDeleted)));
+  static_assert(!(__is_trivially_constructible(AllDeleted,
+                                            const AllDeleted &)));
+  static_assert(!(__is_trivially_constructible(AllDeleted,
+                                            AllDeleted &&)));
+  static_assert(!(__is_trivially_constructible(ExtDefaulted)));
+  static_assert(!(__is_trivially_constructible(ExtDefaulted,
+                                            const ExtDefaulted &)));
+  static_assert(!(__is_trivially_constructible(ExtDefaulted,
+                                            ExtDefaulted &&)));
+
+  static_assert((__is_trivially_constructible(TriviallyConstructibleTemplate)));
+  static_assert(!(__is_trivially_constructible(class_forward))); // expected-error {{incomplete type 'class_forward' used in type trait expression}}
+  static_assert(!(__is_trivially_constructible(class_forward[])));
+  static_assert(!(__is_trivially_constructible(void)));
+
+  static_assert((__is_trivially_assignable(int&, int)));
+  static_assert((__is_trivially_assignable(int&, int&)));
+  static_assert((__is_trivially_assignable(int&, int&&)));
+  static_assert((__is_trivially_assignable(int&, const int&)));
+  static_assert((__is_trivially_assignable(POD&, POD)));
+  static_assert((__is_trivially_assignable(POD&, POD&)));
+  static_assert((__is_trivially_assignable(POD&, POD&&)));
+  static_assert((__is_trivially_assignable(POD&, const POD&)));
+  static_assert((__is_trivially_assignable(int*&, int*)));
+  static_assert((__is_trivially_assignable(AllDefaulted,
+                                         const AllDefaulted &)));
+  static_assert((__is_trivially_assignable(AllDefaulted,
+                                         AllDefaulted &&)));
+
+  static_assert(!(__is_trivially_assignable(int*&, float*)));
+  static_assert(!(__is_trivially_assignable(HasCopyAssign&, HasCopyAssign)));
+  static_assert(!(__is_trivially_assignable(HasCopyAssign&, HasCopyAssign&)));
+  static_assert(!(__is_trivially_assignable(HasCopyAssign&, const HasCopyAssign&)));
+  static_assert(!(__is_trivially_assignable(HasCopyAssign&, HasCopyAssign&&)));
+  static_assert(!(__is_trivially_assignable(TrivialMoveButNotCopy&,
+                                        TrivialMoveButNotCopy&)));
+  static_assert(!(__is_trivially_assignable(TrivialMoveButNotCopy&,
+                                        const TrivialMoveButNotCopy&)));
+  static_assert(!(__is_trivially_assignable(AllDeleted,
+                                         const AllDeleted &)));
+  static_assert(!(__is_trivially_assignable(AllDeleted,
+                                         AllDeleted &&)));
+  static_assert(!(__is_trivially_assignable(ExtDefaulted,
+                                         const ExtDefaulted &)));
+  static_assert(!(__is_trivially_assignable(ExtDefaulted,
+                                         ExtDefaulted &&)));
+
+  static_assert((__is_trivially_assignable(HasDefaultTrivialCopyAssign&,
+                                         HasDefaultTrivialCopyAssign&)));
+  static_assert((__is_trivially_assignable(HasDefaultTrivialCopyAssign&,
+                                       const HasDefaultTrivialCopyAssign&)));
+  static_assert((__is_trivially_assignable(TrivialMoveButNotCopy&,
+                                         TrivialMoveButNotCopy)));
+  static_assert((__is_trivially_assignable(TrivialMoveButNotCopy&,
+                                         TrivialMoveButNotCopy&&)));
+  static_assert((__is_trivially_assignable(int&, int)));
+  static_assert((__is_trivially_assignable(int&, int&)));
+  static_assert((__is_trivially_assignable(int&, int&&)));
+  static_assert((__is_trivially_assignable(int&, const int&)));
+  static_assert((__is_trivially_assignable(POD&, POD)));
+  static_assert((__is_trivially_assignable(POD&, POD&)));
+  static_assert((__is_trivially_assignable(POD&, POD&&)));
+  static_assert((__is_trivially_assignable(POD&, const POD&)));
+  static_assert((__is_trivially_assignable(int*&, int*)));
+  static_assert((__is_trivially_assignable(AllDefaulted,
+                                         const AllDefaulted &)));
+  static_assert((__is_trivially_assignable(AllDefaulted,
+                                         AllDefaulted &&)));
+
+  static_assert(!(__is_assignable(int *&, float *)));
+  static_assert((__is_assignable(HasCopyAssign &, HasCopyAssign)));
+  static_assert((__is_assignable(HasCopyAssign &, HasCopyAssign &)));
+  static_assert((__is_assignable(HasCopyAssign &, const HasCopyAssign &)));
+  static_assert((__is_assignable(HasCopyAssign &, HasCopyAssign &&)));
+  static_assert((__is_assignable(TrivialMoveButNotCopy &,
+                               TrivialMoveButNotCopy &)));
+  static_assert((__is_assignable(TrivialMoveButNotCopy &,
+                               const TrivialMoveButNotCopy &)));
+  static_assert(!(__is_assignable(AllDeleted,
+                               const AllDeleted &)));
+  static_assert(!(__is_assignable(AllDeleted,
+                               AllDeleted &&)));
+  static_assert((__is_assignable(ExtDefaulted,
+                               const ExtDefaulted &)));
+  static_assert((__is_assignable(ExtDefaulted,
+                               ExtDefaulted &&)));
+
+  static_assert((__is_assignable(HasDefaultTrivialCopyAssign &,
+                               HasDefaultTrivialCopyAssign &)));
+  static_assert((__is_assignable(HasDefaultTrivialCopyAssign &,
+                               const HasDefaultTrivialCopyAssign &)));
+  static_assert((__is_assignable(TrivialMoveButNotCopy &,
+                               TrivialMoveButNotCopy)));
+  static_assert((__is_assignable(TrivialMoveButNotCopy &,
+                               TrivialMoveButNotCopy &&)));
+
+  static_assert(__is_assignable(ACompleteType, ACompleteType));
+  static_assert(!__is_assignable(AnIncompleteType, AnIncompleteType)); // expected-error {{incomplete type}}
+  static_assert(!__is_assignable(AnIncompleteType[], AnIncompleteType[]));
+  static_assert(!__is_assignable(AnIncompleteType[1], AnIncompleteType[1])); // expected-error {{incomplete type}}
+  static_assert(!__is_assignable(void, void));
+  static_assert(!__is_assignable(const volatile void, const volatile void));
 }
 
 void constructible_checks() {
-  { int arr[T(__is_constructible(HasNoThrowConstructorWithArgs))]; }
-  { int arr[F(__is_nothrow_constructible(HasNoThrowConstructorWithArgs))]; } // MSVC doesn't look into default args and gets this wrong.
+  static_assert(__is_constructible(HasNoThrowConstructorWithArgs));
+  static_assert(!__is_nothrow_constructible(HasNoThrowConstructorWithArgs)); // MSVC doesn't look into default args and gets this wrong.
 
-  { int arr[T(__is_constructible(HasNoThrowConstructorWithArgs, HasCons))]; }
-  { int arr[T(__is_nothrow_constructible(HasNoThrowConstructorWithArgs, HasCons))]; }
+  static_assert(__is_constructible(HasNoThrowConstructorWithArgs, HasCons));
+  static_assert(__is_nothrow_constructible(HasNoThrowConstructorWithArgs, HasCons));
 
-  { int arr[T(__is_constructible(NonTrivialDefault))]; }
-  { int arr[F(__is_nothrow_constructible(NonTrivialDefault))]; }
+  static_assert(__is_constructible(NonTrivialDefault));
+  static_assert(!__is_nothrow_constructible(NonTrivialDefault));
 
-  { int arr[T(__is_constructible(int))]; }
-  { int arr[T(__is_nothrow_constructible(int))]; }
+  static_assert(__is_constructible(int));
+  static_assert(__is_nothrow_constructible(int));
 
-  { int arr[F(__is_constructible(NonPOD))]; }
-  { int arr[F(__is_nothrow_constructible(NonPOD))]; }
+  static_assert(!__is_constructible(NonPOD));
+  static_assert(!__is_nothrow_constructible(NonPOD));
 
-  { int arr[T(__is_constructible(NonPOD, int))]; }
-  { int arr[F(__is_nothrow_constructible(NonPOD, int))]; }
+  static_assert(__is_constructible(NonPOD, int));
+  static_assert(!__is_nothrow_constructible(NonPOD, int));
 
   // PR19178
-  { int arr[F(__is_constructible(Abstract))]; }
-  { int arr[F(__is_nothrow_constructible(Abstract))]; }
+  static_assert(!__is_constructible(Abstract));
+  static_assert(!__is_nothrow_constructible(Abstract));
 
   // PR20228
-  { int arr[T(__is_constructible(VariadicCtor,
-                                 int, int, int, int, int, int, int, int, int))]; }
+  static_assert(__is_constructible(VariadicCtor,
+                                 int, int, int, int, int, int, int, int, int));
 
   // PR25513
-  { int arr[F(__is_constructible(int(int)))]; }
-  { int arr[T(__is_constructible(int const &, long))]; }
-
-  { int arr[T(__is_constructible(ACompleteType))]; }
-  { int arr[T(__is_nothrow_constructible(ACompleteType))]; }
-  { int arr[F(__is_constructible(AnIncompleteType))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_nothrow_constructible(AnIncompleteType))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_constructible(AnIncompleteType[]))]; }
-  { int arr[F(__is_nothrow_constructible(AnIncompleteType[]))]; }
-  { int arr[F(__is_constructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_nothrow_constructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_constructible(void))]; }
-  { int arr[F(__is_nothrow_constructible(void))]; }
-  { int arr[F(__is_constructible(const volatile void))]; }
-  { int arr[F(__is_nothrow_constructible(const volatile void))]; }
+  static_assert(!__is_constructible(int(int)));
+  static_assert(__is_constructible(int const &, long));
+
+  static_assert(__is_constructible(ACompleteType));
+  static_assert(__is_nothrow_constructible(ACompleteType));
+  static_assert(!__is_constructible(AnIncompleteType)); // expected-error {{incomplete type}}
+  static_assert(!__is_nothrow_constructible(AnIncompleteType)); // expected-error {{incomplete type}}
+  static_assert(!__is_constructible(AnIncompleteType[]));
+  static_assert(!__is_nothrow_constructible(AnIncompleteType[]));
+  static_assert(!__is_constructible(AnIncompleteType[1])); // expected-error {{incomplete type}}
+  static_assert(!__is_nothrow_constructible(AnIncompleteType[1])); // expected-error {{incomplete type}}
+  static_assert(!__is_constructible(void));
+  static_assert(!__is_nothrow_constructible(void));
+  static_assert(!__is_constructible(const volatile void));
+  static_assert(!__is_nothrow_constructible(const volatile void));
 }
 
 // Instantiation of __is_trivially_constructible
@@ -2727,32 +2727,32 @@ struct is_trivially_constructible {
 };
 
 void is_trivially_constructible_test() {
-  { int arr[T((is_trivially_constructible::value))]; }
-  { int arr[T((is_trivially_constructible::value))]; }
-  { int arr[T((is_trivially_constructible::value))]; }
-  { int arr[T((is_trivially_constructible::value))]; }
-  { int arr[T((is_trivially_constructible::value))]; }
-  { int arr[T((is_trivially_constructible::value))]; }
-  { int arr[T((is_trivially_constructible::value))]; }
-  { int arr[T((is_trivially_constructible::value))]; }
-  { int arr[T((is_trivially_constructible::value))]; }
-  { int arr[T((is_trivially_constructible::value))]; }
-  { int arr[T((is_trivially_constructible::value))]; }
-  { int arr[T((is_trivially_constructible::value))]; }
-
-  { int arr[F((is_trivially_constructible::value))]; }
-  { int arr[F((is_trivially_constructible::value))]; }
-  { int arr[F((is_trivially_constructible::value))]; }
-  { int arr[F((is_trivially_constructible::value))]; } // PR19178
-
-  { int arr[T(__is_trivially_constructible(ACompleteType))]; }
-  { int arr[F(__is_trivially_constructible(AnIncompleteType))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_trivially_constructible(AnIncompleteType[]))]; }
-  { int arr[F(__is_trivially_constructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_trivially_constructible(void))]; }
-  { int arr[F(__is_trivially_constructible(const volatile void))]; }
+  static_assert((is_trivially_constructible::value));
+  static_assert((is_trivially_constructible::value));
+  static_assert((is_trivially_constructible::value));
+  static_assert((is_trivially_constructible::value));
+  static_assert((is_trivially_constructible::value));
+  static_assert((is_trivially_constructible::value));
+  static_assert((is_trivially_constructible::value));
+  static_assert((is_trivially_constructible::value));
+  static_assert((is_trivially_constructible::value));
+  static_assert((is_trivially_constructible::value));
+  static_assert((is_trivially_constructible::value));
+  static_assert((is_trivially_constructible::value));
+
+  static_assert(!(is_trivially_constructible::value));
+  static_assert(!(is_trivially_constructible::value));
+  static_assert(!(is_trivially_constructible::value));
+  static_assert(!(is_trivially_constructible::value)); // PR19178
+
+  static_assert(__is_trivially_constructible(ACompleteType));
+  static_assert(!__is_trivially_constructible(AnIncompleteType)); // expected-error {{incomplete type}}
+  static_assert(!__is_trivially_constructible(AnIncompleteType[]));
+  static_assert(!__is_trivially_constructible(AnIncompleteType[1])); // expected-error {{incomplete type}}
+  static_assert(!__is_trivially_constructible(void));
+  static_assert(!__is_trivially_constructible(const volatile void));
 }
 
 template 
@@ -2762,365 +2762,359 @@ struct ConvertsToRef {
 };
 
 void reference_binds_to_temporary_checks() {
-  { int arr[F((__reference_binds_to_temporary(int &, int &)))]; }
-  { int arr[F((__reference_binds_to_temporary(int &, int &&)))]; }
+  static_assert(!(__reference_binds_to_temporary(int &, int &)));
+  static_assert(!(__reference_binds_to_temporary(int &, int &&)));
 
-  { int arr[F((__reference_binds_to_temporary(int const &, int &)))]; }
-  { int arr[F((__reference_binds_to_temporary(int const &, int const &)))]; }
-  { int arr[F((__reference_binds_to_temporary(int const &, int &&)))]; }
+  static_assert(!(__reference_binds_to_temporary(int const &, int &)));
+  static_assert(!(__reference_binds_to_temporary(int const &, int const &)));
+  static_assert(!(__reference_binds_to_temporary(int const &, int &&)));
 
-  { int arr[F((__reference_binds_to_temporary(int &, long &)))]; } // doesn't construct
-  { int arr[T((__reference_binds_to_temporary(int const &, long &)))]; }
-  { int arr[T((__reference_binds_to_temporary(int const &, long &&)))]; }
-  { int arr[T((__reference_binds_to_temporary(int &&, long &)))]; }
+  static_assert(!(__reference_binds_to_temporary(int &, long &))); // doesn't construct
+  static_assert((__reference_binds_to_temporary(int const &, long &)));
+  static_assert((__reference_binds_to_temporary(int const &, long &&)));
+  static_assert((__reference_binds_to_temporary(int &&, long &)));
 
   using LRef = ConvertsToRef;
   using RRef = ConvertsToRef;
   using CLRef = ConvertsToRef;
   using LongRef = ConvertsToRef;
-  { int arr[T((__is_constructible(int &, LRef)))]; }
-  { int arr[F((__reference_binds_to_temporary(int &, LRef)))]; }
+  static_assert((__is_constructible(int &, LRef)));
+  static_assert(!(__reference_binds_to_temporary(int &, LRef)));
 
-  { int arr[T((__is_constructible(int &&, RRef)))]; }
-  { int arr[F((__reference_binds_to_temporary(int &&, RRef)))]; }
+  static_assert((__is_constructible(int &&, RRef)));
+  static_assert(!(__reference_binds_to_temporary(int &&, RRef)));
 
-  { int arr[T((__is_constructible(int const &, CLRef)))]; }
-  { int arr[F((__reference_binds_to_temporary(int &&, CLRef)))]; }
+  static_assert((__is_constructible(int const &, CLRef)));
+  static_assert(!(__reference_binds_to_temporary(int &&, CLRef)));
 
-  { int arr[T((__is_constructible(int const &, LongRef)))]; }
-  { int arr[T((__reference_binds_to_temporary(int const &, LongRef)))]; }
+  static_assert((__is_constructible(int const &, LongRef)));
+  static_assert((__reference_binds_to_temporary(int const &, LongRef)));
 
   // Test that it doesn't accept non-reference types as input.
-  { int arr[F((__reference_binds_to_temporary(int, long)))]; }
+  static_assert(!(__reference_binds_to_temporary(int, long)));
 
-  { int arr[T((__reference_binds_to_temporary(const int &, long)))]; }
+  static_assert((__reference_binds_to_temporary(const int &, long)));
 }
 
 void reference_constructs_from_temporary_checks() {
-  static_assert(!__reference_constructs_from_temporary(int &, int &), "");
-  static_assert(!__reference_constructs_from_temporary(int &, int &&), "");
+  static_assert(!__reference_constructs_from_temporary(int &, int &));
+  static_assert(!__reference_constructs_from_temporary(int &, int &&));
 
-  static_assert(!__reference_constructs_from_temporary(int const &, int &), "");
-  static_assert(!__reference_constructs_from_temporary(int const &, int const &), "");
-  static_assert(!__reference_constructs_from_temporary(int const &, int &&), "");
+  static_assert(!__reference_constructs_from_temporary(int const &, int &));
+  static_assert(!__reference_constructs_from_temporary(int const &, int const &));
+  static_assert(!__reference_constructs_from_temporary(int const &, int &&));
 
-  static_assert(!__reference_constructs_from_temporary(int &, long &), ""); // doesn't construct
+  static_assert(!__reference_constructs_from_temporary(int &, long &)); // doesn't construct
 
-  static_assert(__reference_constructs_from_temporary(int const &, long &), "");
-  static_assert(__reference_constructs_from_temporary(int const &, long &&), "");
-  static_assert(__reference_constructs_from_temporary(int &&, long &), "");
+  static_assert(__reference_constructs_from_temporary(int const &, long &));
+  static_assert(__reference_constructs_from_temporary(int const &, long &&));
+  static_assert(__reference_constructs_from_temporary(int &&, long &));
 
   using LRef = ConvertsToRef;
   using RRef = ConvertsToRef;
   using CLRef = ConvertsToRef;
   using LongRef = ConvertsToRef;
-  static_assert(__is_constructible(int &, LRef), "");
-  static_assert(!__reference_constructs_from_temporary(int &, LRef), "");
+  static_assert(__is_constructible(int &, LRef));
+  static_assert(!__reference_constructs_from_temporary(int &, LRef));
 
-  static_assert(__is_constructible(int &&, RRef), "");
-  static_assert(!__reference_constructs_from_temporary(int &&, RRef), "");
+  static_assert(__is_constructible(int &&, RRef));
+  static_assert(!__reference_constructs_from_temporary(int &&, RRef));
 
-  static_assert(__is_constructible(int const &, CLRef), "");
-  static_assert(!__reference_constructs_from_temporary(int &&, CLRef), "");
+  static_assert(__is_constructible(int const &, CLRef));
+  static_assert(!__reference_constructs_from_temporary(int &&, CLRef));
 
-  static_assert(__is_constructible(int const &, LongRef), "");
-  static_assert(__reference_constructs_from_temporary(int const &, LongRef), "");
+  static_assert(__is_constructible(int const &, LongRef));
+  static_assert(__reference_constructs_from_temporary(int const &, LongRef));
 
   // Test that it doesn't accept non-reference types as input.
-  static_assert(!__reference_constructs_from_temporary(int, long), "");
+  static_assert(!__reference_constructs_from_temporary(int, long));
 
-  static_assert(__reference_constructs_from_temporary(const int &, long), "");
+  static_assert(__reference_constructs_from_temporary(const int &, long));
 
   // Additional checks
-  static_assert(__reference_constructs_from_temporary(POD const&, Derives), "");
-  static_assert(__reference_constructs_from_temporary(int&&, int), "");
-  static_assert(__reference_constructs_from_temporary(const int&, int), "");
-  static_assert(!__reference_constructs_from_temporary(int&&, int&&), "");
-  static_assert(!__reference_constructs_from_temporary(const int&, int&&), "");
-  static_assert(__reference_constructs_from_temporary(int&&, long&&), "");
-  static_assert(__reference_constructs_from_temporary(int&&, long), "");
+  static_assert(__reference_constructs_from_temporary(POD const&, Derives));
+  static_assert(__reference_constructs_from_temporary(int&&, int));
+  static_assert(__reference_constructs_from_temporary(const int&, int));
+  static_assert(!__reference_constructs_from_temporary(int&&, int&&));
+  static_assert(!__reference_constructs_from_temporary(const int&, int&&));
+  static_assert(__reference_constructs_from_temporary(int&&, long&&));
+  static_assert(__reference_constructs_from_temporary(int&&, long));
 }
 
 void array_rank() {
-  int t01[T(__array_rank(IntAr) == 1)];
-  int t02[T(__array_rank(ConstIntArAr) == 2)];
+  static_assert(__array_rank(IntAr) == 1);
+  static_assert(__array_rank(ConstIntArAr) == 2);
 }
 
 void array_extent() {
-  int t01[T(__array_extent(IntAr, 0) == 10)];
-  int t02[T(__array_extent(ConstIntArAr, 0) == 4)];
-  int t03[T(__array_extent(ConstIntArAr, 1) == 10)];
+  static_assert(__array_extent(IntAr, 0) == 10);
+  static_assert(__array_extent(ConstIntArAr, 0) == 4);
+  static_assert(__array_extent(ConstIntArAr, 1) == 10);
 }
 
 void is_destructible_test() {
-  { int arr[T(__is_destructible(int))]; }
-  { int arr[T(__is_destructible(int[2]))]; }
-  { int arr[F(__is_destructible(int[]))]; }
-  { int arr[F(__is_destructible(void))]; }
-  { int arr[T(__is_destructible(int &))]; }
-  { int arr[T(__is_destructible(HasDest))]; }
-  { int arr[F(__is_destructible(AllPrivate))]; }
-  { int arr[T(__is_destructible(SuperNonTrivialStruct))]; }
-  { int arr[T(__is_destructible(AllDefaulted))]; }
-  { int arr[F(__is_destructible(AllDeleted))]; }
-  { int arr[T(__is_destructible(ThrowingDtor))]; }
-  { int arr[T(__is_destructible(NoThrowDtor))]; }
-
-  { int arr[T(__is_destructible(ACompleteType))]; }
-  { int arr[F(__is_destructible(AnIncompleteType))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_destructible(AnIncompleteType[]))]; }
-  { int arr[F(__is_destructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_destructible(void))]; }
-  { int arr[F(__is_destructible(const volatile void))]; }
+  static_assert(__is_destructible(int));
+  static_assert(__is_destructible(int[2]));
+  static_assert(!__is_destructible(int[]));
+  static_assert(!__is_destructible(void));
+  static_assert(__is_destructible(int &));
+  static_assert(__is_destructible(HasDest));
+  static_assert(!__is_destructible(AllPrivate));
+  static_assert(__is_destructible(SuperNonTrivialStruct));
+  static_assert(__is_destructible(AllDefaulted));
+  static_assert(!__is_destructible(AllDeleted));
+  static_assert(__is_destructible(ThrowingDtor));
+  static_assert(__is_destructible(NoThrowDtor));
+
+  static_assert(__is_destructible(ACompleteType));
+  static_assert(!__is_destructible(AnIncompleteType)); // expected-error {{incomplete type}}
+  static_assert(!__is_destructible(AnIncompleteType[]));
+  static_assert(!__is_destructible(AnIncompleteType[1])); // expected-error {{incomplete type}}
+  static_assert(!__is_destructible(void));
+  static_assert(!__is_destructible(const volatile void));
 }
 
 void is_nothrow_destructible_test() {
-  { int arr[T(__is_nothrow_destructible(int))]; }
-  { int arr[T(__is_nothrow_destructible(int[2]))]; }
-  { int arr[F(__is_nothrow_destructible(int[]))]; }
-  { int arr[F(__is_nothrow_destructible(void))]; }
-  { int arr[T(__is_nothrow_destructible(int &))]; }
-  { int arr[T(__is_nothrow_destructible(HasDest))]; }
-  { int arr[F(__is_nothrow_destructible(AllPrivate))]; }
-  { int arr[T(__is_nothrow_destructible(SuperNonTrivialStruct))]; }
-  { int arr[T(__is_nothrow_destructible(AllDefaulted))]; }
-  { int arr[F(__is_nothrow_destructible(AllDeleted))]; }
-  { int arr[F(__is_nothrow_destructible(ThrowingDtor))]; }
-  { int arr[T(__is_nothrow_destructible(NoExceptDtor))]; }
-  { int arr[T(__is_nothrow_destructible(NoThrowDtor))]; }
-
-  { int arr[T(__is_nothrow_destructible(ACompleteType))]; }
-  { int arr[F(__is_nothrow_destructible(AnIncompleteType))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_nothrow_destructible(AnIncompleteType[]))]; }
-  { int arr[F(__is_nothrow_destructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_nothrow_destructible(void))]; }
-  { int arr[F(__is_nothrow_destructible(const volatile void))]; }
+  static_assert(__is_nothrow_destructible(int));
+  static_assert(__is_nothrow_destructible(int[2]));
+  static_assert(!__is_nothrow_destructible(int[]));
+  static_assert(!__is_nothrow_destructible(void));
+  static_assert(__is_nothrow_destructible(int &));
+  static_assert(__is_nothrow_destructible(HasDest));
+  static_assert(!__is_nothrow_destructible(AllPrivate));
+  static_assert(__is_nothrow_destructible(SuperNonTrivialStruct));
+  static_assert(__is_nothrow_destructible(AllDefaulted));
+  static_assert(!__is_nothrow_destructible(AllDeleted));
+  static_assert(!__is_nothrow_destructible(ThrowingDtor));
+  static_assert(__is_nothrow_destructible(NoExceptDtor));
+  static_assert(__is_nothrow_destructible(NoThrowDtor));
+
+  static_assert(__is_nothrow_destructible(ACompleteType));
+  static_assert(!__is_nothrow_destructible(AnIncompleteType)); // expected-error {{incomplete type}}
+  static_assert(!__is_nothrow_destructible(AnIncompleteType[]));
+  static_assert(!__is_nothrow_destructible(AnIncompleteType[1])); // expected-error {{incomplete type}}
+  static_assert(!__is_nothrow_destructible(void));
+  static_assert(!__is_nothrow_destructible(const volatile void));
 }
 
 void is_trivially_destructible_test() {
-  { int arr[T(__is_trivially_destructible(int))]; }
-  { int arr[T(__is_trivially_destructible(int[2]))]; }
-  { int arr[F(__is_trivially_destructible(int[]))]; }
-  { int arr[F(__is_trivially_destructible(void))]; }
-  { int arr[T(__is_trivially_destructible(int &))]; }
-  { int arr[F(__is_trivially_destructible(HasDest))]; }
-  { int arr[F(__is_trivially_destructible(AllPrivate))]; }
-  { int arr[F(__is_trivially_destructible(SuperNonTrivialStruct))]; }
-  { int arr[T(__is_trivially_destructible(AllDefaulted))]; }
-  { int arr[F(__is_trivially_destructible(AllDeleted))]; }
-  { int arr[F(__is_trivially_destructible(ThrowingDtor))]; }
-  { int arr[F(__is_trivially_destructible(NoThrowDtor))]; }
-
-  { int arr[T(__is_trivially_destructible(ACompleteType))]; }
-  { int arr[F(__is_trivially_destructible(AnIncompleteType))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_trivially_destructible(AnIncompleteType[]))]; }
-  { int arr[F(__is_trivially_destructible(AnIncompleteType[1]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__is_trivially_destructible(void))]; }
-  { int arr[F(__is_trivially_destructible(const volatile void))]; }
+  static_assert(__is_trivially_destructible(int));
+  static_assert(__is_trivially_destructible(int[2]));
+  static_assert(!__is_trivially_destructible(int[]));
+  static_assert(!__is_trivially_destructible(void));
+  static_assert(__is_trivially_destructible(int &));
+  static_assert(!__is_trivially_destructible(HasDest));
+  static_assert(!__is_trivially_destructible(AllPrivate));
+  static_assert(!__is_trivially_destructible(SuperNonTrivialStruct));
+  static_assert(__is_trivially_destructible(AllDefaulted));
+  static_assert(!__is_trivially_destructible(AllDeleted));
+  static_assert(!__is_trivially_destructible(ThrowingDtor));
+  static_assert(!__is_trivially_destructible(NoThrowDtor));
+
+  static_assert(__is_trivially_destructible(ACompleteType));
+  static_assert(!__is_trivially_destructible(AnIncompleteType)); // expected-error {{incomplete type}}
+  static_assert(!__is_trivially_destructible(AnIncompleteType[]));
+  static_assert(!__is_trivially_destructible(AnIncompleteType[1])); // expected-error {{incomplete type}}
+  static_assert(!__is_trivially_destructible(void));
+  static_assert(!__is_trivially_destructible(const volatile void));
 }
 
-// Instantiation of __has_unique_object_representations
-template 
-struct has_unique_object_representations {
-  static const bool value = __has_unique_object_representations(T);
-};
-
-static_assert(!has_unique_object_representations::value, "void is never unique");
-static_assert(!has_unique_object_representations::value, "void is never unique");
-static_assert(!has_unique_object_representations::value, "void is never unique");
-static_assert(!has_unique_object_representations::value, "void is never unique");
+static_assert(!__has_unique_object_representations(void), "void is never unique");
+static_assert(!__has_unique_object_representations(const void), "void is never unique");
+static_assert(!__has_unique_object_representations(volatile void), "void is never unique");
+static_assert(!__has_unique_object_representations(const volatile void), "void is never unique");
 
-static_assert(has_unique_object_representations::value, "integrals are");
-static_assert(has_unique_object_representations::value, "integrals are");
-static_assert(has_unique_object_representations::value, "integrals are");
-static_assert(has_unique_object_representations::value, "integrals are");
+static_assert(__has_unique_object_representations(int), "integrals are");
+static_assert(__has_unique_object_representations(const int), "integrals are");
+static_assert(__has_unique_object_representations(volatile int), "integrals are");
+static_assert(__has_unique_object_representations(const volatile int), "integrals are");
 
-static_assert(has_unique_object_representations::value, "as are pointers");
-static_assert(has_unique_object_representations::value, "as are pointers");
-static_assert(has_unique_object_representations::value, "are pointers");
-static_assert(has_unique_object_representations::value, "as are pointers");
+static_assert(__has_unique_object_representations(void *), "as are pointers");
+static_assert(__has_unique_object_representations(const void *), "as are pointers");
+static_assert(__has_unique_object_representations(volatile void *), "are pointers");
+static_assert(__has_unique_object_representations(const volatile void *), "as are pointers");
 
-static_assert(has_unique_object_representations::value, "as are pointers");
-static_assert(has_unique_object_representations::value, "as are pointers");
-static_assert(has_unique_object_representations::value, "as are pointers");
-static_assert(has_unique_object_representations::value, "as are pointers");
+static_assert(__has_unique_object_representations(int *), "as are pointers");
+static_assert(__has_unique_object_representations(const int *), "as are pointers");
+static_assert(__has_unique_object_representations(volatile int *), "as are pointers");
+static_assert(__has_unique_object_representations(const volatile int *), "as are pointers");
 
 class C {};
 using FP = int (*)(int);
 using PMF = int (C::*)(int);
 using PMD = int C::*;
 
-static_assert(has_unique_object_representations::value, "even function pointers");
-static_assert(has_unique_object_representations::value, "even function pointers");
-static_assert(has_unique_object_representations::value, "even function pointers");
-static_assert(has_unique_object_representations::value, "even function pointers");
-
-static_assert(has_unique_object_representations::value, "and pointer to members");
-static_assert(has_unique_object_representations::value, "and pointer to members");
-static_assert(has_unique_object_representations::value, "and pointer to members");
-static_assert(has_unique_object_representations::value, "and pointer to members");
-
-static_assert(has_unique_object_representations::value, "and pointer to members");
-static_assert(has_unique_object_representations::value, "and pointer to members");
-static_assert(has_unique_object_representations::value, "and pointer to members");
-static_assert(has_unique_object_representations::value, "and pointer to members");
-
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-static_assert(has_unique_object_representations::value, "yes, all integral types");
-
-static_assert(!has_unique_object_representations::value, "but not void!");
-static_assert(!has_unique_object_representations::value, "or nullptr_t");
-static_assert(!has_unique_object_representations::value, "definitely not Floating Point");
-static_assert(!has_unique_object_representations::value, "definitely not Floating Point");
-static_assert(!has_unique_object_representations::value, "definitely not Floating Point");
+static_assert(__has_unique_object_representations(FP), "even function pointers");
+static_assert(__has_unique_object_representations(const FP), "even function pointers");
+static_assert(__has_unique_object_representations(volatile FP), "even function pointers");
+static_assert(__has_unique_object_representations(const volatile FP), "even function pointers");
+
+static_assert(__has_unique_object_representations(PMF), "and pointer to members");
+static_assert(__has_unique_object_representations(const PMF), "and pointer to members");
+static_assert(__has_unique_object_representations(volatile PMF), "and pointer to members");
+static_assert(__has_unique_object_representations(const volatile PMF), "and pointer to members");
+
+static_assert(__has_unique_object_representations(PMD), "and pointer to members");
+static_assert(__has_unique_object_representations(const PMD), "and pointer to members");
+static_assert(__has_unique_object_representations(volatile PMD), "and pointer to members");
+static_assert(__has_unique_object_representations(const volatile PMD), "and pointer to members");
+
+static_assert(__has_unique_object_representations(bool), "yes, all integral types");
+static_assert(__has_unique_object_representations(char), "yes, all integral types");
+static_assert(__has_unique_object_representations(signed char), "yes, all integral types");
+static_assert(__has_unique_object_representations(unsigned char), "yes, all integral types");
+static_assert(__has_unique_object_representations(short), "yes, all integral types");
+static_assert(__has_unique_object_representations(unsigned short), "yes, all integral types");
+static_assert(__has_unique_object_representations(int), "yes, all integral types");
+static_assert(__has_unique_object_representations(unsigned int), "yes, all integral types");
+static_assert(__has_unique_object_representations(long), "yes, all integral types");
+static_assert(__has_unique_object_representations(unsigned long), "yes, all integral types");
+static_assert(__has_unique_object_representations(long long), "yes, all integral types");
+static_assert(__has_unique_object_representations(unsigned long long), "yes, all integral types");
+static_assert(__has_unique_object_representations(wchar_t), "yes, all integral types");
+static_assert(__has_unique_object_representations(char16_t), "yes, all integral types");
+static_assert(__has_unique_object_representations(char32_t), "yes, all integral types");
+
+static_assert(!__has_unique_object_representations(void), "but not void!");
+static_assert(!__has_unique_object_representations(decltype(nullptr)), "or nullptr_t");
+static_assert(!__has_unique_object_representations(float), "definitely not Floating Point");
+static_assert(!__has_unique_object_representations(double), "definitely not Floating Point");
+static_assert(!__has_unique_object_representations(long double), "definitely not Floating Point");
 
 struct NoPadding {
   int a;
   int b;
 };
 
-static_assert(has_unique_object_representations::value, "types without padding are");
+static_assert(__has_unique_object_representations(NoPadding), "types without padding are");
 
 struct InheritsFromNoPadding : NoPadding {
   int c;
   int d;
 };
 
-static_assert(has_unique_object_representations::value, "types without padding are");
+static_assert(__has_unique_object_representations(InheritsFromNoPadding), "types without padding are");
 
 struct VirtuallyInheritsFromNoPadding : virtual NoPadding {
   int c;
   int d;
 };
 
-static_assert(!has_unique_object_representations::value, "No virtual inheritance");
+static_assert(!__has_unique_object_representations(VirtuallyInheritsFromNoPadding), "No virtual inheritance");
 
 struct Padding {
   char a;
   int b;
 };
 
-//static_assert(!has_unique_object_representations::value, "but not with padding");
+//static_assert(!__has_unique_object_representations(Padding), "but not with padding");
 
 struct InheritsFromPadding : Padding {
   int c;
   int d;
 };
 
-static_assert(!has_unique_object_representations::value, "or its subclasses");
+static_assert(!__has_unique_object_representations(InheritsFromPadding), "or its subclasses");
 
 struct TailPadding {
   int a;
   char b;
 };
 
-static_assert(!has_unique_object_representations::value, "even at the end");
+static_assert(!__has_unique_object_representations(TailPadding), "even at the end");
 
 struct TinyStruct {
   char a;
 };
 
-static_assert(has_unique_object_representations::value, "Should be no padding");
+static_assert(__has_unique_object_representations(TinyStruct), "Should be no padding");
 
 struct InheritsFromTinyStruct : TinyStruct {
   int b;
 };
 
-static_assert(!has_unique_object_representations::value, "Inherit causes padding");
+static_assert(!__has_unique_object_representations(InheritsFromTinyStruct), "Inherit causes padding");
 
 union NoPaddingUnion {
   int a;
   unsigned int b;
 };
 
-static_assert(has_unique_object_representations::value, "unions follow the same rules as structs");
+static_assert(__has_unique_object_representations(NoPaddingUnion), "unions follow the same rules as structs");
 
 union PaddingUnion {
   int a;
   long long b;
 };
 
-static_assert(!has_unique_object_representations::value, "unions follow the same rules as structs");
+static_assert(!__has_unique_object_representations(PaddingUnion), "unions follow the same rules as structs");
 
 struct NotTriviallyCopyable {
   int x;
   NotTriviallyCopyable(const NotTriviallyCopyable &) {}
 };
 
-static_assert(!has_unique_object_representations::value, "must be trivially copyable");
+static_assert(!__has_unique_object_representations(NotTriviallyCopyable), "must be trivially copyable");
 
 struct HasNonUniqueMember {
   float x;
 };
 
-static_assert(!has_unique_object_representations::value, "all members must be unique");
+static_assert(!__has_unique_object_representations(HasNonUniqueMember), "all members must be unique");
 
 enum ExampleEnum { xExample,
                    yExample };
 enum LLEnum : long long { xLongExample,
                           yLongExample };
 
-static_assert(has_unique_object_representations::value, "Enums are integrals, so unique!");
-static_assert(has_unique_object_representations::value, "Enums are integrals, so unique!");
+static_assert(__has_unique_object_representations(ExampleEnum), "Enums are integrals, so unique!");
+static_assert(__has_unique_object_representations(LLEnum), "Enums are integrals, so unique!");
 
 enum class ExampleEnumClass { xExample,
                               yExample };
 enum class LLEnumClass : long long { xLongExample,
                                      yLongExample };
 
-static_assert(has_unique_object_representations::value, "Enums are integrals, so unique!");
-static_assert(has_unique_object_representations::value, "Enums are integrals, so unique!");
+static_assert(__has_unique_object_representations(ExampleEnumClass), "Enums are integrals, so unique!");
+static_assert(__has_unique_object_representations(LLEnumClass), "Enums are integrals, so unique!");
 
 // because references aren't trivially copyable.
-static_assert(!has_unique_object_representations::value, "No references!");
-static_assert(!has_unique_object_representations::value, "No references!");
-static_assert(!has_unique_object_representations::value, "No references!");
-static_assert(!has_unique_object_representations::value, "No references!");
-static_assert(!has_unique_object_representations::value, "No empty types!");
-static_assert(!has_unique_object_representations::value, "No empty types!");
+static_assert(!__has_unique_object_representations(int &), "No references!");
+static_assert(!__has_unique_object_representations(const int &), "No references!");
+static_assert(!__has_unique_object_representations(volatile int &), "No references!");
+static_assert(!__has_unique_object_representations(const volatile int &), "No references!");
+static_assert(!__has_unique_object_representations(Empty), "No empty types!");
+static_assert(!__has_unique_object_representations(EmptyUnion), "No empty types!");
 
 class Compressed : Empty {
   int x;
 };
 
-static_assert(has_unique_object_representations::value, "But inheriting from one is ok");
+static_assert(__has_unique_object_representations(Compressed), "But inheriting from one is ok");
 
 class EmptyInheritor : Compressed {};
 
-static_assert(has_unique_object_representations::value, "As long as the base has items, empty is ok");
+static_assert(__has_unique_object_representations(EmptyInheritor), "As long as the base has items, empty is ok");
 
 class Dynamic {
   virtual void A();
   int i;
 };
 
-static_assert(!has_unique_object_representations::value, "Dynamic types are not valid");
+static_assert(!__has_unique_object_representations(Dynamic), "Dynamic types are not valid");
 
 class InheritsDynamic : Dynamic {
   int j;
 };
 
-static_assert(!has_unique_object_representations::value, "Dynamic types are not valid");
+static_assert(!__has_unique_object_representations(InheritsDynamic), "Dynamic types are not valid");
 
-static_assert(has_unique_object_representations::value, "Arrays are fine, as long as their value type is");
-static_assert(has_unique_object_representations::value, "Arrays are fine, as long as their value type is");
-static_assert(has_unique_object_representations::value, "Arrays are fine, as long as their value type is");
-static_assert(!has_unique_object_representations::value, "So no array of doubles!");
-static_assert(!has_unique_object_representations::value, "So no array of doubles!");
-static_assert(!has_unique_object_representations::value, "So no array of doubles!");
+static_assert(__has_unique_object_representations(int[42]), "Arrays are fine, as long as their value type is");
+static_assert(__has_unique_object_representations(int[]), "Arrays are fine, as long as their value type is");
+static_assert(__has_unique_object_representations(int[][42]), "Arrays are fine, as long as their value type is");
+static_assert(!__has_unique_object_representations(double[42]), "So no array of doubles!");
+static_assert(!__has_unique_object_representations(double[]), "So no array of doubles!");
+static_assert(!__has_unique_object_representations(double[][42]), "So no array of doubles!");
 
 struct __attribute__((aligned(16))) WeirdAlignment {
   int i;
@@ -3128,9 +3122,9 @@ struct __attribute__((aligned(16))) WeirdAlignment {
 union __attribute__((aligned(16))) WeirdAlignmentUnion {
   int i;
 };
-static_assert(!has_unique_object_representations::value, "Alignment causes padding");
-static_assert(!has_unique_object_representations::value, "Alignment causes padding");
-static_assert(!has_unique_object_representations::value, "Also no arrays that have padding");
+static_assert(!__has_unique_object_representations(WeirdAlignment), "Alignment causes padding");
+static_assert(!__has_unique_object_representations(WeirdAlignmentUnion), "Alignment causes padding");
+static_assert(!__has_unique_object_representations(WeirdAlignment[42]), "Also no arrays that have padding");
 
 struct __attribute__((packed)) PackedNoPadding1 {
   short i;
@@ -3140,41 +3134,41 @@ struct __attribute__((packed)) PackedNoPadding2 {
   int j;
   short i;
 };
-static_assert(has_unique_object_representations::value, "Packed structs have no padding");
-static_assert(has_unique_object_representations::value, "Packed structs have no padding");
-
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
-static_assert(!has_unique_object_representations::value, "Functions are not unique");
+static_assert(__has_unique_object_representations(PackedNoPadding1), "Packed structs have no padding");
+static_assert(__has_unique_object_representations(PackedNoPadding2), "Packed structs have no padding");
+
+static_assert(!__has_unique_object_representations(int(int)), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int) const), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int) volatile), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int) const volatile), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int) &), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int) const &), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int) volatile &), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int) const volatile &), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int) &&), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int) const &&), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int) volatile &&), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int) const volatile &&), "Functions are not unique");
+
+static_assert(!__has_unique_object_representations(int(int, ...)), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int, ...) const), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int, ...) volatile), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int, ...) const volatile), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int, ...) &), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int, ...) const &), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int, ...) volatile &), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int, ...) const volatile &), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int, ...) &&), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int, ...) const &&), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int, ...) volatile &&), "Functions are not unique");
+static_assert(!__has_unique_object_representations(int(int, ...) const volatile &&), "Functions are not unique");
 
 void foo(){
   static auto lambda = []() {};
-  static_assert(!has_unique_object_representations::value, "Lambdas follow struct rules");
+  static_assert(!__has_unique_object_representations(decltype(lambda)), "Lambdas follow struct rules");
   int i;
   static auto lambda2 = [i]() {};
-  static_assert(has_unique_object_representations::value, "Lambdas follow struct rules");
+  static_assert(__has_unique_object_representations(decltype(lambda2)), "Lambdas follow struct rules");
 }
 
 struct PaddedBitfield {
@@ -3214,26 +3208,26 @@ struct UnnamedEmptyBitfieldSplit {
   short also_named;
 };
 
-static_assert(!has_unique_object_representations::value, "Bitfield padding");
-static_assert(has_unique_object_representations::value, "Bitfield padding");
-static_assert(!has_unique_object_representations::value, "Bitfield padding");
-static_assert(!has_unique_object_representations::value, "Bitfield padding");
-static_assert(!has_unique_object_representations::value, "Bitfield padding");
-static_assert(has_unique_object_representations::value, "Bitfield padding");
+static_assert(!__has_unique_object_representations(PaddedBitfield), "Bitfield padding");
+static_assert(__has_unique_object_representations(UnPaddedBitfield), "Bitfield padding");
+static_assert(!__has_unique_object_representations(AlignedPaddedBitfield), "Bitfield padding");
+static_assert(!__has_unique_object_representations(UnnamedBitfield), "Bitfield padding");
+static_assert(!__has_unique_object_representations(UnnamedBitfieldPacked), "Bitfield padding");
+static_assert(__has_unique_object_representations(UnnamedEmptyBitfield), "Bitfield padding");
 static_assert(sizeof(UnnamedEmptyBitfieldSplit) != (sizeof(short) * 2), "Wrong size");
-static_assert(!has_unique_object_representations::value, "Bitfield padding");
+static_assert(!__has_unique_object_representations(UnnamedEmptyBitfieldSplit), "Bitfield padding");
 
 struct BoolBitfield {
   bool b : 8;
 };
 
-static_assert(has_unique_object_representations::value, "Bitfield bool");
+static_assert(__has_unique_object_representations(BoolBitfield), "Bitfield bool");
 
 struct BoolBitfield2 {
   bool b : 16;
 };
 
-static_assert(!has_unique_object_representations::value, "Bitfield bool");
+static_assert(!__has_unique_object_representations(BoolBitfield2), "Bitfield bool");
 
 struct GreaterSizeBitfield {
   //expected-warning@+1 {{width of bit-field 'n'}}
@@ -3241,13 +3235,13 @@ struct GreaterSizeBitfield {
 };
 
 static_assert(sizeof(GreaterSizeBitfield) == 128, "Bitfield Size");
-static_assert(!has_unique_object_representations::value, "Bitfield padding");
+static_assert(!__has_unique_object_representations(GreaterSizeBitfield), "Bitfield padding");
 
 struct StructWithRef {
   int &I;
 };
 
-static_assert(has_unique_object_representations::value, "References are still unique");
+static_assert(__has_unique_object_representations(StructWithRef), "References are still unique");
 
 struct NotUniqueBecauseTailPadding {
   int &r;
@@ -3257,12 +3251,12 @@ struct CanBeUniqueIfNoPadding : NotUniqueBecauseTailPadding {
   char b[7];
 };
 
-static_assert(!has_unique_object_representations::value,
+static_assert(!__has_unique_object_representations(NotUniqueBecauseTailPadding),
               "non trivial");
 // Can be unique on Itanium, since the is child class' data is 'folded' into the
 // parent's tail padding.
 static_assert(sizeof(CanBeUniqueIfNoPadding) != 16 ||
-              has_unique_object_representations::value,
+              __has_unique_object_representations(CanBeUniqueIfNoPadding),
               "inherit from std layout");
 
 namespace ErrorType {
@@ -3274,10 +3268,10 @@ namespace ErrorType {
   bool b = __has_unique_object_representations(T);
 };
 
-static_assert(!has_unique_object_representations<_BitInt(7)>::value, "BitInt:");
-static_assert(has_unique_object_representations<_BitInt(8)>::value, "BitInt:");
-static_assert(!has_unique_object_representations<_BitInt(127)>::value, "BitInt:");
-static_assert(has_unique_object_representations<_BitInt(128)>::value, "BitInt:");
+static_assert(!__has_unique_object_representations(_BitInt(7)), "BitInt:");
+static_assert(__has_unique_object_representations(_BitInt(8)), "BitInt:");
+static_assert(!__has_unique_object_representations(_BitInt(127)), "BitInt:");
+static_assert(__has_unique_object_representations(_BitInt(128)), "BitInt:");
 
 
 namespace PR46209 {
@@ -3292,8 +3286,8 @@ namespace PR46209 {
     Foo foo;
   };
 
-  static_assert(!__is_trivially_assignable(Foo &, const Foo &), "");
-  static_assert(!__is_trivially_assignable(Bar &, const Bar &), "");
+  static_assert(!__is_trivially_assignable(Foo &, const Foo &));
+  static_assert(!__is_trivially_assignable(Bar &, const Bar &));
 
   // Foo2 has both a trivial assignment operator and a non-trivial one.
   struct Foo2 {
@@ -3306,8 +3300,8 @@ namespace PR46209 {
     Foo2 foo;
   };
 
-  static_assert(__is_trivially_assignable(Foo2 &, const Foo2 &), "");
-  static_assert(__is_trivially_assignable(Bar2 &, const Bar2 &), "");
+  static_assert(__is_trivially_assignable(Foo2 &, const Foo2 &));
+  static_assert(__is_trivially_assignable(Bar2 &, const Bar2 &));
 }
 
 namespace ConstClass {
@@ -3317,7 +3311,7 @@ namespace ConstClass {
   struct B {
     const A a;
   };
-  static_assert(!__is_trivially_assignable(B&, const B&), "");
+  static_assert(!__is_trivially_assignable(B&, const B&));
 }
 
 namespace type_trait_expr_numargs_overflow {
@@ -3343,21 +3337,44 @@ void test() { (void) __is_constructible(int, T32768(int)); }
 
 namespace is_trivially_relocatable {
 
-static_assert(!__is_trivially_relocatable(void), "");
-static_assert(__is_trivially_relocatable(int), "");
-static_assert(__is_trivially_relocatable(int[]), "");
+static_assert(!__is_trivially_relocatable(void));
+static_assert(__is_trivially_relocatable(int));
+static_assert(__is_trivially_relocatable(int[]));
+static_assert(__is_trivially_relocatable(const int));
+static_assert(__is_trivially_relocatable(volatile int));
 
 enum Enum {};
-static_assert(__is_trivially_relocatable(Enum), "");
-static_assert(__is_trivially_relocatable(Enum[]), "");
+static_assert(__is_trivially_relocatable(Enum));
+static_assert(__is_trivially_relocatable(Enum[]));
 
 union Union {int x;};
-static_assert(__is_trivially_relocatable(Union), "");
-static_assert(__is_trivially_relocatable(Union[]), "");
+static_assert(__is_trivially_relocatable(Union));
+static_assert(__is_trivially_relocatable(Union[]));
 
 struct Trivial {};
-static_assert(__is_trivially_relocatable(Trivial), "");
-static_assert(__is_trivially_relocatable(Trivial[]), "");
+static_assert(__is_trivially_relocatable(Trivial));
+static_assert(__is_trivially_relocatable(const Trivial));
+static_assert(__is_trivially_relocatable(volatile Trivial));
+
+static_assert(__is_trivially_relocatable(Trivial[]));
+static_assert(__is_trivially_relocatable(const Trivial[]));
+static_assert(__is_trivially_relocatable(volatile Trivial[]));
+
+static_assert(__is_trivially_relocatable(int[10]));
+static_assert(__is_trivially_relocatable(const int[10]));
+static_assert(__is_trivially_relocatable(volatile int[10]));
+
+static_assert(__is_trivially_relocatable(int[10][10]));
+static_assert(__is_trivially_relocatable(const int[10][10]));
+static_assert(__is_trivially_relocatable(volatile int[10][10]));
+
+static_assert(__is_trivially_relocatable(int[]));
+static_assert(__is_trivially_relocatable(const int[]));
+static_assert(__is_trivially_relocatable(volatile int[]));
+
+static_assert(__is_trivially_relocatable(int[][10]));
+static_assert(__is_trivially_relocatable(const int[][10]));
+static_assert(__is_trivially_relocatable(volatile int[][10]));
 
 struct Incomplete; // expected-note {{forward declaration of 'is_trivially_relocatable::Incomplete'}}
 bool unused = __is_trivially_relocatable(Incomplete); // expected-error {{incomplete type}}
@@ -3365,67 +3382,75 @@ bool unused = __is_trivially_relocatable(Incomplete); // expected-error {{incomp
 struct NontrivialDtor {
   ~NontrivialDtor() {}
 };
-static_assert(!__is_trivially_relocatable(NontrivialDtor), "");
-static_assert(!__is_trivially_relocatable(NontrivialDtor[]), "");
+static_assert(!__is_trivially_relocatable(NontrivialDtor));
+static_assert(!__is_trivially_relocatable(NontrivialDtor[]));
+static_assert(!__is_trivially_relocatable(const NontrivialDtor));
+static_assert(!__is_trivially_relocatable(volatile NontrivialDtor));
 
 struct NontrivialCopyCtor {
   NontrivialCopyCtor(const NontrivialCopyCtor&) {}
 };
-static_assert(!__is_trivially_relocatable(NontrivialCopyCtor), "");
-static_assert(!__is_trivially_relocatable(NontrivialCopyCtor[]), "");
+static_assert(!__is_trivially_relocatable(NontrivialCopyCtor));
+static_assert(!__is_trivially_relocatable(NontrivialCopyCtor[]));
 
 struct NontrivialMoveCtor {
   NontrivialMoveCtor(NontrivialMoveCtor&&) {}
 };
-static_assert(!__is_trivially_relocatable(NontrivialMoveCtor), "");
-static_assert(!__is_trivially_relocatable(NontrivialMoveCtor[]), "");
+static_assert(!__is_trivially_relocatable(NontrivialMoveCtor));
+static_assert(!__is_trivially_relocatable(NontrivialMoveCtor[]));
 
 struct [[clang::trivial_abi]] TrivialAbiNontrivialDtor {
   ~TrivialAbiNontrivialDtor() {}
 };
-static_assert(__is_trivially_relocatable(TrivialAbiNontrivialDtor), "");
-static_assert(__is_trivially_relocatable(TrivialAbiNontrivialDtor[]), "");
+static_assert(__is_trivially_relocatable(TrivialAbiNontrivialDtor));
+static_assert(__is_trivially_relocatable(TrivialAbiNontrivialDtor[]));
+static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialDtor));
+static_assert(__is_trivially_relocatable(volatile TrivialAbiNontrivialDtor));
 
 struct [[clang::trivial_abi]] TrivialAbiNontrivialCopyCtor {
   TrivialAbiNontrivialCopyCtor(const TrivialAbiNontrivialCopyCtor&) {}
 };
-static_assert(__is_trivially_relocatable(TrivialAbiNontrivialCopyCtor), "");
-static_assert(__is_trivially_relocatable(TrivialAbiNontrivialCopyCtor[]), "");
+static_assert(__is_trivially_relocatable(TrivialAbiNontrivialCopyCtor));
+static_assert(__is_trivially_relocatable(TrivialAbiNontrivialCopyCtor[]));
+static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialCopyCtor));
+static_assert(__is_trivially_relocatable(volatile TrivialAbiNontrivialCopyCtor));
 
 // A more complete set of tests for the behavior of trivial_abi can be found in
 // clang/test/SemaCXX/attr-trivial-abi.cpp
 struct [[clang::trivial_abi]] TrivialAbiNontrivialMoveCtor {
   TrivialAbiNontrivialMoveCtor(TrivialAbiNontrivialMoveCtor&&) {}
 };
-static_assert(__is_trivially_relocatable(TrivialAbiNontrivialMoveCtor), "");
-static_assert(__is_trivially_relocatable(TrivialAbiNontrivialMoveCtor[]), "");
+static_assert(__is_trivially_relocatable(TrivialAbiNontrivialMoveCtor));
+static_assert(__is_trivially_relocatable(TrivialAbiNontrivialMoveCtor[]));
+static_assert(__is_trivially_relocatable(const TrivialAbiNontrivialMoveCtor));
+static_assert(__is_trivially_relocatable(volatile TrivialAbiNontrivialMoveCtor));
 
 } // namespace is_trivially_relocatable
 
 namespace is_trivially_equality_comparable {
 struct ForwardDeclared; // expected-note {{forward declaration of 'is_trivially_equality_comparable::ForwardDeclared'}}
-static_assert(!__is_trivially_equality_comparable(ForwardDeclared), ""); // expected-error {{incomplete type 'ForwardDeclared' used in type trait expression}}
+static_assert(!__is_trivially_equality_comparable(ForwardDeclared)); // expected-error {{incomplete type 'ForwardDeclared' used in type trait expression}}
 
-static_assert(!__is_trivially_equality_comparable(void), "");
-static_assert(__is_trivially_equality_comparable(int), "");
-static_assert(!__is_trivially_equality_comparable(int[]), "");
-static_assert(!__is_trivially_equality_comparable(int[3]), "");
-static_assert(!__is_trivially_equality_comparable(float), "");
-static_assert(!__is_trivially_equality_comparable(double), "");
-static_assert(!__is_trivially_equality_comparable(long double), "");
+static_assert(!__is_trivially_equality_comparable(void));
+static_assert(__is_trivially_equality_comparable(int));
+static_assert(!__is_trivially_equality_comparable(int[]));
+static_assert(!__is_trivially_equality_comparable(int[3]));
+static_assert(!__is_trivially_equality_comparable(float));
+static_assert(!__is_trivially_equality_comparable(double));
+static_assert(!__is_trivially_equality_comparable(long double));
 
 struct NonTriviallyEqualityComparableNoComparator {
   int i;
   int j;
 };
-static_assert(!__is_trivially_equality_comparable(NonTriviallyEqualityComparableNoComparator), "");
+static_assert(!__is_trivially_equality_comparable(NonTriviallyEqualityComparableNoComparator));
 
 struct NonTriviallyEqualityComparableNonDefaultedComparator {
   int i;
   int j;
   bool operator==(const NonTriviallyEqualityComparableNonDefaultedComparator&);
 };
-static_assert(!__is_trivially_equality_comparable(NonTriviallyEqualityComparableNonDefaultedComparator), "");
+static_assert(!__is_trivially_equality_comparable(NonTriviallyEqualityComparableNonDefaultedComparator));
 
 #if __cplusplus >= 202002L
 
@@ -3479,7 +3504,7 @@ struct NotTriviallyEqualityComparableHasPadding {
 
   bool operator==(const NotTriviallyEqualityComparableHasPadding&) const = default;
 };
-static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableHasPadding), "");
+static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableHasPadding));
 
 struct NotTriviallyEqualityComparableHasFloat {
   float i;
@@ -3487,7 +3512,7 @@ struct NotTriviallyEqualityComparableHasFloat {
 
   bool operator==(const NotTriviallyEqualityComparableHasFloat&) const = default;
 };
-static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableHasFloat), "");
+static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableHasFloat));
 
 struct NotTriviallyEqualityComparableHasTailPadding {
   int i;
@@ -3495,14 +3520,14 @@ struct NotTriviallyEqualityComparableHasTailPadding {
 
   bool operator==(const NotTriviallyEqualityComparableHasTailPadding&) const = default;
 };
-static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableHasTailPadding), "");
+static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableHasTailPadding));
 
 struct NotTriviallyEqualityComparableBase : NotTriviallyEqualityComparableHasTailPadding {
   char j;
 
   bool operator==(const NotTriviallyEqualityComparableBase&) const = default;
 };
-static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableBase), "");
+static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableBase));
 
 class TriviallyEqualityComparablePaddedOutBase {
   int i;
@@ -3511,14 +3536,14 @@ class TriviallyEqualityComparablePaddedOutBase {
 public:
   bool operator==(const TriviallyEqualityComparablePaddedOutBase&) const = default;
 };
-static_assert(!__is_trivially_equality_comparable(TriviallyEqualityComparablePaddedOutBase), "");
+static_assert(!__is_trivially_equality_comparable(TriviallyEqualityComparablePaddedOutBase));
 
 struct TriviallyEqualityComparablePaddedOut : TriviallyEqualityComparablePaddedOutBase {
   char j[3];
 
   bool operator==(const TriviallyEqualityComparablePaddedOut&) const = default;
 };
-static_assert(__is_trivially_equality_comparable(TriviallyEqualityComparablePaddedOut), "");
+static_assert(__is_trivially_equality_comparable(TriviallyEqualityComparablePaddedOut));
 
 struct TriviallyEqualityComparable1 {
   char i;
@@ -3641,7 +3666,7 @@ struct TriviallyEqualityComparable {
 
   friend bool operator==(const TriviallyEqualityComparable&, const TriviallyEqualityComparable&) = default;
 };
-static_assert(__is_trivially_equality_comparable(TriviallyEqualityComparable), "");
+static_assert(__is_trivially_equality_comparable(TriviallyEqualityComparable));
 
 struct TriviallyEqualityComparableNonTriviallyCopyable {
   TriviallyEqualityComparableNonTriviallyCopyable(const TriviallyEqualityComparableNonTriviallyCopyable&);
@@ -3657,7 +3682,7 @@ struct NotTriviallyEqualityComparableHasPadding {
 
   friend bool operator==(const NotTriviallyEqualityComparableHasPadding&, const NotTriviallyEqualityComparableHasPadding&) = default;
 };
-static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableHasPadding), "");
+static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableHasPadding));
 
 struct NotTriviallyEqualityComparableHasFloat {
   float i;
@@ -3665,7 +3690,7 @@ struct NotTriviallyEqualityComparableHasFloat {
 
   friend bool operator==(const NotTriviallyEqualityComparableHasFloat&, const NotTriviallyEqualityComparableHasFloat&) = default;
 };
-static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableHasFloat), "");
+static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableHasFloat));
 
 struct NotTriviallyEqualityComparableHasTailPadding {
   int i;
@@ -3673,14 +3698,14 @@ struct NotTriviallyEqualityComparableHasTailPadding {
 
   friend bool operator==(const NotTriviallyEqualityComparableHasTailPadding&, const NotTriviallyEqualityComparableHasTailPadding&) = default;
 };
-static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableHasTailPadding), "");
+static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableHasTailPadding));
 
 struct NotTriviallyEqualityComparableBase : NotTriviallyEqualityComparableHasTailPadding {
   char j;
 
   friend bool operator==(const NotTriviallyEqualityComparableBase&, const NotTriviallyEqualityComparableBase&) = default;
 };
-static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableBase), "");
+static_assert(!__is_trivially_equality_comparable(NotTriviallyEqualityComparableBase));
 
 class TriviallyEqualityComparablePaddedOutBase {
   int i;
@@ -3689,14 +3714,14 @@ class TriviallyEqualityComparablePaddedOutBase {
 public:
   friend bool operator==(const TriviallyEqualityComparablePaddedOutBase&, const TriviallyEqualityComparablePaddedOutBase&) = default;
 };
-static_assert(!__is_trivially_equality_comparable(TriviallyEqualityComparablePaddedOutBase), "");
+static_assert(!__is_trivially_equality_comparable(TriviallyEqualityComparablePaddedOutBase));
 
 struct TriviallyEqualityComparablePaddedOut : TriviallyEqualityComparablePaddedOutBase {
   char j[3];
 
   friend bool operator==(const TriviallyEqualityComparablePaddedOut&, const TriviallyEqualityComparablePaddedOut&) = default;
 };
-static_assert(__is_trivially_equality_comparable(TriviallyEqualityComparablePaddedOut), "");
+static_assert(__is_trivially_equality_comparable(TriviallyEqualityComparablePaddedOut));
 
 struct TriviallyEqualityComparable1 {
   char i;
@@ -3813,10 +3838,10 @@ union D {
   int x;
 };
 
-static_assert(__can_pass_in_regs(A), "");
-static_assert(__can_pass_in_regs(A), "");
-static_assert(!__can_pass_in_regs(B), "");
-static_assert(__can_pass_in_regs(D), "");
+static_assert(__can_pass_in_regs(A));
+static_assert(__can_pass_in_regs(A));
+static_assert(!__can_pass_in_regs(B));
+static_assert(__can_pass_in_regs(D));
 
 void test_errors() {
   (void)__can_pass_in_regs(const A); // expected-error {{not an unqualified class type}}
@@ -3833,379 +3858,379 @@ struct S {};
 template  using remove_const_t = __remove_const(T);
 
 void check_remove_const() {
-  static_assert(__is_same(remove_const_t, void), "");
-  static_assert(__is_same(remove_const_t, void), "");
-  static_assert(__is_same(remove_const_t, int), "");
-  static_assert(__is_same(remove_const_t, int), "");
-  static_assert(__is_same(remove_const_t, volatile int), "");
-  static_assert(__is_same(remove_const_t, volatile int), "");
-  static_assert(__is_same(remove_const_t, int *), "");
-  static_assert(__is_same(remove_const_t, int *), "");
-  static_assert(__is_same(remove_const_t, int const *), "");
-  static_assert(__is_same(remove_const_t, int const *__restrict), "");
-  static_assert(__is_same(remove_const_t, int &), "");
-  static_assert(__is_same(remove_const_t, int const &), "");
-  static_assert(__is_same(remove_const_t, int &&), "");
-  static_assert(__is_same(remove_const_t, int const &&), "");
-  static_assert(__is_same(remove_const_t, int()), "");
-  static_assert(__is_same(remove_const_t, int (*)()), "");
-  static_assert(__is_same(remove_const_t, int (&)()), "");
-
-  static_assert(__is_same(remove_const_t, S), "");
-  static_assert(__is_same(remove_const_t, S), "");
-  static_assert(__is_same(remove_const_t, volatile S), "");
-  static_assert(__is_same(remove_const_t, S *__restrict), "");
-  static_assert(__is_same(remove_const_t, volatile S), "");
-  static_assert(__is_same(remove_const_t, S *volatile __restrict), "");
-  static_assert(__is_same(remove_const_t, int S::*), "");
-  static_assert(__is_same(remove_const_t, int(S::*)()), "");
+  static_assert(__is_same(remove_const_t, void));
+  static_assert(__is_same(remove_const_t, void));
+  static_assert(__is_same(remove_const_t, int));
+  static_assert(__is_same(remove_const_t, int));
+  static_assert(__is_same(remove_const_t, volatile int));
+  static_assert(__is_same(remove_const_t, volatile int));
+  static_assert(__is_same(remove_const_t, int *));
+  static_assert(__is_same(remove_const_t, int *));
+  static_assert(__is_same(remove_const_t, int const *));
+  static_assert(__is_same(remove_const_t, int const *__restrict));
+  static_assert(__is_same(remove_const_t, int &));
+  static_assert(__is_same(remove_const_t, int const &));
+  static_assert(__is_same(remove_const_t, int &&));
+  static_assert(__is_same(remove_const_t, int const &&));
+  static_assert(__is_same(remove_const_t, int()));
+  static_assert(__is_same(remove_const_t, int (*)()));
+  static_assert(__is_same(remove_const_t, int (&)()));
+
+  static_assert(__is_same(remove_const_t, S));
+  static_assert(__is_same(remove_const_t, S));
+  static_assert(__is_same(remove_const_t, volatile S));
+  static_assert(__is_same(remove_const_t, S *__restrict));
+  static_assert(__is_same(remove_const_t, volatile S));
+  static_assert(__is_same(remove_const_t, S *volatile __restrict));
+  static_assert(__is_same(remove_const_t, int S::*));
+  static_assert(__is_same(remove_const_t, int(S::*)()));
 }
 
 template  using remove_restrict_t = __remove_restrict(T);
 
 void check_remove_restrict() {
-  static_assert(__is_same(remove_restrict_t, void), "");
-  static_assert(__is_same(remove_restrict_t, int), "");
-  static_assert(__is_same(remove_restrict_t, const int), "");
-  static_assert(__is_same(remove_restrict_t, volatile int), "");
-  static_assert(__is_same(remove_restrict_t, int *), "");
-  static_assert(__is_same(remove_restrict_t, int *const volatile), "");
-  static_assert(__is_same(remove_restrict_t, int *), "");
-  static_assert(__is_same(remove_restrict_t, int *), "");
-  static_assert(__is_same(remove_restrict_t, int &), "");
-  static_assert(__is_same(remove_restrict_t, int &), "");
-  static_assert(__is_same(remove_restrict_t, int &&), "");
-  static_assert(__is_same(remove_restrict_t, int &&), "");
-  static_assert(__is_same(remove_restrict_t, int()), "");
-  static_assert(__is_same(remove_restrict_t, int (*const volatile)()), "");
-  static_assert(__is_same(remove_restrict_t, int (&)()), "");
-
-  static_assert(__is_same(remove_restrict_t, S), "");
-  static_assert(__is_same(remove_restrict_t, const S), "");
-  static_assert(__is_same(remove_restrict_t, volatile S), "");
-  static_assert(__is_same(remove_restrict_t, S *), "");
-  static_assert(__is_same(remove_restrict_t, S *const volatile), "");
-  static_assert(__is_same(remove_restrict_t, int S::*), "");
-  static_assert(__is_same(remove_restrict_t, int(S::*const volatile)()), "");
+  static_assert(__is_same(remove_restrict_t, void));
+  static_assert(__is_same(remove_restrict_t, int));
+  static_assert(__is_same(remove_restrict_t, const int));
+  static_assert(__is_same(remove_restrict_t, volatile int));
+  static_assert(__is_same(remove_restrict_t, int *));
+  static_assert(__is_same(remove_restrict_t, int *const volatile));
+  static_assert(__is_same(remove_restrict_t, int *));
+  static_assert(__is_same(remove_restrict_t, int *));
+  static_assert(__is_same(remove_restrict_t, int &));
+  static_assert(__is_same(remove_restrict_t, int &));
+  static_assert(__is_same(remove_restrict_t, int &&));
+  static_assert(__is_same(remove_restrict_t, int &&));
+  static_assert(__is_same(remove_restrict_t, int()));
+  static_assert(__is_same(remove_restrict_t, int (*const volatile)()));
+  static_assert(__is_same(remove_restrict_t, int (&)()));
+
+  static_assert(__is_same(remove_restrict_t, S));
+  static_assert(__is_same(remove_restrict_t, const S));
+  static_assert(__is_same(remove_restrict_t, volatile S));
+  static_assert(__is_same(remove_restrict_t, S *));
+  static_assert(__is_same(remove_restrict_t, S *const volatile));
+  static_assert(__is_same(remove_restrict_t, int S::*));
+  static_assert(__is_same(remove_restrict_t, int(S::*const volatile)()));
 }
 
 template  using remove_volatile_t = __remove_volatile(T);
 
 void check_remove_volatile() {
-  static_assert(__is_same(remove_volatile_t, void), "");
-  static_assert(__is_same(remove_volatile_t, void), "");
-  static_assert(__is_same(remove_volatile_t, int), "");
-  static_assert(__is_same(remove_volatile_t, const int), "");
-  static_assert(__is_same(remove_volatile_t, int), "");
-  static_assert(__is_same(remove_volatile_t, int *__restrict), "");
-  static_assert(__is_same(remove_volatile_t, const int), "");
-  static_assert(__is_same(remove_volatile_t, int *const __restrict), "");
-  static_assert(__is_same(remove_volatile_t, int *), "");
-  static_assert(__is_same(remove_volatile_t, int *), "");
-  static_assert(__is_same(remove_volatile_t, int volatile *), "");
-  static_assert(__is_same(remove_volatile_t, int &), "");
-  static_assert(__is_same(remove_volatile_t, int volatile &), "");
-  static_assert(__is_same(remove_volatile_t, int &&), "");
-  static_assert(__is_same(remove_volatile_t, int volatile &&), "");
-  static_assert(__is_same(remove_volatile_t, int()), "");
-  static_assert(__is_same(remove_volatile_t, int (*)()), "");
-  static_assert(__is_same(remove_volatile_t, int (&)()), "");
-
-  static_assert(__is_same(remove_volatile_t, S), "");
-  static_assert(__is_same(remove_volatile_t, const S), "");
-  static_assert(__is_same(remove_volatile_t, S), "");
-  static_assert(__is_same(remove_volatile_t, const S), "");
-  static_assert(__is_same(remove_volatile_t, int S::*), "");
-  static_assert(__is_same(remove_volatile_t, int(S::*)()), "");
+  static_assert(__is_same(remove_volatile_t, void));
+  static_assert(__is_same(remove_volatile_t, void));
+  static_assert(__is_same(remove_volatile_t, int));
+  static_assert(__is_same(remove_volatile_t, const int));
+  static_assert(__is_same(remove_volatile_t, int));
+  static_assert(__is_same(remove_volatile_t, int *__restrict));
+  static_assert(__is_same(remove_volatile_t, const int));
+  static_assert(__is_same(remove_volatile_t, int *const __restrict));
+  static_assert(__is_same(remove_volatile_t, int *));
+  static_assert(__is_same(remove_volatile_t, int *));
+  static_assert(__is_same(remove_volatile_t, int volatile *));
+  static_assert(__is_same(remove_volatile_t, int &));
+  static_assert(__is_same(remove_volatile_t, int volatile &));
+  static_assert(__is_same(remove_volatile_t, int &&));
+  static_assert(__is_same(remove_volatile_t, int volatile &&));
+  static_assert(__is_same(remove_volatile_t, int()));
+  static_assert(__is_same(remove_volatile_t, int (*)()));
+  static_assert(__is_same(remove_volatile_t, int (&)()));
+
+  static_assert(__is_same(remove_volatile_t, S));
+  static_assert(__is_same(remove_volatile_t, const S));
+  static_assert(__is_same(remove_volatile_t, S));
+  static_assert(__is_same(remove_volatile_t, const S));
+  static_assert(__is_same(remove_volatile_t, int S::*));
+  static_assert(__is_same(remove_volatile_t, int(S::*)()));
 }
 
 template  using remove_cv_t = __remove_cv(T);
 
 void check_remove_cv() {
-  static_assert(__is_same(remove_cv_t, void), "");
-  static_assert(__is_same(remove_cv_t, void), "");
-  static_assert(__is_same(remove_cv_t, int), "");
-  static_assert(__is_same(remove_cv_t, int), "");
-  static_assert(__is_same(remove_cv_t, int), "");
-  static_assert(__is_same(remove_cv_t, int), "");
-  static_assert(__is_same(remove_cv_t, int *), "");
-  static_assert(__is_same(remove_cv_t, int *), "");
-  static_assert(__is_same(remove_cv_t, int const *), "");
-  static_assert(__is_same(remove_cv_t, int const *__restrict), "");
-  static_assert(__is_same(remove_cv_t, int const *_Nonnull), "");
-  static_assert(__is_same(remove_cv_t, int &), "");
-  static_assert(__is_same(remove_cv_t, int const volatile &), "");
-  static_assert(__is_same(remove_cv_t, int &&), "");
-  static_assert(__is_same(remove_cv_t, int const volatile &&), "");
-  static_assert(__is_same(remove_cv_t, int()), "");
-  static_assert(__is_same(remove_cv_t, int (*)()), "");
-  static_assert(__is_same(remove_cv_t, int (&)()), "");
-
-  static_assert(__is_same(remove_cv_t, S), "");
-  static_assert(__is_same(remove_cv_t, S), "");
-  static_assert(__is_same(remove_cv_t, S), "");
-  static_assert(__is_same(remove_cv_t, S), "");
-  static_assert(__is_same(remove_cv_t, int S::*), "");
-  static_assert(__is_same(remove_cv_t, int(S::*)()), "");
+  static_assert(__is_same(remove_cv_t, void));
+  static_assert(__is_same(remove_cv_t, void));
+  static_assert(__is_same(remove_cv_t, int));
+  static_assert(__is_same(remove_cv_t, int));
+  static_assert(__is_same(remove_cv_t, int));
+  static_assert(__is_same(remove_cv_t, int));
+  static_assert(__is_same(remove_cv_t, int *));
+  static_assert(__is_same(remove_cv_t, int *));
+  static_assert(__is_same(remove_cv_t, int const *));
+  static_assert(__is_same(remove_cv_t, int const *__restrict));
+  static_assert(__is_same(remove_cv_t, int const *_Nonnull));
+  static_assert(__is_same(remove_cv_t, int &));
+  static_assert(__is_same(remove_cv_t, int const volatile &));
+  static_assert(__is_same(remove_cv_t, int &&));
+  static_assert(__is_same(remove_cv_t, int const volatile &&));
+  static_assert(__is_same(remove_cv_t, int()));
+  static_assert(__is_same(remove_cv_t, int (*)()));
+  static_assert(__is_same(remove_cv_t, int (&)()));
+
+  static_assert(__is_same(remove_cv_t, S));
+  static_assert(__is_same(remove_cv_t, S));
+  static_assert(__is_same(remove_cv_t, S));
+  static_assert(__is_same(remove_cv_t, S));
+  static_assert(__is_same(remove_cv_t, int S::*));
+  static_assert(__is_same(remove_cv_t, int(S::*)()));
 }
 
 template  using add_pointer_t = __add_pointer(T);
 
 void add_pointer() {
-  static_assert(__is_same(add_pointer_t, void *), "");
-  static_assert(__is_same(add_pointer_t, const void *), "");
-  static_assert(__is_same(add_pointer_t, volatile void *), "");
-  static_assert(__is_same(add_pointer_t, const volatile void *), "");
-  static_assert(__is_same(add_pointer_t, int *), "");
-  static_assert(__is_same(add_pointer_t, const int *), "");
-  static_assert(__is_same(add_pointer_t, volatile int *), "");
-  static_assert(__is_same(add_pointer_t, const volatile int *), "");
-  static_assert(__is_same(add_pointer_t, int **), "");
-  static_assert(__is_same(add_pointer_t, int *), "");
-  static_assert(__is_same(add_pointer_t, int *), "");
-  static_assert(__is_same(add_pointer_t, int (*)()), "");
-  static_assert(__is_same(add_pointer_t, int (**)()), "");
-  static_assert(__is_same(add_pointer_t, int (*)()), "");
-
-  static_assert(__is_same(add_pointer_t, S *), "");
-  static_assert(__is_same(add_pointer_t, const S *), "");
-  static_assert(__is_same(add_pointer_t, volatile S *), "");
-  static_assert(__is_same(add_pointer_t, const volatile S *), "");
-  static_assert(__is_same(add_pointer_t, int S::**), "");
-  static_assert(__is_same(add_pointer_t, int(S::**)()), "");
-
-  static_assert(__is_same(add_pointer_t, int __attribute__((address_space(1))) *), "");
-  static_assert(__is_same(add_pointer_t, S __attribute__((address_space(2))) *), "");
+  static_assert(__is_same(add_pointer_t, void *));
+  static_assert(__is_same(add_pointer_t, const void *));
+  static_assert(__is_same(add_pointer_t, volatile void *));
+  static_assert(__is_same(add_pointer_t, const volatile void *));
+  static_assert(__is_same(add_pointer_t, int *));
+  static_assert(__is_same(add_pointer_t, const int *));
+  static_assert(__is_same(add_pointer_t, volatile int *));
+  static_assert(__is_same(add_pointer_t, const volatile int *));
+  static_assert(__is_same(add_pointer_t, int **));
+  static_assert(__is_same(add_pointer_t, int *));
+  static_assert(__is_same(add_pointer_t, int *));
+  static_assert(__is_same(add_pointer_t, int (*)()));
+  static_assert(__is_same(add_pointer_t, int (**)()));
+  static_assert(__is_same(add_pointer_t, int (*)()));
+
+  static_assert(__is_same(add_pointer_t, S *));
+  static_assert(__is_same(add_pointer_t, const S *));
+  static_assert(__is_same(add_pointer_t, volatile S *));
+  static_assert(__is_same(add_pointer_t, const volatile S *));
+  static_assert(__is_same(add_pointer_t, int S::**));
+  static_assert(__is_same(add_pointer_t, int(S::**)()));
+
+  static_assert(__is_same(add_pointer_t, int __attribute__((address_space(1))) *));
+  static_assert(__is_same(add_pointer_t, S __attribute__((address_space(2))) *));
 }
 
 template  using remove_pointer_t = __remove_pointer(T);
 
 void remove_pointer() {
-  static_assert(__is_same(remove_pointer_t, void), "");
-  static_assert(__is_same(remove_pointer_t, const void), "");
-  static_assert(__is_same(remove_pointer_t, volatile void), "");
-  static_assert(__is_same(remove_pointer_t, const volatile void), "");
-  static_assert(__is_same(remove_pointer_t, int), "");
-  static_assert(__is_same(remove_pointer_t, const int), "");
-  static_assert(__is_same(remove_pointer_t, volatile int), "");
-  static_assert(__is_same(remove_pointer_t, const volatile int), "");
-  static_assert(__is_same(remove_pointer_t, int), "");
-  static_assert(__is_same(remove_pointer_t, const int), "");
-  static_assert(__is_same(remove_pointer_t, volatile int), "");
-  static_assert(__is_same(remove_pointer_t, const volatile int), "");
-  static_assert(__is_same(remove_pointer_t, int), "");
-  static_assert(__is_same(remove_pointer_t, int), "");
-  static_assert(__is_same(remove_pointer_t, int), "");
-  static_assert(__is_same(remove_pointer_t, int &), "");
-  static_assert(__is_same(remove_pointer_t, int &&), "");
-  static_assert(__is_same(remove_pointer_t, int()), "");
-  static_assert(__is_same(remove_pointer_t, int()), "");
-  static_assert(__is_same(remove_pointer_t, int (&)()), "");
-
-  static_assert(__is_same(remove_pointer_t, S), "");
-  static_assert(__is_same(remove_pointer_t, const S), "");
-  static_assert(__is_same(remove_pointer_t, volatile S), "");
-  static_assert(__is_same(remove_pointer_t, const volatile S), "");
-  static_assert(__is_same(remove_pointer_t, int S::*), "");
-  static_assert(__is_same(remove_pointer_t, int(S::*)()), "");
-
-  static_assert(__is_same(remove_pointer_t, int __attribute__((address_space(1)))), "");
-  static_assert(__is_same(remove_pointer_t, S  __attribute__((address_space(2)))), "");
-
-  static_assert(__is_same(remove_pointer_t, int (^)(char)), "");
+  static_assert(__is_same(remove_pointer_t, void));
+  static_assert(__is_same(remove_pointer_t, const void));
+  static_assert(__is_same(remove_pointer_t, volatile void));
+  static_assert(__is_same(remove_pointer_t, const volatile void));
+  static_assert(__is_same(remove_pointer_t, int));
+  static_assert(__is_same(remove_pointer_t, const int));
+  static_assert(__is_same(remove_pointer_t, volatile int));
+  static_assert(__is_same(remove_pointer_t, const volatile int));
+  static_assert(__is_same(remove_pointer_t, int));
+  static_assert(__is_same(remove_pointer_t, const int));
+  static_assert(__is_same(remove_pointer_t, volatile int));
+  static_assert(__is_same(remove_pointer_t, const volatile int));
+  static_assert(__is_same(remove_pointer_t, int));
+  static_assert(__is_same(remove_pointer_t, int));
+  static_assert(__is_same(remove_pointer_t, int));
+  static_assert(__is_same(remove_pointer_t, int &));
+  static_assert(__is_same(remove_pointer_t, int &&));
+  static_assert(__is_same(remove_pointer_t, int()));
+  static_assert(__is_same(remove_pointer_t, int()));
+  static_assert(__is_same(remove_pointer_t, int (&)()));
+
+  static_assert(__is_same(remove_pointer_t, S));
+  static_assert(__is_same(remove_pointer_t, const S));
+  static_assert(__is_same(remove_pointer_t, volatile S));
+  static_assert(__is_same(remove_pointer_t, const volatile S));
+  static_assert(__is_same(remove_pointer_t, int S::*));
+  static_assert(__is_same(remove_pointer_t, int(S::*)()));
+
+  static_assert(__is_same(remove_pointer_t, int __attribute__((address_space(1)))));
+  static_assert(__is_same(remove_pointer_t, S  __attribute__((address_space(2)))));
+
+  static_assert(__is_same(remove_pointer_t, int (^)(char)));
 }
 
 template  using add_lvalue_reference_t = __add_lvalue_reference(T);
 
 void add_lvalue_reference() {
-  static_assert(__is_same(add_lvalue_reference_t, void), "");
-  static_assert(__is_same(add_lvalue_reference_t, const void), "");
-  static_assert(__is_same(add_lvalue_reference_t, volatile void), "");
-  static_assert(__is_same(add_lvalue_reference_t, const volatile void), "");
-  static_assert(__is_same(add_lvalue_reference_t, int &), "");
-  static_assert(__is_same(add_lvalue_reference_t, const int &), "");
-  static_assert(__is_same(add_lvalue_reference_t, volatile int &), "");
-  static_assert(__is_same(add_lvalue_reference_t, const volatile int &), "");
-  static_assert(__is_same(add_lvalue_reference_t, int *&), "");
-  static_assert(__is_same(add_lvalue_reference_t, int &), "");
-  static_assert(__is_same(add_lvalue_reference_t, int &), ""); // reference collapsing
-  static_assert(__is_same(add_lvalue_reference_t, int (&)()), "");
-  static_assert(__is_same(add_lvalue_reference_t, int (*&)()), "");
-  static_assert(__is_same(add_lvalue_reference_t, int (&)()), "");
-
-  static_assert(__is_same(add_lvalue_reference_t, S &), "");
-  static_assert(__is_same(add_lvalue_reference_t, const S &), "");
-  static_assert(__is_same(add_lvalue_reference_t, volatile S &), "");
-  static_assert(__is_same(add_lvalue_reference_t, const volatile S &), "");
-  static_assert(__is_same(add_lvalue_reference_t, int S::*&), "");
-  static_assert(__is_same(add_lvalue_reference_t, int(S::*&)()), "");
+  static_assert(__is_same(add_lvalue_reference_t, void));
+  static_assert(__is_same(add_lvalue_reference_t, const void));
+  static_assert(__is_same(add_lvalue_reference_t, volatile void));
+  static_assert(__is_same(add_lvalue_reference_t, const volatile void));
+  static_assert(__is_same(add_lvalue_reference_t, int &));
+  static_assert(__is_same(add_lvalue_reference_t, const int &));
+  static_assert(__is_same(add_lvalue_reference_t, volatile int &));
+  static_assert(__is_same(add_lvalue_reference_t, const volatile int &));
+  static_assert(__is_same(add_lvalue_reference_t, int *&));
+  static_assert(__is_same(add_lvalue_reference_t, int &));
+  static_assert(__is_same(add_lvalue_reference_t, int &)); // reference collapsing
+  static_assert(__is_same(add_lvalue_reference_t, int (&)()));
+  static_assert(__is_same(add_lvalue_reference_t, int (*&)()));
+  static_assert(__is_same(add_lvalue_reference_t, int (&)()));
+
+  static_assert(__is_same(add_lvalue_reference_t, S &));
+  static_assert(__is_same(add_lvalue_reference_t, const S &));
+  static_assert(__is_same(add_lvalue_reference_t, volatile S &));
+  static_assert(__is_same(add_lvalue_reference_t, const volatile S &));
+  static_assert(__is_same(add_lvalue_reference_t, int S::*&));
+  static_assert(__is_same(add_lvalue_reference_t, int(S::*&)()));
 }
 
 template  using add_rvalue_reference_t = __add_rvalue_reference(T);
 
 void add_rvalue_reference() {
-  static_assert(__is_same(add_rvalue_reference_t, void), "");
-  static_assert(__is_same(add_rvalue_reference_t, const void), "");
-  static_assert(__is_same(add_rvalue_reference_t, volatile void), "");
-  static_assert(__is_same(add_rvalue_reference_t, const volatile void), "");
-  static_assert(__is_same(add_rvalue_reference_t, int &&), "");
-  static_assert(__is_same(add_rvalue_reference_t, const int &&), "");
-  static_assert(__is_same(add_rvalue_reference_t, volatile int &&), "");
-  static_assert(__is_same(add_rvalue_reference_t, const volatile int &&), "");
-  static_assert(__is_same(add_rvalue_reference_t, int *&&), "");
-  static_assert(__is_same(add_rvalue_reference_t, int &), ""); // reference collapsing
-  static_assert(__is_same(add_rvalue_reference_t, int &&), "");
-  static_assert(__is_same(add_rvalue_reference_t, int(&&)()), "");
-  static_assert(__is_same(add_rvalue_reference_t, int (*&&)()), "");
-  static_assert(__is_same(add_rvalue_reference_t, int (&)()), ""); // reference collapsing
-
-  static_assert(__is_same(add_rvalue_reference_t, S &&), "");
-  static_assert(__is_same(add_rvalue_reference_t, const S &&), "");
-  static_assert(__is_same(add_rvalue_reference_t, volatile S &&), "");
-  static_assert(__is_same(add_rvalue_reference_t, const volatile S &&), "");
-  static_assert(__is_same(add_rvalue_reference_t, int S::*&&), "");
-  static_assert(__is_same(add_rvalue_reference_t, int(S::* &&)()), "");
+  static_assert(__is_same(add_rvalue_reference_t, void));
+  static_assert(__is_same(add_rvalue_reference_t, const void));
+  static_assert(__is_same(add_rvalue_reference_t, volatile void));
+  static_assert(__is_same(add_rvalue_reference_t, const volatile void));
+  static_assert(__is_same(add_rvalue_reference_t, int &&));
+  static_assert(__is_same(add_rvalue_reference_t, const int &&));
+  static_assert(__is_same(add_rvalue_reference_t, volatile int &&));
+  static_assert(__is_same(add_rvalue_reference_t, const volatile int &&));
+  static_assert(__is_same(add_rvalue_reference_t, int *&&));
+  static_assert(__is_same(add_rvalue_reference_t, int &)); // reference collapsing
+  static_assert(__is_same(add_rvalue_reference_t, int &&));
+  static_assert(__is_same(add_rvalue_reference_t, int(&&)()));
+  static_assert(__is_same(add_rvalue_reference_t, int (*&&)()));
+  static_assert(__is_same(add_rvalue_reference_t, int (&)())); // reference collapsing
+
+  static_assert(__is_same(add_rvalue_reference_t, S &&));
+  static_assert(__is_same(add_rvalue_reference_t, const S &&));
+  static_assert(__is_same(add_rvalue_reference_t, volatile S &&));
+  static_assert(__is_same(add_rvalue_reference_t, const volatile S &&));
+  static_assert(__is_same(add_rvalue_reference_t, int S::*&&));
+  static_assert(__is_same(add_rvalue_reference_t, int(S::* &&)()));
 }
 
 template  using remove_reference_t = __remove_reference_t(T);
 
 void check_remove_reference() {
-  static_assert(__is_same(remove_reference_t, void), "");
-  static_assert(__is_same(remove_reference_t, const volatile void), "");
-  static_assert(__is_same(remove_reference_t, int), "");
-  static_assert(__is_same(remove_reference_t, const int), "");
-  static_assert(__is_same(remove_reference_t, volatile int), "");
-  static_assert(__is_same(remove_reference_t, const volatile int), "");
-  static_assert(__is_same(remove_reference_t, int *), "");
-  static_assert(__is_same(remove_reference_t, int *const volatile), "");
-  static_assert(__is_same(remove_reference_t, int const *const volatile), "");
-  static_assert(__is_same(remove_reference_t, int), "");
-  static_assert(__is_same(remove_reference_t, int const volatile), "");
-  static_assert(__is_same(remove_reference_t, int), "");
-  static_assert(__is_same(remove_reference_t, int const volatile), "");
-  static_assert(__is_same(remove_reference_t, int()), "");
-  static_assert(__is_same(remove_reference_t, int (*const volatile)()), "");
-  static_assert(__is_same(remove_reference_t, int()), "");
-
-  static_assert(__is_same(remove_reference_t, S), "");
-  static_assert(__is_same(remove_reference_t, S), "");
-  static_assert(__is_same(remove_reference_t, S), "");
-  static_assert(__is_same(remove_reference_t, const S), "");
-  static_assert(__is_same(remove_reference_t, const S), "");
-  static_assert(__is_same(remove_reference_t, const S), "");
-  static_assert(__is_same(remove_reference_t, volatile S), "");
-  static_assert(__is_same(remove_reference_t, volatile S), "");
-  static_assert(__is_same(remove_reference_t, volatile S), "");
-  static_assert(__is_same(remove_reference_t, const volatile S), "");
-  static_assert(__is_same(remove_reference_t, const volatile S), "");
-  static_assert(__is_same(remove_reference_t, const volatile S), "");
-  static_assert(__is_same(remove_reference_t, int S::*const volatile), "");
-  static_assert(__is_same(remove_reference_t, int(S::*const volatile)()), "");
-  static_assert(__is_same(remove_reference_t, int(S::*const volatile)() &), "");
+  static_assert(__is_same(remove_reference_t, void));
+  static_assert(__is_same(remove_reference_t, const volatile void));
+  static_assert(__is_same(remove_reference_t, int));
+  static_assert(__is_same(remove_reference_t, const int));
+  static_assert(__is_same(remove_reference_t, volatile int));
+  static_assert(__is_same(remove_reference_t, const volatile int));
+  static_assert(__is_same(remove_reference_t, int *));
+  static_assert(__is_same(remove_reference_t, int *const volatile));
+  static_assert(__is_same(remove_reference_t, int const *const volatile));
+  static_assert(__is_same(remove_reference_t, int));
+  static_assert(__is_same(remove_reference_t, int const volatile));
+  static_assert(__is_same(remove_reference_t, int));
+  static_assert(__is_same(remove_reference_t, int const volatile));
+  static_assert(__is_same(remove_reference_t, int()));
+  static_assert(__is_same(remove_reference_t, int (*const volatile)()));
+  static_assert(__is_same(remove_reference_t, int()));
+
+  static_assert(__is_same(remove_reference_t, S));
+  static_assert(__is_same(remove_reference_t, S));
+  static_assert(__is_same(remove_reference_t, S));
+  static_assert(__is_same(remove_reference_t, const S));
+  static_assert(__is_same(remove_reference_t, const S));
+  static_assert(__is_same(remove_reference_t, const S));
+  static_assert(__is_same(remove_reference_t, volatile S));
+  static_assert(__is_same(remove_reference_t, volatile S));
+  static_assert(__is_same(remove_reference_t, volatile S));
+  static_assert(__is_same(remove_reference_t, const volatile S));
+  static_assert(__is_same(remove_reference_t, const volatile S));
+  static_assert(__is_same(remove_reference_t, const volatile S));
+  static_assert(__is_same(remove_reference_t, int S::*const volatile));
+  static_assert(__is_same(remove_reference_t, int(S::*const volatile)()));
+  static_assert(__is_same(remove_reference_t, int(S::*const volatile)() &));
 }
 
 template  using remove_cvref_t = __remove_cvref(T);
 
 void check_remove_cvref() {
-  static_assert(__is_same(remove_cvref_t, void), "");
-  static_assert(__is_same(remove_cvref_t, void), "");
-  static_assert(__is_same(remove_cvref_t, int), "");
-  static_assert(__is_same(remove_cvref_t, int), "");
-  static_assert(__is_same(remove_cvref_t, int), "");
-  static_assert(__is_same(remove_cvref_t, int), "");
-  static_assert(__is_same(remove_cvref_t, int *), "");
-  static_assert(__is_same(remove_cvref_t, int *), "");
-  static_assert(__is_same(remove_cvref_t, int const *), "");
-  static_assert(__is_same(remove_cvref_t, int const *__restrict), "");
-  static_assert(__is_same(remove_cvref_t, int const *_Nonnull), "");
-  static_assert(__is_same(remove_cvref_t, int), "");
-  static_assert(__is_same(remove_cvref_t, int), "");
-  static_assert(__is_same(remove_cvref_t, int), "");
-  static_assert(__is_same(remove_cvref_t, int), "");
-  static_assert(__is_same(remove_cvref_t, int()), "");
-  static_assert(__is_same(remove_cvref_t, int (*)()), "");
-  static_assert(__is_same(remove_cvref_t, int()), "");
-
-  static_assert(__is_same(remove_cvref_t, S), "");
-  static_assert(__is_same(remove_cvref_t, S), "");
-  static_assert(__is_same(remove_cvref_t, S), "");
-  static_assert(__is_same(remove_cvref_t, S), "");
-  static_assert(__is_same(remove_cvref_t, S), "");
-  static_assert(__is_same(remove_cvref_t, S), "");
-  static_assert(__is_same(remove_cvref_t, S), "");
-  static_assert(__is_same(remove_cvref_t, S), "");
-  static_assert(__is_same(remove_cvref_t, S), "");
-  static_assert(__is_same(remove_cvref_t, S), "");
-  static_assert(__is_same(remove_cvref_t, S), "");
-  static_assert(__is_same(remove_cvref_t, S), "");
-  static_assert(__is_same(remove_cvref_t, int S::*), "");
-  static_assert(__is_same(remove_cvref_t, int(S::*)()), "");
-  static_assert(__is_same(remove_cvref_t, int(S::*)() &), "");
-  static_assert(__is_same(remove_cvref_t, int(S::*)() &&), "");
+  static_assert(__is_same(remove_cvref_t, void));
+  static_assert(__is_same(remove_cvref_t, void));
+  static_assert(__is_same(remove_cvref_t, int));
+  static_assert(__is_same(remove_cvref_t, int));
+  static_assert(__is_same(remove_cvref_t, int));
+  static_assert(__is_same(remove_cvref_t, int));
+  static_assert(__is_same(remove_cvref_t, int *));
+  static_assert(__is_same(remove_cvref_t, int *));
+  static_assert(__is_same(remove_cvref_t, int const *));
+  static_assert(__is_same(remove_cvref_t, int const *__restrict));
+  static_assert(__is_same(remove_cvref_t, int const *_Nonnull));
+  static_assert(__is_same(remove_cvref_t, int));
+  static_assert(__is_same(remove_cvref_t, int));
+  static_assert(__is_same(remove_cvref_t, int));
+  static_assert(__is_same(remove_cvref_t, int));
+  static_assert(__is_same(remove_cvref_t, int()));
+  static_assert(__is_same(remove_cvref_t, int (*)()));
+  static_assert(__is_same(remove_cvref_t, int()));
+
+  static_assert(__is_same(remove_cvref_t, S));
+  static_assert(__is_same(remove_cvref_t, S));
+  static_assert(__is_same(remove_cvref_t, S));
+  static_assert(__is_same(remove_cvref_t, S));
+  static_assert(__is_same(remove_cvref_t, S));
+  static_assert(__is_same(remove_cvref_t, S));
+  static_assert(__is_same(remove_cvref_t, S));
+  static_assert(__is_same(remove_cvref_t, S));
+  static_assert(__is_same(remove_cvref_t, S));
+  static_assert(__is_same(remove_cvref_t, S));
+  static_assert(__is_same(remove_cvref_t, S));
+  static_assert(__is_same(remove_cvref_t, S));
+  static_assert(__is_same(remove_cvref_t, int S::*));
+  static_assert(__is_same(remove_cvref_t, int(S::*)()));
+  static_assert(__is_same(remove_cvref_t, int(S::*)() &));
+  static_assert(__is_same(remove_cvref_t, int(S::*)() &&));
 }
 
 template  using decay_t = __decay(T);
 
 void check_decay() {
-  static_assert(__is_same(decay_t, void), "");
-  static_assert(__is_same(decay_t, void), "");
-  static_assert(__is_same(decay_t, int), "");
-  static_assert(__is_same(decay_t, int), "");
-  static_assert(__is_same(decay_t, int), "");
-  static_assert(__is_same(decay_t, int), "");
-  static_assert(__is_same(decay_t, int *), "");
-  static_assert(__is_same(decay_t, int *), "");
-  static_assert(__is_same(decay_t, int *), "");
-  static_assert(__is_same(decay_t, int const *), "");
-  static_assert(__is_same(decay_t, int const *), "");
-  static_assert(__is_same(decay_t, int), "");
-  static_assert(__is_same(decay_t, int), "");
-  static_assert(__is_same(decay_t, int), "");
-  static_assert(__is_same(decay_t, int), "");
-  static_assert(__is_same(decay_t, int (*)()), "");
-  static_assert(__is_same(decay_t, int (*)()), "");
-  static_assert(__is_same(decay_t, int (*)()), "");
-  static_assert(__is_same(decay_t, int (*)()), "");
-  static_assert(__is_same(decay_t, int (*)()), "");
-  static_assert(__is_same(decay_t, int (*)()), "");
-  static_assert(__is_same(decay_t, int *), "");
-  static_assert(__is_same(decay_t, int *), "");
-
-  static_assert(__is_same(decay_t, S), "");
-  static_assert(__is_same(decay_t, S), "");
-  static_assert(__is_same(decay_t, S), "");
-  static_assert(__is_same(decay_t, S), "");
-  static_assert(__is_same(decay_t, S), "");
-  static_assert(__is_same(decay_t, S), "");
-  static_assert(__is_same(decay_t, S), "");
-  static_assert(__is_same(decay_t, S), "");
-  static_assert(__is_same(decay_t, S), "");
-  static_assert(__is_same(decay_t, S), "");
-  static_assert(__is_same(decay_t, S), "");
-  static_assert(__is_same(decay_t, S), "");
-  static_assert(__is_same(decay_t, int S::*), "");
-  static_assert(__is_same(decay_t, int(S::*)()), "");
-  static_assert(__is_same(decay_t, int S::*), "");
-  static_assert(__is_same(decay_t, int(S::*)()), "");
-  static_assert(__is_same(decay_t, int S::*), "");
+  static_assert(__is_same(decay_t, void));
+  static_assert(__is_same(decay_t, void));
+  static_assert(__is_same(decay_t, int));
+  static_assert(__is_same(decay_t, int));
+  static_assert(__is_same(decay_t, int));
+  static_assert(__is_same(decay_t, int));
+  static_assert(__is_same(decay_t, int *));
+  static_assert(__is_same(decay_t, int *));
+  static_assert(__is_same(decay_t, int *));
+  static_assert(__is_same(decay_t, int const *));
+  static_assert(__is_same(decay_t, int const *));
+  static_assert(__is_same(decay_t, int));
+  static_assert(__is_same(decay_t, int));
+  static_assert(__is_same(decay_t, int));
+  static_assert(__is_same(decay_t, int));
+  static_assert(__is_same(decay_t, int (*)()));
+  static_assert(__is_same(decay_t, int (*)()));
+  static_assert(__is_same(decay_t, int (*)()));
+  static_assert(__is_same(decay_t, int (*)()));
+  static_assert(__is_same(decay_t, int (*)()));
+  static_assert(__is_same(decay_t, int (*)()));
+  static_assert(__is_same(decay_t, int *));
+  static_assert(__is_same(decay_t, int *));
+
+  static_assert(__is_same(decay_t, S));
+  static_assert(__is_same(decay_t, S));
+  static_assert(__is_same(decay_t, S));
+  static_assert(__is_same(decay_t, S));
+  static_assert(__is_same(decay_t, S));
+  static_assert(__is_same(decay_t, S));
+  static_assert(__is_same(decay_t, S));
+  static_assert(__is_same(decay_t, S));
+  static_assert(__is_same(decay_t, S));
+  static_assert(__is_same(decay_t, S));
+  static_assert(__is_same(decay_t, S));
+  static_assert(__is_same(decay_t, S));
+  static_assert(__is_same(decay_t, int S::*));
+  static_assert(__is_same(decay_t, int(S::*)()));
+  static_assert(__is_same(decay_t, int S::*));
+  static_assert(__is_same(decay_t, int(S::*)()));
+  static_assert(__is_same(decay_t, int S::*));
 }
 
 template  struct CheckAbominableFunction {};
 template 
 struct CheckAbominableFunction {
   static void checks() {
-    static_assert(__is_same(add_lvalue_reference_t, M), "");
-    static_assert(__is_same(add_pointer_t, M), "");
-    static_assert(__is_same(add_rvalue_reference_t, M), "");
-    static_assert(__is_same(decay_t, M), "");
-    static_assert(__is_same(remove_const_t, M), "");
-    static_assert(__is_same(remove_volatile_t, M), "");
-    static_assert(__is_same(remove_cv_t, M), "");
-    static_assert(__is_same(remove_cvref_t, M), "");
-    static_assert(__is_same(remove_pointer_t, M), "");
-    static_assert(__is_same(remove_reference_t, M), "");
-
-    static_assert(!__is_referenceable(M), "");
+    static_assert(__is_same(add_lvalue_reference_t, M));
+    static_assert(__is_same(add_pointer_t, M));
+    static_assert(__is_same(add_rvalue_reference_t, M));
+    static_assert(__is_same(decay_t, M));
+    static_assert(__is_same(remove_const_t, M));
+    static_assert(__is_same(remove_volatile_t, M));
+    static_assert(__is_same(remove_cv_t, M));
+    static_assert(__is_same(remove_cvref_t, M));
+    static_assert(__is_same(remove_pointer_t, M));
+    static_assert(__is_same(remove_reference_t, M));
+
+    static_assert(!__is_referenceable(M));
   }
 };
 
@@ -4226,10 +4251,10 @@ void check_abominable_function() {
 template  using make_signed_t = __make_signed(T);
 template 
 void check_make_signed() {
-  static_assert(__is_same(make_signed_t, Expected), "");
-  static_assert(__is_same(make_signed_t, const Expected), "");
-  static_assert(__is_same(make_signed_t, volatile Expected), "");
-  static_assert(__is_same(make_signed_t, const volatile Expected), "");
+  static_assert(__is_same(make_signed_t, Expected));
+  static_assert(__is_same(make_signed_t, const Expected));
+  static_assert(__is_same(make_signed_t, volatile Expected));
+  static_assert(__is_same(make_signed_t, const volatile Expected));
 }
 
 #if defined(__ILP32__) || defined(__LLP64__)
@@ -4339,10 +4364,10 @@ using make_unsigned_t = __make_unsigned(T);
 
 template 
 void check_make_unsigned() {
-  static_assert(__is_same(make_unsigned_t, Expected), "");
-  static_assert(__is_same(make_unsigned_t, const Expected), "");
-  static_assert(__is_same(make_unsigned_t, volatile Expected), "");
-  static_assert(__is_same(make_unsigned_t, const volatile Expected), "");
+  static_assert(__is_same(make_unsigned_t, Expected));
+  static_assert(__is_same(make_unsigned_t, const Expected));
+  static_assert(__is_same(make_unsigned_t, volatile Expected));
+  static_assert(__is_same(make_unsigned_t, const volatile Expected));
 }
 
 void make_unsigned() {
@@ -4425,74 +4450,74 @@ void make_unsigned() {
 template  using remove_extent_t = __remove_extent(T);
 
 void remove_extent() {
-  static_assert(__is_same(remove_extent_t, void), "");
-  static_assert(__is_same(remove_extent_t, int), "");
-  static_assert(__is_same(remove_extent_t, int), "");
-  static_assert(__is_same(remove_extent_t, int), "");
-  static_assert(__is_same(remove_extent_t, int[2]), "");
-  static_assert(__is_same(remove_extent_t, int[2]), "");
-  static_assert(__is_same(remove_extent_t, const int), "");
-  static_assert(__is_same(remove_extent_t, const int), "");
-  static_assert(__is_same(remove_extent_t, const int[2]), "");
-  static_assert(__is_same(remove_extent_t, const int[2]), "");
-  static_assert(__is_same(remove_extent_t, volatile int), "");
-  static_assert(__is_same(remove_extent_t, volatile int), "");
-  static_assert(__is_same(remove_extent_t, volatile int[2]), "");
-  static_assert(__is_same(remove_extent_t, volatile int[2]), "");
-  static_assert(__is_same(remove_extent_t, const volatile int), "");
-  static_assert(__is_same(remove_extent_t, const volatile int), "");
-  static_assert(__is_same(remove_extent_t, const volatile int[2]), "");
-  static_assert(__is_same(remove_extent_t, const volatile int[2]), "");
-  static_assert(__is_same(remove_extent_t, int *), "");
-  static_assert(__is_same(remove_extent_t, int &), "");
-  static_assert(__is_same(remove_extent_t, int &&), "");
-  static_assert(__is_same(remove_extent_t, int()), "");
-  static_assert(__is_same(remove_extent_t, int (*)()), "");
-  static_assert(__is_same(remove_extent_t, int (&)()), "");
-
-  static_assert(__is_same(remove_extent_t, S), "");
-  static_assert(__is_same(remove_extent_t, int S::*), "");
-  static_assert(__is_same(remove_extent_t, int(S::*)()), "");
+  static_assert(__is_same(remove_extent_t, void));
+  static_assert(__is_same(remove_extent_t, int));
+  static_assert(__is_same(remove_extent_t, int));
+  static_assert(__is_same(remove_extent_t, int));
+  static_assert(__is_same(remove_extent_t, int[2]));
+  static_assert(__is_same(remove_extent_t, int[2]));
+  static_assert(__is_same(remove_extent_t, const int));
+  static_assert(__is_same(remove_extent_t, const int));
+  static_assert(__is_same(remove_extent_t, const int[2]));
+  static_assert(__is_same(remove_extent_t, const int[2]));
+  static_assert(__is_same(remove_extent_t, volatile int));
+  static_assert(__is_same(remove_extent_t, volatile int));
+  static_assert(__is_same(remove_extent_t, volatile int[2]));
+  static_assert(__is_same(remove_extent_t, volatile int[2]));
+  static_assert(__is_same(remove_extent_t, const volatile int));
+  static_assert(__is_same(remove_extent_t, const volatile int));
+  static_assert(__is_same(remove_extent_t, const volatile int[2]));
+  static_assert(__is_same(remove_extent_t, const volatile int[2]));
+  static_assert(__is_same(remove_extent_t, int *));
+  static_assert(__is_same(remove_extent_t, int &));
+  static_assert(__is_same(remove_extent_t, int &&));
+  static_assert(__is_same(remove_extent_t, int()));
+  static_assert(__is_same(remove_extent_t, int (*)()));
+  static_assert(__is_same(remove_extent_t, int (&)()));
+
+  static_assert(__is_same(remove_extent_t, S));
+  static_assert(__is_same(remove_extent_t, int S::*));
+  static_assert(__is_same(remove_extent_t, int(S::*)()));
 
   using SomeArray = int[1][2];
-  static_assert(__is_same(remove_extent_t, const int[2]), "");
+  static_assert(__is_same(remove_extent_t, const int[2]));
 }
 
 template  using remove_all_extents_t = __remove_all_extents(T);
 
 void remove_all_extents() {
-  static_assert(__is_same(remove_all_extents_t, void), "");
-  static_assert(__is_same(remove_all_extents_t, int), "");
-  static_assert(__is_same(remove_all_extents_t, const int), "");
-  static_assert(__is_same(remove_all_extents_t, volatile int), "");
-  static_assert(__is_same(remove_all_extents_t, const volatile int), "");
-  static_assert(__is_same(remove_all_extents_t, int), "");
-  static_assert(__is_same(remove_all_extents_t, int), "");
-  static_assert(__is_same(remove_all_extents_t, int), "");
-  static_assert(__is_same(remove_all_extents_t, int), "");
-  static_assert(__is_same(remove_all_extents_t, const int), "");
-  static_assert(__is_same(remove_all_extents_t, const int), "");
-  static_assert(__is_same(remove_all_extents_t, const int), "");
-  static_assert(__is_same(remove_all_extents_t, const int), "");
-  static_assert(__is_same(remove_all_extents_t, volatile int), "");
-  static_assert(__is_same(remove_all_extents_t, volatile int), "");
-  static_assert(__is_same(remove_all_extents_t, volatile int), "");
-  static_assert(__is_same(remove_all_extents_t, volatile int), "");
-  static_assert(__is_same(remove_all_extents_t, const volatile int), "");
-  static_assert(__is_same(remove_all_extents_t, const volatile int), "");
-  static_assert(__is_same(remove_all_extents_t, const volatile int), "");
-  static_assert(__is_same(remove_all_extents_t, const volatile int), "");
-  static_assert(__is_same(remove_all_extents_t, int *), "");
-  static_assert(__is_same(remove_all_extents_t, int &), "");
-  static_assert(__is_same(remove_all_extents_t, int &&), "");
-  static_assert(__is_same(remove_all_extents_t, int()), "");
-  static_assert(__is_same(remove_all_extents_t, int (*)()), "");
-  static_assert(__is_same(remove_all_extents_t, int (&)()), "");
-
-  static_assert(__is_same(remove_all_extents_t, S), "");
-  static_assert(__is_same(remove_all_extents_t, int S::*), "");
-  static_assert(__is_same(remove_all_extents_t, int(S::*)()), "");
+  static_assert(__is_same(remove_all_extents_t, void));
+  static_assert(__is_same(remove_all_extents_t, int));
+  static_assert(__is_same(remove_all_extents_t, const int));
+  static_assert(__is_same(remove_all_extents_t, volatile int));
+  static_assert(__is_same(remove_all_extents_t, const volatile int));
+  static_assert(__is_same(remove_all_extents_t, int));
+  static_assert(__is_same(remove_all_extents_t, int));
+  static_assert(__is_same(remove_all_extents_t, int));
+  static_assert(__is_same(remove_all_extents_t, int));
+  static_assert(__is_same(remove_all_extents_t, const int));
+  static_assert(__is_same(remove_all_extents_t, const int));
+  static_assert(__is_same(remove_all_extents_t, const int));
+  static_assert(__is_same(remove_all_extents_t, const int));
+  static_assert(__is_same(remove_all_extents_t, volatile int));
+  static_assert(__is_same(remove_all_extents_t, volatile int));
+  static_assert(__is_same(remove_all_extents_t, volatile int));
+  static_assert(__is_same(remove_all_extents_t, volatile int));
+  static_assert(__is_same(remove_all_extents_t, const volatile int));
+  static_assert(__is_same(remove_all_extents_t, const volatile int));
+  static_assert(__is_same(remove_all_extents_t, const volatile int));
+  static_assert(__is_same(remove_all_extents_t, const volatile int));
+  static_assert(__is_same(remove_all_extents_t, int *));
+  static_assert(__is_same(remove_all_extents_t, int &));
+  static_assert(__is_same(remove_all_extents_t, int &&));
+  static_assert(__is_same(remove_all_extents_t, int()));
+  static_assert(__is_same(remove_all_extents_t, int (*)()));
+  static_assert(__is_same(remove_all_extents_t, int (&)()));
+
+  static_assert(__is_same(remove_all_extents_t, S));
+  static_assert(__is_same(remove_all_extents_t, int S::*));
+  static_assert(__is_same(remove_all_extents_t, int(S::*)()));
 
   using SomeArray = int[1][2];
-  static_assert(__is_same(remove_all_extents_t, const int), "");
+  static_assert(__is_same(remove_all_extents_t, const int));
 }
diff --git a/clang/test/SemaCXX/warn-self-move.cpp b/clang/test/SemaCXX/warn-self-move.cpp
index 0987e9b6bf6017c8134829eb6c4681819322f075..5937bb705ed22726ae67811cb03efe09055b0a18 100644
--- a/clang/test/SemaCXX/warn-self-move.cpp
+++ b/clang/test/SemaCXX/warn-self-move.cpp
@@ -16,6 +16,9 @@ void int_test() {
   x = std::move(x);  // expected-warning{{explicitly moving}}
   (x) = std::move(x);  // expected-warning{{explicitly moving}}
 
+  x = static_cast(x);  // expected-warning{{explicitly moving}}
+  (x) = static_cast(x);  // expected-warning{{explicitly moving}}
+
   using std::move;
   x = move(x); // expected-warning{{explicitly moving}} \
                    expected-warning {{unqualified call to 'std::move}}
@@ -26,6 +29,9 @@ void global_int_test() {
   global = std::move(global);  // expected-warning{{explicitly moving}}
   (global) = std::move(global);  // expected-warning{{explicitly moving}}
 
+  global = static_cast(global);  // expected-warning{{explicitly moving}}
+  (global) = static_cast(global);  // expected-warning{{explicitly moving}}
+
   using std::move;
   global = move(global); // expected-warning{{explicitly moving}} \
                              expected-warning {{unqualified call to 'std::move}}
@@ -35,11 +41,16 @@ class field_test {
   int x;
   field_test(field_test&& other) {
     x = std::move(x);  // expected-warning{{explicitly moving}}
+    x = static_cast(x);  // expected-warning{{explicitly moving}}
     x = std::move(other.x);
+    x = static_cast(other.x);
     other.x = std::move(x);
+    other.x = static_cast(x);
     other.x = std::move(other.x);  // expected-warning{{explicitly moving}}
+    other.x = static_cast(other.x);  // expected-warning{{explicitly moving}}
   }
   void withSuggest(int x) {
+    x = static_cast(x); // expected-warning{{explicitly moving variable of type 'int' to itself; did you mean to move to member 'x'?}}
     x = std::move(x); // expected-warning{{explicitly moving variable of type 'int' to itself; did you mean to move to member 'x'?}}
   }
 };
@@ -50,11 +61,15 @@ struct C { C() {}; ~C() {} };
 void struct_test() {
   A a;
   a = std::move(a);  // expected-warning{{explicitly moving}}
+  a = static_cast(a);  // expected-warning{{explicitly moving}}
 
   B b;
   b = std::move(b);  // expected-warning{{explicitly moving}}
+  b = static_cast(b);  // expected-warning{{explicitly moving}}
   b.a = std::move(b.a);  // expected-warning{{explicitly moving}}
+  b.a = static_cast(b.a);  // expected-warning{{explicitly moving}}
 
   C c;
   c = std::move(c);  // expected-warning{{explicitly moving}}
+  c = static_cast(c);  // expected-warning{{explicitly moving}}
 }
diff --git a/clang/test/SemaCXX/warn-unsequenced-paren-list-init.cpp b/clang/test/SemaCXX/warn-unsequenced-paren-list-init.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5aeeb45f81e226c311f0159d419f88c70b8aef18
--- /dev/null
+++ b/clang/test/SemaCXX/warn-unsequenced-paren-list-init.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -Wno-unused -Wunsequenced -verify %s
+
+struct A {
+  int x, y;
+};
+
+void test() {
+  int a = 0;
+
+  A agg1( a++, a++ ); // no warning
+  A agg2( a++ + a, a++ ); // expected-warning {{unsequenced modification and access to 'a'}}
+
+  int arr1[]( a++, a++ ); // no warning
+  int arr2[]( a++ + a, a++ ); // expected-warning {{unsequenced modification and access to 'a'}}
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/any-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/any-errors.hlsl
new file mode 100644
index 0000000000000000000000000000000000000000..862b94652073122e6249d7a60e2df9b58c838cab
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/any-errors.hlsl
@@ -0,0 +1,12 @@
+
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected
+
+bool test_too_few_arg() {
+  return __builtin_hlsl_elementwise_any();
+  // expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+bool test_too_many_arg(float2 p0) {
+  return __builtin_hlsl_elementwise_any(p0, p0);
+  // expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/exp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/exp-errors.hlsl
new file mode 100644
index 0000000000000000000000000000000000000000..e2e79abb74a32d213cacef1a53ebde3004f2a917
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/exp-errors.hlsl
@@ -0,0 +1,27 @@
+
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected -DTEST_FUNC=__builtin_elementwise_exp
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected -DTEST_FUNC=__builtin_elementwise_exp2
+float test_too_few_arg() {
+  return TEST_FUNC();
+  // expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+float2 test_too_many_arg(float2 p0) {
+  return TEST_FUNC(p0, p0);
+  // expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+float builtin_bool_to_float_type_promotion(bool p1) {
+  return TEST_FUNC(p1);
+  // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'bool')}}
+}
+
+float builtin_exp_int_to_float_promotion(int p1) {
+  return TEST_FUNC(p1);
+  // expected-error@-1 {{1st argument must be a floating point type (was 'int')}}
+}
+
+float2 builtin_exp_int2_to_float2_promotion(int2 p1) {
+  return TEST_FUNC(p1);
+  // expected-error@-1 {{1st argument must be a floating point type (was 'int2' (aka 'vector'))}}
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl
new file mode 100644
index 0000000000000000000000000000000000000000..0b6843591455bd3ff89e58456aa26a89079b5db2
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected
+
+float2 test_no_second_arg(float2 p0) {
+  return __builtin_hlsl_mad(p0);
+  // expected-error@-1 {{too few arguments to function call, expected 3, have 1}}
+}
+
+float2 test_no_third_arg(float2 p0) {
+  return __builtin_hlsl_mad(p0, p0);
+  // expected-error@-1 {{too few arguments to function call, expected 3, have 2}}
+}
+
+float2 test_too_many_arg(float2 p0) {
+  return __builtin_hlsl_mad(p0, p0, p0, p0);
+  // expected-error@-1 {{too many arguments to function call, expected 3, have 4}}
+}
+
+float2 test_mad_no_second_arg(float2 p0) {
+  return mad(p0);
+  // expected-error@-1 {{no matching function for call to 'mad'}}
+}
+
+float2 test_mad_vector_size_mismatch(float3 p0, float2 p1) {
+  return mad(p0, p0, p1);
+  // expected-warning@-1 {{implicit conversion truncates vector: 'float3' (aka 'vector') to 'float __attribute__((ext_vector_type(2)))' (vector of 2 'float' values)}}
+}
+
+float2 test_mad_builtin_vector_size_mismatch(float3 p0, float2 p1) {
+  return __builtin_hlsl_mad(p0, p1, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_mad' must have the same type}}
+}
+
+float test_mad_scalar_mismatch(float p0, half p1) {
+  return mad(p1, p0, p1);
+  // expected-error@-1 {{call to 'mad' is ambiguous}}
+}
+
+float2 test_mad_element_type_mismatch(half2 p0, float2 p1) {
+  return mad(p1, p0, p1);
+  // expected-error@-1 {{call to 'mad' is ambiguous}}
+}
+
+float2 test_builtin_mad_float2_splat(float p0, float2 p1) {
+  return __builtin_hlsl_mad(p0, p1, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_mad' must be vectors}}
+}
+
+float3 test_builtin_mad_float3_splat(float p0, float3 p1) {
+  return __builtin_hlsl_mad(p0, p1, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_mad' must be vectors}}
+}
+
+float4 test_builtin_mad_float4_splat(float p0, float4 p1) {
+  return __builtin_hlsl_mad(p0, p1, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_mad' must be vectors}}
+}
+
+float2 test_mad_float2_int_splat(float2 p0, int p1) {
+  return __builtin_hlsl_mad(p0, p1, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_mad' must be vectors}}
+}
+
+float3 test_mad_float3_int_splat(float3 p0, int p1) {
+  return __builtin_hlsl_mad(p0, p1, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_mad' must be vectors}}
+}
+
+float2 test_builtin_mad_int_vect_to_float_vec_promotion(int2 p0, float p1) {
+  return __builtin_hlsl_mad(p0, p1, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_mad' must be vectors}}
+}
+
+float builtin_bool_to_float_type_promotion(float p0, bool p1) {
+  return __builtin_hlsl_mad(p0, p0, p1);
+  // expected-error@-1 {{3rd argument must be a vector, integer or floating point type (was 'bool')}}
+}
+
+float builtin_bool_to_float_type_promotion2(bool p0, float p1) {
+  return __builtin_hlsl_mad(p1, p0, p1);
+  // expected-error@-1 {{2nd argument must be a vector, integer or floating point type (was 'bool')}}
+}
+
+float builtin_mad_int_to_float_promotion(float p0, int p1) {
+  return __builtin_hlsl_mad(p0, p0, p1);
+  // expected-error@-1 {{arguments are of different types ('double' vs 'int')}}
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl
new file mode 100644
index 0000000000000000000000000000000000000000..dc4501dbd6d15a48e56ba8d7207d77348b23f19b
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/rcp-errors.hlsl
@@ -0,0 +1,27 @@
+
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected
+
+float test_too_few_arg() {
+  return __builtin_hlsl_elementwise_rcp();
+  // expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+float2 test_too_many_arg(float2 p0) {
+  return __builtin_hlsl_elementwise_rcp(p0, p0);
+  // expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+float builtin_bool_to_float_type_promotion(bool p1) {
+  return __builtin_hlsl_elementwise_rcp(p1);
+  // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'bool')}}
+}
+
+float builtin_rcp_int_to_float_promotion(int p1) {
+  return __builtin_hlsl_elementwise_rcp(p1);
+  // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}}
+}
+
+float2 builtin_rcp_int2_to_float2_promotion(int2 p1) {
+  return __builtin_hlsl_elementwise_rcp(p1);
+  // expected-error@-1 {{passing 'int2' (aka 'vector') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
+}
diff --git a/clang/test/SemaObjC/integer-overflow.m b/clang/test/SemaObjC/integer-overflow.m
index 6d82e2951c1e656cac1df41a02e2267aef695673..255142729f8d56cfa56dd39f4db0de5426c9323e 100644
--- a/clang/test/SemaObjC/integer-overflow.m
+++ b/clang/test/SemaObjC/integer-overflow.m
@@ -9,10 +9,10 @@
 }
 
 - (void)testIntegerOverflows {
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (void)[self add:0 with:4608 * 1024 * 1024];
 
-// expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
+// expected-warning@+1 {{overflow in expression; result is 536'870'912 with type 'int'}}
   (void)[self add:0 with:[self add:4608 * 1024 * 1024 with:0]];
 }
 @end
diff --git a/clang/test/SemaObjC/objc-literal-nsnumber.m b/clang/test/SemaObjC/objc-literal-nsnumber.m
index aa7dc955fb5feb2706d9f27351eb1686a072a626..a6c098947b0b2aadbd959f6d9b1a989f1b4c9f6a 100644
--- a/clang/test/SemaObjC/objc-literal-nsnumber.m
+++ b/clang/test/SemaObjC/objc-literal-nsnumber.m
@@ -64,7 +64,7 @@ int main(void) {
   @-five; // expected-error{{@- must be followed by a number to form an NSNumber object}}
   @+five; // expected-error{{@+ must be followed by a number to form an NSNumber object}}
   NSNumber *av = @(1391126400000);
-  NSNumber *bv = @(1391126400 * 1000); // expected-warning {{overflow in expression; result is -443003904 with type 'int'}}
+  NSNumber *bv = @(1391126400 * 1000); // expected-warning {{overflow in expression; result is -443'003'904 with type 'int'}}
   NSNumber *cv = @(big * thousand);
 }
 
diff --git a/clang/test/SemaOpenACC/compute-construct-ast.cpp b/clang/test/SemaOpenACC/compute-construct-ast.cpp
index 351fd1c3e0ee5615ecad4197123e79a22b91b9dc..55c080838a18861a0abe99e2b4c0c39dede64a2f 100644
--- a/clang/test/SemaOpenACC/compute-construct-ast.cpp
+++ b/clang/test/SemaOpenACC/compute-construct-ast.cpp
@@ -1,5 +1,12 @@
 // RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s
 
+// Test this with PCH.
+// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s
+// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s
+
+#ifndef PCH_HELPER
+#define PCH_HELPER
+
 void NormalFunc() {
   // FIXME: Add a test once we have clauses for this.
   // CHECK-LABEL: NormalFunc
@@ -15,6 +22,30 @@ void NormalFunc() {
 #pragma acc parallel
     {}
   }
+  // FIXME: Add a test once we have clauses for this.
+  // CHECK-NEXT: OpenACCComputeConstruct {{.*}}serial
+  // CHECK-NEXT: CompoundStmt
+#pragma acc serial
+  {
+#pragma acc serial
+  // CHECK-NEXT: OpenACCComputeConstruct {{.*}}serial
+  // CHECK-NEXT: OpenACCComputeConstruct {{.*}}serial
+  // CHECK-NEXT: CompoundStmt
+#pragma acc serial
+    {}
+  }
+  // FIXME: Add a test once we have clauses for this.
+  // CHECK-NEXT: OpenACCComputeConstruct {{.*}}kernels
+  // CHECK-NEXT: CompoundStmt
+#pragma acc kernels
+  {
+#pragma acc kernels
+  // CHECK-NEXT: OpenACCComputeConstruct {{.*}}kernels
+  // CHECK-NEXT: OpenACCComputeConstruct {{.*}}kernels
+  // CHECK-NEXT: CompoundStmt
+#pragma acc kernels
+    {}
+  }
 }
 
 template
@@ -24,6 +55,16 @@ void TemplFunc() {
     typename T::type I;
   }
 
+#pragma acc serial
+  {
+    typename T::type I;
+  }
+
+#pragma acc kernels
+  {
+    typename T::type I;
+  }
+
   // CHECK-LABEL: FunctionTemplateDecl {{.*}}TemplFunc
   // CHECK-NEXT: TemplateTypeParmDecl
 
@@ -34,6 +75,14 @@ void TemplFunc() {
   // CHECK-NEXT: CompoundStmt
   // CHECK-NEXT: DeclStmt
   // CHECK-NEXT: VarDecl{{.*}} I 'typename T::type'
+  // CHECK-NEXT: OpenACCComputeConstruct {{.*}}serial
+  // CHECK-NEXT: CompoundStmt
+  // CHECK-NEXT: DeclStmt
+  // CHECK-NEXT: VarDecl{{.*}} I 'typename T::type'
+  // CHECK-NEXT: OpenACCComputeConstruct {{.*}}kernels
+  // CHECK-NEXT: CompoundStmt
+  // CHECK-NEXT: DeclStmt
+  // CHECK-NEXT: VarDecl{{.*}} I 'typename T::type'
 
   // Check instantiation.
   // CHECK-LABEL: FunctionDecl{{.*}} used TemplFunc 'void ()' implicit_instantiation
@@ -45,6 +94,14 @@ void TemplFunc() {
   // CHECK-NEXT: CompoundStmt
   // CHECK-NEXT: DeclStmt
   // CHECK-NEXT: VarDecl{{.*}} I 'typename S::type':'int'
+  // CHECK-NEXT: OpenACCComputeConstruct {{.*}}serial
+  // CHECK-NEXT: CompoundStmt
+  // CHECK-NEXT: DeclStmt
+  // CHECK-NEXT: VarDecl{{.*}} I 'typename S::type':'int'
+  // CHECK-NEXT: OpenACCComputeConstruct {{.*}}kernels
+  // CHECK-NEXT: CompoundStmt
+  // CHECK-NEXT: DeclStmt
+  // CHECK-NEXT: VarDecl{{.*}} I 'typename S::type':'int'
 }
 
 struct S {
@@ -54,3 +111,5 @@ struct S {
 void use() {
   TemplFunc();
 }
+#endif
+
diff --git a/clang/test/SemaOpenACC/no-branch-in-out.c b/clang/test/SemaOpenACC/no-branch-in-out.c
index eccc64324500450de184c1d7939d3dd744b073bd..5fff18eb7cdd7b08c2d675cbdbc532eab935d223 100644
--- a/clang/test/SemaOpenACC/no-branch-in-out.c
+++ b/clang/test/SemaOpenACC/no-branch-in-out.c
@@ -37,6 +37,18 @@ void BreakContinue() {
       break; // expected-error{{invalid branch out of OpenACC Compute Construct}}
   }
 
+#pragma acc serial
+  for(int i = 0; i < 5; ++i) {
+    if (i > 1)
+      break; // expected-error{{invalid branch out of OpenACC Compute Construct}}
+  }
+
+#pragma acc kernels
+  for(int i = 0; i < 5; ++i) {
+    if (i > 1)
+      break; // expected-error{{invalid branch out of OpenACC Compute Construct}}
+  }
+
 #pragma acc parallel
   switch(j) {
     case 1:
@@ -99,6 +111,16 @@ void Return() {
     return;// expected-error{{invalid return out of OpenACC Compute Construct}}
   }
 
+#pragma acc serial
+  {
+    return;// expected-error{{invalid return out of OpenACC Compute Construct}}
+  }
+
+#pragma acc kernels
+  {
+    return;// expected-error{{invalid return out of OpenACC Compute Construct}}
+  }
+
 #pragma acc parallel
   {
     {
@@ -255,6 +277,34 @@ LABEL13:{}
   LABEL14:{}
   ({goto LABEL14;});
   }
+
+
+
+  ({goto LABEL15;});// expected-error{{cannot jump from this goto statement to its label}}
+#pragma acc serial// expected-note{{invalid branch into OpenACC Compute Construct}}
+  {
+LABEL15:{}
+  }
+
+LABEL16:{}
+#pragma acc serial// expected-note{{invalid branch out of OpenACC Compute Construct}}
+  {
+  ({goto LABEL16;});// expected-error{{cannot jump from this goto statement to its label}}
+  }
+
+
+  ({goto LABEL17;});// expected-error{{cannot jump from this goto statement to its label}}
+#pragma acc kernels// expected-note{{invalid branch into OpenACC Compute Construct}}
+  {
+LABEL17:{}
+  }
+
+LABEL18:{}
+#pragma acc kernels// expected-note{{invalid branch out of OpenACC Compute Construct}}
+  {
+  ({goto LABEL18;});// expected-error{{cannot jump from this goto statement to its label}}
+  }
+
 }
 
 void IndirectGoto1() {
@@ -329,6 +379,14 @@ void DuffsDevice() {
   }
   }
 
+  switch (j) {
+#pragma acc kernels
+  for(int i =0; i < 5; ++i) {
+    default: // expected-error{{invalid branch into OpenACC Compute Construct}}
+      {}
+  }
+  }
+
   switch (j) {
 #pragma acc parallel
   for(int i =0; i < 5; ++i) {
@@ -336,4 +394,12 @@ void DuffsDevice() {
       {}
   }
   }
+
+  switch (j) {
+#pragma acc serial
+  for(int i =0; i < 5; ++i) {
+    case 'a' ... 'z': // expected-error{{invalid branch into OpenACC Compute Construct}}
+      {}
+  }
+  }
 }
diff --git a/clang/test/SemaOpenACC/no-branch-in-out.cpp b/clang/test/SemaOpenACC/no-branch-in-out.cpp
index 6ee4553cd30351d42493cdb61fb8900f13396542..bc559f1898f1bc2e1d7ac4a4b31f978c47b38546 100644
--- a/clang/test/SemaOpenACC/no-branch-in-out.cpp
+++ b/clang/test/SemaOpenACC/no-branch-in-out.cpp
@@ -147,6 +147,17 @@ void Exceptions() {
     throw; // expected-error{{invalid throw out of OpenACC Compute Construct}}
   }
 
+#pragma acc serial
+  for(int i = 0; i < 5; ++i) {
+    throw; // expected-error{{invalid throw out of OpenACC Compute Construct}}
+  }
+
+#pragma acc kernels
+  for(int i = 0; i < 5; ++i) {
+    throw; // expected-error{{invalid throw out of OpenACC Compute Construct}}
+  }
+
+
 #pragma acc parallel
   for(int i = 0; i < 5; ++i) {
     try {
diff --git a/clang/test/SemaOpenACC/parallel-assoc-stmt-inst.cpp b/clang/test/SemaOpenACC/parallel-assoc-stmt-inst.cpp
index 0464e164a754e6df0e553207379e7d3c183e6197..f533baa4c0e68c2aa2d9c50bbbfb522e6c617e40 100644
--- a/clang/test/SemaOpenACC/parallel-assoc-stmt-inst.cpp
+++ b/clang/test/SemaOpenACC/parallel-assoc-stmt-inst.cpp
@@ -4,6 +4,10 @@ template
 void Func() {
 #pragma acc parallel
     typename T::type I; //#ILOC
+#pragma acc serial
+    typename T::type IS; //#ILOCSERIAL
+#pragma acc kernels
+    typename T::type IK; //#ILOCKERNELS
 }
 
 struct S {
@@ -13,6 +17,8 @@ struct S {
 void use() {
   Func();
   // expected-error@#ILOC{{type 'int' cannot be used prior to '::' because it has no members}}
-  // expected-note@+1{{in instantiation of function template specialization 'Func' requested here}}
+  // expected-note@+3{{in instantiation of function template specialization 'Func' requested here}}
+  // expected-error@#ILOCSERIAL{{type 'int' cannot be used prior to '::' because it has no members}}
+  // expected-error@#ILOCKERNELS{{type 'int' cannot be used prior to '::' because it has no members}}
   Func();
 }
diff --git a/clang/test/SemaOpenACC/parallel-loc-and-stmt.c b/clang/test/SemaOpenACC/parallel-loc-and-stmt.c
index 5189a6aa44f04294b364d72d40229e21950318f0..ba29f6da8ba25d48b246acb828a89a2d1bd50ce7 100644
--- a/clang/test/SemaOpenACC/parallel-loc-and-stmt.c
+++ b/clang/test/SemaOpenACC/parallel-loc-and-stmt.c
@@ -3,14 +3,32 @@
 // expected-error@+1{{OpenACC construct 'parallel' cannot be used here; it can only be used in a statement context}}
 #pragma acc parallel
 
+// expected-error@+1{{OpenACC construct 'serial' cannot be used here; it can only be used in a statement context}}
+#pragma acc serial
+
+// expected-error@+1{{OpenACC construct 'kernels' cannot be used here; it can only be used in a statement context}}
+#pragma acc kernels
+
 // expected-error@+1{{OpenACC construct 'parallel' cannot be used here; it can only be used in a statement context}}
 #pragma acc parallel
 int foo;
+// expected-error@+1{{OpenACC construct 'serial' cannot be used here; it can only be used in a statement context}}
+#pragma acc serial
+int foo2;
+// expected-error@+1{{OpenACC construct 'kernels' cannot be used here; it can only be used in a statement context}}
+#pragma acc kernels
+int foo3;
 
 struct S {
 // expected-error@+1{{OpenACC construct 'parallel' cannot be used here; it can only be used in a statement context}}
 #pragma acc parallel
 int foo;
+// expected-error@+1{{OpenACC construct 'serial' cannot be used here; it can only be used in a statement context}}
+#pragma acc serial
+int foo2;
+// expected-error@+1{{OpenACC construct 'kernels' cannot be used here; it can only be used in a statement context}}
+#pragma acc kernels
+int foo3;
 };
 
 void func() {
@@ -31,6 +49,15 @@ void func() {
 #pragma acc parallel
   }
 
+  {
+// expected-error@+2{{expected statement}}
+#pragma acc serial
+  }
+  {
+// expected-error@+2{{expected statement}}
+#pragma acc kernels
+  }
+
 #pragma acc parallel
   while(0){}
 
diff --git a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
index 1b97484767b1a556ccca9d7c57ebf4ddfcd64e02..067a404c489aa61dca9f63649673fd98bc615801 100644
--- a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -54,5 +54,5 @@ struct Z {
 
 struct W {
   int w;
-  constexpr W() __constant = default; // expected-error {{defaulted definition of default constructor is not constexpr}}
+  constexpr W() __constant = default; // expected-error {{defaulted definition of default constructor cannot be marked constexpr}}
 };
diff --git a/clang/test/SemaTemplate/concepts-lambda.cpp b/clang/test/SemaTemplate/concepts-lambda.cpp
index 0b7580f91043c74e9507d9f87ad647bdd5b1a046..fac790d09f9cf2ff667b0eed2dd36a9f44697a2a 100644
--- a/clang/test/SemaTemplate/concepts-lambda.cpp
+++ b/clang/test/SemaTemplate/concepts-lambda.cpp
@@ -90,6 +90,64 @@ struct Foo {
 
 static_assert(ConstructibleWithN);
 
+namespace GH56556 {
+
+template 
+inline constexpr It declare ();
+
+template  typename Template>
+concept D = requires {
+	{ []  (Template &) {}(declare()) };
+};
+
+template 
+struct B {};
+
+template 
+struct Adapter;
+
+template  T>
+struct Adapter {};
+
+template struct Adapter>;
+
+} // namespace GH56556
+
+namespace GH82849 {
+
+template 
+concept C = requires(T t) {
+  requires requires (T u) {
+    [](V) {
+      return requires(V v) {
+        [](V w) {}(v);
+      };
+    }(t);
+  };
+};
+
+template 
+struct Widget;
+
+template 
+struct Widget {
+  static F create(F from) {
+    return from;
+  }
+};
+
+template 
+bool foo() {
+  return C;
+}
+
+void bar() {
+  // https://github.com/llvm/llvm-project/issues/49570#issuecomment-1664966972
+  Widget::create(0);
+}
+
+} // namespace GH82849
+
 }
 
 // GH60642 reported an assert being hit, make sure we don't assert.
diff --git a/clang/test/TableGen/target-builtins-prototype-parser.td b/clang/test/TableGen/target-builtins-prototype-parser.td
new file mode 100644
index 0000000000000000000000000000000000000000..555aebb3ccfb1f54cb16679dc05d506b56c8fdd5
--- /dev/null
+++ b/clang/test/TableGen/target-builtins-prototype-parser.td
@@ -0,0 +1,115 @@
+// RUN: clang-tblgen -I %p/../../include/ %s --gen-clang-builtins | FileCheck %s
+// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_LANES 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_LANES
+// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_COMMA 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_COMMA
+// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_TYPE 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_TYPE
+// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_A 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_A
+// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_B 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_B
+// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_C 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_C
+// RUN: not clang-tblgen -I %p/../../include/ %s --gen-clang-builtins -DERROR_EXPECTED_D 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_D
+
+include "clang/Basic/BuiltinsBase.td"
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_01, "E8idE4b", "")
+  let Prototype = "_ExtVector<8,int>(double, _ExtVector<4,        bool>)";
+  let Spellings = ["__builtin_01"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_02, "E8UiE4s", "")
+  let Prototype = "_ExtVector<8,unsigned int>(_ExtVector<4, short>)";
+  let Spellings = ["__builtin_02"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_03, "di", "")
+  let Prototype = "double(int)";
+  let Spellings = ["__builtin_03"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_04, "diIUi", "")
+ let Prototype = "double(int, _Constant unsigned int)";
+  let Spellings = ["__builtin_04"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_05, "v&v&", "")
+ let Prototype = "void&(void&)";
+  let Spellings = ["__builtin_05"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_06, "v*v*cC*.", "")
+ let Prototype = "void*(void*, char const*, ...)";
+  let Spellings = ["__builtin_06"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_07, "E8iE4dE4b.", "")
+  let Prototype = "_ExtVector<8, int>(_ExtVector<4,double>, _ExtVector<4, bool>, ...)";
+  let Spellings = ["__builtin_07"];
+}
+
+def : Builtin {
+// CHECK: BUILTIN(__builtin_08, "di*R", "")
+  let Prototype = "double(int * restrict)";
+  let Spellings = ["__builtin_08"];
+}
+
+#ifdef ERROR_EXPECTED_LANES
+def : Builtin {
+// ERROR_EXPECTED_LANES: :[[# @LINE + 1]]:7: error: Expected number of lanes after '_ExtVector<'
+  let Prototype = "_ExtVector(double)";
+  let Spellings = ["__builtin_test_use_clang_extended_vectors"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_COMMA
+def : Builtin {
+// ERROR_EXPECTED_COMMA: :[[# @LINE + 1]]:7: error: Expected ',' after number of lanes in '_ExtVector<'
+  let Prototype = "_ExtVector<8 int>(double)";
+  let Spellings = ["__builtin_test_use_clang_extended_vectors"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_TYPE
+def : Builtin {
+// ERROR_EXPECTED_TYPE: :[[# @LINE + 1]]:7: error: Expected '>' after scalar type in '_ExtVector'
+  let Prototype = "_ExtVector<8, int (double)";
+  let Spellings = ["__builtin_test_use_clang_extended_vectors"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_A
+def : Builtin {
+// ERROR_EXPECTED_A: :[[# @LINE + 1]]:7: error: Expected '<' after '_ExtVector'
+  let Prototype = "_ExtVector(8, int) (double)";
+  let Spellings = ["__builtin_test_use_clang_extended_vectors"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_B
+def : Builtin {
+// ERROR_EXPECTED_B: :[[# @LINE + 1]]:7: error: Expected '<' after '_ExtVector'
+  let Prototype = "double(_ExtVector(8, int))";
+  let Spellings = ["__builtin_test_use_clang_extended_vectors"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_C
+def : Builtin {
+// ERROR_EXPECTED_C: :[[# @LINE + 1]]:7: error: Unknown Type: _EtxVector<8, int>
+  let Prototype = "_EtxVector<8, int>(void)";
+  let Spellings = ["__builtin_test_use_clang_extended_vectors"];
+}
+#endif
+
+#ifdef ERROR_EXPECTED_D
+def : Builtin {
+// ERROR_EXPECTED_D: :[[# @LINE + 1]]:7: error: Expected number of lanes after '_ExtVector<'
+  let Prototype = "_ExtVector<>(void)";
+  let Spellings = ["__builtin_test_use_clang_extended_vectors"];
+}
+#endif
+
diff --git a/clang/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h b/clang/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h
index 173b937e527037ab104f47eb0c70e3da9d597598..0614835dcc8172b0917f9146d4a6bc61b60cdb4e 100644
--- a/clang/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h
+++ b/clang/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h
@@ -1,4 +1,4 @@
-//==-- loop_proto_to_llvm.h - Protobuf-C++ conversion ----------------------------==//
+//===- loop_proto_to_llvm.h - Protobuf-C++ conversion -----------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp
index 7d45e999448d9f82551bb7b26ac733c7688eafd9..701ab81c57c3d0e1b6249aaea043bc2771e9cd9a 100644
--- a/clang/tools/clang-installapi/Options.cpp
+++ b/clang/tools/clang-installapi/Options.cpp
@@ -99,6 +99,33 @@ bool Options::processLinkerOptions(InputArgList &Args) {
   return true;
 }
 
+bool Options::processFrontendOptions(InputArgList &Args) {
+  // Do not claim any arguments, as they will be passed along for CC1
+  // invocations.
+  if (auto *A = Args.getLastArgNoClaim(OPT_x)) {
+    FEOpts.LangMode = llvm::StringSwitch(A->getValue())
+                          .Case("c", clang::Language::C)
+                          .Case("c++", clang::Language::CXX)
+                          .Case("objective-c", clang::Language::ObjC)
+                          .Case("objective-c++", clang::Language::ObjCXX)
+                          .Default(clang::Language::Unknown);
+
+    if (FEOpts.LangMode == clang::Language::Unknown) {
+      Diags->Report(clang::diag::err_drv_invalid_value)
+          << A->getAsString(Args) << A->getValue();
+      return false;
+    }
+  }
+  for (auto *A : Args.filtered(OPT_ObjC, OPT_ObjCXX)) {
+    if (A->getOption().matches(OPT_ObjC))
+      FEOpts.LangMode = clang::Language::ObjC;
+    else
+      FEOpts.LangMode = clang::Language::ObjCXX;
+  }
+
+  return true;
+}
+
 Options::Options(DiagnosticsEngine &Diag, FileManager *FM,
                  InputArgList &ArgList)
     : Diags(&Diag), FM(FM) {
@@ -108,11 +135,16 @@ Options::Options(DiagnosticsEngine &Diag, FileManager *FM,
   if (!processLinkerOptions(ArgList))
     return;
 
-  /// Any remaining arguments should be handled by invoking the clang frontend.
+  if (!processFrontendOptions(ArgList))
+    return;
+
+  /// Any unclaimed arguments should be handled by invoking the clang frontend.
   for (const Arg *A : ArgList) {
     if (A->isClaimed())
       continue;
-    FrontendArgs.emplace_back(A->getAsString(ArgList));
+
+    FrontendArgs.emplace_back(A->getSpelling());
+    llvm::copy(A->getValues(), std::back_inserter(FrontendArgs));
   }
   FrontendArgs.push_back("-fsyntax-only");
 }
@@ -130,6 +162,7 @@ InstallAPIContext Options::createContext() {
   Ctx.BA.AppExtensionSafe = LinkerOpts.AppExtensionSafe;
   Ctx.FT = DriverOpts.OutFT;
   Ctx.OutputLoc = DriverOpts.OutputPath;
+  Ctx.LangMode = FEOpts.LangMode;
 
   // Process inputs.
   for (const std::string &ListPath : DriverOpts.FileLists) {
diff --git a/clang/tools/clang-installapi/Options.h b/clang/tools/clang-installapi/Options.h
index f68addf1972880917f7e8465a93c6441f99d33dc..9d4d841284fd11c18e6a780606929654bfd6c430 100644
--- a/clang/tools/clang-installapi/Options.h
+++ b/clang/tools/clang-installapi/Options.h
@@ -62,15 +62,22 @@ struct LinkerOptions {
   bool IsDylib = false;
 };
 
+struct FrontendOptions {
+  /// \brief The language mode to parse headers in.
+  Language LangMode = Language::ObjC;
+};
+
 class Options {
 private:
   bool processDriverOptions(llvm::opt::InputArgList &Args);
   bool processLinkerOptions(llvm::opt::InputArgList &Args);
+  bool processFrontendOptions(llvm::opt::InputArgList &Args);
 
 public:
   /// The various options grouped together.
   DriverOptions DriverOpts;
   LinkerOptions LinkerOpts;
+  FrontendOptions FEOpts;
 
   Options() = delete;
 
diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index 576e8f2cd7f8fd2851b1f24bbba3fb3204648b4b..535ef42c78c46317976c29be80b3a83f0eeef75b 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -405,12 +405,22 @@ fatbinary(ArrayRef> InputFiles,
   CmdArgs.push_back("-type=o");
   CmdArgs.push_back("-bundle-align=4096");
 
+  if (Args.hasArg(OPT_compress))
+    CmdArgs.push_back("-compress");
+  if (auto *Arg = Args.getLastArg(OPT_compression_level_eq))
+    CmdArgs.push_back(
+        Args.MakeArgString(Twine("-compression-level=") + Arg->getValue()));
+
   SmallVector Targets = {"-targets=host-x86_64-unknown-linux"};
   for (const auto &[File, Arch] : InputFiles)
     Targets.push_back(Saver.save("hipv4-amdgcn-amd-amdhsa--" + Arch));
   CmdArgs.push_back(Saver.save(llvm::join(Targets, ",")));
 
+#ifdef _WIN32
+  CmdArgs.push_back("-input=NUL");
+#else
   CmdArgs.push_back("-input=/dev/null");
+#endif
   for (const auto &[File, Arch] : InputFiles)
     CmdArgs.push_back(Saver.save("-input=" + File));
 
diff --git a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
index 763426570c2a6fe9f1e1ee771121a30c95b4bb4f..0a8bd541c4524221837c6262e7af35906b241e8d 100644
--- a/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
+++ b/clang/tools/clang-linker-wrapper/LinkerWrapperOpts.td
@@ -58,6 +58,10 @@ def print_wrapped_module : Flag<["--"], "print-wrapped-module">,
   HelpText<"Print the wrapped module's IR for testing">;
 def save_temps : Flag<["--"], "save-temps">,
   Flags<[WrapperOnlyOption]>, HelpText<"Save intermediate results">;
+def compress : Flag<["--"], "compress">,
+  Flags<[WrapperOnlyOption]>, HelpText<"Compress bundled files">;
+def compression_level_eq : Joined<["--"], "compression-level=">,
+  Flags<[WrapperOnlyOption]>, HelpText<"Specify the compression level (integer)">;
 
 def wrapper_time_trace_eq : Joined<["--"], "wrapper-time-trace=">,
   Flags<[WrapperOnlyOption]>, MetaVarName<"">,
@@ -84,10 +88,6 @@ def linker_arg_EQ : Joined<["--"], "linker-arg=">,
   Flags<[DeviceOnlyOption, HelpHidden]>,
   HelpText<"An extra argument to be passed to the linker">;
 
-// Separator between the linker wrapper and host linker flags.
-def separator : Flag<["--"], "">, Flags<[WrapperOnlyOption]>,
-  HelpText<"The separator for the wrapped linker arguments">;
-
 // Arguments for the LLVM backend.
 def mllvm : Separate<["-"], "mllvm">, Flags<[WrapperOnlyOption]>,
   MetaVarName<"">, HelpText<"Arguments passed to the LLVM invocation">;
diff --git a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
index ec67e24552e9c9633485545f1d53aceceff2a8c4..e336417586f70bd9fe030d3167f45584866fbc28 100644
--- a/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
+++ b/clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
@@ -145,6 +145,9 @@ int main(int argc, const char **argv) {
                          cl::init(false), cl::cat(ClangOffloadBundlerCategory));
   cl::opt Verbose("verbose", cl::desc("Print debug information.\n"),
                         cl::init(false), cl::cat(ClangOffloadBundlerCategory));
+  cl::opt CompressionLevel(
+      "compression-level", cl::desc("Specify the compression level (integer)"),
+      cl::value_desc("n"), cl::Optional, cl::cat(ClangOffloadBundlerCategory));
 
   // Process commandline options and report errors
   sys::PrintStackTraceOnErrorSignal(argv[0]);
@@ -178,6 +181,8 @@ int main(int argc, const char **argv) {
     BundlerConfig.Compress = Compress;
   if (Verbose.getNumOccurrences() > 0)
     BundlerConfig.Verbose = Verbose;
+  if (CompressionLevel.getNumOccurrences() > 0)
+    BundlerConfig.CompressionLevel = CompressionLevel;
 
   BundlerConfig.TargetNames = TargetNames;
   BundlerConfig.InputFileNames = InputFileNames;
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index 9811d2a87533593727af2b2d138aafb0de136a81..d042fecc3dbe63af73ebedf3930c24888f3f4b47 100644
--- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -869,7 +869,7 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
 
   DependencyScanningService Service(ScanMode, Format, OptimizeArgs,
                                     EagerLoadModules);
-  llvm::ThreadPool Pool(llvm::hardware_concurrency(NumThreads));
+  llvm::DefaultThreadPool Pool(llvm::hardware_concurrency(NumThreads));
   std::vector> WorkerTools;
   for (unsigned I = 0; I < Pool.getMaxConcurrency(); ++I)
     WorkerTools.push_back(std::make_unique(Service));
diff --git a/clang/tools/diagtool/DiagTool.cpp b/clang/tools/diagtool/DiagTool.cpp
index 99abe5755f713080a4e8f87c453a034cba9a76b1..384eef560c6cac913087740ac0bfcc0b80d19c3c 100644
--- a/clang/tools/diagtool/DiagTool.cpp
+++ b/clang/tools/diagtool/DiagTool.cpp
@@ -1,4 +1,4 @@
-//===- DiagTool.cpp - Classes for defining diagtool tools -------------------===//
+//===- DiagTool.cpp - Classes for defining diagtool tools -----------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp
index a55e06500d9d9202132d0d12b46cd3d88ccbacae..5498c3f9d4a20d5c4ed798bde3ad79b9cfc9baf9 100644
--- a/clang/tools/driver/cc1as_main.cpp
+++ b/clang/tools/driver/cc1as_main.cpp
@@ -428,6 +428,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
   MCTargetOptions MCOptions;
   MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind;
   MCOptions.EmitCompactUnwindNonCanonical = Opts.EmitCompactUnwindNonCanonical;
+  MCOptions.X86RelaxRelocations = Opts.RelaxELFRelocations;
+  MCOptions.CompressDebugSections = Opts.CompressDebugSections;
   MCOptions.AsSecureLogFile = Opts.AsSecureLogFile;
 
   std::unique_ptr MAI(
@@ -436,9 +438,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
 
   // Ensure MCAsmInfo initialization occurs before any use, otherwise sections
   // may be created with a combination of default and explicit settings.
-  MAI->setCompressDebugSections(Opts.CompressDebugSections);
 
-  MAI->setRelaxELFRelocations(Opts.RelaxELFRelocations);
 
   bool IsBinary = Opts.OutputType == AssemblerInvocation::FT_Obj;
   if (Opts.OutputPath.empty())
diff --git a/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp b/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp
index 3f21a149f7e1a339545057aaacd19bdeace443a7..db0ba5d7e1ed0795bb83c5b123278faceaae6707 100644
--- a/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp
+++ b/clang/unittests/AST/ASTImporterODRStrategiesTest.cpp
@@ -1,4 +1,4 @@
-//===- unittest/AST/ASTImporterODRStrategiesTest.cpp -----------------------===//
+//===- ASTImporterODRStrategiesTest.cpp -----------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/unittests/AST/MatchVerifier.h b/clang/unittests/AST/MatchVerifier.h
index 8bcf05642cb5bcca96fcc9a14dce13eef96f7c7b..da1e351da4a096f4f7ebf002937068ecac725060 100644
--- a/clang/unittests/AST/MatchVerifier.h
+++ b/clang/unittests/AST/MatchVerifier.h
@@ -116,6 +116,10 @@ MatchVerifier::match(const std::string &Code,
     Args.push_back("-std=c++20");
     FileName = "input.cc";
     break;
+  case Lang_CXX23:
+    Args.push_back("-std=c++23");
+    FileName = "input.cc";
+    break;
   case Lang_OpenCL:
     Args.push_back("-cl-no-stdinc");
     FileName = "input.cl";
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index b75da7bc1ed0699f1b872a9fa693feac00721adf..87774b00956a5a13a28b6febfc46a39412a631e4 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2107,6 +2107,20 @@ TEST_P(ASTMatchersTest, IsPure) {
   EXPECT_TRUE(notMatches("class X { int f(); };", cxxMethodDecl(isPure())));
 }
 
+TEST_P(ASTMatchersTest, IsExplicitObjectMemberFunction) {
+  if (!GetParam().isCXX23OrLater()) {
+    return;
+  }
+
+  auto ExpObjParamFn = cxxMethodDecl(isExplicitObjectMemberFunction());
+  EXPECT_TRUE(
+      notMatches("struct A { static int operator()(int); };", ExpObjParamFn));
+  EXPECT_TRUE(notMatches("struct A { int operator+(int); };", ExpObjParamFn));
+  EXPECT_TRUE(
+      matches("struct A { int operator-(this A, int); };", ExpObjParamFn));
+  EXPECT_TRUE(matches("struct A { void fun(this A &&self); };", ExpObjParamFn));
+}
+
 TEST_P(ASTMatchersTest, IsCopyAssignmentOperator) {
   if (!GetParam().isCXX()) {
     return;
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index ae30c03126d768ca3964c8191911bb660cba6780..0edc65162fbe3f8e9095c60628a8eedfc7df7b2f 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -2754,7 +2754,7 @@ TEST(MatchFinderAPI, MatchesDynamic) {
 static std::vector allTestClangConfigs() {
   std::vector all_configs;
   for (TestLanguage lang : {Lang_C89, Lang_C99, Lang_CXX03, Lang_CXX11,
-                            Lang_CXX14, Lang_CXX17, Lang_CXX20}) {
+                            Lang_CXX14, Lang_CXX17, Lang_CXX20, Lang_CXX23}) {
     TestClangConfig config;
     config.Language = lang;
 
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTest.h b/clang/unittests/ASTMatchers/ASTMatchersTest.h
index 79c6186054839c3e90296ffd31463be938bd768d..1ed1b5958a8b3a10810fa59a2269fd9c75012f06 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTest.h
+++ b/clang/unittests/ASTMatchers/ASTMatchersTest.h
@@ -62,22 +62,28 @@ private:
 
 inline ArrayRef langCxx11OrLater() {
   static const TestLanguage Result[] = {Lang_CXX11, Lang_CXX14, Lang_CXX17,
-                                        Lang_CXX20};
+                                        Lang_CXX20, Lang_CXX23};
   return ArrayRef(Result);
 }
 
 inline ArrayRef langCxx14OrLater() {
-  static const TestLanguage Result[] = {Lang_CXX14, Lang_CXX17, Lang_CXX20};
+  static const TestLanguage Result[] = {Lang_CXX14, Lang_CXX17, Lang_CXX20,
+                                        Lang_CXX23};
   return ArrayRef(Result);
 }
 
 inline ArrayRef langCxx17OrLater() {
-  static const TestLanguage Result[] = {Lang_CXX17, Lang_CXX20};
+  static const TestLanguage Result[] = {Lang_CXX17, Lang_CXX20, Lang_CXX23};
   return ArrayRef(Result);
 }
 
 inline ArrayRef langCxx20OrLater() {
-  static const TestLanguage Result[] = {Lang_CXX20};
+  static const TestLanguage Result[] = {Lang_CXX20, Lang_CXX23};
+  return ArrayRef(Result);
+}
+
+inline ArrayRef langCxx23OrLater() {
+  static const TestLanguage Result[] = {Lang_CXX23};
   return ArrayRef(Result);
 }
 
diff --git a/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp b/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
index 9428f06ade5851a67d2613bca66a5ee93451a4e9..013bb912dfb8cd120aa01e88f909bcededc0452e 100644
--- a/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
+++ b/clang/unittests/ASTMatchers/Dynamic/RegistryTest.cpp
@@ -1,10 +1,10 @@
-//===- unittest/ASTMatchers/Dynamic/RegistryTest.cpp - Registry unit tests -===//
+//===- RegistryTest.cpp - Registry unit tests -----------------------------===//
 //
 // 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
 //
-//===-----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 
 #include "../ASTMatchersTest.h"
 #include "clang/ASTMatchers/Dynamic/Registry.h"
diff --git a/clang/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp b/clang/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
index c62a6b385e286dcc6ae0771ab713019afaea4284..2449a2907ac8bf836e1ae0b1f492a4c3ef2d0623 100644
--- a/clang/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
+++ b/clang/unittests/ASTMatchers/Dynamic/VariantValueTest.cpp
@@ -1,10 +1,10 @@
-//===- unittest/ASTMatchers/Dynamic/VariantValueTest.cpp - VariantValue unit tests -===//
+//===- VariantValueTest.cpp - VariantValue unit tests ---------------------===//
 //
 // 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
 //
-//===-----------------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 
 #include "../ASTMatchersTest.h"
 #include "clang/ASTMatchers/Dynamic/VariantValue.h"
diff --git a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
index 8799d03dfd3c58836e7bb97a578414774f9ffc8b..465a8e21690c4a62fe41abc71801a3da52bfc767 100644
--- a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
@@ -190,7 +190,8 @@ TEST_F(EnvironmentTest, JoinRecords) {
     Env2.setValue(Loc, Val2);
 
     Environment::ValueModel Model;
-    Environment EnvJoined = Environment::join(Env1, Env2, Model);
+    Environment EnvJoined =
+        Environment::join(Env1, Env2, Model, Environment::DiscardExprState);
     auto *JoinedVal = cast(EnvJoined.getValue(Loc));
     EXPECT_NE(JoinedVal, &Val1);
     EXPECT_NE(JoinedVal, &Val2);
diff --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp b/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
index 09f5524e152c9fac86f714d5e5306bc68ee5cc8b..5c4d42c6ccdcf80a082e9d133ead859057ee64c4 100644
--- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.cpp
@@ -179,7 +179,10 @@ llvm::Error test::checkDataflowWithNoopAnalysis(
       // -fnodelayed-template-parsing is the default everywhere but on Windows.
       // Set it explicitly so that tests behave the same on Windows as on other
       // platforms.
-      "-fsyntax-only", "-fno-delayed-template-parsing",
+      // Set -Wno-unused-value because it's often desirable in tests to write
+      // expressions with unused value, and we don't want the output to be
+      // cluttered with warnings about them.
+      "-fsyntax-only", "-fno-delayed-template-parsing", "-Wno-unused-value",
       "-std=" +
           std::string(LangStandard::getLangStandardForKind(Std).getName())};
   AnalysisInputs AI(
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index f534ccb1254701bb0af5133f82d3fce5abbfd0d0..a8c282f140b4cd01b2de0cc2af030537f2c2965f 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -1476,6 +1476,69 @@ TEST(TransferTest, BaseClassInitializer) {
       llvm::Succeeded());
 }
 
+TEST(TransferTest, FieldsDontHaveValuesInConstructor) {
+  // In a constructor, unlike in regular member functions, we don't want fields
+  // to be pre-initialized with values, because doing so is the job of the
+  // constructor.
+  std::string Code = R"(
+    struct target {
+      target() {
+        0;
+        // [[p]]
+        // Mention the field so it is modeled;
+        Val;
+      }
+
+      int Val;
+    };
+ )";
+  runDataflow(
+      Code,
+      [](const llvm::StringMap> &Results,
+         ASTContext &ASTCtx) {
+        const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
+        EXPECT_EQ(getFieldValue(Env.getThisPointeeStorageLocation(), "Val",
+                                ASTCtx, Env),
+                  nullptr);
+      });
+}
+
+TEST(TransferTest, FieldsDontHaveValuesInConstructorWithBaseClass) {
+  // See above, but for a class with a base class.
+  std::string Code = R"(
+    struct Base {
+        int BaseVal;
+    };
+
+    struct target  : public Base {
+      target() {
+        0;
+        // [[p]]
+        // Mention the fields so they are modeled.
+        BaseVal;
+        Val;
+      }
+
+      int Val;
+    };
+ )";
+  runDataflow(
+      Code,
+      [](const llvm::StringMap> &Results,
+         ASTContext &ASTCtx) {
+        const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
+        // FIXME: The field of the base class should already have been
+        // initialized with a value by the base constructor. This test documents
+        // the current buggy behavior.
+        EXPECT_EQ(getFieldValue(Env.getThisPointeeStorageLocation(), "BaseVal",
+                                ASTCtx, Env),
+                  nullptr);
+        EXPECT_EQ(getFieldValue(Env.getThisPointeeStorageLocation(), "Val",
+                                ASTCtx, Env),
+                  nullptr);
+      });
+}
+
 TEST(TransferTest, StructModeledFieldsWithAccessor) {
   std::string Code = R"(
     class S {
@@ -5672,6 +5735,39 @@ TEST(TransferTest, ContextSensitiveReturnInt) {
       {BuiltinOptions{ContextSensitiveOptions{}}});
 }
 
+TEST(TransferTest, ContextSensitiveReturnRecord) {
+  std::string Code = R"(
+    struct S {
+      bool B;
+    };
+
+    S makeS(bool BVal) { return {BVal}; }
+
+    void target() {
+      S FalseS = makeS(false);
+      S TrueS = makeS(true);
+      // [[p]]
+    }
+  )";
+  runDataflow(
+      Code,
+      [](const llvm::StringMap> &Results,
+         ASTContext &ASTCtx) {
+        const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
+
+        auto &FalseSLoc =
+            getLocForDecl(ASTCtx, Env, "FalseS");
+        auto &TrueSLoc =
+            getLocForDecl(ASTCtx, Env, "TrueS");
+
+        EXPECT_EQ(getFieldValue(&FalseSLoc, "B", ASTCtx, Env),
+                  &Env.getBoolLiteralValue(false));
+        EXPECT_EQ(getFieldValue(&TrueSLoc, "B", ASTCtx, Env),
+                  &Env.getBoolLiteralValue(true));
+      },
+      {BuiltinOptions{ContextSensitiveOptions{}}});
+}
+
 TEST(TransferTest, ContextSensitiveMethodLiteral) {
   std::string Code = R"(
     class MyClass {
diff --git a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
index 34f9b0b23719fe8da89adea858ac42857b2fef58..9d05a0d6ca4010bc3d34fcf56663328b0441c338 100644
--- a/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
@@ -244,15 +244,17 @@ TEST_F(DiscardExprStateTest, WhileStatement) {
   EXPECT_NE(NotEqOpState.Env.getValue(NotEqOp), nullptr);
 
   // In the block that calls `foo(p)`, the value for `p != nullptr` is discarded
-  // because it is not consumed by this block.
+  // because it is not consumed outside the block it is in.
   const auto &CallFooState = blockStateForStmt(BlockStates, CallFoo);
   EXPECT_EQ(CallFooState.Env.getValue(NotEqOp), nullptr);
 }
 
 TEST_F(DiscardExprStateTest, BooleanOperator) {
   std::string Code = R"(
-    bool target(bool b1, bool b2) {
-      return b1 && b2;
+    void f();
+    void target(bool b1, bool b2) {
+      if (b1 && b2)
+        f();
     }
   )";
   auto BlockStates = llvm::cantFail(runAnalysis(
@@ -260,46 +262,80 @@ TEST_F(DiscardExprStateTest, BooleanOperator) {
 
   const auto &AndOp =
       matchNode(binaryOperator(hasOperatorName("&&")));
-  const auto &Return = matchNode(returnStmt());
+  const auto &CallF =
+      matchNode(callExpr(callee(functionDecl(hasName("f")))));
 
   // In the block that evaluates the LHS of the `&&` operator, the LHS is
   // associated with a value, while the right-hand side is not (unsurprisingly,
   // as it hasn't been evaluated yet).
   const auto &LHSState = blockStateForStmt(BlockStates, *AndOp.getLHS());
   auto *LHSValue = cast(LHSState.Env.getValue(*AndOp.getLHS()));
-  ASSERT_NE(LHSValue, nullptr);
+  EXPECT_NE(LHSValue, nullptr);
   EXPECT_EQ(LHSState.Env.getValue(*AndOp.getRHS()), nullptr);
 
-  // In the block that evaluates the RHS, the RHS is associated with a
-  // value. The value for the LHS has been discarded as it is not consumed by
-  // this block.
+  // In the block that evaluates the RHS, both the LHS and RHS are associated
+  // with values, as they are both subexpressions of the `&&` operator, which
+  // is evaluated in a later block.
   const auto &RHSState = blockStateForStmt(BlockStates, *AndOp.getRHS());
-  EXPECT_EQ(RHSState.Env.getValue(*AndOp.getLHS()), nullptr);
-  auto *RHSValue = cast(RHSState.Env.getValue(*AndOp.getRHS()));
-  ASSERT_NE(RHSValue, nullptr);
-
-  // In the block that evaluates the return statement, the expression `b1 && b2`
-  // is associated with a value (and check that it's the right one).
-  // The expressions `b1` and `b2` are _not_ associated with a value in this
-  // block, even though they are consumed by the block, because:
-  // * This block has two prececessor blocks (the one that evaluates `b1` and
-  //   the one that evaluates `b2`).
-  // * `b1` is only associated with a value in the block that evaluates `b1` but
-  //   not the block that evalutes `b2`, so the join operation discards the
-  //   value for `b1`.
-  // * `b2` is only associated with a value in the block that evaluates `b2` but
-  //   not the block that evaluates `b1`, the the join operation discards the
-  //   value for `b2`.
-  // Nevertheless, the analysis generates the correct formula for `b1 && b2`
-  // because the transfer function for the `&&` operator retrieves the values
-  // for its operands from the environments for the blocks that compute the
-  // operands, rather than from the environment for the block that contains the
-  // `&&`.
-  const auto &ReturnState = blockStateForStmt(BlockStates, Return);
-  EXPECT_EQ(ReturnState.Env.getValue(*AndOp.getLHS()), nullptr);
-  EXPECT_EQ(ReturnState.Env.getValue(*AndOp.getRHS()), nullptr);
-  EXPECT_EQ(ReturnState.Env.getValue(AndOp),
-            &ReturnState.Env.makeAnd(*LHSValue, *RHSValue));
+  EXPECT_EQ(RHSState.Env.getValue(*AndOp.getLHS()), LHSValue);
+  auto *RHSValue = RHSState.Env.get(*AndOp.getRHS());
+  EXPECT_NE(RHSValue, nullptr);
+
+  // In the block that evaluates `b1 && b2`, the `&&` as well as its operands
+  // are associated with values.
+  const auto &AndOpState = blockStateForStmt(BlockStates, AndOp);
+  EXPECT_EQ(AndOpState.Env.getValue(*AndOp.getLHS()), LHSValue);
+  EXPECT_EQ(AndOpState.Env.getValue(*AndOp.getRHS()), RHSValue);
+  EXPECT_EQ(AndOpState.Env.getValue(AndOp),
+            &AndOpState.Env.makeAnd(*LHSValue, *RHSValue));
+
+  // In the block that calls `f()`, none of `b1`, `b2`, or `b1 && b2` should be
+  // associated with values.
+  const auto &CallFState = blockStateForStmt(BlockStates, CallF);
+  EXPECT_EQ(CallFState.Env.getValue(*AndOp.getLHS()), nullptr);
+  EXPECT_EQ(CallFState.Env.getValue(*AndOp.getRHS()), nullptr);
+  EXPECT_EQ(CallFState.Env.getValue(AndOp), nullptr);
+}
+
+TEST_F(DiscardExprStateTest, ConditionalOperator) {
+  std::string Code = R"(
+    void f(int*, int);
+    void g();
+    bool cond();
+
+    void target() {
+      int i = 0;
+      if (cond())
+        f(&i, cond() ? 1 : 0);
+      g();
+    }
+  )";
+  auto BlockStates = llvm::cantFail(runAnalysis(
+      Code, [](ASTContext &C) { return NoopAnalysis(C); }));
+
+  const auto &AddrOfI =
+      matchNode(unaryOperator(hasOperatorName("&")));
+  const auto &CallF =
+      matchNode(callExpr(callee(functionDecl(hasName("f")))));
+  const auto &CallG =
+      matchNode(callExpr(callee(functionDecl(hasName("g")))));
+
+  // In the block that evaluates `&i`, it should obviously have a value.
+  const auto &AddrOfIState = blockStateForStmt(BlockStates, AddrOfI);
+  auto *AddrOfIVal = AddrOfIState.Env.get(AddrOfI);
+  EXPECT_NE(AddrOfIVal, nullptr);
+
+  // Because of the conditional operator, the `f(...)` call is evaluated in a
+  // different block than `&i`, but `&i` still needs to have a value here
+  // because it's a subexpression of the call.
+  const auto &CallFState = blockStateForStmt(BlockStates, CallF);
+  EXPECT_NE(&CallFState, &AddrOfIState);
+  EXPECT_EQ(CallFState.Env.get(AddrOfI), AddrOfIVal);
+
+  // In the block that calls `g()`, `&i` should no longer be associated with a
+  // value.
+  const auto &CallGState = blockStateForStmt(BlockStates, CallG);
+  EXPECT_EQ(CallGState.Env.get(AddrOfI), nullptr);
 }
 
 struct NonConvergingLattice {
diff --git a/clang/unittests/Basic/DarwinSDKInfoTest.cpp b/clang/unittests/Basic/DarwinSDKInfoTest.cpp
index 5f24e6eae515d226a2f5f8a56a879a5e2465e5cb..7214f3bc8e19f48ed4c48eb7928f8d39824dc4fb 100644
--- a/clang/unittests/Basic/DarwinSDKInfoTest.cpp
+++ b/clang/unittests/Basic/DarwinSDKInfoTest.cpp
@@ -168,6 +168,16 @@ TEST(DarwinSDKInfoTest, ParseAndTestMappingIOSDerived) {
   EXPECT_EQ(
       *Mapping->map(VersionTuple(13, 0), VersionTuple(), VersionTuple(99, 99)),
       VersionTuple(99, 99));
+
+  // Verify introduced, deprecated, and obsoleted mappings.
+  EXPECT_EQ(Mapping->mapIntroducedAvailabilityVersion(VersionTuple(10, 1)),
+            VersionTuple(10.0));
+  EXPECT_EQ(Mapping->mapDeprecatedObsoletedAvailabilityVersion(
+                VersionTuple(100000, 0)),
+            VersionTuple(100000));
+  EXPECT_EQ(
+      Mapping->mapDeprecatedObsoletedAvailabilityVersion(VersionTuple(13.0)),
+      VersionTuple(15, 0, 99));
 }
 
 TEST(DarwinSDKInfoTest, MissingKeys) {
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp
index c736dac8dabf2134e0f720f54bf79635a4659e7f..fcba0e63c7825497a79b4d4ce810d8b2613c8af5 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -620,6 +620,24 @@ TEST_F(TokenAnnotatorTest, UnderstandsCasts) {
   ASSERT_EQ(Tokens.size(), 8u) << Tokens;
   EXPECT_TOKEN(Tokens[3], tok::r_paren, TT_Unknown);
   EXPECT_TOKEN(Tokens[4], tok::amp, TT_BinaryOperator);
+
+  Tokens = annotate("#define FOO(bar) foo((uint64_t)&bar)");
+  ASSERT_EQ(Tokens.size(), 15u) << Tokens;
+  EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_CastRParen);
+  EXPECT_TOKEN(Tokens[11], tok::amp, TT_UnaryOperator);
+
+  Tokens = annotate("#define FOO(bar) foo((Foo) & bar)");
+  ASSERT_EQ(Tokens.size(), 15u) << Tokens;
+  EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_Unknown);
+  EXPECT_TOKEN(Tokens[11], tok::amp, TT_BinaryOperator);
+
+  auto Style = getLLVMStyle();
+  Style.TypeNames.push_back("Foo");
+  Tokens = annotate("#define FOO(bar) foo((Foo)&bar)", Style);
+  ASSERT_EQ(Tokens.size(), 15u) << Tokens;
+  EXPECT_TOKEN(Tokens[9], tok::identifier, TT_TypeName);
+  EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_CastRParen);
+  EXPECT_TOKEN(Tokens[11], tok::amp, TT_UnaryOperator);
 }
 
 TEST_F(TokenAnnotatorTest, UnderstandsDynamicExceptionSpecifier) {
@@ -1751,9 +1769,13 @@ TEST_F(TokenAnnotatorTest, UnderstandsFunctionDeclarationNames) {
   EXPECT_TOKEN(Tokens[3], tok::identifier, TT_Unknown);
   EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_FunctionTypeLParen);
 
+  Tokens = annotate("int iso_time(time_t);");
+  ASSERT_EQ(Tokens.size(), 7u) << Tokens;
+  EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName);
+
   auto Style = getLLVMStyle();
-  Style.TypeNames.push_back("time_t");
-  Tokens = annotate("int iso_time(time_t);", Style);
+  Style.TypeNames.push_back("MyType");
+  Tokens = annotate("int iso_time(MyType);", Style);
   ASSERT_EQ(Tokens.size(), 7u) << Tokens;
   EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName);
   EXPECT_TOKEN(Tokens[3], tok::identifier, TT_TypeName);
diff --git a/clang/unittests/Interpreter/CMakeLists.txt b/clang/unittests/Interpreter/CMakeLists.txt
index 712641afb976dd4f4d780ade824c69254960341f..b56e1e21015db91a85e6aa8a0a51b604eb057327 100644
--- a/clang/unittests/Interpreter/CMakeLists.txt
+++ b/clang/unittests/Interpreter/CMakeLists.txt
@@ -7,8 +7,10 @@ set(LLVM_LINK_COMPONENTS
   )
 
 add_clang_unittest(ClangReplInterpreterTests
+  IncrementalCompilerBuilderTest.cpp
   IncrementalProcessingTest.cpp
   InterpreterTest.cpp
+  InterpreterExtensionsTest.cpp
   CodeCompletionTest.cpp
   )
 target_link_libraries(ClangReplInterpreterTests PUBLIC
@@ -17,6 +19,7 @@ target_link_libraries(ClangReplInterpreterTests PUBLIC
   clangInterpreter
   clangFrontend
   clangSema
+  LLVMTestingSupport
   )
 
 # Exceptions on Windows are not yet supported.
diff --git a/clang/unittests/Interpreter/IncrementalCompilerBuilderTest.cpp b/clang/unittests/Interpreter/IncrementalCompilerBuilderTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f729566f7efde6daf631c8b9db8efccf15339185
--- /dev/null
+++ b/clang/unittests/Interpreter/IncrementalCompilerBuilderTest.cpp
@@ -0,0 +1,47 @@
+//=== unittests/Interpreter/IncrementalCompilerBuilderTest.cpp ------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Interpreter/Interpreter.h"
+#include "clang/Lex/PreprocessorOptions.h"
+#include "llvm/Support/Error.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace clang;
+
+namespace {
+
+// Usually FrontendAction takes the raw pointers and wraps them back into
+// unique_ptrs in InitializeFileRemapping()
+static void cleanupRemappedFileBuffers(CompilerInstance &CI) {
+  for (const auto &RB : CI.getPreprocessorOpts().RemappedFileBuffers) {
+    delete RB.second;
+  }
+  CI.getPreprocessorOpts().clearRemappedFiles();
+}
+
+TEST(IncrementalCompilerBuilder, SetCompilerArgs) {
+  std::vector ClangArgv = {"-Xclang", "-ast-dump-all"};
+  auto CB = clang::IncrementalCompilerBuilder();
+  CB.SetCompilerArgs(ClangArgv);
+  auto CI = cantFail(CB.CreateCpp());
+  EXPECT_TRUE(CI->getFrontendOpts().ASTDumpAll);
+  cleanupRemappedFileBuffers(*CI);
+}
+
+TEST(IncrementalCompilerBuilder, SetTargetTriple) {
+  auto CB = clang::IncrementalCompilerBuilder();
+  CB.SetTargetTriple("armv6-none-eabi");
+  auto CI = cantFail(CB.CreateCpp());
+  EXPECT_EQ(CI->getTargetOpts().Triple, "armv6-none-unknown-eabi");
+  cleanupRemappedFileBuffers(*CI);
+}
+
+} // end anonymous namespace
diff --git a/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f1c3d65ab0a95d049706b8ba4b4a6755fe5321e4
--- /dev/null
+++ b/clang/unittests/Interpreter/InterpreterExtensionsTest.cpp
@@ -0,0 +1,103 @@
+//===- unittests/Interpreter/InterpreterExtensionsTest.cpp ----------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Unit tests for Clang's Interpreter library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Interpreter/Interpreter.h"
+
+#include "clang/AST/Expr.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/Sema.h"
+
+#include "llvm/Support/Error.h"
+#include "llvm/Testing/Support/Error.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include 
+
+using namespace clang;
+namespace {
+
+class TestCreateResetExecutor : public Interpreter {
+public:
+  TestCreateResetExecutor(std::unique_ptr CI,
+                          llvm::Error &Err)
+      : Interpreter(std::move(CI), Err) {}
+
+  llvm::Error testCreateExecutor() { return Interpreter::CreateExecutor(); }
+
+  void resetExecutor() { Interpreter::ResetExecutor(); }
+};
+
+TEST(InterpreterExtensionsTest, ExecutorCreateReset) {
+  clang::IncrementalCompilerBuilder CB;
+  llvm::Error ErrOut = llvm::Error::success();
+  TestCreateResetExecutor Interp(cantFail(CB.CreateCpp()), ErrOut);
+  cantFail(std::move(ErrOut));
+  cantFail(Interp.testCreateExecutor());
+  Interp.resetExecutor();
+  cantFail(Interp.testCreateExecutor());
+  EXPECT_THAT_ERROR(Interp.testCreateExecutor(),
+                    llvm::FailedWithMessage("Operation failed. "
+                                            "Execution engine exists"));
+}
+
+class RecordRuntimeIBMetrics : public Interpreter {
+  struct NoopRuntimeInterfaceBuilder : public RuntimeInterfaceBuilder {
+    NoopRuntimeInterfaceBuilder(Sema &S) : S(S) {}
+
+    TransformExprFunction *getPrintValueTransformer() override {
+      TransformerQueries += 1;
+      return &noop;
+    }
+
+    static ExprResult noop(RuntimeInterfaceBuilder *Builder, Expr *E,
+                           ArrayRef FixedArgs) {
+      auto *B = static_cast(Builder);
+      B->TransformedExprs += 1;
+      return B->S.ActOnFinishFullExpr(E, /*DiscardedValue=*/false);
+    }
+
+    Sema &S;
+    size_t TransformedExprs = 0;
+    size_t TransformerQueries = 0;
+  };
+
+public:
+  // Inherit with using wouldn't make it public
+  RecordRuntimeIBMetrics(std::unique_ptr CI, llvm::Error &Err)
+      : Interpreter(std::move(CI), Err) {}
+
+  std::unique_ptr FindRuntimeInterface() override {
+    assert(RuntimeIBPtr == nullptr && "We create the builder only once");
+    Sema &S = getCompilerInstance()->getSema();
+    auto RuntimeIB = std::make_unique(S);
+    RuntimeIBPtr = RuntimeIB.get();
+    return RuntimeIB;
+  }
+
+  NoopRuntimeInterfaceBuilder *RuntimeIBPtr = nullptr;
+};
+
+TEST(InterpreterExtensionsTest, FindRuntimeInterface) {
+  clang::IncrementalCompilerBuilder CB;
+  llvm::Error ErrOut = llvm::Error::success();
+  RecordRuntimeIBMetrics Interp(cantFail(CB.CreateCpp()), ErrOut);
+  cantFail(std::move(ErrOut));
+  cantFail(Interp.Parse("int a = 1; a"));
+  cantFail(Interp.Parse("int b = 2; b"));
+  cantFail(Interp.Parse("int c = 3; c"));
+  EXPECT_EQ(3U, Interp.RuntimeIBPtr->TransformedExprs);
+  EXPECT_EQ(1U, Interp.RuntimeIBPtr->TransformerQueries);
+}
+
+} // end anonymous namespace
diff --git a/clang/unittests/Sema/SemaNoloadLookupTest.cpp b/clang/unittests/Sema/SemaNoloadLookupTest.cpp
index b24c72cba407f3a4c8c979bc2c6d1a162f4ecad7..cf89c7331e4e0fd06c7ecaccae56fdf74294f86a 100644
--- a/clang/unittests/Sema/SemaNoloadLookupTest.cpp
+++ b/clang/unittests/Sema/SemaNoloadLookupTest.cpp
@@ -64,7 +64,7 @@ public:
     CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();
 
     std::string CacheBMIPath =
-        llvm::Twine(TestDir + "/" + ModuleName + " .pcm").str();
+        llvm::Twine(TestDir + "/" + ModuleName + ".pcm").str();
     std::string PrebuiltModulePath =
         "-fprebuilt-module-path=" + TestDir.str().str();
     const char *Args[] = {"clang++",
@@ -75,9 +75,7 @@ public:
                           TestDir.c_str(),
                           "-I",
                           TestDir.c_str(),
-                          FileName.c_str(),
-                          "-o",
-                          CacheBMIPath.c_str()};
+                          FileName.c_str()};
     std::shared_ptr Invocation =
         createInvocation(Args, CIOpts);
     EXPECT_TRUE(Invocation);
@@ -85,7 +83,8 @@ public:
     CompilerInstance Instance;
     Instance.setDiagnostics(Diags.get());
     Instance.setInvocation(Invocation);
-    GenerateModuleInterfaceAction Action;
+    Instance.getFrontendOpts().OutputFile = CacheBMIPath;
+    GenerateReducedModuleInterfaceAction Action;
     EXPECT_TRUE(Instance.ExecuteAction(Action));
     EXPECT_FALSE(Diags->hasErrorOccurred());
 
diff --git a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
index ed0daa43436eb6d79742ba171b9c6b3e714035cb..ad8892b8c8be1e055baec762886b9e29e29d41c4 100644
--- a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
+++ b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
@@ -69,9 +69,9 @@ export int aa = 43;
     CIOpts.Diags = Diags;
     CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();
 
-    const char *Args[] = {
-        "clang++",       "-std=c++20", "--precompile", "-working-directory",
-        TestDir.c_str(), "a.cppm",     "-o",           BMIPath.c_str()};
+    const char *Args[] = {"clang++",       "-std=c++20",
+                          "--precompile",  "-working-directory",
+                          TestDir.c_str(), "a.cppm"};
     std::shared_ptr Invocation =
         createInvocation(Args, CIOpts);
     EXPECT_TRUE(Invocation);
@@ -88,6 +88,8 @@ export int aa = 43;
     Instance.setDiagnostics(Diags.get());
     Instance.setInvocation(Invocation);
 
+    Instance.getFrontendOpts().OutputFile = BMIPath;
+
     if (auto VFSWithRemapping = createVFSFromCompilerInvocation(
             Instance.getInvocation(), Instance.getDiagnostics(), CIOpts.VFS))
       CIOpts.VFS = VFSWithRemapping;
@@ -95,7 +97,7 @@ export int aa = 43;
 
     Instance.getHeaderSearchOpts().ValidateASTInputFilesContent = true;
 
-    GenerateModuleInterfaceAction Action;
+    GenerateReducedModuleInterfaceAction Action;
     EXPECT_TRUE(Instance.ExecuteAction(Action));
     EXPECT_FALSE(Diags->hasErrorOccurred());
   }
diff --git a/clang/unittests/Serialization/NoCommentsTest.cpp b/clang/unittests/Serialization/NoCommentsTest.cpp
index 2632a6337807acf8f30f6506d0648adcb69d83bd..a0a564aeff9a15e43006da6593ca009bc12f9294 100644
--- a/clang/unittests/Serialization/NoCommentsTest.cpp
+++ b/clang/unittests/Serialization/NoCommentsTest.cpp
@@ -90,9 +90,9 @@ void foo() {}
   CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();
 
   std::string CacheBMIPath = llvm::Twine(TestDir + "/Comments.pcm").str();
-  const char *Args[] = {
-      "clang++",       "-std=c++20",    "--precompile", "-working-directory",
-      TestDir.c_str(), "Comments.cppm", "-o",           CacheBMIPath.c_str()};
+  const char *Args[] = {"clang++",       "-std=c++20",
+                        "--precompile",  "-working-directory",
+                        TestDir.c_str(), "Comments.cppm"};
   std::shared_ptr Invocation =
       createInvocation(Args, CIOpts);
   ASSERT_TRUE(Invocation);
@@ -100,7 +100,8 @@ void foo() {}
   CompilerInstance Instance;
   Instance.setDiagnostics(Diags.get());
   Instance.setInvocation(Invocation);
-  GenerateModuleInterfaceAction Action;
+  Instance.getFrontendOpts().OutputFile = CacheBMIPath;
+  GenerateReducedModuleInterfaceAction Action;
   ASSERT_TRUE(Instance.ExecuteAction(Action));
   ASSERT_FALSE(Diags->hasErrorOccurred());
 
diff --git a/clang/unittests/Serialization/VarDeclConstantInitTest.cpp b/clang/unittests/Serialization/VarDeclConstantInitTest.cpp
index 7efa1c1d64a964a9f56d78678ed5d8402d03e88f..5cbbfb9ff003b377063703322f7b1e220f8751d4 100644
--- a/clang/unittests/Serialization/VarDeclConstantInitTest.cpp
+++ b/clang/unittests/Serialization/VarDeclConstantInitTest.cpp
@@ -96,10 +96,9 @@ export namespace Fibonacci
   CIOpts.Diags = Diags;
   CIOpts.VFS = llvm::vfs::createPhysicalFileSystem();
 
-  std::string CacheBMIPath = llvm::Twine(TestDir + "/Cached.pcm").str();
-  const char *Args[] = {
-      "clang++",       "-std=c++20",  "--precompile", "-working-directory",
-      TestDir.c_str(), "Cached.cppm", "-o",           CacheBMIPath.c_str()};
+  const char *Args[] = {"clang++",       "-std=c++20",
+                        "--precompile",  "-working-directory",
+                        TestDir.c_str(), "Cached.cppm"};
   std::shared_ptr Invocation =
       createInvocation(Args, CIOpts);
   ASSERT_TRUE(Invocation);
@@ -108,7 +107,11 @@ export namespace Fibonacci
   CompilerInstance Instance;
   Instance.setDiagnostics(Diags.get());
   Instance.setInvocation(Invocation);
-  GenerateModuleInterfaceAction Action;
+
+  std::string CacheBMIPath = llvm::Twine(TestDir + "/Cached.pcm").str();
+  Instance.getFrontendOpts().OutputFile = CacheBMIPath;
+
+  GenerateReducedModuleInterfaceAction Action;
   ASSERT_TRUE(Instance.ExecuteAction(Action));
   ASSERT_FALSE(Diags->hasErrorOccurred());
 
diff --git a/clang/unittests/StaticAnalyzer/CMakeLists.txt b/clang/unittests/StaticAnalyzer/CMakeLists.txt
index 775f0f8486b8f9f78fa87fe8c852f75234a1ecbb..db56e77331b821195cd366c2cfdabead09492256 100644
--- a/clang/unittests/StaticAnalyzer/CMakeLists.txt
+++ b/clang/unittests/StaticAnalyzer/CMakeLists.txt
@@ -11,6 +11,7 @@ add_clang_unittest(StaticAnalysisTests
   CallEventTest.cpp
   ConflictingEvalCallsTest.cpp
   FalsePositiveRefutationBRVisitorTest.cpp
+  IsCLibraryFunctionTest.cpp
   NoStateChangeFuncVisitorTest.cpp
   ParamRegionTest.cpp
   RangeSetTest.cpp
diff --git a/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp b/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..19c66cc6bee1eb227c6bc709c8b7057f8ca511e3
--- /dev/null
+++ b/clang/unittests/StaticAnalyzer/IsCLibraryFunctionTest.cpp
@@ -0,0 +1,89 @@
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+#include 
+
+using namespace clang;
+using namespace ento;
+using namespace ast_matchers;
+
+testing::AssertionResult extractFunctionDecl(StringRef Code,
+                                             const FunctionDecl *&Result) {
+  auto ASTUnit = tooling::buildASTFromCode(Code);
+  if (!ASTUnit)
+    return testing::AssertionFailure() << "AST construction failed";
+
+  ASTContext &Context = ASTUnit->getASTContext();
+  if (Context.getDiagnostics().hasErrorOccurred())
+    return testing::AssertionFailure() << "Compilation error";
+
+  auto Matches = ast_matchers::match(functionDecl().bind("fn"), Context);
+  if (Matches.empty())
+    return testing::AssertionFailure() << "No function declaration found";
+
+  if (Matches.size() > 1)
+    return testing::AssertionFailure()
+           << "Multiple function declarations found";
+
+  Result = Matches[0].getNodeAs("fn");
+  return testing::AssertionSuccess();
+}
+
+TEST(IsCLibraryFunctionTest, AcceptsGlobal) {
+  const FunctionDecl *Result;
+  ASSERT_TRUE(extractFunctionDecl(R"cpp(void fun();)cpp", Result));
+  EXPECT_TRUE(CheckerContext::isCLibraryFunction(Result));
+}
+
+TEST(IsCLibraryFunctionTest, AcceptsExternCGlobal) {
+  const FunctionDecl *Result;
+  ASSERT_TRUE(
+      extractFunctionDecl(R"cpp(extern "C" { void fun(); })cpp", Result));
+  EXPECT_TRUE(CheckerContext::isCLibraryFunction(Result));
+}
+
+TEST(IsCLibraryFunctionTest, RejectsNoInlineNoExternalLinkage) {
+  // Functions that are neither inlined nor externally visible cannot be C library functions.
+  const FunctionDecl *Result;
+  ASSERT_TRUE(extractFunctionDecl(R"cpp(static void fun();)cpp", Result));
+  EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result));
+}
+
+TEST(IsCLibraryFunctionTest, RejectsAnonymousNamespace) {
+  const FunctionDecl *Result;
+  ASSERT_TRUE(
+      extractFunctionDecl(R"cpp(namespace { void fun(); })cpp", Result));
+  EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result));
+}
+
+TEST(IsCLibraryFunctionTest, AcceptsStdNamespace) {
+  const FunctionDecl *Result;
+  ASSERT_TRUE(
+      extractFunctionDecl(R"cpp(namespace std { void fun(); })cpp", Result));
+  EXPECT_TRUE(CheckerContext::isCLibraryFunction(Result));
+}
+
+TEST(IsCLibraryFunctionTest, RejectsOtherNamespaces) {
+  const FunctionDecl *Result;
+  ASSERT_TRUE(
+      extractFunctionDecl(R"cpp(namespace stdx { void fun(); })cpp", Result));
+  EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result));
+}
+
+TEST(IsCLibraryFunctionTest, RejectsClassStatic) {
+  const FunctionDecl *Result;
+  ASSERT_TRUE(
+      extractFunctionDecl(R"cpp(class A { static void fun(); };)cpp", Result));
+  EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result));
+}
+
+TEST(IsCLibraryFunctionTest, RejectsClassMember) {
+  const FunctionDecl *Result;
+  ASSERT_TRUE(extractFunctionDecl(R"cpp(class A { void fun(); };)cpp", Result));
+  EXPECT_FALSE(CheckerContext::isCLibraryFunction(Result));
+}
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
index 91de8d17c9d5f2254a231f8688f8decc86db18a0..376874eb351de12ec0618d6ed1f9d98f443e1ae5 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
@@ -1,4 +1,4 @@
-//===- unittest/Tooling/RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp -===//
+//===- CXXOperatorCallExprTraverser.cpp -----------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksBinaryOperator.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksBinaryOperator.cpp
index 4c5b2b66c068fddcb6d331f1d29e14ba34b303a4..3d7a02872541c8a0f1600973e412043c99449f36 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksBinaryOperator.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksBinaryOperator.cpp
@@ -1,4 +1,4 @@
-//===- unittests/Tooling/RecursiveASTVisitorTests/CallbacksBinaryOperator.cpp -===//
+//===- CallbacksBinaryOperator.cpp ----------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCompoundAssignOperator.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCompoundAssignOperator.cpp
index f381d5e88a59f414a20268900c5b5d2688093d6e..34a39d2f8b7b9506792852d5c22010f69c89f77b 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCompoundAssignOperator.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksCompoundAssignOperator.cpp
@@ -1,4 +1,4 @@
-//===- unittests/Tooling/RecursiveASTVisitorTests/CallbacksCompoundAssignOperator.cpp -===//
+//===- CallbacksCompoundAssignOperator.cpp --------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksUnaryOperator.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksUnaryOperator.cpp
index 26c755599be800c5fd840768c17704b92d48d8fc..c0c7de474d0dc58c39d0d16dba75a148b845fd11 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksUnaryOperator.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/CallbacksUnaryOperator.cpp
@@ -1,4 +1,4 @@
-//===- unittests/Tooling/RecursiveASTVisitorTests/CallbacksUnaryOperator.cpp -===//
+//===- CallbacksUnaryOperator.cpp -----------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
index a15f4c83c5ebd9b8e879e6c53f148c7f7214d470..8750f78349443ebfa30033b1b3ab52453944141c 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp
@@ -1,4 +1,4 @@
-//===- unittest/Tooling/RecursiveASTVisitorTests/InitListExprPostOrderNoQueue.cpp -===//
+//===- InitListExprPostOrderNoQueue.cpp -----------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
index 1dafeef7cda7db44a9669aa3b7cdff1e42fbc4a9..8db88e1e06397576443cb12d17eba062f9c7e2cb 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp
@@ -1,4 +1,4 @@
-//===- unittest/Tooling/RecursiveASTVisitorTests/InitListExprPreOrderNoQueue.cpp -===//
+//===- InitListExprPreOrderNoQueue.cpp ------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
index 5eee19f0730e42ca9bfa4294afed7c8781a3ac65..f068e53ae9c288665be67082c5fc27d888c4cf95 100644
--- a/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
+++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp
@@ -1,4 +1,4 @@
-//===- unittest/Tooling/RecursiveASTVisitorTests/TemplateArgumentLocTraverser.cpp -===//
+//===- TemplateArgumentLocTraverser.cpp -----------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
index 48f55b8af97e4ee1d748b7106663f18949a53855..94f12a08164fdc5e17f186ffc29f9ce841e90b2f 100644
--- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
+++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
@@ -47,9 +47,47 @@ private:
     if (!Prototype.ends_with(")"))
       PrintFatalError(Loc, "Expected closing brace at end of prototype");
     Prototype = Prototype.drop_back();
-    for (auto T = Prototype.split(','); !T.first.empty();
-         Prototype = T.second, T = Prototype.split(','))
-      ParseType(T.first);
+
+    // Look through the input parameters.
+    const size_t end = Prototype.size();
+    for (size_t I = 0; I != end;) {
+      const StringRef Current = Prototype.substr(I, end);
+      // Skip any leading space or commas
+      if (Current.starts_with(" ") || Current.starts_with(",")) {
+        ++I;
+        continue;
+      }
+
+      // Check if we are in _ExtVector. We do this first because
+      // extended vectors are written in template form with the syntax
+      // _ExtVector< ..., ...>, so we need to make sure we are not
+      // detecting the comma of the template class as a separator for
+      // the parameters of the prototype. Note: the assumption is that
+      // we cannot have nested _ExtVector.
+      if (Current.starts_with("_ExtVector<")) {
+        const size_t EndTemplate = Current.find('>', 0);
+        ParseType(Current.substr(0, EndTemplate + 1));
+        // Move the prototype beyond _ExtVector<...>
+        I += EndTemplate + 1;
+        continue;
+      }
+
+      // We know that we are past _ExtVector, therefore the first seen
+      // comma is the boundary of a parameter in the prototype.
+      if (size_t CommaPos = Current.find(',', 0)) {
+        if (CommaPos != StringRef::npos) {
+          StringRef T = Current.substr(0, CommaPos);
+          ParseType(T);
+          // Move the prototype beyond the comma.
+          I += CommaPos + 1;
+          continue;
+        }
+      }
+
+      // No more commas, parse final parameter.
+      ParseType(Current);
+      I = end;
+    }
   }
 
   void ParseType(StringRef T) {
@@ -85,6 +123,28 @@ private:
       if (Substitution.empty())
         PrintFatalError(Loc, "Not a template");
       ParseType(Substitution);
+    } else if (T.consume_front("_ExtVector")) {
+      // Clang extended vector types are mangled as follows:
+      //
+      // '_ExtVector<'  ','  '>'
+
+      // Before parsing T(=), make sure the syntax of
+      // `_ExtVector` is correct...
+      if (!T.consume_front("<"))
+        PrintFatalError(Loc, "Expected '<' after '_ExtVector'");
+      unsigned long long Lanes;
+      if (llvm::consumeUnsignedInteger(T, 10, Lanes))
+        PrintFatalError(Loc, "Expected number of lanes after '_ExtVector<'");
+      Type += "E" + std::to_string(Lanes);
+      if (!T.consume_front(","))
+        PrintFatalError(Loc,
+                        "Expected ',' after number of lanes in '_ExtVector<'");
+      if (!T.consume_back(">"))
+        PrintFatalError(
+            Loc, "Expected '>' after scalar type in '_ExtVector'");
+
+      // ...all good, we can check if we have a valid ``.
+      ParseType(T);
     } else {
       auto ReturnTypeVal = StringSwitch(T)
                                .Case("__builtin_va_list_ref", "A")
diff --git a/clang/utils/TableGen/ClangOpcodesEmitter.cpp b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
index 1c41301ab3aeeba52aafe9831eac637928afd0df..120e1e2efa32b4adf676844cea7c826901723953 100644
--- a/clang/utils/TableGen/ClangOpcodesEmitter.cpp
+++ b/clang/utils/TableGen/ClangOpcodesEmitter.cpp
@@ -274,7 +274,7 @@ void ClangOpcodesEmitter::EmitGroup(raw_ostream &OS, StringRef N,
 
   // Emit the prototype of the group emitter in the header.
   OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n";
-  OS << "bool " << EmitFuncName << "(";
+  OS << "[[nodiscard]] bool " << EmitFuncName << "(";
   for (size_t I = 0, N = Types->size(); I < N; ++I)
     OS << "PrimType, ";
   for (auto *Arg : Args)
diff --git a/clang/www/c_status.html b/clang/www/c_status.html
index 3955a1d79639764a2acd2ccde2b00d2d22f3e1e5..9e4600b3e66acb17cbd1c1f590757ebebfd4df5b 100644
--- a/clang/www/c_status.html
+++ b/clang/www/c_status.html
@@ -784,7 +784,7 @@ conformance.

Free positioning of labels inside compound statements
N2508 - Clang 18 + Clang 18 Clarification request for C17 example of undefined behavior @@ -1156,7 +1156,7 @@ conformance.

Remove trigraphs??! N2940 - Clang 18 + Clang 18 Improved normal enumerations @@ -1196,12 +1196,12 @@ conformance.

Type inference for object declarations N3007 - Clang 18 + Clang 18 constexpr for object definitions N3018 - No + Clang 19 Introduce storage class specifiers for compound literals diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 8b638e06f4aab6c987ae5b756dd20ef778f43760..c20a5d021e9d95871e4355868a86cd00c25dad16 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -2668,13 +2668,13 @@ of class templates 438 CD2 Possible flaw in wording for multiple accesses to object between sequence points - Unknown + Clang 2.7 439 CD1 Guarantees on casting pointer back to cv-qualified version of original type - Unknown + Clang 2.7 440 @@ -2686,7 +2686,7 @@ of class templates 441 CD1 Ordering of static reference initialization - Unknown + Clang 2.7 442 @@ -2812,7 +2812,7 @@ of class templates 462 CD3 Lifetime of temporaries bound to comma expressions - Unknown + Clang 2.7 463 @@ -2992,7 +2992,7 @@ of class templates 492 CD1 typeid constness inconsistent with example - Unknown + Clang 2.7 493 @@ -3154,7 +3154,7 @@ of class templates 519 CD1 Null pointer preservation in void* conversions - Yes + Clang 2.7 520 @@ -3468,7 +3468,7 @@ and POD class 571 CD2 References declared const - Unknown + Clang 2.7 572 @@ -11076,7 +11076,7 @@ and POD class 1878 CD4 operator auto template - Clang 18 + Clang 18 1879 @@ -12384,7 +12384,7 @@ and POD class 2096 CD4 Constraints on literal unions - Duplicate of 2598 + Duplicate of 2598 2097 @@ -14478,7 +14478,7 @@ and POD class 2445 C++20 Partial ordering with rewritten candidates - Unknown + Clang 19 2446 @@ -15306,7 +15306,7 @@ and POD class 2583 C++23 Common initial sequence should consider over-alignment - Unknown + Clang 19 2584 @@ -15396,7 +15396,7 @@ and POD class 2598 C++23 Unions should not require a non-static data member of literal type - Clang 18 + Clang 18 2599 @@ -15726,7 +15726,7 @@ and POD class 2653 C++23 Can an explicit object parameter have a default argument? - Clang 18 + Clang 18 2654 @@ -15840,7 +15840,7 @@ and POD class 2672 DR Lambda body SFINAE is still required, contrary to intent and note - Clang 18 + Clang 18 2673 @@ -15930,7 +15930,7 @@ and POD class 2687 C++23 Calling an explicit object member function via an address-of-overload-set - Clang 18 + Clang 18 2688 @@ -16542,7 +16542,7 @@ and POD class 2789 DR Overload resolution with implicit and explicit object member functions - Clang 18 + Clang 18 2790 diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 301f141b2f2b60f4c01f9da8fd5bd41cc4edd2d7..1e36b90356c3e1abbb042b95fff95f0868c07b85 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -115,7 +115,7 @@ C++23, informally referred to as C++26.

Unevaluated strings P2361R6 - Clang 18 + Clang 18 Add @, $, and ` to the basic character set @@ -145,13 +145,13 @@ C++23, informally referred to as C++26.

Placeholder variables with no name P2169R4 - Clang 18 + Clang 18 Template parameter initialization P2308R1 (DR) - Clang 18 + Clang 18 Pack Indexing @@ -161,7 +161,7 @@ C++23, informally referred to as C++26.

Remove Deprecated Arithmetic Conversion on Enumerations P2864R2 - Clang 18 + Clang 18 @@ -197,7 +197,7 @@ C++23, informally referred to as C++26.

Simpler implicit move - P2266R1 + P2266R3 Clang 13 @@ -239,7 +239,7 @@ C++23, informally referred to as C++26.

Deducing this P0847R7 - Clang 18 + Clang 18 P2797R0 @@ -356,14 +356,7 @@ C++23, informally referred to as C++26.

Relaxing some constexpr restrictions P2448R2 - -
Clang 17 (Partial) - We do not support outside of defaulted special memeber functions the change that constexpr functions no - longer have to be constexpr compatible but rather support a less restricted requirements for constexpr - functions. Which include allowing non-literal types as return values and parameters, allow calling of - non-constexpr functions and constructors. -
- + Clang 19 Using unknown pointers and references in constant expressions @@ -388,7 +381,7 @@ C++23, informally referred to as C++26.

Portable assumptions P1774R8 - No + Clang 19 Support for UTF-8 as a portable source file encoding @@ -843,7 +836,13 @@ C++23, informally referred to as C++26.

Class template argument deduction for alias templates P1814R0 - No + +
+ Clang 19 (Partial) + The associated constraints (over.match.class.deduct#3.3) for the + synthesized deduction guides are not yet implemented. +
+ Permit conversions to arrays of unknown bound diff --git a/clang/www/make_cxx_dr_status b/clang/www/make_cxx_dr_status index 38f847cdc1b7f9f542a8d481096370b23eb8b4c0..7183e1a6d2be1afbfabc7440f18c256a9109f131 100755 --- a/clang/www/make_cxx_dr_status +++ b/clang/www/make_cxx_dr_status @@ -1,6 +1,7 @@ #! /usr/bin/env python3 import sys, os, re, urllib.request +latest_release = 18 clang_www_dir = os.path.dirname(__file__) default_issue_list_path = os.path.join(clang_www_dir, 'cwg_index.html') @@ -127,8 +128,6 @@ out_file.write('''\ Available in Clang? ''') -latest_release = 17 - class AvailabilityError(RuntimeError): pass diff --git a/cmake/Modules/CMakePolicy.cmake b/cmake/Modules/CMakePolicy.cmake index 0ec32ad8637f3dc237806719a4812528b82e31d4..1c18c1810dae6266f7bc8c306cbf33e7af8c5557 100644 --- a/cmake/Modules/CMakePolicy.cmake +++ b/cmake/Modules/CMakePolicy.cmake @@ -10,3 +10,16 @@ endif() if(POLICY CMP0116) cmake_policy(SET CMP0116 OLD) endif() + +# MSVC debug information format flags are selected via +# CMAKE_MSVC_DEBUG_INFORMATION_FORMAT, instead of +# embedding flags in e.g. CMAKE_CXX_FLAGS_RELEASE. +# New in CMake 3.25. +# +# Supports debug info with SCCache +# (https://github.com/mozilla/sccache?tab=readme-ov-file#usage) +# avoiding “fatal error C1041: cannot open program database; if +# multiple CL.EXE write to the same .PDB file, please use /FS" +if(POLICY CMP0141) + cmake_policy(SET CMP0141 NEW) +endif() diff --git a/cmake/Modules/LLVMVersion.cmake b/cmake/Modules/LLVMVersion.cmake new file mode 100644 index 0000000000000000000000000000000000000000..5e28283fbc1c60a0565f1e176087ae1a0eff0f6e --- /dev/null +++ b/cmake/Modules/LLVMVersion.cmake @@ -0,0 +1,15 @@ +# The LLVM Version number information + +if(NOT DEFINED LLVM_VERSION_MAJOR) + set(LLVM_VERSION_MAJOR 19) +endif() +if(NOT DEFINED LLVM_VERSION_MINOR) + set(LLVM_VERSION_MINOR 0) +endif() +if(NOT DEFINED LLVM_VERSION_PATCH) + set(LLVM_VERSION_PATCH 0) +endif() +if(NOT DEFINED LLVM_VERSION_SUFFIX) + set(LLVM_VERSION_SUFFIX git) +endif() + diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index 8a2b138d8d7020d510532780043c8feb96529337..d562a6206c00e7edd72ee6b559e5bd0a78338f73 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -502,7 +502,10 @@ append_list_if(MINGW -fms-extensions SANITIZER_COMMON_CFLAGS) # # Note that this type of issue was discovered with lsan, but can apply to other # sanitizers. -append_list_if(COMPILER_RT_HAS_TRIVIAL_AUTO_INIT -ftrivial-auto-var-init=pattern SANITIZER_COMMON_CFLAGS) +# Disable PowerPC because of https://github.com/llvm/llvm-project/issues/84654. +if(NOT "${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "powerpc") + append_list_if(COMPILER_RT_HAS_TRIVIAL_AUTO_INIT -ftrivial-auto-var-init=pattern SANITIZER_COMMON_CFLAGS) +endif() # Set common link flags. # TODO: We should consider using the same model as libc++, that is use either diff --git a/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake index 6a62d3bf7adcedd5517e40af3a493bce88551b60..1882893ad42c0c0ddc93400769fcd2d7e5c9c43e 100644 --- a/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake +++ b/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake @@ -116,7 +116,7 @@ function(darwin_test_archs os valid_archs) if(NOT TEST_COMPILE_ONLY) message(STATUS "Finding valid architectures for ${os}...") set(SIMPLE_C ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/src.c) - file(WRITE ${SIMPLE_C} "#include \nint main(void) { printf(__FILE__); return 0; }\n") + file(WRITE ${SIMPLE_C} "#include \n#include \nint main(void) { printf(__FILE__); fork(); return 0; }\n") set(os_linker_flags) foreach(flag ${DARWIN_${os}_LINK_FLAGS}) diff --git a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake index 25e7823716fc2f47b8d415d8f22c4d98a8479606..e8e5f612d5b03c3bc9fb64edad84d71702c763f6 100644 --- a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake +++ b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake @@ -583,7 +583,8 @@ function(add_security_warnings out_flags macosx_sdk_version) append_list_if(COMPILER_RT_HAS_RETURN_STACK_ADDRESS_FLAG -Werror=return-stack-address flags) append_list_if(COMPILER_RT_HAS_SIZEOF_ARRAY_DECAY_FLAG -Werror=sizeof-array-decay flags) append_list_if(COMPILER_RT_HAS_FORMAT_INSUFFICIENT_ARGS_FLAG -Werror=format-insufficient-args flags) - append_list_if(COMPILER_RT_HAS_BUILTIN_FORMAL_SECURITY_FLAG -Werror=format-security flags) + # GCC complains if we pass -Werror=format-security without -Wformat + append_list_if(COMPILER_RT_HAS_BUILTIN_FORMAL_SECURITY_FLAG -Wformat -Werror=format-security flags) append_list_if(COMPILER_RT_HAS_SIZEOF_ARRAY_DIV_FLAG -Werror=sizeof-array-div) append_list_if(COMPILER_RT_HAS_SIZEOF_POINTER_DIV_FLAG -Werror=sizeof-pointer-div) diff --git a/compiler-rt/cmake/base-config-ix.cmake b/compiler-rt/cmake/base-config-ix.cmake index 908c8a40278cf0cd1ed95cf8225c182942152d5e..1e3317de80ac3a36dde1192be5bc82e2ed1208e1 100644 --- a/compiler-rt/cmake/base-config-ix.cmake +++ b/compiler-rt/cmake/base-config-ix.cmake @@ -156,6 +156,7 @@ if(APPLE) option(COMPILER_RT_ENABLE_WATCHOS "Enable building for watchOS - Experimental" Off) option(COMPILER_RT_ENABLE_TVOS "Enable building for tvOS - Experimental" Off) + option(COMPILER_RT_ENABLE_XROS "Enable building for xrOS - Experimental" Off) else() option(COMPILER_RT_DEFAULT_TARGET_ONLY "Build builtins only for the default target" Off) diff --git a/compiler-rt/cmake/builtin-config-ix.cmake b/compiler-rt/cmake/builtin-config-ix.cmake index b17c43bf6a68b89082167b1b47c11c1a3c6708b2..33c97b1ac28aff8d733c43bcc53486e7c1be0138 100644 --- a/compiler-rt/cmake/builtin-config-ix.cmake +++ b/compiler-rt/cmake/builtin-config-ix.cmake @@ -1,4 +1,5 @@ include(BuiltinTests) +include(CheckIncludeFiles) include(CheckCSourceCompiles) # Make all the tests only check the compiler @@ -43,6 +44,8 @@ void foo(void) __arm_streaming_compatible { } ") +check_include_files("sys/auxv.h" COMPILER_RT_HAS_AUXV) + if(ANDROID) set(OS_NAME "Android") else() @@ -92,6 +95,8 @@ if(APPLE) find_darwin_sdk_dir(DARWIN_watchos_SYSROOT watchos) find_darwin_sdk_dir(DARWIN_tvossim_SYSROOT appletvsimulator) find_darwin_sdk_dir(DARWIN_tvos_SYSROOT appletvos) + find_darwin_sdk_dir(DARWIN_xrossim_SYSROOT xrsimulator) + find_darwin_sdk_dir(DARWIN_xros_SYSROOT xros) # Get supported architecture from SDKSettings. function(sdk_has_arch_support sdk_path os arch has_support) @@ -162,6 +167,11 @@ if(APPLE) list(APPEND DARWIN_tvossim_BUILTIN_ALL_POSSIBLE_ARCHS arm64) endif() endif() + if(COMPILER_RT_ENABLE_XROS) + list(APPEND DARWIN_EMBEDDED_PLATFORMS xros) + set(DARWIN_xros_BUILTIN_ALL_POSSIBLE_ARCHS ${ARM64} ${ARM32}) + set(DARWIN_xrossim_BUILTIN_ALL_POSSIBLE_ARCHS arm64) + endif() set(BUILTIN_SUPPORTED_OS osx) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index 2ca18ebb4ad489627c254a1697d7ac4ec23722fa..4f47142850a55eab870d3dfe6f01ff52d695f0a9 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -103,7 +103,7 @@ check_cxx_compiler_flag("-Werror -msse4.2" COMPILER_RT_HAS_MSSE4_2_FLAG) check_cxx_compiler_flag(--sysroot=. COMPILER_RT_HAS_SYSROOT_FLAG) check_cxx_compiler_flag("-Werror -mcrc" COMPILER_RT_HAS_MCRC_FLAG) check_cxx_compiler_flag(-fno-partial-inlining COMPILER_RT_HAS_FNO_PARTIAL_INLINING_FLAG) -check_cxx_compiler_flag(-Werror -ftrivial-auto-var-init=pattern COMPILER_RT_HAS_TRIVIAL_AUTO_INIT) +check_cxx_compiler_flag("-Werror -ftrivial-auto-var-init=pattern" COMPILER_RT_HAS_TRIVIAL_AUTO_INIT) if(NOT WIN32 AND NOT CYGWIN) # MinGW warns if -fvisibility-inlines-hidden is used. @@ -150,21 +150,21 @@ check_cxx_compiler_flag(/wd4391 COMPILER_RT_HAS_WD4391_FLAG) check_cxx_compiler_flag(/wd4722 COMPILER_RT_HAS_WD4722_FLAG) check_cxx_compiler_flag(/wd4800 COMPILER_RT_HAS_WD4800_FLAG) -check_cxx_compiler_flag(-Werror -Warray-bounds COMPILER_RT_HAS_ARRAY_BOUNDS_FLAG) -check_cxx_compiler_flag(-Werror -Wuninitialized COMPILER_RT_HAS_UNINITIALIZED_FLAG) -check_cxx_compiler_flag(-Werror -Wshadow COMPILER_RT_HAS_SHADOW_FLAG) -check_cxx_compiler_flag(-Werror -Wempty-body COMPILER_RT_HAS_EMPTY_BODY_FLAG) -check_cxx_compiler_flag(-Werror -Wsizeof-pointer-memaccess COMPILER_RT_HAS_SIZEOF_POINTER_MEMACCESS_FLAG) -check_cxx_compiler_flag(-Werror -Wsizeof-array-argument COMPILER_RT_HAS_SIZEOF_ARRAY_ARGUMENT_FLAG) -check_cxx_compiler_flag(-Werror -Wsuspicious-memaccess COMPILER_RT_HAS_SUSPICIOUS_MEMACCESS_FLAG) -check_cxx_compiler_flag(-Werror -Wbuiltin-memcpy-chk-size COMPILER_RT_HAS_BUILTIN_MEMCPY_CHK_SIZE_FLAG) -check_cxx_compiler_flag(-Werror -Warray-bounds-pointer-arithmetic COMPILER_RT_HAS_ARRAY_BOUNDS_POINTER_ARITHMETIC_FLAG) -check_cxx_compiler_flag(-Werror -Wreturn-stack-address COMPILER_RT_HAS_RETURN_STACK_ADDRESS_FLAG) -check_cxx_compiler_flag(-Werror -Wsizeof-array-decay COMPILER_RT_HAS_SIZEOF_ARRAY_DECAY_FLAG) -check_cxx_compiler_flag(-Werror -Wformat-insufficient-args COMPILER_RT_HAS_FORMAT_INSUFFICIENT_ARGS_FLAG) -check_cxx_compiler_flag(-Werror -Wformat-security COMPILER_RT_HAS_BUILTIN_FORMAL_SECURITY_FLAG) -check_cxx_compiler_flag(-Werror -Wsizeof-array-div COMPILER_RT_HAS_SIZEOF_ARRAY_DIV_FLAG) -check_cxx_compiler_flag(-Werror -Wsizeof-pointer-div COMPILER_RT_HAS_SIZEOF_POINTER_DIV_FLAG) +check_cxx_compiler_flag("-Werror -Warray-bounds" COMPILER_RT_HAS_ARRAY_BOUNDS_FLAG) +check_cxx_compiler_flag("-Werror -Wuninitialized" COMPILER_RT_HAS_UNINITIALIZED_FLAG) +check_cxx_compiler_flag("-Werror -Wshadow" COMPILER_RT_HAS_SHADOW_FLAG) +check_cxx_compiler_flag("-Werror -Wempty-body" COMPILER_RT_HAS_EMPTY_BODY_FLAG) +check_cxx_compiler_flag("-Werror -Wsizeof-pointer-memaccess" COMPILER_RT_HAS_SIZEOF_POINTER_MEMACCESS_FLAG) +check_cxx_compiler_flag("-Werror -Wsizeof-array-argument" COMPILER_RT_HAS_SIZEOF_ARRAY_ARGUMENT_FLAG) +check_cxx_compiler_flag("-Werror -Wsuspicious-memaccess" COMPILER_RT_HAS_SUSPICIOUS_MEMACCESS_FLAG) +check_cxx_compiler_flag("-Werror -Wbuiltin-memcpy-chk-size" COMPILER_RT_HAS_BUILTIN_MEMCPY_CHK_SIZE_FLAG) +check_cxx_compiler_flag("-Werror -Warray-bounds-pointer-arithmetic" COMPILER_RT_HAS_ARRAY_BOUNDS_POINTER_ARITHMETIC_FLAG) +check_cxx_compiler_flag("-Werror -Wreturn-stack-address" COMPILER_RT_HAS_RETURN_STACK_ADDRESS_FLAG) +check_cxx_compiler_flag("-Werror -Wsizeof-array-decay" COMPILER_RT_HAS_SIZEOF_ARRAY_DECAY_FLAG) +check_cxx_compiler_flag("-Werror -Wformat-insufficient-args" COMPILER_RT_HAS_FORMAT_INSUFFICIENT_ARGS_FLAG) +check_cxx_compiler_flag("-Werror -Wformat-security" COMPILER_RT_HAS_BUILTIN_FORMAL_SECURITY_FLAG) +check_cxx_compiler_flag("-Werror -Wsizeof-array-div" COMPILER_RT_HAS_SIZEOF_ARRAY_DIV_FLAG) +check_cxx_compiler_flag("-Werror -Wsizeof-pointer-div" COMPILER_RT_HAS_SIZEOF_POINTER_DIV_FLAG) # Symbols. check_symbol_exists(__func__ "" COMPILER_RT_HAS_FUNC_SYMBOL) diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index 3f2c0f0436393d2822b0fd24606bae5aac510c9e..f9611574a562b4c5927e413284b1734de7b72cea 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -917,7 +917,7 @@ cmake_dependent_option(COMPILER_RT_BUILD_CRT "Build crtbegin.o/crtend.o" ON "COM if (COMPILER_RT_BUILD_CRT) add_compiler_rt_component(crt) - option(COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY "Use eh_frame in crtbegin.o/crtend.o" OFF) + option(COMPILER_RT_CRT_USE_EH_FRAME_REGISTRY "Use eh_frame in crtbegin.o/crtend.o" ON) include(CheckSectionExists) check_section_exists(".init_array" COMPILER_RT_HAS_INITFINI_ARRAY diff --git a/compiler-rt/lib/builtins/aarch64/sme-abi.S b/compiler-rt/lib/builtins/aarch64/sme-abi.S index d470ecaf7aaad1974963cd368728aaee0119a596..4c0ff66931db7b2ccd6fcb5c2131ff8250b3e85e 100644 --- a/compiler-rt/lib/builtins/aarch64/sme-abi.S +++ b/compiler-rt/lib/builtins/aarch64/sme-abi.S @@ -26,9 +26,10 @@ // abort(). Note that there is no need to preserve any state before the call, // because the function does not return. DEFINE_COMPILERRT_PRIVATE_FUNCTION(do_abort) -.cfi_startproc - .variant_pcs SYMBOL_NAME(do_abort) - stp x29, x30, [sp, #-32]! + .cfi_startproc + .variant_pcs SYMBOL_NAME(do_abort) + BTI_C + stp x29, x30, [sp, #-32]! cntd x0 // Store VG to a stack location that we describe with .cfi_offset str x0, [sp, #16] @@ -36,22 +37,23 @@ DEFINE_COMPILERRT_PRIVATE_FUNCTION(do_abort) .cfi_offset w30, -24 .cfi_offset w29, -32 .cfi_offset 46, -16 - bl __arm_sme_state - tbz x0, #0, 2f + bl __arm_sme_state + tbz x0, #0, 2f 1: - smstop sm + smstop sm 2: // We can't make this into a tail-call because the unwinder would // need to restore the value of VG. - bl SYMBOL_NAME(abort) -.cfi_endproc + bl SYMBOL_NAME(abort) + .cfi_endproc END_COMPILERRT_FUNCTION(do_abort) // __arm_sme_state fills the result registers based on a local // that is set as part of the compiler-rt startup code. // __aarch64_has_sme_and_tpidr2_el0 DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_sme_state) - .variant_pcs __arm_sme_state + .variant_pcs __arm_sme_state + BTI_C mov x0, xzr mov x1, xzr @@ -68,7 +70,8 @@ DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_sme_state) END_COMPILERRT_OUTLINE_FUNCTION(__arm_sme_state) DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_tpidr2_restore) - .variant_pcs __arm_tpidr2_restore + .variant_pcs __arm_tpidr2_restore + BTI_C // If TPIDR2_EL0 is nonnull, the subroutine aborts in some platform-specific // manner. mrs x14, TPIDR2_EL0 @@ -103,7 +106,8 @@ DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_tpidr2_restore) END_COMPILERRT_OUTLINE_FUNCTION(__arm_tpidr2_restore) DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_tpidr2_save) - .variant_pcs __arm_tpidr2_restore + .variant_pcs __arm_tpidr2_restore + BTI_C // If the current thread does not have access to TPIDR2_EL0, the subroutine // does nothing. adrp x14, TPIDR2_SYMBOL @@ -143,7 +147,8 @@ DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_tpidr2_save) END_COMPILERRT_OUTLINE_FUNCTION(__arm_tpidr2_save) DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_za_disable) - .variant_pcs __arm_tpidr2_restore + .variant_pcs __arm_tpidr2_restore + BTI_C // If the current thread does not have access to SME, the subroutine does // nothing. adrp x14, TPIDR2_SYMBOL @@ -174,3 +179,8 @@ DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_za_disable) 0: ret END_COMPILERRT_OUTLINE_FUNCTION(__arm_za_disable) + +NO_EXEC_STACK_DIRECTIVE + +// GNU property note for BTI and PAC +GNU_PROPERTY_BTI_PAC diff --git a/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp index 71770166805f782c38f990a738dc2471d17fb4c4..db80eb383885e65360a94be7824c99185655f15f 100644 --- a/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerUtilWindows.cpp @@ -21,10 +21,15 @@ #include #include #include +// clang-format off #include - -// This must be included after windows.h. +// These must be included after windows.h. +// archicture need to be set before including +// libloaderapi +#include +#include #include +// clang-format on namespace fuzzer { @@ -234,8 +239,20 @@ size_t PageSize() { } void SetThreadName(std::thread &thread, const std::string &name) { - // TODO ? - // to UTF-8 then SetThreadDescription ? + typedef HRESULT(WINAPI * proc)(HANDLE, PCWSTR); + HMODULE kbase = GetModuleHandleA("KernelBase.dll"); + proc ThreadNameProc = + reinterpret_cast(GetProcAddress(kbase, "SetThreadDescription")); + if (ThreadNameProc) { + std::wstring buf; + auto sz = MultiByteToWideChar(CP_UTF8, 0, name.data(), -1, nullptr, 0); + if (sz > 0) { + buf.resize(sz); + if (MultiByteToWideChar(CP_UTF8, 0, name.data(), -1, &buf[0], sz) > 0) { + (void)ThreadNameProc(thread.native_handle(), buf.c_str()); + } + } + } } } // namespace fuzzer diff --git a/compiler-rt/lib/msan/tests/CMakeLists.txt b/compiler-rt/lib/msan/tests/CMakeLists.txt index 6ef63ff8216638e731f569556275b8d9fa3afc31..412a0f6b3de7f20d979bb26d4489b5343b2878a3 100644 --- a/compiler-rt/lib/msan/tests/CMakeLists.txt +++ b/compiler-rt/lib/msan/tests/CMakeLists.txt @@ -10,7 +10,8 @@ set(MSAN_LIBCXX_CFLAGS -fsanitize-memory-track-origins -fno-sanitize-memory-param-retval # unittests test mostly this mode. -Wno-pedantic - -Xclang -fdepfile-entry=${COMPILER_RT_OUTPUT_DIR}/share/msan_ignorelist.txt + # Do not instrument __gxx_personality_v0 (part of libcxxabi) + -fsanitize-ignorelist=${COMPILER_RT_OUTPUT_DIR}/share/msan_ignorelist.txt ) # Unittest sources and build flags. diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c b/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c index b9642ca7f6810f2cc871480a16e716f550f28ef3..741b01faada4e27a33c3ebf336fa3abb7d585492 100644 --- a/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformWindows.c @@ -93,12 +93,13 @@ ValueProfNode *__llvm_profile_end_vnodes(void) { return &VNodesEnd; } ValueProfNode *CurrentVNode = &VNodesStart + 1; ValueProfNode *EndVNode = &VNodesEnd; -/* lld-link provides __buildid symbol which ponits to the 16 bytes build id when +/* lld-link provides __buildid symbol which points to the 16 bytes build id when * using /build-id flag. https://lld.llvm.org/windows_support.html#lld-flags */ #define BUILD_ID_LEN 16 -COMPILER_RT_WEAK uint8_t __buildid[BUILD_ID_LEN]; +COMPILER_RT_WEAK uint8_t __buildid[BUILD_ID_LEN] = {0}; COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) { - if (*__buildid) { + static const uint8_t zeros[BUILD_ID_LEN] = {0}; + if (memcmp(__buildid, zeros, BUILD_ID_LEN) != 0) { if (Writer && lprofWriteOneBinaryId(Writer, BUILD_ID_LEN, __buildid, 0) == -1) return -1; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 47697ef280aa0d767a8395814e2e7de8c2e2b8c1..c451fc962c52940da2e200ed6f9a15650ceb233e 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -1098,7 +1098,7 @@ inline u32 GetNumberOfCPUsCached() { } // namespace __sanitizer -inline void *operator new(__sanitizer::operator_new_size_type size, +inline void *operator new(__sanitizer::usize size, __sanitizer::LowLevelAllocator &alloc) { return alloc.Allocate(size); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 3ecdb55cdbf72f5b9599c10453aa8e932904bc9d..a1be676730a78688d12a2383837eb2fad9b9ba9f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -974,7 +974,7 @@ INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - SSIZE_T res = REAL(read)(fd, ptr, count); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(read)(fd, ptr, count); if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); return res; @@ -1009,7 +1009,7 @@ INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - SSIZE_T res = REAL(pread)(fd, ptr, count, offset); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pread)(fd, ptr, count, offset); if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); return res; @@ -1027,7 +1027,7 @@ INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - SSIZE_T res = REAL(pread64)(fd, ptr, count, offset); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pread64)(fd, ptr, count, offset); if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); return res; @@ -1043,7 +1043,7 @@ INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov, void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); - SSIZE_T res = REAL(readv)(fd, iov, iovcnt); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(readv)(fd, iov, iovcnt); if (res > 0) write_iovec(ctx, iov, iovcnt, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); return res; @@ -1059,7 +1059,7 @@ INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt, void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); - SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(preadv)(fd, iov, iovcnt, offset); if (res > 0) write_iovec(ctx, iov, iovcnt, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); return res; @@ -1075,7 +1075,8 @@ INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt, void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); - SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset); + SSIZE_T res = + COMMON_INTERCEPTOR_BLOCK_REAL(preadv64)(fd, iov, iovcnt, offset); if (res > 0) write_iovec(ctx, iov, iovcnt, res); if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); return res; @@ -1091,8 +1092,9 @@ INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) { COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); - SSIZE_T res = REAL(write)(fd, ptr, count); - // FIXME: this check should be _before_ the call to REAL(write), not after + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(write)(fd, ptr, count); + // FIXME: this check should be _before_ the call to + // COMMON_INTERCEPTOR_BLOCK_REAL(write), not after if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res); return res; } @@ -1121,7 +1123,7 @@ INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) { COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); - SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pwrite)(fd, ptr, count, offset); if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res); return res; } @@ -1137,7 +1139,7 @@ INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count, COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); - SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pwrite64)(fd, ptr, count, offset); if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res); return res; } @@ -1153,7 +1155,7 @@ INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov, COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); - SSIZE_T res = REAL(writev)(fd, iov, iovcnt); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(writev)(fd, iov, iovcnt); if (res > 0) read_iovec(ctx, iov, iovcnt, res); return res; } @@ -1169,7 +1171,7 @@ INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt, COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); - SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(pwritev)(fd, iov, iovcnt, offset); if (res > 0) read_iovec(ctx, iov, iovcnt, res); return res; } @@ -1185,7 +1187,8 @@ INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt, COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); - SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset); + SSIZE_T res = + COMMON_INTERCEPTOR_BLOCK_REAL(pwritev64)(fd, iov, iovcnt, offset); if (res > 0) read_iovec(ctx, iov, iovcnt, res); return res; } @@ -2549,7 +2552,7 @@ INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - int res = REAL(wait)(status); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(wait)(status); if (res != -1 && status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); return res; @@ -2567,7 +2570,7 @@ INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop, // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - int res = REAL(waitid)(idtype, id, infop, options); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(waitid)(idtype, id, infop, options); if (res != -1 && infop) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz); return res; @@ -2578,7 +2581,7 @@ INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - int res = REAL(waitpid)(pid, status, options); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(waitpid)(pid, status, options); if (res != -1 && status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); return res; @@ -2589,7 +2592,7 @@ INTERCEPTOR(int, wait3, int *status, int options, void *rusage) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - int res = REAL(wait3)(status, options, rusage); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(wait3)(status, options, rusage); if (res != -1) { if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz); @@ -2603,7 +2606,8 @@ INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - int res = REAL(__wait4)(pid, status, options, rusage); + int res = + COMMON_INTERCEPTOR_BLOCK_REAL(__wait4)(pid, status, options, rusage); if (res != -1) { if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz); @@ -2618,7 +2622,7 @@ INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - int res = REAL(wait4)(pid, status, options, rusage); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(wait4)(pid, status, options, rusage); if (res != -1) { if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status)); if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz); @@ -2996,7 +3000,7 @@ INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) { COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen)); addrlen0 = *addrlen; } - int fd2 = REAL(accept)(fd, addr, addrlen); + int fd2 = COMMON_INTERCEPTOR_BLOCK_REAL(accept)(fd, addr, addrlen); if (fd2 >= 0) { if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2); if (addr && addrlen) @@ -3021,7 +3025,7 @@ INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) { // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - int fd2 = REAL(accept4)(fd, addr, addrlen, f); + int fd2 = COMMON_INTERCEPTOR_BLOCK_REAL(accept4)(fd, addr, addrlen, f); if (fd2 >= 0) { if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2); if (addr && addrlen) @@ -3045,7 +3049,7 @@ INTERCEPTOR(int, paccept, int fd, void *addr, unsigned *addrlen, addrlen0 = *addrlen; } if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set)); - int fd2 = REAL(paccept)(fd, addr, addrlen, set, f); + int fd2 = COMMON_INTERCEPTOR_BLOCK_REAL(paccept)(fd, addr, addrlen, set, f); if (fd2 >= 0) { if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2); if (addr && addrlen) @@ -3126,7 +3130,7 @@ INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg, // FIXME: under ASan the call below may write to freed memory and corrupt // its metadata. See // https://github.com/google/sanitizers/issues/321. - SSIZE_T res = REAL(recvmsg)(fd, msg, flags); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(recvmsg)(fd, msg, flags); if (res >= 0) { if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); if (msg) { @@ -3147,7 +3151,8 @@ INTERCEPTOR(int, recvmmsg, int fd, struct __sanitizer_mmsghdr *msgvec, void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, recvmmsg, fd, msgvec, vlen, flags, timeout); if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz); - int res = REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout); + int res = + COMMON_INTERCEPTOR_BLOCK_REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout); if (res >= 0) { if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); for (int i = 0; i < res; ++i) { @@ -3225,7 +3230,7 @@ INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg, COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); } - SSIZE_T res = REAL(sendmsg)(fd, msg, flags); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(sendmsg)(fd, msg, flags); if (common_flags()->intercept_send && res >= 0 && msg) read_msghdr(ctx, msg, res); return res; @@ -3244,7 +3249,7 @@ INTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec, COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); } - int res = REAL(sendmmsg)(fd, msgvec, vlen, flags); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(sendmmsg)(fd, msgvec, vlen, flags); if (res >= 0 && msgvec) { for (int i = 0; i < res; ++i) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len, @@ -3267,7 +3272,7 @@ INTERCEPTOR(int, msgsnd, int msqid, const void *msgp, SIZE_T msgsz, COMMON_INTERCEPTOR_ENTER(ctx, msgsnd, msqid, msgp, msgsz, msgflg); if (msgp) COMMON_INTERCEPTOR_READ_RANGE(ctx, msgp, sizeof(long) + msgsz); - int res = REAL(msgsnd)(msqid, msgp, msgsz, msgflg); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(msgsnd)(msqid, msgp, msgsz, msgflg); return res; } @@ -3275,7 +3280,8 @@ INTERCEPTOR(SSIZE_T, msgrcv, int msqid, void *msgp, SIZE_T msgsz, long msgtyp, int msgflg) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, msgrcv, msqid, msgp, msgsz, msgtyp, msgflg); - SSIZE_T len = REAL(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg); + SSIZE_T len = + COMMON_INTERCEPTOR_BLOCK_REAL(msgrcv)(msqid, msgp, msgsz, msgtyp, msgflg); if (len != -1) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msgp, sizeof(long) + len); return len; @@ -6119,7 +6125,7 @@ INTERCEPTOR(int, flopen, const char *path, int flags, ...) { if (path) { COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1); } - return REAL(flopen)(path, flags, mode); + return COMMON_INTERCEPTOR_BLOCK_REAL(flopen)(path, flags, mode); } INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) { @@ -6132,7 +6138,7 @@ INTERCEPTOR(int, flopenat, int dirfd, const char *path, int flags, ...) { if (path) { COMMON_INTERCEPTOR_READ_RANGE(ctx, path, internal_strlen(path) + 1); } - return REAL(flopenat)(dirfd, path, flags, mode); + return COMMON_INTERCEPTOR_BLOCK_REAL(flopenat)(dirfd, path, flags, mode); } #define INIT_FLOPEN \ @@ -6717,7 +6723,7 @@ INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, recv, fd, buf, len, flags); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); - SSIZE_T res = REAL(recv)(fd, buf, len, flags); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(recv)(fd, buf, len, flags); if (res > 0) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len)); } @@ -6734,7 +6740,8 @@ INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags, SIZE_T srcaddr_sz; if (srcaddr) srcaddr_sz = *addrlen; (void)srcaddr_sz; // prevent "set but not used" warning - SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(recvfrom)(fd, buf, len, flags, + srcaddr, addrlen); if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len)); if (res >= 0 && srcaddr) @@ -6757,7 +6764,7 @@ INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) { COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); } - SSIZE_T res = REAL(send)(fd, buf, len, flags); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(send)(fd, buf, len, flags); if (common_flags()->intercept_send && res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len)); return res; @@ -6772,7 +6779,8 @@ INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags, COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); } // Can't check dstaddr as it may have uninitialized padding at the end. - SSIZE_T res = REAL(sendto)(fd, buf, len, flags, dstaddr, addrlen); + SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(sendto)(fd, buf, len, flags, + dstaddr, addrlen); if (common_flags()->intercept_send && res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len)); return res; @@ -6789,7 +6797,7 @@ INTERCEPTOR(int, eventfd_read, int fd, __sanitizer_eventfd_t *value) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, eventfd_read, fd, value); COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); - int res = REAL(eventfd_read)(fd, value); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(eventfd_read)(fd, value); if (res == 0) { COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, sizeof(*value)); if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd); @@ -6803,7 +6811,7 @@ INTERCEPTOR(int, eventfd_write, int fd, __sanitizer_eventfd_t value) { COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd); COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd); } - int res = REAL(eventfd_write)(fd, value); + int res = COMMON_INTERCEPTOR_BLOCK_REAL(eventfd_write)(fd, value); return res; } #define INIT_EVENTFD_READ_WRITE \ @@ -7426,7 +7434,8 @@ INTERCEPTOR(int, open_by_handle_at, int mount_fd, struct file_handle* handle, COMMON_INTERCEPTOR_READ_RANGE( ctx, &sanitizer_handle->f_handle, sanitizer_handle->handle_bytes); - return REAL(open_by_handle_at)(mount_fd, handle, flags); + return COMMON_INTERCEPTOR_BLOCK_REAL(open_by_handle_at)(mount_fd, handle, + flags); } #define INIT_OPEN_BY_HANDLE_AT COMMON_INTERCEPT_FUNCTION(open_by_handle_at) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc index c10943b3e487932002f36dd1cf50b5d57699c7ee..b3161690f3ce8a74168aa6b7d84e27dae124f091 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_syscalls.inc @@ -2808,6 +2808,15 @@ PRE_SYSCALL(fchownat) POST_SYSCALL(fchownat) (long res, long dfd, const void *filename, long user, long group, long flag) {} +PRE_SYSCALL(fchmodat2)(long dfd, const void *filename, long mode, long flag) { + if (filename) + PRE_READ(filename, + __sanitizer::internal_strlen((const char *)filename) + 1); +} + +POST_SYSCALL(fchmodat2) +(long res, long dfd, const void *filename, long mode, long flag) {} + PRE_SYSCALL(openat)(long dfd, const void *filename, long flags, long mode) { if (filename) PRE_READ(filename, diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h index 992721757e88da456590b2c5087e55fc304869d3..294e330c4d56117732b8bee5d8d325554ae006d3 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h @@ -191,15 +191,10 @@ typedef uptr OFF_T; #endif typedef u64 OFF64_T; -#if (SANITIZER_WORDSIZE == 64) || SANITIZER_APPLE -typedef uptr operator_new_size_type; +#ifdef __SIZE_TYPE__ +typedef __SIZE_TYPE__ usize; #else -# if defined(__s390__) && !defined(__s390x__) -// Special case: 31-bit s390 has unsigned long as size_t. -typedef unsigned long operator_new_size_type; -# else -typedef u32 operator_new_size_type; -# endif +typedef uptr usize; #endif typedef u64 tid_t; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp index 40fe56661250e5a94cef4425f265d494bb54a338..97085e895a34b213b88fd86d0a1d696963945e95 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp @@ -212,8 +212,10 @@ struct InternalDeadlockDetector { return initialized > 0; } }; - -static THREADLOCAL InternalDeadlockDetector deadlock_detector; +// This variable is used by the __tls_get_addr interceptor, so cannot use the +// global-dynamic TLS model, as that would result in crashes. +__attribute__((tls_model("initial-exec"))) static THREADLOCAL + InternalDeadlockDetector deadlock_detector; void CheckedMutex::LockImpl(uptr pc) { deadlock_detector.Lock(type_, pc); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_placement_new.h b/compiler-rt/lib/sanitizer_common/sanitizer_placement_new.h index 1ceb8b909268f3ebfc85941822609f55cf41ed89..c9b917b453461abd6be642aa07bc3766ce740265 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_placement_new.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_placement_new.h @@ -17,8 +17,6 @@ #include "sanitizer_internal_defs.h" -inline void *operator new(__sanitizer::operator_new_size_type sz, void *p) { - return p; -} +inline void *operator new(__sanitizer::usize sz, void *p) { return p; } #endif // SANITIZER_PLACEMENT_NEW_H diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h index fa6077384d982651b849fc0a7b8103a8234f23f0..9e1fd6d6dca3c6301013cb2a73a57bc311f89b20 100644 --- a/compiler-rt/lib/scudo/standalone/combined.h +++ b/compiler-rt/lib/scudo/standalone/combined.h @@ -1081,6 +1081,11 @@ private: // An array of Size (at least one) elements of type Entry is immediately // following to this struct. }; + static_assert(sizeof(AllocationRingBuffer) % + alignof(typename AllocationRingBuffer::Entry) == + 0, + "invalid alignment"); + // Pointer to memory mapped area starting with AllocationRingBuffer struct, // and immediately followed by Size elements of type Entry. atomic_uptr RingBufferAddress = {}; @@ -1553,16 +1558,6 @@ private: constexpr u32 kFramesPerStack = 16; static_assert(isPowerOfTwo(kFramesPerStack)); - // We need StackDepot to be aligned to 8-bytes so the ring we store after - // is correctly assigned. - static_assert(sizeof(StackDepot) % alignof(atomic_u64) == 0); - - // Make sure the maximum sized StackDepot fits withint a uintptr_t to - // simplify the overflow checking. - static_assert(sizeof(StackDepot) + UINT32_MAX * sizeof(atomic_u64) * - UINT32_MAX * sizeof(atomic_u32) < - UINTPTR_MAX); - if (AllocationRingBufferSize > kMaxU32Pow2 / kStacksPerRingBufferEntry) return; u32 TabSize = static_cast(roundUpPowerOfTwo(kStacksPerRingBufferEntry * @@ -1570,7 +1565,6 @@ private: if (TabSize > UINT32_MAX / kFramesPerStack) return; u32 RingSize = static_cast(TabSize * kFramesPerStack); - DCHECK(isPowerOfTwo(RingSize)); uptr StackDepotSize = sizeof(StackDepot) + sizeof(atomic_u64) * RingSize + sizeof(atomic_u32) * TabSize; @@ -1596,10 +1590,6 @@ private: atomic_store(&RingBufferAddress, reinterpret_cast(RB), memory_order_release); - static_assert(sizeof(AllocationRingBuffer) % - alignof(typename AllocationRingBuffer::Entry) == - 0, - "invalid alignment"); } void unmapRingBuffer() { diff --git a/compiler-rt/lib/scudo/standalone/stack_depot.h b/compiler-rt/lib/scudo/standalone/stack_depot.h index 620137e44f372309ea463cbb2e987b50203bf31a..cf3cabf7085b6034bc4ed4fb96bd76536e245a4c 100644 --- a/compiler-rt/lib/scudo/standalone/stack_depot.h +++ b/compiler-rt/lib/scudo/standalone/stack_depot.h @@ -199,6 +199,10 @@ public: void enable() NO_THREAD_SAFETY_ANALYSIS { RingEndMu.unlock(); } }; +// We need StackDepot to be aligned to 8-bytes so the ring we store after +// is correctly assigned. +static_assert(sizeof(StackDepot) % alignof(atomic_u64) == 0); + } // namespace scudo #endif // SCUDO_STACK_DEPOT_H_ diff --git a/compiler-rt/lib/scudo/standalone/tests/memtag_test.cpp b/compiler-rt/lib/scudo/standalone/tests/memtag_test.cpp index fd277f962a9aaacc1d848b180b9fc00a571d99ca..37a18858e67c2cfcf074b0a8de05fb3377ba8024 100644 --- a/compiler-rt/lib/scudo/standalone/tests/memtag_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/memtag_test.cpp @@ -12,12 +12,17 @@ #include "platform.h" #include "tests/scudo_unit_test.h" +extern "C" void __hwasan_init() __attribute__((weak)); + #if SCUDO_LINUX namespace scudo { TEST(MemtagBasicDeathTest, Unsupported) { if (archSupportsMemoryTagging()) GTEST_SKIP(); + // Skip when running with HWASan. + if (&__hwasan_init != 0) + GTEST_SKIP(); EXPECT_DEATH(archMemoryTagGranuleSize(), "not supported"); EXPECT_DEATH(untagPointer((uptr)0), "not supported"); diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp index a9f6673ac44e90e3768172a717ae8d95f79f9311..24309ab66b2e671ad3917b168055d411a1e79330 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -2863,6 +2863,17 @@ void InitializeInterceptors() { new(interceptor_ctx()) InterceptorContext(); + // Interpose __tls_get_addr before the common interposers. This is needed + // because dlsym() may call malloc on failure which could result in other + // interposed functions being called that could eventually make use of TLS. +#ifdef NEED_TLS_GET_ADDR +# if !SANITIZER_S390 + TSAN_INTERCEPT(__tls_get_addr); +# else + TSAN_INTERCEPT(__tls_get_addr_internal); + TSAN_INTERCEPT(__tls_get_offset); +# endif +#endif InitializeCommonInterceptors(); InitializeSignalInterceptors(); InitializeLibdispatchInterceptors(); @@ -3010,15 +3021,6 @@ void InitializeInterceptors() { TSAN_INTERCEPT(__cxa_atexit); TSAN_INTERCEPT(_exit); -#ifdef NEED_TLS_GET_ADDR -#if !SANITIZER_S390 - TSAN_INTERCEPT(__tls_get_addr); -#else - TSAN_INTERCEPT(__tls_get_addr_internal); - TSAN_INTERCEPT(__tls_get_offset); -#endif -#endif - TSAN_MAYBE_INTERCEPT__LWP_EXIT; TSAN_MAYBE_INTERCEPT_THR_EXIT; diff --git a/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp b/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aab66502bd16fc64f01c10071b737d101aabaaec --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Windows/issue64990.cpp @@ -0,0 +1,20 @@ +// Repro for the issue #64990: Asan with Windows EH generates __asan_xxx runtime calls without required funclet tokens +// RUN: %clang_cl_asan %Od %s -EHsc %Fe%t +// RUN: not %run %t 2>&1 | FileCheck %s + +// UNSUPPORTED: target={{.*-windows-gnu}} + +char buff1[6] = "hello"; +char buff2[6] = "hello"; + +int main(int argc, char **argv) { + try { + throw 1; + } catch (...) { + // Make asan generate call to __asan_memcpy inside the EH pad. + __builtin_memcpy(buff1, buff2 + 3, 6); + } + return 0; +} + +// CHECK: SUMMARY: AddressSanitizer: global-buffer-overflow {{.*}} in __asan_memcpy diff --git a/compiler-rt/test/builtins/Unit/ctor_dtor.c b/compiler-rt/test/builtins/Unit/ctor_dtor.c index 3d5f895a0a1cd16d87a6aa2bbd0693865fe97b03..47560722a9f7505e034e482dea7a940adc99d776 100644 --- a/compiler-rt/test/builtins/Unit/ctor_dtor.c +++ b/compiler-rt/test/builtins/Unit/ctor_dtor.c @@ -9,13 +9,23 @@ // Ensure the various startup functions are called in the proper order. +// CHECK: __register_frame_info() /// ctor() is here if ld.so/libc supports DT_INIT/DT_FINI // CHECK: main() /// dtor() is here if ld.so/libc supports DT_INIT/DT_FINI +// CHECK: __deregister_frame_info() struct object; static int counter; +void __register_frame_info(const void *fi, struct object *obj) { + printf("__register_frame_info()\n"); +} + +void __deregister_frame_info(const void *fi) { + printf("__deregister_frame_info()\n"); +} + void __attribute__((constructor)) ctor() { printf("ctor()\n"); ++counter; diff --git a/compiler-rt/test/lit.common.cfg.py b/compiler-rt/test/lit.common.cfg.py index 113777b0ea8a1965df2382266e1b1a02fe2af5f3..ae28681915afb3e35b4b29ebb6babe908034dd8a 100644 --- a/compiler-rt/test/lit.common.cfg.py +++ b/compiler-rt/test/lit.common.cfg.py @@ -738,22 +738,6 @@ if config.lto_supported: if config.have_rpc_xdr_h: config.available_features.add("sunrpc") -# Ask llvm-config about assertion mode. -try: - llvm_config_cmd = subprocess.Popen( - [os.path.join(config.llvm_tools_dir, "llvm-config"), "--assertion-mode"], - stdout=subprocess.PIPE, - env=config.environment, - ) -except OSError as e: - print("Could not launch llvm-config in " + config.llvm_tools_dir) - print(" Failed with error #{0}: {1}".format(e.errno, e.strerror)) - exit(42) - -if re.search(r"ON", llvm_config_cmd.stdout.read().decode("ascii")): - config.available_features.add("asserts") -llvm_config_cmd.wait() - # Sanitizer tests tend to be flaky on Windows due to PR24554, so add some # retries. We don't do this on otther platforms because it's slower. if platform.system() == "Windows": diff --git a/compiler-rt/test/orc/lit.cfg.py b/compiler-rt/test/orc/lit.cfg.py index bd031d79826d3a0b7e0981a079b85459a106bdae..897cefb3d1930dea7542d4e2d5d7691863ffffdb 100644 --- a/compiler-rt/test/orc/lit.cfg.py +++ b/compiler-rt/test/orc/lit.cfg.py @@ -1,6 +1,7 @@ # -*- Python -*- import os +import subprocess # Setup config name. config.name = "ORC" + config.name_suffix @@ -79,3 +80,14 @@ config.excludes = ["Inputs"] if config.host_os not in ["Darwin", "FreeBSD", "Linux", "Windows"]: config.unsupported = True + +# Ask llvm-config about assertion mode. +try: + llvm_config_result = subprocess.check_output( + [os.path.join(config.llvm_tools_dir, "llvm-config"), "--assertion-mode"], + env=config.environment, + ) + if llvm_config_result.startswith(b"ON"): + config.available_features.add("asserts") +except OSError as e: + lit_config.warning(f"Could not determine if LLVM was built with assertions: {e}") diff --git a/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter_default_impl.cpp b/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter_default_impl.cpp index 1ac04b53491e14211b988b69f5632fbcbc2d7adf..1d1fbf7299e8b49e4997d579926e4f14fc7de529 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter_default_impl.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_inline8bit_counter_default_impl.cpp @@ -3,7 +3,9 @@ // REQUIRES: has_sancovcc,stable-runtime,linux,x86_64-target-arch -// RUN: %clangxx -O0 %s -fsanitize-coverage=inline-8bit-counters,pc-table -o %t +/// In glibc 2.39+, fprintf has a nonnull attribute. Disable nonnull-attribute, +/// which would increase counters for ubsan. +// RUN: %clangxx -O0 %s -fsanitize-coverage=inline-8bit-counters,pc-table -fno-sanitize=nonnull-attribute -o %t // RUN: rm -f %t-counters %t-pcs // RUN: env %tool_options="cov_8bit_counters_out=%t-counters cov_pcs_out=%t-pcs verbosity=1" %run %t 2>&1 | FileCheck %s diff --git a/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_symbolize.cpp b/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_symbolize.cpp index daa994c8116251bd3554dbfce16c9966fd9f879a..b168954a1c92cf931642faaa18bae13e0ebcf3cc 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_symbolize.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/sanitizer_coverage_symbolize.cpp @@ -7,7 +7,9 @@ // RUN: rm -rf $DIR // RUN: mkdir -p $DIR // RUN: cd $DIR -// RUN: %clangxx -O0 -fsanitize-coverage=trace-pc-guard %s -o %t +/// In glibc 2.39+, fprintf has a nonnull attribute. Disable nonnull-attribute, +/// which would increase counters for ubsan. +// RUN: %clangxx -O0 -fsanitize-coverage=trace-pc-guard -fno-sanitize=nonnull-attribute %s -o %t // RUN: %env_tool_opts=coverage=1 %t 2>&1 | FileCheck %s // RUN: rm -rf $DIR diff --git a/compiler-rt/test/tsan/pthread_atfork_deadlock3.c b/compiler-rt/test/tsan/pthread_atfork_deadlock3.c index 793eaf6ac867472c26302b3495d7d85b1d8dd29b..41b8f051b33c12b07462c55680ae9534e7782598 100644 --- a/compiler-rt/test/tsan/pthread_atfork_deadlock3.c +++ b/compiler-rt/test/tsan/pthread_atfork_deadlock3.c @@ -28,17 +28,17 @@ void *worker(void *main) { } void atfork() { + write(2, "in atfork\n", strlen("in atfork\n")); barrier_wait(&barrier); barrier_wait(&barrier); - write(2, "in atfork\n", strlen("in atfork\n")); static volatile long a; __atomic_fetch_add(&a, 1, __ATOMIC_RELEASE); } void afterfork() { + write(2, "in afterfork\n", strlen("in afterfork\n")); barrier_wait(&barrier); barrier_wait(&barrier); - write(2, "in afterfork\n", strlen("in afterfork\n")); static volatile long a; __atomic_fetch_add(&a, 1, __ATOMIC_RELEASE); } diff --git a/compiler-rt/test/tsan/signal_in_read.c b/compiler-rt/test/tsan/signal_in_read.c new file mode 100644 index 0000000000000000000000000000000000000000..ec50d9d02174561a812349c4134065b904a6eabc --- /dev/null +++ b/compiler-rt/test/tsan/signal_in_read.c @@ -0,0 +1,59 @@ +// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s + +#include "test.h" + +#include +#include +#include +#include +#include +#include +#include + +static int SignalPipeFd[] = {-1, -1}; +static int BlockingPipeFd[] = {-1, -1}; + +static void Handler(int _) { assert(write(SignalPipeFd[1], ".", 1) == 1); } + +static void *ThreadFunc(void *_) { + char C; + assert(read(BlockingPipeFd[0], &C, sizeof(C)) == 1); + assert(C == '.'); + return 0; +} + +int main() { + alarm(60); // Kill the test if it hangs. + + assert(pipe(SignalPipeFd) == 0); + assert(pipe(BlockingPipeFd) == 0); + + struct sigaction act; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + act.sa_handler = Handler; + assert(sigaction(SIGUSR1, &act, 0) == 0); + + pthread_t Thr; + assert(pthread_create(&Thr, 0, ThreadFunc, 0) == 0); + + // Give the thread enough time to block in the read call. + usleep(1000000); + + // Signal the thread, this should run the signal handler and unblock the read + // below. + pthread_kill(Thr, SIGUSR1); + char C; + assert(read(SignalPipeFd[0], &C, 1) == 1); + + // Unblock the thread and join it. + assert(write(BlockingPipeFd[1], &C, 1) == 1); + void *_ = 0; + assert(pthread_join(Thr, &_) == 0); + + fprintf(stderr, "PASS\n"); + return 0; +} + +// CHECK-NOT: WARNING: ThreadSanitizer: +// CHECK: PASS diff --git a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp index 79ff74cb2d0aeb3e1c23a7988f983d018272efe5..3f11ae018fc858c1f001afc732a40d14e2496004 100644 --- a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp +++ b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member-2.cpp @@ -2,7 +2,7 @@ // RUN: %clangxx %target_itanium_abi_host_triple %t -o %t.out // RUN: %test_debuginfo %s %t.out // XFAIL: gdb-clang-incompatibility -// XFAIL: system-darwin && target-aarch64 +// XFAIL: system-darwin // DEBUGGER: delete breakpoints // DEBUGGER: break static-member.cpp:33 diff --git a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp index abfa8e3337f64d975115ff926896bfd8dcc74650..57316dfd64040452eb81a3aeb03068922cd56e74 100644 --- a/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp +++ b/cross-project-tests/debuginfo-tests/llgdb-tests/static-member.cpp @@ -2,7 +2,7 @@ // RUN: %clangxx %target_itanium_abi_host_triple %t -o %t.out // RUN: %test_debuginfo %s %t.out // XFAIL: !system-darwin && gdb-clang-incompatibility -// XFAIL: system-darwin && target-aarch64 +// XFAIL: system-darwin // DEBUGGER: delete breakpoints // DEBUGGER: break static-member.cpp:33 // DEBUGGER: r diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt index 21617aeea0215ecf867d6bf7a1003fa27e646447..71141e5efac4888cb03b32f2aa0bcc891f892f66 100644 --- a/flang/CMakeLists.txt +++ b/flang/CMakeLists.txt @@ -413,6 +413,14 @@ if (LLVM_COMPILER_IS_GCC_COMPATIBLE) endif() +# Clang on Darwin enables non-POSIX extensions by default, which allows the +# macro HUGE to leak out of even when it is never directly included, +# conflicting with Flang's HUGE symbols. +# Set _POSIX_C_SOURCE to avoid including these extensions. +if (APPLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_POSIX_C_SOURCE=200809") +endif() + list(REMOVE_DUPLICATES CMAKE_CXX_FLAGS) # Determine HOST_LINK_VERSION on Darwin. diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md index baecfd7c48fd06cc89513433d6efba9f584e137e..697bd131c04c7a16de6a9732e929b7ee3c1093ec 100644 --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -706,6 +706,21 @@ end `INDEX` include an optional `BACK=` argument, but it doesn't actually work. +* Allocatable components of array and structure constructors are deallocated + after use without calling final subroutines. + The standard does not specify when and how deallocation of array and structure + constructors allocatable components should happen. All compilers free the + memory after use, but the behavior when the allocatable component is a derived + type with finalization differ, especially when dealing with nested array and + structure constructors expressions. Some compilers call final routine for the + allocatable components of each constructor sub-expressions, some call it only + for the allocatable component of the top level constructor, and some only + deallocate the memory. Deallocating only the memory offers the most + flexibility when lowering such expressions, and it is not clear finalization + is desirable in such context (Fortran interop 1.6.2 in F2018 standards require + array and structure constructors not to be finalized, so it also makes sense + not to finalize their allocatable components when releasing their storage). + ## De Facto Standard Features * `EXTENDS_TYPE_OF()` returns `.TRUE.` if both of its arguments have the diff --git a/flang/docs/OpenMP-declare-target.md b/flang/docs/OpenMP-declare-target.md new file mode 100644 index 0000000000000000000000000000000000000000..d29a46807e1eafb8ff78a4823754742ef4c42d6e --- /dev/null +++ b/flang/docs/OpenMP-declare-target.md @@ -0,0 +1,257 @@ + + +# Introduction to Declare Target + +In OpenMP `declare target` is a directive that can be applied to a function or +variable (primarily global) to notate to the compiler that it should be +generated in a particular device's environment. In essence whether something +should be emitted for host or device, or both. An example of its usage for +both data and functions can be seen below. + +```Fortran +module test_0 + integer :: sp = 0 +!$omp declare target link(sp) +end module test_0 + +program main + use test_0 +!$omp target map(tofrom:sp) + sp = 1 +!$omp end target +end program +``` + +In the above example, we create a variable in a separate module, mark it +as `declare target` and then map it, embedding it into the device IR and +assigning to it. + + +```Fortran +function func_t_device() result(i) + !$omp declare target to(func_t_device) device_type(nohost) + INTEGER :: I + I = 1 +end function func_t_device + +program main +!$omp target + call func_t_device() +!$omp end target +end program +``` + +In the above example, we are stating that a function is required on device +utilising `declare target`, and that we will not be utilising it on host, +so we are in theory free to remove or ignore it there. A user could also +in this case, leave off the `declare target` from the function and it +would be implicitly marked `declare target any` (for both host and device), +as it's been utilised within a target region. + +# Declare Target as represented in the OpenMP Dialect + +In the OpenMP Dialect `declare target` is not represented by a specific +`operation`. Instead, it's an OpenMP dialect specific `attribute` that can be +applied to any operation in any dialect, which helps to simplify the +utilisation of it. Rather than replacing or modifying existing global or +function `operations` in a dialect, it applies to it as extra metadata that +the lowering can use in different ways as is necessary. + +The `attribute` is composed of multiple fields representing the clauses you +would find on the `declare target` directive i.e. device type (`nohost`, +`any`, `host`) or the capture clause (`link` or `to`). A small example of +`declare target` applied to a Fortran `real` can be found below: + +``` +fir.global internal @_QFEi {omp.declare_target = +#omp.declaretarget} : f32 { + %0 = fir.undefined f32 + fir.has_value %0 : f32 +} +``` + +This would look similar for function style `operations`. + +The application and access of this attribute is aided by an OpenMP Dialect +MLIR Interface named `DeclareTargetInterface`, which can be utilised on +operations to access the appropriate interface functions, e.g.: + +```C++ +auto declareTargetGlobal = +llvm::dyn_cast(Op.getOperation()); +declareTargetGlobal.isDeclareTarget(); +``` + +# Declare Target Fortran OpenMP Lowering + +The initial lowering of `declare target` to MLIR for both use-cases is done +inside of the usual OpenMP lowering in flang/lib/Lower/OpenMP.cpp. However, +some direct calls to `declare target` related functions from Flang's +lowering bridge in flang/lib/Lower/Bridge.cpp are made. + +The marking of operations with the declare target attribute happens in two +phases, the second one optional and contingent on the first failing. The +initial phase happens when the declare target directive and its clauses +are initially processed, with the primary data gathering for the directive and +clause happening in a function called `getDeclareTargetInfo`. This is then used +to feed the `markDeclareTarget` function, which does the actual marking +utilising the `DeclareTargetInterface`. If it encounters a variable or function +that has been marked twice over multiple directives with two differing device +types (e.g. `host`, `nohost`), then it will swap the device type to `any`. + +Whenever we invoke `genFIR` on an `OpenMPDeclarativeConstruct` from the +lowering bridge, we are also invoking another function called +`gatherOpenMPDeferredDeclareTargets`, which gathers information relevant to the +application of the `declare target` attribute. This information +includes the symbol that it should be applied to, device type clause, +and capture clause, and it is stored in a vector that is part of the lowering +bridge's instantiation of the `AbstractConverter`. It is only stored if we +encounter a function or variable symbol that does not have an operation +instantiated for it yet. This cannot happen as part of the +initial marking as we must store this data in the lowering bridge and we +only have access to the abstract version of the converter via the OpenMP +lowering. + +The information produced by the first phase is used in the second phase, +which is a form of deferred processing of the `declare target` marked +operations that have delayed generation and cannot be proccessed in the +first phase. The main notable case this occurs currently is when a +Fortran function interface has been marked. This is +done via the function +`markOpenMPDeferredDeclareTargetFunctions`, which is called from the lowering +bridge at the end of the lowering process allowing us to mark those where +possible. It iterates over the data previously gathered by +`gatherOpenMPDeferredDeclareTargets` +checking if any of the recorded symbols have now had their corresponding +operations instantiated and applying the declare target attribute where +possible utilising `markDeclareTarget`. However, it must be noted that it +is still possible for operations not to be generated for certain symbols, +in particular the case of function interfaces that are not directly used +or defined within the current module. This means we cannot emit errors in +the case of left-over unmarked symbols. These must (and should) be caught +by the initial semantic analysis. + +NOTE: `declare target` can be applied to implicit `SAVE` attributed variables. +However, by default Flang does not represent these as `GlobalOp`'s, which means +we cannot tag and lower them as `declare target` normally. Instead, similarly +to the way `threadprivate` handles these cases, we raise and initialize the +variable as an internal `GlobalOp` and apply the attribute. This occurs in the +flang/lib/Lower/OpenMP.cpp function `genDeclareTargetIntGlobal`. + +# Declare Target Transformation Passes for Flang + +There are currently two passes within Flang that are related to the processing +of `declare target`: +* `OMPMarkDeclareTarget` - This pass is in charge of marking functions captured +(called from) in `target` regions or other `declare target` marked functions as +`declare target`. It does so recursively, i.e. nested calls will also be +implicitly marked. It currently will try to mark things as conservatively as +possible, e.g. if captured in a `target` region it will apply `nohost`, unless +it encounters a `host` `declare target` in which case it will apply the `any` +device type. Functions are handled similarly, except we utilise the parent's +device type where possible. +* `OMPFunctionFiltering` - This is executed after the `OMPMarkDeclareTarget` +pass, and its job is to conservatively remove host functions from +the module where possible when compiling for the device. This helps make +sure that most incompatible code for the host is not lowered for the +device. Host functions with `target` regions in them need to be preserved +(e.g. for lowering the `target region`(s) inside). Otherwise, it removes +any function marked as a `declare target host` function and any uses will be +replaced with `undef`'s so that the remaining host code doesn't become broken. +Host functions with `target` regions are marked with a `declare target host` +attribute so they will be removed after outlining the target regions contained +inside. + +While this infrastructure could be generally applicable to more than just Flang, +it is only utilised in the Flang frontend, so it resides there rather than in +the OpenMP dialect codebase. + +# Declare Target OpenMP Dialect To LLVM-IR Lowering + +The OpenMP dialect lowering of `declare target` is done through the +`amendOperation` flow, as it's not an `operation` but rather an +`attribute`. This is triggered immediately after the corresponding +operation has been lowered to LLVM-IR. As it is applicable to +different types of operations, we must specialise this function for +each operation type that we may encounter. Currently, this is +`GlobalOp`'s and `FuncOp`'s. + +`FuncOp` processing is fairly simple. When compiling for the device, +`host` marked functions are removed, including those that could not +be removed earlier due to having `target` directives within. This +leaves `any`, `device` or indeterminable functions left in the +module to lower further. When compiling for the host, no filtering is +done because `nohost` functions must be available as a fallback +implementation. + +For `GlobalOp`'s, the processing is a little more complex. We +currently leverage the `registerTargetGlobalVariable` and +`getAddrOfDeclareTargetVar` `OMPIRBuilder` functions shared with Clang. +These two functions invoke each other depending on the clauses and options +provided to the `OMPIRBuilder` (in particular, unified shared memory). Their +main purposes are the generation of a new global device pointer with a +"ref_" prefix on the device and enqueuing metadata generation by the +`OMPIRBuilder` to be produced at module finalization time. This is done +for both host and device and it links the newly generated device global +pointer and the host pointer together across the two modules. + +Similarly to other metadata (e.g. for `TargetOp`) that is shared across +both host and device modules, processing of `GlobalOp`'s in the device +needs access to the previously generated host IR file, which is done +through another `attribute` applied to the `ModuleOp` by the compiler +frontend. The file is loaded in and consumed by the `OMPIRBuilder` to +populate it's `OffloadInfoManager` data structures, keeping host and +device appropriately synchronised. + +The second (and more important to remember) is that as we effectively replace +the original LLVM-IR generated for the `declare target` marked `GlobalOp` we +have some corrections we need to do for `TargetOp`'s (or other region +operations that use them directly) which still refer to the original lowered +global operation. This is done via `handleDeclareTargetMapVar` which is invoked +as the final function and alteration to the lowered `target` region, it's only +invoked for device as it's only required in the case where we have emitted the +"ref" pointer , and it effectively replaces all uses of the originally lowered +global symbol, with our new global ref pointer's symbol. Currently we do not +remove or delete the old symbol, this is due to the fact that the same symbol +can be utilised across multiple target regions, if we remove it, we risk +breaking lowerings of target regions that will be processed at a later time. +To appropriately delete these no longer necessary symbols we would need a +deferred removal process at the end of the module, which is currently not in +place. It may be possible to store this information in the OMPIRBuilder and +then perform this cleanup process on finalization, but this is open for +discussion and implementation still. + +# Current Support + +For the moment, `declare target` should work for: +* Marking functions/subroutines and function/subroutine interfaces for +generation on host, device or both. +* Implicit function/subroutine capture for calls emitted in a `target` region +or explicitly marked `declare target` function/subroutine. Note: Calls made +via arguments passed to other functions must still be themselves marked +`declare target`, e.g. passing a `C` function pointer and invoking it, then +the interface and the `C` function in the other module must be marked +`declare target`, with the same type of marking as indicated by the +specification. +* Marking global variables with `declare target`'s `link` clause and mapping +the data to the device data environment utilising `declare target`. This may +not work for all types yet, but for scalars and arrays of scalars, it +should. + +Doesn't work for, or needs further testing for: +* Marking the following types with `declare target link` (needs further +testing): + * Descriptor based types, e.g. pointers/allocatables. + * Derived types. + * Members of derived types (use-case needs legality checking with OpenMP +specification). +* Marking global variables with `declare target`'s `to` clause. A lot of the +lowering should exist, but it needs further testing and likely some further +changes to fully function. diff --git a/flang/docs/index.md b/flang/docs/index.md index d974a3628b01d245a94919127f906cbb1fcf73ff..b4dbdc87fdf685fadd60168b4ab95c2745b892b7 100644 --- a/flang/docs/index.md +++ b/flang/docs/index.md @@ -68,6 +68,7 @@ on how to get in touch with us and to learn more about the current status. OpenACC OpenACC-descriptor-management.md OpenMP-4.5-grammar.md + OpenMP-declare-target OpenMP-descriptor-management OpenMP-semantics OptionComparison diff --git a/flang/include/flang/Evaluate/integer.h b/flang/include/flang/Evaluate/integer.h index 2fce4bedfaee0ff2edce18e5fda84ce0732c16e3..7395645701265d7e687e79db2953cdb9fdace0d9 100644 --- a/flang/include/flang/Evaluate/integer.h +++ b/flang/include/flang/Evaluate/integer.h @@ -27,8 +27,8 @@ #include #include -// Some environments, viz. clang on Darwin, allow the macro HUGE -// to leak out of even when it is never directly included. +// Some environments, viz. glibc 2.17, allow the macro HUGE +// to leak out of . #undef HUGE namespace Fortran::evaluate::value { @@ -154,7 +154,10 @@ public: } } } else { - INT signExtension{-(n < 0)}; + // Avoid left shifts of negative signed values (that's an undefined + // behavior in C++). + auto signExtension{std::make_unsigned_t(n < 0)}; + signExtension = ~signExtension + 1; static_assert(nBits >= partBits); if constexpr (nBits > partBits) { signExtension <<= nBits - partBits; @@ -478,7 +481,12 @@ public: SINT n = ToUInt(); constexpr std::size_t maxBits{CHAR_BIT * sizeof n}; if constexpr (bits < maxBits) { - n |= -(n >> (bits - 1)) << bits; + // Avoid left shifts of negative signed values (that's an undefined + // behavior in C++). + auto u{std::make_unsigned_t(ToUInt())}; + u = (u >> (bits - 1)) << (bits - 1); // Get the sign bit only. + u = ~u + 1; // Negate top bits if not 0. + n |= static_cast(u); } return n; } diff --git a/flang/include/flang/Evaluate/real.h b/flang/include/flang/Evaluate/real.h index 62c99cebc316842c74574450e3a148c922e274c6..d0da9634651f36254f22c28b2773893c0ac20abd 100644 --- a/flang/include/flang/Evaluate/real.h +++ b/flang/include/flang/Evaluate/real.h @@ -18,8 +18,8 @@ #include #include -// Some environments, viz. clang on Darwin, allow the macro HUGE -// to leak out of even when it is never directly included. +// Some environments, viz. glibc 2.17, allow the macro HUGE +// to leak out of . #undef HUGE namespace llvm { diff --git a/flang/include/flang/Evaluate/traverse.h b/flang/include/flang/Evaluate/traverse.h index 8d75cc2df7247b4d2c996ba96409a18c898d5b51..7f4a67d97e64e76f5910fa9b61b0a74e4fb4b1d0 100644 --- a/flang/include/flang/Evaluate/traverse.h +++ b/flang/include/flang/Evaluate/traverse.h @@ -45,7 +45,9 @@ #include namespace Fortran::evaluate { -template class Traverse { +template +class Traverse { public: explicit Traverse(Visitor &v) : visitor_{v} {} @@ -108,12 +110,13 @@ public: } Result operator()(const Symbol &symbol) const { const Symbol &ultimate{symbol.GetUltimate()}; - if (const auto *assoc{ - ultimate.detailsIf()}) { - return visitor_(assoc->expr()); - } else { - return visitor_.Default(); + if constexpr (TraverseAssocEntityDetails) { + if (const auto *assoc{ + ultimate.detailsIf()}) { + return visitor_(assoc->expr()); + } } + return visitor_.Default(); } Result operator()(const StaticDataObject &) const { return visitor_.Default(); @@ -284,7 +287,8 @@ private: // For validity checks across an expression: if any operator() result is // false, so is the overall result. template > + bool TraverseAssocEntityDetails = true, + typename Base = Traverse> struct AllTraverse : public Base { explicit AllTraverse(Visitor &v) : Base{v} {} using Base::operator(); @@ -296,7 +300,8 @@ struct AllTraverse : public Base { // is truthful is the final result. Works for Booleans, pointers, // and std::optional<>. template > + bool TraverseAssocEntityDetails = true, + typename Base = Traverse> class AnyTraverse : public Base { public: explicit AnyTraverse(Visitor &v) : Base{v} {} @@ -315,7 +320,8 @@ private: }; template > + bool TraverseAssocEntityDetails = true, + typename Base = Traverse> struct SetTraverse : public Base { explicit SetTraverse(Visitor &v) : Base{v} {} using Base::operator(); diff --git a/flang/include/flang/Lower/OpenMP.h b/flang/include/flang/Lower/OpenMP.h index e6fe7fb2276dea7c18748adea818a3fb74acebaa..3b22a652d1fc1e6a6ef656f6813732faa65879f3 100644 --- a/flang/include/flang/Lower/OpenMP.h +++ b/flang/include/flang/Lower/OpenMP.h @@ -13,12 +13,19 @@ #ifndef FORTRAN_LOWER_OPENMP_H #define FORTRAN_LOWER_OPENMP_H +#include "llvm/ADT/SmallVector.h" + #include +#include namespace mlir { class Value; class Operation; class Location; +namespace omp { +enum class DeclareTargetDeviceType : uint32_t; +enum class DeclareTargetCaptureClause : uint32_t; +} // namespace omp } // namespace mlir namespace fir { @@ -49,6 +56,12 @@ struct Evaluation; struct Variable; } // namespace pft +struct OMPDeferredDeclareTargetInfo { + mlir::omp::DeclareTargetCaptureClause declareTargetCaptureClause; + mlir::omp::DeclareTargetDeviceType declareTargetDeviceType; + const Fortran::semantics::Symbol &sym; +}; + // Generate the OpenMP terminator for Operation at Location. mlir::Operation *genOpenMPTerminator(fir::FirOpBuilder &, mlir::Operation *, mlir::Location); @@ -86,6 +99,14 @@ bool isOpenMPDeviceDeclareTarget(Fortran::lower::AbstractConverter &, Fortran::semantics::SemanticsContext &, Fortran::lower::pft::Evaluation &, const parser::OpenMPDeclarativeConstruct &); +void gatherOpenMPDeferredDeclareTargets( + Fortran::lower::AbstractConverter &, Fortran::semantics::SemanticsContext &, + Fortran::lower::pft::Evaluation &, + const parser::OpenMPDeclarativeConstruct &, + llvm::SmallVectorImpl &); +bool markOpenMPDeferredDeclareTargetFunctions( + mlir::Operation *, llvm::SmallVectorImpl &, + AbstractConverter &); void genOpenMPRequires(mlir::Operation *, const Fortran::semantics::Symbol *); } // namespace lower diff --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h index bd9b67b14b966cd3fc06e29dfeba6353f3e52c11..d61bf681be61941f63553bd25581954ae483d349 100644 --- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h +++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h @@ -309,6 +309,10 @@ public: void createStoreWithConvert(mlir::Location loc, mlir::Value val, mlir::Value addr); + /// Create a fir.load if \p val is a reference or pointer type. Return the + /// result of the load if it was created, otherwise return \p val + mlir::Value loadIfRef(mlir::Location loc, mlir::Value val); + /// Create a new FuncOp. If the function may have already been created, use /// `addNamedFunction` instead. mlir::func::FuncOp createFunction(mlir::Location loc, llvm::StringRef name, diff --git a/flang/include/flang/Optimizer/Builder/HLFIRTools.h b/flang/include/flang/Optimizer/Builder/HLFIRTools.h index 170e134baef614d9c0a5543fa01ccd3734cee9b9..ce87941d5382caf50a01d86bb9d521113c2a8e22 100644 --- a/flang/include/flang/Optimizer/Builder/HLFIRTools.h +++ b/flang/include/flang/Optimizer/Builder/HLFIRTools.h @@ -230,7 +230,8 @@ translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder, /// on the IR. fir::ExtendedValue translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder, - fir::FortranVariableOpInterface fortranVariable); + fir::FortranVariableOpInterface fortranVariable, + bool forceHlfirBase = false); /// Generate declaration for a fir::ExtendedValue in memory. fir::FortranVariableOpInterface diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h index 7cb99d61a686edfdf231f6ee8f323e85af9462c0..ca15b4bc34b29eecc6d8b4bfdeb9d300163fb050 100644 --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -338,6 +338,7 @@ struct IntrinsicLibrary { mlir::Value genSign(mlir::Type, llvm::ArrayRef); mlir::Value genSind(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genSize(mlir::Type, llvm::ArrayRef); + fir::ExtendedValue genSizeOf(mlir::Type, llvm::ArrayRef); mlir::Value genSpacing(mlir::Type resultType, llvm::ArrayRef args); fir::ExtendedValue genSpread(mlir::Type, llvm::ArrayRef); diff --git a/flang/include/flang/Optimizer/Dialect/CMakeLists.txt b/flang/include/flang/Optimizer/Dialect/CMakeLists.txt index fe9864a26295d22528a80413de4d1a4344a0e575..f00993d4d377804c28fd7acb1776c2cd0ab52f58 100644 --- a/flang/include/flang/Optimizer/Dialect/CMakeLists.txt +++ b/flang/include/flang/Optimizer/Dialect/CMakeLists.txt @@ -1,6 +1,10 @@ # This replicates part of the add_mlir_dialect cmake function from MLIR that # cannot be used her because it expects to be run inside MLIR directory which # is not the case for FIR. +set(LLVM_TARGET_DEFINITIONS FIRDialect.td) +mlir_tablegen(FIRDialect.h.inc -gen-dialect-decls -dialect=fir) +mlir_tablegen(FIRDialect.cpp.inc -gen-dialect-defs -dialect=fir) + set(LLVM_TARGET_DEFINITIONS FIRAttr.td) mlir_tablegen(FIREnumAttr.h.inc -gen-enum-decls) mlir_tablegen(FIREnumAttr.cpp.inc -gen-enum-defs) diff --git a/flang/include/flang/Optimizer/Dialect/FIRAttr.td b/flang/include/flang/Optimizer/Dialect/FIRAttr.td index 66d6cd471116b05d67bc89053b88f46474653580..2ac4af9e66aa80891eb5796fa85a73e5f41bc057 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRAttr.td +++ b/flang/include/flang/Optimizer/Dialect/FIRAttr.td @@ -16,7 +16,7 @@ include "flang/Optimizer/Dialect/FIRDialect.td" include "mlir/IR/EnumAttr.td" -class fir_Attr : AttrDef; +class fir_Attr : AttrDef; def FIRnoAttributes : I32BitEnumAttrCaseNone<"None">; def FIRallocatable : I32BitEnumAttrCaseBit<"allocatable", 0>; @@ -91,7 +91,7 @@ def fir_CUDADataAttribute : I32EnumAttr< } def fir_CUDADataAttributeAttr : - EnumAttr { + EnumAttr { let assemblyFormat = [{ ```<` $value `>` }]; } @@ -109,7 +109,7 @@ def fir_CUDAProcAttribute : I32EnumAttr< } def fir_CUDAProcAttributeAttr : - EnumAttr { + EnumAttr { let assemblyFormat = [{ ```<` $value `>` }]; } diff --git a/flang/include/flang/Optimizer/Dialect/FIRDialect.h b/flang/include/flang/Optimizer/Dialect/FIRDialect.h index 238385505dbff708d0934452cc315c3cff2b3e50..ed7c98ec82e2d155f1636608077b986a2a85013a 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRDialect.h +++ b/flang/include/flang/Optimizer/Dialect/FIRDialect.h @@ -15,43 +15,14 @@ #include "mlir/IR/Dialect.h" +#include "flang/Optimizer/Dialect/FIRDialect.h.inc" + namespace mlir { class IRMapping; } // namespace mlir namespace fir { -/// FIR dialect -class FIROpsDialect final : public mlir::Dialect { -public: - explicit FIROpsDialect(mlir::MLIRContext *ctx); - virtual ~FIROpsDialect(); - - static llvm::StringRef getDialectNamespace() { return "fir"; } - - mlir::Type parseType(mlir::DialectAsmParser &parser) const override; - void printType(mlir::Type ty, mlir::DialectAsmPrinter &p) const override; - - mlir::Attribute parseAttribute(mlir::DialectAsmParser &parser, - mlir::Type type) const override; - void printAttribute(mlir::Attribute attr, - mlir::DialectAsmPrinter &p) const override; - - /// Return string name of fir.runtime attribute. - static constexpr llvm::StringRef getFirRuntimeAttrName() { - return "fir.runtime"; - } - -private: - // Register the Attributes of this dialect. - void registerAttributes(); - // Register the Types of this dialect. - void registerTypes(); - // Register external interfaces on operations of - // this dialect. - void registerOpExternalInterfaces(); -}; - /// The FIR codegen dialect is a dialect containing a small set of transient /// operations used exclusively during code generation. class FIRCodeGenDialect final : public mlir::Dialect { diff --git a/flang/include/flang/Optimizer/Dialect/FIRDialect.td b/flang/include/flang/Optimizer/Dialect/FIRDialect.td index b366b6d40e4e21387d40012c662b9f28985b2544..0dfb3eda585ceb38469894e22ac6adbaaa4f16b7 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRDialect.td +++ b/flang/include/flang/Optimizer/Dialect/FIRDialect.td @@ -21,7 +21,7 @@ include "mlir/Interfaces/InferTypeOpInterface.td" include "mlir/Interfaces/LoopLikeInterface.td" include "mlir/Interfaces/SideEffectInterfaces.td" -def fir_Dialect : Dialect { +def FIROpsDialect : Dialect { let name = "fir"; let cppNamespace = "::fir"; let useDefaultTypePrinterParser = 0; @@ -30,10 +30,33 @@ def fir_Dialect : Dialect { let dependentDialects = [ // Arith dialect provides FastMathFlagsAttr // supported by some FIR operations. - "arith::ArithDialect", + "mlir::arith::ArithDialect", // TBAA Tag types - "LLVM::LLVMDialect" + "mlir::LLVM::LLVMDialect" ]; + let extraClassDeclaration = [{ + private: + // Register the builtin Attributes. + void registerAttributes(); + // Register the builtin Types. + void registerTypes(); + // Register external interfaces on operations of + // this dialect. + void registerOpExternalInterfaces(); + public: + mlir::Type parseType(mlir::DialectAsmParser &parser) const override; + void printType(mlir::Type ty, mlir::DialectAsmPrinter &p) const override; + + mlir::Attribute parseAttribute(mlir::DialectAsmParser &parser, + mlir::Type type) const override; + void printAttribute(mlir::Attribute attr, + mlir::DialectAsmPrinter &p) const override; + + // Return string name of fir.runtime attribute. + static constexpr llvm::StringRef getFirRuntimeAttrName() { + return "fir.runtime"; + } + }]; } #endif // FORTRAN_DIALECT_FIR_DIALECT diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td index db5e5f4bc682e6f067a42e2f6e3a422fe60d0c31..65a86d25333b5ddd0c5206edbdecfbfa61f1bb91 100644 --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -27,7 +27,7 @@ include "mlir/IR/BuiltinAttributes.td" // Base class for FIR operations. // All operations automatically get a prefix of "fir.". class fir_Op traits> - : Op; + : Op; // Base class for FIR operations that take a single argument class fir_SimpleOp traits> diff --git a/flang/include/flang/Optimizer/Dialect/FIRTypes.td b/flang/include/flang/Optimizer/Dialect/FIRTypes.td index 2a2f50720859e7002f84e563f5e40e7ea3449e28..4c6a8064991ab01670d64fd816c0ab6e478d9055 100644 --- a/flang/include/flang/Optimizer/Dialect/FIRTypes.td +++ b/flang/include/flang/Optimizer/Dialect/FIRTypes.td @@ -22,7 +22,7 @@ include "flang/Optimizer/Dialect/FIRDialect.td" class FIR_Type traits = [], string baseCppClass = "::mlir::Type"> - : TypeDef { + : TypeDef { let mnemonic = typeMnemonic; } diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td index c82eae154d31a1571a5f78ca27457bf8720972e1..743a6c98ec1a03446be766fb4e0ffac0151c2c34 100644 --- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td +++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td @@ -1358,7 +1358,9 @@ def hlfir_YieldOp : hlfir_Op<"yield", [Terminator, ParentOneOf<["RegionAssignOp" let assemblyFormat = "$entity attr-dict `:` type($entity) custom($cleanup)"; } -def hlfir_ElementalAddrOp : hlfir_Op<"elemental_addr", [Terminator, HasParent<"RegionAssignOp">, RecursiveMemoryEffects, RecursivelySpeculatable, hlfir_ElementalOpInterface]> { +def hlfir_ElementalAddrOp : hlfir_Op<"elemental_addr", [Terminator, HasParent<"RegionAssignOp">, + RecursiveMemoryEffects, RecursivelySpeculatable, hlfir_ElementalOpInterface, + AttrSizedOperandSegments]> { let summary = "Yield the address of a vector subscripted variable inside an hlfir.region_assign"; let description = [{ Special terminator node for the left-hand side region of an hlfir.region_assign @@ -1398,6 +1400,7 @@ def hlfir_ElementalAddrOp : hlfir_Op<"elemental_addr", [Terminator, HasParent<"R let arguments = (ins fir_ShapeType:$shape, + Optional:$mold, Variadic:$typeparams, OptionalAttr:$unordered ); @@ -1406,11 +1409,15 @@ def hlfir_ElementalAddrOp : hlfir_Op<"elemental_addr", [Terminator, HasParent<"R MaxSizedRegion<1>:$cleanup); let builders = [ - OpBuilder<(ins "mlir::Value":$shape, CArg<"bool", "false">:$isUnordered)> + OpBuilder<(ins "mlir::Value":$shape, + CArg<"mlir::Value", "{}">:$mold, + CArg<"mlir::ValueRange", "{}">:$typeparams, + CArg<"bool", "false">:$isUnordered)> ]; let assemblyFormat = [{ - $shape (`typeparams` $typeparams^)? (`unordered` $unordered^)? + $shape (`mold` $mold^)? (`typeparams` $typeparams^)? + (`unordered` $unordered^)? attr-dict `:` type(operands) $body custom($cleanup)}]; diff --git a/flang/include/flang/Parser/char-block.h b/flang/include/flang/Parser/char-block.h index fc5de2607b51b979aa7450f0bb533be55629751d..acd8aee98bf8db29b1db4bfc4b5ce85a06d6331f 100644 --- a/flang/include/flang/Parser/char-block.h +++ b/flang/include/flang/Parser/char-block.h @@ -129,6 +129,13 @@ public: private: int Compare(const CharBlock &that) const { + // "memcmp" in glibc has "nonnull" attributes on the input pointers. + // Avoid passing null pointers, since it would result in an undefined + // behavior. + if (size() == 0) + return that.size() == 0 ? 0 : -1; + if (that.size() == 0) + return 1; std::size_t bytes{std::min(size(), that.size())}; int cmp{std::memcmp(static_cast(begin()), static_cast(that.begin()), bytes)}; diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index 125025dab5f4485325a9aa4d88d934717079cc91..c3175a5d1a111d3e0f177dfad3c709e296ba0dcb 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -417,8 +417,12 @@ public: ProcEntityDetails(ProcEntityDetails &&) = default; ProcEntityDetails &operator=(const ProcEntityDetails &) = default; + const Symbol *rawProcInterface() const { return rawProcInterface_; } const Symbol *procInterface() const { return procInterface_; } - void set_procInterface(const Symbol &sym) { procInterface_ = &sym; } + void set_procInterfaces(const Symbol &raw, const Symbol &resolved) { + rawProcInterface_ = &raw; + procInterface_ = &resolved; + } inline bool HasExplicitInterface() const; // Be advised: !init().has_value() => uninitialized pointer, @@ -430,6 +434,7 @@ public: void set_isCUDAKernel(bool yes = true) { isCUDAKernel_ = yes; } private: + const Symbol *rawProcInterface_{nullptr}; const Symbol *procInterface_{nullptr}; std::optional init_; bool isCUDAKernel_{false}; diff --git a/flang/include/flang/Semantics/type.h b/flang/include/flang/Semantics/type.h index 8965d29d8889dade080a4fbf80999d478ed6543e..5520b02e6790d0b5ce61da12b6e8e7b3e00fef1a 100644 --- a/flang/include/flang/Semantics/type.h +++ b/flang/include/flang/Semantics/type.h @@ -306,7 +306,7 @@ public: } // For TYPE IS & CLASS IS: kind type parameters must be // explicit and equal, len type parameters are ignored. - bool Match(const DerivedTypeSpec &) const; + bool MatchesOrExtends(const DerivedTypeSpec &) const; std::string AsFortran() const; std::string VectorTypeAsFortran() const; diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp index 14abac5ff9ba801425822c38739508e348d06fab..0e7d97900328bb2e637660ebaee4514c20051f88 100644 --- a/flang/lib/Evaluate/check-expression.cpp +++ b/flang/lib/Evaluate/check-expression.cpp @@ -250,6 +250,8 @@ public: } } return false; + } else if (!CheckVarOrComponent(ultimate)) { + return false; } else if (!ultimate.attrs().test(semantics::Attr::TARGET)) { if (messages_) { messages_->Say( @@ -267,7 +269,7 @@ public: } return false; } else { - return CheckVarOrComponent(ultimate); + return true; } } bool operator()(const StaticDataObject &) const { return false; } @@ -318,24 +320,23 @@ public: private: bool CheckVarOrComponent(const semantics::Symbol &symbol) { const Symbol &ultimate{symbol.GetUltimate()}; - if (IsAllocatable(ultimate)) { - if (messages_) { - messages_->Say( - "An initial data target may not be a reference to an ALLOCATABLE '%s'"_err_en_US, - ultimate.name()); - emittedMessage_ = true; - } - return false; - } else if (ultimate.Corank() > 0) { - if (messages_) { - messages_->Say( - "An initial data target may not be a reference to a coarray '%s'"_err_en_US, - ultimate.name()); - emittedMessage_ = true; - } - return false; + const char *unacceptable{nullptr}; + if (ultimate.Corank() > 0) { + unacceptable = "a coarray"; + } else if (IsAllocatable(ultimate)) { + unacceptable = "an ALLOCATABLE"; + } else if (IsPointer(ultimate)) { + unacceptable = "a POINTER"; + } else { + return true; } - return true; + if (messages_) { + messages_->Say( + "An initial data target may not be a reference to %s '%s'"_err_en_US, + unacceptable, ultimate.name()); + emittedMessage_ = true; + } + return false; } parser::ContextualMessages *messages_; diff --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h index 798bc5f37f6f424202719f90c39299151f8a7d1d..9dd8c3843465d5c183c430c1dcd4778daf25fc84 100644 --- a/flang/lib/Evaluate/fold-implementation.h +++ b/flang/lib/Evaluate/fold-implementation.h @@ -39,8 +39,8 @@ #include #include -// Some environments, viz. clang on Darwin, allow the macro HUGE -// to leak out of even when it is never directly included. +// Some environments, viz. glibc 2.17, allow the macro HUGE +// to leak out of . #undef HUGE namespace Fortran::evaluate { diff --git a/flang/lib/Evaluate/intrinsics-library.cpp b/flang/lib/Evaluate/intrinsics-library.cpp index e68c5ed3f6a8b1b9d5c76d4d66639f1074f934f4..7315a7a057b102aabd0d1d9c18bdcd4fdcca6d3f 100644 --- a/flang/lib/Evaluate/intrinsics-library.cpp +++ b/flang/lib/Evaluate/intrinsics-library.cpp @@ -299,8 +299,8 @@ struct HostRuntimeLibrary, LibraryVersion::Libm> { /// Define libm extensions /// Bessel functions are defined in POSIX.1-2001. -// Remove float bessel functions for AIX as they are not supported -#ifndef _AIX +// Remove float bessel functions for AIX and Darwin as they are not supported +#if !defined(_AIX) && !defined(__APPLE__) template <> struct HostRuntimeLibrary { using F = FuncPointer; using FN = FuncPointer; diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index a8f2e5b445ed2b325728cf4e4093c182c8c583e1..9b98d22cc58e53377b64569fcf8866eb9560c591 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -2635,19 +2635,30 @@ SpecificCall IntrinsicProcTable::Implementation::HandleNull( static const char *const keywords[]{"mold", nullptr}; if (CheckAndRearrangeArguments(arguments, context.messages(), keywords, 1) && arguments[0]) { - if (Expr * mold{arguments[0]->UnwrapExpr()}) { - bool isProcPtrTarget{IsProcedurePointerTarget(*mold)}; + Expr *mold{arguments[0]->UnwrapExpr()}; + bool isBareNull{IsBareNullPointer(mold)}; + if (isBareNull) { + // NULL(NULL()), NULL(NULL(NULL())), &c. are all just NULL() + mold = nullptr; + } + if (mold) { + bool isProcPtrTarget{ + IsProcedurePointerTarget(*mold) && !IsNullObjectPointer(*mold)}; if (isProcPtrTarget || IsAllocatableOrPointerObject(*mold)) { characteristics::DummyArguments args; std::optional fResult; if (isProcPtrTarget) { // MOLD= procedure pointer - const Symbol *last{GetLastSymbol(*mold)}; - CHECK(last); - auto procPointer{IsProcedure(*last) - ? characteristics::Procedure::Characterize(*last, context) - : std::nullopt}; - // procPointer is null if there was an error with the analysis + std::optional procPointer; + if (IsNullProcedurePointer(*mold)) { + procPointer = + characteristics::Procedure::Characterize(*mold, context); + } else { + const Symbol *last{GetLastSymbol(*mold)}; + procPointer = + characteristics::Procedure::Characterize(DEREF(last), context); + } + // procPointer is vacant if there was an error with the analysis // associated with the procedure pointer if (procPointer) { args.emplace_back("mold"s, @@ -2676,8 +2687,10 @@ SpecificCall IntrinsicProcTable::Implementation::HandleNull( } } } - context.messages().Say(arguments[0]->sourceLocation(), - "MOLD= argument to NULL() must be a pointer or allocatable"_err_en_US); + if (!isBareNull) { + context.messages().Say(arguments[0]->sourceLocation(), + "MOLD= argument to NULL() must be a pointer or allocatable"_err_en_US); + } } characteristics::Procedure::Attrs attrs; attrs.set(characteristics::Procedure::Attr::NullPointer); diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp index e7fc651b9173fe1d97b0205fedd5165c3ea375a9..f514a25b010241bc8db96ce66f62951b18c74a8c 100644 --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -995,8 +995,10 @@ template semantics::UnorderedSymbolSet CollectSymbols( const Expr &); // HasVectorSubscript() -struct HasVectorSubscriptHelper : public AnyTraverse { - using Base = AnyTraverse; +struct HasVectorSubscriptHelper + : public AnyTraverse { + using Base = AnyTraverse; HasVectorSubscriptHelper() : Base{*this} {} using Base::operator(); bool operator()(const Subscript &ss) const { @@ -1045,9 +1047,10 @@ parser::Message *AttachDeclaration( } class FindImpureCallHelper - : public AnyTraverse> { + : public AnyTraverse, + /*TraverseAssocEntityDetails=*/false> { using Result = std::optional; - using Base = AnyTraverse; + using Base = AnyTraverse; public: explicit FindImpureCallHelper(FoldingContext &c) : Base{*this}, context_{c} {} diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 153ce0623ab3aee0bd98d9695f741854c080e76a..a668ba4116faab5f443a4a668426dd7dd0c55af1 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -618,7 +618,8 @@ public: assert(details && "No host-association found"); const Fortran::semantics::Symbol &hsym = details->symbol(); mlir::Type hSymType = genType(hsym); - Fortran::lower::SymbolBox hsb = lookupSymbol(hsym); + Fortran::lower::SymbolBox hsb = + lookupSymbol(hsym, /*symMap=*/nullptr, /*forceHlfirBase=*/true); auto allocate = [&](llvm::ArrayRef shape, llvm::ArrayRef typeParams) -> mlir::Value { @@ -727,7 +728,8 @@ public: void createHostAssociateVarCloneDealloc( const Fortran::semantics::Symbol &sym) override final { mlir::Location loc = genLocation(sym.name()); - Fortran::lower::SymbolBox hsb = lookupSymbol(sym); + Fortran::lower::SymbolBox hsb = + lookupSymbol(sym, /*symMap=*/nullptr, /*forceHlfirBase=*/true); fir::ExtendedValue hexv = symBoxToExtendedValue(hsb); hexv.match( @@ -960,13 +962,14 @@ private: /// Find the symbol in the local map or return null. Fortran::lower::SymbolBox lookupSymbol(const Fortran::semantics::Symbol &sym, - Fortran::lower::SymMap *symMap = nullptr) { + Fortran::lower::SymMap *symMap = nullptr, + bool forceHlfirBase = false) { symMap = symMap ? symMap : &localSymbols; if (lowerToHighLevelFIR()) { if (std::optional var = symMap->lookupVariableDefinition(sym)) { - auto exv = - hlfir::translateToExtendedValue(toLocation(), *builder, *var); + auto exv = hlfir::translateToExtendedValue(toLocation(), *builder, *var, + forceHlfirBase); return exv.match( [](mlir::Value x) -> Fortran::lower::SymbolBox { return Fortran::lower::SymbolBox::Intrinsic{x}; @@ -2633,6 +2636,9 @@ private: ompDeviceCodeFound || Fortran::lower::isOpenMPDeviceDeclareTarget( *this, bridge.getSemanticsContext(), getEval(), ompDecl); + Fortran::lower::gatherOpenMPDeferredDeclareTargets( + *this, bridge.getSemanticsContext(), getEval(), ompDecl, + ompDeferredDeclareTarget); genOpenMPDeclarativeConstruct( *this, localSymbols, bridge.getSemanticsContext(), getEval(), ompDecl); builder->restoreInsertionPoint(insertPt); @@ -5171,6 +5177,13 @@ private: /// lowering. void finalizeOpenMPLowering( const Fortran::semantics::Symbol *globalOmpRequiresSymbol) { + if (!ompDeferredDeclareTarget.empty()) { + bool deferredDeviceFuncFound = + Fortran::lower::markOpenMPDeferredDeclareTargetFunctions( + getModuleOp().getOperation(), ompDeferredDeclareTarget, *this); + ompDeviceCodeFound = ompDeviceCodeFound || deferredDeviceFuncFound; + } + // Set the module attribute related to OpenMP requires directives if (ompDeviceCodeFound) Fortran::lower::genOpenMPRequires(getModuleOp().getOperation(), @@ -5227,6 +5240,13 @@ private: /// intended for device offloading has been detected bool ompDeviceCodeFound = false; + /// Keeps track of symbols defined as declare target that could not be + /// processed at the time of lowering the declare target construct, such + /// as certain cases where interfaces are declared but not defined within + /// a module. + llvm::SmallVector + ompDeferredDeclareTarget; + const Fortran::lower::ExprToValueMap *exprValueOverrides{nullptr}; /// Stack of derived type under construction to avoid infinite loops when diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp index baf08b58a91b3f6b9483c9cc61d47f4d14915692..6e3ce101ef1af95102279569e5a3b13c5c6a087f 100644 --- a/flang/lib/Lower/ConvertCall.cpp +++ b/flang/lib/Lower/ConvertCall.cpp @@ -970,6 +970,18 @@ mlir::Value static getZeroLowerBounds(mlir::Location loc, return builder.genShift(loc, lowerBounds); } +static bool +isSimplyContiguous(const Fortran::evaluate::ActualArgument &arg, + Fortran::evaluate::FoldingContext &foldingContext) { + if (const auto *expr = arg.UnwrapExpr()) + return Fortran::evaluate::IsSimplyContiguous(*expr, foldingContext); + const Fortran::semantics::Symbol *sym = arg.GetAssumedTypeDummy(); + assert(sym && + "expect ActualArguments to be expression or assumed-type symbols"); + return sym->Rank() == 0 || + Fortran::evaluate::IsSimplyContiguous(*sym, foldingContext); +} + /// When dummy is not ALLOCATABLE, POINTER and is not passed in register, /// prepare the actual argument according to the interface. Do as needed: /// - address element if this is an array argument in an elemental call. @@ -985,7 +997,7 @@ static PreparedDummyArgument preparePresentUserCallActualArgument( const Fortran::lower::PreparedActualArgument &preparedActual, mlir::Type dummyType, const Fortran::lower::CallerInterface::PassedEntity &arg, - const Fortran::lower::SomeExpr &expr, CallContext &callContext) { + CallContext &callContext) { Fortran::evaluate::FoldingContext &foldingContext = callContext.converter.getFoldingContext(); @@ -1036,7 +1048,7 @@ static PreparedDummyArgument preparePresentUserCallActualArgument( const bool mustDoCopyInOut = actual.isArray() && arg.mustBeMadeContiguous() && (passingPolymorphicToNonPolymorphic || - !Fortran::evaluate::IsSimplyContiguous(expr, foldingContext)); + !isSimplyContiguous(*arg.entity, foldingContext)); const bool actualIsAssumedRank = actual.isAssumedRank(); // Create dummy type with actual argument rank when the dummy is an assumed @@ -1114,9 +1126,11 @@ static PreparedDummyArgument preparePresentUserCallActualArgument( arg.mayBeModifiedByCall() ? copyIn.getVar() : mlir::Value{}); } } else { + const Fortran::lower::SomeExpr *expr = arg.entity->UnwrapExpr(); + assert(expr && "expression actual argument cannot be an assumed type"); // The actual is an expression value, place it into a temporary // and register the temporary destruction after the call. - mlir::Type storageType = callContext.converter.genType(expr); + mlir::Type storageType = callContext.converter.genType(*expr); mlir::NamedAttribute byRefAttr = fir::getAdaptToByRefAttr(builder); hlfir::AssociateOp associate = hlfir::genAssociateExpr( loc, builder, entity, storageType, "", byRefAttr); @@ -1202,7 +1216,7 @@ static PreparedDummyArgument preparePresentUserCallActualArgument( if (auto baseBoxDummy = mlir::dyn_cast(dummyType)) if (baseBoxDummy.isAssumedRank()) if (const Fortran::semantics::Symbol *sym = - Fortran::evaluate::UnwrapWholeSymbolDataRef(expr)) + Fortran::evaluate::UnwrapWholeSymbolDataRef(*arg.entity)) if (Fortran::semantics::IsAssumedSizeArray(sym->GetUltimate())) TODO(loc, "passing assumed-size to assumed-rank array"); @@ -1224,10 +1238,10 @@ static PreparedDummyArgument prepareUserCallActualArgument( const Fortran::lower::PreparedActualArgument &preparedActual, mlir::Type dummyType, const Fortran::lower::CallerInterface::PassedEntity &arg, - const Fortran::lower::SomeExpr &expr, CallContext &callContext) { + CallContext &callContext) { if (!preparedActual.handleDynamicOptional()) - return preparePresentUserCallActualArgument( - loc, builder, preparedActual, dummyType, arg, expr, callContext); + return preparePresentUserCallActualArgument(loc, builder, preparedActual, + dummyType, arg, callContext); // Conditional dummy argument preparation. The actual may be absent // at runtime, causing any addressing, copy, and packaging to have @@ -1249,7 +1263,7 @@ static PreparedDummyArgument prepareUserCallActualArgument( builder.setInsertionPointToStart(preparationBlock); PreparedDummyArgument unconditionalDummy = preparePresentUserCallActualArgument(loc, builder, preparedActual, - dummyType, arg, expr, callContext); + dummyType, arg, callContext); builder.restoreInsertionPoint(insertPt); // TODO: when forwarding an optional to an optional of the same kind @@ -1291,10 +1305,11 @@ static PreparedDummyArgument prepareProcedurePointerActualArgument( const Fortran::lower::PreparedActualArgument &preparedActual, mlir::Type dummyType, const Fortran::lower::CallerInterface::PassedEntity &arg, - const Fortran::lower::SomeExpr &expr, CallContext &callContext) { + CallContext &callContext) { // NULL() actual to procedure pointer dummy - if (Fortran::evaluate::UnwrapExpr(expr) && + if (Fortran::evaluate::UnwrapExpr( + *arg.entity) && fir::isBoxProcAddressType(dummyType)) { auto boxTy{Fortran::lower::getUntypedBoxProcType(builder.getContext())}; auto tempBoxProc{builder.createTemporary(loc, boxTy)}; @@ -1335,9 +1350,6 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals, caller.placeInput(arg, builder.genAbsentOp(loc, argTy)); continue; } - const auto *expr = arg.entity->UnwrapExpr(); - if (!expr) - TODO(loc, "assumed type actual argument"); switch (arg.passBy) { case PassBy::Value: { @@ -1380,7 +1392,7 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals, case PassBy::BaseAddress: case PassBy::BoxChar: { PreparedDummyArgument preparedDummy = prepareUserCallActualArgument( - loc, builder, *preparedActual, argTy, arg, *expr, callContext); + loc, builder, *preparedActual, argTy, arg, callContext); callCleanUps.append(preparedDummy.cleanups.rbegin(), preparedDummy.cleanups.rend()); caller.placeInput(arg, preparedDummy.dummy); @@ -1388,7 +1400,7 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals, case PassBy::BoxProcRef: { PreparedDummyArgument preparedDummy = prepareProcedurePointerActualArgument(loc, builder, *preparedActual, - argTy, arg, *expr, callContext); + argTy, arg, callContext); callCleanUps.append(preparedDummy.cleanups.rbegin(), preparedDummy.cleanups.rend()); caller.placeInput(arg, preparedDummy.dummy); @@ -1408,6 +1420,9 @@ genUserCall(Fortran::lower::PreparedActualArguments &loweredActuals, caller.placeInput(arg, actual); } break; case PassBy::MutableBox: { + const Fortran::lower::SomeExpr *expr = arg.entity->UnwrapExpr(); + // C709 and C710. + assert(expr && "cannot pass TYPE(*) to POINTER or ALLOCATABLE"); hlfir::Entity actual = preparedActual->getActual(loc, builder); if (Fortran::evaluate::UnwrapExpr( *expr)) { @@ -2405,8 +2420,34 @@ genProcedureRef(CallContext &callContext) { caller.getPassedArguments()) if (const auto *actual = arg.entity) { const auto *expr = actual->UnwrapExpr(); - if (!expr) - TODO(loc, "assumed type actual argument"); + if (!expr) { + // TYPE(*) actual argument. + const Fortran::evaluate::Symbol *assumedTypeSym = + actual->GetAssumedTypeDummy(); + if (!assumedTypeSym) + fir::emitFatalError( + loc, "expected assumed-type symbol as actual argument"); + std::optional var = + callContext.symMap.lookupVariableDefinition(*assumedTypeSym); + if (!var) + fir::emitFatalError(loc, "assumed-type symbol was not lowered"); + hlfir::Entity actual{*var}; + std::optional isPresent; + if (arg.isOptional()) { + // Passing an optional TYPE(*) to an optional TYPE(*). Note that + // TYPE(*) cannot be ALLOCATABLE/POINTER (C709) so there is no + // need to cover the case of passing an ALLOCATABLE/POINTER to an + // OPTIONAL. + fir::FirOpBuilder &builder = callContext.getBuilder(); + isPresent = + builder.create(loc, builder.getI1Type(), actual) + .getResult(); + } + loweredActuals.push_back(Fortran::lower::PreparedActualArgument{ + hlfir::Entity{*var}, isPresent}); + continue; + } + if (Fortran::evaluate::UnwrapExpr( *expr)) { if ((arg.passBy != diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp index 68ecaa19d2d5d1255de6c8da6270776763168018..c5bfbdf6b8c115a5e1cc4ce0effbf5d6e07cea8d 100644 --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -761,9 +761,17 @@ private: // of the whole designator (not the ones of the vector subscripted part). // These are not yet known and will be added when finalizing the designator // lowering. - auto elementalAddrOp = - builder.create(loc, shape, - /*isUnordered=*/true); + // The resulting designator may be polymorphic, in which case the resulting + // type is the base of the vector subscripted part because + // allocatable/pointer components cannot be referenced after a vector + // subscripted part. Set the mold to the current base. It will be erased if + // the resulting designator is not polymorphic. + assert(partInfo.base.has_value() && + "vector subscripted part must have a base"); + mlir::Value mold = *partInfo.base; + auto elementalAddrOp = builder.create( + loc, shape, mold, mlir::ValueRange{}, + /*isUnordered=*/true); setVectorSubscriptElementAddrOp(elementalAddrOp); builder.setInsertionPointToEnd(&elementalAddrOp.getBody().front()); mlir::Region::BlockArgListType indices = elementalAddrOp.getIndices(); @@ -804,15 +812,8 @@ private: hlfir::EntityWithAttributes elementAddr) { fir::FirOpBuilder &builder = getBuilder(); builder.setInsertionPointToEnd(&elementalAddrOp.getBody().front()); - // For polymorphic entities, it will be needed to add a mold on the - // hlfir.elemental so that we are able to create temporary storage - // for it using the dynamic type. It seems that a reference to the mold - // entity can be created by evaluating the hlfir.elemental_addr - // for a single index. The evaluation should be legal as long as - // the hlfir.elemental_addr has no side effects, otherwise, - // it is not clear how to get the mold reference. - if (elementAddr.isPolymorphic()) - TODO(loc, "vector subscripted polymorphic entity in HLFIR"); + if (!elementAddr.isPolymorphic()) + elementalAddrOp.getMoldMutable().clear(); builder.create(loc, elementAddr); builder.setInsertionPointAfter(elementalAddrOp); } @@ -929,6 +930,8 @@ HlfirDesignatorBuilder::convertVectorSubscriptedExprToElementalAddr( hlfir::genLengthParameters(loc, builder, elementAddrEntity, lengths); if (!lengths.empty()) elementalAddrOp.getTypeparamsMutable().assign(lengths); + if (!elementAddrEntity.isPolymorphic()) + elementalAddrOp.getMoldMutable().clear(); // Create the hlfir.yield terminator inside the hlfir.elemental_body. builder.setInsertionPointToEnd(&elementalAddrOp.getBody().front()); builder.create(loc, elementAddrEntity); @@ -1844,6 +1847,16 @@ private: builder.genIfThen(loc, isAlloc).genThen(genAssign).end(); } + if (fir::isRecordWithAllocatableMember(recTy)) { + // Deallocate allocatable components without calling final subroutines. + // The Fortran 2018 section 9.7.3.2 about deallocation is not ruling + // about the fate of allocatable components of structure constructors, + // and there is no behavior consensus in other compilers. + fir::FirOpBuilder *bldr = &builder; + getStmtCtx().attachCleanup([=]() { + fir::runtime::genDerivedTypeDestroyWithoutFinalization(*bldr, loc, box); + }); + } return varOp; } diff --git a/flang/lib/Lower/IO.cpp b/flang/lib/Lower/IO.cpp index 699897adcd0b2e15de8f0d214d586d10214677ac..ac82276bcddbd0daac379f3cf465856081f4af71 100644 --- a/flang/lib/Lower/IO.cpp +++ b/flang/lib/Lower/IO.cpp @@ -242,8 +242,11 @@ static void makeNextConditionalOn(fir::FirOpBuilder &builder, // is in a fir.iterate_while loop, the result must be propagated up to the // loop scope as an extra ifOp result. (The propagation is done in genIoLoop.) mlir::TypeRange resTy; + // TypeRange does not own its contents, so make sure the the type object + // is live until the end of the function. + mlir::IntegerType boolTy = builder.getI1Type(); if (inLoop) - resTy = builder.getI1Type(); + resTy = boolTy; auto ifOp = builder.create(loc, resTy, ok, /*withElseRegion=*/inLoop); builder.setInsertionPointToStart(&ifOp.getThenRegion().front()); diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index 151077d81ba14a3fe1d43937b753a7d2a6c3e814..d2c6006ecf914a9b38b3e72451e12d146e959d6d 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -1041,14 +1041,6 @@ static mlir::Value genLogicalCombiner(fir::FirOpBuilder &builder, return builder.create(loc, value1.getType(), combined); } -static mlir::Value loadIfRef(fir::FirOpBuilder &builder, mlir::Location loc, - mlir::Value value) { - if (mlir::isa( - value.getType())) - return builder.create(loc, value); - return value; -} - static mlir::Value genComparisonCombiner(fir::FirOpBuilder &builder, mlir::Location loc, mlir::arith::CmpIPredicate pred, @@ -1066,8 +1058,8 @@ static mlir::Value genScalarCombiner(fir::FirOpBuilder &builder, mlir::acc::ReductionOperator op, mlir::Type ty, mlir::Value value1, mlir::Value value2) { - value1 = loadIfRef(builder, loc, value1); - value2 = loadIfRef(builder, loc, value2); + value1 = builder.loadIfRef(loc, value1); + value2 = builder.loadIfRef(loc, value2); if (op == mlir::acc::ReductionOperator::AccAdd) { if (ty.isIntOrIndex()) return builder.create(loc, value1, value2); diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 90fc1f80f57ab7e3ad8d4d080e653378311a8822..5cff95c7d125b074e164e300c5141da6886e9525 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -1120,7 +1120,21 @@ genTargetOp(Fortran::lower::AbstractConverter &converter, if (auto refType = baseOp.getType().dyn_cast()) eleType = refType.getElementType(); - if (fir::isa_trivial(eleType) || fir::isa_char(eleType)) { + // If a variable is specified in declare target link and if device + // type is not specified as `nohost`, it needs to be mapped tofrom + mlir::ModuleOp mod = converter.getFirOpBuilder().getModule(); + mlir::Operation *op = mod.lookupSymbol(converter.mangleName(sym)); + auto declareTargetOp = + llvm::dyn_cast_if_present(op); + if (declareTargetOp && declareTargetOp.isDeclareTarget()) { + if (declareTargetOp.getDeclareTargetCaptureClause() == + mlir::omp::DeclareTargetCaptureClause::link && + declareTargetOp.getDeclareTargetDeviceType() != + mlir::omp::DeclareTargetDeviceType::nohost) { + mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO; + mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM; + } + } else if (fir::isa_trivial(eleType) || fir::isa_char(eleType)) { captureKind = mlir::omp::VariableCaptureKind::ByCopy; } else if (!fir::isa_builtin_cptr_type(eleType)) { mapFlag |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO; @@ -1238,6 +1252,31 @@ static mlir::omp::DeclareTargetDeviceType getDeclareTargetInfo( return deviceType; } +static void collectDeferredDeclareTargets( + Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPDeclareTargetConstruct &declareTargetConstruct, + llvm::SmallVectorImpl + &deferredDeclareTarget) { + llvm::SmallVector symbolAndClause; + mlir::omp::DeclareTargetDeviceType devType = getDeclareTargetInfo( + converter, semaCtx, eval, declareTargetConstruct, symbolAndClause); + // Return the device type only if at least one of the targets for the + // directive is a function or subroutine + mlir::ModuleOp mod = converter.getFirOpBuilder().getModule(); + + for (const DeclareTargetCapturePair &symClause : symbolAndClause) { + mlir::Operation *op = mod.lookupSymbol(converter.mangleName( + std::get(symClause))); + + if (!op) { + deferredDeclareTarget.push_back( + {std::get<0>(symClause), devType, std::get<1>(symClause)}); + } + } +} + static std::optional getDeclareTargetFunctionDevice( Fortran::lower::AbstractConverter &converter, @@ -1245,7 +1284,7 @@ getDeclareTargetFunctionDevice( Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenMPDeclareTargetConstruct &declareTargetConstruct) { - llvm::SmallVector symbolAndClause; + llvm::SmallVector symbolAndClause; mlir::omp::DeclareTargetDeviceType deviceType = getDeclareTargetInfo( converter, semaCtx, eval, declareTargetConstruct, symbolAndClause); @@ -1253,10 +1292,10 @@ getDeclareTargetFunctionDevice( // directive is a function or subroutine mlir::ModuleOp mod = converter.getFirOpBuilder().getModule(); for (const DeclareTargetCapturePair &symClause : symbolAndClause) { - mlir::Operation *op = mod.lookupSymbol( - converter.mangleName(std::get(symClause))); + mlir::Operation *op = mod.lookupSymbol(converter.mangleName( + std::get(symClause))); - if (mlir::isa(op)) + if (mlir::isa_and_nonnull(op)) return deviceType; } @@ -1810,7 +1849,11 @@ genOMP(Fortran::lower::AbstractConverter &converter, /*outerCombined=*/false); break; case llvm::omp::Directive::OMPD_workshare: - TODO(currentLocation, "Workshare construct"); + // FIXME: Workshare is not a commonly used OpenMP construct, an + // implementation for this feature will come later. For the codes + // that use this construct, add a single construct for now. + genSingleOp(converter, semaCtx, eval, /*genNested=*/true, currentLocation, + beginClauseList, endClauseList); break; default: singleDirective = false; @@ -1845,7 +1888,8 @@ genOMP(Fortran::lower::AbstractConverter &converter, } if ((llvm::omp::workShareSet & llvm::omp::blockConstructSet) .test(directive.v)) { - TODO(currentLocation, "Workshare construct"); + genSingleOp(converter, semaCtx, eval, /*genNested=*/false, currentLocation, + beginClauseList, endClauseList); combinedDirective = true; } if (!combinedDirective) @@ -2002,56 +2046,56 @@ genOMP(Fortran::lower::AbstractConverter &converter, atomicConstruct.u); } +static void +markDeclareTarget(mlir::Operation *op, + Fortran::lower::AbstractConverter &converter, + mlir::omp::DeclareTargetCaptureClause captureClause, + mlir::omp::DeclareTargetDeviceType deviceType) { + // TODO: Add support for program local variables with declare target applied + auto declareTargetOp = llvm::dyn_cast(op); + if (!declareTargetOp) + fir::emitFatalError( + converter.getCurrentLocation(), + "Attempt to apply declare target on unsupported operation"); + + // The function or global already has a declare target applied to it, very + // likely through implicit capture (usage in another declare target + // function/subroutine). It should be marked as any if it has been assigned + // both host and nohost, else we skip, as there is no change + if (declareTargetOp.isDeclareTarget()) { + if (declareTargetOp.getDeclareTargetDeviceType() != deviceType) + declareTargetOp.setDeclareTarget(mlir::omp::DeclareTargetDeviceType::any, + captureClause); + return; + } + + declareTargetOp.setDeclareTarget(deviceType, captureClause); +} + static void genOMP(Fortran::lower::AbstractConverter &converter, Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenMPDeclareTargetConstruct &declareTargetConstruct) { - llvm::SmallVector symbolAndClause; + llvm::SmallVector symbolAndClause; mlir::ModuleOp mod = converter.getFirOpBuilder().getModule(); mlir::omp::DeclareTargetDeviceType deviceType = getDeclareTargetInfo( converter, semaCtx, eval, declareTargetConstruct, symbolAndClause); for (const DeclareTargetCapturePair &symClause : symbolAndClause) { - mlir::Operation *op = mod.lookupSymbol( - converter.mangleName(std::get(symClause))); - // There's several cases this can currently be triggered and it could be - // one of the following: - // 1) Invalid argument passed to a declare target that currently isn't - // captured by a frontend semantic check - // 2) The symbol of a valid argument is not correctly updated by one of - // the prior passes, resulting in missing symbol information - // 3) It's a variable internal to a module or program, that is legal by - // Fortran OpenMP standards, but is currently unhandled as they do not - // appear in the symbol table as they are represented as allocas + mlir::Operation *op = mod.lookupSymbol(converter.mangleName( + std::get(symClause))); + + // Some symbols are deferred until later in the module, these are handled + // upon finalization of the module for OpenMP inside of Bridge, so we simply + // skip for now. if (!op) - TODO(converter.getCurrentLocation(), - "Missing symbol, possible case of currently unsupported use of " - "a program local variable in declare target or erroneous symbol " - "information "); - - auto declareTargetOp = - llvm::dyn_cast(op); - if (!declareTargetOp) - fir::emitFatalError( - converter.getCurrentLocation(), - "Attempt to apply declare target on unsupported operation"); - - // The function or global already has a declare target applied to it, very - // likely through implicit capture (usage in another declare target - // function/subroutine). It should be marked as any if it has been assigned - // both host and nohost, else we skip, as there is no change - if (declareTargetOp.isDeclareTarget()) { - if (declareTargetOp.getDeclareTargetDeviceType() != deviceType) - declareTargetOp.setDeclareTarget( - mlir::omp::DeclareTargetDeviceType::any, - std::get(symClause)); continue; - } - declareTargetOp.setDeclareTarget( - deviceType, std::get(symClause)); + markDeclareTarget( + op, converter, + std::get(symClause), deviceType); } } @@ -2510,6 +2554,24 @@ bool Fortran::lower::isOpenMPTargetConstruct( return llvm::omp::allTargetSet.test(dir); } +void Fortran::lower::gatherOpenMPDeferredDeclareTargets( + Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semaCtx, + Fortran::lower::pft::Evaluation &eval, + const Fortran::parser::OpenMPDeclarativeConstruct &ompDecl, + llvm::SmallVectorImpl + &deferredDeclareTarget) { + std::visit( + Fortran::common::visitors{ + [&](const Fortran::parser::OpenMPDeclareTargetConstruct &ompReq) { + collectDeferredDeclareTargets(converter, semaCtx, eval, ompReq, + deferredDeclareTarget); + }, + [&](const auto &) {}, + }, + ompDecl.u); +} + bool Fortran::lower::isOpenMPDeviceDeclareTarget( Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semaCtx, @@ -2528,6 +2590,42 @@ bool Fortran::lower::isOpenMPDeviceDeclareTarget( ompDecl.u); } +// In certain cases such as subroutine or function interfaces which declare +// but do not define or directly call the subroutine or function in the same +// module, their lowering is delayed until after the declare target construct +// itself is processed, so there symbol is not within the table. +// +// This function will also return true if we encounter any device declare +// target cases, to satisfy checking if we require the requires attributes +// on the module. +bool Fortran::lower::markOpenMPDeferredDeclareTargetFunctions( + mlir::Operation *mod, + llvm::SmallVectorImpl &deferredDeclareTargets, + AbstractConverter &converter) { + bool deviceCodeFound = false; + auto modOp = llvm::cast(mod); + for (auto declTar : deferredDeclareTargets) { + mlir::Operation *op = modOp.lookupSymbol(converter.mangleName(declTar.sym)); + + // Due to interfaces being optionally emitted on usage in a module, + // not finding an operation at this point cannot be a hard error, we + // simply ignore it for now. + // TODO: Add semantic checks for detecting cases where an erronous + // (undefined) symbol has been supplied to a declare target clause + if (!op) + continue; + + auto devType = declTar.declareTargetDeviceType; + if (!deviceCodeFound && devType != mlir::omp::DeclareTargetDeviceType::host) + deviceCodeFound = true; + + markDeclareTarget(op, converter, declTar.declareTargetCaptureClause, + devType); + } + + return deviceCodeFound; +} + void Fortran::lower::genOpenMPRequires( mlir::Operation *mod, const Fortran::semantics::Symbol *symbol) { using MlirRequires = mlir::omp::ClauseRequires; diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h index f57cd7420ce4d50036bfe085e5ec5f6a8d811665..76a15e8bcaab9bf03840bc5b7ae54bb8c236b7fe 100644 --- a/flang/lib/Lower/OpenMP/Utils.h +++ b/flang/lib/Lower/OpenMP/Utils.h @@ -40,7 +40,7 @@ namespace omp { using DeclareTargetCapturePair = std::pair; + const Fortran::semantics::Symbol &>; mlir::omp::MapInfoOp createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc, diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp index 788c99e40105a26b6557b0cd6f0ff5034c1436a1..12da7412888a3b1935f539e6f8dffb4a08015137 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -16,6 +16,7 @@ #include "flang/Optimizer/Builder/Todo.h" #include "flang/Optimizer/Dialect/FIRAttr.h" #include "flang/Optimizer/Dialect/FIROpsSupport.h" +#include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Optimizer/Support/FatalError.h" #include "flang/Optimizer/Support/InternalNames.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" @@ -404,6 +405,12 @@ void fir::FirOpBuilder::createStoreWithConvert(mlir::Location loc, create(loc, cast, addr); } +mlir::Value fir::FirOpBuilder::loadIfRef(mlir::Location loc, mlir::Value val) { + if (fir::isa_ref_type(val.getType())) + return create(loc, val); + return val; +} + fir::StringLitOp fir::FirOpBuilder::createStringLitOp(mlir::Location loc, llvm::StringRef data) { auto type = fir::CharacterType::get(getContext(), 1, data.size()); diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp index 4ffa303f27103ae2072710b3bfcaf51c5e5cb2a3..c7a550814e1d588356c9950cba4f5d3bb1299743 100644 --- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp +++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp @@ -848,36 +848,38 @@ hlfir::LoopNest hlfir::genLoopNest(mlir::Location loc, static fir::ExtendedValue translateVariableToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder, - hlfir::Entity variable) { + hlfir::Entity variable, + bool forceHlfirBase = false) { assert(variable.isVariable() && "must be a variable"); /// When going towards FIR, use the original base value to avoid /// introducing descriptors at runtime when they are not required. - mlir::Value firBase = variable.getFirBase(); + mlir::Value base = + forceHlfirBase ? variable.getBase() : variable.getFirBase(); if (variable.isMutableBox()) - return fir::MutableBoxValue(firBase, getExplicitTypeParams(variable), + return fir::MutableBoxValue(base, getExplicitTypeParams(variable), fir::MutableProperties{}); - if (firBase.getType().isa()) { + if (base.getType().isa()) { if (!variable.isSimplyContiguous() || variable.isPolymorphic() || variable.isDerivedWithLengthParameters() || variable.isOptional()) { llvm::SmallVector nonDefaultLbounds = getNonDefaultLowerBounds(loc, builder, variable); - return fir::BoxValue(firBase, nonDefaultLbounds, + return fir::BoxValue(base, nonDefaultLbounds, getExplicitTypeParams(variable)); } // Otherwise, the variable can be represented in a fir::ExtendedValue // without the overhead of a fir.box. - firBase = genVariableRawAddress(loc, builder, variable); + base = genVariableRawAddress(loc, builder, variable); } if (variable.isScalar()) { if (variable.isCharacter()) { - if (firBase.getType().isa()) - return genUnboxChar(loc, builder, firBase); + if (base.getType().isa()) + return genUnboxChar(loc, builder, base); mlir::Value len = genCharacterVariableLength(loc, builder, variable); - return fir::CharBoxValue{firBase, len}; + return fir::CharBoxValue{base, len}; } - return firBase; + return base; } llvm::SmallVector extents; llvm::SmallVector nonDefaultLbounds; @@ -893,15 +895,16 @@ translateVariableToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder, } if (variable.isCharacter()) return fir::CharArrayBoxValue{ - firBase, genCharacterVariableLength(loc, builder, variable), extents, + base, genCharacterVariableLength(loc, builder, variable), extents, nonDefaultLbounds}; - return fir::ArrayBoxValue{firBase, extents, nonDefaultLbounds}; + return fir::ArrayBoxValue{base, extents, nonDefaultLbounds}; } fir::ExtendedValue hlfir::translateToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder, - fir::FortranVariableOpInterface var) { - return translateVariableToExtendedValue(loc, builder, var); + fir::FortranVariableOpInterface var, + bool forceHlfirBase) { + return translateVariableToExtendedValue(loc, builder, var, forceHlfirBase); } std::pair> @@ -1033,9 +1036,9 @@ hlfir::cloneToElementalOp(mlir::Location loc, fir::FirOpBuilder &builder, return hlfir::loadTrivialScalar(l, b, newAddr); }; mlir::Type elementType = scalarAddress.getFortranElementType(); - return hlfir::genElementalOp(loc, builder, elementType, - elementalAddrOp.getShape(), typeParams, - genKernel, !elementalAddrOp.isOrdered()); + return hlfir::genElementalOp( + loc, builder, elementType, elementalAddrOp.getShape(), typeParams, + genKernel, !elementalAddrOp.isOrdered(), elementalAddrOp.getMold()); } bool hlfir::elementalOpMustProduceTemp(hlfir::ElementalOp elemental) { diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index fb9b58ef69c6ae98952756b326188ab839ccc31b..ca5ab6fcea342a09eefd1d82854ecbd27448f20f 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -567,6 +567,10 @@ static constexpr IntrinsicHandler handlers[]{ {"dim", asAddr, handleDynamicOptional}, {"kind", asValue}}}, /*isElemental=*/false}, + {"sizeof", + &I::genSizeOf, + {{{"a", asBox}}}, + /*isElemental=*/false}, {"sleep", &I::genSleep, {{{"seconds", asValue}}}, /*isElemental=*/false}, {"spacing", &I::genSpacing}, {"spread", @@ -689,22 +693,22 @@ prettyPrintIntrinsicName(fir::FirOpBuilder &builder, mlir::Location loc, } // Generate a call to the Fortran runtime library providing -// support for 128-bit float math via a third-party library. -// If the compiler is built without FLANG_RUNTIME_F128_MATH_LIB, -// this function will report an error. +// support for 128-bit float math. +// On 'LDBL_MANT_DIG == 113' targets the implementation +// is provided by FortranRuntime, otherwise, it is done via +// FortranFloat128Math library. In the latter case the compiler +// has to be built with FLANG_RUNTIME_F128_MATH_LIB to guarantee +// proper linking actions in the driver. static mlir::Value genLibF128Call(fir::FirOpBuilder &builder, mlir::Location loc, const MathOperation &mathOp, mlir::FunctionType libFuncType, llvm::ArrayRef args) { -#ifndef FLANG_RUNTIME_F128_MATH_LIB - std::string message = prettyPrintIntrinsicName( - builder, loc, "compiler is built without support for '", mathOp.key, "'", - libFuncType); - fir::emitFatalError(loc, message, /*genCrashDiag=*/false); -#else // FLANG_RUNTIME_F128_MATH_LIB + // TODO: if we knew that the C 'long double' does not have 113-bit mantissa + // on the target, we could have asserted that FLANG_RUNTIME_F128_MATH_LIB + // must be specified. For now just always generate the call even + // if it will be unresolved. return genLibCall(builder, loc, mathOp, libFuncType, args); -#endif // FLANG_RUNTIME_F128_MATH_LIB } mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc, @@ -926,6 +930,14 @@ constexpr auto FuncTypeInteger8Real16 = genFuncType, Ty::Real<16>>; constexpr auto FuncTypeReal16Complex16 = genFuncType, Ty::Complex<16>>; +constexpr auto FuncTypeComplex16Complex16 = + genFuncType, Ty::Complex<16>>; +constexpr auto FuncTypeComplex16Complex16Complex16 = + genFuncType, Ty::Complex<16>, Ty::Complex<16>>; +constexpr auto FuncTypeComplex16Complex16Integer4 = + genFuncType, Ty::Complex<16>, Ty::Integer<4>>; +constexpr auto FuncTypeComplex16Complex16Integer8 = + genFuncType, Ty::Complex<16>, Ty::Integer<8>>; static constexpr MathOperation mathOperations[] = { {"abs", "fabsf", genFuncType, Ty::Real<4>>, @@ -944,6 +956,8 @@ static constexpr MathOperation mathOperations[] = { {"acos", RTNAME_STRING(AcosF128), FuncTypeReal16Real16, genLibF128Call}, {"acos", "cacosf", genFuncType, Ty::Complex<4>>, genLibCall}, {"acos", "cacos", genFuncType, Ty::Complex<8>>, genLibCall}, + {"acos", RTNAME_STRING(CAcosF128), FuncTypeComplex16Complex16, + genLibF128Call}, {"acosh", "acoshf", genFuncType, Ty::Real<4>>, genLibCall}, {"acosh", "acosh", genFuncType, Ty::Real<8>>, genLibCall}, {"acosh", RTNAME_STRING(AcoshF128), FuncTypeReal16Real16, genLibF128Call}, @@ -951,6 +965,8 @@ static constexpr MathOperation mathOperations[] = { genLibCall}, {"acosh", "cacosh", genFuncType, Ty::Complex<8>>, genLibCall}, + {"acosh", RTNAME_STRING(CAcoshF128), FuncTypeComplex16Complex16, + genLibF128Call}, // llvm.trunc behaves the same way as libm's trunc. {"aint", "llvm.trunc.f32", genFuncType, Ty::Real<4>>, genLibCall}, @@ -972,6 +988,8 @@ static constexpr MathOperation mathOperations[] = { {"asin", RTNAME_STRING(AsinF128), FuncTypeReal16Real16, genLibF128Call}, {"asin", "casinf", genFuncType, Ty::Complex<4>>, genLibCall}, {"asin", "casin", genFuncType, Ty::Complex<8>>, genLibCall}, + {"asin", RTNAME_STRING(CAsinF128), FuncTypeComplex16Complex16, + genLibF128Call}, {"asinh", "asinhf", genFuncType, Ty::Real<4>>, genLibCall}, {"asinh", "asinh", genFuncType, Ty::Real<8>>, genLibCall}, {"asinh", RTNAME_STRING(AsinhF128), FuncTypeReal16Real16, genLibF128Call}, @@ -979,6 +997,8 @@ static constexpr MathOperation mathOperations[] = { genLibCall}, {"asinh", "casinh", genFuncType, Ty::Complex<8>>, genLibCall}, + {"asinh", RTNAME_STRING(CAsinhF128), FuncTypeComplex16Complex16, + genLibF128Call}, {"atan", "atanf", genFuncType, Ty::Real<4>>, genMathOp}, {"atan", "atan", genFuncType, Ty::Real<8>>, @@ -986,6 +1006,8 @@ static constexpr MathOperation mathOperations[] = { {"atan", RTNAME_STRING(AtanF128), FuncTypeReal16Real16, genLibF128Call}, {"atan", "catanf", genFuncType, Ty::Complex<4>>, genLibCall}, {"atan", "catan", genFuncType, Ty::Complex<8>>, genLibCall}, + {"atan", RTNAME_STRING(CAtanF128), FuncTypeComplex16Complex16, + genLibF128Call}, {"atan2", "atan2f", genFuncType, Ty::Real<4>, Ty::Real<4>>, genMathOp}, {"atan2", "atan2", genFuncType, Ty::Real<8>, Ty::Real<8>>, @@ -999,6 +1021,8 @@ static constexpr MathOperation mathOperations[] = { genLibCall}, {"atanh", "catanh", genFuncType, Ty::Complex<8>>, genLibCall}, + {"atanh", RTNAME_STRING(CAtanhF128), FuncTypeComplex16Complex16, + genLibF128Call}, {"bessel_j0", "j0f", genFuncType, Ty::Real<4>>, genLibCall}, {"bessel_j0", "j0", genFuncType, Ty::Real<8>>, genLibCall}, {"bessel_j0", RTNAME_STRING(J0F128), FuncTypeReal16Real16, genLibF128Call}, @@ -1038,11 +1062,15 @@ static constexpr MathOperation mathOperations[] = { genComplexMathOp}, {"cos", "ccos", genFuncType, Ty::Complex<8>>, genComplexMathOp}, + {"cos", RTNAME_STRING(CCosF128), FuncTypeComplex16Complex16, + genLibF128Call}, {"cosh", "coshf", genFuncType, Ty::Real<4>>, genLibCall}, {"cosh", "cosh", genFuncType, Ty::Real<8>>, genLibCall}, {"cosh", RTNAME_STRING(CoshF128), FuncTypeReal16Real16, genLibF128Call}, {"cosh", "ccoshf", genFuncType, Ty::Complex<4>>, genLibCall}, {"cosh", "ccosh", genFuncType, Ty::Complex<8>>, genLibCall}, + {"cosh", RTNAME_STRING(CCoshF128), FuncTypeComplex16Complex16, + genLibF128Call}, {"divc", {}, genFuncType, Ty::Complex<2>, Ty::Complex<2>>, @@ -1080,6 +1108,8 @@ static constexpr MathOperation mathOperations[] = { genComplexMathOp}, {"exp", "cexp", genFuncType, Ty::Complex<8>>, genComplexMathOp}, + {"exp", RTNAME_STRING(CExpF128), FuncTypeComplex16Complex16, + genLibF128Call}, {"feclearexcept", "feclearexcept", genFuncType, Ty::Integer<4>>, genLibCall}, {"fedisableexcept", "fedisableexcept", @@ -1131,6 +1161,8 @@ static constexpr MathOperation mathOperations[] = { genComplexMathOp}, {"log", "clog", genFuncType, Ty::Complex<8>>, genComplexMathOp}, + {"log", RTNAME_STRING(CLogF128), FuncTypeComplex16Complex16, + genLibF128Call}, {"log10", "log10f", genFuncType, Ty::Real<4>>, genMathOp}, {"log10", "log10", genFuncType, Ty::Real<8>>, @@ -1178,6 +1210,8 @@ static constexpr MathOperation mathOperations[] = { genComplexMathOp}, {"pow", "cpow", genFuncType, Ty::Complex<8>, Ty::Complex<8>>, genComplexMathOp}, + {"pow", RTNAME_STRING(CPowF128), FuncTypeComplex16Complex16Complex16, + genLibF128Call}, {"pow", RTNAME_STRING(FPow4i), genFuncType, Ty::Real<4>, Ty::Integer<4>>, genMathOp}, @@ -1200,10 +1234,14 @@ static constexpr MathOperation mathOperations[] = { genFuncType, Ty::Complex<4>, Ty::Integer<4>>, genLibCall}, {"pow", RTNAME_STRING(zpowi), genFuncType, Ty::Complex<8>, Ty::Integer<4>>, genLibCall}, + {"pow", RTNAME_STRING(cqpowi), FuncTypeComplex16Complex16Integer4, + genLibF128Call}, {"pow", RTNAME_STRING(cpowk), genFuncType, Ty::Complex<4>, Ty::Integer<8>>, genLibCall}, {"pow", RTNAME_STRING(zpowk), genFuncType, Ty::Complex<8>, Ty::Integer<8>>, genLibCall}, + {"pow", RTNAME_STRING(cqpowk), FuncTypeComplex16Complex16Integer8, + genLibF128Call}, {"sign", "copysignf", genFuncType, Ty::Real<4>, Ty::Real<4>>, genMathOp}, {"sign", "copysign", genFuncType, Ty::Real<8>, Ty::Real<8>>, @@ -1222,11 +1260,15 @@ static constexpr MathOperation mathOperations[] = { genComplexMathOp}, {"sin", "csin", genFuncType, Ty::Complex<8>>, genComplexMathOp}, + {"sin", RTNAME_STRING(CSinF128), FuncTypeComplex16Complex16, + genLibF128Call}, {"sinh", "sinhf", genFuncType, Ty::Real<4>>, genLibCall}, {"sinh", "sinh", genFuncType, Ty::Real<8>>, genLibCall}, {"sinh", RTNAME_STRING(SinhF128), FuncTypeReal16Real16, genLibF128Call}, {"sinh", "csinhf", genFuncType, Ty::Complex<4>>, genLibCall}, {"sinh", "csinh", genFuncType, Ty::Complex<8>>, genLibCall}, + {"sinh", RTNAME_STRING(CSinhF128), FuncTypeComplex16Complex16, + genLibF128Call}, {"sqrt", "sqrtf", genFuncType, Ty::Real<4>>, genMathOp}, {"sqrt", "sqrt", genFuncType, Ty::Real<8>>, @@ -1236,6 +1278,8 @@ static constexpr MathOperation mathOperations[] = { genComplexMathOp}, {"sqrt", "csqrt", genFuncType, Ty::Complex<8>>, genComplexMathOp}, + {"sqrt", RTNAME_STRING(CSqrtF128), FuncTypeComplex16Complex16, + genLibF128Call}, {"tan", "tanf", genFuncType, Ty::Real<4>>, genMathOp}, {"tan", "tan", genFuncType, Ty::Real<8>>, @@ -1245,6 +1289,8 @@ static constexpr MathOperation mathOperations[] = { genComplexMathOp}, {"tan", "ctan", genFuncType, Ty::Complex<8>>, genComplexMathOp}, + {"tan", RTNAME_STRING(CTanF128), FuncTypeComplex16Complex16, + genLibF128Call}, {"tanh", "tanhf", genFuncType, Ty::Real<4>>, genMathOp}, {"tanh", "tanh", genFuncType, Ty::Real<8>>, @@ -1254,6 +1300,8 @@ static constexpr MathOperation mathOperations[] = { genComplexMathOp}, {"tanh", "ctanh", genFuncType, Ty::Complex<8>>, genComplexMathOp}, + {"tanh", RTNAME_STRING(CTanhF128), FuncTypeComplex16Complex16, + genLibF128Call}, }; // This helper class computes a "distance" between two function types. @@ -5902,6 +5950,20 @@ IntrinsicLibrary::genSize(mlir::Type resultType, .getResults()[0]; } +// SIZEOF +fir::ExtendedValue +IntrinsicLibrary::genSizeOf(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 1); + mlir::Value box = fir::getBase(args[0]); + mlir::Value eleSize = builder.create(loc, resultType, box); + if (!fir::isArray(args[0])) + return eleSize; + mlir::Value arraySize = builder.createConvert( + loc, resultType, fir::runtime::genSize(builder, loc, box)); + return builder.create(loc, eleSize, arraySize); +} + // TAND mlir::Value IntrinsicLibrary::genTand(mlir::Type resultType, llvm::ArrayRef args) { diff --git a/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp b/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp index 846a78931acba73c9fdaa3102aa07b56aee9ed5e..746c275f37eaca2dfd52c2bdbeebd313792052f3 100644 --- a/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp +++ b/flang/lib/Optimizer/CodeGen/BoxedProcedure.cpp @@ -209,6 +209,7 @@ public: BoxprocTypeRewriter typeConverter(mlir::UnknownLoc::get(context)); mlir::Dialect *firDialect = context->getLoadedDialect("fir"); getModule().walk([&](mlir::Operation *op) { + bool opIsValid = true; typeConverter.setLocation(op->getLoc()); if (auto addr = mlir::dyn_cast(op)) { mlir::Type ty = addr.getVal().getType(); @@ -220,6 +221,7 @@ public: rewriter.setInsertionPoint(addr); rewriter.replaceOpWithNewOp( addr, typeConverter.convertType(addr.getType()), addr.getVal()); + opIsValid = false; } else if (typeConverter.needsConversion(resTy)) { rewriter.startOpModification(op); op->getResult(0).setType(typeConverter.convertType(resTy)); @@ -271,10 +273,12 @@ public: llvm::ArrayRef{tramp}); rewriter.replaceOpWithNewOp(embox, toTy, adjustCall.getResult(0)); + opIsValid = false; } else { // Just forward the function as a pointer. rewriter.replaceOpWithNewOp(embox, toTy, embox.getFunc()); + opIsValid = false; } } else if (auto global = mlir::dyn_cast(op)) { auto ty = global.getType(); @@ -297,6 +301,7 @@ public: rewriter.replaceOpWithNewOp( mem, toTy, uniqName, bindcName, isPinned, mem.getTypeparams(), mem.getShape()); + opIsValid = false; } } else if (auto mem = mlir::dyn_cast(op)) { auto ty = mem.getType(); @@ -310,6 +315,7 @@ public: rewriter.replaceOpWithNewOp( mem, toTy, uniqName, bindcName, mem.getTypeparams(), mem.getShape()); + opIsValid = false; } } else if (auto coor = mlir::dyn_cast(op)) { auto ty = coor.getType(); @@ -321,6 +327,7 @@ public: auto toBaseTy = typeConverter.convertType(baseTy); rewriter.replaceOpWithNewOp(coor, toTy, coor.getRef(), coor.getCoor(), toBaseTy); + opIsValid = false; } } else if (auto index = mlir::dyn_cast(op)) { auto ty = index.getType(); @@ -332,6 +339,7 @@ public: auto toOnTy = typeConverter.convertType(onTy); rewriter.replaceOpWithNewOp( index, toTy, index.getFieldId(), toOnTy, index.getTypeparams()); + opIsValid = false; } } else if (auto index = mlir::dyn_cast(op)) { auto ty = index.getType(); @@ -342,7 +350,8 @@ public: auto toTy = typeConverter.convertType(ty); auto toOnTy = typeConverter.convertType(onTy); rewriter.replaceOpWithNewOp( - mem, toTy, index.getFieldId(), toOnTy, index.getTypeparams()); + index, toTy, index.getFieldId(), toOnTy, index.getTypeparams()); + opIsValid = false; } } else if (op->getDialect() == firDialect) { rewriter.startOpModification(op); @@ -354,7 +363,7 @@ public: rewriter.finalizeOpModification(op); } // Ensure block arguments are updated if needed. - if (op->getNumRegions() != 0) { + if (opIsValid && op->getNumRegions() != 0) { rewriter.startOpModification(op); for (mlir::Region ®ion : op->getRegions()) for (mlir::Block &block : region.getBlocks()) diff --git a/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp b/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp index 8e7f59f76383c96fd4765f83e7711c97c740bb3c..b1b0e9b766a62563802f294548d91bfefa97ac03 100644 --- a/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp +++ b/flang/lib/Optimizer/CodeGen/TBAABuilder.cpp @@ -102,7 +102,8 @@ void TBAABuilder::attachTBAATag(AliasAnalysisOpInterface op, Type baseFIRType, return; mlir::LLVM::LLVMFuncOp func = op->getParentOfType(); - assert(func && "func.func should have already been converted to llvm.func"); + if (!func) + return; ++tagAttachmentCounter; if (tagAttachmentLimit != kTagAttachmentUnlimited && diff --git a/flang/lib/Optimizer/CodeGen/Target.cpp b/flang/lib/Optimizer/CodeGen/Target.cpp index 7c77bdd79008f1f7c07d0b2ad6c89c27021683a6..cea7a1f97f419ff17f420d4f296f1c40f2106685 100644 --- a/flang/lib/Optimizer/CodeGen/Target.cpp +++ b/flang/lib/Optimizer/CodeGen/Target.cpp @@ -737,7 +737,8 @@ struct TargetAArch64 : public GenericTarget { CodeGenSpecifics::Marshalling marshal; const auto *sem = &floatToSemantics(kindMap, eleTy); if (sem == &llvm::APFloat::IEEEsingle() || - sem == &llvm::APFloat::IEEEdouble()) { + sem == &llvm::APFloat::IEEEdouble() || + sem == &llvm::APFloat::IEEEquad()) { // [2 x t] array of 2 eleTy marshal.emplace_back(fir::SequenceType::get({2}, eleTy), AT{}); } else { @@ -751,7 +752,8 @@ struct TargetAArch64 : public GenericTarget { CodeGenSpecifics::Marshalling marshal; const auto *sem = &floatToSemantics(kindMap, eleTy); if (sem == &llvm::APFloat::IEEEsingle() || - sem == &llvm::APFloat::IEEEdouble()) { + sem == &llvm::APFloat::IEEEdouble() || + sem == &llvm::APFloat::IEEEquad()) { // Use a type that will be translated into LLVM as: // { t, t } struct of 2 eleTy marshal.emplace_back(mlir::TupleType::get(eleTy.getContext(), diff --git a/flang/lib/Optimizer/Dialect/FIRDialect.cpp b/flang/lib/Optimizer/Dialect/FIRDialect.cpp index 850b6120b2a00e2305f6e92adc6447bac2c77420..4d1e8cd1405afef32b22af53383e14c0f438dda9 100644 --- a/flang/lib/Optimizer/Dialect/FIRDialect.cpp +++ b/flang/lib/Optimizer/Dialect/FIRDialect.cpp @@ -18,6 +18,8 @@ #include "mlir/Target/LLVMIR/ModuleTranslation.h" #include "mlir/Transforms/InliningUtils.h" +#include "flang/Optimizer/Dialect/FIRDialect.cpp.inc" + using namespace fir; namespace { @@ -58,9 +60,7 @@ struct FIRInlinerInterface : public mlir::DialectInlinerInterface { }; } // namespace -fir::FIROpsDialect::FIROpsDialect(mlir::MLIRContext *ctx) - : mlir::Dialect("fir", ctx, mlir::TypeID::get()) { - getContext()->loadDialect(); +void fir::FIROpsDialect::initialize() { registerTypes(); registerAttributes(); addOperations< @@ -94,11 +94,6 @@ void fir::addFIRToLLVMIRExtension(mlir::DialectRegistry ®istry) { }); } -// anchor the class vtable to this compilation unit -fir::FIROpsDialect::~FIROpsDialect() { - // do nothing -} - mlir::Type fir::FIROpsDialect::parseType(mlir::DialectAsmParser &parser) const { return parseFirType(const_cast(this), parser); } diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp index 8bc92a991a69cff6c6f8584dff859e7ea8756f1e..8bad4e445082d20e61ad63ad81acf524ecaf2620 100644 --- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp +++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "flang/Optimizer/HLFIR/HLFIROps.h" + #include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Optimizer/Dialect/FIRType.h" #include "flang/Optimizer/Dialect/Support/FIRContext.h" @@ -1152,7 +1153,9 @@ hlfir::MatmulOp::canonicalize(MatmulOp matmulOp, // but we do need to get rid of the hlfir.destroy for the hlfir.transpose // result (which is entirely removed) - for (mlir::Operation *user : transposeOp->getResult(0).getUsers()) + llvm::SmallVector users( + transposeOp->getResult(0).getUsers()); + for (mlir::Operation *user : users) if (auto destroyOp = mlir::dyn_cast_or_null(user)) rewriter.eraseOp(destroyOp); rewriter.eraseOp(transposeOp); @@ -1403,33 +1406,45 @@ void hlfir::AsExprOp::getEffects( // ElementalOp //===----------------------------------------------------------------------===// -void hlfir::ElementalOp::build(mlir::OpBuilder &builder, - mlir::OperationState &odsState, - mlir::Type resultType, mlir::Value shape, - mlir::Value mold, mlir::ValueRange typeparams, - bool isUnordered) { +/// Common builder for ElementalOp and ElementalAddrOp to add the arguments and +/// create the elemental body. Result and clean-up body must be handled in +/// specific builders. +template +static void buildElemental(mlir::OpBuilder &builder, + mlir::OperationState &odsState, mlir::Value shape, + mlir::Value mold, mlir::ValueRange typeparams, + bool isUnordered) { odsState.addOperands(shape); if (mold) odsState.addOperands(mold); odsState.addOperands(typeparams); - odsState.addTypes(resultType); odsState.addAttribute( - getOperandSegmentSizesAttrName(odsState.name), + Op::getOperandSegmentSizesAttrName(odsState.name), builder.getDenseI32ArrayAttr({/*shape=*/1, (mold ? 1 : 0), static_cast(typeparams.size())})); if (isUnordered) - odsState.addAttribute(getUnorderedAttrName(odsState.name), + odsState.addAttribute(Op::getUnorderedAttrName(odsState.name), isUnordered ? builder.getUnitAttr() : nullptr); mlir::Region *bodyRegion = odsState.addRegion(); bodyRegion->push_back(new mlir::Block{}); - if (auto exprType = resultType.dyn_cast()) { - unsigned dim = exprType.getRank(); + if (auto shapeType = shape.getType().dyn_cast()) { + unsigned dim = shapeType.getRank(); mlir::Type indexType = builder.getIndexType(); for (unsigned d = 0; d < dim; ++d) bodyRegion->front().addArgument(indexType, odsState.location); } } +void hlfir::ElementalOp::build(mlir::OpBuilder &builder, + mlir::OperationState &odsState, + mlir::Type resultType, mlir::Value shape, + mlir::Value mold, mlir::ValueRange typeparams, + bool isUnordered) { + odsState.addTypes(resultType); + buildElemental(builder, odsState, shape, mold, typeparams, + isUnordered); +} + mlir::Value hlfir::ElementalOp::getElementEntity() { return mlir::cast(getBody()->back()).getElementValue(); } @@ -1678,19 +1693,11 @@ static void printYieldOpCleanup(mlir::OpAsmPrinter &p, YieldOp yieldOp, void hlfir::ElementalAddrOp::build(mlir::OpBuilder &builder, mlir::OperationState &odsState, - mlir::Value shape, bool isUnordered) { - odsState.addOperands(shape); - if (isUnordered) - odsState.addAttribute(getUnorderedAttrName(odsState.name), - isUnordered ? builder.getUnitAttr() : nullptr); - mlir::Region *bodyRegion = odsState.addRegion(); - bodyRegion->push_back(new mlir::Block{}); - if (auto shapeType = shape.getType().dyn_cast()) { - unsigned dim = shapeType.getRank(); - mlir::Type indexType = builder.getIndexType(); - for (unsigned d = 0; d < dim; ++d) - bodyRegion->front().addArgument(indexType, odsState.location); - } + mlir::Value shape, mlir::Value mold, + mlir::ValueRange typeparams, + bool isUnordered) { + buildElemental(builder, odsState, shape, mold, + typeparams, isUnordered); // Push cleanUp region. odsState.addRegion(); } @@ -1864,7 +1871,8 @@ hlfir::ForallIndexOp::canonicalize(hlfir::ForallIndexOp indexOp, return mlir::failure(); auto insertPt = rewriter.saveInsertionPoint(); - for (mlir::Operation *user : indexOp->getResult(0).getUsers()) + llvm::SmallVector users(indexOp->getResult(0).getUsers()); + for (mlir::Operation *user : users) if (auto loadOp = mlir::dyn_cast(user)) { rewriter.setInsertionPoint(loadOp); rewriter.replaceOpWithNewOp( diff --git a/flang/lib/Optimizer/Transforms/OMPFunctionFiltering.cpp b/flang/lib/Optimizer/Transforms/OMPFunctionFiltering.cpp index 466bf53e8dbd60529910c52a887b1592b5ca90b8..959099d039a5e60f4fbc76b160862355bc7449f0 100644 --- a/flang/lib/Optimizer/Transforms/OMPFunctionFiltering.cpp +++ b/flang/lib/Optimizer/Transforms/OMPFunctionFiltering.cpp @@ -79,12 +79,15 @@ public: // Remove the callOp callOp->erase(); } - if (!hasTargetRegion) + if (!hasTargetRegion) { funcOp.erase(); - else if (declareTargetOp) + return WalkResult::skip(); + } + if (declareTargetOp) declareTargetOp.setDeclareTarget(declareType, omp::DeclareTargetCaptureClause::to); } + return WalkResult::advance(); }); } }; diff --git a/flang/lib/Parser/token-sequence.cpp b/flang/lib/Parser/token-sequence.cpp index c5a630c471d16eafbef6a2af6a417a8cce7402e9..799d13a423660cabbc2ed251afe698e0924f2776 100644 --- a/flang/lib/Parser/token-sequence.cpp +++ b/flang/lib/Parser/token-sequence.cpp @@ -136,7 +136,10 @@ void TokenSequence::Put( } void TokenSequence::Put(const CharBlock &t, Provenance provenance) { - Put(&t[0], t.size(), provenance); + // Avoid t[0] if t is empty: it would create a reference to nullptr, + // which is UB. + const char *addr{t.size() ? &t[0] : nullptr}; + Put(addr, t.size(), provenance); } void TokenSequence::Put(const std::string &s, Provenance provenance) { diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index 719bea34406aa099d10ce8c51f0d28654bcd8df6..431cef207935085e79b73705c9ae696e49da190f 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -1195,9 +1195,7 @@ void CheckHelper::CheckArraySpec( void CheckHelper::CheckProcEntity( const Symbol &symbol, const ProcEntityDetails &details) { CheckSymbolType(symbol); - const Symbol *interface { - details.procInterface() ? &details.procInterface()->GetUltimate() : nullptr - }; + const Symbol *interface{details.procInterface()}; if (details.isDummy()) { if (!symbol.attrs().test(Attr::POINTER) && // C843 (symbol.attrs().test(Attr::INTENT_IN) || @@ -3236,6 +3234,8 @@ void CheckHelper::CheckSymbolType(const Symbol &symbol) { const Symbol *result{FindFunctionResult(symbol)}; const Symbol &relevant{result ? *result : symbol}; if (IsAllocatable(relevant)) { // always ok + } else if (IsProcedurePointer(symbol) && result && IsPointer(*result)) { + // procedure pointer returning allocatable or pointer: ok } else if (IsPointer(relevant) && !IsProcedure(relevant)) { // object pointers are always ok } else if (auto dyType{evaluate::DynamicType::From(relevant)}) { diff --git a/flang/lib/Semantics/check-select-type.cpp b/flang/lib/Semantics/check-select-type.cpp index 6515cf25e0d7df9a460703e2f8872a6f073f3d92..94d16a719277af63b98fe518758e4f53e55b3467 100644 --- a/flang/lib/Semantics/check-select-type.cpp +++ b/flang/lib/Semantics/check-select-type.cpp @@ -120,31 +120,25 @@ private: bool PassesDerivedTypeChecks(const semantics::DerivedTypeSpec &derived, parser::CharBlock sourceLoc) const { for (const auto &pair : derived.parameters()) { - if (pair.second.isLen() && !pair.second.isAssumed()) { // C1160 + if (pair.second.isLen() && !pair.second.isAssumed()) { // F'2023 C1165 context_.Say(sourceLoc, - "The type specification statement must have " - "LEN type parameter as assumed"_err_en_US); + "The type specification statement must have LEN type parameter as assumed"_err_en_US); return false; } } - if (!IsExtensibleType(&derived)) { // C1161 + if (!IsExtensibleType(&derived)) { // F'2023 C1166 context_.Say(sourceLoc, - "The type specification statement must not specify " - "a type with a SEQUENCE attribute or a BIND attribute"_err_en_US); + "The type specification statement must not specify a type with a SEQUENCE attribute or a BIND attribute"_err_en_US); return false; } - if (!selectorType_.IsUnlimitedPolymorphic()) { // C1162 - if (const semantics::Scope * guardScope{derived.typeSymbol().scope()}) { - if (const auto *selDerivedTypeSpec{ - evaluate::GetDerivedTypeSpec(selectorType_)}) { - if (!derived.Match(*selDerivedTypeSpec) && - !guardScope->FindComponent(selDerivedTypeSpec->name())) { - context_.Say(sourceLoc, - "Type specification '%s' must be an extension" - " of TYPE '%s'"_err_en_US, - derived.AsFortran(), selDerivedTypeSpec->AsFortran()); - return false; - } + if (!selectorType_.IsUnlimitedPolymorphic()) { // F'2023 C1167 + if (const auto *selDerivedTypeSpec{ + evaluate::GetDerivedTypeSpec(selectorType_)}) { + if (!derived.MatchesOrExtends(*selDerivedTypeSpec)) { + context_.Say(sourceLoc, + "Type specification '%s' must be an extension of TYPE '%s'"_err_en_US, + derived.AsFortran(), selDerivedTypeSpec->AsFortran()); + return false; } } } diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index 37fe0240537b8ee2df77f0f24a93955998a93008..b4df7216a33e207024f3a35849f65be438c22314 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -924,8 +924,8 @@ void ModFileWriter::PutProcEntity(llvm::raw_ostream &os, const Symbol &symbol) { os, symbol, [&]() { os << "procedure("; - if (details.procInterface()) { - os << details.procInterface()->name(); + if (details.rawProcInterface()) { + os << details.rawProcInterface()->name(); } else if (details.type()) { PutType(os, *details.type()); } @@ -1622,8 +1622,8 @@ void SubprogramSymbolCollector::DoSymbol( } }, [this](const ProcEntityDetails &details) { - if (details.procInterface()) { - DoSymbol(*details.procInterface()); + if (details.rawProcInterface()) { + DoSymbol(*details.rawProcInterface()); } else { DoType(details.type()); } diff --git a/flang/lib/Semantics/resolve-names-utils.cpp b/flang/lib/Semantics/resolve-names-utils.cpp index b901080e2860c43001ebc98028066529b71fedf8..801473876e7e2be496216925a903afa09fde2ba4 100644 --- a/flang/lib/Semantics/resolve-names-utils.cpp +++ b/flang/lib/Semantics/resolve-names-utils.cpp @@ -845,8 +845,9 @@ void SymbolMapper::MapSymbolExprs(Symbol &symbol) { }, [&](ProcEntityDetails &proc) { if (const Symbol * - mappedSymbol{MapInterface(proc.procInterface())}) { - proc.set_procInterface(*mappedSymbol); + mappedSymbol{MapInterface(proc.rawProcInterface())}) { + proc.set_procInterfaces( + *mappedSymbol, BypassGeneric(mappedSymbol->GetUltimate())); } else if (const DeclTypeSpec * mappedType{MapType(proc.type())}) { proc.set_type(*mappedType); } diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 5a95d3a98992a75be13dde881f549a67585acce0..67392a02cf1862e0c225d1b69cb4890653ed63e6 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -4983,7 +4983,8 @@ Symbol &DeclarationVisitor::DeclareProcEntity( "The interface for procedure '%s' has already been declared"_err_en_US); context().SetError(symbol); } else if (interface) { - details->set_procInterface(*interface); + details->set_procInterfaces( + *interface, BypassGeneric(interface->GetUltimate())); if (interface->test(Symbol::Flag::Function)) { symbol.set(Symbol::Flag::Function); } else if (interface->test(Symbol::Flag::Subroutine)) { @@ -5658,10 +5659,10 @@ void DeclarationVisitor::Post(const parser::ProcInterface &x) { } void DeclarationVisitor::Post(const parser::ProcDecl &x) { const auto &name{std::get(x.t)}; - const Symbol *procInterface{nullptr}; - if (interfaceName_ && interfaceName_->symbol) { - procInterface = &BypassGeneric(*interfaceName_->symbol); - } + // Don't use BypassGeneric or GetUltimate on this symbol, they can + // lead to unusable names in module files. + const Symbol *procInterface{ + interfaceName_ ? interfaceName_->symbol : nullptr}; auto attrs{HandleSaveName(name.source, GetAttrs())}; DerivedTypeDetails *dtDetails{nullptr}; if (Symbol * symbol{currScope().symbol()}) { @@ -6624,10 +6625,9 @@ void DeclarationVisitor::CheckExplicitInterface(const parser::Name &name) { if (const Symbol * symbol{name.symbol}) { const Symbol &ultimate{symbol->GetUltimate()}; if (!context().HasError(*symbol) && !context().HasError(ultimate) && - !ultimate.HasExplicitInterface()) { + !BypassGeneric(ultimate).HasExplicitInterface()) { Say(name, - "'%s' must be an abstract interface or a procedure with " - "an explicit interface"_err_en_US, + "'%s' must be an abstract interface or a procedure with an explicit interface"_err_en_US, symbol->name()); } } @@ -8447,7 +8447,6 @@ void ResolveNamesVisitor::FinishSpecificationPart( misparsedStmtFuncFound_ = false; funcResultStack().CompleteFunctionResultType(); CheckImports(); - bool inModule{currScope().kind() == Scope::Kind::Module}; for (auto &pair : currScope()) { auto &symbol{*pair.second}; if (NeedsExplicitType(symbol)) { @@ -8462,13 +8461,6 @@ void ResolveNamesVisitor::FinishSpecificationPart( if (symbol.has()) { CheckGenericProcedures(symbol); } - if (inModule && symbol.attrs().test(Attr::EXTERNAL) && - !symbol.test(Symbol::Flag::Function) && - !symbol.test(Symbol::Flag::Subroutine)) { - // in a module, external proc without return type is subroutine - symbol.set( - symbol.GetType() ? Symbol::Flag::Function : Symbol::Flag::Subroutine); - } if (!symbol.has()) { CheckPossibleBadForwardRef(symbol); } @@ -8990,8 +8982,18 @@ void ResolveNamesVisitor::ResolveSpecificationParts(ProgramTree &node) { } EndScopeForNode(node); // Ensure that every object entity has a type. + bool inModule{node.GetKind() == ProgramTree::Kind::Module || + node.GetKind() == ProgramTree::Kind::Submodule}; for (auto &pair : *node.scope()) { - ApplyImplicitRules(*pair.second); + Symbol &symbol{*pair.second}; + if (inModule && symbol.attrs().test(Attr::EXTERNAL) && + !symbol.test(Symbol::Flag::Function) && + !symbol.test(Symbol::Flag::Subroutine)) { + // in a module, external proc without return type is subroutine + symbol.set( + symbol.GetType() ? Symbol::Flag::Function : Symbol::Flag::Subroutine); + } + ApplyImplicitRules(symbol); } } diff --git a/flang/lib/Semantics/rewrite-directives.cpp b/flang/lib/Semantics/rewrite-directives.cpp index bab91d25308225b7da9598437c501cd419cd6507..2c3c87f2546a35621f00bfdae2874846bda74df0 100644 --- a/flang/lib/Semantics/rewrite-directives.cpp +++ b/flang/lib/Semantics/rewrite-directives.cpp @@ -11,7 +11,7 @@ #include "flang/Parser/parse-tree.h" #include "flang/Semantics/semantics.h" #include "flang/Semantics/symbol.h" -#include "llvm/Frontend/OpenMP/OMP.h.inc" +#include "llvm/Frontend/OpenMP/OMP.h" #include namespace Fortran::semantics { diff --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp index 2ab3189cf4064e3b97c4f91e30cca8baf73961c3..381905b89fb2dd2aeffa67092fd7d994b26484d8 100644 --- a/flang/lib/Semantics/symbol.cpp +++ b/flang/lib/Semantics/symbol.cpp @@ -452,6 +452,9 @@ llvm::raw_ostream &operator<<( llvm::raw_ostream &operator<<( llvm::raw_ostream &os, const ProcEntityDetails &x) { if (x.procInterface_) { + if (x.rawProcInterface_ != x.procInterface_) { + os << ' ' << x.rawProcInterface_->name() << " ->"; + } os << ' ' << x.procInterface_->name(); } else { DumpType(os, x.type()); diff --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp index f931ae07072010c90c4b3a99fd578cc7a38ea58f..bf999b090419c631ad2247445913e8970789edc4 100644 --- a/flang/lib/Semantics/tools.cpp +++ b/flang/lib/Semantics/tools.cpp @@ -465,9 +465,7 @@ const Symbol *FindInterface(const Symbol &symbol) { return common::visit( common::visitors{ [](const ProcEntityDetails &details) { - const Symbol *interface { - details.procInterface() - }; + const Symbol *interface{details.procInterface()}; return interface ? FindInterface(*interface) : nullptr; }, [](const ProcBindingDetails &details) { diff --git a/flang/lib/Semantics/type.cpp b/flang/lib/Semantics/type.cpp index e812283fc6f1902929656c2d4c4ebd13e827b418..44e49673300bfd2bf8bb5c390648d07bdc1b88bb 100644 --- a/flang/lib/Semantics/type.cpp +++ b/flang/lib/Semantics/type.cpp @@ -231,27 +231,36 @@ ParamValue *DerivedTypeSpec::FindParameter(SourceName target) { const_cast(this)->FindParameter(target)); } -bool DerivedTypeSpec::Match(const DerivedTypeSpec &that) const { - if (&typeSymbol_ != &that.typeSymbol_) { - return false; - } - for (const auto &pair : parameters_) { - const Symbol *tpSym{scope_ ? scope_->FindSymbol(pair.first) : nullptr}; - const auto *tpDetails{ - tpSym ? tpSym->detailsIf() : nullptr}; - if (!tpDetails) { - return false; - } - if (tpDetails->attr() != common::TypeParamAttr::Kind) { - continue; +static bool MatchKindParams(const Symbol &typeSymbol, + const DerivedTypeSpec &thisSpec, const DerivedTypeSpec &thatSpec) { + for (auto ref : typeSymbol.get().paramDecls()) { + if (ref->get().attr() == common::TypeParamAttr::Kind) { + const auto *thisValue{thisSpec.FindParameter(ref->name())}; + const auto *thatValue{thatSpec.FindParameter(ref->name())}; + if (!thisValue || !thatValue || *thisValue != *thatValue) { + return false; + } } - const ParamValue &value{pair.second}; - auto iter{that.parameters_.find(pair.first)}; - if (iter == that.parameters_.end() || iter->second != value) { + } + if (const DerivedTypeSpec * + parent{typeSymbol.GetParentTypeSpec(typeSymbol.scope())}) { + return MatchKindParams(parent->typeSymbol(), thisSpec, thatSpec); + } else { + return true; + } +} + +bool DerivedTypeSpec::MatchesOrExtends(const DerivedTypeSpec &that) const { + const Symbol *typeSymbol{&typeSymbol_}; + while (typeSymbol != &that.typeSymbol_) { + if (const DerivedTypeSpec * + parent{typeSymbol->GetParentTypeSpec(typeSymbol->scope())}) { + typeSymbol = &parent->typeSymbol_; + } else { return false; } } - return true; + return MatchKindParams(*typeSymbol, *this, that); } class InstantiateHelper { diff --git a/flang/runtime/CMakeLists.txt b/flang/runtime/CMakeLists.txt index ac89184a7cbffc111553c0450737cfdd5e2c3fdf..7dd60b5edcd5fbc09dec4713626affd5e01e9ccd 100644 --- a/flang/runtime/CMakeLists.txt +++ b/flang/runtime/CMakeLists.txt @@ -57,12 +57,6 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) REAL(16) is mapped to __float128, or libm for targets where REAL(16) \ is mapped to long double, etc." ) - - if (NOT FLANG_RUNTIME_F128_MATH_LIB STREQUAL "") - add_compile_definitions( - -DFLANG_RUNTIME_F128_MATH_LIB="${FLANG_RUNTIME_F128_MATH_LIB}" - ) - endif() endif() include(CheckCXXSymbolExists) @@ -78,6 +72,16 @@ check_cxx_source_compiles( " HAVE_DECL_STRERROR_S) +# Check if 128-bit float computations can be done via long double. +check_cxx_source_compiles( + "#include + #if LDBL_MANT_DIG != 113 + #error LDBL_MANT_DIG != 113 + #endif + int main() { return 0; } + " + HAVE_LDBL_MANT_DIG_113) + check_cxx_compiler_flag(-fno-lto FLANG_RUNTIME_HAS_FNO_LTO_FLAG) if (FLANG_RUNTIME_HAS_FNO_LTO_FLAG) set(NO_LTO_FLAGS "-fno-lto") @@ -100,9 +104,7 @@ add_definitions(-U_GLIBCXX_ASSERTIONS) add_definitions(-U_LIBCPP_ENABLE_ASSERTIONS) add_subdirectory(FortranMain) -if (NOT ${FLANG_RUNTIME_F128_MATH_LIB} STREQUAL "") - add_subdirectory(Float128Math) -endif() +add_subdirectory(Float128Math) set(sources ISO_Fortran_binding.cpp @@ -319,6 +321,29 @@ if (NOT FLANG_EXPERIMENTAL_OMP_OFFLOAD_BUILD STREQUAL "off") endif() endif() +if (NOT TARGET FortranFloat128Math) + # If FortranFloat128Math is not defined, then we are not building + # standalone FortranFloat128Math library. Instead, include + # the relevant sources into FortranRuntime itself. + # The information is provided via FortranFloat128MathILib + # interface library. + get_target_property(f128_sources + FortranFloat128MathILib INTERFACE_SOURCES + ) + if (f128_sources) + # The interface may define special macros for Float128Math files, + # so we need to propagate them. + get_target_property(f128_defs + FortranFloat128MathILib INTERFACE_COMPILE_DEFINITIONS + ) + set_property(SOURCE ${f128_sources} + APPEND PROPERTY COMPILE_DEFINITIONS + ${f128_defs} + ) + list(APPEND sources ${f128_sources}) + endif() +endif() + if (NOT DEFINED MSVC) add_flang_library(FortranRuntime ${sources} diff --git a/flang/runtime/Float128Math/CMakeLists.txt b/flang/runtime/Float128Math/CMakeLists.txt index 60d44c78be0fafa53256f4d0ea2ce56e790b6f89..980356131b680e9f391a977ba6149347f863c4c2 100644 --- a/flang/runtime/Float128Math/CMakeLists.txt +++ b/flang/runtime/Float128Math/CMakeLists.txt @@ -16,34 +16,6 @@ include(CheckLibraryExists) -if (${FLANG_RUNTIME_F128_MATH_LIB} STREQUAL "libquadmath") - check_include_file(quadmath.h FOUND_QUADMATH_HEADER) - if(FOUND_QUADMATH_HEADER) - add_compile_definitions(HAS_QUADMATHLIB) - else() - message(FATAL_ERROR - "FLANG_RUNTIME_F128_MATH_LIB setting requires quadmath.h " - "to be available: ${FLANG_RUNTIME_F128_MATH_LIB}" - ) - endif() -elseif (${FLANG_RUNTIME_F128_MATH_LIB} STREQUAL "libm") - check_library_exists(m sinl "" FOUND_LIBM) - check_library_exists(m sinf128 "" FOUND_LIBMF128) - if (FOUND_LIBM) - add_compile_definitions(HAS_LIBM) - endif() - if (FOUND_LIBMF128) - add_compile_definitions(HAS_LIBMF128) - endif() -endif() - -if (NOT FOUND_QUADMATH_HEADER AND NOT FOUND_LIBM) - message(FATAL_ERROR - "Unsupported third-party library for Fortran F128 math runtime: " - "${FLANG_RUNTIME_F128_MATH_LIB}" - ) -endif() - set(sources acos.cpp acosh.cpp @@ -52,8 +24,8 @@ set(sources atan.cpp atan2.cpp atanh.cpp - cabs.cpp ceil.cpp + complex-math.c cos.cpp cosh.cpp erf.cpp @@ -94,18 +66,61 @@ set(sources ) include_directories(AFTER "${CMAKE_CURRENT_SOURCE_DIR}/..") -add_flang_library(FortranFloat128Math STATIC INSTALL_WITH_TOOLCHAIN ${sources}) +add_library(FortranFloat128MathILib INTERFACE) -if (DEFINED MSVC) - set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded) - add_flang_library(FortranFloat128Math.static STATIC INSTALL_WITH_TOOLCHAIN - ${sources} - ) - set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebug) - add_flang_library(FortranFloat128Math.static_dbg STATIC INSTALL_WITH_TOOLCHAIN - ${sources} - ) - add_dependencies(FortranFloat128Math FortranFloat128Math.static - FortranFloat128Math.static_dbg - ) +if (FLANG_RUNTIME_F128_MATH_LIB) + if (${FLANG_RUNTIME_F128_MATH_LIB} STREQUAL "libquadmath") + check_include_file(quadmath.h FOUND_QUADMATH_HEADER) + if(FOUND_QUADMATH_HEADER) + add_compile_definitions(HAS_QUADMATHLIB) + else() + message(FATAL_ERROR + "FLANG_RUNTIME_F128_MATH_LIB setting requires quadmath.h " + "to be available: ${FLANG_RUNTIME_F128_MATH_LIB}" + ) + endif() + else() + message(FATAL_ERROR + "Unsupported third-party library for Fortran F128 math runtime: " + "${FLANG_RUNTIME_F128_MATH_LIB}" + ) + endif() + + add_flang_library(FortranFloat128Math STATIC INSTALL_WITH_TOOLCHAIN + ${sources}) + + if (DEFINED MSVC) + set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded) + add_flang_library(FortranFloat128Math.static STATIC INSTALL_WITH_TOOLCHAIN + ${sources} + ) + set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebug) + add_flang_library(FortranFloat128Math.static_dbg STATIC INSTALL_WITH_TOOLCHAIN + ${sources} + ) + add_dependencies(FortranFloat128Math FortranFloat128Math.static + FortranFloat128Math.static_dbg + ) + endif() +elseif (HAVE_LDBL_MANT_DIG_113) + # We can use 'long double' versions from libc. + check_library_exists(m sinl "" FOUND_LIBM) + if (FOUND_LIBM) + target_compile_definitions(FortranFloat128MathILib INTERFACE + HAS_LIBM + ) + target_sources(FortranFloat128MathILib INTERFACE ${sources}) + else() + message(FATAL_ERROR "FortranRuntime cannot build without libm") + endif() +else() + # We can use '__float128' version from libc, if it has them. + check_library_exists(m sinf128 "" FOUND_LIBMF128) + if (FOUND_LIBMF128) + target_compile_definitions(FortranFloat128MathILib INTERFACE + HAS_LIBMF128 + ) + # Enable this, when math-entries.h and complex-math.h is ready. + # target_sources(FortranFloat128MathILib INTERFACE ${sources}) + endif() endif() diff --git a/flang/runtime/Float128Math/cabs.cpp b/flang/runtime/Float128Math/cabs.cpp deleted file mode 100644 index 3b8c9d17003c6e0027d2f3da57d0c37a7c935d4c..0000000000000000000000000000000000000000 --- a/flang/runtime/Float128Math/cabs.cpp +++ /dev/null @@ -1,24 +0,0 @@ -//===-- runtime/Float128Math/cabs.cpp -------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "math-entries.h" - -namespace Fortran::runtime { -extern "C" { -#if 0 -// FIXME: temporarily disabled. Need to add pure C entry point -// using C _Complex ABI. -#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 -// NOTE: Flang calls the runtime APIs using C _Complex ABI -CppTypeFor RTDEF(CAbsF128)(CFloat128ComplexType x) { - return CAbs::invoke(x); -} -#endif -#endif -} // extern "C" -} // namespace Fortran::runtime diff --git a/flang/runtime/Float128Math/complex-math.c b/flang/runtime/Float128Math/complex-math.c new file mode 100644 index 0000000000000000000000000000000000000000..d0180c63a0d7bf7978dba23feb804b65c1d732da --- /dev/null +++ b/flang/runtime/Float128Math/complex-math.c @@ -0,0 +1,55 @@ +/*===-- runtime/Float128Math/complex-math.c -------------------------*- 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 + * + * ===-----------------------------------------------------------------------=== + */ + +#include "complex-math.h" + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 + +CFloat128Type RTDEF(CAbsF128)(CFloat128ComplexType x) { return CAbs(x); } +CFloat128ComplexType RTDEF(CAcosF128)(CFloat128ComplexType x) { + return CAcos(x); +} +CFloat128ComplexType RTDEF(CAcoshF128)(CFloat128ComplexType x) { + return CAcosh(x); +} +CFloat128ComplexType RTDEF(CAsinF128)(CFloat128ComplexType x) { + return CAsin(x); +} +CFloat128ComplexType RTDEF(CAsinhF128)(CFloat128ComplexType x) { + return CAsinh(x); +} +CFloat128ComplexType RTDEF(CAtanF128)(CFloat128ComplexType x) { + return CAtan(x); +} +CFloat128ComplexType RTDEF(CAtanhF128)(CFloat128ComplexType x) { + return CAtanh(x); +} +CFloat128ComplexType RTDEF(CCosF128)(CFloat128ComplexType x) { return CCos(x); } +CFloat128ComplexType RTDEF(CCoshF128)(CFloat128ComplexType x) { + return CCosh(x); +} +CFloat128ComplexType RTDEF(CExpF128)(CFloat128ComplexType x) { return CExp(x); } +CFloat128ComplexType RTDEF(CLogF128)(CFloat128ComplexType x) { return CLog(x); } +CFloat128ComplexType RTDEF(CPowF128)( + CFloat128ComplexType x, CFloat128ComplexType p) { + return CPow(x, p); +} +CFloat128ComplexType RTDEF(CSinF128)(CFloat128ComplexType x) { return CSin(x); } +CFloat128ComplexType RTDEF(CSinhF128)(CFloat128ComplexType x) { + return CSinh(x); +} +CFloat128ComplexType RTDEF(CSqrtF128)(CFloat128ComplexType x) { + return CSqrt(x); +} +CFloat128ComplexType RTDEF(CTanF128)(CFloat128ComplexType x) { return CTan(x); } +CFloat128ComplexType RTDEF(CTanhF128)(CFloat128ComplexType x) { + return CTanh(x); +} + +#endif // LDBL_MANT_DIG == 113 || HAS_FLOAT128 diff --git a/flang/runtime/Float128Math/complex-math.h b/flang/runtime/Float128Math/complex-math.h new file mode 100644 index 0000000000000000000000000000000000000000..81dd53a175d1aa325f37209412508b91fc250c77 --- /dev/null +++ b/flang/runtime/Float128Math/complex-math.h @@ -0,0 +1,62 @@ +/*===-- runtime/Float128Math/complex-math.h -------------------------*- 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 FORTRAN_RUNTIME_FLOAT128MATH_COMPLEX_MATH_H_ +#define FORTRAN_RUNTIME_FLOAT128MATH_COMPLEX_MATH_H_ + +#include "flang/Common/float128.h" +#include "flang/Runtime/entry-names.h" + +#if HAS_QUADMATHLIB +#include "quadmath.h" +#define CAbs(x) cabsq(x) +#define CAcos(x) cacosq(x) +#define CAcosh(x) cacoshq(x) +#define CAsin(x) casinq(x) +#define CAsinh(x) casinhq(x) +#define CAtan(x) catanq(x) +#define CAtanh(x) catanhq(x) +#define CCos(x) ccosq(x) +#define CCosh(x) ccoshq(x) +#define CExp(x) cexpq(x) +#define CLog(x) clogq(x) +#define CPow(x, p) cpowq(x, p) +#define CSin(x) csinq(x) +#define CSinh(x) csinhq(x) +#define CSqrt(x) csqrtq(x) +#define CTan(x) ctanq(x) +#define CTanh(x) ctanhq(x) +#elif LDBL_MANT_DIG == 113 +/* Use 'long double' versions of libm functions. */ +#include + +#define CAbs(x) cabsl(x) +#define CAcos(x) cacosl(x) +#define CAcosh(x) cacoshl(x) +#define CAsin(x) casinl(x) +#define CAsinh(x) casinhl(x) +#define CAtan(x) catanl(x) +#define CAtanh(x) catanhl(x) +#define CCos(x) ccosl(x) +#define CCosh(x) ccoshl(x) +#define CExp(x) cexpl(x) +#define CLog(x) clogl(x) +#define CPow(x, p) cpowl(x, p) +#define CSin(x) csinl(x) +#define CSinh(x) csinhl(x) +#define CSqrt(x) csqrtl(x) +#define CTan(x) ctanl(x) +#define CTanh(x) ctanhl(x) +#elif HAS_LIBMF128 +/* We can use __float128 versions of libm functions. + * __STDC_WANT_IEC_60559_TYPES_EXT__ needs to be defined + * before including math.h to enable the *f128 prototypes. */ +#error "Float128Math build with glibc>=2.26 is unsupported yet" +#endif + +#endif /* FORTRAN_RUNTIME_FLOAT128MATH_COMPLEX_MATH_H_ */ diff --git a/flang/runtime/Float128Math/exponent.cpp b/flang/runtime/Float128Math/exponent.cpp index c0e43c0ee8d36e3798fa3881093bb5b31933de3c..1be1dd0d0ac8b824d158342989d7376d15c81164 100644 --- a/flang/runtime/Float128Math/exponent.cpp +++ b/flang/runtime/Float128Math/exponent.cpp @@ -12,7 +12,7 @@ namespace Fortran::runtime { extern "C" { -#if LDBL_MANT_DIG != 113 && HAS_FLOAT128 +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 // EXPONENT (16.9.75) CppTypeFor RTDEF(Exponent16_4)(F128Type x) { return Exponent>(x); diff --git a/flang/runtime/Float128Math/fraction.cpp b/flang/runtime/Float128Math/fraction.cpp index 8de6d3c7ff6c072acfde63349e5a653ca5f3f9a2..8c9889b7f6871edcfa41526e605000c92b271380 100644 --- a/flang/runtime/Float128Math/fraction.cpp +++ b/flang/runtime/Float128Math/fraction.cpp @@ -12,7 +12,7 @@ namespace Fortran::runtime { extern "C" { -#if LDBL_MANT_DIG != 113 && HAS_FLOAT128 +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 // FRACTION (16.9.80) F128Type RTDEF(Fraction16)(F128Type x) { return Fraction(x); } #endif diff --git a/flang/runtime/Float128Math/math-entries.h b/flang/runtime/Float128Math/math-entries.h index ad3f6aa18aa9a100803b5717c2ab81adb0bbcae6..1eab7c86f2ed765df95a66c051267f336b626ddf 100644 --- a/flang/runtime/Float128Math/math-entries.h +++ b/flang/runtime/Float128Math/math-entries.h @@ -106,11 +106,59 @@ DEFINE_FALLBACK_F128(Y0) DEFINE_FALLBACK_F128(Y1) DEFINE_FALLBACK_F128(Yn) -#if HAS_LIBM -#include +#if HAS_QUADMATHLIB +// Define wrapper callers for libquadmath. +#include "quadmath.h" +DEFINE_SIMPLE_ALIAS(Abs, fabsq) +DEFINE_SIMPLE_ALIAS(Acos, acosq) +DEFINE_SIMPLE_ALIAS(Acosh, acoshq) +DEFINE_SIMPLE_ALIAS(Asin, asinq) +DEFINE_SIMPLE_ALIAS(Asinh, asinhq) +DEFINE_SIMPLE_ALIAS(Atan, atanq) +DEFINE_SIMPLE_ALIAS(Atan2, atan2q) +DEFINE_SIMPLE_ALIAS(Atanh, atanhq) +DEFINE_SIMPLE_ALIAS(Ceil, ceilq) +DEFINE_SIMPLE_ALIAS(Cos, cosq) +DEFINE_SIMPLE_ALIAS(Cosh, coshq) +DEFINE_SIMPLE_ALIAS(Erf, erfq) +DEFINE_SIMPLE_ALIAS(Erfc, erfcq) +DEFINE_SIMPLE_ALIAS(Exp, expq) +DEFINE_SIMPLE_ALIAS(Floor, floorq) +DEFINE_SIMPLE_ALIAS(Frexp, frexpq) +DEFINE_SIMPLE_ALIAS(Hypot, hypotq) +DEFINE_SIMPLE_ALIAS(Ilogb, ilogbq) +DEFINE_SIMPLE_ALIAS(Isinf, isinfq) +DEFINE_SIMPLE_ALIAS(Isnan, isnanq) +DEFINE_SIMPLE_ALIAS(J0, j0q) +DEFINE_SIMPLE_ALIAS(J1, j1q) +DEFINE_SIMPLE_ALIAS(Jn, jnq) +DEFINE_SIMPLE_ALIAS(Ldexp, ldexpq) +DEFINE_SIMPLE_ALIAS(Lgamma, lgammaq) +DEFINE_SIMPLE_ALIAS(Llround, llroundq) +DEFINE_SIMPLE_ALIAS(Log, logq) +DEFINE_SIMPLE_ALIAS(Log10, log10q) +DEFINE_SIMPLE_ALIAS(Lround, lroundq) +DEFINE_SIMPLE_ALIAS(Nextafter, nextafterq) +DEFINE_SIMPLE_ALIAS(Pow, powq) +DEFINE_SIMPLE_ALIAS(Round, roundq) +DEFINE_SIMPLE_ALIAS(Sin, sinq) +DEFINE_SIMPLE_ALIAS(Sinh, sinhq) +DEFINE_SIMPLE_ALIAS(Sqrt, sqrtq) +DEFINE_SIMPLE_ALIAS(Tan, tanq) +DEFINE_SIMPLE_ALIAS(Tanh, tanhq) +DEFINE_SIMPLE_ALIAS(Tgamma, tgammaq) +DEFINE_SIMPLE_ALIAS(Trunc, truncq) +DEFINE_SIMPLE_ALIAS(Y0, y0q) +DEFINE_SIMPLE_ALIAS(Y1, y1q) +DEFINE_SIMPLE_ALIAS(Yn, ynq) +// Use cmath INFINITY/NAN definition. Rely on C implicit conversions. +#define F128_RT_INFINITY (INFINITY) +#define F128_RT_QNAN (NAN) +#elif LDBL_MANT_DIG == 113 // Define wrapper callers for libm. -#if LDBL_MANT_DIG == 113 +#include + // Use STD math functions. They provide IEEE-754 128-bit float // support either via 'long double' or __float128. // The Bessel's functions are not present in STD namespace. @@ -122,9 +170,6 @@ DEFINE_SIMPLE_ALIAS(Asinh, std::asinh) DEFINE_SIMPLE_ALIAS(Atan, std::atan) DEFINE_SIMPLE_ALIAS(Atan2, std::atan2) DEFINE_SIMPLE_ALIAS(Atanh, std::atanh) -// TODO: enable complex abs, when ABI adjustment for complex -// data type is resolved. -// DEFINE_SIMPLE_ALIAS(CAbs, std::abs) DEFINE_SIMPLE_ALIAS(Ceil, std::ceil) DEFINE_SIMPLE_ALIAS(Cos, std::cos) DEFINE_SIMPLE_ALIAS(Cosh, std::cosh) @@ -165,70 +210,11 @@ DEFINE_SIMPLE_ALIAS(Yn, ynl) (std::numeric_limits>::infinity()) #define F128_RT_QNAN \ (std::numeric_limits>::quiet_NaN()) -#else // LDBL_MANT_DIG != 113 -#if !HAS_LIBMF128 -// glibc >=2.26 seems to have complete support for __float128 -// versions of the math functions. -#error "FLANG_RUNTIME_F128_MATH_LIB=libm build requires libm >=2.26" -#endif - +#elif HAS_LIBMF128 // We can use __float128 versions of libm functions. // __STDC_WANT_IEC_60559_TYPES_EXT__ needs to be defined // before including cmath to enable the *f128 prototypes. -// TODO: this needs to be enabled separately, especially -// for complex data types that require C++ complex to C complex -// adjustment to match the ABIs. -#error "Unsupported FLANG_RUNTIME_F128_MATH_LIB=libm build" -#endif // LDBL_MANT_DIG != 113 -#elif HAS_QUADMATHLIB -// Define wrapper callers for libquadmath. -#include "quadmath.h" -DEFINE_SIMPLE_ALIAS(Abs, fabsq) -DEFINE_SIMPLE_ALIAS(Acos, acosq) -DEFINE_SIMPLE_ALIAS(Acosh, acoshq) -DEFINE_SIMPLE_ALIAS(Asin, asinq) -DEFINE_SIMPLE_ALIAS(Asinh, asinhq) -DEFINE_SIMPLE_ALIAS(Atan, atanq) -DEFINE_SIMPLE_ALIAS(Atan2, atan2q) -DEFINE_SIMPLE_ALIAS(Atanh, atanhq) -DEFINE_SIMPLE_ALIAS(Ceil, ceilq) -DEFINE_SIMPLE_ALIAS(Cos, cosq) -DEFINE_SIMPLE_ALIAS(Cosh, coshq) -DEFINE_SIMPLE_ALIAS(Erf, erfq) -DEFINE_SIMPLE_ALIAS(Erfc, erfcq) -DEFINE_SIMPLE_ALIAS(Exp, expq) -DEFINE_SIMPLE_ALIAS(Floor, floorq) -DEFINE_SIMPLE_ALIAS(Frexp, frexpq) -DEFINE_SIMPLE_ALIAS(Hypot, hypotq) -DEFINE_SIMPLE_ALIAS(Ilogb, ilogbq) -DEFINE_SIMPLE_ALIAS(Isinf, isinfq) -DEFINE_SIMPLE_ALIAS(Isnan, isnanq) -DEFINE_SIMPLE_ALIAS(J0, j0q) -DEFINE_SIMPLE_ALIAS(J1, j1q) -DEFINE_SIMPLE_ALIAS(Jn, jnq) -DEFINE_SIMPLE_ALIAS(Ldexp, ldexpq) -DEFINE_SIMPLE_ALIAS(Lgamma, lgammaq) -DEFINE_SIMPLE_ALIAS(Llround, llroundq) -DEFINE_SIMPLE_ALIAS(Log, logq) -DEFINE_SIMPLE_ALIAS(Log10, log10q) -DEFINE_SIMPLE_ALIAS(Lround, lroundq) -DEFINE_SIMPLE_ALIAS(Nextafter, nextafterq) -DEFINE_SIMPLE_ALIAS(Pow, powq) -DEFINE_SIMPLE_ALIAS(Round, roundq) -DEFINE_SIMPLE_ALIAS(Sin, sinq) -DEFINE_SIMPLE_ALIAS(Sinh, sinhq) -DEFINE_SIMPLE_ALIAS(Sqrt, sqrtq) -DEFINE_SIMPLE_ALIAS(Tan, tanq) -DEFINE_SIMPLE_ALIAS(Tanh, tanhq) -DEFINE_SIMPLE_ALIAS(Tgamma, tgammaq) -DEFINE_SIMPLE_ALIAS(Trunc, truncq) -DEFINE_SIMPLE_ALIAS(Y0, y0q) -DEFINE_SIMPLE_ALIAS(Y1, y1q) -DEFINE_SIMPLE_ALIAS(Yn, ynq) - -// Use cmath INFINITY/NAN definition. Rely on C implicit conversions. -#define F128_RT_INFINITY (INFINITY) -#define F128_RT_QNAN (NAN) +#error "Float128Math build with glibc>=2.26 is unsupported yet" #endif } // namespace Fortran::runtime diff --git a/flang/runtime/Float128Math/mod-real.cpp b/flang/runtime/Float128Math/mod-real.cpp index 9cc2926e45d51ab7d5eb1952fefa0c1be656fb07..42e6ce76e2fa1b8baf1882626d431d6bea968103 100644 --- a/flang/runtime/Float128Math/mod-real.cpp +++ b/flang/runtime/Float128Math/mod-real.cpp @@ -12,7 +12,7 @@ namespace Fortran::runtime { extern "C" { -#if LDBL_MANT_DIG != 113 && HAS_FLOAT128 +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 // MOD (16.9.135) F128Type RTDEF(ModReal16)( F128Type x, F128Type p, const char *sourceFile, int sourceLine) { diff --git a/flang/runtime/Float128Math/modulo-real.cpp b/flang/runtime/Float128Math/modulo-real.cpp index b25797fd8f41284a7c91ad7b2b4ced8b1ca7ec70..13000aba8c8323fec30c6f66531fdb48588bce95 100644 --- a/flang/runtime/Float128Math/modulo-real.cpp +++ b/flang/runtime/Float128Math/modulo-real.cpp @@ -12,7 +12,7 @@ namespace Fortran::runtime { extern "C" { -#if LDBL_MANT_DIG != 113 && HAS_FLOAT128 +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 // MODULO (16.9.136) F128Type RTDEF(ModuloReal16)( F128Type x, F128Type p, const char *sourceFile, int sourceLine) { diff --git a/flang/runtime/Float128Math/nearest.cpp b/flang/runtime/Float128Math/nearest.cpp index fd990532e5229361d0f43d9cc65ff9b26eb4da41..148ac4ef839160d51b080d10694208ca69585884 100644 --- a/flang/runtime/Float128Math/nearest.cpp +++ b/flang/runtime/Float128Math/nearest.cpp @@ -11,7 +11,7 @@ namespace Fortran::runtime { extern "C" { -#if LDBL_MANT_DIG != 113 && HAS_FLOAT128 +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(Nearest16)( CppTypeFor x, bool positive) { return Nextafter::invoke( diff --git a/flang/runtime/Float128Math/rrspacing.cpp b/flang/runtime/Float128Math/rrspacing.cpp index f2187f42313ae50438a0fedfd20fdfe5a8878021..feddac418eec39e8b72fe3c46c40e4a0a09dd0d6 100644 --- a/flang/runtime/Float128Math/rrspacing.cpp +++ b/flang/runtime/Float128Math/rrspacing.cpp @@ -12,7 +12,7 @@ namespace Fortran::runtime { extern "C" { -#if LDBL_MANT_DIG != 113 && HAS_FLOAT128 +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 // FRACTION (16.9.80) F128Type RTDEF(RRSpacing16)(F128Type x) { return RRSpacing<113>(x); } #endif diff --git a/flang/runtime/Float128Math/scale.cpp b/flang/runtime/Float128Math/scale.cpp index d6b843150e726f35c68962094d9036120244a453..0be958bd9f2a729246383c8752894735d42f240e 100644 --- a/flang/runtime/Float128Math/scale.cpp +++ b/flang/runtime/Float128Math/scale.cpp @@ -13,7 +13,7 @@ namespace Fortran::runtime { extern "C" { -#if LDBL_MANT_DIG != 113 && HAS_FLOAT128 +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 F128Type RTDEF(Scale16)(F128Type x, std::int64_t p) { auto ip{static_cast(p)}; if (ip != p) { diff --git a/flang/runtime/Float128Math/set-exponent.cpp b/flang/runtime/Float128Math/set-exponent.cpp index 0f942d238b8f35e22bf8492247ce7ec89eb2c8b8..99c34af7962b9a9cff61040e3c4a5f2307a791c8 100644 --- a/flang/runtime/Float128Math/set-exponent.cpp +++ b/flang/runtime/Float128Math/set-exponent.cpp @@ -12,7 +12,7 @@ namespace Fortran::runtime { extern "C" { -#if LDBL_MANT_DIG != 113 && HAS_FLOAT128 +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 // SET_EXPONENT (16.9.171) F128Type RTDEF(SetExponent16)(F128Type x, std::int64_t p) { return SetExponent(x, p); diff --git a/flang/runtime/Float128Math/spacing.cpp b/flang/runtime/Float128Math/spacing.cpp index d00e74644f8a863c7c52ba54ddefec175fbc971b..a86c0b30e567ab7431b0cb20c11420831f4a25a3 100644 --- a/flang/runtime/Float128Math/spacing.cpp +++ b/flang/runtime/Float128Math/spacing.cpp @@ -12,7 +12,7 @@ namespace Fortran::runtime { extern "C" { -#if LDBL_MANT_DIG != 113 && HAS_FLOAT128 +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 // SPACING (16.9.180) F128Type RTDEF(Spacing16)(F128Type x) { return Spacing<113>(x); } #endif diff --git a/flang/runtime/buffer.h b/flang/runtime/buffer.h index a77a5a5dda5c783124f1b928141363f569b2411f..93fda36f500d31d076fd69434eef16c09e1b8e4f 100644 --- a/flang/runtime/buffer.h +++ b/flang/runtime/buffer.h @@ -148,10 +148,15 @@ private: buffer_ = reinterpret_cast(AllocateMemoryOrCrash(terminator, size_)); auto chunk{std::min(length_, oldSize - start_)}; - std::memcpy(buffer_, old + start_, chunk); + // "memcpy" in glibc has a "nonnull" attribute on the source pointer. + // Avoid passing a null pointer, since it would result in an undefined + // behavior. + if (old != nullptr) { + std::memcpy(buffer_, old + start_, chunk); + std::memcpy(buffer_ + chunk, old, length_ - chunk); + FreeMemory(old); + } start_ = 0; - std::memcpy(buffer_ + chunk, old, length_ - chunk); - FreeMemory(old); } } diff --git a/flang/runtime/command.cpp b/flang/runtime/command.cpp index 7c44890545bd3fbb226c277ae7f773a9dd90c810..fabfe601688bbff6e69f9dc23b9118ebef832303 100644 --- a/flang/runtime/command.cpp +++ b/flang/runtime/command.cpp @@ -196,11 +196,11 @@ std::int32_t RTNAME(GetCommand)(const Descriptor *value, } static std::size_t LengthWithoutTrailingSpaces(const Descriptor &d) { - std::size_t s{d.ElementBytes() - 1}; - while (*d.OffsetElement(s) == ' ') { + std::size_t s{d.ElementBytes()}; // This can be 0. + while (s != 0 && *d.OffsetElement(s - 1) == ' ') { --s; } - return s + 1; + return s; } std::int32_t RTNAME(GetEnvVariable)(const Descriptor &name, diff --git a/flang/runtime/complex-powi.cpp b/flang/runtime/complex-powi.cpp index 18723bb93cbf17228e5e667fb7faef176fff936f..77031e40242791b9cdb26611d8c0e4413474e251 100644 --- a/flang/runtime/complex-powi.cpp +++ b/flang/runtime/complex-powi.cpp @@ -6,6 +6,7 @@ * * ===-----------------------------------------------------------------------=== */ +#include "flang/Common/float128.h" #include "flang/Runtime/entry-names.h" #include #include @@ -79,6 +80,30 @@ extern "C" double _Complex RTNAME(zpowk)( double _Complex base, std::int64_t exp) { return tgpowi(base, exp); } + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +// Duplicate CFloat128ComplexType definition from flang/Common/float128.h. +// float128.h does not define it for C++, because _Complex triggers +// c99-extension warnings. We decided to disable warnings for this +// particular file, so we can use _Complex here. +#if LDBL_MANT_DIG == 113 +typedef long double _Complex Qcomplex; +#elif HAS_FLOAT128 +#if !defined(_ARCH_PPC) || defined(__LONG_DOUBLE_IEEE128__) +typedef _Complex float __attribute__((mode(TC))) Qcomplex; +#else +typedef _Complex float __attribute__((mode(KC))) Qcomplex; +#endif +#endif + +extern "C" Qcomplex RTNAME(cqpowi)(Qcomplex base, std::int32_t exp) { + return tgpowi(base, exp); +} +extern "C" Qcomplex RTNAME(cqpowk)(Qcomplex base, std::int64_t exp) { + return tgpowi(base, exp); +} +#endif + #else // on MSVC, C complex is always just a struct of two members as it is not // supported as a builtin type. So we use C++ complex here as that has the @@ -116,10 +141,28 @@ extern "C" Fcomplex RTNAME(cpowk)(Fcomplex base, std::int64_t exp) { return *(Fcomplex *)(&cppres); } -extern "C" Dcomplex RTNAME(zpowk)(Dcomplex base, std::int32_t exp) { +extern "C" Dcomplex RTNAME(zpowk)(Dcomplex base, std::int64_t exp) { auto cppbase = *(std::complex *)(&base); auto cppres = tgpowi(cppbase, exp); return *(Dcomplex *)(&cppres); } +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +struct Qcomplex { + CFloat128Type re; + CFloat128Type im; +}; + +extern "C" Dcomplex RTNAME(cqpowi)(Qcomplex base, std::int32_t exp) { + auto cppbase = *(std::complex *)(&base); + auto cppres = tgpowi(cppbase, exp); + return *(Qcomplex *)(&cppres); +} + +extern "C" Dcomplex RTNAME(cqpowk)(Qcomplex base, std::int64_t exp) { + auto cppbase = *(std::complex *)(&base); + auto cppres = tgpowi(cppbase, exp); + return *(Qcomplex *)(&cppres); +} +#endif #endif diff --git a/flang/runtime/complex-reduction.c b/flang/runtime/complex-reduction.c index 72c31ce08b875a7f91437fc944dac09cd6d03c51..c91d12539911766d8aadf6ff87e4607f0216a812 100644 --- a/flang/runtime/complex-reduction.c +++ b/flang/runtime/complex-reduction.c @@ -82,7 +82,8 @@ static long_double_Complex_t CMPLXL(long double r, long double i) { * supports __builtin_complex. For Clang, require >=12.0. * Otherwise, rely on the memory layout compatibility. */ -#if (defined(__clang_major__) && (__clang_major__ >= 12)) || defined(__GNUC__) +#if (defined(__clang_major__) && (__clang_major__ >= 12)) || \ + (defined(__GNUC__) && !defined(__clang__)) #define CMPLXF128 __builtin_complex #else static CFloat128ComplexType CMPLXF128(CFloat128Type r, CFloat128Type i) { diff --git a/flang/runtime/numeric.cpp b/flang/runtime/numeric.cpp index d61f32e1d5b866ec545418764896a9694ea4847a..abd3e500029fe49ab915b17e93f99d73f769ac0a 100644 --- a/flang/runtime/numeric.cpp +++ b/flang/runtime/numeric.cpp @@ -324,16 +324,6 @@ CppTypeFor RTDEF(Exponent10_8)( CppTypeFor x) { return Exponent>(x); } -#elif LDBL_MANT_DIG == 113 -// The __float128 implementation resides in FortranFloat128Math library. -CppTypeFor RTDEF(Exponent16_4)( - CppTypeFor x) { - return Exponent>(x); -} -CppTypeFor RTDEF(Exponent16_8)( - CppTypeFor x) { - return Exponent>(x); -} #endif CppTypeFor RTDEF(Floor4_1)( @@ -441,12 +431,6 @@ CppTypeFor RTDEF(Fraction10)( CppTypeFor x) { return Fraction(x); } -#elif LDBL_MANT_DIG == 113 -// The __float128 implementation resides in FortranFloat128Math library. -CppTypeFor RTDEF(Fraction16)( - CppTypeFor x) { - return Fraction(x); -} #endif bool RTDEF(IsFinite4)(CppTypeFor x) { @@ -529,13 +513,6 @@ CppTypeFor RTDEF(ModReal10)( const char *sourceFile, int sourceLine) { return RealMod(x, p, sourceFile, sourceLine); } -#elif LDBL_MANT_DIG == 113 -// The __float128 implementation resides in FortranFloat128Math library. -CppTypeFor RTDEF(ModReal16)( - CppTypeFor x, CppTypeFor p, - const char *sourceFile, int sourceLine) { - return RealMod(x, p, sourceFile, sourceLine); -} #endif CppTypeFor RTDEF(ModuloInteger1)( @@ -586,13 +563,6 @@ CppTypeFor RTDEF(ModuloReal10)( const char *sourceFile, int sourceLine) { return RealMod(x, p, sourceFile, sourceLine); } -#elif LDBL_MANT_DIG == 113 -// The __float128 implementation resides in FortranFloat128Math library. -CppTypeFor RTDEF(ModuloReal16)( - CppTypeFor x, CppTypeFor p, - const char *sourceFile, int sourceLine) { - return RealMod(x, p, sourceFile, sourceLine); -} #endif CppTypeFor RTDEF(Nearest4)( @@ -608,12 +578,6 @@ CppTypeFor RTDEF(Nearest10)( CppTypeFor x, bool positive) { return Nearest<64>(x, positive); } -#elif LDBL_MANT_DIG == 113 -// The __float128 implementation resides in FortranFloat128Math library. -CppTypeFor RTDEF(Nearest16)( - CppTypeFor x, bool positive) { - return Nearest<113>(x, positive); -} #endif CppTypeFor RTDEF(Nint4_1)( @@ -721,12 +685,6 @@ CppTypeFor RTDEF(RRSpacing10)( CppTypeFor x) { return RRSpacing<64>(x); } -#elif LDBL_MANT_DIG == 113 -// The __float128 implementation resides in FortranFloat128Math library. -CppTypeFor RTDEF(RRSpacing16)( - CppTypeFor x) { - return RRSpacing<113>(x); -} #endif CppTypeFor RTDEF(SetExponent4)( @@ -742,12 +700,6 @@ CppTypeFor RTDEF(SetExponent10)( CppTypeFor x, std::int64_t p) { return SetExponent(x, p); } -#elif LDBL_MANT_DIG == 113 -// The __float128 implementation resides in FortranFloat128Math library. -CppTypeFor RTDEF(SetExponent16)( - CppTypeFor x, std::int64_t p) { - return SetExponent(x, p); -} #endif CppTypeFor RTDEF(Scale4)( @@ -763,12 +715,6 @@ CppTypeFor RTDEF(Scale10)( CppTypeFor x, std::int64_t p) { return Scale(x, p); } -#elif LDBL_MANT_DIG == 113 -// The __float128 implementation resides in FortranFloat128Math library. -CppTypeFor RTDEF(Scale16)( - CppTypeFor x, std::int64_t p) { - return Scale(x, p); -} #endif // SELECTED_INT_KIND @@ -823,12 +769,6 @@ CppTypeFor RTDEF(Spacing10)( CppTypeFor x) { return Spacing<64>(x); } -#elif LDBL_MANT_DIG == 113 -// The __float128 implementation resides in FortranFloat128Math library. -CppTypeFor RTDEF(Spacing16)( - CppTypeFor x) { - return Spacing<113>(x); -} #endif CppTypeFor RTDEF(FPow4i)( diff --git a/flang/runtime/temporary-stack.cpp b/flang/runtime/temporary-stack.cpp index b4d7c6064457f2aba2233338da4b43c490481663..667b10e04dbd293c534891ced5fec62d3bba634b 100644 --- a/flang/runtime/temporary-stack.cpp +++ b/flang/runtime/temporary-stack.cpp @@ -93,8 +93,13 @@ void DescriptorStorage::resize(size_type newCapacity) { } Descriptor **newData = static_cast(AllocateMemoryOrCrash(terminator_, bytes)); - memcpy(newData, data_, capacity_ * sizeof(Descriptor *)); - FreeMemory(data_); + // "memcpy" in glibc has a "nonnull" attribute on the source pointer. + // Avoid passing a null pointer, since it would result in an undefined + // behavior. + if (data_ != nullptr) { + memcpy(newData, data_, capacity_ * sizeof(Descriptor *)); + FreeMemory(data_); + } data_ = newData; capacity_ = newCapacity; } diff --git a/flang/test/Fir/memory-allocation-opt.fir b/flang/test/Fir/memory-allocation-opt.fir index 44fdaad4a5c2045d36b1a28980b38bbff541af1a..cfbca2f83ef8eccb564313b451b34ee6d9bbf6f1 100644 --- a/flang/test/Fir/memory-allocation-opt.fir +++ b/flang/test/Fir/memory-allocation-opt.fir @@ -1,6 +1,4 @@ // RUN: fir-opt --memory-allocation-opt="dynamic-array-on-heap=true maximum-array-alloc-size=1024" %s | FileCheck %s -// FIXME: started crashing on windows https://github.com/llvm/llvm-project/issues/83534 -// UNSUPPORTED: system-windows // Test for size of array being too big. diff --git a/flang/test/Fir/target-complex16.f90 b/flang/test/Fir/target-complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..9245b205f68a05ea4ecb17a30c1c840f8e9027f5 --- /dev/null +++ b/flang/test/Fir/target-complex16.f90 @@ -0,0 +1,29 @@ +// RUN: tco --target=aarch64-unknown-linux-gnu %s | FileCheck %s --check-prefix=AARCH64 + +// AARCH64-LABEL: define { fp128, fp128 } @gen16() +func.func @gen16() -> !fir.complex<16> { + // AARCH64: %[[VAL1:.*]] = alloca { fp128, fp128 }, i64 1, align 16 + %1 = fir.undefined !fir.complex<16> + %2 = arith.constant 1.0 : f128 + %3 = arith.constant -4.0 : f128 + %c0 = arith.constant 0 : i32 + // AARCH64: store { fp128, fp128 } { fp128 0xL0000000000000000C001000000000000, fp128 0xL00000000000000003FFF000000000000 }, ptr %[[VAL1]], align 16 + %4 = fir.insert_value %1, %3, [0 : index] : (!fir.complex<16>, f128) -> !fir.complex<16> + %c1 = arith.constant 1 : i32 + %5 = fir.insert_value %4, %2, [1 : index] : (!fir.complex<16>, f128) -> !fir.complex<16> + // AARCH64: %[[VAL2:.*]] = load { fp128, fp128 }, ptr %[[VAL1]], align 16 + // AARCH64: ret { fp128, fp128 } %[[VAL2]] + return %5 : !fir.complex<16> +} + +// AARCH64: declare void @sink16([2 x fp128]) +func.func private @sink16(!fir.complex<16>) -> () + +// AARCH64-LABEL: define void @call16() +func.func @call16() { + // AARCH64: = call { fp128, fp128 } @gen16() + %1 = fir.call @gen16() : () -> !fir.complex<16> + // AARCH64: call void @sink16([2 x fp128] % + fir.call @sink16(%1) : (!fir.complex<16>) -> () + return +} diff --git a/flang/test/HLFIR/assumed-type-actual-args.f90 b/flang/test/HLFIR/assumed-type-actual-args.f90 new file mode 100644 index 0000000000000000000000000000000000000000..58c282b6ab188472d81af45c29d330548d3336bd --- /dev/null +++ b/flang/test/HLFIR/assumed-type-actual-args.f90 @@ -0,0 +1,226 @@ +! Test lowering to FIR of actual arguments that are assumed type +! variables (Fortran 2018 7.3.2.2 point 3). +! RUN: bbc --polymorphic-type -emit-hlfir -o - %s | FileCheck %s + +subroutine test1(x) + interface + subroutine s1(x) + type(*) :: x + end subroutine + end interface + type(*) :: x + call s1(x) +end subroutine + +subroutine test2(x) + interface + subroutine s2(x) + type(*) :: x(*) + end subroutine + end interface + type(*) :: x(*) + call s2(x) +end subroutine + +subroutine test3(x) + interface + subroutine s3(x) + type(*) :: x(:) + end subroutine + end interface + type(*) :: x(:) + call s3(x) +end subroutine + +subroutine test4(x) + interface + subroutine s4(x) + type(*) :: x(*) + end subroutine + end interface + type(*) :: x(:) + call s4(x) +end subroutine + +subroutine test3b(x) + interface + subroutine s3b(x) + type(*), optional, contiguous :: x(:) + end subroutine + end interface + type(*), optional :: x(:) + call s3b(x) +end subroutine + +subroutine test4b(x) + interface + subroutine s4b(x) + type(*), optional :: x(*) + end subroutine + end interface + type(*), optional :: x(:) + call s4b(x) +end subroutine + +subroutine test4c(x) + interface + subroutine s4c(x) + type(*), optional :: x(*) + end subroutine + end interface + type(*), contiguous, optional :: x(:) + call s4c(x) +end subroutine + +subroutine test4d(x) + interface + subroutine s4d(x) + type(*) :: x(*) + end subroutine + end interface + type(*), contiguous :: x(:) + call s4d(x) +end subroutine + +subroutine test5(x) + interface + subroutine s5(x) + type(*) :: x(..) + end subroutine + end interface + type(*) :: x(:) + call s5(x) +end subroutine + +subroutine test5b(x) + interface + subroutine s5b(x) + type(*), optional, contiguous :: x(..) + end subroutine + end interface + type(*), optional :: x(:) + call s5b(x) +end subroutine + +! CHECK-LABEL: func.func @_QPtest1( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref {fir.bindc_name = "x"}) { +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest1Ex"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: fir.call @_QPs1(%[[VAL_1]]#1) fastmath : (!fir.ref) -> () +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QPtest2( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref> {fir.bindc_name = "x"}) { +! CHECK: %[[VAL_1:.*]] = arith.constant -1 : index +! CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_1]] : (index) -> !fir.shape<1> +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_2]]) {uniq_name = "_QFtest2Ex"} : (!fir.ref>, !fir.shape<1>) -> (!fir.box>, !fir.ref>) +! CHECK: fir.call @_QPs2(%[[VAL_3]]#1) fastmath : (!fir.ref>) -> () +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QPtest3( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "x"}) { +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest3Ex"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: fir.call @_QPs3(%[[VAL_1]]#0) fastmath : (!fir.box>) -> () +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QPtest4( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "x"}) { +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest4Ex"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_2:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 : (!fir.box>) -> (!fir.box>, i1) +! CHECK: %[[VAL_3:.*]] = fir.box_addr %[[VAL_2]]#0 : (!fir.box>) -> !fir.ref> +! CHECK: fir.call @_QPs4(%[[VAL_3]]) fastmath : (!fir.ref>) -> () +! CHECK: hlfir.copy_out %[[VAL_2]]#0, %[[VAL_2]]#1 to %[[VAL_1]]#0 : (!fir.box>, i1, !fir.box>) -> () +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QPtest3b( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "x", fir.optional}) { +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest3bEx"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_2:.*]] = fir.is_present %[[VAL_1]]#0 : (!fir.box>) -> i1 +! CHECK: %[[VAL_3:.*]]:4 = fir.if %[[VAL_2]] -> (!fir.box>, !fir.box>, i1, !fir.box>) { +! CHECK: %[[VAL_4:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 : (!fir.box>) -> (!fir.box>, i1) +! CHECK: fir.result %[[VAL_4]]#0, %[[VAL_4]]#0, %[[VAL_4]]#1, %[[VAL_1]]#0 : !fir.box>, !fir.box>, i1, !fir.box> +! CHECK: } else { +! CHECK: %[[VAL_5:.*]] = fir.absent !fir.box> +! CHECK: %[[VAL_6:.*]] = fir.absent !fir.box> +! CHECK: %[[VAL_7:.*]] = arith.constant false +! CHECK: %[[VAL_8:.*]] = fir.absent !fir.box> +! CHECK: fir.result %[[VAL_5]], %[[VAL_6]], %[[VAL_7]], %[[VAL_8]] : !fir.box>, !fir.box>, i1, !fir.box> +! CHECK: } +! CHECK: fir.call @_QPs3b(%[[VAL_9:.*]]#0) fastmath : (!fir.box>) -> () +! CHECK: hlfir.copy_out %[[VAL_9]]#1, %[[VAL_9]]#2 to %[[VAL_9]]#3 : (!fir.box>, i1, !fir.box>) -> () +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QPtest4b( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "x", fir.optional}) { +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest4bEx"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_2:.*]] = fir.is_present %[[VAL_1]]#0 : (!fir.box>) -> i1 +! CHECK: %[[VAL_3:.*]]:4 = fir.if %[[VAL_2]] -> (!fir.ref>, !fir.box>, i1, !fir.box>) { +! CHECK: %[[VAL_4:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 : (!fir.box>) -> (!fir.box>, i1) +! CHECK: %[[VAL_5:.*]] = fir.box_addr %[[VAL_4]]#0 : (!fir.box>) -> !fir.ref> +! CHECK: fir.result %[[VAL_5]], %[[VAL_4]]#0, %[[VAL_4]]#1, %[[VAL_1]]#0 : !fir.ref>, !fir.box>, i1, !fir.box> +! CHECK: } else { +! CHECK: %[[VAL_6:.*]] = fir.absent !fir.ref> +! CHECK: %[[VAL_7:.*]] = fir.absent !fir.box> +! CHECK: %[[VAL_8:.*]] = arith.constant false +! CHECK: %[[VAL_9:.*]] = fir.absent !fir.box> +! CHECK: fir.result %[[VAL_6]], %[[VAL_7]], %[[VAL_8]], %[[VAL_9]] : !fir.ref>, !fir.box>, i1, !fir.box> +! CHECK: } +! CHECK: fir.call @_QPs4b(%[[VAL_10:.*]]#0) fastmath : (!fir.ref>) -> () +! CHECK: hlfir.copy_out %[[VAL_10]]#1, %[[VAL_10]]#2 to %[[VAL_10]]#3 : (!fir.box>, i1, !fir.box>) -> () +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QPtest4c( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "x", fir.contiguous, fir.optional}) { +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest4cEx"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_2:.*]] = fir.is_present %[[VAL_1]]#0 : (!fir.box>) -> i1 +! CHECK: %[[VAL_3:.*]] = fir.if %[[VAL_2]] -> (!fir.ref>) { +! CHECK: %[[VAL_4:.*]] = fir.box_addr %[[VAL_1]]#1 : (!fir.box>) -> !fir.ref> +! CHECK: fir.result %[[VAL_4]] : !fir.ref> +! CHECK: } else { +! CHECK: %[[VAL_5:.*]] = fir.absent !fir.ref> +! CHECK: fir.result %[[VAL_5]] : !fir.ref> +! CHECK: } +! CHECK: fir.call @_QPs4c(%[[VAL_3]]) fastmath : (!fir.ref>) -> () +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QPtest4d( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "x", fir.contiguous}) { +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest4dEx"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_2:.*]] = fir.box_addr %[[VAL_1]]#1 : (!fir.box>) -> !fir.ref> +! CHECK: fir.call @_QPs4d(%[[VAL_2]]) fastmath : (!fir.ref>) -> () +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QPtest5( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "x"}) { +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest5Ex"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_2:.*]] = fir.convert %[[VAL_1]]#0 : (!fir.box>) -> !fir.box> +! CHECK: fir.call @_QPs5(%[[VAL_2]]) fastmath : (!fir.box>) -> () +! CHECK: return +! CHECK: } + +! CHECK-LABEL: func.func @_QPtest5b( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.box> {fir.bindc_name = "x", fir.optional}) { +! CHECK: %[[VAL_1:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest5bEx"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_2:.*]] = fir.is_present %[[VAL_1]]#0 : (!fir.box>) -> i1 +! CHECK: %[[VAL_3:.*]]:4 = fir.if %[[VAL_2]] -> (!fir.box>, !fir.box>, i1, !fir.box>) { +! CHECK: %[[VAL_4:.*]]:2 = hlfir.copy_in %[[VAL_1]]#0 : (!fir.box>) -> (!fir.box>, i1) +! CHECK: fir.result %[[VAL_4]]#0, %[[VAL_4]]#0, %[[VAL_4]]#1, %[[VAL_1]]#0 : !fir.box>, !fir.box>, i1, !fir.box> +! CHECK: } else { +! CHECK: %[[VAL_5:.*]] = fir.absent !fir.box> +! CHECK: %[[VAL_6:.*]] = fir.absent !fir.box> +! CHECK: %[[VAL_7:.*]] = arith.constant false +! CHECK: %[[VAL_8:.*]] = fir.absent !fir.box> +! CHECK: fir.result %[[VAL_5]], %[[VAL_6]], %[[VAL_7]], %[[VAL_8]] : !fir.box>, !fir.box>, i1, !fir.box> +! CHECK: } +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_10:.*]]#0 : (!fir.box>) -> !fir.box> +! CHECK: fir.call @_QPs5b(%[[VAL_9]]) fastmath : (!fir.box>) -> () +! CHECK: hlfir.copy_out %[[VAL_10]]#1, %[[VAL_10]]#2 to %[[VAL_10]]#3 : (!fir.box>, i1, !fir.box>) -> () +! CHECK: return +! CHECK: } diff --git a/flang/test/HLFIR/element-addr.fir b/flang/test/HLFIR/element-addr.fir index 73946f8b40e3db0280dc5fb1c3f7dab82ef7e401..c3c48edd9b5639433bbf796954fc10f779fc5c71 100644 --- a/flang/test/HLFIR/element-addr.fir +++ b/flang/test/HLFIR/element-addr.fir @@ -114,3 +114,45 @@ func.func @unordered() { // CHECK: } // CHECK: return // CHECK: } + +// "X(VECTOR) = Y" with polymorphic X and Y and user defined assignment. +func.func @test_mold(%x: !fir.class>>, %y: !fir.class>>, %vector: !fir.box>) { + hlfir.region_assign { + hlfir.yield %y : !fir.class>> + } to { + %c0 = arith.constant 0 : index + %0:3 = fir.box_dims %vector, %c0 : (!fir.box>, index) -> (index, index, index) + %1 = fir.shape %0#1 : (index) -> !fir.shape<1> + hlfir.elemental_addr %1 mold %x unordered : !fir.shape<1>, !fir.class>> { + ^bb0(%arg3: index): + %2 = hlfir.designate %vector (%arg3) : (!fir.box>, index) -> !fir.ref + %3 = fir.load %2 : !fir.ref + %4 = hlfir.designate %x (%3) : (!fir.class>>, i64) -> !fir.class> + hlfir.yield %4 : !fir.class> + } + } user_defined_assign (%arg3: !fir.class>) to (%arg4: !fir.class>) { + fir.call @user_def_assign(%arg4, %arg3) : (!fir.class>, !fir.class>) -> () + } + return +} +func.func private @user_def_assign(!fir.class>, !fir.class>) +// CHECK-LABEL: func.func @test_mold( +// CHECK-SAME: %[[VAL_0:[^:]*]]: !fir.class>>, +// CHECK-SAME: %[[VAL_1:.*]]: !fir.class>>, +// CHECK-SAME: %[[VAL_2:.*]]: !fir.box>) { +// CHECK: hlfir.region_assign { +// CHECK: hlfir.yield %[[VAL_1]] : !fir.class>> +// CHECK: } to { +// CHECK: %[[VAL_3:.*]] = arith.constant 0 : index +// CHECK: %[[VAL_4:.*]]:3 = fir.box_dims %[[VAL_2]], %[[VAL_3]] : (!fir.box>, index) -> (index, index, index) +// CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_4]]#1 : (index) -> !fir.shape<1> +// CHECK: hlfir.elemental_addr %[[VAL_5]] mold %[[VAL_0]] unordered : !fir.shape<1>, !fir.class>> { +// CHECK: ^bb0(%[[VAL_6:.*]]: index): +// CHECK: %[[VAL_7:.*]] = hlfir.designate %[[VAL_2]] (%[[VAL_6]]) : (!fir.box>, index) -> !fir.ref +// CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_7]] : !fir.ref +// CHECK: %[[VAL_9:.*]] = hlfir.designate %[[VAL_0]] (%[[VAL_8]]) : (!fir.class>>, i64) -> !fir.class> +// CHECK: hlfir.yield %[[VAL_9]] : !fir.class> +// CHECK: } +// CHECK: } user_defined_assign (%[[VAL_10:.*]]: !fir.class>) to (%[[VAL_11:.*]]: !fir.class>) { +// CHECK: fir.call @user_def_assign(%[[VAL_11]], %[[VAL_10]]) : (!fir.class>, !fir.class>) -> () +// CHECK: } diff --git a/flang/test/Lower/HLFIR/structure-constructor.f90 b/flang/test/Lower/HLFIR/structure-constructor.f90 index ff0c27f274f32a4d317f50ed436d837d4f2018a2..d02427d2ff671ad610ac63108eb85042a92f6518 100644 --- a/flang/test/Lower/HLFIR/structure-constructor.f90 +++ b/flang/test/Lower/HLFIR/structure-constructor.f90 @@ -161,6 +161,8 @@ end subroutine test4 ! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_20]] realloc keep_lhs_len temporary_lhs : !fir.box>>>, !fir.ref>>>> ! CHECK: } ! CHECK: hlfir.assign %[[VAL_12]]#0 to %[[VAL_3]]#0 : !fir.ref>>>}>>, !fir.ref>>>}>> +! CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_13]] : (!fir.box>>>}>>) -> !fir.box +! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_27]] ! CHECK: return ! CHECK: } @@ -201,6 +203,8 @@ end subroutine test5 ! CHECK: hlfir.assign %[[VAL_24]] to %[[VAL_18]] realloc temporary_lhs : !fir.box>>>}>>>>, !fir.ref>>>}>>>>> ! CHECK: } ! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_3]]#0 : !fir.ref>>>}>>>>}>>, !fir.ref>>>}>>>>}>> +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_12]] : (!fir.box>>>}>>>>}>>) -> !fir.box +! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_24]] ! CHECK: return ! CHECK: } @@ -291,6 +295,10 @@ end subroutine test6 ! CHECK: %[[VAL_70:.*]] = hlfir.as_expr %[[VAL_48]]#0 move %[[VAL_69]] : (!fir.heap}>>>, i1) -> !hlfir.expr<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>> ! CHECK: hlfir.assign %[[VAL_70]] to %[[VAL_44]] temporary_lhs : !hlfir.expr<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>, !fir.ref}>>> ! CHECK: hlfir.assign %[[VAL_20]]#0 to %[[VAL_12]]#0 : !fir.ref>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>, !fir.ref>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>> +! CHECK: %[[VAL_71:.*]] = fir.convert %[[VAL_21]] : (!fir.box>>>}>>>>}>,t6m:!fir.array<1x!fir.type<_QMtypesTt1{c:!fir.char<1,4>}>>}>>) -> !fir.box +! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_71]] +! CHECK: %[[VAL_72:.*]] = fir.convert %[[VAL_29]] : (!fir.box>>>}>>>>}>>) -> !fir.box +! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_72]] ! CHECK: return ! CHECK: } @@ -375,6 +383,8 @@ end subroutine test8 ! CHECK: hlfir.assign %[[VAL_29]] to %[[VAL_22]] realloc keep_lhs_len temporary_lhs : !fir.heap>, !fir.ref>>> ! CHECK: } ! CHECK: hlfir.assign %[[VAL_14]]#0 to %[[VAL_2]]#0 : !fir.ref>>}>>, !fir.ref>>}>> +! CHECK: %[[VAL_30:.*]] = fir.convert %[[VAL_15]] : (!fir.box>>}>>) -> !fir.box +! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_30]] ! CHECK: return ! CHECK: } @@ -410,6 +420,8 @@ end subroutine test9 ! CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_12]]#0{"c"} typeparams %[[VAL_19]] {fortran_attrs = #fir.var_attrs} : (!fir.ref>>}>>, index) -> !fir.ref>>> ! CHECK: hlfir.assign %[[VAL_11]]#0 to %[[VAL_20]] realloc keep_lhs_len temporary_lhs : !fir.ref>, !fir.ref>>> ! CHECK: hlfir.assign %[[VAL_12]]#0 to %[[VAL_2]]#0 : !fir.ref>>}>>, !fir.ref>>}>> +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_13]] : (!fir.box>>}>>) -> !fir.box +! CHECK: fir.call @_FortranADestroyWithoutFinalization(%[[VAL_21]] ! CHECK: return ! CHECK: } diff --git a/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 b/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 index 2f463cfaa8b07c735ee81c8f038f2a57dc7f29f1..d4026a37720f7501a5c395117eb1fc0bd118baef 100644 --- a/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 +++ b/flang/test/Lower/HLFIR/vector-subscript-as-value.f90 @@ -1,6 +1,6 @@ ! Test lowering of vector subscript designators outside of the ! assignment left-and side and input IO context. -! RUN: bbc -emit-hlfir -o - -I nw %s 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -o - -I nw %s --polymorphic-type 2>&1 | FileCheck %s subroutine foo(x, y) integer :: x(100) @@ -182,3 +182,37 @@ end subroutine ! CHECK: %[[VAL_27:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_26]]) substr %[[VAL_15]], %[[VAL_16]] typeparams %[[VAL_22]] : (!fir.box>>, i64, index, index, index) -> !fir.boxchar<1> ! CHECK: hlfir.yield_element %[[VAL_27]] : !fir.boxchar<1> ! CHECK: } + +subroutine test_passing_subscripted_poly(x, vector) + interface + subroutine do_something(x) + class(*) :: x(:) + end subroutine + end interface + class(*) :: x(:, :) + integer(8) :: vector(:) + call do_something(x(314, vector)) +end subroutine +! CHECK-LABEL: func.func @_QPtest_passing_subscripted_poly( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.class> +! CHECK-SAME: %[[VAL_1:.*]]: !fir.box> +! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFtest_passing_subscripted_polyEvector"} : (!fir.box>) -> (!fir.box>, !fir.box>) +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] {uniq_name = "_QFtest_passing_subscripted_polyEx"} : (!fir.class>) -> (!fir.class>, !fir.class>) +! CHECK: %[[VAL_4:.*]] = arith.constant 314 : index +! CHECK: %[[VAL_5:.*]] = arith.constant 0 : index +! CHECK: %[[VAL_6:.*]]:3 = fir.box_dims %[[VAL_2]]#0, %[[VAL_5]] : (!fir.box>, index) -> (index, index, index) +! CHECK: %[[VAL_7:.*]] = fir.shape %[[VAL_6]]#1 : (index) -> !fir.shape<1> +! CHECK: %[[VAL_8:.*]] = hlfir.elemental %[[VAL_7]] mold %[[VAL_3]]#0 unordered : (!fir.shape<1>, !fir.class>) -> !hlfir.expr { +! CHECK: ^bb0(%[[VAL_9:.*]]: index): +! CHECK: %[[VAL_10:.*]] = hlfir.designate %[[VAL_2]]#0 (%[[VAL_9]]) : (!fir.box>, index) -> !fir.ref +! CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_10]] : !fir.ref +! CHECK: %[[VAL_12:.*]] = hlfir.designate %[[VAL_3]]#0 (%[[VAL_4]], %[[VAL_11]]) : (!fir.class>, index, i64) -> !fir.class +! CHECK: hlfir.yield_element %[[VAL_12]] : !fir.class +! CHECK: } +! CHECK: %[[VAL_13:.*]]:3 = hlfir.associate %[[VAL_8]](%[[VAL_7]]) {adapt.valuebyref} : (!hlfir.expr, !fir.shape<1>) -> (!fir.class>>, !fir.class>>, i1) +! CHECK: %[[VAL_14:.*]] = fir.rebox %[[VAL_13]]#0 : (!fir.class>>) -> !fir.class> +! CHECK: fir.call @_QPdo_something(%[[VAL_14]]) fastmath : (!fir.class>) -> () +! CHECK: hlfir.end_associate %[[VAL_13]]#0, %[[VAL_13]]#2 : !fir.class>>, i1 +! CHECK: hlfir.destroy %[[VAL_8]] : !hlfir.expr +! CHECK: return +! CHECK: } diff --git a/flang/test/Lower/Intrinsics/acos_complex16.f90 b/flang/test/Lower/Intrinsics/acos_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..5b3545e472e04375a1c96f1b9b4d163838d34fe3 --- /dev/null +++ b/flang/test/Lower/Intrinsics/acos_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACAcosF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = acos(a) +end diff --git a/flang/test/Lower/Intrinsics/acosh_complex16.f90 b/flang/test/Lower/Intrinsics/acosh_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..a80238d72e45172cae2bcceda09c515b7fe85bde --- /dev/null +++ b/flang/test/Lower/Intrinsics/acosh_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACAcoshF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = acosh(a) +end diff --git a/flang/test/Lower/Intrinsics/asin_complex16.f90 b/flang/test/Lower/Intrinsics/asin_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..982bf6f21b16fff3d9d9b981399a2e38b8b0e2d5 --- /dev/null +++ b/flang/test/Lower/Intrinsics/asin_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACAsinF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = asin(a) +end diff --git a/flang/test/Lower/Intrinsics/asinh_complex16.f90 b/flang/test/Lower/Intrinsics/asinh_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..2d658a68f8a2b48664d56158ff2fecd365d494be --- /dev/null +++ b/flang/test/Lower/Intrinsics/asinh_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACAsinhF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = asinh(a) +end diff --git a/flang/test/Lower/Intrinsics/atan_complex16.f90 b/flang/test/Lower/Intrinsics/atan_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..315928d8856831a52ad71cb6264a9be422b95389 --- /dev/null +++ b/flang/test/Lower/Intrinsics/atan_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACAtanF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = atan(a) +end diff --git a/flang/test/Lower/Intrinsics/atanh_complex16.f90 b/flang/test/Lower/Intrinsics/atanh_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..0d9f798ea4a2b1fc6015c6ace51a149d27fe382f --- /dev/null +++ b/flang/test/Lower/Intrinsics/atanh_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACAtanhF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = atanh(a) +end diff --git a/flang/test/Lower/Intrinsics/cos_complex16.f90 b/flang/test/Lower/Intrinsics/cos_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..79b89ce057e12b547f2a55a542e7d5cee56b7384 --- /dev/null +++ b/flang/test/Lower/Intrinsics/cos_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACCosF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = cos(a) +end diff --git a/flang/test/Lower/Intrinsics/cosh_complex16.f90 b/flang/test/Lower/Intrinsics/cosh_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..dc1723b4582049f1b2496c92c6685ede1f6f7ea5 --- /dev/null +++ b/flang/test/Lower/Intrinsics/cosh_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACCoshF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = cosh(a) +end diff --git a/flang/test/Lower/Intrinsics/exp_complex16.f90 b/flang/test/Lower/Intrinsics/exp_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..972285c654bfe401f20a13709ea6d4071d5a8f95 --- /dev/null +++ b/flang/test/Lower/Intrinsics/exp_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACExpF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = exp(a) +end diff --git a/flang/test/Lower/Intrinsics/log_complex16.f90 b/flang/test/Lower/Intrinsics/log_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..d5d0eb388ca2fef59ac4490a3b9e9ab696f5c7df --- /dev/null +++ b/flang/test/Lower/Intrinsics/log_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACLogF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = log(a) +end diff --git a/flang/test/Lower/Intrinsics/missing-math-runtime.f90 b/flang/test/Lower/Intrinsics/missing-math-runtime.f90 deleted file mode 100644 index 699678fcf2bcec06b7d91813f7b223a74f7596e4..0000000000000000000000000000000000000000 --- a/flang/test/Lower/Intrinsics/missing-math-runtime.f90 +++ /dev/null @@ -1,12 +0,0 @@ -! If the compiler is built without 128-bit float math -! support, an appropriate error message is emitted. -! UNSUPPORTED: flang-supports-f128-math -! RUN: bbc -emit-fir %s -o /dev/null >%t 2>&1 || echo -! RUN: FileCheck %s --input-file=%t - - complex(16) :: a - real(16) :: b -! CHECK: compiler is built without support for 'ABS(COMPLEX(KIND=16))' - b = abs(a) -end - diff --git a/flang/test/Lower/Intrinsics/pow_complex16.f90 b/flang/test/Lower/Intrinsics/pow_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..db6b207aea907390113e6d37bbd45d0f947f4db0 --- /dev/null +++ b/flang/test/Lower/Intrinsics/pow_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACPowF128({{.*}}){{.*}}: (!fir.complex<16>, !fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = a ** b +end diff --git a/flang/test/Lower/Intrinsics/pow_complex16i.f90 b/flang/test/Lower/Intrinsics/pow_complex16i.f90 new file mode 100644 index 0000000000000000000000000000000000000000..1cabaf94f8a6059398a4de4bf6813d62d1f48404 --- /dev/null +++ b/flang/test/Lower/Intrinsics/pow_complex16i.f90 @@ -0,0 +1,9 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranAcqpowi({{.*}}){{.*}}: (!fir.complex<16>, i32) -> !fir.complex<16> + complex(16) :: a + integer(4) :: b + b = a ** b +end diff --git a/flang/test/Lower/Intrinsics/pow_complex16k.f90 b/flang/test/Lower/Intrinsics/pow_complex16k.f90 new file mode 100644 index 0000000000000000000000000000000000000000..e3b1b4d31afa7224ea7570a23c3662d7e9d568b4 --- /dev/null +++ b/flang/test/Lower/Intrinsics/pow_complex16k.f90 @@ -0,0 +1,9 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranAcqpowk({{.*}}){{.*}}: (!fir.complex<16>, i64) -> !fir.complex<16> + complex(16) :: a + integer(8) :: b + b = a ** b +end diff --git a/flang/test/Lower/Intrinsics/sin_complex16.f90 b/flang/test/Lower/Intrinsics/sin_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..5114501e48dac77aef4fbba8fb1ab498c5a77ce7 --- /dev/null +++ b/flang/test/Lower/Intrinsics/sin_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACSinF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = sin(a) +end diff --git a/flang/test/Lower/Intrinsics/sinh_complex16.f90 b/flang/test/Lower/Intrinsics/sinh_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..5baf9ea8052a2a6ebb8e3e427fd3f6ca67127bdf --- /dev/null +++ b/flang/test/Lower/Intrinsics/sinh_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACSinhF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = sinh(a) +end diff --git a/flang/test/Lower/Intrinsics/sizeof.f90 b/flang/test/Lower/Intrinsics/sizeof.f90 new file mode 100644 index 0000000000000000000000000000000000000000..959ca1692b5144cc892be6a73dcdf2d9a4a71f91 --- /dev/null +++ b/flang/test/Lower/Intrinsics/sizeof.f90 @@ -0,0 +1,23 @@ +! Test SIZEOF lowering for polymorphic entities. +! RUN: bbc -emit-hlfir --polymorphic-type -o - %s | FileCheck %s + +integer(8) function test1(x) + class(*) :: x + test1 = sizeof(x) +end function +! CHECK-LABEL: func.func @_QPtest1( +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtest1Ex"} : (!fir.class) -> (!fir.class, !fir.class) +! CHECK: %[[VAL_4:.*]] = fir.box_elesize %[[VAL_3]]#1 : (!fir.class) -> i64 +! CHECK: hlfir.assign %[[VAL_4]] to %{{.*}} : i64, !fir.ref + +integer(8) function test2(x) + class(*) :: x(:, :) + test2 = sizeof(x) +end function +! CHECK-LABEL: func.func @_QPtest2( +! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFtest2Ex"} : (!fir.class>) -> (!fir.class>, !fir.class>) +! CHECK: %[[VAL_4:.*]] = fir.box_elesize %[[VAL_3]]#1 : (!fir.class>) -> i64 +! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_3]]#1 : (!fir.class>) -> !fir.box +! CHECK: %[[VAL_9:.*]] = fir.call @_FortranASize(%[[VAL_7]], %{{.*}}, %{{.*}}) fastmath : (!fir.box, !fir.ref, i32) -> i64 +! CHECK: %[[VAL_10:.*]] = arith.muli %[[VAL_4]], %[[VAL_9]] : i64 +! CHECK: hlfir.assign %[[VAL_10]] to %{{.*}} : i64, !fir.ref diff --git a/flang/test/Lower/Intrinsics/sqrt_complex16.f90 b/flang/test/Lower/Intrinsics/sqrt_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..75ffa22a6e2ed11429172765cd2d23fca43092fc --- /dev/null +++ b/flang/test/Lower/Intrinsics/sqrt_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACSqrtF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = sqrt(a) +end diff --git a/flang/test/Lower/Intrinsics/tan_complex16.f90 b/flang/test/Lower/Intrinsics/tan_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..7217145f81b0067024c530a16d3dd0b15859ba70 --- /dev/null +++ b/flang/test/Lower/Intrinsics/tan_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACTanF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = tan(a) +end diff --git a/flang/test/Lower/Intrinsics/tanh_complex16.f90 b/flang/test/Lower/Intrinsics/tanh_complex16.f90 new file mode 100644 index 0000000000000000000000000000000000000000..1965094c5bce0ecc0fb706298c149513853b8150 --- /dev/null +++ b/flang/test/Lower/Intrinsics/tanh_complex16.f90 @@ -0,0 +1,8 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK: fir.call @_FortranACTanhF128({{.*}}){{.*}}: (!fir.complex<16>) -> !fir.complex<16> + complex(16) :: a, b + b = tanh(a) +end diff --git a/flang/test/Lower/OpenMP/FIR/delayed-privatization-firstprivate.f90 b/flang/test/Lower/OpenMP/FIR/delayed-privatization-firstprivate.f90 index 122542345f104b1015b7f838f0e4588c74d5456f..50938342dee7c2cfb675ed10037f0ad77e7a4540 100644 --- a/flang/test/Lower/OpenMP/FIR/delayed-privatization-firstprivate.f90 +++ b/flang/test/Lower/OpenMP/FIR/delayed-privatization-firstprivate.f90 @@ -1,6 +1,9 @@ ! Test delayed privatization for the `private` clause. -! RUN: bbc -emit-fir -hlfir=false -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir \ +! RUN: --openmp-enable-delayed-privatization -o - %s 2>&1 | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false -fopenmp --openmp-enable-delayed-privatization \ +! RUN: -o - %s 2>&1 | FileCheck %s subroutine delayed_privatization_firstprivate implicit none diff --git a/flang/test/Lower/OpenMP/FIR/delayed-privatization-private.f90 b/flang/test/Lower/OpenMP/FIR/delayed-privatization-private.f90 index 2e9995ea1fd4c47e04161f7ff94ff7df66b144ce..b13687faa3f26da6d7fab04a91deb4ea1a7bd327 100644 --- a/flang/test/Lower/OpenMP/FIR/delayed-privatization-private.f90 +++ b/flang/test/Lower/OpenMP/FIR/delayed-privatization-private.f90 @@ -1,6 +1,9 @@ ! Test delayed privatization for the `private` clause. -! RUN: bbc -emit-fir -hlfir=false -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir -fopenmp -mmlir \ +! RUN: --openmp-enable-delayed-privatization -o - %s 2>&1 | FileCheck %s +! RUN: bbc -emit-fir -hlfir=false -fopenmp --openmp-enable-delayed-privatization \ +! RUN: -o - %s 2>&1 | FileCheck %s subroutine delayed_privatization_private implicit none diff --git a/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90 b/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90 new file mode 100644 index 0000000000000000000000000000000000000000..1998c3da23af5fe51313e874ab786af64e6e831b --- /dev/null +++ b/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90 @@ -0,0 +1,60 @@ +!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s --check-prefixes ALL,HOST +!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-device %s -o - | FileCheck %s --check-prefixes ALL + +program main + use, intrinsic :: iso_c_binding + implicit none + interface + subroutine any_interface() bind(c,name="any_interface") + use, intrinsic :: iso_c_binding + implicit none + !$omp declare target enter(any_interface) device_type(any) + end subroutine any_interface + + subroutine host_interface() bind(c,name="host_interface") + use, intrinsic :: iso_c_binding + implicit none + !$omp declare target enter(host_interface) device_type(host) + end subroutine host_interface + + subroutine device_interface() bind(c,name="device_interface") + use, intrinsic :: iso_c_binding + implicit none + !$omp declare target enter(device_interface) device_type(nohost) + end subroutine device_interface + + subroutine called_from_target_interface(f1, f2) bind(c,name="called_from_target_interface") + use, intrinsic :: iso_c_binding + implicit none + type(c_funptr),value :: f1 + type(c_funptr),value :: f2 + end subroutine called_from_target_interface + + subroutine called_from_host_interface(f1) bind(c,name="called_from_host_interface") + use, intrinsic :: iso_c_binding + implicit none + type(c_funptr),value :: f1 + end subroutine called_from_host_interface + + subroutine unused_unemitted_interface() bind(c,name="unused_unemitted_interface") + use, intrinsic :: iso_c_binding + implicit none + !$omp declare target enter(unused_unemitted_interface) device_type(nohost) + end subroutine unused_unemitted_interface + + end interface + + CALL called_from_host_interface(c_funloc(host_interface)) +!$omp target + CALL called_from_target_interface(c_funloc(any_interface), c_funloc(device_interface)) +!$omp end target + end program main + +!HOST-LABEL: func.func {{.*}} @host_interface() +!HOST-SAME: {{.*}}, omp.declare_target = #omp.declaretarget{{.*}} +!ALL-LABEL: func.func {{.*}} @called_from_target_interface(!fir.ref, !fir.ref) +!ALL-SAME: {{.*}}, omp.declare_target = #omp.declaretarget{{.*}} +!ALL-LABEL: func.func {{.*}} @any_interface() +!ALL-SAME: {{.*}}, omp.declare_target = #omp.declaretarget{{.*}} +!ALL-LABEL: func.func {{.*}} @device_interface() +!ALL-SAME: {{.*}}, omp.declare_target = #omp.declaretarget{{.*}} diff --git a/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 b/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 new file mode 100644 index 0000000000000000000000000000000000000000..7cd0597161578d4c2b388d60272de5c0ff0dbc58 --- /dev/null +++ b/flang/test/Lower/OpenMP/declare-target-link-tarop-cap.f90 @@ -0,0 +1,55 @@ +!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s +!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-device %s -o - | FileCheck %s +!RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s +!RUN: bbc -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s + +program test_link + + integer :: test_int = 1 + !$omp declare target link(test_int) + + integer :: test_array_1d(3) = (/1,2,3/) + !$omp declare target link(test_array_1d) + + integer, pointer :: test_ptr1 + !$omp declare target link(test_ptr1) + + integer, target :: test_target = 1 + !$omp declare target link(test_target) + + integer, pointer :: test_ptr2 + !$omp declare target link(test_ptr2) + + !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref, i32) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.ref {name = "test_int"} + !$omp target + test_int = test_int + 1 + !$omp end target + + + !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref>, !fir.array<3xi32>) map_clauses(implicit, tofrom) capture(ByRef) bounds({{%.*}}) -> !fir.ref> {name = "test_array_1d"} + !$omp target + do i = 1,3 + test_array_1d(i) = i * 2 + end do + !$omp end target + + allocate(test_ptr1) + test_ptr1 = 1 + !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref>>, !fir.box>) map_clauses(implicit, tofrom) capture(ByRef) members({{%.*}} : !fir.llvm_ptr>) -> !fir.ref>> {name = "test_ptr1"} + !$omp target + test_ptr1 = test_ptr1 + 1 + !$omp end target + + !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref, i32) map_clauses(implicit, tofrom) capture(ByRef) -> !fir.ref {name = "test_target"} + !$omp target + test_target = test_target + 1 + !$omp end target + + + !CHECK-DAG: {{%.*}} = omp.map_info var_ptr({{%.*}} : !fir.ref>>, !fir.box>) map_clauses(implicit, tofrom) capture(ByRef) members({{%.*}} : !fir.llvm_ptr>) -> !fir.ref>> {name = "test_ptr2"} + test_ptr2 => test_target + !$omp target + test_ptr2 = test_ptr2 + 1 + !$omp end target + +end diff --git a/flang/test/Lower/OpenMP/delayed-privatization-firstprivate.f90 b/flang/test/Lower/OpenMP/delayed-privatization-firstprivate.f90 index e3d2a5a8af26086a705eb80b7e0ec5c0ca3876ea..0fb81d68016a485e5c923ad9a39338f2c2d477c7 100644 --- a/flang/test/Lower/OpenMP/delayed-privatization-firstprivate.f90 +++ b/flang/test/Lower/OpenMP/delayed-privatization-firstprivate.f90 @@ -1,6 +1,9 @@ ! Test delayed privatization for the `firstprivate` clause. -! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --openmp-enable-delayed-privatization \ +! RUN: -o - %s 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 \ +! RUN: | FileCheck %s subroutine delayed_privatization_firstprivate implicit none diff --git a/flang/test/Lower/OpenMP/delayed-privatization-private-firstprivate.f90 b/flang/test/Lower/OpenMP/delayed-privatization-private-firstprivate.f90 index 46eef6eb3bcf6af8c17b0cbbc96d39fe67bdcce9..337e7d5ec885cb784c33dc6ad1d29d7d0457b890 100644 --- a/flang/test/Lower/OpenMP/delayed-privatization-private-firstprivate.f90 +++ b/flang/test/Lower/OpenMP/delayed-privatization-private-firstprivate.f90 @@ -1,6 +1,9 @@ ! Test delayed privatization for both `private` and `firstprivate` clauses. -! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --openmp-enable-delayed-privatization \ +! RUN: -o - %s 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 \ +! RUN: | FileCheck %s subroutine delayed_privatization_private_firstprivate implicit none diff --git a/flang/test/Lower/OpenMP/delayed-privatization-private.f90 b/flang/test/Lower/OpenMP/delayed-privatization-private.f90 index 240e0e71bfcd16ad18994a90573c694945e3819f..7208521bcd77e491bb4a880f2d7afd6bf860d39d 100644 --- a/flang/test/Lower/OpenMP/delayed-privatization-private.f90 +++ b/flang/test/Lower/OpenMP/delayed-privatization-private.f90 @@ -1,6 +1,9 @@ ! Test delayed privatization for the `private` clause. -! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --openmp-enable-delayed-privatization \ +! RUN: -o - %s 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 \ +! RUN: | FileCheck %s subroutine delayed_privatization_private implicit none diff --git a/flang/test/Lower/OpenMP/delayed-privatization-reduction.f90 b/flang/test/Lower/OpenMP/delayed-privatization-reduction.f90 index c61f352b9b055a0592010f3555d289d1b19a508c..a7eeb1faceadef85886920dad7b2420c7660f770 100644 --- a/flang/test/Lower/OpenMP/delayed-privatization-reduction.f90 +++ b/flang/test/Lower/OpenMP/delayed-privatization-reduction.f90 @@ -3,7 +3,10 @@ ! that the block arguments are added in the proper order (reductions first and ! then delayed privatization. -! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --openmp-enable-delayed-privatization \ +! RUN: -o - %s 2>&1 | FileCheck %s +! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 \ +! RUN: | FileCheck %s subroutine red_and_delayed_private integer :: red diff --git a/flang/test/Lower/OpenMP/parallel-private-clause-str.f90 b/flang/test/Lower/OpenMP/parallel-private-clause-str.f90 index f668957624b497116c2d2fffcc661990b54bfc0c..025e51e066176469aaa0f909d357d2ec94d996b0 100644 --- a/flang/test/Lower/OpenMP/parallel-private-clause-str.f90 +++ b/flang/test/Lower/OpenMP/parallel-private-clause-str.f90 @@ -10,7 +10,7 @@ !CHECK: %[[C_DECL:.*]]:2 = hlfir.declare %[[C_BOX_REF]] typeparams %{{.*}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_stringEc"} : (!fir.ref>>>, i32) -> (!fir.ref>>>, !fir.ref>>>) !CHECK: omp.parallel { !CHECK: %[[C_PVT_BOX_REF:.*]] = fir.alloca !fir.box>> {bindc_name = "c", pinned, uniq_name = "_QFtest_allocatable_stringEc"} -!CHECK: %[[C_BOX:.*]] = fir.load %[[C_DECL]]#1 : !fir.ref>>> +!CHECK: %[[C_BOX:.*]] = fir.load %[[C_DECL]]#0 : !fir.ref>>> !CHECK: fir.if %{{.*}} { !CHECK: %[[C_PVT_MEM:.*]] = fir.allocmem !fir.char<1,?>(%{{.*}} : index) {fir.must_be_heap = true, uniq_name = "_QFtest_allocatable_stringEc.alloc"} !CHECK: %[[C_PVT_BOX:.*]] = fir.embox %[[C_PVT_MEM]] typeparams %{{.*}} : (!fir.heap>, index) -> !fir.box>> @@ -18,7 +18,7 @@ !CHECK: } !CHECK: %[[C_PVT_DECL:.*]]:2 = hlfir.declare %[[C_PVT_BOX_REF]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_stringEc"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) !CHECK: fir.if %{{.*}} { -!CHECK: %[[C_PVT_BOX:.*]] = fir.load %[[C_PVT_DECL]]#1 : !fir.ref>>> +!CHECK: %[[C_PVT_BOX:.*]] = fir.load %[[C_PVT_DECL]]#0 : !fir.ref>>> !CHECK: %[[C_PVT_BOX_ADDR:.*]] = fir.box_addr %[[C_PVT_BOX]] : (!fir.box>>) -> !fir.heap> !CHECK: fir.freemem %[[C_PVT_BOX_ADDR]] : !fir.heap> !CHECK: } @@ -38,16 +38,16 @@ end subroutine !CHECK: %[[C_DECL:.*]]:2 = hlfir.declare %[[C_BOX_REF]] typeparams %{{.*}} {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_string_arrayEc"} : (!fir.ref>>>>, i32) -> (!fir.ref>>>>, !fir.ref>>>>) !CHECK: omp.parallel { !CHECK: %[[C_PVT_BOX_REF:.*]] = fir.alloca !fir.box>>> {bindc_name = "c", pinned, uniq_name = "_QFtest_allocatable_string_arrayEc"} -!CHECK: %{{.*}} = fir.load %[[C_DECL]]#1 : !fir.ref>>>> +!CHECK: %{{.*}} = fir.load %[[C_DECL]]#0 : !fir.ref>>>> !CHECK: fir.if %{{.*}} { !CHECK: %[[C_PVT_ALLOC:.*]] = fir.allocmem !fir.array>(%{{.*}} : index), %{{.*}} {fir.must_be_heap = true, uniq_name = "_QFtest_allocatable_string_arrayEc.alloc"} !CHECK: %[[C_PVT_BOX:.*]] = fir.embox %[[C_PVT_ALLOC]](%{{.*}}) typeparams %{{.*}} : (!fir.heap>>, !fir.shapeshift<1>, index) -> !fir.box>>> !CHECK: fir.store %[[C_PVT_BOX]] to %[[C_PVT_BOX_REF]] : !fir.ref>>>> !CHECK: } !CHECK: %[[C_PVT_DECL:.*]]:2 = hlfir.declare %[[C_PVT_BOX_REF]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFtest_allocatable_string_arrayEc"} : (!fir.ref>>>>) -> (!fir.ref>>>>, !fir.ref>>>>) -!CHECK: %{{.*}} = fir.load %[[C_PVT_DECL]]#1 : !fir.ref>>>> +!CHECK: %{{.*}} = fir.load %[[C_PVT_DECL]]#0 : !fir.ref>>>> !CHECK: fir.if %{{.*}} { -!CHECK: %[[C_PVT_BOX:.*]] = fir.load %[[C_PVT_DECL]]#1 : !fir.ref>>>> +!CHECK: %[[C_PVT_BOX:.*]] = fir.load %[[C_PVT_DECL]]#0 : !fir.ref>>>> !CHECK: %[[C_PVT_ADDR:.*]] = fir.box_addr %[[C_PVT_BOX]] : (!fir.box>>>) -> !fir.heap>> !CHECK: fir.freemem %[[C_PVT_ADDR]] : !fir.heap>> !CHECK: } diff --git a/flang/test/Lower/OpenMP/parallel-private-clause.f90 b/flang/test/Lower/OpenMP/parallel-private-clause.f90 index 3e46d315f8cc47ea67a646645a133ae06193cfa2..5578b6710da7cdc63566f124af2e35320b737bb4 100644 --- a/flang/test/Lower/OpenMP/parallel-private-clause.f90 +++ b/flang/test/Lower/OpenMP/parallel-private-clause.f90 @@ -150,8 +150,8 @@ end subroutine !FIRDialect-DAG: %[[X4_PVT:.*]] = fir.alloca !fir.box>> {bindc_name = "x4", pinned, uniq_name = "{{.*}}Ex4"} !FIRDialect-DAG: %[[X4_PVT_DECL:.*]]:2 = hlfir.declare %[[X4_PVT]] {fortran_attrs = #fir.var_attrs, uniq_name = "{{.*}}Ex4"} : (!fir.ref>>>) -> (!fir.ref>>>, !fir.ref>>>) -!FIRDialect-DAG: %[[TMP58:.*]] = fir.load %[[X4_DECL]]#1 : !fir.ref>>> -!FIRDialect-DAG: %[[TMP97:.*]] = fir.load %[[X4_DECL]]#1 : !fir.ref>>> +!FIRDialect-DAG: %[[TMP58:.*]] = fir.load %[[X4_DECL]]#0 : !fir.ref>>> +!FIRDialect-DAG: %[[TMP97:.*]] = fir.load %[[X4_DECL]]#0 : !fir.ref>>> !FIRDialect-DAG: %[[TMP98:.*]]:3 = fir.box_dims %[[TMP97]], {{.*}} : (!fir.box>>, index) -> (index, index, index) !FIRDialect-DAG: %[[TMP101:.*]] = fir.allocmem !fir.array, {{.*}} {fir.must_be_heap = true, uniq_name = "{{.*}}Ex4.alloc"} @@ -192,12 +192,12 @@ end subroutine !FIRDialect-DAG: } !FIRDialect-DAG: %[[X5_PVT_DECL:.*]]:2 = hlfir.declare %[[X5_PVT]] {fortran_attrs = #fir.var_attrs, uniq_name = "_QFprivate_clause_real_call_allocatableEx5"} : (!fir.ref>>) -> (!fir.ref>>, !fir.ref>>) !FIRDialect-DAG: fir.call @_QFprivate_clause_real_call_allocatablePhelper_private_clause_real_call_allocatable(%[[X5_PVT_DECL]]#0) fastmath : (!fir.ref>>) -> () -!FIRDialect-DAG: %{{.*}} = fir.load %[[X5_PVT_DECL]]#1 : !fir.ref>> +!FIRDialect-DAG: %{{.*}} = fir.load %[[X5_PVT_DECL]]#0 : !fir.ref>> !FIRDialect-DAG: fir.if %{{.*}} { -!FIRDialect-DAG: %{{.*}} = fir.load %[[X5_PVT_DECL]]#1 : !fir.ref>> +!FIRDialect-DAG: %{{.*}} = fir.load %[[X5_PVT_DECL]]#0 : !fir.ref>> -!FIRDialect-DAG: fir.store %{{.*}} to %[[X5_PVT_DECL]]#1 : !fir.ref>> +!FIRDialect-DAG: fir.store %{{.*}} to %[[X5_PVT_DECL]]#0 : !fir.ref>> !FIRDialect-DAG: } !FIRDialect-DAG: omp.terminator !FIRDialect-DAG: } @@ -313,12 +313,12 @@ subroutine simple_loop_1 print*, i end do ! FIRDialect: omp.yield - ! FIRDialect: {{%.*}} = fir.load %[[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: {{%.*}} = fir.load %[[R_DECL]]#0 : !fir.ref>> ! FIRDialect: fir.if {{%.*}} { - ! FIRDialect: [[LD:%.*]] = fir.load %[[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: [[LD:%.*]] = fir.load %[[R_DECL]]#0 : !fir.ref>> ! FIRDialect: [[AD:%.*]] = fir.box_addr [[LD]] : (!fir.box>) -> !fir.heap ! FIRDialect: fir.freemem [[AD]] : !fir.heap - ! FIRDialect: fir.store {{%.*}} to %[[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: fir.store {{%.*}} to %[[R_DECL]]#0 : !fir.ref>> !$OMP END DO ! FIRDialect: omp.terminator !$OMP END PARALLEL @@ -351,12 +351,12 @@ subroutine simple_loop_2 print*, i end do ! FIRDialect: omp.yield - ! FIRDialect: {{%.*}} = fir.load %[[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: {{%.*}} = fir.load %[[R_DECL]]#0 : !fir.ref>> ! FIRDialect: fir.if {{%.*}} { - ! FIRDialect: [[LD:%.*]] = fir.load %[[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: [[LD:%.*]] = fir.load %[[R_DECL]]#0 : !fir.ref>> ! FIRDialect: [[AD:%.*]] = fir.box_addr [[LD]] : (!fir.box>) -> !fir.heap ! FIRDialect: fir.freemem [[AD]] : !fir.heap - ! FIRDialect: fir.store {{%.*}} to %[[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: fir.store {{%.*}} to %[[R_DECL]]#0 : !fir.ref>> !$OMP END DO ! FIRDialect: omp.terminator !$OMP END PARALLEL @@ -388,12 +388,12 @@ subroutine simple_loop_3 print*, i end do ! FIRDialect: omp.yield - ! FIRDialect: {{%.*}} = fir.load [[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: {{%.*}} = fir.load [[R_DECL]]#0 : !fir.ref>> ! FIRDialect: fir.if {{%.*}} { - ! FIRDialect: [[LD:%.*]] = fir.load [[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: [[LD:%.*]] = fir.load [[R_DECL]]#0 : !fir.ref>> ! FIRDialect: [[AD:%.*]] = fir.box_addr [[LD]] : (!fir.box>) -> !fir.heap ! FIRDialect: fir.freemem [[AD]] : !fir.heap - ! FIRDialect: fir.store {{%.*}} to [[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: fir.store {{%.*}} to [[R_DECL]]#0 : !fir.ref>> !$OMP END PARALLEL DO ! FIRDialect: omp.terminator end subroutine @@ -421,10 +421,10 @@ subroutine simd_loop_1 end do !$OMP END SIMD ! FIRDialect: omp.yield - ! FIRDialect: {{%.*}} = fir.load [[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: {{%.*}} = fir.load [[R_DECL]]#0 : !fir.ref>> ! FIRDialect: fir.if {{%.*}} { - ! FIRDialect: [[LD:%.*]] = fir.load [[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: [[LD:%.*]] = fir.load [[R_DECL]]#0 : !fir.ref>> ! FIRDialect: [[AD:%.*]] = fir.box_addr [[LD]] : (!fir.box>) -> !fir.heap ! FIRDialect: fir.freemem [[AD]] : !fir.heap - ! FIRDialect: fir.store {{%.*}} to [[R_DECL]]#1 : !fir.ref>> + ! FIRDialect: fir.store {{%.*}} to [[R_DECL]]#0 : !fir.ref>> end subroutine diff --git a/flang/test/Lower/OpenMP/workshare.f90 b/flang/test/Lower/OpenMP/workshare.f90 new file mode 100644 index 0000000000000000000000000000000000000000..1e11677a15e1f03fc330e0951fe119df0b7fa06f --- /dev/null +++ b/flang/test/Lower/OpenMP/workshare.f90 @@ -0,0 +1,42 @@ + +!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s + +!CHECK-LABEL: func @_QPsb1 +subroutine sb1(arr) + integer :: arr(:) +!CHECK: omp.parallel { + !$omp parallel +!CHECK: omp.single { + !$omp workshare + arr = 0 + !$omp end workshare +!CHECK: } + !$omp end parallel +!CHECK: } +end subroutine + +!CHECK-LABEL: func @_QPsb2 +subroutine sb2(arr) + integer :: arr(:) +!CHECK: omp.parallel { + !$omp parallel +!CHECK: omp.single nowait { + !$omp workshare + arr = 0 + !$omp end workshare nowait +!CHECK: } + !$omp end parallel +!CHECK: } +end subroutine + +!CHECK-LABEL: func @_QPsb3 +subroutine sb3(arr) + integer :: arr(:) +!CHECK: omp.parallel { +!CHECK: omp.single { + !$omp parallel workshare + arr = 0 + !$omp end parallel workshare +!CHECK: } +!CHECK: } +end subroutine diff --git a/flang/test/Semantics/declarations06.f90 b/flang/test/Semantics/declarations06.f90 index 532b0461d391e621271fc6ee1c8ee54d869d6324..ae9ef6acd75423e52bdf182afcfeab7fd75dc9b7 100644 --- a/flang/test/Semantics/declarations06.f90 +++ b/flang/test/Semantics/declarations06.f90 @@ -16,6 +16,7 @@ module m procedure(cf1), pointer :: pp1 procedure(cf2), pointer :: pp2 procedure(cf3), pointer :: pp3 + procedure(cf5), pointer :: pp4 ! ok contains !ERROR: CLASS entity 'cf1' must be a dummy argument, allocatable, or object pointer class(t) function cf1() @@ -33,4 +34,12 @@ module m !ERROR: CLASS entity 'd3' must be a dummy argument, allocatable, or object pointer class(t), external, pointer :: d3 end + function cf4() + class(t), pointer :: cf4 + cf4 => v3 + end + function cf5 + procedure(cf4), pointer :: cf5 + cf5 => cf4 + end end diff --git a/flang/test/Semantics/forall01.f90 b/flang/test/Semantics/forall01.f90 index a81eb9621e77c645ccf116993057a1316178fa8f..72ad9ecd39471aaf08a4343e7959a29baf894f7d 100644 --- a/flang/test/Semantics/forall01.f90 +++ b/flang/test/Semantics/forall01.f90 @@ -135,3 +135,14 @@ subroutine forall7(x) end forall end select end subroutine + +subroutine forall8(x) + real :: x(10) + real, external :: foo + !ERROR: Impure procedure 'foo' may not be referenced in a FORALL + forall(i=1:10) x(i) = foo() + i + !OK + associate(y => foo()) + forall (i=1:10) x(i) = y + i + end associate +end subroutine diff --git a/flang/test/Semantics/init01.f90 b/flang/test/Semantics/init01.f90 index f58c034d5deab21e606ee752ba9675a0f8ad9276..f85feef097cdca5183b9e10f58eac48fbd6f34a7 100644 --- a/flang/test/Semantics/init01.f90 +++ b/flang/test/Semantics/init01.f90 @@ -8,6 +8,17 @@ subroutine objectpointers(j) real, save :: x3 real, target :: x4 real, target, save :: x5(10) + real, pointer :: x6 + type t1 + real, allocatable :: c1 + real, allocatable, codimension[:] :: c2 + real :: c3 + real :: c4(10) + real, pointer :: c5 + end type + type(t1), target, save :: o1 + type(t1), save :: o2 + type(t1), target :: o3 !ERROR: An initial data target may not be a reference to an ALLOCATABLE 'x1' real, pointer :: p1 => x1 !ERROR: An initial data target may not be a reference to a coarray 'x2' @@ -20,6 +31,52 @@ subroutine objectpointers(j) real, pointer :: p5 => x5(j) !ERROR: Pointer has rank 0 but target has rank 1 real, pointer :: p6 => x5 +!ERROR: An initial data target may not be a reference to a POINTER 'x6' + real, pointer :: p7 => x6 +!ERROR: An initial data target may not be a reference to an ALLOCATABLE 'c1' + real, pointer :: p1o => o1%c1 +!ERROR: An initial data target may not be a reference to a coarray 'c2' + real, pointer :: p2o => o1%c2 +!ERROR: An initial data target may not be a reference to an object 'o2' that lacks the TARGET attribute + real, pointer :: p3o => o2%c3 +!ERROR: An initial data target may not be a reference to an object 'o3' that lacks the SAVE attribute + real, pointer :: p4o => o3%c3 +!ERROR: An initial data target must be a designator with constant subscripts + real, pointer :: p5o => o1%c4(j) +!ERROR: Pointer has rank 0 but target has rank 1 + real, pointer :: p6o => o1%c4 +!ERROR: An initial data target may not be a reference to a POINTER 'c5' + real, pointer :: p7o => o1%c5 + type t2 + !ERROR: An initial data target may not be a reference to an ALLOCATABLE 'x1' + real, pointer :: p1 => x1 + !ERROR: An initial data target may not be a reference to a coarray 'x2' + real, pointer :: p2 => x2 + !ERROR: An initial data target may not be a reference to an object 'x3' that lacks the TARGET attribute + real, pointer :: p3 => x3 + !ERROR: An initial data target may not be a reference to an object 'x4' that lacks the SAVE attribute + real, pointer :: p4 => x4 + !ERROR: An initial data target must be a designator with constant subscripts + real, pointer :: p5 => x5(j) + !ERROR: Pointer has rank 0 but target has rank 1 + real, pointer :: p6 => x5 + !ERROR: An initial data target may not be a reference to a POINTER 'x6' + real, pointer :: p7 => x6 + !ERROR: An initial data target may not be a reference to an ALLOCATABLE 'c1' + real, pointer :: p1o => o1%c1 + !ERROR: An initial data target may not be a reference to a coarray 'c2' + real, pointer :: p2o => o1%c2 + !ERROR: An initial data target may not be a reference to an object 'o2' that lacks the TARGET attribute + real, pointer :: p3o => o2%c3 + !ERROR: An initial data target may not be a reference to an object 'o3' that lacks the SAVE attribute + real, pointer :: p4o => o3%c3 + !ERROR: An initial data target must be a designator with constant subscripts + real, pointer :: p5o => o1%c4(j) + !ERROR: Pointer has rank 0 but target has rank 1 + real, pointer :: p6o => o1%c4 + !ERROR: An initial data target may not be a reference to a POINTER 'c5' + real, pointer :: p7o => o1%c5 + end type !TODO: type incompatibility, non-deferred type parameter values, contiguity diff --git a/flang/test/Semantics/modfile64.f90 b/flang/test/Semantics/modfile64.f90 new file mode 100644 index 0000000000000000000000000000000000000000..e9df005c9ffd314c931250b5ef799e7cb6a0194b --- /dev/null +++ b/flang/test/Semantics/modfile64.f90 @@ -0,0 +1,29 @@ +! RUN: %python %S/test_modfile.py %s %flang_fc1 +module mod0 + interface proc + module procedure proc + end interface + contains + subroutine proc + end +end +module mod1 + use mod0,renamed_proc=>proc + procedure(renamed_proc),pointer :: p +end module + +!Expect: mod0.mod +!module mod0 +!interface proc +!procedure::proc +!end interface +!contains +!subroutine proc() +!end +!end + +!Expect: mod1.mod +!module mod1 +!use mod0,only:renamed_proc=>proc +!procedure(renamed_proc),pointer::p +!end diff --git a/flang/test/Semantics/null01.f90 b/flang/test/Semantics/null01.f90 index 71567fb0a67346551a0ad39fb0fcc2419310ebe9..b61d464d0e7ceed36c5f956b404ad9dc611761a3 100644 --- a/flang/test/Semantics/null01.f90 +++ b/flang/test/Semantics/null01.f90 @@ -65,12 +65,22 @@ subroutine test real(kind=eight) :: r8check logical, pointer :: lp ip0 => null() ! ok + ip0 => null(null()) ! ok + ip0 => null(null(null())) ! ok ip1 => null() ! ok + ip1 => null(null()) ! ok + ip1 => null(null(null())) ! ok ip2 => null() ! ok + ip2 => null(null()) ! ok + ip2 => null(null(null())) ! ok !ERROR: MOLD= argument to NULL() must be a pointer or allocatable ip0 => null(mold=1) !ERROR: MOLD= argument to NULL() must be a pointer or allocatable + ip0 => null(null(mold=1)) + !ERROR: MOLD= argument to NULL() must be a pointer or allocatable ip0 => null(mold=j) + !ERROR: MOLD= argument to NULL() must be a pointer or allocatable + ip0 => null(mold=null(mold=j)) dt0x = dt0(null()) dt0x = dt0(ip0=null()) dt0x = dt0(ip0=null(ip0)) diff --git a/flang/test/Semantics/resolve09.f90 b/flang/test/Semantics/resolve09.f90 index c5e4277b3b6114bbf26ff48c5702ccc209f2a76e..634b9861f3b67f1efdbb86c1732c5b2c78254dc5 100644 --- a/flang/test/Semantics/resolve09.f90 +++ b/flang/test/Semantics/resolve09.f90 @@ -52,25 +52,49 @@ contains end end -module m - ! subroutine vs. function is determined at end of specification part - external :: a - procedure() :: b +module m1 + !Function vs subroutine in a module is resolved to a subroutine if + !no other information. + external :: exts, extf, extunk + procedure() :: procs, procf, procunk contains - subroutine s() - call a() - !ERROR: Cannot call subroutine 'b' like a function - x = b() + subroutine s + call exts() + call procs() + x = extf() + x = procf() end end +module m2 + use m1 + contains + subroutine test + call exts() ! ok + call procs() ! ok + call extunk() ! ok + call procunk() ! ok + x = extf() ! ok + x = procf() ! ok + !ERROR: Cannot call subroutine 'extunk' like a function + !ERROR: Function result characteristics are not known + x = extunk() + !ERROR: Cannot call subroutine 'procunk' like a function + !ERROR: Function result characteristics are not known + x = procunk() + end +end + +module modulename +end + ! Call to entity in global scope, even with IMPORT, NONE subroutine s4 block import, none integer :: i - !ERROR: 'm' is not a callable procedure - call m() + !ERROR: 'modulename' is not a callable procedure + call modulename() end block end diff --git a/flang/test/Semantics/selecttype03.f90 b/flang/test/Semantics/selecttype03.f90 index eb343c4ccc5300462038b4bb396ec15b2f4ac7a6..c440960f404a3e3d231983942e8641b0668eab6f 100644 --- a/flang/test/Semantics/selecttype03.f90 +++ b/flang/test/Semantics/selecttype03.f90 @@ -65,7 +65,7 @@ select type (b => array1(V,2)) b%i = 1 !VDC type is (t2) !ERROR: Actual argument associated with INTENT(IN OUT) dummy argument 'z=' is not definable - !BECAUSE: Variable 'b' has a vector subscript + !BECAUSE: Construct association 'b' has a vector subscript call sub_with_in_and_inout_param_vector(b,b) !VDC end select select type(b => foo(1) ) diff --git a/flang/test/Semantics/selecttype04.f90 b/flang/test/Semantics/selecttype04.f90 new file mode 100644 index 0000000000000000000000000000000000000000..535576b0ac9aa59e147c0c705d5ed54721fbfb49 --- /dev/null +++ b/flang/test/Semantics/selecttype04.f90 @@ -0,0 +1,31 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +! Check F'2023 C1167 +module m + type :: base(kindparam, lenparam) + integer, kind :: kindparam + integer, len :: lenparam + end type + type, extends(base) :: ext1 + contains + procedure :: tbp + end type + type, extends(ext1) :: ext2 + end type + contains + function tbp(x) + class(ext1(123,*)), target :: x + class(ext1(123,:)), pointer :: tbp + tbp => x + end + subroutine test + type(ext1(123,456)), target :: var + select type (sel => var%tbp()) + type is (ext1(123,*)) ! ok + type is (ext2(123,*)) ! ok + !ERROR: Type specification 'ext1(kindparam=234_4,lenparam=*)' must be an extension of TYPE 'ext1(kindparam=123_4,lenparam=:)' + type is (ext1(234,*)) + !ERROR: Type specification 'ext2(kindparam=234_4,lenparam=*)' must be an extension of TYPE 'ext1(kindparam=123_4,lenparam=:)' + type is (ext2(234,*)) + end select + end +end diff --git a/flang/unittests/Frontend/FrontendActionTest.cpp b/flang/unittests/Frontend/FrontendActionTest.cpp index 6ec15832d96d3cb11aec687c8cc5a30d93ece45e..123f428cc8b40b1e0c289d158419cd9ddb5f46ad 100644 --- a/flang/unittests/Frontend/FrontendActionTest.cpp +++ b/flang/unittests/Frontend/FrontendActionTest.cpp @@ -198,7 +198,7 @@ TEST_F(FrontendActionTest, EmitLLVM) { EXPECT_TRUE(success); EXPECT_TRUE(!outputFileBuffer.empty()); - EXPECT_TRUE(llvm::StringRef(outputFileBuffer.data()) + EXPECT_TRUE(llvm::StringRef(outputFileBuffer.begin(), outputFileBuffer.size()) .contains("define void @_QQmain()")); } @@ -227,6 +227,7 @@ TEST_F(FrontendActionTest, EmitAsm) { EXPECT_TRUE(success); EXPECT_TRUE(!outputFileBuffer.empty()); - EXPECT_TRUE(llvm::StringRef(outputFileBuffer.data()).contains("_QQmain")); + EXPECT_TRUE(llvm::StringRef(outputFileBuffer.begin(), outputFileBuffer.size()) + .contains("_QQmain")); } } // namespace diff --git a/flang/unittests/Runtime/Ragged.cpp b/flang/unittests/Runtime/Ragged.cpp index 4b261b14789c47078960056a18c91ebcc4d7016c..5049bc83405f177c0142f8683330331bdaea9998 100644 --- a/flang/unittests/Runtime/Ragged.cpp +++ b/flang/unittests/Runtime/Ragged.cpp @@ -14,7 +14,7 @@ using namespace Fortran::runtime; TEST(Ragged, RaggedArrayAllocateDeallocateTest) { struct RaggedArrayHeader header; unsigned rank = 2; - int64_t *extents = new int64_t[2]; + int64_t *extents = reinterpret_cast(malloc(2 * sizeof(int64_t))); extents[0] = 10; extents[1] = 100; RaggedArrayHeader *ret = (RaggedArrayHeader *)_FortranARaggedArrayAllocate( diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 0b72b1c5481651bd413df6a310b68c2f9a959ac9..6edf5c656193db378d87e7aa72f24fff2a3f56ff 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -39,7 +39,11 @@ set(LIBC_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) set(LIBC_ENABLE_USE_BY_CLANG OFF CACHE BOOL "Whether or not to place libc in a build directory findable by a just built clang") # Defining a global namespace to enclose all libc functions. -set(LIBC_NAMESPACE "__llvm_libc_${LLVM_VERSION_MAJOR}_${LLVM_VERSION_MINOR}_${LLVM_VERSION_PATCH}_${LLVM_VERSION_SUFFIX}" +set(default_namespace "__llvm_libc") +if(LLVM_VERSION_MAJOR) + set(default_namespace "__llvm_libc_${LLVM_VERSION_MAJOR}_${LLVM_VERSION_MINOR}_${LLVM_VERSION_PATCH}_${LLVM_VERSION_SUFFIX}") +endif() +set(LIBC_NAMESPACE ${default_namespace} CACHE STRING "The namespace to use to enclose internal implementations. Must start with '__llvm_libc'." ) @@ -56,6 +60,10 @@ if(LLVM_LIBC_FULL_BUILD OR LLVM_LIBC_GPU_BUILD) message(STATUS "Will use ${LIBC_HDRGEN_EXE} for libc header generation.") endif() endif() +# We will build the GPU utilities if we are not doing a runtimes build. +if(LLVM_LIBC_GPU_BUILD AND NOT LLVM_RUNTIMES_BUILD) + add_subdirectory(utils/gpu) +endif() set(NEED_LIBC_HDRGEN FALSE) if(NOT LLVM_RUNTIMES_BUILD) @@ -75,11 +83,6 @@ if(LIBC_HDRGEN_ONLY OR NEED_LIBC_HDRGEN) # When libc is build as part of the runtimes/bootstrap build's CMake run, we # only need to build the host tools to build the libc. So, we just do enough # to build libc-hdrgen and return. - - # Always make the RPC server availible to other projects for GPU mode. - if(LLVM_LIBC_GPU_BUILD) - add_subdirectory(utils/gpu/server) - endif() return() endif() unset(NEED_LIBC_HDRGEN) @@ -232,7 +235,13 @@ else() set(LIBC_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}) endif() if(LIBC_TARGET_OS_IS_GPU) - set(LIBC_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) + if(LLVM_RUNTIMES_TARGET) + set(LIBC_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${LLVM_RUNTIMES_TARGET}) + elseif(LIBC_TARGET_TRIPLE) + set(LIBC_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${LIBC_TARGET_TRIPLE}) + else() + set(LIBC_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}) + endif() else() set(LIBC_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}) endif() diff --git a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake index 72b04822d8b84a6db749b3eb3227596cba99a59d..5bc0898298ce39ddcf4dd5b7ec0b59e21e2bb1aa 100644 --- a/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake +++ b/libc/cmake/modules/LLVMLibCCompileOptionRules.cmake @@ -2,10 +2,10 @@ function(_get_compile_options_from_flags output_var) set(compile_options "") if(LIBC_TARGET_ARCHITECTURE_IS_RISCV64 OR(LIBC_CPU_FEATURES MATCHES "FMA")) - check_flag(ADD_FMA_FLAG ${FMA_OPT_FLAG} ${flags}) + check_flag(ADD_FMA_FLAG ${FMA_OPT_FLAG} ${ARGN}) endif() - check_flag(ADD_SSE4_2_FLAG ${ROUND_OPT_FLAG} ${flags}) - check_flag(ADD_EXPLICIT_SIMD_OPT_FLAG ${EXPLICIT_SIMD_OPT_FLAG} ${flags}) + check_flag(ADD_SSE4_2_FLAG ${ROUND_OPT_FLAG} ${ARGN}) + check_flag(ADD_EXPLICIT_SIMD_OPT_FLAG ${EXPLICIT_SIMD_OPT_FLAG} ${ARGN}) if(LLVM_COMPILER_IS_GCC_COMPATIBLE) if(ADD_FMA_FLAG) @@ -108,7 +108,7 @@ function(_get_common_compile_options output_var flags) set(${output_var} ${compile_options} PARENT_SCOPE) endfunction() -function(_get_common_test_compile_options output_var flags) +function(_get_common_test_compile_options output_var c_test flags) _get_compile_options_from_flags(compile_flags ${flags}) set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT} ${compile_flags}) @@ -122,7 +122,9 @@ function(_get_common_test_compile_options output_var flags) list(APPEND compile_options "-fno-exceptions") list(APPEND compile_options "-fno-unwind-tables") list(APPEND compile_options "-fno-asynchronous-unwind-tables") - list(APPEND compile_options "-fno-rtti") + if(NOT ${c_test}) + list(APPEND compile_options "-fno-rtti") + endif() endif() if(LIBC_COMPILER_HAS_FIXED_POINT) diff --git a/libc/cmake/modules/LLVMLibCFlagRules.cmake b/libc/cmake/modules/LLVMLibCFlagRules.cmake index 9bec716516f288083d39abaa40f0e272a7ee3677..18e36dfde5cc194898691363fb8e3b7d8b9ac4be 100644 --- a/libc/cmake/modules/LLVMLibCFlagRules.cmake +++ b/libc/cmake/modules/LLVMLibCFlagRules.cmake @@ -131,9 +131,9 @@ endfunction(get_fq_dep_list_without_flag) # Check if a `flag` is set function(check_flag result flag_name) - list(FIND ARGN ${flag_name}_FLAG has_flag) + list(FIND ARGN ${flag_name} has_flag) if(${has_flag} LESS 0) - list(FIND ARGN "${flag_name}_FLAG__ONLY" has_flag) + list(FIND ARGN "${flag_name}__ONLY" has_flag) endif() if(${has_flag} GREATER -1) set(${result} TRUE PARENT_SCOPE) diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake index 836e15d34741b2aa516e7d72baa8671010acb48d..eb6be91b55e2619a54115958670b2d3e256c602f 100644 --- a/libc/cmake/modules/LLVMLibCTestRules.cmake +++ b/libc/cmake/modules/LLVMLibCTestRules.cmake @@ -111,7 +111,7 @@ function(create_libc_unittest fq_target_name) cmake_parse_arguments( "LIBC_UNITTEST" - "NO_RUN_POSTBUILD" # Optional arguments + "NO_RUN_POSTBUILD;C_TEST" # Optional arguments "SUITE;CXX_STANDARD" # Single value arguments "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS;LINK_LIBRARIES;FLAGS" # Multi-value arguments ${ARGN} @@ -126,11 +126,14 @@ function(create_libc_unittest fq_target_name) endif() get_fq_deps_list(fq_deps_list ${LIBC_UNITTEST_DEPENDS}) - list(APPEND fq_deps_list libc.src.__support.StringUtil.error_to_string - libc.test.UnitTest.ErrnoSetterMatcher) + if(NOT LIBC_UNITTEST_C_TEST) + list(APPEND fq_deps_list libc.src.__support.StringUtil.error_to_string + libc.test.UnitTest.ErrnoSetterMatcher) + endif() list(REMOVE_DUPLICATES fq_deps_list) - _get_common_test_compile_options(compile_options "${LIBC_UNITTEST_FLAGS}") + _get_common_test_compile_options(compile_options "${LIBC_UNITTEST_C_TEST}" + "${LIBC_UNITTEST_FLAGS}") list(APPEND compile_options ${LIBC_UNITTEST_COMPILE_OPTIONS}) if(SHOW_INTERMEDIATE_OBJECTS) @@ -214,7 +217,9 @@ function(create_libc_unittest fq_target_name) ) # LibcUnitTest should not depend on anything in LINK_LIBRARIES. - list(APPEND link_libraries LibcDeathTestExecutors.unit LibcTest.unit) + if(NOT LIBC_UNITTEST_C_TEST) + list(APPEND link_libraries LibcDeathTestExecutors.unit LibcTest.unit) + endif() target_link_libraries(${fq_build_target_name} PRIVATE ${link_libraries}) @@ -595,9 +600,11 @@ function(add_libc_hermetic_test test_name) get_object_files_for_test( link_object_files skipped_entrypoints_list ${fq_deps_list}) if(skipped_entrypoints_list) - set(msg "Skipping hermetic test ${fq_target_name} as it has missing deps: " - "${skipped_entrypoints_list}.") - message(STATUS ${msg}) + if(LIBC_CMAKE_VERBOSE_LOGGING) + set(msg "Skipping hermetic test ${fq_target_name} as it has missing deps: " + "${skipped_entrypoints_list}.") + message(STATUS ${msg}) + endif() return() endif() list(REMOVE_DUPLICATES link_object_files) diff --git a/libc/cmake/modules/prepare_libc_gpu_build.cmake b/libc/cmake/modules/prepare_libc_gpu_build.cmake index 7e9fc746ea91d96ed77c6117b7756f2e3157f38e..bea6bb016491b6e8b8aff7a53134a03cc57ba457 100644 --- a/libc/cmake/modules/prepare_libc_gpu_build.cmake +++ b/libc/cmake/modules/prepare_libc_gpu_build.cmake @@ -48,10 +48,20 @@ endif() set(LIBC_GPU_TEST_ARCHITECTURE "" CACHE STRING "Architecture for the GPU tests") if(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) - check_cxx_compiler_flag("-nogpulib -mcpu=native" PLATFORM_HAS_GPU) + # Identify any locally installed NVIDIA GPUs on the system using 'nvptx-arch'. + find_program(LIBC_AMDGPU_ARCH + NAMES amdgpu-arch NO_DEFAULT_PATH + PATHS ${LLVM_BINARY_DIR}/bin ${compiler_path}) + if(LIBC_AMDGPU_ARCH) + execute_process(COMMAND ${LIBC_AMDGPU_ARCH} + OUTPUT_VARIABLE arch_tool_output + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(arch_tool_output MATCHES "^gfx[0-9]+") + set(PLATFORM_HAS_GPU TRUE) + endif() + endif() elseif(LIBC_TARGET_ARCHITECTURE_IS_NVPTX) # Identify any locally installed NVIDIA GPUs on the system using 'nvptx-arch'. - # Using 'check_cxx_compiler_flag' does not work currently due to the link job. find_program(LIBC_NVPTX_ARCH NAMES nvptx-arch NO_DEFAULT_PATH PATHS ${LLVM_BINARY_DIR}/bin ${compiler_path}) @@ -83,6 +93,41 @@ else() endif() set(LIBC_GPU_TARGET_ARCHITECTURE "${gpu_test_architecture}") +# Identify the GPU loader utility used to run tests. +set(LIBC_GPU_LOADER_EXECUTABLE "" CACHE STRING "Executable for the GPU loader.") +if(LIBC_GPU_LOADER_EXECUTABLE) + set(gpu_loader_executable ${LIBC_GPU_LOADER_EXECUTABLE}) +elseif(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) + find_program(LIBC_AMDHSA_LOADER_EXECUTABLE + NAMES amdhsa-loader NO_DEFAULT_PATH + PATHS ${LLVM_BINARY_DIR}/bin ${compiler_path}) + if(LIBC_AMDHSA_LOADER_EXECUTABLE) + set(gpu_loader_executable ${LIBC_AMDHSA_LOADER_EXECUTABLE}) + endif() +elseif(LIBC_TARGET_ARCHITECTURE_IS_NVPTX) + find_program(LIBC_NVPTX_LOADER_EXECUTABLE + NAMES nvptx-loader NO_DEFAULT_PATH + PATHS ${LLVM_BINARY_DIR}/bin ${compiler_path}) + if(LIBC_NVPTX_LOADER_EXECUTABLE) + set(gpu_loader_executable ${LIBC_NVPTX_LOADER_EXECUTABLE}) + endif() +endif() +if(NOT TARGET libc.utils.gpu.loader AND gpu_loader_executable) + add_custom_target(libc.utils.gpu.loader) + set_target_properties( + libc.utils.gpu.loader + PROPERTIES + EXECUTABLE "${gpu_loader_executable}" + ) +endif() + +if(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) + # The AMDGPU environment uses different code objects to encode the ABI for + # kernel calls and intrinsic functions. We want to specify this manually to + # conform to whatever the test suite was built to handle. + set(LIBC_GPU_CODE_OBJECT_VERSION 5) +endif() + if(LIBC_TARGET_ARCHITECTURE_IS_NVPTX) # FIXME: This is a hack required to keep the CUDA package from trying to find # pthreads. We only link the CUDA driver, so this is unneeded. @@ -93,10 +138,3 @@ if(LIBC_TARGET_ARCHITECTURE_IS_NVPTX) get_filename_component(LIBC_CUDA_ROOT "${CUDAToolkit_BIN_DIR}" DIRECTORY ABSOLUTE) endif() endif() - -if(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) - # The AMDGPU environment uses different code objects to encode the ABI for - # kernel calls and intrinsic functions. We want to specify this manually to - # conform to whatever the test suite was built to handle. - set(LIBC_GPU_CODE_OBJECT_VERSION 5) -endif() diff --git a/libc/config/baremetal/api.td b/libc/config/baremetal/api.td index 3da83d9eb30cff55cf2d0cf63b11c0990dc1cf72..33b3a03828e9c7427b18f5b7e059672e2bc458de 100644 --- a/libc/config/baremetal/api.td +++ b/libc/config/baremetal/api.td @@ -1,6 +1,8 @@ include "config/public_api.td" include "spec/stdc.td" +include "spec/stdc_ext.td" +include "spec/llvm_libc_stdfix_ext.td" def AssertMacro : MacroDef<"assert"> { let Defn = [{ diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt index a61d9feac2938db1d81cd71a2b9956a295a92729..6e4fdb0362643655f8d7053c5cd59dbca965c225 100644 --- a/libc/config/baremetal/arm/entrypoints.txt +++ b/libc/config/baremetal/arm/entrypoints.txt @@ -76,7 +76,6 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdio.vsprintf libc.src.stdio.vsnprintf - # stdbit.h entrypoints libc.src.stdbit.stdc_leading_zeros_uc libc.src.stdbit.stdc_leading_zeros_us @@ -280,6 +279,40 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.truncl ) +if(LIBC_COMPILER_HAS_FIXED_POINT) + list(APPEND TARGET_LIBM_ENTRYPOINTS + # stdfix.h _Fract and _Accum entrypoints + libc.src.stdfix.abshk + libc.src.stdfix.abshr + libc.src.stdfix.absk + libc.src.stdfix.absr + libc.src.stdfix.abslk + libc.src.stdfix.abslr + libc.src.stdfix.exphk + libc.src.stdfix.expk + libc.src.stdfix.roundhk + libc.src.stdfix.roundhr + libc.src.stdfix.roundk + libc.src.stdfix.roundr + libc.src.stdfix.roundlk + libc.src.stdfix.roundlr + libc.src.stdfix.rounduhk + libc.src.stdfix.rounduhr + libc.src.stdfix.rounduk + libc.src.stdfix.roundur + libc.src.stdfix.roundulk + libc.src.stdfix.roundulr + libc.src.stdfix.sqrtuhk + libc.src.stdfix.sqrtuhr + libc.src.stdfix.sqrtuk + libc.src.stdfix.sqrtur + # libc.src.stdfix.sqrtulk + libc.src.stdfix.sqrtulr + libc.src.stdfix.uhksqrtus + libc.src.stdfix.uksqrtui + ) +endif() + set(TARGET_LLVMLIBC_ENTRYPOINTS ${TARGET_LIBC_ENTRYPOINTS} ${TARGET_LIBM_ENTRYPOINTS} diff --git a/libc/config/baremetal/arm/headers.txt b/libc/config/baremetal/arm/headers.txt index 4c02ac84018d8589ad751d03603a27982b9de3a6..68d7017fda8027bc1eef453ac6e40ed1dc0b45eb 100644 --- a/libc/config/baremetal/arm/headers.txt +++ b/libc/config/baremetal/arm/headers.txt @@ -4,8 +4,10 @@ set(TARGET_PUBLIC_HEADERS libc.include.fenv libc.include.errno libc.include.float + libc.include.stdint libc.include.inttypes libc.include.math + libc.include.stdfix libc.include.stdio libc.include.stdlib libc.include.string diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt index 533f9f9f3685069f9e951f20219463e63fd842f5..6e4fdb0362643655f8d7053c5cd59dbca965c225 100644 --- a/libc/config/baremetal/riscv/entrypoints.txt +++ b/libc/config/baremetal/riscv/entrypoints.txt @@ -279,6 +279,40 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.truncl ) +if(LIBC_COMPILER_HAS_FIXED_POINT) + list(APPEND TARGET_LIBM_ENTRYPOINTS + # stdfix.h _Fract and _Accum entrypoints + libc.src.stdfix.abshk + libc.src.stdfix.abshr + libc.src.stdfix.absk + libc.src.stdfix.absr + libc.src.stdfix.abslk + libc.src.stdfix.abslr + libc.src.stdfix.exphk + libc.src.stdfix.expk + libc.src.stdfix.roundhk + libc.src.stdfix.roundhr + libc.src.stdfix.roundk + libc.src.stdfix.roundr + libc.src.stdfix.roundlk + libc.src.stdfix.roundlr + libc.src.stdfix.rounduhk + libc.src.stdfix.rounduhr + libc.src.stdfix.rounduk + libc.src.stdfix.roundur + libc.src.stdfix.roundulk + libc.src.stdfix.roundulr + libc.src.stdfix.sqrtuhk + libc.src.stdfix.sqrtuhr + libc.src.stdfix.sqrtuk + libc.src.stdfix.sqrtur + # libc.src.stdfix.sqrtulk + libc.src.stdfix.sqrtulr + libc.src.stdfix.uhksqrtus + libc.src.stdfix.uksqrtui + ) +endif() + set(TARGET_LLVMLIBC_ENTRYPOINTS ${TARGET_LIBC_ENTRYPOINTS} ${TARGET_LIBM_ENTRYPOINTS} diff --git a/libc/config/baremetal/riscv/headers.txt b/libc/config/baremetal/riscv/headers.txt index 4c02ac84018d8589ad751d03603a27982b9de3a6..68d7017fda8027bc1eef453ac6e40ed1dc0b45eb 100644 --- a/libc/config/baremetal/riscv/headers.txt +++ b/libc/config/baremetal/riscv/headers.txt @@ -4,8 +4,10 @@ set(TARGET_PUBLIC_HEADERS libc.include.fenv libc.include.errno libc.include.float + libc.include.stdint libc.include.inttypes libc.include.math + libc.include.stdfix libc.include.stdio libc.include.stdlib libc.include.string diff --git a/libc/config/darwin/arm/headers.txt b/libc/config/darwin/arm/headers.txt index d80628445af5c5276944fa8d030283026089d4fd..86e7145972324ad7c8befe3deca8f14ffd2e766c 100644 --- a/libc/config/darwin/arm/headers.txt +++ b/libc/config/darwin/arm/headers.txt @@ -3,6 +3,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.errno libc.include.fenv libc.include.float + libc.include.stdint libc.include.inttypes libc.include.limits libc.include.math diff --git a/libc/config/darwin/x86_64/headers.txt b/libc/config/darwin/x86_64/headers.txt index 1e81e303ddd6b47ed7c3d4e25483242b8d85206e..acd2402649877482f0e9b1698e8b01d68576094e 100644 --- a/libc/config/darwin/x86_64/headers.txt +++ b/libc/config/darwin/x86_64/headers.txt @@ -4,6 +4,7 @@ set(TARGET_PUBLIC_HEADERS # Fenv is currently disabled. #libc.include.fenv libc.include.float + libc.include.stdint libc.include.inttypes libc.include.limits libc.include.math diff --git a/libc/config/gpu/api.td b/libc/config/gpu/api.td index dbd212be56a3f10ddd48bed780516ca6ff408b17..607b8b6d5900c8909437ffdbc2c9e25039db8230 100644 --- a/libc/config/gpu/api.td +++ b/libc/config/gpu/api.td @@ -4,6 +4,7 @@ include "spec/stdc.td" include "spec/posix.td" include "spec/gpu_ext.td" include "spec/gnu_ext.td" +include "spec/stdc_ext.td" include "spec/llvm_libc_ext.td" def AssertMacro : MacroDef<"assert"> { diff --git a/libc/config/gpu/headers.txt b/libc/config/gpu/headers.txt index 3b04dd89fafe6f721b0b9c52c106307185bd0761..dd16938da8a447c2e332124b7146a66ba8b33f47 100644 --- a/libc/config/gpu/headers.txt +++ b/libc/config/gpu/headers.txt @@ -3,6 +3,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.ctype libc.include.string libc.include.float + libc.include.stdint libc.include.inttypes libc.include.limits libc.include.math diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 06832a41221dd8dcefb25f0b9ef34b31e4516ca8..1656973cb27c8a01371bb45952d1d15863654144 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -51,6 +51,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.mempcpy libc.src.string.memrchr libc.src.string.memset + libc.src.string.memset_explicit libc.src.string.rindex libc.src.string.stpcpy libc.src.string.stpncpy @@ -184,6 +185,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.mman.munlock libc.src.sys.mman.mlockall libc.src.sys.mman.munlockall + libc.src.sys.mman.msync # sys/random.h entrypoints libc.src.sys.random.getrandom @@ -333,6 +335,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fminl libc.src.math.fmod libc.src.math.fmodf + libc.src.math.fmodl libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl @@ -424,11 +427,18 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.floorf128 libc.src.math.fmaxf128 libc.src.math.fminf128 + libc.src.math.fmodf128 libc.src.math.frexpf128 libc.src.math.ilogbf128 libc.src.math.ldexpf128 libc.src.math.llogbf128 libc.src.math.logbf128 + libc.src.math.llrintf128 + libc.src.math.llroundf128 + libc.src.math.lrintf128 + libc.src.math.lroundf128 + libc.src.math.modff128 + libc.src.math.rintf128 libc.src.math.roundf128 libc.src.math.sqrtf128 libc.src.math.truncf128 diff --git a/libc/config/linux/aarch64/headers.txt b/libc/config/linux/aarch64/headers.txt index 21b880cf2bb9bba0e3cfa61714f06a45a5d44d34..47db4434b09b33d6ccde3c2f4369c3165200b65b 100644 --- a/libc/config/linux/aarch64/headers.txt +++ b/libc/config/linux/aarch64/headers.txt @@ -5,6 +5,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.features libc.include.fenv libc.include.float + libc.include.stdint libc.include.inttypes libc.include.limits libc.include.math diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td index 5a1d7642f1aebedf8cf4b756de05841221038e8c..75432a2a29865226ef98e9d45101bdd69a994076 100644 --- a/libc/config/linux/api.td +++ b/libc/config/linux/api.td @@ -5,8 +5,9 @@ include "spec/posix.td" include "spec/linux.td" include "spec/gnu_ext.td" include "spec/bsd_ext.td" -include "spec/llvm_libc_ext.td" include "spec/stdc_ext.td" +include "spec/llvm_libc_ext.td" +include "spec/llvm_libc_stdfix_ext.td" def AssertMacro : MacroDef<"assert"> { let Defn = [{ diff --git a/libc/config/linux/arm/headers.txt b/libc/config/linux/arm/headers.txt index 268c8c41702af51ddc8dcb58ae370cf7184b16be..307bb6b146a4ccb51d1e98651061b5949a7f370d 100644 --- a/libc/config/linux/arm/headers.txt +++ b/libc/config/linux/arm/headers.txt @@ -3,6 +3,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.fenv libc.include.errno libc.include.float + libc.include.stdint libc.include.inttypes libc.include.math libc.include.stdckdint diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index bf518083b51f554abd6f1aa697ece56b97688525..07d1acfcfe079d9ef36127681332666bb50a31b7 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -190,6 +190,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.mman.munlock libc.src.sys.mman.mlockall libc.src.sys.mman.munlockall + libc.src.sys.mman.msync # sys/random.h entrypoints libc.src.sys.random.getrandom @@ -342,6 +343,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fmaxl libc.src.math.fmod libc.src.math.fmodf + libc.src.math.fmodl libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl @@ -433,11 +435,18 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.floorf128 libc.src.math.fmaxf128 libc.src.math.fminf128 + libc.src.math.fmodf128 libc.src.math.frexpf128 libc.src.math.ilogbf128 libc.src.math.ldexpf128 libc.src.math.llogbf128 libc.src.math.logbf128 + libc.src.math.llrintf128 + libc.src.math.llroundf128 + libc.src.math.lrintf128 + libc.src.math.lroundf128 + libc.src.math.modff128 + libc.src.math.rintf128 libc.src.math.roundf128 libc.src.math.sqrtf128 libc.src.math.truncf128 diff --git a/libc/config/linux/riscv/headers.txt b/libc/config/linux/riscv/headers.txt index 3ebea2e2b07bfbc7b77bd4e23d562b9cc51bbc8f..c858bcc978d9dab5b97dcc6ad183262e92b47374 100644 --- a/libc/config/linux/riscv/headers.txt +++ b/libc/config/linux/riscv/headers.txt @@ -7,6 +7,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.features libc.include.fenv libc.include.float + libc.include.stdint libc.include.inttypes libc.include.limits libc.include.math diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index bc10512d942fa7f450e84e9741a2ccc0935851bc..e0324061a9c78c05e947007523858ea751f20173 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -51,6 +51,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.string.mempcpy libc.src.string.memrchr libc.src.string.memset + libc.src.string.memset_explicit libc.src.string.rindex libc.src.string.stpcpy libc.src.string.stpncpy @@ -147,6 +148,21 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.stdbit.stdc_has_single_bit_ui libc.src.stdbit.stdc_has_single_bit_ul libc.src.stdbit.stdc_has_single_bit_ull + libc.src.stdbit.stdc_bit_width_uc + libc.src.stdbit.stdc_bit_width_us + libc.src.stdbit.stdc_bit_width_ui + libc.src.stdbit.stdc_bit_width_ul + libc.src.stdbit.stdc_bit_width_ull + libc.src.stdbit.stdc_bit_floor_uc + libc.src.stdbit.stdc_bit_floor_us + libc.src.stdbit.stdc_bit_floor_ui + libc.src.stdbit.stdc_bit_floor_ul + libc.src.stdbit.stdc_bit_floor_ull + libc.src.stdbit.stdc_bit_ceil_uc + libc.src.stdbit.stdc_bit_ceil_us + libc.src.stdbit.stdc_bit_ceil_ui + libc.src.stdbit.stdc_bit_ceil_ul + libc.src.stdbit.stdc_bit_ceil_ull # stdlib.h entrypoints libc.src.stdlib.abs @@ -212,6 +228,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.sys.mman.munlock libc.src.sys.mman.mlockall libc.src.sys.mman.munlockall + libc.src.sys.mman.msync # sys/random.h entrypoints libc.src.sys.random.getrandom @@ -359,6 +376,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fmaxl libc.src.math.fmod libc.src.math.fmodf + libc.src.math.fmodl libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl @@ -452,11 +470,18 @@ if(LIBC_TYPES_HAS_FLOAT128) libc.src.math.floorf128 libc.src.math.fmaxf128 libc.src.math.fminf128 + libc.src.math.fmodf128 libc.src.math.frexpf128 libc.src.math.ilogbf128 libc.src.math.ldexpf128 libc.src.math.llogbf128 libc.src.math.logbf128 + libc.src.math.llrintf128 + libc.src.math.llroundf128 + libc.src.math.lrintf128 + libc.src.math.lroundf128 + libc.src.math.modff128 + libc.src.math.rintf128 libc.src.math.roundf128 libc.src.math.sqrtf128 libc.src.math.truncf128 @@ -472,6 +497,8 @@ if(LIBC_COMPILER_HAS_FIXED_POINT) libc.src.stdfix.absr libc.src.stdfix.abslk libc.src.stdfix.abslr + libc.src.stdfix.exphk + libc.src.stdfix.expk libc.src.stdfix.roundhk libc.src.stdfix.roundhr libc.src.stdfix.roundk @@ -490,6 +517,8 @@ if(LIBC_COMPILER_HAS_FIXED_POINT) libc.src.stdfix.sqrtur # libc.src.stdfix.sqrtulk libc.src.stdfix.sqrtulr + libc.src.stdfix.uhksqrtus + libc.src.stdfix.uksqrtui ) endif() diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt index a887eba6805bca670826a7c2a54bdd4cc3ddbe07..e51c79319427062f15c1db14f7a8c01c720889ba 100644 --- a/libc/config/linux/x86_64/headers.txt +++ b/libc/config/linux/x86_64/headers.txt @@ -7,6 +7,7 @@ set(TARGET_PUBLIC_HEADERS libc.include.features libc.include.fenv libc.include.float + libc.include.stdint libc.include.inttypes libc.include.limits libc.include.math diff --git a/libc/config/windows/entrypoints.txt b/libc/config/windows/entrypoints.txt index 1c9ed7bbcfed690a05a74dc0163d6c609e0df78c..d6227a427afe2b86860e3f4f9bbfea177f390edc 100644 --- a/libc/config/windows/entrypoints.txt +++ b/libc/config/windows/entrypoints.txt @@ -155,6 +155,7 @@ set(TARGET_LIBM_ENTRYPOINTS libc.src.math.fmaxl libc.src.math.fmod libc.src.math.fmodf + libc.src.math.fmodl libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl diff --git a/libc/docs/c23.rst b/libc/docs/c23.rst index ec9d40947cc5670e1c0685ddc7e43b9e4afe1012..24cef8539393df897d111ffe06b993df6bc11f05 100644 --- a/libc/docs/c23.rst +++ b/libc/docs/c23.rst @@ -15,36 +15,15 @@ Implementation Status (It's helpful to review 'Annex B (Informative) Library Summary' for these.) -New headers: - -* stdbit.h -* stdckdint.h (|check|, macros are only defined with `__GNUC__` builtins) Additions: -* uchar.h - - * mbrtoc8 - * c8rtomb - * char*_t - -* string.h - - * memset_explicit - * memccpy - * strdup - * strndup - -* time.h - - * gmtime_r - * localtime_r - * timegm - * timespec_getres - * strftime conversion specifiers +* fenv.h - * 0b - * 0B + * fesetexcept + * fetestexceptflag + * fegetmode + * fesetmode * math.h * acospi* @@ -96,20 +75,87 @@ Additions: * dfmal * fsqrt* * dsqrtl -* fenv.h - - * fesetexcept - * fetestexceptflag - * fegetmode - * fesetmode +* stdbit.h (New header) +* stdckdint.h (New header) |check| * stddef.h * unreachable * stdlib.h + * strfromd + * strfromf + * strfroml * free_sized * free_aligned_sized * memalignment +* string.h + + * memset_explicit |check| + * memccpy + * strdup + * strndup * tgmath.h - * + * acospi + * asinpi + * atan2pi + * atanpi + * compoundn + * cospi + * erf + * exp10m1 + * exp10 + * exp2m1 + * fmaximum + * fmaximum_mag + * fmaximum_num + * fmaximum_mag_num + * fminimum + * fminimum_mag + * fminimum_num + * fminimum_mag_num + * fromfpx + * fromfp + * llogb + * log10p1 + * log2p1 + * logp1 + * nextdown + * nextup + * pown + * powr + * rootn + * roundeven + * rsqrt + * scalbn + * sinpi + * tanpi + * ufromfpx + * ufromfp + * fadd + * dadd + * fsub + * dsub + * fmul + * dmul + * fdiv + * ddiv + * ffma + * dfma + * fsqrt + * dsqrt +* time.h + + * gmtime_r + * localtime_r + * timegm + * timespec_getres + * strftime conversion specifiers + + * 0b + * 0B +* uchar.h + + * mbrtoc8 + * c8rtomb + * char*_t diff --git a/libc/docs/full_cross_build.rst b/libc/docs/full_cross_build.rst index f06464534f152d695dc351185d371bf81edd76c2..100e17a977e764b2744a4647fed4b6c4cd306e39 100644 --- a/libc/docs/full_cross_build.rst +++ b/libc/docs/full_cross_build.rst @@ -94,6 +94,8 @@ The above ``ninja`` command will build the libc static archives ``libc.a`` and ``libm.a`` for the target specified with ``-DLIBC_TARGET_TRIPLE`` in the CMake configure step. +.. _runtimes_cross_build: + Runtimes cross build ==================== @@ -230,3 +232,12 @@ component of the target triple as ``none``. For example, to build for a 32-bit arm target on bare metal, one can use a target triple like ``arm-none-eabi``. Other than that, the libc for a bare metal target can be built using any of the three recipes described above. + +Building for the GPU +==================== + +To build for a GPU architecture, it should only be necessary to specify the +target triple as one of the supported GPU targets. Currently, this is either +``nvptx64-nvidia-cuda`` for NVIDIA GPUs or ``amdgcn-amd-amdhsa`` for AMD GPUs. +More detailed information is provided in the :ref:`GPU +documentation`. diff --git a/libc/docs/gpu/building.rst b/libc/docs/gpu/building.rst new file mode 100644 index 0000000000000000000000000000000000000000..dab21e1324d2817218e5fa3e6a8cf3a6bd287823 --- /dev/null +++ b/libc/docs/gpu/building.rst @@ -0,0 +1,246 @@ +.. _libc_gpu_building: + +====================== +Building libs for GPUs +====================== + +.. contents:: Table of Contents + :depth: 4 + :local: + +Building the GPU C library +========================== + +This document will present recipes to build the LLVM C library targeting a GPU +architecture. The GPU build uses the same :ref:`cross build` +support as the other targets. However, the GPU target has the restriction that +it *must* be built with an up-to-date ``clang`` compiler. This is because the +GPU target uses several compiler extensions to target GPU architectures. + +The LLVM C library currently supports two GPU targets. This is either +``nvptx64-nvidia-cuda`` for NVIDIA GPUs or ``amdgcn-amd-amdhsa`` for AMD GPUs. +Targeting these architectures is done through ``clang``'s cross-compiling +support using the ``--target=`` flag. The following sections will +describe how to build the GPU support specifically. + +Once you have finished building, refer to :ref:`libc_gpu_usage` to get started +with the newly built C library. + +Standard runtimes build +----------------------- + +The simplest way to build the GPU libc is to use the existing LLVM runtimes +support. This will automatically handle bootstrapping an up-to-date ``clang`` +compiler and using it to build the C library. The following CMake invocation +will instruct it to build the ``libc`` runtime targeting both AMD and NVIDIA +GPUs. + +.. code-block:: sh + + $> cd llvm-project # The llvm-project checkout + $> mkdir build + $> cd build + $> cmake ../llvm -G Ninja \ + -DLLVM_ENABLE_PROJECTS="clang;lld" \ + -DLLVM_ENABLE_RUNTIMES="openmp" \ + -DCMAKE_BUILD_TYPE= \ # Select build type + -DCMAKE_INSTALL_PREFIX= \ # Where the libraries will live + -DRUNTIMES_nvptx64-nvidia-cuda_LLVM_ENABLE_RUNTIMES=libc \ + -DRUNTIMES_amdgcn-amd-amdhsa_LLVM_ENABLE_RUNTIMES=libc \ + -DLLVM_RUNTIME_TARGETS="default;amdgcn-amd-amdhsa;nvptx64-nvidia-cuda" + $> ninja install + +We need ``clang`` to build the GPU C library and ``lld`` to link AMDGPU +executables, so we enable them in ``LLVM_ENABLE_PROJECTS``. We add ``openmp`` to +``LLVM_ENABLED_RUNTIMES`` so it is built for the default target and provides +OpenMP support. We then set ``RUNTIMES__LLVM_ENABLE_RUNTIMES`` to enable +``libc`` for the GPU targets. The ``LLVM_RUNTIME_TARGETS`` sets the enabled +targets to build, in this case we want the default target and the GPU targets. +Note that if ``libc`` were included in ``LLVM_ENABLE_RUNTIMES`` it would build +targeting the default host environment as well. + +Runtimes cross build +-------------------- + +For users wanting more direct control over the build process, the build steps +can be done manually instead. This build closely follows the instructions in the +:ref:`main documentation` but is specialized for the GPU +build. We follow the same steps to first build the libc tools and a suitable +compiler. These tools must all be up-to-date with the libc source. + +.. code-block:: sh + + $> cd llvm-project # The llvm-project checkout + $> mkdir build-libc-tools # A different build directory for the build tools + $> cd build-libc-tools + $> HOST_C_COMPILER= # For example "clang" + $> HOST_CXX_COMPILER= # For example "clang++" + $> cmake ../llvm \ + -G Ninja \ + -DLLVM_ENABLE_PROJECTS="clang;libc" \ + -DCMAKE_C_COMPILER=$HOST_C_COMPILER \ + -DCMAKE_CXX_COMPILER=$HOST_CXX_COMPILER \ + -DLLVM_LIBC_FULL_BUILD=ON \ + -DLIBC_HDRGEN_ONLY=ON \ # Only build the 'libc-hdrgen' tool + -DCMAKE_BUILD_TYPE=Release # Release suggested to make "clang" fast + $> ninja # Build the 'clang' compiler + $> ninja libc-hdrgen # Build the 'libc-hdrgen' tool + +Once this has finished the build directory should contain the ``clang`` compiler +and the ``libc-hdrgen`` executable. We will use the ``clang`` compiler to build +the GPU code and the ``libc-hdrgen`` tool to create the necessary headers. We +use these tools to bootstrap the build out of the runtimes directory targeting a +GPU architecture. + +.. code-block:: sh + + $> cd llvm-project # The llvm-project checkout + $> mkdir build # A different build directory for the build tools + $> cd build + $> TARGET_TRIPLE= + $> TARGET_C_COMPILER= + $> TARGET_CXX_COMPILER= + $> HDRGEN= + $> cmake ../runtimes \ # Point to the runtimes build + -G Ninja \ + -DLLVM_ENABLE_RUNTIMES=libc \ + -DCMAKE_C_COMPILER=$TARGET_C_COMPILER \ + -DCMAKE_CXX_COMPILER=$TARGET_CXX_COMPILER \ + -DLLVM_LIBC_FULL_BUILD=ON \ + -DLLVM_RUNTIMES_TARGET=$TARGET_TRIPLE \ + -DLIBC_HDRGEN_EXE=$HDRGEN \ + -DCMAKE_BUILD_TYPE=Release + $> ninja install + +The above steps will result in a build targeting one of the supported GPU +architectures. Building for multiple targets requires separate CMake +invocations. + +Standalone cross build +---------------------- + +The GPU build can also be targeted directly as long as the compiler used is a +supported ``clang`` compiler. This method is generally not recommended as it can +only target a single GPU architecture. + +.. code-block:: sh + + $> cd llvm-project # The llvm-project checkout + $> mkdir build # A different build directory for the build tools + $> cd build + $> CLANG_C_COMPILER= # Must be a trunk build + $> CLANG_CXX_COMPILER= # Must be a trunk build + $> TARGET_TRIPLE= + $> cmake ../llvm \ # Point to the llvm directory + -G Ninja \ + -DLLVM_ENABLE_PROJECTS=libc \ + -DCMAKE_C_COMPILER=$CLANG_C_COMPILER \ + -DCMAKE_CXX_COMPILER=$CLANG_CXX_COMPILER \ + -DLLVM_LIBC_FULL_BUILD=ON \ + -DLIBC_TARGET_TRIPLE=$TARGET_TRIPLE \ + -DCMAKE_BUILD_TYPE=Release + $> ninja install + +This will build and install the GPU C library along with all the other LLVM +libraries. + +Build overview +============== + +Once installed, the GPU build will create several files used for different +targets. This section will briefly describe their purpose. + +**lib//libcgpu-amdgpu.a or lib/libcgpu-amdgpu.a** + A static library containing fat binaries supporting AMD GPUs. These are built + using the support described in the `clang documentation + `_. These are intended to + be static libraries included natively for offloading languages like CUDA, HIP, + or OpenMP. This implements the standard C library. + +**lib//libmgpu-amdgpu.a or lib/libmgpu-amdgpu.a** + A static library containing fat binaries that implements the standard math + library for AMD GPUs. + +**lib//libcgpu-nvptx.a or lib/libcgpu-nvptx.a** + A static library containing fat binaries that implement the standard C library + for NVIDIA GPUs. + +**lib//libmgpu-nvptx.a or lib/libmgpu-nvptx.a** + A static library containing fat binaries that implement the standard math + library for NVIDIA GPUs. + +**include/** + The include directory where all of the generated headers for the target will + go. These definitions are strictly for the GPU when being targeted directly. + +**lib/clang//include/llvm-libc-wrappers/llvm-libc-decls** + These are wrapper headers created for offloading languages like CUDA, HIP, or + OpenMP. They contain functions supported in the GPU libc along with attributes + and metadata that declare them on the target device and make them compatible + with the host headers. + +**lib//libc.a** + The main C library static archive containing LLVM-IR targeting the given GPU. + It can be linked directly or inspected depending on the target support. + +**lib//libm.a** + The C library static archive providing implementations of the standard math + functions. + +**lib//libc.bc** + An alternate form of the library provided as a single LLVM-IR bitcode blob. + This can be used similarly to NVIDIA's or AMD's device libraries. + +**lib//libm.bc** + An alternate form of the library provided as a single LLVM-IR bitcode blob + containing the standard math functions. + +**lib//crt1.o** + An LLVM-IR file containing startup code to call the ``main`` function on the + GPU. This is used similarly to the standard C library startup object. + +**bin/amdhsa-loader** + A binary utility used to launch executables compiled targeting the AMD GPU. + This will be included if the build system found the ``hsa-runtime64`` library + either in ``/opt/rocm`` or the current CMake installation directory. This is + required to build the GPU tests .See the :ref:`libc GPU usage` + for more information. + +**bin/nvptx-loader** + A binary utility used to launch executables compiled targeting the NVIDIA GPU. + This will be included if the build system found the CUDA driver API. This is + required for building tests. + +**include/llvm-libc-rpc-server.h** + A header file containing definitions that can be used to interface with the + :ref:`RPC server`. + +**lib/libllvmlibc_rpc_server.a** + The static library containing the implementation of the RPC server. This can + be used to enable host services for anyone looking to interface with the + :ref:`RPC client`. + +CMake options +============= + +This section briefly lists a few of the CMake variables that specifically +control the GPU build of the C library. + +**LLVM_LIBC_FULL_BUILD**:BOOL + This flag controls whether or not the libc build will generate its own + headers. This must always be on when targeting the GPU. + +**LIBC_GPU_TEST_ARCHITECTURE**:STRING + Sets the architecture used to build the GPU tests for, such as ``gfx90a`` or + ``sm_80`` for AMD and NVIDIA GPUs respectively. The default behavior is to + detect the system's GPU architecture using the ``native`` option. If this + option is not set and a GPU was not detected the tests will not be built. + +**LIBC_GPU_TEST_JOBS**:STRING + Sets the number of threads used to run GPU tests. The GPU test suite will + commonly run out of resources if this is not constrained so it is recommended + to keep it low. The default value is a single thread. + +**LIBC_GPU_LOADER_EXECUTABLE**:STRING + Overrides the default loader used for running GPU tests. If this is not + provided the standard one will be built. diff --git a/libc/docs/gpu/index.rst b/libc/docs/gpu/index.rst index 2d765486665040a48b011c03ddc599b34a533dee..1fca67205acb4dd0bfc0d8feb51b08d03415acda 100644 --- a/libc/docs/gpu/index.rst +++ b/libc/docs/gpu/index.rst @@ -12,8 +12,9 @@ learn more about this project. .. toctree:: + building using support - testing rpc + testing motivation diff --git a/libc/docs/gpu/rpc.rst b/libc/docs/gpu/rpc.rst index 7b0b35af4da88cd92a32c35d17e345c4450cefb5..9d6d8099db951c9366dbb46f5eac9e5f7a9b13ee 100644 --- a/libc/docs/gpu/rpc.rst +++ b/libc/docs/gpu/rpc.rst @@ -188,6 +188,8 @@ in the GPU executable as an indicator for whether or not the server can be checked. These details should ideally be handled by the GPU language runtime, but the following example shows how it can be used by a standard user. +.. _libc_gpu_cuda_server: + .. code-block:: cuda #include diff --git a/libc/docs/gpu/using.rst b/libc/docs/gpu/using.rst index 1a48c8a3bcba3156b3d67e42a5d3d81492ef9ab2..11a00cd620d8661789eba5c91384dd87a00dc3d1 100644 --- a/libc/docs/gpu/using.rst +++ b/libc/docs/gpu/using.rst @@ -1,6 +1,5 @@ .. _libc_gpu_usage: - =================== Using libc for GPUs =================== @@ -9,54 +8,98 @@ Using libc for GPUs :depth: 4 :local: -Building the GPU library -======================== - -LLVM's libc GPU support *must* be built with an up-to-date ``clang`` compiler -due to heavy reliance on ``clang``'s GPU support. This can be done automatically -using the LLVM runtimes support. The GPU build is done using cross-compilation -to the GPU architecture. This project currently supports AMD and NVIDIA GPUs -which can be targeted using the appropriate target name. The following -invocation will enable a cross-compiling build for the GPU architecture and -enable the ``libc`` project only for them. +Using the GPU C library +======================= + +Once you have finished :ref:`building` the GPU C library it +can be used to run libc or libm functions directly on the GPU. Currently, not +all C standard functions are supported on the GPU. Consult the :ref:`list of +supported functions` for a comprehensive list. + +The GPU C library supports two main usage modes. The first is as a supplementary +library for offloading languages such as OpenMP, CUDA, or HIP. These aim to +provide standard system utilities similarly to existing vendor libraries. The +second method treats the GPU as a hosted target by compiling C or C++ for it +directly. This is more similar to targeting OpenCL and is primarily used for +exported functions on the GPU and testing. + +Offloading usage +---------------- + +Offloading languages like CUDA, HIP, or OpenMP work by compiling a single source +file for both the host target and a list of offloading devices. In order to +support standard compilation flows, the ``clang`` driver uses fat binaries, +described in the `clang documentation +`_. This linking mode is used +by the OpenMP toolchain, but is currently opt-in for the CUDA and HIP toolchains +through the ``--offload-new-driver``` and ``-fgpu-rdc`` flags. + +The installation should contain a static library called ``libcgpu-amdgpu.a`` or +``libcgpu-nvptx.a`` depending on which GPU architectures your build targeted. +These contain fat binaries compatible with the offloading toolchain such that +they can be used directly. .. code-block:: sh - $> cd llvm-project # The llvm-project checkout - $> mkdir build - $> cd build - $> cmake ../llvm -G Ninja \ - -DLLVM_ENABLE_PROJECTS="clang;lld;compiler-rt" \ - -DLLVM_ENABLE_RUNTIMES="openmp" \ - -DCMAKE_BUILD_TYPE= \ # Select build type - -DCMAKE_INSTALL_PREFIX= \ # Where 'libcgpu.a' will live - -DRUNTIMES_nvptx64-nvidia-cuda_LLVM_ENABLE_RUNTIMES=libc \ - -DRUNTIMES_amdgcn-amd-amdhsa_LLVM_ENABLE_RUNTIMES=libc \ - -DLLVM_RUNTIME_TARGETS=default;amdgcn-amd-amdhsa;nvptx64-nvidia-cuda - $> ninja install - -Since we want to include ``clang``, ``lld`` and ``compiler-rt`` in our -toolchain, we list them in ``LLVM_ENABLE_PROJECTS``. To ensure ``libc`` is built -using a compatible compiler and to support ``openmp`` offloading, we list them -in ``LLVM_ENABLE_RUNTIMES`` to build them after the enabled projects using the -newly built compiler. ``CMAKE_INSTALL_PREFIX`` specifies the installation -directory in which to install the ``libcgpu-nvptx.a`` and ``libcgpu-amdgpu.a`` -libraries and headers along with LLVM. The generated headers will be placed in -``include/``. - -Usage -===== - -Once the static archive has been built it can be linked directly -with offloading applications as a standard library. This process is described in -the `clang documentation `_. -This linking mode is used by the OpenMP toolchain, but is currently opt-in for -the CUDA and HIP toolchains through the ``--offload-new-driver``` and -``-fgpu-rdc`` flags. A typical usage will look this this: + $> clang opnemp.c -fopenmp --offload-arch=gfx90a -lcgpu-amdgpu + $> clang cuda.cu --offload-arch=sm_80 --offload-new-driver -fgpu-rdc -lcgpu-nvptx + $> clang hip.hip --offload-arch=gfx940 --offload-new-driver -fgpu-rdc -lcgpu-amdgpu + +This will automatically link in the needed function definitions if they were +required by the user's application. Normally using the ``-fgpu-rdc`` option +results in sub-par performance due to ABA linking. However, the offloading +toolchain supports the ``--foffload-lto`` option to support LTO on the target +device. + +Offloading languages require that functions present on the device be declared as +such. This is done with the ``__device__`` keyword in CUDA and HIP or the +``declare target`` pragma in OpenMP. This requires that the LLVM C library +exposes its implemented functions to the compiler when it is used to build. We +support this by providing wrapper headers in the compiler's resource directory. +These are located in ``/include/llvm-libc-wrappers`` in your +installation. + +The support for HIP and CUDA is more experimental, requiring manual intervention +to link and use the facilities. An example of this is shown in the :ref:`CUDA +server example`. The OpenMP Offloading toolchain is +completely integrated with the LLVM C library however. It will automatically +handle including the necessary libraries, define device-side interfaces, and run +the RPC server. + +OpenMP Offloading example +^^^^^^^^^^^^^^^^^^^^^^^^^ + +This section provides a simple example of compiling an OpenMP program with the +GPU C library. + +.. code-block:: c++ + + #include + + int main() { + FILE *file = stderr; + #pragma omp target teams num_teams(2) thread_limit(2) + #pragma omp parallel num_threads(2) + { fputs("Hello from OpenMP!\n", file); } + } + +This can simply be compiled like any other OpenMP application to print from two +threads and two blocks. .. code-block:: sh - $> clang foo.c -fopenmp --offload-arch=gfx90a -lcgpu + $> clang openmp.c -fopenmp --offload-arch=gfx90a + $> ./a.out + Hello from OpenMP! + Hello from OpenMP! + Hello from OpenMP! + Hello from OpenMP! + +Including the wrapper headers, linking the C library, and running the :ref:`RPC +server` are all handled automatically by the compiler and runtime. + +Binary format +^^^^^^^^^^^^^ The ``libcgpu.a`` static archive is a fat-binary containing LLVM-IR for each supported target device. The supported architectures can be seen using LLVM's @@ -64,25 +107,145 @@ supported target device. The supported architectures can be seen using LLVM's .. code-block:: sh - $> llvm-objdump --offloading libcgpu.a - libcgpu.a(strcmp.cpp.o): file format elf64-x86-64 + $> llvm-objdump --offloading libcgpu-amdgpu.a + libcgpu-amdgpu.a(strcmp.cpp.o): file format elf64-x86-64 OFFLOADING IMAGE [0]: kind llvm ir arch generic triple amdgcn-amd-amdhsa producer none + ... Because the device code is stored inside a fat binary, it can be difficult to inspect the resulting code. This can be done using the following utilities: .. code-block:: sh - $> llvm-ar x libcgpu.a strcmp.cpp.o - $> clang-offload-packager strcmp.cpp.o --image=arch=gfx90a,file=gfx90a.bc - $> opt -S out.bc - ... + $> llvm-ar x libcgpu.a strcmp.cpp.o + $> clang-offload-packager strcmp.cpp.o --image=arch=generic,file=strcmp.bc + $> opt -S out.bc + ... Please note that this fat binary format is provided for compatibility with existing offloading toolchains. The implementation in ``libc`` does not depend on any existing offloading languages and is completely freestanding. + +Direct compilation +------------------ + +Instead of using standard offloading languages, we can also target the CPU +directly using C and C++ to create a GPU executable similarly to OpenCL. This is +done by targeting the GPU architecture using `clang's cross compilation +support `_. This is the +method that the GPU C library uses both to build the library and to run tests. + +This allows us to easily define GPU specific libraries and programs that fit +well into existing tools. In order to target the GPU effectively we rely heavily +on the compiler's intrinsic and built-in functions. For example, the following +function gets the thread identifier in the 'x' dimension on both GPUs supported +GPUs. + +.. code-block:: c++ + + uint32_t get_thread_id_x() { + #if defined(__AMDGPU__) + return __builtin_amdgcn_workitem_id_x(); + #elif defined(__NVPTX__) + return __nvvm_read_ptx_sreg_tid_x(); + #else + #error "Unsupported platform" + #endif + } + +We can then compile this for both NVPTX and AMDGPU into LLVM-IR using the +following commands. + +.. code-block:: sh + + $> clang id.c --target=amdgcn-amd-amdhsa -mcpu=native -nogpulib -flto -c + $> clang id.c --target=nvptx64-nvidia-cuda -march=native -nogpulib -flto -c + +We use this support to treat the GPU as a hosted environment by providing a C +library and startup object just like a standard C library running on the host +machine. Then, in order to execute these programs, we provide a loader utility +to launch the executable on the GPU similar to a cross-compiling emulator. + +Building for AMDGPU targets +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The AMDGPU target supports several features natively by virtue of using ``lld`` +as its linker. The installation will include the ``include/amdgcn-amd-amdhsa`` +and ``lib/amdgcn-amd-amdha`` directories that contain the necessary code to use +the library. We can directly link against ``libc.a`` and use LTO to generate the +final executable. + +.. code-block:: c++ + + #include + + int main() { fputs("Hello from AMDGPU!\n", stdout); } + +This program can then be compiled using the ``clang`` compiler. Note that +``-flto`` and ``-mcpu=`` should be defined. This is because the GPU +sub-architectures do not have strict backwards compatibility. Use ``-mcpu=help`` +for accepted arguments or ``-mcpu=native`` to target the system's installed GPUs +if present. Additionally, the AMDGPU target always uses ``-flto`` because we +currently do not fully support ELF linking in ``lld``. Once built, we use the +``amdhsa-loader`` utility to launch execution on the GPU. This will be built if +the ``hsa_runtime64`` library was found during build time. + +.. code-block:: sh + + $> clang hello.c --target=amdgcn-amd-amdhsa -mcpu=native -flto -lc /lib/amdgcn-amd-amdhsa/crt1.o + $> amdhsa-loader --threads 2 --blocks 2 a.out + Hello from AMDGPU! + Hello from AMDGPU! + Hello from AMDGPU! + Hello from AMDGPU! + +This will include the ``stdio.h`` header, which is found in the +``include/amdgcn-amd-amdhsa`` directory. We define out ``main`` function like a +standard application. The startup utility in ``lib/amdgcn-amd-amdhsa/crt1.o`` +will handle the necessary steps to execute the ``main`` function along with +global initializers and command line arguments. Finally, we link in the +``libc.a`` library stored in ``lib/amdgcn-amd-amdhsa`` to define the standard C +functions. + +The search paths for the include directories and libraries are automatically +handled by the compiler. We use this support internally to run unit tests on the +GPU directly. See :ref:`libc_gpu_testing` for more information. The installation +also provides ``libc.bc`` which is a single LLVM-IR bitcode blob that can be +used instead of the static library. + +Building for NVPTX targets +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The infrastructure is the same as the AMDGPU example. However, the NVPTX binary +utilities are very limited and must be targeted directly. There is no linker +support for static libraries so we need to link in the ``libc.bc`` bitcode and +inform the compiler driver of the file's contents. + +.. code-block:: c++ + + #include + + int main(int argc, char **argv, char **envp) { + fputs("Hello from NVPTX!\n", stdout); + } + +Additionally, the NVPTX ABI requires that every function signature matches. This +requires us to pass the full prototype from ``main``. The installation will +contain the ``nvptx-loader`` utility if the CUDA driver was found during +compilation. + +.. code-block:: sh + + $> clang hello.c --target=nvptx64-nvidia-cuda -march=native \ + -x ir /lib/nvptx64-nvidia-cuda/libc.bc \ + -x ir /lib/nvptx64-nvidia-cuda/crt1.o + $> nvptx-loader --threads 2 --blocks 2 a.out + Hello from NVPTX! + Hello from NVPTX! + Hello from NVPTX! + Hello from NVPTX! diff --git a/libc/docs/index.rst b/libc/docs/index.rst index a50eb080c9ee49f23180d0e1696bb736b24bbcbd..370fcd843974e848272ca05ebfb450b91628b479 100644 --- a/libc/docs/index.rst +++ b/libc/docs/index.rst @@ -78,6 +78,7 @@ stages there is no ABI stability in any form. dev/index.rst porting contributing + talks .. toctree:: :hidden: diff --git a/libc/docs/math/index.rst b/libc/docs/math/index.rst index 80d12718edccda0dd8154923329fc1292ba4a337..6984b785125f1a25fb8584591cc3e184057d39db 100644 --- a/libc/docs/math/index.rst +++ b/libc/docs/math/index.rst @@ -169,7 +169,9 @@ Basic Operations +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | fmodf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ -| fmodl | | | | | | | | | | | | | +| fmodl | |check| | |check| | | |check| | |check| | | | |check| | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| fmodf128 | |check| | |check| | | |check| | | | | | | | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | frexp | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ @@ -209,12 +211,16 @@ Basic Operations +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | llrintl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| llrintf128 | |check| | |check| | | |check| | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | llround | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | llroundf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | llroundl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| llroundf128 | |check| | |check| | | |check| | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | logb | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | logbf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | @@ -229,18 +235,24 @@ Basic Operations +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | lrintl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| lrintf128 | |check| | |check| | | |check| | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | lround | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | lroundf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | lroundl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| lroundf128 | |check| | |check| | | |check| | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | modf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | modff | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | modfl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| modff128 | |check| | |check| | | |check| | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | nan | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | nanf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | @@ -283,6 +295,8 @@ Basic Operations +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | rintl | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ +| rintf128 | |check| | |check| | | |check| | | | | | | | | | ++--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | round | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | +--------------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+---------+ | roundf | |check| | |check| | |check| | |check| | |check| | | | |check| | |check| | |check| | | | @@ -555,13 +569,13 @@ Legends: Performance =========== -* Simple performance testings are located at: `libc/test/src/math/differential_testing `_. +* Simple performance testings are located at: `libc/test/src/math/performance_testing `_. * We also use the *perf* tool from the `CORE-MATH `_ project: `link `_. The performance results from the CORE-MATH's perf tool are reported in the table below, using the system library as reference (such as the `GNU C library `_ - on Linux). Fmod performance results obtained with "differential_testing". + on Linux). Fmod performance results obtained with "performance_testing". +--------------+-------------------------------+-------------------------------+-------------------------------------+----------------------------------------------------------------------+ | | Reciprocal throughput (clk) | Latency (clk) | Testing ranges | Testing configuration | diff --git a/libc/docs/math/stdfix.rst b/libc/docs/math/stdfix.rst index 79f499e61f121c12895cef81ea935350cabde6c5..d8dcb0cfa4c521d527c6d863f751e72edca1fe23 100644 --- a/libc/docs/math/stdfix.rst +++ b/libc/docs/math/stdfix.rst @@ -4,14 +4,19 @@ StdFix Functions .. include:: ../check.rst -Standards ---------- +Standards and Goals +------------------- - stdfix.h is specified in the `ISO/IEC TR 18037:2008 `_, C extensions to support embedded processors . - Its `specifications `_. +- Our goal is to implement a complete set of math functions for fixed point + types, most of them are currently not included in the ISO/IEC TR + 18037:2008 standard. Our math functions for fixed point types are modeled + after the C99/C23 math functions for floating point types. + --------------- Source location --------------- @@ -53,6 +58,8 @@ Predefined Macros Fixed-point Arithmetics ======================= +The following functions are included in the ISO/IEC TR 18037:2008 standard. + +---------------+------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------+ | Function Name | _Fract (r) | _Accum (k) | | +------------------------------+----------------------------+------------------------------+------------------------------+----------------------------+------------------------------+ @@ -78,8 +85,6 @@ Fixed-point Arithmetics +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+ | round | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+ -| sqrt | |check| | | |check| | | |check| | | |check| | | |check| | | | | -+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+ ================== ========= Type Generic Macro Available @@ -93,6 +98,9 @@ roundfx Higher math functions ===================== +The following math functions are modeled after C99/C23 math functions for +floating point types, but are not part of the ISO/IEC TR 18037:2008 spec. + +---------------+------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------+ | Function Name | _Fract (r) | _Accum (k) | | +------------------------------+----------------------------+------------------------------+------------------------------+----------------------------+------------------------------+ @@ -102,12 +110,14 @@ Higher math functions +===============+================+=============+===============+============+================+=============+================+=============+===============+============+================+=============+ | cos | | | | | | | | | | | | | +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+ -| exp | | | | | | | | | | | | | +| exp | | | | | | | | |check| | | |check| | | | +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+ | log | | | | | | | | | | | | | +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+ | sin | | | | | | | | | | | | | +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+ +| sqrt | |check| | | |check| | | |check| | | |check| | | |check| | | | | ++---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+ | tan | | | | | | | | | | | | | +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+ @@ -115,6 +125,9 @@ Higher math functions Conversion Functions ==================== +The following conversion functions are included in the ISO/IEC TR 18037:2008 +standard. + +---------------+------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------+ | Function Name | _Fract (r) | _Accum (k) | | +------------------------------+----------------------------+------------------------------+------------------------------+----------------------------+------------------------------+ diff --git a/libc/docs/stdbit.rst b/libc/docs/stdbit.rst index b579e9dbbc2f5129b6ad2fa6bd068eb3adbaedf1..9b4974cf1479b1682e3301c1a5ba30756ca1a304 100644 --- a/libc/docs/stdbit.rst +++ b/libc/docs/stdbit.rst @@ -86,21 +86,21 @@ stdc_has_single_bit_us |check| stdc_has_single_bit_ui |check| stdc_has_single_bit_ul |check| stdc_has_single_bit_ull |check| -stdc_bit_width_uc -stdc_bit_width_us -stdc_bit_width_ui -stdc_bit_width_ul -stdc_bit_width_ull -stdc_bit_floor_uc -stdc_bit_floor_us -stdc_bit_floor_ui -stdc_bit_floor_ul -stdc_bit_floor_ull -stdc_bit_ceil_uc -stdc_bit_ceil_us -stdc_bit_ceil_ui -stdc_bit_ceil_ul -stdc_bit_ceil_ull +stdc_bit_width_uc |check| +stdc_bit_width_us |check| +stdc_bit_width_ui |check| +stdc_bit_width_ul |check| +stdc_bit_width_ull |check| +stdc_bit_floor_uc |check| +stdc_bit_floor_us |check| +stdc_bit_floor_ui |check| +stdc_bit_floor_ul |check| +stdc_bit_floor_ull |check| +stdc_bit_ceil_uc |check| +stdc_bit_ceil_us |check| +stdc_bit_ceil_ui |check| +stdc_bit_ceil_ul |check| +stdc_bit_ceil_ull |check| ============================ ========= @@ -125,9 +125,9 @@ stdc_first_trailing_one |check| stdc_count_zeros |check| stdc_count_ones |check| stdc_has_single_bit |check| -stdc_bit_width -stdc_bit_floor -stdc_bit_ceil +stdc_bit_width |check| +stdc_bit_floor |check| +stdc_bit_ceil |check| ========================= ========= Standards diff --git a/libc/docs/talks.rst b/libc/docs/talks.rst new file mode 100644 index 0000000000000000000000000000000000000000..174de0f56e7dd44cdde7ebaa192603556e0fe734 --- /dev/null +++ b/libc/docs/talks.rst @@ -0,0 +1,30 @@ +===== +Talks +===== +---- +2023 +---- +* Math functions in LLVM libc or yet another correctly rounded libm - Tue Ly + + * `slides `__ + * `video `__ +* The LLVM C Library for GPUs - Joseph Huber + + * `slides `__ + * `video `__ + +---- +2022 +---- +* Using LLVM's libc - Sivachandra Reddy, Michael Jones, Tue Ly + + * `slides `__ + * `video `__ +* Using modern CPU instructions to improve LLVM's libc math library - Tue Ly + + * `slides `__ + * `video `__ +* Approximating at Scale: How strto float in LLVM’s libc is faster - Michael Jones + + * `slides `__ + * `video `__ diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt index 9090b3bca01e0de83b07a2f414eeb0a9a2cda219..34d6839fd789a9c6be503f971c2c8d084b895ae0 100644 --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -84,6 +84,14 @@ add_gen_header( .llvm-libc-macros.float_macros ) +add_gen_header( + stdint + DEF_FILE stdint.h.def + GEN_HDR stdint.h + DEPENDS + .llvm-libc-macros.stdint_macros +) + add_gen_header( limits DEF_FILE limits.h.def diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt index 157b786aa7e81552a6bc647d7b879ae465795850..635ccadfb49e7deea058ec2ca0a2361dab2b314f 100644 --- a/libc/include/llvm-libc-macros/CMakeLists.txt +++ b/libc/include/llvm-libc-macros/CMakeLists.txt @@ -67,6 +67,12 @@ add_macro_header( file-seek-macros.h ) +add_macro_header( + stdint_macros + HDR + stdint-macros.h +) + add_macro_header( float_macros HDR diff --git a/libc/include/llvm-libc-macros/inttypes-macros.h b/libc/include/llvm-libc-macros/inttypes-macros.h index 8e7d4f558a63b616a0ea798aa522cbe1bd5a08d3..9b554670271ee808c441c4641aec4406f7cbaf37 100644 --- a/libc/include/llvm-libc-macros/inttypes-macros.h +++ b/libc/include/llvm-libc-macros/inttypes-macros.h @@ -9,11 +9,9 @@ #define LLVM_LIBC_MACROS_INTTYPES_MACROS_H // fprintf/scanf format macros. -// POSIX.1-2008, Technical Corrigendum 1, XBD/TC1-2008/0050 [211] is applied. +#define __STDC_VERSION_INTTYPES_H__ 202311L // clang provides these macros, so we don't need to define them. -// TODO: ISO C23 will provide binary notations. - #ifndef __clang__ #if __UINTPTR_MAX__ == __UINT64_MAX__ #define __PRI64 "l" @@ -117,6 +115,94 @@ #define __UINTPTR_FMTX__ __PRIPTR "X" #endif +// only recent clang provides these macros, so we need to check if they are +// available. +#ifndef __UINT8_FMTb__ +#define __UINT8_FMTb__ "hhb" +#endif +#ifndef __UINT16_FMTb__ +#define __UINT16_FMTb__ "hb" +#endif +#ifndef __UINT32_FMTb__ +#define __UINT32_FMTb__ "b" +#endif +#ifndef __UINT64_FMTb__ +#define __UINT64_FMTb__ __PRI64 "b" +#endif +#ifndef __UINT_LEAST8_FMTb__ +#define __UINT_LEAST8_FMTb__ "hhb" +#endif +#ifndef __UINT_LEAST16_FMTb__ +#define __UINT_LEAST16_FMTb__ "hb" +#endif +#ifndef __UINT_LEAST32_FMTb__ +#define __UINT_LEAST32_FMTb__ "b" +#endif +#ifndef __UINT_LEAST64_FMTb__ +#define __UINT_LEAST64_FMTb__ __PRI64 "b" +#endif +#ifndef __UINT_FAST8_FMTb__ +#define __UINT_FAST8_FMTb__ "hhb" +#endif +#ifndef __UINT_FAST16_FMTb__ +#define __UINT_FAST16_FMTb__ "hb" +#endif +#ifndef __UINT_FAST32_FMTb__ +#define __UINT_FAST32_FMTb__ "b" +#endif +#ifndef __UINT_FAST64_FMTb__ +#define __UINT_FAST64_FMTb__ __PRI64 "b" +#endif +#ifndef __UINTMAX_FMTb__ +#define __UINTMAX_FMTb__ __PRI64 "b" +#endif +#ifndef __UINTPTR_FMTb__ +#define __UINTPTR_FMTb__ __PRIPTR "b" +#endif + +#ifndef __UINT8_FMTB__ +#define __UINT8_FMTB__ "hhB" +#endif +#ifndef __UINT16_FMTB__ +#define __UINT16_FMTB__ "hB" +#endif +#ifndef __UINT32_FMTB__ +#define __UINT32_FMTB__ "B" +#endif +#ifndef __UINT64_FMTB__ +#define __UINT64_FMTB__ __PRI64 "B" +#endif +#ifndef __UINT_LEAST8_FMTB__ +#define __UINT_LEAST8_FMTB__ "hhB" +#endif +#ifndef __UINT_LEAST16_FMTB__ +#define __UINT_LEAST16_FMTB__ "hB" +#endif +#ifndef __UINT_LEAST32_FMTB__ +#define __UINT_LEAST32_FMTB__ "B" +#endif +#ifndef __UINT_LEAST64_FMTB__ +#define __UINT_LEAST64_FMTB__ __PRI64 "B" +#endif +#ifndef __UINT_FAST8_FMTB__ +#define __UINT_FAST8_FMTB__ "hhB" +#endif +#ifndef __UINT_FAST16_FMTB__ +#define __UINT_FAST16_FMTB__ "hB" +#endif +#ifndef __UINT_FAST32_FMTB__ +#define __UINT_FAST32_FMTB__ "B" +#endif +#ifndef __UINT_FAST64_FMTB__ +#define __UINT_FAST64_FMTB__ __PRI64 "B" +#endif +#ifndef __UINTMAX_FMTB__ +#define __UINTMAX_FMTB__ __PRI64 "B" +#endif +#ifndef __UINTPTR_FMTB__ +#define __UINTPTR_FMTB__ __PRIPTR "B" +#endif + // The fprintf() macros for signed integers. #define PRId8 __INT8_FMTd__ #define PRId16 __INT16_FMTd__ @@ -209,6 +295,36 @@ #define PRIXMAX __UINTMAX_FMTX__ #define PRIXPTR __UINTPTR_FMTX__ +#define PRIb8 __UINT8_FMTb__ +#define PRIb16 __UINT16_FMTb__ +#define PRIb32 __UINT32_FMTb__ +#define PRIb64 __UINT64_FMTb__ +#define PRIbLEAST8 __UINT_LEAST8_FMTb__ +#define PRIbLEAST16 __UINT_LEAST16_FMTb__ +#define PRIbLEAST32 __UINT_LEAST32_FMTb__ +#define PRIbLEAST64 __UINT_LEAST64_FMTb__ +#define PRIbFAST8 __UINT_FAST8_FMTb__ +#define PRIbFAST16 __UINT_FAST16_FMTb__ +#define PRIbFAST32 __UINT_FAST32_FMTb__ +#define PRIbFAST64 __UINT_FAST64_FMTb__ +#define PRIbMAX __UINTMAX_FMTb__ +#define PRIbPTR __UINTPTR_FMTb__ + +#define PRIB8 __UINT8_FMTB__ +#define PRIB16 __UINT16_FMTB__ +#define PRIB32 __UINT32_FMTB__ +#define PRIB64 __UINT64_FMTB__ +#define PRIBLEAST8 __UINT_LEAST8_FMTB__ +#define PRIBLEAST16 __UINT_LEAST16_FMTB__ +#define PRIBLEAST32 __UINT_LEAST32_FMTB__ +#define PRIBLEAST64 __UINT_LEAST64_FMTB__ +#define PRIBFAST8 __UINT_FAST8_FMTB__ +#define PRIBFAST16 __UINT_FAST16_FMTB__ +#define PRIBFAST32 __UINT_FAST32_FMTB__ +#define PRIBFAST64 __UINT_FAST64_FMTB__ +#define PRIBMAX __UINTMAX_FMTB__ +#define PRIBPTR __UINTPTR_FMTB__ + // The fscanf() macros for signed integers. #define SCNd8 __INT8_FMTd__ #define SCNd16 __INT16_FMTd__ @@ -286,4 +402,19 @@ #define SCNxMAX __UINTMAX_FMTx__ #define SCNxPTR __UINTPTR_FMTx__ +#define SCNb8 __UINT8_FMTb__ +#define SCNb16 __UINT16_FMTb__ +#define SCNb32 __UINT32_FMTb__ +#define SCNb64 __UINT64_FMTb__ +#define SCNbLEAST8 __UINT_LEAST8_FMTb__ +#define SCNbLEAST16 __UINT_LEAST16_FMTb__ +#define SCNbLEAST32 __UINT_LEAST32_FMTb__ +#define SCNbLEAST64 __UINT_LEAST64_FMTb__ +#define SCNbFAST8 __UINT_FAST8_FMTb__ +#define SCNbFAST16 __UINT_FAST16_FMTb__ +#define SCNbFAST32 __UINT_FAST32_FMTb__ +#define SCNbFAST64 __UINT_FAST64_FMTb__ +#define SCNbMAX __UINTMAX_FMTb__ +#define SCNbPTR __UINTPTR_FMTb__ + #endif // LLVM_LIBC_MACROS_INTTYPES_MACROS_H diff --git a/libc/include/llvm-libc-macros/stdbit-macros.h b/libc/include/llvm-libc-macros/stdbit-macros.h index e3a36d10ed92aba95b502ef2922a0e3beb126215..10c0fac3c8dd8648eb959d2a49bdbb20f297fd43 100644 --- a/libc/include/llvm-libc-macros/stdbit-macros.h +++ b/libc/include/llvm-libc-macros/stdbit-macros.h @@ -172,6 +172,41 @@ inline bool stdc_has_single_bit(unsigned long x) { inline bool stdc_has_single_bit(unsigned long long x) { return stdc_has_single_bit_ull(x); } +inline unsigned stdc_bit_width(unsigned char x) { return stdc_bit_width_uc(x); } +inline unsigned stdc_bit_width(unsigned short x) { + return stdc_bit_width_us(x); +} +inline unsigned stdc_bit_width(unsigned x) { return stdc_bit_width_ui(x); } +inline unsigned stdc_bit_width(unsigned long x) { return stdc_bit_width_ul(x); } +inline unsigned stdc_bit_width(unsigned long long x) { + return stdc_bit_width_ull(x); +} +inline unsigned char stdc_bit_floor(unsigned char x) { + return stdc_bit_floor_uc(x); +} +inline unsigned short stdc_bit_floor(unsigned short x) { + return stdc_bit_floor_us(x); +} +inline unsigned stdc_bit_floor(unsigned x) { return stdc_bit_floor_ui(x); } +inline unsigned long stdc_bit_floor(unsigned long x) { + return stdc_bit_floor_ul(x); +} +inline unsigned long long stdc_bit_floor(unsigned long long x) { + return stdc_bit_floor_ull(x); +} +inline unsigned char stdc_bit_ceil(unsigned char x) { + return stdc_bit_ceil_uc(x); +} +inline unsigned short stdc_bit_ceil(unsigned short x) { + return stdc_bit_ceil_us(x); +} +inline unsigned stdc_bit_ceil(unsigned x) { return stdc_bit_ceil_ui(x); } +inline unsigned long stdc_bit_ceil(unsigned long x) { + return stdc_bit_ceil_ul(x); +} +inline unsigned long long stdc_bit_ceil(unsigned long long x) { + return stdc_bit_ceil_ull(x); +} #else #define stdc_leading_zeros(x) \ _Generic((x), \ @@ -250,6 +285,27 @@ inline bool stdc_has_single_bit(unsigned long long x) { unsigned: stdc_has_single_bit_ui, \ unsigned long: stdc_has_single_bit_ul, \ unsigned long long: stdc_has_single_bit_ull)(x) +#define stdc_bit_width(x) \ + _Generic((x), \ + unsigned char: stdc_bit_width_uc, \ + unsigned short: stdc_bit_width_us, \ + unsigned: stdc_bit_width_ui, \ + unsigned long: stdc_bit_width_ul, \ + unsigned long long: stdc_bit_width_ull)(x) +#define stdc_bit_floor(x) \ + _Generic((x), \ + unsigned char: stdc_bit_floor_uc, \ + unsigned short: stdc_bit_floor_us, \ + unsigned: stdc_bit_floor_ui, \ + unsigned long: stdc_bit_floor_ul, \ + unsigned long long: stdc_bit_floor_ull)(x) +#define stdc_bit_ceil(x) \ + _Generic((x), \ + unsigned char: stdc_bit_ceil_uc, \ + unsigned short: stdc_bit_ceil_us, \ + unsigned: stdc_bit_ceil_ui, \ + unsigned long: stdc_bit_ceil_ul, \ + unsigned long long: stdc_bit_ceil_ull)(x) #endif // __cplusplus #endif // __LLVM_LIBC_MACROS_STDBIT_MACROS_H diff --git a/libc/include/llvm-libc-macros/stdint-macros.h b/libc/include/llvm-libc-macros/stdint-macros.h new file mode 100644 index 0000000000000000000000000000000000000000..1d5da2b783b6eb56966068e75c0f8afc09853d7e --- /dev/null +++ b/libc/include/llvm-libc-macros/stdint-macros.h @@ -0,0 +1,878 @@ +//===-- Definition of macros from stdint.h --------------------------------===// +// +// 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_MACROS_STDINT_MACROS_H +#define LLVM_LIBC_MACROS_STDINT_MACROS_H + +// These definitions are copied directly from the clang implementation located +// at 'clang/lib/Headers/stdint.h'. We provide it here again for compatibility. + +/* C99 7.18.1.1 Exact-width integer types. + * C99 7.18.1.2 Minimum-width integer types. + * C99 7.18.1.3 Fastest minimum-width integer types. + * + * The standard requires that exact-width type be defined for 8-, 16-, 32-, and + * 64-bit types if they are implemented. Other exact width types are optional. + * This implementation defines an exact-width types for every integer width + * that is represented in the standard integer types. + * + * The standard also requires minimum-width types be defined for 8-, 16-, 32-, + * and 64-bit widths regardless of whether there are corresponding exact-width + * types. + * + * To accommodate targets that are missing types that are exactly 8, 16, 32, or + * 64 bits wide, this implementation takes an approach of cascading + * redefinitions, redefining __int_leastN_t to successively smaller exact-width + * types. It is therefore important that the types are defined in order of + * descending widths. + * + * We currently assume that the minimum-width types and the fastest + * minimum-width types are the same. This is allowed by the standard, but is + * suboptimal. + * + * In violation of the standard, some targets do not implement a type that is + * wide enough to represent all of the required widths (8-, 16-, 32-, 64-bit). + * To accommodate these targets, a required minimum-width type is only + * defined if there exists an exact-width type of equal or greater width. + */ + +#ifdef __INT64_TYPE__ +#ifndef __int8_t_defined /* glibc sys/types.h also defines int64_t*/ +typedef __INT64_TYPE__ int64_t; +#endif /* __int8_t_defined */ +typedef __UINT64_TYPE__ uint64_t; +#undef __int_least64_t +#define __int_least64_t int64_t +#undef __uint_least64_t +#define __uint_least64_t uint64_t +#undef __int_least32_t +#define __int_least32_t int64_t +#undef __uint_least32_t +#define __uint_least32_t uint64_t +#undef __int_least16_t +#define __int_least16_t int64_t +#undef __uint_least16_t +#define __uint_least16_t uint64_t +#undef __int_least8_t +#define __int_least8_t int64_t +#undef __uint_least8_t +#define __uint_least8_t uint64_t +#endif /* __INT64_TYPE__ */ + +#ifdef __int_least64_t +typedef __int_least64_t int_least64_t; +typedef __uint_least64_t uint_least64_t; +typedef __int_least64_t int_fast64_t; +typedef __uint_least64_t uint_fast64_t; +#endif /* __int_least64_t */ + +#ifdef __INT56_TYPE__ +typedef __INT56_TYPE__ int56_t; +typedef __UINT56_TYPE__ uint56_t; +typedef int56_t int_least56_t; +typedef uint56_t uint_least56_t; +typedef int56_t int_fast56_t; +typedef uint56_t uint_fast56_t; +#undef __int_least32_t +#define __int_least32_t int56_t +#undef __uint_least32_t +#define __uint_least32_t uint56_t +#undef __int_least16_t +#define __int_least16_t int56_t +#undef __uint_least16_t +#define __uint_least16_t uint56_t +#undef __int_least8_t +#define __int_least8_t int56_t +#undef __uint_least8_t +#define __uint_least8_t uint56_t +#endif /* __INT56_TYPE__ */ + +#ifdef __INT48_TYPE__ +typedef __INT48_TYPE__ int48_t; +typedef __UINT48_TYPE__ uint48_t; +typedef int48_t int_least48_t; +typedef uint48_t uint_least48_t; +typedef int48_t int_fast48_t; +typedef uint48_t uint_fast48_t; +#undef __int_least32_t +#define __int_least32_t int48_t +#undef __uint_least32_t +#define __uint_least32_t uint48_t +#undef __int_least16_t +#define __int_least16_t int48_t +#undef __uint_least16_t +#define __uint_least16_t uint48_t +#undef __int_least8_t +#define __int_least8_t int48_t +#undef __uint_least8_t +#define __uint_least8_t uint48_t +#endif /* __INT48_TYPE__ */ + +#ifdef __INT40_TYPE__ +typedef __INT40_TYPE__ int40_t; +typedef __UINT40_TYPE__ uint40_t; +typedef int40_t int_least40_t; +typedef uint40_t uint_least40_t; +typedef int40_t int_fast40_t; +typedef uint40_t uint_fast40_t; +#undef __int_least32_t +#define __int_least32_t int40_t +#undef __uint_least32_t +#define __uint_least32_t uint40_t +#undef __int_least16_t +#define __int_least16_t int40_t +#undef __uint_least16_t +#define __uint_least16_t uint40_t +#undef __int_least8_t +#define __int_least8_t int40_t +#undef __uint_least8_t +#define __uint_least8_t uint40_t +#endif /* __INT40_TYPE__ */ + +#ifdef __INT32_TYPE__ + +#ifndef __int8_t_defined /* glibc sys/types.h also defines int32_t*/ +typedef __INT32_TYPE__ int32_t; +#endif /* __int8_t_defined */ + +#ifndef __uint32_t_defined /* more glibc compatibility */ +#define __uint32_t_defined +typedef __UINT32_TYPE__ uint32_t; +#endif /* __uint32_t_defined */ + +#undef __int_least32_t +#define __int_least32_t int32_t +#undef __uint_least32_t +#define __uint_least32_t uint32_t +#undef __int_least16_t +#define __int_least16_t int32_t +#undef __uint_least16_t +#define __uint_least16_t uint32_t +#undef __int_least8_t +#define __int_least8_t int32_t +#undef __uint_least8_t +#define __uint_least8_t uint32_t +#endif /* __INT32_TYPE__ */ + +#ifdef __int_least32_t +typedef __int_least32_t int_least32_t; +typedef __uint_least32_t uint_least32_t; +typedef __int_least32_t int_fast32_t; +typedef __uint_least32_t uint_fast32_t; +#endif /* __int_least32_t */ + +#ifdef __INT24_TYPE__ +typedef __INT24_TYPE__ int24_t; +typedef __UINT24_TYPE__ uint24_t; +typedef int24_t int_least24_t; +typedef uint24_t uint_least24_t; +typedef int24_t int_fast24_t; +typedef uint24_t uint_fast24_t; +#undef __int_least16_t +#define __int_least16_t int24_t +#undef __uint_least16_t +#define __uint_least16_t uint24_t +#undef __int_least8_t +#define __int_least8_t int24_t +#undef __uint_least8_t +#define __uint_least8_t uint24_t +#endif /* __INT24_TYPE__ */ + +#ifdef __INT16_TYPE__ +#ifndef __int8_t_defined /* glibc sys/types.h also defines int16_t*/ +typedef __INT16_TYPE__ int16_t; +#endif /* __int8_t_defined */ +typedef __UINT16_TYPE__ uint16_t; +#undef __int_least16_t +#define __int_least16_t int16_t +#undef __uint_least16_t +#define __uint_least16_t uint16_t +#undef __int_least8_t +#define __int_least8_t int16_t +#undef __uint_least8_t +#define __uint_least8_t uint16_t +#endif /* __INT16_TYPE__ */ + +#ifdef __int_least16_t +typedef __int_least16_t int_least16_t; +typedef __uint_least16_t uint_least16_t; +typedef __int_least16_t int_fast16_t; +typedef __uint_least16_t uint_fast16_t; +#endif /* __int_least16_t */ + +#ifdef __INT8_TYPE__ +#ifndef __int8_t_defined /* glibc sys/types.h also defines int8_t*/ +typedef __INT8_TYPE__ int8_t; +#endif /* __int8_t_defined */ +typedef __UINT8_TYPE__ uint8_t; +#undef __int_least8_t +#define __int_least8_t int8_t +#undef __uint_least8_t +#define __uint_least8_t uint8_t +#endif /* __INT8_TYPE__ */ + +#ifdef __int_least8_t +typedef __int_least8_t int_least8_t; +typedef __uint_least8_t uint_least8_t; +typedef __int_least8_t int_fast8_t; +typedef __uint_least8_t uint_fast8_t; +#endif /* __int_least8_t */ + +/* prevent glibc sys/types.h from defining conflicting types */ +#ifndef __int8_t_defined +#define __int8_t_defined +#endif /* __int8_t_defined */ + +/* C99 7.18.1.4 Integer types capable of holding object pointers. + */ +#define __stdint_join3(a, b, c) a##b##c + +#ifndef _INTPTR_T +#ifndef __intptr_t_defined +typedef __INTPTR_TYPE__ intptr_t; +#define __intptr_t_defined +#define _INTPTR_T +#endif +#endif + +#ifndef _UINTPTR_T +typedef __UINTPTR_TYPE__ uintptr_t; +#define _UINTPTR_T +#endif + +/* C99 7.18.1.5 Greatest-width integer types. + */ +typedef __INTMAX_TYPE__ intmax_t; +typedef __UINTMAX_TYPE__ uintmax_t; + +/* C99 7.18.4 Macros for minimum-width integer constants. + * + * The standard requires that integer constant macros be defined for all the + * minimum-width types defined above. As 8-, 16-, 32-, and 64-bit minimum-width + * types are required, the corresponding integer constant macros are defined + * here. This implementation also defines minimum-width types for every other + * integer width that the target implements, so corresponding macros are + * defined below, too. + * + * These macros are defined using the same successive-shrinking approach as + * the type definitions above. It is likewise important that macros are defined + * in order of decending width. + * + * Note that C++ should not check __STDC_CONSTANT_MACROS here, contrary to the + * claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]). + */ + +#define __int_c_join(a, b) a##b +#define __int_c(v, suffix) __int_c_join(v, suffix) +#define __uint_c(v, suffix) __int_c_join(v##U, suffix) + +#ifdef __INT64_TYPE__ +#undef __int64_c_suffix +#undef __int32_c_suffix +#undef __int16_c_suffix +#undef __int8_c_suffix +#ifdef __INT64_C_SUFFIX__ +#define __int64_c_suffix __INT64_C_SUFFIX__ +#define __int32_c_suffix __INT64_C_SUFFIX__ +#define __int16_c_suffix __INT64_C_SUFFIX__ +#define __int8_c_suffix __INT64_C_SUFFIX__ +#endif /* __INT64_C_SUFFIX__ */ +#endif /* __INT64_TYPE__ */ + +#ifdef __int_least64_t +#ifdef __int64_c_suffix +#define INT64_C(v) __int_c(v, __int64_c_suffix) +#define UINT64_C(v) __uint_c(v, __int64_c_suffix) +#else +#define INT64_C(v) v +#define UINT64_C(v) v##U +#endif /* __int64_c_suffix */ +#endif /* __int_least64_t */ + +#ifdef __INT56_TYPE__ +#undef __int32_c_suffix +#undef __int16_c_suffix +#undef __int8_c_suffix +#ifdef __INT56_C_SUFFIX__ +#define INT56_C(v) __int_c(v, __INT56_C_SUFFIX__) +#define UINT56_C(v) __uint_c(v, __INT56_C_SUFFIX__) +#define __int32_c_suffix __INT56_C_SUFFIX__ +#define __int16_c_suffix __INT56_C_SUFFIX__ +#define __int8_c_suffix __INT56_C_SUFFIX__ +#else +#define INT56_C(v) v +#define UINT56_C(v) v##U +#endif /* __INT56_C_SUFFIX__ */ +#endif /* __INT56_TYPE__ */ + +#ifdef __INT48_TYPE__ +#undef __int32_c_suffix +#undef __int16_c_suffix +#undef __int8_c_suffix +#ifdef __INT48_C_SUFFIX__ +#define INT48_C(v) __int_c(v, __INT48_C_SUFFIX__) +#define UINT48_C(v) __uint_c(v, __INT48_C_SUFFIX__) +#define __int32_c_suffix __INT48_C_SUFFIX__ +#define __int16_c_suffix __INT48_C_SUFFIX__ +#define __int8_c_suffix __INT48_C_SUFFIX__ +#else +#define INT48_C(v) v +#define UINT48_C(v) v##U +#endif /* __INT48_C_SUFFIX__ */ +#endif /* __INT48_TYPE__ */ + +#ifdef __INT40_TYPE__ +#undef __int32_c_suffix +#undef __int16_c_suffix +#undef __int8_c_suffix +#ifdef __INT40_C_SUFFIX__ +#define INT40_C(v) __int_c(v, __INT40_C_SUFFIX__) +#define UINT40_C(v) __uint_c(v, __INT40_C_SUFFIX__) +#define __int32_c_suffix __INT40_C_SUFFIX__ +#define __int16_c_suffix __INT40_C_SUFFIX__ +#define __int8_c_suffix __INT40_C_SUFFIX__ +#else +#define INT40_C(v) v +#define UINT40_C(v) v##U +#endif /* __INT40_C_SUFFIX__ */ +#endif /* __INT40_TYPE__ */ + +#ifdef __INT32_TYPE__ +#undef __int32_c_suffix +#undef __int16_c_suffix +#undef __int8_c_suffix +#ifdef __INT32_C_SUFFIX__ +#define __int32_c_suffix __INT32_C_SUFFIX__ +#define __int16_c_suffix __INT32_C_SUFFIX__ +#define __int8_c_suffix __INT32_C_SUFFIX__ +#endif /* __INT32_C_SUFFIX__ */ +#endif /* __INT32_TYPE__ */ + +#ifdef __int_least32_t +#ifdef __int32_c_suffix +#define INT32_C(v) __int_c(v, __int32_c_suffix) +#define UINT32_C(v) __uint_c(v, __int32_c_suffix) +#else +#define INT32_C(v) v +#define UINT32_C(v) v##U +#endif /* __int32_c_suffix */ +#endif /* __int_least32_t */ + +#ifdef __INT24_TYPE__ +#undef __int16_c_suffix +#undef __int8_c_suffix +#ifdef __INT24_C_SUFFIX__ +#define INT24_C(v) __int_c(v, __INT24_C_SUFFIX__) +#define UINT24_C(v) __uint_c(v, __INT24_C_SUFFIX__) +#define __int16_c_suffix __INT24_C_SUFFIX__ +#define __int8_c_suffix __INT24_C_SUFFIX__ +#else +#define INT24_C(v) v +#define UINT24_C(v) v##U +#endif /* __INT24_C_SUFFIX__ */ +#endif /* __INT24_TYPE__ */ + +#ifdef __INT16_TYPE__ +#undef __int16_c_suffix +#undef __int8_c_suffix +#ifdef __INT16_C_SUFFIX__ +#define __int16_c_suffix __INT16_C_SUFFIX__ +#define __int8_c_suffix __INT16_C_SUFFIX__ +#endif /* __INT16_C_SUFFIX__ */ +#endif /* __INT16_TYPE__ */ + +#ifdef __int_least16_t +#ifdef __int16_c_suffix +#define INT16_C(v) __int_c(v, __int16_c_suffix) +#define UINT16_C(v) __uint_c(v, __int16_c_suffix) +#else +#define INT16_C(v) v +#define UINT16_C(v) v##U +#endif /* __int16_c_suffix */ +#endif /* __int_least16_t */ + +#ifdef __INT8_TYPE__ +#undef __int8_c_suffix +#ifdef __INT8_C_SUFFIX__ +#define __int8_c_suffix __INT8_C_SUFFIX__ +#endif /* __INT8_C_SUFFIX__ */ +#endif /* __INT8_TYPE__ */ + +#ifdef __int_least8_t +#ifdef __int8_c_suffix +#define INT8_C(v) __int_c(v, __int8_c_suffix) +#define UINT8_C(v) __uint_c(v, __int8_c_suffix) +#else +#define INT8_C(v) v +#define UINT8_C(v) v##U +#endif /* __int8_c_suffix */ +#endif /* __int_least8_t */ + +/* C99 7.18.2.1 Limits of exact-width integer types. + * C99 7.18.2.2 Limits of minimum-width integer types. + * C99 7.18.2.3 Limits of fastest minimum-width integer types. + * + * The presence of limit macros are completely optional in C99. This + * implementation defines limits for all of the types (exact- and + * minimum-width) that it defines above, using the limits of the minimum-width + * type for any types that do not have exact-width representations. + * + * As in the type definitions, this section takes an approach of + * successive-shrinking to determine which limits to use for the standard (8, + * 16, 32, 64) bit widths when they don't have exact representations. It is + * therefore important that the definitions be kept in order of decending + * widths. + * + * Note that C++ should not check __STDC_LIMIT_MACROS here, contrary to the + * claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]). + */ + +#ifdef __INT64_TYPE__ +#define INT64_MAX INT64_C(9223372036854775807) +#define INT64_MIN (-INT64_C(9223372036854775807) - 1) +#define UINT64_MAX UINT64_C(18446744073709551615) + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define UINT64_WIDTH 64 +#define INT64_WIDTH UINT64_WIDTH + +#define __UINT_LEAST64_WIDTH UINT64_WIDTH +#undef __UINT_LEAST32_WIDTH +#define __UINT_LEAST32_WIDTH UINT64_WIDTH +#undef __UINT_LEAST16_WIDTH +#define __UINT_LEAST16_WIDTH UINT64_WIDTH +#undef __UINT_LEAST8_MAX +#define __UINT_LEAST8_MAX UINT64_MAX +#endif /* __STDC_VERSION__ */ + +#define __INT_LEAST64_MIN INT64_MIN +#define __INT_LEAST64_MAX INT64_MAX +#define __UINT_LEAST64_MAX UINT64_MAX +#undef __INT_LEAST32_MIN +#define __INT_LEAST32_MIN INT64_MIN +#undef __INT_LEAST32_MAX +#define __INT_LEAST32_MAX INT64_MAX +#undef __UINT_LEAST32_MAX +#define __UINT_LEAST32_MAX UINT64_MAX +#undef __INT_LEAST16_MIN +#define __INT_LEAST16_MIN INT64_MIN +#undef __INT_LEAST16_MAX +#define __INT_LEAST16_MAX INT64_MAX +#undef __UINT_LEAST16_MAX +#define __UINT_LEAST16_MAX UINT64_MAX +#undef __INT_LEAST8_MIN +#define __INT_LEAST8_MIN INT64_MIN +#undef __INT_LEAST8_MAX +#define __INT_LEAST8_MAX INT64_MAX +#undef __UINT_LEAST8_MAX +#define __UINT_LEAST8_MAX UINT64_MAX +#endif /* __INT64_TYPE__ */ + +#ifdef __INT_LEAST64_MIN +#define INT_LEAST64_MIN __INT_LEAST64_MIN +#define INT_LEAST64_MAX __INT_LEAST64_MAX +#define UINT_LEAST64_MAX __UINT_LEAST64_MAX +#define INT_FAST64_MIN __INT_LEAST64_MIN +#define INT_FAST64_MAX __INT_LEAST64_MAX +#define UINT_FAST64_MAX __UINT_LEAST64_MAX + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define UINT_LEAST64_WIDTH __UINT_LEAST64_WIDTH +#define INT_LEAST64_WIDTH UINT_LEAST64_WIDTH +#define UINT_FAST64_WIDTH __UINT_LEAST64_WIDTH +#define INT_FAST64_WIDTH UINT_FAST64_WIDTH +#endif /* __STDC_VERSION__ */ +#endif /* __INT_LEAST64_MIN */ + +#ifdef __INT56_TYPE__ +#define INT56_MAX INT56_C(36028797018963967) +#define INT56_MIN (-INT56_C(36028797018963967) - 1) +#define UINT56_MAX UINT56_C(72057594037927935) +#define INT_LEAST56_MIN INT56_MIN +#define INT_LEAST56_MAX INT56_MAX +#define UINT_LEAST56_MAX UINT56_MAX +#define INT_FAST56_MIN INT56_MIN +#define INT_FAST56_MAX INT56_MAX +#define UINT_FAST56_MAX UINT56_MAX + +#undef __INT_LEAST32_MIN +#define __INT_LEAST32_MIN INT56_MIN +#undef __INT_LEAST32_MAX +#define __INT_LEAST32_MAX INT56_MAX +#undef __UINT_LEAST32_MAX +#define __UINT_LEAST32_MAX UINT56_MAX +#undef __INT_LEAST16_MIN +#define __INT_LEAST16_MIN INT56_MIN +#undef __INT_LEAST16_MAX +#define __INT_LEAST16_MAX INT56_MAX +#undef __UINT_LEAST16_MAX +#define __UINT_LEAST16_MAX UINT56_MAX +#undef __INT_LEAST8_MIN +#define __INT_LEAST8_MIN INT56_MIN +#undef __INT_LEAST8_MAX +#define __INT_LEAST8_MAX INT56_MAX +#undef __UINT_LEAST8_MAX +#define __UINT_LEAST8_MAX UINT56_MAX + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define UINT56_WIDTH 56 +#define INT56_WIDTH UINT56_WIDTH +#define UINT_LEAST56_WIDTH UINT56_WIDTH +#define INT_LEAST56_WIDTH UINT_LEAST56_WIDTH +#define UINT_FAST56_WIDTH UINT56_WIDTH +#define INT_FAST56_WIDTH UINT_FAST56_WIDTH +#undef __UINT_LEAST32_WIDTH +#define __UINT_LEAST32_WIDTH UINT56_WIDTH +#undef __UINT_LEAST16_WIDTH +#define __UINT_LEAST16_WIDTH UINT56_WIDTH +#undef __UINT_LEAST8_WIDTH +#define __UINT_LEAST8_WIDTH UINT56_WIDTH +#endif /* __STDC_VERSION__ */ +#endif /* __INT56_TYPE__ */ + +#ifdef __INT48_TYPE__ +#define INT48_MAX INT48_C(140737488355327) +#define INT48_MIN (-INT48_C(140737488355327) - 1) +#define UINT48_MAX UINT48_C(281474976710655) +#define INT_LEAST48_MIN INT48_MIN +#define INT_LEAST48_MAX INT48_MAX +#define UINT_LEAST48_MAX UINT48_MAX +#define INT_FAST48_MIN INT48_MIN +#define INT_FAST48_MAX INT48_MAX +#define UINT_FAST48_MAX UINT48_MAX + +#undef __INT_LEAST32_MIN +#define __INT_LEAST32_MIN INT48_MIN +#undef __INT_LEAST32_MAX +#define __INT_LEAST32_MAX INT48_MAX +#undef __UINT_LEAST32_MAX +#define __UINT_LEAST32_MAX UINT48_MAX +#undef __INT_LEAST16_MIN +#define __INT_LEAST16_MIN INT48_MIN +#undef __INT_LEAST16_MAX +#define __INT_LEAST16_MAX INT48_MAX +#undef __UINT_LEAST16_MAX +#define __UINT_LEAST16_MAX UINT48_MAX +#undef __INT_LEAST8_MIN +#define __INT_LEAST8_MIN INT48_MIN +#undef __INT_LEAST8_MAX +#define __INT_LEAST8_MAX INT48_MAX +#undef __UINT_LEAST8_MAX +#define __UINT_LEAST8_MAX UINT48_MAX + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define UINT48_WIDTH 48 +#define INT48_WIDTH UINT48_WIDTH +#define UINT_LEAST48_WIDTH UINT48_WIDTH +#define INT_LEAST48_WIDTH UINT_LEAST48_WIDTH +#define UINT_FAST48_WIDTH UINT48_WIDTH +#define INT_FAST48_WIDTH UINT_FAST48_WIDTH +#undef __UINT_LEAST32_WIDTH +#define __UINT_LEAST32_WIDTH UINT48_WIDTH +#undef __UINT_LEAST16_WIDTH +#define __UINT_LEAST16_WIDTH UINT48_WIDTH +#undef __UINT_LEAST8_WIDTH +#define __UINT_LEAST8_WIDTH UINT48_WIDTH +#endif /* __STDC_VERSION__ */ +#endif /* __INT48_TYPE__ */ + +#ifdef __INT40_TYPE__ +#define INT40_MAX INT40_C(549755813887) +#define INT40_MIN (-INT40_C(549755813887) - 1) +#define UINT40_MAX UINT40_C(1099511627775) +#define INT_LEAST40_MIN INT40_MIN +#define INT_LEAST40_MAX INT40_MAX +#define UINT_LEAST40_MAX UINT40_MAX +#define INT_FAST40_MIN INT40_MIN +#define INT_FAST40_MAX INT40_MAX +#define UINT_FAST40_MAX UINT40_MAX + +#undef __INT_LEAST32_MIN +#define __INT_LEAST32_MIN INT40_MIN +#undef __INT_LEAST32_MAX +#define __INT_LEAST32_MAX INT40_MAX +#undef __UINT_LEAST32_MAX +#define __UINT_LEAST32_MAX UINT40_MAX +#undef __INT_LEAST16_MIN +#define __INT_LEAST16_MIN INT40_MIN +#undef __INT_LEAST16_MAX +#define __INT_LEAST16_MAX INT40_MAX +#undef __UINT_LEAST16_MAX +#define __UINT_LEAST16_MAX UINT40_MAX +#undef __INT_LEAST8_MIN +#define __INT_LEAST8_MIN INT40_MIN +#undef __INT_LEAST8_MAX +#define __INT_LEAST8_MAX INT40_MAX +#undef __UINT_LEAST8_MAX +#define __UINT_LEAST8_MAX UINT40_MAX + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define UINT40_WIDTH 40 +#define INT40_WIDTH UINT40_WIDTH +#define UINT_LEAST40_WIDTH UINT40_WIDTH +#define INT_LEAST40_WIDTH UINT_LEAST40_WIDTH +#define UINT_FAST40_WIDTH UINT40_WIDTH +#define INT_FAST40_WIDTH UINT_FAST40_WIDTH +#undef __UINT_LEAST32_WIDTH +#define __UINT_LEAST32_WIDTH UINT40_WIDTH +#undef __UINT_LEAST16_WIDTH +#define __UINT_LEAST16_WIDTH UINT40_WIDTH +#undef __UINT_LEAST8_WIDTH +#define __UINT_LEAST8_WIDTH UINT40_WIDTH +#endif /* __STDC_VERSION__ */ +#endif /* __INT40_TYPE__ */ + +#ifdef __INT32_TYPE__ +#define INT32_MAX INT32_C(2147483647) +#define INT32_MIN (-INT32_C(2147483647) - 1) +#define UINT32_MAX UINT32_C(4294967295) + +#undef __INT_LEAST32_MIN +#define __INT_LEAST32_MIN INT32_MIN +#undef __INT_LEAST32_MAX +#define __INT_LEAST32_MAX INT32_MAX +#undef __UINT_LEAST32_MAX +#define __UINT_LEAST32_MAX UINT32_MAX +#undef __INT_LEAST16_MIN +#define __INT_LEAST16_MIN INT32_MIN +#undef __INT_LEAST16_MAX +#define __INT_LEAST16_MAX INT32_MAX +#undef __UINT_LEAST16_MAX +#define __UINT_LEAST16_MAX UINT32_MAX +#undef __INT_LEAST8_MIN +#define __INT_LEAST8_MIN INT32_MIN +#undef __INT_LEAST8_MAX +#define __INT_LEAST8_MAX INT32_MAX +#undef __UINT_LEAST8_MAX +#define __UINT_LEAST8_MAX UINT32_MAX + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define UINT32_WIDTH 32 +#define INT32_WIDTH UINT32_WIDTH +#undef __UINT_LEAST32_WIDTH +#define __UINT_LEAST32_WIDTH UINT32_WIDTH +#undef __UINT_LEAST16_WIDTH +#define __UINT_LEAST16_WIDTH UINT32_WIDTH +#undef __UINT_LEAST8_WIDTH +#define __UINT_LEAST8_WIDTH UINT32_WIDTH +#endif /* __STDC_VERSION__ */ +#endif /* __INT32_TYPE__ */ + +#ifdef __INT_LEAST32_MIN +#define INT_LEAST32_MIN __INT_LEAST32_MIN +#define INT_LEAST32_MAX __INT_LEAST32_MAX +#define UINT_LEAST32_MAX __UINT_LEAST32_MAX +#define INT_FAST32_MIN __INT_LEAST32_MIN +#define INT_FAST32_MAX __INT_LEAST32_MAX +#define UINT_FAST32_MAX __UINT_LEAST32_MAX + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define UINT_LEAST32_WIDTH __UINT_LEAST32_WIDTH +#define INT_LEAST32_WIDTH UINT_LEAST32_WIDTH +#define UINT_FAST32_WIDTH __UINT_LEAST32_WIDTH +#define INT_FAST32_WIDTH UINT_FAST32_WIDTH +#endif /* __STDC_VERSION__ */ +#endif /* __INT_LEAST32_MIN */ + +#ifdef __INT24_TYPE__ +#define INT24_MAX INT24_C(8388607) +#define INT24_MIN (-INT24_C(8388607) - 1) +#define UINT24_MAX UINT24_C(16777215) +#define INT_LEAST24_MIN INT24_MIN +#define INT_LEAST24_MAX INT24_MAX +#define UINT_LEAST24_MAX UINT24_MAX +#define INT_FAST24_MIN INT24_MIN +#define INT_FAST24_MAX INT24_MAX +#define UINT_FAST24_MAX UINT24_MAX + +#undef __INT_LEAST16_MIN +#define __INT_LEAST16_MIN INT24_MIN +#undef __INT_LEAST16_MAX +#define __INT_LEAST16_MAX INT24_MAX +#undef __UINT_LEAST16_MAX +#define __UINT_LEAST16_MAX UINT24_MAX +#undef __INT_LEAST8_MIN +#define __INT_LEAST8_MIN INT24_MIN +#undef __INT_LEAST8_MAX +#define __INT_LEAST8_MAX INT24_MAX +#undef __UINT_LEAST8_MAX +#define __UINT_LEAST8_MAX UINT24_MAX + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define UINT24_WIDTH 24 +#define INT24_WIDTH UINT24_WIDTH +#define UINT_LEAST24_WIDTH UINT24_WIDTH +#define INT_LEAST24_WIDTH UINT_LEAST24_WIDTH +#define UINT_FAST24_WIDTH UINT24_WIDTH +#define INT_FAST24_WIDTH UINT_FAST24_WIDTH +#undef __UINT_LEAST16_WIDTH +#define __UINT_LEAST16_WIDTH UINT24_WIDTH +#undef __UINT_LEAST8_WIDTH +#define __UINT_LEAST8_WIDTH UINT24_WIDTH +#endif /* __STDC_VERSION__ */ +#endif /* __INT24_TYPE__ */ + +#ifdef __INT16_TYPE__ +#define INT16_MAX INT16_C(32767) +#define INT16_MIN (-INT16_C(32767) - 1) +#define UINT16_MAX UINT16_C(65535) + +#undef __INT_LEAST16_MIN +#define __INT_LEAST16_MIN INT16_MIN +#undef __INT_LEAST16_MAX +#define __INT_LEAST16_MAX INT16_MAX +#undef __UINT_LEAST16_MAX +#define __UINT_LEAST16_MAX UINT16_MAX +#undef __INT_LEAST8_MIN +#define __INT_LEAST8_MIN INT16_MIN +#undef __INT_LEAST8_MAX +#define __INT_LEAST8_MAX INT16_MAX +#undef __UINT_LEAST8_MAX +#define __UINT_LEAST8_MAX UINT16_MAX + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define UINT16_WIDTH 16 +#define INT16_WIDTH UINT16_WIDTH +#undef __UINT_LEAST16_WIDTH +#define __UINT_LEAST16_WIDTH UINT16_WIDTH +#undef __UINT_LEAST8_WIDTH +#define __UINT_LEAST8_WIDTH UINT16_WIDTH +#endif /* __STDC_VERSION__ */ +#endif /* __INT16_TYPE__ */ + +#ifdef __INT_LEAST16_MIN +#define INT_LEAST16_MIN __INT_LEAST16_MIN +#define INT_LEAST16_MAX __INT_LEAST16_MAX +#define UINT_LEAST16_MAX __UINT_LEAST16_MAX +#define INT_FAST16_MIN __INT_LEAST16_MIN +#define INT_FAST16_MAX __INT_LEAST16_MAX +#define UINT_FAST16_MAX __UINT_LEAST16_MAX + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define UINT_LEAST16_WIDTH __UINT_LEAST16_WIDTH +#define INT_LEAST16_WIDTH UINT_LEAST16_WIDTH +#define UINT_FAST16_WIDTH __UINT_LEAST16_WIDTH +#define INT_FAST16_WIDTH UINT_FAST16_WIDTH +#endif /* __STDC_VERSION__ */ +#endif /* __INT_LEAST16_MIN */ + +#ifdef __INT8_TYPE__ +#define INT8_MAX INT8_C(127) +#define INT8_MIN (-INT8_C(127) - 1) +#define UINT8_MAX UINT8_C(255) + +#undef __INT_LEAST8_MIN +#define __INT_LEAST8_MIN INT8_MIN +#undef __INT_LEAST8_MAX +#define __INT_LEAST8_MAX INT8_MAX +#undef __UINT_LEAST8_MAX +#define __UINT_LEAST8_MAX UINT8_MAX + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define UINT8_WIDTH 8 +#define INT8_WIDTH UINT8_WIDTH +#undef __UINT_LEAST8_WIDTH +#define __UINT_LEAST8_WIDTH UINT8_WIDTH +#endif /* __STDC_VERSION__ */ +#endif /* __INT8_TYPE__ */ + +#ifdef __INT_LEAST8_MIN +#define INT_LEAST8_MIN __INT_LEAST8_MIN +#define INT_LEAST8_MAX __INT_LEAST8_MAX +#define UINT_LEAST8_MAX __UINT_LEAST8_MAX +#define INT_FAST8_MIN __INT_LEAST8_MIN +#define INT_FAST8_MAX __INT_LEAST8_MAX +#define UINT_FAST8_MAX __UINT_LEAST8_MAX + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define UINT_LEAST8_WIDTH __UINT_LEAST8_WIDTH +#define INT_LEAST8_WIDTH UINT_LEAST8_WIDTH +#define UINT_FAST8_WIDTH __UINT_LEAST8_WIDTH +#define INT_FAST8_WIDTH UINT_FAST8_WIDTH +#endif /* __STDC_VERSION__ */ +#endif /* __INT_LEAST8_MIN */ + +/* Some utility macros */ +#define __INTN_MIN(n) __stdint_join3(INT, n, _MIN) +#define __INTN_MAX(n) __stdint_join3(INT, n, _MAX) +#define __UINTN_MAX(n) __stdint_join3(UINT, n, _MAX) +#define __INTN_C(n, v) __stdint_join3(INT, n, _C(v)) +#define __UINTN_C(n, v) __stdint_join3(UINT, n, _C(v)) + +/* C99 7.18.2.4 Limits of integer types capable of holding object pointers. */ +/* C99 7.18.3 Limits of other integer types. */ + +#define INTPTR_MIN (-__INTPTR_MAX__ - 1) +#define INTPTR_MAX __INTPTR_MAX__ +#define UINTPTR_MAX __UINTPTR_MAX__ +#define PTRDIFF_MIN (-__PTRDIFF_MAX__ - 1) +#define PTRDIFF_MAX __PTRDIFF_MAX__ +#define SIZE_MAX __SIZE_MAX__ + +/* C23 7.22.2.4 Width of integer types capable of holding object pointers. */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +/* NB: The C standard requires that these be the same value, but the compiler + exposes separate internal width macros. */ +#define INTPTR_WIDTH __INTPTR_WIDTH__ +#define UINTPTR_WIDTH __UINTPTR_WIDTH__ +#endif + +/* ISO9899:2011 7.20 (C11 Annex K): Define RSIZE_MAX if __STDC_WANT_LIB_EXT1__ + * is enabled. */ +#if defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__ >= 1 +#define RSIZE_MAX (SIZE_MAX >> 1) +#endif + +/* C99 7.18.2.5 Limits of greatest-width integer types. */ +#define INTMAX_MIN (-__INTMAX_MAX__ - 1) +#define INTMAX_MAX __INTMAX_MAX__ +#define UINTMAX_MAX __UINTMAX_MAX__ + +/* C23 7.22.2.5 Width of greatest-width integer types. */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +/* NB: The C standard requires that these be the same value, but the compiler + exposes separate internal width macros. */ +#define INTMAX_WIDTH __INTMAX_WIDTH__ +#define UINTMAX_WIDTH __UINTMAX_WIDTH__ +#endif + +/* C99 7.18.3 Limits of other integer types. */ +#define SIG_ATOMIC_MIN __INTN_MIN(__SIG_ATOMIC_WIDTH__) +#define SIG_ATOMIC_MAX __INTN_MAX(__SIG_ATOMIC_WIDTH__) +#ifdef __WINT_UNSIGNED__ +#define WINT_MIN __UINTN_C(__WINT_WIDTH__, 0) +#define WINT_MAX __UINTN_MAX(__WINT_WIDTH__) +#else +#define WINT_MIN __INTN_MIN(__WINT_WIDTH__) +#define WINT_MAX __INTN_MAX(__WINT_WIDTH__) +#endif + +#ifndef WCHAR_MAX +#define WCHAR_MAX __WCHAR_MAX__ +#endif +#ifndef WCHAR_MIN +#if __WCHAR_MAX__ == __INTN_MAX(__WCHAR_WIDTH__) +#define WCHAR_MIN __INTN_MIN(__WCHAR_WIDTH__) +#else +#define WCHAR_MIN __UINTN_C(__WCHAR_WIDTH__, 0) +#endif +#endif + +/* 7.18.4.2 Macros for greatest-width integer constants. */ +#define INTMAX_C(v) __int_c(v, __INTMAX_C_SUFFIX__) +#define UINTMAX_C(v) __int_c(v, __UINTMAX_C_SUFFIX__) + +/* C23 7.22.3.x Width of other integer types. */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define PTRDIFF_WIDTH __PTRDIFF_WIDTH__ +#define SIG_ATOMIC_WIDTH __SIG_ATOMIC_WIDTH__ +#define SIZE_WIDTH __SIZE_WIDTH__ +#define WCHAR_WIDTH __WCHAR_WIDTH__ +#define WINT_WIDTH __WINT_WIDTH__ +#endif +#endif // LLVM_LIBC_MACROS_STDINT_MACROS_H diff --git a/libc/test/src/math/differential_testing/hypot_diff.cpp b/libc/include/stdint.h.def similarity index 53% rename from libc/test/src/math/differential_testing/hypot_diff.cpp rename to libc/include/stdint.h.def index c61e589bdb2dffaa0767671bc382f7bafe02a932..9e269101acd2fb3aeab01875adc1b59575467d8f 100644 --- a/libc/test/src/math/differential_testing/hypot_diff.cpp +++ b/libc/include/stdint.h.def @@ -1,4 +1,4 @@ -//===-- Differential test for hypot ---------------------------------------===// +//===-- C standard library header stdint.h --------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,11 +6,9 @@ // //===----------------------------------------------------------------------===// -#include "BinaryOpSingleOutputDiff.h" +#ifndef LLVM_LIBC_STDINT_H +#define LLVM_LIBC_STDINT_H -#include "src/math/hypot.h" +#include -#include - -BINARY_OP_SINGLE_OUTPUT_DIFF(double, LIBC_NAMESPACE::hypot, ::hypot, - "hypot_diff.log") +#endif // LLVM_LIBC_STDINT_H diff --git a/libc/spec/gnu_ext.td b/libc/spec/gnu_ext.td index add07d75050df431e2e417a51a794b692e935708..161bb4e4a0d9d0c6b8dd735cae83da42a858c24d 100644 --- a/libc/spec/gnu_ext.td +++ b/libc/spec/gnu_ext.td @@ -33,8 +33,6 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> { RetValSpec, [ArgSpec, ArgSpec, ArgSpec] >, - FunctionSpec<"exp10", RetValSpec, [ArgSpec]>, - FunctionSpec<"exp10f", RetValSpec, [ArgSpec]>, ] >; diff --git a/libc/spec/llvm_libc_ext.td b/libc/spec/llvm_libc_ext.td index 2fd0c5f78fb8a72fd0f629924c50bb833149042a..ca61d4ef371a2e9736a67f854001355d335b4cb5 100644 --- a/libc/spec/llvm_libc_ext.td +++ b/libc/spec/llvm_libc_ext.td @@ -52,8 +52,8 @@ def LLVMLibcExt : StandardSpec<"llvm_libc_ext"> { >; let Headers = [ - Strings, - Sched, Assert, + Sched, + Strings, ]; } diff --git a/libc/spec/llvm_libc_stdfix_ext.td b/libc/spec/llvm_libc_stdfix_ext.td new file mode 100644 index 0000000000000000000000000000000000000000..7bc7ec5464081bde7ae00f4a4ec2fd2493d4f8c7 --- /dev/null +++ b/libc/spec/llvm_libc_stdfix_ext.td @@ -0,0 +1,27 @@ +def LLVMLibcStdfixExt : StandardSpec<"llvm_libc_stdfix_ext"> { + HeaderSpec StdFix = HeaderSpec< + "stdfix.h", + [], // macros + [], // types + [], // enums + [ // functions + GuardedFunctionSpec<"exphk", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, + GuardedFunctionSpec<"expk", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, + + GuardedFunctionSpec<"sqrtuhr", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, + GuardedFunctionSpec<"sqrtur", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, + GuardedFunctionSpec<"sqrtulr", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, + + GuardedFunctionSpec<"sqrtuhk", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, + GuardedFunctionSpec<"sqrtuk", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, + GuardedFunctionSpec<"sqrtulk", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, + + GuardedFunctionSpec<"uhksqrtus", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, + GuardedFunctionSpec<"uksqrtui", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, + ] + >; + + let Headers = [ + StdFix, + ]; +} diff --git a/libc/spec/posix.td b/libc/spec/posix.td index 70be692e208a882d77d95162ce613613ca015c47..d0f5a4584dd45b815e485edad1d4eb5a7690d56c 100644 --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -309,6 +309,11 @@ def POSIX : StandardSpec<"POSIX"> { RetValSpec, [ArgSpec] >, + FunctionSpec< + "msync", + RetValSpec, + [ArgSpec, ArgSpec, ArgSpec] + >, ] >; diff --git a/libc/spec/spec.td b/libc/spec/spec.td index 998f37fb26deed472db5e31168684918923bd546..a44a7ae131b5d97b2a049914c5ee47dd294c6727 100644 --- a/libc/spec/spec.td +++ b/libc/spec/spec.td @@ -111,6 +111,7 @@ def IntPtr : PtrType; def RestrictedIntPtr : RestrictedPtrType; def FloatPtr : PtrType; def DoublePtr : PtrType; +def Float128Ptr : PtrType; def UnsignedCharPtr : PtrType; def SigHandlerT : NamedType<"__sighandler_t">; diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td index 94ac62966f3ba5388968b6e68c56e39c9b8a3836..1f14fe758130e8a99ee97e697d4d871f4da98aed 100644 --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -234,6 +234,11 @@ def StdC : StandardSpec<"stdc"> { RetValSpec, [ArgSpec, ArgSpec, ArgSpec] >, + FunctionSpec< + "memset_explicit", + RetValSpec, + [ArgSpec, ArgSpec, ArgSpec] + >, FunctionSpec< "strcpy", RetValSpec, @@ -400,8 +405,9 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"fmaf", RetValSpec, [ArgSpec, ArgSpec, ArgSpec]>, FunctionSpec<"fmod", RetValSpec, [ArgSpec, ArgSpec]>, - FunctionSpec<"fmodf", RetValSpec, [ArgSpec, ArgSpec]>, + FunctionSpec<"fmodl", RetValSpec, [ArgSpec, ArgSpec]>, + GuardedFunctionSpec<"fmodf128", RetValSpec, [ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"frexp", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"frexpf", RetValSpec, [ArgSpec, ArgSpec]>, @@ -446,6 +452,7 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"modf", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"modff", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"modfl", RetValSpec, [ArgSpec, ArgSpec]>, + GuardedFunctionSpec<"modff128", RetValSpec, [ArgSpec, ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"cos", RetValSpec, [ArgSpec]>, FunctionSpec<"cosf", RetValSpec, [ArgSpec]>, @@ -465,6 +472,9 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"expm1", RetValSpec, [ArgSpec]>, FunctionSpec<"expm1f", RetValSpec, [ArgSpec]>, + FunctionSpec<"exp10", RetValSpec, [ArgSpec]>, + FunctionSpec<"exp10f", RetValSpec, [ArgSpec]>, + FunctionSpec<"remainderf", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"remainder", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"remainderl", RetValSpec, [ArgSpec, ArgSpec]>, @@ -481,22 +491,27 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"lround", RetValSpec, [ArgSpec]>, FunctionSpec<"lroundf", RetValSpec, [ArgSpec]>, FunctionSpec<"lroundl", RetValSpec, [ArgSpec]>, + GuardedFunctionSpec<"lroundf128", RetValSpec, [ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"llround", RetValSpec, [ArgSpec]>, FunctionSpec<"llroundf", RetValSpec, [ArgSpec]>, FunctionSpec<"llroundl", RetValSpec, [ArgSpec]>, + GuardedFunctionSpec<"llroundf128", RetValSpec, [ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"rint", RetValSpec, [ArgSpec]>, FunctionSpec<"rintf", RetValSpec, [ArgSpec]>, FunctionSpec<"rintl", RetValSpec, [ArgSpec]>, + GuardedFunctionSpec<"rintf128", RetValSpec, [ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"lrint", RetValSpec, [ArgSpec]>, FunctionSpec<"lrintf", RetValSpec, [ArgSpec]>, FunctionSpec<"lrintl", RetValSpec, [ArgSpec]>, + GuardedFunctionSpec<"lrintf128", RetValSpec, [ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"llrint", RetValSpec, [ArgSpec]>, FunctionSpec<"llrintf", RetValSpec, [ArgSpec]>, FunctionSpec<"llrintl", RetValSpec, [ArgSpec]>, + GuardedFunctionSpec<"llrintf128", RetValSpec, [ArgSpec], "LIBC_TYPES_HAS_FLOAT128">, FunctionSpec<"sqrt", RetValSpec, [ArgSpec]>, FunctionSpec<"sqrtf", RetValSpec, [ArgSpec]>, @@ -800,7 +815,10 @@ def StdC : StandardSpec<"stdc"> { Macro<"stdc_first_trailing_one">, Macro<"stdc_count_zeros">, Macro<"stdc_count_ones">, - Macro<"stdc_has_single_bit"> + Macro<"stdc_has_single_bit">, + Macro<"std_bit_width">, + Macro<"std_bit_floor">, + Macro<"std_bit_ceil"> ], // Macros [], // Types [], // Enumerations @@ -854,7 +872,22 @@ def StdC : StandardSpec<"stdc"> { FunctionSpec<"stdc_has_single_bit_us", RetValSpec, [ArgSpec]>, FunctionSpec<"stdc_has_single_bit_ui", RetValSpec, [ArgSpec]>, FunctionSpec<"stdc_has_single_bit_ul", RetValSpec, [ArgSpec]>, - FunctionSpec<"stdc_has_single_bit_ull", RetValSpec, [ArgSpec]> + FunctionSpec<"stdc_has_single_bit_ull", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_width_uc", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_width_us", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_width_ui", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_width_ul", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_width_ull", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_floor_uc", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_floor_us", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_floor_ui", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_floor_ul", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_floor_ull", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_ceil_uc", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_ceil_us", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_ceil_ui", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_ceil_ul", RetValSpec, [ArgSpec]>, + FunctionSpec<"stdc_bit_ceil_ull", RetValSpec, [ArgSpec]> ] // Functions >; @@ -931,7 +964,9 @@ def StdC : StandardSpec<"stdc"> { HeaderSpec IntTypes = HeaderSpec< "inttypes.h", - [], // Macros + [ + Macro<"__STDC_VERSION_INTTYPES_H__">, + ], // Macros [ IMaxDivTType, ], // Types @@ -963,6 +998,8 @@ def StdC : StandardSpec<"stdc"> { ] >; + HeaderSpec StdInt = HeaderSpec<"StdInt.h">; + HeaderSpec Limits = HeaderSpec<"limits.h">; NamedType SigAtomicT = NamedType<"sig_atomic_t">; @@ -1268,6 +1305,7 @@ def StdC : StandardSpec<"stdc"> { Errno, Fenv, Float, + StdInt, Limits, Math, String, diff --git a/libc/spec/stdc_ext.td b/libc/spec/stdc_ext.td index be1e6d4ba2fcdc6c10399ac4a6bf63ddea08f244..6620142146c4710858e40829ba0ea75d8b84807c 100644 --- a/libc/spec/stdc_ext.td +++ b/libc/spec/stdc_ext.td @@ -47,14 +47,6 @@ def StdcExt : StandardSpec<"stdc_ext"> { GuardedFunctionSpec<"rounduhk", RetValSpec, [ArgSpec, ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, GuardedFunctionSpec<"rounduk", RetValSpec, [ArgSpec, ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, GuardedFunctionSpec<"roundulk", RetValSpec, [ArgSpec, ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, - - GuardedFunctionSpec<"sqrtuhr", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, - GuardedFunctionSpec<"sqrtur", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, - GuardedFunctionSpec<"sqrtulr", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, - - GuardedFunctionSpec<"sqrtuhk", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, - GuardedFunctionSpec<"sqrtuk", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, - GuardedFunctionSpec<"sqrtulk", RetValSpec, [ArgSpec], "LIBC_COMPILER_HAS_FIXED_POINT">, ] >; diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt index 1a4b3e9a2145c021798127b60879ebe113c74f4a..2e5a026bf423cd622c8c01e8268637068bd7d58a 100644 --- a/libc/src/__support/CMakeLists.txt +++ b/libc/src/__support/CMakeLists.txt @@ -95,6 +95,7 @@ add_header_library( HDRS integer_to_string.h DEPENDS + .uint libc.src.__support.common libc.src.__support.CPP.algorithm libc.src.__support.CPP.limits @@ -193,30 +194,18 @@ add_header_library( libc.src.__support.CPP.type_traits ) -add_header_library( - integer_utils - HDRS - integer_utils.h - DEPENDS - .math_extras - .number_pair - libc.src.__support.common - libc.src.__support.CPP.bit - libc.src.__support.CPP.type_traits -) - add_header_library( uint HDRS UInt.h DEPENDS - .integer_utils .math_extras .number_pair libc.src.__support.CPP.array libc.src.__support.CPP.bit libc.src.__support.CPP.type_traits libc.src.__support.macros.optimization + libc.src.__support.macros.properties.types ) add_header_library( @@ -225,6 +214,7 @@ add_header_library( UInt128.h DEPENDS .uint + libc.src.__support.macros.properties.types ) add_header_library( diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt index 6c35bc7090819ee647de2642320a2defabc5796b..6216505eae23a35ccbb5009d1609178075bc947d 100644 --- a/libc/src/__support/CPP/CMakeLists.txt +++ b/libc/src/__support/CPP/CMakeLists.txt @@ -49,6 +49,7 @@ add_header_library( DEPENDS .type_traits libc.include.llvm-libc-macros.limits_macros + libc.src.__support.macros.properties.types ) add_header_library( diff --git a/libc/src/__support/CPP/bit.h b/libc/src/__support/CPP/bit.h index 7d11e7d5c497e0c5fe36ddf3afad300950f41445..1a05728b850653eea61971f1e0fdef0dcd9ac890 100644 --- a/libc/src/__support/CPP/bit.h +++ b/libc/src/__support/CPP/bit.h @@ -27,13 +27,14 @@ namespace LIBC_NAMESPACE::cpp { // This implementation of bit_cast requires trivially-constructible To, to avoid // UB in the implementation. -template < - typename To, typename From, - typename = cpp::enable_if_t::value && - cpp::is_trivially_copyable::value && - cpp::is_trivially_copyable::value>> -LIBC_INLINE constexpr To bit_cast(const From &from) { +template +LIBC_INLINE constexpr cpp::enable_if_t< + (sizeof(To) == sizeof(From)) && + cpp::is_trivially_constructible::value && + cpp::is_trivially_copyable::value && + cpp::is_trivially_copyable::value, + To> +bit_cast(const From &from) { MSAN_UNPOISON(&from, sizeof(From)); #if LIBC_HAS_BUILTIN(__builtin_bit_cast) return __builtin_bit_cast(To, from); @@ -51,8 +52,10 @@ LIBC_INLINE constexpr To bit_cast(const From &from) { #endif // LIBC_HAS_BUILTIN(__builtin_bit_cast) } -template >> -[[nodiscard]] LIBC_INLINE constexpr bool has_single_bit(T value) { +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, + bool> +has_single_bit(T value) { return (value != 0) && ((value & (value - 1)) == 0); } @@ -70,8 +73,9 @@ template >> /// Only unsigned integral types are allowed. /// /// Returns cpp::numeric_limits::digits on an input of 0. -template >> -[[nodiscard]] LIBC_INLINE constexpr int countr_zero(T value) { +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +countr_zero(T value) { if (!value) return cpp::numeric_limits::digits; if (value & 0x1) @@ -103,8 +107,9 @@ ADD_SPECIALIZATION(countr_zero, unsigned long long, __builtin_ctzll) /// Only unsigned integral types are allowed. /// /// Returns cpp::numeric_limits::digits on an input of 0. -template >> -[[nodiscard]] LIBC_INLINE constexpr int countl_zero(T value) { +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +countl_zero(T value) { if (!value) return cpp::numeric_limits::digits; // Bisection method. @@ -135,8 +140,9 @@ ADD_SPECIALIZATION(countl_zero, unsigned long long, __builtin_clzll) /// Only unsigned integral types are allowed. /// /// Returns cpp::numeric_limits::digits on an input of all ones. -template >> -[[nodiscard]] LIBC_INLINE constexpr int countl_one(T value) { +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +countl_one(T value) { return cpp::countl_zero(~value); } @@ -147,8 +153,9 @@ template >> /// Only unsigned integral types are allowed. /// /// Returns cpp::numeric_limits::digits on an input of all ones. -template >> -[[nodiscard]] LIBC_INLINE constexpr int countr_one(T value) { +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +countr_one(T value) { return cpp::countr_zero(~value); } @@ -156,8 +163,9 @@ template >> /// Returns 0 otherwise. /// /// Ex. bit_width(5) == 3. -template >> -[[nodiscard]] LIBC_INLINE constexpr int bit_width(T value) { +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +bit_width(T value) { return cpp::numeric_limits::digits - cpp::countl_zero(value); } @@ -165,11 +173,12 @@ template >> /// nonzero. Returns 0 otherwise. /// /// Ex. bit_floor(5) == 4. -template >> -[[nodiscard]] LIBC_INLINE constexpr T bit_floor(T value) { +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, T> +bit_floor(T value) { if (!value) return 0; - return T(1) << (cpp::bit_width(value) - 1); + return static_cast(T(1) << (cpp::bit_width(value) - 1)); } /// Returns the smallest integral power of two no smaller than value if value is @@ -179,39 +188,43 @@ template >> /// /// The return value is undefined if the input is larger than the largest power /// of two representable in T. -template >> -[[nodiscard]] LIBC_INLINE constexpr T bit_ceil(T value) { +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, T> +bit_ceil(T value) { if (value < 2) return 1; - return T(1) << cpp::bit_width(value - 1u); + return static_cast(T(1) << cpp::bit_width(value - 1U)); } // Rotate algorithms make use of "Safe, Efficient, and Portable Rotate in C/C++" // from https://blog.regehr.org/archives/1063. // Forward-declare rotr so that rotl can use it. -template >> -[[nodiscard]] LIBC_INLINE constexpr T rotr(T value, int rotate); +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, T> +rotr(T value, int rotate); -template >> -[[nodiscard]] LIBC_INLINE constexpr T rotl(T value, int rotate) { +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, T> +rotl(T value, int rotate) { constexpr unsigned N = cpp::numeric_limits::digits; rotate = rotate % N; if (!rotate) return value; if (rotate < 0) - return cpp::rotr(value, -rotate); + return cpp::rotr(value, -rotate); return (value << rotate) | (value >> (N - rotate)); } -template -[[nodiscard]] LIBC_INLINE constexpr T rotr(T value, int rotate) { +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, T> +rotr(T value, int rotate) { constexpr unsigned N = cpp::numeric_limits::digits; rotate = rotate % N; if (!rotate) return value; if (rotate < 0) - return cpp::rotl(value, -rotate); + return cpp::rotl(value, -rotate); return (value >> rotate) | (value << (N - rotate)); } @@ -226,33 +239,42 @@ LIBC_INLINE constexpr To bit_or_static_cast(const From &from) { } } -template >> -[[nodiscard]] LIBC_INLINE constexpr int first_leading_zero(T value) { +// TODO: remove from 'bit.h' as it is not a standard function. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +first_leading_zero(T value) { return value == cpp::numeric_limits::max() ? 0 : countl_one(value) + 1; } -template >> -[[nodiscard]] LIBC_INLINE constexpr int first_leading_one(T value) { +// TODO: remove from 'bit.h' as it is not a standard function. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +first_leading_one(T value) { return first_leading_zero(static_cast(~value)); } -template >> -[[nodiscard]] LIBC_INLINE constexpr int first_trailing_zero(T value) { +// TODO: remove from 'bit.h' as it is not a standard function. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +first_trailing_zero(T value) { return value == cpp::numeric_limits::max() ? 0 : countr_zero(static_cast(~value)) + 1; } -template >> -[[nodiscard]] LIBC_INLINE constexpr int first_trailing_one(T value) { +// TODO: remove from 'bit.h' as it is not a standard function. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +first_trailing_one(T value) { return value == cpp::numeric_limits::max() ? 0 : countr_zero(value) + 1; } -/// Count number of 1's aka population count or hamming weight. +/// Count number of 1's aka population count or Hamming weight. /// /// Only unsigned integral types are allowed. -template >> -[[nodiscard]] LIBC_INLINE constexpr int count_ones(T value) { +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +popcount(T value) { int count = 0; for (int i = 0; i != cpp::numeric_limits::digits; ++i) if ((value >> i) & 0x1) @@ -261,7 +283,7 @@ template >> } #define ADD_SPECIALIZATION(TYPE, BUILTIN) \ template <> \ - [[nodiscard]] LIBC_INLINE constexpr int count_ones(TYPE value) { \ + [[nodiscard]] LIBC_INLINE constexpr int popcount(TYPE value) { \ return BUILTIN(value); \ } ADD_SPECIALIZATION(unsigned char, __builtin_popcount) @@ -272,9 +294,11 @@ ADD_SPECIALIZATION(unsigned long long, __builtin_popcountll) // TODO: 128b specializations? #undef ADD_SPECIALIZATION -template >> -[[nodiscard]] LIBC_INLINE constexpr int count_zeros(T value) { - return count_ones(static_cast(~value)); +// TODO: remove from 'bit.h' as it is not a standard function. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +count_zeros(T value) { + return popcount(static_cast(~value)); } } // namespace LIBC_NAMESPACE::cpp diff --git a/libc/src/__support/CPP/limits.h b/libc/src/__support/CPP/limits.h index 1ffde5f9556f8718deb7f292b09137f2a2ce7b6f..5b9b3e755c72baacb3e76a59721729741f4677d1 100644 --- a/libc/src/__support/CPP/limits.h +++ b/libc/src/__support/CPP/limits.h @@ -12,7 +12,8 @@ #include "include/llvm-libc-macros/limits-macros.h" // CHAR_BIT #include "src/__support/CPP/type_traits/is_integral.h" #include "src/__support/CPP/type_traits/is_signed.h" -#include "src/__support/macros/attributes.h" // LIBC_INLINE +#include "src/__support/macros/attributes.h" // LIBC_INLINE +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 namespace LIBC_NAMESPACE { namespace cpp { @@ -76,7 +77,7 @@ template <> struct numeric_limits : public internal::integer_impl {}; -#ifdef __SIZEOF_INT128__ +#ifdef LIBC_TYPES_HAS_INT128 // On platform where UInt128 resolves to __uint128_t, this specialization // provides the limits of UInt128. template <> diff --git a/libc/src/__support/CPP/type_traits/is_integral.h b/libc/src/__support/CPP/type_traits/is_integral.h index 2808be594b20edd1884e5cb58e53e9e6ad1ad7aa..68e16ff84183360a5d2e63f48b28cd77ec165338 100644 --- a/libc/src/__support/CPP/type_traits/is_integral.h +++ b/libc/src/__support/CPP/type_traits/is_integral.h @@ -11,6 +11,7 @@ #include "src/__support/CPP/type_traits/is_same.h" #include "src/__support/CPP/type_traits/remove_cv.h" #include "src/__support/macros/attributes.h" +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 namespace LIBC_NAMESPACE::cpp { @@ -25,7 +26,7 @@ private: public: LIBC_INLINE_VAR static constexpr bool value = __is_unqualified_any_of< T, -#ifdef __SIZEOF_INT128__ +#ifdef LIBC_TYPES_HAS_INT128 __int128_t, __uint128_t, #endif char, signed char, unsigned char, short, unsigned short, int, diff --git a/libc/src/__support/CPP/type_traits/make_signed.h b/libc/src/__support/CPP/type_traits/make_signed.h index 21302850bfd4abd7390e5c888ea831c094b54562..4652d8b6bfa56ad9111c93735825f440352e307c 100644 --- a/libc/src/__support/CPP/type_traits/make_signed.h +++ b/libc/src/__support/CPP/type_traits/make_signed.h @@ -9,6 +9,7 @@ #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_MAKE_SIGNED_H #include "src/__support/CPP/type_traits/type_identity.h" +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 namespace LIBC_NAMESPACE::cpp { @@ -26,7 +27,7 @@ template <> struct make_signed : type_identity {}; template <> struct make_signed : type_identity {}; template <> struct make_signed : type_identity {}; -#ifdef __SIZEOF_INT128__ +#ifdef LIBC_TYPES_HAS_INT128 template <> struct make_signed<__int128_t> : type_identity<__int128_t> {}; template <> struct make_signed<__uint128_t> : type_identity<__int128_t> {}; #endif diff --git a/libc/src/__support/CPP/type_traits/make_unsigned.h b/libc/src/__support/CPP/type_traits/make_unsigned.h index 20948014a66574f50466be8ac42aeb077144e89d..1e814ae002a777b094fef12a8412b3be9d21e9b8 100644 --- a/libc/src/__support/CPP/type_traits/make_unsigned.h +++ b/libc/src/__support/CPP/type_traits/make_unsigned.h @@ -9,6 +9,7 @@ #define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_MAKE_UNSIGNED_H #include "src/__support/CPP/type_traits/type_identity.h" +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 namespace LIBC_NAMESPACE::cpp { @@ -31,7 +32,7 @@ template <> struct make_unsigned : type_identity {}; template <> struct make_unsigned : type_identity {}; -#ifdef __SIZEOF_INT128__ +#ifdef LIBC_TYPES_HAS_INT128 template <> struct make_unsigned<__int128_t> : type_identity<__uint128_t> {}; template <> struct make_unsigned<__uint128_t> : type_identity<__uint128_t> {}; #endif diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h index 7b3882dde1b72bb445952821bc502763108656a9..b06b3f7b73959a91fe89d88635c56d50947f77ea 100644 --- a/libc/src/__support/FPUtil/FPBits.h +++ b/libc/src/__support/FPUtil/FPBits.h @@ -640,6 +640,7 @@ public: using UP::EXP_MASK; using UP::FRACTION_MASK; using UP::SIG_LEN; + using UP::SIG_MASK; using UP::SIGN_MASK; LIBC_INLINE_VAR static constexpr int MAX_BIASED_EXPONENT = (1 << UP::EXP_LEN) - 1; @@ -729,6 +730,9 @@ public: bits = UP::merge(bits, mantVal, FRACTION_MASK); } + LIBC_INLINE constexpr void set_significand(StorageType sigVal) { + bits = UP::merge(bits, sigVal, SIG_MASK); + } // Unsafe function to create a floating point representation. // It simply packs the sign, biased exponent and mantissa values without // checking bound nor normalization. @@ -755,20 +759,19 @@ public: // 4) "number" zero value is not processed correctly. // 5) Number is unsigned, so the result can be only positive. LIBC_INLINE static constexpr RetT make_value(StorageType number, int ep) { - static_assert(fp_type != FPType::X86_Binary80, - "This function is not tested for X86 Extended Precision"); - FPRepImpl result; - // offset: +1 for sign, but -1 for implicit first bit - int lz = cpp::countl_zero(number) - UP::EXP_LEN; + FPRepImpl result(0); + int lz = + UP::FRACTION_LEN + 1 - (UP::STORAGE_LEN - cpp::countl_zero(number)); + number <<= lz; ep -= lz; if (LIBC_LIKELY(ep >= 0)) { // Implicit number bit will be removed by mask - result.set_mantissa(number); + result.set_significand(number); result.set_biased_exponent(ep + 1); } else { - result.set_mantissa(number >> -ep); + result.set_significand(number >> -ep); } return RetT(result.uintval()); } diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h index f25fa9b3026c1a8da2a952fe21be06526288bcd9..73fd7381c3c83877a44dcca5aa98499e7758e57d 100644 --- a/libc/src/__support/FPUtil/dyadic_float.h +++ b/libc/src/__support/FPUtil/dyadic_float.h @@ -31,7 +31,7 @@ namespace LIBC_NAMESPACE::fputil { // To simplify and improve the efficiency, many functions will assume that the // inputs are normal. template struct DyadicFloat { - using MantissaType = LIBC_NAMESPACE::cpp::UInt; + using MantissaType = LIBC_NAMESPACE::UInt; Sign sign = Sign::POS; int exponent = 0; diff --git a/libc/src/__support/FPUtil/generic/FMod.h b/libc/src/__support/FPUtil/generic/FMod.h index 2d31290bc4bc2ca9b6966c493a13ad9fc4c3686e..24fb264b779b734fac0071dc7f9d1e07f8761eac 100644 --- a/libc/src/__support/FPUtil/generic/FMod.h +++ b/libc/src/__support/FPUtil/generic/FMod.h @@ -117,63 +117,9 @@ namespace generic { // be implemented in another handler. // Signaling NaN converted to quiet NaN with FE_INVALID exception. // https://www.open-std.org/JTC1/SC22/WG14/www/docs/n1011.htm -template struct FModExceptionalInputHandler { - - static_assert(cpp::is_floating_point_v, - "FModCStandardWrapper instantiated with invalid type."); - - LIBC_INLINE static bool pre_check(T x, T y, T &out) { - using FPB = fputil::FPBits; - const T quiet_nan = FPB::quiet_nan().get_val(); - FPB sx(x), sy(y); - if (LIBC_LIKELY(!sy.is_zero() && !sy.is_inf_or_nan() && - !sx.is_inf_or_nan())) { - return false; - } - - if (sx.is_nan() || sy.is_nan()) { - if ((sx.is_nan() && !sx.is_quiet_nan()) || - (sy.is_nan() && !sy.is_quiet_nan())) - fputil::raise_except_if_required(FE_INVALID); - out = quiet_nan; - return true; - } - - if (sx.is_inf() || sy.is_zero()) { - fputil::raise_except_if_required(FE_INVALID); - fputil::set_errno_if_required(EDOM); - out = quiet_nan; - return true; - } - - if (sy.is_inf()) { - out = x; - return true; - } - - // case where x == 0 - out = x; - return true; - } -}; - -template struct FModFastMathWrapper { - - static_assert(cpp::is_floating_point_v, - "FModFastMathWrapper instantiated with invalid type."); - - static bool pre_check(T, T, T &) { return false; } -}; - -template class FModDivisionSimpleHelper { -private: - using StorageType = typename FPBits::StorageType; - -public: - LIBC_INLINE constexpr static StorageType execute(int exp_diff, - int sides_zeroes_count, - StorageType m_x, - StorageType m_y) { +template struct FModDivisionSimpleHelper { + LIBC_INLINE constexpr static T execute(int exp_diff, int sides_zeroes_count, + T m_x, T m_y) { while (exp_diff > sides_zeroes_count) { exp_diff -= sides_zeroes_count; m_x <<= sides_zeroes_count; @@ -185,28 +131,21 @@ public: } }; -template class FModDivisionInvMultHelper { -private: - using FPB = FPBits; - using StorageType = typename FPB::StorageType; - -public: - LIBC_INLINE constexpr static StorageType execute(int exp_diff, - int sides_zeroes_count, - StorageType m_x, - StorageType m_y) { +template struct FModDivisionInvMultHelper { + LIBC_INLINE constexpr static T execute(int exp_diff, int sides_zeroes_count, + T m_x, T m_y) { + constexpr int LENGTH = sizeof(T) * CHAR_BIT; if (exp_diff > sides_zeroes_count) { - StorageType inv_hy = (cpp::numeric_limits::max() / m_y); + T inv_hy = (cpp::numeric_limits::max() / m_y); while (exp_diff > sides_zeroes_count) { exp_diff -= sides_zeroes_count; - StorageType hd = - (m_x * inv_hy) >> (FPB::TOTAL_LEN - sides_zeroes_count); + T hd = (m_x * inv_hy) >> (LENGTH - sides_zeroes_count); m_x <<= sides_zeroes_count; m_x -= hd * m_y; while (LIBC_UNLIKELY(m_x > m_y)) m_x -= m_y; } - StorageType hd = (m_x * inv_hy) >> (FPB::TOTAL_LEN - exp_diff); + T hd = (m_x * inv_hy) >> (LENGTH - exp_diff); m_x <<= exp_diff; m_x -= hd * m_y; while (LIBC_UNLIKELY(m_x > m_y)) @@ -219,22 +158,49 @@ public: } }; -template , - class DivisionHelper = FModDivisionSimpleHelper> +template ::StorageType, + typename DivisionHelper = FModDivisionSimpleHelper> class FMod { - static_assert(cpp::is_floating_point_v, + static_assert(cpp::is_floating_point_v && cpp::is_unsigned_v && + (sizeof(U) * CHAR_BIT > FPBits::FRACTION_LEN), "FMod instantiated with invalid type."); private: using FPB = FPBits; using StorageType = typename FPB::StorageType; + LIBC_INLINE static bool pre_check(T x, T y, T &out) { + using FPB = fputil::FPBits; + const T quiet_nan = FPB::quiet_nan().get_val(); + FPB sx(x), sy(y); + if (LIBC_LIKELY(!sy.is_zero() && !sy.is_inf_or_nan() && + !sx.is_inf_or_nan())) + return false; + + if (sx.is_nan() || sy.is_nan()) { + if (sx.is_signaling_nan() || sy.is_signaling_nan()) + fputil::raise_except_if_required(FE_INVALID); + out = quiet_nan; + return true; + } + + if (sx.is_inf() || sy.is_zero()) { + fputil::raise_except_if_required(FE_INVALID); + fputil::set_errno_if_required(EDOM); + out = quiet_nan; + return true; + } + + out = x; + return true; + } + LIBC_INLINE static constexpr FPB eval_internal(FPB sx, FPB sy) { if (LIBC_LIKELY(sx.uintval() <= sy.uintval())) { if (sx.uintval() < sy.uintval()) return sx; // |x|<|y| return x - return FPB(FPB::zero()); // |x|=|y| return 0.0 + return FPB::zero(); // |x|=|y| return 0.0 } int e_x = sx.get_biased_exponent(); @@ -247,11 +213,11 @@ private: StorageType m_y = sy.get_explicit_mantissa(); StorageType d = (e_x == e_y) ? (m_x - m_y) : (m_x << (e_x - e_y)) % m_y; if (d == 0) - return FPB(FPB::zero()); + return FPB::zero(); // iy - 1 because of "zero power" for number with power 1 return FPB::make_value(d, e_y - 1); } - /* Both subnormal special case. */ + // Both subnormal special case. if (LIBC_UNLIKELY(e_x == 0 && e_y == 0)) { FPB d; d.set_mantissa(sx.uintval() % sy.uintval()); @@ -259,15 +225,17 @@ private: } // Note that hx is not subnormal by conditions above. - StorageType m_x = sx.get_explicit_mantissa(); + U m_x = static_cast(sx.get_explicit_mantissa()); e_x--; - StorageType m_y = sy.get_explicit_mantissa(); - int lead_zeros_m_y = FPB::EXP_LEN; + U m_y = static_cast(sy.get_explicit_mantissa()); + constexpr int DEFAULT_LEAD_ZEROS = + sizeof(U) * CHAR_BIT - FPB::FRACTION_LEN - 1; + int lead_zeros_m_y = DEFAULT_LEAD_ZEROS; if (LIBC_LIKELY(e_y > 0)) { e_y--; } else { - m_y = sy.get_mantissa(); + m_y = static_cast(sy.get_mantissa()); lead_zeros_m_y = cpp::countl_zero(m_y); } @@ -286,26 +254,27 @@ private: { // Shift hx left until the end or n = 0 - int left_shift = exp_diff < int(FPB::EXP_LEN) ? exp_diff : FPB::EXP_LEN; + int left_shift = + exp_diff < DEFAULT_LEAD_ZEROS ? exp_diff : DEFAULT_LEAD_ZEROS; m_x <<= left_shift; exp_diff -= left_shift; } m_x %= m_y; if (LIBC_UNLIKELY(m_x == 0)) - return FPB(FPB::zero()); + return FPB::zero(); if (exp_diff == 0) - return FPB::make_value(m_x, e_y); + return FPB::make_value(static_cast(m_x), e_y); - /* hx next can't be 0, because hx < hy, hy % 2 == 1 hx * 2^i % hy != 0 */ + // hx next can't be 0, because hx < hy, hy % 2 == 1 hx * 2^i % hy != 0 m_x = DivisionHelper::execute(exp_diff, sides_zeroes_count, m_x, m_y); - return FPB::make_value(m_x, e_y); + return FPB::make_value(static_cast(m_x), e_y); } public: LIBC_INLINE static T eval(T x, T y) { - if (T out; Wrapper::pre_check(x, y, out)) + if (T out; LIBC_UNLIKELY(pre_check(x, y, out))) return out; FPB sx(x), sy(y); Sign sign = sx.sign(); diff --git a/libc/src/__support/GPU/CMakeLists.txt b/libc/src/__support/GPU/CMakeLists.txt index d7ebd3cab7abe5b5ecbf87b46c1db17086d11ce7..28fd9a1ebcc97ed3e3c148d623c1b916fdbde885 100644 --- a/libc/src/__support/GPU/CMakeLists.txt +++ b/libc/src/__support/GPU/CMakeLists.txt @@ -1,11 +1,9 @@ -if(NOT LIBC_TARGET_OS_IS_GPU) +if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_ARCHITECTURE}) return() endif() -foreach(target nvptx amdgpu generic) - add_subdirectory(${target}) - list(APPEND target_gpu_utils libc.src.__support.GPU.${target}.${target}_utils) -endforeach() +add_subdirectory(${LIBC_TARGET_ARCHITECTURE}) +set(target_gpu_utils libc.src.__support.GPU.${LIBC_TARGET_ARCHITECTURE}.${LIBC_TARGET_ARCHITECTURE}_utils) add_header_library( utils @@ -14,3 +12,15 @@ add_header_library( DEPENDS ${target_gpu_utils} ) + +add_object_library( + allocator + SRCS + allocator.cpp + HDRS + allocator.h + DEPENDS + libc.src.__support.common + libc.src.__support.GPU.utils + libc.src.__support.RPC.rpc_client +) diff --git a/libc/src/__support/GPU/allocator.cpp b/libc/src/__support/GPU/allocator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a049959964cfc2f60ffe5eb54032bf23cc1768fc --- /dev/null +++ b/libc/src/__support/GPU/allocator.cpp @@ -0,0 +1,45 @@ +//===-- GPU memory allocator implementation ---------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "allocator.h" + +#include "src/__support/GPU/utils.h" +#include "src/__support/RPC/rpc_client.h" + +namespace LIBC_NAMESPACE { +namespace { + +void *rpc_allocate(uint64_t size) { + void *ptr = nullptr; + rpc::Client::Port port = rpc::client.open(); + port.send_and_recv([=](rpc::Buffer *buffer) { buffer->data[0] = size; }, + [&](rpc::Buffer *buffer) { + ptr = reinterpret_cast(buffer->data[0]); + }); + port.close(); + return ptr; +} + +void rpc_free(void *ptr) { + rpc::Client::Port port = rpc::client.open(); + port.send([=](rpc::Buffer *buffer) { + buffer->data[0] = reinterpret_cast(ptr); + }); + port.close(); +} + +} // namespace + +namespace gpu { + +void *allocate(uint64_t size) { return rpc_allocate(size); } + +void deallocate(void *ptr) { rpc_free(ptr); } + +} // namespace gpu +} // namespace LIBC_NAMESPACE diff --git a/libc/src/__support/GPU/allocator.h b/libc/src/__support/GPU/allocator.h new file mode 100644 index 0000000000000000000000000000000000000000..99eeb6826cc284b35fbf1db4b685bd36c8b5164a --- /dev/null +++ b/libc/src/__support/GPU/allocator.h @@ -0,0 +1,23 @@ +//===-- GPU memory allocator implementation ---------------------*- 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___SUPPORT_GPU_ALLOCATOR_H +#define LLVM_LIBC_SRC___SUPPORT_GPU_ALLOCATOR_H + +#include + +namespace LIBC_NAMESPACE { +namespace gpu { + +void *allocate(uint64_t size); +void deallocate(void *ptr); + +} // namespace gpu +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC___SUPPORT_GPU_ALLOCATOR_H diff --git a/libc/src/__support/RPC/rpc.h b/libc/src/__support/RPC/rpc.h index 5ed39ae0d7f7a90b81fc5f585414043844e3567f..5dcae518bb6f8fc1438457d5e3ebacbf36270a7d 100644 --- a/libc/src/__support/RPC/rpc.h +++ b/libc/src/__support/RPC/rpc.h @@ -310,7 +310,7 @@ private: LIBC_INLINE Port &operator=(Port &&) = default; friend struct Client; - template friend struct Server; + friend struct Server; friend class cpp::optional>; public: @@ -369,7 +369,7 @@ static_assert(cpp::is_trivially_copyable::value && "The client is not trivially copyable from the server"); /// The RPC server used to respond to the client. -template struct Server { +struct Server { LIBC_INLINE Server() = default; LIBC_INLINE Server(const Server &) = delete; LIBC_INLINE Server &operator=(const Server &) = delete; @@ -379,10 +379,12 @@ template struct Server { : process(port_count, buffer) {} using Port = rpc::Port; - LIBC_INLINE cpp::optional try_open(uint32_t start = 0); - LIBC_INLINE Port open(); + LIBC_INLINE cpp::optional try_open(uint32_t lane_size, + uint32_t start = 0); + LIBC_INLINE Port open(uint32_t lane_size); - LIBC_INLINE static uint64_t allocation_size(uint32_t port_count) { + LIBC_INLINE static uint64_t allocation_size(uint32_t lane_size, + uint32_t port_count) { return Process::allocation_size(port_count, lane_size); } @@ -556,10 +558,8 @@ template /// Attempts to open a port to use as the server. The server can only open a /// port if it has a pending receive operation -template -[[clang::convergent]] LIBC_INLINE - cpp::optional::Port> - Server::try_open(uint32_t start) { +[[clang::convergent]] LIBC_INLINE cpp::optional +Server::try_open(uint32_t lane_size, uint32_t start) { // Perform a naive linear scan for a port that has a pending request. for (uint32_t index = start; index < process.port_count; ++index) { uint64_t lane_mask = gpu::get_lane_mask(); @@ -588,10 +588,9 @@ template return cpp::nullopt; } -template -LIBC_INLINE typename Server::Port Server::open() { +LIBC_INLINE Server::Port Server::open(uint32_t lane_size) { for (;;) { - if (cpp::optional p = try_open()) + if (cpp::optional p = try_open(lane_size)) return cpp::move(p.value()); sleep_briefly(); } diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h index ae1fe7aaa182871c10dcd4d72c9faf8fc4b46dec..d92d61ed094ebe1a8eeca3a78b87df8211236d96 100644 --- a/libc/src/__support/UInt.h +++ b/libc/src/__support/UInt.h @@ -14,35 +14,84 @@ #include "src/__support/CPP/limits.h" #include "src/__support/CPP/optional.h" #include "src/__support/CPP/type_traits.h" -#include "src/__support/integer_utils.h" #include "src/__support/macros/attributes.h" // LIBC_INLINE #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY -#include "src/__support/math_extras.h" // SumCarry, DiffBorrow +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128, LIBC_TYPES_HAS_INT64 +#include "src/__support/math_extras.h" // SumCarry, DiffBorrow #include "src/__support/number_pair.h" #include // For size_t #include -namespace LIBC_NAMESPACE::cpp { +namespace LIBC_NAMESPACE { namespace internal { template struct half_width; -template <> struct half_width : type_identity {}; -template <> struct half_width : type_identity {}; -template <> struct half_width : type_identity {}; -#ifdef __SIZEOF_INT128__ -template <> struct half_width<__uint128_t> : type_identity {}; -#endif // __SIZEOF_INT128__ +template <> struct half_width : cpp::type_identity {}; +template <> struct half_width : cpp::type_identity {}; +template <> struct half_width : cpp::type_identity {}; +#ifdef LIBC_TYPES_HAS_INT128 +template <> struct half_width<__uint128_t> : cpp::type_identity {}; +#endif // LIBC_TYPES_HAS_INT128 template using half_width_t = typename half_width::type; + +template constexpr NumberPair full_mul(T a, T b) { + NumberPair pa = split(a); + NumberPair pb = split(b); + NumberPair prod; + + prod.lo = pa.lo * pb.lo; // exact + prod.hi = pa.hi * pb.hi; // exact + NumberPair lo_hi = split(pa.lo * pb.hi); // exact + NumberPair hi_lo = split(pa.hi * pb.lo); // exact + + constexpr size_t HALF_BIT_WIDTH = sizeof(T) * CHAR_BIT / 2; + + auto r1 = add_with_carry(prod.lo, lo_hi.lo << HALF_BIT_WIDTH, T(0)); + prod.lo = r1.sum; + prod.hi = add_with_carry(prod.hi, lo_hi.hi, r1.carry).sum; + + auto r2 = add_with_carry(prod.lo, hi_lo.lo << HALF_BIT_WIDTH, T(0)); + prod.lo = r2.sum; + prod.hi = add_with_carry(prod.hi, hi_lo.hi, r2.carry).sum; + + return prod; +} + +template <> +LIBC_INLINE constexpr NumberPair full_mul(uint32_t a, + uint32_t b) { + uint64_t prod = uint64_t(a) * uint64_t(b); + NumberPair result; + result.lo = uint32_t(prod); + result.hi = uint32_t(prod >> 32); + return result; +} + +#ifdef LIBC_TYPES_HAS_INT128 +template <> +LIBC_INLINE constexpr NumberPair full_mul(uint64_t a, + uint64_t b) { + __uint128_t prod = __uint128_t(a) * __uint128_t(b); + NumberPair result; + result.lo = uint64_t(prod); + result.hi = uint64_t(prod >> 64); + return result; +} +#endif // LIBC_TYPES_HAS_INT128 + } // namespace internal template struct BigInt { - static_assert(is_integral_v && is_unsigned_v, + static_assert(cpp::is_integral_v && cpp::is_unsigned_v, "WordType must be unsigned integer."); + using word_type = WordType; + LIBC_INLINE_VAR static constexpr bool SIGNED = Signed; + LIBC_INLINE_VAR static constexpr size_t BITS = Bits; LIBC_INLINE_VAR static constexpr size_t WORD_SIZE = sizeof(WordType) * CHAR_BIT; @@ -50,6 +99,10 @@ struct BigInt { "Number of bits in BigInt should be a multiple of WORD_SIZE."); LIBC_INLINE_VAR static constexpr size_t WORD_COUNT = Bits / WORD_SIZE; + + using unsigned_type = BigInt; + using signed_type = BigInt; + cpp::array val{}; LIBC_INLINE constexpr BigInt() = default; @@ -69,7 +122,7 @@ struct BigInt { WordType sign = 0; if constexpr (Signed && OtherSigned) { sign = static_cast( - -static_cast>(other.is_neg())); + -static_cast>(other.is_neg())); } for (; i < WORD_COUNT; ++i) val[i] = sign; @@ -77,7 +130,7 @@ struct BigInt { } // Construct a BigInt from a C array. - template = 0> + template = 0> LIBC_INLINE constexpr BigInt(const WordType (&nums)[N]) { size_t min_wordcount = N < WORD_COUNT ? N : WORD_COUNT; size_t i = 0; @@ -90,7 +143,7 @@ struct BigInt { } // Initialize the first word to |v| and the rest to 0. - template >> + template >> LIBC_INLINE constexpr BigInt(T v) { val[0] = static_cast(v); @@ -255,15 +308,13 @@ struct BigInt { // Returns the carry value produced by the multiplication operation. LIBC_INLINE constexpr WordType mul(WordType x) { BigInt<2 * WORD_SIZE, Signed, WordType> partial_sum(0); - WordType carry = 0; for (size_t i = 0; i < WORD_COUNT; ++i) { - NumberPair prod = full_mul(val[i], x); + NumberPair prod = internal::full_mul(val[i], x); BigInt<2 * WORD_SIZE, Signed, WordType> tmp({prod.lo, prod.hi}); - carry += partial_sum.add(tmp); + const WordType carry = partial_sum.add(tmp); val[i] = partial_sum.val[0]; partial_sum.val[0] = partial_sum.val[1]; partial_sum.val[1] = carry; - carry = 0; } return partial_sum.val[1]; } @@ -291,7 +342,8 @@ struct BigInt { WordType carry = 0; for (size_t i = 0; i < WORD_COUNT; ++i) { for (size_t j = 0; j <= i; j++) { - NumberPair prod = full_mul(val[j], other.val[i - j]); + NumberPair prod = + internal::full_mul(val[j], other.val[i - j]); BigInt<2 * WORD_SIZE, Signed, WordType> tmp({prod.lo, prod.hi}); carry += partial_sum.add(tmp); } @@ -319,7 +371,8 @@ struct BigInt { i < OTHER_WORDCOUNT ? 0 : i - OTHER_WORDCOUNT + 1; const size_t upper_idx = i < WORD_COUNT ? i : WORD_COUNT - 1; for (size_t j = lower_idx; j <= upper_idx; ++j) { - NumberPair prod = full_mul(val[j], other.val[i - j]); + NumberPair prod = + internal::full_mul(val[j], other.val[i - j]); BigInt<2 * WORD_SIZE, Signed, WordType> tmp({prod.lo, prod.hi}); carry += partial_sum.add(tmp); } @@ -361,7 +414,7 @@ struct BigInt { // product. for (size_t i = 0; i < WORD_COUNT; ++i) { NumberPair prod = - full_mul(val[i], other.val[WORD_COUNT - 1 - i]); + internal::full_mul(val[i], other.val[WORD_COUNT - 1 - i]); BigInt<2 * WORD_SIZE, Signed, WordType> tmp({prod.lo, prod.hi}); carry += partial_sum.add(tmp); } @@ -370,7 +423,8 @@ struct BigInt { partial_sum.val[1] = carry; carry = 0; for (size_t j = i - WORD_COUNT + 1; j < WORD_COUNT; ++j) { - NumberPair prod = full_mul(val[j], other.val[i - j]); + NumberPair prod = + internal::full_mul(val[j], other.val[i - j]); BigInt<2 * WORD_SIZE, Signed, WordType> tmp({prod.lo, prod.hi}); carry += partial_sum.add(tmp); } @@ -399,7 +453,7 @@ struct BigInt { // div takes another BigInt of the same size and divides this by it. The value // of this will be set to the quotient, and the return value is the remainder. - LIBC_INLINE constexpr optional div(const BigInt &other) { + LIBC_INLINE constexpr cpp::optional div(const BigInt &other) { BigInt remainder(0); if (*this < other) { remainder = *this; @@ -410,7 +464,7 @@ struct BigInt { return remainder; } if (other == 0) { - return nullopt; + return cpp::nullopt; } BigInt quotient(0); @@ -441,12 +495,12 @@ struct BigInt { // Since the remainder of each division step < x < 2^(WORD_SIZE / 2), the // computation of each step is now properly contained within WordType. // And finally we perform some extra alignment steps for the remaining bits. - LIBC_INLINE constexpr optional + LIBC_INLINE constexpr cpp::optional div_uint_half_times_pow_2(internal::half_width_t x, size_t e) { BigInt remainder(0); if (x == 0) { - return nullopt; + return cpp::nullopt; } if (e >= Bits) { remainder = *this; @@ -456,7 +510,7 @@ struct BigInt { BigInt quotient(0); WordType x_word = static_cast(x); - constexpr size_t LOG2_WORD_SIZE = bit_width(WORD_SIZE) - 1; + constexpr size_t LOG2_WORD_SIZE = cpp::bit_width(WORD_SIZE) - 1; constexpr size_t HALF_WORD_SIZE = WORD_SIZE >> 1; constexpr WordType HALF_MASK = ((WordType(1) << HALF_WORD_SIZE) - 1); // lower = smallest multiple of WORD_SIZE that is >= e. @@ -579,19 +633,33 @@ struct BigInt { return *this; } - LIBC_INLINE constexpr uint64_t clz() { - uint64_t leading_zeroes = 0; - for (size_t i = WORD_COUNT; i > 0; --i) { - if (val[i - 1] == 0) { - leading_zeroes += WORD_SIZE; - } else { - leading_zeroes += countl_zero(val[i - 1]); + // TODO: remove and use cpp::countl_zero below. + [[nodiscard]] LIBC_INLINE constexpr int clz() const { + constexpr int word_digits = cpp::numeric_limits::digits; + int leading_zeroes = 0; + for (auto i = val.size(); i > 0;) { + --i; + const int zeroes = cpp::countl_zero(val[i]); + leading_zeroes += zeroes; + if (zeroes != word_digits) break; - } } return leading_zeroes; } + // TODO: remove and use cpp::countr_zero below. + [[nodiscard]] LIBC_INLINE constexpr int ctz() const { + constexpr int word_digits = cpp::numeric_limits::digits; + int trailing_zeroes = 0; + for (auto word : val) { + const int zeroes = cpp::countr_zero(word); + trailing_zeroes += zeroes; + if (zeroes != word_digits) + break; + } + return trailing_zeroes; + } + LIBC_INLINE constexpr void shift_left(size_t s) { if constexpr (Bits == WORD_SIZE) { // Use native types if possible. @@ -615,7 +683,7 @@ struct BigInt { val[1] = uint32_t(tmp >> 32); return; } -#ifdef __SIZEOF_INT128__ +#ifdef LIBC_TYPES_HAS_INT128 if constexpr ((Bits == 128) && (WORD_SIZE == 64)) { // Use builtin 128 bits if available; if (s >= 128) { @@ -629,7 +697,7 @@ struct BigInt { val[1] = uint64_t(tmp >> 64); return; } -#endif // __SIZEOF_INT128__ +#endif // LIBC_TYPES_HAS_INT128 if (LIBC_UNLIKELY(s == 0)) return; @@ -686,7 +754,7 @@ struct BigInt { val[1] = uint32_t(tmp >> 32); return; } -#ifdef __SIZEOF_INT128__ +#ifdef LIBC_TYPES_HAS_INT128 if constexpr ((Bits == 128) && (WORD_SIZE == 64)) { // Use builtin 128 bits if available; if (s >= 128) { @@ -704,7 +772,7 @@ struct BigInt { val[1] = uint64_t(tmp >> 64); return; } -#endif // __SIZEOF_INT128__ +#endif // LIBC_TYPES_HAS_INT128 if (LIBC_UNLIKELY(s == 0)) return; @@ -872,11 +940,11 @@ namespace internal { // availability. template struct WordTypeSelector : cpp::type_identity< -#if defined(UINT64_MAX) +#ifdef LIBC_TYPES_HAS_INT64 uint64_t #else uint32_t -#endif +#endif // LIBC_TYPES_HAS_INT64 > { }; // Except if we request 32 bits explicitly. @@ -892,16 +960,18 @@ template using Int = BigInt>; // Provides limits of U/Int<128>. -template <> class numeric_limits> { +template <> class cpp::numeric_limits> { public: LIBC_INLINE static constexpr UInt<128> max() { return UInt<128>({0xffff'ffff'ffff'ffff, 0xffff'ffff'ffff'ffff}); } LIBC_INLINE static constexpr UInt<128> min() { return UInt<128>(0); } + // Meant to match std::numeric_limits interface. + // NOLINTNEXTLINE(readability-identifier-naming) LIBC_INLINE_VAR static constexpr int digits = 128; }; -template <> class numeric_limits> { +template <> class cpp::numeric_limits> { public: LIBC_INLINE static constexpr Int<128> max() { return Int<128>({0xffff'ffff'ffff'ffff, 0x7fff'ffff'ffff'ffff}); @@ -909,69 +979,183 @@ public: LIBC_INLINE static constexpr Int<128> min() { return Int<128>({0, 0x8000'0000'0000'0000}); } + // Meant to match std::numeric_limits interface. + // NOLINTNEXTLINE(readability-identifier-naming) LIBC_INLINE_VAR static constexpr int digits = 128; }; -// Provides is_integral of U/Int<128>, U/Int<192>, U/Int<256>. -template -struct is_integral> : cpp::true_type {}; +// type traits to determine whether a T is a BigInt. +template struct is_big_int : cpp::false_type {}; -// Provides is_unsigned of UInt<128>, UInt<192>, UInt<256>. template -struct is_unsigned> : cpp::bool_constant {}; +struct is_big_int> : cpp::true_type {}; -template -struct make_unsigned> - : type_identity> {}; +template +LIBC_INLINE_VAR constexpr bool is_big_int_v = is_big_int::value; -template -struct make_signed> - : type_identity> {}; +namespace cpp { -namespace internal { -template struct is_custom_uint : cpp::false_type {}; - -template -struct is_custom_uint> : cpp::true_type {}; -} // namespace internal - -// bit_cast to UInt -// Note: The standard scheme for SFINAE selection is to have exactly one -// function instanciation valid at a time. This is usually done by having a -// predicate in one function and the negated predicate in the other one. -// e.g. -// template::value == true> ... -// template::value == false> ... -// -// Unfortunately this would make the default 'cpp::bit_cast' aware of -// 'is_custom_uint' (or any other customization). To prevent exposing all -// customizations in the original function, we create a different function with -// four 'typename's instead of three - otherwise it would be considered as a -// redeclaration of the same function leading to "error: template parameter -// redefines default argument". -template ::value && - cpp::is_trivially_copyable::value>, - typename = cpp::enable_if_t::value>> -LIBC_INLINE constexpr To bit_cast(const From &from) { +// Specialization of cpp::bit_cast ('bit.h') from T to BigInt. +template +LIBC_INLINE constexpr cpp::enable_if_t< + (sizeof(To) == sizeof(From)) && cpp::is_trivially_copyable::value && + cpp::is_trivially_copyable::value && is_big_int::value, + To> +bit_cast(const From &from) { To out; using Storage = decltype(out.val); out.val = cpp::bit_cast(from); return out; } -// bit_cast from UInt -template < - typename To, size_t Bits, - typename = cpp::enable_if_t) && - cpp::is_trivially_constructible::value && - cpp::is_trivially_copyable::value && - cpp::is_trivially_copyable>::value>> -LIBC_INLINE constexpr To bit_cast(const UInt &from) { +// Specialization of cpp::bit_cast ('bit.h') from BigInt to T. +template +LIBC_INLINE constexpr cpp::enable_if_t< + sizeof(To) == sizeof(UInt) && + cpp::is_trivially_constructible::value && + cpp::is_trivially_copyable::value && + cpp::is_trivially_copyable>::value, + To> +bit_cast(const UInt &from) { return cpp::bit_cast(from.val); } -} // namespace LIBC_NAMESPACE::cpp +// Specialization of cpp::has_single_bit ('bit.h') for BigInt. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, bool> +has_single_bit(T value) { + int bits = 0; + for (auto word : value.val) { + if (word == 0) + continue; + bits += popcount(word); + if (bits > 1) + return false; + } + return bits == 1; +} + +// Specialization of cpp::countr_zero ('bit.h') for BigInt. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +countr_zero(const T &value) { + return value.ctz(); +} + +// Specialization of cpp::countl_zero ('bit.h') for BigInt. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +countl_zero(const T &value) { + return value.clz(); +} + +// Specialization of cpp::countl_one ('bit.h') for BigInt. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +countl_one(T value) { + // TODO : Implement a faster version not involving operator~. + return cpp::countl_zero(~value); +} + +// Specialization of cpp::countr_one ('bit.h') for BigInt. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +countr_one(T value) { + // TODO : Implement a faster version not involving operator~. + return cpp::countr_zero(~value); +} + +// Specialization of cpp::bit_width ('bit.h') for BigInt. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, int> +bit_width(T value) { + return cpp::numeric_limits::digits - cpp::countl_zero(value); +} + +// Forward-declare rotr so that rotl can use it. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, T> +rotr(T value, int rotate); + +// Specialization of cpp::rotl ('bit.h') for BigInt. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, T> +rotl(T value, int rotate) { + constexpr unsigned N = cpp::numeric_limits::digits; + rotate = rotate % N; + if (!rotate) + return value; + if (rotate < 0) + return cpp::rotr(value, -rotate); + return (value << rotate) | (value >> (N - rotate)); +} + +// Specialization of cpp::rotr ('bit.h') for BigInt. +template +[[nodiscard]] LIBC_INLINE constexpr cpp::enable_if_t, T> +rotr(T value, int rotate) { + constexpr unsigned N = cpp::numeric_limits::digits; + rotate = rotate % N; + if (!rotate) + return value; + if (rotate < 0) + return cpp::rotl(value, -rotate); + return (value >> rotate) | (value << (N - rotate)); +} + +} // namespace cpp + +// Specialization of mask_trailing_ones ('math_extras.h') for BigInt. +template +LIBC_INLINE constexpr cpp::enable_if_t, T> +mask_trailing_ones() { + static_assert(!T::SIGNED); + if (count == 0) + return T(); + constexpr unsigned T_BITS = CHAR_BIT * sizeof(T); + static_assert(count <= T_BITS && "Invalid bit index"); + using word_type = typename T::word_type; + T out; + constexpr int CHUNK_INDEX_CONTAINING_BIT = + static_cast(count / T::WORD_SIZE); + int index = 0; + for (auto &word : out.val) { + if (index < CHUNK_INDEX_CONTAINING_BIT) + word = -1; + else if (index > CHUNK_INDEX_CONTAINING_BIT) + word = 0; + else + word = mask_trailing_ones(); + ++index; + } + return out; +} + +// Specialization of mask_leading_ones ('math_extras.h') for BigInt. +template +LIBC_INLINE constexpr cpp::enable_if_t, T> mask_leading_ones() { + static_assert(!T::SIGNED); + if (count == 0) + return T(); + constexpr unsigned T_BITS = CHAR_BIT * sizeof(T); + static_assert(count <= T_BITS && "Invalid bit index"); + using word_type = typename T::word_type; + T out; + constexpr int CHUNK_INDEX_CONTAINING_BIT = + static_cast((T::BITS - count - 1ULL) / T::WORD_SIZE); + int index = 0; + for (auto &word : out.val) { + if (index < CHUNK_INDEX_CONTAINING_BIT) + word = 0; + else if (index > CHUNK_INDEX_CONTAINING_BIT) + word = -1; + else + word = mask_leading_ones(); + ++index; + } + return out; +} + +} // namespace LIBC_NAMESPACE #endif // LLVM_LIBC_SRC___SUPPORT_UINT_H diff --git a/libc/src/__support/UInt128.h b/libc/src/__support/UInt128.h index 0558e5095f9f51dc6972437d2dae6e37d73dbe2a..b6ef9ca18eb01f80cc93bca2e85f555a78c15bc3 100644 --- a/libc/src/__support/UInt128.h +++ b/libc/src/__support/UInt128.h @@ -10,13 +10,14 @@ #define LLVM_LIBC_SRC___SUPPORT_UINT128_H #include "UInt.h" +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 -#if defined(__SIZEOF_INT128__) +#ifdef LIBC_TYPES_HAS_INT128 using UInt128 = __uint128_t; using Int128 = __int128_t; #else -using UInt128 = LIBC_NAMESPACE::cpp::UInt<128>; -using Int128 = LIBC_NAMESPACE::cpp::Int<128>; -#endif +using UInt128 = LIBC_NAMESPACE::UInt<128>; +using Int128 = LIBC_NAMESPACE::Int<128>; +#endif // LIBC_TYPES_HAS_INT128 #endif // LLVM_LIBC_SRC___SUPPORT_UINT128_H diff --git a/libc/src/__support/blockstore.h b/libc/src/__support/blockstore.h index d78e4be5fa9ca42f02bfcb661e0cf38d896ebd8b..dc5fdd1b92fc29f1f79f125b99b4e57d58e50182 100644 --- a/libc/src/__support/blockstore.h +++ b/libc/src/__support/blockstore.h @@ -45,7 +45,7 @@ protected: struct Pair { Block *first, *second; }; - Pair getLastBlocks() { + Pair get_last_blocks() { if (REVERSE_ORDER) return {current, current->next}; Block *prev = nullptr; @@ -56,20 +56,20 @@ protected: return {curr, prev}; } - Block *getLastBlock() { return getLastBlocks().first; } + Block *get_last_block() { return get_last_blocks().first; } public: constexpr BlockStore() = default; ~BlockStore() = default; - class iterator { + class Iterator { Block *block; size_t index; public: - constexpr iterator(Block *b, size_t i) : block(b), index(i) {} + constexpr Iterator(Block *b, size_t i) : block(b), index(i) {} - iterator &operator++() { + Iterator &operator++() { if (REVERSE_ORDER) { if (index == 0) return *this; @@ -98,11 +98,11 @@ public: return *reinterpret_cast(block->data + sizeof(T) * true_index); } - bool operator==(const iterator &rhs) const { + bool operator==(const Iterator &rhs) const { return block == rhs.block && index == rhs.index; } - bool operator!=(const iterator &rhs) const { + bool operator!=(const Iterator &rhs) const { return block != rhs.block || index != rhs.index; } }; @@ -138,7 +138,7 @@ public: } T &back() { - return *reinterpret_cast(getLastBlock()->data + + return *reinterpret_cast(get_last_block()->data + sizeof(T) * (fill_count - 1)); } @@ -146,7 +146,7 @@ public: fill_count--; if (fill_count || current == &first) return; - auto [last, prev] = getLastBlocks(); + auto [last, prev] = get_last_blocks(); if (REVERSE_ORDER) { LIBC_ASSERT(last == current); current = current->next; @@ -162,18 +162,18 @@ public: bool empty() const { return current == &first && !fill_count; } - iterator begin() { + Iterator begin() { if (REVERSE_ORDER) - return iterator(current, fill_count); + return Iterator(current, fill_count); else - return iterator(&first, 0); + return Iterator(&first, 0); } - iterator end() { + Iterator end() { if (REVERSE_ORDER) - return iterator(&first, 0); + return Iterator(&first, 0); else - return iterator(current, fill_count); + return Iterator(current, fill_count); } }; diff --git a/libc/src/__support/fixed_point/CMakeLists.txt b/libc/src/__support/fixed_point/CMakeLists.txt index 0ed118f24088492df2d46e0c4383a443d1ad4f8b..3b744081765e4fad04471ee529ef3437cd12705e 100644 --- a/libc/src/__support/fixed_point/CMakeLists.txt +++ b/libc/src/__support/fixed_point/CMakeLists.txt @@ -32,5 +32,6 @@ add_header_library( libc.src.__support.macros.attributes libc.src.__support.macros.optimization libc.src.__support.CPP.bit + libc.src.__support.CPP.limits libc.src.__support.CPP.type_traits ) diff --git a/libc/src/__support/fixed_point/fx_rep.h b/libc/src/__support/fixed_point/fx_rep.h index f8593a93684cbcda3a74eb62454411ce11fb79dd..f13640a6c0191821f06d04fe0c0c8b26b2c6e091 100644 --- a/libc/src/__support/fixed_point/fx_rep.h +++ b/libc/src/__support/fixed_point/fx_rep.h @@ -45,9 +45,11 @@ template <> struct FXRep { SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; LIBC_INLINE static constexpr Type MIN() { return SFRACT_MIN; } - LIBC_INLINE static constexpr Type MAX() { return SFRACT_MIN; } + LIBC_INLINE static constexpr Type MAX() { return SFRACT_MAX; } LIBC_INLINE static constexpr Type ZERO() { return 0.0HR; } LIBC_INLINE static constexpr Type EPS() { return SFRACT_EPSILON; } + LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5HR; } + LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25HR; } using StorageType = typename internal::Storage::Type; using CompType = cpp::make_signed_t; @@ -63,9 +65,11 @@ template <> struct FXRep { SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; LIBC_INLINE static constexpr Type MIN() { return USFRACT_MIN; } - LIBC_INLINE static constexpr Type MAX() { return USFRACT_MIN; } + LIBC_INLINE static constexpr Type MAX() { return USFRACT_MAX; } LIBC_INLINE static constexpr Type ZERO() { return 0.0UHR; } LIBC_INLINE static constexpr Type EPS() { return USFRACT_EPSILON; } + LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5UHR; } + LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25UHR; } using StorageType = typename internal::Storage::Type; using CompType = cpp::make_unsigned_t; @@ -81,9 +85,11 @@ template <> struct FXRep { SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; LIBC_INLINE static constexpr Type MIN() { return FRACT_MIN; } - LIBC_INLINE static constexpr Type MAX() { return FRACT_MIN; } + LIBC_INLINE static constexpr Type MAX() { return FRACT_MAX; } LIBC_INLINE static constexpr Type ZERO() { return 0.0R; } LIBC_INLINE static constexpr Type EPS() { return FRACT_EPSILON; } + LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5R; } + LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25R; } using StorageType = typename internal::Storage::Type; using CompType = cpp::make_signed_t; @@ -99,9 +105,11 @@ template <> struct FXRep { SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; LIBC_INLINE static constexpr Type MIN() { return UFRACT_MIN; } - LIBC_INLINE static constexpr Type MAX() { return UFRACT_MIN; } + LIBC_INLINE static constexpr Type MAX() { return UFRACT_MAX; } LIBC_INLINE static constexpr Type ZERO() { return 0.0UR; } LIBC_INLINE static constexpr Type EPS() { return UFRACT_EPSILON; } + LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5UR; } + LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25UR; } using StorageType = typename internal::Storage::Type; using CompType = cpp::make_unsigned_t; @@ -117,9 +125,11 @@ template <> struct FXRep { SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; LIBC_INLINE static constexpr Type MIN() { return LFRACT_MIN; } - LIBC_INLINE static constexpr Type MAX() { return LFRACT_MIN; } + LIBC_INLINE static constexpr Type MAX() { return LFRACT_MAX; } LIBC_INLINE static constexpr Type ZERO() { return 0.0LR; } LIBC_INLINE static constexpr Type EPS() { return LFRACT_EPSILON; } + LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5LR; } + LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25LR; } using StorageType = typename internal::Storage::Type; using CompType = cpp::make_signed_t; @@ -135,9 +145,11 @@ template <> struct FXRep { SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; LIBC_INLINE static constexpr Type MIN() { return ULFRACT_MIN; } - LIBC_INLINE static constexpr Type MAX() { return ULFRACT_MIN; } + LIBC_INLINE static constexpr Type MAX() { return ULFRACT_MAX; } LIBC_INLINE static constexpr Type ZERO() { return 0.0ULR; } LIBC_INLINE static constexpr Type EPS() { return ULFRACT_EPSILON; } + LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5ULR; } + LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25ULR; } using StorageType = typename internal::Storage::Type; using CompType = cpp::make_unsigned_t; @@ -153,9 +165,11 @@ template <> struct FXRep { SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; LIBC_INLINE static constexpr Type MIN() { return SACCUM_MIN; } - LIBC_INLINE static constexpr Type MAX() { return SACCUM_MIN; } + LIBC_INLINE static constexpr Type MAX() { return SACCUM_MAX; } LIBC_INLINE static constexpr Type ZERO() { return 0.0HK; } LIBC_INLINE static constexpr Type EPS() { return SACCUM_EPSILON; } + LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5HK; } + LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25HK; } using StorageType = typename internal::Storage::Type; using CompType = cpp::make_signed_t; @@ -171,9 +185,11 @@ template <> struct FXRep { SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; LIBC_INLINE static constexpr Type MIN() { return USACCUM_MIN; } - LIBC_INLINE static constexpr Type MAX() { return USACCUM_MIN; } + LIBC_INLINE static constexpr Type MAX() { return USACCUM_MAX; } LIBC_INLINE static constexpr Type ZERO() { return 0.0UHK; } LIBC_INLINE static constexpr Type EPS() { return USACCUM_EPSILON; } + LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5UHK; } + LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25UHK; } using StorageType = typename internal::Storage::Type; using CompType = cpp::make_unsigned_t; @@ -189,9 +205,11 @@ template <> struct FXRep { SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; LIBC_INLINE static constexpr Type MIN() { return ACCUM_MIN; } - LIBC_INLINE static constexpr Type MAX() { return ACCUM_MIN; } + LIBC_INLINE static constexpr Type MAX() { return ACCUM_MAX; } LIBC_INLINE static constexpr Type ZERO() { return 0.0K; } LIBC_INLINE static constexpr Type EPS() { return ACCUM_EPSILON; } + LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5K; } + LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25K; } using StorageType = typename internal::Storage::Type; using CompType = cpp::make_signed_t; @@ -207,9 +225,11 @@ template <> struct FXRep { SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; LIBC_INLINE static constexpr Type MIN() { return UACCUM_MIN; } - LIBC_INLINE static constexpr Type MAX() { return UACCUM_MIN; } + LIBC_INLINE static constexpr Type MAX() { return UACCUM_MAX; } LIBC_INLINE static constexpr Type ZERO() { return 0.0UK; } LIBC_INLINE static constexpr Type EPS() { return UACCUM_EPSILON; } + LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5UK; } + LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25UK; } using StorageType = typename internal::Storage::Type; using CompType = cpp::make_unsigned_t; @@ -225,9 +245,11 @@ template <> struct FXRep { SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; LIBC_INLINE static constexpr Type MIN() { return LACCUM_MIN; } - LIBC_INLINE static constexpr Type MAX() { return LACCUM_MIN; } + LIBC_INLINE static constexpr Type MAX() { return LACCUM_MAX; } LIBC_INLINE static constexpr Type ZERO() { return 0.0LK; } LIBC_INLINE static constexpr Type EPS() { return LACCUM_EPSILON; } + LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5LK; } + LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25LK; } using StorageType = typename internal::Storage::Type; using CompType = cpp::make_signed_t; @@ -243,9 +265,11 @@ template <> struct FXRep { SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN; LIBC_INLINE static constexpr Type MIN() { return ULACCUM_MIN; } - LIBC_INLINE static constexpr Type MAX() { return ULACCUM_MIN; } + LIBC_INLINE static constexpr Type MAX() { return ULACCUM_MAX; } LIBC_INLINE static constexpr Type ZERO() { return 0.0ULK; } LIBC_INLINE static constexpr Type EPS() { return ULACCUM_EPSILON; } + LIBC_INLINE static constexpr Type ONE_HALF() { return 0.5ULK; } + LIBC_INLINE static constexpr Type ONE_FOURTH() { return 0.25ULK; } using StorageType = typename internal::Storage::Type; using CompType = cpp::make_unsigned_t; diff --git a/libc/src/__support/fixed_point/sqrt.h b/libc/src/__support/fixed_point/sqrt.h index d8df294b18a1a8dba9c2586790ceb46a57000096..4ec016ceab0028372d94b38e75c585e0c7a60d6d 100644 --- a/libc/src/__support/fixed_point/sqrt.h +++ b/libc/src/__support/fixed_point/sqrt.h @@ -11,6 +11,7 @@ #include "include/llvm-libc-macros/stdfix-macros.h" #include "src/__support/CPP/bit.h" +#include "src/__support/CPP/limits.h" // CHAR_BIT #include "src/__support/CPP/type_traits.h" #include "src/__support/macros/attributes.h" // LIBC_INLINE #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY @@ -28,16 +29,73 @@ template struct SqrtConfig; template <> struct SqrtConfig { using Type = unsigned short fract; static constexpr int EXTRA_STEPS = 0; + + // Linear approximation for the initial values, with errors bounded by: + // max(1.5 * 2^-11, eps) + // Generated with Sollya: + // > for i from 4 to 15 do { + // P = fpminimax(sqrt(x), 1, [|8, 8|], [i * 2^-4, (i + 1)*2^-4], + // fixed, absolute); + // print("{", coeff(P, 1), "uhr,", coeff(P, 0), "uhr},"); + // }; + static constexpr Type FIRST_APPROX[12][2] = { + {0x1.e8p-1uhr, 0x1.0cp-2uhr}, {0x1.bap-1uhr, 0x1.28p-2uhr}, + {0x1.94p-1uhr, 0x1.44p-2uhr}, {0x1.74p-1uhr, 0x1.6p-2uhr}, + {0x1.6p-1uhr, 0x1.74p-2uhr}, {0x1.4ep-1uhr, 0x1.88p-2uhr}, + {0x1.3ep-1uhr, 0x1.9cp-2uhr}, {0x1.32p-1uhr, 0x1.acp-2uhr}, + {0x1.22p-1uhr, 0x1.c4p-2uhr}, {0x1.18p-1uhr, 0x1.d4p-2uhr}, + {0x1.08p-1uhr, 0x1.fp-2uhr}, {0x1.04p-1uhr, 0x1.f8p-2uhr}, + }; }; template <> struct SqrtConfig { using Type = unsigned fract; static constexpr int EXTRA_STEPS = 1; + + // Linear approximation for the initial values, with errors bounded by: + // max(1.5 * 2^-11, eps) + // Generated with Sollya: + // > for i from 4 to 15 do { + // P = fpminimax(sqrt(x), 1, [|16, 16|], [i * 2^-4, (i + 1)*2^-4], + // fixed, absolute); + // print("{", coeff(P, 1), "ur,", coeff(P, 0), "ur},"); + // }; + static constexpr Type FIRST_APPROX[12][2] = { + {0x1.e378p-1ur, 0x1.0ebp-2ur}, {0x1.b512p-1ur, 0x1.2b94p-2ur}, + {0x1.91fp-1ur, 0x1.45dcp-2ur}, {0x1.7622p-1ur, 0x1.5e24p-2ur}, + {0x1.5f5ap-1ur, 0x1.74e4p-2ur}, {0x1.4c58p-1ur, 0x1.8a4p-2ur}, + {0x1.3c1ep-1ur, 0x1.9e84p-2ur}, {0x1.2e0cp-1ur, 0x1.b1d8p-2ur}, + {0x1.21aap-1ur, 0x1.c468p-2ur}, {0x1.16bap-1ur, 0x1.d62cp-2ur}, + {0x1.0cfp-1ur, 0x1.e74cp-2ur}, {0x1.0418p-1ur, 0x1.f7ep-2ur}, + }; }; template <> struct SqrtConfig { using Type = unsigned long fract; static constexpr int EXTRA_STEPS = 2; + + // Linear approximation for the initial values, with errors bounded by: + // max(1.5 * 2^-11, eps) + // Generated with Sollya: + // > for i from 4 to 15 do { + // P = fpminimax(sqrt(x), 1, [|32, 32|], [i * 2^-4, (i + 1)*2^-4], + // fixed, absolute); + // print("{", coeff(P, 1), "ulr,", coeff(P, 0), "ulr},"); + // }; + static constexpr Type FIRST_APPROX[12][2] = { + {0x1.e3779b98p-1ulr, 0x1.0eaff788p-2ulr}, + {0x1.b5167872p-1ulr, 0x1.2b908ad4p-2ulr}, + {0x1.91f195cap-1ulr, 0x1.45da800cp-2ulr}, + {0x1.761ebcb4p-1ulr, 0x1.5e27004cp-2ulr}, + {0x1.5f619986p-1ulr, 0x1.74db933cp-2ulr}, + {0x1.4c583adep-1ulr, 0x1.8a3fbfccp-2ulr}, + {0x1.3c1a591cp-1ulr, 0x1.9e88373cp-2ulr}, + {0x1.2e08545ap-1ulr, 0x1.b1dd2534p-2ulr}, + {0x1.21b05c0ap-1ulr, 0x1.c45e023p-2ulr}, + {0x1.16becd02p-1ulr, 0x1.d624031p-2ulr}, + {0x1.0cf49fep-1ulr, 0x1.e743b844p-2ulr}, + {0x1.04214e9cp-1ulr, 0x1.f7ce2c3cp-2ulr}, + }; }; template <> @@ -46,46 +104,38 @@ struct SqrtConfig : SqrtConfig {}; template <> struct SqrtConfig : SqrtConfig {}; -// TODO: unsigned long accum type is 64-bit, and will need 64-bit fract type. -// Probably we will use DyadicFloat<64> for intermediate computations instead. - -// Linear approximation for the initial values, with errors bounded by: -// max(1.5 * 2^-11, eps) -// Generated with Sollya: -// > for i from 4 to 15 do { -// P = fpminimax(sqrt(x), 1, [|8, 8|], [i * 2^-4, (i + 1)*2^-4], -// fixed, absolute); -// print("{", coeff(P, 1), "uhr,", coeff(P, 0), "uhr},"); -// }; -static constexpr unsigned short fract SQRT_FIRST_APPROX[12][2] = { - {0x1.e8p-1uhr, 0x1.0cp-2uhr}, {0x1.bap-1uhr, 0x1.28p-2uhr}, - {0x1.94p-1uhr, 0x1.44p-2uhr}, {0x1.74p-1uhr, 0x1.6p-2uhr}, - {0x1.6p-1uhr, 0x1.74p-2uhr}, {0x1.4ep-1uhr, 0x1.88p-2uhr}, - {0x1.3ep-1uhr, 0x1.9cp-2uhr}, {0x1.32p-1uhr, 0x1.acp-2uhr}, - {0x1.22p-1uhr, 0x1.c4p-2uhr}, {0x1.18p-1uhr, 0x1.d4p-2uhr}, - {0x1.08p-1uhr, 0x1.fp-2uhr}, {0x1.04p-1uhr, 0x1.f8p-2uhr}, +// Integer square root +template <> struct SqrtConfig { + using OutType = unsigned short accum; + using FracType = unsigned fract; + // For fast-but-less-accurate version + using FastFracType = unsigned short fract; + using HalfType = unsigned char; }; -} // namespace internal +template <> struct SqrtConfig { + using OutType = unsigned accum; + using FracType = unsigned long fract; + // For fast-but-less-accurate version + using FastFracType = unsigned fract; + using HalfType = unsigned short; +}; -template -LIBC_INLINE constexpr cpp::enable_if_t, T> sqrt(T x) { - using BitType = typename FXRep::StorageType; - BitType x_bit = cpp::bit_cast(x); +// TODO: unsigned long accum type is 64-bit, and will need 64-bit fract type. +// Probably we will use DyadicFloat<64> for intermediate computations instead. - if (LIBC_UNLIKELY(x_bit == 0)) - return FXRep::ZERO(); +} // namespace internal - int leading_zeros = cpp::countl_zero(x_bit); - constexpr int STORAGE_LENGTH = sizeof(BitType) * CHAR_BIT; - constexpr int EXP_ADJUSTMENT = STORAGE_LENGTH - FXRep::FRACTION_LEN - 1; - // x_exp is the real exponent of the leading bit of x. - int x_exp = EXP_ADJUSTMENT - leading_zeros; - int shift = EXP_ADJUSTMENT - 1 - (x_exp & (~1)); - // Normalize. - x_bit <<= shift; - using FracType = typename internal::SqrtConfig::Type; - FracType x_frac = cpp::bit_cast(x_bit); +// Core computation for sqrt with normalized inputs (0.25 <= x < 1). +template +LIBC_INLINE constexpr typename Config::Type +sqrt_core(typename Config::Type x_frac) { + using FracType = typename Config::Type; + using FXRep = FXRep; + using StorageType = typename FXRep::StorageType; + // Exact case: + if (x_frac == FXRep::ONE_FOURTH()) + return FXRep::ONE_HALF(); // Use use Newton method to approximate sqrt(a): // x_{n + 1} = 1/2 (x_n + a / x_n) @@ -96,9 +146,10 @@ LIBC_INLINE constexpr cpp::enable_if_t, T> sqrt(T x) { // are between 0b0100 and 0b1111. Hence the lookup table only needs 12 // entries, and we can get the index by subtracting the leading 4 bits of // x_frac by 4 = 0b0100. - int index = (x_bit >> (STORAGE_LENGTH - 4)) - 4; - FracType a = static_cast(internal::SQRT_FIRST_APPROX[index][0]); - FracType b = static_cast(internal::SQRT_FIRST_APPROX[index][1]); + StorageType x_bit = cpp::bit_cast(x_frac); + int index = (static_cast(x_bit >> (FXRep::TOTAL_LEN - 4))) - 4; + FracType a = Config::FIRST_APPROX[index][0]; + FracType b = Config::FIRST_APPROX[index][1]; // Initial approximation step. // Estimated error bounds: | r - sqrt(x_frac) | < max(1.5 * 2^-11, eps). @@ -112,9 +163,34 @@ LIBC_INLINE constexpr cpp::enable_if_t, T> sqrt(T x) { // Blanchard, J. D. and Chamberland, M., "Newton's Method Without Division", // The American Mathematical Monthly (2023). // https://chamberland.math.grinnell.edu/papers/newton.pdf - for (int i = 0; i < internal::SqrtConfig::EXTRA_STEPS; ++i) + for (int i = 0; i < Config::EXTRA_STEPS; ++i) r = (r >> 1) + (x_frac >> 1) / r; + return r; +} + +template +LIBC_INLINE constexpr cpp::enable_if_t, T> sqrt(T x) { + using BitType = typename FXRep::StorageType; + BitType x_bit = cpp::bit_cast(x); + + if (LIBC_UNLIKELY(x_bit == 0)) + return FXRep::ZERO(); + + int leading_zeros = cpp::countl_zero(x_bit); + constexpr int STORAGE_LENGTH = sizeof(BitType) * CHAR_BIT; + constexpr int EXP_ADJUSTMENT = STORAGE_LENGTH - FXRep::FRACTION_LEN - 1; + // x_exp is the real exponent of the leading bit of x. + int x_exp = EXP_ADJUSTMENT - leading_zeros; + int shift = EXP_ADJUSTMENT - 1 - (x_exp & (~1)); + // Normalize. + x_bit <<= shift; + using FracType = typename internal::SqrtConfig::Type; + FracType x_frac = cpp::bit_cast(x_bit); + + // Compute sqrt(x_frac) using Newton-method. + FracType r = sqrt_core>(x_frac); + // Re-scaling r >>= EXP_ADJUSTMENT - (x_exp >> 1); @@ -122,6 +198,59 @@ LIBC_INLINE constexpr cpp::enable_if_t, T> sqrt(T x) { return cpp::bit_cast(r); } +// Integer square root - Accurate version: +// Absolute errors < 2^(-fraction length). +template +LIBC_INLINE constexpr typename internal::SqrtConfig::OutType isqrt(T x) { + using OutType = typename internal::SqrtConfig::OutType; + using FracType = typename internal::SqrtConfig::FracType; + + if (x == 0) + return FXRep::ZERO(); + + // Normalize the leading bits to the first two bits. + // Shift and then Bit cast x to x_frac gives us: + // x = 2^(FRACTION_LEN + 1 - shift) * x_frac; + int leading_zeros = cpp::countl_zero(x); + int shift = ((leading_zeros >> 1) << 1); + x <<= shift; + // Convert to frac type and compute square root. + FracType x_frac = cpp::bit_cast(x); + FracType r = sqrt_core>(x_frac); + // To rescale back to the OutType (Accum) + r >>= (shift >> 1); + + return cpp::bit_cast(r); +} + +// Integer square root - Fast but less accurate version: +// Relative errors < 2^(-fraction length). +template +LIBC_INLINE constexpr typename internal::SqrtConfig::OutType +isqrt_fast(T x) { + using OutType = typename internal::SqrtConfig::OutType; + using FracType = typename internal::SqrtConfig::FastFracType; + using StorageType = typename FXRep::StorageType; + + if (x == 0) + return FXRep::ZERO(); + + // Normalize the leading bits to the first two bits. + // Shift and then Bit cast x to x_frac gives us: + // x = 2^(FRACTION_LEN + 1 - shift) * x_frac; + int leading_zeros = cpp::countl_zero(x); + int shift = (leading_zeros & (~1)); + x <<= shift; + // Convert to frac type and compute square root. + FracType x_frac = cpp::bit_cast( + static_cast(x >> FXRep::FRACTION_LEN)); + OutType r = + static_cast(sqrt_core>(x_frac)); + // To rescale back to the OutType (Accum) + r <<= (FXRep::INTEGRAL_LEN - (shift >> 1)); + return cpp::bit_cast(r); +} + } // namespace LIBC_NAMESPACE::fixed_point #endif // LIBC_COMPILER_HAS_FIXED_POINT diff --git a/libc/src/__support/float_to_string.h b/libc/src/__support/float_to_string.h index 744842ced8d7727beb436cd886b7c82a12fc8a55..1287c3e9a84fac93f9f75471a3e7b1a9c1c9a7c7 100644 --- a/libc/src/__support/float_to_string.h +++ b/libc/src/__support/float_to_string.h @@ -179,8 +179,8 @@ LIBC_INLINE constexpr uint32_t length_for_num(uint32_t idx, // TODO: Fix long doubles (needs bigger table or alternate algorithm.) // Currently the table values are generated, which is very slow. template -LIBC_INLINE constexpr cpp::UInt get_table_positive(int exponent, - size_t i) { +LIBC_INLINE constexpr UInt get_table_positive(int exponent, + size_t i) { // INT_SIZE is the size of int that is used for the internal calculations of // this function. It should be large enough to hold 2^(exponent+constant), so // ~1000 for double and ~16000 for long double. Be warned that the time @@ -191,17 +191,17 @@ LIBC_INLINE constexpr cpp::UInt get_table_positive(int exponent, if (shift_amount < 0) { return 1; } - cpp::UInt num(0); + UInt num(0); // MOD_SIZE is one of the limiting factors for how big the constant argument // can get, since it needs to be small enough to fit in the result UInt, // otherwise we'll get truncation on return. - constexpr cpp::UInt MOD_SIZE = - (cpp::UInt(EXP10_9) + constexpr UInt MOD_SIZE = + (UInt(EXP10_9) << (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0))); - num = cpp::UInt(1) << (shift_amount); + num = UInt(1) << (shift_amount); if (i > 0) { - cpp::UInt fives(EXP5_9); + UInt fives(EXP5_9); fives.pow_n(i); num = num / fives; } @@ -217,8 +217,7 @@ LIBC_INLINE constexpr cpp::UInt get_table_positive(int exponent, } template -LIBC_INLINE cpp::UInt get_table_positive_df(int exponent, - size_t i) { +LIBC_INLINE UInt get_table_positive_df(int exponent, size_t i) { static_assert(INT_SIZE == 256, "Only 256 is supported as an int size right now."); // This version uses dyadic floats with 256 bit mantissas to perform the same @@ -233,11 +232,11 @@ LIBC_INLINE cpp::UInt get_table_positive_df(int exponent, return 1; } fputil::DyadicFloat num(false, 0, 1); - constexpr cpp::UInt MOD_SIZE = - (cpp::UInt(EXP10_9) + constexpr UInt MOD_SIZE = + (UInt(EXP10_9) << (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0))); - constexpr cpp::UInt FIVE_EXP_MINUS_NINE_MANT{ + constexpr UInt FIVE_EXP_MINUS_NINE_MANT{ {0xf387295d242602a7, 0xfdd7645e011abac9, 0x31680a88f8953030, 0x89705f4136b4a597}}; @@ -251,7 +250,7 @@ LIBC_INLINE cpp::UInt get_table_positive_df(int exponent, num = mul_pow_2(num, shift_amount); // Adding one is part of the formula. - cpp::UInt int_num = static_cast>(num) + 1; + UInt int_num = static_cast>(num) + 1; if (int_num > MOD_SIZE) { auto rem = int_num @@ -261,7 +260,7 @@ LIBC_INLINE cpp::UInt get_table_positive_df(int exponent, int_num = rem; } - cpp::UInt result = int_num; + UInt result = int_num; return result; } @@ -275,11 +274,11 @@ LIBC_INLINE cpp::UInt get_table_positive_df(int exponent, // The formula being used looks more like this: // floor(10^(9*(-i)) * 2^(c_0 + (-e))) % (10^9 * 2^c_0) template -LIBC_INLINE cpp::UInt get_table_negative(int exponent, size_t i) { +LIBC_INLINE UInt get_table_negative(int exponent, size_t i) { int shift_amount = CALC_SHIFT_CONST - exponent; - cpp::UInt num(1); - constexpr cpp::UInt MOD_SIZE = - (cpp::UInt(EXP10_9) + UInt num(1); + constexpr UInt MOD_SIZE = + (UInt(EXP10_9) << (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0))); size_t ten_blocks = i; @@ -298,12 +297,12 @@ LIBC_INLINE cpp::UInt get_table_negative(int exponent, size_t i) { } if (five_blocks > 0) { - cpp::UInt fives(EXP5_9); + UInt fives(EXP5_9); fives.pow_n(five_blocks); num = fives; } if (ten_blocks > 0) { - cpp::UInt tens(EXP10_9); + UInt tens(EXP10_9); tens.pow_n(ten_blocks); if (five_blocks <= 0) { num = tens; @@ -327,8 +326,7 @@ LIBC_INLINE cpp::UInt get_table_negative(int exponent, size_t i) { } template -LIBC_INLINE cpp::UInt get_table_negative_df(int exponent, - size_t i) { +LIBC_INLINE UInt get_table_negative_df(int exponent, size_t i) { static_assert(INT_SIZE == 256, "Only 256 is supported as an int size right now."); // This version uses dyadic floats with 256 bit mantissas to perform the same @@ -341,11 +339,11 @@ LIBC_INLINE cpp::UInt get_table_negative_df(int exponent, int shift_amount = CALC_SHIFT_CONST - exponent; fputil::DyadicFloat num(false, 0, 1); - constexpr cpp::UInt MOD_SIZE = - (cpp::UInt(EXP10_9) + constexpr UInt MOD_SIZE = + (UInt(EXP10_9) << (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0))); - constexpr cpp::UInt TEN_EXP_NINE_MANT(EXP10_9); + constexpr UInt TEN_EXP_NINE_MANT(EXP10_9); static const fputil::DyadicFloat TEN_EXP_NINE(false, 0, TEN_EXP_NINE_MANT); @@ -356,7 +354,7 @@ LIBC_INLINE cpp::UInt get_table_negative_df(int exponent, } num = mul_pow_2(num, shift_amount); - cpp::UInt int_num = static_cast>(num); + UInt int_num = static_cast>(num); if (int_num > MOD_SIZE) { auto rem = int_num @@ -366,16 +364,16 @@ LIBC_INLINE cpp::UInt get_table_negative_df(int exponent, int_num = rem; } - cpp::UInt result = int_num; + UInt result = int_num; return result; } -LIBC_INLINE uint32_t fast_uint_mod_1e9(const cpp::UInt &val) { +LIBC_INLINE uint32_t fast_uint_mod_1e9(const UInt &val) { // The formula for mult_const is: // 1 + floor((2^(bits in target integer size + log_2(divider))) / divider) // Where divider is 10^9 and target integer size is 128. - const cpp::UInt mult_const( + const UInt mult_const( {0x31680A88F8953031u, 0x89705F4136B4A597u, 0}); const auto middle = (mult_const * val); const uint64_t result = static_cast(middle[2]); @@ -385,9 +383,9 @@ LIBC_INLINE uint32_t fast_uint_mod_1e9(const cpp::UInt &val) { } LIBC_INLINE uint32_t mul_shift_mod_1e9(const FPBits::StorageType mantissa, - const cpp::UInt &large, + const UInt &large, const int32_t shift_amount) { - cpp::UInt val(large); + UInt val(large); val = (val * mantissa) >> shift_amount; return static_cast( val.div_uint_half_times_pow_2(static_cast(EXP10_9), 0).value()); @@ -452,7 +450,7 @@ public: const uint32_t pos_exp = idx * IDX_SIZE; - cpp::UInt val; + UInt val; #if defined(LIBC_COPT_FLOAT_TO_STR_USE_DYADIC_FLOAT) // ----------------------- DYADIC FLOAT CALC MODE ------------------------ @@ -502,7 +500,7 @@ public: if (exponent < 0) { const int32_t idx = -exponent / IDX_SIZE; - cpp::UInt val; + UInt val; const uint32_t pos_exp = static_cast(idx * IDX_SIZE); @@ -643,7 +641,7 @@ template <> class FloatToString { internal::div_ceil(sizeof(long double) * CHAR_BIT, UINT_WORD_SIZE) * UINT_WORD_SIZE; - using wide_int = cpp::UInt; + using wide_int = UInt; // float_as_fixed represents the floating point number as a fixed point number // with the point EXTRA_INT_WIDTH bits from the left of the number. This can @@ -658,7 +656,7 @@ template <> class FloatToString { size_t block_buffer_valid = 0; template - LIBC_INLINE static constexpr BlockInt grab_digits(cpp::UInt &int_num) { + LIBC_INLINE static constexpr BlockInt grab_digits(UInt &int_num) { auto wide_result = int_num.div_uint_half_times_pow_2(EXP5_9, 9); // the optional only comes into effect when dividing by 0, which will // never happen here. Thus, we just assert that it has value. @@ -713,8 +711,8 @@ template <> class FloatToString { float_as_fixed.shift_left(SHIFT_AMOUNT); // If there are still digits above the decimal point, handle those. - if (float_as_fixed.clz() < EXTRA_INT_WIDTH) { - cpp::UInt above_decimal_point = + if (float_as_fixed.clz() < static_cast(EXTRA_INT_WIDTH)) { + UInt above_decimal_point = float_as_fixed >> FLOAT_AS_INT_WIDTH; size_t positive_int_block_index = 0; diff --git a/libc/src/__support/high_precision_decimal.h b/libc/src/__support/high_precision_decimal.h index d29f8c4cd932f45cae5409fb355280df97007e8c..2c5a349e4495eb3a315f2c92d456ff8f5d8f43bf 100644 --- a/libc/src/__support/high_precision_decimal.h +++ b/libc/src/__support/high_precision_decimal.h @@ -9,6 +9,7 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H #define LLVM_LIBC_SRC___SUPPORT_HIGH_PRECISION_DECIMAL_H +#include "src/__support/CPP/limits.h" #include "src/__support/ctype_utils.h" #include "src/__support/str_to_integer.h" #include @@ -115,9 +116,10 @@ class HighPrecisionDecimal { uint8_t digits[MAX_NUM_DIGITS]; private: - bool should_round_up(int32_t roundToDigit, RoundDirection round) { - if (roundToDigit < 0 || - static_cast(roundToDigit) >= this->num_digits) { + LIBC_INLINE bool should_round_up(int32_t round_to_digit, + RoundDirection round) { + if (round_to_digit < 0 || + static_cast(round_to_digit) >= this->num_digits) { return false; } @@ -133,8 +135,8 @@ private: // Else round to nearest. // If we're right in the middle and there are no extra digits - if (this->digits[roundToDigit] == 5 && - static_cast(roundToDigit + 1) == this->num_digits) { + if (this->digits[round_to_digit] == 5 && + static_cast(round_to_digit + 1) == this->num_digits) { // Round up if we've truncated (since that means the result is slightly // higher than what's represented.) @@ -143,22 +145,22 @@ private: } // If this exactly halfway, round to even. - if (roundToDigit == 0) + if (round_to_digit == 0) // When the input is ".5". return false; - return this->digits[roundToDigit - 1] % 2 != 0; + return this->digits[round_to_digit - 1] % 2 != 0; } - // If there are digits after roundToDigit, they must be non-zero since we + // If there are digits after round_to_digit, they must be non-zero since we // trim trailing zeroes after all operations that change digits. - return this->digits[roundToDigit] >= 5; + return this->digits[round_to_digit] >= 5; } // Takes an amount to left shift and returns the number of new digits needed // to store the result based on LEFT_SHIFT_DIGIT_TABLE. - uint32_t get_num_new_digits(uint32_t lShiftAmount) { + LIBC_INLINE uint32_t get_num_new_digits(uint32_t lshift_amount) { const char *power_of_five = - LEFT_SHIFT_DIGIT_TABLE[lShiftAmount].power_of_five; - uint32_t new_digits = LEFT_SHIFT_DIGIT_TABLE[lShiftAmount].new_digits; + LEFT_SHIFT_DIGIT_TABLE[lshift_amount].power_of_five; + uint32_t new_digits = LEFT_SHIFT_DIGIT_TABLE[lshift_amount].new_digits; uint32_t digit_index = 0; while (power_of_five[digit_index] != 0) { if (digit_index >= this->num_digits) { @@ -176,7 +178,7 @@ private: } // Trim all trailing 0s - void trim_trailing_zeroes() { + LIBC_INLINE void trim_trailing_zeroes() { while (this->num_digits > 0 && this->digits[this->num_digits - 1] == 0) { --this->num_digits; } @@ -186,19 +188,19 @@ private: } // Perform a digitwise binary non-rounding right shift on this value by - // shiftAmount. The shiftAmount can't be more than MAX_SHIFT_AMOUNT to prevent - // overflow. - void right_shift(uint32_t shiftAmount) { + // shift_amount. The shift_amount can't be more than MAX_SHIFT_AMOUNT to + // prevent overflow. + LIBC_INLINE void right_shift(uint32_t shift_amount) { uint32_t read_index = 0; uint32_t write_index = 0; uint64_t accumulator = 0; - const uint64_t shift_mask = (uint64_t(1) << shiftAmount) - 1; + const uint64_t shift_mask = (uint64_t(1) << shift_amount) - 1; // Warm Up phase: we don't have enough digits to start writing, so just // read them into the accumulator. - while (accumulator >> shiftAmount == 0) { + while (accumulator >> shift_amount == 0) { uint64_t read_digit = 0; // If there are still digits to read, read the next one, else the digit is // assumed to be 0. @@ -217,7 +219,7 @@ private: // read. Keep reading until we run out of digits. while (read_index < this->num_digits) { uint64_t read_digit = this->digits[read_index]; - uint64_t write_digit = accumulator >> shiftAmount; + uint64_t write_digit = accumulator >> shift_amount; accumulator &= shift_mask; this->digits[write_index] = static_cast(write_digit); accumulator = accumulator * 10 + read_digit; @@ -228,7 +230,7 @@ private: // Cool Down phase: All of the readable digits have been read, so just write // the remainder, while treating any more digits as 0. while (accumulator > 0) { - uint64_t write_digit = accumulator >> shiftAmount; + uint64_t write_digit = accumulator >> shift_amount; accumulator &= shift_mask; if (write_index < MAX_NUM_DIGITS) { this->digits[write_index] = static_cast(write_digit); @@ -243,10 +245,10 @@ private: } // Perform a digitwise binary non-rounding left shift on this value by - // shiftAmount. The shiftAmount can't be more than MAX_SHIFT_AMOUNT to prevent - // overflow. - void left_shift(uint32_t shiftAmount) { - uint32_t new_digits = this->get_num_new_digits(shiftAmount); + // shift_amount. The shift_amount can't be more than MAX_SHIFT_AMOUNT to + // prevent overflow. + LIBC_INLINE void left_shift(uint32_t shift_amount) { + uint32_t new_digits = this->get_num_new_digits(shift_amount); int32_t read_index = this->num_digits - 1; uint32_t write_index = this->num_digits + new_digits; @@ -260,7 +262,7 @@ private: // writing. while (read_index >= 0) { accumulator += static_cast(this->digits[read_index]) - << shiftAmount; + << shift_amount; uint64_t next_accumulator = accumulator / 10; uint64_t write_digit = accumulator - (10 * next_accumulator); --write_index; @@ -296,45 +298,52 @@ private: } public: - // numString is assumed to be a string of numeric characters. It doesn't + // num_string is assumed to be a string of numeric characters. It doesn't // handle leading spaces. - HighPrecisionDecimal(const char *__restrict numString) { + LIBC_INLINE + HighPrecisionDecimal( + const char *__restrict num_string, + const size_t num_len = cpp::numeric_limits::max()) { bool saw_dot = false; + size_t num_cur = 0; // This counts the digits in the number, even if there isn't space to store // them all. uint32_t total_digits = 0; - while (isdigit(*numString) || *numString == '.') { - if (*numString == '.') { + while (num_cur < num_len && + (isdigit(num_string[num_cur]) || num_string[num_cur] == '.')) { + if (num_string[num_cur] == '.') { if (saw_dot) { break; } this->decimal_point = total_digits; saw_dot = true; } else { - if (*numString == '0' && this->num_digits == 0) { + if (num_string[num_cur] == '0' && this->num_digits == 0) { --this->decimal_point; - ++numString; + ++num_cur; continue; } ++total_digits; if (this->num_digits < MAX_NUM_DIGITS) { this->digits[this->num_digits] = - static_cast(*numString - '0'); + static_cast(num_string[num_cur] - '0'); ++this->num_digits; - } else if (*numString != '0') { + } else if (num_string[num_cur] != '0') { this->truncated = true; } } - ++numString; + ++num_cur; } if (!saw_dot) this->decimal_point = total_digits; - if ((*numString | 32) == 'e') { - ++numString; - if (isdigit(*numString) || *numString == '+' || *numString == '-') { - auto result = strtointeger(numString, 10); + if (num_cur < num_len && ((num_string[num_cur] | 32) == 'e')) { + ++num_cur; + if (isdigit(num_string[num_cur]) || num_string[num_cur] == '+' || + num_string[num_cur] == '-') { + auto result = + strtointeger(num_string + num_cur, 10, num_len - num_cur); if (result.has_error()) { // TODO: handle error } @@ -358,33 +367,34 @@ public: this->trim_trailing_zeroes(); } - // Binary shift left (shiftAmount > 0) or right (shiftAmount < 0) - void shift(int shiftAmount) { - if (shiftAmount == 0) { + // Binary shift left (shift_amount > 0) or right (shift_amount < 0) + LIBC_INLINE void shift(int shift_amount) { + if (shift_amount == 0) { return; } // Left - else if (shiftAmount > 0) { - while (static_cast(shiftAmount) > MAX_SHIFT_AMOUNT) { + else if (shift_amount > 0) { + while (static_cast(shift_amount) > MAX_SHIFT_AMOUNT) { this->left_shift(MAX_SHIFT_AMOUNT); - shiftAmount -= MAX_SHIFT_AMOUNT; + shift_amount -= MAX_SHIFT_AMOUNT; } - this->left_shift(shiftAmount); + this->left_shift(shift_amount); } // Right else { - while (static_cast(shiftAmount) < -MAX_SHIFT_AMOUNT) { + while (static_cast(shift_amount) < -MAX_SHIFT_AMOUNT) { this->right_shift(MAX_SHIFT_AMOUNT); - shiftAmount += MAX_SHIFT_AMOUNT; + shift_amount += MAX_SHIFT_AMOUNT; } - this->right_shift(-shiftAmount); + this->right_shift(-shift_amount); } } // Round the number represented to the closest value of unsigned int type T. // This is done ignoring overflow. template - T round_to_integer_type(RoundDirection round = RoundDirection::Nearest) { + LIBC_INLINE T + round_to_integer_type(RoundDirection round = RoundDirection::Nearest) { T result = 0; uint32_t cur_digit = 0; @@ -404,10 +414,10 @@ public: // Extra functions for testing. - uint8_t *get_digits() { return this->digits; } - uint32_t get_num_digits() { return this->num_digits; } - int32_t get_decimal_point() { return this->decimal_point; } - void set_truncated(bool trunc) { this->truncated = trunc; } + LIBC_INLINE uint8_t *get_digits() { return this->digits; } + LIBC_INLINE uint32_t get_num_digits() { return this->num_digits; } + LIBC_INLINE int32_t get_decimal_point() { return this->decimal_point; } + LIBC_INLINE void set_truncated(bool trunc) { this->truncated = trunc; } }; } // namespace internal diff --git a/libc/src/__support/integer_literals.h b/libc/src/__support/integer_literals.h index 08bc6973b1582b780efa6de9c636ecc376557cd9..de1f88fbd3f3f5b0e22a1c82572a07a53d7a5fd8 100644 --- a/libc/src/__support/integer_literals.h +++ b/libc/src/__support/integer_literals.h @@ -115,13 +115,13 @@ template struct Parser { } }; -// Specialization for cpp::UInt. +// Specialization for UInt. // Because this code runs at compile time we try to make it efficient. For // binary and hexadecimal formats we read digits by chunks of 64 bits and // produce the BigInt internal representation direcly. For decimal numbers we // go the slow path and use slower BigInt arithmetic. -template struct Parser> { - using UIntT = cpp::UInt; +template struct Parser> { + using UIntT = UInt; template static constexpr UIntT parse(const char *str) { const DigitBuffer buffer(str); if constexpr (base == 10) { @@ -166,7 +166,7 @@ LIBC_INLINE constexpr UInt128 operator""_u128(const char *x) { } LIBC_INLINE constexpr auto operator""_u256(const char *x) { - return internal::parse_with_prefix>(x); + return internal::parse_with_prefix>(x); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/__support/integer_to_string.h b/libc/src/__support/integer_to_string.h index 8d3859c8eb0ca5fb07ba19705ecc82004f28c9ea..ac0bdd688aeab222cd3cdfefc48c524547f64e9e 100644 --- a/libc/src/__support/integer_to_string.h +++ b/libc/src/__support/integer_to_string.h @@ -67,6 +67,7 @@ #include "src/__support/CPP/span.h" #include "src/__support/CPP/string_view.h" #include "src/__support/CPP/type_traits.h" +#include "src/__support/UInt.h" // is_big_int #include "src/__support/common.h" namespace LIBC_NAMESPACE { @@ -149,6 +150,18 @@ public: using StringBufferWriter = StringBufferWriterImpl; using BackwardStringBufferWriter = StringBufferWriterImpl; +template struct IntegerWriterUnsigned {}; + +template +struct IntegerWriterUnsigned>> { + using type = cpp::make_unsigned_t; +}; + +template +struct IntegerWriterUnsigned>> { + using type = typename T::unsigned_type; +}; + } // namespace details namespace radix { @@ -163,10 +176,10 @@ template using Custom = details::Fmt; // See file header for documentation. template class IntegerToString { - static_assert(cpp::is_integral_v); + static_assert(cpp::is_integral_v || is_big_int_v); LIBC_INLINE static constexpr size_t compute_buffer_size() { - constexpr auto max_digits = []() -> size_t { + constexpr auto MAX_DIGITS = []() -> size_t { // We size the string buffer for base 10 using an approximation algorithm: // // size = ceil(sizeof(T) * 5 / 2) @@ -188,19 +201,19 @@ template class IntegerToString { // For other bases, we approximate by rounding down to the nearest power // of two base, since the space needed is easy to calculate and it won't // overestimate by too much. - constexpr auto floor_log_2 = [](size_t num) -> size_t { + constexpr auto FLOOR_LOG_2 = [](size_t num) -> size_t { size_t i = 0; for (; num > 1; num /= 2) ++i; return i; }; - constexpr size_t BITS_PER_DIGIT = floor_log_2(Fmt::BASE); + constexpr size_t BITS_PER_DIGIT = FLOOR_LOG_2(Fmt::BASE); return ((sizeof(T) * 8 + (BITS_PER_DIGIT - 1)) / BITS_PER_DIGIT); }; - constexpr size_t digit_size = cpp::max(max_digits(), Fmt::MIN_DIGITS); - constexpr size_t sign_size = Fmt::BASE == 10 ? 1 : 0; - constexpr size_t prefix_size = Fmt::PREFIX ? 2 : 0; - return digit_size + sign_size + prefix_size; + constexpr size_t DIGIT_SIZE = cpp::max(MAX_DIGITS(), Fmt::MIN_DIGITS); + constexpr size_t SIGN_SIZE = Fmt::BASE == 10 ? 1 : 0; + constexpr size_t PREFIX_SIZE = Fmt::PREFIX ? 2 : 0; + return DIGIT_SIZE + SIGN_SIZE + PREFIX_SIZE; } static constexpr size_t BUFFER_SIZE = compute_buffer_size(); @@ -208,8 +221,8 @@ template class IntegerToString { // An internal stateless structure that handles the number formatting logic. struct IntegerWriter { - static_assert(cpp::is_integral_v); - using UNSIGNED_T = cpp::make_unsigned_t; + static_assert(cpp::is_integral_v || is_big_int_v); + using UNSIGNED_T = typename details::IntegerWriterUnsigned::type; LIBC_INLINE static char digit_char(uint8_t digit) { if (digit < 10) diff --git a/libc/src/__support/integer_utils.h b/libc/src/__support/integer_utils.h deleted file mode 100644 index 15e04bda8082311019612ef891c26ac9582269a1..0000000000000000000000000000000000000000 --- a/libc/src/__support/integer_utils.h +++ /dev/null @@ -1,69 +0,0 @@ -//===-- Utilities for integers. ---------------------------------*- 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___SUPPORT_INTEGER_UTILS_H -#define LLVM_LIBC_SRC___SUPPORT_INTEGER_UTILS_H - -#include "src/__support/CPP/type_traits.h" -#include "src/__support/common.h" - -#include "math_extras.h" -#include "number_pair.h" - -#include - -namespace LIBC_NAMESPACE { - -template constexpr NumberPair full_mul(T a, T b) { - NumberPair pa = split(a); - NumberPair pb = split(b); - NumberPair prod; - - prod.lo = pa.lo * pb.lo; // exact - prod.hi = pa.hi * pb.hi; // exact - NumberPair lo_hi = split(pa.lo * pb.hi); // exact - NumberPair hi_lo = split(pa.hi * pb.lo); // exact - - constexpr size_t HALF_BIT_WIDTH = sizeof(T) * CHAR_BIT / 2; - - auto r1 = add_with_carry(prod.lo, lo_hi.lo << HALF_BIT_WIDTH, T(0)); - prod.lo = r1.sum; - prod.hi = add_with_carry(prod.hi, lo_hi.hi, r1.carry).sum; - - auto r2 = add_with_carry(prod.lo, hi_lo.lo << HALF_BIT_WIDTH, T(0)); - prod.lo = r2.sum; - prod.hi = add_with_carry(prod.hi, hi_lo.hi, r2.carry).sum; - - return prod; -} - -template <> -LIBC_INLINE constexpr NumberPair full_mul(uint32_t a, - uint32_t b) { - uint64_t prod = uint64_t(a) * uint64_t(b); - NumberPair result; - result.lo = uint32_t(prod); - result.hi = uint32_t(prod >> 32); - return result; -} - -#ifdef __SIZEOF_INT128__ -template <> -LIBC_INLINE constexpr NumberPair full_mul(uint64_t a, - uint64_t b) { - __uint128_t prod = __uint128_t(a) * __uint128_t(b); - NumberPair result; - result.lo = uint64_t(prod); - result.hi = uint64_t(prod >> 64); - return result; -} -#endif // __SIZEOF_INT128__ - -} // namespace LIBC_NAMESPACE - -#endif // LLVM_LIBC_SRC___SUPPORT_INTEGER_UTILS_H diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h index 8760f78875c41735a5a920b14f6125c4a02920e3..d43cf99e6859beb7a3edf7d10fb1651831f70c29 100644 --- a/libc/src/__support/macros/properties/types.h +++ b/libc/src/__support/macros/properties/types.h @@ -17,6 +17,8 @@ #include "src/__support/macros/properties/cpu_features.h" #include "src/__support/macros/properties/os.h" +#include // UINT64_MAX, __SIZEOF_INT128__ + // 'long double' properties. #if (LDBL_MANT_DIG == 53) #define LIBC_TYPES_LONG_DOUBLE_IS_FLOAT64 @@ -26,6 +28,16 @@ #define LIBC_TYPES_LONG_DOUBLE_IS_FLOAT128 #endif +// int64 / uint64 support +#if defined(UINT64_MAX) +#define LIBC_TYPES_HAS_INT64 +#endif // UINT64_MAX + +// int128 / uint128 support +#if defined(__SIZEOF_INT128__) +#define LIBC_TYPES_HAS_INT128 +#endif // defined(__SIZEOF_INT128__) + // -- float16 support --------------------------------------------------------- // TODO: move this logic to "llvm-libc-types/float16.h" #if defined(LIBC_TARGET_ARCH_IS_X86_64) && defined(LIBC_TARGET_CPU_HAS_SSE2) diff --git a/libc/src/__support/math_extras.h b/libc/src/__support/math_extras.h index ae367994706c0f3c9b305824f95253099e400379..c6b458ddecdabf42440eae72f7d15a24038e49cc 100644 --- a/libc/src/__support/math_extras.h +++ b/libc/src/__support/math_extras.h @@ -20,23 +20,20 @@ namespace LIBC_NAMESPACE { // Create a bitmask with the count right-most bits set to 1, and all other bits // set to 0. Only unsigned types are allowed. template -LIBC_INLINE constexpr T mask_trailing_ones() { - static_assert(cpp::is_unsigned_v); - constexpr unsigned t_bits = CHAR_BIT * sizeof(T); - static_assert(count <= t_bits && "Invalid bit index"); - // It's important not to initialize T with -1, since T may be BigInt which - // will take -1 as a uint64_t and only initialize the low 64 bits. - constexpr T all_zeroes(0); - constexpr T all_ones(~all_zeroes); // bitwise NOT performs integer promotion. - return count == 0 ? 0 : (all_ones >> (t_bits - count)); +LIBC_INLINE constexpr cpp::enable_if_t, T> +mask_trailing_ones() { + constexpr unsigned T_BITS = CHAR_BIT * sizeof(T); + static_assert(count <= T_BITS && "Invalid bit index"); + return count == 0 ? 0 : (T(-1) >> (T_BITS - count)); } // Create a bitmask with the count left-most bits set to 1, and all other bits // set to 0. Only unsigned types are allowed. template -LIBC_INLINE constexpr T mask_leading_ones() { - constexpr T mask(mask_trailing_ones()); - return T(~mask); // bitwise NOT performs integer promotion. +LIBC_INLINE constexpr cpp::enable_if_t, T> +mask_leading_ones() { + constexpr T MASK(mask_trailing_ones()); + return T(~MASK); // bitwise NOT performs integer promotion. } // Add with carry diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h index d2bf3f85b2709aa84a08f425480cc217b73b342a..073e1dc672172376771b0badb5b1ee6f93355c89 100644 --- a/libc/src/__support/str_to_float.h +++ b/libc/src/__support/str_to_float.h @@ -313,14 +313,15 @@ constexpr int32_t NUM_POWERS_OF_TWO = // on the Simple Decimal Conversion algorithm by Nigel Tao, described at this // link: https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html template -LIBC_INLINE FloatConvertReturn -simple_decimal_conversion(const char *__restrict numStart, - RoundDirection round = RoundDirection::Nearest) { +LIBC_INLINE FloatConvertReturn simple_decimal_conversion( + const char *__restrict numStart, + const size_t num_len = cpp::numeric_limits::max(), + RoundDirection round = RoundDirection::Nearest) { using FPBits = typename fputil::FPBits; using StorageType = typename FPBits::StorageType; int32_t exp2 = 0; - HighPrecisionDecimal hpd = HighPrecisionDecimal(numStart); + HighPrecisionDecimal hpd = HighPrecisionDecimal(numStart, num_len); FloatConvertReturn output; @@ -523,7 +524,7 @@ clinger_fast_path(ExpandedFloat init_num, FPBits result; T float_mantissa; - if constexpr (cpp::is_same_v>) { + if constexpr (cpp::is_same_v>) { float_mantissa = static_cast(fputil::DyadicFloat<128>( Sign::POS, 0, fputil::DyadicFloat<128>::MantissaType( @@ -600,13 +601,17 @@ clinger_fast_path(ExpandedFloat init_num, // non-inf result for this size of float. The value is // log10(2^(exponent bias)). // The generic approximation uses the fact that log10(2^x) ~= x/3 -template constexpr int32_t get_upper_bound() { +template LIBC_INLINE constexpr int32_t get_upper_bound() { return fputil::FPBits::EXP_BIAS / 3; } -template <> constexpr int32_t get_upper_bound() { return 39; } +template <> LIBC_INLINE constexpr int32_t get_upper_bound() { + return 39; +} -template <> constexpr int32_t get_upper_bound() { return 309; } +template <> LIBC_INLINE constexpr int32_t get_upper_bound() { + return 309; +} // The lower bound is the largest negative base-10 exponent that could possibly // give a non-zero result for this size of float. The value is @@ -616,18 +621,18 @@ template <> constexpr int32_t get_upper_bound() { return 309; } // low base 10 exponent with a very high intermediate mantissa can cancel each // other out, and subnormal numbers allow for the result to be at the very low // end of the final mantissa. -template constexpr int32_t get_lower_bound() { +template LIBC_INLINE constexpr int32_t get_lower_bound() { using FPBits = typename fputil::FPBits; return -((FPBits::EXP_BIAS + static_cast(FPBits::FRACTION_LEN + FPBits::STORAGE_LEN)) / 3); } -template <> constexpr int32_t get_lower_bound() { +template <> LIBC_INLINE constexpr int32_t get_lower_bound() { return -(39 + 6 + 10); } -template <> constexpr int32_t get_lower_bound() { +template <> LIBC_INLINE constexpr int32_t get_lower_bound() { return -(309 + 15 + 20); } @@ -637,9 +642,10 @@ template <> constexpr int32_t get_lower_bound() { // accuracy. The resulting mantissa and exponent are placed in outputMantissa // and outputExp2. template -LIBC_INLINE FloatConvertReturn -decimal_exp_to_float(ExpandedFloat init_num, const char *__restrict numStart, - bool truncated, RoundDirection round) { +LIBC_INLINE FloatConvertReturn decimal_exp_to_float( + ExpandedFloat init_num, bool truncated, RoundDirection round, + const char *__restrict numStart, + const size_t num_len = cpp::numeric_limits::max()) { using FPBits = typename fputil::FPBits; using StorageType = typename FPBits::StorageType; @@ -701,7 +707,7 @@ decimal_exp_to_float(ExpandedFloat init_num, const char *__restrict numStart, #endif // LIBC_COPT_STRTOFLOAT_DISABLE_EISEL_LEMIRE #ifndef LIBC_COPT_STRTOFLOAT_DISABLE_SIMPLE_DECIMAL_CONVERSION - output = simple_decimal_conversion(numStart, round); + output = simple_decimal_conversion(numStart, num_len, round); #else #warning "Simple decimal conversion is disabled, result may not be correct." #endif // LIBC_COPT_STRTOFLOAT_DISABLE_SIMPLE_DECIMAL_CONVERSION @@ -894,6 +900,8 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT, if (!seen_digit) return output; + // TODO: When adding max length argument, handle the case of a trailing + // EXPONENT MARKER, see scanf for more details. if (tolower(src[index]) == EXPONENT_MARKER) { bool has_sign = false; if (src[index + 1] == '+' || src[index + 1] == '-') { @@ -928,7 +936,7 @@ decimal_string_to_float(const char *__restrict src, const char DECIMAL_POINT, output.value = {0, 0}; } else { auto temp = - decimal_exp_to_float({mantissa, exponent}, src, truncated, round); + decimal_exp_to_float({mantissa, exponent}, truncated, round, src); output.value = temp.num; output.error = temp.error; } @@ -1071,6 +1079,8 @@ nan_mantissa_from_ncharseq(const cpp::string_view ncharseq) { // Takes a pointer to a string and a pointer to a string pointer. This function // is used as the backend for all of the string to float functions. +// TODO: Add src_len member to match strtointeger. +// TODO: Next, move from char* and length to string_view template LIBC_INLINE StrToNumResult strtofloatingpoint(const char *__restrict src) { using FPBits = typename fputil::FPBits; diff --git a/libc/src/__support/str_to_integer.h b/libc/src/__support/str_to_integer.h index e83a508e086b18ab83198f527eec672ab2cb6a2a..b87808993fee500965a731a5abe08cb6734fad5d 100644 --- a/libc/src/__support/str_to_integer.h +++ b/libc/src/__support/str_to_integer.h @@ -21,11 +21,15 @@ namespace internal { // Returns a pointer to the first character in src that is not a whitespace // character (as determined by isspace()) -LIBC_INLINE const char *first_non_whitespace(const char *__restrict src) { - while (internal::isspace(*src)) { - ++src; +// TODO: Change from returning a pointer to returning a length. +LIBC_INLINE const char * +first_non_whitespace(const char *__restrict src, + size_t src_len = cpp::numeric_limits::max()) { + size_t src_cur = 0; + while (src_cur < src_len && internal::isspace(src[src_cur])) { + ++src_cur; } - return src; + return src + src_cur; } LIBC_INLINE int b36_char_to_int(char input) { @@ -38,61 +42,64 @@ LIBC_INLINE int b36_char_to_int(char input) { // checks if the next 3 characters of the string pointer are the start of a // hexadecimal number. Does not advance the string pointer. -LIBC_INLINE bool is_hex_start(const char *__restrict src) { +LIBC_INLINE bool +is_hex_start(const char *__restrict src, + size_t src_len = cpp::numeric_limits::max()) { + if (src_len < 3) + return false; return *src == '0' && (*(src + 1) | 32) == 'x' && isalnum(*(src + 2)) && b36_char_to_int(*(src + 2)) < 16; } // Takes the address of the string pointer and parses the base from the start of -// it. This function will advance |src| to the first valid digit in the inferred -// base. -LIBC_INLINE int infer_base(const char *__restrict *__restrict src) { +// it. +LIBC_INLINE int infer_base(const char *__restrict src, size_t src_len) { // A hexadecimal number is defined as "the prefix 0x or 0X followed by a // sequence of the decimal digits and the letters a (or A) through f (or F) // with values 10 through 15 respectively." (C standard 6.4.4.1) - if (is_hex_start(*src)) { - (*src) += 2; + if (is_hex_start(src, src_len)) return 16; - } // An octal number is defined as "the prefix 0 optionally followed by a - // sequence of the digits 0 through 7 only" (C standard 6.4.4.1) and so any - // number that starts with 0, including just 0, is an octal number. - else if (**src == '0') { + // An octal number is defined as "the prefix 0 optionally followed by a + // sequence of the digits 0 through 7 only" (C standard 6.4.4.1) and so any + // number that starts with 0, including just 0, is an octal number. + if (src_len > 0 && src[0] == '0') return 8; - } // A decimal number is defined as beginning "with a nonzero digit and - // consist[ing] of a sequence of decimal digits." (C standard 6.4.4.1) - else { - return 10; - } + // A decimal number is defined as beginning "with a nonzero digit and + // consist[ing] of a sequence of decimal digits." (C standard 6.4.4.1) + return 10; } // Takes a pointer to a string and the base to convert to. This function is used // as the backend for all of the string to int functions. template -LIBC_INLINE StrToNumResult strtointeger(const char *__restrict src, - int base) { +LIBC_INLINE StrToNumResult +strtointeger(const char *__restrict src, int base, + const size_t src_len = cpp::numeric_limits::max()) { + // TODO: Rewrite to support numbers longer than long long unsigned long long result = 0; bool is_number = false; - const char *original_src = src; + size_t src_cur = 0; int error_val = 0; - if (base < 0 || base == 1 || base > 36) { - error_val = EINVAL; - return {0, 0, error_val}; - } + if (src_len == 0) + return {0, 0, 0}; + + if (base < 0 || base == 1 || base > 36) + return {0, 0, EINVAL}; - src = first_non_whitespace(src); + src_cur = first_non_whitespace(src, src_len) - src; char result_sign = '+'; - if (*src == '+' || *src == '-') { - result_sign = *src; - ++src; + if (src[src_cur] == '+' || src[src_cur] == '-') { + result_sign = src[src_cur]; + ++src_cur; } - if (base == 0) { - base = infer_base(&src); - } else if (base == 16 && is_hex_start(src)) { - src = src + 2; - } + if (base == 0) + base = infer_base(src + src_cur, src_len - src_cur); + + if (base == 16 && is_hex_start(src + src_cur, src_len - src_cur)) + src_cur = src_cur + 2; constexpr bool IS_UNSIGNED = (cpp::numeric_limits::min() == 0); const bool is_positive = (result_sign == '+'); @@ -103,13 +110,13 @@ LIBC_INLINE StrToNumResult strtointeger(const char *__restrict src, unsigned long long const abs_max = (is_positive ? cpp::numeric_limits::max() : NEGATIVE_MAX); unsigned long long const abs_max_div_by_base = abs_max / base; - while (isalnum(*src)) { - int cur_digit = b36_char_to_int(*src); + while (src_cur < src_len && isalnum(src[src_cur])) { + int cur_digit = b36_char_to_int(src[src_cur]); if (cur_digit >= base) break; is_number = true; - ++src; + ++src_cur; // If the number has already hit the maximum value for the current type then // the result cannot change, but we still need to advance src to the end of @@ -133,7 +140,7 @@ LIBC_INLINE StrToNumResult strtointeger(const char *__restrict src, } } - ptrdiff_t str_len = is_number ? (src - original_src) : 0; + ptrdiff_t str_len = is_number ? (src_cur) : 0; if (error_val == ERANGE) { if (is_positive || IS_UNSIGNED) diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt index 882befd9f7e7ff1de6e0d4f76923be6aac0f8132..bba02aa78a2313cc25874a45066910b2c4f4edc0 100644 --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -119,6 +119,8 @@ add_math_entrypoint_object(fminf128) add_math_entrypoint_object(fmod) add_math_entrypoint_object(fmodf) +add_math_entrypoint_object(fmodl) +add_math_entrypoint_object(fmodf128) add_math_entrypoint_object(frexp) add_math_entrypoint_object(frexpf) @@ -163,22 +165,27 @@ add_math_entrypoint_object(logbf128) add_math_entrypoint_object(llrint) add_math_entrypoint_object(llrintf) add_math_entrypoint_object(llrintl) +add_math_entrypoint_object(llrintf128) add_math_entrypoint_object(llround) add_math_entrypoint_object(llroundf) add_math_entrypoint_object(llroundl) +add_math_entrypoint_object(llroundf128) add_math_entrypoint_object(lrint) add_math_entrypoint_object(lrintf) add_math_entrypoint_object(lrintl) +add_math_entrypoint_object(lrintf128) add_math_entrypoint_object(lround) add_math_entrypoint_object(lroundf) add_math_entrypoint_object(lroundl) +add_math_entrypoint_object(lroundf128) add_math_entrypoint_object(modf) add_math_entrypoint_object(modff) add_math_entrypoint_object(modfl) +add_math_entrypoint_object(modff128) add_math_entrypoint_object(nan) add_math_entrypoint_object(nanf) @@ -210,6 +217,7 @@ add_math_entrypoint_object(remquol) add_math_entrypoint_object(rint) add_math_entrypoint_object(rintf) add_math_entrypoint_object(rintl) +add_math_entrypoint_object(rintf128) add_math_entrypoint_object(round) add_math_entrypoint_object(roundf) diff --git a/libc/src/math/amdgpu/CMakeLists.txt b/libc/src/math/amdgpu/CMakeLists.txt index c300730208d50992a3f853b8d4a34a7e5ca12f3b..93735a556a31bf453d416ad988775de5d98b7c98 100644 --- a/libc/src/math/amdgpu/CMakeLists.txt +++ b/libc/src/math/amdgpu/CMakeLists.txt @@ -176,26 +176,6 @@ add_entrypoint_object( -O2 ) -add_entrypoint_object( - modf - SRCS - modf.cpp - HDRS - ../modf.h - COMPILE_OPTIONS - -O2 -) - -add_entrypoint_object( - modff - SRCS - modff.cpp - HDRS - ../modff.h - COMPILE_OPTIONS - -O2 -) - add_entrypoint_object( nearbyint SRCS diff --git a/libc/src/math/docs/add_math_function.md b/libc/src/math/docs/add_math_function.md index 6f08bf037c578e224c7dd4f481034b48ed5cb63e..f8bc8a3bdd8b1d3cc8567eabea86b7602928008e 100644 --- a/libc/src/math/docs/add_math_function.md +++ b/libc/src/math/docs/add_math_function.md @@ -129,11 +129,11 @@ implementation (which is very often glibc). - Add a performance test to: ``` - libc/test/src/math/differential_testing/_perf.cpp + libc/test/src/math/performance_testing/_perf.cpp ``` - Add the corresponding entry point to: ``` - libc/test/src/math/differential_testing/CMakeLists.txt + libc/test/src/math/performance_testing/CMakeLists.txt ``` ## Build and Run @@ -189,8 +189,8 @@ implementation (which is very often glibc). - Build and Run performance test: ``` - $ ninja libc.test.src.math.differential_testing._perf - $ projects/libc/test/src/math/differential_testing/libc.test.src.math.differential_testing._perf + $ ninja libc.test.src.math.performance_testing._perf + $ projects/libc/test/src/math/performance_testing/libc.test.src.math.performance_testing._perf $ cat _perf.log ``` diff --git a/libc/src/math/fmodf128.h b/libc/src/math/fmodf128.h new file mode 100644 index 0000000000000000000000000000000000000000..b3242705f025eebb9367d47eb0b5c18ebc0eb51b --- /dev/null +++ b/libc/src/math/fmodf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for fmodf128 ----------------------*- 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_MATH_FMODF128_H +#define LLVM_LIBC_SRC_MATH_FMODF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 fmodf128(float128 x, float128 y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMODF128_H diff --git a/libc/src/math/fmodl.h b/libc/src/math/fmodl.h new file mode 100644 index 0000000000000000000000000000000000000000..f259ddb238a8e4757a70b1d718cea7ab54b1000b --- /dev/null +++ b/libc/src/math/fmodl.h @@ -0,0 +1,18 @@ +//===-- Implementation header for fmodl -------------------------*- 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_MATH_FMODL_H +#define LLVM_LIBC_SRC_MATH_FMODL_H + +namespace LIBC_NAMESPACE { + +long double fmodl(long double x, long double y); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_FMODL_H diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt index 82d2a5e66af781c1159648b65cc4ceb6f6cb188e..bc4e9b34cfc2f6fceff617d8fb6f346167923d2e 100644 --- a/libc/src/math/generic/CMakeLists.txt +++ b/libc/src/math/generic/CMakeLists.txt @@ -375,10 +375,10 @@ add_entrypoint_object( lround.cpp HDRS ../lround.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations - COMPILE_OPTIONS - -O2 ) add_entrypoint_object( @@ -387,10 +387,10 @@ add_entrypoint_object( lroundf.cpp HDRS ../lroundf.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations - COMPILE_OPTIONS - -O2 ) add_entrypoint_object( @@ -399,10 +399,23 @@ add_entrypoint_object( lroundl.cpp HDRS ../lroundl.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations +) + +add_entrypoint_object( + lroundf128 + SRCS + lroundf128.cpp + HDRS + ../lroundf128.h COMPILE_OPTIONS - -O2 + -O3 + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.nearest_integer_operations ) add_entrypoint_object( @@ -411,10 +424,10 @@ add_entrypoint_object( llround.cpp HDRS ../llround.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations - COMPILE_OPTIONS - -O2 ) add_entrypoint_object( @@ -423,10 +436,10 @@ add_entrypoint_object( llroundf.cpp HDRS ../llroundf.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations - COMPILE_OPTIONS - -O2 ) add_entrypoint_object( @@ -435,10 +448,23 @@ add_entrypoint_object( llroundl.cpp HDRS ../llroundl.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations +) + +add_entrypoint_object( + llroundf128 + SRCS + llroundf128.cpp + HDRS + ../llroundf128.h COMPILE_OPTIONS - -O2 + -O3 + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.nearest_integer_operations ) add_entrypoint_object( @@ -447,10 +473,10 @@ add_entrypoint_object( rint.cpp HDRS ../rint.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations - COMPILE_OPTIONS - -O2 ) add_entrypoint_object( @@ -459,10 +485,10 @@ add_entrypoint_object( rintf.cpp HDRS ../rintf.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations - COMPILE_OPTIONS - -O2 ) add_entrypoint_object( @@ -471,10 +497,23 @@ add_entrypoint_object( rintl.cpp HDRS ../rintl.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations +) + +add_entrypoint_object( + rintf128 + SRCS + rintf128.cpp + HDRS + ../rintf128.h COMPILE_OPTIONS - -O2 + -O3 + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.nearest_integer_operations ) add_entrypoint_object( @@ -483,10 +522,10 @@ add_entrypoint_object( lrint.cpp HDRS ../lrint.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations - COMPILE_OPTIONS - -O2 ) add_entrypoint_object( @@ -495,10 +534,10 @@ add_entrypoint_object( lrintf.cpp HDRS ../lrintf.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations - COMPILE_OPTIONS - -O2 ) add_entrypoint_object( @@ -507,10 +546,23 @@ add_entrypoint_object( lrintl.cpp HDRS ../lrintl.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations +) + +add_entrypoint_object( + lrintf128 + SRCS + lrintf128.cpp + HDRS + ../lrintf128.h COMPILE_OPTIONS - -O2 + -O3 + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.nearest_integer_operations ) add_entrypoint_object( @@ -519,10 +571,10 @@ add_entrypoint_object( llrint.cpp HDRS ../llrint.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations - COMPILE_OPTIONS - -O2 ) add_entrypoint_object( @@ -531,10 +583,10 @@ add_entrypoint_object( llrintf.cpp HDRS ../llrintf.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations - COMPILE_OPTIONS - -O2 ) add_entrypoint_object( @@ -543,10 +595,23 @@ add_entrypoint_object( llrintl.cpp HDRS ../llrintl.h + COMPILE_OPTIONS + -O3 DEPENDS libc.src.__support.FPUtil.nearest_integer_operations +) + +add_entrypoint_object( + llrintf128 + SRCS + llrintf128.cpp + HDRS + ../llrintf128.h COMPILE_OPTIONS - -O2 + -O3 + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.nearest_integer_operations ) add_entrypoint_object( @@ -1342,7 +1407,7 @@ add_entrypoint_object( DEPENDS libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( @@ -1354,7 +1419,7 @@ add_entrypoint_object( DEPENDS libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 ) add_entrypoint_object( @@ -1366,7 +1431,20 @@ add_entrypoint_object( DEPENDS libc.src.__support.FPUtil.manipulation_functions COMPILE_OPTIONS - -O2 + -O3 +) + +add_entrypoint_object( + modff128 + SRCS + modff128.cpp + HDRS + ../modff128.h + DEPENDS + libc.src.__support.macros.properties.types + libc.src.__support.FPUtil.manipulation_functions + COMPILE_OPTIONS + -O3 ) add_entrypoint_object( @@ -1781,7 +1859,6 @@ add_entrypoint_object( HDRS ../fmod.h DEPENDS - libc.include.math libc.src.__support.FPUtil.generic.fmod COMPILE_OPTIONS -O3 @@ -1794,7 +1871,31 @@ add_entrypoint_object( HDRS ../fmodf.h DEPENDS - libc.include.math + libc.src.__support.FPUtil.generic.fmod + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fmodl + SRCS + fmodl.cpp + HDRS + ../fmodl.h + DEPENDS + libc.src.__support.FPUtil.generic.fmod + COMPILE_OPTIONS + -O3 +) + +add_entrypoint_object( + fmodf128 + SRCS + fmodf128.cpp + HDRS + ../fmodf128.h + DEPENDS + libc.src.__support.macros.properties.types libc.src.__support.FPUtil.generic.fmod COMPILE_OPTIONS -O3 diff --git a/libc/src/math/generic/fmodf.cpp b/libc/src/math/generic/fmodf.cpp index 7a29ff1f18d319d12a191e391376bc3da242d46e..9a9e46e29b4662a296a648b888ad8879fadeb0fb 100644 --- a/libc/src/math/generic/fmodf.cpp +++ b/libc/src/math/generic/fmodf.cpp @@ -13,7 +13,7 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(float, fmodf, (float x, float y)) { - return fputil::generic::FMod::eval(x, y); + return fputil::generic::FMod::eval(x, y); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmodf128.cpp b/libc/src/math/generic/fmodf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..08a379702d889b19d774ffb78ceb3f1ca018ed36 --- /dev/null +++ b/libc/src/math/generic/fmodf128.cpp @@ -0,0 +1,19 @@ +//===-- Single-precision fmodf128 function --------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/fmodf128.h" +#include "src/__support/FPUtil/generic/FMod.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, fmodf128, (float128 x, float128 y)) { + return fputil::generic::FMod::eval(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/fmodl.cpp b/libc/src/math/generic/fmodl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23a37028905573a3acd082f95668bafd94f1ce8e --- /dev/null +++ b/libc/src/math/generic/fmodl.cpp @@ -0,0 +1,19 @@ +//===-- Single-precision fmodl function -----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/fmodl.h" +#include "src/__support/FPUtil/generic/FMod.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long double, fmodl, (long double x, long double y)) { + return fputil::generic::FMod::eval(x, y); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/hypotf.cpp b/libc/src/math/generic/hypotf.cpp index 614aa399fcc21b8227c7bae0a9c2a67ca461e3c9..ffbf706aefaf6b98a38a9f3a90c5ed3fc5bbe00a 100644 --- a/libc/src/math/generic/hypotf.cpp +++ b/libc/src/math/generic/hypotf.cpp @@ -48,8 +48,8 @@ LLVM_LIBC_FUNCTION(float, hypotf, (float x, float y)) { // Correct rounding. double r_sq = result.get_val() * result.get_val(); double diff = sum_sq - r_sq; - constexpr uint64_t mask = 0x0000'0000'3FFF'FFFFULL; - uint64_t lrs = result.uintval() & mask; + constexpr uint64_t MASK = 0x0000'0000'3FFF'FFFFULL; + uint64_t lrs = result.uintval() & MASK; if (lrs == 0x0000'0000'1000'0000ULL && err < diff) { result.set_uintval(result.uintval() | 1ULL); diff --git a/libc/src/math/generic/llrintf128.cpp b/libc/src/math/generic/llrintf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e5a4c50a26e8cefae51541d2aab7c0addf31bfa1 --- /dev/null +++ b/libc/src/math/generic/llrintf128.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of llrintf128 function -----------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/llrintf128.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long long, llrintf128, (float128 x)) { + return fputil::round_to_signed_integer_using_current_rounding_mode( + x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/llroundf128.cpp b/libc/src/math/generic/llroundf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..25791631dd7e748995ba704c94b92ba9f3870d51 --- /dev/null +++ b/libc/src/math/generic/llroundf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of llroundf128 function ----------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/llroundf128.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long long, llroundf128, (float128 x)) { + return fputil::round_to_signed_integer(x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/lrintf128.cpp b/libc/src/math/generic/lrintf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e06062fc5802471cec74399cadc217737fa8123 --- /dev/null +++ b/libc/src/math/generic/lrintf128.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of lrintf128 function ------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/lrintf128.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long, lrintf128, (float128 x)) { + return fputil::round_to_signed_integer_using_current_rounding_mode(x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/lroundf128.cpp b/libc/src/math/generic/lroundf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f93c475038256d12e630850d727ddfc2f5d29054 --- /dev/null +++ b/libc/src/math/generic/lroundf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of lroundf128 function -----------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/lroundf128.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long, lroundf128, (float128 x)) { + return fputil::round_to_signed_integer(x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/modff128.cpp b/libc/src/math/generic/modff128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6aef5f510a95333a90e8ff8fbd49ed4d73e9fb26 --- /dev/null +++ b/libc/src/math/generic/modff128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of modff128 function -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/modff128.h" +#include "src/__support/FPUtil/ManipulationFunctions.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, modff128, (float128 x, float128 *iptr)) { + return fputil::modf(x, *iptr); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/generic/rintf128.cpp b/libc/src/math/generic/rintf128.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ba9912d6f8538eb58535910f70390c9033d9720c --- /dev/null +++ b/libc/src/math/generic/rintf128.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of rintf128 function -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/math/rintf128.h" +#include "src/__support/FPUtil/NearestIntegerOperations.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(float128, rintf128, (float128 x)) { + return fputil::round_using_current_rounding_mode(x); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/math/llrintf128.h b/libc/src/math/llrintf128.h new file mode 100644 index 0000000000000000000000000000000000000000..ac9c249342cc708b24720c4689e64b26efbf5060 --- /dev/null +++ b/libc/src/math/llrintf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for llrintf128 --------------------*- 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_MATH_LLRINTF128_H +#define LLVM_LIBC_SRC_MATH_LLRINTF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +long long llrintf128(float128 x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_LLRINTF128_H diff --git a/libc/src/math/llroundf128.h b/libc/src/math/llroundf128.h new file mode 100644 index 0000000000000000000000000000000000000000..3245dfafc4d5a70a5b03041b903550cbb51bb374 --- /dev/null +++ b/libc/src/math/llroundf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for llroundf128 -------------------*- 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_MATH_LLROUNDF128_H +#define LLVM_LIBC_SRC_MATH_LLROUNDF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +long long llroundf128(float128 x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_LLROUNDF128_H diff --git a/libc/src/math/lrintf128.h b/libc/src/math/lrintf128.h new file mode 100644 index 0000000000000000000000000000000000000000..8f3f5ceabd3c218db631abfa2e91e53c4c9c0772 --- /dev/null +++ b/libc/src/math/lrintf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for lrintf128 ---------------------*- 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_MATH_LRINTF128_H +#define LLVM_LIBC_SRC_MATH_LRINTF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +long lrintf128(float128 x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_LRINTF128_H diff --git a/libc/src/math/lroundf128.h b/libc/src/math/lroundf128.h new file mode 100644 index 0000000000000000000000000000000000000000..663b3732655b2fb635dd7c728121deb7ff749671 --- /dev/null +++ b/libc/src/math/lroundf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for lroundf128 --------------------*- 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_MATH_LROUNDF128_H +#define LLVM_LIBC_SRC_MATH_LROUNDF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +long lroundf128(float128 x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_LROUNDF128_H diff --git a/libc/src/math/modff128.h b/libc/src/math/modff128.h new file mode 100644 index 0000000000000000000000000000000000000000..48e614be95b9826e2703ece162b1d0474810dbc0 --- /dev/null +++ b/libc/src/math/modff128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for modff128 -----------------------*- 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_MATH_MODFF128_H +#define LLVM_LIBC_SRC_MATH_MODFF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 modff128(float128 x, float128 *iptr); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_MODFF128_H diff --git a/libc/src/math/nvptx/CMakeLists.txt b/libc/src/math/nvptx/CMakeLists.txt index 56bff1472f134f47d4c0721845b939e1366ea251..581e1c6a3044b2ebedf0b612c151d6f2639998ed 100644 --- a/libc/src/math/nvptx/CMakeLists.txt +++ b/libc/src/math/nvptx/CMakeLists.txt @@ -177,26 +177,6 @@ add_entrypoint_object( -O2 ) -add_entrypoint_object( - modf - SRCS - modf.cpp - HDRS - ../modf.h - COMPILE_OPTIONS - -O2 -) - -add_entrypoint_object( - modff - SRCS - modff.cpp - HDRS - ../modff.h - COMPILE_OPTIONS - -O2 -) - add_entrypoint_object( nearbyint SRCS diff --git a/libc/src/math/rintf128.h b/libc/src/math/rintf128.h new file mode 100644 index 0000000000000000000000000000000000000000..2d9248974f024f718ebef90f0cbc0dc5f37b7bcf --- /dev/null +++ b/libc/src/math/rintf128.h @@ -0,0 +1,20 @@ +//===-- Implementation header for rintf128 ----------------------*- 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_MATH_RINTF128_H +#define LLVM_LIBC_SRC_MATH_RINTF128_H + +#include "src/__support/macros/properties/types.h" + +namespace LIBC_NAMESPACE { + +float128 rintf128(float128 x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_MATH_RINTF128_H diff --git a/libc/src/stdbit/CMakeLists.txt b/libc/src/stdbit/CMakeLists.txt index 8bc7dd7852bbca0ab641d9456fccd11ce357a5d9..2aef2029f2df0bf2bd634ebcebd5197252a366c0 100644 --- a/libc/src/stdbit/CMakeLists.txt +++ b/libc/src/stdbit/CMakeLists.txt @@ -10,6 +10,9 @@ set(prefixes count_zeros count_ones has_single_bit + bit_width + bit_floor + bit_ceil ) set(suffixes c s i l ll) foreach(prefix IN LISTS prefixes) diff --git a/libc/src/math/nvptx/modf.cpp b/libc/src/stdbit/stdc_bit_ceil_uc.cpp similarity index 61% rename from libc/src/math/nvptx/modf.cpp rename to libc/src/stdbit/stdc_bit_ceil_uc.cpp index 07dbbd6059c35f33ac0827e5b83b1847838d9e08..675ae4a0edb0212a2f2c201a20ce15e6dbb960d5 100644 --- a/libc/src/math/nvptx/modf.cpp +++ b/libc/src/stdbit/stdc_bit_ceil_uc.cpp @@ -1,4 +1,4 @@ -//===-- Implementation of the GPU modf function ---------------------------===// +//===-- Implementation of stdc_bit_ceil_uc --------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,13 +6,15 @@ // //===----------------------------------------------------------------------===// -#include "src/math/modf.h" +#include "src/stdbit/stdc_bit_ceil_uc.h" + +#include "src/__support/CPP/bit.h" #include "src/__support/common.h" namespace LIBC_NAMESPACE { -LLVM_LIBC_FUNCTION(double, modf, (double x, double *iptr)) { - return __builtin_modf(x, iptr); +LLVM_LIBC_FUNCTION(unsigned char, stdc_bit_ceil_uc, (unsigned char value)) { + return cpp::bit_ceil(value); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_ceil_uc.h b/libc/src/stdbit/stdc_bit_ceil_uc.h new file mode 100644 index 0000000000000000000000000000000000000000..204261e410812136c2db5643ebc508a962bb94be --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_uc.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_ceil_uc --------------*- 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_STDBIT_STDC_BIT_CEIL_UC_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UC_H + +namespace LIBC_NAMESPACE { + +unsigned char stdc_bit_ceil_uc(unsigned char value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UC_H diff --git a/libc/src/math/amdgpu/modff.cpp b/libc/src/stdbit/stdc_bit_ceil_ui.cpp similarity index 62% rename from libc/src/math/amdgpu/modff.cpp rename to libc/src/stdbit/stdc_bit_ceil_ui.cpp index ad35f9006b5122408030dd490147b13a39780876..a8ac9726179bc73cff65b4b292846ad017e3a9ed 100644 --- a/libc/src/math/amdgpu/modff.cpp +++ b/libc/src/stdbit/stdc_bit_ceil_ui.cpp @@ -1,4 +1,4 @@ -//===-- Implementation of the GPU modff function --------------------------===// +//===-- Implementation of stdc_bit_ceil_ui --------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,13 +6,15 @@ // //===----------------------------------------------------------------------===// -#include "src/math/modff.h" +#include "src/stdbit/stdc_bit_ceil_ui.h" + +#include "src/__support/CPP/bit.h" #include "src/__support/common.h" namespace LIBC_NAMESPACE { -LLVM_LIBC_FUNCTION(float, modff, (float x, float *iptr)) { - return __builtin_modff(x, iptr); +LLVM_LIBC_FUNCTION(unsigned, stdc_bit_ceil_ui, (unsigned value)) { + return cpp::bit_ceil(value); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_ceil_ui.h b/libc/src/stdbit/stdc_bit_ceil_ui.h new file mode 100644 index 0000000000000000000000000000000000000000..db66c336e36624f71a268c9ba77346933903b158 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_ui.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_ceil_ui --------------*- 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_STDBIT_STDC_BIT_CEIL_UI_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UI_H + +namespace LIBC_NAMESPACE { + +unsigned stdc_bit_ceil_ui(unsigned value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UI_H diff --git a/libc/src/math/amdgpu/modf.cpp b/libc/src/stdbit/stdc_bit_ceil_ul.cpp similarity index 61% rename from libc/src/math/amdgpu/modf.cpp rename to libc/src/stdbit/stdc_bit_ceil_ul.cpp index 07dbbd6059c35f33ac0827e5b83b1847838d9e08..18a9c38b5b4cf6ddfebc3cc8a8be2dc94dc275f4 100644 --- a/libc/src/math/amdgpu/modf.cpp +++ b/libc/src/stdbit/stdc_bit_ceil_ul.cpp @@ -1,4 +1,4 @@ -//===-- Implementation of the GPU modf function ---------------------------===// +//===-- Implementation of stdc_bit_ceil_ul --------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,13 +6,15 @@ // //===----------------------------------------------------------------------===// -#include "src/math/modf.h" +#include "src/stdbit/stdc_bit_ceil_ul.h" + +#include "src/__support/CPP/bit.h" #include "src/__support/common.h" namespace LIBC_NAMESPACE { -LLVM_LIBC_FUNCTION(double, modf, (double x, double *iptr)) { - return __builtin_modf(x, iptr); +LLVM_LIBC_FUNCTION(unsigned long, stdc_bit_ceil_ul, (unsigned long value)) { + return cpp::bit_ceil(value); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_ceil_ul.h b/libc/src/stdbit/stdc_bit_ceil_ul.h new file mode 100644 index 0000000000000000000000000000000000000000..f8393a42fcbfc13a66de886ec46663c5f04dd570 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_ul.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_ceil_ul --------------*- 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_STDBIT_STDC_BIT_CEIL_UL_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UL_H + +namespace LIBC_NAMESPACE { + +unsigned long stdc_bit_ceil_ul(unsigned long value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_UL_H diff --git a/libc/src/stdbit/stdc_bit_ceil_ull.cpp b/libc/src/stdbit/stdc_bit_ceil_ull.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0989f36ab7685ab55c5b647e86ccba229f775e83 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_ull.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of stdc_bit_ceil_ull -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_ceil_ull.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned long long, stdc_bit_ceil_ull, + (unsigned long long value)) { + return cpp::bit_ceil(value); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_ceil_ull.h b/libc/src/stdbit/stdc_bit_ceil_ull.h new file mode 100644 index 0000000000000000000000000000000000000000..e65f537efb172f8ddcf5805b49bebe1dd34c8093 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_ull.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_ceil_ull -------------*- 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_STDBIT_STDC_BIT_CEIL_ULL_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_ULL_H + +namespace LIBC_NAMESPACE { + +unsigned long long stdc_bit_ceil_ull(unsigned long long value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_ULL_H diff --git a/libc/src/stdbit/stdc_bit_ceil_us.cpp b/libc/src/stdbit/stdc_bit_ceil_us.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f86a216bb840e9363cf5caaba7a737020cf5fc8a --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_us.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of stdc_bit_ceil_us --------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_ceil_us.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned short, stdc_bit_ceil_us, (unsigned short value)) { + return cpp::bit_ceil(value); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_ceil_us.h b/libc/src/stdbit/stdc_bit_ceil_us.h new file mode 100644 index 0000000000000000000000000000000000000000..16a14e51b743341d0749765dadfc210ddb1535c1 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_ceil_us.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_ceil_us --------------*- 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_STDBIT_STDC_BIT_CEIL_US_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_US_H + +namespace LIBC_NAMESPACE { + +unsigned short stdc_bit_ceil_us(unsigned short value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_CEIL_US_H diff --git a/libc/src/stdbit/stdc_bit_floor_uc.cpp b/libc/src/stdbit/stdc_bit_floor_uc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6cb04c9eb43e62bd57ed2bb9c91818809e812f52 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_floor_uc.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of stdc_bit_floor_uc -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_floor_uc.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned char, stdc_bit_floor_uc, (unsigned char value)) { + return cpp::bit_floor(value); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_floor_uc.h b/libc/src/stdbit/stdc_bit_floor_uc.h new file mode 100644 index 0000000000000000000000000000000000000000..d6f53c5f6997978f341f04e38454525d0f57e9df --- /dev/null +++ b/libc/src/stdbit/stdc_bit_floor_uc.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_floor_uc -------------*- 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_STDBIT_STDC_BIT_FLOOR_UC_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_FLOOR_UC_H + +namespace LIBC_NAMESPACE { + +unsigned char stdc_bit_floor_uc(unsigned char value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_FLOOR_UC_H diff --git a/libc/src/math/nvptx/modff.cpp b/libc/src/stdbit/stdc_bit_floor_ui.cpp similarity index 62% rename from libc/src/math/nvptx/modff.cpp rename to libc/src/stdbit/stdc_bit_floor_ui.cpp index ad35f9006b5122408030dd490147b13a39780876..149b63f190cf37ebfd27c57884bc1ae367d6e81b 100644 --- a/libc/src/math/nvptx/modff.cpp +++ b/libc/src/stdbit/stdc_bit_floor_ui.cpp @@ -1,4 +1,4 @@ -//===-- Implementation of the GPU modff function --------------------------===// +//===-- Implementation of stdc_bit_floor_ui -------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,13 +6,15 @@ // //===----------------------------------------------------------------------===// -#include "src/math/modff.h" +#include "src/stdbit/stdc_bit_floor_ui.h" + +#include "src/__support/CPP/bit.h" #include "src/__support/common.h" namespace LIBC_NAMESPACE { -LLVM_LIBC_FUNCTION(float, modff, (float x, float *iptr)) { - return __builtin_modff(x, iptr); +LLVM_LIBC_FUNCTION(unsigned, stdc_bit_floor_ui, (unsigned value)) { + return cpp::bit_floor(value); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_floor_ui.h b/libc/src/stdbit/stdc_bit_floor_ui.h new file mode 100644 index 0000000000000000000000000000000000000000..fcc606386f86d3cef3f6b7f3324a2e57df3b3076 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_floor_ui.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_floor_ui -------------*- 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_STDBIT_STDC_BIT_FLOOR_UI_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_FLOOR_UI_H + +namespace LIBC_NAMESPACE { + +unsigned stdc_bit_floor_ui(unsigned value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_FLOOR_UI_H diff --git a/libc/src/stdbit/stdc_bit_floor_ul.cpp b/libc/src/stdbit/stdc_bit_floor_ul.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a29a044545684e49920dc8a93062eb80a9dc0f37 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_floor_ul.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of stdc_bit_floor_ul -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_floor_ul.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned long, stdc_bit_floor_ul, (unsigned long value)) { + return cpp::bit_floor(value); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_floor_ul.h b/libc/src/stdbit/stdc_bit_floor_ul.h new file mode 100644 index 0000000000000000000000000000000000000000..08327aa60c90699605f154db9197dfc333aa0b1d --- /dev/null +++ b/libc/src/stdbit/stdc_bit_floor_ul.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_floor_ul -------------*- 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_STDBIT_STDC_BIT_FLOOR_UL_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_FLOOR_UL_H + +namespace LIBC_NAMESPACE { + +unsigned long stdc_bit_floor_ul(unsigned long value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_FLOOR_UL_H diff --git a/libc/src/stdbit/stdc_bit_floor_ull.cpp b/libc/src/stdbit/stdc_bit_floor_ull.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1084b6357322740b7ae8fd8752a13b31de7391e --- /dev/null +++ b/libc/src/stdbit/stdc_bit_floor_ull.cpp @@ -0,0 +1,21 @@ +//===-- Implementation of stdc_bit_floor_ull ------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_floor_ull.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned long long, stdc_bit_floor_ull, + (unsigned long long value)) { + return cpp::bit_floor(value); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_floor_ull.h b/libc/src/stdbit/stdc_bit_floor_ull.h new file mode 100644 index 0000000000000000000000000000000000000000..8f360b23855ad675f9cf41dd815d54269bfa472f --- /dev/null +++ b/libc/src/stdbit/stdc_bit_floor_ull.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_floor_ull ------------*- 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_STDBIT_STDC_BIT_FLOOR_ULL_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_FLOOR_ULL_H + +namespace LIBC_NAMESPACE { + +unsigned long long stdc_bit_floor_ull(unsigned long long value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_FLOOR_ULL_H diff --git a/libc/src/stdbit/stdc_bit_floor_us.cpp b/libc/src/stdbit/stdc_bit_floor_us.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1357a980e3a8a3d814658aa59659d5e8786663d --- /dev/null +++ b/libc/src/stdbit/stdc_bit_floor_us.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of stdc_bit_floor_us -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_floor_us.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned short, stdc_bit_floor_us, (unsigned short value)) { + return cpp::bit_floor(value); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_floor_us.h b/libc/src/stdbit/stdc_bit_floor_us.h new file mode 100644 index 0000000000000000000000000000000000000000..fcd0b9e3c549a117d6d35f7bd7941461e079c560 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_floor_us.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_floor_us -------------*- 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_STDBIT_STDC_BIT_FLOOR_US_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_FLOOR_US_H + +namespace LIBC_NAMESPACE { + +unsigned short stdc_bit_floor_us(unsigned short value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_FLOOR_US_H diff --git a/libc/src/stdbit/stdc_bit_width_uc.cpp b/libc/src/stdbit/stdc_bit_width_uc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2c361c1bbb1cfeca0d77dea15a96605d7f4305ff --- /dev/null +++ b/libc/src/stdbit/stdc_bit_width_uc.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of stdc_bit_width_uc -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_width_uc.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned, stdc_bit_width_uc, (unsigned char value)) { + return static_cast(cpp::bit_width(value)); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_width_uc.h b/libc/src/stdbit/stdc_bit_width_uc.h new file mode 100644 index 0000000000000000000000000000000000000000..70c038aaf1dfe5623d1c540252a0d1c2bcc1256a --- /dev/null +++ b/libc/src/stdbit/stdc_bit_width_uc.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_width_uc -------------*- 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_STDBIT_STDC_BIT_WIDTH_UC_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_WIDTH_UC_H + +namespace LIBC_NAMESPACE { + +unsigned stdc_bit_width_uc(unsigned char value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_WIDTH_UC_H diff --git a/libc/src/stdbit/stdc_bit_width_ui.cpp b/libc/src/stdbit/stdc_bit_width_ui.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b94452b09bd506e446c0157c50b03085908535ec --- /dev/null +++ b/libc/src/stdbit/stdc_bit_width_ui.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of stdc_bit_width_ui -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_width_ui.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned, stdc_bit_width_ui, (unsigned value)) { + return static_cast(cpp::bit_width(value)); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_width_ui.h b/libc/src/stdbit/stdc_bit_width_ui.h new file mode 100644 index 0000000000000000000000000000000000000000..9e8de3d6ef46e4a3523b441a16f9ab7bc03f8ffd --- /dev/null +++ b/libc/src/stdbit/stdc_bit_width_ui.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_width_ui -------------*- 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_STDBIT_STDC_BIT_WIDTH_UI_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_WIDTH_UI_H + +namespace LIBC_NAMESPACE { + +unsigned stdc_bit_width_ui(unsigned value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_WIDTH_UI_H diff --git a/libc/src/stdbit/stdc_bit_width_ul.cpp b/libc/src/stdbit/stdc_bit_width_ul.cpp new file mode 100644 index 0000000000000000000000000000000000000000..80044314e4b21eddbac762c94dbbe9f1fe0ea490 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_width_ul.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of stdc_bit_width_ul -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_width_ul.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned, stdc_bit_width_ul, (unsigned long value)) { + return static_cast(cpp::bit_width(value)); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_width_ul.h b/libc/src/stdbit/stdc_bit_width_ul.h new file mode 100644 index 0000000000000000000000000000000000000000..447a2918e2f2bb39edb16b752ebd705f648bff1c --- /dev/null +++ b/libc/src/stdbit/stdc_bit_width_ul.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_width_ul -------------*- 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_STDBIT_STDC_BIT_WIDTH_UL_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_WIDTH_UL_H + +namespace LIBC_NAMESPACE { + +unsigned stdc_bit_width_ul(unsigned long value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_WIDTH_UL_H diff --git a/libc/src/stdbit/stdc_bit_width_ull.cpp b/libc/src/stdbit/stdc_bit_width_ull.cpp new file mode 100644 index 0000000000000000000000000000000000000000..006fa20b2de5e7825013161e7d8592423d24d46a --- /dev/null +++ b/libc/src/stdbit/stdc_bit_width_ull.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of stdc_bit_width_ull ------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_width_ull.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned, stdc_bit_width_ull, (unsigned long long value)) { + return static_cast(cpp::bit_width(value)); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_width_ull.h b/libc/src/stdbit/stdc_bit_width_ull.h new file mode 100644 index 0000000000000000000000000000000000000000..bc51897f448fc30a64169626eba89e3894a571c8 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_width_ull.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_width_ull ------------*- 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_STDBIT_STDC_BIT_WIDTH_ULL_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_WIDTH_ULL_H + +namespace LIBC_NAMESPACE { + +unsigned stdc_bit_width_ull(unsigned long long value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_WIDTH_ULL_H diff --git a/libc/src/stdbit/stdc_bit_width_us.cpp b/libc/src/stdbit/stdc_bit_width_us.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d9f72bf5d060298d7da11a117b526d5c3cd4bf1 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_width_us.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of stdc_bit_width_us -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/stdbit/stdc_bit_width_us.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned, stdc_bit_width_us, (unsigned short value)) { + return static_cast(cpp::bit_width(value)); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_bit_width_us.h b/libc/src/stdbit/stdc_bit_width_us.h new file mode 100644 index 0000000000000000000000000000000000000000..02cd37426eb4c1ef2f37d75d380f8202308e8248 --- /dev/null +++ b/libc/src/stdbit/stdc_bit_width_us.h @@ -0,0 +1,18 @@ +//===-- Implementation header for stdc_bit_width_us -------------*- 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_STDBIT_STDC_BIT_WIDTH_US_H +#define LLVM_LIBC_SRC_STDBIT_STDC_BIT_WIDTH_US_H + +namespace LIBC_NAMESPACE { + +unsigned stdc_bit_width_us(unsigned short value); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDBIT_STDC_BIT_WIDTH_US_H diff --git a/libc/src/stdbit/stdc_count_ones_uc.cpp b/libc/src/stdbit/stdc_count_ones_uc.cpp index 5a7314caa3baa031567127dda7931d7ad1e6270c..1e998ff521b7db3b98d3dfa56a68d93ed156e610 100644 --- a/libc/src/stdbit/stdc_count_ones_uc.cpp +++ b/libc/src/stdbit/stdc_count_ones_uc.cpp @@ -14,7 +14,7 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_ones_uc, (unsigned char value)) { - return static_cast(cpp::count_ones(value)); + return static_cast(cpp::popcount(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_count_ones_ui.cpp b/libc/src/stdbit/stdc_count_ones_ui.cpp index 289f4bac31f7b8813799be4b94622a3cb2940716..e457dd793db33d2cb4bd7b16fcd36bd5900fa80c 100644 --- a/libc/src/stdbit/stdc_count_ones_ui.cpp +++ b/libc/src/stdbit/stdc_count_ones_ui.cpp @@ -14,7 +14,7 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_ones_ui, (unsigned value)) { - return static_cast(cpp::count_ones(value)); + return static_cast(cpp::popcount(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_count_ones_ul.cpp b/libc/src/stdbit/stdc_count_ones_ul.cpp index 83f3279d7919373d099bff037e0c736f3a60e569..ed86653fc7ee2e36509e94d228f293776fb56421 100644 --- a/libc/src/stdbit/stdc_count_ones_ul.cpp +++ b/libc/src/stdbit/stdc_count_ones_ul.cpp @@ -14,7 +14,7 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_ones_ul, (unsigned long value)) { - return static_cast(cpp::count_ones(value)); + return static_cast(cpp::popcount(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_count_ones_ull.cpp b/libc/src/stdbit/stdc_count_ones_ull.cpp index 104788aaf21265ab36c4c9ee6e458daef44b7b1a..c5ecc3cda6477ad7b31d86bc082da886a31f017b 100644 --- a/libc/src/stdbit/stdc_count_ones_ull.cpp +++ b/libc/src/stdbit/stdc_count_ones_ull.cpp @@ -14,7 +14,7 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_ones_ull, (unsigned long long value)) { - return static_cast(cpp::count_ones(value)); + return static_cast(cpp::popcount(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdbit/stdc_count_ones_us.cpp b/libc/src/stdbit/stdc_count_ones_us.cpp index 4b6ff0b94b626a94416384e78e447f8b966e678a..465c5c374e7c64bfa3530e70a481b8e4d94a95db 100644 --- a/libc/src/stdbit/stdc_count_ones_us.cpp +++ b/libc/src/stdbit/stdc_count_ones_us.cpp @@ -14,7 +14,7 @@ namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(unsigned, stdc_count_ones_us, (unsigned short value)) { - return static_cast(cpp::count_ones(value)); + return static_cast(cpp::popcount(value)); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/CMakeLists.txt b/libc/src/stdfix/CMakeLists.txt index cb2134fe33cf9c789712aa381691d1c17aa79432..10d76ae31349f9f5cf101bcc7c71c8597debe7fc 100644 --- a/libc/src/stdfix/CMakeLists.txt +++ b/libc/src/stdfix/CMakeLists.txt @@ -11,7 +11,6 @@ foreach(suffix IN ITEMS hr r lr hk k lk) abs${suffix}.cpp COMPILE_OPTIONS -O3 - -ffixed-point DEPENDS libc.src.__support.fixed_point.fx_bits ) @@ -26,7 +25,6 @@ foreach(suffix IN ITEMS uhr ur ulr uhk uk) sqrt${suffix}.cpp COMPILE_OPTIONS -O3 - -ffixed-point DEPENDS libc.src.__support.fixed_point.sqrt ) @@ -41,8 +39,57 @@ foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk) round${suffix}.cpp COMPILE_OPTIONS -O3 - -ffixed-point DEPENDS libc.src.__support.fixed_point.fx_bits ) endforeach() + +add_entrypoint_object( + uhksqrtus + HDRS + uhksqrtus.h + SRCS + uhksqrtus.cpp + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.fixed_point.sqrt +) + +add_entrypoint_object( + uksqrtui + HDRS + uksqrtui.h + SRCS + uksqrtui.cpp + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.fixed_point.sqrt +) + +add_entrypoint_object( + exphk + HDRS + exphk.h + SRCS + exphk.cpp + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.fixed_point.fx_rep + libc.src.__support.CPP.bit +) + +add_entrypoint_object( + expk + HDRS + expk.h + SRCS + expk.cpp + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.__support.fixed_point.fx_rep + libc.src.__support.CPP.bit +) diff --git a/libc/src/stdfix/exphk.cpp b/libc/src/stdfix/exphk.cpp new file mode 100644 index 0000000000000000000000000000000000000000..19a972b390c71b0792eba307d375a45426e65c76 --- /dev/null +++ b/libc/src/stdfix/exphk.cpp @@ -0,0 +1,92 @@ +//===-- Implementation of exphk function ----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "exphk.h" +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/fx_bits.h" + +namespace LIBC_NAMESPACE { + +namespace { + +// Look up tables for exp(hi) and exp(mid). +// Generated with Sollya: +// > for i from 0 to 89 do { +// hi = floor(i/8) - 5; +// m = i/8 - floor(i/8) - 0.5; +// e_hi = nearestint(exp(hi) * 2^7) * 2^-7; +// e_mid = nearestint(exp(m) * 2^7) * 2^-7; +// print(hi, e_hi, m, e_mid); +// }; +// Notice that when i = 88 and 89, e_hi will overflow short accum range. +static constexpr short accum EXP_HI[12] = { + 0x1.0p-7hk, 0x1.0p-6hk, 0x1.8p-5hk, 0x1.1p-3hk, 0x1.78p-2hk, 0x1.0p0hk, + 0x1.5cp1hk, 0x1.d9p2hk, 0x1.416p4hk, 0x1.b4dp5hk, 0x1.28d4p7hk, SACCUM_MAX, +}; + +static constexpr short accum EXP_MID[8] = { + 0x1.38p-1hk, 0x1.6p-1hk, 0x1.9p-1hk, 0x1.c4p-1hk, + 0x1.0p0hk, 0x1.22p0hk, 0x1.48p0hk, 0x1.74p0hk, +}; + +} // anonymous namespace + +LLVM_LIBC_FUNCTION(short accum, exphk, (short accum x)) { + using FXRep = fixed_point::FXRep; + using StorageType = typename FXRep::StorageType; + // Output overflow + if (LIBC_UNLIKELY(x >= 0x1.64p2hk)) + return FXRep::MAX(); + // Lower bound where exp(x) -> 0: + // floor(log(2^-8) * 2^7) * 2^-7 + if (LIBC_UNLIKELY(x <= -0x1.63p2hk)) + return FXRep::ZERO(); + + // Current range of x: + // -0x1.628p2 <= x <= 0x1.638p2 + // Range reduction: + // x = hi + mid + lo, + // where: + // hi is an integer + // mid * 2^3 is an integer + // |lo| <= 2^-4. + // Then exp(x) = exp(hi + mid + lo) = exp(hi) * exp(mid) * exp(lo) + // ~ exp(hi) * exp(mid) * (1 + lo) + // with relative errors < |lo|^2 <= 2^-8. + // exp(hi) and exp(mid) are extracted from small lookup tables. + + // Round-to-nearest 1/8, tie-to-(+Int): + constexpr short accum ONE_SIXTEENTH = 0x1.0p-4hk; + // x_rounded = floor(x + 1/16). + short accum x_rounded = ((x + ONE_SIXTEENTH) >> (FXRep::FRACTION_LEN - 3)) + << (FXRep::FRACTION_LEN - 3); + short accum lo = x - x_rounded; + + // Range of x_rounded: + // x_rounded >= floor((-0x1.628p2 + 0x1.0p-4) * 2^3) * 2^-3 + // = -0x1.6p2 = -5.5 + // To get the indices, we shift the values so that it start with 0. + // Range of indices: 0 <= indices <= 89 + StorageType indices = cpp::bit_cast((x_rounded + 0x1.6p2hk) >> + (FXRep::FRACTION_LEN - 3)); + // So we have the following relation: + // indices = (hi + mid + 44/8) * 8 + // That implies: + // hi + mid = indices/8 - 5.5 + // So for lookup tables, we can use the upper 4 bits to get: + // exp( floor(indices / 8) - 5 ) + // and lower 3 bits for: + // exp( (indices - floor(indices)) - 0.5 ) + short accum exp_hi = EXP_HI[indices >> 3]; + short accum exp_mid = EXP_MID[indices & 0x7]; + // exp(x) ~ exp(hi) * exp(mid) * (1 + lo); + return (exp_hi * (exp_mid * (0x1.0p0hk + lo))); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/exphk.h b/libc/src/stdfix/exphk.h new file mode 100644 index 0000000000000000000000000000000000000000..da03bb76d53f5369700670d9429cbfac6b7e8d9c --- /dev/null +++ b/libc/src/stdfix/exphk.h @@ -0,0 +1,20 @@ +//===-- Implementation header for exphk -------------------------*- 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_STDFIX_EXPHK_H +#define LLVM_LIBC_SRC_STDFIX_EXPHK_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +short accum exphk(short accum x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_EXPHK_H diff --git a/libc/src/stdfix/expk.cpp b/libc/src/stdfix/expk.cpp new file mode 100644 index 0000000000000000000000000000000000000000..57227fd27769ccf39367da8234216d49e8cc0082 --- /dev/null +++ b/libc/src/stdfix/expk.cpp @@ -0,0 +1,104 @@ +//===-- Implementation of expk function ----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "expk.h" +#include "src/__support/CPP/bit.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/fx_bits.h" + +namespace LIBC_NAMESPACE { + +namespace { + +// Look up tables for exp(hi) and exp(mid). +// Generated with Sollya: +// > for i from 0 to 23 do { +// hi = i - 11; +// e_hi = nearestint(exp(hi) * 2^15) * 2^-15; +// print(e_hi, "k,"); +// }; +static constexpr accum EXP_HI[24] = { + 0x1p-15k, 0x1p-15k, 0x1p-13k, 0x1.6p-12k, + 0x1.ep-11k, 0x1.44p-9k, 0x1.bap-8k, 0x1.2cp-6k, + 0x1.97cp-5k, 0x1.153p-3k, 0x1.78b8p-2k, 0x1p0k, + 0x1.5bf1p1k, 0x1.d8e68p2k, 0x1.415e6p4k, 0x1.b4c9p5k, + 0x1.28d388p7k, 0x1.936dc6p8k, 0x1.1228858p10k, 0x1.749ea7cp11k, + 0x1.fa7157cp12k, 0x1.5829dcf8p14k, 0x1.d3c4489p15k, ACCUM_MAX, +}; + +// Generated with Sollya: +// > for i from 0 to 15 do { +// m = i/16 - 0.0625; +// e_m = nearestint(exp(m) * 2^15) * 2^-15; +// print(e_m, "k,"); +// }; +static constexpr accum EXP_MID[16] = { + 0x1.e0fcp-1k, 0x1p0k, 0x1.1082p0k, 0x1.2216p0k, + 0x1.34ccp0k, 0x1.48b6p0k, 0x1.5deap0k, 0x1.747ap0k, + 0x1.8c8p0k, 0x1.a612p0k, 0x1.c14cp0k, 0x1.de46p0k, + 0x1.fd1ep0k, 0x1.0efap1k, 0x1.2074p1k, 0x1.330ep1k, +}; + +} // anonymous namespace + +LLVM_LIBC_FUNCTION(accum, expk, (accum x)) { + using FXRep = fixed_point::FXRep; + using StorageType = typename FXRep::StorageType; + // Output overflow + // > floor(log(2^16) * 2^15) * 2^-15 + if (LIBC_UNLIKELY(x >= 0x1.62e4p3k)) + return FXRep::MAX(); + // Lower bound where exp(x) -> 0: + // floor(log(2^-16) * 2^15) * 2^-15 + if (LIBC_UNLIKELY(x <= -0x1.62e44p3k)) + return FXRep::ZERO(); + + // Current range of x: + // -0x1.62e4p3 <= x <= 0x1.62e3cp3 + // Range reduction: + // x = hi + mid + lo, + // where: + // hi is an integer + // mid * 2^4 is an integer + // |lo| <= 2^-5. + // Then exp(x) = exp(hi + mid + lo) = exp(hi) * exp(mid) * exp(lo) + // ~ exp(hi) * exp(mid) * (1 + lo + lo^2 / 2) + // with relative errors < |lo|^3/2 <= 2^-16. + // exp(hi) and exp(mid) are extracted from small lookup tables. + + // Round-to-nearest 1/16, tie-to-(+Int): + constexpr accum ONE_THIRTY_SECOND = 0x1.0p-5k; + // x_rounded = floor(x + 1/16). + accum x_rounded = ((x + ONE_THIRTY_SECOND) >> (FXRep::FRACTION_LEN - 4)) + << (FXRep::FRACTION_LEN - 4); + accum lo = x - x_rounded; + + // Range of x_rounded: + // x_rounded >= floor((-0x1.62e4p3 + 0x1.0p-5) * 2^4) * 2^-4 + // = -0x1.62p3 = -11.0625 + // To get the indices, we shift the values so that it start with 0. + // Range of indices: 0 <= indices <= 355. + StorageType indices = cpp::bit_cast((x_rounded + 0x1.62p3k) >> + (FXRep::FRACTION_LEN - 4)); + // So we have the following relation: + // indices = (hi + mid + 177/16) * 16 + // That implies: + // hi + mid = indices/16 - 11.0625 + // So for lookup tables, we can use the upper 4 bits to get: + // exp( floor(indices / 16) - 11 ) + // and lower 4 bits for: + // exp( (indices - floor(indices)) - 0.0625 ) + accum exp_hi = EXP_HI[indices >> 4]; + accum exp_mid = EXP_MID[indices & 0xf]; + // exp(x) ~ exp(hi) * exp(mid) * (1 + lo); + accum l1 = 0x1.0p0k + (lo >> 1); // = 1 + lo / 2 + accum l2 = 0x1.0p0k + lo * l1; // = 1 + lo * (1 + lo / 2) = 1 + lo + lo^2/2 + return (exp_hi * (exp_mid * l2)); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/expk.h b/libc/src/stdfix/expk.h new file mode 100644 index 0000000000000000000000000000000000000000..4526686a200b474e68231b1a5c75b3fe266f880e --- /dev/null +++ b/libc/src/stdfix/expk.h @@ -0,0 +1,20 @@ +//===-- Implementation header for expk --------------------------*- 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_STDFIX_EXPK_H +#define LLVM_LIBC_SRC_STDFIX_EXPK_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +accum expk(accum x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_EXPK_H diff --git a/libc/src/stdfix/uhksqrtus.cpp b/libc/src/stdfix/uhksqrtus.cpp new file mode 100644 index 0000000000000000000000000000000000000000..335750ae902b28e2ff396a36ae8f47b1c93766be --- /dev/null +++ b/libc/src/stdfix/uhksqrtus.cpp @@ -0,0 +1,23 @@ +//===-- Implementation of uhksqrtus function ------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "uhksqrtus.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/sqrt.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned short accum, uhksqrtus, (unsigned short x)) { +#ifdef LIBC_FAST_MATH + return fixed_point::isqrt_fast(x); +#else + return fixed_point::isqrt(x); +#endif +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/uhksqrtus.h b/libc/src/stdfix/uhksqrtus.h new file mode 100644 index 0000000000000000000000000000000000000000..c24846a800303730d64d647f61fac3d41dd4e67f --- /dev/null +++ b/libc/src/stdfix/uhksqrtus.h @@ -0,0 +1,20 @@ +//===-- Implementation header for uhksqrtus ---------------------*- 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_STDFIX_UHKSQRTUS_H +#define LLVM_LIBC_SRC_STDFIX_UHKSQRTUS_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +unsigned short accum uhksqrtus(unsigned short x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_UHKSQRTUS_H diff --git a/libc/src/stdfix/uksqrtui.cpp b/libc/src/stdfix/uksqrtui.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee1ae1335027a2f49f3fe27c2c3421605f6f7e6f --- /dev/null +++ b/libc/src/stdfix/uksqrtui.cpp @@ -0,0 +1,23 @@ +//===-- Implementation of uksqrtui function -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "uksqrtui.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/sqrt.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned accum, uksqrtui, (unsigned int x)) { +#ifdef LIBC_FAST_MATH + return fixed_point::isqrt_fast(x); +#else + return fixed_point::isqrt(x); +#endif +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/uksqrtui.h b/libc/src/stdfix/uksqrtui.h new file mode 100644 index 0000000000000000000000000000000000000000..cd4ff41ea100a76d06e209d8cd4010ec0909a256 --- /dev/null +++ b/libc/src/stdfix/uksqrtui.h @@ -0,0 +1,20 @@ +//===-- Implementation header for uksqrtui ----------------------*- 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_STDFIX_UKSQRTUI_H +#define LLVM_LIBC_SRC_STDFIX_UKSQRTUI_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +unsigned accum uksqrtui(unsigned int x); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_UKSQRTUI_H diff --git a/libc/src/stdio/printf_core/float_dec_converter.h b/libc/src/stdio/printf_core/float_dec_converter.h index a6c68329e660238bfe6f5b173ba889908485afdc..5270fc9de037acee2f17d2804ba3e41862c6a60b 100644 --- a/libc/src/stdio/printf_core/float_dec_converter.h +++ b/libc/src/stdio/printf_core/float_dec_converter.h @@ -12,6 +12,7 @@ #include "src/__support/CPP/string_view.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/rounding_mode.h" +#include "src/__support/UInt.h" // is_big_int_v #include "src/__support/float_to_string.h" #include "src/__support/integer_to_string.h" #include "src/__support/libc_assert.h" @@ -33,7 +34,8 @@ using ExponentString = // Returns true if value is divisible by 2^p. template -LIBC_INLINE constexpr cpp::enable_if_t, bool> +LIBC_INLINE constexpr cpp::enable_if_t || is_big_int_v, + bool> multiple_of_power_of_2(T value, uint32_t p) { return (value & ((T(1) << p) - 1)) == 0; } @@ -76,7 +78,8 @@ LIBC_INLINE RoundDirection get_round_direction(int last_digit, bool truncated, } template -LIBC_INLINE constexpr cpp::enable_if_t, bool> +LIBC_INLINE constexpr cpp::enable_if_t || is_big_int_v, + bool> zero_after_digits(int32_t base_2_exp, int32_t digits_after_point, T mantissa, const int32_t mant_width) { const int32_t required_twos = -base_2_exp - digits_after_point - 1; diff --git a/libc/src/stdlib/gpu/CMakeLists.txt b/libc/src/stdlib/gpu/CMakeLists.txt index 71ae10648d004e57f329890aceb7b5ccba5159f1..f8a11ec3ffb0027354c617044970cde7b137a5ee 100644 --- a/libc/src/stdlib/gpu/CMakeLists.txt +++ b/libc/src/stdlib/gpu/CMakeLists.txt @@ -6,7 +6,7 @@ add_entrypoint_object( ../malloc.h DEPENDS libc.include.stdlib - libc.src.__support.RPC.rpc_client + libc.src.__support.GPU.allocator ) add_entrypoint_object( @@ -28,5 +28,5 @@ add_entrypoint_object( ../abort.h DEPENDS libc.include.stdlib - libc.src.__support.RPC.rpc_client + libc.src.__support.GPU.allocator ) diff --git a/libc/src/stdlib/gpu/free.cpp b/libc/src/stdlib/gpu/free.cpp index 3a41e5febad0bba53c60bea3e635c9272b03ab4c..fb5703b78ae6c9a71bbfb35b2ecb1279604a3949 100644 --- a/libc/src/stdlib/gpu/free.cpp +++ b/libc/src/stdlib/gpu/free.cpp @@ -7,17 +7,12 @@ //===----------------------------------------------------------------------===// #include "src/stdlib/free.h" -#include "src/__support/RPC/rpc_client.h" + +#include "src/__support/GPU/allocator.h" #include "src/__support/common.h" namespace LIBC_NAMESPACE { -LLVM_LIBC_FUNCTION(void, free, (void *ptr)) { - rpc::Client::Port port = rpc::client.open(); - port.send([=](rpc::Buffer *buffer) { - buffer->data[0] = reinterpret_cast(ptr); - }); - port.close(); -} +LLVM_LIBC_FUNCTION(void, free, (void *ptr)) { gpu::deallocate(ptr); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/stdlib/gpu/malloc.cpp b/libc/src/stdlib/gpu/malloc.cpp index a219690783051339447284005d0d65cd546bd9c7..93558231d0811e1508e79258b540b39ba0229032 100644 --- a/libc/src/stdlib/gpu/malloc.cpp +++ b/libc/src/stdlib/gpu/malloc.cpp @@ -7,20 +7,14 @@ //===----------------------------------------------------------------------===// #include "src/stdlib/malloc.h" -#include "src/__support/RPC/rpc_client.h" + +#include "src/__support/GPU/allocator.h" #include "src/__support/common.h" namespace LIBC_NAMESPACE { LLVM_LIBC_FUNCTION(void *, malloc, (size_t size)) { - void *ptr = nullptr; - rpc::Client::Port port = rpc::client.open(); - port.send_and_recv([=](rpc::Buffer *buffer) { buffer->data[0] = size; }, - [&](rpc::Buffer *buffer) { - ptr = reinterpret_cast(buffer->data[0]); - }); - port.close(); - return ptr; + return gpu::allocate(size); } } // namespace LIBC_NAMESPACE diff --git a/libc/src/string/CMakeLists.txt b/libc/src/string/CMakeLists.txt index 1c893280e8a3c2dddc040e42fa5803fee1dfae68..56588ffafb86f01f0784082da6ece4db2c5f2f65 100644 --- a/libc/src/string/CMakeLists.txt +++ b/libc/src/string/CMakeLists.txt @@ -441,6 +441,17 @@ add_entrypoint_object( .memory_utils.inline_memcpy ) +add_entrypoint_object( + memset_explicit + SRCS + memset_explicit.cpp + HDRS + memset_explicit.h + DEPENDS + .string_utils + .memory_utils.inline_memset +) + # Helper to define a function with multiple implementations # - Computes flags to satisfy required/rejected features and arch, # - Declares an entry point, diff --git a/libc/src/string/memory_utils/op_generic.h b/libc/src/string/memory_utils/op_generic.h index c7dbd5dd1d6cceb91c92d29f0ee212b33b9c33d0..efaff80b7e4da02eeec9f262ecd019b51c06b48e 100644 --- a/libc/src/string/memory_utils/op_generic.h +++ b/libc/src/string/memory_utils/op_generic.h @@ -28,6 +28,7 @@ #include "src/__support/common.h" #include "src/__support/endian.h" #include "src/__support/macros/optimization.h" +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT64 #include "src/string/memory_utils/op_builtin.h" #include "src/string/memory_utils/utils.h" @@ -37,10 +38,6 @@ static_assert((UINTPTR_MAX == 4294967295U) || (UINTPTR_MAX == 18446744073709551615UL), "We currently only support 32- or 64-bit platforms"); -#if defined(UINT64_MAX) -#define LLVM_LIBC_HAS_UINT64 -#endif - namespace LIBC_NAMESPACE { // Compiler types using the vector attributes. using generic_v128 = uint8_t __attribute__((__vector_size__(16))); @@ -60,31 +57,44 @@ template struct is_scalar : cpp::false_type {}; template <> struct is_scalar : cpp::true_type {}; template <> struct is_scalar : cpp::true_type {}; template <> struct is_scalar : cpp::true_type {}; -#ifdef LLVM_LIBC_HAS_UINT64 +#ifdef LIBC_TYPES_HAS_INT64 template <> struct is_scalar : cpp::true_type {}; -#endif // LLVM_LIBC_HAS_UINT64 +#endif // LIBC_TYPES_HAS_INT64 +// Meant to match std::numeric_limits interface. +// NOLINTNEXTLINE(readability-identifier-naming) template constexpr bool is_scalar_v = is_scalar::value; template struct is_vector : cpp::false_type {}; template <> struct is_vector : cpp::true_type {}; template <> struct is_vector : cpp::true_type {}; template <> struct is_vector : cpp::true_type {}; +// Meant to match std::numeric_limits interface. +// NOLINTNEXTLINE(readability-identifier-naming) template constexpr bool is_vector_v = is_vector::value; template struct is_array : cpp::false_type {}; template struct is_array> { + // Meant to match std::numeric_limits interface. + // NOLINTNEXTLINE(readability-identifier-naming) static constexpr bool value = is_scalar_v || is_vector_v; }; +// Meant to match std::numeric_limits interface. +// NOLINTNEXTLINE(readability-identifier-naming) template constexpr bool is_array_v = is_array::value; +// Meant to match std::numeric_limits interface. +// NOLINTBEGIN(readability-identifier-naming) template constexpr bool is_element_type_v = is_scalar_v || is_vector_v || is_array_v; +// NOLINTEND(readability-identifier-naming) // Helper struct to retrieve the number of elements of an array. template struct array_size {}; template struct array_size> : cpp::integral_constant {}; +// Meant to match std::numeric_limits interface. +// NOLINTNEXTLINE(readability-identifier-naming) template constexpr size_t array_size_v = array_size::value; // Generic operations for the above type categories. @@ -95,10 +105,10 @@ template T load(CPtr src) { return ::LIBC_NAMESPACE::load(src); } else if constexpr (is_array_v) { using value_type = typename T::value_type; - T Value; - for (size_t I = 0; I < array_size_v; ++I) - Value[I] = load(src + (I * sizeof(value_type))); - return Value; + T value; + for (size_t i = 0; i < array_size_v; ++i) + value[i] = load(src + (i * sizeof(value_type))); + return value; } } @@ -108,8 +118,8 @@ template void store(Ptr dst, T value) { ::LIBC_NAMESPACE::store(dst, value); } else if constexpr (is_array_v) { using value_type = typename T::value_type; - for (size_t I = 0; I < array_size_v; ++I) - store(dst + (I * sizeof(value_type)), value[I]); + for (size_t i = 0; i < array_size_v; ++i) + store(dst + (i * sizeof(value_type)), value[i]); } } @@ -118,11 +128,11 @@ template T splat(uint8_t value) { if constexpr (is_scalar_v) return T(~0) / T(0xFF) * T(value); else if constexpr (is_vector_v) { - T Out; + T out; // This for loop is optimized out for vector types. for (size_t i = 0; i < sizeof(T); ++i) - Out[i] = value; - return Out; + out[i] = value; + return out; } } @@ -140,8 +150,8 @@ template struct Memset { } else if constexpr (is_array_v) { using value_type = typename T::value_type; const auto Splat = splat(value); - for (size_t I = 0; I < array_size_v; ++I) - store(dst + (I * sizeof(value_type)), Splat); + for (size_t i = 0; i < array_size_v; ++i) + store(dst + (i * sizeof(value_type)), Splat); } } @@ -453,7 +463,7 @@ public: if (LIBC_UNLIKELY(count >= threshold) && helper.not_aligned()) { if (auto value = block(p1, p2)) return value; - adjust(helper.offset(), p1, p2, count); + adjust(helper.offset, p1, p2, count); } return loop_and_tail(p1, p2, count); } @@ -533,7 +543,7 @@ template struct Bcmp { if (LIBC_UNLIKELY(count >= threshold) && helper.not_aligned()) { if (auto value = block(p1, p2)) return value; - adjust(helper.offset(), p1, p2, count); + adjust(helper.offset, p1, p2, count); } return loop_and_tail(p1, p2, count); } diff --git a/libc/src/string/memory_utils/op_x86.h b/libc/src/string/memory_utils/op_x86.h index 2852636c48a74d12fc2bc8ced56470972b262984..1afa91f20e6591670354ce9f5f43e910e2600425 100644 --- a/libc/src/string/memory_utils/op_x86.h +++ b/libc/src/string/memory_utils/op_x86.h @@ -40,12 +40,12 @@ namespace LIBC_NAMESPACE::x86 { // A set of constants to check compile time features. -LIBC_INLINE_VAR constexpr bool kSse2 = LLVM_LIBC_IS_DEFINED(__SSE2__); -LIBC_INLINE_VAR constexpr bool kSse41 = LLVM_LIBC_IS_DEFINED(__SSE4_1__); -LIBC_INLINE_VAR constexpr bool kAvx = LLVM_LIBC_IS_DEFINED(__AVX__); -LIBC_INLINE_VAR constexpr bool kAvx2 = LLVM_LIBC_IS_DEFINED(__AVX2__); -LIBC_INLINE_VAR constexpr bool kAvx512F = LLVM_LIBC_IS_DEFINED(__AVX512F__); -LIBC_INLINE_VAR constexpr bool kAvx512BW = LLVM_LIBC_IS_DEFINED(__AVX512BW__); +LIBC_INLINE_VAR constexpr bool K_SSE2 = LLVM_LIBC_IS_DEFINED(__SSE2__); +LIBC_INLINE_VAR constexpr bool K_SSE41 = LLVM_LIBC_IS_DEFINED(__SSE4_1__); +LIBC_INLINE_VAR constexpr bool K_AVX = LLVM_LIBC_IS_DEFINED(__AVX__); +LIBC_INLINE_VAR constexpr bool K_AVX2 = LLVM_LIBC_IS_DEFINED(__AVX2__); +LIBC_INLINE_VAR constexpr bool K_AVX512_F = LLVM_LIBC_IS_DEFINED(__AVX512F__); +LIBC_INLINE_VAR constexpr bool K_AVX512_BW = LLVM_LIBC_IS_DEFINED(__AVX512BW__); /////////////////////////////////////////////////////////////////////////////// // Memcpy repmovsb implementation diff --git a/libc/src/string/memory_utils/utils.h b/libc/src/string/memory_utils/utils.h index 701a84375ea8e7923a810b01645bb4594587761f..79526d19c6b3dc10f6cd2fcfaad87a359702344a 100644 --- a/libc/src/string/memory_utils/utils.h +++ b/libc/src/string/memory_utils/utils.h @@ -205,9 +205,9 @@ LIBC_INLINE MemcmpReturnType cmp_neq_uint64_t(uint64_t a, uint64_t b) { // Loads bytes from memory (possibly unaligned) and materializes them as // type. template LIBC_INLINE T load(CPtr ptr) { - T Out; - memcpy_inline(&Out, ptr); - return Out; + T out; + memcpy_inline(&out, ptr); + return out; } // Stores a value of type T in memory (possibly unaligned). @@ -228,12 +228,12 @@ LIBC_INLINE ValueType load_aligned(CPtr src) { static_assert(sizeof(ValueType) >= (sizeof(T) + ... + sizeof(TS))); const ValueType value = load(assume_aligned(src)); if constexpr (sizeof...(TS) > 0) { - constexpr size_t shift = sizeof(T) * 8; + constexpr size_t SHIFT = sizeof(T) * 8; const ValueType next = load_aligned(src + sizeof(T)); if constexpr (Endian::IS_LITTLE) - return value | (next << shift); + return value | (next << SHIFT); else if constexpr (Endian::IS_BIG) - return (value << shift) | next; + return (value << SHIFT) | next; else static_assert(cpp::always_false, "Invalid endianness"); } else { @@ -261,16 +261,16 @@ LIBC_INLINE auto load64_aligned(CPtr src, size_t offset) { template LIBC_INLINE void store_aligned(ValueType value, Ptr dst) { static_assert(sizeof(ValueType) >= (sizeof(T) + ... + sizeof(TS))); - constexpr size_t shift = sizeof(T) * 8; + constexpr size_t SHIFT = sizeof(T) * 8; if constexpr (Endian::IS_LITTLE) { store(assume_aligned(dst), value & ~T(0)); if constexpr (sizeof...(TS) > 0) - store_aligned(value >> shift, dst + sizeof(T)); + store_aligned(value >> SHIFT, dst + sizeof(T)); } else if constexpr (Endian::IS_BIG) { constexpr size_t OFFSET = (0 + ... + sizeof(TS)); store(assume_aligned(dst + OFFSET), value & ~T(0)); if constexpr (sizeof...(TS) > 0) - store_aligned(value >> shift, dst); + store_aligned(value >> SHIFT, dst); } else { static_assert(cpp::always_false, "Invalid endianness"); } @@ -336,13 +336,10 @@ LIBC_INLINE void align_to_next_boundary(T1 *__restrict &p1, T2 *__restrict &p2, template struct AlignHelper { LIBC_INLINE AlignHelper(CPtr ptr) - : offset_(distance_to_next_aligned(ptr)) {} + : offset(distance_to_next_aligned(ptr)) {} - LIBC_INLINE bool not_aligned() const { return offset_ != SIZE; } - LIBC_INLINE uintptr_t offset() const { return offset_; } - -private: - uintptr_t offset_; + LIBC_INLINE bool not_aligned() const { return offset != SIZE; } + uintptr_t offset; }; LIBC_INLINE void prefetch_for_write(CPtr dst) { diff --git a/libc/src/string/memory_utils/x86_64/inline_memcpy.h b/libc/src/string/memory_utils/x86_64/inline_memcpy.h index dd09d4f3e812b0c279190853ecb1ce5e997a3962..ae61b1235bd08c588aaae9154e1fe18e209358dd 100644 --- a/libc/src/string/memory_utils/x86_64/inline_memcpy.h +++ b/libc/src/string/memory_utils/x86_64/inline_memcpy.h @@ -30,11 +30,11 @@ namespace LIBC_NAMESPACE { namespace x86 { -LIBC_INLINE_VAR constexpr size_t kOneCacheline = 64; -LIBC_INLINE_VAR constexpr size_t kTwoCachelines = 2 * kOneCacheline; -LIBC_INLINE_VAR constexpr size_t kThreeCachelines = 3 * kOneCacheline; +LIBC_INLINE_VAR constexpr size_t K_ONE_CACHELINE = 64; +LIBC_INLINE_VAR constexpr size_t K_TWO_CACHELINES = 2 * K_ONE_CACHELINE; +LIBC_INLINE_VAR constexpr size_t K_THREE_CACHELINES = 3 * K_ONE_CACHELINE; -LIBC_INLINE_VAR constexpr bool kUseSoftwarePrefetching = +LIBC_INLINE_VAR constexpr bool K_USE_SOFTWARE_PREFETCHING = LLVM_LIBC_IS_DEFINED(LIBC_COPT_MEMCPY_X86_USE_SOFTWARE_PREFETCHING); // Whether to use rep;movsb exclusively (0), not at all (SIZE_MAX), or only @@ -42,7 +42,7 @@ LIBC_INLINE_VAR constexpr bool kUseSoftwarePrefetching = #ifndef LIBC_COPT_MEMCPY_X86_USE_REPMOVSB_FROM_SIZE #define LIBC_COPT_MEMCPY_X86_USE_REPMOVSB_FROM_SIZE SIZE_MAX #endif -LIBC_INLINE_VAR constexpr size_t kRepMovsbThreshold = +LIBC_INLINE_VAR constexpr size_t K_REP_MOVSB_THRESHOLD = LIBC_COPT_MEMCPY_X86_USE_REPMOVSB_FROM_SIZE; } // namespace x86 @@ -73,10 +73,10 @@ inline_memcpy_x86_avx_ge64(Ptr __restrict dst, CPtr __restrict src, inline_memcpy_x86_sse2_ge64_sw_prefetching(Ptr __restrict dst, CPtr __restrict src, size_t count) { using namespace LIBC_NAMESPACE::x86; - prefetch_to_local_cache(src + kOneCacheline); + prefetch_to_local_cache(src + K_ONE_CACHELINE); if (count <= 128) return builtin::Memcpy<64>::head_tail(dst, src, count); - prefetch_to_local_cache(src + kTwoCachelines); + prefetch_to_local_cache(src + K_TWO_CACHELINES); // Aligning 'dst' on a 32B boundary. builtin::Memcpy<32>::block(dst, src); align_to_next_boundary<32, Arg::Dst>(dst, src, count); @@ -89,22 +89,22 @@ inline_memcpy_x86_sse2_ge64_sw_prefetching(Ptr __restrict dst, // - count >= 128. if (count < 352) { // Two cache lines at a time. - while (offset + kTwoCachelines + 32 <= count) { - prefetch_to_local_cache(src + offset + kOneCacheline); - prefetch_to_local_cache(src + offset + kTwoCachelines); - builtin::Memcpy::block_offset(dst, src, offset); - offset += kTwoCachelines; + while (offset + K_TWO_CACHELINES + 32 <= count) { + prefetch_to_local_cache(src + offset + K_ONE_CACHELINE); + prefetch_to_local_cache(src + offset + K_TWO_CACHELINES); + builtin::Memcpy::block_offset(dst, src, offset); + offset += K_TWO_CACHELINES; } } else { // Three cache lines at a time. - while (offset + kThreeCachelines + 32 <= count) { - prefetch_to_local_cache(src + offset + kOneCacheline); - prefetch_to_local_cache(src + offset + kTwoCachelines); - prefetch_to_local_cache(src + offset + kThreeCachelines); + while (offset + K_THREE_CACHELINES + 32 <= count) { + prefetch_to_local_cache(src + offset + K_ONE_CACHELINE); + prefetch_to_local_cache(src + offset + K_TWO_CACHELINES); + prefetch_to_local_cache(src + offset + K_THREE_CACHELINES); // It is likely that this copy will be turned into a 'rep;movsb' on // non-AVX machines. - builtin::Memcpy::block_offset(dst, src, offset); - offset += kThreeCachelines; + builtin::Memcpy::block_offset(dst, src, offset); + offset += K_THREE_CACHELINES; } } return builtin::Memcpy<32>::loop_and_tail_offset(dst, src, count, offset); @@ -114,11 +114,11 @@ inline_memcpy_x86_sse2_ge64_sw_prefetching(Ptr __restrict dst, inline_memcpy_x86_avx_ge64_sw_prefetching(Ptr __restrict dst, CPtr __restrict src, size_t count) { using namespace LIBC_NAMESPACE::x86; - prefetch_to_local_cache(src + kOneCacheline); + prefetch_to_local_cache(src + K_ONE_CACHELINE); if (count <= 128) return builtin::Memcpy<64>::head_tail(dst, src, count); - prefetch_to_local_cache(src + kTwoCachelines); - prefetch_to_local_cache(src + kThreeCachelines); + prefetch_to_local_cache(src + K_TWO_CACHELINES); + prefetch_to_local_cache(src + K_THREE_CACHELINES); if (count < 256) return builtin::Memcpy<128>::head_tail(dst, src, count); // Aligning 'dst' on a 32B boundary. @@ -131,13 +131,13 @@ inline_memcpy_x86_avx_ge64_sw_prefetching(Ptr __restrict dst, // - we prefetched cachelines at 'src + 64', 'src + 128', and 'src + 196' // - 'dst' is 32B aligned, // - count >= 128. - while (offset + kThreeCachelines + 64 <= count) { + while (offset + K_THREE_CACHELINES + 64 <= count) { // Three cache lines at a time. - prefetch_to_local_cache(src + offset + kOneCacheline); - prefetch_to_local_cache(src + offset + kTwoCachelines); - prefetch_to_local_cache(src + offset + kThreeCachelines); - builtin::Memcpy::block_offset(dst, src, offset); - offset += kThreeCachelines; + prefetch_to_local_cache(src + offset + K_ONE_CACHELINE); + prefetch_to_local_cache(src + offset + K_TWO_CACHELINES); + prefetch_to_local_cache(src + offset + K_THREE_CACHELINES); + builtin::Memcpy::block_offset(dst, src, offset); + offset += K_THREE_CACHELINES; } return builtin::Memcpy<64>::loop_and_tail_offset(dst, src, count, offset); } @@ -145,13 +145,13 @@ inline_memcpy_x86_avx_ge64_sw_prefetching(Ptr __restrict dst, [[maybe_unused]] LIBC_INLINE void inline_memcpy_x86(Ptr __restrict dst, CPtr __restrict src, size_t count) { #if defined(__AVX512F__) - constexpr size_t vector_size = 64; + constexpr size_t VECTOR_SIZE = 64; #elif defined(__AVX__) - constexpr size_t vector_size = 32; + constexpr size_t VECTOR_SIZE = 32; #elif defined(__SSE2__) - constexpr size_t vector_size = 16; + constexpr size_t VECTOR_SIZE = 16; #else - constexpr size_t vector_size = 8; + constexpr size_t VECTOR_SIZE = 8; #endif if (count == 0) return; @@ -174,20 +174,20 @@ inline_memcpy_x86(Ptr __restrict dst, CPtr __restrict src, size_t count) { // But it's not profitable to use larger size if it's not natively // supported: we will both use more instructions and handle fewer // sizes in earlier branches. - if (vector_size >= 16 ? count < 16 : count <= 16) + if (VECTOR_SIZE >= 16 ? count < 16 : count <= 16) return builtin::Memcpy<8>::head_tail(dst, src, count); - if (vector_size >= 32 ? count < 32 : count <= 32) + if (VECTOR_SIZE >= 32 ? count < 32 : count <= 32) return builtin::Memcpy<16>::head_tail(dst, src, count); - if (vector_size >= 64 ? count < 64 : count <= 64) + if (VECTOR_SIZE >= 64 ? count < 64 : count <= 64) return builtin::Memcpy<32>::head_tail(dst, src, count); - if constexpr (x86::kAvx) { - if constexpr (x86::kUseSoftwarePrefetching) { + if constexpr (x86::K_AVX) { + if constexpr (x86::K_USE_SOFTWARE_PREFETCHING) { return inline_memcpy_x86_avx_ge64_sw_prefetching(dst, src, count); } else { return inline_memcpy_x86_avx_ge64(dst, src, count); } } else { - if constexpr (x86::kUseSoftwarePrefetching) { + if constexpr (x86::K_USE_SOFTWARE_PREFETCHING) { return inline_memcpy_x86_sse2_ge64_sw_prefetching(dst, src, count); } else { return inline_memcpy_x86_sse2_ge64(dst, src, count); @@ -198,12 +198,12 @@ inline_memcpy_x86(Ptr __restrict dst, CPtr __restrict src, size_t count) { [[maybe_unused]] LIBC_INLINE void inline_memcpy_x86_maybe_interpose_repmovsb(Ptr __restrict dst, CPtr __restrict src, size_t count) { - if constexpr (x86::kRepMovsbThreshold == 0) { + if constexpr (x86::K_REP_MOVSB_THRESHOLD == 0) { return x86::Memcpy::repmovsb(dst, src, count); - } else if constexpr (x86::kRepMovsbThreshold == SIZE_MAX) { + } else if constexpr (x86::K_REP_MOVSB_THRESHOLD == SIZE_MAX) { return inline_memcpy_x86(dst, src, count); } else { - if (LIBC_UNLIKELY(count >= x86::kRepMovsbThreshold)) + if (LIBC_UNLIKELY(count >= x86::K_REP_MOVSB_THRESHOLD)) return x86::Memcpy::repmovsb(dst, src, count); else return inline_memcpy_x86(dst, src, count); diff --git a/libc/src/string/memory_utils/x86_64/inline_memset.h b/libc/src/string/memory_utils/x86_64/inline_memset.h index 41eadf2dcc00cc14cbd8003256d9b8b238db9f00..584efcbea4be37d7de868ccb7ba277a3833595cb 100644 --- a/libc/src/string/memory_utils/x86_64/inline_memset.h +++ b/libc/src/string/memory_utils/x86_64/inline_memset.h @@ -18,11 +18,13 @@ namespace LIBC_NAMESPACE { namespace x86 { // Size of one cache line for software prefetching -LIBC_INLINE_VAR constexpr size_t kOneCachelineSize = 64; -LIBC_INLINE_VAR constexpr size_t kTwoCachelinesSize = kOneCachelineSize * 2; -LIBC_INLINE_VAR constexpr size_t kFiveCachelinesSize = kOneCachelineSize * 5; +LIBC_INLINE_VAR constexpr size_t K_ONE_CACHELINE_SIZE = 64; +LIBC_INLINE_VAR constexpr size_t K_TWO_CACHELINES_SIZE = + K_ONE_CACHELINE_SIZE * 2; +LIBC_INLINE_VAR constexpr size_t K_FIVE_CACHELINES_SIZE = + K_ONE_CACHELINE_SIZE * 5; -LIBC_INLINE_VAR constexpr bool kUseSoftwarePrefetchingMemset = +LIBC_INLINE_VAR constexpr bool K_USE_SOFTWARE_PREFETCHING_MEMSET = LLVM_LIBC_IS_DEFINED(LIBC_COPT_MEMSET_X86_USE_SOFTWARE_PREFETCHING); } // namespace x86 @@ -47,15 +49,15 @@ using uint512_t = cpp::array; [[maybe_unused]] LIBC_INLINE static void inline_memset_x86_gt64_sw_prefetching(Ptr dst, uint8_t value, size_t count) { - constexpr size_t PREFETCH_DISTANCE = x86::kFiveCachelinesSize; - constexpr size_t PREFETCH_DEGREE = x86::kTwoCachelinesSize; + constexpr size_t PREFETCH_DISTANCE = x86::K_FIVE_CACHELINES_SIZE; + constexpr size_t PREFETCH_DEGREE = x86::K_TWO_CACHELINES_SIZE; constexpr size_t SIZE = sizeof(uint256_t); // Prefetch one cache line - prefetch_for_write(dst + x86::kOneCachelineSize); + prefetch_for_write(dst + x86::K_ONE_CACHELINE_SIZE); if (count <= 128) return generic::Memset::head_tail(dst, value, count); // Prefetch the second cache line - prefetch_for_write(dst + x86::kTwoCachelinesSize); + prefetch_for_write(dst + x86::K_TWO_CACHELINES_SIZE); // Aligned loop generic::Memset::block(dst, value); align_to_next_boundary<32>(dst, count); @@ -67,7 +69,7 @@ inline_memset_x86_gt64_sw_prefetching(Ptr dst, uint8_t value, size_t count) { while (offset + PREFETCH_DEGREE + SIZE <= count) { prefetch_for_write(dst + offset + PREFETCH_DISTANCE); prefetch_for_write(dst + offset + PREFETCH_DISTANCE + - x86::kOneCachelineSize); + x86::K_ONE_CACHELINE_SIZE); for (size_t i = 0; i < PREFETCH_DEGREE; i += SIZE, offset += SIZE) generic::Memset::block(dst + offset, value); } @@ -93,7 +95,7 @@ inline_memset_x86(Ptr dst, uint8_t value, size_t count) { return generic::Memset::head_tail(dst, value, count); if (count <= 64) return generic::Memset::head_tail(dst, value, count); - if constexpr (x86::kUseSoftwarePrefetchingMemset) + if constexpr (x86::K_USE_SOFTWARE_PREFETCHING_MEMSET) return inline_memset_x86_gt64_sw_prefetching(dst, value, count); if (count <= 128) return generic::Memset::head_tail(dst, value, count); diff --git a/libc/src/string/memset_explicit.cpp b/libc/src/string/memset_explicit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a8656d1e791e846f1ac24ad0ee5c1a95b6b238df --- /dev/null +++ b/libc/src/string/memset_explicit.cpp @@ -0,0 +1,25 @@ +//===-- Implementation of memset_explicit ---------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/string/memset_explicit.h" +#include "src/__support/common.h" +#include "src/string/memory_utils/inline_memset.h" + +namespace LIBC_NAMESPACE { + +[[gnu::noinline]] LLVM_LIBC_FUNCTION(void *, memset_explicit, + (void *dst, int value, size_t count)) { + // Use the inline memset function to set the memory. + inline_memset(dst, static_cast(value), count); + // avoid dead store elimination + // The asm itself should also be sufficient to behave as a compiler barrier. + asm("" : : "r"(dst) : "memory"); + return dst; +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/string/memset_explicit.h b/libc/src/string/memset_explicit.h new file mode 100644 index 0000000000000000000000000000000000000000..f6c189761a123cd84a50384c597777d090ceca5a --- /dev/null +++ b/libc/src/string/memset_explicit.h @@ -0,0 +1,20 @@ +//===-- Implementation header for memset_explicit ---------------*- 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_STRING_MEMSET_EXPLICIT_H +#define LLVM_LIBC_SRC_STRING_MEMSET_EXPLICIT_H + +#include // size_t + +namespace LIBC_NAMESPACE { + +[[gnu::noinline]] void *memset_explicit(void *ptr, int value, size_t count); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STRING_MEMSET_EXPLICIT_H diff --git a/libc/src/sys/mman/CMakeLists.txt b/libc/src/sys/mman/CMakeLists.txt index f11f5ac9df9f2fd9081fdd7ba1686128f01a5a76..b49f73873c2006e2bfb32a6ad22088be5f0df8c2 100644 --- a/libc/src/sys/mman/CMakeLists.txt +++ b/libc/src/sys/mman/CMakeLists.txt @@ -78,3 +78,10 @@ add_entrypoint_object( DEPENDS .${LIBC_TARGET_OS}.munlockall ) + +add_entrypoint_object( + msync + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.msync +) diff --git a/libc/src/sys/mman/linux/CMakeLists.txt b/libc/src/sys/mman/linux/CMakeLists.txt index a6feff1f0bec199b41074a289e6fb71c3d025f4c..04086ee5d332548b7272ef3cbc438011389a6307 100644 --- a/libc/src/sys/mman/linux/CMakeLists.txt +++ b/libc/src/sys/mman/linux/CMakeLists.txt @@ -139,3 +139,16 @@ add_entrypoint_object( libc.src.__support.OSUtil.osutil libc.src.errno.errno ) + +add_entrypoint_object( + msync + SRCS + msync.cpp + HDRS + ../msync.h + DEPENDS + libc.include.sys_mman + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) diff --git a/libc/src/sys/mman/linux/msync.cpp b/libc/src/sys/mman/linux/msync.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d2544f023c2c0d99b1945c77cede254267a7abe --- /dev/null +++ b/libc/src/sys/mman/linux/msync.cpp @@ -0,0 +1,25 @@ +//===---------- Linux implementation of the msync function ----------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/sys/mman/msync.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. + +#include "src/errno/libc_errno.h" +#include // For syscall numbers. + +namespace LIBC_NAMESPACE { +LLVM_LIBC_FUNCTION(int, msync, (void *addr, size_t len, int flags)) { + long ret = syscall_impl(SYS_msync, cpp::bit_cast(addr), len, flags); + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + return 0; +} +} // namespace LIBC_NAMESPACE diff --git a/libc/src/sys/mman/msync.h b/libc/src/sys/mman/msync.h new file mode 100644 index 0000000000000000000000000000000000000000..08afdd8c06285754bd8c4b0493739114b01d5bb0 --- /dev/null +++ b/libc/src/sys/mman/msync.h @@ -0,0 +1,21 @@ +//===-- Implementation header for msync function ----------------*- 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_SYS_MMAN_MSYNC_H +#define LLVM_LIBC_SRC_SYS_MMAN_MSYNC_H + +#include +#include + +namespace LIBC_NAMESPACE { + +int msync(void *addr, size_t len, int flags); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_SYS_MMAN_MSYNC_H diff --git a/libc/test/UnitTest/CMakeLists.txt b/libc/test/UnitTest/CMakeLists.txt index 4668f0061975f852f2e8bc259f90b5b4f1e087b9..f7a6f4a91fabcf41bdf4b7ec3d7418638ad13780 100644 --- a/libc/test/UnitTest/CMakeLists.txt +++ b/libc/test/UnitTest/CMakeLists.txt @@ -73,7 +73,9 @@ add_unittest_framework_library( libc.src.__support.CPP.string_view libc.src.__support.CPP.type_traits libc.src.__support.fixed_point.fx_rep + libc.src.__support.macros.properties.types libc.src.__support.OSUtil.osutil + libc.src.__support.uint libc.src.__support.uint128 ) @@ -103,6 +105,7 @@ add_header_library( DEPENDS libc.src.__support.CPP.string libc.src.__support.CPP.type_traits + libc.src.__support.uint ) add_unittest_framework_library( diff --git a/libc/test/UnitTest/LibcTest.cpp b/libc/test/UnitTest/LibcTest.cpp index 7b0e4fca83683b93528b19c5f90fe5ed05353360..03cd25191ecd5c473ce477a2b87af1a6ea40bd92 100644 --- a/libc/test/UnitTest/LibcTest.cpp +++ b/libc/test/UnitTest/LibcTest.cpp @@ -13,6 +13,7 @@ #include "src/__support/CPP/string_view.h" #include "src/__support/UInt128.h" #include "src/__support/fixed_point/fx_rep.h" +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 #include "test/UnitTest/TestLogger.h" #if __STDC_HOSTED__ @@ -38,7 +39,8 @@ TestLogger &operator<<(TestLogger &logger, Location Loc) { // When the value is UInt128, __uint128_t or wider, show its hexadecimal // digits. template -cpp::enable_if_t && (sizeof(T) > sizeof(uint64_t)), +cpp::enable_if_t<(cpp::is_integral_v && (sizeof(T) > sizeof(uint64_t))) || + is_big_int_v, cpp::string> describeValue(T Value) { static_assert(sizeof(T) % 8 == 0, "Unsupported size of UInt"); @@ -47,11 +49,10 @@ describeValue(T Value) { } // When the value is of a standard integral type, just display it as normal. -template -cpp::enable_if_t && - sizeof(ValType) <= sizeof(uint64_t), +template +cpp::enable_if_t && (sizeof(T) <= sizeof(uint64_t)), cpp::string> -describeValue(ValType Value) { +describeValue(T Value) { return cpp::to_string(Value); } @@ -215,18 +216,18 @@ TEST_SPECIALIZATION(bool); // We cannot just use a single UInt128 specialization as that resolves to only // one type, UInt<128> or __uint128_t. We want both overloads as we want to -#ifdef __SIZEOF_INT128__ +#ifdef LIBC_TYPES_HAS_INT128 // When builtin __uint128_t type is available, include its specialization // also. TEST_SPECIALIZATION(__uint128_t); -#endif +#endif // LIBC_TYPES_HAS_INT128 -TEST_SPECIALIZATION(LIBC_NAMESPACE::cpp::Int<128>); +TEST_SPECIALIZATION(LIBC_NAMESPACE::Int<128>); -TEST_SPECIALIZATION(LIBC_NAMESPACE::cpp::UInt<128>); -TEST_SPECIALIZATION(LIBC_NAMESPACE::cpp::UInt<192>); -TEST_SPECIALIZATION(LIBC_NAMESPACE::cpp::UInt<256>); -TEST_SPECIALIZATION(LIBC_NAMESPACE::cpp::UInt<320>); +TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<128>); +TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<192>); +TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<256>); +TEST_SPECIALIZATION(LIBC_NAMESPACE::UInt<320>); TEST_SPECIALIZATION(LIBC_NAMESPACE::cpp::string_view); TEST_SPECIALIZATION(LIBC_NAMESPACE::cpp::string); diff --git a/libc/test/UnitTest/LibcTest.h b/libc/test/UnitTest/LibcTest.h index 639f60058325760e303d8f922398be075bb17504..a813a59d2d67f38a7fb6e5806f636b1b4024c679 100644 --- a/libc/test/UnitTest/LibcTest.h +++ b/libc/test/UnitTest/LibcTest.h @@ -125,10 +125,11 @@ protected: // is the result of the |Cond| operation on |LHS| and |RHS|. Though not bad, // |Cond| on mismatched |LHS| and |RHS| types can potentially succeed because // of type promotion. - template || - cpp::is_fixed_point_v, - int> = 0> + template < + typename ValType, + cpp::enable_if_t || is_big_int_v || + cpp::is_fixed_point_v, + int> = 0> bool test(TestCond Cond, ValType LHS, ValType RHS, const char *LHSStr, const char *RHSStr, internal::Location Loc) { return internal::test(Ctx, Cond, LHS, RHS, LHSStr, RHSStr, Loc); diff --git a/libc/test/UnitTest/StringUtils.h b/libc/test/UnitTest/StringUtils.h index 54cff97ceafb4e668fd7145cb627a1659fb2c9a3..cab0b58f969058e90b27e2c690090c3dba63ee4d 100644 --- a/libc/test/UnitTest/StringUtils.h +++ b/libc/test/UnitTest/StringUtils.h @@ -11,12 +11,13 @@ #include "src/__support/CPP/string.h" #include "src/__support/CPP/type_traits.h" +#include "src/__support/UInt.h" namespace LIBC_NAMESPACE { // Return the first N hex digits of an integer as a string in upper case. template -cpp::enable_if_t, cpp::string> +cpp::enable_if_t || is_big_int_v, cpp::string> int_to_hex(T value, size_t length = sizeof(T) * 2) { cpp::string s(length, '0'); diff --git a/libc/test/UnitTest/TestLogger.cpp b/libc/test/UnitTest/TestLogger.cpp index 6bb0e17dc3888ef169d0f28e1cd71004c7835bef..4756188b46cb0b3831e3e0569c963b944e7397bd 100644 --- a/libc/test/UnitTest/TestLogger.cpp +++ b/libc/test/UnitTest/TestLogger.cpp @@ -2,7 +2,9 @@ #include "src/__support/CPP/string.h" #include "src/__support/CPP/string_view.h" #include "src/__support/OSUtil/io.h" // write_to_stderr +#include "src/__support/UInt.h" // is_big_int #include "src/__support/UInt128.h" +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 #include @@ -47,8 +49,9 @@ template <> TestLogger &TestLogger::operator<<(void *addr) { } template TestLogger &TestLogger::operator<<(T t) { - if constexpr (cpp::is_integral_v && cpp::is_unsigned_v && - sizeof(T) > sizeof(uint64_t)) { + if constexpr (is_big_int_v || + (cpp::is_integral_v && cpp::is_unsigned_v && + (sizeof(T) > sizeof(uint64_t)))) { static_assert(sizeof(T) % 8 == 0, "Unsupported size of UInt"); const IntegerToString buffer(t); return *this << buffer.view(); @@ -68,15 +71,15 @@ template TestLogger &TestLogger::operator<< (unsigned short); template TestLogger &TestLogger::operator<< (unsigned int); template TestLogger &TestLogger::operator<< (unsigned long); template TestLogger & -TestLogger::operator<< (unsigned long long); + TestLogger::operator<< (unsigned long long); -#ifdef __SIZEOF_INT128__ +#ifdef LIBC_TYPES_HAS_INT128 template TestLogger &TestLogger::operator<< <__uint128_t>(__uint128_t); -#endif -template TestLogger &TestLogger::operator<< >(cpp::UInt<128>); -template TestLogger &TestLogger::operator<< >(cpp::UInt<192>); -template TestLogger &TestLogger::operator<< >(cpp::UInt<256>); -template TestLogger &TestLogger::operator<< >(cpp::UInt<320>); +#endif // LIBC_TYPES_HAS_INT128 +template TestLogger &TestLogger::operator<< >(UInt<128>); +template TestLogger &TestLogger::operator<< >(UInt<192>); +template TestLogger &TestLogger::operator<< >(UInt<256>); +template TestLogger &TestLogger::operator<< >(UInt<320>); // TODO: Add floating point formatting once it's supported by StringStream. diff --git a/libc/test/include/CMakeLists.txt b/libc/test/include/CMakeLists.txt index bf845c94170f97f3a3dd0de2c85a2d08ddcb1e2d..8d8dff53169f6ac21cbcdf8ebdd88634d2f19538 100644 --- a/libc/test/include/CMakeLists.txt +++ b/libc/test/include/CMakeLists.txt @@ -22,16 +22,42 @@ if(LLVM_LIBC_FULL_BUILD AND libc.include.stdbit IN_LIST TARGET_PUBLIC_HEADERS) stdbit_test SUITE libc_include_tests + HDRS + stdbit_stub.h SRCS stdbit_test.cpp DEPENDS libc.include.llvm-libc-macros.stdbit_macros + libc.include.llvm_libc_common_h libc.include.stdbit # Intentionally do not depend on libc.src.stdbit.*. The include test is # simply testing the macros provided by stdbit.h, not the implementation # of the underlying functions which the type generic macros may dispatch # to. ) + add_libc_test( + stdbit_c_test + C_TEST + UNIT_TEST_ONLY + SUITE + libc_include_tests + HDRS + stdbit_stub.h + SRCS + stdbit_test.c + COMPILE_OPTIONS + -Wall + -Werror + DEPENDS + libc.include.llvm-libc-macros.stdbit_macros + libc.include.llvm_libc_common_h + libc.include.stdbit + libc.src.assert.__assert_fail + # Intentionally do not depend on libc.src.stdbit.*. The include test is + # simply testing the macros provided by stdbit.h, not the implementation + # of the underlying functions which the type generic macros may dispatch + # to. + ) endif() add_libc_test( diff --git a/libc/test/include/stdbit_stub.h b/libc/test/include/stdbit_stub.h new file mode 100644 index 0000000000000000000000000000000000000000..65b1ca3b2c29767d9ca17be76c9cae3da62b7eea --- /dev/null +++ b/libc/test/include/stdbit_stub.h @@ -0,0 +1,73 @@ +//===-- Utilities for testing stdbit --------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +/* + * Declare these BEFORE including stdbit-macros.h so that this test may still be + * run even if a given target doesn't yet have these individual entrypoints + * enabled. + */ + +#include "include/__llvm-libc-common.h" + +#include // bool in C + +#define STDBIT_STUB_FUNCTION(FUNC_NAME, LEADING_VAL) \ + unsigned FUNC_NAME##_uc(unsigned char x) __NOEXCEPT { \ + return LEADING_VAL##AU; \ + } \ + unsigned FUNC_NAME##_us(unsigned short x) __NOEXCEPT { \ + return LEADING_VAL##BU; \ + } \ + unsigned FUNC_NAME##_ui(unsigned int x) __NOEXCEPT { \ + return LEADING_VAL##CU; \ + } \ + unsigned FUNC_NAME##_ul(unsigned long x) __NOEXCEPT { \ + return LEADING_VAL##DU; \ + } \ + unsigned FUNC_NAME##_ull(unsigned long long x) __NOEXCEPT { \ + return LEADING_VAL##EU; \ + } + +__BEGIN_C_DECLS + +STDBIT_STUB_FUNCTION(stdc_leading_zeros, 0xA) +STDBIT_STUB_FUNCTION(stdc_leading_ones, 0xB) +STDBIT_STUB_FUNCTION(stdc_trailing_zeros, 0xC) +STDBIT_STUB_FUNCTION(stdc_trailing_ones, 0xD) +STDBIT_STUB_FUNCTION(stdc_first_leading_zero, 0xE) +STDBIT_STUB_FUNCTION(stdc_first_leading_one, 0xF) +STDBIT_STUB_FUNCTION(stdc_first_trailing_zero, 0x0) +STDBIT_STUB_FUNCTION(stdc_first_trailing_one, 0x1) +STDBIT_STUB_FUNCTION(stdc_count_zeros, 0x2) +STDBIT_STUB_FUNCTION(stdc_count_ones, 0x3) + +bool stdc_has_single_bit_uc(unsigned char x) __NOEXCEPT { return false; } +bool stdc_has_single_bit_us(unsigned short x) __NOEXCEPT { return false; } +bool stdc_has_single_bit_ui(unsigned x) __NOEXCEPT { return false; } +bool stdc_has_single_bit_ul(unsigned long x) __NOEXCEPT { return false; } +bool stdc_has_single_bit_ull(unsigned long long x) __NOEXCEPT { return false; } + +STDBIT_STUB_FUNCTION(stdc_bit_width, 0x4) + +unsigned char stdc_bit_floor_uc(unsigned char x) __NOEXCEPT { return 0x5AU; } +unsigned short stdc_bit_floor_us(unsigned short x) __NOEXCEPT { return 0x5BU; } +unsigned stdc_bit_floor_ui(unsigned x) __NOEXCEPT { return 0x5CU; } +unsigned long stdc_bit_floor_ul(unsigned long x) __NOEXCEPT { return 0x5DUL; } +unsigned long long stdc_bit_floor_ull(unsigned long long x) __NOEXCEPT { + return 0x5EULL; +} + +unsigned char stdc_bit_ceil_uc(unsigned char x) __NOEXCEPT { return 0x6AU; } +unsigned short stdc_bit_ceil_us(unsigned short x) __NOEXCEPT { return 0x6BU; } +unsigned stdc_bit_ceil_ui(unsigned x) __NOEXCEPT { return 0x6CU; } +unsigned long stdc_bit_ceil_ul(unsigned long x) __NOEXCEPT { return 0x6DUL; } +unsigned long long stdc_bit_ceil_ull(unsigned long long x) __NOEXCEPT { + return 0x6EULL; +} + +__END_C_DECLS diff --git a/libc/test/include/stdbit_test.c b/libc/test/include/stdbit_test.c new file mode 100644 index 0000000000000000000000000000000000000000..e278e9a7374e081635018847c2674fc39500e39b --- /dev/null +++ b/libc/test/include/stdbit_test.c @@ -0,0 +1,61 @@ +//===-- Unittests for stdbit ----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +/* + * The intent of this test is validate that: + * 1. We provide the definition of the various type generic macros of stdbit.h + * (the macros are transitively included from stdbit-macros.h by stdbit.h). + * 2. It dispatches to the correct underlying function. + * Because unit tests build without public packaging, the object files produced + * do not contain non-namespaced symbols. + */ + +/* + * Declare these BEFORE including stdbit-macros.h so that this test may still be + * run even if a given target doesn't yet have these individual entrypoints + * enabled. + */ +#include "stdbit_stub.h" + +#include "include/llvm-libc-macros/stdbit-macros.h" + +#include + +#define CHECK_FUNCTION(FUNC_NAME, VAL) \ + do { \ + assert(FUNC_NAME((unsigned char)0U) == VAL##AU); \ + assert(FUNC_NAME((unsigned short)0U) == VAL##BU); \ + assert(FUNC_NAME(0U) == VAL##CU); \ + assert(FUNC_NAME(0UL) == VAL##DU); \ + assert(FUNC_NAME(0ULL) == VAL##EU); \ + } while (0) + +int main(void) { + CHECK_FUNCTION(stdc_leading_zeros, 0xA); + CHECK_FUNCTION(stdc_leading_ones, 0xB); + CHECK_FUNCTION(stdc_trailing_zeros, 0xC); + CHECK_FUNCTION(stdc_trailing_ones, 0xD); + CHECK_FUNCTION(stdc_first_leading_zero, 0xE); + CHECK_FUNCTION(stdc_first_leading_one, 0xF); + CHECK_FUNCTION(stdc_first_trailing_zero, 0x0); + CHECK_FUNCTION(stdc_first_trailing_one, 0x1); + CHECK_FUNCTION(stdc_count_zeros, 0x2); + CHECK_FUNCTION(stdc_count_ones, 0x3); + + assert(!stdc_has_single_bit((unsigned char)1U)); + assert(!stdc_has_single_bit((unsigned short)1U)); + assert(!stdc_has_single_bit(1U)); + assert(!stdc_has_single_bit(1UL)); + assert(!stdc_has_single_bit(1ULL)); + + CHECK_FUNCTION(stdc_bit_width, 0x4); + CHECK_FUNCTION(stdc_bit_floor, 0x5); + CHECK_FUNCTION(stdc_bit_ceil, 0x6); + + return 0; +} diff --git a/libc/test/include/stdbit_test.cpp b/libc/test/include/stdbit_test.cpp index acb79ca0f3ff11dbe49fb10cc8b6ba51a85f84a0..f3227eb86959ebd8f76ecb69ae9ff1cc04ea1aa4 100644 --- a/libc/test/include/stdbit_test.cpp +++ b/libc/test/include/stdbit_test.cpp @@ -22,71 +22,7 @@ * run even if a given target doesn't yet have these individual entrypoints * enabled. */ -extern "C" { -unsigned stdc_leading_zeros_uc(unsigned char) noexcept { return 0xAAU; } -unsigned stdc_leading_zeros_us(unsigned short) noexcept { return 0xABU; } -unsigned stdc_leading_zeros_ui(unsigned) noexcept { return 0xACU; } -unsigned stdc_leading_zeros_ul(unsigned long) noexcept { return 0xADU; } -unsigned stdc_leading_zeros_ull(unsigned long long) noexcept { return 0xAFU; } -unsigned stdc_leading_ones_uc(unsigned char) noexcept { return 0xBAU; } -unsigned stdc_leading_ones_us(unsigned short) noexcept { return 0xBBU; } -unsigned stdc_leading_ones_ui(unsigned) noexcept { return 0xBCU; } -unsigned stdc_leading_ones_ul(unsigned long) noexcept { return 0xBDU; } -unsigned stdc_leading_ones_ull(unsigned long long) noexcept { return 0xBFU; } -unsigned stdc_trailing_zeros_uc(unsigned char) noexcept { return 0xCAU; } -unsigned stdc_trailing_zeros_us(unsigned short) noexcept { return 0xCBU; } -unsigned stdc_trailing_zeros_ui(unsigned) noexcept { return 0xCCU; } -unsigned stdc_trailing_zeros_ul(unsigned long) noexcept { return 0xCDU; } -unsigned stdc_trailing_zeros_ull(unsigned long long) noexcept { return 0xCFU; } -unsigned stdc_trailing_ones_uc(unsigned char) noexcept { return 0xDAU; } -unsigned stdc_trailing_ones_us(unsigned short) noexcept { return 0xDBU; } -unsigned stdc_trailing_ones_ui(unsigned) noexcept { return 0xDCU; } -unsigned stdc_trailing_ones_ul(unsigned long) noexcept { return 0xDDU; } -unsigned stdc_trailing_ones_ull(unsigned long long) noexcept { return 0xDFU; } -unsigned stdc_first_leading_zero_uc(unsigned char) noexcept { return 0xEAU; } -unsigned stdc_first_leading_zero_us(unsigned short) noexcept { return 0xEBU; } -unsigned stdc_first_leading_zero_ui(unsigned) noexcept { return 0xECU; } -unsigned stdc_first_leading_zero_ul(unsigned long) noexcept { return 0xEDU; } -unsigned stdc_first_leading_zero_ull(unsigned long long) noexcept { - return 0xEFU; -} -unsigned stdc_first_leading_one_uc(unsigned char) noexcept { return 0xFAU; } -unsigned stdc_first_leading_one_us(unsigned short) noexcept { return 0xFBU; } -unsigned stdc_first_leading_one_ui(unsigned) noexcept { return 0xFCU; } -unsigned stdc_first_leading_one_ul(unsigned long) noexcept { return 0xFDU; } -unsigned stdc_first_leading_one_ull(unsigned long long) noexcept { - return 0xFFU; -} -unsigned stdc_first_trailing_zero_uc(unsigned char) noexcept { return 0x0AU; } -unsigned stdc_first_trailing_zero_us(unsigned short) noexcept { return 0x0BU; } -unsigned stdc_first_trailing_zero_ui(unsigned) noexcept { return 0x0CU; } -unsigned stdc_first_trailing_zero_ul(unsigned long) noexcept { return 0x0DU; } -unsigned stdc_first_trailing_zero_ull(unsigned long long) noexcept { - return 0x0FU; -} -unsigned stdc_first_trailing_one_uc(unsigned char) noexcept { return 0x1AU; } -unsigned stdc_first_trailing_one_us(unsigned short) noexcept { return 0x1BU; } -unsigned stdc_first_trailing_one_ui(unsigned) noexcept { return 0x1CU; } -unsigned stdc_first_trailing_one_ul(unsigned long) noexcept { return 0x1DU; } -unsigned stdc_first_trailing_one_ull(unsigned long long) noexcept { - return 0x1FU; -} -unsigned stdc_count_zeros_uc(unsigned char) noexcept { return 0x2AU; } -unsigned stdc_count_zeros_us(unsigned short) noexcept { return 0x2BU; } -unsigned stdc_count_zeros_ui(unsigned) noexcept { return 0x2CU; } -unsigned stdc_count_zeros_ul(unsigned long) noexcept { return 0x2DU; } -unsigned stdc_count_zeros_ull(unsigned long long) noexcept { return 0x2FU; } -unsigned stdc_count_ones_uc(unsigned char) noexcept { return 0x3AU; } -unsigned stdc_count_ones_us(unsigned short) noexcept { return 0x3BU; } -unsigned stdc_count_ones_ui(unsigned) noexcept { return 0x3CU; } -unsigned stdc_count_ones_ul(unsigned long) noexcept { return 0x3DU; } -unsigned stdc_count_ones_ull(unsigned long long) noexcept { return 0x3FU; } -bool stdc_has_single_bit_uc(unsigned char) noexcept { return false; } -bool stdc_has_single_bit_us(unsigned short) noexcept { return false; } -bool stdc_has_single_bit_ui(unsigned) noexcept { return false; } -bool stdc_has_single_bit_ul(unsigned long) noexcept { return false; } -bool stdc_has_single_bit_ull(unsigned long long) noexcept { return false; } -} +#include "stdbit_stub.h" #include "include/llvm-libc-macros/stdbit-macros.h" @@ -95,7 +31,7 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroLeadingZeros) { EXPECT_EQ(stdc_leading_zeros(static_cast(0U)), 0xABU); EXPECT_EQ(stdc_leading_zeros(0U), 0xACU); EXPECT_EQ(stdc_leading_zeros(0UL), 0xADU); - EXPECT_EQ(stdc_leading_zeros(0ULL), 0xAFU); + EXPECT_EQ(stdc_leading_zeros(0ULL), 0xAEU); } TEST(LlvmLibcStdbitTest, TypeGenericMacroLeadingOnes) { @@ -103,7 +39,7 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroLeadingOnes) { EXPECT_EQ(stdc_leading_ones(static_cast(0U)), 0xBBU); EXPECT_EQ(stdc_leading_ones(0U), 0xBCU); EXPECT_EQ(stdc_leading_ones(0UL), 0xBDU); - EXPECT_EQ(stdc_leading_ones(0ULL), 0xBFU); + EXPECT_EQ(stdc_leading_ones(0ULL), 0xBEU); } TEST(LlvmLibcStdbitTest, TypeGenericMacroTrailingZeros) { @@ -111,7 +47,7 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroTrailingZeros) { EXPECT_EQ(stdc_trailing_zeros(static_cast(0U)), 0xCBU); EXPECT_EQ(stdc_trailing_zeros(0U), 0xCCU); EXPECT_EQ(stdc_trailing_zeros(0UL), 0xCDU); - EXPECT_EQ(stdc_trailing_zeros(0ULL), 0xCFU); + EXPECT_EQ(stdc_trailing_zeros(0ULL), 0xCEU); } TEST(LlvmLibcStdbitTest, TypeGenericMacroTrailingOnes) { @@ -119,7 +55,7 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroTrailingOnes) { EXPECT_EQ(stdc_trailing_ones(static_cast(0U)), 0xDBU); EXPECT_EQ(stdc_trailing_ones(0U), 0xDCU); EXPECT_EQ(stdc_trailing_ones(0UL), 0xDDU); - EXPECT_EQ(stdc_trailing_ones(0ULL), 0xDFU); + EXPECT_EQ(stdc_trailing_ones(0ULL), 0xDEU); } TEST(LlvmLibcStdbitTest, TypeGenericMacroFirstLeadingZero) { @@ -127,7 +63,7 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroFirstLeadingZero) { EXPECT_EQ(stdc_first_leading_zero(static_cast(0U)), 0xEBU); EXPECT_EQ(stdc_first_leading_zero(0U), 0xECU); EXPECT_EQ(stdc_first_leading_zero(0UL), 0xEDU); - EXPECT_EQ(stdc_first_leading_zero(0ULL), 0xEFU); + EXPECT_EQ(stdc_first_leading_zero(0ULL), 0xEEU); } TEST(LlvmLibcStdbitTest, TypeGenericMacroFirstLeadingOne) { @@ -135,7 +71,7 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroFirstLeadingOne) { EXPECT_EQ(stdc_first_leading_one(static_cast(0U)), 0xFBU); EXPECT_EQ(stdc_first_leading_one(0U), 0xFCU); EXPECT_EQ(stdc_first_leading_one(0UL), 0xFDU); - EXPECT_EQ(stdc_first_leading_one(0ULL), 0xFFU); + EXPECT_EQ(stdc_first_leading_one(0ULL), 0xFEU); } TEST(LlvmLibcStdbitTest, TypeGenericMacroFirstTrailingZero) { @@ -143,7 +79,7 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroFirstTrailingZero) { EXPECT_EQ(stdc_first_trailing_zero(static_cast(0U)), 0x0BU); EXPECT_EQ(stdc_first_trailing_zero(0U), 0x0CU); EXPECT_EQ(stdc_first_trailing_zero(0UL), 0x0DU); - EXPECT_EQ(stdc_first_trailing_zero(0ULL), 0x0FU); + EXPECT_EQ(stdc_first_trailing_zero(0ULL), 0x0EU); } TEST(LlvmLibcStdbitTest, TypeGenericMacroFirstTrailingOne) { @@ -151,7 +87,7 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroFirstTrailingOne) { EXPECT_EQ(stdc_first_trailing_one(static_cast(0U)), 0x1BU); EXPECT_EQ(stdc_first_trailing_one(0U), 0x1CU); EXPECT_EQ(stdc_first_trailing_one(0UL), 0x1DU); - EXPECT_EQ(stdc_first_trailing_one(0ULL), 0x1FU); + EXPECT_EQ(stdc_first_trailing_one(0ULL), 0x1EU); } TEST(LlvmLibcStdbitTest, TypeGenericMacroCountZeros) { @@ -159,7 +95,7 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroCountZeros) { EXPECT_EQ(stdc_count_zeros(static_cast(0U)), 0x2BU); EXPECT_EQ(stdc_count_zeros(0U), 0x2CU); EXPECT_EQ(stdc_count_zeros(0UL), 0x2DU); - EXPECT_EQ(stdc_count_zeros(0ULL), 0x2FU); + EXPECT_EQ(stdc_count_zeros(0ULL), 0x2EU); } TEST(LlvmLibcStdbitTest, TypeGenericMacroCountOnes) { @@ -167,7 +103,7 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroCountOnes) { EXPECT_EQ(stdc_count_ones(static_cast(0U)), 0x3BU); EXPECT_EQ(stdc_count_ones(0U), 0x3CU); EXPECT_EQ(stdc_count_ones(0UL), 0x3DU); - EXPECT_EQ(stdc_count_ones(0ULL), 0x3FU); + EXPECT_EQ(stdc_count_ones(0ULL), 0x3EU); } TEST(LlvmLibcStdbitTest, TypeGenericMacroHasSingleBit) { @@ -177,3 +113,31 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroHasSingleBit) { EXPECT_EQ(stdc_has_single_bit(1UL), false); EXPECT_EQ(stdc_has_single_bit(1ULL), false); } + +TEST(LlvmLibcStdbitTest, TypeGenericMacroBitWidth) { + EXPECT_EQ(stdc_bit_width(static_cast(1U)), 0x4AU); + EXPECT_EQ(stdc_bit_width(static_cast(1U)), 0x4BU); + EXPECT_EQ(stdc_bit_width(1U), 0x4CU); + EXPECT_EQ(stdc_bit_width(1UL), 0x4DU); + EXPECT_EQ(stdc_bit_width(1ULL), 0x4EU); +} + +TEST(LlvmLibcStdbitTest, TypeGenericMacroBitFloor) { + EXPECT_EQ(stdc_bit_floor(static_cast(0U)), + static_cast(0x5AU)); + EXPECT_EQ(stdc_bit_floor(static_cast(0U)), + static_cast(0x5BU)); + EXPECT_EQ(stdc_bit_floor(0U), 0x5CU); + EXPECT_EQ(stdc_bit_floor(0UL), 0x5DUL); + EXPECT_EQ(stdc_bit_floor(0ULL), 0x5EULL); +} + +TEST(LlvmLibcStdbitTest, TypeGenericMacroBitCeil) { + EXPECT_EQ(stdc_bit_ceil(static_cast(0U)), + static_cast(0x6AU)); + EXPECT_EQ(stdc_bit_ceil(static_cast(0U)), + static_cast(0x6BU)); + EXPECT_EQ(stdc_bit_ceil(0U), 0x6CU); + EXPECT_EQ(stdc_bit_ceil(0UL), 0x6DUL); + EXPECT_EQ(stdc_bit_ceil(0ULL), 0x6EULL); +} diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt index 9ad868551f071cfe9fa60c930fb42952526767ea..f70ffda3f700e514e55fdc0c2a003ae0137abe40 100644 --- a/libc/test/src/CMakeLists.txt +++ b/libc/test/src/CMakeLists.txt @@ -40,7 +40,6 @@ add_subdirectory(__support) add_subdirectory(ctype) add_subdirectory(errno) add_subdirectory(fenv) -add_subdirectory(inttypes) add_subdirectory(math) add_subdirectory(search) add_subdirectory(stdbit) @@ -50,6 +49,9 @@ add_subdirectory(stdlib) add_subdirectory(string) add_subdirectory(wchar) +# Depends on utilities in stdlib +add_subdirectory(inttypes) + if(${LIBC_TARGET_OS} STREQUAL "linux") add_subdirectory(fcntl) add_subdirectory(sched) diff --git a/libc/test/src/__support/CMakeLists.txt b/libc/test/src/__support/CMakeLists.txt index 7200ac276fe502fa8145f7e270c9d54f29ca1e17..91dd0dc4decfe060a59c1e6be1510cee6f17a6a8 100644 --- a/libc/test/src/__support/CMakeLists.txt +++ b/libc/test/src/__support/CMakeLists.txt @@ -27,7 +27,9 @@ add_libc_test( SRCS math_extras_test.cpp DEPENDS + libc.src.__support.integer_literals libc.src.__support.math_extras + libc.src.__support.uint128 ) add_libc_test( @@ -56,6 +58,19 @@ add_libc_test( libc.src.errno.errno ) + +add_libc_test( + str_to_integer_test + SUITE + libc-support-tests + SRCS + str_to_integer_test.cpp + DEPENDS + libc.src.__support.integer_literals + libc.src.__support.str_to_integer + libc.src.errno.errno +) + add_libc_test( integer_to_string_test SUITE @@ -91,8 +106,9 @@ if(NOT LIBC_TARGET_ARCHITECTURE_IS_NVPTX) SRCS uint_test.cpp DEPENDS - libc.src.__support.uint libc.src.__support.CPP.optional + libc.src.__support.macros.properties.types + libc.src.__support.uint ) endif() @@ -103,8 +119,9 @@ add_libc_test( SRCS integer_literals_test.cpp DEPENDS - libc.src.__support.integer_literals libc.src.__support.CPP.optional + libc.src.__support.integer_literals + libc.src.__support.macros.properties.types ) add_libc_test( diff --git a/libc/test/src/__support/CPP/CMakeLists.txt b/libc/test/src/__support/CPP/CMakeLists.txt index d7f332f5b0fbd9cae53c3e19fec597ca371d0006..f94429e03b3cbc6f60dc9155448b8464753811a9 100644 --- a/libc/test/src/__support/CPP/CMakeLists.txt +++ b/libc/test/src/__support/CPP/CMakeLists.txt @@ -8,6 +8,7 @@ add_libc_test( bit_test.cpp DEPENDS libc.src.__support.CPP.bit + libc.src.__support.macros.properties.types libc.src.__support.uint ) @@ -49,6 +50,7 @@ add_libc_test( limits_test.cpp DEPENDS libc.src.__support.CPP.limits + libc.src.__support.macros.properties.types libc.src.__support.uint ) diff --git a/libc/test/src/__support/CPP/bit_test.cpp b/libc/test/src/__support/CPP/bit_test.cpp index 115a5d505c4b7a2926687c5a04d150381b8496c1..3deb1f41dcf8826ad03756a296ec7a2741e4b3a4 100644 --- a/libc/test/src/__support/CPP/bit_test.cpp +++ b/libc/test/src/__support/CPP/bit_test.cpp @@ -8,25 +8,47 @@ #include "src/__support/CPP/bit.h" #include "src/__support/UInt.h" +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 #include "test/UnitTest/Test.h" #include namespace LIBC_NAMESPACE::cpp { -using UnsignedTypes = - testing::TypeList>; +using UnsignedTypesNoBigInt = testing::TypeList< +#if defined(LIBC_TYPES_HAS_INT128) + __uint128_t, +#endif // LIBC_TYPES_HAS_INT128 + unsigned char, unsigned short, unsigned int, unsigned long, + unsigned long long>; + +using UnsignedTypes = testing::TypeList< +#if defined(LIBC_TYPES_HAS_INT128) + __uint128_t, +#endif // LIBC_TYPES_HAS_INT128 + unsigned char, unsigned short, unsigned int, unsigned long, + unsigned long long, UInt<128>>; TYPED_TEST(LlvmLibcBitTest, HasSingleBit, UnsignedTypes) { - EXPECT_FALSE(has_single_bit(T(0))); - EXPECT_FALSE(has_single_bit(~T(0))); + constexpr auto ZERO = T(0); + constexpr auto ALL_ONES = T(~ZERO); + EXPECT_FALSE(has_single_bit(ZERO)); + EXPECT_FALSE(has_single_bit(ALL_ONES)); + for (T value = 1; value; value <<= 1) EXPECT_TRUE(has_single_bit(value)); + + // We test that if two bits are set has_single_bit returns false. + // We do this by setting the highest or lowest bit depending or where the + // current bit is. This is a bit convoluted but it helps catch a bug on BigInt + // where we have to work on an element-by-element basis. + constexpr auto MIDPOINT = T(ALL_ONES / 2); + constexpr auto LSB = T(1); + constexpr auto MSB = T(~(ALL_ONES >> 1)); + for (T value = 1; value; value <<= 1) { + auto two_bits_value = value | ((value <= MIDPOINT) ? MSB : LSB); + EXPECT_FALSE(has_single_bit(two_bits_value)); + } } TYPED_TEST(LlvmLibcBitTest, CountLZero, UnsignedTypes) { @@ -206,42 +228,42 @@ TEST(LlvmLibcBitTest, Rotr) { rotr(0x12345678deadbeefULL, -19)); } -TYPED_TEST(LlvmLibcBitTest, FirstLeadingZero, UnsignedTypes) { +TYPED_TEST(LlvmLibcBitTest, FirstLeadingZero, UnsignedTypesNoBigInt) { EXPECT_EQ(first_leading_zero(cpp::numeric_limits::max()), 0); for (int i = 0U; i != cpp::numeric_limits::digits; ++i) EXPECT_EQ(first_leading_zero(~(T(1) << i)), cpp::numeric_limits::digits - i); } -TYPED_TEST(LlvmLibcBitTest, FirstLeadingOne, UnsignedTypes) { +TYPED_TEST(LlvmLibcBitTest, FirstLeadingOne, UnsignedTypesNoBigInt) { EXPECT_EQ(first_leading_one(static_cast(0)), 0); for (int i = 0U; i != cpp::numeric_limits::digits; ++i) EXPECT_EQ(first_leading_one(T(1) << i), cpp::numeric_limits::digits - i); } -TYPED_TEST(LlvmLibcBitTest, FirstTrailingZero, UnsignedTypes) { +TYPED_TEST(LlvmLibcBitTest, FirstTrailingZero, UnsignedTypesNoBigInt) { EXPECT_EQ(first_trailing_zero(cpp::numeric_limits::max()), 0); for (int i = 0U; i != cpp::numeric_limits::digits; ++i) EXPECT_EQ(first_trailing_zero(~(T(1) << i)), i + 1); } -TYPED_TEST(LlvmLibcBitTest, FirstTrailingOne, UnsignedTypes) { +TYPED_TEST(LlvmLibcBitTest, FirstTrailingOne, UnsignedTypesNoBigInt) { EXPECT_EQ(first_trailing_one(cpp::numeric_limits::max()), 0); for (int i = 0U; i != cpp::numeric_limits::digits; ++i) EXPECT_EQ(first_trailing_one(T(1) << i), i + 1); } -TYPED_TEST(LlvmLibcBitTest, CountZeros, UnsignedTypes) { +TYPED_TEST(LlvmLibcBitTest, CountZeros, UnsignedTypesNoBigInt) { EXPECT_EQ(count_zeros(T(0)), cpp::numeric_limits::digits); for (int i = 0; i != cpp::numeric_limits::digits; ++i) EXPECT_EQ(count_zeros(cpp::numeric_limits::max() >> i), i); } -TYPED_TEST(LlvmLibcBitTest, CountOnes, UnsignedTypes) { - EXPECT_EQ(count_ones(T(0)), 0); +TYPED_TEST(LlvmLibcBitTest, CountOnes, UnsignedTypesNoBigInt) { + EXPECT_EQ(popcount(T(0)), 0); for (int i = 0; i != cpp::numeric_limits::digits; ++i) - EXPECT_EQ(count_ones(cpp::numeric_limits::max() >> i), + EXPECT_EQ(popcount(cpp::numeric_limits::max() >> i), cpp::numeric_limits::digits - i); } diff --git a/libc/test/src/__support/CPP/limits_test.cpp b/libc/test/src/__support/CPP/limits_test.cpp index 12641b7b51b6ce8d8a05f94b30bea93820484ade..efcd6839d07337e646cd575d8a2656740f1e9db0 100644 --- a/libc/test/src/__support/CPP/limits_test.cpp +++ b/libc/test/src/__support/CPP/limits_test.cpp @@ -8,6 +8,7 @@ #include "src/__support/CPP/limits.h" #include "src/__support/UInt.h" +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 #include "test/UnitTest/Test.h" namespace LIBC_NAMESPACE { @@ -32,14 +33,13 @@ TEST(LlvmLibcLimitsTest, LimitsFollowSpec) { } TEST(LlvmLibcLimitsTest, UInt128Limits) { - auto umax128 = cpp::numeric_limits>::max(); - auto umax64 = - LIBC_NAMESPACE::cpp::UInt<128>(cpp::numeric_limits::max()); + auto umax128 = cpp::numeric_limits>::max(); + auto umax64 = LIBC_NAMESPACE::UInt<128>(cpp::numeric_limits::max()); EXPECT_GT(umax128, umax64); - ASSERT_EQ(~LIBC_NAMESPACE::cpp::UInt<128>(0), umax128); -#ifdef __SIZEOF_INT128__ + ASSERT_EQ(~LIBC_NAMESPACE::UInt<128>(0), umax128); +#ifdef LIBC_TYPES_HAS_INT128 ASSERT_EQ(~__uint128_t(0), cpp::numeric_limits<__uint128_t>::max()); -#endif +#endif // LIBC_TYPES_HAS_INT128 } } // namespace LIBC_NAMESPACE diff --git a/libc/test/src/__support/high_precision_decimal_test.cpp b/libc/test/src/__support/high_precision_decimal_test.cpp index a9c039e45774e9b1fe1830ff6b405de1e3ce8fe6..2bb28bcdab0212833d504f3a88f768098c55be4f 100644 --- a/libc/test/src/__support/high_precision_decimal_test.cpp +++ b/libc/test/src/__support/high_precision_decimal_test.cpp @@ -406,3 +406,31 @@ TEST(LlvmLibcHighPrecisionDecimalTest, BigExpTest) { // Same, but since the number is negative the net result is -123456788 EXPECT_EQ(big_negative_hpd.get_decimal_point(), -123456789 + 1); } + +TEST(LlvmLibcHighPrecisionDecimalTest, NumLenExpTest) { + LIBC_NAMESPACE::internal::HighPrecisionDecimal hpd = + LIBC_NAMESPACE::internal::HighPrecisionDecimal("1e123456789", 5); + + // The length of 5 includes things like the "e" so it only gets 3 digits of + // exponent. + EXPECT_EQ(hpd.get_decimal_point(), 123 + 1); + + LIBC_NAMESPACE::internal::HighPrecisionDecimal negative_hpd = + LIBC_NAMESPACE::internal::HighPrecisionDecimal("1e-123456789", 5); + + // The negative sign also counts as a character. + EXPECT_EQ(negative_hpd.get_decimal_point(), -12 + 1); +} + +TEST(LlvmLibcHighPrecisionDecimalTest, NumLenDigitsTest) { + LIBC_NAMESPACE::internal::HighPrecisionDecimal hpd = + LIBC_NAMESPACE::internal::HighPrecisionDecimal("123456789e1", 5); + + EXPECT_EQ(hpd.round_to_integer_type(), uint64_t(12345)); + + LIBC_NAMESPACE::internal::HighPrecisionDecimal longer_hpd = + LIBC_NAMESPACE::internal::HighPrecisionDecimal("123456789e1", 10); + + // With 10 characters it should see the e, but not actually act on it. + EXPECT_EQ(longer_hpd.round_to_integer_type(), uint64_t(123456789)); +} diff --git a/libc/test/src/__support/integer_literals_test.cpp b/libc/test/src/__support/integer_literals_test.cpp index 10c3625a0e5a4915ea415725202f275267617e35..5298cf30156e207a0c4d0795e3f6cce22f34e66f 100644 --- a/libc/test/src/__support/integer_literals_test.cpp +++ b/libc/test/src/__support/integer_literals_test.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "src/__support/integer_literals.h" +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 #include "test/UnitTest/Test.h" using LIBC_NAMESPACE::operator""_u8; @@ -66,7 +67,7 @@ TEST(LlvmLibcIntegerLiteralTest, u64) { } TEST(LlvmLibcIntegerLiteralTest, u128) { -#if defined(__SIZEOF_INT128__) +#ifdef LIBC_TYPES_HAS_INT128 const __uint128_t ZERO = 0; const __uint128_t U8_MAX = UINT8_MAX; const __uint128_t U16_MAX = UINT16_MAX; @@ -80,7 +81,7 @@ TEST(LlvmLibcIntegerLiteralTest, u128) { const UInt128 U32_MAX = UINT32_MAX; const UInt128 U64_MAX = UINT64_MAX; const UInt128 U128_MAX = (U64_MAX << 64) | U64_MAX; -#endif +#endif // LIBC_TYPES_HAS_INT128 EXPECT_EQ(ZERO, 0_u128); EXPECT_EQ(U8_MAX, 255_u128); EXPECT_EQ(U8_MAX, 0xFF_u128); @@ -104,7 +105,7 @@ TEST(LlvmLibcIntegerLiteralTest, u128) { } TEST(LlvmLibcIntegerLiteralTest, u256) { - using UInt256 = LIBC_NAMESPACE::cpp::UInt<256>; + using UInt256 = LIBC_NAMESPACE::UInt<256>; const UInt256 ZERO = 0; const UInt256 U8_MAX = UINT8_MAX; const UInt256 U16_MAX = UINT16_MAX; diff --git a/libc/test/src/__support/integer_to_string_test.cpp b/libc/test/src/__support/integer_to_string_test.cpp index 2a19c5bf7549c6868dd79e922ed13d4458f4afdc..a2a80c81b9f69fbb11657b98e65f7fd2c89e26e0 100644 --- a/libc/test/src/__support/integer_to_string_test.cpp +++ b/libc/test/src/__support/integer_to_string_test.cpp @@ -228,7 +228,7 @@ TEST(LlvmLibcIntegerToStringTest, UINT64_Base_36) { } TEST(LlvmLibcIntegerToStringTest, UINT256_Base_16) { - using UInt256 = LIBC_NAMESPACE::cpp::UInt<256>; + using UInt256 = LIBC_NAMESPACE::UInt<256>; using type = IntegerToString>; EXPECT( type, diff --git a/libc/test/src/__support/math_extras_test.cpp b/libc/test/src/__support/math_extras_test.cpp index e55d995592cc1c740b6e3f440e872647e262ef82..ed064363d446bbf2201192fbabf1671980e714c3 100644 --- a/libc/test/src/__support/math_extras_test.cpp +++ b/libc/test/src/__support/math_extras_test.cpp @@ -6,34 +6,59 @@ // //===----------------------------------------------------------------------===// +#include "src/__support/UInt128.h" // UInt128 +#include "src/__support/integer_literals.h" #include "src/__support/math_extras.h" #include "test/UnitTest/Test.h" namespace LIBC_NAMESPACE { TEST(LlvmLibcBlockMathExtrasTest, mask_trailing_ones) { - EXPECT_EQ(uint8_t(0), (mask_leading_ones())); - EXPECT_EQ(uint8_t(0), (mask_trailing_ones())); - EXPECT_EQ(uint16_t(0), (mask_leading_ones())); - EXPECT_EQ(uint16_t(0), (mask_trailing_ones())); - EXPECT_EQ(uint32_t(0), (mask_leading_ones())); - EXPECT_EQ(uint32_t(0), (mask_trailing_ones())); - EXPECT_EQ(uint64_t(0), (mask_leading_ones())); - EXPECT_EQ(uint64_t(0), (mask_trailing_ones())); - - EXPECT_EQ(uint32_t(0x00000003), (mask_trailing_ones())); - EXPECT_EQ(uint32_t(0xC0000000), (mask_leading_ones())); - - EXPECT_EQ(uint32_t(0x000007FF), (mask_trailing_ones())); - EXPECT_EQ(uint32_t(0xFFE00000), (mask_leading_ones())); - - EXPECT_EQ(uint32_t(0xFFFFFFFF), (mask_trailing_ones())); - EXPECT_EQ(uint32_t(0xFFFFFFFF), (mask_leading_ones())); - EXPECT_EQ(uint64_t(0xFFFFFFFFFFFFFFFF), (mask_trailing_ones())); - EXPECT_EQ(uint64_t(0xFFFFFFFFFFFFFFFF), (mask_leading_ones())); - - EXPECT_EQ(uint64_t(0x0000FFFFFFFFFFFF), (mask_trailing_ones())); - EXPECT_EQ(uint64_t(0xFFFFFFFFFFFF0000), (mask_leading_ones())); + EXPECT_EQ(0_u8, (mask_leading_ones())); + EXPECT_EQ(0_u8, (mask_trailing_ones())); + EXPECT_EQ(0_u16, (mask_leading_ones())); + EXPECT_EQ(0_u16, (mask_trailing_ones())); + EXPECT_EQ(0_u32, (mask_leading_ones())); + EXPECT_EQ(0_u32, (mask_trailing_ones())); + EXPECT_EQ(0_u64, (mask_leading_ones())); + EXPECT_EQ(0_u64, (mask_trailing_ones())); + + EXPECT_EQ(0x00000003_u32, (mask_trailing_ones())); + EXPECT_EQ(0xC0000000_u32, (mask_leading_ones())); + + EXPECT_EQ(0x000007FF_u32, (mask_trailing_ones())); + EXPECT_EQ(0xFFE00000_u32, (mask_leading_ones())); + + EXPECT_EQ(0xFFFFFFFF_u32, (mask_trailing_ones())); + EXPECT_EQ(0xFFFFFFFF_u32, (mask_leading_ones())); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF_u64, (mask_trailing_ones())); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF_u64, (mask_leading_ones())); + + EXPECT_EQ(0x0000FFFFFFFFFFFF_u64, (mask_trailing_ones())); + EXPECT_EQ(0xFFFFFFFFFFFF0000_u64, (mask_leading_ones())); + + EXPECT_EQ(0_u128, (mask_trailing_ones())); + EXPECT_EQ(0_u128, (mask_leading_ones())); + + EXPECT_EQ(0x00000000000000007FFFFFFFFFFFFFFF_u128, + (mask_trailing_ones())); + EXPECT_EQ(0xFFFFFFFFFFFFFFFE0000000000000000_u128, + (mask_leading_ones())); + + EXPECT_EQ(0x0000000000000000FFFFFFFFFFFFFFFF_u128, + (mask_trailing_ones())); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF0000000000000000_u128, + (mask_leading_ones())); + + EXPECT_EQ(0x0000000000000001FFFFFFFFFFFFFFFF_u128, + (mask_trailing_ones())); + EXPECT_EQ(0xFFFFFFFFFFFFFFFF8000000000000000_u128, + (mask_leading_ones())); + + EXPECT_EQ(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF_u128, + (mask_trailing_ones())); + EXPECT_EQ(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF_u128, + (mask_leading_ones())); } } // namespace LIBC_NAMESPACE diff --git a/libc/test/src/__support/str_to_integer_test.cpp b/libc/test/src/__support/str_to_integer_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..34b645b4b38c831d51d4fe084b265f600b46f98c --- /dev/null +++ b/libc/test/src/__support/str_to_integer_test.cpp @@ -0,0 +1,240 @@ +//===-- Unittests for str_to_integer --------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/str_to_integer.h" +#include "src/errno/libc_errno.h" +#include + +#include "test/UnitTest/Test.h" + +// This file is for testing the src_len argument and other internal interface +// features. Primary testing is done in stdlib/StrolTest.cpp through the public +// interface. + +TEST(LlvmLibcStrToIntegerTest, SimpleLength) { + auto result = LIBC_NAMESPACE::internal::strtointeger("12345", 10, 10); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(5)); + ASSERT_EQ(result.value, 12345); + + result = LIBC_NAMESPACE::internal::strtointeger("12345", 10, 2); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(2)); + ASSERT_EQ(result.value, 12); + + result = LIBC_NAMESPACE::internal::strtointeger("12345", 10, 0); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(0)); + ASSERT_EQ(result.value, 0); +} + +TEST(LlvmLibcStrToIntegerTest, LeadingSpaces) { + auto result = + LIBC_NAMESPACE::internal::strtointeger(" 12345", 10, 15); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(10)); + ASSERT_EQ(result.value, 12345); + + result = LIBC_NAMESPACE::internal::strtointeger(" 12345", 10, 10); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(10)); + ASSERT_EQ(result.value, 12345); + + result = LIBC_NAMESPACE::internal::strtointeger(" 12345", 10, 7); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(7)); + ASSERT_EQ(result.value, 12); + + result = LIBC_NAMESPACE::internal::strtointeger(" 12345", 10, 5); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(0)); + ASSERT_EQ(result.value, 0); + + result = LIBC_NAMESPACE::internal::strtointeger(" 12345", 10, 0); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(0)); + ASSERT_EQ(result.value, 0); +} + +TEST(LlvmLibcStrToIntegerTest, LeadingSign) { + auto result = LIBC_NAMESPACE::internal::strtointeger("+12345", 10, 10); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(6)); + ASSERT_EQ(result.value, 12345); + + result = LIBC_NAMESPACE::internal::strtointeger("-12345", 10, 10); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(6)); + ASSERT_EQ(result.value, -12345); + + result = LIBC_NAMESPACE::internal::strtointeger("+12345", 10, 6); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(6)); + ASSERT_EQ(result.value, 12345); + + result = LIBC_NAMESPACE::internal::strtointeger("-12345", 10, 6); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(6)); + ASSERT_EQ(result.value, -12345); + + result = LIBC_NAMESPACE::internal::strtointeger("+12345", 10, 3); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(3)); + ASSERT_EQ(result.value, 12); + + result = LIBC_NAMESPACE::internal::strtointeger("-12345", 10, 3); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(3)); + ASSERT_EQ(result.value, -12); + + result = LIBC_NAMESPACE::internal::strtointeger("+12345", 10, 1); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(0)); + ASSERT_EQ(result.value, 0); + + result = LIBC_NAMESPACE::internal::strtointeger("-12345", 10, 1); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(0)); + ASSERT_EQ(result.value, 0); + + result = LIBC_NAMESPACE::internal::strtointeger("+12345", 10, 0); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(0)); + ASSERT_EQ(result.value, 0); + + result = LIBC_NAMESPACE::internal::strtointeger("-12345", 10, 0); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(0)); + ASSERT_EQ(result.value, 0); +} + +TEST(LlvmLibcStrToIntegerTest, Base16PrefixAutoSelect) { + auto result = LIBC_NAMESPACE::internal::strtointeger("0x12345", 0, 10); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(7)); + ASSERT_EQ(result.value, 0x12345); + + result = LIBC_NAMESPACE::internal::strtointeger("0x12345", 0, 7); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(7)); + ASSERT_EQ(result.value, 0x12345); + + result = LIBC_NAMESPACE::internal::strtointeger("0x12345", 0, 5); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(5)); + ASSERT_EQ(result.value, 0x123); + + result = LIBC_NAMESPACE::internal::strtointeger("0x12345", 0, 2); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(1)); + ASSERT_EQ(result.value, 0); + + result = LIBC_NAMESPACE::internal::strtointeger("0x12345", 0, 0); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(0)); + ASSERT_EQ(result.value, 0); +} + +TEST(LlvmLibcStrToIntegerTest, Base16PrefixManualSelect) { + auto result = LIBC_NAMESPACE::internal::strtointeger("0x12345", 16, 10); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(7)); + ASSERT_EQ(result.value, 0x12345); + + result = LIBC_NAMESPACE::internal::strtointeger("0x12345", 16, 7); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(7)); + ASSERT_EQ(result.value, 0x12345); + + result = LIBC_NAMESPACE::internal::strtointeger("0x12345", 16, 5); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(5)); + ASSERT_EQ(result.value, 0x123); + + result = LIBC_NAMESPACE::internal::strtointeger("0x12345", 16, 2); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(1)); + ASSERT_EQ(result.value, 0); + + result = LIBC_NAMESPACE::internal::strtointeger("0x12345", 16, 0); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(0)); + ASSERT_EQ(result.value, 0); +} + +TEST(LlvmLibcStrToIntegerTest, Base8PrefixAutoSelect) { + auto result = LIBC_NAMESPACE::internal::strtointeger("012345", 0, 10); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(6)); + ASSERT_EQ(result.value, 012345); + + result = LIBC_NAMESPACE::internal::strtointeger("012345", 0, 6); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(6)); + ASSERT_EQ(result.value, 012345); + + result = LIBC_NAMESPACE::internal::strtointeger("012345", 0, 4); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(4)); + ASSERT_EQ(result.value, 0123); + + result = LIBC_NAMESPACE::internal::strtointeger("012345", 0, 1); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(1)); + ASSERT_EQ(result.value, 0); + + result = LIBC_NAMESPACE::internal::strtointeger("012345", 0, 0); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(0)); + ASSERT_EQ(result.value, 0); +} + +TEST(LlvmLibcStrToIntegerTest, Base8PrefixManualSelect) { + auto result = LIBC_NAMESPACE::internal::strtointeger("012345", 8, 10); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(6)); + ASSERT_EQ(result.value, 012345); + + result = LIBC_NAMESPACE::internal::strtointeger("012345", 8, 6); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(6)); + ASSERT_EQ(result.value, 012345); + + result = LIBC_NAMESPACE::internal::strtointeger("012345", 8, 4); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(4)); + ASSERT_EQ(result.value, 0123); + + result = LIBC_NAMESPACE::internal::strtointeger("012345", 8, 1); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(1)); + ASSERT_EQ(result.value, 0); + + result = LIBC_NAMESPACE::internal::strtointeger("012345", 8, 0); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(0)); + ASSERT_EQ(result.value, 0); +} + +TEST(LlvmLibcStrToIntegerTest, CombinedTests) { + auto result = + LIBC_NAMESPACE::internal::strtointeger(" -0x123", 0, 10); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(10)); + ASSERT_EQ(result.value, -0x123); + + result = LIBC_NAMESPACE::internal::strtointeger(" -0x123", 0, 8); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(8)); + ASSERT_EQ(result.value, -0x1); + + result = LIBC_NAMESPACE::internal::strtointeger(" -0x123", 0, 7); + EXPECT_FALSE(result.has_error()); + EXPECT_EQ(result.parsed_len, ptrdiff_t(6)); + ASSERT_EQ(result.value, 0); +} diff --git a/libc/test/src/__support/uint_test.cpp b/libc/test/src/__support/uint_test.cpp index 963c553b10d01d501569929f39dfb9580a420ced..851656e9fcbbb036b65935724d103bfa014f8c45 100644 --- a/libc/test/src/__support/uint_test.cpp +++ b/libc/test/src/__support/uint_test.cpp @@ -8,25 +8,26 @@ #include "src/__support/CPP/optional.h" #include "src/__support/UInt.h" +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT128 #include "test/UnitTest/Test.h" #include // HUGE_VALF, HUGE_VALF namespace LIBC_NAMESPACE { -using LL_UInt64 = cpp::UInt<64>; -// We want to test cpp::UInt<128> explicitly. So, for +using LL_UInt64 = UInt<64>; +// We want to test UInt<128> explicitly. So, for // convenience, we use a sugar which does not conflict with the UInt128 type // which can resolve to __uint128_t if the platform has it. -using LL_UInt128 = cpp::UInt<128>; -using LL_UInt192 = cpp::UInt<192>; -using LL_UInt256 = cpp::UInt<256>; -using LL_UInt320 = cpp::UInt<320>; -using LL_UInt512 = cpp::UInt<512>; -using LL_UInt1024 = cpp::UInt<1024>; +using LL_UInt128 = UInt<128>; +using LL_UInt192 = UInt<192>; +using LL_UInt256 = UInt<256>; +using LL_UInt320 = UInt<320>; +using LL_UInt512 = UInt<512>; +using LL_UInt1024 = UInt<1024>; -using LL_Int128 = cpp::Int<128>; -using LL_Int192 = cpp::Int<192>; +using LL_Int128 = Int<128>; +using LL_Int192 = Int<192>; TEST(LlvmLibcUIntClassTest, BitCastToFromDouble) { static_assert(cpp::is_trivially_copyable::value); @@ -41,7 +42,7 @@ TEST(LlvmLibcUIntClassTest, BitCastToFromDouble) { } } -#ifdef __SIZEOF_INT128__ +#ifdef LIBC_TYPES_HAS_INT128 TEST(LlvmLibcUIntClassTest, BitCastToFromNativeUint128) { static_assert(cpp::is_trivially_copyable::value); static_assert(sizeof(LL_UInt128) == sizeof(__uint128_t)); @@ -52,7 +53,7 @@ TEST(LlvmLibcUIntClassTest, BitCastToFromNativeUint128) { EXPECT_TRUE(value == forth); } } -#endif +#endif // LIBC_TYPES_HAS_INT128 #ifdef LIBC_TYPES_HAS_FLOAT128 TEST(LlvmLibcUIntClassTest, BitCastToFromNativeFloat128) { @@ -652,7 +653,7 @@ TEST(LlvmLibcUIntClassTest, BasicArithmeticInt128Tests) { ASSERT_EQ(c * b, b); } -#ifdef __SIZEOF_INT128__ +#ifdef LIBC_TYPES_HAS_INT128 TEST(LlvmLibcUIntClassTest, ConstructorFromUInt128Tests) { __uint128_t a = (__uint128_t(123) << 64) + 1; @@ -677,8 +678,8 @@ TEST(LlvmLibcUIntClassTest, ConstructorFromUInt128Tests) { } TEST(LlvmLibcUIntClassTest, WordTypeUInt128Tests) { - using LL_UInt256_128 = cpp::BigInt<256, false, __uint128_t>; - using LL_UInt128_128 = cpp::BigInt<128, false, __uint128_t>; + using LL_UInt256_128 = BigInt<256, false, __uint128_t>; + using LL_UInt128_128 = BigInt<128, false, __uint128_t>; LL_UInt256_128 a(1); @@ -707,10 +708,10 @@ TEST(LlvmLibcUIntClassTest, WordTypeUInt128Tests) { EXPECT_TRUE(f == r); } -#endif // __SIZEOF_INT128__ +#endif // LIBC_TYPES_HAS_INT128 TEST(LlvmLibcUIntClassTest, OtherWordTypeTests) { - using LL_UInt96 = cpp::BigInt<96, false, uint32_t>; + using LL_UInt96 = BigInt<96, false, uint32_t>; LL_UInt96 a(1); diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt index ad7dfdb3dfd9eceb89d428a89361c91a8fe62f32..b8a4aafcd97aa27e572666536bca2ac05f893f61 100644 --- a/libc/test/src/math/CMakeLists.txt +++ b/libc/test/src/math/CMakeLists.txt @@ -1721,5 +1721,5 @@ add_subdirectory(smoke) if(NOT LLVM_LIBC_FULL_BUILD) add_subdirectory(exhaustive) - add_subdirectory(differential_testing) + add_subdirectory(performance_testing) endif() diff --git a/libc/test/src/math/differential_testing/ceilf_diff.cpp b/libc/test/src/math/differential_testing/ceilf_diff.cpp deleted file mode 100644 index 7c0bb1e95a03fd69c7e6f3301bb7430ea41dcd93..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/ceilf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for ceilf----------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/ceilf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::ceilf, ::ceilf, - "ceilf_diff.log") diff --git a/libc/test/src/math/differential_testing/cosf_diff.cpp b/libc/test/src/math/differential_testing/cosf_diff.cpp deleted file mode 100644 index ee3102384a8e6b79bf1c71a761a4dcc9cac39bf3..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/cosf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for cosf ----------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/cosf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::cosf, ::cosf, - "cosf_diff.log") diff --git a/libc/test/src/math/differential_testing/exp2f_diff.cpp b/libc/test/src/math/differential_testing/exp2f_diff.cpp deleted file mode 100644 index 545c6de320fc7c48d44752e32c12f385581dc7d8..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/exp2f_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for exp2f----------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/exp2f.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::exp2f, ::exp2f, - "exp2f_diff.log") diff --git a/libc/test/src/math/differential_testing/expf_diff.cpp b/libc/test/src/math/differential_testing/expf_diff.cpp deleted file mode 100644 index 7c2e90744bc915692dd60af7e8bc7351819fa58f..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/expf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for expf ----------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/expf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::expf, ::expf, - "expf_diff.log") diff --git a/libc/test/src/math/differential_testing/expm1f_diff.cpp b/libc/test/src/math/differential_testing/expm1f_diff.cpp deleted file mode 100644 index 3cbd8a99690fb4933cd6ed959d88afc6deed5ff3..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/expm1f_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for expm1f --------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/expm1f.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::expm1f, ::expm1f, - "expm1f_diff.log") diff --git a/libc/test/src/math/differential_testing/fabsf_diff.cpp b/libc/test/src/math/differential_testing/fabsf_diff.cpp deleted file mode 100644 index 9bf9eff888fb51aff8880625f0f5adb396c55468..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/fabsf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for fabsf----------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/fabsf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::fabsf, ::fabsf, - "fabsf_diff.log") diff --git a/libc/test/src/math/differential_testing/floorf_diff.cpp b/libc/test/src/math/differential_testing/floorf_diff.cpp deleted file mode 100644 index 6d72927b5010c575c0f5960a7ee5c0fce36f6a13..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/floorf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for floorf---------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/floorf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::floorf, ::floorf, - "floorf_diff.log") diff --git a/libc/test/src/math/differential_testing/log2f_diff.cpp b/libc/test/src/math/differential_testing/log2f_diff.cpp deleted file mode 100644 index aef431dce48701e0bef357a2859f7cea39643ad6..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/log2f_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for log2f ---------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/log2f.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::log2f, ::log2f, - "log2f_diff.log") diff --git a/libc/test/src/math/differential_testing/logbf_diff.cpp b/libc/test/src/math/differential_testing/logbf_diff.cpp deleted file mode 100644 index 37441eb40a4dfaf9739d271f0a2b98b43fbfae2e..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/logbf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for logbf----------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/logbf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::logbf, ::logbf, - "logbf_diff.log") diff --git a/libc/test/src/math/differential_testing/logf_diff.cpp b/libc/test/src/math/differential_testing/logf_diff.cpp deleted file mode 100644 index 4ed1307f71208102da3612f97bf56a156a59a8d8..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/logf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for logf ----------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/logf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::logf, ::logf, - "logf_diff.log") diff --git a/libc/test/src/math/differential_testing/nearbyintf_diff.cpp b/libc/test/src/math/differential_testing/nearbyintf_diff.cpp deleted file mode 100644 index 14200116883db4c21e7b8cacb98cfa3a2b603934..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/nearbyintf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for nearbyintf-----------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/nearbyintf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::nearbyintf, ::nearbyintf, - "nearbyintf_diff.log") diff --git a/libc/test/src/math/differential_testing/rintf_diff.cpp b/libc/test/src/math/differential_testing/rintf_diff.cpp deleted file mode 100644 index e60f66085e5d7054bf260be197d62c16355ef4ce..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/rintf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for rintf----------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/rintf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::rintf, ::rintf, - "rintf_diff.log") diff --git a/libc/test/src/math/differential_testing/roundf_diff.cpp b/libc/test/src/math/differential_testing/roundf_diff.cpp deleted file mode 100644 index e1401a01af3574d090ef0c97d17f781d521f930d..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/roundf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for roundf---------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/roundf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::roundf, ::roundf, - "roundf_diff.log") diff --git a/libc/test/src/math/differential_testing/sinf_diff.cpp b/libc/test/src/math/differential_testing/sinf_diff.cpp deleted file mode 100644 index cb4557e6796b5561adcddd42e79af9185369886b..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/sinf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for sinf ----------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/sinf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::sinf, ::sinf, - "sinf_diff.log") diff --git a/libc/test/src/math/differential_testing/sqrtf_diff.cpp b/libc/test/src/math/differential_testing/sqrtf_diff.cpp deleted file mode 100644 index 22ddeaac9caf9997a7f4e80967f8da5b17693219..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/sqrtf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for sqrtf----------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/sqrtf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::sqrtf, ::sqrtf, - "sqrtf_diff.log") diff --git a/libc/test/src/math/differential_testing/truncf_diff.cpp b/libc/test/src/math/differential_testing/truncf_diff.cpp deleted file mode 100644 index 7f6ac4e6a926941358b08ee3e728e4a7944c377a..0000000000000000000000000000000000000000 --- a/libc/test/src/math/differential_testing/truncf_diff.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- Differential test for truncf---------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "SingleInputSingleOutputDiff.h" - -#include "src/math/truncf.h" - -#include - -SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::truncf, ::truncf, - "truncf_diff.log") diff --git a/libc/test/src/math/exhaustive/fmod_generic_impl_test.cpp b/libc/test/src/math/exhaustive/fmod_generic_impl_test.cpp index b47d24c54869bbab3102c2a9c5d9796833d52738..25a5e3898599ae9862be54a990af387c120c21df 100644 --- a/libc/test/src/math/exhaustive/fmod_generic_impl_test.cpp +++ b/libc/test/src/math/exhaustive/fmod_generic_impl_test.cpp @@ -19,10 +19,11 @@ namespace mpfr = LIBC_NAMESPACE::testing::mpfr; template class LlvmLibcFModTest : public LIBC_NAMESPACE::testing::Test { + using U = typename LIBC_NAMESPACE::fputil::FPBits::StorageType; using DivisionHelper = LIBC_NAMESPACE::cpp::conditional_t< InverseMultiplication, - LIBC_NAMESPACE::fputil::generic::FModDivisionInvMultHelper, - LIBC_NAMESPACE::fputil::generic::FModDivisionSimpleHelper>; + LIBC_NAMESPACE::fputil::generic::FModDivisionInvMultHelper, + LIBC_NAMESPACE::fputil::generic::FModDivisionSimpleHelper>; static constexpr std::array test_bases = { T(0.0), @@ -39,9 +40,7 @@ class LlvmLibcFModTest : public LIBC_NAMESPACE::testing::Test { public: void testExtensive() { - using FMod = LIBC_NAMESPACE::fputil::generic::FMod< - T, LIBC_NAMESPACE::fputil::generic::FModFastMathWrapper, - DivisionHelper>; + using FMod = LIBC_NAMESPACE::fputil::generic::FMod; using nl = std::numeric_limits; int min2 = nl::min_exponent - nl::digits - 5; int max2 = nl::max_exponent + 3; diff --git a/libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h b/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h similarity index 69% rename from libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h rename to libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h index 48572e78e5153e07fd3e9f579c9bebf62a106339..504d1be94b891c1c3df40492f28606354ebed7dc 100644 --- a/libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h +++ b/libc/test/src/math/performance_testing/BinaryOpSingleOutputPerf.h @@ -7,14 +7,14 @@ //===----------------------------------------------------------------------===// #include "src/__support/FPUtil/FPBits.h" -#include "test/src/math/differential_testing/Timer.h" +#include "test/src/math/performance_testing/Timer.h" #include namespace LIBC_NAMESPACE { namespace testing { -template class BinaryOpSingleOutputDiff { +template class BinaryOpSingleOutputPerf { using FPBits = fputil::FPBits; using StorageType = typename FPBits::StorageType; static constexpr StorageType UIntMax = @@ -23,40 +23,6 @@ template class BinaryOpSingleOutputDiff { public: typedef T Func(T, T); - static uint64_t run_diff_in_range(Func myFunc, Func otherFunc, - StorageType startingBit, - StorageType endingBit, StorageType N, - std::ofstream &log) { - uint64_t result = 0; - if (endingBit < startingBit) { - return result; - } - - StorageType step = (endingBit - startingBit) / N; - for (StorageType bitsX = startingBit, bitsY = endingBit;; - bitsX += step, bitsY -= step) { - T x = T(FPBits(bitsX)); - T y = T(FPBits(bitsY)); - FPBits myBits = FPBits(myFunc(x, y)); - FPBits otherBits = FPBits(otherFunc(x, y)); - if (myBits.uintval() != otherBits.uintval()) { - result++; - log << " Input: " << bitsX << ", " << bitsY << " (" << x << ", " - << y << ")\n" - << " My result: " << myBits.uintval() << " (" << myBits.get_val() - << ")\n" - << "Other result: " << otherBits.uintval() << " (" - << otherBits.get_val() << ")\n" - << '\n'; - } - - if (endingBit - bitsX < step) { - break; - } - } - return result; - } - static void run_perf_in_range(Func myFunc, Func otherFunc, StorageType startingBit, StorageType endingBit, StorageType N, std::ofstream &log) { @@ -69,8 +35,8 @@ public: StorageType step = (endingBit - startingBit) / N; for (StorageType bitsX = startingBit, bitsY = endingBit;; bitsX += step, bitsY -= step) { - T x = T(FPBits(bitsX)); - T y = T(FPBits(bitsY)); + T x = FPBits(bitsX).get_val(); + T y = FPBits(bitsY).get_val(); result = func(x, y); if (endingBit - bitsX < step) { break; @@ -110,17 +76,17 @@ public: log << " Performance tests with inputs in denormal range:\n"; run_perf_in_range(myFunc, otherFunc, /* startingBit= */ StorageType(0), /* endingBit= */ FPBits::max_subnormal().uintval(), - 1'000'001, log); + 10'000'001, log); log << "\n Performance tests with inputs in normal range:\n"; run_perf_in_range(myFunc, otherFunc, /* startingBit= */ FPBits::min_normal().uintval(), /* endingBit= */ FPBits::max_normal().uintval(), - 100'000'001, log); + 10'000'001, log); log << "\n Performance tests with inputs in normal range with exponents " "close to each other:\n"; run_perf_in_range( myFunc, otherFunc, /* startingBit= */ FPBits(T(0x1.0p-10)).uintval(), - /* endingBit= */ FPBits(T(0x1.0p+10)).uintval(), 10'000'001, log); + /* endingBit= */ FPBits(T(0x1.0p+10)).uintval(), 1'001'001, log); } static void run_diff(Func myFunc, Func otherFunc, const char *logFile) { @@ -148,16 +114,9 @@ public: } // namespace testing } // namespace LIBC_NAMESPACE -#define BINARY_OP_SINGLE_OUTPUT_DIFF(T, myFunc, otherFunc, filename) \ - int main() { \ - LIBC_NAMESPACE::testing::BinaryOpSingleOutputDiff::run_diff( \ - &myFunc, &otherFunc, filename); \ - return 0; \ - } - #define BINARY_OP_SINGLE_OUTPUT_PERF(T, myFunc, otherFunc, filename) \ int main() { \ - LIBC_NAMESPACE::testing::BinaryOpSingleOutputDiff::run_perf( \ + LIBC_NAMESPACE::testing::BinaryOpSingleOutputPerf::run_perf( \ &myFunc, &otherFunc, filename); \ return 0; \ } diff --git a/libc/test/src/math/differential_testing/CMakeLists.txt b/libc/test/src/math/performance_testing/CMakeLists.txt similarity index 58% rename from libc/test/src/math/differential_testing/CMakeLists.txt rename to libc/test/src/math/performance_testing/CMakeLists.txt index 878f81f1d573c8f64bf5b21fd5dfb5bca599df5e..d1fb24e37f7286bbb64fde9b60d7e152d99437a8 100644 --- a/libc/test/src/math/differential_testing/CMakeLists.txt +++ b/libc/test/src/math/performance_testing/CMakeLists.txt @@ -4,28 +4,28 @@ add_library( Timer.h ) -# A convenience target to build all differential tests. -add_custom_target(libc-math-differential-tests) +# A convenience target to build all performance tests. +add_custom_target(libc-math-performance-tests) -function(add_diff_binary target_name) +function(add_perf_binary target_name) cmake_parse_arguments( - "DIFF" + "PERF" "" # No optional arguments "SUITE;CXX_STANDARD" # Single value arguments "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS" # Multi-value arguments ${ARGN} ) - if(NOT DIFF_SRCS) - message(FATAL_ERROR "'add_diff_binary' target requires a SRCS list of .cpp " + if(NOT PERF_SRCS) + message(FATAL_ERROR "'add_perf_binary' target requires a SRCS list of .cpp " "files.") endif() - if(NOT DIFF_DEPENDS) - message(FATAL_ERROR "'add_diff_binary' target requires a DEPENDS list of " + if(NOT PERF_DEPENDS) + message(FATAL_ERROR "'add_perf_binary' target requires a DEPENDS list of " "'add_entrypoint_object' targets.") endif() get_fq_target_name(${target_name} fq_target_name) - get_fq_deps_list(fq_deps_list ${DIFF_DEPENDS}) + get_fq_deps_list(fq_deps_list ${PERF_DEPENDS}) get_object_files_for_test( link_object_files skipped_entrypoints_list ${fq_deps_list}) if(skipped_entrypoints_list) @@ -40,18 +40,18 @@ function(add_diff_binary target_name) add_executable( ${fq_target_name} EXCLUDE_FROM_ALL - ${DIFF_SRCS} - ${DIFF_HDRS} + ${PERF_SRCS} + ${PERF_HDRS} ) target_include_directories( ${fq_target_name} PRIVATE ${LIBC_SOURCE_DIR} ) - if(DIFF_COMPILE_OPTIONS) + if(PERF_COMPILE_OPTIONS) target_compile_options( ${fq_target_name} - PRIVATE ${DIFF_COMPILE_OPTIONS} + PRIVATE ${PERF_COMPILE_OPTIONS} ) endif() @@ -62,11 +62,11 @@ function(add_diff_binary target_name) set_target_properties(${fq_target_name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - if(DIFF_CXX_STANDARD) + if(PERF_CXX_STANDARD) set_target_properties( ${fq_target_name} PROPERTIES - CXX_STANDARD ${DIFF_CXX_STANDARD} + CXX_STANDARD ${PERF_CXX_STANDARD} ) endif() @@ -75,31 +75,22 @@ function(add_diff_binary target_name) libc.src.__support.FPUtil.fp_bits ${fq_deps_list} ) - add_dependencies(libc-math-differential-tests ${fq_target_name}) + add_dependencies(libc-math-performance-tests ${fq_target_name}) endfunction() add_header_library( single_input_single_output_diff HDRS - SingleInputSingleOutputDiff.h + SingleInputSingleOutputPerf.h ) add_header_library( binary_op_single_output_diff HDRS - BinaryOpSingleOutputDiff.h + BinaryOpSingleOutputPerf.h ) -add_diff_binary( - sinf_diff - SRCS - sinf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.sinf -) - -add_diff_binary( +add_perf_binary( sinf_perf SRCS sinf_perf.cpp @@ -110,16 +101,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - cosf_diff - SRCS - cosf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.cosf -) - -add_diff_binary( +add_perf_binary( cosf_perf SRCS cosf_perf.cpp @@ -130,16 +112,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - expm1f_diff - SRCS - expm1f_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.expm1f -) - -add_diff_binary( +add_perf_binary( expm1f_perf SRCS expm1f_perf.cpp @@ -150,16 +123,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - ceilf_diff - SRCS - ceilf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.ceilf -) - -add_diff_binary( +add_perf_binary( ceilf_perf SRCS ceilf_perf.cpp @@ -170,16 +134,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - exp2f_diff - SRCS - exp2f_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.exp2f -) - -add_diff_binary( +add_perf_binary( exp2f_perf SRCS exp2f_perf.cpp @@ -190,16 +145,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - expf_diff - SRCS - expf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.expf -) - -add_diff_binary( +add_perf_binary( expf_perf SRCS expf_perf.cpp @@ -210,16 +156,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - fabsf_diff - SRCS - fabsf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.fabsf -) - -add_diff_binary( +add_perf_binary( fabsf_perf SRCS fabsf_perf.cpp @@ -230,16 +167,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - floorf_diff - SRCS - floorf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.floorf -) - -add_diff_binary( +add_perf_binary( floorf_perf SRCS floorf_perf.cpp @@ -250,7 +178,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( +add_perf_binary( log10f_perf SRCS log10f_perf.cpp @@ -261,7 +189,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( +add_perf_binary( log1pf_perf SRCS log1pf_perf.cpp @@ -272,18 +200,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - log2f_diff - SRCS - log2f_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.log2f - COMPILE_OPTIONS - -fno-builtin -) - -add_diff_binary( +add_perf_binary( log2f_perf SRCS log2f_perf.cpp @@ -294,18 +211,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - logf_diff - SRCS - logf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.logf - COMPILE_OPTIONS - -fno-builtin -) - -add_diff_binary( +add_perf_binary( logf_perf SRCS logf_perf.cpp @@ -316,16 +222,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - logbf_diff - SRCS - logbf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.logbf -) - -add_diff_binary( +add_perf_binary( logbf_perf SRCS logbf_perf.cpp @@ -336,16 +233,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - nearbyintf_diff - SRCS - nearbyintf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.nearbyintf -) - -add_diff_binary( +add_perf_binary( nearbyintf_perf SRCS nearbyintf_perf.cpp @@ -356,16 +244,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - rintf_diff - SRCS - rintf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.rintf -) - -add_diff_binary( +add_perf_binary( rintf_perf SRCS rintf_perf.cpp @@ -376,16 +255,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - roundf_diff - SRCS - roundf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.roundf -) - -add_diff_binary( +add_perf_binary( roundf_perf SRCS roundf_perf.cpp @@ -396,16 +266,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - sqrtf_diff - SRCS - sqrtf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.sqrtf -) - -add_diff_binary( +add_perf_binary( sqrtf_perf SRCS sqrtf_perf.cpp @@ -416,16 +277,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - truncf_diff - SRCS - truncf_diff.cpp - DEPENDS - .single_input_single_output_diff - libc.src.math.truncf -) - -add_diff_binary( +add_perf_binary( truncf_perf SRCS truncf_perf.cpp @@ -436,18 +288,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - hypotf_diff - SRCS - hypotf_diff.cpp - DEPENDS - .binary_op_single_output_diff - libc.src.math.hypotf - COMPILE_OPTIONS - -fno-builtin -) - -add_diff_binary( +add_perf_binary( hypotf_perf SRCS hypotf_perf.cpp @@ -458,18 +299,7 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - hypot_diff - SRCS - hypot_diff.cpp - DEPENDS - .binary_op_single_output_diff - libc.src.math.hypot - COMPILE_OPTIONS - -fno-builtin -) - -add_diff_binary( +add_perf_binary( hypot_perf SRCS hypot_perf.cpp @@ -480,42 +310,46 @@ add_diff_binary( -fno-builtin ) -add_diff_binary( - fmodf_diff +add_perf_binary( + fmodf_perf SRCS - fmodf_diff.cpp + fmodf_perf.cpp DEPENDS .single_input_single_output_diff libc.src.math.fmodf + COMPILE_OPTIONS + -fno-builtin ) -add_diff_binary( - fmodf_perf +add_perf_binary( + fmod_perf SRCS - fmodf_perf.cpp + fmod_perf.cpp DEPENDS .single_input_single_output_diff - libc.src.math.fmodf + libc.src.math.fmod COMPILE_OPTIONS -fno-builtin ) -add_diff_binary( - fmod_diff +add_perf_binary( + fmodl_perf SRCS - fmod_diff.cpp + fmodl_perf.cpp DEPENDS .single_input_single_output_diff - libc.src.math.fmod + libc.src.math.fmodl + COMPILE_OPTIONS + -fno-builtin ) -add_diff_binary( - fmod_perf +add_perf_binary( + fmodf128_perf SRCS - fmod_perf.cpp + fmodf128_perf.cpp DEPENDS .single_input_single_output_diff - libc.src.math.fmod + libc.src.math.fmodf128 COMPILE_OPTIONS -fno-builtin ) diff --git a/libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h b/libc/test/src/math/performance_testing/SingleInputSingleOutputPerf.h similarity index 64% rename from libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h rename to libc/test/src/math/performance_testing/SingleInputSingleOutputPerf.h index 5e8310e889dc67079ad830cacfb70350447645a4..b5b38313a69ca9fcf1da8976da339ef17ad83c69 100644 --- a/libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h +++ b/libc/test/src/math/performance_testing/SingleInputSingleOutputPerf.h @@ -7,14 +7,14 @@ //===----------------------------------------------------------------------===// #include "src/__support/FPUtil/FPBits.h" -#include "test/src/math/differential_testing/Timer.h" +#include "test/src/math/performance_testing/Timer.h" #include namespace LIBC_NAMESPACE { namespace testing { -template class SingleInputSingleOutputDiff { +template class SingleInputSingleOutputPerf { using FPBits = fputil::FPBits; using StorageType = typename FPBits::StorageType; static constexpr StorageType UIntMax = @@ -23,40 +23,18 @@ template class SingleInputSingleOutputDiff { public: typedef T Func(T); - static void runDiff(Func myFunc, Func otherFunc, const char *logFile) { - StorageType diffCount = 0; - std::ofstream log(logFile); - log << "Starting diff for values from 0 to " << UIntMax << '\n' - << "Only differing results will be logged.\n\n"; - for (StorageType bits = 0;; ++bits) { - T x = T(FPBits(bits)); - T myResult = myFunc(x); - T otherResult = otherFunc(x); - StorageType myBits = FPBits(myResult).uintval(); - StorageType otherBits = FPBits(otherResult).uintval(); - if (myBits != otherBits) { - ++diffCount; - log << " Input: " << bits << " (" << x << ")\n" - << " My result: " << myBits << " (" << myResult << ")\n" - << "Other result: " << otherBits << " (" << otherResult << ")\n" - << '\n'; - } - if (bits == UIntMax) - break; - } - log << "Total number of differing results: " << diffCount << '\n'; - } - static void runPerfInRange(Func myFunc, Func otherFunc, StorageType startingBit, StorageType endingBit, std::ofstream &log) { auto runner = [=](Func func) { + constexpr StorageType N = 10'010'001; + StorageType step = (endingBit - startingBit) / N; + if (step == 0) + step = 1; volatile T result; - for (StorageType bits = startingBit;; ++bits) { - T x = T(FPBits(bits)); + for (StorageType bits = startingBit; bits < endingBit; bits += step) { + T x = FPBits(bits).get_val(); result = func(x); - if (bits == endingBit) - break; } }; @@ -104,16 +82,9 @@ public: } // namespace testing } // namespace LIBC_NAMESPACE -#define SINGLE_INPUT_SINGLE_OUTPUT_DIFF(T, myFunc, otherFunc, filename) \ - int main() { \ - LIBC_NAMESPACE::testing::SingleInputSingleOutputDiff::runDiff( \ - &myFunc, &otherFunc, filename); \ - return 0; \ - } - #define SINGLE_INPUT_SINGLE_OUTPUT_PERF(T, myFunc, otherFunc, filename) \ int main() { \ - LIBC_NAMESPACE::testing::SingleInputSingleOutputDiff::runPerf( \ + LIBC_NAMESPACE::testing::SingleInputSingleOutputPerf::runPerf( \ &myFunc, &otherFunc, filename); \ return 0; \ } diff --git a/libc/test/src/math/differential_testing/Timer.cpp b/libc/test/src/math/performance_testing/Timer.cpp similarity index 100% rename from libc/test/src/math/differential_testing/Timer.cpp rename to libc/test/src/math/performance_testing/Timer.cpp diff --git a/libc/test/src/math/differential_testing/Timer.h b/libc/test/src/math/performance_testing/Timer.h similarity index 77% rename from libc/test/src/math/differential_testing/Timer.h rename to libc/test/src/math/performance_testing/Timer.h index 0d9518c37d9e0f7e128d5de90a957db694a38b44..2327ede260ab9d71d7ded9006e068be5a413e601 100644 --- a/libc/test/src/math/differential_testing/Timer.h +++ b/libc/test/src/math/performance_testing/Timer.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIBC_TEST_SRC_MATH_DIFFERENTIAL_TESTING_TIMER_H -#define LLVM_LIBC_TEST_SRC_MATH_DIFFERENTIAL_TESTING_TIMER_H +#ifndef LLVM_LIBC_TEST_SRC_MATH_PERFORMACE_TESTING_TIMER_H +#define LLVM_LIBC_TEST_SRC_MATH_PERFORMACE_TESTING_TIMER_H #include @@ -30,4 +30,4 @@ public: } // namespace testing } // namespace LIBC_NAMESPACE -#endif // LLVM_LIBC_TEST_SRC_MATH_DIFFERENTIAL_TESTING_TIMER_H +#endif // LLVM_LIBC_TEST_SRC_MATH_PERFORMANCE_TESTING_TIMER_H diff --git a/libc/test/src/math/differential_testing/ceilf_perf.cpp b/libc/test/src/math/performance_testing/ceilf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/ceilf_perf.cpp rename to libc/test/src/math/performance_testing/ceilf_perf.cpp index c304231e0678dee4e75b0697c956c6914b1cc591..04e96f6fb2dccce329c0448f01823452bb020c2c 100644 --- a/libc/test/src/math/differential_testing/ceilf_perf.cpp +++ b/libc/test/src/math/performance_testing/ceilf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/ceilf.h" diff --git a/libc/test/src/math/differential_testing/cosf_perf.cpp b/libc/test/src/math/performance_testing/cosf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/cosf_perf.cpp rename to libc/test/src/math/performance_testing/cosf_perf.cpp index 981a94133b8040641c2cdca8804a5e32b38170fe..1501b8bf25404432e549e6011e482190379e3e37 100644 --- a/libc/test/src/math/differential_testing/cosf_perf.cpp +++ b/libc/test/src/math/performance_testing/cosf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/cosf.h" diff --git a/libc/test/src/math/differential_testing/exp2f_perf.cpp b/libc/test/src/math/performance_testing/exp2f_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/exp2f_perf.cpp rename to libc/test/src/math/performance_testing/exp2f_perf.cpp index 4aae5220e6a51671a9bff2732e1cf89df30034bd..19a70ac6569aa4b29f43d6717f8a374d3cac8010 100644 --- a/libc/test/src/math/differential_testing/exp2f_perf.cpp +++ b/libc/test/src/math/performance_testing/exp2f_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/exp2f.h" diff --git a/libc/test/src/math/differential_testing/expf_perf.cpp b/libc/test/src/math/performance_testing/expf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/expf_perf.cpp rename to libc/test/src/math/performance_testing/expf_perf.cpp index c34173b21b4f60aec0e6a6f67416cc755afadddc..4b743514023d12d8017ee5a7c92f554b943f7048 100644 --- a/libc/test/src/math/differential_testing/expf_perf.cpp +++ b/libc/test/src/math/performance_testing/expf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/expf.h" diff --git a/libc/test/src/math/differential_testing/expm1f_perf.cpp b/libc/test/src/math/performance_testing/expm1f_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/expm1f_perf.cpp rename to libc/test/src/math/performance_testing/expm1f_perf.cpp index 3c25ef81d4808c351844ebebf185beae8b94d852..128ab351d86db1216052269fe0e4463c5089656b 100644 --- a/libc/test/src/math/differential_testing/expm1f_perf.cpp +++ b/libc/test/src/math/performance_testing/expm1f_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/expm1f.h" diff --git a/libc/test/src/math/differential_testing/fabsf_perf.cpp b/libc/test/src/math/performance_testing/fabsf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/fabsf_perf.cpp rename to libc/test/src/math/performance_testing/fabsf_perf.cpp index f9f9cea72c6dae822c7b159517edcddbd205c3ca..b6c6add75d230cb2237e92c9f6e21b0974d0d3ca 100644 --- a/libc/test/src/math/differential_testing/fabsf_perf.cpp +++ b/libc/test/src/math/performance_testing/fabsf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/fabsf.h" diff --git a/libc/test/src/math/differential_testing/floorf_perf.cpp b/libc/test/src/math/performance_testing/floorf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/floorf_perf.cpp rename to libc/test/src/math/performance_testing/floorf_perf.cpp index abd1cd7885ffd21fe6be0c8fe47e235c7370ed2f..0f1087b3c8236b275453b51db4673fb1fd2d1589 100644 --- a/libc/test/src/math/differential_testing/floorf_perf.cpp +++ b/libc/test/src/math/performance_testing/floorf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/floorf.h" diff --git a/libc/test/src/math/differential_testing/fmod_perf.cpp b/libc/test/src/math/performance_testing/fmod_perf.cpp similarity index 93% rename from libc/test/src/math/differential_testing/fmod_perf.cpp rename to libc/test/src/math/performance_testing/fmod_perf.cpp index 219ee7860a242be06a17d701404324eb04b74baa..fa9b4c6b41287b33df931a624c6935cfb58ace69 100644 --- a/libc/test/src/math/differential_testing/fmod_perf.cpp +++ b/libc/test/src/math/performance_testing/fmod_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "BinaryOpSingleOutputDiff.h" +#include "BinaryOpSingleOutputPerf.h" #include "src/math/fmod.h" diff --git a/libc/test/src/math/differential_testing/fmodf_diff.cpp b/libc/test/src/math/performance_testing/fmodf128_perf.cpp similarity index 62% rename from libc/test/src/math/differential_testing/fmodf_diff.cpp rename to libc/test/src/math/performance_testing/fmodf128_perf.cpp index 7029b1ee42cd0e7d6308d8c689de237e4814d7bf..8165e9254dd56121428c758d7a3226ddda11cf37 100644 --- a/libc/test/src/math/differential_testing/fmodf_diff.cpp +++ b/libc/test/src/math/performance_testing/fmodf128_perf.cpp @@ -1,4 +1,4 @@ -//===-- Differential test for fmodf ---------------------------------------===// +//===-- Differential test for fmodf128 ------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -8,9 +8,9 @@ #include "BinaryOpSingleOutputDiff.h" -#include "src/math/fmodf.h" +#include "src/math/fmodf128.h" #include -BINARY_OP_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::fmodf, ::fmodf, - "fmodf_diff.log") +BINARY_OP_SINGLE_OUTPUT_PERF(float, LIBC_NAMESPACE::fmodf128, ::fmodf128, + "fmodf128_perf.log") diff --git a/libc/test/src/math/differential_testing/fmodf_perf.cpp b/libc/test/src/math/performance_testing/fmodf_perf.cpp similarity index 93% rename from libc/test/src/math/differential_testing/fmodf_perf.cpp rename to libc/test/src/math/performance_testing/fmodf_perf.cpp index c2927bb1ea9d9fe6c4f5ea3af2d125cd321444f9..f13f02e2439da34cac5a1ff0dc1dbf97094d77eb 100644 --- a/libc/test/src/math/differential_testing/fmodf_perf.cpp +++ b/libc/test/src/math/performance_testing/fmodf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "BinaryOpSingleOutputDiff.h" +#include "BinaryOpSingleOutputPerf.h" #include "src/math/fmodf.h" diff --git a/libc/test/src/math/differential_testing/fmod_diff.cpp b/libc/test/src/math/performance_testing/fmodl_perf.cpp similarity index 63% rename from libc/test/src/math/differential_testing/fmod_diff.cpp rename to libc/test/src/math/performance_testing/fmodl_perf.cpp index 026e529c6cae2a90337a1265b351750d393ff44e..aefdf2d6b42fcfc21c99fdfb80a3de21b2d3e7e8 100644 --- a/libc/test/src/math/differential_testing/fmod_diff.cpp +++ b/libc/test/src/math/performance_testing/fmodl_perf.cpp @@ -1,4 +1,4 @@ -//===-- Differential test for fmod ----------------------------------------===// +//===-- Differential test for fmodl ---------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -8,9 +8,9 @@ #include "BinaryOpSingleOutputDiff.h" -#include "src/math/fmod.h" +#include "src/math/fmodl.h" #include -BINARY_OP_SINGLE_OUTPUT_DIFF(double, LIBC_NAMESPACE::fmod, ::fmod, - "fmod_diff.log") +BINARY_OP_SINGLE_OUTPUT_PERF(long double, LIBC_NAMESPACE::fmodl, ::fmodl, + "fmodl_perf.log") diff --git a/libc/test/src/math/differential_testing/hypot_perf.cpp b/libc/test/src/math/performance_testing/hypot_perf.cpp similarity index 93% rename from libc/test/src/math/differential_testing/hypot_perf.cpp rename to libc/test/src/math/performance_testing/hypot_perf.cpp index 01a72e6fbc3d795a0f25a0760d81f8e3f93db7aa..393697b754033025262566050f570a0d9f3045ca 100644 --- a/libc/test/src/math/differential_testing/hypot_perf.cpp +++ b/libc/test/src/math/performance_testing/hypot_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "BinaryOpSingleOutputDiff.h" +#include "BinaryOpSingleOutputPerf.h" #include "src/math/hypot.h" diff --git a/libc/test/src/math/differential_testing/hypotf_perf.cpp b/libc/test/src/math/performance_testing/hypotf_perf.cpp similarity index 93% rename from libc/test/src/math/differential_testing/hypotf_perf.cpp rename to libc/test/src/math/performance_testing/hypotf_perf.cpp index ed57b186f889ba854100a0287c3b0baa8956aedd..f711729377dacfb91018b74d40ae79c37c2322ec 100644 --- a/libc/test/src/math/differential_testing/hypotf_perf.cpp +++ b/libc/test/src/math/performance_testing/hypotf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "BinaryOpSingleOutputDiff.h" +#include "BinaryOpSingleOutputPerf.h" #include "src/math/hypotf.h" diff --git a/libc/test/src/math/differential_testing/log10f_perf.cpp b/libc/test/src/math/performance_testing/log10f_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/log10f_perf.cpp rename to libc/test/src/math/performance_testing/log10f_perf.cpp index 60c1161a31cf963fcbdc0390c137b468d48dab04..32a31b932528556ce6c03102e8a7599d06a97cc0 100644 --- a/libc/test/src/math/differential_testing/log10f_perf.cpp +++ b/libc/test/src/math/performance_testing/log10f_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/log10f.h" diff --git a/libc/test/src/math/differential_testing/log1pf_perf.cpp b/libc/test/src/math/performance_testing/log1pf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/log1pf_perf.cpp rename to libc/test/src/math/performance_testing/log1pf_perf.cpp index 5cd523d82184cc3e5c8aa398356d320cb98b6cee..18c168423b87d149cc100d6a50bfb9a99caf0088 100644 --- a/libc/test/src/math/differential_testing/log1pf_perf.cpp +++ b/libc/test/src/math/performance_testing/log1pf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/log1pf.h" diff --git a/libc/test/src/math/differential_testing/log2f_perf.cpp b/libc/test/src/math/performance_testing/log2f_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/log2f_perf.cpp rename to libc/test/src/math/performance_testing/log2f_perf.cpp index ee899394c421edeb0fbaedde053a65d7e7742e3e..c4c4dbf4d9f554cddc909ea309631017131b050c 100644 --- a/libc/test/src/math/differential_testing/log2f_perf.cpp +++ b/libc/test/src/math/performance_testing/log2f_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/log2f.h" diff --git a/libc/test/src/math/differential_testing/logbf_perf.cpp b/libc/test/src/math/performance_testing/logbf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/logbf_perf.cpp rename to libc/test/src/math/performance_testing/logbf_perf.cpp index 89d5bd13f9316b63721b2effef7a6f3ae787cef3..eefd64b8ae913fc01c19f3ae37c36d13fb4d0bf0 100644 --- a/libc/test/src/math/differential_testing/logbf_perf.cpp +++ b/libc/test/src/math/performance_testing/logbf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/logbf.h" diff --git a/libc/test/src/math/differential_testing/logf_perf.cpp b/libc/test/src/math/performance_testing/logf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/logf_perf.cpp rename to libc/test/src/math/performance_testing/logf_perf.cpp index f1b3f986bd40a380f8a4ddea025117a00a9bfe9a..53f4f50e09efe4c0fcd7ec69f2a1fbb12d15c4e6 100644 --- a/libc/test/src/math/differential_testing/logf_perf.cpp +++ b/libc/test/src/math/performance_testing/logf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/logf.h" diff --git a/libc/test/src/math/differential_testing/nearbyintf_perf.cpp b/libc/test/src/math/performance_testing/nearbyintf_perf.cpp similarity index 93% rename from libc/test/src/math/differential_testing/nearbyintf_perf.cpp rename to libc/test/src/math/performance_testing/nearbyintf_perf.cpp index 9c5736fb4ab04809dc6f5849321075d29e2be8df..ae708dd21324328c4cbafa6e8a3d6a6cfdeff28d 100644 --- a/libc/test/src/math/differential_testing/nearbyintf_perf.cpp +++ b/libc/test/src/math/performance_testing/nearbyintf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/nearbyintf.h" diff --git a/libc/test/src/math/differential_testing/rintf_perf.cpp b/libc/test/src/math/performance_testing/rintf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/rintf_perf.cpp rename to libc/test/src/math/performance_testing/rintf_perf.cpp index 432e5da77f3789e4dd2234f28831fcf8d9c22704..6347ac9149af6e24e0a2b255b0479cf52defbad0 100644 --- a/libc/test/src/math/differential_testing/rintf_perf.cpp +++ b/libc/test/src/math/performance_testing/rintf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/rintf.h" diff --git a/libc/test/src/math/differential_testing/roundf_perf.cpp b/libc/test/src/math/performance_testing/roundf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/roundf_perf.cpp rename to libc/test/src/math/performance_testing/roundf_perf.cpp index 091c7b2b86800f4c4a1a1d392bfc70b6e5130ce8..36becacba07cb54baaee8cfa730aa6ff70410cd9 100644 --- a/libc/test/src/math/differential_testing/roundf_perf.cpp +++ b/libc/test/src/math/performance_testing/roundf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/roundf.h" diff --git a/libc/test/src/math/differential_testing/sinf_perf.cpp b/libc/test/src/math/performance_testing/sinf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/sinf_perf.cpp rename to libc/test/src/math/performance_testing/sinf_perf.cpp index 7247bca2853d881b25721fe5c0b4446861ed28e3..43ba60e1ef76a4f23f673df0b581ac9a4501c2e2 100644 --- a/libc/test/src/math/differential_testing/sinf_perf.cpp +++ b/libc/test/src/math/performance_testing/sinf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/sinf.h" diff --git a/libc/test/src/math/differential_testing/sqrtf_perf.cpp b/libc/test/src/math/performance_testing/sqrtf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/sqrtf_perf.cpp rename to libc/test/src/math/performance_testing/sqrtf_perf.cpp index 5ae586ba31267ddef5391985ca0502d7b8426db6..71325518533b60046bb7f92912e5ccc5fb4b219b 100644 --- a/libc/test/src/math/differential_testing/sqrtf_perf.cpp +++ b/libc/test/src/math/performance_testing/sqrtf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/sqrtf.h" diff --git a/libc/test/src/math/differential_testing/truncf_perf.cpp b/libc/test/src/math/performance_testing/truncf_perf.cpp similarity index 92% rename from libc/test/src/math/differential_testing/truncf_perf.cpp rename to libc/test/src/math/performance_testing/truncf_perf.cpp index e07db1320fddd79b157cbfba27e01f7e38d6e38f..ff74c6b4eb64df2f3f66113058887c2cbe0c6930 100644 --- a/libc/test/src/math/differential_testing/truncf_perf.cpp +++ b/libc/test/src/math/performance_testing/truncf_perf.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "SingleInputSingleOutputDiff.h" +#include "SingleInputSingleOutputPerf.h" #include "src/math/truncf.h" diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt index be1810944495b24aa7a656b8b8dbdbc5c08008fc..d9be172056a83387b124d3a8ac24a04f7d0a4fbc 100644 --- a/libc/test/src/math/smoke/CMakeLists.txt +++ b/libc/test/src/math/smoke/CMakeLists.txt @@ -387,6 +387,24 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + lroundf128_test + SUITE + libc-math-smoke-tests + SRCS + lroundf128_test.cpp + HDRS + RoundToIntegerTest.h + DEPENDS + libc.include.math + libc.src.errno.errno + libc.src.fenv.feclearexcept + libc.src.fenv.feraiseexcept + libc.src.fenv.fetestexcept + libc.src.math.lroundf128 + libc.src.__support.FPUtil.fp_bits +) + add_fp_unittest( llround_test SUITE @@ -441,6 +459,24 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + llroundf128_test + SUITE + libc-math-smoke-tests + SRCS + llroundf128_test.cpp + HDRS + RoundToIntegerTest.h + DEPENDS + libc.include.math + libc.src.errno.errno + libc.src.fenv.feclearexcept + libc.src.fenv.feraiseexcept + libc.src.fenv.fetestexcept + libc.src.math.llroundf128 + libc.src.__support.FPUtil.fp_bits +) + add_fp_unittest( rint_test SUITE @@ -486,6 +522,21 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + rintf128_test + SUITE + libc-math-smoke-tests + SRCS + rintf128_test.cpp + HDRS + RIntTest.h + DEPENDS + libc.include.math + libc.src.math.rintf128 + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits +) + add_fp_unittest( lrint_test SUITE @@ -531,6 +582,21 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + lrintf128_test + SUITE + libc-math-smoke-tests + SRCS + lrintf128_test.cpp + HDRS + RoundToIntegerTest.h + DEPENDS + libc.include.math + libc.src.math.lrintf128 + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits +) + add_fp_unittest( llrint_test SUITE @@ -576,6 +642,21 @@ add_fp_unittest( libc.src.__support.FPUtil.fp_bits ) +add_fp_unittest( + llrintf128_test + SUITE + libc-math-smoke-tests + SRCS + llrintf128_test.cpp + HDRS + RoundToIntegerTest.h + DEPENDS + libc.include.math + libc.src.math.llrintf128 + libc.src.__support.FPUtil.fenv_impl + libc.src.__support.FPUtil.fp_bits +) + add_fp_unittest( expf_test SUITE @@ -997,8 +1078,6 @@ add_fp_unittest( libc.src.math.modf libc.src.__support.FPUtil.basic_operations libc.src.__support.FPUtil.nearest_integer_operations - # Requires C++ limits. - UNIT_TEST_ONLY ) add_fp_unittest( @@ -1014,8 +1093,6 @@ add_fp_unittest( libc.src.math.modff libc.src.__support.FPUtil.basic_operations libc.src.__support.FPUtil.nearest_integer_operations - # Requires C++ limits. - UNIT_TEST_ONLY ) add_fp_unittest( @@ -1033,6 +1110,21 @@ add_fp_unittest( libc.src.__support.FPUtil.nearest_integer_operations ) +add_fp_unittest( + modff128_test + SUITE + libc-math-smoke-tests + SRCS + modff128_test.cpp + HDRS + ModfTest.h + DEPENDS + libc.include.math + libc.src.math.modff128 + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.nearest_integer_operations +) + add_fp_unittest( fdimf_test SUITE @@ -1701,6 +1793,42 @@ add_fp_unittest( UNIT_TEST_ONLY ) +add_fp_unittest( + fmodl_test + SUITE + libc-math-smoke-tests + SRCS + fmodl_test.cpp + HDRS + FModTest.h + DEPENDS + libc.include.math + libc.src.errno.errno + libc.src.math.fmodl + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.nearest_integer_operations + # FIXME: Currently fails on the GPU build. + UNIT_TEST_ONLY +) + +add_fp_unittest( + fmodf128_test + SUITE + libc-math-smoke-tests + SRCS + fmodf128_test.cpp + HDRS + FModTest.h + DEPENDS + libc.include.math + libc.src.errno.errno + libc.src.math.fmodf128 + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.nearest_integer_operations + # FIXME: Currently fails on the GPU build. + UNIT_TEST_ONLY +) + add_fp_unittest( coshf_test SUITE diff --git a/libc/test/src/math/smoke/ModfTest.h b/libc/test/src/math/smoke/ModfTest.h index a73e5ae4298faab857cd45ab6b08eb4b5e39c37c..d7e15a7ed68206cba0c0cc347ee2002d9dd8a205 100644 --- a/libc/test/src/math/smoke/ModfTest.h +++ b/libc/test/src/math/smoke/ModfTest.h @@ -84,10 +84,12 @@ public: constexpr StorageType COUNT = 100'000; constexpr StorageType STEP = STORAGE_MAX / COUNT; for (StorageType i = 0, v = 0; i <= COUNT; ++i, v += STEP) { - T x = FPBits(v).get_val(); - if (isnan(x) || isinf(x) || x == T(0.0)) + FPBits x_bits = FPBits(v); + if (x_bits.is_zero() || x_bits.is_inf_or_nan()) continue; + T x = x_bits.get_val(); + T integral; T frac = func(x, &integral); ASSERT_TRUE(LIBC_NAMESPACE::fputil::abs(frac) < 1.0l); diff --git a/clang/lib/AST/Interp/ByteCodeGenError.cpp b/libc/test/src/math/smoke/fmodf128_test.cpp similarity index 60% rename from clang/lib/AST/Interp/ByteCodeGenError.cpp rename to libc/test/src/math/smoke/fmodf128_test.cpp index 5fd3d77c38420034468a101a6e418c56fc0663ae..f75aadac8438640e82b29a95ae28ecf00bf5fc71 100644 --- a/clang/lib/AST/Interp/ByteCodeGenError.cpp +++ b/libc/test/src/math/smoke/fmodf128_test.cpp @@ -1,4 +1,4 @@ -//===--- ByteCodeGenError.h - Byte code generation error --------*- C++ -*-===// +//===-- Unittests for fmodf128 --------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,9 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "ByteCodeGenError.h" +#include "FModTest.h" -using namespace clang; -using namespace clang::interp; +#include "src/math/fmodf128.h" -char ByteCodeGenError::ID; +LIST_FMOD_TESTS(float128, LIBC_NAMESPACE::fmodf128) diff --git a/libc/test/src/math/smoke/fmodl_test.cpp b/libc/test/src/math/smoke/fmodl_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b69ed8ec85c84b9c42457d369ea23f19e942957f --- /dev/null +++ b/libc/test/src/math/smoke/fmodl_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for fmodl -----------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "FModTest.h" + +#include "src/math/fmodl.h" + +LIST_FMOD_TESTS(long double, LIBC_NAMESPACE::fmodl) diff --git a/libc/test/src/math/differential_testing/hypotf_diff.cpp b/libc/test/src/math/smoke/llrintf128_test.cpp similarity index 53% rename from libc/test/src/math/differential_testing/hypotf_diff.cpp rename to libc/test/src/math/smoke/llrintf128_test.cpp index d1c70fc2b6edbdc953febdcb0dfbb4e11f1fa63b..8847b2918e631e839d5c25d6b628ba6e7753cc8c 100644 --- a/libc/test/src/math/differential_testing/hypotf_diff.cpp +++ b/libc/test/src/math/smoke/llrintf128_test.cpp @@ -1,4 +1,4 @@ -//===-- Differential test for hypotf --------------------------------------===// +//===-- Unittests for llrintf128 ------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,11 +6,9 @@ // //===----------------------------------------------------------------------===// -#include "BinaryOpSingleOutputDiff.h" +#include "RoundToIntegerTest.h" -#include "src/math/hypotf.h" +#include "src/math/llrintf128.h" -#include - -BINARY_OP_SINGLE_OUTPUT_DIFF(float, LIBC_NAMESPACE::hypotf, ::hypotf, - "hypotf_diff.log") +LIST_ROUND_TO_INTEGER_TESTS_WITH_MODES(float128, long long, + LIBC_NAMESPACE::llrintf128) diff --git a/libc/test/src/math/smoke/llroundf128_test.cpp b/libc/test/src/math/smoke/llroundf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b00055e759f85f909e4b00e309b310d23b58af5b --- /dev/null +++ b/libc/test/src/math/smoke/llroundf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for llroundf128 -----------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "RoundToIntegerTest.h" + +#include "src/math/llroundf128.h" + +LIST_ROUND_TO_INTEGER_TESTS(float128, long long, LIBC_NAMESPACE::llroundf128) diff --git a/libc/test/src/math/smoke/lrintf128_test.cpp b/libc/test/src/math/smoke/lrintf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a559ccf0eda7220b3c5f6109835ea46094936a5c --- /dev/null +++ b/libc/test/src/math/smoke/lrintf128_test.cpp @@ -0,0 +1,14 @@ +//===-- Unittests for lrintf128 -------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "RoundToIntegerTest.h" + +#include "src/math/lrintf128.h" + +LIST_ROUND_TO_INTEGER_TESTS_WITH_MODES(float128, long, + LIBC_NAMESPACE::lrintf128) diff --git a/libc/test/src/math/smoke/lroundf128_test.cpp b/libc/test/src/math/smoke/lroundf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ed87c9af0489961d8c5468a42f146d03d0522111 --- /dev/null +++ b/libc/test/src/math/smoke/lroundf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for lroundf128 ------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "RoundToIntegerTest.h" + +#include "src/math/lroundf128.h" + +LIST_ROUND_TO_INTEGER_TESTS(float128, long, LIBC_NAMESPACE::lroundf128) diff --git a/libc/test/src/math/smoke/modff128_test.cpp b/libc/test/src/math/smoke/modff128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..062d40138e729362ed935b2f2077f8d2cb42321c --- /dev/null +++ b/libc/test/src/math/smoke/modff128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for modff128 --------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "ModfTest.h" + +#include "src/math/modff128.h" + +LIST_MODF_TESTS(float128, LIBC_NAMESPACE::modff128) diff --git a/libc/test/src/math/smoke/rintf128_test.cpp b/libc/test/src/math/smoke/rintf128_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..11078d795bac4d2f10c8cc2147eb67df91bc0546 --- /dev/null +++ b/libc/test/src/math/smoke/rintf128_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for rintf128 --------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "RIntTest.h" + +#include "src/math/rintf128.h" + +LIST_RINT_TESTS(float128, LIBC_NAMESPACE::rintf128) diff --git a/libc/test/src/stdbit/CMakeLists.txt b/libc/test/src/stdbit/CMakeLists.txt index a886ee4a35325d2b647cbedcecbead703bd11a4d..c3f8059d2d9b2a25d8b5340a34273e24161a1bb9 100644 --- a/libc/test/src/stdbit/CMakeLists.txt +++ b/libc/test/src/stdbit/CMakeLists.txt @@ -12,6 +12,9 @@ set(prefixes count_zeros count_ones has_single_bit + bit_width + bit_floor + bit_ceil ) set(suffixes c s i l ll) foreach(prefix IN LISTS prefixes) diff --git a/libc/test/src/stdbit/stdc_bit_ceil_uc_test.cpp b/libc/test/src/stdbit/stdc_bit_ceil_uc_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ef87b0d44de64e0be96cf4010e4f807b101fc75 --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_ceil_uc_test.cpp @@ -0,0 +1,34 @@ +//===-- Unittests for stdc_bit_ceil_uc ------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_ceil_uc.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitceilUcTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_uc(0U), + static_cast(1)); +} + +TEST(LlvmLibcStdcBitceilUcTest, Ones) { + for (unsigned i = 0U; i != UCHAR_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_uc(1U << i), + static_cast(1U << i)); +} + +TEST(LlvmLibcStdcBitceilUcTest, OneLessThanPowsTwo) { + for (unsigned i = 2U; i != UCHAR_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_uc((1U << i) - 1), + static_cast(1U << i)); +} + +TEST(LlvmLibcStdcBitceilUcTest, OneMoreThanPowsTwo) { + for (unsigned i = 1U; i != UCHAR_WIDTH - 1; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_uc((1U << i) + 1), + static_cast(1U << (i + 1))); +} diff --git a/libc/test/src/stdbit/stdc_bit_ceil_ui_test.cpp b/libc/test/src/stdbit/stdc_bit_ceil_ui_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b6f2a564ff15db5b59eebb0fba1be5c0549da8a --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_ceil_ui_test.cpp @@ -0,0 +1,30 @@ +//===-- Unittests for stdc_bit_ceil_ui ------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_ceil_ui.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitceilUiTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ui(0U), 1U); +} + +TEST(LlvmLibcStdcBitceilUiTest, Ones) { + for (unsigned i = 0U; i != UINT_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ui(1U << i), 1U << i); +} + +TEST(LlvmLibcStdcBitceilUiTest, OneLessThanPowsTwo) { + for (unsigned i = 2U; i != UINT_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ui((1U << i) - 1), 1U << i); +} + +TEST(LlvmLibcStdcBitceilUiTest, OneMoreThanPowsTwo) { + for (unsigned i = 1U; i != UINT_WIDTH - 1; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ui((1U << i) + 1), 1U << (i + 1)); +} diff --git a/libc/test/src/stdbit/stdc_bit_ceil_ul_test.cpp b/libc/test/src/stdbit/stdc_bit_ceil_ul_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d4dbb38ea02af6f14f15687fca46fe68e5418a6a --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_ceil_ul_test.cpp @@ -0,0 +1,30 @@ +//===-- Unittests for stdc_bit_ceil_ul ------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_ceil_ul.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitceilUlTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ul(0UL), 1UL); +} + +TEST(LlvmLibcStdcBitceilUlTest, Ones) { + for (unsigned i = 0U; i != ULONG_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ul(1UL << i), 1UL << i); +} + +TEST(LlvmLibcStdcBitceilUlTest, OneLessThanPowsTwo) { + for (unsigned i = 2U; i != ULONG_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ul((1UL << i) - 1), 1UL << i); +} + +TEST(LlvmLibcStdcBitceilUlTest, OneMoreThanPowsTwo) { + for (unsigned i = 1U; i != ULONG_WIDTH - 1; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ul((1UL << i) + 1), 1UL << (i + 1)); +} diff --git a/libc/test/src/stdbit/stdc_bit_ceil_ull_test.cpp b/libc/test/src/stdbit/stdc_bit_ceil_ull_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..762f4f0627e6a89e5e01ef006829c91be6902ce3 --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_ceil_ull_test.cpp @@ -0,0 +1,31 @@ +//===-- Unittests for stdc_bit_ceil_ull -----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_ceil_ull.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitceilUllTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ull(0ULL), 1ULL); +} + +TEST(LlvmLibcStdcBitceilUllTest, Ones) { + for (unsigned i = 0U; i != ULLONG_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ull(1ULL << i), 1ULL << i); +} + +TEST(LlvmLibcStdcBitceilUllTest, OneLessThanPowsTwo) { + for (unsigned i = 2U; i != ULLONG_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ull((1ULL << i) - 1), 1ULL << i); +} + +TEST(LlvmLibcStdcBitceilUllTest, OneMoreThanPowsTwo) { + for (unsigned i = 1U; i != ULLONG_WIDTH - 1; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_ull((1ULL << i) + 1), + 1ULL << (i + 1)); +} diff --git a/libc/test/src/stdbit/stdc_bit_ceil_us_test.cpp b/libc/test/src/stdbit/stdc_bit_ceil_us_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..56873c51828f10432709192b8e83dd81393d7062 --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_ceil_us_test.cpp @@ -0,0 +1,34 @@ +//===-- Unittests for stdc_bit_ceil_us ------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_ceil_us.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitceilUsTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_us(0U), + static_cast(1)); +} + +TEST(LlvmLibcStdcBitceilUsTest, Ones) { + for (unsigned i = 0U; i != USHRT_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_us(1U << i), + static_cast(1U << i)); +} + +TEST(LlvmLibcStdcBitceilUsTest, OneLessThanPowsTwo) { + for (unsigned i = 2U; i != USHRT_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_us((1U << i) - 1), + static_cast(1U << i)); +} + +TEST(LlvmLibcStdcBitceilUsTest, OneMoreThanPowsTwo) { + for (unsigned i = 1U; i != USHRT_WIDTH - 1; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_ceil_us((1U << i) + 1), + static_cast(1U << (i + 1))); +} diff --git a/libc/test/src/stdbit/stdc_bit_floor_uc_test.cpp b/libc/test/src/stdbit/stdc_bit_floor_uc_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..254abd043d6e0c3d07bae5126be8c722abd5afcd --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_floor_uc_test.cpp @@ -0,0 +1,22 @@ +//===-- Unittests for stdc_bit_floor_uc -----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_floor_uc.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitfloorUcTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_floor_uc(0U), + static_cast(0)); +} + +TEST(LlvmLibcStdcBitfloorUcTest, Ones) { + for (unsigned i = 0U; i != UCHAR_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_floor_uc(UCHAR_MAX >> i), + static_cast(1 << (UCHAR_WIDTH - i - 1))); +} diff --git a/libc/test/src/stdbit/stdc_bit_floor_ui_test.cpp b/libc/test/src/stdbit/stdc_bit_floor_ui_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53790402a9bda9906aef870ef809f8d254b58ad0 --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_floor_ui_test.cpp @@ -0,0 +1,21 @@ +//===-- Unittests for stdc_bit_floor_ui -----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_floor_ui.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitfloorUiTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_floor_ui(0U), 0U); +} + +TEST(LlvmLibcStdcBitfloorUiTest, Ones) { + for (unsigned i = 0U; i != INT_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_floor_ui(UINT_MAX >> i), + 1U << (UINT_WIDTH - i - 1)); +} diff --git a/libc/test/src/stdbit/stdc_bit_floor_ul_test.cpp b/libc/test/src/stdbit/stdc_bit_floor_ul_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c574437e02b796e8b8ec3073032c67d40c24312 --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_floor_ul_test.cpp @@ -0,0 +1,21 @@ +//===-- Unittests for stdc_bit_floor_ul -----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_floor_ul.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitfloorUlTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_floor_ul(0UL), 0UL); +} + +TEST(LlvmLibcStdcBitfloorUlTest, Ones) { + for (unsigned i = 0U; i != ULONG_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_floor_ul(ULONG_MAX >> i), + 1UL << (ULONG_WIDTH - i - 1)); +} diff --git a/libc/test/src/stdbit/stdc_bit_floor_ull_test.cpp b/libc/test/src/stdbit/stdc_bit_floor_ull_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4717d427a40a72203295291122ce978c9aa4f8b5 --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_floor_ull_test.cpp @@ -0,0 +1,21 @@ +//===-- Unittests for stdc_bit_floor_ull ----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_floor_ull.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitfloorUllTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_floor_ull(0ULL), 0ULL); +} + +TEST(LlvmLibcStdcBitfloorUllTest, Ones) { + for (unsigned i = 0U; i != ULLONG_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_floor_ull(ULLONG_MAX >> i), + 1ULL << (ULLONG_WIDTH - i - 1)); +} diff --git a/libc/test/src/stdbit/stdc_bit_floor_us_test.cpp b/libc/test/src/stdbit/stdc_bit_floor_us_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4df87fb079ba76d93e43a07526788794a06e92e0 --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_floor_us_test.cpp @@ -0,0 +1,22 @@ +//===-- Unittests for stdc_bit_floor_us -----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_floor_us.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitfloorUsTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_floor_us(0U), + static_cast(0)); +} + +TEST(LlvmLibcStdcBitfloorUsTest, Ones) { + for (unsigned i = 0U; i != USHRT_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_floor_us(USHRT_MAX >> i), + static_cast(1 << (USHRT_WIDTH - i - 1))); +} diff --git a/libc/test/src/stdbit/stdc_bit_width_uc_test.cpp b/libc/test/src/stdbit/stdc_bit_width_uc_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63c6503542b1f7e20a2fbd5893f0ad69bbd43101 --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_width_uc_test.cpp @@ -0,0 +1,21 @@ +//===-- Unittests for stdc_bit_width_uc -----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_width_uc.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitWidthUcTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_width_uc(0U), 0U); +} + +TEST(LlvmLibcStdcBitWidthUcTest, Ones) { + for (unsigned i = 0U; i != UCHAR_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_width_uc(UCHAR_MAX >> i), + UCHAR_WIDTH - i); +} diff --git a/libc/test/src/stdbit/stdc_bit_width_ui_test.cpp b/libc/test/src/stdbit/stdc_bit_width_ui_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..43acdde5dd2077f8c8b44cb450bc1a1e9cd0734f --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_width_ui_test.cpp @@ -0,0 +1,20 @@ +//===-- Unittests for stdc_bit_width_ui -----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_width_ui.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitWidthUiTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_width_ui(0U), 0U); +} + +TEST(LlvmLibcStdcBitWidthUiTest, Ones) { + for (unsigned i = 0U; i != UINT_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_width_ui(UINT_MAX >> i), UINT_WIDTH - i); +} diff --git a/libc/test/src/stdbit/stdc_bit_width_ul_test.cpp b/libc/test/src/stdbit/stdc_bit_width_ul_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0a286942655f6112f2c4f679f6ae5b575d6d1424 --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_width_ul_test.cpp @@ -0,0 +1,21 @@ +//===-- Unittests for stdc_bit_width_ul -----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_width_ul.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitWidthUlTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_width_ul(0U), 0U); +} + +TEST(LlvmLibcStdcBitWidthUlTest, Ones) { + for (unsigned i = 0U; i != ULONG_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_width_ul(ULONG_MAX >> i), + ULONG_WIDTH - i); +} diff --git a/libc/test/src/stdbit/stdc_bit_width_ull_test.cpp b/libc/test/src/stdbit/stdc_bit_width_ull_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..31475f6e6541beebba9058c3a75738d617eb56db --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_width_ull_test.cpp @@ -0,0 +1,21 @@ +//===-- Unittests for stdc_bit_width_ull ----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_width_ull.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitWidthUllTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_width_ull(0U), 0U); +} + +TEST(LlvmLibcStdcBitWidthUllTest, Ones) { + for (unsigned i = 0U; i != ULLONG_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_width_ull(ULLONG_MAX >> i), + ULLONG_WIDTH - i); +} diff --git a/libc/test/src/stdbit/stdc_bit_width_us_test.cpp b/libc/test/src/stdbit/stdc_bit_width_us_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..031c502f19c5eab75b4532fcb12f74ffbce951a3 --- /dev/null +++ b/libc/test/src/stdbit/stdc_bit_width_us_test.cpp @@ -0,0 +1,21 @@ +//===-- Unittests for stdc_bit_width_us -----------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/__support/CPP/limits.h" +#include "src/stdbit/stdc_bit_width_us.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcStdcBitWidthUsTest, Zero) { + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_width_us(0U), 0U); +} + +TEST(LlvmLibcStdcBitWidthUsTest, Ones) { + for (unsigned i = 0U; i != USHRT_WIDTH; ++i) + EXPECT_EQ(LIBC_NAMESPACE::stdc_bit_width_us(USHRT_MAX >> i), + USHRT_WIDTH - i); +} diff --git a/libc/test/src/stdbit/stdc_has_single_bit_uc_test.cpp b/libc/test/src/stdbit/stdc_has_single_bit_uc_test.cpp index 6212b1ec765a5df213e66cf1d22506ab387c53df..1bc189cf0b665fd4206b09e4cb845c52b63d3e1f 100644 --- a/libc/test/src/stdbit/stdc_has_single_bit_uc_test.cpp +++ b/libc/test/src/stdbit/stdc_has_single_bit_uc_test.cpp @@ -10,11 +10,11 @@ #include "src/stdbit/stdc_has_single_bit_uc.h" #include "test/UnitTest/Test.h" -TEST(LlvmLibcStdcCountOnesUcTest, Zero) { +TEST(LlvmLibcStdcHasSingleBitUcTest, Zero) { EXPECT_EQ(LIBC_NAMESPACE::stdc_has_single_bit_uc(0U), false); } -TEST(LlvmLibcStdcCountOnesUcTest, OneHot) { +TEST(LlvmLibcStdcHasSingleBitUcTest, OneHot) { for (unsigned i = 0U; i != UCHAR_WIDTH; ++i) EXPECT_EQ(LIBC_NAMESPACE::stdc_has_single_bit_uc(1U << i), true); } diff --git a/libc/test/src/stdbit/stdc_has_single_bit_ui_test.cpp b/libc/test/src/stdbit/stdc_has_single_bit_ui_test.cpp index 2e00507aa0258cd151ec430527d78a98a2c81bfe..c0b6abcf8fdc158a37b6bc7524ea432286cd8523 100644 --- a/libc/test/src/stdbit/stdc_has_single_bit_ui_test.cpp +++ b/libc/test/src/stdbit/stdc_has_single_bit_ui_test.cpp @@ -10,11 +10,11 @@ #include "src/stdbit/stdc_has_single_bit_ui.h" #include "test/UnitTest/Test.h" -TEST(LlvmLibcStdcCountOnesUiTest, Zero) { +TEST(LlvmLibcStdcHasSingleBitUiTest, Zero) { EXPECT_EQ(LIBC_NAMESPACE::stdc_has_single_bit_ui(0U), false); } -TEST(LlvmLibcStdcCountOnesUiTest, OneHot) { +TEST(LlvmLibcStdcHasSingleBitUiTest, OneHot) { for (unsigned i = 0U; i != UINT_WIDTH; ++i) EXPECT_EQ(LIBC_NAMESPACE::stdc_has_single_bit_ui(1U << i), true); } diff --git a/libc/test/src/stdbit/stdc_has_single_bit_ul_test.cpp b/libc/test/src/stdbit/stdc_has_single_bit_ul_test.cpp index 8c0178998bbec16a4a005830945b826be34b64ba..4c29fff748e98d029bf358948e159ed33a094aa6 100644 --- a/libc/test/src/stdbit/stdc_has_single_bit_ul_test.cpp +++ b/libc/test/src/stdbit/stdc_has_single_bit_ul_test.cpp @@ -10,11 +10,11 @@ #include "src/stdbit/stdc_has_single_bit_ul.h" #include "test/UnitTest/Test.h" -TEST(LlvmLibcStdcCountOnesUlTest, Zero) { +TEST(LlvmLibcStdcHasSingleBitUlTest, Zero) { EXPECT_EQ(LIBC_NAMESPACE::stdc_has_single_bit_ul(0U), false); } -TEST(LlvmLibcStdcCountOnesUlTest, OneHot) { +TEST(LlvmLibcStdcHasSingleBitUlTest, OneHot) { for (unsigned i = 0U; i != ULONG_WIDTH; ++i) EXPECT_EQ(LIBC_NAMESPACE::stdc_has_single_bit_ul(1UL << i), true); } diff --git a/libc/test/src/stdbit/stdc_has_single_bit_ull_test.cpp b/libc/test/src/stdbit/stdc_has_single_bit_ull_test.cpp index 1d9f976b6d63388877acab7565a10086e8309e03..59716468cc7080086247ba988ca2f2aca8fc9556 100644 --- a/libc/test/src/stdbit/stdc_has_single_bit_ull_test.cpp +++ b/libc/test/src/stdbit/stdc_has_single_bit_ull_test.cpp @@ -10,11 +10,11 @@ #include "src/stdbit/stdc_has_single_bit_ull.h" #include "test/UnitTest/Test.h" -TEST(LlvmLibcStdcCountOnesUllTest, Zero) { +TEST(LlvmLibcStdcHasSingleBitUllTest, Zero) { EXPECT_EQ(LIBC_NAMESPACE::stdc_has_single_bit_ull(0U), false); } -TEST(LlvmLibcStdcCountOnesUllTest, OneHot) { +TEST(LlvmLibcStdcHasSingleBitUllTest, OneHot) { for (unsigned i = 0U; i != ULLONG_WIDTH; ++i) EXPECT_EQ(LIBC_NAMESPACE::stdc_has_single_bit_ull(1ULL << i), true); } diff --git a/libc/test/src/stdbit/stdc_has_single_bit_us_test.cpp b/libc/test/src/stdbit/stdc_has_single_bit_us_test.cpp index 52c4de88104459150785720f3c98c58c0485cdf2..a038f6fac012323872d8f17f983b57d026dac194 100644 --- a/libc/test/src/stdbit/stdc_has_single_bit_us_test.cpp +++ b/libc/test/src/stdbit/stdc_has_single_bit_us_test.cpp @@ -10,11 +10,11 @@ #include "src/stdbit/stdc_has_single_bit_us.h" #include "test/UnitTest/Test.h" -TEST(LlvmLibcStdcCountOnesUsTest, Zero) { +TEST(LlvmLibcStdcHasSingleBitUsTest, Zero) { EXPECT_EQ(LIBC_NAMESPACE::stdc_has_single_bit_us(0U), false); } -TEST(LlvmLibcStdcCountOnesUsTest, OneHot) { +TEST(LlvmLibcStdcHasSingleBitUsTest, OneHot) { for (unsigned i = 0U; i != USHRT_WIDTH; ++i) EXPECT_EQ(LIBC_NAMESPACE::stdc_has_single_bit_us(1U << i), true); } diff --git a/libc/test/src/stdfix/CMakeLists.txt b/libc/test/src/stdfix/CMakeLists.txt index 4140b5b29f3b3ca75038cf24d67f1c9f46e54e29..74a1fb13127cc3da10e0d52e4dd0ca46db6b1ebe 100644 --- a/libc/test/src/stdfix/CMakeLists.txt +++ b/libc/test/src/stdfix/CMakeLists.txt @@ -15,7 +15,6 @@ foreach(suffix IN ITEMS hr r lr hk k lk) abs${suffix}_test.cpp COMPILE_OPTIONS -O3 - -ffixed-point DEPENDS libc.src.stdfix.abs${suffix} libc.src.__support.fixed_point.fx_bits @@ -33,7 +32,6 @@ foreach(suffix IN ITEMS uhr ur ulr uhk uk) sqrt${suffix}_test.cpp COMPILE_OPTIONS -O3 - -ffixed-point DEPENDS libc.src.stdfix.sqrt${suffix} libc.src.__support.CPP.bit @@ -55,9 +53,82 @@ foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk) round${suffix}_test.cpp COMPILE_OPTIONS -O3 - -ffixed-point DEPENDS libc.src.stdfix.round${suffix} libc.src.__support.fixed_point.fx_bits ) endforeach() + +add_libc_test( + uhksqrtus_test + SUITE + libc-stdfix-tests + HDRS + ISqrtTest.h + SRCS + uhksqrtus_test.cpp + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.stdfix.uhksqrtus + libc.src.__support.CPP.bit + libc.src.__support.fixed_point.fx_rep + libc.src.__support.fixed_point.sqrt + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.sqrt +) + +add_libc_test( + uksqrtui_test + SUITE + libc-stdfix-tests + HDRS + ISqrtTest.h + SRCS + uksqrtui_test.cpp + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.stdfix.uksqrtui + libc.src.__support.CPP.bit + libc.src.__support.fixed_point.fx_rep + libc.src.__support.fixed_point.sqrt + libc.src.__support.FPUtil.basic_operations + libc.src.__support.FPUtil.sqrt +) + +add_libc_test( + exphk_test + SUITE + libc-stdfix-tests + HDRS + ExpTest.h + SRCS + exphk_test.cpp + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.stdfix.exphk + libc.src.math.exp + libc.src.__support.CPP.bit + libc.src.__support.fixed_point.fx_rep + libc.src.__support.FPUtil.basic_operations +) + +add_libc_test( + expk_test + SUITE + libc-stdfix-tests + HDRS + ExpTest.h + SRCS + expk_test.cpp + COMPILE_OPTIONS + -O3 + DEPENDS + libc.src.stdfix.expk + libc.src.math.exp + libc.src.__support.CPP.bit + libc.src.__support.fixed_point.fx_rep + libc.src.__support.FPUtil.basic_operations +) diff --git a/libc/test/src/stdfix/ExpTest.h b/libc/test/src/stdfix/ExpTest.h new file mode 100644 index 0000000000000000000000000000000000000000..e588cebf621b902d7572f9b01e15ccb2a9c3a893 --- /dev/null +++ b/libc/test/src/stdfix/ExpTest.h @@ -0,0 +1,77 @@ +//===-- Utility class to test integer sqrt ----------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/fixed_point/fx_rep.h" +#include "src/__support/fixed_point/sqrt.h" + +#include "src/math/exp.h" + +template class ExpTest : public LIBC_NAMESPACE::testing::Test { + + using FXRep = LIBC_NAMESPACE::fixed_point::FXRep; + static constexpr T zero = FXRep::ZERO(); + static constexpr T one = static_cast(1); + static constexpr T eps = FXRep::EPS(); + +public: + typedef T (*ExpFunc)(T); + + void test_special_numbers(ExpFunc func) { + EXPECT_EQ(one, func(T(0))); + EXPECT_EQ(FXRep::MAX(), func(T(30))); + EXPECT_EQ(zero, func(T(-30))); + } + + void test_range_with_step(ExpFunc func, T step, bool rel_error) { + constexpr int COUNT = 255; + constexpr double ERR = 3.0 * static_cast(eps); + double x_d = 0.0; + T x = step; + for (int i = 0; i < COUNT; ++i) { + x += step; + x_d = static_cast(x); + double y_d = static_cast(func(x)); + double result = LIBC_NAMESPACE::exp(x_d); + double errors = rel_error + ? LIBC_NAMESPACE::fputil::abs((y_d / result) - 1.0) + : LIBC_NAMESPACE::fputil::abs(y_d - result); + if (errors > ERR) { + // Print out the failure input and output. + EXPECT_EQ(x, T(0)); + EXPECT_EQ(func(x), zero); + } + ASSERT_TRUE(errors <= ERR); + } + } + + void test_positive_range(ExpFunc func) { + test_range_with_step(func, T(0x1.0p-6), /*rel_error*/ true); + } + + void test_negative_range(ExpFunc func) { + test_range_with_step(func, T(-0x1.0p-6), /*rel_error*/ false); + } +}; + +#define LIST_EXP_TESTS(Name, T, func) \ + using LlvmLibcExp##Name##Test = ExpTest; \ + TEST_F(LlvmLibcExp##Name##Test, SpecialNumbers) { \ + test_special_numbers(&func); \ + } \ + TEST_F(LlvmLibcExp##Name##Test, PositiveRange) { \ + test_positive_range(&func); \ + } \ + TEST_F(LlvmLibcExp##Name##Test, NegativeRange) { \ + test_negative_range(&func); \ + } \ + static_assert(true, "Require semicolon.") diff --git a/libc/test/src/stdfix/ISqrtTest.h b/libc/test/src/stdfix/ISqrtTest.h new file mode 100644 index 0000000000000000000000000000000000000000..405162b706a9f1caf1b48256a1ec5ccc047c63ae --- /dev/null +++ b/libc/test/src/stdfix/ISqrtTest.h @@ -0,0 +1,63 @@ +//===-- Utility class to test integer sqrt ----------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "test/UnitTest/FPMatcher.h" +#include "test/UnitTest/Test.h" + +#include "src/__support/CPP/bit.h" +#include "src/__support/FPUtil/BasicOperations.h" +#include "src/__support/FPUtil/sqrt.h" +#include "src/__support/fixed_point/fx_rep.h" +#include "src/__support/fixed_point/sqrt.h" + +template class ISqrtTest : public LIBC_NAMESPACE::testing::Test { + + using OutType = + typename LIBC_NAMESPACE::fixed_point::internal::SqrtConfig::OutType; + using FXRep = LIBC_NAMESPACE::fixed_point::FXRep; + static constexpr OutType zero = FXRep::ZERO(); + static constexpr OutType one = static_cast(1); + static constexpr OutType eps = FXRep::EPS(); + +public: + typedef OutType (*SqrtFunc)(T); + + void testSpecialNumbers(SqrtFunc func) { + EXPECT_EQ(zero, func(T(0))); + + EXPECT_EQ(one, func(T(1))); + EXPECT_EQ(static_cast(2.0), func(T(4))); + EXPECT_EQ(static_cast(4.0), func(T(16))); + EXPECT_EQ(static_cast(16.0), func(T(256))); + + constexpr int COUNT = 255; + constexpr double ERR = 3.0 * static_cast(eps); + double x_d = 0.0; + T x = 0; + for (int i = 0; i < COUNT; ++i) { + x_d += 1.0; + ++x; + double y_d = static_cast(func(x)); + double result = LIBC_NAMESPACE::fputil::sqrt(x_d); + double errors = LIBC_NAMESPACE::fputil::abs((y_d / result) - 1.0); + if (errors > ERR) { + // Print out the failure input and output. + EXPECT_EQ(x, T(0)); + EXPECT_EQ(func(x), zero); + } + ASSERT_TRUE(errors <= ERR); + } + } +}; + +#define LIST_ISQRT_TESTS(Name, T, func) \ + using LlvmLibcISqrt##Name##Test = ISqrtTest; \ + TEST_F(LlvmLibcISqrt##Name##Test, SpecialNumbers) { \ + testSpecialNumbers(&func); \ + } \ + static_assert(true, "Require semicolon.") diff --git a/libc/test/src/stdfix/RoundTest.h b/libc/test/src/stdfix/RoundTest.h index 06343addbef20e7eaf4e4cf5bac0a85c1216f3b4..d3ae04db9749ba517d83b114734a69a81ad46b53 100644 --- a/libc/test/src/stdfix/RoundTest.h +++ b/libc/test/src/stdfix/RoundTest.h @@ -28,7 +28,7 @@ public: void testSpecialNumbers(RoundFunc func) { EXPECT_EQ(zero, func(zero, FXRep::FRACTION_LEN - 5)); - EXPECT_EQ(max, func(min, 0)); + EXPECT_EQ(min, func(min, 0)); EXPECT_EQ(max, func(max, FXRep::FRACTION_LEN)); EXPECT_EQ(one, func(half, 0)); diff --git a/libc/test/src/stdfix/exphk_test.cpp b/libc/test/src/stdfix/exphk_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..24e92dc902faea1dad38d02cdc0f817495c03865 --- /dev/null +++ b/libc/test/src/stdfix/exphk_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for exphk -----------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "ExpTest.h" + +#include "src/stdfix/exphk.h" + +LIST_EXP_TESTS(hk, short accum, LIBC_NAMESPACE::exphk); diff --git a/libc/test/src/stdfix/expk_test.cpp b/libc/test/src/stdfix/expk_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc322037af04a7da2345daffb488e4e04d34d03b --- /dev/null +++ b/libc/test/src/stdfix/expk_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for expk ------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "ExpTest.h" + +#include "src/stdfix/expk.h" + +LIST_EXP_TESTS(k, accum, LIBC_NAMESPACE::expk); diff --git a/libc/test/src/stdfix/uhksqrtus_test.cpp b/libc/test/src/stdfix/uhksqrtus_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a33297413980de63898907fa9dac0c003f84b0b8 --- /dev/null +++ b/libc/test/src/stdfix/uhksqrtus_test.cpp @@ -0,0 +1,20 @@ +//===-- Unittests for uhksqrtus -------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "ISqrtTest.h" + +#include "src/__support/fixed_point/sqrt.h" +#include "src/stdfix/uhksqrtus.h" + +unsigned short accum uhksqrtus_fast(unsigned short x) { + return LIBC_NAMESPACE::fixed_point::isqrt_fast(x); +} + +LIST_ISQRT_TESTS(US, unsigned short, LIBC_NAMESPACE::uhksqrtus); + +LIST_ISQRT_TESTS(USFast, unsigned short, uhksqrtus_fast); diff --git a/libc/test/src/stdfix/uksqrtui_test.cpp b/libc/test/src/stdfix/uksqrtui_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f4c057099daaf30a4d03e61089137501b085fa1 --- /dev/null +++ b/libc/test/src/stdfix/uksqrtui_test.cpp @@ -0,0 +1,20 @@ +//===-- Unittests for uksqrtui --------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "ISqrtTest.h" + +#include "src/__support/fixed_point/sqrt.h" +#include "src/stdfix/uksqrtui.h" + +unsigned accum uksqrtui_fast(unsigned int x) { + return LIBC_NAMESPACE::fixed_point::isqrt_fast(x); +} + +LIST_ISQRT_TESTS(UI, unsigned int, LIBC_NAMESPACE::uksqrtui); + +LIST_ISQRT_TESTS(UIFast, unsigned int, uksqrtui_fast); diff --git a/libc/test/src/string/CMakeLists.txt b/libc/test/src/string/CMakeLists.txt index 6088289532d771da1195cceb58f9a7209d56b07f..c1caec5fd912c82f810e8ba584dd9d3417eb75ea 100644 --- a/libc/test/src/string/CMakeLists.txt +++ b/libc/test/src/string/CMakeLists.txt @@ -418,6 +418,16 @@ add_libc_test( libc.src.string.strxfrm ) +add_libc_test( + memset_explicit_test + SUITE + libc-string-tests + SRCS + memset_explicit_test.cpp + DEPENDS + libc.src.string.memset_explicit +) + # Tests all implementations that can run on the target CPU. function(add_libc_multi_impl_test name) get_property(fq_implementations GLOBAL PROPERTY ${name}_implementations) diff --git a/libc/test/src/string/memory_utils/CMakeLists.txt b/libc/test/src/string/memory_utils/CMakeLists.txt index 567f85e37bfab49c044005ed8be5c627b768583e..a0dddd2f97b585cdac1bb874f7a353962ac44780 100644 --- a/libc/test/src/string/memory_utils/CMakeLists.txt +++ b/libc/test/src/string/memory_utils/CMakeLists.txt @@ -12,6 +12,7 @@ add_libc_test( libc.src.__support.CPP.array libc.src.__support.CPP.cstddef libc.src.__support.CPP.span + libc.src.__support.macros.properties.types libc.src.__support.macros.sanitizer libc.src.string.memory_utils.memory_utils UNIT_TEST_ONLY diff --git a/libc/test/src/string/memory_utils/op_tests.cpp b/libc/test/src/string/memory_utils/op_tests.cpp index 15ac9607bf3e3df72396d040107b360e314a371b..703a26b16b03f0a53390e1df0be0c31c62400688 100644 --- a/libc/test/src/string/memory_utils/op_tests.cpp +++ b/libc/test/src/string/memory_utils/op_tests.cpp @@ -7,9 +7,10 @@ //===----------------------------------------------------------------------===// #include "memory_check_utils.h" +#include "src/__support/macros/properties/types.h" // LIBC_TYPES_HAS_INT64 #include "src/string/memory_utils/op_aarch64.h" #include "src/string/memory_utils/op_builtin.h" -#include "src/string/memory_utils/op_generic.h" // LLVM_LIBC_HAS_UINT64 +#include "src/string/memory_utils/op_generic.h" #include "src/string/memory_utils/op_riscv.h" #include "src/string/memory_utils/op_x86.h" #include "test/UnitTest/Test.h" @@ -124,9 +125,9 @@ using MemsetImplementations = testing::TypeList< builtin::Memset<32>, // builtin::Memset<64>, #endif -#ifdef LLVM_LIBC_HAS_UINT64 +#ifdef LIBC_TYPES_HAS_INT64 generic::Memset, generic::Memset>, -#endif +#endif // LIBC_TYPES_HAS_INT64 #ifdef __AVX512F__ generic::Memset, generic::Memset>, #endif @@ -210,9 +211,9 @@ using BcmpImplementations = testing::TypeList< #ifndef LIBC_TARGET_ARCH_IS_ARM // Removing non uint8_t types for ARM generic::Bcmp, generic::Bcmp, // -#ifdef LLVM_LIBC_HAS_UINT64 +#ifdef LIBC_TYPES_HAS_INT64 generic::Bcmp, -#endif // LLVM_LIBC_HAS_UINT64 +#endif // LIBC_TYPES_HAS_INT64 generic::BcmpSequence, generic::BcmpSequence, // generic::BcmpSequence, // @@ -292,9 +293,9 @@ using MemcmpImplementations = testing::TypeList< #ifndef LIBC_TARGET_ARCH_IS_ARM // Removing non uint8_t types for ARM generic::Memcmp, generic::Memcmp, // -#ifdef LLVM_LIBC_HAS_UINT64 +#ifdef LIBC_TYPES_HAS_INT64 generic::Memcmp, -#endif // LLVM_LIBC_HAS_UINT64 +#endif // LIBC_TYPES_HAS_INT64 generic::MemcmpSequence, generic::MemcmpSequence, // #endif // LIBC_TARGET_ARCH_IS_ARM diff --git a/libc/test/src/string/memset_explicit_test.cpp b/libc/test/src/string/memset_explicit_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bb5111bd639e3a958ccf30299cb756b6be66ffaf --- /dev/null +++ b/libc/test/src/string/memset_explicit_test.cpp @@ -0,0 +1,31 @@ +//===-- Unittests for memset_explicit -------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "memory_utils/memory_check_utils.h" +#include "src/string/memset_explicit.h" +#include "test/UnitTest/Test.h" + +namespace LIBC_NAMESPACE { + +// Apply the same tests as memset + +static inline void Adaptor(cpp::span p1, uint8_t value, size_t size) { + LIBC_NAMESPACE::memset_explicit(p1.begin(), value, size); +} + +TEST(LlvmLibcmemsetExplicitTest, SizeSweep) { + static constexpr size_t kMaxSize = 400; + Buffer DstBuffer(kMaxSize); + for (size_t size = 0; size < kMaxSize; ++size) { + const char value = size % 10; + auto dst = DstBuffer.span().subspan(0, size); + ASSERT_TRUE((CheckMemset(dst, value, size))); + } +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/test/src/sys/mman/linux/CMakeLists.txt b/libc/test/src/sys/mman/linux/CMakeLists.txt index 09ab5b09be6403680a7063e1fbd4bc3cf6a28000..6f7fc34d8d3ce3ba344af1c7eeaddad030be98ba 100644 --- a/libc/test/src/sys/mman/linux/CMakeLists.txt +++ b/libc/test/src/sys/mman/linux/CMakeLists.txt @@ -107,3 +107,23 @@ add_libc_unittest( libc.src.unistd.sysconf libc.test.UnitTest.ErrnoSetterMatcher ) + +add_libc_unittest( + msync_test + SUITE + libc_sys_mman_unittests + SRCS + msync_test.cpp + DEPENDS + libc.include.sys_mman + libc.include.unistd + libc.src.errno.errno + libc.src.sys.mman.mmap + libc.src.sys.mman.munmap + libc.src.sys.mman.msync + libc.src.sys.mman.mincore + libc.src.sys.mman.mlock + libc.src.sys.mman.munlock + libc.src.unistd.sysconf + libc.test.UnitTest.ErrnoSetterMatcher +) diff --git a/libc/test/src/sys/mman/linux/msync_test.cpp b/libc/test/src/sys/mman/linux/msync_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d60415b1243ab018665e39e78aa0464f0bef622 --- /dev/null +++ b/libc/test/src/sys/mman/linux/msync_test.cpp @@ -0,0 +1,69 @@ +//===-- Unittests for msync -----------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "src/errno/libc_errno.h" +#include "src/sys/mman/mlock.h" +#include "src/sys/mman/mmap.h" +#include "src/sys/mman/msync.h" +#include "src/sys/mman/munlock.h" +#include "src/sys/mman/munmap.h" +#include "src/unistd/sysconf.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/LibcTest.h" +#include "test/UnitTest/Test.h" + +using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; + +struct PageHolder { + size_t size; + void *addr; + + PageHolder() + : size(LIBC_NAMESPACE::sysconf(_SC_PAGESIZE)), + addr(LIBC_NAMESPACE::mmap(nullptr, size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)) {} + ~PageHolder() { + if (addr != MAP_FAILED) + LIBC_NAMESPACE::munmap(addr, size); + } + + char &operator[](size_t i) { return reinterpret_cast(addr)[i]; } + + bool is_valid() { return addr != MAP_FAILED; } +}; + +TEST(LlvmLibcMsyncTest, UnMappedMemory) { + EXPECT_THAT(LIBC_NAMESPACE::msync(nullptr, 1024, MS_SYNC), Fails(ENOMEM)); + EXPECT_THAT(LIBC_NAMESPACE::msync(nullptr, 1024, MS_ASYNC), Fails(ENOMEM)); +} + +TEST(LlvmLibcMsyncTest, LockedPage) { + PageHolder page; + ASSERT_TRUE(page.is_valid()); + ASSERT_THAT(LIBC_NAMESPACE::mlock(page.addr, page.size), Succeeds()); + EXPECT_THAT( + LIBC_NAMESPACE::msync(page.addr, page.size, MS_SYNC | MS_INVALIDATE), + Fails(EBUSY)); + ASSERT_THAT(LIBC_NAMESPACE::munlock(page.addr, page.size), Succeeds()); + EXPECT_THAT(LIBC_NAMESPACE::msync(page.addr, page.size, MS_SYNC), Succeeds()); +} + +TEST(LlvmLibcMsyncTest, UnalignedAddress) { + PageHolder page; + ASSERT_TRUE(page.is_valid()); + EXPECT_THAT(LIBC_NAMESPACE::msync(&page[1], page.size - 1, MS_SYNC), + Fails(EINVAL)); +} + +TEST(LlvmLibcMsyncTest, InvalidFlag) { + PageHolder page; + ASSERT_TRUE(page.is_valid()); + EXPECT_THAT(LIBC_NAMESPACE::msync(page.addr, page.size, MS_SYNC | MS_ASYNC), + Fails(EINVAL)); + EXPECT_THAT(LIBC_NAMESPACE::msync(page.addr, page.size, -1), Fails(EINVAL)); +} diff --git a/libc/utils/CMakeLists.txt b/libc/utils/CMakeLists.txt index 7bf02a4af7deaef86bab1f4d632a78c35b303e0e..11f25503cc13e26ebdc854df55634363fbef2a83 100644 --- a/libc/utils/CMakeLists.txt +++ b/libc/utils/CMakeLists.txt @@ -1,6 +1,3 @@ if(LLVM_INCLUDE_TESTS) add_subdirectory(MPFRWrapper) endif() -if(LIBC_TARGET_OS_IS_GPU) - add_subdirectory(gpu) -endif() diff --git a/libc/utils/gpu/CMakeLists.txt b/libc/utils/gpu/CMakeLists.txt index 4d1ebcfb9f8e65a2e678d52ee5d9cf4950919b03..7c15f36052cf3b2cf7c9679245cd38d5e068b606 100644 --- a/libc/utils/gpu/CMakeLists.txt +++ b/libc/utils/gpu/CMakeLists.txt @@ -1,4 +1,2 @@ add_subdirectory(server) -if(LIBC_TARGET_OS_IS_GPU) - add_subdirectory(loader) -endif() +add_subdirectory(loader) diff --git a/libc/utils/gpu/loader/CMakeLists.txt b/libc/utils/gpu/loader/CMakeLists.txt index 189460bb02e6e56bf721cc6e7f88304aab727a72..b562cdc521c07693a4150a8cdc4f2a5da42f20c4 100644 --- a/libc/utils/gpu/loader/CMakeLists.txt +++ b/libc/utils/gpu/loader/CMakeLists.txt @@ -6,37 +6,18 @@ target_include_directories(gpu_loader PUBLIC ${LIBC_SOURCE_DIR} ) -# This utility needs to be compiled for the host system when cross compiling. -if(LLVM_RUNTIMES_TARGET OR LIBC_TARGET_TRIPLE) - target_compile_options(gpu_loader PUBLIC --target=${LLVM_HOST_TRIPLE}) - target_link_libraries(gpu_loader PUBLIC "--target=${LLVM_HOST_TRIPLE}") -endif() - find_package(hsa-runtime64 QUIET 1.2.0 HINTS ${CMAKE_INSTALL_PREFIX} PATHS /opt/rocm) -if(hsa-runtime64_FOUND AND LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) +if(hsa-runtime64_FOUND) add_subdirectory(amdgpu) -elseif(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) - message(STATUS "Skipping HSA loader for gpu target, no HSA was detected") endif() # The CUDA loader requires LLVM to traverse the ELF image for symbols. -find_package(LLVM QUIET) -if(CUDAToolkit_FOUND AND LLVM_FOUND AND LIBC_TARGET_ARCHITECTURE_IS_NVPTX) +find_package(CUDAToolkit 11.2 QUIET) +if(CUDAToolkit_FOUND) add_subdirectory(nvptx) -elseif(LIBC_TARGET_ARCHITECTURE_IS_NVPTX) - message(STATUS "Skipping CUDA loader for gpu target, no CUDA was detected") endif() -# Add a custom target to be used for testing. -set(LIBC_GPU_LOADER_EXECUTABLE "" CACHE STRING "Overriding binary for the GPU loader.") -if(LIBC_GPU_LOADER_EXECUTABLE) - add_custom_target(libc.utils.gpu.loader) - set_target_properties( - libc.utils.gpu.loader - PROPERTIES - EXECUTABLE "${LIBC_GPU_LOADER_EXECUTABLE}" - ) -elseif(TARGET amdhsa-loader AND LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) +if(TARGET amdhsa-loader AND LIBC_TARGET_ARCHITECTURE_IS_AMDGPU) add_custom_target(libc.utils.gpu.loader) add_dependencies(libc.utils.gpu.loader amdhsa-loader) set_target_properties( @@ -56,11 +37,10 @@ elseif(TARGET nvptx-loader AND LIBC_TARGET_ARCHITECTURE_IS_NVPTX) ) endif() -if(TARGET libc.utils.gpu.loader) - get_target_property(gpu_loader_tgt libc.utils.gpu.loader "TARGET") - if(gpu_loader_tgt) +foreach(gpu_loader_tgt amdhsa-loader nvptx-loader) + if(TARGET ${gpu_loader_tgt}) install(TARGETS ${gpu_loader_tgt} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT libc) endif() -endif() +endforeach() diff --git a/libc/utils/gpu/loader/Loader.h b/libc/utils/gpu/loader/Loader.h index e2aabb08c11dac0e3048e107ee5ac13d423ecd3a..93380383701978774e370211a7fa69214d8988af 100644 --- a/libc/utils/gpu/loader/Loader.h +++ b/libc/utils/gpu/loader/Loader.h @@ -11,6 +11,7 @@ #include "utils/gpu/server/llvmlibc_rpc_server.h" +#include "llvm-libc-types/rpc_opcodes_t.h" #include "include/llvm-libc-types/test_rpc_opcodes_t.h" #include @@ -85,7 +86,7 @@ void *copy_argument_vector(int argc, char **argv, Allocator alloc) { // Ensure the vector is null terminated. reinterpret_cast(dev_argv)[argv_size] = nullptr; return dev_argv; -}; +} /// Copy the system's environment to GPU memory allocated using \p alloc. template @@ -95,7 +96,7 @@ void *copy_environment(char **envp, Allocator alloc) { ++envc; return copy_argument_vector(envc, envp, alloc); -}; +} inline void handle_error(const char *msg) { fprintf(stderr, "%s\n", msg); diff --git a/libc/utils/gpu/loader/amdgpu/CMakeLists.txt b/libc/utils/gpu/loader/amdgpu/CMakeLists.txt index b99319f504011262940ee5220cbf6082373d158a..97a2de9f8379ab51181abba1888df116e8ba40af 100644 --- a/libc/utils/gpu/loader/amdgpu/CMakeLists.txt +++ b/libc/utils/gpu/loader/amdgpu/CMakeLists.txt @@ -1,5 +1,4 @@ add_executable(amdhsa-loader Loader.cpp) -add_dependencies(amdhsa-loader libc.src.__support.RPC.rpc) target_link_libraries(amdhsa-loader PRIVATE diff --git a/libc/utils/gpu/loader/nvptx/CMakeLists.txt b/libc/utils/gpu/loader/nvptx/CMakeLists.txt index e76362a1e8cca66098fdf5f2de272f85efdc1a4a..948493959badf20b5946cd450f0cc772c6c7a606 100644 --- a/libc/utils/gpu/loader/nvptx/CMakeLists.txt +++ b/libc/utils/gpu/loader/nvptx/CMakeLists.txt @@ -1,10 +1,10 @@ add_executable(nvptx-loader Loader.cpp) -add_dependencies(nvptx-loader libc.src.__support.RPC.rpc) if(NOT LLVM_ENABLE_RTTI) target_compile_options(nvptx-loader PRIVATE -fno-rtti) endif() -target_include_directories(nvptx-loader PRIVATE ${LLVM_INCLUDE_DIRS}) +target_include_directories(nvptx-loader PRIVATE + ${LLVM_MAIN_INCLUDE_DIR} ${LLVM_BINARY_DIR}/include) target_link_libraries(nvptx-loader PRIVATE gpu_loader diff --git a/libc/utils/gpu/server/CMakeLists.txt b/libc/utils/gpu/server/CMakeLists.txt index 8712f24de84f7b4fffc87320cf73f625e7fa6ffe..6fca72cfae95fb28545803248ad894154d6cb734 100644 --- a/libc/utils/gpu/server/CMakeLists.txt +++ b/libc/utils/gpu/server/CMakeLists.txt @@ -5,25 +5,20 @@ target_include_directories(llvmlibc_rpc_server PRIVATE ${LIBC_SOURCE_DIR}) target_include_directories(llvmlibc_rpc_server PUBLIC ${LIBC_SOURCE_DIR}/include) target_include_directories(llvmlibc_rpc_server PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) - # Ignore unsupported clang attributes if we're using GCC. target_compile_options(llvmlibc_rpc_server PUBLIC $<$:-Wno-attributes>) target_compile_definitions(llvmlibc_rpc_server PUBLIC LIBC_NAMESPACE=${LIBC_NAMESPACE}) -# This utility needs to be compiled for the host system when cross compiling. -if(LLVM_RUNTIMES_TARGET OR LIBC_TARGET_TRIPLE) - target_compile_options(llvmlibc_rpc_server PUBLIC - --target=${LLVM_HOST_TRIPLE}) - target_link_libraries(llvmlibc_rpc_server PUBLIC - "--target=${LLVM_HOST_TRIPLE}") -endif() - # Install the server and associated header. install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/llvmlibc_rpc_server.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT libc-headers) +install(FILES ${LIBC_SOURCE_DIR}/include/llvm-libc-types/rpc_opcodes_t.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + RENAME llvmlibc_rpc_opcodes.h + COMPONENT libc-headers) install(TARGETS llvmlibc_rpc_server ARCHIVE DESTINATION "lib${LLVM_LIBDIR_SUFFIX}" COMPONENT libc) diff --git a/libc/utils/gpu/server/llvmlibc_rpc_server.h b/libc/utils/gpu/server/llvmlibc_rpc_server.h index f1a8fe06281cbf7a4de53d7146ead53d232df691..b7f2a463b1f5c8aa38fe9a96f083af950012ca48 100644 --- a/libc/utils/gpu/server/llvmlibc_rpc_server.h +++ b/libc/utils/gpu/server/llvmlibc_rpc_server.h @@ -11,8 +11,6 @@ #include -#include "llvm-libc-types/rpc_opcodes_t.h" - #ifdef __cplusplus extern "C" { #endif @@ -84,7 +82,7 @@ rpc_status_t rpc_handle_server(uint32_t device_id); /// Register a callback to handle an opcode from the RPC client. The associated /// data must remain accessible as long as the user intends to handle the server /// with this callback. -rpc_status_t rpc_register_callback(uint32_t device_id, rpc_opcode_t opcode, +rpc_status_t rpc_register_callback(uint32_t device_id, uint16_t opcode, rpc_opcode_callback_ty callback, void *data); /// Obtain a pointer to a local client buffer that can be copied directly to the diff --git a/libc/utils/gpu/server/rpc_server.cpp b/libc/utils/gpu/server/rpc_server.cpp index 707807a5cbaf7d88a2394d0cce27f0cdf17b02fc..90af1569c4c53b8ab435736e78250e833775a162 100644 --- a/libc/utils/gpu/server/rpc_server.cpp +++ b/libc/utils/gpu/server/rpc_server.cpp @@ -27,231 +27,220 @@ static_assert(sizeof(rpc_buffer_t) == sizeof(rpc::Buffer), static_assert(RPC_MAXIMUM_PORT_COUNT == rpc::MAX_PORT_COUNT, "Incorrect maximum port count"); -// The client needs to support different lane sizes for the SIMT model. Because -// of this we need to select between the possible sizes that the client can use. -struct Server { - template - Server(std::unique_ptr> &&server) - : server(std::move(server)) {} - - rpc_status_t handle_server( - const std::unordered_map &callbacks, - const std::unordered_map &callback_data, - uint32_t &index) { - rpc_status_t ret = RPC_STATUS_SUCCESS; - std::visit( - [&](auto &server) { - ret = handle_server(*server, callbacks, callback_data, index); - }, - server); - return ret; - } - -private: - template - rpc_status_t handle_server( - rpc::Server &server, - const std::unordered_map &callbacks, - const std::unordered_map &callback_data, - uint32_t &index) { - auto port = server.try_open(index); - if (!port) - return RPC_STATUS_SUCCESS; - - switch (port->get_opcode()) { - case RPC_WRITE_TO_STREAM: - case RPC_WRITE_TO_STDERR: - case RPC_WRITE_TO_STDOUT: - case RPC_WRITE_TO_STDOUT_NEWLINE: { - uint64_t sizes[lane_size] = {0}; - void *strs[lane_size] = {nullptr}; - FILE *files[lane_size] = {nullptr}; - if (port->get_opcode() == RPC_WRITE_TO_STREAM) { - port->recv([&](rpc::Buffer *buffer, uint32_t id) { - files[id] = reinterpret_cast(buffer->data[0]); - }); - } else if (port->get_opcode() == RPC_WRITE_TO_STDERR) { - std::fill(files, files + lane_size, stderr); - } else { - std::fill(files, files + lane_size, stdout); - } - - port->recv_n(strs, sizes, [&](uint64_t size) { return new char[size]; }); - port->send([&](rpc::Buffer *buffer, uint32_t id) { - flockfile(files[id]); - buffer->data[0] = fwrite_unlocked(strs[id], 1, sizes[id], files[id]); - if (port->get_opcode() == RPC_WRITE_TO_STDOUT_NEWLINE && - buffer->data[0] == sizes[id]) - buffer->data[0] += fwrite_unlocked("\n", 1, 1, files[id]); - funlockfile(files[id]); - delete[] reinterpret_cast(strs[id]); - }); - break; - } - case RPC_READ_FROM_STREAM: { - uint64_t sizes[lane_size] = {0}; - void *data[lane_size] = {nullptr}; - port->recv([&](rpc::Buffer *buffer, uint32_t id) { - data[id] = new char[buffer->data[0]]; - sizes[id] = fread(data[id], 1, buffer->data[0], - file::to_stream(buffer->data[1])); - }); - port->send_n(data, sizes); - port->send([&](rpc::Buffer *buffer, uint32_t id) { - delete[] reinterpret_cast(data[id]); - std::memcpy(buffer->data, &sizes[id], sizeof(uint64_t)); - }); - break; - } - case RPC_READ_FGETS: { - uint64_t sizes[lane_size] = {0}; - void *data[lane_size] = {nullptr}; - port->recv([&](rpc::Buffer *buffer, uint32_t id) { - data[id] = new char[buffer->data[0]]; - const char *str = - fgets(reinterpret_cast(data[id]), buffer->data[0], - file::to_stream(buffer->data[1])); - sizes[id] = !str ? 0 : std::strlen(str) + 1; - }); - port->send_n(data, sizes); - for (uint32_t id = 0; id < lane_size; ++id) - if (data[id]) - delete[] reinterpret_cast(data[id]); - break; - } - case RPC_OPEN_FILE: { - uint64_t sizes[lane_size] = {0}; - void *paths[lane_size] = {nullptr}; - port->recv_n(paths, sizes, [&](uint64_t size) { return new char[size]; }); - port->recv_and_send([&](rpc::Buffer *buffer, uint32_t id) { - FILE *file = fopen(reinterpret_cast(paths[id]), - reinterpret_cast(buffer->data)); - buffer->data[0] = reinterpret_cast(file); - }); - break; - } - case RPC_CLOSE_FILE: { - port->recv_and_send([&](rpc::Buffer *buffer, uint32_t id) { - FILE *file = reinterpret_cast(buffer->data[0]); - buffer->data[0] = fclose(file); - }); - break; - } - case RPC_EXIT: { - // Send a response to the client to signal that we are ready to exit. - port->recv_and_send([](rpc::Buffer *) {}); - port->recv([](rpc::Buffer *buffer) { - int status = 0; - std::memcpy(&status, buffer->data, sizeof(int)); - exit(status); - }); - break; - } - case RPC_ABORT: { - // Send a response to the client to signal that we are ready to abort. - port->recv_and_send([](rpc::Buffer *) {}); - port->recv([](rpc::Buffer *) {}); - abort(); - break; - } - case RPC_HOST_CALL: { - uint64_t sizes[lane_size] = {0}; - void *args[lane_size] = {nullptr}; - port->recv_n(args, sizes, [&](uint64_t size) { return new char[size]; }); +template +rpc_status_t handle_server_impl( + rpc::Server &server, + const std::unordered_map &callbacks, + const std::unordered_map &callback_data, + uint32_t &index) { + auto port = server.try_open(lane_size, index); + if (!port) + return RPC_STATUS_SUCCESS; + + switch (port->get_opcode()) { + case RPC_WRITE_TO_STREAM: + case RPC_WRITE_TO_STDERR: + case RPC_WRITE_TO_STDOUT: + case RPC_WRITE_TO_STDOUT_NEWLINE: { + uint64_t sizes[lane_size] = {0}; + void *strs[lane_size] = {nullptr}; + FILE *files[lane_size] = {nullptr}; + if (port->get_opcode() == RPC_WRITE_TO_STREAM) { port->recv([&](rpc::Buffer *buffer, uint32_t id) { - reinterpret_cast(buffer->data[0])(args[id]); - }); - port->send([&](rpc::Buffer *, uint32_t id) { - delete[] reinterpret_cast(args[id]); - }); - break; - } - case RPC_FEOF: { - port->recv_and_send([](rpc::Buffer *buffer) { - buffer->data[0] = feof(file::to_stream(buffer->data[0])); - }); - break; - } - case RPC_FERROR: { - port->recv_and_send([](rpc::Buffer *buffer) { - buffer->data[0] = ferror(file::to_stream(buffer->data[0])); - }); - break; - } - case RPC_CLEARERR: { - port->recv_and_send([](rpc::Buffer *buffer) { - clearerr(file::to_stream(buffer->data[0])); - }); - break; - } - case RPC_FSEEK: { - port->recv_and_send([](rpc::Buffer *buffer) { - buffer->data[0] = fseek(file::to_stream(buffer->data[0]), - static_cast(buffer->data[1]), - static_cast(buffer->data[2])); - }); - break; - } - case RPC_FTELL: { - port->recv_and_send([](rpc::Buffer *buffer) { - buffer->data[0] = ftell(file::to_stream(buffer->data[0])); - }); - break; - } - case RPC_FFLUSH: { - port->recv_and_send([](rpc::Buffer *buffer) { - buffer->data[0] = fflush(file::to_stream(buffer->data[0])); + files[id] = reinterpret_cast(buffer->data[0]); }); - break; - } - case RPC_UNGETC: { - port->recv_and_send([](rpc::Buffer *buffer) { - buffer->data[0] = ungetc(static_cast(buffer->data[0]), - file::to_stream(buffer->data[1])); - }); - break; - } - case RPC_NOOP: { - port->recv([](rpc::Buffer *) {}); - break; - } - default: { - auto handler = - callbacks.find(static_cast(port->get_opcode())); - - // We error out on an unhandled opcode. - if (handler == callbacks.end()) - return RPC_STATUS_UNHANDLED_OPCODE; - - // Invoke the registered callback with a reference to the port. - void *data = - callback_data.at(static_cast(port->get_opcode())); - rpc_port_t port_ref{reinterpret_cast(&*port), lane_size}; - (handler->second)(port_ref, data); - } + } else if (port->get_opcode() == RPC_WRITE_TO_STDERR) { + std::fill(files, files + lane_size, stderr); + } else { + std::fill(files, files + lane_size, stdout); } - // Increment the index so we start the scan after this port. - index = port->get_index() + 1; - port->close(); - return RPC_STATUS_CONTINUE; + port->recv_n(strs, sizes, [&](uint64_t size) { return new char[size]; }); + port->send([&](rpc::Buffer *buffer, uint32_t id) { + flockfile(files[id]); + buffer->data[0] = fwrite_unlocked(strs[id], 1, sizes[id], files[id]); + if (port->get_opcode() == RPC_WRITE_TO_STDOUT_NEWLINE && + buffer->data[0] == sizes[id]) + buffer->data[0] += fwrite_unlocked("\n", 1, 1, files[id]); + funlockfile(files[id]); + delete[] reinterpret_cast(strs[id]); + }); + break; + } + case RPC_READ_FROM_STREAM: { + uint64_t sizes[lane_size] = {0}; + void *data[lane_size] = {nullptr}; + port->recv([&](rpc::Buffer *buffer, uint32_t id) { + data[id] = new char[buffer->data[0]]; + sizes[id] = + fread(data[id], 1, buffer->data[0], file::to_stream(buffer->data[1])); + }); + port->send_n(data, sizes); + port->send([&](rpc::Buffer *buffer, uint32_t id) { + delete[] reinterpret_cast(data[id]); + std::memcpy(buffer->data, &sizes[id], sizeof(uint64_t)); + }); + break; + } + case RPC_READ_FGETS: { + uint64_t sizes[lane_size] = {0}; + void *data[lane_size] = {nullptr}; + port->recv([&](rpc::Buffer *buffer, uint32_t id) { + data[id] = new char[buffer->data[0]]; + const char *str = + fgets(reinterpret_cast(data[id]), buffer->data[0], + file::to_stream(buffer->data[1])); + sizes[id] = !str ? 0 : std::strlen(str) + 1; + }); + port->send_n(data, sizes); + for (uint32_t id = 0; id < lane_size; ++id) + if (data[id]) + delete[] reinterpret_cast(data[id]); + break; + } + case RPC_OPEN_FILE: { + uint64_t sizes[lane_size] = {0}; + void *paths[lane_size] = {nullptr}; + port->recv_n(paths, sizes, [&](uint64_t size) { return new char[size]; }); + port->recv_and_send([&](rpc::Buffer *buffer, uint32_t id) { + FILE *file = fopen(reinterpret_cast(paths[id]), + reinterpret_cast(buffer->data)); + buffer->data[0] = reinterpret_cast(file); + }); + break; + } + case RPC_CLOSE_FILE: { + port->recv_and_send([&](rpc::Buffer *buffer, uint32_t id) { + FILE *file = reinterpret_cast(buffer->data[0]); + buffer->data[0] = fclose(file); + }); + break; + } + case RPC_EXIT: { + // Send a response to the client to signal that we are ready to exit. + port->recv_and_send([](rpc::Buffer *) {}); + port->recv([](rpc::Buffer *buffer) { + int status = 0; + std::memcpy(&status, buffer->data, sizeof(int)); + exit(status); + }); + break; + } + case RPC_ABORT: { + // Send a response to the client to signal that we are ready to abort. + port->recv_and_send([](rpc::Buffer *) {}); + port->recv([](rpc::Buffer *) {}); + abort(); + break; + } + case RPC_HOST_CALL: { + uint64_t sizes[lane_size] = {0}; + void *args[lane_size] = {nullptr}; + port->recv_n(args, sizes, [&](uint64_t size) { return new char[size]; }); + port->recv([&](rpc::Buffer *buffer, uint32_t id) { + reinterpret_cast(buffer->data[0])(args[id]); + }); + port->send([&](rpc::Buffer *, uint32_t id) { + delete[] reinterpret_cast(args[id]); + }); + break; + } + case RPC_FEOF: { + port->recv_and_send([](rpc::Buffer *buffer) { + buffer->data[0] = feof(file::to_stream(buffer->data[0])); + }); + break; + } + case RPC_FERROR: { + port->recv_and_send([](rpc::Buffer *buffer) { + buffer->data[0] = ferror(file::to_stream(buffer->data[0])); + }); + break; + } + case RPC_CLEARERR: { + port->recv_and_send([](rpc::Buffer *buffer) { + clearerr(file::to_stream(buffer->data[0])); + }); + break; + } + case RPC_FSEEK: { + port->recv_and_send([](rpc::Buffer *buffer) { + buffer->data[0] = fseek(file::to_stream(buffer->data[0]), + static_cast(buffer->data[1]), + static_cast(buffer->data[2])); + }); + break; + } + case RPC_FTELL: { + port->recv_and_send([](rpc::Buffer *buffer) { + buffer->data[0] = ftell(file::to_stream(buffer->data[0])); + }); + break; + } + case RPC_FFLUSH: { + port->recv_and_send([](rpc::Buffer *buffer) { + buffer->data[0] = fflush(file::to_stream(buffer->data[0])); + }); + break; + } + case RPC_UNGETC: { + port->recv_and_send([](rpc::Buffer *buffer) { + buffer->data[0] = ungetc(static_cast(buffer->data[0]), + file::to_stream(buffer->data[1])); + }); + break; + } + case RPC_NOOP: { + port->recv([](rpc::Buffer *) {}); + break; + } + default: { + auto handler = + callbacks.find(static_cast(port->get_opcode())); + + // We error out on an unhandled opcode. + if (handler == callbacks.end()) + return RPC_STATUS_UNHANDLED_OPCODE; + + // Invoke the registered callback with a reference to the port. + void *data = + callback_data.at(static_cast(port->get_opcode())); + rpc_port_t port_ref{reinterpret_cast(&*port), lane_size}; + (handler->second)(port_ref, data); + } } - std::variant>, - std::unique_ptr>, - std::unique_ptr>> - server; -}; + // Increment the index so we start the scan after this port. + index = port->get_index() + 1; + port->close(); + + return RPC_STATUS_CONTINUE; +} struct Device { - template - Device(uint32_t num_ports, void *buffer, std::unique_ptr &&server) - : buffer(buffer), server(std::move(server)), client(num_ports, buffer) {} + Device(uint32_t lane_size, uint32_t num_ports, void *buffer) + : lane_size(lane_size), buffer(buffer), server(num_ports, buffer), + client(num_ports, buffer) {} + + rpc_status_t handle_server(uint32_t &index) { + switch (lane_size) { + case 1: + return handle_server_impl<1>(server, callbacks, callback_data, index); + case 32: + return handle_server_impl<32>(server, callbacks, callback_data, index); + case 64: + return handle_server_impl<64>(server, callbacks, callback_data, index); + default: + return RPC_STATUS_INVALID_LANE_SIZE; + } + } + + uint32_t lane_size; void *buffer; - Server server; + rpc::Server server; rpc::Client client; - std::unordered_map callbacks; - std::unordered_map callback_data; + std::unordered_map callbacks; + std::unordered_map callback_data; }; // A struct containing all the runtime state required to run the RPC server. @@ -287,24 +276,6 @@ rpc_status_t rpc_shutdown(void) { return RPC_STATUS_SUCCESS; } -template -rpc_status_t server_init_impl(uint32_t device_id, uint64_t num_ports, - rpc_alloc_ty alloc, void *data) { - uint64_t size = rpc::Server::allocation_size(num_ports); - void *buffer = alloc(size, data); - - if (!buffer) - return RPC_STATUS_ERROR; - - state->devices[device_id] = std::make_unique( - num_ports, buffer, - std::make_unique>(num_ports, buffer)); - if (!state->devices[device_id]) - return RPC_STATUS_ERROR; - - return RPC_STATUS_SUCCESS; -} - rpc_status_t rpc_server_init(uint32_t device_id, uint64_t num_ports, uint32_t lane_size, rpc_alloc_ty alloc, void *data) { @@ -312,28 +283,20 @@ rpc_status_t rpc_server_init(uint32_t device_id, uint64_t num_ports, return RPC_STATUS_NOT_INITIALIZED; if (device_id >= state->num_devices) return RPC_STATUS_OUT_OF_RANGE; + if (lane_size != 1 && lane_size != 32 && lane_size != 64) + return RPC_STATUS_INVALID_LANE_SIZE; if (!state->devices[device_id]) { - switch (lane_size) { - case 1: - if (rpc_status_t err = - server_init_impl<1>(device_id, num_ports, alloc, data)) - return err; - break; - case 32: { - if (rpc_status_t err = - server_init_impl<32>(device_id, num_ports, alloc, data)) - return err; - break; - } - case 64: - if (rpc_status_t err = - server_init_impl<64>(device_id, num_ports, alloc, data)) - return err; - break; - default: - return RPC_STATUS_INVALID_LANE_SIZE; - } + uint64_t size = rpc::Server::allocation_size(lane_size, num_ports); + void *buffer = alloc(size, data); + + if (!buffer) + return RPC_STATUS_ERROR; + + state->devices[device_id] = + std::make_unique(lane_size, num_ports, buffer); + if (!state->devices[device_id]) + return RPC_STATUS_ERROR; } return RPC_STATUS_SUCCESS; @@ -365,15 +328,14 @@ rpc_status_t rpc_handle_server(uint32_t device_id) { uint32_t index = 0; for (;;) { - auto &device = *state->devices[device_id]; - rpc_status_t status = device.server.handle_server( - device.callbacks, device.callback_data, index); + Device &device = *state->devices[device_id]; + rpc_status_t status = device.handle_server(index); if (status != RPC_STATUS_CONTINUE) return status; } } -rpc_status_t rpc_register_callback(uint32_t device_id, rpc_opcode_t opcode, +rpc_status_t rpc_register_callback(uint32_t device_id, uint16_t opcode, rpc_opcode_callback_ty callback, void *data) { if (!state) @@ -396,26 +358,26 @@ const void *rpc_get_client_buffer(uint32_t device_id) { uint64_t rpc_get_client_size() { return sizeof(rpc::Client); } -using ServerPort = std::variant::Port *>; +using ServerPort = std::variant; ServerPort get_port(rpc_port_t ref) { - return reinterpret_cast::Port *>(ref.handle); + return reinterpret_cast(ref.handle); } void rpc_send(rpc_port_t ref, rpc_port_callback_ty callback, void *data) { - auto port = reinterpret_cast::Port *>(ref.handle); + auto port = reinterpret_cast(ref.handle); port->send([=](rpc::Buffer *buffer) { callback(reinterpret_cast(buffer), data); }); } void rpc_send_n(rpc_port_t ref, const void *const *src, uint64_t *size) { - auto port = reinterpret_cast::Port *>(ref.handle); + auto port = reinterpret_cast(ref.handle); port->send_n(src, size); } void rpc_recv(rpc_port_t ref, rpc_port_callback_ty callback, void *data) { - auto port = reinterpret_cast::Port *>(ref.handle); + auto port = reinterpret_cast(ref.handle); port->recv([=](rpc::Buffer *buffer) { callback(reinterpret_cast(buffer), data); }); @@ -423,14 +385,14 @@ void rpc_recv(rpc_port_t ref, rpc_port_callback_ty callback, void *data) { void rpc_recv_n(rpc_port_t ref, void **dst, uint64_t *size, rpc_alloc_ty alloc, void *data) { - auto port = reinterpret_cast::Port *>(ref.handle); + auto port = reinterpret_cast(ref.handle); auto alloc_fn = [=](uint64_t size) { return alloc(size, data); }; port->recv_n(dst, size, alloc_fn); } void rpc_recv_and_send(rpc_port_t ref, rpc_port_callback_ty callback, void *data) { - auto port = reinterpret_cast::Port *>(ref.handle); + auto port = reinterpret_cast(ref.handle); port->recv_and_send([=](rpc::Buffer *buffer) { callback(reinterpret_cast(buffer), data); }); diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt index d392e95077ac5795d67b2211cb59267b7c7c6005..e565c47c76687acfe13fb39e02bfa3aa7cab9b52 100644 --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -229,8 +229,6 @@ option(LIBCXX_USE_COMPILER_RT "Use compiler-rt instead of libgcc" OFF) # ABI Library options --------------------------------------------------------- if (MSVC) set(LIBCXX_DEFAULT_ABI_LIBRARY "vcruntime") -elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - set(LIBCXX_DEFAULT_ABI_LIBRARY "libcxxrt") else() set(LIBCXX_DEFAULT_ABI_LIBRARY "libcxxabi") endif() diff --git a/libcxx/docs/Contributing.rst b/libcxx/docs/Contributing.rst index 596d86ef224490478361eca10efc54b47ed66df5..90aabc9c4ff6fae6a8c9b23b927492aeb629c307 100644 --- a/libcxx/docs/Contributing.rst +++ b/libcxx/docs/Contributing.rst @@ -156,7 +156,7 @@ sure you don't forget anything: - Did you add all new named declarations to the ``std`` module? - If you added a header: - - Did you add it to ``include/module.modulemap.in``? + - Did you add it to ``include/module.modulemap``? - Did you add it to ``include/CMakeLists.txt``? - If it's a public header, did you update ``utils/libcxx/header_information.py``? diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 60e0aea9768b4f182facdd6210be2fd126c82540..b213f430aa5922bd79dc53b433ee513798d23011 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -442,7 +442,7 @@ Status --------------------------------------------------- ----------------- ``__cpp_lib_span_initializer_list`` ``202311L`` --------------------------------------------------- ----------------- - ``__cpp_lib_sstream_from_string_view`` *unimplemented* + ``__cpp_lib_sstream_from_string_view`` ``202306L`` --------------------------------------------------- ----------------- ``__cpp_lib_submdspan`` *unimplemented* --------------------------------------------------- ----------------- diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst index 0d381df5f0442c7bb69b5002953877becaf1b581..04f16610f8117ee6d8e7d0bd3ba02ec66a16f646 100644 --- a/libcxx/docs/ReleaseNotes/19.rst +++ b/libcxx/docs/ReleaseNotes/19.rst @@ -41,6 +41,7 @@ Implemented Papers - P2637R3 - Member ``visit`` - P2652R2 - Disallow User Specialization of ``allocator_traits`` - P2819R2 - Add ``tuple`` protocol to ``complex`` +- P2495R3 - Interfacing ``stringstream``\s with ``string_view`` - P2302R4 - ``std::ranges::contains`` - P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with`` diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index 70480b338205804cba66fe94f29de84e82a2aefe..e00345533b865d35ac2d32f4609e08a0ee330fb1 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -65,7 +65,7 @@ `2997 `__,"LWG 491 and the specification of ``{forward_,}list::unique``","June 2021","","" `3410 `__,"``lexicographical_compare_three_way`` is overspecified","June 2021","|Complete|","17.0","|spaceship|" `3430 `__,"``std::fstream`` & co. should be constructible from string_view","June 2021","","" -`3462 `__,"§[formatter.requirements]: Formatter requirements forbid use of ``fc.arg()``","June 2021","","","|format|" +`3462 `__,"§[formatter.requirements]: Formatter requirements forbid use of ``fc.arg()``","June 2021","|Nothing To Do|","","|format|" `3481 `__,"``viewable_range`` mishandles lvalue move-only views","June 2021","Superseded by `P2415R2 `__","","|ranges|" `3506 `__,"Missing allocator-extended constructors for ``priority_queue``","June 2021","|Complete|","14.0" `3517 `__,"``join_view::iterator``'s ``iter_swap`` is underconstrained","June 2021","|Complete|","14.0","|ranges|" @@ -169,7 +169,7 @@ "`3683 `__","``operator==`` for ``polymorphic_allocator`` cannot deduce template argument in common cases","July 2022","","" "`3687 `__","``expected`` move constructor should move","July 2022","|Complete|","16.0" "`3692 `__","``zip_view::iterator``'s ``operator<=>`` is overconstrained","July 2022","","","|ranges| |spaceship|" -"`3701 `__","Make ``formatter, charT>`` requirement explicit","July 2022","","","|format|" +"`3701 `__","Make ``formatter, charT>`` requirement explicit","July 2022","|Complete|","15.0","|format|" "`3702 `__","Should ``zip_transform_view::iterator`` remove ``operator<``","July 2022","","","|ranges| |spaceship|" "`3703 `__","Missing requirements for ``expected`` requires ``is_void``","July 2022","|Complete|","16.0" "`3704 `__","LWG 2059 added overloads that might be ill-formed for sets","July 2022","","" diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv index 1c895f79a4c0f1d4e926e1c21f9ec031322dc749..4a5443dea115c8549f47dcb2a03017641689d80d 100644 --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -6,7 +6,7 @@ "`P2545R4 `__","LWG","Read-Copy Update (RCU)","Varna June 2023","","","" "`P2530R3 `__","LWG","Hazard Pointers for C++26","Varna June 2023","","","" "`P2538R1 `__","LWG","ADL-proof ``std::projected``","Varna June 2023","|Complete|","18.0","|ranges|" -"`P2495R3 `__","LWG","Interfacing ``stringstreams`` with ``string_view``","Varna June 2023","","","" +"`P2495R3 `__","LWG","Interfacing ``stringstream``\s with ``string_view``","Varna June 2023","|Complete|","19.0","" "`P2510R3 `__","LWG","Formatting pointers","Varna June 2023","|Complete| [#note-P2510R3]_","17.0","|format|" "`P2198R7 `__","LWG","Freestanding Feature-Test Macros and Implementation-Defined Extensions","Varna June 2023","","","" "`P2338R4 `__","LWG","Freestanding Library: Character primitives and the C library","Varna June 2023","","","" diff --git a/libcxx/docs/Status/SpaceshipPapers.csv b/libcxx/docs/Status/SpaceshipPapers.csv index 48fe417bc7dc0a9bf600f68bc0c656e818686b50..21b788ee429216dca0bc7c29a2486ed771de2a71 100644 --- a/libcxx/docs/Status/SpaceshipPapers.csv +++ b/libcxx/docs/Status/SpaceshipPapers.csv @@ -3,10 +3,10 @@ `P2404R3 `_,"Relaxing ``equality_comparable_with``'s, ``totally_ordered_with``'s, and ``three_way_comparable_with``'s common reference requirements to support move-only types",, `LWG3330 `_,Include ```` from most library headers,"|Complete|","13.0" `LWG3347 `_,"``std::pair`` now requires ``T`` and ``U`` to be *less-than-comparable*",|Nothing To Do|, -`LWG3350 `_,Simplify return type of lexicographical_compare_three_way,|Nothing To Do|, +`LWG3350 `_,Simplify return type of ``lexicographical_compare_three_way``,|Nothing To Do|, `LWG3360 `_,``three_way_comparable_with`` is inconsistent with similar concepts,|Nothing To Do|, -`LWG3380 `_,common_type and comparison categories,|Nothing To Do|, -`LWG3395 `_,Definition for three-way comparison needs to be updated,|Nothing To Do|, +`LWG3380 `_,``common_type`` and comparison categories,|Nothing To Do|, +`LWG3395 `_,Definition for *three-way* comparison needs to be updated,|Nothing To Do|, `P0905R1 `_,Symmetry for spaceship,, `P1120R0 `_,Consistency improvements for ``<=>`` and other comparison operators,, `LWG3431 `_,``<=>`` for containers should require ``three_way_comparable`` instead of ``<=>``,, diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 459b077087e2b58c383bab7055efb7bb5fde4b3e..63adc03fae2980ae792a66ce52f0004f73a8d4ea 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -380,7 +380,6 @@ set(files __format/format_context.h __format/format_error.h __format/format_functions.h - __format/format_fwd.h __format/format_parse_context.h __format/format_string.h __format/format_to_n_result.h @@ -430,6 +429,7 @@ set(files __fwd/array.h __fwd/bit_reference.h __fwd/complex.h + __fwd/format.h __fwd/fstream.h __fwd/functional.h __fwd/ios.h @@ -701,6 +701,7 @@ set(files __thread/thread.h __thread/timed_backoff_policy.h __tree + __tuple/find_index.h __tuple/make_tuple_types.h __tuple/pair_like.h __tuple/sfinae_helpers.h @@ -968,6 +969,7 @@ set(files mdspan memory memory_resource + module.modulemap mutex new numbers @@ -1021,18 +1023,10 @@ set(files wctype.h ) -foreach(feature LIBCXX_ENABLE_FILESYSTEM LIBCXX_ENABLE_LOCALIZATION LIBCXX_ENABLE_THREADS LIBCXX_ENABLE_WIDE_CHARACTERS) - if (NOT ${${feature}}) - set(requires_${feature} "requires LIBCXX_CONFIGURED_WITHOUT_SUPPORT_FOR_THIS_HEADER") - endif() -endforeach() - configure_file("__config_site.in" "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/__config_site" @ONLY) -configure_file("module.modulemap.in" "${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap" @ONLY) configure_file("${LIBCXX_ASSERTION_HANDLER_FILE}" "${LIBCXX_GENERATED_INCLUDE_DIR}/__assertion_handler" COPYONLY) set(_all_includes "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}/__config_site" - "${LIBCXX_GENERATED_INCLUDE_DIR}/module.modulemap" "${LIBCXX_GENERATED_INCLUDE_DIR}/__assertion_handler") foreach(f ${files}) set(src "${CMAKE_CURRENT_SOURCE_DIR}/${f}") diff --git a/libcxx/include/__availability b/libcxx/include/__availability index 78438c55a3b7ba039edce5eed195cc11c82e8ec4..bb3ed0a8da521bf608dda9295096db19e2415874 100644 --- a/libcxx/include/__availability +++ b/libcxx/include/__availability @@ -72,11 +72,10 @@ # endif #endif -// Availability markup is disabled when building the library, or when the compiler +// Availability markup is disabled when building the library, or when a non-Clang +// compiler is used because only Clang supports the necessary attributes. // doesn't support the proper attributes. -#if defined(_LIBCPP_BUILDING_LIBRARY) || defined(_LIBCXXABI_BUILDING_LIBRARY) || \ - !__has_feature(attribute_availability_with_strict) || !__has_feature(attribute_availability_in_templates) || \ - !__has_extension(pragma_clang_attribute_external_declaration) +#if defined(_LIBCPP_BUILDING_LIBRARY) || defined(_LIBCXXABI_BUILDING_LIBRARY) || !defined(_LIBCPP_COMPILER_CLANG_BASED) # if !defined(_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS) # define _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS # endif diff --git a/libcxx/include/__config b/libcxx/include/__config index 8d4d17378b297344174d1eec430b694fbfd173d9..11e13e0c24986a36589d4658b578d06287679aa7 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -174,6 +174,12 @@ // The implementation moved to the header, but we still export the symbols from // the dylib for backwards compatibility. # define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10 +// Define std::array/std::string_view iterators to be __wrap_iters instead of raw +// pointers, which prevents people from relying on a non-portable implementation +// detail. This is especially useful because enabling bounded iterators hardening +// requires code not to make these assumptions. +# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY +# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW # elif _LIBCPP_ABI_VERSION == 1 # if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF)) // Enable compiling copies of now inline methods into the dylib to support @@ -400,6 +406,10 @@ _LIBCPP_HARDENING_MODE_DEBUG # define __has_include(...) 0 # endif +# ifndef __has_warning +# define __has_warning(...) 0 +# endif + # if !defined(_LIBCPP_COMPILER_CLANG_BASED) && __cplusplus < 201103L # error "libc++ only supports C++03 with Clang-based compilers. Please enable C++11" # endif @@ -717,6 +727,23 @@ typedef __char32_t char32_t; # define _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION _LIBCPP_ALWAYS_INLINE # endif +# ifdef _LIBCPP_COMPILER_CLANG_BASED +# define _LIBCPP_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") +# define _LIBCPP_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str) _Pragma(_LIBCPP_TOSTRING(clang diagnostic ignored str)) +# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) +# elif defined(_LIBCPP_COMPILER_GCC) +# define _LIBCPP_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") +# define _LIBCPP_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str) +# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) _Pragma(_LIBCPP_TOSTRING(GCC diagnostic ignored str)) +# else +# define _LIBCPP_DIAGNOSTIC_PUSH +# define _LIBCPP_DIAGNOSTIC_POP +# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str) +# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) +# endif + # if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_FAST # define _LIBCPP_HARDENING_SIG f # elif _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_EXTENSIVE @@ -804,16 +831,33 @@ typedef __char32_t char32_t; # define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 _LIBCPP_HIDE_FROM_ABI # endif +// TODO: Remove this workaround once we drop support for Clang 16 +#if __has_warning("-Wc++23-extensions") +# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++23-extensions") +#else +# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++2b-extensions") +#endif + // Inline namespaces are available in Clang/GCC/MSVC regardless of C++ dialect. // clang-format off -# define _LIBCPP_BEGIN_NAMESPACE_STD namespace _LIBCPP_TYPE_VISIBILITY_DEFAULT std { \ +# define _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_DIAGNOSTIC_PUSH \ + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++11-extensions") \ + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \ + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \ + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \ + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION \ + _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \ + _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \ + _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \ + _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++23-extensions") \ + namespace _LIBCPP_TYPE_VISIBILITY_DEFAULT std { \ inline namespace _LIBCPP_ABI_NAMESPACE { -# define _LIBCPP_END_NAMESPACE_STD }} +# define _LIBCPP_END_NAMESPACE_STD }} _LIBCPP_DIAGNOSTIC_POP # define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM _LIBCPP_BEGIN_NAMESPACE_STD \ inline namespace __fs { namespace filesystem { -# define _LIBCPP_END_NAMESPACE_FILESYSTEM _LIBCPP_END_NAMESPACE_STD }} +# define _LIBCPP_END_NAMESPACE_FILESYSTEM }} _LIBCPP_END_NAMESPACE_STD // clang-format on # if __has_attribute(__enable_if__) @@ -1250,23 +1294,6 @@ __sanitizer_verify_double_ended_contiguous_container(const void*, const void*, c // the ABI inconsistent. # endif -# ifdef _LIBCPP_COMPILER_CLANG_BASED -# define _LIBCPP_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") -# define _LIBCPP_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") -# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str) _Pragma(_LIBCPP_TOSTRING(clang diagnostic ignored str)) -# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) -# elif defined(_LIBCPP_COMPILER_GCC) -# define _LIBCPP_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") -# define _LIBCPP_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") -# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str) -# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) _Pragma(_LIBCPP_TOSTRING(GCC diagnostic ignored str)) -# else -# define _LIBCPP_DIAGNOSTIC_PUSH -# define _LIBCPP_DIAGNOSTIC_POP -# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED(str) -# define _LIBCPP_GCC_DIAGNOSTIC_IGNORED(str) -# endif - // c8rtomb() and mbrtoc8() were added in C++20 and C23. Support for these // functions is gradually being added to existing C libraries. The conditions // below check for known C library versions and conditions under which these diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h index 53e2f718bc1b358f53603fe03c94082d91b0cd2c..c9027de9238cdd7878df568f35fbd18aeb5ab9ed 100644 --- a/libcxx/include/__exception/exception_ptr.h +++ b/libcxx/include/__exception/exception_ptr.h @@ -26,6 +26,8 @@ #ifndef _LIBCPP_ABI_MICROSOFT +# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION + namespace __cxxabiv1 { extern "C" { @@ -37,14 +39,16 @@ _LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception* __cxa_init_primary_exception( void*, std::type_info*, void( -# if defined(_WIN32) +# if defined(_WIN32) __thiscall -# endif +# endif *)(void*)) throw(); } } // namespace __cxxabiv1 +# endif + #endif namespace std { // purposefully not using versioning namespace diff --git a/libcxx/include/__format/concepts.h b/libcxx/include/__format/concepts.h index 299c5f40ee35b4ea843e55d76beb6e5bb4838783..d7b5a9d16df70a99267d988b8d117652897439cd 100644 --- a/libcxx/include/__format/concepts.h +++ b/libcxx/include/__format/concepts.h @@ -13,8 +13,8 @@ #include <__concepts/same_as.h> #include <__concepts/semiregular.h> #include <__config> -#include <__format/format_fwd.h> #include <__format/format_parse_context.h> +#include <__fwd/format.h> #include <__type_traits/is_specialization.h> #include <__type_traits/remove_const.h> #include <__utility/pair.h> diff --git a/libcxx/include/__format/format_arg.h b/libcxx/include/__format/format_arg.h index b786ac3b3620e3d59d83c0667de04792261cc976..4924e5fb325336307ce179f5eadee662dbabdbbf 100644 --- a/libcxx/include/__format/format_arg.h +++ b/libcxx/include/__format/format_arg.h @@ -14,9 +14,9 @@ #include <__concepts/arithmetic.h> #include <__config> #include <__format/concepts.h> -#include <__format/format_fwd.h> #include <__format/format_parse_context.h> #include <__functional/invoke.h> +#include <__fwd/format.h> #include <__memory/addressof.h> #include <__type_traits/conditional.h> #include <__utility/forward.h> diff --git a/libcxx/include/__format/format_args.h b/libcxx/include/__format/format_args.h index 9e0afecc0ae967212fa88c954050308776063235..79fe51f96c6a5063fb572db42fd3b476cde51cd5 100644 --- a/libcxx/include/__format/format_args.h +++ b/libcxx/include/__format/format_args.h @@ -14,7 +14,7 @@ #include <__config> #include <__format/format_arg.h> #include <__format/format_arg_store.h> -#include <__format/format_fwd.h> +#include <__fwd/format.h> #include #include diff --git a/libcxx/include/__format/format_context.h b/libcxx/include/__format/format_context.h index 68dcdb49d3aae666a33f990d2ac734198b699d8a..d131e942aca60b0042ba9e9cfc5bfbcf470d6169 100644 --- a/libcxx/include/__format/format_context.h +++ b/libcxx/include/__format/format_context.h @@ -18,7 +18,7 @@ #include <__format/format_arg_store.h> #include <__format/format_args.h> #include <__format/format_error.h> -#include <__format/format_fwd.h> +#include <__fwd/format.h> #include <__iterator/back_insert_iterator.h> #include <__iterator/concepts.h> #include <__memory/addressof.h> diff --git a/libcxx/include/__format/formatter.h b/libcxx/include/__format/formatter.h index 079befc5bd9ca61836d551acab034395a720870c..47e35789b8175bc1baa7663e922f2cef9be48217 100644 --- a/libcxx/include/__format/formatter.h +++ b/libcxx/include/__format/formatter.h @@ -12,7 +12,7 @@ #include <__availability> #include <__config> -#include <__format/format_fwd.h> +#include <__fwd/format.h> #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__fwd/array.h b/libcxx/include/__fwd/array.h index ff3a3eeeefc71f7847e81da36143cd22a71eb165..b429d0c5a95427df0b6d41b210714fef1ac3f845 100644 --- a/libcxx/include/__fwd/array.h +++ b/libcxx/include/__fwd/array.h @@ -35,6 +35,12 @@ template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp&& get(const array<_Tp, _Size>&&) _NOEXCEPT; #endif +template +struct __is_std_array : false_type {}; + +template +struct __is_std_array > : true_type {}; + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___FWD_ARRAY_H diff --git a/libcxx/include/__format/format_fwd.h b/libcxx/include/__fwd/format.h similarity index 89% rename from libcxx/include/__format/format_fwd.h rename to libcxx/include/__fwd/format.h index 120b2fc8d47de80097501c05b93f0e21190919f0..6f5c71243711fe9ce7dc6ebba84ef88cee5afaa3 100644 --- a/libcxx/include/__format/format_fwd.h +++ b/libcxx/include/__fwd/format.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___FORMAT_FORMAT_FWD_H -#define _LIBCPP___FORMAT_FORMAT_FWD_H +#ifndef _LIBCPP___FWD_FORMAT_H +#define _LIBCPP___FWD_FORMAT_H #include <__availability> #include <__config> @@ -36,4 +36,4 @@ struct _LIBCPP_TEMPLATE_VIS formatter; _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP___FORMAT_FORMAT_FWD_H +#endif // _LIBCPP___FWD_FORMAT_H diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index ec7d694c4a55fd487d8f570a4c78473709faf341..e6691e78a267f84002fa6c8232abdbf9cad5889f 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -284,13 +284,21 @@ public: _LIBCPP_HIDE_FROM_ABI __hash_iterator() _NOEXCEPT : __node_(nullptr) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __node_->__upcast()->__get_value(); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container iterator"); + return __node_->__upcast()->__get_value(); + } _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container iterator"); return pointer_traits::pointer_to(__node_->__upcast()->__get_value()); } _LIBCPP_HIDE_FROM_ABI __hash_iterator& operator++() { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to increment a non-incrementable unordered container iterator"); __node_ = __node_->__next_; return *this; } @@ -345,12 +353,20 @@ public: _LIBCPP_HIDE_FROM_ABI __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT : __node_(__x.__node_) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __node_->__upcast()->__get_value(); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); + return __node_->__upcast()->__get_value(); + } _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_iterator"); return pointer_traits::pointer_to(__node_->__upcast()->__get_value()); } _LIBCPP_HIDE_FROM_ABI __hash_const_iterator& operator++() { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to increment a non-incrementable unordered container const_iterator"); __node_ = __node_->__next_; return *this; } @@ -400,13 +416,21 @@ public: _LIBCPP_HIDE_FROM_ABI __hash_local_iterator() _NOEXCEPT : __node_(nullptr) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __node_->__upcast()->__get_value(); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container local_iterator"); + return __node_->__upcast()->__get_value(); + } _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container local_iterator"); return pointer_traits::pointer_to(__node_->__upcast()->__get_value()); } _LIBCPP_HIDE_FROM_ABI __hash_local_iterator& operator++() { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to increment a non-incrementable unordered container local_iterator"); __node_ = __node_->__next_; if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) __node_ = nullptr; @@ -475,13 +499,21 @@ public: __bucket_(__x.__bucket_), __bucket_count_(__x.__bucket_count_) {} - _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __node_->__upcast()->__get_value(); } + _LIBCPP_HIDE_FROM_ABI reference operator*() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); + return __node_->__upcast()->__get_value(); + } _LIBCPP_HIDE_FROM_ABI pointer operator->() const { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); return pointer_traits::pointer_to(__node_->__upcast()->__get_value()); } _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator& operator++() { + _LIBCPP_ASSERT_NON_NULL( + __node_ != nullptr, "Attempted to increment a non-incrementable unordered container const_local_iterator"); __node_ = __node_->__next_; if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_) __node_ = nullptr; diff --git a/libcxx/include/__iterator/bounded_iter.h b/libcxx/include/__iterator/bounded_iter.h index 906ba3df0c5789b7b2b2d3928fa2fcb1e91db066..a1a941ffbaaf11866d6577a2af0042421a74b9bd 100644 --- a/libcxx/include/__iterator/bounded_iter.h +++ b/libcxx/include/__iterator/bounded_iter.h @@ -31,13 +31,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD // Iterator wrapper that carries the valid range it is allowed to access. // // This is a simple iterator wrapper for contiguous iterators that points -// within a [begin, end) range and carries these bounds with it. The iterator -// ensures that it is pointing within that [begin, end) range when it is -// dereferenced. +// within a [begin, end] range and carries these bounds with it. The iterator +// ensures that it is pointing within [begin, end) range when it is +// dereferenced. It also ensures that it is never iterated outside of +// [begin, end]. This is important for two reasons: // -// Arithmetic operations are allowed and the bounds of the resulting iterator -// are not checked. Hence, it is possible to create an iterator pointing outside -// its range, but it is not possible to dereference it. +// 1. It allows `operator*` and `operator++` bounds checks to be `iter != end`. +// This is both less for the optimizer to prove, and aligns with how callers +// typically use iterators. +// +// 2. Advancing an iterator out of bounds is undefined behavior (see the table +// in [input.iterators]). In particular, when the underlying iterator is a +// pointer, it is undefined at the language level (see [expr.add]). If +// bounded iterators exhibited this undefined behavior, we risk compiler +// optimizations deleting non-redundant bounds checks. template ::value > > struct __bounded_iter { using value_type = typename iterator_traits<_Iterator>::value_type; @@ -51,8 +58,8 @@ struct __bounded_iter { // Create a singular iterator. // - // Such an iterator does not point to any object and is conceptually out of bounds, so it is - // not dereferenceable. Observing operations like comparison and assignment are valid. + // Such an iterator points past the end of an empty span, so it is not dereferenceable. + // Observing operations like comparison and assignment are valid. _LIBCPP_HIDE_FROM_ABI __bounded_iter() = default; _LIBCPP_HIDE_FROM_ABI __bounded_iter(__bounded_iter const&) = default; @@ -70,18 +77,20 @@ struct __bounded_iter { private: // Create an iterator wrapping the given iterator, and whose bounds are described - // by the provided [begin, end) range. + // by the provided [begin, end] range. // - // This constructor does not check whether the resulting iterator is within its bounds. - // However, it does check that the provided [begin, end) range is a valid range (that - // is, begin <= end). + // The constructor does not check whether the resulting iterator is within its bounds. It is a + // responsibility of the container to ensure that the given bounds are valid. // // Since it is non-standard for iterators to have this constructor, __bounded_iter must // be created via `std::__make_bounded_iter`. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __bounded_iter( _Iterator __current, _Iterator __begin, _Iterator __end) : __current_(__current), __begin_(__begin), __end_(__end) { - _LIBCPP_ASSERT_INTERNAL(__begin <= __end, "__bounded_iter(current, begin, end): [begin, end) is not a valid range"); + _LIBCPP_ASSERT_INTERNAL( + __begin <= __current, "__bounded_iter(current, begin, end): current and begin are inconsistent"); + _LIBCPP_ASSERT_INTERNAL( + __current <= __end, "__bounded_iter(current, begin, end): current and end are inconsistent"); } template @@ -90,30 +99,37 @@ private: public: // Dereference and indexing operations. // - // These operations check that the iterator is dereferenceable, that is within [begin, end). + // These operations check that the iterator is dereferenceable. Since the class invariant is + // that the iterator is always within `[begin, end]`, we only need to check it's not pointing to + // `end`. This is easier for the optimizer because it aligns with the `iter != container.end()` + // checks that typical callers already use (see + // https://github.com/llvm/llvm-project/issues/78829). _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator*() const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( - __in_bounds(__current_), "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator"); + __current_ != __end_, "__bounded_iter::operator*: Attempt to dereference an iterator at the end"); return *__current_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pointer operator->() const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( - __in_bounds(__current_), "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator"); + __current_ != __end_, "__bounded_iter::operator->: Attempt to dereference an iterator at the end"); return std::__to_address(__current_); } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 reference operator[](difference_type __n) const _NOEXCEPT { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( - __in_bounds(__current_ + __n), "__bounded_iter::operator[]: Attempt to index an iterator out-of-range"); + __n >= __begin_ - __current_, "__bounded_iter::operator[]: Attempt to index an iterator past the start"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __n < __end_ - __current_, "__bounded_iter::operator[]: Attempt to index an iterator at or past the end"); return __current_[__n]; } // Arithmetic operations. // - // These operations do not check that the resulting iterator is within the bounds, since that - // would make it impossible to create a past-the-end iterator. + // These operations check that the iterator remains within `[begin, end]`. _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __bounded_iter& operator++() _NOEXCEPT { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __current_ != __end_, "__bounded_iter::operator++: Attempt to advance an iterator past the end"); ++__current_; return *this; } @@ -124,6 +140,8 @@ public: } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __bounded_iter& operator--() _NOEXCEPT { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __current_ != __begin_, "__bounded_iter::operator--: Attempt to rewind an iterator past the start"); --__current_; return *this; } @@ -134,6 +152,10 @@ public: } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __bounded_iter& operator+=(difference_type __n) _NOEXCEPT { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __n >= __begin_ - __current_, "__bounded_iter::operator+=: Attempt to rewind an iterator past the start"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __n <= __end_ - __current_, "__bounded_iter::operator+=: Attempt to advance an iterator past the end"); __current_ += __n; return *this; } @@ -151,6 +173,10 @@ public: } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __bounded_iter& operator-=(difference_type __n) _NOEXCEPT { + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __n <= __current_ - __begin_, "__bounded_iter::operator-=: Attempt to rewind an iterator past the start"); + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __n >= __current_ - __end_, "__bounded_iter::operator-=: Attempt to advance an iterator past the end"); __current_ -= __n; return *this; } @@ -197,15 +223,10 @@ public: } private: - // Return whether the given iterator is in the bounds of this __bounded_iter. - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Iterator const& __iter) const { - return __iter >= __begin_ && __iter < __end_; - } - template friend struct pointer_traits; _Iterator __current_; // current iterator - _Iterator __begin_, __end_; // valid range represented as [begin, end) + _Iterator __begin_, __end_; // valid range represented as [begin, end] }; template diff --git a/libcxx/include/__iterator/wrap_iter.h b/libcxx/include/__iterator/wrap_iter.h index 3827241e5fe4761d6216090e67a0ce27444c9bca..3124826189ad7c0b602ea30ca2f3a6fffd285d3e 100644 --- a/libcxx/include/__iterator/wrap_iter.h +++ b/libcxx/include/__iterator/wrap_iter.h @@ -97,10 +97,14 @@ private: friend class __wrap_iter; template friend class basic_string; + template + friend class basic_string_view; template friend class _LIBCPP_TEMPLATE_VIS vector; template friend class _LIBCPP_TEMPLATE_VIS span; + template + friend struct array; }; template diff --git a/libcxx/include/__tuple/find_index.h b/libcxx/include/__tuple/find_index.h new file mode 100644 index 0000000000000000000000000000000000000000..133b00419d0c6ca15111230c27b4f83e399e22d5 --- /dev/null +++ b/libcxx/include/__tuple/find_index.h @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// 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 _LIBCPP___TUPLE_FIND_INDEX_H +#define _LIBCPP___TUPLE_FIND_INDEX_H + +#include <__config> +#include <__type_traits/is_same.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 14 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __find_detail { + +static constexpr size_t __not_found = static_cast(-1); +static constexpr size_t __ambiguous = __not_found - 1; + +inline _LIBCPP_HIDE_FROM_ABI constexpr size_t __find_idx_return(size_t __curr_i, size_t __res, bool __matches) { + return !__matches ? __res : (__res == __not_found ? __curr_i : __ambiguous); +} + +template +inline _LIBCPP_HIDE_FROM_ABI constexpr size_t __find_idx(size_t __i, const bool (&__matches)[_Nx]) { + return __i == _Nx + ? __not_found + : __find_detail::__find_idx_return(__i, __find_detail::__find_idx(__i + 1, __matches), __matches[__i]); +} + +template +struct __find_exactly_one_checked { + static constexpr bool __matches[sizeof...(_Args)] = {is_same<_T1, _Args>::value...}; + static constexpr size_t value = __find_detail::__find_idx(0, __matches); + static_assert(value != __not_found, "type not found in type list"); + static_assert(value != __ambiguous, "type occurs more than once in type list"); +}; + +template +struct __find_exactly_one_checked<_T1> { + static_assert(!is_same<_T1, _T1>::value, "type not in empty type list"); +}; + +} // namespace __find_detail + +template +struct __find_exactly_one_t : public __find_detail::__find_exactly_one_checked<_T1, _Args...> {}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 14 + +#endif // _LIBCPP___TUPLE_FIND_INDEX_H diff --git a/libcxx/include/__type_traits/is_convertible.h b/libcxx/include/__type_traits/is_convertible.h index bc91d8b234308afce153122eac613fd7e3868806..414c2a6d6a0de078b579d2b841b3a185b64233fa 100644 --- a/libcxx/include/__type_traits/is_convertible.h +++ b/libcxx/include/__type_traits/is_convertible.h @@ -11,12 +11,6 @@ #include <__config> #include <__type_traits/integral_constant.h> -#include <__type_traits/is_array.h> -#include <__type_traits/is_function.h> -#include <__type_traits/is_void.h> -#include <__type_traits/remove_reference.h> -#include <__utility/declval.h> -#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h index 8af23668a815f7f3d472a617672d67b7b2adf255..b488a9829c3849e9e8221c6a1a0cf527b4ae7f34 100644 --- a/libcxx/include/__utility/pair.h +++ b/libcxx/include/__utility/pair.h @@ -120,14 +120,13 @@ struct _LIBCPP_TEMPLATE_VIS pair #else struct _CheckArgs { template - static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_explicit_default() { - return is_default_constructible<_T1>::value && is_default_constructible<_T2>::value && - !__enable_implicit_default<>(); + static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_implicit_default() { + return __is_implicitly_default_constructible<_T1>::value && __is_implicitly_default_constructible<_T2>::value; } template - static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_implicit_default() { - return __is_implicitly_default_constructible<_T1>::value && __is_implicitly_default_constructible<_T2>::value; + static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_default() { + return is_default_constructible<_T1>::value && is_default_constructible<_T2>::value; } template @@ -139,58 +138,25 @@ struct _LIBCPP_TEMPLATE_VIS pair static _LIBCPP_HIDE_FROM_ABI constexpr bool __is_implicit() { return is_convertible<_U1, first_type>::value && is_convertible<_U2, second_type>::value; } - - template - static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_explicit() { - return __is_pair_constructible<_U1, _U2>() && !__is_implicit<_U1, _U2>(); - } - - template - static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_implicit() { - return __is_pair_constructible<_U1, _U2>() && __is_implicit<_U1, _U2>(); - } }; template using _CheckArgsDep _LIBCPP_NODEBUG = typename conditional< _MaybeEnable, _CheckArgs, __check_tuple_constructor_fail>::type; - template ::__enable_explicit_default(), int> = 0> - explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair() _NOEXCEPT_( - is_nothrow_default_constructible::value&& is_nothrow_default_constructible::value) - : first(), second() {} - - template ::__enable_implicit_default(), int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair() _NOEXCEPT_( - is_nothrow_default_constructible::value&& is_nothrow_default_constructible::value) + template ::__enable_default(), int> = 0> + explicit(!_CheckArgsDep<_Dummy>::__enable_implicit_default()) _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR pair() + _NOEXCEPT_( + is_nothrow_default_constructible::value&& is_nothrow_default_constructible::value) : first(), second() {} - template ::template __enable_explicit<_T1 const&, _T2 const&>(), int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(_T1 const& __t1, _T2 const& __t2) + template ::template __is_pair_constructible<_T1 const&, _T2 const&>(), int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit( + !_CheckArgsDep<_Dummy>::template __is_implicit<_T1 const&, _T2 const&>()) pair(_T1 const& __t1, _T2 const& __t2) _NOEXCEPT_(is_nothrow_copy_constructible::value&& is_nothrow_copy_constructible::value) : first(__t1), second(__t2) {} - template ::template __enable_implicit<_T1 const&, _T2 const&>(), int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(_T1 const& __t1, _T2 const& __t2) - _NOEXCEPT_(is_nothrow_copy_constructible::value&& is_nothrow_copy_constructible::value) - : first(__t1), second(__t2) {} - - template < -# if _LIBCPP_STD_VER >= 23 // http://wg21.link/P1951 - class _U1 = _T1, - class _U2 = _T2, -# else - class _U1, - class _U2, -# endif - __enable_if_t<_CheckArgs::template __enable_explicit<_U1, _U2>(), int> = 0 > - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(_U1&& __u1, _U2&& __u2) - _NOEXCEPT_(is_nothrow_constructible::value&& is_nothrow_constructible::value) - : first(std::forward<_U1>(__u1)), second(std::forward<_U2>(__u2)) { - } - template < # if _LIBCPP_STD_VER >= 23 // http://wg21.link/P1951 class _U1 = _T1, @@ -199,9 +165,11 @@ struct _LIBCPP_TEMPLATE_VIS pair class _U1, class _U2, # endif - __enable_if_t<_CheckArgs::template __enable_implicit<_U1, _U2>(), int> = 0 > - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(_U1&& __u1, _U2&& __u2) - _NOEXCEPT_(is_nothrow_constructible::value&& is_nothrow_constructible::value) + __enable_if_t<_CheckArgs::template __is_pair_constructible<_U1, _U2>(), int> = 0 > + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_CheckArgs::template __is_implicit<_U1, _U2>()) + pair(_U1&& __u1, _U2&& __u2) + _NOEXCEPT_((is_nothrow_constructible::value && + is_nothrow_constructible::value)) : first(std::forward<_U1>(__u1)), second(std::forward<_U2>(__u2)) { } @@ -215,28 +183,18 @@ struct _LIBCPP_TEMPLATE_VIS pair template (), int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(pair<_U1, _U2> const& __p) - _NOEXCEPT_(is_nothrow_constructible::value&& - is_nothrow_constructible::value) - : first(__p.first), second(__p.second) {} - - template (), int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(pair<_U1, _U2> const& __p) - _NOEXCEPT_(is_nothrow_constructible::value&& - is_nothrow_constructible::value) + __enable_if_t<_CheckArgs::template __is_pair_constructible<_U1 const&, _U2 const&>(), int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit( + !_CheckArgs::template __is_implicit<_U1 const&, _U2 const&>()) pair(pair<_U1, _U2> const& __p) + _NOEXCEPT_((is_nothrow_constructible::value && + is_nothrow_constructible::value)) : first(__p.first), second(__p.second) {} - template (), int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(pair<_U1, _U2>&& __p) _NOEXCEPT_( - is_nothrow_constructible::value&& is_nothrow_constructible::value) - : first(std::forward<_U1>(__p.first)), second(std::forward<_U2>(__p.second)) {} - - template (), int> = 0> - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(pair<_U1, _U2>&& __p) _NOEXCEPT_( - is_nothrow_constructible::value&& is_nothrow_constructible::value) + template (), int> = 0> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_CheckArgs::template __is_implicit<_U1, _U2>()) + pair(pair<_U1, _U2>&& __p) + _NOEXCEPT_((is_nothrow_constructible::value && + is_nothrow_constructible::value)) : first(std::forward<_U1>(__p.first)), second(std::forward<_U2>(__p.second)) {} # if _LIBCPP_STD_VER >= 23 diff --git a/libcxx/include/array b/libcxx/include/array index 961b620efb935726dfec09166c632f7e4699ba97..7fa5dc1479349ef0ef710229ca41fc26fe262ada 100644 --- a/libcxx/include/array +++ b/libcxx/include/array @@ -120,6 +120,7 @@ template const T&& get(const array&&) noexce #include <__config> #include <__fwd/array.h> #include <__iterator/reverse_iterator.h> +#include <__iterator/wrap_iter.h> #include <__tuple/sfinae_helpers.h> #include <__type_traits/conditional.h> #include <__type_traits/is_array.h> @@ -167,14 +168,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD template struct _LIBCPP_TEMPLATE_VIS array { // types: - using __self = array; - using value_type = _Tp; - using reference = value_type&; - using const_reference = const value_type&; - using iterator = value_type*; - using const_iterator = const value_type*; - using pointer = value_type*; - using const_pointer = const value_type*; + using __self = array; + using value_type = _Tp; + using reference = value_type&; + using const_reference = const value_type&; + using pointer = value_type*; + using const_pointer = const value_type*; +#if defined(_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY) + using iterator = __wrap_iter; + using const_iterator = __wrap_iter; +#else + using iterator = pointer; + using const_iterator = const_pointer; +#endif using size_type = size_t; using difference_type = ptrdiff_t; using reverse_iterator = std::reverse_iterator; diff --git a/libcxx/include/atomic b/libcxx/include/atomic index 61ff61d415dd84c6bbc6c184d309355d672b8b86..cb142b09bff333178aff44dfd05a98f33f6101de 100644 --- a/libcxx/include/atomic +++ b/libcxx/include/atomic @@ -587,6 +587,12 @@ template */ +#include <__config> + +#if _LIBCPP_STD_VER < 23 && defined(_LIBCPP_STDATOMIC_H) +# error is incompatible with before C++23. Please compile with -std=c++23. +#endif + #include <__atomic/aliases.h> #include <__atomic/atomic.h> #include <__atomic/atomic_base.h> @@ -601,7 +607,6 @@ template #include <__atomic/is_always_lock_free.h> #include <__atomic/kill_dependency.h> #include <__atomic/memory_order.h> -#include <__config> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -612,10 +617,6 @@ template # error is not implemented #endif -#ifdef kill_dependency -# error is incompatible with before C++23. Please compile with -std=c++23. -#endif - #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include # include diff --git a/libcxx/include/format b/libcxx/include/format index b2fe0053b974bbf6cab5c64d8d546e408396c6ac..c0485c5a103596dea7dfe216bc3baa6da14884e0 100644 --- a/libcxx/include/format +++ b/libcxx/include/format @@ -199,7 +199,6 @@ namespace std { #include <__format/format_context.h> #include <__format/format_error.h> #include <__format/format_functions.h> -#include <__format/format_fwd.h> #include <__format/format_parse_context.h> #include <__format/format_string.h> #include <__format/format_to_n_result.h> @@ -215,6 +214,7 @@ namespace std { #include <__format/range_default_formatter.h> #include <__format/range_formatter.h> #include <__format/unicode.h> +#include <__fwd/format.h> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/iosfwd b/libcxx/include/iosfwd index 1579fa12754daff928ff6a3514a164eaf9532c2f..f1c2cbd9669679256eaac3081baf744dcda7bd6b 100644 --- a/libcxx/include/iosfwd +++ b/libcxx/include/iosfwd @@ -142,7 +142,7 @@ typedef fpos u8streampos; typedef fpos u16streampos; typedef fpos u32streampos; -#if _LIBCPP_STD_VER >= 20 +#if _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM) template , class _Allocator = allocator<_CharT>> class basic_syncbuf; @@ -160,7 +160,7 @@ using osyncstream = basic_osyncstream; using wosyncstream = basic_osyncstream; # endif -#endif // _LIBCPP_STD_VER >=20 +#endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM) // Include other forward declarations here template > diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp index cdbb0a63fc0eae251152c077e4030d65416a96da..b1e728cde868da1e8c91ae8e62b678a86ef490a3 100644 --- a/libcxx/include/libcxx.imp +++ b/libcxx/include/libcxx.imp @@ -374,7 +374,6 @@ { include: [ "<__format/format_context.h>", "private", "", "public" ] }, { include: [ "<__format/format_error.h>", "private", "", "public" ] }, { include: [ "<__format/format_functions.h>", "private", "", "public" ] }, - { include: [ "<__format/format_fwd.h>", "private", "", "public" ] }, { include: [ "<__format/format_parse_context.h>", "private", "", "public" ] }, { include: [ "<__format/format_string.h>", "private", "", "public" ] }, { include: [ "<__format/format_to_n_result.h>", "private", "", "public" ] }, @@ -425,6 +424,7 @@ { include: [ "<__fwd/bit_reference.h>", "private", "", "public" ] }, { include: [ "<__fwd/bit_reference.h>", "private", "", "public" ] }, { include: [ "<__fwd/complex.h>", "private", "", "public" ] }, + { include: [ "<__fwd/format.h>", "private", "", "public" ] }, { include: [ "<__fwd/fstream.h>", "private", "", "public" ] }, { include: [ "<__fwd/functional.h>", "private", "", "public" ] }, { include: [ "<__fwd/ios.h>", "private", "", "public" ] }, @@ -697,6 +697,7 @@ { include: [ "<__thread/this_thread.h>", "private", "", "public" ] }, { include: [ "<__thread/thread.h>", "private", "", "public" ] }, { include: [ "<__thread/timed_backoff_policy.h>", "private", "", "public" ] }, + { include: [ "<__tuple/find_index.h>", "private", "", "public" ] }, { include: [ "<__tuple/make_tuple_types.h>", "private", "", "public" ] }, { include: [ "<__tuple/pair_like.h>", "private", "", "public" ] }, { include: [ "<__tuple/sfinae_helpers.h>", "private", "", "public" ] }, diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap similarity index 99% rename from libcxx/include/module.modulemap.in rename to libcxx/include/module.modulemap index b247f97c1804d9be2ed40ddb26fbdd9dd5ef2921..0bd2831b7f159c8041118f7ac3354524e2d8a15f 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap @@ -1315,7 +1315,7 @@ module std_private_format_format_functions [system] { header "__format/format_functions.h" export std_string } -module std_private_format_format_fwd [system] { header "__format/format_fwd.h" } +module std_private_format_fwd [system] { header "__fwd/format.h" } module std_private_format_format_parse_context [system] { header "__format/format_parse_context.h" } module std_private_format_format_string [system] { header "__format/format_string.h" } module std_private_format_format_to_n_result [system] { @@ -1799,6 +1799,7 @@ module std_private_thread_thread [system] { } module std_private_thread_timed_backoff_policy [system] { header "__thread/timed_backoff_policy.h" } +module std_private_tuple_find_index [system] { header "__tuple/find_index.h" } module std_private_tuple_make_tuple_types [system] { header "__tuple/make_tuple_types.h" } module std_private_tuple_pair_like [system] { header "__tuple/pair_like.h" diff --git a/libcxx/include/span b/libcxx/include/span index 9efaac517fc8f6781f09c2c28906afe84a67dc13..c0fe25ddb4beb966a9b77c450f282f09a5f2f9a2 100644 --- a/libcxx/include/span +++ b/libcxx/include/span @@ -130,10 +130,12 @@ template #include <__assert> #include <__config> +#include <__fwd/array.h> #include <__fwd/span.h> #include <__iterator/bounded_iter.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> +#include <__iterator/reverse_iterator.h> #include <__iterator/wrap_iter.h> #include <__memory/pointer_traits.h> #include <__ranges/concepts.h> @@ -141,13 +143,16 @@ template #include <__ranges/enable_borrowed_range.h> #include <__ranges/enable_view.h> #include <__ranges/size.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_const.h> #include <__type_traits/is_convertible.h> +#include <__type_traits/remove_cv.h> #include <__type_traits/remove_cvref.h> #include <__type_traits/remove_reference.h> #include <__type_traits/type_identity.h> #include <__utility/forward.h> -#include // for array -#include // for byte +#include // for byte +#include #include #include @@ -171,12 +176,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 -template -struct __is_std_array : false_type {}; - -template -struct __is_std_array> : true_type {}; - template struct __is_std_span : false_type {}; @@ -564,10 +563,8 @@ _LIBCPP_HIDE_FROM_ABI auto as_writable_bytes(span<_Tp, _Extent> __s) noexcept { return __s.__as_writable_bytes(); } -# if _LIBCPP_STD_VER >= 20 template span(_It, _EndOrSize) -> span>>; -# endif // _LIBCPP_STD_VER >= 20 template span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>; @@ -588,6 +585,7 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 +# include # include # include # include diff --git a/libcxx/include/sstream b/libcxx/include/sstream index 60bec52209d75e5b7a3dfb59723b6e4137dfbcf0..5873deb8318ecffecf513722064793efca77be98 100644 --- a/libcxx/include/sstream +++ b/libcxx/include/sstream @@ -48,6 +48,13 @@ public: template explicit basic_stringbuf(const basic_string& s, ios_base::openmode which = ios_base::in | ios_base::out); // C++20 + template + explicit basic_stringbuf(const T& t, + ios_base::openmode which = ios_base::in | ios_base::out); // Since C++26 + template + basic_stringbuf(const T& t, const Allocator& a); // Since C++26 + template + basic_stringbuf(const T& t, ios_base::openmode which, const Allocator& a); // Since C++26 basic_stringbuf(const basic_stringbuf&) = delete; basic_stringbuf(basic_stringbuf&& rhs); basic_stringbuf(basic_stringbuf&& rhs, const allocator_type& a); // C++20 @@ -69,6 +76,8 @@ public: template void str(const basic_string& s); // C++20 void str(basic_string&& s); // C++20 + template + void str(const T& t); // Since C++26 protected: // [stringbuf.virtuals] Overridden virtual functions: @@ -121,6 +130,12 @@ public: template explicit basic_istringstream(const basic_string& s, ios_base::openmode which = ios_base::in); // C++20 + template + explicit basic_istringstream(const T& t, ios_base::openmode which = ios_base::in); // Since C++26 + template + basic_istringstream(const T& t, const Allocator& a); // Since C++26 + template + basic_istringstream(const T& t, ios_base::openmode which, const Allocator& a); // Since C++26 basic_istringstream(const basic_istringstream&) = delete; basic_istringstream(basic_istringstream&& rhs); @@ -141,6 +156,8 @@ public: template void str(const basic_string& s); // C++20 void str(basic_string&& s); // C++20 + template + void str(const T& t); // Since C++26 }; template @@ -182,6 +199,12 @@ public: template explicit basic_ostringstream(const basic_string& s, ios_base::openmode which = ios_base::out); // C++20 + template + explicit basic_ostringstream(const T& t, ios_base::openmode which = ios_base::out); // Since C++26 + template + basic_ostringstream(const T& t, const Allocator& a); // Since C++26 + template + basic_ostringstream(const T& t, ios_base::openmode which, const Allocator& a); // Since C++26 basic_ostringstream(const basic_ostringstream&) = delete; basic_ostringstream(basic_ostringstream&& rhs); @@ -202,6 +225,8 @@ public: template void str(const basic_string& s); // C++20 void str(basic_string&& s); // C++20 + template + void str(const T& t); // Since C++26 }; template @@ -243,6 +268,13 @@ public: template explicit basic_stringstream(const basic_string& s, ios_base::openmode which = ios_base::out | ios_base::in); // C++20 + template + explicit basic_stringstream(const T& t, + ios_base::openmode which = ios_base::out | ios_base::in); // Since C++26 + template + basic_stringstream(const T& t, const Allocator& a); // Since C++26 + template + basic_stringstream(const T& t, ios_base::openmode which, const Allocator& a); // Since C++26 basic_stringstream(const basic_stringstream&) = delete; basic_stringstream(basic_stringstream&& rhs); @@ -263,6 +295,8 @@ public: template void str(const basic_string& s); // C++20 void str(basic_string&& s); // C++20 + template + void str(const T& t); // Since C++26 }; template @@ -281,10 +315,12 @@ typedef basic_stringstream wstringstream; #include <__availability> #include <__config> #include <__fwd/sstream.h> +#include <__type_traits/is_convertible.h> #include <__utility/swap.h> #include #include #include +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -371,6 +407,30 @@ public: } #endif // _LIBCPP_STD_VER >= 20 +#if _LIBCPP_STD_VER >= 26 + + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI explicit basic_stringbuf(const _Tp& __t, + ios_base::openmode __which = ios_base::in | ios_base::out) + : basic_stringbuf(__t, __which, _Allocator()) {} + + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI basic_stringbuf(const _Tp& __t, const _Allocator& __a) + : basic_stringbuf(__t, ios_base::in | ios_base::out, __a) {} + + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI basic_stringbuf(const _Tp& __t, ios_base::openmode __which, const _Allocator& __a) + : __hm_(nullptr), __mode_(__which) { + basic_string_view<_CharT, _Traits> __sv = __t; + __str_ = string_type(__sv, __a); + __init_buf_ptrs(); + } + +#endif // _LIBCPP_STD_VER >= 26 + basic_stringbuf(const basic_stringbuf&) = delete; basic_stringbuf(basic_stringbuf&& __rhs) : __mode_(__rhs.__mode_) { __move_init(std::move(__rhs)); } @@ -444,6 +504,18 @@ public: } #endif // _LIBCPP_STD_VER >= 20 +#if _LIBCPP_STD_VER >= 26 + + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI void str(const _Tp& __t) { + basic_string_view<_CharT, _Traits> __sv = __t; + __str_ = __sv; + __init_buf_ptrs(); + } + +#endif // _LIBCPP_STD_VER >= 26 + protected: // [stringbuf.virtuals] Overridden virtual functions: int_type underflow() override; @@ -831,6 +903,25 @@ public: : basic_istream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch | ios_base::in) {} #endif // _LIBCPP_STD_VER >= 20 +#if _LIBCPP_STD_VER >= 26 + + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI explicit basic_istringstream(const _Tp& __t, ios_base::openmode __which = ios_base::in) + : basic_istringstream(__t, __which, _Allocator()) {} + + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI basic_istringstream(const _Tp& __t, const _Allocator& __a) + : basic_istringstream(__t, ios_base::in, __a) {} + + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI basic_istringstream(const _Tp& __t, ios_base::openmode __which, const _Allocator& __a) + : basic_istream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__t, __which | ios_base::in, __a) {} + +#endif // _LIBCPP_STD_VER >= 26 + basic_istringstream(const basic_istringstream&) = delete; _LIBCPP_HIDE_FROM_ABI basic_istringstream(basic_istringstream&& __rhs) : basic_istream<_CharT, _Traits>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) { @@ -882,6 +973,14 @@ public: _LIBCPP_HIDE_FROM_ABI void str(string_type&& __s) { __sb_.str(std::move(__s)); } #endif // _LIBCPP_STD_VER >= 20 + +#if _LIBCPP_STD_VER >= 26 + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI void str(const _Tp& __t) { + rdbuf()->str(__t); + } +#endif // _LIBCPP_STD_VER >= 26 }; template @@ -940,6 +1039,25 @@ public: : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch | ios_base::out) {} #endif // _LIBCPP_STD_VER >= 20 +#if _LIBCPP_STD_VER >= 26 + + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI explicit basic_ostringstream(const _Tp& __t, ios_base::openmode __which = ios_base::out) + : basic_ostringstream(__t, __which | ios_base::out, _Allocator()) {} + + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI basic_ostringstream(const _Tp& __t, const _Allocator& __a) + : basic_ostringstream(__t, ios_base::out, __a) {} + + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI basic_ostringstream(const _Tp& __t, ios_base::openmode __which, const _Allocator& __a) + : basic_ostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__t, __which | ios_base::out, __a) {} + +#endif // _LIBCPP_STD_VER >= 26 + basic_ostringstream(const basic_ostringstream&) = delete; _LIBCPP_HIDE_FROM_ABI basic_ostringstream(basic_ostringstream&& __rhs) : basic_ostream<_CharT, _Traits>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) { @@ -992,6 +1110,14 @@ public: _LIBCPP_HIDE_FROM_ABI void str(string_type&& __s) { __sb_.str(std::move(__s)); } #endif // _LIBCPP_STD_VER >= 20 + +#if _LIBCPP_STD_VER >= 26 + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI void str(const _Tp& __t) { + rdbuf()->str(__t); + } +#endif // _LIBCPP_STD_VER >= 26 }; template @@ -1053,6 +1179,26 @@ public: : basic_iostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__s, __wch) {} #endif // _LIBCPP_STD_VER >= 20 +#if _LIBCPP_STD_VER >= 26 + + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI explicit basic_stringstream(const _Tp& __t, + ios_base::openmode __which = ios_base::out | ios_base::in) + : basic_stringstream(__t, __which, _Allocator()) {} + + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI basic_stringstream(const _Tp& __t, const _Allocator& __a) + : basic_stringstream(__t, ios_base::out | ios_base::in, __a) {} + + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI basic_stringstream(const _Tp& __t, ios_base::openmode __which, const _Allocator& __a) + : basic_iostream<_CharT, _Traits>(std::addressof(__sb_)), __sb_(__t, __which, __a) {} + +#endif // _LIBCPP_STD_VER >= 26 + basic_stringstream(const basic_stringstream&) = delete; _LIBCPP_HIDE_FROM_ABI basic_stringstream(basic_stringstream&& __rhs) : basic_iostream<_CharT, _Traits>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) { @@ -1104,6 +1250,14 @@ public: _LIBCPP_HIDE_FROM_ABI void str(string_type&& __s) { __sb_.str(std::move(__s)); } #endif // _LIBCPP_STD_VER >= 20 + +#if _LIBCPP_STD_VER >= 26 + template + requires is_convertible_v> + _LIBCPP_HIDE_FROM_ABI void str(const _Tp& __t) { + rdbuf()->str(__t); + } +#endif // _LIBCPP_STD_VER >= 26 }; template diff --git a/libcxx/include/string_view b/libcxx/include/string_view index 48bbcd80021670e44ec9d60688f77dc551ddf4af..e8584a69c1e1b3fcc6868ec87057323562dfa634 100644 --- a/libcxx/include/string_view +++ b/libcxx/include/string_view @@ -215,6 +215,7 @@ namespace std { #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> #include <__iterator/reverse_iterator.h> +#include <__iterator/wrap_iter.h> #include <__memory/pointer_traits.h> #include <__ranges/concepts.h> #include <__ranges/data.h> @@ -278,10 +279,12 @@ public: using const_pointer = const _CharT*; using reference = _CharT&; using const_reference = const _CharT&; -#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS +#if defined(_LIBCPP_ABI_BOUNDED_ITERATORS) using const_iterator = __bounded_iter; +#elif defined(_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW) + using const_iterator = __wrap_iter; #else - using const_iterator = const_pointer; // See [string.view.iterators] + using const_iterator = const_pointer; #endif using iterator = const_iterator; using const_reverse_iterator = std::reverse_iterator; @@ -307,9 +310,10 @@ public: : __data_(__s), __size_(__len) { #if _LIBCPP_STD_VER >= 14 - // This will result in creating an invalid `string_view` object -- some calculations involving `size` would - // overflow, making it effectively truncated. - _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN( + // Allocations must fit in `ptrdiff_t` for pointer arithmetic to work. If `__len` exceeds it, the input + // range could not have been valid. Most likely the caller underflowed some arithmetic and inadvertently + // passed in a negative length. + _LIBCPP_ASSERT_VALID_INPUT_RANGE( __len <= static_cast(numeric_limits::max()), "string_view::string_view(_CharT *, size_t): length does not fit in difference_type"); _LIBCPP_ASSERT_NON_NULL( @@ -353,7 +357,7 @@ public: #ifdef _LIBCPP_ABI_BOUNDED_ITERATORS return std::__make_bounded_iter(data(), data(), data() + size()); #else - return __data_; + return const_iterator(__data_); #endif } @@ -361,7 +365,7 @@ public: #ifdef _LIBCPP_ABI_BOUNDED_ITERATORS return std::__make_bounded_iter(data() + size(), data(), data() + size()); #else - return __data_ + __size_; + return const_iterator(__data_ + __size_); #endif } diff --git a/libcxx/include/tuple b/libcxx/include/tuple index 0101d64aea4a722a29e021283b0cd9d5a45e8689..e63e4e25a7d2bd7ad9ea7276590d20f3ae5b9f88 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -213,6 +213,7 @@ template #include <__fwd/tuple.h> #include <__memory/allocator_arg_t.h> #include <__memory/uses_allocator.h> +#include <__tuple/find_index.h> #include <__tuple/make_tuple_types.h> #include <__tuple/sfinae_helpers.h> #include <__tuple/tuple_element.h> @@ -548,10 +549,6 @@ class _LIBCPP_TEMPLATE_VIS tuple { public: // [tuple.cnstr] - _LIBCPP_DIAGNOSTIC_PUSH - _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++20-extensions") - _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++20-extensions") - // tuple() constructors (including allocator_arg_t variants) template